1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Voltage regulators coupler for NVIDIA Tegra30
4 * Copyright (C) 2019 GRATE-DRIVER project
5 *
6 * Voltage constraints borrowed from downstream kernel sources
7 * Copyright (C) 2010-2011 NVIDIA Corporation
8 */
9
10#define pr_fmt(fmt)	"tegra voltage-coupler: " fmt
11
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/of.h>
15#include <linux/regulator/coupler.h>
16#include <linux/regulator/driver.h>
17#include <linux/regulator/machine.h>
18
19#include <soc/tegra/fuse.h>
20
21struct tegra_regulator_coupler {
22	struct regulator_coupler coupler;
23	struct regulator_dev *core_rdev;
24	struct regulator_dev *cpu_rdev;
25	int core_min_uV;
26};
27
28static inline struct tegra_regulator_coupler *
29to_tegra_coupler(struct regulator_coupler *coupler)
30{
31	return container_of(coupler, struct tegra_regulator_coupler, coupler);
32}
33
34static int tegra30_core_limit(struct tegra_regulator_coupler *tegra,
35			      struct regulator_dev *core_rdev)
36{
37	int core_min_uV = 0;
38	int core_max_uV;
39	int core_cur_uV;
40	int err;
41
42	if (tegra->core_min_uV > 0)
43		return tegra->core_min_uV;
44
45	core_cur_uV = regulator_get_voltage_rdev(core_rdev);
46	if (core_cur_uV < 0)
47		return core_cur_uV;
48
49	core_max_uV = max(core_cur_uV, 1200000);
50
51	err = regulator_check_voltage(core_rdev, &core_min_uV, &core_max_uV);
52	if (err)
53		return err;
54
55	/*
56	 * Limit minimum CORE voltage to a value left from bootloader or,
57	 * if it's unreasonably low value, to the most common 1.2v or to
58	 * whatever maximum value defined via board's device-tree.
59	 */
60	tegra->core_min_uV = core_max_uV;
61
62	pr_info("core minimum voltage limited to %duV\n", tegra->core_min_uV);
63
64	return tegra->core_min_uV;
65}
66
67static int tegra30_core_cpu_limit(int cpu_uV)
68{
69	if (cpu_uV < 800000)
70		return 950000;
71
72	if (cpu_uV < 900000)
73		return 1000000;
74
75	if (cpu_uV < 1000000)
76		return 1100000;
77
78	if (cpu_uV < 1100000)
79		return 1200000;
80
81	if (cpu_uV < 1250000) {
82		switch (tegra_sku_info.cpu_speedo_id) {
83		case 0 ... 1:
84		case 4:
85		case 7 ... 8:
86			return 1200000;
87
88		default:
89			return 1300000;
90		}
91	}
92
93	return -EINVAL;
94}
95
96static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra,
97				  struct regulator_dev *cpu_rdev,
98				  struct regulator_dev *core_rdev)
99{
100	int core_min_uV, core_max_uV = INT_MAX;
101	int cpu_min_uV, cpu_max_uV = INT_MAX;
102	int cpu_min_uV_consumers = 0;
103	int core_min_limited_uV;
104	int core_target_uV;
105	int cpu_target_uV;
106	int core_max_step;
107	int cpu_max_step;
108	int max_spread;
109	int core_uV;
110	int cpu_uV;
111	int err;
112
113	/*
114	 * CPU voltage should not got lower than 300mV from the CORE.
115	 * CPU voltage should stay below the CORE by 100mV+, depending
116	 * by the CORE voltage. This applies to all Tegra30 SoC's.
117	 */
118	max_spread = cpu_rdev->constraints->max_spread[0];
119	cpu_max_step = cpu_rdev->constraints->max_uV_step;
120	core_max_step = core_rdev->constraints->max_uV_step;
121
122	if (!max_spread) {
123		pr_err_once("cpu-core max-spread is undefined in device-tree\n");
124		max_spread = 300000;
125	}
126
127	if (!cpu_max_step) {
128		pr_err_once("cpu max-step is undefined in device-tree\n");
129		cpu_max_step = 150000;
130	}
131
132	if (!core_max_step) {
133		pr_err_once("core max-step is undefined in device-tree\n");
134		core_max_step = 150000;
135	}
136
137	/*
138	 * The CORE voltage scaling is currently not hooked up in drivers,
139	 * hence we will limit the minimum CORE voltage to a reasonable value.
140	 * This should be good enough for the time being.
141	 */
142	core_min_uV = tegra30_core_limit(tegra, core_rdev);
143	if (core_min_uV < 0)
144		return core_min_uV;
145
146	err = regulator_check_consumers(core_rdev, &core_min_uV, &core_max_uV,
147					PM_SUSPEND_ON);
148	if (err)
149		return err;
150
151	core_uV = regulator_get_voltage_rdev(core_rdev);
152	if (core_uV < 0)
153		return core_uV;
154
155	cpu_min_uV = core_min_uV - max_spread;
156
157	err = regulator_check_consumers(cpu_rdev, &cpu_min_uV, &cpu_max_uV,
158					PM_SUSPEND_ON);
159	if (err)
160		return err;
161
162	err = regulator_check_consumers(cpu_rdev, &cpu_min_uV_consumers,
163					&cpu_max_uV, PM_SUSPEND_ON);
164	if (err)
165		return err;
166
167	err = regulator_check_voltage(cpu_rdev, &cpu_min_uV, &cpu_max_uV);
168	if (err)
169		return err;
170
171	cpu_uV = regulator_get_voltage_rdev(cpu_rdev);
172	if (cpu_uV < 0)
173		return cpu_uV;
174
175	/*
176	 * CPU's regulator may not have any consumers, hence the voltage
177	 * must not be changed in that case because CPU simply won't
178	 * survive the voltage drop if it's running on a higher frequency.
179	 */
180	if (!cpu_min_uV_consumers)
181		cpu_min_uV = max(cpu_uV, cpu_min_uV);
182
183	/*
184	 * Bootloader shall set up voltages correctly, but if it
185	 * happens that there is a violation, then try to fix it
186	 * at first.
187	 */
188	core_min_limited_uV = tegra30_core_cpu_limit(cpu_uV);
189	if (core_min_limited_uV < 0)
190		return core_min_limited_uV;
191
192	core_min_uV = max(core_min_uV, tegra30_core_cpu_limit(cpu_min_uV));
193
194	err = regulator_check_voltage(core_rdev, &core_min_uV, &core_max_uV);
195	if (err)
196		return err;
197
198	if (core_min_limited_uV > core_uV) {
199		pr_err("core voltage constraint violated: %d %d %d\n",
200		       core_uV, core_min_limited_uV, cpu_uV);
201		goto update_core;
202	}
203
204	while (cpu_uV != cpu_min_uV || core_uV != core_min_uV) {
205		if (cpu_uV < cpu_min_uV) {
206			cpu_target_uV = min(cpu_uV + cpu_max_step, cpu_min_uV);
207		} else {
208			cpu_target_uV = max(cpu_uV - cpu_max_step, cpu_min_uV);
209			cpu_target_uV = max(core_uV - max_spread, cpu_target_uV);
210		}
211
212		if (cpu_uV == cpu_target_uV)
213			goto update_core;
214
215		err = regulator_set_voltage_rdev(cpu_rdev,
216						 cpu_target_uV,
217						 cpu_max_uV,
218						 PM_SUSPEND_ON);
219		if (err)
220			return err;
221
222		cpu_uV = cpu_target_uV;
223update_core:
224		core_min_limited_uV = tegra30_core_cpu_limit(cpu_uV);
225		if (core_min_limited_uV < 0)
226			return core_min_limited_uV;
227
228		core_target_uV = max(core_min_limited_uV, core_min_uV);
229
230		if (core_uV < core_target_uV) {
231			core_target_uV = min(core_target_uV, core_uV + core_max_step);
232			core_target_uV = min(core_target_uV, cpu_uV + max_spread);
233		} else {
234			core_target_uV = max(core_target_uV, core_uV - core_max_step);
235		}
236
237		if (core_uV == core_target_uV)
238			continue;
239
240		err = regulator_set_voltage_rdev(core_rdev,
241						 core_target_uV,
242						 core_max_uV,
243						 PM_SUSPEND_ON);
244		if (err)
245			return err;
246
247		core_uV = core_target_uV;
248	}
249
250	return 0;
251}
252
253static int tegra30_regulator_balance_voltage(struct regulator_coupler *coupler,
254					     struct regulator_dev *rdev,
255					     suspend_state_t state)
256{
257	struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
258	struct regulator_dev *core_rdev = tegra->core_rdev;
259	struct regulator_dev *cpu_rdev = tegra->cpu_rdev;
260
261	if ((core_rdev != rdev && cpu_rdev != rdev) || state != PM_SUSPEND_ON) {
262		pr_err("regulators are not coupled properly\n");
263		return -EINVAL;
264	}
265
266	return tegra30_voltage_update(tegra, cpu_rdev, core_rdev);
267}
268
269static int tegra30_regulator_attach(struct regulator_coupler *coupler,
270				    struct regulator_dev *rdev)
271{
272	struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
273	struct device_node *np = rdev->dev.of_node;
274
275	if (of_property_read_bool(np, "nvidia,tegra-core-regulator") &&
276	    !tegra->core_rdev) {
277		tegra->core_rdev = rdev;
278		return 0;
279	}
280
281	if (of_property_read_bool(np, "nvidia,tegra-cpu-regulator") &&
282	    !tegra->cpu_rdev) {
283		tegra->cpu_rdev = rdev;
284		return 0;
285	}
286
287	return -EINVAL;
288}
289
290static int tegra30_regulator_detach(struct regulator_coupler *coupler,
291				    struct regulator_dev *rdev)
292{
293	struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
294
295	if (tegra->core_rdev == rdev) {
296		tegra->core_rdev = NULL;
297		return 0;
298	}
299
300	if (tegra->cpu_rdev == rdev) {
301		tegra->cpu_rdev = NULL;
302		return 0;
303	}
304
305	return -EINVAL;
306}
307
308static struct tegra_regulator_coupler tegra30_coupler = {
309	.coupler = {
310		.attach_regulator = tegra30_regulator_attach,
311		.detach_regulator = tegra30_regulator_detach,
312		.balance_voltage = tegra30_regulator_balance_voltage,
313	},
314};
315
316static int __init tegra_regulator_coupler_init(void)
317{
318	if (!of_machine_is_compatible("nvidia,tegra30"))
319		return 0;
320
321	return regulator_coupler_register(&tegra30_coupler.coupler);
322}
323arch_initcall(tegra_regulator_coupler_init);
324