OSDN Git Service

ARM: tegra: Don't enable unused PLLs on resume from suspend
authorDmitry Osipenko <digetx@gmail.com>
Tue, 12 Jan 2021 13:50:31 +0000 (16:50 +0300)
committerThierry Reding <treding@nvidia.com>
Tue, 19 Jan 2021 17:20:42 +0000 (18:20 +0100)
PLLC and PLLM are usually disabled on system suspend because all devices
which use these PLLs are either suspended or switched away to other clock
source. Don't enable unused PLLs on resume from suspend by keeping track
of the enable-state of the PLLs across suspend-resume.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Tested-by: Matt Merhar <mattmerhar@protonmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
arch/arm/mach-tegra/sleep-tegra20.S
arch/arm/mach-tegra/sleep-tegra30.S

index 0e00ba8..a5a36cc 100644 (file)
 #define APB_MISC_XM2CFGCPADCTRL2       0x8e4
 #define APB_MISC_XM2CFGDPADCTRL2       0x8e8
 
-.macro pll_enable, rd, r_car_base, pll_base
+#define PLLC_STORE_MASK                        (1 << 0)
+#define PLLM_STORE_MASK                        (1 << 1)
+#define PLLP_STORE_MASK                        (1 << 2)
+
+.macro test_pll_state, rd, test_mask
+       ldr     \rd, tegra_pll_state
+       tst     \rd, #\test_mask
+.endm
+
+.macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask
+       ldr     \rd, [\r_car_base, #\pll_base]
+       tst     \rd, #(1 << 30)
+       ldr     \rd, tegra_pll_state
+       biceq   \rd, \rd, #\pll_mask
+       orrne   \rd, \rd, #\pll_mask
+       adr     \tmp, tegra_pll_state
+       str     \rd, [\tmp]
+.endm
+
+.macro pll_enable, rd, r_car_base, pll_base, test_mask
+       test_pll_state \rd, \test_mask
+       beq     1f
+
        ldr     \rd, [\r_car_base, #\pll_base]
        tst     \rd, #(1 << 30)
        orreq   \rd, \rd, #(1 << 30)
        streq   \rd, [\r_car_base, #\pll_base]
+1:
 .endm
 
 .macro emc_device_mask, rd, base
@@ -177,9 +200,9 @@ ENTRY(tegra20_lp1_reset)
        str     r1, [r0, #CLK_RESET_CCLK_DIVIDER]
        str     r1, [r0, #CLK_RESET_SCLK_DIVIDER]
 
-       pll_enable r1, r0, CLK_RESET_PLLM_BASE
-       pll_enable r1, r0, CLK_RESET_PLLP_BASE
-       pll_enable r1, r0, CLK_RESET_PLLC_BASE
+       pll_enable r1, r0, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
+       pll_enable r1, r0, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
+       pll_enable r1, r0, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
 
        adr     r2, tegra20_sdram_pad_address
        adr     r4, tegra20_sdram_pad_save
@@ -270,6 +293,10 @@ tegra20_switch_cpu_to_clk32k:
        add     r1, r1, #2
        wait_until r1, r7, r9
 
+       store_pll_state r0, r1, r5, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
+       store_pll_state r0, r1, r5, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
+       store_pll_state r0, r1, r5, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
+
        /* disable PLLM, PLLP and PLLC */
        ldr     r0, [r5, #CLK_RESET_PLLM_BASE]
        bic     r0, r0, #(1 << 30)
@@ -396,6 +423,9 @@ tegra20_sdram_pad_save:
        .long   0
        .endr
 
+tegra_pll_state:
+       .word   0x0
+
        .ltorg
 /* dummy symbol for end of IRAM */
        .align L1_CACHE_SHIFT
index 2667bcd..0cc40b6 100644 (file)
 
 #define TEGRA30_POWER_HOTPLUG_SHUTDOWN (1 << 27) /* Hotplug shutdown */
 
+#define PLLA_STORE_MASK                        (1 << 0)
+#define PLLC_STORE_MASK                        (1 << 1)
+#define PLLM_STORE_MASK                        (1 << 2)
+#define PLLP_STORE_MASK                        (1 << 3)
+#define PLLX_STORE_MASK                        (1 << 4)
+#define PLLM_PMC_STORE_MASK            (1 << 5)
+
 .macro emc_device_mask, rd, base
        ldr     \rd, [\base, #EMC_ADR_CFG]
        tst     \rd, #0x1
        bne     1001b
 .endm
 
-.macro pll_enable, rd, r_car_base, pll_base, pll_misc
+.macro test_pll_state, rd, test_mask
+       ldr     \rd, tegra_pll_state
+       tst     \rd, #\test_mask
+.endm
+
+.macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask
+       ldr     \rd, [\r_car_base, #\pll_base]
+       tst     \rd, #(1 << 30)
+       ldr     \rd, tegra_pll_state
+       biceq   \rd, \rd, #\pll_mask
+       orrne   \rd, \rd, #\pll_mask
+       adr     \tmp, tegra_pll_state
+       str     \rd, [\tmp]
+.endm
+
+.macro store_pllm_pmc_state, rd, tmp, pmc_base
+       ldr     \rd, [\pmc_base, #PMC_PLLP_WB0_OVERRIDE]
+       tst     \rd, #(1 << 12)
+       ldr     \rd, tegra_pll_state
+       biceq   \rd, \rd, #PLLM_PMC_STORE_MASK
+       orrne   \rd, \rd, #PLLM_PMC_STORE_MASK
+       adr     \tmp, tegra_pll_state
+       str     \rd, [\tmp]
+.endm
+
+.macro pllm_pmc_enable, rd, pmc_base
+       test_pll_state \rd, PLLM_PMC_STORE_MASK
+
+       ldrne   \rd, [\pmc_base, #PMC_PLLP_WB0_OVERRIDE]
+       orrne   \rd, \rd, #(1 << 12)
+       strne   \rd, [\pmc_base, #PMC_PLLP_WB0_OVERRIDE]
+.endm
+
+.macro pll_enable, rd, r_car_base, pll_base, pll_misc, test_mask
+       test_pll_state \rd, \test_mask
+       beq     1f
+
        ldr     \rd, [\r_car_base, #\pll_base]
        tst     \rd, #(1 << 30)
        orreq   \rd, \rd, #(1 << 30)
        orr     \rd, \rd, #(1 << 18)
        str     \rd, [\r_car_base, #\pll_misc]
        .endif
+1:
 .endm
 
-.macro pll_locked, rd, r_car_base, pll_base
+.macro pll_locked, rd, r_car_base, pll_base, test_mask
+       test_pll_state \rd, \test_mask
+       beq     2f
 1:
        ldr     \rd, [\r_car_base, #\pll_base]
        tst     \rd, #(1 << 27)
        beq     1b
+2:
 .endm
 
 .macro pll_iddq_exit, rd, car, iddq, iddq_bit
@@ -342,34 +389,30 @@ ENTRY(tegra30_lp1_reset)
 
        /* enable PLLM via PMC */
        mov32   r2, TEGRA_PMC_BASE
-       ldr     r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
-       orr     r1, r1, #(1 << 12)
-       str     r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
+       pllm_pmc_enable r1, r2
 
-       pll_enable r1, r0, CLK_RESET_PLLM_BASE, 0
-       pll_enable r1, r0, CLK_RESET_PLLC_BASE, 0
-       pll_enable r1, r0, CLK_RESET_PLLX_BASE, 0
+       pll_enable r1, r0, CLK_RESET_PLLM_BASE, 0, PLLM_STORE_MASK
+       pll_enable r1, r0, CLK_RESET_PLLC_BASE, 0, PLLC_STORE_MASK
+       pll_enable r1, r0, CLK_RESET_PLLX_BASE, 0, PLLX_STORE_MASK
 
        b       _pll_m_c_x_done
 
 _no_pll_iddq_exit:
        /* enable PLLM via PMC */
        mov32   r2, TEGRA_PMC_BASE
-       ldr     r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
-       orr     r1, r1, #(1 << 12)
-       str     r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
+       pllm_pmc_enable r1, r2
 
-       pll_enable r1, r0, CLK_RESET_PLLM_BASE, CLK_RESET_PLLM_MISC
-       pll_enable r1, r0, CLK_RESET_PLLC_BASE, CLK_RESET_PLLC_MISC
+       pll_enable r1, r0, CLK_RESET_PLLM_BASE, CLK_RESET_PLLM_MISC, PLLM_STORE_MASK
+       pll_enable r1, r0, CLK_RESET_PLLC_BASE, CLK_RESET_PLLC_MISC, PLLC_STORE_MASK
 
 _pll_m_c_x_done:
-       pll_enable r1, r0, CLK_RESET_PLLP_BASE, CLK_RESET_PLLP_MISC
-       pll_enable r1, r0, CLK_RESET_PLLA_BASE, CLK_RESET_PLLA_MISC
+       pll_enable r1, r0, CLK_RESET_PLLP_BASE, CLK_RESET_PLLP_MISC, PLLP_STORE_MASK
+       pll_enable r1, r0, CLK_RESET_PLLA_BASE, CLK_RESET_PLLA_MISC, PLLA_STORE_MASK
 
-       pll_locked r1, r0, CLK_RESET_PLLM_BASE
-       pll_locked r1, r0, CLK_RESET_PLLP_BASE
-       pll_locked r1, r0, CLK_RESET_PLLA_BASE
-       pll_locked r1, r0, CLK_RESET_PLLC_BASE
+       pll_locked r1, r0, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
+       pll_locked r1, r0, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
+       pll_locked r1, r0, CLK_RESET_PLLA_BASE, PLLA_STORE_MASK
+       pll_locked r1, r0, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
 
        /*
         * CPUFreq driver could select other PLL for CPU. PLLX will be
@@ -380,7 +423,7 @@ _pll_m_c_x_done:
        cmp     r1, #TEGRA30
        beq     1f
 
-       pll_locked r1, r0, CLK_RESET_PLLX_BASE
+       pll_locked r1, r0, CLK_RESET_PLLX_BASE, PLLX_STORE_MASK
 
        ldr     r1, [r0, #CLK_RESET_PLLP_BASE]
        bic     r1, r1, #(1<<31)        @ disable PllP bypass
@@ -593,6 +636,9 @@ tegra_sdram_pad_save:
        .long   0
        .endr
 
+tegra_pll_state:
+       .word   0x0
+
 /*
  * tegra30_tear_down_core
  *
@@ -641,6 +687,14 @@ tegra30_switch_cpu_to_clk32k:
        add     r1, r1, #2
        wait_until r1, r7, r9
 
+       /* store enable-state of PLLs */
+       store_pll_state r0, r1, r5, CLK_RESET_PLLA_BASE, PLLA_STORE_MASK
+       store_pll_state r0, r1, r5, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
+       store_pll_state r0, r1, r5, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
+       store_pll_state r0, r1, r5, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
+       store_pll_state r0, r1, r5, CLK_RESET_PLLX_BASE, PLLX_STORE_MASK
+       store_pllm_pmc_state r0, r1, r4
+
        /* disable PLLM via PMC in LP1 */
        ldr     r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
        bic     r0, r0, #(1 << 12)