Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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 = cpu_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);