| From: Stephen Warren <swarren@nvidia.com> |
| Date: Thu, 3 Oct 2019 14:50:31 -0600 |
| Subject: ARM: tegra: Enable PLLP bypass during Tegra124 LP1 |
| |
| commit 1a3388d506bf5b45bb283e6a4c4706cfb4897333 upstream. |
| |
| For a little over a year, U-Boot has configured the flow controller to |
| perform automatic RAM re-repair on off->on power transitions of the CPU |
| rail[1]. This is mandatory for correct operation of Tegra124. However, |
| RAM re-repair relies on certain clocks, which the kernel must enable and |
| leave running. PLLP is one of those clocks. This clock is shut down |
| during LP1 in order to save power. Enable bypass (which I believe routes |
| osc_div_clk, essentially the crystal clock, to the PLL output) so that |
| this clock signal toggles even though the PLL is not active. This is |
| required so that LP1 power mode (system suspend) operates correctly. |
| |
| The bypass configuration must then be undone when resuming from LP1, so |
| that all peripheral clocks run at the expected rate. Without this, many |
| peripherals won't work correctly; for example, the UART baud rate would |
| be incorrect. |
| |
| NVIDIA's downstream kernel code only does this if not compiled for |
| Tegra30, so the added code is made conditional upon the chip ID. |
| NVIDIA's downstream code makes this change conditional upon the active |
| CPU cluster. The upstream kernel currently doesn't support cluster |
| switching, so this patch doesn't test the active CPU cluster ID. |
| |
| [1] 3cc7942a4ae5 ARM: tegra: implement RAM repair |
| |
| Reported-by: Jonathan Hunter <jonathanh@nvidia.com> |
| Signed-off-by: Stephen Warren <swarren@nvidia.com> |
| Signed-off-by: Thierry Reding <treding@nvidia.com> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| arch/arm/mach-tegra/sleep-tegra30.S | 11 +++++++++++ |
| 1 file changed, 11 insertions(+) |
| |
| --- a/arch/arm/mach-tegra/sleep-tegra30.S |
| +++ b/arch/arm/mach-tegra/sleep-tegra30.S |
| @@ -378,6 +378,14 @@ _pll_m_c_x_done: |
| pll_locked r1, r0, CLK_RESET_PLLC_BASE |
| pll_locked r1, r0, CLK_RESET_PLLX_BASE |
| |
| + tegra_get_soc_id TEGRA_APB_MISC_BASE, r1 |
| + cmp r1, #TEGRA30 |
| + beq 1f |
| + ldr r1, [r0, #CLK_RESET_PLLP_BASE] |
| + bic r1, r1, #(1<<31) @ disable PllP bypass |
| + str r1, [r0, #CLK_RESET_PLLP_BASE] |
| +1: |
| + |
| mov32 r7, TEGRA_TMRUS_BASE |
| ldr r1, [r7] |
| add r1, r1, #LOCK_DELAY |
| @@ -637,7 +645,10 @@ tegra30_switch_cpu_to_clk32k: |
| str r0, [r4, #PMC_PLLP_WB0_OVERRIDE] |
| |
| /* disable PLLP, PLLA, PLLC and PLLX */ |
| + tegra_get_soc_id TEGRA_APB_MISC_BASE, r1 |
| + cmp r1, #TEGRA30 |
| ldr r0, [r5, #CLK_RESET_PLLP_BASE] |
| + orrne r0, r0, #(1 << 31) @ enable PllP bypass on fast cluster |
| bic r0, r0, #(1 << 30) |
| str r0, [r5, #CLK_RESET_PLLP_BASE] |
| ldr r0, [r5, #CLK_RESET_PLLA_BASE] |