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