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-enable-ramp-delay", &pval);
  94        if (!ret)
  95                constraints->enable_time = pval;
  96
  97        constraints->soft_start = of_property_read_bool(np,
  98                                        "regulator-soft-start");
  99        ret = of_property_read_u32(np, "regulator-active-discharge", &pval);
 100        if (!ret) {
 101                constraints->active_discharge =
 102                                (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE :
 103                                        REGULATOR_ACTIVE_DISCHARGE_DISABLE;
 104        }
 105
 106        if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
 107                if (desc && desc->of_map_mode) {
 108                        ret = desc->of_map_mode(pval);
 109                        if (ret == -EINVAL)
 110                                pr_err("%s: invalid mode %u\n", np->name, pval);
 111                        else
 112                                constraints->initial_mode = ret;
 113                } else {
 114                        pr_warn("%s: mapping for mode %d not defined\n",
 115                                np->name, pval);
 116                }
 117        }
 118
 119        if (!of_property_read_u32(np, "regulator-system-load", &pval))
 120                constraints->system_load = pval;
 121
 122        constraints->over_current_protection = of_property_read_bool(np,
 123                                        "regulator-over-current-protection");
 124
 125        for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
 126                switch (i) {
 127                case PM_SUSPEND_MEM:
 128                        suspend_state = &constraints->state_mem;
 129                        break;
 130                case PM_SUSPEND_MAX:
 131                        suspend_state = &constraints->state_disk;
 132                        break;
 133                case PM_SUSPEND_ON:
 134                case PM_SUSPEND_FREEZE:
 135                case PM_SUSPEND_STANDBY:
 136                default:
 137                        continue;
 138                }
 139
 140                suspend_np = of_get_child_by_name(np, regulator_states[i]);
 141                if (!suspend_np || !suspend_state)
 142                        continue;
 143
 144                if (!of_property_read_u32(suspend_np, "regulator-mode",
 145                                          &pval)) {
 146                        if (desc && desc->of_map_mode) {
 147                                ret = desc->of_map_mode(pval);
 148                                if (ret == -EINVAL)
 149                                        pr_err("%s: invalid mode %u\n",
 150                                               np->name, pval);
 151                                else
 152                                        suspend_state->mode = ret;
 153                        } else {
 154                                pr_warn("%s: mapping for mode %d not defined\n",
 155                                        np->name, pval);
 156                        }
 157                }
 158
 159                if (of_property_read_bool(suspend_np,
 160                                        "regulator-on-in-suspend"))
 161                        suspend_state->enabled = true;
 162                else if (of_property_read_bool(suspend_np,
 163                                        "regulator-off-in-suspend"))
 164                        suspend_state->disabled = true;
 165
 166                if (!of_property_read_u32(suspend_np,
 167                                        "regulator-suspend-microvolt", &pval))
 168                        suspend_state->uV = pval;
 169
 170                if (i == PM_SUSPEND_MEM)
 171                        constraints->initial_state = PM_SUSPEND_MEM;
 172
 173                of_node_put(suspend_np);
 174                suspend_state = NULL;
 175                suspend_np = NULL;
 176        }
 177}
 178
 179/**
 180 * of_get_regulator_init_data - extract regulator_init_data structure info
 181 * @dev: device requesting for regulator_init_data
 182 * @node: regulator device node
 183 * @desc: regulator description
 184 *
 185 * Populates regulator_init_data structure by extracting data from device
 186 * tree node, returns a pointer to the populated struture or NULL if memory
 187 * alloc fails.
 188 */
 189struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
 190                                          struct device_node *node,
 191                                          const struct regulator_desc *desc)
 192{
 193        struct regulator_init_data *init_data;
 194
 195        if (!node)
 196                return NULL;
 197
 198        init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL);
 199        if (!init_data)
 200                return NULL; /* Out of memory? */
 201
 202        of_get_regulation_constraints(node, &init_data, desc);
 203        return init_data;
 204}
 205EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
 206
 207struct devm_of_regulator_matches {
 208        struct of_regulator_match *matches;
 209        unsigned int num_matches;
 210};
 211
 212static void devm_of_regulator_put_matches(struct device *dev, void *res)
 213{
 214        struct devm_of_regulator_matches *devm_matches = res;
 215        int i;
 216
 217        for (i = 0; i < devm_matches->num_matches; i++)
 218                of_node_put(devm_matches->matches[i].of_node);
 219}
 220
 221/**
 222 * of_regulator_match - extract multiple regulator init data from device tree.
 223 * @dev: device requesting the data
 224 * @node: parent device node of the regulators
 225 * @matches: match table for the regulators
 226 * @num_matches: number of entries in match table
 227 *
 228 * This function uses a match table specified by the regulator driver to
 229 * parse regulator init data from the device tree. @node is expected to
 230 * contain a set of child nodes, each providing the init data for one
 231 * regulator. The data parsed from a child node will be matched to a regulator
 232 * based on either the deprecated property regulator-compatible if present,
 233 * or otherwise the child node's name. Note that the match table is modified
 234 * in place and an additional of_node reference is taken for each matched
 235 * regulator.
 236 *
 237 * Returns the number of matches found or a negative error code on failure.
 238 */
 239int of_regulator_match(struct device *dev, struct device_node *node,
 240                       struct of_regulator_match *matches,
 241                       unsigned int num_matches)
 242{
 243        unsigned int count = 0;
 244        unsigned int i;
 245        const char *name;
 246        struct device_node *child;
 247        struct devm_of_regulator_matches *devm_matches;
 248
 249        if (!dev || !node)
 250                return -EINVAL;
 251
 252        devm_matches = devres_alloc(devm_of_regulator_put_matches,
 253                                    sizeof(struct devm_of_regulator_matches),
 254                                    GFP_KERNEL);
 255        if (!devm_matches)
 256                return -ENOMEM;
 257
 258        devm_matches->matches = matches;
 259        devm_matches->num_matches = num_matches;
 260
 261        devres_add(dev, devm_matches);
 262
 263        for (i = 0; i < num_matches; i++) {
 264                struct of_regulator_match *match = &matches[i];
 265                match->init_data = NULL;
 266                match->of_node = NULL;
 267        }
 268
 269        for_each_child_of_node(node, child) {
 270                name = of_get_property(child,
 271                                        "regulator-compatible", NULL);
 272                if (!name)
 273                        name = child->name;
 274                for (i = 0; i < num_matches; i++) {
 275                        struct of_regulator_match *match = &matches[i];
 276                        if (match->of_node)
 277                                continue;
 278
 279                        if (strcmp(match->name, name))
 280                                continue;
 281
 282                        match->init_data =
 283                                of_get_regulator_init_data(dev, child,
 284                                                           match->desc);
 285                        if (!match->init_data) {
 286                                dev_err(dev,
 287                                        "failed to parse DT for regulator %s\n",
 288                                        child->name);
 289                                return -EINVAL;
 290                        }
 291                        match->of_node = of_node_get(child);
 292                        count++;
 293                        break;
 294                }
 295        }
 296
 297        return count;
 298}
 299EXPORT_SYMBOL_GPL(of_regulator_match);
 300
 301struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
 302                                            const struct regulator_desc *desc,
 303                                            struct regulator_config *config,
 304                                            struct device_node **node)
 305{
 306        struct device_node *search, *child;
 307        struct regulator_init_data *init_data = NULL;
 308        const char *name;
 309
 310        if (!dev->of_node || !desc->of_match)
 311                return NULL;
 312
 313        if (desc->regulators_node)
 314                search = of_get_child_by_name(dev->of_node,
 315                                              desc->regulators_node);
 316        else
 317                search = dev->of_node;
 318
 319        if (!search) {
 320                dev_dbg(dev, "Failed to find regulator container node '%s'\n",
 321                        desc->regulators_node);
 322                return NULL;
 323        }
 324
 325        for_each_available_child_of_node(search, child) {
 326                name = of_get_property(child, "regulator-compatible", NULL);
 327                if (!name)
 328                        name = child->name;
 329
 330                if (strcmp(desc->of_match, name))
 331                        continue;
 332
 333                init_data = of_get_regulator_init_data(dev, child, desc);
 334                if (!init_data) {
 335                        dev_err(dev,
 336                                "failed to parse DT for regulator %s\n",
 337                                child->name);
 338                        break;
 339                }
 340
 341                if (desc->of_parse_cb) {
 342                        if (desc->of_parse_cb(child, desc, config)) {
 343                                dev_err(dev,
 344                                        "driver callback failed to parse DT for regulator %s\n",
 345                                        child->name);
 346                                init_data = NULL;
 347                                break;
 348                        }
 349                }
 350
 351                of_node_get(child);
 352                *node = child;
 353                break;
 354        }
 355
 356        of_node_put(search);
 357
 358        return init_data;
 359}
 360