linux/drivers/regulator/scmi-regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// System Control and Management Interface (SCMI) based regulator driver
   4//
   5// Copyright (C) 2020-2021 ARM Ltd.
   6//
   7// Implements a regulator driver on top of the SCMI Voltage Protocol.
   8//
   9// The ARM SCMI Protocol aims in general to hide as much as possible all the
  10// underlying operational details while providing an abstracted interface for
  11// its users to operate upon: as a consequence the resulting operational
  12// capabilities and configurability of this regulator device are much more
  13// limited than the ones usually available on a standard physical regulator.
  14//
  15// The supported SCMI regulator ops are restricted to the bare minimum:
  16//
  17//  - 'status_ops': enable/disable/is_enabled
  18//  - 'voltage_ops': get_voltage_sel/set_voltage_sel
  19//                   list_voltage/map_voltage
  20//
  21// Each SCMI regulator instance is associated, through the means of a proper DT
  22// entry description, to a specific SCMI Voltage Domain.
  23
  24#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  25
  26#include <linux/linear_range.h>
  27#include <linux/module.h>
  28#include <linux/of.h>
  29#include <linux/regulator/driver.h>
  30#include <linux/regulator/machine.h>
  31#include <linux/regulator/of_regulator.h>
  32#include <linux/scmi_protocol.h>
  33#include <linux/slab.h>
  34#include <linux/types.h>
  35
  36static const struct scmi_voltage_proto_ops *voltage_ops;
  37
  38struct scmi_regulator {
  39        u32 id;
  40        struct scmi_device *sdev;
  41        struct scmi_protocol_handle *ph;
  42        struct regulator_dev *rdev;
  43        struct device_node *of_node;
  44        struct regulator_desc desc;
  45        struct regulator_config conf;
  46};
  47
  48struct scmi_regulator_info {
  49        int num_doms;
  50        struct scmi_regulator **sregv;
  51};
  52
  53static int scmi_reg_enable(struct regulator_dev *rdev)
  54{
  55        struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
  56
  57        return voltage_ops->config_set(sreg->ph, sreg->id,
  58                                       SCMI_VOLTAGE_ARCH_STATE_ON);
  59}
  60
  61static int scmi_reg_disable(struct regulator_dev *rdev)
  62{
  63        struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
  64
  65        return voltage_ops->config_set(sreg->ph, sreg->id,
  66                                       SCMI_VOLTAGE_ARCH_STATE_OFF);
  67}
  68
  69static int scmi_reg_is_enabled(struct regulator_dev *rdev)
  70{
  71        int ret;
  72        u32 config;
  73        struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
  74
  75        ret = voltage_ops->config_get(sreg->ph, sreg->id, &config);
  76        if (ret) {
  77                dev_err(&sreg->sdev->dev,
  78                        "Error %d reading regulator %s status.\n",
  79                        ret, sreg->desc.name);
  80                return ret;
  81        }
  82
  83        return config & SCMI_VOLTAGE_ARCH_STATE_ON;
  84}
  85
  86static int scmi_reg_get_voltage_sel(struct regulator_dev *rdev)
  87{
  88        int ret;
  89        s32 volt_uV;
  90        struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
  91
  92        ret = voltage_ops->level_get(sreg->ph, sreg->id, &volt_uV);
  93        if (ret)
  94                return ret;
  95
  96        return sreg->desc.ops->map_voltage(rdev, volt_uV, volt_uV);
  97}
  98
  99static int scmi_reg_set_voltage_sel(struct regulator_dev *rdev,
 100                                    unsigned int selector)
 101{
 102        s32 volt_uV;
 103        struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
 104
 105        volt_uV = sreg->desc.ops->list_voltage(rdev, selector);
 106        if (volt_uV <= 0)
 107                return -EINVAL;
 108
 109        return voltage_ops->level_set(sreg->ph, sreg->id, 0x0, volt_uV);
 110}
 111
 112static const struct regulator_ops scmi_reg_fixed_ops = {
 113        .enable = scmi_reg_enable,
 114        .disable = scmi_reg_disable,
 115        .is_enabled = scmi_reg_is_enabled,
 116};
 117
 118static const struct regulator_ops scmi_reg_linear_ops = {
 119        .enable = scmi_reg_enable,
 120        .disable = scmi_reg_disable,
 121        .is_enabled = scmi_reg_is_enabled,
 122        .get_voltage_sel = scmi_reg_get_voltage_sel,
 123        .set_voltage_sel = scmi_reg_set_voltage_sel,
 124        .list_voltage = regulator_list_voltage_linear,
 125        .map_voltage = regulator_map_voltage_linear,
 126};
 127
 128static const struct regulator_ops scmi_reg_discrete_ops = {
 129        .enable = scmi_reg_enable,
 130        .disable = scmi_reg_disable,
 131        .is_enabled = scmi_reg_is_enabled,
 132        .get_voltage_sel = scmi_reg_get_voltage_sel,
 133        .set_voltage_sel = scmi_reg_set_voltage_sel,
 134        .list_voltage = regulator_list_voltage_table,
 135        .map_voltage = regulator_map_voltage_iterate,
 136};
 137
 138static int
 139scmi_config_linear_regulator_mappings(struct scmi_regulator *sreg,
 140                                      const struct scmi_voltage_info *vinfo)
 141{
 142        s32 delta_uV;
 143
 144        /*
 145         * Note that SCMI voltage domains describable by linear ranges
 146         * (segments) {low, high, step} are guaranteed to come in one single
 147         * triplet by the SCMI Voltage Domain protocol support itself.
 148         */
 149
 150        delta_uV = (vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_HIGH] -
 151                        vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW]);
 152
 153        /* Rule out buggy negative-intervals answers from fw */
 154        if (delta_uV < 0) {
 155                dev_err(&sreg->sdev->dev,
 156                        "Invalid volt-range %d-%duV for domain %d\n",
 157                        vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW],
 158                        vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_HIGH],
 159                        sreg->id);
 160                return -EINVAL;
 161        }
 162
 163        if (!delta_uV) {
 164                /* Just one fixed voltage exposed by SCMI */
 165                sreg->desc.fixed_uV =
 166                        vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW];
 167                sreg->desc.n_voltages = 1;
 168                sreg->desc.ops = &scmi_reg_fixed_ops;
 169        } else {
 170                /* One simple linear mapping. */
 171                sreg->desc.min_uV =
 172                        vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW];
 173                sreg->desc.uV_step =
 174                        vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_STEP];
 175                sreg->desc.linear_min_sel = 0;
 176                sreg->desc.n_voltages = (delta_uV / sreg->desc.uV_step) + 1;
 177                sreg->desc.ops = &scmi_reg_linear_ops;
 178        }
 179
 180        return 0;
 181}
 182
 183static int
 184scmi_config_discrete_regulator_mappings(struct scmi_regulator *sreg,
 185                                        const struct scmi_voltage_info *vinfo)
 186{
 187        /* Discrete non linear levels are mapped to volt_table */
 188        sreg->desc.n_voltages = vinfo->num_levels;
 189
 190        if (sreg->desc.n_voltages > 1) {
 191                sreg->desc.volt_table = (const unsigned int *)vinfo->levels_uv;
 192                sreg->desc.ops = &scmi_reg_discrete_ops;
 193        } else {
 194                sreg->desc.fixed_uV = vinfo->levels_uv[0];
 195                sreg->desc.ops = &scmi_reg_fixed_ops;
 196        }
 197
 198        return 0;
 199}
 200
 201static int scmi_regulator_common_init(struct scmi_regulator *sreg)
 202{
 203        int ret;
 204        struct device *dev = &sreg->sdev->dev;
 205        const struct scmi_voltage_info *vinfo;
 206
 207        vinfo = voltage_ops->info_get(sreg->ph, sreg->id);
 208        if (!vinfo) {
 209                dev_warn(dev, "Failure to get voltage domain %d\n",
 210                         sreg->id);
 211                return -ENODEV;
 212        }
 213
 214        /*
 215         * Regulator framework does not fully support negative voltages
 216         * so we discard any voltage domain reported as supporting negative
 217         * voltages: as a consequence each levels_uv entry is guaranteed to
 218         * be non-negative from here on.
 219         */
 220        if (vinfo->negative_volts_allowed) {
 221                dev_warn(dev, "Negative voltages NOT supported...skip %s\n",
 222                         sreg->of_node->full_name);
 223                return -EOPNOTSUPP;
 224        }
 225
 226        sreg->desc.name = devm_kasprintf(dev, GFP_KERNEL, "%s", vinfo->name);
 227        if (!sreg->desc.name)
 228                return -ENOMEM;
 229
 230        sreg->desc.id = sreg->id;
 231        sreg->desc.type = REGULATOR_VOLTAGE;
 232        sreg->desc.owner = THIS_MODULE;
 233        sreg->desc.of_match_full_name = true;
 234        sreg->desc.of_match = sreg->of_node->full_name;
 235        sreg->desc.regulators_node = "regulators";
 236        if (vinfo->segmented)
 237                ret = scmi_config_linear_regulator_mappings(sreg, vinfo);
 238        else
 239                ret = scmi_config_discrete_regulator_mappings(sreg, vinfo);
 240        if (ret)
 241                return ret;
 242
 243        /*
 244         * Using the scmi device here to have DT searched from Voltage
 245         * protocol node down.
 246         */
 247        sreg->conf.dev = dev;
 248
 249        /* Store for later retrieval via rdev_get_drvdata() */
 250        sreg->conf.driver_data = sreg;
 251
 252        return 0;
 253}
 254
 255static int process_scmi_regulator_of_node(struct scmi_device *sdev,
 256                                          struct scmi_protocol_handle *ph,
 257                                          struct device_node *np,
 258                                          struct scmi_regulator_info *rinfo)
 259{
 260        u32 dom, ret;
 261
 262        ret = of_property_read_u32(np, "reg", &dom);
 263        if (ret)
 264                return ret;
 265
 266        if (dom >= rinfo->num_doms)
 267                return -ENODEV;
 268
 269        if (rinfo->sregv[dom]) {
 270                dev_err(&sdev->dev,
 271                        "SCMI Voltage Domain %d already in use. Skipping: %s\n",
 272                        dom, np->full_name);
 273                return -EINVAL;
 274        }
 275
 276        rinfo->sregv[dom] = devm_kzalloc(&sdev->dev,
 277                                         sizeof(struct scmi_regulator),
 278                                         GFP_KERNEL);
 279        if (!rinfo->sregv[dom])
 280                return -ENOMEM;
 281
 282        rinfo->sregv[dom]->id = dom;
 283        rinfo->sregv[dom]->sdev = sdev;
 284        rinfo->sregv[dom]->ph = ph;
 285
 286        /* get hold of good nodes */
 287        of_node_get(np);
 288        rinfo->sregv[dom]->of_node = np;
 289
 290        dev_dbg(&sdev->dev,
 291                "Found SCMI Regulator entry -- OF node [%d] -> %s\n",
 292                dom, np->full_name);
 293
 294        return 0;
 295}
 296
 297static int scmi_regulator_probe(struct scmi_device *sdev)
 298{
 299        int d, ret, num_doms;
 300        struct device_node *np, *child;
 301        const struct scmi_handle *handle = sdev->handle;
 302        struct scmi_regulator_info *rinfo;
 303        struct scmi_protocol_handle *ph;
 304
 305        if (!handle)
 306                return -ENODEV;
 307
 308        voltage_ops = handle->devm_protocol_get(sdev,
 309                                                SCMI_PROTOCOL_VOLTAGE, &ph);
 310        if (IS_ERR(voltage_ops))
 311                return PTR_ERR(voltage_ops);
 312
 313        num_doms = voltage_ops->num_domains_get(ph);
 314        if (num_doms <= 0) {
 315                if (!num_doms) {
 316                        dev_err(&sdev->dev,
 317                                "number of voltage domains invalid\n");
 318                        num_doms = -EINVAL;
 319                } else {
 320                        dev_err(&sdev->dev,
 321                                "failed to get voltage domains - err:%d\n",
 322                                num_doms);
 323                }
 324
 325                return num_doms;
 326        }
 327
 328        rinfo = devm_kzalloc(&sdev->dev, sizeof(*rinfo), GFP_KERNEL);
 329        if (!rinfo)
 330                return -ENOMEM;
 331
 332        /* Allocate pointers array for all possible domains */
 333        rinfo->sregv = devm_kcalloc(&sdev->dev, num_doms,
 334                                    sizeof(void *), GFP_KERNEL);
 335        if (!rinfo->sregv)
 336                return -ENOMEM;
 337
 338        rinfo->num_doms = num_doms;
 339
 340        /*
 341         * Start collecting into rinfo->sregv possibly good SCMI Regulators as
 342         * described by a well-formed DT entry and associated with an existing
 343         * plausible SCMI Voltage Domain number, all belonging to this SCMI
 344         * platform instance node (handle->dev->of_node).
 345         */
 346        np = of_find_node_by_name(handle->dev->of_node, "regulators");
 347        for_each_child_of_node(np, child) {
 348                ret = process_scmi_regulator_of_node(sdev, ph, child, rinfo);
 349                /* abort on any mem issue */
 350                if (ret == -ENOMEM) {
 351                        of_node_put(child);
 352                        return ret;
 353                }
 354        }
 355
 356        /*
 357         * Register a regulator for each valid regulator-DT-entry that we
 358         * can successfully reach via SCMI and has a valid associated voltage
 359         * domain.
 360         */
 361        for (d = 0; d < num_doms; d++) {
 362                struct scmi_regulator *sreg = rinfo->sregv[d];
 363
 364                /* Skip empty slots */
 365                if (!sreg)
 366                        continue;
 367
 368                ret = scmi_regulator_common_init(sreg);
 369                /* Skip invalid voltage domains */
 370                if (ret)
 371                        continue;
 372
 373                sreg->rdev = devm_regulator_register(&sdev->dev, &sreg->desc,
 374                                                     &sreg->conf);
 375                if (IS_ERR(sreg->rdev)) {
 376                        sreg->rdev = NULL;
 377                        continue;
 378                }
 379
 380                dev_info(&sdev->dev,
 381                         "Regulator %s registered for domain [%d]\n",
 382                         sreg->desc.name, sreg->id);
 383        }
 384
 385        dev_set_drvdata(&sdev->dev, rinfo);
 386
 387        return 0;
 388}
 389
 390static void scmi_regulator_remove(struct scmi_device *sdev)
 391{
 392        int d;
 393        struct scmi_regulator_info *rinfo;
 394
 395        rinfo = dev_get_drvdata(&sdev->dev);
 396        if (!rinfo)
 397                return;
 398
 399        for (d = 0; d < rinfo->num_doms; d++) {
 400                if (!rinfo->sregv[d])
 401                        continue;
 402                of_node_put(rinfo->sregv[d]->of_node);
 403        }
 404}
 405
 406static const struct scmi_device_id scmi_regulator_id_table[] = {
 407        { SCMI_PROTOCOL_VOLTAGE,  "regulator" },
 408        { },
 409};
 410MODULE_DEVICE_TABLE(scmi, scmi_regulator_id_table);
 411
 412static struct scmi_driver scmi_drv = {
 413        .name           = "scmi-regulator",
 414        .probe          = scmi_regulator_probe,
 415        .remove         = scmi_regulator_remove,
 416        .id_table       = scmi_regulator_id_table,
 417};
 418
 419module_scmi_driver(scmi_drv);
 420
 421MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
 422MODULE_DESCRIPTION("ARM SCMI regulator driver");
 423MODULE_LICENSE("GPL v2");
 424