Skip to content

Commit d8ca7d1

Browse files
digetxbroonie
authored andcommitted
regulator: core: Introduce API for regulators coupling customization
Right now regulator core supports only one type of regulators coupling, the "voltage max-spread" which keeps voltages of coupled regulators in a given range from each other. A more sophisticated coupling may be required in practice, one example is the NVIDIA Tegra SoCs which besides the max-spreading have other restrictions that must be adhered. Introduce API that allow platforms to provide their own customized coupling algorithms. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent a188339 commit d8ca7d1

File tree

5 files changed

+225
-44
lines changed

5 files changed

+225
-44
lines changed

drivers/regulator/core.c

+116-20
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/regmap.h>
2929
#include <linux/regulator/of_regulator.h>
3030
#include <linux/regulator/consumer.h>
31+
#include <linux/regulator/coupler.h>
3132
#include <linux/regulator/driver.h>
3233
#include <linux/regulator/machine.h>
3334
#include <linux/module.h>
@@ -55,6 +56,7 @@ static DEFINE_MUTEX(regulator_list_mutex);
5556
static LIST_HEAD(regulator_map_list);
5657
static LIST_HEAD(regulator_ena_gpio_list);
5758
static LIST_HEAD(regulator_supply_alias_list);
59+
static LIST_HEAD(regulator_coupler_list);
5860
static bool has_full_constraints;
5961

6062
static struct dentry *debugfs_root;
@@ -3439,11 +3441,10 @@ static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
34393441
struct coupling_desc *c_desc = &rdev->coupling_desc;
34403442
struct regulator_dev **c_rdevs = c_desc->coupled_rdevs;
34413443
struct regulation_constraints *constraints = rdev->constraints;
3442-
int max_spread = constraints->max_spread;
34433444
int desired_min_uV = 0, desired_max_uV = INT_MAX;
34443445
int max_current_uV = 0, min_current_uV = INT_MAX;
34453446
int highest_min_uV = 0, target_uV, possible_uV;
3446-
int i, ret;
3447+
int i, ret, max_spread;
34473448
bool done;
34483449

34493450
*current_uV = -1;
@@ -3497,6 +3498,8 @@ static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
34973498
}
34983499
}
34993500

3501+
max_spread = constraints->max_spread[0];
3502+
35003503
/*
35013504
* Let target_uV be equal to the desired one if possible.
35023505
* If not, set it to minimum voltage, allowed by other coupled
@@ -3578,9 +3581,11 @@ static int regulator_balance_voltage(struct regulator_dev *rdev,
35783581
struct regulator_dev **c_rdevs;
35793582
struct regulator_dev *best_rdev;
35803583
struct coupling_desc *c_desc = &rdev->coupling_desc;
3584+
struct regulator_coupler *coupler = c_desc->coupler;
35813585
int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev;
3582-
bool best_c_rdev_done, c_rdev_done[MAX_COUPLED];
35833586
unsigned int delta, best_delta;
3587+
unsigned long c_rdev_done = 0;
3588+
bool best_c_rdev_done;
35843589

35853590
c_rdevs = c_desc->coupled_rdevs;
35863591
n_coupled = c_desc->n_coupled;
@@ -3597,8 +3602,9 @@ static int regulator_balance_voltage(struct regulator_dev *rdev,
35973602
return -EPERM;
35983603
}
35993604

3600-
for (i = 0; i < n_coupled; i++)
3601-
c_rdev_done[i] = false;
3605+
/* Invoke custom balancer for customized couplers */
3606+
if (coupler && coupler->balance_voltage)
3607+
return coupler->balance_voltage(coupler, rdev, state);
36023608

36033609
/*
36043610
* Find the best possible voltage change on each loop. Leave the loop
@@ -3625,7 +3631,7 @@ static int regulator_balance_voltage(struct regulator_dev *rdev,
36253631
*/
36263632
int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0;
36273633

3628-
if (c_rdev_done[i])
3634+
if (test_bit(i, &c_rdev_done))
36293635
continue;
36303636

