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