Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // System Control and Management Interface (SCMI) based regulator driver
0004 //
0005 // Copyright (C) 2020-2021 ARM Ltd.
0006 //
0007 // Implements a regulator driver on top of the SCMI Voltage Protocol.
0008 //
0009 // The ARM SCMI Protocol aims in general to hide as much as possible all the
0010 // underlying operational details while providing an abstracted interface for
0011 // its users to operate upon: as a consequence the resulting operational
0012 // capabilities and configurability of this regulator device are much more
0013 // limited than the ones usually available on a standard physical regulator.
0014 //
0015 // The supported SCMI regulator ops are restricted to the bare minimum:
0016 //
0017 //  - 'status_ops': enable/disable/is_enabled
0018 //  - 'voltage_ops': get_voltage_sel/set_voltage_sel
0019 //           list_voltage/map_voltage
0020 //
0021 // Each SCMI regulator instance is associated, through the means of a proper DT
0022 // entry description, to a specific SCMI Voltage Domain.
0023 
0024 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0025 
0026 #include <linux/linear_range.h>
0027 #include <linux/module.h>
0028 #include <linux/of.h>
0029 #include <linux/regulator/driver.h>
0030 #include <linux/regulator/machine.h>
0031 #include <linux/regulator/of_regulator.h>
0032 #include <linux/scmi_protocol.h>
0033 #include <linux/slab.h>
0034 #include <linux/types.h>
0035 
0036 static const struct scmi_voltage_proto_ops *voltage_ops;
0037 
0038 struct scmi_regulator {
0039     u32 id;
0040     struct scmi_device *sdev;
0041     struct scmi_protocol_handle *ph;
0042     struct regulator_dev *rdev;
0043     struct device_node *of_node;
0044     struct regulator_desc desc;
0045     struct regulator_config conf;
0046 };
0047 
0048 struct scmi_regulator_info {
0049     int num_doms;
0050     struct scmi_regulator **sregv;
0051 };
0052 
0053 static int scmi_reg_enable(struct regulator_dev *rdev)
0054 {
0055     struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
0056 
0057     return voltage_ops->config_set(sreg->ph, sreg->id,
0058                        SCMI_VOLTAGE_ARCH_STATE_ON);
0059 }
0060 
0061 static int scmi_reg_disable(struct regulator_dev *rdev)
0062 {
0063     struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
0064 
0065     return voltage_ops->config_set(sreg->ph, sreg->id,
0066                        SCMI_VOLTAGE_ARCH_STATE_OFF);
0067 }
0068 
0069 static int scmi_reg_is_enabled(struct regulator_dev *rdev)
0070 {
0071     int ret;
0072     u32 config;
0073     struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
0074 
0075     ret = voltage_ops->config_get(sreg->ph, sreg->id, &config);
0076     if (ret) {
0077         dev_err(&sreg->sdev->dev,
0078             "Error %d reading regulator %s status.\n",
0079             ret, sreg->desc.name);
0080         return ret;
0081     }
0082 
0083     return config & SCMI_VOLTAGE_ARCH_STATE_ON;
0084 }
0085 
0086 static int scmi_reg_get_voltage_sel(struct regulator_dev *rdev)
0087 {
0088     int ret;
0089     s32 volt_uV;
0090     struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
0091 
0092     ret = voltage_ops->level_get(sreg->ph, sreg->id, &volt_uV);
0093     if (ret)
0094         return ret;
0095 
0096     return sreg->desc.ops->map_voltage(rdev, volt_uV, volt_uV);
0097 }
0098 
0099 static int scmi_reg_set_voltage_sel(struct regulator_dev *rdev,
0100                     unsigned int selector)
0101 {
0102     s32 volt_uV;
0103     struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
0104 
0105     volt_uV = sreg->desc.ops->list_voltage(rdev, selector);
0106     if (volt_uV <= 0)
0107         return -EINVAL;
0108 
0109     return voltage_ops->level_set(sreg->ph, sreg->id, 0x0, volt_uV);
0110 }
0111 
0112 static const struct regulator_ops scmi_reg_fixed_ops = {
0113     .enable = scmi_reg_enable,
0114     .disable = scmi_reg_disable,
0115     .is_enabled = scmi_reg_is_enabled,
0116 };
0117 
0118 static const struct regulator_ops scmi_reg_linear_ops = {
0119     .enable = scmi_reg_enable,
0120     .disable = scmi_reg_disable,
0121     .is_enabled = scmi_reg_is_enabled,
0122     .get_voltage_sel = scmi_reg_get_voltage_sel,
0123     .set_voltage_sel = scmi_reg_set_voltage_sel,
0124     .list_voltage = regulator_list_voltage_linear,
0125     .map_voltage = regulator_map_voltage_linear,
0126 };
0127 
0128 static const struct regulator_ops scmi_reg_discrete_ops = {
0129     .enable = scmi_reg_enable,
0130     .disable = scmi_reg_disable,
0131     .is_enabled = scmi_reg_is_enabled,
0132     .get_voltage_sel = scmi_reg_get_voltage_sel,
0133     .set_voltage_sel = scmi_reg_set_voltage_sel,
0134     .list_voltage = regulator_list_voltage_table,
0135     .map_voltage = regulator_map_voltage_iterate,
0136 };
0137 
0138 static int
0139 scmi_config_linear_regulator_mappings(struct scmi_regulator *sreg,
0140                       const struct scmi_voltage_info *vinfo)
0141 {
0142     s32 delta_uV;
0143 
0144     /*
0145      * Note that SCMI voltage domains describable by linear ranges
0146      * (segments) {low, high, step} are guaranteed to come in one single
0147      * triplet by the SCMI Voltage Domain protocol support itself.
0148      */
0149 
0150     delta_uV = (vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_HIGH] -
0151             vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW]);
0152 
0153     /* Rule out buggy negative-intervals answers from fw */
0154     if (delta_uV < 0) {
0155         dev_err(&sreg->sdev->dev,
0156             "Invalid volt-range %d-%duV for domain %d\n",
0157             vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW],
0158             vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_HIGH],
0159             sreg->id);
0160         return -EINVAL;
0161     }
0162 
0163     if (!delta_uV) {
0164         /* Just one fixed voltage exposed by SCMI */
0165         sreg->desc.fixed_uV =
0166             vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW];
0167         sreg->desc.n_voltages = 1;
0168         sreg->desc.ops = &scmi_reg_fixed_ops;
0169     } else {
0170         /* One simple linear mapping. */
0171         sreg->desc.min_uV =
0172             vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW];
0173         sreg->desc.uV_step =
0174             vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_STEP];
0175         sreg->desc.linear_min_sel = 0;
0176         sreg->desc.n_voltages = (delta_uV / sreg->desc.uV_step) + 1;
0177         sreg->desc.ops = &scmi_reg_linear_ops;
0178     }
0179 
0180     return 0;
0181 }
0182 
0183 static int
0184 scmi_config_discrete_regulator_mappings(struct scmi_regulator *sreg,
0185                     const struct scmi_voltage_info *vinfo)
0186 {
0187     /* Discrete non linear levels are mapped to volt_table */
0188     sreg->desc.n_voltages = vinfo->num_levels;
0189 
0190     if (sreg->desc.n_voltages > 1) {
0191         sreg->desc.volt_table = (const unsigned int *)vinfo->levels_uv;
0192         sreg->desc.ops = &scmi_reg_discrete_ops;
0193     } else {
0194         sreg->desc.fixed_uV = vinfo->levels_uv[0];
0195         sreg->desc.ops = &scmi_reg_fixed_ops;
0196     }
0197 
0198     return 0;
0199 }
0200 
0201 static int scmi_regulator_common_init(struct scmi_regulator *sreg)
0202 {
0203     int ret;
0204     struct device *dev = &sreg->sdev->dev;
0205     const struct scmi_voltage_info *vinfo;
0206 
0207     vinfo = voltage_ops->info_get(sreg->ph, sreg->id);
0208     if (!vinfo) {
0209         dev_warn(dev, "Failure to get voltage domain %d\n",
0210              sreg->id);
0211         return -ENODEV;
0212     }
0213 
0214     /*
0215      * Regulator framework does not fully support negative voltages
0216      * so we discard any voltage domain reported as supporting negative
0217      * voltages: as a consequence each levels_uv entry is guaranteed to
0218      * be non-negative from here on.
0219      */
0220     if (vinfo->negative_volts_allowed) {
0221         dev_warn(dev, "Negative voltages NOT supported...skip %s\n",
0222              sreg->of_node->full_name);
0223         return -EOPNOTSUPP;
0224     }
0225 
0226     sreg->desc.name = devm_kasprintf(dev, GFP_KERNEL, "%s", vinfo->name);
0227     if (!sreg->desc.name)
0228         return -ENOMEM;
0229 
0230     sreg->desc.id = sreg->id;
0231     sreg->desc.type = REGULATOR_VOLTAGE;
0232     sreg->desc.owner = THIS_MODULE;
0233     sreg->desc.of_match_full_name = true;
0234     sreg->desc.of_match = sreg->of_node->full_name;
0235     sreg->desc.regulators_node = "regulators";
0236     if (vinfo->segmented)
0237         ret = scmi_config_linear_regulator_mappings(sreg, vinfo);
0238     else
0239         ret = scmi_config_discrete_regulator_mappings(sreg, vinfo);
0240     if (ret)
0241         return ret;
0242 
0243     /*
0244      * Using the scmi device here to have DT searched from Voltage
0245      * protocol node down.
0246      */
0247     sreg->conf.dev = dev;
0248 
0249     /* Store for later retrieval via rdev_get_drvdata() */
0250     sreg->conf.driver_data = sreg;
0251 
0252     return 0;
0253 }
0254 
0255 static int process_scmi_regulator_of_node(struct scmi_device *sdev,
0256                       struct scmi_protocol_handle *ph,
0257                       struct device_node *np,
0258                       struct scmi_regulator_info *rinfo)
0259 {
0260     u32 dom, ret;
0261 
0262     ret = of_property_read_u32(np, "reg", &dom);
0263     if (ret)
0264         return ret;
0265 
0266     if (dom >= rinfo->num_doms)
0267         return -ENODEV;
0268 
0269     if (rinfo->sregv[dom]) {
0270         dev_err(&sdev->dev,
0271             "SCMI Voltage Domain %d already in use. Skipping: %s\n",
0272             dom, np->full_name);
0273         return -EINVAL;
0274     }
0275 
0276     rinfo->sregv[dom] = devm_kzalloc(&sdev->dev,
0277                      sizeof(struct scmi_regulator),
0278                      GFP_KERNEL);
0279     if (!rinfo->sregv[dom])
0280         return -ENOMEM;
0281 
0282     rinfo->sregv[dom]->id = dom;
0283     rinfo->sregv[dom]->sdev = sdev;
0284     rinfo->sregv[dom]->ph = ph;
0285 
0286     /* get hold of good nodes */
0287     of_node_get(np);
0288     rinfo->sregv[dom]->of_node = np;
0289 
0290     dev_dbg(&sdev->dev,
0291         "Found SCMI Regulator entry -- OF node [%d] -> %s\n",
0292         dom, np->full_name);
0293 
0294     return 0;
0295 }
0296 
0297 static int scmi_regulator_probe(struct scmi_device *sdev)
0298 {
0299     int d, ret, num_doms;
0300     struct device_node *np, *child;
0301     const struct scmi_handle *handle = sdev->handle;
0302     struct scmi_regulator_info *rinfo;
0303     struct scmi_protocol_handle *ph;
0304 
0305     if (!handle)
0306         return -ENODEV;
0307 
0308     voltage_ops = handle->devm_protocol_get(sdev,
0309                         SCMI_PROTOCOL_VOLTAGE, &ph);
0310     if (IS_ERR(voltage_ops))
0311         return PTR_ERR(voltage_ops);
0312 
0313     num_doms = voltage_ops->num_domains_get(ph);
0314     if (num_doms <= 0) {
0315         if (!num_doms) {
0316             dev_err(&sdev->dev,
0317                 "number of voltage domains invalid\n");
0318             num_doms = -EINVAL;
0319         } else {
0320             dev_err(&sdev->dev,
0321                 "failed to get voltage domains - err:%d\n",
0322                 num_doms);
0323         }
0324 
0325         return num_doms;
0326     }
0327 
0328     rinfo = devm_kzalloc(&sdev->dev, sizeof(*rinfo), GFP_KERNEL);
0329     if (!rinfo)
0330         return -ENOMEM;
0331 
0332     /* Allocate pointers array for all possible domains */
0333     rinfo->sregv = devm_kcalloc(&sdev->dev, num_doms,
0334                     sizeof(void *), GFP_KERNEL);
0335     if (!rinfo->sregv)
0336         return -ENOMEM;
0337 
0338     rinfo->num_doms = num_doms;
0339 
0340     /*
0341      * Start collecting into rinfo->sregv possibly good SCMI Regulators as
0342      * described by a well-formed DT entry and associated with an existing
0343      * plausible SCMI Voltage Domain number, all belonging to this SCMI
0344      * platform instance node (handle->dev->of_node).
0345      */
0346     of_node_get(handle->dev->of_node);
0347     np = of_find_node_by_name(handle->dev->of_node, "regulators");
0348     for_each_child_of_node(np, child) {
0349         ret = process_scmi_regulator_of_node(sdev, ph, child, rinfo);
0350         /* abort on any mem issue */
0351         if (ret == -ENOMEM) {
0352             of_node_put(child);
0353             return ret;
0354         }
0355     }
0356     of_node_put(np);
0357     /*
0358      * Register a regulator for each valid regulator-DT-entry that we
0359      * can successfully reach via SCMI and has a valid associated voltage
0360      * domain.
0361      */
0362     for (d = 0; d < num_doms; d++) {
0363         struct scmi_regulator *sreg = rinfo->sregv[d];
0364 
0365         /* Skip empty slots */
0366         if (!sreg)
0367             continue;
0368 
0369         ret = scmi_regulator_common_init(sreg);
0370         /* Skip invalid voltage domains */
0371         if (ret)
0372             continue;
0373 
0374         sreg->rdev = devm_regulator_register(&sdev->dev, &sreg->desc,
0375                              &sreg->conf);
0376         if (IS_ERR(sreg->rdev)) {
0377             sreg->rdev = NULL;
0378             continue;
0379         }
0380 
0381         dev_info(&sdev->dev,
0382              "Regulator %s registered for domain [%d]\n",
0383              sreg->desc.name, sreg->id);
0384     }
0385 
0386     dev_set_drvdata(&sdev->dev, rinfo);
0387 
0388     return 0;
0389 }
0390 
0391 static void scmi_regulator_remove(struct scmi_device *sdev)
0392 {
0393     int d;
0394     struct scmi_regulator_info *rinfo;
0395 
0396     rinfo = dev_get_drvdata(&sdev->dev);
0397     if (!rinfo)
0398         return;
0399 
0400     for (d = 0; d < rinfo->num_doms; d++) {
0401         if (!rinfo->sregv[d])
0402             continue;
0403         of_node_put(rinfo->sregv[d]->of_node);
0404     }
0405 }
0406 
0407 static const struct scmi_device_id scmi_regulator_id_table[] = {
0408     { SCMI_PROTOCOL_VOLTAGE,  "regulator" },
0409     { },
0410 };
0411 MODULE_DEVICE_TABLE(scmi, scmi_regulator_id_table);
0412 
0413 static struct scmi_driver scmi_drv = {
0414     .name       = "scmi-regulator",
0415     .probe      = scmi_regulator_probe,
0416     .remove     = scmi_regulator_remove,
0417     .id_table   = scmi_regulator_id_table,
0418 };
0419 
0420 module_scmi_driver(scmi_drv);
0421 
0422 MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
0423 MODULE_DESCRIPTION("ARM SCMI regulator driver");
0424 MODULE_LICENSE("GPL v2");