diff options
-rw-r--r-- | Documentation/admin-guide/kernel-parameters.txt | 7 | ||||
-rw-r--r-- | drivers/regulator/core.c | 73 | ||||
-rw-r--r-- | drivers/regulator/palmas-regulator.c | 2 | ||||
-rw-r--r-- | drivers/regulator/stpmic1_regulator.c | 2 |
4 files changed, 56 insertions, 28 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 65731b060e3f..825159394da2 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -5544,6 +5544,13 @@ print every Nth verbose statement, where N is the value specified. + regulator_ignore_unused + [REGULATOR] + Prevents regulator framework from disabling regulators + that are unused, due no driver claiming them. This may + be useful for debug and development, but should not be + needed on a platform with proper driver support. + relax_domain_level= [KNL, SMP] Set scheduler's default relax_domain_level. See Documentation/admin-guide/cgroup-v1/cpusets.rst. diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 3137e40fcd3e..00221ff369c2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2918,7 +2918,8 @@ static int _regulator_enable(struct regulator *regulator) /* Fallthrough on positive return values - already enabled */ } - rdev->use_count++; + if (regulator->enable_count == 1) + rdev->use_count++; return 0; @@ -2993,37 +2994,40 @@ static int _regulator_disable(struct regulator *regulator) lockdep_assert_held_once(&rdev->mutex.base); - if (WARN(rdev->use_count <= 0, + if (WARN(regulator->enable_count == 0, "unbalanced disables for %s\n", rdev_get_name(rdev))) return -EIO; - /* are we the last user and permitted to disable ? */ - if (rdev->use_count == 1 && - (rdev->constraints && !rdev->constraints->always_on)) { - - /* we are last user */ - if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { - ret = _notifier_call_chain(rdev, - REGULATOR_EVENT_PRE_DISABLE, - NULL); - if (ret & NOTIFY_STOP_MASK) - return -EINVAL; - - ret = _regulator_do_disable(rdev); - if (ret < 0) { - rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret)); - _notifier_call_chain(rdev, - REGULATOR_EVENT_ABORT_DISABLE, + if (regulator->enable_count == 1) { + /* disabling last enable_count from this regulator */ + /* are we the last user and permitted to disable ? */ + if (rdev->use_count == 1 && + (rdev->constraints && !rdev->constraints->always_on)) { + + /* we are last user */ + if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { + ret = _notifier_call_chain(rdev, + REGULATOR_EVENT_PRE_DISABLE, + NULL); + if (ret & NOTIFY_STOP_MASK) + return -EINVAL; + + ret = _regulator_do_disable(rdev); + if (ret < 0) { + rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret)); + _notifier_call_chain(rdev, + REGULATOR_EVENT_ABORT_DISABLE, + NULL); + return ret; + } + _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, NULL); - return ret; } - _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, - NULL); - } - rdev->use_count = 0; - } else if (rdev->use_count > 1) { - rdev->use_count--; + rdev->use_count = 0; + } else if (rdev->use_count > 1) { + rdev->use_count--; + } } if (ret == 0) @@ -6234,6 +6238,14 @@ unlock: return 0; } +static bool regulator_ignore_unused; +static int __init regulator_ignore_unused_setup(char *__unused) +{ + regulator_ignore_unused = true; + return 1; +} +__setup("regulator_ignore_unused", regulator_ignore_unused_setup); + static void regulator_init_complete_work_function(struct work_struct *work) { /* @@ -6246,6 +6258,15 @@ static void regulator_init_complete_work_function(struct work_struct *work) class_for_each_device(®ulator_class, NULL, NULL, regulator_register_resolve_supply); + /* + * For debugging purposes, it may be useful to prevent unused + * regulators from being disabled. + */ + if (regulator_ignore_unused) { + pr_warn("regulator: Not disabling unused regulators\n"); + return; + } + /* If we have a full configuration then disable any regulators * we have permission to change the status for and which are * not in use or always_on. This is effectively the default diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index e0dc033aae0f..60656a815b9e 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -1594,7 +1594,7 @@ static const struct of_device_id of_palmas_match_tbl[] = { static int palmas_regulators_probe(struct platform_device *pdev) { struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); - struct palmas_pmic_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct palmas_pmic_platform_data *pdata; struct device_node *node = pdev->dev.of_node; struct palmas_pmic_driver_data *driver_data; struct regulator_config config = { }; diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c index 79d1a3eb18d4..a498df7cb016 100644 --- a/drivers/regulator/stpmic1_regulator.c +++ b/drivers/regulator/stpmic1_regulator.c @@ -15,7 +15,7 @@ #include <dt-bindings/mfd/st,stpmic1.h> /** - * struct stpmic1 regulator description: this structure is used as driver data + * struct stpmic1_regulator_cfg - this structure is used as driver data * @desc: regulator framework description * @mask_reset_reg: mask reset register address * @mask_reset_mask: mask rank and mask reset register mask |