brintos

brintos / linux-shallow public Read only

0
0
Text · 12.7 KiB · 8fd43c6 Raw
535 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Voltage regulators coupler for NVIDIA Tegra304 * Copyright (C) 2019 GRATE-DRIVER project5 *6 * Voltage constraints borrowed from downstream kernel sources7 * Copyright (C) 2010-2011 NVIDIA Corporation8 */9 10#define pr_fmt(fmt)	"tegra voltage-coupler: " fmt11 12#include <linux/init.h>13#include <linux/kernel.h>14#include <linux/of.h>15#include <linux/reboot.h>16#include <linux/regulator/coupler.h>17#include <linux/regulator/driver.h>18#include <linux/regulator/machine.h>19#include <linux/suspend.h>20 21#include <soc/tegra/fuse.h>22#include <soc/tegra/pmc.h>23 24struct tegra_regulator_coupler {25	struct regulator_coupler coupler;26	struct regulator_dev *core_rdev;27	struct regulator_dev *cpu_rdev;28	struct notifier_block reboot_notifier;29	struct notifier_block suspend_notifier;30	int core_min_uV, cpu_min_uV;31	bool sys_reboot_mode_req;32	bool sys_reboot_mode;33	bool sys_suspend_mode_req;34	bool sys_suspend_mode;35};36 37static inline struct tegra_regulator_coupler *38to_tegra_coupler(struct regulator_coupler *coupler)39{40	return container_of(coupler, struct tegra_regulator_coupler, coupler);41}42 43static int tegra30_core_limit(struct tegra_regulator_coupler *tegra,44			      struct regulator_dev *core_rdev)45{46	int core_min_uV = 0;47	int core_max_uV;48	int core_cur_uV;49	int err;50 51	/*52	 * Tegra30 SoC has critical DVFS-capable devices that are53	 * permanently-active or active at a boot time, like EMC54	 * (DRAM controller) or Display controller for example.55	 *56	 * The voltage of a CORE SoC power domain shall not be dropped below57	 * a minimum level, which is determined by device's clock rate.58	 * This means that we can't fully allow CORE voltage scaling until59	 * the state of all DVFS-critical CORE devices is synced.60	 */61	if (tegra_pmc_core_domain_state_synced() && !tegra->sys_reboot_mode) {62		pr_info_once("voltage state synced\n");63		return 0;64	}65 66	if (tegra->core_min_uV > 0)67		return tegra->core_min_uV;68 69	core_cur_uV = regulator_get_voltage_rdev(core_rdev);70	if (core_cur_uV < 0)71		return core_cur_uV;72 73	core_max_uV = max(core_cur_uV, 1200000);74 75	err = regulator_check_voltage(core_rdev, &core_min_uV, &core_max_uV);76	if (err)77		return err;78 79	/*80	 * Limit minimum CORE voltage to a value left from bootloader or,81	 * if it's unreasonably low value, to the most common 1.2v or to82	 * whatever maximum value defined via board's device-tree.83	 */84	tegra->core_min_uV = core_max_uV;85 86	pr_info("core voltage initialized to %duV\n", tegra->core_min_uV);87 88	return tegra->core_min_uV;89}90 91static int tegra30_core_cpu_limit(int cpu_uV)92{93	if (cpu_uV < 800000)94		return 950000;95 96	if (cpu_uV < 900000)97		return 1000000;98 99	if (cpu_uV < 1000000)100		return 1100000;101 102	if (cpu_uV < 1100000)103		return 1200000;104 105	if (cpu_uV < 1250000) {106		switch (tegra_sku_info.cpu_speedo_id) {107		case 0 ... 1:108		case 4:109		case 7 ... 8:110			return 1200000;111 112		default:113			return 1300000;114		}115	}116 117	return -EINVAL;118}119 120static int tegra30_cpu_nominal_uV(void)121{122	switch (tegra_sku_info.cpu_speedo_id) {123	case 10 ... 11:124		return  850000;125 126	case 9:127		return  912000;128 129	case 1 ...  3:130	case 7 ...  8:131		return 1050000;132 133	default:134		return 1125000;135 136	case  4 ...  6:137	case 12 ... 13:138		return 1237000;139	}140}141 142static int tegra30_core_nominal_uV(void)143{144	switch (tegra_sku_info.soc_speedo_id) {145	case 0:146		return 1200000;147 148	case 1:149		if (tegra_sku_info.cpu_speedo_id != 7 &&150		    tegra_sku_info.cpu_speedo_id != 8)151			return 1200000;152 153		fallthrough;154 155	case 2:156		if (tegra_sku_info.cpu_speedo_id != 13)157			return 1300000;158 159		return 1350000;160 161	default:162		return 1250000;163	}164}165 166static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra,167				  struct regulator_dev *cpu_rdev,168				  struct regulator_dev *core_rdev)169{170	int core_min_uV, core_max_uV = INT_MAX;171	int cpu_min_uV, cpu_max_uV = INT_MAX;172	int cpu_min_uV_consumers = 0;173	int core_min_limited_uV;174	int core_target_uV;175	int cpu_target_uV;176	int core_max_step;177	int cpu_max_step;178	int max_spread;179	int core_uV;180	int cpu_uV;181	int err;182 183	/*184	 * CPU voltage should not got lower than 300mV from the CORE.185	 * CPU voltage should stay below the CORE by 100mV+, depending186	 * by the CORE voltage. This applies to all Tegra30 SoC's.187	 */188	max_spread = cpu_rdev->constraints->max_spread[0];189	cpu_max_step = cpu_rdev->constraints->max_uV_step;190	core_max_step = core_rdev->constraints->max_uV_step;191 192	if (!max_spread) {193		pr_err_once("cpu-core max-spread is undefined in device-tree\n");194		max_spread = 300000;195	}196 197	if (!cpu_max_step) {198		pr_err_once("cpu max-step is undefined in device-tree\n");199		cpu_max_step = 150000;200	}201 202	if (!core_max_step) {203		pr_err_once("core max-step is undefined in device-tree\n");204		core_max_step = 150000;205	}206 207	/*208	 * The CORE voltage scaling is currently not hooked up in drivers,209	 * hence we will limit the minimum CORE voltage to a reasonable value.210	 * This should be good enough for the time being.211	 */212	core_min_uV = tegra30_core_limit(tegra, core_rdev);213	if (core_min_uV < 0)214		return core_min_uV;215 216	err = regulator_check_consumers(core_rdev, &core_min_uV, &core_max_uV,217					PM_SUSPEND_ON);218	if (err)219		return err;220 221	/* prepare voltage level for suspend */222	if (tegra->sys_suspend_mode)223		core_min_uV = clamp(tegra30_core_nominal_uV(),224				    core_min_uV, core_max_uV);225 226	core_uV = regulator_get_voltage_rdev(core_rdev);227	if (core_uV < 0)228		return core_uV;229 230	cpu_min_uV = core_min_uV - max_spread;231 232	err = regulator_check_consumers(cpu_rdev, &cpu_min_uV, &cpu_max_uV,233					PM_SUSPEND_ON);234	if (err)235		return err;236 237	err = regulator_check_consumers(cpu_rdev, &cpu_min_uV_consumers,238					&cpu_max_uV, PM_SUSPEND_ON);239	if (err)240		return err;241 242	err = regulator_check_voltage(cpu_rdev, &cpu_min_uV, &cpu_max_uV);243	if (err)244		return err;245 246	cpu_uV = regulator_get_voltage_rdev(cpu_rdev);247	if (cpu_uV < 0)248		return cpu_uV;249 250	/* store boot voltage level */251	if (!tegra->cpu_min_uV)252		tegra->cpu_min_uV = cpu_uV;253 254	/*255	 * CPU's regulator may not have any consumers, hence the voltage256	 * must not be changed in that case because CPU simply won't257	 * survive the voltage drop if it's running on a higher frequency.258	 */259	if (!cpu_min_uV_consumers)260		cpu_min_uV = max(cpu_uV, cpu_min_uV);261 262	/*263	 * Bootloader shall set up voltages correctly, but if it264	 * happens that there is a violation, then try to fix it265	 * at first.266	 */267	core_min_limited_uV = tegra30_core_cpu_limit(cpu_uV);268	if (core_min_limited_uV < 0)269		return core_min_limited_uV;270 271	core_min_uV = max(core_min_uV, tegra30_core_cpu_limit(cpu_min_uV));272 273	err = regulator_check_voltage(core_rdev, &core_min_uV, &core_max_uV);274	if (err)275		return err;276 277	/* restore boot voltage level */278	if (tegra->sys_reboot_mode)279		cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV);280 281	/* prepare voltage level for suspend */282	if (tegra->sys_suspend_mode)283		cpu_min_uV = clamp(tegra30_cpu_nominal_uV(),284				   cpu_min_uV, cpu_max_uV);285 286	if (core_min_limited_uV > core_uV) {287		pr_err("core voltage constraint violated: %d %d %d\n",288		       core_uV, core_min_limited_uV, cpu_uV);289		goto update_core;290	}291 292	while (cpu_uV != cpu_min_uV || core_uV != core_min_uV) {293		if (cpu_uV < cpu_min_uV) {294			cpu_target_uV = min(cpu_uV + cpu_max_step, cpu_min_uV);295		} else {296			cpu_target_uV = max(cpu_uV - cpu_max_step, cpu_min_uV);297			cpu_target_uV = max(core_uV - max_spread, cpu_target_uV);298		}299 300		if (cpu_uV == cpu_target_uV)301			goto update_core;302 303		err = regulator_set_voltage_rdev(cpu_rdev,304						 cpu_target_uV,305						 cpu_max_uV,306						 PM_SUSPEND_ON);307		if (err)308			return err;309 310		cpu_uV = cpu_target_uV;311update_core:312		core_min_limited_uV = tegra30_core_cpu_limit(cpu_uV);313		if (core_min_limited_uV < 0)314			return core_min_limited_uV;315 316		core_target_uV = max(core_min_limited_uV, core_min_uV);317 318		if (core_uV < core_target_uV) {319			core_target_uV = min(core_target_uV, core_uV + core_max_step);320			core_target_uV = min(core_target_uV, cpu_uV + max_spread);321		} else {322			core_target_uV = max(core_target_uV, core_uV - core_max_step);323		}324 325		if (core_uV == core_target_uV)326			continue;327 328		err = regulator_set_voltage_rdev(core_rdev,329						 core_target_uV,330						 core_max_uV,331						 PM_SUSPEND_ON);332		if (err)333			return err;334 335		core_uV = core_target_uV;336	}337 338	return 0;339}340 341static int tegra30_regulator_balance_voltage(struct regulator_coupler *coupler,342					     struct regulator_dev *rdev,343					     suspend_state_t state)344{345	struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);346	struct regulator_dev *core_rdev = tegra->core_rdev;347	struct regulator_dev *cpu_rdev = tegra->cpu_rdev;348 349	if ((core_rdev != rdev && cpu_rdev != rdev) || state != PM_SUSPEND_ON) {350		pr_err("regulators are not coupled properly\n");351		return -EINVAL;352	}353 354	tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req);355	tegra->sys_suspend_mode = READ_ONCE(tegra->sys_suspend_mode_req);356 357	return tegra30_voltage_update(tegra, cpu_rdev, core_rdev);358}359 360static int tegra30_regulator_prepare_suspend(struct tegra_regulator_coupler *tegra,361					     bool sys_suspend_mode)362{363	int err;364 365	if (!tegra->core_rdev || !tegra->cpu_rdev)366		return 0;367 368	/*369	 * All power domains are enabled early during resume from suspend370	 * by GENPD core.  Domains like VENC may require a higher voltage371	 * when enabled during resume from suspend.  This also prepares372	 * hardware for resuming from LP0.373	 */374 375	WRITE_ONCE(tegra->sys_suspend_mode_req, sys_suspend_mode);376 377	err = regulator_sync_voltage_rdev(tegra->cpu_rdev);378	if (err)379		return err;380 381	err = regulator_sync_voltage_rdev(tegra->core_rdev);382	if (err)383		return err;384 385	return 0;386}387 388static int tegra30_regulator_suspend(struct notifier_block *notifier,389				     unsigned long mode, void *arg)390{391	struct tegra_regulator_coupler *tegra;392	int ret = 0;393 394	tegra = container_of(notifier, struct tegra_regulator_coupler,395			     suspend_notifier);396 397	switch (mode) {398	case PM_HIBERNATION_PREPARE:399	case PM_RESTORE_PREPARE:400	case PM_SUSPEND_PREPARE:401		ret = tegra30_regulator_prepare_suspend(tegra, true);402		break;403 404	case PM_POST_HIBERNATION:405	case PM_POST_RESTORE:406	case PM_POST_SUSPEND:407		ret = tegra30_regulator_prepare_suspend(tegra, false);408		break;409	}410 411	if (ret)412		pr_err("failed to prepare regulators: %d\n", ret);413 414	return notifier_from_errno(ret);415}416 417static int tegra30_regulator_prepare_reboot(struct tegra_regulator_coupler *tegra,418					    bool sys_reboot_mode)419{420	int err;421 422	if (!tegra->core_rdev || !tegra->cpu_rdev)423		return 0;424 425	WRITE_ONCE(tegra->sys_reboot_mode_req, true);426 427	/*428	 * Some devices use CPU soft-reboot method and in this case we429	 * should ensure that voltages are sane for the reboot by restoring430	 * the minimum boot levels.431	 */432	err = regulator_sync_voltage_rdev(tegra->cpu_rdev);433	if (err)434		return err;435 436	err = regulator_sync_voltage_rdev(tegra->core_rdev);437	if (err)438		return err;439 440	WRITE_ONCE(tegra->sys_reboot_mode_req, sys_reboot_mode);441 442	return 0;443}444 445static int tegra30_regulator_reboot(struct notifier_block *notifier,446				    unsigned long event, void *cmd)447{448	struct tegra_regulator_coupler *tegra;449	int ret;450 451	if (event != SYS_RESTART)452		return NOTIFY_DONE;453 454	tegra = container_of(notifier, struct tegra_regulator_coupler,455			     reboot_notifier);456 457	ret = tegra30_regulator_prepare_reboot(tegra, true);458 459	return notifier_from_errno(ret);460}461 462static int tegra30_regulator_attach(struct regulator_coupler *coupler,463				    struct regulator_dev *rdev)464{465	struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);466	struct device_node *np = rdev->dev.of_node;467 468	if (of_property_read_bool(np, "nvidia,tegra-core-regulator") &&469	    !tegra->core_rdev) {470		tegra->core_rdev = rdev;471		return 0;472	}473 474	if (of_property_read_bool(np, "nvidia,tegra-cpu-regulator") &&475	    !tegra->cpu_rdev) {476		tegra->cpu_rdev = rdev;477		return 0;478	}479 480	return -EINVAL;481}482 483static int tegra30_regulator_detach(struct regulator_coupler *coupler,484				    struct regulator_dev *rdev)485{486	struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);487 488	/*489	 * We don't expect regulators to be decoupled during reboot,490	 * this may race with the reboot handler and shouldn't ever491	 * happen in practice.492	 */493	if (WARN_ON_ONCE(system_state > SYSTEM_RUNNING))494		return -EPERM;495 496	if (tegra->core_rdev == rdev) {497		tegra->core_rdev = NULL;498		return 0;499	}500 501	if (tegra->cpu_rdev == rdev) {502		tegra->cpu_rdev = NULL;503		return 0;504	}505 506	return -EINVAL;507}508 509static struct tegra_regulator_coupler tegra30_coupler = {510	.coupler = {511		.attach_regulator = tegra30_regulator_attach,512		.detach_regulator = tegra30_regulator_detach,513		.balance_voltage = tegra30_regulator_balance_voltage,514	},515	.reboot_notifier.notifier_call = tegra30_regulator_reboot,516	.suspend_notifier.notifier_call = tegra30_regulator_suspend,517};518 519static int __init tegra_regulator_coupler_init(void)520{521	int err;522 523	if (!of_machine_is_compatible("nvidia,tegra30"))524		return 0;525 526	err = register_reboot_notifier(&tegra30_coupler.reboot_notifier);527	WARN_ON(err);528 529	err = register_pm_notifier(&tegra30_coupler.suspend_notifier);530	WARN_ON(err);531 532	return regulator_coupler_register(&tegra30_coupler.coupler);533}534arch_initcall(tegra_regulator_coupler_init);535