ARM: tegra114: add support for system suspend
Subsystems (6)
v2 cover ARM: tegra114: add support for system suspend
This series introduce system suspend function for Tegra114 and depend on the series of "ARM: tegra114: cpuidle: add power down state".
Verified on Seaboard, Cardhu and Dalmore and with THUMB2_KERNEL as well.
V2:
* do some fixes from the comments in the review
Joseph Lo (11):
ARM: tegra: do v7_invalidate_l1 only when CPU is Cortex-A9
ARM: tegra: add a flag for tegra_disable_clean_inv_dcache to do LoUIS
or ALL
ARM: tegra114: set up the correct L2 data RAM latency for Cortex-A15
ARM: tegra114: add low level support code for cluster power down
ARM: tegra114: shut off the CPU rail when the last CPU in suspend
ARM: tegra114: hook tegra_tear_down_cpu function
ARM: tegra114: flowctrl: add support for cpu_suspend_enter/exit
clk: tegra114: add suspend/resume function for tegra_cpu_car_ops
ARM: tegra: remove the limitation that Tegra114 can't support suspend
ARM: dts: tegra114: dalmore: add GPIO power key support
ARM: dts: tegra114: dalmore: add PM configurations for PMC
arch/arm/boot/dts/tegra114-dalmore.dts | 18 ++++++++++++++++++ arch/arm/mach-tegra/flowctrl.c | 2 ++ arch/arm/mach-tegra/flowctrl.h | 7 +++++++ arch/arm/mach-tegra/headsmp.S | 3 ++- arch/arm/mach-tegra/hotplug.c | 2 +- arch/arm/mach-tegra/pm.c | 8 +++----- arch/arm/mach-tegra/pmc.c | 16 +++++++++++++++- arch/arm/mach-tegra/reset-handler.S | 8 ++++++-- arch/arm/mach-tegra/sleep-tegra20.S | 1 + arch/arm/mach-tegra/sleep-tegra30.S | 7 ++++++- arch/arm/mach-tegra/sleep.S | 29 ++++++++++++++++++++++++++++- arch/arm/mach-tegra/sleep.h | 6 +++++- drivers/clk/tegra/clk-tegra114.c | 26 ++++++++++++++++++++++++++ 13 files changed, 120 insertions(+), 13 deletions(-)
Signature · 1 line
1.8.3.2
PATCH v2 1/11 ARM: tegra: do v7_invalidate_l1 only when CPU is Cortex-A9
The v7_invalidate_l1 was used for the L1 cache that come out from reset in a undefined state. This is no need for Cortex-A15. We do it for A9 only.
---
V2:
* take care the v7_invalidate_l1 in tegra_secondary_startup also
--- arch/arm/mach-tegra/headsmp.S | 3 ++- arch/arm/mach-tegra/reset-handler.S | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/headsmp.S +2 -1
@@ -6,6 +6,7 @@ .section ".text.head", "ax" ENTRY(tegra_secondary_startup) - bl v7_invalidate_l1 + check_cpu_part_num 0xc09, r8, r9 + bleq v7_invalidate_l1 b secondary_startup ENDPROC(tegra_secondary_startup)
arch/arm/mach-tegra/reset-handler.S +5 -2
@@ -40,9 +40,11 @@ * re-enabling sdram. * * r6: SoC ID + * r8: CPU part number */ ENTRY(tegra_resume) - bl v7_invalidate_l1 + check_cpu_part_num 0xc09, r8, r9 + bleq v7_invalidate_l1 cpu_id r0 tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
@@ -70,7 +72,8 @@ no_cpu0_chk: str r1, [r2] 1: - check_cpu_part_num 0xc09, r8, r9 + mov32 r9, 0xc09 + cmp r8, r9 bne not_ca9 #ifdef CONFIG_HAVE_ARM_SCU /* enable SCU */
Signature · 1 line
1.8.3.2
PATCH v2 2/11 ARM: tegra: add a flag for tegra_disable_clean_inv_dcache to do LoUIS or ALL
In reply to Joseph LoAdding a flag for tegra_disable_clean_inv_dcache to flush cache as LoUIS or ALL. After this patch, the v7_flush_dcache_louis is used for CPU hotplug and CPU suspend in CPU power down (e.g. CPU idle power-down mode) case. And the v7_flush_dcache_all is used for CPU cluster power down (e.g. suspend to LP2 mode).
---
V2:
* change the define value of TEGRA_FLUSH_CACHE_LOUIS and ALL to 0 and 1
--- arch/arm/mach-tegra/hotplug.c | 2 +- arch/arm/mach-tegra/sleep-tegra20.S | 1 + arch/arm/mach-tegra/sleep-tegra30.S | 1 + arch/arm/mach-tegra/sleep.S | 7 ++++++- arch/arm/mach-tegra/sleep.h | 6 +++++- 5 files changed, 14 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/hotplug.c +1 -1
@@ -37,7 +37,7 @@ int tegra_cpu_kill(unsigned cpu)void __ref tegra_cpu_die (unsigned int cpu) {/* Clean L1 data cache */ -tegra_disable_clean_inv_dcache (); +tegra_disable_clean_inv_dcache (TEGRA_FLUSH_CACHE_LOUIS );/* Shut down the current CPU. */ tegra_hotplug_shutdown ();
arch/arm/mach-tegra/sleep-tegra20.S +1 -0
@@ -191,6 +191,7 @@ ENTRY(tegra20_sleep_cpu_secondary_finish) mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency /* Flush and disable the L1 data cache */ + mov r0, #TEGRA_FLUSH_CACHE_LOUIS bl tegra_disable_clean_inv_dcache mov32 r0, TEGRA_PMC_VIRT + PMC_SCRATCH41
arch/arm/mach-tegra/sleep-tegra30.S +1 -0
@@ -137,6 +137,7 @@ ENTRY(tegra30_sleep_cpu_secondary_finish) mov r7, lr /* Flush and disable the L1 data cache */ + mov r0, #TEGRA_FLUSH_CACHE_LOUIS bl tegra_disable_clean_inv_dcache /* Powergate this CPU. */
arch/arm/mach-tegra/sleep.S +6 -1
@@ -56,7 +56,9 @@ ENTRY(tegra_disable_clean_inv_dcache) isb /* Flush the D-cache */ - bl v7_flush_dcache_louis + cmp r0, #TEGRA_FLUSH_CACHE_ALL + blne v7_flush_dcache_louis + bleq v7_flush_dcache_all /* Trun off coherency */ exit_smp r4, r5
@@ -73,9 +75,12 @@ ENDPROC(tegra_disable_clean_inv_dcache) * tegra?_tear_down_cpu */ ENTRY(tegra_sleep_cpu_finish) + mov r4, r0 /* Flush and disable the L1 data cache */ + mov r0, #TEGRA_FLUSH_CACHE_ALL bl tegra_disable_clean_inv_dcache + mov r0, r4 mov32 r6, tegra_tear_down_cpu ldr r1, [r6] add r1, r1, r0
arch/arm/mach-tegra/sleep.h +5 -1
@@ -41,6 +41,10 @@#define CPU_NOT_RESETTABLE 0#endif +/* flag of tegra_disable_clean_inv_dcache to do LoUIS or all */ +#define TEGRA_FLUSH_CACHE_LOUIS 0 +#define TEGRA_FLUSH_CACHE_ALL 1 +#ifdef __ASSEMBLY__/* returns the offset of the flow controller halt register for a cpu */ .macro cpu_to_halt_reg rd, rcpu
@@ -144,7 +148,7 @@ void tegra_pen_lock(void);void tegra_pen_unlock (void );void tegra_resume (void );int tegra_sleep_cpu_finish (unsigned long ); -void tegra_disable_clean_inv_dcache (void ); +void tegra_disable_clean_inv_dcache (u32 flag);#ifdef CONFIG_HOTPLUG_CPU void tegra20_hotplug_shutdown (void );
Signature · 1 line
1.8.3.2
PATCH v2 3/11 ARM: tegra114: set up the correct L2 data RAM latency for Cortex-A15
In reply to Joseph LoWhen there is a cluster power down cycle in suspend, we need to set up the correct L2 RAM data RAM latency to make L2 cache work correctly. This is only needed for cluster 0 and needs to be done in tegra_resume before the cache is enabled.
---
V2:
* no change
--- arch/arm/mach-tegra/reset-handler.S | 1 + arch/arm/mach-tegra/sleep.S | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+)
arch/arm/mach-tegra/reset-handler.S +1 -0
@@ -45,6 +45,7 @@ ENTRY(tegra_resume) check_cpu_part_num 0xc09, r8, r9 bleq v7_invalidate_l1 + blne tegra_init_l2_for_a15 cpu_id r0 tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
arch/arm/mach-tegra/sleep.S +22 -0
@@ -69,6 +69,28 @@ ENDPROC(tegra_disable_clean_inv_dcache) #ifdef CONFIG_PM_SLEEP /* + * tegra_init_l2_for_a15 + * + * set up the correct L2 cache data RAM latency + */ +ENTRY(tegra_init_l2_for_a15) + mrc p15, 0, r0, c0, c0, 5 + ubfx r0, r0, #8, #4 + tst r0, #1 @ only need for cluster 0 + bne _exit_init_l2_a15 + + mrc p15, 0x1, r0, c9, c0, 2 + and r0, r0, #7 + cmp r0, #2 + bicne r0, r0, #7 + orrne r0, r0, #2 + mcrne p15, 0x1, r0, c9, c0, 2 +_exit_init_l2_a15: + + mov pc, lr +ENDPROC(tegra_init_l2_for_a15) + +/* * tegra_sleep_cpu_finish(unsigned long v2p) * * enters suspend in LP2 by turning off the mmu and jumping to
Signature · 1 line
1.8.3.2
PATCH v2 4/11 ARM: tegra114: add low level support code for cluster power down
In reply to Joseph LoWhen the CPU cluster power down, the vGIC is powered down too. The flow controller needs to monitor the legacy interrupt controller to wake up CPU. So setting up the appropriate wake up event in flow controller.
---
V2:
* no change
--- arch/arm/mach-tegra/flowctrl.h | 2 ++ arch/arm/mach-tegra/sleep-tegra30.S | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-)
arch/arm/mach-tegra/flowctrl.h +2 -0
@@ -28,6 +28,8 @@#define FLOW_CTRL_SCLK_RESUME (1 << 27)#define FLOW_CTRL_HALT_CPU_IRQ (1 << 10)#define FLOW_CTRL_HALT_CPU_FIQ (1 << 8) +#define FLOW_CTRL_HALT_LIC_IRQ (1 << 11) +#define FLOW_CTRL_HALT_LIC_FIQ (1 << 10)#define FLOW_CTRL_HALT_GIC_IRQ (1 << 9)#define FLOW_CTRL_HALT_GIC_FIQ (1 << 8)#define FLOW_CTRL_CPU0_CSR 0x8
arch/arm/mach-tegra/sleep-tegra30.S +5 -1
@@ -175,8 +175,12 @@ tegra30_enter_sleep: orr r0, r0, #FLOW_CTRL_CSR_ENABLE str r0, [r6, r2] + tegra_get_soc_id TEGRA_APB_MISC_BASE, r10 + cmp r10, #TEGRA30 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT - orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ + orreq r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ + orrne r0, r0, #FLOW_CTRL_HALT_LIC_IRQ | FLOW_CTRL_HALT_LIC_FIQ + cpu_to_halt_reg r2, r1 str r0, [r6, r2] dsb
Signature · 1 line
1.8.3.2
PATCH v2 5/11 ARM: tegra114: shut off the CPU rail when the last CPU in suspend
In reply to Joseph LoWhen the last CPU core in suspend, the CPU power rail can be turned off by setting flags to flow controller. Then the flow controller will inform PMC to turn off the CPU rail when the last CPU goes into suspend.
---
V2:
* presumably we need to code the cut off the CRAIL after Tegra114, modify the code for that
--- arch/arm/mach-tegra/flowctrl.h | 5 +++++ arch/arm/mach-tegra/pmc.c | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-)
arch/arm/mach-tegra/flowctrl.h +5 -0
@@ -35,6 +35,11 @@#define FLOW_CTRL_CPU0_CSR 0x8#define FLOW_CTRL_CSR_INTR_FLAG (1 << 15)#define FLOW_CTRL_CSR_EVENT_FLAG (1 << 14) +#define FLOW_CTRL_CSR_ENABLE_EXT_CRAIL (1 << 13) +#define FLOW_CTRL_CSR_ENABLE_EXT_NCPU (1 << 12) +#define FLOW_CTRL_CSR_ENABLE_EXT_MASK ( \ + FLOW_CTRL_CSR_ENABLE_EXT_NCPU | \ + FLOW_CTRL_CSR_ENABLE_EXT_CRAIL)#define FLOW_CTRL_CSR_ENABLE (1 << 0)#define FLOW_CTRL_HALT_CPU1_EVENTS 0x14#define FLOW_CTRL_CPU1_CSR 0x18
arch/arm/mach-tegra/pmc.c +15 -1
@@ -21,6 +21,7 @@#include <linux/of.h> #include <linux/of_address.h> +#include "flowctrl.h" #include "fuse.h" #include "pm.h" #include "pmc.h"
@@ -195,13 +196,26 @@ enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)void tegra_pmc_pm_set (enum tegra_suspend_mode mode) { -u32 reg; +u32 reg, csr_reg;unsigned long rate =0 ; reg =tegra_pmc_readl (PMC_CTRL ); reg |=TEGRA_POWER_CPU_PWRREQ_OE ; reg &= ~TEGRA_POWER_EFFECT_LP0 ; +switch (tegra_chip_id) { +case TEGRA20 : +case TEGRA30 : +break ; +default : +/* Turn off CRAIL */ + csr_reg =flowctrl_read_cpu_csr (0 ); + csr_reg &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK ; + csr_reg |=FLOW_CTRL_CSR_ENABLE_EXT_CRAIL ; +flowctrl_write_cpu_csr (0 , csr_reg); +break ; + } +switch (mode) {case TEGRA_SUSPEND_LP2 : rate =clk_get_rate (tegra_pclk);
Signature · 1 line
1.8.3.2
PATCH v2 6/11 ARM: tegra114: hook tegra_tear_down_cpu function
In reply to Joseph LoHooking tegra_tear_down_cpu for Tegra114 for supporting cluster power down when CPU cluster suspneded in LP2.
---
V2:
* take care the combination of the selection of the config ARCH_TEGRA_3x_SOC and TEGRA_114_SOC
--- arch/arm/mach-tegra/pm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm/mach-tegra/pm.c +3 -1
@@ -52,7 +52,9 @@ static void tegra_tear_down_cpu_init(void) tegra_tear_down_cpu = tegra20_tear_down_cpu;break ;case TEGRA30 : -if (IS_ENABLED (CONFIG_ARCH_TEGRA_3x_SOC)) +case TEGRA114 : +if (IS_ENABLED (CONFIG_ARCH_TEGRA_3x_SOC) || +IS_ENABLED (CONFIG_ARCH_TEGRA_114_SOC )) tegra_tear_down_cpu = tegra30_tear_down_cpu;break ; }
Signature · 1 line
1.8.3.2
PATCH v2 7/11 ARM: tegra114: flowctrl: add support for cpu_suspend_enter/exit
In reply to Joseph LoThe flow controller can help CPU to go into suspend mode (powered-down state). When CPU goes into powered-down state, it needs some careful settings before getting into and after leaving. The enter and exit functions do that by configuring appropriate mode for flow controller.
For Tegra114, the setting is compatible with Tegra30.
---
V2:
* no change
--- arch/arm/mach-tegra/flowctrl.c | 2 ++ 1 file changed, 2 insertions(+)
arch/arm/mach-tegra/flowctrl.c +2 -0
@@ -86,6 +86,7 @@ void flowctrl_cpu_suspend_enter(unsigned int cpuid) reg |=TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid;break ;case TEGRA30 : +case TEGRA114 :/* clear wfe bitmap */ reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP ;/* clear wfi bitmap */
@@ -123,6 +124,7 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid) reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP ;break ;case TEGRA30 : +case TEGRA114 :/* clear wfe bitmap */ reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP ;/* clear wfi bitmap */
Signature · 1 line
1.8.3.2
PATCH v2 8/11 clk: tegra114: add suspend/resume function for tegra_cpu_car_ops
In reply to Joseph LoAdding suspend/resume function for tegra_cpu_car_ops. We only save and restore the setting of the clock of CoreSight. Other clocks still need to be taken care by clock driver.
---
V2:
* fix the coding style
--- drivers/clk/tegra/clk-tegra114.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
drivers/clk/tegra/clk-tegra114.c +26 -0
@@ -290,6 +290,12 @@#define PMC_PLLM_WB0_OVERRIDE 0x1dc#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0 +#ifdef CONFIG_PM_SLEEP +static struct cpu_clk_suspend_context { +u32 clk_csite_src; +} tegra114_cpu_clk_sctx; +#endif +static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM *32 ];static void __iomem *clk_base;
@@ -2142,9 +2148,29 @@ static void tegra114_disable_cpu_clock(u32 cpu)/* flow controller would take care in the power sequence. */ } +#ifdef CONFIG_PM_SLEEP +static void tegra114_cpu_clock_suspend (void ) +{ +/* switch coresite to clk_m, save off original source */ + tegra114_cpu_clk_sctx.clk_csite_src = +readl (clk_base +CLK_SOURCE_CSITE ); +writel (3 <<30 , clk_base +CLK_SOURCE_CSITE ); +} + +static void tegra114_cpu_clock_resume (void ) +{ +writel (tegra114_cpu_clk_sctx.clk_csite_src, + clk_base +CLK_SOURCE_CSITE ); +} +#endif +static struct tegra_cpu_car_ops tegra114_cpu_car_ops = { .wait_for_reset = tegra114_wait_cpu_in_reset, .disable_clock = tegra114_disable_cpu_clock, +#ifdef CONFIG_PM_SLEEP + .suspend = tegra114_cpu_clock_suspend, + .resume = tegra114_cpu_clock_resume, +#endif };static const struct of_device_id pmc_match[]__initconst = {
Signature · 1 line
1.8.3.2
PATCH v2 9/11 ARM: tegra: remove the limitation that Tegra114 can't support suspend
In reply to Joseph LoThe Tegra114 can support suspend function now, removing the limitation.
---
V2:
* no change
--- arch/arm/mach-tegra/pm.c | 4 ---- 1 file changed, 4 deletions(-)
arch/arm/mach-tegra/pm.c +0 -4
@@ -173,10 +173,6 @@ void tegra_idle_lp2_last(void)enum tegra_suspend_mode tegra_pm_validate_suspend_mode (enum tegra_suspend_mode mode) { -/* Tegra114 didn't support any suspending mode yet. */ -if (tegra_chip_id ==TEGRA114 ) -return TEGRA_SUSPEND_NONE ; -/* * The Tegra devices only support suspending to LP2 currently. */
Signature · 1 line
1.8.3.2
PATCH v2 10/11 ARM: dts: tegra114: dalmore: add GPIO power key support
In reply to Joseph LoAdding the GPIO power key and enabling the wake up function.
---
V2:
* no change
--- arch/arm/boot/dts/tegra114-dalmore.dts | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/arm/boot/dts/tegra114-dalmore.dts +11 -0
@@ -883,6 +883,17 @@ }; }; + gpio-keys { + compatible = "gpio-keys"; + + power { + label = "Power"; + gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; + linux,code = <116>; /* KEY_POWER */ + gpio-key,wakeup; + }; + }; + regulators { compatible = "simple-bus"; #address-cells = <1>;
Signature · 1 line
1.8.3.2
PATCH v2 10/11 ARM: dts: tegra114: dalmore: add GPIO power key support
Quoted 1 line · Joseph Lo
Adding the GPIO power key and enabling the wake up function.
I think I'll skip this one patch, because Laxman posted a more complete patch "[PATCH V2] ARM: tegra: enable gpio-keys on dalmore". which includes this change, plus defines another 3 keys.
PATCH v2 10/11 ARM: dts: tegra114: dalmore: add GPIO power key support
Quoted 6 lines · Stephen Warren
Quoted 1 line · Joseph Lo
Adding the GPIO power key and enabling the wake up function.
I think I'll skip this one patch, because Laxman posted a more complete patch "[PATCH V2] ARM: tegra: enable gpio-keys on dalmore". which includes this change, plus defines another 3 keys.
OK, I agree your decision.
Thanks,
Joseph
PATCH v2 11/11 ARM: dts: tegra114: dalmore: add PM configurations for PMC
In reply to Joseph LoAdding the PM configurations for PMC to support platform suspend.
---
V2:
* no change
--- arch/arm/boot/dts/tegra114-dalmore.dts | 7 +++++++ 1 file changed, 7 insertions(+)
arch/arm/boot/dts/tegra114-dalmore.dts +7 -0
@@ -850,6 +850,13 @@ pmc { nvidia,invert-interrupt; + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <500>; + nvidia,cpu-pwr-off-time = <300>; + nvidia,core-pwr-good-time = <641 3845>; + nvidia,core-pwr-off-time = <61036>; + nvidia,core-power-req-active-high; + nvidia,sys-clock-req-active-high; }; ahub {
Signature · 1 line
1.8.3.2
v2 cover ARM: tegra114: add support for system suspend
In reply to Joseph LoQuoted 4 lines · Joseph Lo
This series introduce system suspend function for Tegra114 and depend on the series of "ARM: tegra114: cpuidle: add power down state".
Verified on Seaboard, Cardhu and Dalmore and with
THUMB2_KERNELas well.
Patches 1-9 applied to Tegra's for-3.12/soc branch. Patch 10 dropped since Laxman's patch was more complete. Patch 11 applied to Tegra's for-3.12/dt branch.