36313637
ret = regulator_get_optimal_voltage(c_rdevs[i],
@@ -3660,7 +3666,8 @@ static int regulator_balance_voltage(struct regulator_dev *rdev,
36603666
if (ret < 0)
36613667
goto out;
36623668

3663-
c_rdev_done[best_c_rdev] = best_c_rdev_done;
3669+
if (best_c_rdev_done)
3670+
set_bit(best_c_rdev, &c_rdev_done);
36643671

36653672
} while (n_coupled > 1);
36663673

@@ -4712,8 +4719,60 @@ static int regulator_register_resolve_supply(struct device *dev, void *data)
47124719
return 0;
47134720
}
47144721

4722+
int regulator_coupler_register(struct regulator_coupler *coupler)
4723+
{
4724+
mutex_lock(&regulator_list_mutex);
4725+
list_add_tail(&coupler->list, &regulator_coupler_list);
4726+
mutex_unlock(&regulator_list_mutex);
4727+
4728+
return 0;
4729+
}
4730+
4731+
static struct regulator_coupler *
4732+
regulator_find_coupler(struct regulator_dev *rdev)
4733+
{
4734+
struct regulator_coupler *coupler;
4735+
int err;
4736+
4737+
/*
4738+
* Note that regulators are appended to the list and the generic
4739+
* coupler is registered first, hence it will be attached at last
4740+
* if nobody cared.
4741+
*/
4742+
list_for_each_entry_reverse(coupler, &regulator_coupler_list, list) {
4743+
err = coupler->attach_regulator(coupler, rdev);
4744+
if (!err) {
4745+
if (!coupler->balance_voltage &&
4746+
rdev->coupling_desc.n_coupled > 2)
4747+
goto err_unsupported;
4748+
4749+
return coupler;
4750+
}
4751+
4752+
if (err < 0)
4753+
return ERR_PTR(err);
4754+
4755+
if (err == 1)
4756+
continue;
4757+
4758+
break;
4759+
}
4760+
4761+
return ERR_PTR(-EINVAL);
4762+
4763+
err_unsupported:
4764+
if (coupler->detach_regulator)
4765+
coupler->detach_regulator(coupler, rdev);
4766+
4767+
rdev_err(rdev,
4768+
"Voltage balancing for multiple regulator couples is unimplemented\n");
4769+
4770+
return ERR_PTR(-EPERM);
4771+
}
4772+
47154773
static void regulator_resolve_coupling(struct regulator_dev *rdev)
47164774
{
4775+
struct regulator_coupler *coupler = rdev->coupling_desc.coupler;
47174776
struct coupling_desc *c_desc = &rdev->coupling_desc;
47184777
int n_coupled = c_desc->n_coupled;
47194778
struct regulator_dev *c_rdev;
@@ -4729,6 +4788,12 @@ static void regulator_resolve_coupling(struct regulator_dev *rdev)
47294788
if (!c_rdev)
47304789
continue;
47314790

4791+
if (c_rdev->coupling_desc.coupler != coupler) {
4792+
rdev_err(rdev, "coupler mismatch with %s\n",
4793+
rdev_get_name(c_rdev));
4794+
return;
4795+
}
4796+
47324797
regulator_lock(c_rdev);
47334798

47344799
c_desc->coupled_rdevs[i] = c_rdev;
@@ -4742,10 +4807,12 @@ static void regulator_resolve_coupling(struct regulator_dev *rdev)
47424807

47434808
static void regulator_remove_coupling(struct regulator_dev *rdev)
47444809
{
4810+
struct regulator_coupler *coupler = rdev->coupling_desc.coupler;
47454811
struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc;
47464812
struct regulator_dev *__c_rdev, *c_rdev;
47474813
unsigned int __n_coupled, n_coupled;
47484814
int i, k;
4815+
int err;
47494816

47504817
n_coupled = c_desc->n_coupled;
47514818

@@ -4775,21 +4842,33 @@ static void regulator_remove_coupling(struct regulator_dev *rdev)
47754842
c_desc->coupled_rdevs[i] = NULL;
47764843
c_desc->n_resolved--;
47774844
}
4845+
4846+
if (coupler && coupler->detach_regulator) {
4847+
err = coupler->detach_regulator(coupler, rdev);
4848+
if (err)
4849+
rdev_err(rdev, "failed to detach from coupler: %d\n",
4850+
err);
4851+
}
4852+
4853+
kfree(rdev->coupling_desc.coupled_rdevs);
4854+
rdev->coupling_desc.coupled_rdevs = NULL;
47784855
}
47794856

