178380743SDmitry Osipenko // SPDX-License-Identifier: GPL-2.0+
278380743SDmitry Osipenko /*
378380743SDmitry Osipenko  * Voltage regulators coupler for NVIDIA Tegra30
478380743SDmitry Osipenko  * Copyright (C) 2019 GRATE-DRIVER project
578380743SDmitry Osipenko  *
678380743SDmitry Osipenko  * Voltage constraints borrowed from downstream kernel sources
778380743SDmitry Osipenko  * Copyright (C) 2010-2011 NVIDIA Corporation
878380743SDmitry Osipenko  */
978380743SDmitry Osipenko 
1078380743SDmitry Osipenko #define pr_fmt(fmt)	"tegra voltage-coupler: " fmt
1178380743SDmitry Osipenko 
1278380743SDmitry Osipenko #include <linux/init.h>
1378380743SDmitry Osipenko #include <linux/kernel.h>
1478380743SDmitry Osipenko #include <linux/of.h>
1503978d42SDmitry Osipenko #include <linux/reboot.h>
1678380743SDmitry Osipenko #include <linux/regulator/coupler.h>
1778380743SDmitry Osipenko #include <linux/regulator/driver.h>
1878380743SDmitry Osipenko #include <linux/regulator/machine.h>
19*80ef351cSDmitry Osipenko #include <linux/suspend.h>
2078380743SDmitry Osipenko 
2178380743SDmitry Osipenko #include <soc/tegra/fuse.h>
22029f7e24SDmitry Osipenko #include <soc/tegra/pmc.h>
2378380743SDmitry Osipenko 
2478380743SDmitry Osipenko struct tegra_regulator_coupler {
2578380743SDmitry Osipenko 	struct regulator_coupler coupler;
2678380743SDmitry Osipenko 	struct regulator_dev *core_rdev;
2778380743SDmitry Osipenko 	struct regulator_dev *cpu_rdev;
2803978d42SDmitry Osipenko 	struct notifier_block reboot_notifier;
29*80ef351cSDmitry Osipenko 	struct notifier_block suspend_notifier;
3003978d42SDmitry Osipenko 	int core_min_uV, cpu_min_uV;
3103978d42SDmitry Osipenko 	bool sys_reboot_mode_req;
3203978d42SDmitry Osipenko 	bool sys_reboot_mode;
33*80ef351cSDmitry Osipenko 	bool sys_suspend_mode_req;
34*80ef351cSDmitry Osipenko 	bool sys_suspend_mode;
3578380743SDmitry Osipenko };
3678380743SDmitry Osipenko 
3778380743SDmitry Osipenko static inline struct tegra_regulator_coupler *
to_tegra_coupler(struct regulator_coupler * coupler)3878380743SDmitry Osipenko to_tegra_coupler(struct regulator_coupler *coupler)
3978380743SDmitry Osipenko {
4078380743SDmitry Osipenko 	return container_of(coupler, struct tegra_regulator_coupler, coupler);
4178380743SDmitry Osipenko }
4278380743SDmitry Osipenko 
tegra30_core_limit(struct tegra_regulator_coupler * tegra,struct regulator_dev * core_rdev)4378380743SDmitry Osipenko static int tegra30_core_limit(struct tegra_regulator_coupler *tegra,
4478380743SDmitry Osipenko 			      struct regulator_dev *core_rdev)
4578380743SDmitry Osipenko {
4678380743SDmitry Osipenko 	int core_min_uV = 0;
4778380743SDmitry Osipenko 	int core_max_uV;
4878380743SDmitry Osipenko 	int core_cur_uV;
4978380743SDmitry Osipenko 	int err;
5078380743SDmitry Osipenko 
51029f7e24SDmitry Osipenko 	/*
52029f7e24SDmitry Osipenko 	 * Tegra30 SoC has critical DVFS-capable devices that are
53029f7e24SDmitry Osipenko 	 * permanently-active or active at a boot time, like EMC
54029f7e24SDmitry Osipenko 	 * (DRAM controller) or Display controller for example.
55029f7e24SDmitry Osipenko 	 *
56029f7e24SDmitry Osipenko 	 * The voltage of a CORE SoC power domain shall not be dropped below
57029f7e24SDmitry Osipenko 	 * a minimum level, which is determined by device's clock rate.
58029f7e24SDmitry Osipenko 	 * This means that we can't fully allow CORE voltage scaling until
59029f7e24SDmitry Osipenko 	 * the state of all DVFS-critical CORE devices is synced.
60029f7e24SDmitry Osipenko 	 */
61029f7e24SDmitry Osipenko 	if (tegra_pmc_core_domain_state_synced() && !tegra->sys_reboot_mode) {
62029f7e24SDmitry Osipenko 		pr_info_once("voltage state synced\n");
63029f7e24SDmitry Osipenko 		return 0;
64029f7e24SDmitry Osipenko 	}
65029f7e24SDmitry Osipenko 
6678380743SDmitry Osipenko 	if (tegra->core_min_uV > 0)
6778380743SDmitry Osipenko 		return tegra->core_min_uV;
6878380743SDmitry Osipenko 
6978380743SDmitry Osipenko 	core_cur_uV = regulator_get_voltage_rdev(core_rdev);
7078380743SDmitry Osipenko 	if (core_cur_uV < 0)
7178380743SDmitry Osipenko 		return core_cur_uV;
7278380743SDmitry Osipenko 
7378380743SDmitry Osipenko 	core_max_uV = max(core_cur_uV, 1200000);
7478380743SDmitry Osipenko 
7578380743SDmitry Osipenko 	err = regulator_check_voltage(core_rdev, &core_min_uV, &core_max_uV);
7678380743SDmitry Osipenko 	if (err)
7778380743SDmitry Osipenko 		return err;
7878380743SDmitry Osipenko 
7978380743SDmitry Osipenko 	/*
8078380743SDmitry Osipenko 	 * Limit minimum CORE voltage to a value left from bootloader or,
8178380743SDmitry Osipenko 	 * if it's unreasonably low value, to the most common 1.2v or to
8278380743SDmitry Osipenko 	 * whatever maximum value defined via board's device-tree.
8378380743SDmitry Osipenko 	 */
8478380743SDmitry Osipenko 	tegra->core_min_uV = core_max_uV;
8578380743SDmitry Osipenko 
86029f7e24SDmitry Osipenko 	pr_info("core voltage initialized to %duV\n", tegra->core_min_uV);
8778380743SDmitry Osipenko 
8878380743SDmitry Osipenko 	return tegra->core_min_uV;
8978380743SDmitry Osipenko }
9078380743SDmitry Osipenko 
tegra30_core_cpu_limit(int cpu_uV)9178380743SDmitry Osipenko static int tegra30_core_cpu_limit(int cpu_uV)
9278380743SDmitry Osipenko {
9378380743SDmitry Osipenko 	if (cpu_uV < 800000)
9478380743SDmitry Osipenko 		return 950000;
9578380743SDmitry Osipenko 
9678380743SDmitry Osipenko 	if (cpu_uV < 900000)
9778380743SDmitry Osipenko 		return 1000000;
9878380743SDmitry Osipenko 
9978380743SDmitry Osipenko 	if (cpu_uV < 1000000)
10078380743SDmitry Osipenko 		return 1100000;
10178380743SDmitry Osipenko 
10278380743SDmitry Osipenko 	if (cpu_uV < 1100000)
10378380743SDmitry Osipenko 		return 1200000;
10478380743SDmitry Osipenko 
10578380743SDmitry Osipenko 	if (cpu_uV < 1250000) {
10678380743SDmitry Osipenko 		switch (tegra_sku_info.cpu_speedo_id) {
10778380743SDmitry Osipenko 		case 0 ... 1:
10878380743SDmitry Osipenko 		case 4:
10978380743SDmitry Osipenko 		case 7 ... 8:
11078380743SDmitry Osipenko 			return 1200000;
11178380743SDmitry Osipenko 
11278380743SDmitry Osipenko 		default:
11378380743SDmitry Osipenko 			return 1300000;
11478380743SDmitry Osipenko 		}
11578380743SDmitry Osipenko 	}
11678380743SDmitry Osipenko 
11778380743SDmitry Osipenko 	return -EINVAL;
11878380743SDmitry Osipenko }
11978380743SDmitry Osipenko 
tegra30_cpu_nominal_uV(void)120*80ef351cSDmitry Osipenko static int tegra30_cpu_nominal_uV(void)
121*80ef351cSDmitry Osipenko {
122*80ef351cSDmitry Osipenko 	switch (tegra_sku_info.cpu_speedo_id) {
123*80ef351cSDmitry Osipenko 	case 10 ... 11:
124*80ef351cSDmitry Osipenko 		return  850000;
125*80ef351cSDmitry Osipenko 
126*80ef351cSDmitry Osipenko 	case 9:
127*80ef351cSDmitry Osipenko 		return  912000;
128*80ef351cSDmitry Osipenko 
129*80ef351cSDmitry Osipenko 	case 1 ...  3:
130*80ef351cSDmitry Osipenko 	case 7 ...  8:
131*80ef351cSDmitry Osipenko 		return 1050000;
132*80ef351cSDmitry Osipenko 
133*80ef351cSDmitry Osipenko 	default:
134*80ef351cSDmitry Osipenko 		return 1125000;
135*80ef351cSDmitry Osipenko 
136*80ef351cSDmitry Osipenko 	case  4 ...  6:
137*80ef351cSDmitry Osipenko 	case 12 ... 13:
138*80ef351cSDmitry Osipenko 		return 1237000;
139*80ef351cSDmitry Osipenko 	}
140*80ef351cSDmitry Osipenko }
141*80ef351cSDmitry Osipenko 
tegra30_core_nominal_uV(void)142*80ef351cSDmitry Osipenko static int tegra30_core_nominal_uV(void)
143*80ef351cSDmitry Osipenko {
144*80ef351cSDmitry Osipenko 	switch (tegra_sku_info.soc_speedo_id) {
145*80ef351cSDmitry Osipenko 	case 0:
146*80ef351cSDmitry Osipenko 		return 1200000;
147*80ef351cSDmitry Osipenko 
148*80ef351cSDmitry Osipenko 	case 1:
149*80ef351cSDmitry Osipenko 		if (tegra_sku_info.cpu_speedo_id != 7 &&
150*80ef351cSDmitry Osipenko 		    tegra_sku_info.cpu_speedo_id != 8)
151*80ef351cSDmitry Osipenko 			return 1200000;
152*80ef351cSDmitry Osipenko 
153*80ef351cSDmitry Osipenko 		fallthrough;
154*80ef351cSDmitry Osipenko 
155*80ef351cSDmitry Osipenko 	case 2:
156*80ef351cSDmitry Osipenko 		if (tegra_sku_info.cpu_speedo_id != 13)
157*80ef351cSDmitry Osipenko 			return 1300000;
158*80ef351cSDmitry Osipenko 
159*80ef351cSDmitry Osipenko 		return 1350000;
160*80ef351cSDmitry Osipenko 
161*80ef351cSDmitry Osipenko 	default:
162*80ef351cSDmitry Osipenko 		return 1250000;
163*80ef351cSDmitry Osipenko 	}
164*80ef351cSDmitry Osipenko }
165*80ef351cSDmitry Osipenko 
tegra30_voltage_update(struct tegra_regulator_coupler * tegra,struct regulator_dev * cpu_rdev,struct regulator_dev * core_rdev)16678380743SDmitry Osipenko static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra,
16778380743SDmitry Osipenko 				  struct regulator_dev *cpu_rdev,
16878380743SDmitry Osipenko 				  struct regulator_dev *core_rdev)
16978380743SDmitry Osipenko {
17078380743SDmitry Osipenko 	int core_min_uV, core_max_uV = INT_MAX;
17178380743SDmitry Osipenko 	int cpu_min_uV, cpu_max_uV = INT_MAX;
17278380743SDmitry Osipenko 	int cpu_min_uV_consumers = 0;
17378380743SDmitry Osipenko 	int core_min_limited_uV;
17478380743SDmitry Osipenko 	int core_target_uV;
17578380743SDmitry Osipenko 	int cpu_target_uV;
17678380743SDmitry Osipenko 	int core_max_step;
17778380743SDmitry Osipenko 	int cpu_max_step;
17878380743SDmitry Osipenko 	int max_spread;
17978380743SDmitry Osipenko 	int core_uV;
18078380743SDmitry Osipenko 	int cpu_uV;
18178380743SDmitry Osipenko 	int err;
18278380743SDmitry Osipenko 
18378380743SDmitry Osipenko 	/*
18478380743SDmitry Osipenko 	 * CPU voltage should not got lower than 300mV from the CORE.
18578380743SDmitry Osipenko 	 * CPU voltage should stay below the CORE by 100mV+, depending
18678380743SDmitry Osipenko 	 * by the CORE voltage. This applies to all Tegra30 SoC's.
18778380743SDmitry Osipenko 	 */
18878380743SDmitry Osipenko 	max_spread = cpu_rdev->constraints->max_spread[0];
18978380743SDmitry Osipenko 	cpu_max_step = cpu_rdev->constraints->max_uV_step;
19078380743SDmitry Osipenko 	core_max_step = core_rdev->constraints->max_uV_step;
19178380743SDmitry Osipenko 
19278380743SDmitry Osipenko 	if (!max_spread) {
19378380743SDmitry Osipenko 		pr_err_once("cpu-core max-spread is undefined in device-tree\n");
19478380743SDmitry Osipenko 		max_spread = 300000;
19578380743SDmitry Osipenko 	}
19678380743SDmitry Osipenko 
19778380743SDmitry Osipenko 	if (!cpu_max_step) {
19878380743SDmitry Osipenko 		pr_err_once("cpu max-step is undefined in device-tree\n");
19978380743SDmitry Osipenko 		cpu_max_step = 150000;
20078380743SDmitry Osipenko 	}
20178380743SDmitry Osipenko 
20278380743SDmitry Osipenko 	if (!core_max_step) {
20378380743SDmitry Osipenko 		pr_err_once("core max-step is undefined in device-tree\n");
20478380743SDmitry Osipenko 		core_max_step = 150000;
20578380743SDmitry Osipenko 	}
20678380743SDmitry Osipenko 
20778380743SDmitry Osipenko 	/*
20878380743SDmitry Osipenko 	 * The CORE voltage scaling is currently not hooked up in drivers,
20978380743SDmitry Osipenko 	 * hence we will limit the minimum CORE voltage to a reasonable value.
21078380743SDmitry Osipenko 	 * This should be good enough for the time being.
21178380743SDmitry Osipenko 	 */
21278380743SDmitry Osipenko 	core_min_uV = tegra30_core_limit(tegra, core_rdev);
21378380743SDmitry Osipenko 	if (core_min_uV < 0)
21478380743SDmitry Osipenko 		return core_min_uV;
21578380743SDmitry Osipenko 
21678380743SDmitry Osipenko 	err = regulator_check_consumers(core_rdev, &core_min_uV, &core_max_uV,
21778380743SDmitry Osipenko 					PM_SUSPEND_ON);
21878380743SDmitry Osipenko 	if (err)
21978380743SDmitry Osipenko 		return err;
22078380743SDmitry Osipenko 
221*80ef351cSDmitry Osipenko 	/* prepare voltage level for suspend */
222*80ef351cSDmitry Osipenko 	if (tegra->sys_suspend_mode)
223*80ef351cSDmitry Osipenko 		core_min_uV = clamp(tegra30_core_nominal_uV(),
224*80ef351cSDmitry Osipenko 				    core_min_uV, core_max_uV);
225*80ef351cSDmitry Osipenko 
22678380743SDmitry Osipenko 	core_uV = regulator_get_voltage_rdev(core_rdev);
22778380743SDmitry Osipenko 	if (core_uV < 0)
22878380743SDmitry Osipenko 		return core_uV;
22978380743SDmitry Osipenko 
23078380743SDmitry Osipenko 	cpu_min_uV = core_min_uV - max_spread;
23178380743SDmitry Osipenko 
23278380743SDmitry Osipenko 	err = regulator_check_consumers(cpu_rdev, &cpu_min_uV, &cpu_max_uV,
23378380743SDmitry Osipenko 					PM_SUSPEND_ON);
23478380743SDmitry Osipenko 	if (err)
23578380743SDmitry Osipenko 		return err;
23678380743SDmitry Osipenko 
23778380743SDmitry Osipenko 	err = regulator_check_consumers(cpu_rdev, &cpu_min_uV_consumers,
23878380743SDmitry Osipenko 					&cpu_max_uV, PM_SUSPEND_ON);
23978380743SDmitry Osipenko 	if (err)
24078380743SDmitry Osipenko 		return err;
24178380743SDmitry Osipenko 
24278380743SDmitry Osipenko 	err = regulator_check_voltage(cpu_rdev, &cpu_min_uV, &cpu_max_uV);
24378380743SDmitry Osipenko 	if (err)
24478380743SDmitry Osipenko 		return err;
24578380743SDmitry Osipenko 
24678380743SDmitry Osipenko 	cpu_uV = regulator_get_voltage_rdev(cpu_rdev);
24778380743SDmitry Osipenko 	if (cpu_uV < 0)
24878380743SDmitry Osipenko 		return cpu_uV;
24978380743SDmitry Osipenko 
25003978d42SDmitry Osipenko 	/* store boot voltage level */
25103978d42SDmitry Osipenko 	if (!tegra->cpu_min_uV)
25203978d42SDmitry Osipenko 		tegra->cpu_min_uV = cpu_uV;
25303978d42SDmitry Osipenko 
25478380743SDmitry Osipenko 	/*
25578380743SDmitry Osipenko 	 * CPU's regulator may not have any consumers, hence the voltage
25678380743SDmitry Osipenko 	 * must not be changed in that case because CPU simply won't
25778380743SDmitry Osipenko 	 * survive the voltage drop if it's running on a higher frequency.
25878380743SDmitry Osipenko 	 */
25978380743SDmitry Osipenko 	if (!cpu_min_uV_consumers)
260ef85bb58SDmitry Osipenko 		cpu_min_uV = max(cpu_uV, cpu_min_uV);
26178380743SDmitry Osipenko 
26278380743SDmitry Osipenko 	/*
26378380743SDmitry Osipenko 	 * Bootloader shall set up voltages correctly, but if it
26478380743SDmitry Osipenko 	 * happens that there is a violation, then try to fix it
26578380743SDmitry Osipenko 	 * at first.
26678380743SDmitry Osipenko 	 */
26778380743SDmitry Osipenko 	core_min_limited_uV = tegra30_core_cpu_limit(cpu_uV);
26878380743SDmitry Osipenko 	if (core_min_limited_uV < 0)
26978380743SDmitry Osipenko 		return core_min_limited_uV;
27078380743SDmitry Osipenko 
27178380743SDmitry Osipenko 	core_min_uV = max(core_min_uV, tegra30_core_cpu_limit(cpu_min_uV));
27278380743SDmitry Osipenko 
27378380743SDmitry Osipenko 	err = regulator_check_voltage(core_rdev, &core_min_uV, &core_max_uV);
27478380743SDmitry Osipenko 	if (err)
27578380743SDmitry Osipenko 		return err;
27678380743SDmitry Osipenko 
27703978d42SDmitry Osipenko 	/* restore boot voltage level */
27803978d42SDmitry Osipenko 	if (tegra->sys_reboot_mode)
27903978d42SDmitry Osipenko 		cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV);
28003978d42SDmitry Osipenko 
281*80ef351cSDmitry Osipenko 	/* prepare voltage level for suspend */
282*80ef351cSDmitry Osipenko 	if (tegra->sys_suspend_mode)
283*80ef351cSDmitry Osipenko 		cpu_min_uV = clamp(tegra30_cpu_nominal_uV(),
284*80ef351cSDmitry Osipenko 				   cpu_min_uV, cpu_max_uV);
285*80ef351cSDmitry Osipenko 
28678380743SDmitry Osipenko 	if (core_min_limited_uV > core_uV) {
28778380743SDmitry Osipenko 		pr_err("core voltage constraint violated: %d %d %d\n",
28878380743SDmitry Osipenko 		       core_uV, core_min_limited_uV, cpu_uV);
28978380743SDmitry Osipenko 		goto update_core;
29078380743SDmitry Osipenko 	}
29178380743SDmitry Osipenko 
29278380743SDmitry Osipenko 	while (cpu_uV != cpu_min_uV || core_uV != core_min_uV) {
29378380743SDmitry Osipenko 		if (cpu_uV < cpu_min_uV) {
29478380743SDmitry Osipenko 			cpu_target_uV = min(cpu_uV + cpu_max_step, cpu_min_uV);
29578380743SDmitry Osipenko 		} else {
29678380743SDmitry Osipenko 			cpu_target_uV = max(cpu_uV - cpu_max_step, cpu_min_uV);
29778380743SDmitry Osipenko 			cpu_target_uV = max(core_uV - max_spread, cpu_target_uV);
29878380743SDmitry Osipenko 		}
29978380743SDmitry Osipenko 
30045f019a6SDmitry Osipenko 		if (cpu_uV == cpu_target_uV)
30145f019a6SDmitry Osipenko 			goto update_core;
30245f019a6SDmitry Osipenko 
30378380743SDmitry Osipenko 		err = regulator_set_voltage_rdev(cpu_rdev,
30478380743SDmitry Osipenko 						 cpu_target_uV,
30578380743SDmitry Osipenko 						 cpu_max_uV,
30678380743SDmitry Osipenko 						 PM_SUSPEND_ON);
30778380743SDmitry Osipenko 		if (err)
30878380743SDmitry Osipenko 			return err;
30978380743SDmitry Osipenko 
31078380743SDmitry Osipenko 		cpu_uV = cpu_target_uV;
31178380743SDmitry Osipenko update_core:
31278380743SDmitry Osipenko 		core_min_limited_uV = tegra30_core_cpu_limit(cpu_uV);
31378380743SDmitry Osipenko 		if (core_min_limited_uV < 0)
31478380743SDmitry Osipenko 			return core_min_limited_uV;
31578380743SDmitry Osipenko 
31678380743SDmitry Osipenko 		core_target_uV = max(core_min_limited_uV, core_min_uV);
31778380743SDmitry Osipenko 
31878380743SDmitry Osipenko 		if (core_uV < core_target_uV) {
31978380743SDmitry Osipenko 			core_target_uV = min(core_target_uV, core_uV + core_max_step);
32078380743SDmitry Osipenko 			core_target_uV = min(core_target_uV, cpu_uV + max_spread);
32178380743SDmitry Osipenko 		} else {
32278380743SDmitry Osipenko 			core_target_uV = max(core_target_uV, core_uV - core_max_step);
32378380743SDmitry Osipenko 		}
32478380743SDmitry Osipenko 
32545f019a6SDmitry Osipenko 		if (core_uV == core_target_uV)
32645f019a6SDmitry Osipenko 			continue;
32745f019a6SDmitry Osipenko 
32878380743SDmitry Osipenko 		err = regulator_set_voltage_rdev(core_rdev,
32978380743SDmitry Osipenko 						 core_target_uV,
33078380743SDmitry Osipenko 						 core_max_uV,
33178380743SDmitry Osipenko 						 PM_SUSPEND_ON);
33278380743SDmitry Osipenko 		if (err)
33378380743SDmitry Osipenko 			return err;
33478380743SDmitry Osipenko 
33578380743SDmitry Osipenko 		core_uV = core_target_uV;
33678380743SDmitry Osipenko 	}
33778380743SDmitry Osipenko 
33878380743SDmitry Osipenko 	return 0;
33978380743SDmitry Osipenko }
34078380743SDmitry Osipenko 
tegra30_regulator_balance_voltage(struct regulator_coupler * coupler,struct regulator_dev * rdev,suspend_state_t state)34178380743SDmitry Osipenko static int tegra30_regulator_balance_voltage(struct regulator_coupler *coupler,
34278380743SDmitry Osipenko 					     struct regulator_dev *rdev,
34378380743SDmitry Osipenko 					     suspend_state_t state)
34478380743SDmitry Osipenko {
34578380743SDmitry Osipenko 	struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
34678380743SDmitry Osipenko 	struct regulator_dev *core_rdev = tegra->core_rdev;
34778380743SDmitry Osipenko 	struct regulator_dev *cpu_rdev = tegra->cpu_rdev;
34878380743SDmitry Osipenko 
34978380743SDmitry Osipenko 	if ((core_rdev != rdev && cpu_rdev != rdev) || state != PM_SUSPEND_ON) {
35078380743SDmitry Osipenko 		pr_err("regulators are not coupled properly\n");
35178380743SDmitry Osipenko 		return -EINVAL;
35278380743SDmitry Osipenko 	}
35378380743SDmitry Osipenko 
35403978d42SDmitry Osipenko 	tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req);
355*80ef351cSDmitry Osipenko 	tegra->sys_suspend_mode = READ_ONCE(tegra->sys_suspend_mode_req);
35603978d42SDmitry Osipenko 
35778380743SDmitry Osipenko 	return tegra30_voltage_update(tegra, cpu_rdev, core_rdev);
35878380743SDmitry Osipenko }
35978380743SDmitry Osipenko 
tegra30_regulator_prepare_suspend(struct tegra_regulator_coupler * tegra,bool sys_suspend_mode)360*80ef351cSDmitry Osipenko static int tegra30_regulator_prepare_suspend(struct tegra_regulator_coupler *tegra,
361*80ef351cSDmitry Osipenko 					     bool sys_suspend_mode)
362*80ef351cSDmitry Osipenko {
363*80ef351cSDmitry Osipenko 	int err;
364*80ef351cSDmitry Osipenko 
365*80ef351cSDmitry Osipenko 	if (!tegra->core_rdev || !tegra->cpu_rdev)
366*80ef351cSDmitry Osipenko 		return 0;
367*80ef351cSDmitry Osipenko 
368*80ef351cSDmitry Osipenko 	/*
369*80ef351cSDmitry Osipenko 	 * All power domains are enabled early during resume from suspend
370*80ef351cSDmitry Osipenko 	 * by GENPD core.  Domains like VENC may require a higher voltage
371*80ef351cSDmitry Osipenko 	 * when enabled during resume from suspend.  This also prepares
372*80ef351cSDmitry Osipenko 	 * hardware for resuming from LP0.
373*80ef351cSDmitry Osipenko 	 */
374*80ef351cSDmitry Osipenko 
375*80ef351cSDmitry Osipenko 	WRITE_ONCE(tegra->sys_suspend_mode_req, sys_suspend_mode);
376*80ef351cSDmitry Osipenko 
377*80ef351cSDmitry Osipenko 	err = regulator_sync_voltage_rdev(tegra->cpu_rdev);
378*80ef351cSDmitry Osipenko 	if (err)
379*80ef351cSDmitry Osipenko 		return err;
380*80ef351cSDmitry Osipenko 
381*80ef351cSDmitry Osipenko 	err = regulator_sync_voltage_rdev(tegra->core_rdev);
382*80ef351cSDmitry Osipenko 	if (err)
383*80ef351cSDmitry Osipenko 		return err;
384*80ef351cSDmitry Osipenko 
385*80ef351cSDmitry Osipenko 	return 0;
386*80ef351cSDmitry Osipenko }
387*80ef351cSDmitry Osipenko 
tegra30_regulator_suspend(struct notifier_block * notifier,unsigned long mode,void * arg)388*80ef351cSDmitry Osipenko static int tegra30_regulator_suspend(struct notifier_block *notifier,
389*80ef351cSDmitry Osipenko 				     unsigned long mode, void *arg)
390*80ef351cSDmitry Osipenko {
391*80ef351cSDmitry Osipenko 	struct tegra_regulator_coupler *tegra;
392*80ef351cSDmitry Osipenko 	int ret = 0;
393*80ef351cSDmitry Osipenko 
394*80ef351cSDmitry Osipenko 	tegra = container_of(notifier, struct tegra_regulator_coupler,
395*80ef351cSDmitry Osipenko 			     suspend_notifier);
396*80ef351cSDmitry Osipenko 
397*80ef351cSDmitry Osipenko 	switch (mode) {
398*80ef351cSDmitry Osipenko 	case PM_HIBERNATION_PREPARE:
399*80ef351cSDmitry Osipenko 	case PM_RESTORE_PREPARE:
400*80ef351cSDmitry Osipenko 	case PM_SUSPEND_PREPARE:
401*80ef351cSDmitry Osipenko 		ret = tegra30_regulator_prepare_suspend(tegra, true);
402*80ef351cSDmitry Osipenko 		break;
403*80ef351cSDmitry Osipenko 
404*80ef351cSDmitry Osipenko 	case PM_POST_HIBERNATION:
405*80ef351cSDmitry Osipenko 	case PM_POST_RESTORE:
406*80ef351cSDmitry Osipenko 	case PM_POST_SUSPEND:
407*80ef351cSDmitry Osipenko 		ret = tegra30_regulator_prepare_suspend(tegra, false);
408*80ef351cSDmitry Osipenko 		break;
409*80ef351cSDmitry Osipenko 	}
410*80ef351cSDmitry Osipenko 
411*80ef351cSDmitry Osipenko 	if (ret)
412*80ef351cSDmitry Osipenko 		pr_err("failed to prepare regulators: %d\n", ret);
413*80ef351cSDmitry Osipenko 
414*80ef351cSDmitry Osipenko 	return notifier_from_errno(ret);
415*80ef351cSDmitry Osipenko }
416*80ef351cSDmitry Osipenko 
tegra30_regulator_prepare_reboot(struct tegra_regulator_coupler * tegra,bool sys_reboot_mode)41703978d42SDmitry Osipenko static int tegra30_regulator_prepare_reboot(struct tegra_regulator_coupler *tegra,
41803978d42SDmitry Osipenko 					    bool sys_reboot_mode)
41903978d42SDmitry Osipenko {
42003978d42SDmitry Osipenko 	int err;
42103978d42SDmitry Osipenko 
42203978d42SDmitry Osipenko 	if (!tegra->core_rdev || !tegra->cpu_rdev)
42303978d42SDmitry Osipenko 		return 0;
42403978d42SDmitry Osipenko 
42503978d42SDmitry Osipenko 	WRITE_ONCE(tegra->sys_reboot_mode_req, true);
42603978d42SDmitry Osipenko 
42703978d42SDmitry Osipenko 	/*
42803978d42SDmitry Osipenko 	 * Some devices use CPU soft-reboot method and in this case we
42903978d42SDmitry Osipenko 	 * should ensure that voltages are sane for the reboot by restoring
43003978d42SDmitry Osipenko 	 * the minimum boot levels.
43103978d42SDmitry Osipenko 	 */
43203978d42SDmitry Osipenko 	err = regulator_sync_voltage_rdev(tegra->cpu_rdev);
43303978d42SDmitry Osipenko 	if (err)
43403978d42SDmitry Osipenko 		return err;
43503978d42SDmitry Osipenko 
43603978d42SDmitry Osipenko 	err = regulator_sync_voltage_rdev(tegra->core_rdev);
43703978d42SDmitry Osipenko 	if (err)
43803978d42SDmitry Osipenko 		return err;
43903978d42SDmitry Osipenko 
44003978d42SDmitry Osipenko 	WRITE_ONCE(tegra->sys_reboot_mode_req, sys_reboot_mode);
44103978d42SDmitry Osipenko 
44203978d42SDmitry Osipenko 	return 0;
44303978d42SDmitry Osipenko }
44403978d42SDmitry Osipenko 
tegra30_regulator_reboot(struct notifier_block * notifier,unsigned long event,void * cmd)44503978d42SDmitry Osipenko static int tegra30_regulator_reboot(struct notifier_block *notifier,
44603978d42SDmitry Osipenko 				    unsigned long event, void *cmd)
44703978d42SDmitry Osipenko {
44803978d42SDmitry Osipenko 	struct tegra_regulator_coupler *tegra;
44903978d42SDmitry Osipenko 	int ret;
45003978d42SDmitry Osipenko 
45103978d42SDmitry Osipenko 	if (event != SYS_RESTART)
45203978d42SDmitry Osipenko 		return NOTIFY_DONE;
45303978d42SDmitry Osipenko 
45403978d42SDmitry Osipenko 	tegra = container_of(notifier, struct tegra_regulator_coupler,
45503978d42SDmitry Osipenko 			     reboot_notifier);
45603978d42SDmitry Osipenko 
45703978d42SDmitry Osipenko 	ret = tegra30_regulator_prepare_reboot(tegra, true);
45803978d42SDmitry Osipenko 
45903978d42SDmitry Osipenko 	return notifier_from_errno(ret);
46003978d42SDmitry Osipenko }
46103978d42SDmitry Osipenko 
tegra30_regulator_attach(struct regulator_coupler * coupler,struct regulator_dev * rdev)46278380743SDmitry Osipenko static int tegra30_regulator_attach(struct regulator_coupler *coupler,
46378380743SDmitry Osipenko 				    struct regulator_dev *rdev)
46478380743SDmitry Osipenko {
46578380743SDmitry Osipenko 	struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
46678380743SDmitry Osipenko 	struct device_node *np = rdev->dev.of_node;
46778380743SDmitry Osipenko 
46878380743SDmitry Osipenko 	if (of_property_read_bool(np, "nvidia,tegra-core-regulator") &&
46978380743SDmitry Osipenko 	    !tegra->core_rdev) {
47078380743SDmitry Osipenko 		tegra->core_rdev = rdev;
47178380743SDmitry Osipenko 		return 0;
47278380743SDmitry Osipenko 	}
47378380743SDmitry Osipenko 
47478380743SDmitry Osipenko 	if (of_property_read_bool(np, "nvidia,tegra-cpu-regulator") &&
47578380743SDmitry Osipenko 	    !tegra->cpu_rdev) {
47678380743SDmitry Osipenko 		tegra->cpu_rdev = rdev;
47778380743SDmitry Osipenko 		return 0;
47878380743SDmitry Osipenko 	}
47978380743SDmitry Osipenko 
48078380743SDmitry Osipenko 	return -EINVAL;
48178380743SDmitry Osipenko }
48278380743SDmitry Osipenko 
tegra30_regulator_detach(struct regulator_coupler * coupler,struct regulator_dev * rdev)48378380743SDmitry Osipenko static int tegra30_regulator_detach(struct regulator_coupler *coupler,
48478380743SDmitry Osipenko 				    struct regulator_dev *rdev)
48578380743SDmitry Osipenko {
48678380743SDmitry Osipenko 	struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
48778380743SDmitry Osipenko 
48803978d42SDmitry Osipenko 	/*
48903978d42SDmitry Osipenko 	 * We don't expect regulators to be decoupled during reboot,
49003978d42SDmitry Osipenko 	 * this may race with the reboot handler and shouldn't ever
49103978d42SDmitry Osipenko 	 * happen in practice.
49203978d42SDmitry Osipenko 	 */
49303978d42SDmitry Osipenko 	if (WARN_ON_ONCE(system_state > SYSTEM_RUNNING))
49403978d42SDmitry Osipenko 		return -EPERM;
49503978d42SDmitry Osipenko 
49678380743SDmitry Osipenko 	if (tegra->core_rdev == rdev) {
49778380743SDmitry Osipenko 		tegra->core_rdev = NULL;
49878380743SDmitry Osipenko 		return 0;
49978380743SDmitry Osipenko 	}
50078380743SDmitry Osipenko 
50178380743SDmitry Osipenko 	if (tegra->cpu_rdev == rdev) {
50278380743SDmitry Osipenko 		tegra->cpu_rdev = NULL;
50378380743SDmitry Osipenko 		return 0;
50478380743SDmitry Osipenko 	}
50578380743SDmitry Osipenko 
50678380743SDmitry Osipenko 	return -EINVAL;
50778380743SDmitry Osipenko }
50878380743SDmitry Osipenko 
50978380743SDmitry Osipenko static struct tegra_regulator_coupler tegra30_coupler = {
51078380743SDmitry Osipenko 	.coupler = {
51178380743SDmitry Osipenko 		.attach_regulator = tegra30_regulator_attach,
51278380743SDmitry Osipenko 		.detach_regulator = tegra30_regulator_detach,
51378380743SDmitry Osipenko 		.balance_voltage = tegra30_regulator_balance_voltage,
51478380743SDmitry Osipenko 	},
51503978d42SDmitry Osipenko 	.reboot_notifier.notifier_call = tegra30_regulator_reboot,
516*80ef351cSDmitry Osipenko 	.suspend_notifier.notifier_call = tegra30_regulator_suspend,
51778380743SDmitry Osipenko };
51878380743SDmitry Osipenko 
tegra_regulator_coupler_init(void)51978380743SDmitry Osipenko static int __init tegra_regulator_coupler_init(void)
52078380743SDmitry Osipenko {
52103978d42SDmitry Osipenko 	int err;
52203978d42SDmitry Osipenko 
52378380743SDmitry Osipenko 	if (!of_machine_is_compatible("nvidia,tegra30"))
52478380743SDmitry Osipenko 		return 0;
52578380743SDmitry Osipenko 
52603978d42SDmitry Osipenko 	err = register_reboot_notifier(&tegra30_coupler.reboot_notifier);
52703978d42SDmitry Osipenko 	WARN_ON(err);
52803978d42SDmitry Osipenko 
529*80ef351cSDmitry Osipenko 	err = register_pm_notifier(&tegra30_coupler.suspend_notifier);
530*80ef351cSDmitry Osipenko 	WARN_ON(err);
531*80ef351cSDmitry Osipenko 
53278380743SDmitry Osipenko 	return regulator_coupler_register(&tegra30_coupler.coupler);
53378380743SDmitry Osipenko }
53478380743SDmitry Osipenko arch_initcall(tegra_regulator_coupler_init);
535