1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4*4882a593Smuzhiyun * http://www.samsung.com/
5*4882a593Smuzhiyun * Author: Marek Szyprowski <m.szyprowski@samsung.com>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Simplified generic voltage coupler from regulator core.c
8*4882a593Smuzhiyun * The main difference is that it keeps current regulator voltage
9*4882a593Smuzhiyun * if consumers didn't apply their constraints yet.
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/of.h>
15*4882a593Smuzhiyun #include <linux/regulator/coupler.h>
16*4882a593Smuzhiyun #include <linux/regulator/driver.h>
17*4882a593Smuzhiyun #include <linux/regulator/machine.h>
18*4882a593Smuzhiyun
regulator_get_optimal_voltage(struct regulator_dev * rdev,int * current_uV,int * min_uV,int * max_uV,suspend_state_t state)19*4882a593Smuzhiyun static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
20*4882a593Smuzhiyun int *current_uV,
21*4882a593Smuzhiyun int *min_uV, int *max_uV,
22*4882a593Smuzhiyun suspend_state_t state)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun struct coupling_desc *c_desc = &rdev->coupling_desc;
25*4882a593Smuzhiyun struct regulator_dev **c_rdevs = c_desc->coupled_rdevs;
26*4882a593Smuzhiyun struct regulation_constraints *constraints = rdev->constraints;
27*4882a593Smuzhiyun int desired_min_uV = 0, desired_max_uV = INT_MAX;
28*4882a593Smuzhiyun int max_current_uV = 0, min_current_uV = INT_MAX;
29*4882a593Smuzhiyun int highest_min_uV = 0, target_uV, possible_uV;
30*4882a593Smuzhiyun int i, ret, max_spread, n_coupled = c_desc->n_coupled;
31*4882a593Smuzhiyun bool done;
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun *current_uV = -1;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /* Find highest min desired voltage */
36*4882a593Smuzhiyun for (i = 0; i < n_coupled; i++) {
37*4882a593Smuzhiyun int tmp_min = 0;
38*4882a593Smuzhiyun int tmp_max = INT_MAX;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun lockdep_assert_held_once(&c_rdevs[i]->mutex.base);
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun ret = regulator_check_consumers(c_rdevs[i],
43*4882a593Smuzhiyun &tmp_min,
44*4882a593Smuzhiyun &tmp_max, state);
45*4882a593Smuzhiyun if (ret < 0)
46*4882a593Smuzhiyun return ret;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun if (tmp_min == 0) {
49*4882a593Smuzhiyun ret = regulator_get_voltage_rdev(c_rdevs[i]);
50*4882a593Smuzhiyun if (ret < 0)
51*4882a593Smuzhiyun return ret;
52*4882a593Smuzhiyun tmp_min = ret;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* apply constraints */
56*4882a593Smuzhiyun ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max);
57*4882a593Smuzhiyun if (ret < 0)
58*4882a593Smuzhiyun return ret;
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun highest_min_uV = max(highest_min_uV, tmp_min);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun if (i == 0) {
63*4882a593Smuzhiyun desired_min_uV = tmp_min;
64*4882a593Smuzhiyun desired_max_uV = tmp_max;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun max_spread = constraints->max_spread[0];
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /*
71*4882a593Smuzhiyun * Let target_uV be equal to the desired one if possible.
72*4882a593Smuzhiyun * If not, set it to minimum voltage, allowed by other coupled
73*4882a593Smuzhiyun * regulators.
74*4882a593Smuzhiyun */
75*4882a593Smuzhiyun target_uV = max(desired_min_uV, highest_min_uV - max_spread);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /*
78*4882a593Smuzhiyun * Find min and max voltages, which currently aren't violating
79*4882a593Smuzhiyun * max_spread.
80*4882a593Smuzhiyun */
81*4882a593Smuzhiyun for (i = 1; i < n_coupled; i++) {
82*4882a593Smuzhiyun int tmp_act;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun tmp_act = regulator_get_voltage_rdev(c_rdevs[i]);
85*4882a593Smuzhiyun if (tmp_act < 0)
86*4882a593Smuzhiyun return tmp_act;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun min_current_uV = min(tmp_act, min_current_uV);
89*4882a593Smuzhiyun max_current_uV = max(tmp_act, max_current_uV);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /*
93*4882a593Smuzhiyun * Correct target voltage, so as it currently isn't
94*4882a593Smuzhiyun * violating max_spread
95*4882a593Smuzhiyun */
96*4882a593Smuzhiyun possible_uV = max(target_uV, max_current_uV - max_spread);
97*4882a593Smuzhiyun possible_uV = min(possible_uV, min_current_uV + max_spread);
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun if (possible_uV > desired_max_uV)
100*4882a593Smuzhiyun return -EINVAL;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun done = (possible_uV == target_uV);
103*4882a593Smuzhiyun desired_min_uV = possible_uV;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun /* Set current_uV if wasn't done earlier in the code and if necessary */
106*4882a593Smuzhiyun if (*current_uV == -1) {
107*4882a593Smuzhiyun ret = regulator_get_voltage_rdev(rdev);
108*4882a593Smuzhiyun if (ret < 0)
109*4882a593Smuzhiyun return ret;
110*4882a593Smuzhiyun *current_uV = ret;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun *min_uV = desired_min_uV;
114*4882a593Smuzhiyun *max_uV = desired_max_uV;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun return done;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
exynos_coupler_balance_voltage(struct regulator_coupler * coupler,struct regulator_dev * rdev,suspend_state_t state)119*4882a593Smuzhiyun static int exynos_coupler_balance_voltage(struct regulator_coupler *coupler,
120*4882a593Smuzhiyun struct regulator_dev *rdev,
121*4882a593Smuzhiyun suspend_state_t state)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun struct regulator_dev **c_rdevs;
124*4882a593Smuzhiyun struct regulator_dev *best_rdev;
125*4882a593Smuzhiyun struct coupling_desc *c_desc = &rdev->coupling_desc;
126*4882a593Smuzhiyun int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev;
127*4882a593Smuzhiyun unsigned int delta, best_delta;
128*4882a593Smuzhiyun unsigned long c_rdev_done = 0;
129*4882a593Smuzhiyun bool best_c_rdev_done;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun c_rdevs = c_desc->coupled_rdevs;
132*4882a593Smuzhiyun n_coupled = c_desc->n_coupled;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /*
135*4882a593Smuzhiyun * Find the best possible voltage change on each loop. Leave the loop
136*4882a593Smuzhiyun * if there isn't any possible change.
137*4882a593Smuzhiyun */
138*4882a593Smuzhiyun do {
139*4882a593Smuzhiyun best_c_rdev_done = false;
140*4882a593Smuzhiyun best_delta = 0;
141*4882a593Smuzhiyun best_min_uV = 0;
142*4882a593Smuzhiyun best_max_uV = 0;
143*4882a593Smuzhiyun best_c_rdev = 0;
144*4882a593Smuzhiyun best_rdev = NULL;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /*
147*4882a593Smuzhiyun * Find highest difference between optimal voltage
148*4882a593Smuzhiyun * and current voltage.
149*4882a593Smuzhiyun */
150*4882a593Smuzhiyun for (i = 0; i < n_coupled; i++) {
151*4882a593Smuzhiyun /*
152*4882a593Smuzhiyun * optimal_uV is the best voltage that can be set for
153*4882a593Smuzhiyun * i-th regulator at the moment without violating
154*4882a593Smuzhiyun * max_spread constraint in order to balance
155*4882a593Smuzhiyun * the coupled voltages.
156*4882a593Smuzhiyun */
157*4882a593Smuzhiyun int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun if (test_bit(i, &c_rdev_done))
160*4882a593Smuzhiyun continue;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun ret = regulator_get_optimal_voltage(c_rdevs[i],
163*4882a593Smuzhiyun ¤t_uV,
164*4882a593Smuzhiyun &optimal_uV,
165*4882a593Smuzhiyun &optimal_max_uV,
166*4882a593Smuzhiyun state);
167*4882a593Smuzhiyun if (ret < 0)
168*4882a593Smuzhiyun goto out;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun delta = abs(optimal_uV - current_uV);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun if (delta && best_delta <= delta) {
173*4882a593Smuzhiyun best_c_rdev_done = ret;
174*4882a593Smuzhiyun best_delta = delta;
175*4882a593Smuzhiyun best_rdev = c_rdevs[i];
176*4882a593Smuzhiyun best_min_uV = optimal_uV;
177*4882a593Smuzhiyun best_max_uV = optimal_max_uV;
178*4882a593Smuzhiyun best_c_rdev = i;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* Nothing to change, return successfully */
183*4882a593Smuzhiyun if (!best_rdev) {
184*4882a593Smuzhiyun ret = 0;
185*4882a593Smuzhiyun goto out;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun ret = regulator_set_voltage_rdev(best_rdev, best_min_uV,
189*4882a593Smuzhiyun best_max_uV, state);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun if (ret < 0)
192*4882a593Smuzhiyun goto out;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun if (best_c_rdev_done)
195*4882a593Smuzhiyun set_bit(best_c_rdev, &c_rdev_done);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun } while (n_coupled > 1);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun out:
200*4882a593Smuzhiyun return ret;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
exynos_coupler_attach(struct regulator_coupler * coupler,struct regulator_dev * rdev)203*4882a593Smuzhiyun static int exynos_coupler_attach(struct regulator_coupler *coupler,
204*4882a593Smuzhiyun struct regulator_dev *rdev)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun return 0;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun static struct regulator_coupler exynos_coupler = {
210*4882a593Smuzhiyun .attach_regulator = exynos_coupler_attach,
211*4882a593Smuzhiyun .balance_voltage = exynos_coupler_balance_voltage,
212*4882a593Smuzhiyun };
213*4882a593Smuzhiyun
exynos_coupler_init(void)214*4882a593Smuzhiyun static int __init exynos_coupler_init(void)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun if (!of_machine_is_compatible("samsung,exynos5800"))
217*4882a593Smuzhiyun return 0;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun return regulator_coupler_register(&exynos_coupler);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun arch_initcall(exynos_coupler_init);
222