From 08f87f769b595151be1afeff53e144f543faa614 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 06 Dec 2023 09:51:13 +0000 Subject: [PATCH] add dts config --- kernel/drivers/regulator/of_regulator.c | 219 ++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 137 insertions(+), 82 deletions(-) diff --git a/kernel/drivers/regulator/of_regulator.c b/kernel/drivers/regulator/of_regulator.c index b255590..b11a434 100644 --- a/kernel/drivers/regulator/of_regulator.c +++ b/kernel/drivers/regulator/of_regulator.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * OF helpers for regulator framework * * Copyright (C) 2011 Texas Instruments, Inc. * Rajendra Nayak <rnayak@ti.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <linux/module.h> @@ -20,11 +16,13 @@ #include "internal.h" static const char *const regulator_states[PM_SUSPEND_MAX + 1] = { + [PM_SUSPEND_STANDBY] = "regulator-state-standby", [PM_SUSPEND_MEM] = "regulator-state-mem", [PM_SUSPEND_MAX] = "regulator-state-disk", }; -static void of_get_regulation_constraints(struct device_node *np, +static int of_get_regulation_constraints(struct device *dev, + struct device_node *np, struct regulator_init_data **init_data, const struct regulator_desc *desc) { @@ -33,7 +31,12 @@ struct device_node *suspend_np; unsigned int mode; int ret, i, len; + int n_phandles; u32 pval; + + n_phandles = of_count_phandle_with_args(np, "regulator-coupled-with", + NULL); + n_phandles = max(n_phandles, 0); constraints->name = of_get_property(np, "regulator-name", NULL); @@ -95,8 +98,8 @@ if (!ret) constraints->settling_time_up = pval; if (constraints->settling_time_up && constraints->settling_time) { - pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n", - np->name); + pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n", + np); constraints->settling_time_up = 0; } @@ -105,8 +108,8 @@ if (!ret) constraints->settling_time_down = pval; if (constraints->settling_time_down && constraints->settling_time) { - pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n", - np->name); + pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n", + np); constraints->settling_time_down = 0; } @@ -127,12 +130,12 @@ if (desc && desc->of_map_mode) { mode = desc->of_map_mode(pval); if (mode == REGULATOR_MODE_INVALID) - pr_err("%s: invalid mode %u\n", np->name, pval); + pr_err("%pOFn: invalid mode %u\n", np, pval); else constraints->initial_mode = mode; } else { - pr_warn("%s: mapping for mode %d not defined\n", - np->name, pval); + pr_warn("%pOFn: mapping for mode %d not defined\n", + np, pval); } } @@ -144,14 +147,14 @@ ret = of_property_read_u32_index(np, "regulator-allowed-modes", i, &pval); if (ret) { - pr_err("%s: couldn't read allowed modes index %d, ret=%d\n", - np->name, i, ret); + pr_err("%pOFn: couldn't read allowed modes index %d, ret=%d\n", + np, i, ret); break; } mode = desc->of_map_mode(pval); if (mode == REGULATOR_MODE_INVALID) - pr_err("%s: invalid regulator-allowed-modes element %u\n", - np->name, pval); + pr_err("%pOFn: invalid regulator-allowed-modes element %u\n", + np, pval); else constraints->valid_modes_mask |= mode; } @@ -159,16 +162,28 @@ constraints->valid_ops_mask |= REGULATOR_CHANGE_MODE; } else { - pr_warn("%s: mode mapping not defined\n", np->name); + pr_warn("%pOFn: mode mapping not defined\n", np); } } if (!of_property_read_u32(np, "regulator-system-load", &pval)) constraints->system_load = pval; - if (!of_property_read_u32(np, "regulator-coupled-max-spread", + if (n_phandles) { + constraints->max_spread = devm_kzalloc(dev, + sizeof(*constraints->max_spread) * n_phandles, + GFP_KERNEL); + + if (!constraints->max_spread) + return -ENOMEM; + + of_property_read_u32_array(np, "regulator-coupled-max-spread", + constraints->max_spread, n_phandles); + } + + if (!of_property_read_u32(np, "regulator-max-step-microvolt", &pval)) - constraints->max_spread = pval; + constraints->max_uV_step = pval; constraints->over_current_protection = of_property_read_bool(np, "regulator-over-current-protection"); @@ -181,29 +196,35 @@ case PM_SUSPEND_MAX: suspend_state = &constraints->state_disk; break; + case PM_SUSPEND_STANDBY: + suspend_state = &constraints->state_standby; + break; case PM_SUSPEND_ON: case PM_SUSPEND_TO_IDLE: - case PM_SUSPEND_STANDBY: default: continue; } suspend_np = of_get_child_by_name(np, regulator_states[i]); - if (!suspend_np || !suspend_state) + if (!suspend_np) continue; + if (!suspend_state) { + of_node_put(suspend_np); + continue; + } if (!of_property_read_u32(suspend_np, "regulator-mode", &pval)) { if (desc && desc->of_map_mode) { mode = desc->of_map_mode(pval); if (mode == REGULATOR_MODE_INVALID) - pr_err("%s: invalid mode %u\n", - np->name, pval); + pr_err("%pOFn: invalid mode %u\n", + np, pval); else suspend_state->mode = mode; } else { - pr_warn("%s: mapping for mode %d not defined\n", - np->name, pval); + pr_warn("%pOFn: mapping for mode %d not defined\n", + np, pval); } } @@ -239,6 +260,8 @@ suspend_state = NULL; suspend_np = NULL; } + + return 0; } /** @@ -248,7 +271,7 @@ * @desc: regulator description * * Populates regulator_init_data structure by extracting data from device - * tree node, returns a pointer to the populated struture or NULL if memory + * tree node, returns a pointer to the populated structure or NULL if memory * alloc fails. */ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, @@ -264,7 +287,9 @@ if (!init_data) return NULL; /* Out of memory? */ - of_get_regulation_constraints(node, &init_data, desc); + if (of_get_regulation_constraints(dev, node, &init_data, desc)) + return NULL; + return init_data; } EXPORT_SYMBOL_GPL(of_get_regulator_init_data); @@ -349,8 +374,8 @@ match->desc); if (!match->init_data) { dev_err(dev, - "failed to parse DT for regulator %s\n", - child->name); + "failed to parse DT for regulator %pOFn\n", + child); of_node_put(child); return -EINVAL; } @@ -364,23 +389,25 @@ } EXPORT_SYMBOL_GPL(of_regulator_match); -struct regulator_init_data *regulator_of_get_init_data(struct device *dev, - const struct regulator_desc *desc, - struct regulator_config *config, - struct device_node **node) +static struct +device_node *regulator_of_get_init_node(struct device *dev, + const struct regulator_desc *desc) { struct device_node *search, *child; - struct regulator_init_data *init_data = NULL; const char *name; if (!dev->of_node || !desc->of_match) return NULL; - if (desc->regulators_node) + if (desc->regulators_node) { search = of_get_child_by_name(dev->of_node, desc->regulators_node); - else + } else { search = of_node_get(dev->of_node); + + if (!strcmp(desc->of_match, search->name)) + return search; + } if (!search) { dev_dbg(dev, "Failed to find regulator container node '%s'\n", @@ -390,50 +417,73 @@ for_each_available_child_of_node(search, child) { name = of_get_property(child, "regulator-compatible", NULL); - if (!name) - name = child->name; - - if (strcmp(desc->of_match, name)) - continue; - - init_data = of_get_regulator_init_data(dev, child, desc); - if (!init_data) { - dev_err(dev, - "failed to parse DT for regulator %s\n", - child->name); - break; + if (!name) { + if (!desc->of_match_full_name) + name = child->name; + else + name = child->full_name; } - if (desc->of_parse_cb) { - if (desc->of_parse_cb(child, desc, config)) { - dev_err(dev, - "driver callback failed to parse DT for regulator %s\n", - child->name); - init_data = NULL; - break; - } + if (!strcmp(desc->of_match, name)) { + of_node_put(search); + return of_node_get(child); } - - of_node_get(child); - *node = child; - break; } of_node_put(search); - return init_data; + return NULL; } -static int of_node_match(struct device *dev, const void *data) +struct regulator_init_data *regulator_of_get_init_data(struct device *dev, + const struct regulator_desc *desc, + struct regulator_config *config, + struct device_node **node) { - return dev->of_node == data; + struct device_node *child; + struct regulator_init_data *init_data = NULL; + + child = regulator_of_get_init_node(dev, desc); + if (!child) + return NULL; + + init_data = of_get_regulator_init_data(dev, child, desc); + if (!init_data) { + dev_err(dev, "failed to parse DT for regulator %pOFn\n", child); + goto error; + } + + if (desc->of_parse_cb) { + int ret; + + ret = desc->of_parse_cb(child, desc, config); + if (ret) { + if (ret == -EPROBE_DEFER) { + of_node_put(child); + return ERR_PTR(-EPROBE_DEFER); + } + dev_err(dev, + "driver callback failed to parse DT for regulator %pOFn\n", + child); + goto error; + } + } + + *node = child; + + return init_data; + +error: + of_node_put(child); + + return NULL; } struct regulator_dev *of_find_regulator_by_node(struct device_node *np) { struct device *dev; - dev = class_find_device(®ulator_class, NULL, np, of_node_match); + dev = class_find_device_by_of_node(®ulator_class, np); return dev ? dev_to_rdev(dev) : NULL; } @@ -455,7 +505,8 @@ /* Looks for "to_find" device_node in src's "regulator-coupled-with" property */ static bool of_coupling_find_node(struct device_node *src, - struct device_node *to_find) + struct device_node *to_find, + int *index) { int n_phandles, i; bool found = false; @@ -477,8 +528,10 @@ of_node_put(tmp); - if (found) + if (found) { + *index = i; break; + } } return found; @@ -487,7 +540,7 @@ /** * of_check_coupling_data - Parse rdev's coupling properties and check data * consistency - * @rdev - pointer to regulator_dev whose data is checked + * @rdev: pointer to regulator_dev whose data is checked * * Function checks if all the following conditions are met: * - rdev's max_spread is greater than 0 @@ -499,21 +552,22 @@ */ bool of_check_coupling_data(struct regulator_dev *rdev) { - int max_spread = rdev->constraints->max_spread; struct device_node *node = rdev->dev.of_node; int n_phandles = of_get_n_coupled(rdev); struct device_node *c_node; + int index; int i; bool ret = true; - if (max_spread <= 0) { - dev_err(&rdev->dev, "max_spread value invalid\n"); - return false; - } - /* iterate over rdev's phandles */ for (i = 0; i < n_phandles; i++) { + int max_spread = rdev->constraints->max_spread[i]; int c_max_spread, c_n_phandles; + + if (max_spread <= 0) { + dev_err(&rdev->dev, "max_spread value invalid\n"); + return false; + } c_node = of_parse_phandle(node, "regulator-coupled-with", i); @@ -526,13 +580,19 @@ NULL); if (c_n_phandles != n_phandles) { - dev_err(&rdev->dev, "number of couped reg phandles mismatch\n"); + dev_err(&rdev->dev, "number of coupled reg phandles mismatch\n"); ret = false; goto clean; } - if (of_property_read_u32(c_node, "regulator-coupled-max-spread", - &c_max_spread)) { + if (!of_coupling_find_node(c_node, node, &index)) { + dev_err(&rdev->dev, "missing 2-way linking for coupled regulators\n"); + ret = false; + goto clean; + } + + if (of_property_read_u32_index(c_node, "regulator-coupled-max-spread", + index, &c_max_spread)) { ret = false; goto clean; } @@ -542,11 +602,6 @@ "coupled regulators max_spread mismatch\n"); ret = false; goto clean; - } - - if (!of_coupling_find_node(c_node, node)) { - dev_err(&rdev->dev, "missing 2-way linking for coupled regulators\n"); - ret = false; } clean: -- Gitblit v1.6.2