diff mbox

[v2,06/11] ARM: at91: pm: Workaround DDRSDRC self-refresh bug with LPDDR1 memories.

Message ID 20170328111938.21297-7-alexandre.belloni@free-electrons.com (mailing list archive)
State New, archived
Headers show

Commit Message

Alexandre Belloni March 28, 2017, 11:19 a.m. UTC
As already explained for pm_suspend.S, the DDRSDR controller fails to put
LPDDR1 memories in self-refresh. Force the controller to think it has DDR2
memories during the self-refresh period, as the DDR2 self-refresh spec is
equivalent to LPDDR1, and is correctly implemented in the controller.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/pm.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

Comments

Wenyou.Yang@microchip.com March 29, 2017, 4:53 a.m. UTC | #1
> -----Original Message-----

> From: Alexandre Belloni [mailto:alexandre.belloni@free-electrons.com]

> Sent: 2017年3月28日 19:20

> To: Nicolas Ferre - M43238 <Nicolas.Ferre@microchip.com>

> Cc: linux-kernel@vger.kernel.org; linux-arm-kernel@lists.infradead.org; Boris

> Brezillon <boris.brezillon@free-electrons.com>; Wenyou Yang - A41535

> <Wenyou.Yang@microchip.com>; Alexandre Belloni <alexandre.belloni@free-

> electrons.com>

> Subject: [PATCH v2 06/11] ARM: at91: pm: Workaround DDRSDRC self-refresh

> bug with LPDDR1 memories.

> 

> As already explained for pm_suspend.S, the DDRSDR controller fails to put

> LPDDR1 memories in self-refresh. Force the controller to think it has DDR2

> memories during the self-refresh period, as the DDR2 self-refresh spec is

> equivalent to LPDDR1, and is correctly implemented in the controller.

> 

> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>


Acked-by: Wenyou Yang <wenyou.yang@atmel.com>


> ---

>  arch/arm/mach-at91/pm.c | 20 +++++++++++++++++++-

>  1 file changed, 19 insertions(+), 1 deletion(-)

> 

> diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index

> 3d68d93c11c7..488549bc2bed 100644

> --- a/arch/arm/mach-at91/pm.c

> +++ b/arch/arm/mach-at91/pm.c

> @@ -241,12 +241,27 @@ static void at91_ddr_standby(void)

>  	/* Those two values allow us to delay self-refresh activation

>  	 * to the maximum. */

>  	u32 lpr0, lpr1 = 0;

> +	u32 mdr, saved_mdr0, saved_mdr1 = 0;

>  	u32 saved_lpr0, saved_lpr1 = 0;

> 

> +	/* LPDDR1 --> force DDR2 mode during self-refresh */

> +	saved_mdr0 = at91_ramc_read(0, AT91_DDRSDRC_MDR);

> +	if ((saved_mdr0 & AT91_DDRSDRC_MD) ==

> AT91_DDRSDRC_MD_LOW_POWER_DDR) {

> +		mdr = saved_mdr0 & ~AT91_DDRSDRC_MD;

> +		mdr |= AT91_DDRSDRC_MD_DDR2;

> +		at91_ramc_write(0, AT91_DDRSDRC_MDR, mdr);

> +	}

> +

>  	if (pm_data.ramc[1]) {

>  		saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);

>  		lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;

>  		lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;

> +		saved_mdr1 = at91_ramc_read(1, AT91_DDRSDRC_MDR);

> +		if ((saved_mdr1 & AT91_DDRSDRC_MD) ==

> AT91_DDRSDRC_MD_LOW_POWER_DDR) {

> +			mdr = saved_mdr1 & ~AT91_DDRSDRC_MD;

> +			mdr |= AT91_DDRSDRC_MD_DDR2;

> +			at91_ramc_write(1, AT91_DDRSDRC_MDR, mdr);

> +		}

>  	}

> 

>  	saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR); @@ -260,9

> +275,12 @@ static void at91_ddr_standby(void)

> 

>  	cpu_do_idle();

> 

> +	at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr0);

>  	at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);

> -	if (pm_data.ramc[1])

> +	if (pm_data.ramc[1]) {

> +		at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr1);

>  		at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);

> +	}

>  }

> 

>  static void sama5d3_ddr_standby(void)

> --

> 2.11.0
diff mbox

Patch

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 3d68d93c11c7..488549bc2bed 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -241,12 +241,27 @@  static void at91_ddr_standby(void)
 	/* Those two values allow us to delay self-refresh activation
 	 * to the maximum. */
 	u32 lpr0, lpr1 = 0;
+	u32 mdr, saved_mdr0, saved_mdr1 = 0;
 	u32 saved_lpr0, saved_lpr1 = 0;
 
+	/* LPDDR1 --> force DDR2 mode during self-refresh */
+	saved_mdr0 = at91_ramc_read(0, AT91_DDRSDRC_MDR);
+	if ((saved_mdr0 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) {
+		mdr = saved_mdr0 & ~AT91_DDRSDRC_MD;
+		mdr |= AT91_DDRSDRC_MD_DDR2;
+		at91_ramc_write(0, AT91_DDRSDRC_MDR, mdr);
+	}
+
 	if (pm_data.ramc[1]) {
 		saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
 		lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
 		lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
+		saved_mdr1 = at91_ramc_read(1, AT91_DDRSDRC_MDR);
+		if ((saved_mdr1 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) {
+			mdr = saved_mdr1 & ~AT91_DDRSDRC_MD;
+			mdr |= AT91_DDRSDRC_MD_DDR2;
+			at91_ramc_write(1, AT91_DDRSDRC_MDR, mdr);
+		}
 	}
 
 	saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
@@ -260,9 +275,12 @@  static void at91_ddr_standby(void)
 
 	cpu_do_idle();
 
+	at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr0);
 	at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
-	if (pm_data.ramc[1])
+	if (pm_data.ramc[1]) {
+		at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr1);
 		at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
+	}
 }
 
 static void sama5d3_ddr_standby(void)