1496747e7SDmitry Osipenko // SPDX-License-Identifier: GPL-2.0+
2496747e7SDmitry Osipenko /*
3496747e7SDmitry Osipenko * Voltage regulators coupler for NVIDIA Tegra20
4496747e7SDmitry Osipenko * Copyright (C) 2019 GRATE-DRIVER project
5496747e7SDmitry Osipenko *
6496747e7SDmitry Osipenko * Voltage constraints borrowed from downstream kernel sources
7496747e7SDmitry Osipenko * Copyright (C) 2010-2011 NVIDIA Corporation
8496747e7SDmitry Osipenko */
9496747e7SDmitry Osipenko
10496747e7SDmitry Osipenko #define pr_fmt(fmt) "tegra voltage-coupler: " fmt
11496747e7SDmitry Osipenko
12496747e7SDmitry Osipenko #include <linux/init.h>
13496747e7SDmitry Osipenko #include <linux/kernel.h>
14496747e7SDmitry Osipenko #include <linux/of.h>
1503978d42SDmitry Osipenko #include <linux/reboot.h>
16496747e7SDmitry Osipenko #include <linux/regulator/coupler.h>
17496747e7SDmitry Osipenko #include <linux/regulator/driver.h>
18496747e7SDmitry Osipenko #include <linux/regulator/machine.h>
19*80ef351cSDmitry Osipenko #include <linux/suspend.h>
20496747e7SDmitry Osipenko
21*80ef351cSDmitry Osipenko #include <soc/tegra/fuse.h>
22029f7e24SDmitry Osipenko #include <soc/tegra/pmc.h>
23029f7e24SDmitry Osipenko
24496747e7SDmitry Osipenko struct tegra_regulator_coupler {
25496747e7SDmitry Osipenko struct regulator_coupler coupler;
26496747e7SDmitry Osipenko struct regulator_dev *core_rdev;
27496747e7SDmitry Osipenko struct regulator_dev *cpu_rdev;
28496747e7SDmitry Osipenko struct regulator_dev *rtc_rdev;
2903978d42SDmitry Osipenko struct notifier_block reboot_notifier;
30*80ef351cSDmitry Osipenko struct notifier_block suspend_notifier;
3103978d42SDmitry Osipenko int core_min_uV, cpu_min_uV;
3203978d42SDmitry Osipenko bool sys_reboot_mode_req;
3303978d42SDmitry Osipenko bool sys_reboot_mode;
34*80ef351cSDmitry Osipenko bool sys_suspend_mode_req;
35*80ef351cSDmitry Osipenko bool sys_suspend_mode;
36496747e7SDmitry Osipenko };
37496747e7SDmitry Osipenko
38496747e7SDmitry Osipenko static inline struct tegra_regulator_coupler *
to_tegra_coupler(struct regulator_coupler * coupler)39496747e7SDmitry Osipenko to_tegra_coupler(struct regulator_coupler *coupler)
40496747e7SDmitry Osipenko {
41496747e7SDmitry Osipenko return container_of(coupler, struct tegra_regulator_coupler, coupler);
42496747e7SDmitry Osipenko }
43496747e7SDmitry Osipenko
tegra20_core_limit(struct tegra_regulator_coupler * tegra,struct regulator_dev * core_rdev)44496747e7SDmitry Osipenko static int tegra20_core_limit(struct tegra_regulator_coupler *tegra,
45496747e7SDmitry Osipenko struct regulator_dev *core_rdev)
46496747e7SDmitry Osipenko {
47496747e7SDmitry Osipenko int core_min_uV = 0;
48496747e7SDmitry Osipenko int core_max_uV;
49496747e7SDmitry Osipenko int core_cur_uV;
50496747e7SDmitry Osipenko int err;
51496747e7SDmitry Osipenko
52029f7e24SDmitry Osipenko /*
53029f7e24SDmitry Osipenko * Tegra20 SoC has critical DVFS-capable devices that are
54029f7e24SDmitry Osipenko * permanently-active or active at a boot time, like EMC
55029f7e24SDmitry Osipenko * (DRAM controller) or Display controller for example.
56029f7e24SDmitry Osipenko *
57029f7e24SDmitry Osipenko * The voltage of a CORE SoC power domain shall not be dropped below
58029f7e24SDmitry Osipenko * a minimum level, which is determined by device's clock rate.
59029f7e24SDmitry Osipenko * This means that we can't fully allow CORE voltage scaling until
60029f7e24SDmitry Osipenko * the state of all DVFS-critical CORE devices is synced.
61029f7e24SDmitry Osipenko */
62029f7e24SDmitry Osipenko if (tegra_pmc_core_domain_state_synced() && !tegra->sys_reboot_mode) {
63029f7e24SDmitry Osipenko pr_info_once("voltage state synced\n");
64029f7e24SDmitry Osipenko return 0;
65029f7e24SDmitry Osipenko }
66029f7e24SDmitry Osipenko
67496747e7SDmitry Osipenko if (tegra->core_min_uV > 0)
68496747e7SDmitry Osipenko return tegra->core_min_uV;
69496747e7SDmitry Osipenko
70496747e7SDmitry Osipenko core_cur_uV = regulator_get_voltage_rdev(core_rdev);
71496747e7SDmitry Osipenko if (core_cur_uV < 0)
72496747e7SDmitry Osipenko return core_cur_uV;
73496747e7SDmitry Osipenko
74496747e7SDmitry Osipenko core_max_uV = max(core_cur_uV, 1200000);
75496747e7SDmitry Osipenko
76496747e7SDmitry Osipenko err = regulator_check_voltage(core_rdev, &core_min_uV, &core_max_uV);
77496747e7SDmitry Osipenko if (err)
78496747e7SDmitry Osipenko return err;
79496747e7SDmitry Osipenko
80496747e7SDmitry Osipenko /*
81496747e7SDmitry Osipenko * Limit minimum CORE voltage to a value left from bootloader or,
82496747e7SDmitry Osipenko * if it's unreasonably low value, to the most common 1.2v or to
83496747e7SDmitry Osipenko * whatever maximum value defined via board's device-tree.
84496747e7SDmitry Osipenko */
85496747e7SDmitry Osipenko tegra->core_min_uV = core_max_uV;
86496747e7SDmitry Osipenko
87029f7e24SDmitry Osipenko pr_info("core voltage initialized to %duV\n", tegra->core_min_uV);
88496747e7SDmitry Osipenko
89496747e7SDmitry Osipenko return tegra->core_min_uV;
90496747e7SDmitry Osipenko }
91496747e7SDmitry Osipenko
tegra20_core_rtc_max_spread(struct regulator_dev * core_rdev,struct regulator_dev * rtc_rdev)92496747e7SDmitry Osipenko static int tegra20_core_rtc_max_spread(struct regulator_dev *core_rdev,
93496747e7SDmitry Osipenko struct regulator_dev *rtc_rdev)
94496747e7SDmitry Osipenko {
95496747e7SDmitry Osipenko struct coupling_desc *c_desc = &core_rdev->coupling_desc;
96496747e7SDmitry Osipenko struct regulator_dev *rdev;
97496747e7SDmitry Osipenko int max_spread;
98496747e7SDmitry Osipenko unsigned int i;
99496747e7SDmitry Osipenko
100496747e7SDmitry Osipenko for (i = 1; i < c_desc->n_coupled; i++) {
101496747e7SDmitry Osipenko max_spread = core_rdev->constraints->max_spread[i - 1];
102496747e7SDmitry Osipenko rdev = c_desc->coupled_rdevs[i];
103496747e7SDmitry Osipenko
104496747e7SDmitry Osipenko if (rdev == rtc_rdev && max_spread)
105496747e7SDmitry Osipenko return max_spread;
106496747e7SDmitry Osipenko }
107496747e7SDmitry Osipenko
108496747e7SDmitry Osipenko pr_err_once("rtc-core max-spread is undefined in device-tree\n");
109496747e7SDmitry Osipenko
110496747e7SDmitry Osipenko return 150000;
111496747e7SDmitry Osipenko }
112496747e7SDmitry Osipenko
tegra20_cpu_nominal_uV(void)113*80ef351cSDmitry Osipenko static int tegra20_cpu_nominal_uV(void)
114*80ef351cSDmitry Osipenko {
115*80ef351cSDmitry Osipenko switch (tegra_sku_info.soc_speedo_id) {
116*80ef351cSDmitry Osipenko case 0:
117*80ef351cSDmitry Osipenko return 1100000;
118*80ef351cSDmitry Osipenko case 1:
119*80ef351cSDmitry Osipenko return 1025000;
120*80ef351cSDmitry Osipenko default:
121*80ef351cSDmitry Osipenko return 1125000;
122*80ef351cSDmitry Osipenko }
123*80ef351cSDmitry Osipenko }
124*80ef351cSDmitry Osipenko
tegra20_core_nominal_uV(void)125*80ef351cSDmitry Osipenko static int tegra20_core_nominal_uV(void)
126*80ef351cSDmitry Osipenko {
127*80ef351cSDmitry Osipenko switch (tegra_sku_info.soc_speedo_id) {
128*80ef351cSDmitry Osipenko default:
129*80ef351cSDmitry Osipenko return 1225000;
130*80ef351cSDmitry Osipenko case 2:
131*80ef351cSDmitry Osipenko return 1300000;
132*80ef351cSDmitry Osipenko }
133*80ef351cSDmitry Osipenko }
134*80ef351cSDmitry Osipenko
tegra20_core_rtc_update(struct tegra_regulator_coupler * tegra,struct regulator_dev * core_rdev,struct regulator_dev * rtc_rdev,int cpu_uV,int cpu_min_uV)135496747e7SDmitry Osipenko static int tegra20_core_rtc_update(struct tegra_regulator_coupler *tegra,
136496747e7SDmitry Osipenko struct regulator_dev *core_rdev,
137496747e7SDmitry Osipenko struct regulator_dev *rtc_rdev,
138496747e7SDmitry Osipenko int cpu_uV, int cpu_min_uV)
139496747e7SDmitry Osipenko {
140496747e7SDmitry Osipenko int core_min_uV, core_max_uV = INT_MAX;
141496747e7SDmitry Osipenko int rtc_min_uV, rtc_max_uV = INT_MAX;
142496747e7SDmitry Osipenko int core_target_uV;
143496747e7SDmitry Osipenko int rtc_target_uV;
144496747e7SDmitry Osipenko int max_spread;
145496747e7SDmitry Osipenko int core_uV;
146496747e7SDmitry Osipenko int rtc_uV;
147496747e7SDmitry Osipenko int err;
148496747e7SDmitry Osipenko
149496747e7SDmitry Osipenko /*
150496747e7SDmitry Osipenko * RTC and CORE voltages should be no more than 170mV from each other,
151496747e7SDmitry Osipenko * CPU should be below RTC and CORE by at least 120mV. This applies
152496747e7SDmitry Osipenko * to all Tegra20 SoC's.
153496747e7SDmitry Osipenko */
154496747e7SDmitry Osipenko max_spread = tegra20_core_rtc_max_spread(core_rdev, rtc_rdev);
155496747e7SDmitry Osipenko
156496747e7SDmitry Osipenko /*
157496747e7SDmitry Osipenko * The core voltage scaling is currently not hooked up in drivers,
158496747e7SDmitry Osipenko * hence we will limit the minimum core voltage to a reasonable value.
159496747e7SDmitry Osipenko * This should be good enough for the time being.
160496747e7SDmitry Osipenko */
161496747e7SDmitry Osipenko core_min_uV = tegra20_core_limit(tegra, core_rdev);
162496747e7SDmitry Osipenko if (core_min_uV < 0)
163496747e7SDmitry Osipenko return core_min_uV;
164496747e7SDmitry Osipenko
165496747e7SDmitry Osipenko err = regulator_check_voltage(core_rdev, &core_min_uV, &core_max_uV);
166496747e7SDmitry Osipenko if (err)
167496747e7SDmitry Osipenko return err;
168496747e7SDmitry Osipenko
169496747e7SDmitry Osipenko err = regulator_check_consumers(core_rdev, &core_min_uV, &core_max_uV,
170496747e7SDmitry Osipenko PM_SUSPEND_ON);
171496747e7SDmitry Osipenko if (err)
172496747e7SDmitry Osipenko return err;
173496747e7SDmitry Osipenko
174*80ef351cSDmitry Osipenko /* prepare voltage level for suspend */
175*80ef351cSDmitry Osipenko if (tegra->sys_suspend_mode)
176*80ef351cSDmitry Osipenko core_min_uV = clamp(tegra20_core_nominal_uV(),
177*80ef351cSDmitry Osipenko core_min_uV, core_max_uV);
178*80ef351cSDmitry Osipenko
179496747e7SDmitry Osipenko core_uV = regulator_get_voltage_rdev(core_rdev);
180496747e7SDmitry Osipenko if (core_uV < 0)
181496747e7SDmitry Osipenko return core_uV;
182496747e7SDmitry Osipenko
183496747e7SDmitry Osipenko core_min_uV = max(cpu_min_uV + 125000, core_min_uV);
184496747e7SDmitry Osipenko if (core_min_uV > core_max_uV)
185496747e7SDmitry Osipenko return -EINVAL;
186496747e7SDmitry Osipenko
187496747e7SDmitry Osipenko if (cpu_uV + 120000 > core_uV)
188496747e7SDmitry Osipenko pr_err("core-cpu voltage constraint violated: %d %d\n",
189496747e7SDmitry Osipenko core_uV, cpu_uV + 120000);
190496747e7SDmitry Osipenko
191496747e7SDmitry Osipenko rtc_uV = regulator_get_voltage_rdev(rtc_rdev);
192496747e7SDmitry Osipenko if (rtc_uV < 0)
193496747e7SDmitry Osipenko return rtc_uV;
194496747e7SDmitry Osipenko
195496747e7SDmitry Osipenko if (cpu_uV + 120000 > rtc_uV)
196496747e7SDmitry Osipenko pr_err("rtc-cpu voltage constraint violated: %d %d\n",
197496747e7SDmitry Osipenko rtc_uV, cpu_uV + 120000);
198496747e7SDmitry Osipenko
199496747e7SDmitry Osipenko if (abs(core_uV - rtc_uV) > 170000)
200496747e7SDmitry Osipenko pr_err("core-rtc voltage constraint violated: %d %d\n",
201496747e7SDmitry Osipenko core_uV, rtc_uV);
202496747e7SDmitry Osipenko
203496747e7SDmitry Osipenko rtc_min_uV = max(cpu_min_uV + 125000, core_min_uV - max_spread);
204496747e7SDmitry Osipenko
205496747e7SDmitry Osipenko err = regulator_check_voltage(rtc_rdev, &rtc_min_uV, &rtc_max_uV);
206496747e7SDmitry Osipenko if (err)
207496747e7SDmitry Osipenko return err;
208496747e7SDmitry Osipenko
209496747e7SDmitry Osipenko while (core_uV != core_min_uV || rtc_uV != rtc_min_uV) {
210496747e7SDmitry Osipenko if (core_uV < core_min_uV) {
211496747e7SDmitry Osipenko core_target_uV = min(core_uV + max_spread, core_min_uV);
212496747e7SDmitry Osipenko core_target_uV = min(rtc_uV + max_spread, core_target_uV);
213496747e7SDmitry Osipenko } else {
214496747e7SDmitry Osipenko core_target_uV = max(core_uV - max_spread, core_min_uV);
215496747e7SDmitry Osipenko core_target_uV = max(rtc_uV - max_spread, core_target_uV);
216496747e7SDmitry Osipenko }
217496747e7SDmitry Osipenko
21845f019a6SDmitry Osipenko if (core_uV == core_target_uV)
21945f019a6SDmitry Osipenko goto update_rtc;
22045f019a6SDmitry Osipenko
221496747e7SDmitry Osipenko err = regulator_set_voltage_rdev(core_rdev,
222496747e7SDmitry Osipenko core_target_uV,
223496747e7SDmitry Osipenko core_max_uV,
224496747e7SDmitry Osipenko PM_SUSPEND_ON);
225496747e7SDmitry Osipenko if (err)
226496747e7SDmitry Osipenko return err;
227496747e7SDmitry Osipenko
228496747e7SDmitry Osipenko core_uV = core_target_uV;
22945f019a6SDmitry Osipenko update_rtc:
230496747e7SDmitry Osipenko if (rtc_uV < rtc_min_uV) {
231496747e7SDmitry Osipenko rtc_target_uV = min(rtc_uV + max_spread, rtc_min_uV);
232496747e7SDmitry Osipenko rtc_target_uV = min(core_uV + max_spread, rtc_target_uV);
233496747e7SDmitry Osipenko } else {
234496747e7SDmitry Osipenko rtc_target_uV = max(rtc_uV - max_spread, rtc_min_uV);
235496747e7SDmitry Osipenko rtc_target_uV = max(core_uV - max_spread, rtc_target_uV);
236496747e7SDmitry Osipenko }
237496747e7SDmitry Osipenko
23845f019a6SDmitry Osipenko if (rtc_uV == rtc_target_uV)
23945f019a6SDmitry Osipenko continue;
24045f019a6SDmitry Osipenko
241496747e7SDmitry Osipenko err = regulator_set_voltage_rdev(rtc_rdev,
242496747e7SDmitry Osipenko rtc_target_uV,
243496747e7SDmitry Osipenko rtc_max_uV,
244496747e7SDmitry Osipenko PM_SUSPEND_ON);
245496747e7SDmitry Osipenko if (err)
246496747e7SDmitry Osipenko return err;
247496747e7SDmitry Osipenko
248496747e7SDmitry Osipenko rtc_uV = rtc_target_uV;
249496747e7SDmitry Osipenko }
250496747e7SDmitry Osipenko
251496747e7SDmitry Osipenko return 0;
252496747e7SDmitry Osipenko }
253496747e7SDmitry Osipenko
tegra20_core_voltage_update(struct tegra_regulator_coupler * tegra,struct regulator_dev * cpu_rdev,struct regulator_dev * core_rdev,struct regulator_dev * rtc_rdev)254496747e7SDmitry Osipenko static int tegra20_core_voltage_update(struct tegra_regulator_coupler *tegra,
255496747e7SDmitry Osipenko struct regulator_dev *cpu_rdev,
256496747e7SDmitry Osipenko struct regulator_dev *core_rdev,
257496747e7SDmitry Osipenko struct regulator_dev *rtc_rdev)
258496747e7SDmitry Osipenko {
259496747e7SDmitry Osipenko int cpu_uV;
260496747e7SDmitry Osipenko
261496747e7SDmitry Osipenko cpu_uV = regulator_get_voltage_rdev(cpu_rdev);
262496747e7SDmitry Osipenko if (cpu_uV < 0)
263496747e7SDmitry Osipenko return cpu_uV;
264496747e7SDmitry Osipenko
265496747e7SDmitry Osipenko return tegra20_core_rtc_update(tegra, core_rdev, rtc_rdev,
266496747e7SDmitry Osipenko cpu_uV, cpu_uV);
267496747e7SDmitry Osipenko }
268496747e7SDmitry Osipenko
tegra20_cpu_voltage_update(struct tegra_regulator_coupler * tegra,struct regulator_dev * cpu_rdev,struct regulator_dev * core_rdev,struct regulator_dev * rtc_rdev)269496747e7SDmitry Osipenko static int tegra20_cpu_voltage_update(struct tegra_regulator_coupler *tegra,
270496747e7SDmitry Osipenko struct regulator_dev *cpu_rdev,
271496747e7SDmitry Osipenko struct regulator_dev *core_rdev,
272496747e7SDmitry Osipenko struct regulator_dev *rtc_rdev)
273496747e7SDmitry Osipenko {
274496747e7SDmitry Osipenko int cpu_min_uV_consumers = 0;
275496747e7SDmitry Osipenko int cpu_max_uV = INT_MAX;
276496747e7SDmitry Osipenko int cpu_min_uV = 0;
277496747e7SDmitry Osipenko int cpu_uV;
278496747e7SDmitry Osipenko int err;
279496747e7SDmitry Osipenko
280496747e7SDmitry Osipenko err = regulator_check_voltage(cpu_rdev, &cpu_min_uV, &cpu_max_uV);
281496747e7SDmitry Osipenko if (err)
282496747e7SDmitry Osipenko return err;
283496747e7SDmitry Osipenko
284496747e7SDmitry Osipenko err = regulator_check_consumers(cpu_rdev, &cpu_min_uV, &cpu_max_uV,
285496747e7SDmitry Osipenko PM_SUSPEND_ON);
286496747e7SDmitry Osipenko if (err)
287496747e7SDmitry Osipenko return err;
288496747e7SDmitry Osipenko
289496747e7SDmitry Osipenko err = regulator_check_consumers(cpu_rdev, &cpu_min_uV_consumers,
290496747e7SDmitry Osipenko &cpu_max_uV, PM_SUSPEND_ON);
291496747e7SDmitry Osipenko if (err)
292496747e7SDmitry Osipenko return err;
293496747e7SDmitry Osipenko
294496747e7SDmitry Osipenko cpu_uV = regulator_get_voltage_rdev(cpu_rdev);
295496747e7SDmitry Osipenko if (cpu_uV < 0)
296496747e7SDmitry Osipenko return cpu_uV;
297496747e7SDmitry Osipenko
29803978d42SDmitry Osipenko /* store boot voltage level */
29903978d42SDmitry Osipenko if (!tegra->cpu_min_uV)
30003978d42SDmitry Osipenko tegra->cpu_min_uV = cpu_uV;
30103978d42SDmitry Osipenko
302496747e7SDmitry Osipenko /*
303496747e7SDmitry Osipenko * CPU's regulator may not have any consumers, hence the voltage
304496747e7SDmitry Osipenko * must not be changed in that case because CPU simply won't
305496747e7SDmitry Osipenko * survive the voltage drop if it's running on a higher frequency.
306496747e7SDmitry Osipenko */
307496747e7SDmitry Osipenko if (!cpu_min_uV_consumers)
308496747e7SDmitry Osipenko cpu_min_uV = cpu_uV;
309496747e7SDmitry Osipenko
31003978d42SDmitry Osipenko /* restore boot voltage level */
31103978d42SDmitry Osipenko if (tegra->sys_reboot_mode)
31203978d42SDmitry Osipenko cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV);
31303978d42SDmitry Osipenko
314*80ef351cSDmitry Osipenko /* prepare voltage level for suspend */
315*80ef351cSDmitry Osipenko if (tegra->sys_suspend_mode)
316*80ef351cSDmitry Osipenko cpu_min_uV = clamp(tegra20_cpu_nominal_uV(),
317*80ef351cSDmitry Osipenko cpu_min_uV, cpu_max_uV);
318*80ef351cSDmitry Osipenko
319496747e7SDmitry Osipenko if (cpu_min_uV > cpu_uV) {
320496747e7SDmitry Osipenko err = tegra20_core_rtc_update(tegra, core_rdev, rtc_rdev,
321496747e7SDmitry Osipenko cpu_uV, cpu_min_uV);
322496747e7SDmitry Osipenko if (err)
323496747e7SDmitry Osipenko return err;
324496747e7SDmitry Osipenko
325496747e7SDmitry Osipenko err = regulator_set_voltage_rdev(cpu_rdev, cpu_min_uV,
326496747e7SDmitry Osipenko cpu_max_uV, PM_SUSPEND_ON);
327496747e7SDmitry Osipenko if (err)
328496747e7SDmitry Osipenko return err;
329496747e7SDmitry Osipenko } else if (cpu_min_uV < cpu_uV) {
330496747e7SDmitry Osipenko err = regulator_set_voltage_rdev(cpu_rdev, cpu_min_uV,
331496747e7SDmitry Osipenko cpu_max_uV, PM_SUSPEND_ON);
332496747e7SDmitry Osipenko if (err)
333496747e7SDmitry Osipenko return err;
334496747e7SDmitry Osipenko
335496747e7SDmitry Osipenko err = tegra20_core_rtc_update(tegra, core_rdev, rtc_rdev,
336496747e7SDmitry Osipenko cpu_uV, cpu_min_uV);
337496747e7SDmitry Osipenko if (err)
338496747e7SDmitry Osipenko return err;
339496747e7SDmitry Osipenko }
340496747e7SDmitry Osipenko
341496747e7SDmitry Osipenko return 0;
342496747e7SDmitry Osipenko }
343496747e7SDmitry Osipenko
tegra20_regulator_balance_voltage(struct regulator_coupler * coupler,struct regulator_dev * rdev,suspend_state_t state)344496747e7SDmitry Osipenko static int tegra20_regulator_balance_voltage(struct regulator_coupler *coupler,
345496747e7SDmitry Osipenko struct regulator_dev *rdev,
346496747e7SDmitry Osipenko suspend_state_t state)
347496747e7SDmitry Osipenko {
348496747e7SDmitry Osipenko struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
349496747e7SDmitry Osipenko struct regulator_dev *core_rdev = tegra->core_rdev;
350496747e7SDmitry Osipenko struct regulator_dev *cpu_rdev = tegra->cpu_rdev;
351496747e7SDmitry Osipenko struct regulator_dev *rtc_rdev = tegra->rtc_rdev;
352496747e7SDmitry Osipenko
353496747e7SDmitry Osipenko if ((core_rdev != rdev && cpu_rdev != rdev && rtc_rdev != rdev) ||
354496747e7SDmitry Osipenko state != PM_SUSPEND_ON) {
355496747e7SDmitry Osipenko pr_err("regulators are not coupled properly\n");
356496747e7SDmitry Osipenko return -EINVAL;
357496747e7SDmitry Osipenko }
358496747e7SDmitry Osipenko
35903978d42SDmitry Osipenko tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req);
360*80ef351cSDmitry Osipenko tegra->sys_suspend_mode = READ_ONCE(tegra->sys_suspend_mode_req);
36103978d42SDmitry Osipenko
362496747e7SDmitry Osipenko if (rdev == cpu_rdev)
363496747e7SDmitry Osipenko return tegra20_cpu_voltage_update(tegra, cpu_rdev,
364496747e7SDmitry Osipenko core_rdev, rtc_rdev);
365496747e7SDmitry Osipenko
366496747e7SDmitry Osipenko if (rdev == core_rdev)
367496747e7SDmitry Osipenko return tegra20_core_voltage_update(tegra, cpu_rdev,
368496747e7SDmitry Osipenko core_rdev, rtc_rdev);
369496747e7SDmitry Osipenko
370496747e7SDmitry Osipenko pr_err("changing %s voltage not permitted\n", rdev_get_name(rtc_rdev));
371496747e7SDmitry Osipenko
372496747e7SDmitry Osipenko return -EPERM;
373496747e7SDmitry Osipenko }
374496747e7SDmitry Osipenko
tegra20_regulator_prepare_suspend(struct tegra_regulator_coupler * tegra,bool sys_suspend_mode)375*80ef351cSDmitry Osipenko static int tegra20_regulator_prepare_suspend(struct tegra_regulator_coupler *tegra,
376*80ef351cSDmitry Osipenko bool sys_suspend_mode)
377*80ef351cSDmitry Osipenko {
378*80ef351cSDmitry Osipenko int err;
379*80ef351cSDmitry Osipenko
380*80ef351cSDmitry Osipenko if (!tegra->core_rdev || !tegra->rtc_rdev || !tegra->cpu_rdev)
381*80ef351cSDmitry Osipenko return 0;
382*80ef351cSDmitry Osipenko
383*80ef351cSDmitry Osipenko /*
384*80ef351cSDmitry Osipenko * All power domains are enabled early during resume from suspend
385*80ef351cSDmitry Osipenko * by GENPD core. Domains like VENC may require a higher voltage
386*80ef351cSDmitry Osipenko * when enabled during resume from suspend. This also prepares
387*80ef351cSDmitry Osipenko * hardware for resuming from LP0.
388*80ef351cSDmitry Osipenko */
389*80ef351cSDmitry Osipenko
390*80ef351cSDmitry Osipenko WRITE_ONCE(tegra->sys_suspend_mode_req, sys_suspend_mode);
391*80ef351cSDmitry Osipenko
392*80ef351cSDmitry Osipenko err = regulator_sync_voltage_rdev(tegra->cpu_rdev);
393*80ef351cSDmitry Osipenko if (err)
394*80ef351cSDmitry Osipenko return err;
395*80ef351cSDmitry Osipenko
396*80ef351cSDmitry Osipenko err = regulator_sync_voltage_rdev(tegra->core_rdev);
397*80ef351cSDmitry Osipenko if (err)
398*80ef351cSDmitry Osipenko return err;
399*80ef351cSDmitry Osipenko
400*80ef351cSDmitry Osipenko return 0;
401*80ef351cSDmitry Osipenko }
402*80ef351cSDmitry Osipenko
tegra20_regulator_suspend(struct notifier_block * notifier,unsigned long mode,void * arg)403*80ef351cSDmitry Osipenko static int tegra20_regulator_suspend(struct notifier_block *notifier,
404*80ef351cSDmitry Osipenko unsigned long mode, void *arg)
405*80ef351cSDmitry Osipenko {
406*80ef351cSDmitry Osipenko struct tegra_regulator_coupler *tegra;
407*80ef351cSDmitry Osipenko int ret = 0;
408*80ef351cSDmitry Osipenko
409*80ef351cSDmitry Osipenko tegra = container_of(notifier, struct tegra_regulator_coupler,
410*80ef351cSDmitry Osipenko suspend_notifier);
411*80ef351cSDmitry Osipenko
412*80ef351cSDmitry Osipenko switch (mode) {
413*80ef351cSDmitry Osipenko case PM_HIBERNATION_PREPARE:
414*80ef351cSDmitry Osipenko case PM_RESTORE_PREPARE:
415*80ef351cSDmitry Osipenko case PM_SUSPEND_PREPARE:
416*80ef351cSDmitry Osipenko ret = tegra20_regulator_prepare_suspend(tegra, true);
417*80ef351cSDmitry Osipenko break;
418*80ef351cSDmitry Osipenko
419*80ef351cSDmitry Osipenko case PM_POST_HIBERNATION:
420*80ef351cSDmitry Osipenko case PM_POST_RESTORE:
421*80ef351cSDmitry Osipenko case PM_POST_SUSPEND:
422*80ef351cSDmitry Osipenko ret = tegra20_regulator_prepare_suspend(tegra, false);
423*80ef351cSDmitry Osipenko break;
424*80ef351cSDmitry Osipenko }
425*80ef351cSDmitry Osipenko
426*80ef351cSDmitry Osipenko if (ret)
427*80ef351cSDmitry Osipenko pr_err("failed to prepare regulators: %d\n", ret);
428*80ef351cSDmitry Osipenko
429*80ef351cSDmitry Osipenko return notifier_from_errno(ret);
430*80ef351cSDmitry Osipenko }
431*80ef351cSDmitry Osipenko
tegra20_regulator_prepare_reboot(struct tegra_regulator_coupler * tegra,bool sys_reboot_mode)43203978d42SDmitry Osipenko static int tegra20_regulator_prepare_reboot(struct tegra_regulator_coupler *tegra,
43303978d42SDmitry Osipenko bool sys_reboot_mode)
43403978d42SDmitry Osipenko {
43503978d42SDmitry Osipenko int err;
43603978d42SDmitry Osipenko
43703978d42SDmitry Osipenko if (!tegra->core_rdev || !tegra->rtc_rdev || !tegra->cpu_rdev)
43803978d42SDmitry Osipenko return 0;
43903978d42SDmitry Osipenko
44003978d42SDmitry Osipenko WRITE_ONCE(tegra->sys_reboot_mode_req, true);
44103978d42SDmitry Osipenko
44203978d42SDmitry Osipenko /*
44303978d42SDmitry Osipenko * Some devices use CPU soft-reboot method and in this case we
44403978d42SDmitry Osipenko * should ensure that voltages are sane for the reboot by restoring
44503978d42SDmitry Osipenko * the minimum boot levels.
44603978d42SDmitry Osipenko */
44703978d42SDmitry Osipenko err = regulator_sync_voltage_rdev(tegra->cpu_rdev);
44803978d42SDmitry Osipenko if (err)
44903978d42SDmitry Osipenko return err;
45003978d42SDmitry Osipenko
45103978d42SDmitry Osipenko err = regulator_sync_voltage_rdev(tegra->core_rdev);
45203978d42SDmitry Osipenko if (err)
45303978d42SDmitry Osipenko return err;
45403978d42SDmitry Osipenko
45503978d42SDmitry Osipenko WRITE_ONCE(tegra->sys_reboot_mode_req, sys_reboot_mode);
45603978d42SDmitry Osipenko
45703978d42SDmitry Osipenko return 0;
45803978d42SDmitry Osipenko }
45903978d42SDmitry Osipenko
tegra20_regulator_reboot(struct notifier_block * notifier,unsigned long event,void * cmd)46003978d42SDmitry Osipenko static int tegra20_regulator_reboot(struct notifier_block *notifier,
46103978d42SDmitry Osipenko unsigned long event, void *cmd)
46203978d42SDmitry Osipenko {
46303978d42SDmitry Osipenko struct tegra_regulator_coupler *tegra;
46403978d42SDmitry Osipenko int ret;
46503978d42SDmitry Osipenko
46603978d42SDmitry Osipenko if (event != SYS_RESTART)
46703978d42SDmitry Osipenko return NOTIFY_DONE;
46803978d42SDmitry Osipenko
46903978d42SDmitry Osipenko tegra = container_of(notifier, struct tegra_regulator_coupler,
47003978d42SDmitry Osipenko reboot_notifier);
47103978d42SDmitry Osipenko
47203978d42SDmitry Osipenko ret = tegra20_regulator_prepare_reboot(tegra, true);
47303978d42SDmitry Osipenko
47403978d42SDmitry Osipenko return notifier_from_errno(ret);
47503978d42SDmitry Osipenko }
47603978d42SDmitry Osipenko
tegra20_regulator_attach(struct regulator_coupler * coupler,struct regulator_dev * rdev)477496747e7SDmitry Osipenko static int tegra20_regulator_attach(struct regulator_coupler *coupler,
478496747e7SDmitry Osipenko struct regulator_dev *rdev)
479496747e7SDmitry Osipenko {
480496747e7SDmitry Osipenko struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
481496747e7SDmitry Osipenko struct device_node *np = rdev->dev.of_node;
482496747e7SDmitry Osipenko
483496747e7SDmitry Osipenko if (of_property_read_bool(np, "nvidia,tegra-core-regulator") &&
484496747e7SDmitry Osipenko !tegra->core_rdev) {
485496747e7SDmitry Osipenko tegra->core_rdev = rdev;
486496747e7SDmitry Osipenko return 0;
487496747e7SDmitry Osipenko }
488496747e7SDmitry Osipenko
489496747e7SDmitry Osipenko if (of_property_read_bool(np, "nvidia,tegra-rtc-regulator") &&
490496747e7SDmitry Osipenko !tegra->rtc_rdev) {
491496747e7SDmitry Osipenko tegra->rtc_rdev = rdev;
492496747e7SDmitry Osipenko return 0;
493496747e7SDmitry Osipenko }
494496747e7SDmitry Osipenko
495496747e7SDmitry Osipenko if (of_property_read_bool(np, "nvidia,tegra-cpu-regulator") &&
496496747e7SDmitry Osipenko !tegra->cpu_rdev) {
497496747e7SDmitry Osipenko tegra->cpu_rdev = rdev;
498496747e7SDmitry Osipenko return 0;
499496747e7SDmitry Osipenko }
500496747e7SDmitry Osipenko
501496747e7SDmitry Osipenko return -EINVAL;
502496747e7SDmitry Osipenko }
503496747e7SDmitry Osipenko
tegra20_regulator_detach(struct regulator_coupler * coupler,struct regulator_dev * rdev)504496747e7SDmitry Osipenko static int tegra20_regulator_detach(struct regulator_coupler *coupler,
505496747e7SDmitry Osipenko struct regulator_dev *rdev)
506496747e7SDmitry Osipenko {
507496747e7SDmitry Osipenko struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
508496747e7SDmitry Osipenko
50903978d42SDmitry Osipenko /*
51003978d42SDmitry Osipenko * We don't expect regulators to be decoupled during reboot,
51103978d42SDmitry Osipenko * this may race with the reboot handler and shouldn't ever
51203978d42SDmitry Osipenko * happen in practice.
51303978d42SDmitry Osipenko */
51403978d42SDmitry Osipenko if (WARN_ON_ONCE(system_state > SYSTEM_RUNNING))
51503978d42SDmitry Osipenko return -EPERM;
51603978d42SDmitry Osipenko
517496747e7SDmitry Osipenko if (tegra->core_rdev == rdev) {
518496747e7SDmitry Osipenko tegra->core_rdev = NULL;
519496747e7SDmitry Osipenko return 0;
520496747e7SDmitry Osipenko }
521496747e7SDmitry Osipenko
522496747e7SDmitry Osipenko if (tegra->rtc_rdev == rdev) {
523496747e7SDmitry Osipenko tegra->rtc_rdev = NULL;
524496747e7SDmitry Osipenko return 0;
525496747e7SDmitry Osipenko }
526496747e7SDmitry Osipenko
527496747e7SDmitry Osipenko if (tegra->cpu_rdev == rdev) {
528496747e7SDmitry Osipenko tegra->cpu_rdev = NULL;
529496747e7SDmitry Osipenko return 0;
530496747e7SDmitry Osipenko }
531496747e7SDmitry Osipenko
532496747e7SDmitry Osipenko return -EINVAL;
533496747e7SDmitry Osipenko }
534496747e7SDmitry Osipenko
535496747e7SDmitry Osipenko static struct tegra_regulator_coupler tegra20_coupler = {
536496747e7SDmitry Osipenko .coupler = {
537496747e7SDmitry Osipenko .attach_regulator = tegra20_regulator_attach,
538496747e7SDmitry Osipenko .detach_regulator = tegra20_regulator_detach,
539496747e7SDmitry Osipenko .balance_voltage = tegra20_regulator_balance_voltage,
540496747e7SDmitry Osipenko },
54103978d42SDmitry Osipenko .reboot_notifier.notifier_call = tegra20_regulator_reboot,
542*80ef351cSDmitry Osipenko .suspend_notifier.notifier_call = tegra20_regulator_suspend,
543496747e7SDmitry Osipenko };
544496747e7SDmitry Osipenko
tegra_regulator_coupler_init(void)545496747e7SDmitry Osipenko static int __init tegra_regulator_coupler_init(void)
546496747e7SDmitry Osipenko {
54703978d42SDmitry Osipenko int err;
54803978d42SDmitry Osipenko
549496747e7SDmitry Osipenko if (!of_machine_is_compatible("nvidia,tegra20"))
550496747e7SDmitry Osipenko return 0;
551496747e7SDmitry Osipenko
55203978d42SDmitry Osipenko err = register_reboot_notifier(&tegra20_coupler.reboot_notifier);
55303978d42SDmitry Osipenko WARN_ON(err);
55403978d42SDmitry Osipenko
555*80ef351cSDmitry Osipenko err = register_pm_notifier(&tegra20_coupler.suspend_notifier);
556*80ef351cSDmitry Osipenko WARN_ON(err);
557*80ef351cSDmitry Osipenko
558496747e7SDmitry Osipenko return regulator_coupler_register(&tegra20_coupler.coupler);
559496747e7SDmitry Osipenko }
560496747e7SDmitry Osipenko arch_initcall(tegra_regulator_coupler_init);
561