linux/drivers/regulator/of_regulator.c
<<
>>
Prefs
   1/*
   2 * OF helpers for regulator framework
   3 *
   4 * Copyright (C) 2011 Texas Instruments, Inc.
   5 * Rajendra Nayak <rnayak@ti.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/slab.h>
  15#include <linux/of.h>
  16#include <linux/regulator/machine.h>
  17#include <linux/regulator/driver.h>
  18#include <linux/regulator/of_regulator.h>
  19
  20#include "internal.h"
  21
  22static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
  23        [PM_SUSPEND_MEM]        = "regulator-state-mem",
  24        [PM_SUSPEND_MAX]        = "regulator-state-disk",
  25};
  26
  27static void of_get_regulation_constraints(struct device_node *np,
  28                                        struct regulator_init_data **init_data,
  29                                        const struct regulator_desc *desc)
  30{
  31        struct regulation_constraints *constraints = &(*init_data)->constraints;
  32        struct regulator_state *suspend_state;
  33        struct device_node *suspend_np;
  34        int ret, i;
  35        u32 pval;
  36
  37        constraints->name = of_get_property(np, "regulator-name", NULL);
  38
  39        if (!of_property_read_u32(np, "regulator-min-microvolt", &pval))
  40                constraints->min_uV = pval;
  41
  42        if (!of_property_read_u32(np, "regulator-max-microvolt", &pval))
  43                constraints->max_uV = pval;
  44
  45        /* Voltage change possible? */
  46        if (constraints->min_uV != constraints->max_uV)
  47                constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
  48
  49        /* Do we have a voltage range, if so try to apply it? */
  50        if (constraints->min_uV && constraints->max_uV)
  51                constraints->apply_uV = true;
  52
  53        if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval))
  54                constraints->uV_offset = pval;
  55        if (!of_property_read_u32(np, "regulator-min-microamp", &pval))
  56                constraints->min_uA = pval;
  57        if (!of_property_read_u32(np, "regulator-max-microamp", &pval))
  58                constraints->max_uA = pval;
  59
  60        if (!of_property_read_u32(np, "regulator-input-current-limit-microamp",
  61                                  &pval))
  62                constraints->ilim_uA = pval;
  63
  64        /* Current change possible? */
  65        if (constraints->min_uA != constraints->max_uA)
  66                constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
  67
  68        constraints->boot_on = of_property_read_bool(np, "regulator-boot-on");
  69        constraints->always_on = of_property_read_bool(np, "regulator-always-on");
  70        if (!constraints->always_on) /* status change should be possible. */
  71                constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
  72
  73        constraints->pull_down = of_property_read_bool(np, "regulator-pull-down");
  74
  75        if (of_property_read_bool(np, "regulator-allow-bypass"))
  76                constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
  77
  78        if (of_property_read_bool(np, "regulator-allow-set-load"))
  79                constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS;
  80
  81        ret = of_property_read_u32(np, "regulator-ramp-delay", &pval);
  82        if (!ret) {
  83                if (pval)
  84                        constraints->ramp_delay = pval;
  85                else
  86                        constraints->ramp_disable = true;
  87        }
  88
  89        ret = of_property_read_u32(np, "regulator-settling-time-us", &pval);
  90        if (!ret)
  91                constraints->settling_time = pval;
  92
  93        ret = of_property_read_u32(np, "regulator-settling-time-up-us", &pval);
  94        if (!ret)
  95                constraints->settling_time_up = pval;
  96        if (constraints->settling_time_up && constraints->settling_time) {
  97                pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n",
  98                        np->name);
  99                constraints->settling_time_up = 0;
 100        }
 101
 102        ret = of_property_read_u32(np, "regulator-settling-time-down-us",
 103                                   &pval);
 104        if (!ret)
 105                constraints->settling_time_down = pval;
 106        if (constraints->settling_time_down && constraints->settling_time) {
 107                pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n",
 108                        np->name);
 109                constraints->settling_time_down = 0;
 110        }
 111
 112        ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
 113        if (!ret)
 114                constraints->enable_time = pval;
 115
 116        constraints->soft_start = of_property_read_bool(np,
 117                                        "regulator-soft-start");
 118        ret = of_property_read_u32(np, "regulator-active-discharge", &pval);
 119        if (!ret) {
 120                constraints->active_discharge =
 121                                (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE :
 122                                        REGULATOR_ACTIVE_DISCHARGE_DISABLE;
 123        }
 124
 125        if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
 126                if (desc && desc->of_map_mode) {
 127                        ret = desc->of_map_mode(pval);
 128                        if (ret == -EINVAL)
 129                                pr_err("%s: invalid mode %u\n", np->name, pval);
 130                        else
 131                                constraints->initial_mode = ret;
 132                } else {
 133                        pr_warn("%s: mapping for mode %d not defined\n",
 134                                np->name, pval);
 135                }
 136        }
 137
 138        if (!of_property_read_u32(np, "regulator-system-load", &pval))
 139                constraints->system_load = pval;
 140
 141        constraints->over_current_protection = of_property_read_bool(np,
 142                                        "regulator-over-current-protection");
 143
 144        for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
 145                switch (i) {
 146                case PM_SUSPEND_MEM:
 147                        suspend_state = &constraints->state_mem;
 148                        break;
 149                case PM_SUSPEND_MAX:
 150                        suspend_state = &constraints->state_disk;
 151                        break;
 152                case PM_SUSPEND_ON:
 153                case PM_SUSPEND_FREEZE:
 154                case PM_SUSPEND_STANDBY:
 155                default:
 156                        continue;
 157                }
 158
 159                suspend_np = of_get_child_by_name(np, regulator_states[i]);
 160                if (!suspend_np || !suspend_state)
 161                        continue;
 162
 163                if (!of_property_read_u32(suspend_np, "regulator-mode",
 164                                          &pval)) {
 165                        if (desc && desc->of_map_mode) {
 166                                ret = desc->of_map_mode(pval);
 167                                if (ret == -EINVAL)
 168                                        pr_err("%s: invalid mode %u\n",
 169                                               np->name, pval);
 170                                else
 171                                        suspend_state->mode = ret;
 172                        } else {
 173                                pr_warn("%s: mapping for mode %d not defined\n",
 174                                        np->name, pval);
 175                        }
 176                }
 177
 178                if (of_property_read_bool(suspend_np,
 179                                        "regulator-on-in-suspend"))
 180                        suspend_state->enabled = true;
 181                else if (of_property_read_bool(suspend_np,
 182                                        "regulator-off-in-suspend"))
 183                        suspend_state->disabled = true;
 184
 185                if (!of_property_read_u32(suspend_np,
 186                                        "regulator-suspend-microvolt", &pval))
 187                        suspend_state->uV = pval;
 188
 189                if (i == PM_SUSPEND_MEM)
 190                        constraints->initial_state = PM_SUSPEND_MEM;
 191
 192                of_node_put(suspend_np);
 193                suspend_state = NULL;
 194                suspend_np = NULL;
 195        }
 196}
 197
 198/**
 199 * of_get_regulator_init_data - extract regulator_init_data structure info
 200 * @dev: device requesting for regulator_init_data
 201 * @node: regulator device node
 202 * @desc: regulator description
 203 *
 204 * Populates regulator_init_data structure by extracting data from device
 205 * tree node, returns a pointer to the populated struture or NULL if memory
 206 * alloc fails.
 207 */
 208struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
 209                                          struct device_node *node,
 210                                          const struct regulator_desc *desc)
 211{
 212        struct regulator_init_data *init_data;
 213
 214        if (!node)
 215                return NULL;
 216
 217        init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL);
 218        if (!init_data)
 219                return NULL; /* Out of memory? */
 220
 221        of_get_regulation_constraints(node, &init_data, desc);
 222        return init_data;
 223}
 224EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
 225
 226struct devm_of_regulator_matches {
 227        struct of_regulator_match *matches;
 228        unsigned int num_matches;
 229};
 230
 231static void devm_of_regulator_put_matches(struct device *dev, void *res)
 232{
 233        struct devm_of_regulator_matches *devm_matches = res;
 234        int i;
 235
 236        for (i = 0; i < devm_matches->num_matches; i++)
 237                of_node_put(devm_matches->matches[i].of_node);
 238}
 239
 240/**
 241 * of_regulator_match - extract multiple regulator init data from device tree.
 242 * @dev: device requesting the data
 243 * @node: parent device node of the regulators
 244 * @matches: match table for the regulators
 245 * @num_matches: number of entries in match table
 246 *
 247 * This function uses a match table specified by the regulator driver to
 248 * parse regulator init data from the device tree. @node is expected to
 249 * contain a set of child nodes, each providing the init data for one
 250 * regulator. The data parsed from a child node will be matched to a regulator
 251 * based on either the deprecated property regulator-compatible if present,
 252 * or otherwise the child node's name. Note that the match table is modified
 253 * in place and an additional of_node reference is taken for each matched
 254 * regulator.
 255 *
 256 * Returns the number of matches found or a negative error code on failure.
 257 */
 258int of_regulator_match(struct device *dev, struct device_node *node,
 259                       struct of_regulator_match *matches,
 260                       unsigned int num_matches)
 261{
 262        unsigned int count = 0;
 263        unsigned int i;
 264        const char *name;
 265        struct device_node *child;
 266        struct devm_of_regulator_matches *devm_matches;
 267
 268        if (!dev || !node)
 269                return -EINVAL;
 270
 271        devm_matches = devres_alloc(devm_of_regulator_put_matches,
 272                                    sizeof(struct devm_of_regulator_matches),
 273                                    GFP_KERNEL);
 274        if (!devm_matches)
 275                return -ENOMEM;
 276
 277        devm_matches->matches = matches;
 278        devm_matches->num_matches = num_matches;
 279
 280        devres_add(dev, devm_matches);
 281
 282        for (i = 0; i < num_matches; i++) {
 283                struct of_regulator_match *match = &matches[i];
 284                match->init_data = NULL;
 285                match->of_node = NULL;
 286        }
 287
 288        for_each_child_of_node(node, child) {
 289                name = of_get_property(child,
 290                                        "regulator-compatible", NULL);
 291                if (!name)
 292                        name = child->name;
 293                for (i = 0; i < num_matches; i++) {
 294                        struct of_regulator_match *match = &matches[i];
 295                        if (match->of_node)
 296                                continue;
 297
 298                        if (strcmp(match->name, name))
 299                                continue;
 300
 301                        match->init_data =
 302                                of_get_regulator_init_data(dev, child,
 303                                                           match->desc);
 304                        if (!match->init_data) {
 305                                dev_err(dev,
 306                                        "failed to parse DT for regulator %s\n",
 307                                        child->name);
 308                                return -EINVAL;
 309                        }
 310                        match->of_node = of_node_get(child);
 311                        count++;
 312                        break;
 313                }
 314        }
 315
 316        return count;
 317}
 318EXPORT_SYMBOL_GPL(of_regulator_match);
 319
 320struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
 321                                            const struct regulator_desc *desc,
 322                                            struct regulator_config *config,
 323                                            struct device_node **node)
 324{
 325        struct device_node *search, *child;
 326        struct regulator_init_data *init_data = NULL;
 327        const char *name;
 328
 329        if (!dev->of_node || !desc->of_match)
 330                return NULL;
 331
 332        if (desc->regulators_node)
 333                search = of_get_child_by_name(dev->of_node,
 334                                              desc->regulators_node);
 335        else
 336                search = dev->of_node;
 337
 338        if (!search) {
 339                dev_dbg(dev, "Failed to find regulator container node '%s'\n",
 340                        desc->regulators_node);
 341                return NULL;
 342        }
 343
 344        for_each_available_child_of_node(search, child) {
 345                name = of_get_property(child, "regulator-compatible", NULL);
 346                if (!name)
 347                        name = child->name;
 348
 349                if (strcmp(desc->of_match, name))
 350                        continue;
 351
 352                init_data = of_get_regulator_init_data(dev, child, desc);
 353                if (!init_data) {
 354                        dev_err(dev,
 355                                "failed to parse DT for regulator %s\n",
 356                                child->name);
 357                        break;
 358                }
 359
 360                if (desc->of_parse_cb) {
 361                        if (desc->of_parse_cb(child, desc, config)) {
 362                                dev_err(dev,
 363                                        "driver callback failed to parse DT for regulator %s\n",
 364                                        child->name);
 365                                init_data = NULL;
 366                                break;
 367                        }
 368                }
 369
 370                of_node_get(child);
 371                *node = child;
 372                break;
 373        }
 374
 375        of_node_put(search);
 376
 377        return init_data;
 378}
 379