summaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@microchip.com>2017-03-14 09:38:04 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-30 09:35:18 +0200
commit2705b183263bd6e2969a648d2c7353716ca1d7a8 (patch)
tree00488293c1649918d194b3d6b29c0355485539f6 /arch/arm
parent55b6c187cf9d12d8e667ccfa5386bd162fc7ae2b (diff)
downloadlinux-stable-2705b183263bd6e2969a648d2c7353716ca1d7a8.tar.gz
linux-stable-2705b183263bd6e2969a648d2c7353716ca1d7a8.tar.bz2
linux-stable-2705b183263bd6e2969a648d2c7353716ca1d7a8.zip
ARM: at91: pm: cpu_idle: switch DDR to power-down mode
commit 60b89f1928af80b546b5c3fd8714a62f6f4b8844 upstream. On some DDR controllers, compatible with the sama5d3 one, the sequence to enter/exit/re-enter the self-refresh mode adds more constrains than what is currently written in the at91_idle driver. An actual access to the DDR chip is needed between exit and re-enter of this mode which is somehow difficult to implement. This sequence can completely hang the SoC. It is particularly experienced on parts which embed a L2 cache if the code run between IDLE calls fits in it... Moreover, as the intention is to enter and exit pretty rapidly from IDLE, the power-down mode is a good candidate. So now we use power-down instead of self-refresh. As we can simplify the code for sama5d3 compatible DDR controllers, we instantiate a new sama5d3_ddr_standby() function. Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com> Fixes: 017b5522d5e3 ("ARM: at91: Add new binding for sama5d3-ddramc") Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-at91/pm.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 23726fb31741..d687f860a2da 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -286,6 +286,22 @@ static void at91_ddr_standby(void)
at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
}
+static void sama5d3_ddr_standby(void)
+{
+ u32 lpr0;
+ u32 saved_lpr0;
+
+ saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
+ lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
+ lpr0 |= AT91_DDRSDRC_LPCB_POWER_DOWN;
+
+ at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
+
+ cpu_do_idle();
+
+ at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
+}
+
/* We manage both DDRAM/SDRAM controllers, we need more than one value to
* remember.
*/
@@ -320,7 +336,7 @@ static const struct of_device_id const ramc_ids[] __initconst = {
{ .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
{ .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
{ .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
- { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby },
+ { .compatible = "atmel,sama5d3-ddramc", .data = sama5d3_ddr_standby },
{ /*sentinel*/ }
};