LCOV - code coverage report
Current view: top level - drivers/regulator - of_regulator.c (source / functions) Hit Total Coverage
Test: Real Lines: 66 241 27.4 %
Date: 2020-10-17 15:46:16 Functions: 0 11 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * OF helpers for regulator framework
       4                 :            :  *
       5                 :            :  * Copyright (C) 2011 Texas Instruments, Inc.
       6                 :            :  * Rajendra Nayak <rnayak@ti.com>
       7                 :            :  */
       8                 :            : 
       9                 :            : #include <linux/module.h>
      10                 :            : #include <linux/slab.h>
      11                 :            : #include <linux/of.h>
      12                 :            : #include <linux/regulator/machine.h>
      13                 :            : #include <linux/regulator/driver.h>
      14                 :            : #include <linux/regulator/of_regulator.h>
      15                 :            : 
      16                 :            : #include "internal.h"
      17                 :            : 
      18                 :            : static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
      19                 :            :         [PM_SUSPEND_STANDBY]    = "regulator-state-standby",
      20                 :            :         [PM_SUSPEND_MEM]        = "regulator-state-mem",
      21                 :            :         [PM_SUSPEND_MAX]        = "regulator-state-disk",
      22                 :            : };
      23                 :            : 
      24                 :          3 : static int of_get_regulation_constraints(struct device *dev,
      25                 :            :                                         struct device_node *np,
      26                 :            :                                         struct regulator_init_data **init_data,
      27                 :            :                                         const struct regulator_desc *desc)
      28                 :            : {
      29                 :          3 :         struct regulation_constraints *constraints = &(*init_data)->constraints;
      30                 :            :         struct regulator_state *suspend_state;
      31                 :            :         struct device_node *suspend_np;
      32                 :            :         unsigned int mode;
      33                 :            :         int ret, i, len;
      34                 :            :         int n_phandles;
      35                 :            :         u32 pval;
      36                 :            : 
      37                 :          3 :         n_phandles = of_count_phandle_with_args(np, "regulator-coupled-with",
      38                 :            :                                                 NULL);
      39                 :          3 :         n_phandles = max(n_phandles, 0);
      40                 :            : 
      41                 :          3 :         constraints->name = of_get_property(np, "regulator-name", NULL);
      42                 :            : 
      43                 :          3 :         if (!of_property_read_u32(np, "regulator-min-microvolt", &pval))
      44                 :          3 :                 constraints->min_uV = pval;
      45                 :            : 
      46                 :          3 :         if (!of_property_read_u32(np, "regulator-max-microvolt", &pval))
      47                 :          3 :                 constraints->max_uV = pval;
      48                 :            : 
      49                 :            :         /* Voltage change possible? */
      50                 :          3 :         if (constraints->min_uV != constraints->max_uV)
      51                 :          0 :                 constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
      52                 :            : 
      53                 :            :         /* Do we have a voltage range, if so try to apply it? */
      54                 :          3 :         if (constraints->min_uV && constraints->max_uV)
      55                 :          3 :                 constraints->apply_uV = true;
      56                 :            : 
      57                 :          3 :         if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval))
      58                 :          0 :                 constraints->uV_offset = pval;
      59                 :          3 :         if (!of_property_read_u32(np, "regulator-min-microamp", &pval))
      60                 :          0 :                 constraints->min_uA = pval;
      61                 :          3 :         if (!of_property_read_u32(np, "regulator-max-microamp", &pval))
      62                 :          0 :                 constraints->max_uA = pval;
      63                 :            : 
      64                 :          3 :         if (!of_property_read_u32(np, "regulator-input-current-limit-microamp",
      65                 :            :                                   &pval))
      66                 :          0 :                 constraints->ilim_uA = pval;
      67                 :            : 
      68                 :            :         /* Current change possible? */
      69                 :          3 :         if (constraints->min_uA != constraints->max_uA)
      70                 :          0 :                 constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
      71                 :            : 
      72                 :          3 :         constraints->boot_on = of_property_read_bool(np, "regulator-boot-on");
      73                 :          3 :         constraints->always_on = of_property_read_bool(np, "regulator-always-on");
      74                 :          3 :         if (!constraints->always_on) /* status change should be possible. */
      75                 :          0 :                 constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
      76                 :            : 
      77                 :          3 :         constraints->pull_down = of_property_read_bool(np, "regulator-pull-down");
      78                 :            : 
      79                 :          3 :         if (of_property_read_bool(np, "regulator-allow-bypass"))
      80                 :          0 :                 constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
      81                 :            : 
      82                 :          3 :         if (of_property_read_bool(np, "regulator-allow-set-load"))
      83                 :          0 :                 constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS;
      84                 :            : 
      85                 :            :         ret = of_property_read_u32(np, "regulator-ramp-delay", &pval);
      86                 :          3 :         if (!ret) {
      87                 :          0 :                 if (pval)
      88                 :          0 :                         constraints->ramp_delay = pval;
      89                 :            :                 else
      90                 :          0 :                         constraints->ramp_disable = true;
      91                 :            :         }
      92                 :            : 
      93                 :            :         ret = of_property_read_u32(np, "regulator-settling-time-us", &pval);
      94                 :          3 :         if (!ret)
      95                 :          0 :                 constraints->settling_time = pval;
      96                 :            : 
      97                 :            :         ret = of_property_read_u32(np, "regulator-settling-time-up-us", &pval);
      98                 :          3 :         if (!ret)
      99                 :          0 :                 constraints->settling_time_up = pval;
     100                 :          3 :         if (constraints->settling_time_up && constraints->settling_time) {
     101                 :          0 :                 pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n",
     102                 :            :                         np);
     103                 :          0 :                 constraints->settling_time_up = 0;
     104                 :            :         }
     105                 :            : 
     106                 :            :         ret = of_property_read_u32(np, "regulator-settling-time-down-us",
     107                 :            :                                    &pval);
     108                 :          3 :         if (!ret)
     109                 :          0 :                 constraints->settling_time_down = pval;
     110                 :          3 :         if (constraints->settling_time_down && constraints->settling_time) {
     111                 :          0 :                 pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n",
     112                 :            :                         np);
     113                 :          0 :                 constraints->settling_time_down = 0;
     114                 :            :         }
     115                 :            : 
     116                 :            :         ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
     117                 :          3 :         if (!ret)
     118                 :          0 :                 constraints->enable_time = pval;
     119                 :            : 
     120                 :          3 :         constraints->soft_start = of_property_read_bool(np,
     121                 :            :                                         "regulator-soft-start");
     122                 :            :         ret = of_property_read_u32(np, "regulator-active-discharge", &pval);
     123                 :          3 :         if (!ret) {
     124                 :          0 :                 constraints->active_discharge =
     125                 :          0 :                                 (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE :
     126                 :            :                                         REGULATOR_ACTIVE_DISCHARGE_DISABLE;
     127                 :            :         }
     128                 :            : 
     129                 :          3 :         if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
     130                 :          0 :                 if (desc && desc->of_map_mode) {
     131                 :          0 :                         mode = desc->of_map_mode(pval);
     132                 :          0 :                         if (mode == REGULATOR_MODE_INVALID)
     133                 :          0 :                                 pr_err("%pOFn: invalid mode %u\n", np, pval);
     134                 :            :                         else
     135                 :          0 :                                 constraints->initial_mode = mode;
     136                 :            :                 } else {
     137                 :          0 :                         pr_warn("%pOFn: mapping for mode %d not defined\n",
     138                 :            :                                 np, pval);
     139                 :            :                 }
     140                 :            :         }
     141                 :            : 
     142                 :          3 :         len = of_property_count_elems_of_size(np, "regulator-allowed-modes",
     143                 :            :                                                 sizeof(u32));
     144                 :          3 :         if (len > 0) {
     145                 :          0 :                 if (desc && desc->of_map_mode) {
     146                 :          0 :                         for (i = 0; i < len; i++) {
     147                 :          0 :                                 ret = of_property_read_u32_index(np,
     148                 :            :                                         "regulator-allowed-modes", i, &pval);
     149                 :          0 :                                 if (ret) {
     150                 :          0 :                                         pr_err("%pOFn: couldn't read allowed modes index %d, ret=%d\n",
     151                 :            :                                                 np, i, ret);
     152                 :          0 :                                         break;
     153                 :            :                                 }
     154                 :          0 :                                 mode = desc->of_map_mode(pval);
     155                 :          0 :                                 if (mode == REGULATOR_MODE_INVALID)
     156                 :          0 :                                         pr_err("%pOFn: invalid regulator-allowed-modes element %u\n",
     157                 :            :                                                 np, pval);
     158                 :            :                                 else
     159                 :          0 :                                         constraints->valid_modes_mask |= mode;
     160                 :            :                         }
     161                 :          0 :                         if (constraints->valid_modes_mask)
     162                 :            :                                 constraints->valid_ops_mask
     163                 :          0 :                                         |= REGULATOR_CHANGE_MODE;
     164                 :            :                 } else {
     165                 :          0 :                         pr_warn("%pOFn: mode mapping not defined\n", np);
     166                 :            :                 }
     167                 :            :         }
     168                 :            : 
     169                 :          3 :         if (!of_property_read_u32(np, "regulator-system-load", &pval))
     170                 :          0 :                 constraints->system_load = pval;
     171                 :            : 
     172                 :          3 :         if (n_phandles) {
     173                 :          0 :                 constraints->max_spread = devm_kzalloc(dev,
     174                 :            :                                 sizeof(*constraints->max_spread) * n_phandles,
     175                 :            :                                 GFP_KERNEL);
     176                 :            : 
     177                 :          0 :                 if (!constraints->max_spread)
     178                 :            :                         return -ENOMEM;
     179                 :            : 
     180                 :            :                 of_property_read_u32_array(np, "regulator-coupled-max-spread",
     181                 :            :                                            constraints->max_spread, n_phandles);
     182                 :            :         }
     183                 :            : 
     184                 :          3 :         if (!of_property_read_u32(np, "regulator-max-step-microvolt",
     185                 :            :                                   &pval))
     186                 :          0 :                 constraints->max_uV_step = pval;
     187                 :            : 
     188                 :          3 :         constraints->over_current_protection = of_property_read_bool(np,
     189                 :            :                                         "regulator-over-current-protection");
     190                 :            : 
     191                 :          3 :         for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
     192                 :          3 :                 switch (i) {
     193                 :            :                 case PM_SUSPEND_MEM:
     194                 :          3 :                         suspend_state = &constraints->state_mem;
     195                 :          3 :                         break;
     196                 :            :                 case PM_SUSPEND_MAX:
     197                 :          3 :                         suspend_state = &constraints->state_disk;
     198                 :          3 :                         break;
     199                 :            :                 case PM_SUSPEND_STANDBY:
     200                 :          3 :                         suspend_state = &constraints->state_standby;
     201                 :          3 :                         break;
     202                 :            :                 case PM_SUSPEND_ON:
     203                 :            :                 case PM_SUSPEND_TO_IDLE:
     204                 :            :                 default:
     205                 :          3 :                         continue;
     206                 :            :                 }
     207                 :            : 
     208                 :          3 :                 suspend_np = of_get_child_by_name(np, regulator_states[i]);
     209                 :          3 :                 if (!suspend_np || !suspend_state)
     210                 :          3 :                         continue;
     211                 :            : 
     212                 :          0 :                 if (!of_property_read_u32(suspend_np, "regulator-mode",
     213                 :            :                                           &pval)) {
     214                 :          0 :                         if (desc && desc->of_map_mode) {
     215                 :          0 :                                 mode = desc->of_map_mode(pval);
     216                 :          0 :                                 if (mode == REGULATOR_MODE_INVALID)
     217                 :          0 :                                         pr_err("%pOFn: invalid mode %u\n",
     218                 :            :                                                np, pval);
     219                 :            :                                 else
     220                 :          0 :                                         suspend_state->mode = mode;
     221                 :            :                         } else {
     222                 :          0 :                                 pr_warn("%pOFn: mapping for mode %d not defined\n",
     223                 :            :                                         np, pval);
     224                 :            :                         }
     225                 :            :                 }
     226                 :            : 
     227                 :          0 :                 if (of_property_read_bool(suspend_np,
     228                 :            :                                         "regulator-on-in-suspend"))
     229                 :          0 :                         suspend_state->enabled = ENABLE_IN_SUSPEND;
     230                 :          0 :                 else if (of_property_read_bool(suspend_np,
     231                 :            :                                         "regulator-off-in-suspend"))
     232                 :          0 :                         suspend_state->enabled = DISABLE_IN_SUSPEND;
     233                 :            : 
     234                 :          0 :                 if (!of_property_read_u32(suspend_np,
     235                 :            :                                 "regulator-suspend-min-microvolt", &pval))
     236                 :          0 :                         suspend_state->min_uV = pval;
     237                 :            : 
     238                 :          0 :                 if (!of_property_read_u32(suspend_np,
     239                 :            :                                 "regulator-suspend-max-microvolt", &pval))
     240                 :          0 :                         suspend_state->max_uV = pval;
     241                 :            : 
     242                 :          0 :                 if (!of_property_read_u32(suspend_np,
     243                 :            :                                         "regulator-suspend-microvolt", &pval))
     244                 :          0 :                         suspend_state->uV = pval;
     245                 :            :                 else /* otherwise use min_uV as default suspend voltage */
     246                 :          0 :                         suspend_state->uV = suspend_state->min_uV;
     247                 :            : 
     248                 :          0 :                 if (of_property_read_bool(suspend_np,
     249                 :            :                                         "regulator-changeable-in-suspend"))
     250                 :          0 :                         suspend_state->changeable = true;
     251                 :            : 
     252                 :          0 :                 if (i == PM_SUSPEND_MEM)
     253                 :          0 :                         constraints->initial_state = PM_SUSPEND_MEM;
     254                 :            : 
     255                 :          0 :                 of_node_put(suspend_np);
     256                 :            :                 suspend_state = NULL;
     257                 :            :                 suspend_np = NULL;
     258                 :            :         }
     259                 :            : 
     260                 :            :         return 0;
     261                 :            : }
     262                 :            : 
     263                 :            : /**
     264                 :            :  * of_get_regulator_init_data - extract regulator_init_data structure info
     265                 :            :  * @dev: device requesting for regulator_init_data
     266                 :            :  * @node: regulator device node
     267                 :            :  * @desc: regulator description
     268                 :            :  *
     269                 :            :  * Populates regulator_init_data structure by extracting data from device
     270                 :            :  * tree node, returns a pointer to the populated structure or NULL if memory
     271                 :            :  * alloc fails.
     272                 :            :  */
     273                 :          3 : struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
     274                 :            :                                           struct device_node *node,
     275                 :            :                                           const struct regulator_desc *desc)
     276                 :            : {
     277                 :            :         struct regulator_init_data *init_data;
     278                 :            : 
     279                 :          3 :         if (!node)
     280                 :            :                 return NULL;
     281                 :            : 
     282                 :          3 :         init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL);
     283                 :          3 :         if (!init_data)
     284                 :            :                 return NULL; /* Out of memory? */
     285                 :            : 
     286                 :          3 :         if (of_get_regulation_constraints(dev, node, &init_data, desc))
     287                 :            :                 return NULL;
     288                 :            : 
     289                 :          3 :         return init_data;
     290                 :            : }
     291                 :            : EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
     292                 :            : 
     293                 :            : struct devm_of_regulator_matches {
     294                 :            :         struct of_regulator_match *matches;
     295                 :            :         unsigned int num_matches;
     296                 :            : };
     297                 :            : 
     298                 :          0 : static void devm_of_regulator_put_matches(struct device *dev, void *res)
     299                 :            : {
     300                 :            :         struct devm_of_regulator_matches *devm_matches = res;
     301                 :            :         int i;
     302                 :            : 
     303                 :          0 :         for (i = 0; i < devm_matches->num_matches; i++)
     304                 :          0 :                 of_node_put(devm_matches->matches[i].of_node);
     305                 :          0 : }
     306                 :            : 
     307                 :            : /**
     308                 :            :  * of_regulator_match - extract multiple regulator init data from device tree.
     309                 :            :  * @dev: device requesting the data
     310                 :            :  * @node: parent device node of the regulators
     311                 :            :  * @matches: match table for the regulators
     312                 :            :  * @num_matches: number of entries in match table
     313                 :            :  *
     314                 :            :  * This function uses a match table specified by the regulator driver to
     315                 :            :  * parse regulator init data from the device tree. @node is expected to
     316                 :            :  * contain a set of child nodes, each providing the init data for one
     317                 :            :  * regulator. The data parsed from a child node will be matched to a regulator
     318                 :            :  * based on either the deprecated property regulator-compatible if present,
     319                 :            :  * or otherwise the child node's name. Note that the match table is modified
     320                 :            :  * in place and an additional of_node reference is taken for each matched
     321                 :            :  * regulator.
     322                 :            :  *
     323                 :            :  * Returns the number of matches found or a negative error code on failure.
     324                 :            :  */
     325                 :          0 : int of_regulator_match(struct device *dev, struct device_node *node,
     326                 :            :                        struct of_regulator_match *matches,
     327                 :            :                        unsigned int num_matches)
     328                 :            : {
     329                 :            :         unsigned int count = 0;
     330                 :            :         unsigned int i;
     331                 :            :         const char *name;
     332                 :            :         struct device_node *child;
     333                 :            :         struct devm_of_regulator_matches *devm_matches;
     334                 :            : 
     335                 :          0 :         if (!dev || !node)
     336                 :            :                 return -EINVAL;
     337                 :            : 
     338                 :            :         devm_matches = devres_alloc(devm_of_regulator_put_matches,
     339                 :            :                                     sizeof(struct devm_of_regulator_matches),
     340                 :            :                                     GFP_KERNEL);
     341                 :          0 :         if (!devm_matches)
     342                 :            :                 return -ENOMEM;
     343                 :            : 
     344                 :          0 :         devm_matches->matches = matches;
     345                 :          0 :         devm_matches->num_matches = num_matches;
     346                 :            : 
     347                 :          0 :         devres_add(dev, devm_matches);
     348                 :            : 
     349                 :          0 :         for (i = 0; i < num_matches; i++) {
     350                 :          0 :                 struct of_regulator_match *match = &matches[i];
     351                 :          0 :                 match->init_data = NULL;
     352                 :          0 :                 match->of_node = NULL;
     353                 :            :         }
     354                 :            : 
     355                 :          0 :         for_each_child_of_node(node, child) {
     356                 :          0 :                 name = of_get_property(child,
     357                 :            :                                         "regulator-compatible", NULL);
     358                 :          0 :                 if (!name)
     359                 :          0 :                         name = child->name;
     360                 :          0 :                 for (i = 0; i < num_matches; i++) {
     361                 :          0 :                         struct of_regulator_match *match = &matches[i];
     362                 :          0 :                         if (match->of_node)
     363                 :          0 :                                 continue;
     364                 :            : 
     365                 :          0 :                         if (strcmp(match->name, name))
     366                 :          0 :                                 continue;
     367                 :            : 
     368                 :          0 :                         match->init_data =
     369                 :          0 :                                 of_get_regulator_init_data(dev, child,
     370                 :            :                                                            match->desc);
     371                 :          0 :                         if (!match->init_data) {
     372                 :          0 :                                 dev_err(dev,
     373                 :            :                                         "failed to parse DT for regulator %pOFn\n",
     374                 :            :                                         child);
     375                 :          0 :                                 of_node_put(child);
     376                 :          0 :                                 return -EINVAL;
     377                 :            :                         }
     378                 :          0 :                         match->of_node = of_node_get(child);
     379                 :          0 :                         count++;
     380                 :          0 :                         break;
     381                 :            :                 }
     382                 :            :         }
     383                 :            : 
     384                 :          0 :         return count;
     385                 :            : }
     386                 :            : EXPORT_SYMBOL_GPL(of_regulator_match);
     387                 :            : 
     388                 :            : static struct
     389                 :          3 : device_node *regulator_of_get_init_node(struct device *dev,
     390                 :            :                                         const struct regulator_desc *desc)
     391                 :            : {
     392                 :            :         struct device_node *search, *child;
     393                 :            :         const char *name;
     394                 :            : 
     395                 :          3 :         if (!dev->of_node || !desc->of_match)
     396                 :            :                 return NULL;
     397                 :            : 
     398                 :          0 :         if (desc->regulators_node) {
     399                 :          0 :                 search = of_get_child_by_name(dev->of_node,
     400                 :            :                                               desc->regulators_node);
     401                 :            :         } else {
     402                 :          0 :                 search = of_node_get(dev->of_node);
     403                 :            : 
     404                 :          0 :                 if (!strcmp(desc->of_match, search->name))
     405                 :            :                         return search;
     406                 :            :         }
     407                 :            : 
     408                 :          0 :         if (!search) {
     409                 :            :                 dev_dbg(dev, "Failed to find regulator container node '%s'\n",
     410                 :            :                         desc->regulators_node);
     411                 :            :                 return NULL;
     412                 :            :         }
     413                 :            : 
     414                 :          0 :         for_each_available_child_of_node(search, child) {
     415                 :          0 :                 name = of_get_property(child, "regulator-compatible", NULL);
     416                 :          0 :                 if (!name)
     417                 :          0 :                         name = child->name;
     418                 :            : 
     419                 :          0 :                 if (!strcmp(desc->of_match, name)) {
     420                 :          0 :                         of_node_put(search);
     421                 :          0 :                         return of_node_get(child);
     422                 :            :                 }
     423                 :            :         }
     424                 :            : 
     425                 :          0 :         of_node_put(search);
     426                 :            : 
     427                 :          0 :         return NULL;
     428                 :            : }
     429                 :            : 
     430                 :          3 : struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
     431                 :            :                                             const struct regulator_desc *desc,
     432                 :            :                                             struct regulator_config *config,
     433                 :            :                                             struct device_node **node)
     434                 :            : {
     435                 :            :         struct device_node *child;
     436                 :            :         struct regulator_init_data *init_data = NULL;
     437                 :            : 
     438                 :          3 :         child = regulator_of_get_init_node(dev, desc);
     439                 :          3 :         if (!child)
     440                 :            :                 return NULL;
     441                 :            : 
     442                 :          0 :         init_data = of_get_regulator_init_data(dev, child, desc);
     443                 :          0 :         if (!init_data) {
     444                 :          0 :                 dev_err(dev, "failed to parse DT for regulator %pOFn\n", child);
     445                 :          0 :                 goto error;
     446                 :            :         }
     447                 :            : 
     448                 :          0 :         if (desc->of_parse_cb) {
     449                 :            :                 int ret;
     450                 :            : 
     451                 :          0 :                 ret = desc->of_parse_cb(child, desc, config);
     452                 :          0 :                 if (ret) {
     453                 :          0 :                         if (ret == -EPROBE_DEFER) {
     454                 :          0 :                                 of_node_put(child);
     455                 :          0 :                                 return ERR_PTR(-EPROBE_DEFER);
     456                 :            :                         }
     457                 :          0 :                         dev_err(dev,
     458                 :            :                                 "driver callback failed to parse DT for regulator %pOFn\n",
     459                 :            :                                 child);
     460                 :          0 :                         goto error;
     461                 :            :                 }
     462                 :            :         }
     463                 :            : 
     464                 :          0 :         *node = child;
     465                 :            : 
     466                 :          0 :         return init_data;
     467                 :            : 
     468                 :            : error:
     469                 :          0 :         of_node_put(child);
     470                 :            : 
     471                 :          0 :         return NULL;
     472                 :            : }
     473                 :            : 
     474                 :          0 : struct regulator_dev *of_find_regulator_by_node(struct device_node *np)
     475                 :            : {
     476                 :            :         struct device *dev;
     477                 :            : 
     478                 :            :         dev = class_find_device_by_of_node(&regulator_class, np);
     479                 :            : 
     480                 :          0 :         return dev ? dev_to_rdev(dev) : NULL;
     481                 :            : }
     482                 :            : 
     483                 :            : /*
     484                 :            :  * Returns number of regulators coupled with rdev.
     485                 :            :  */
     486                 :          3 : int of_get_n_coupled(struct regulator_dev *rdev)
     487                 :            : {
     488                 :          3 :         struct device_node *node = rdev->dev.of_node;
     489                 :            :         int n_phandles;
     490                 :            : 
     491                 :          3 :         n_phandles = of_count_phandle_with_args(node,
     492                 :            :                                                 "regulator-coupled-with",
     493                 :            :                                                 NULL);
     494                 :            : 
     495                 :          3 :         return (n_phandles > 0) ? n_phandles : 0;
     496                 :            : }
     497                 :            : 
     498                 :            : /* Looks for "to_find" device_node in src's "regulator-coupled-with" property */
     499                 :          0 : static bool of_coupling_find_node(struct device_node *src,
     500                 :            :                                   struct device_node *to_find,
     501                 :            :                                   int *index)
     502                 :            : {
     503                 :            :         int n_phandles, i;
     504                 :            :         bool found = false;
     505                 :            : 
     506                 :          0 :         n_phandles = of_count_phandle_with_args(src,
     507                 :            :                                                 "regulator-coupled-with",
     508                 :            :                                                 NULL);
     509                 :            : 
     510                 :          0 :         for (i = 0; i < n_phandles; i++) {
     511                 :          0 :                 struct device_node *tmp = of_parse_phandle(src,
     512                 :            :                                            "regulator-coupled-with", i);
     513                 :            : 
     514                 :          0 :                 if (!tmp)
     515                 :            :                         break;
     516                 :            : 
     517                 :            :                 /* found */
     518                 :          0 :                 if (tmp == to_find)
     519                 :            :                         found = true;
     520                 :            : 
     521                 :          0 :                 of_node_put(tmp);
     522                 :            : 
     523                 :          0 :                 if (found) {
     524                 :          0 :                         *index = i;
     525                 :          0 :                         break;
     526                 :            :                 }
     527                 :            :         }
     528                 :            : 
     529                 :          0 :         return found;
     530                 :            : }
     531                 :            : 
     532                 :            : /**
     533                 :            :  * of_check_coupling_data - Parse rdev's coupling properties and check data
     534                 :            :  *                          consistency
     535                 :            :  * @rdev - pointer to regulator_dev whose data is checked
     536                 :            :  *
     537                 :            :  * Function checks if all the following conditions are met:
     538                 :            :  * - rdev's max_spread is greater than 0
     539                 :            :  * - all coupled regulators have the same max_spread
     540                 :            :  * - all coupled regulators have the same number of regulator_dev phandles
     541                 :            :  * - all regulators are linked to each other
     542                 :            :  *
     543                 :            :  * Returns true if all conditions are met.
     544                 :            :  */
     545                 :          0 : bool of_check_coupling_data(struct regulator_dev *rdev)
     546                 :            : {
     547                 :          0 :         struct device_node *node = rdev->dev.of_node;
     548                 :            :         int n_phandles = of_get_n_coupled(rdev);
     549                 :            :         struct device_node *c_node;
     550                 :            :         int index;
     551                 :            :         int i;
     552                 :            :         bool ret = true;
     553                 :            : 
     554                 :            :         /* iterate over rdev's phandles */
     555                 :          0 :         for (i = 0; i < n_phandles; i++) {
     556                 :          0 :                 int max_spread = rdev->constraints->max_spread[i];
     557                 :            :                 int c_max_spread, c_n_phandles;
     558                 :            : 
     559                 :          0 :                 if (max_spread <= 0) {
     560                 :          0 :                         dev_err(&rdev->dev, "max_spread value invalid\n");
     561                 :          0 :                         return false;
     562                 :            :                 }
     563                 :            : 
     564                 :          0 :                 c_node = of_parse_phandle(node,
     565                 :            :                                           "regulator-coupled-with", i);
     566                 :            : 
     567                 :          0 :                 if (!c_node)
     568                 :            :                         ret = false;
     569                 :            : 
     570                 :          0 :                 c_n_phandles = of_count_phandle_with_args(c_node,
     571                 :            :                                                           "regulator-coupled-with",
     572                 :            :                                                           NULL);
     573                 :            : 
     574                 :          0 :                 if (c_n_phandles != n_phandles) {
     575                 :          0 :                         dev_err(&rdev->dev, "number of coupled reg phandles mismatch\n");
     576                 :            :                         ret = false;
     577                 :          0 :                         goto clean;
     578                 :            :                 }
     579                 :            : 
     580                 :          0 :                 if (!of_coupling_find_node(c_node, node, &index)) {
     581                 :          0 :                         dev_err(&rdev->dev, "missing 2-way linking for coupled regulators\n");
     582                 :            :                         ret = false;
     583                 :          0 :                         goto clean;
     584                 :            :                 }
     585                 :            : 
     586                 :          0 :                 if (of_property_read_u32_index(c_node, "regulator-coupled-max-spread",
     587                 :            :                                                index, &c_max_spread)) {
     588                 :            :                         ret = false;
     589                 :            :                         goto clean;
     590                 :            :                 }
     591                 :            : 
     592                 :          0 :                 if (c_max_spread != max_spread) {
     593                 :          0 :                         dev_err(&rdev->dev,
     594                 :            :                                 "coupled regulators max_spread mismatch\n");
     595                 :            :                         ret = false;
     596                 :          0 :                         goto clean;
     597                 :            :                 }
     598                 :            : 
     599                 :            : clean:
     600                 :          0 :                 of_node_put(c_node);
     601                 :          0 :                 if (!ret)
     602                 :            :                         break;
     603                 :            :         }
     604                 :            : 
     605                 :          0 :         return ret;
     606                 :            : }
     607                 :            : 
     608                 :            : /**
     609                 :            :  * of_parse_coupled regulator - Get regulator_dev pointer from rdev's property
     610                 :            :  * @rdev: Pointer to regulator_dev, whose DTS is used as a source to parse
     611                 :            :  *        "regulator-coupled-with" property
     612                 :            :  * @index: Index in phandles array
     613                 :            :  *
     614                 :            :  * Returns the regulator_dev pointer parsed from DTS. If it has not been yet
     615                 :            :  * registered, returns NULL
     616                 :            :  */
     617                 :          0 : struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev,
     618                 :            :                                                  int index)
     619                 :            : {
     620                 :          0 :         struct device_node *node = rdev->dev.of_node;
     621                 :            :         struct device_node *c_node;
     622                 :            :         struct regulator_dev *c_rdev;
     623                 :            : 
     624                 :          0 :         c_node = of_parse_phandle(node, "regulator-coupled-with", index);
     625                 :          0 :         if (!c_node)
     626                 :            :                 return NULL;
     627                 :            : 
     628                 :          0 :         c_rdev = of_find_regulator_by_node(c_node);
     629                 :            : 
     630                 :          0 :         of_node_put(c_node);
     631                 :            : 
     632                 :          0 :         return c_rdev;
     633                 :            : }
    

Generated by: LCOV version 1.14