summaryrefslogtreecommitdiff
path: root/plat/nvidia
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2018-04-19 17:50:31 -0700
committerVarun Wadekar <vwadekar@nvidia.com>2019-01-31 08:50:22 -0800
commit6a397d1d44067d71a0e418f1018db6b497f237da (patch)
treef4a51f2040219577fd4076d73ac5ed5b53cce68d /plat/nvidia
parentda0f47437506b437a7729c22f95b9e351401d4af (diff)
Tegra210: toggle ring oscillator across cluster idle
This patch toggles the ring oscillator state across cluster idle as DFLL loses its state. We dont want garbage values being written to the pmic when we enter cluster idle state, so enable "open loop" when we enter CC6 and restore the state to "closed loop" on exit. Change-Id: I56f4649f57bcc651d6c415a6dcdc978e9444c97b Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Diffstat (limited to 'plat/nvidia')
-rw-r--r--plat/nvidia/tegra/soc/t210/plat_psci_handlers.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index 7907e460..7e176e6f 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -119,6 +119,13 @@ plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
ret = tegra_bpmp_init();
if (ret != 0U) {
+ /*
+ * flag to indicate that BPMP firmware is not
+ * available and the CPU has to handle entry/exit
+ * for all power states
+ */
+ tegra_bpmp_available = false;
+
/* Cluster idle not allowed */
target = PSCI_LOCAL_STATE_RUN;
@@ -131,13 +138,6 @@ plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
val = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL);
if (val == ENABLE_CLOSED_LOOP) {
/*
- * flag to indicate that BPMP firmware is not
- * available and the CPU has to handle entry/exit
- * for all power states
- */
- tegra_bpmp_available = false;
-
- /*
* Acquire the cluster idle lock to stop
* other CPUs from powering up.
*/
@@ -217,6 +217,15 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
if (!tegra_bpmp_available) {
+ /*
+ * When disabled, DFLL loses its state. Enable
+ * open loop state for the DFLL as we dont want
+ * garbage values being written to the pmic
+ * when we enter cluster idle state.
+ */
+ mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL,
+ ENABLE_OPEN_LOOP);
+
/* Find if the platform uses OVR2/MAX77621 PMIC */
cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG);
if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) {
@@ -481,8 +490,19 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
val &= ~PINMUX_PWM_TRISTATE;
mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val);
+
+ /* make sure the setting took effect */
+ val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
+ assert((val & PINMUX_PWM_TRISTATE) == 0U);
}
+ /*
+ * Restore operation mode for the DFLL ring
+ * oscillator
+ */
+ mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL,
+ ENABLE_CLOSED_LOOP);
+
/* release cluster idle lock */
tegra_fc_ccplex_pgexit_unlock();
}