47804857
static int regulator_init_coupling(struct regulator_dev *rdev)
47814858
{
4782-
int n_phandles;
4859+
int err, n_phandles;
4860+
size_t alloc_size;
47834861

47844862
if (!IS_ENABLED(CONFIG_OF))
47854863
n_phandles = 0;
47864864
else
47874865
n_phandles = of_get_n_coupled(rdev);
47884866

4789-
if (n_phandles + 1 > MAX_COUPLED) {
4790-
rdev_err(rdev, "too many regulators coupled\n");
4791-
return -EPERM;
4792-
}
4867+
alloc_size = sizeof(*rdev) * (n_phandles + 1);
4868+
4869+
rdev->coupling_desc.coupled_rdevs = kzalloc(alloc_size, GFP_KERNEL);
4870+
if (!rdev->coupling_desc.coupled_rdevs)
4871+
return -ENOMEM;
47934872

47944873
/*
47954874
* Every regulator should always have coupling descriptor filled with
@@ -4803,23 +4882,35 @@ static int regulator_init_coupling(struct regulator_dev *rdev)
48034882
if (n_phandles == 0)
48044883
return 0;
48054884

4806-
/* regulator, which can't change its voltage, can't be coupled */
4807-
if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
4808-
rdev_err(rdev, "voltage operation not allowed\n");
4885+
if (!of_check_coupling_data(rdev))
48094886
return -EPERM;
4810-
}
48114887

4812-
if (rdev->constraints->max_spread <= 0) {
4813-
rdev_err(rdev, "wrong max_spread value\n");
4814-
return -EPERM;
4888+
rdev->coupling_desc.coupler = regulator_find_coupler(rdev);
4889+
if (IS_ERR(rdev->coupling_desc.coupler)) {
4890+
err = PTR_ERR(rdev->coupling_desc.coupler);
4891+
rdev_err(rdev, "failed to get coupler: %d\n", err);
4892+
return err;
48154893
}
48164894

4817-
if (!of_check_coupling_data(rdev))
4895+
return 0;
4896+
}
4897+
4898+
static int generic_coupler_attach(struct regulator_coupler *coupler,
4899+
struct regulator_dev *rdev)
4900+
{
4901+
if (rdev->coupling_desc.n_coupled > 2) {
4902+
rdev_err(rdev,
4903+
"Voltage balancing for multiple regulator couples is unimplemented\n");
48184904
return -EPERM;
4905+
}
48194906

48204907
return 0;
48214908
}
48224909

4910+
static struct regulator_coupler generic_regulator_coupler = {
4911+
.attach_regulator = generic_coupler_attach,
4912+
};
4913+
48234914
/**
48244915
* regulator_register - register regulator
48254916
* @regulator_desc: regulator to register
@@ -4981,7 +5072,9 @@ regulator_register(const struct regulator_desc *regulator_desc,
49815072
if (ret < 0)
49825073
goto wash;
49835074

5075+
mutex_lock(&regulator_list_mutex);
49845076
ret = regulator_init_coupling(rdev);
5077+
mutex_unlock(&regulator_list_mutex);
49855078
if (ret < 0)
49865079
goto wash;
49875080

@@ -5030,6 +5123,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
50305123
unset_supplies:
50315124
mutex_lock(&regulator_list_mutex);
50325125
unset_regulator_supplies(rdev);
5126+
regulator_remove_coupling(rdev);
50335127
mutex_unlock(&regulator_list_mutex);
50345128
wash:
50355129
kfree(rdev->constraints);
@@ -5485,6 +5579,8 @@ static int __init regulator_init(void)
54855579
#endif
54865580
regulator_dummy_init();
54875581

5582+
regulator_coupler_register(&generic_regulator_coupler);
5583+
54885584
return ret;
54895585
}
54905586

0 commit comments

Comments
 (0)