diff options
author | Nicolas Ferre <nicolas.ferre@microchip.com> | 2017-03-14 04:38:04 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-30 03:41:26 -0400 |
commit | 2ab97521ce11d92f3ccca61561621214a370e2e5 (patch) | |
tree | 35f8cb4cd47937682ee40d4ee79765f063ac7ebc /arch/arm | |
parent | ca5477ad190b87ed19838c49ab8208268f47ae2c (diff) |
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.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index b4332b727e9c..31dde8b6f2ea 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c | |||
@@ -289,6 +289,22 @@ static void at91_ddr_standby(void) | |||
289 | at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); | 289 | at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); |
290 | } | 290 | } |
291 | 291 | ||
292 | static void sama5d3_ddr_standby(void) | ||
293 | { | ||
294 | u32 lpr0; | ||
295 | u32 saved_lpr0; | ||
296 | |||
297 | saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR); | ||
298 | lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB; | ||
299 | lpr0 |= AT91_DDRSDRC_LPCB_POWER_DOWN; | ||
300 | |||
301 | at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0); | ||
302 | |||
303 | cpu_do_idle(); | ||
304 | |||
305 | at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); | ||
306 | } | ||
307 | |||
292 | /* We manage both DDRAM/SDRAM controllers, we need more than one value to | 308 | /* We manage both DDRAM/SDRAM controllers, we need more than one value to |
293 | * remember. | 309 | * remember. |
294 | */ | 310 | */ |
@@ -323,7 +339,7 @@ static const struct of_device_id const ramc_ids[] __initconst = { | |||
323 | { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, | 339 | { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, |
324 | { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, | 340 | { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, |
325 | { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, | 341 | { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, |
326 | { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby }, | 342 | { .compatible = "atmel,sama5d3-ddramc", .data = sama5d3_ddr_standby }, |
327 | { /*sentinel*/ } | 343 | { /*sentinel*/ } |
328 | }; | 344 | }; |
329 | 345 | ||