From 936748fd34be484c8638a8547b4ca85afdfdf3a6 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 4 Mar 2015 12:20:12 +0100 Subject: [PATCH 01/14] ARM: at91: remove ksz8081 phy fixup registration for sama5d4ek board Commit 2b0ba96cea60 ("net: phy: micrel: disable NAND-tree for KSZ8021, KSZ8031, KSZ8051, KSZ8081") automated the NAND-tree mode deactivation process, thus making this phy fixup useless. Remove it along with the associated headers inclusion. Signed-off-by: Boris Brezillon Acked-by: Alexandre Belloni [nicolas.ferre@atmel.com: remove selection of PHYLIB in at91 Kconfig] Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/Kconfig | 1 - arch/arm/mach-at91/sama5.c | 20 -------------------- 2 files changed, 21 deletions(-) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index c74a44324e5b..d65981a8a4a9 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -24,7 +24,6 @@ config SOC_SAMA5 select GENERIC_CLOCKEVENTS select MEMORY select ATMEL_SDRAMC - select PHYLIB if NETDEVICES menu "Atmel AT91 System-on-Chip" diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c index 03dcb441f3d2..23d067a91cff 100644 --- a/arch/arm/mach-at91/sama5.c +++ b/arch/arm/mach-at91/sama5.c @@ -11,13 +11,10 @@ #include #include #include -#include #include #include #include -#include #include -#include #include @@ -29,25 +26,8 @@ #include "generic.h" -static int ksz8081_phy_fixup(struct phy_device *phy) -{ - int value; - - value = phy_read(phy, 0x16); - value &= ~0x20; - phy_write(phy, 0x16, value); - - return 0; -} - static void __init sama5_dt_device_init(void) { - if (of_machine_is_compatible("atmel,sama5d4ek") && - IS_ENABLED(CONFIG_PHYLIB)) { - phy_register_fixup_for_id("fc028000.etherne:00", - ksz8081_phy_fixup); - } - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); at91sam9x5_pm_init(); } From 047794e13632f177e864eba6160cecfbf3875cbe Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Wed, 4 Mar 2015 09:44:45 +0800 Subject: [PATCH 02/14] ARM: at91: pm: change at91_pm_set_standby() to static Since at91_pm_set_standby() will not be used out of the pm.c file, change its attribute from extern to static, remove its declaration as well. Signed-off-by: Wenyou Yang Acked-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/pm.c | 2 +- arch/arm/mach-at91/pm.h | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index aa4116e9452f..a4473dcd0f7c 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -218,7 +218,7 @@ static struct platform_device at91_cpuidle_device = { .name = "cpuidle-at91", }; -void at91_pm_set_standby(void (*at91_standby)(void)) +static void at91_pm_set_standby(void (*at91_standby)(void)) { if (at91_standby) { at91_cpuidle_device.dev.platform_data = at91_standby; diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index 86c0aa819d25..86a9d0b91814 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -15,12 +15,6 @@ #include -#ifdef CONFIG_PM -extern void at91_pm_set_standby(void (*at91_standby)(void)); -#else -static inline void at91_pm_set_standby(void (*at91_standby)(void)) { } -#endif - /* * The AT91RM9200 goes into self-refresh mode with this command, and will * terminate self-refresh automatically on the next SDRAM access. From 05d5970c723cb6d11cef793c77cd07d86d5d4a94 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:44:03 +0800 Subject: [PATCH 03/14] ARM: at91/pm_slowclock: remove the unused code related with SLOWDOWN_MASTER_CLOCK The SLOWDOWN_MASTER_CLOCK definition is not used, remove the redundant code. Signed-off-by: Wenyou Yang Acked-by: Alexandre Belloni Tested-by: Sylvain Rochet Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/pm_slowclock.S | 37 ------------------------------- 1 file changed, 37 deletions(-) diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S index 931f0e302c03..6022d2d8c267 100644 --- a/arch/arm/mach-at91/pm_slowclock.S +++ b/arch/arm/mach-at91/pm_slowclock.S @@ -11,20 +11,11 @@ * published by the Free Software Foundation. * */ - #include #include #include #include -/* - * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master - * clock during suspend by adjusting its prescalar and divisor. - * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there - * are errata regarding adjusting the prescalar and divisor. - */ -#undef SLOWDOWN_MASTER_CLOCK - pmc .req r0 sdramc .req r1 ramc1 .req r2 @@ -177,18 +168,6 @@ sdr_sr_done: wait_mckrdy -#ifdef SLOWDOWN_MASTER_CLOCK - /* - * Set the Master Clock PRES and MDIV fields. - * - * See AT91RM9200 errata #27 and #28 for details. - */ - mov tmp1, #0 - str tmp1, [pmc, #AT91_PMC_MCKR] - - wait_mckrdy -#endif - /* Save PLLA setting and disable it */ ldr tmp1, [pmc, #AT91_CKGR_PLLAR] str tmp1, .saved_pllar @@ -245,22 +224,6 @@ sdr_sr_done: wait_pllalock 4: -#ifdef SLOWDOWN_MASTER_CLOCK - /* - * First set PRES if it was not 0, - * than set CSS and MDIV fields. - * - * See AT91RM9200 errata #27 and #28 for details. - */ - ldr tmp1, .saved_mckr - tst tmp1, #AT91_PMC_PRES - beq 2f - and tmp1, tmp1, #AT91_PMC_PRES - str tmp1, [pmc, #AT91_PMC_MCKR] - - wait_mckrdy -#endif - /* * Restore master clock setting */ From 896bc871a4a2db13212831749d21ffa7f405c73b Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:44:50 +0800 Subject: [PATCH 04/14] ARM: at91: move "select SRAM" under SOC_AT91SAM9 and SOC_SAMA5 To simply the PM config the CONFIG_AT91_SLOW_CLOCK option will be removed, so move "select SRAM" from under AT91_SLOW_CLOCK, add "select SRAM if PM" under SOC_AT91SAM9 and SOC_SAMA5 Signed-off-by: Wenyou Yang Acked-by: Alexandre Belloni Tested-by: Sylvain Rochet Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index d65981a8a4a9..cd0e996565b3 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -24,6 +24,7 @@ config SOC_SAMA5 select GENERIC_CLOCKEVENTS select MEMORY select ATMEL_SDRAMC + select SRAM if PM menu "Atmel AT91 System-on-Chip" @@ -80,6 +81,7 @@ config SOC_AT91RM9200 select CPU_ARM920T select GENERIC_CLOCKEVENTS select HAVE_AT91_USB_CLK + select SRAM if PM config SOC_AT91SAM9 bool "AT91SAM9" @@ -93,6 +95,7 @@ config SOC_AT91SAM9 select HAVE_AT91_UTMI select HAVE_FB_ATMEL select MEMORY + select SRAM if PM help Select this if you are using one of those Atmel SoC: AT91SAM9260 @@ -117,7 +120,6 @@ comment "AT91 Feature Selections" config AT91_SLOW_CLOCK bool "Suspend-to-RAM disables main oscillator" - select SRAM depends on SUSPEND help Select this if you want Suspend-to-RAM to save the most power From 09fc78a601e59de89f125c8e6739fd21a7e2fd01 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:45:35 +0800 Subject: [PATCH 05/14] ARM: at91/pm: remove CONFIG_AT91_SLOW_CLOCK config option The slow clock always exists, selecting CONFIG_AT91_SLOW_CLOCK config is unnecessary for the suspend to memory mode. For this mode the master clock should always switch to the slow clock. Signed-off-by: Wenyou Yang Acked-by: Alexandre Belloni Tested-by: Sylvain Rochet Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/Kconfig | 13 ------------- arch/arm/mach-at91/Makefile | 2 +- arch/arm/mach-at91/pm.c | 12 +----------- 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index cd0e996565b3..89276fb0052a 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -118,19 +118,6 @@ endif # SOC_SAM_V4_V5 comment "AT91 Feature Selections" -config AT91_SLOW_CLOCK - bool "Suspend-to-RAM disables main oscillator" - depends on SUSPEND - help - Select this if you want Suspend-to-RAM to save the most power - possible (without powering off the CPU) by disabling the PLLs - and main oscillator so that only the 32 KiHz clock is available. - - When only that slow-clock is available, some peripherals lose - functionality. Many can't issue wakeup events unless faster - clocks are available. Some lose their operating state and - need to be completely re-initialized. - config AT91_TIMER_HZ int "Kernel HZ (jiffies per second)" range 32 1024 diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 827fdbcce1c7..103c256ecb8b 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_SOC_SAMA5) += sama5.o # Power Management obj-$(CONFIG_PM) += pm.o -obj-$(CONFIG_AT91_SLOW_CLOCK) += pm_slowclock.o +obj-$(CONFIG_PM) += pm_slowclock.o ifeq ($(CONFIG_PM_DEBUG),y) CFLAGS_pm.o += -DDEBUG diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index a4473dcd0f7c..ea4d888994af 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -123,11 +123,9 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock); static void (*slow_clock)(void __iomem *pmc, void __iomem *ramc0, void __iomem *ramc1, int memctrl); -#ifdef CONFIG_AT91_SLOW_CLOCK extern void at91_slow_clock(void __iomem *pmc, void __iomem *ramc0, void __iomem *ramc1, int memctrl); extern u32 at91_slow_clock_sz; -#endif static int at91_pm_enter(suspend_state_t state) { @@ -151,10 +149,9 @@ static int at91_pm_enter(suspend_state_t state) * turning off the main oscillator; reverse on wakeup. */ if (slow_clock) { -#ifdef CONFIG_AT91_SLOW_CLOCK /* copy slow_clock handler to SRAM, and call it */ memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz); -#endif + slow_clock(at91_pmc_base, at91_ramc_base[0], at91_ramc_base[1], at91_pm_data.memctrl); @@ -263,7 +260,6 @@ static __init void at91_dt_ramc(void) at91_pm_set_standby(standby); } -#ifdef CONFIG_AT91_SLOW_CLOCK static void __init at91_pm_sram_init(void) { struct gen_pool *sram_pool; @@ -300,16 +296,10 @@ static void __init at91_pm_sram_init(void) sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base); slow_clock = __arm_ioremap_exec(sram_pbase, at91_slow_clock_sz, false); } -#endif - static void __init at91_pm_init(void) { -#ifdef CONFIG_AT91_SLOW_CLOCK at91_pm_sram_init(); -#endif - - pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : "")); if (at91_cpuidle_device.dev.platform_data) platform_device_register(&at91_cpuidle_device); From d18c570ef3fe9c3b394c0c215b04e9729d85d14f Mon Sep 17 00:00:00 2001 From: Sylvain Rochet Date: Thu, 5 Feb 2015 14:01:23 +0800 Subject: [PATCH 06/14] ARM: at91/pm_slowclock: remove clocks which are already stopped when entering slow clock mode Assume USB PLL and PLL B are already stopped before entering sleep mode. Removed PLL B from slow clock code, all drivers are supposed to properly unprepare clocks. Signed-off-by: Sylvain Rochet Acked-by: Wenyou.Yang [nicolas.ferre@atmel.com: remove the warning printed in pm.c] Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/pm_slowclock.S | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S index 6022d2d8c267..a207dea3a152 100644 --- a/arch/arm/mach-at91/pm_slowclock.S +++ b/arch/arm/mach-at91/pm_slowclock.S @@ -50,15 +50,6 @@ tmp2 .req r5 beq 1b .endm -/* - * Wait until PLLB has locked. - */ - .macro wait_pllblock -1: ldr tmp1, [pmc, #AT91_PMC_SR] - tst tmp1, #AT91_PMC_LOCKB - beq 1b - .endm - .text .arm @@ -176,13 +167,6 @@ sdr_sr_done: orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ str tmp1, [pmc, #AT91_CKGR_PLLAR] - /* Save PLLB setting and disable it */ - ldr tmp1, [pmc, #AT91_CKGR_PLLBR] - str tmp1, .saved_pllbr - - mov tmp1, #AT91_PMC_PLLCOUNT - str tmp1, [pmc, #AT91_CKGR_PLLBR] - /* Turn off the main oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] bic tmp1, tmp1, #AT91_PMC_MOSCEN @@ -200,18 +184,6 @@ sdr_sr_done: wait_moscrdy - /* Restore PLLB setting */ - ldr tmp1, .saved_pllbr - str tmp1, [pmc, #AT91_CKGR_PLLBR] - - tst tmp1, #(AT91_PMC_MUL & 0xff0000) - bne 1f - tst tmp1, #(AT91_PMC_MUL & ~0xff0000) - beq 2f -1: - wait_pllblock -2: - /* Restore PLLA setting */ ldr tmp1, .saved_pllar str tmp1, [pmc, #AT91_CKGR_PLLAR] @@ -279,9 +251,6 @@ ram_restored: .saved_pllar: .word 0 -.saved_pllbr: - .word 0 - .saved_sam9_lpr: .word 0 From 0ab285c2fafe90dfd665b29057666c3953b2592c Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:48:26 +0800 Subject: [PATCH 07/14] ARM: at91/pm_slowclock: create the procedure to handle the sdram self-refresh To decrease the duplicated code, create the procedure to contain both activing and exiting the sdram self-refresh mode. Signed-off-by: Wenyou Yang Tested-by: Sylvain Rochet Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/pm_slowclock.S | 238 +++++++++++++++++------------- 1 file changed, 136 insertions(+), 102 deletions(-) diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S index a207dea3a152..4c5a363646dd 100644 --- a/arch/arm/mach-at91/pm_slowclock.S +++ b/arch/arm/mach-at91/pm_slowclock.S @@ -16,10 +16,10 @@ #include #include +#define SRAMC_SELF_FRESH_ACTIVE 0x01 +#define SRAMC_SELF_FRESH_EXIT 0x00 + pmc .req r0 -sdramc .req r1 -ramc1 .req r2 -memctrl .req r3 tmp1 .req r4 tmp2 .req r5 @@ -75,78 +75,17 @@ ENTRY(at91_slow_clock) mov tmp1, #0 mcr p15, 0, tmp1, c7, c10, 4 - cmp memctrl, #AT91_MEMCTRL_MC - bne ddr_sr_enable + str r0, .pmc_base + str r1, .sramc_base + str r2, .sramc1_base + str r3, .memtype - /* - * at91rm9200 Memory controller - */ - /* Put SDRAM in self-refresh mode */ - mov tmp1, #1 - str tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR] - b sdr_sr_done + /* Active the self-refresh mode */ + mov r0, #SRAMC_SELF_FRESH_ACTIVE + bl at91_sramc_self_refresh - /* - * DDRSDR Memory controller - */ -ddr_sr_enable: - cmp memctrl, #AT91_MEMCTRL_DDRSDR - bne sdr_sr_enable + ldr pmc, .pmc_base - /* LPDDR1 --> force DDR2 mode during self-refresh */ - ldr tmp1, [sdramc, #AT91_DDRSDRC_MDR] - str tmp1, .saved_sam9_mdr - bic tmp1, tmp1, #~AT91_DDRSDRC_MD - cmp tmp1, #AT91_DDRSDRC_MD_LOW_POWER_DDR - ldreq tmp1, [sdramc, #AT91_DDRSDRC_MDR] - biceq tmp1, tmp1, #AT91_DDRSDRC_MD - orreq tmp1, tmp1, #AT91_DDRSDRC_MD_DDR2 - streq tmp1, [sdramc, #AT91_DDRSDRC_MDR] - - /* prepare for DDRAM self-refresh mode */ - ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR] - str tmp1, .saved_sam9_lpr - bic tmp1, #AT91_DDRSDRC_LPCB - orr tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH - - /* figure out if we use the second ram controller */ - cmp ramc1, #0 - beq ddr_no_2nd_ctrl - - ldr tmp2, [ramc1, #AT91_DDRSDRC_MDR] - str tmp2, .saved_sam9_mdr1 - bic tmp2, tmp2, #~AT91_DDRSDRC_MD - cmp tmp2, #AT91_DDRSDRC_MD_LOW_POWER_DDR - ldreq tmp2, [ramc1, #AT91_DDRSDRC_MDR] - biceq tmp2, tmp2, #AT91_DDRSDRC_MD - orreq tmp2, tmp2, #AT91_DDRSDRC_MD_DDR2 - streq tmp2, [ramc1, #AT91_DDRSDRC_MDR] - - ldr tmp2, [ramc1, #AT91_DDRSDRC_LPR] - str tmp2, .saved_sam9_lpr1 - bic tmp2, #AT91_DDRSDRC_LPCB - orr tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH - - /* Enable DDRAM self-refresh mode */ - str tmp2, [ramc1, #AT91_DDRSDRC_LPR] -ddr_no_2nd_ctrl: - str tmp1, [sdramc, #AT91_DDRSDRC_LPR] - - b sdr_sr_done - - /* - * SDRAMC Memory controller - */ -sdr_sr_enable: - /* Enable SDRAM self-refresh mode */ - ldr tmp1, [sdramc, #AT91_SDRAMC_LPR] - str tmp1, .saved_sam9_lpr - - bic tmp1, #AT91_SDRAMC_LPCB - orr tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH - str tmp1, [sdramc, #AT91_SDRAMC_LPR] - -sdr_sr_done: /* Save Master clock setting */ ldr tmp1, [pmc, #AT91_PMC_MCKR] str tmp1, .saved_mckr @@ -199,67 +138,162 @@ sdr_sr_done: /* * Restore master clock setting */ -2: ldr tmp1, .saved_mckr + ldr tmp1, .saved_mckr str tmp1, [pmc, #AT91_PMC_MCKR] wait_mckrdy + /* Exit the self-refresh mode */ + mov r0, #SRAMC_SELF_FRESH_EXIT + bl at91_sramc_self_refresh + + /* Restore registers, and return */ + ldmfd sp!, {r4 - r12, pc} +ENDPROC(at91_slow_clock) + +/* + * void at91_sramc_self_refresh(unsigned int is_active) + * + * @input param: + * @r0: 1 - active self-refresh mode + * 0 - exit self-refresh mode + * register usage: + * @r1: memory type + * @r2: base address of the sram controller + */ + +ENTRY(at91_sramc_self_refresh) + ldr r1, .memtype + ldr r2, .sramc_base + + cmp r1, #AT91_MEMCTRL_MC + bne ddrc_sf + /* * at91rm9200 Memory controller - * Do nothing - self-refresh is automatically disabled. */ - cmp memctrl, #AT91_MEMCTRL_MC - beq ram_restored + + /* + * For exiting the self-refresh mode, do nothing, + * automatically exit the self-refresh mode. + */ + tst r0, #SRAMC_SELF_FRESH_ACTIVE + beq exit_sramc_sf + + /* Active SDRAM self-refresh mode */ + mov r3, #1 + str r3, [r2, #AT91RM9200_SDRAMC_SRR] + b exit_sramc_sf + +ddrc_sf: + cmp r1, #AT91_MEMCTRL_DDRSDR + bne sdramc_sf /* - * DDRSDR Memory controller + * DDR Memory controller */ - cmp memctrl, #AT91_MEMCTRL_DDRSDR - bne sdr_en_restore + tst r0, #SRAMC_SELF_FRESH_ACTIVE + beq ddrc_exit_sf + + /* LPDDR1 --> force DDR2 mode during self-refresh */ + ldr r3, [r2, #AT91_DDRSDRC_MDR] + str r3, .saved_sam9_mdr + bic r3, r3, #~AT91_DDRSDRC_MD + cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR + ldreq r3, [r2, #AT91_DDRSDRC_MDR] + biceq r3, r3, #AT91_DDRSDRC_MD + orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 + streq r3, [r2, #AT91_DDRSDRC_MDR] + + /* Active DDRC self-refresh mode */ + ldr r3, [r2, #AT91_DDRSDRC_LPR] + str r3, .saved_sam9_lpr + bic r3, r3, #AT91_DDRSDRC_LPCB + orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH + str r3, [r2, #AT91_DDRSDRC_LPR] + + /* If using the 2nd ddr controller */ + ldr r2, .sramc1_base + cmp r2, #0 + beq no_2nd_ddrc + + ldr r3, [r2, #AT91_DDRSDRC_MDR] + str r3, .saved_sam9_mdr1 + bic r3, r3, #~AT91_DDRSDRC_MD + cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR + ldreq r3, [r2, #AT91_DDRSDRC_MDR] + biceq r3, r3, #AT91_DDRSDRC_MD + orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 + streq r3, [r2, #AT91_DDRSDRC_MDR] + + /* Active DDRC self-refresh mode */ + ldr r3, [r2, #AT91_DDRSDRC_LPR] + str r3, .saved_sam9_lpr1 + bic r3, r3, #AT91_DDRSDRC_LPCB + orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH + str r3, [r2, #AT91_DDRSDRC_LPR] + +no_2nd_ddrc: + b exit_sramc_sf + +ddrc_exit_sf: /* Restore MDR in case of LPDDR1 */ - ldr tmp1, .saved_sam9_mdr - str tmp1, [sdramc, #AT91_DDRSDRC_MDR] + ldr r3, .saved_sam9_mdr + str r3, [r2, #AT91_DDRSDRC_MDR] /* Restore LPR on AT91 with DDRAM */ - ldr tmp1, .saved_sam9_lpr - str tmp1, [sdramc, #AT91_DDRSDRC_LPR] + ldr r3, .saved_sam9_lpr + str r3, [r2, #AT91_DDRSDRC_LPR] - /* if we use the second ram controller */ - cmp ramc1, #0 - ldrne tmp2, .saved_sam9_mdr1 - strne tmp2, [ramc1, #AT91_DDRSDRC_MDR] - ldrne tmp2, .saved_sam9_lpr1 - strne tmp2, [ramc1, #AT91_DDRSDRC_LPR] + /* If using the 2nd ddr controller */ + ldr r2, .sramc1_base + cmp r2, #0 + ldrne r3, .saved_sam9_mdr1 + strne r3, [r2, #AT91_DDRSDRC_MDR] + ldrne r3, .saved_sam9_lpr1 + strne r3, [r2, #AT91_DDRSDRC_LPR] - b ram_restored + b exit_sramc_sf /* * SDRAMC Memory controller */ -sdr_en_restore: - /* Restore LPR on AT91 with SDRAM */ - ldr tmp1, .saved_sam9_lpr - str tmp1, [sdramc, #AT91_SDRAMC_LPR] +sdramc_sf: + tst r0, #SRAMC_SELF_FRESH_ACTIVE + beq sdramc_exit_sf -ram_restored: - /* Restore registers, and return */ - ldmfd sp!, {r4 - r12, pc} + /* Active SDRAMC self-refresh mode */ + ldr r3, [r2, #AT91_SDRAMC_LPR] + str r3, .saved_sam9_lpr + bic r3, r3, #AT91_SDRAMC_LPCB + orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH + str r3, [r2, #AT91_SDRAMC_LPR] +sdramc_exit_sf: + ldr r3, .saved_sam9_lpr + str r3, [r2, #AT91_SDRAMC_LPR] +exit_sramc_sf: + mov pc, lr +ENDPROC(at91_sramc_self_refresh) + +.pmc_base: + .word 0 +.sramc_base: + .word 0 +.sramc1_base: + .word 0 +.memtype: + .word 0 .saved_mckr: .word 0 - .saved_pllar: .word 0 - .saved_sam9_lpr: .word 0 - .saved_sam9_lpr1: .word 0 - .saved_sam9_mdr: .word 0 - .saved_sam9_mdr1: .word 0 From d94e688cae5661b18164fb7366d1696a1921baba Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:49:01 +0800 Subject: [PATCH 08/14] ARM: at91/pm: move the copying the sram function to the sram initialization phase To decrease the suspend time, move copying the sram function to the sram initialization phase, instead of every time go to suspend. In the meanwhile, substitute fncpy() for memcpy(). If there is no sram allocated for PM, the PM is not supported. Signed-off-by: Wenyou Yang Acked-by: Alexandre Belloni Tested-by: Sylvain Rochet Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/pm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index ea4d888994af..7cb3a33bdba3 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -149,9 +150,6 @@ static int at91_pm_enter(suspend_state_t state) * turning off the main oscillator; reverse on wakeup. */ if (slow_clock) { - /* copy slow_clock handler to SRAM, and call it */ - memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz); - slow_clock(at91_pmc_base, at91_ramc_base[0], at91_ramc_base[1], at91_pm_data.memctrl); @@ -295,6 +293,13 @@ static void __init at91_pm_sram_init(void) sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base); slow_clock = __arm_ioremap_exec(sram_pbase, at91_slow_clock_sz, false); + if (!slow_clock) { + pr_warn("SRAM: Could not map\n"); + return; + } + + /* Copy the slow_clock handler to SRAM */ + slow_clock = fncpy(slow_clock, &at91_slow_clock, at91_slow_clock_sz); } static void __init at91_pm_init(void) @@ -304,7 +309,10 @@ static void __init at91_pm_init(void) if (at91_cpuidle_device.dev.platform_data) platform_device_register(&at91_cpuidle_device); - suspend_set_ops(&at91_pm_ops); + if (slow_clock) + suspend_set_ops(&at91_pm_ops); + else + pr_info("AT91: PM not supported, due to no SRAM allocated\n"); } void __init at91rm9200_pm_init(void) From 23be4be5a666c6b4e6fe8ddbbb84fb4f2efee0a5 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:49:46 +0800 Subject: [PATCH 09/14] ARM: at91/pm: standby mode uses same sram function as suspend to memory mode To simply the PM code, the suspend to standby mode uses same sram function as the suspend to memory mode, running in the internal SRAM, instead of the respective code for each mode. For the suspend to standby mode, the master clock doesn't switch to the slow clock, and PLLA and the main oscillator doesn't turn off as well. Signed-off-by: Wenyou Yang Tested-by: Sylvain Rochet Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/pm.c | 89 ++++++++++++++----------------- arch/arm/mach-at91/pm.h | 10 ++++ arch/arm/mach-at91/pm_slowclock.S | 25 ++++++++- 3 files changed, 75 insertions(+), 49 deletions(-) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 7cb3a33bdba3..3fc5e12043a2 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -128,62 +128,55 @@ extern void at91_slow_clock(void __iomem *pmc, void __iomem *ramc0, void __iomem *ramc1, int memctrl); extern u32 at91_slow_clock_sz; +static void at91_pm_suspend(suspend_state_t state) +{ + unsigned int pm_data = at91_pm_data.memctrl; + + pm_data |= (state == PM_SUSPEND_MEM) ? + AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0; + + slow_clock(at91_pmc_base, at91_ramc_base[0], + at91_ramc_base[1], pm_data); +} + static int at91_pm_enter(suspend_state_t state) { at91_pinctrl_gpio_suspend(); switch (state) { + /* + * Suspend-to-RAM is like STANDBY plus slow clock mode, so + * drivers must suspend more deeply, the master clock switches + * to the clk32k and turns off the main oscillator + */ + case PM_SUSPEND_MEM: /* - * Suspend-to-RAM is like STANDBY plus slow clock mode, so - * drivers must suspend more deeply: only the master clock - * controller may be using the main oscillator. + * Ensure that clocks are in a valid state. */ - case PM_SUSPEND_MEM: - /* - * Ensure that clocks are in a valid state. - */ - if (!at91_pm_verify_clocks()) - goto error; - - /* - * Enter slow clock mode by switching over to clk32k and - * turning off the main oscillator; reverse on wakeup. - */ - if (slow_clock) { - slow_clock(at91_pmc_base, at91_ramc_base[0], - at91_ramc_base[1], - at91_pm_data.memctrl); - break; - } else { - pr_info("AT91: PM - no slow clock mode enabled ...\n"); - /* FALLTHROUGH leaving master clock alone */ - } - - /* - * STANDBY mode has *all* drivers suspended; ignores irqs not - * marked as 'wakeup' event sources; and reduces DRAM power. - * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and - * nothing fancy done with main or cpu clocks. - */ - case PM_SUSPEND_STANDBY: - /* - * NOTE: the Wait-for-Interrupt instruction needs to be - * in icache so no SDRAM accesses are needed until the - * wakeup IRQ occurs and self-refresh is terminated. - * For ARM 926 based chips, this requirement is weaker - * as at91sam9 can access a RAM in self-refresh mode. - */ - if (at91_pm_standby) - at91_pm_standby(); - break; - - case PM_SUSPEND_ON: - cpu_do_idle(); - break; - - default: - pr_debug("AT91: PM - bogus suspend state %d\n", state); + if (!at91_pm_verify_clocks()) goto error; + + at91_pm_suspend(state); + + break; + + /* + * STANDBY mode has *all* drivers suspended; ignores irqs not + * marked as 'wakeup' event sources; and reduces DRAM power. + * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and + * nothing fancy done with main or cpu clocks. + */ + case PM_SUSPEND_STANDBY: + at91_pm_suspend(state); + break; + + case PM_SUSPEND_ON: + cpu_do_idle(); + break; + + default: + pr_debug("AT91: PM - bogus suspend state %d\n", state); + goto error; } error: diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index 86a9d0b91814..dcacfa1ad3fa 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -15,6 +15,14 @@ #include +#define AT91_PM_MEMTYPE_MASK 0x0f + +#define AT91_PM_MODE_OFFSET 4 +#define AT91_PM_MODE_MASK 0x01 +#define AT91_PM_MODE(x) (((x) & AT91_PM_MODE_MASK) << AT91_PM_MODE_OFFSET) + +#define AT91_PM_SLOW_CLOCK 0x01 + /* * The AT91RM9200 goes into self-refresh mode with this command, and will * terminate self-refresh automatically on the next SDRAM access. @@ -25,6 +33,7 @@ * still in self-refresh is "not recommended", but seems to work. */ +#ifndef __ASSEMBLY__ static inline void at91rm9200_standby(void) { u32 lpr = at91_ramc_read(0, AT91RM9200_SDRAMC_LPR); @@ -106,3 +115,4 @@ static inline void at91sam9_sdram_standby(void) } #endif +#endif diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S index 4c5a363646dd..db35f72e7bad 100644 --- a/arch/arm/mach-at91/pm_slowclock.S +++ b/arch/arm/mach-at91/pm_slowclock.S @@ -15,6 +15,7 @@ #include #include #include +#include "pm.h" #define SRAMC_SELF_FRESH_ACTIVE 0x01 #define SRAMC_SELF_FRESH_EXIT 0x00 @@ -78,12 +79,22 @@ ENTRY(at91_slow_clock) str r0, .pmc_base str r1, .sramc_base str r2, .sramc1_base - str r3, .memtype + + and r0, r3, #AT91_PM_MEMTYPE_MASK + str r0, .memtype + + lsr r0, r3, #AT91_PM_MODE_OFFSET + and r0, r0, #AT91_PM_MODE_MASK + str r0, .pm_mode /* Active the self-refresh mode */ mov r0, #SRAMC_SELF_FRESH_ACTIVE bl at91_sramc_self_refresh + ldr r0, .pm_mode + tst r0, #AT91_PM_SLOW_CLOCK + beq skip_disable_main_clock + ldr pmc, .pmc_base /* Save Master clock setting */ @@ -112,9 +123,18 @@ ENTRY(at91_slow_clock) orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] +skip_disable_main_clock: + ldr pmc, .pmc_base + /* Wait for interrupt */ mcr p15, 0, tmp1, c7, c0, 4 + ldr r0, .pm_mode + tst r0, #AT91_PM_SLOW_CLOCK + beq skip_enable_main_clock + + ldr pmc, .pmc_base + /* Turn on the main oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] orr tmp1, tmp1, #AT91_PMC_MOSCEN @@ -143,6 +163,7 @@ ENTRY(at91_slow_clock) wait_mckrdy +skip_enable_main_clock: /* Exit the self-refresh mode */ mov r0, #SRAMC_SELF_FRESH_EXIT bl at91_sramc_self_refresh @@ -284,6 +305,8 @@ ENDPROC(at91_sramc_self_refresh) .word 0 .memtype: .word 0 +.pm_mode: + .word 0 .saved_mckr: .word 0 .saved_pllar: From 828b98fa380662406f9a84e09372b18e45babbf2 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:50:29 +0800 Subject: [PATCH 10/14] ARM: at91/pm: rename file name: pm_slowclock.S --> pm_suspend.S Because the sram function is used for both suspend to memory and the suspend to standby mode, renaming is more elegant. Signed-off-by: Wenyou Yang Acked-by: Alexandre Belloni Tested-by: Sylvain Rochet Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/Makefile | 2 +- arch/arm/mach-at91/{pm_slowclock.S => pm_suspend.S} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/arm/mach-at91/{pm_slowclock.S => pm_suspend.S} (100%) diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 103c256ecb8b..7df8c854f80f 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_SOC_SAMA5) += sama5.o # Power Management obj-$(CONFIG_PM) += pm.o -obj-$(CONFIG_PM) += pm_slowclock.o +obj-$(CONFIG_PM) += pm_suspend.o ifeq ($(CONFIG_PM_DEBUG),y) CFLAGS_pm.o += -DDEBUG diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_suspend.S similarity index 100% rename from arch/arm/mach-at91/pm_slowclock.S rename to arch/arm/mach-at91/pm_suspend.S From 5726a8b9686348e8d203f1bbf9d5fc1bb5899518 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:51:09 +0800 Subject: [PATCH 11/14] ARM: at91/pm: rename function name: at91_slow_clock() --> at91_pm_suspend_sram_fn() As the file name is renamed, rename the function name at91_slow_clock() --> at91_pm_suspend_sram_fn(), rename the function handler's name at the same time. Signed-off-by: Wenyou Yang Acked-by: Alexandre Belloni Tested-by: Sylvain Rochet [nicolas.ferre@atmel.com: little update of the commit message] Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/pm.c | 27 ++++++++++++++------------- arch/arm/mach-at91/pm_suspend.S | 26 +++++++++++--------------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 3fc5e12043a2..a008e9cb88ef 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -120,13 +120,12 @@ int at91_suspend_entering_slow_clock(void) } EXPORT_SYMBOL(at91_suspend_entering_slow_clock); - -static void (*slow_clock)(void __iomem *pmc, void __iomem *ramc0, +static void (*at91_suspend_sram_fn)(void __iomem *pmc, void __iomem *ramc0, void __iomem *ramc1, int memctrl); -extern void at91_slow_clock(void __iomem *pmc, void __iomem *ramc0, +extern void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *ramc0, void __iomem *ramc1, int memctrl); -extern u32 at91_slow_clock_sz; +extern u32 at91_pm_suspend_in_sram_sz; static void at91_pm_suspend(suspend_state_t state) { @@ -135,8 +134,8 @@ static void at91_pm_suspend(suspend_state_t state) pm_data |= (state == PM_SUSPEND_MEM) ? AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0; - slow_clock(at91_pmc_base, at91_ramc_base[0], - at91_ramc_base[1], pm_data); + at91_suspend_sram_fn(at91_pmc_base, at91_ramc_base[0], + at91_ramc_base[1], pm_data); } static int at91_pm_enter(suspend_state_t state) @@ -278,21 +277,23 @@ static void __init at91_pm_sram_init(void) return; } - sram_base = gen_pool_alloc(sram_pool, at91_slow_clock_sz); + sram_base = gen_pool_alloc(sram_pool, at91_pm_suspend_in_sram_sz); if (!sram_base) { - pr_warn("%s: unable to alloc ocram!\n", __func__); + pr_warn("%s: unable to alloc sram!\n", __func__); return; } sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base); - slow_clock = __arm_ioremap_exec(sram_pbase, at91_slow_clock_sz, false); - if (!slow_clock) { + at91_suspend_sram_fn = __arm_ioremap_exec(sram_pbase, + at91_pm_suspend_in_sram_sz, false); + if (!at91_suspend_sram_fn) { pr_warn("SRAM: Could not map\n"); return; } - /* Copy the slow_clock handler to SRAM */ - slow_clock = fncpy(slow_clock, &at91_slow_clock, at91_slow_clock_sz); + /* Copy the pm suspend handler to SRAM */ + at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn, + &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz); } static void __init at91_pm_init(void) @@ -302,7 +303,7 @@ static void __init at91_pm_init(void) if (at91_cpuidle_device.dev.platform_data) platform_device_register(&at91_cpuidle_device); - if (slow_clock) + if (at91_suspend_sram_fn) suspend_set_ops(&at91_pm_ops); else pr_info("AT91: PM not supported, due to no SRAM allocated\n"); diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index db35f72e7bad..1002bb80a939 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -55,23 +55,19 @@ tmp2 .req r5 .arm -/* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc, +/* + * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc, * void __iomem *ramc1, int memctrl) + * @input param: + * @r0: base address of AT91_PMC + * @r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS) + * @r2: base address of second SDRAM Controller or 0 if not present + * @r3: pm information */ -ENTRY(at91_slow_clock) +ENTRY(at91_pm_suspend_in_sram) /* Save registers on stack */ stmfd sp!, {r4 - r12, lr} - /* - * Register usage: - * R0 = Base address of AT91_PMC - * R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS) - * R2 = Base address of second RAM Controller or 0 if not present - * R3 = Memory controller - * R4 = temporary register - * R5 = temporary register - */ - /* Drain write buffer */ mov tmp1, #0 mcr p15, 0, tmp1, c7, c10, 4 @@ -170,7 +166,7 @@ skip_enable_main_clock: /* Restore registers, and return */ ldmfd sp!, {r4 - r12, pc} -ENDPROC(at91_slow_clock) +ENDPROC(at91_pm_suspend_in_sram) /* * void at91_sramc_self_refresh(unsigned int is_active) @@ -320,5 +316,5 @@ ENDPROC(at91_sramc_self_refresh) .saved_sam9_mdr1: .word 0 -ENTRY(at91_slow_clock_sz) - .word .-at91_slow_clock +ENTRY(at91_pm_suspend_in_sram_sz) + .word .-at91_pm_suspend_in_sram From e32d995cf9db8dbf48d0ae25794b1b7b3872857d Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:51:49 +0800 Subject: [PATCH 12/14] ARM: at91/pm: remove unused void (*at91_pm_standby)(void) Because the standby mode use the same sram function as the suspend to memory mode, void (*at91_pm_standby)(void) doesn't need, remove it. Signed-off-by: Wenyou Yang Tested-by: Sylvain Rochet Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/pm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index a008e9cb88ef..9fb868d2b9da 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -42,7 +42,6 @@ static struct { int memctrl; } at91_pm_data; -static void (*at91_pm_standby)(void); void __iomem *at91_ramc_base[2]; static int at91_pm_valid_state(suspend_state_t state) @@ -207,10 +206,8 @@ static struct platform_device at91_cpuidle_device = { static void at91_pm_set_standby(void (*at91_standby)(void)) { - if (at91_standby) { + if (at91_standby) at91_cpuidle_device.dev.platform_data = at91_standby; - at91_pm_standby = at91_standby; - } } static const struct of_device_id ramc_ids[] __initconst = { From 20567658b8f010eea287087bfdbeb25757801aed Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:53:46 +0800 Subject: [PATCH 13/14] ARM: at91/pm_suspend: add the WFI instruction support for ARMv7 Add the WFI instruction to make the cpu to the idle state. In the meanwhile, disable the processor's clock. Signed-off-by: Wenyou Yang Acked-by: Alexandre Belloni Tested-by: Sylvain Rochet Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/pm_suspend.S | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index 1002bb80a939..7c444c259740 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -51,6 +51,24 @@ tmp2 .req r5 beq 1b .endm +/* + * Put the processor to enter the idle state + */ + .macro at91_cpu_idle + +#if defined(CONFIG_CPU_V7) + mov tmp1, #AT91_PMC_PCK + str tmp1, [pmc, #AT91_PMC_SCDR] + + dsb + + wfi @ Wait For Interrupt +#else + mcr p15, 0, tmp1, c7, c0, 4 +#endif + + .endm + .text .arm @@ -123,7 +141,7 @@ skip_disable_main_clock: ldr pmc, .pmc_base /* Wait for interrupt */ - mcr p15, 0, tmp1, c7, c0, 4 + at91_cpu_idle ldr r0, .pm_mode tst r0, #AT91_PM_SLOW_CLOCK From 385acc0dac88d79447a03a1363072fc258429dec Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 9 Mar 2015 11:54:26 +0800 Subject: [PATCH 14/14] ARM: at91/pm: flush data cache and clean, invalidate and disable the L2 cache Flush data cache, and clean, invalidate and disable the L2 cache before going to suspend. Restore the L2 cache configuration and re-enable the L2 cache after waking up. Signed-off-by: Wenyou Yang Acked-by: Alexandre Belloni Tested-by: Sylvain Rochet Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/pm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 9fb868d2b9da..ac947cdd506c 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -133,8 +134,13 @@ static void at91_pm_suspend(suspend_state_t state) pm_data |= (state == PM_SUSPEND_MEM) ? AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0; + flush_cache_all(); + outer_disable(); + at91_suspend_sram_fn(at91_pmc_base, at91_ramc_base[0], at91_ramc_base[1], pm_data); + + outer_resume(); } static int at91_pm_enter(suspend_state_t state)