[PATCH RESEND] pm: at91: Workaround DDRSDRC self-refresh bug with LPDDR1 memories
Yang, Wenyou
Wenyou.Yang at atmel.com
Wed Jan 14 21:54:05 PST 2015
> -----Original Message-----
> From: Ferre, Nicolas
> Sent: Thursday, January 15, 2015 12:48 AM
> To: Peter Rosin; linux-arm-kernel at lists.infradead.org; Yang, Wenyou
> Cc: Peter Rosin; Andrew Victor; Jean-Christophe Plagniol-Villard; Russell King;
> linux-kernel at vger.kernel.org; Alexandre Belloni; Boris BREZILLON
> Subject: Re: [PATCH RESEND] pm: at91: Workaround DDRSDRC self-refresh bug
> with LPDDR1 memories
>
> Le 14/01/2015 14:20, Peter Rosin a écrit :
> > From: Peter Rosin <peda at axentia.se>
> >
> > The DDRSDR controller (on the ATSAMA5D31) fails miserably 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.
> >
> > Assume that the second controller has the same fault, and that other
> > CPUs in the family has the same problem, but that is untested.
> >
> > Signed-off-by: Peter Rosin <peda at axentia.se>
>
> I've just verified your code and the scope of this issue and your implementation
> makes perfect sense.
>
> Acked-by: Nicolas Ferre <nicolas.ferre at atmel.com>
>
> Peter,
> Thanks for your patch. You will probably see it appearing in 3.20 or 3.21.
>
> Wenyou,
> Can you please integrate the patch from Peter in your current rework of the PM
> routines (keeping his authorship of course)?
Of course, I will integrate.
> Please tell me if I can help with this.
>
> Best regards,
>
>
> > ---
> > arch/arm/mach-at91/pm_slowclock.S | 43
> +++++++++++++++++++++++++++++++-----
> > include/soc/at91/at91sam9_ddrsdr.h | 2 +-
> > 2 files changed, 39 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/arm/mach-at91/pm_slowclock.S
> > b/arch/arm/mach-at91/pm_slowclock.S
> > index 20018779bae7..63a9e0b0a17d 100644
> > --- a/arch/arm/mach-at91/pm_slowclock.S
> > +++ b/arch/arm/mach-at91/pm_slowclock.S
> > @@ -143,6 +143,16 @@ ddr_sr_enable:
> > cmp memctrl, #AT91_MEMCTRL_DDRSDR
> > bne sdr_sr_enable
> >
> > + /* 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
> > @@ -151,14 +161,26 @@ ddr_sr_enable:
> >
> > /* figure out if we use the second ram controller */
> > cmp ramc1, #0
> > - ldrne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
> > - strne tmp2, .saved_sam9_lpr1
> > - bicne tmp2, #AT91_DDRSDRC_LPCB
> > - orrne tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
> > + 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]
> > - strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
> >
> > b sdr_sr_done
> >
> > @@ -289,12 +311,17 @@ sdr_sr_done:
> > */
> > cmp memctrl, #AT91_MEMCTRL_DDRSDR
> > bne sdr_en_restore
> > + /* Restore MDR in case of LPDDR1 */
> > + ldr tmp1, .saved_sam9_mdr
> > + str tmp1, [sdramc, #AT91_DDRSDRC_MDR]
> > /* Restore LPR on AT91 with DDRAM */
> > ldr tmp1, .saved_sam9_lpr
> > str tmp1, [sdramc, #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]
> >
> > @@ -328,5 +355,11 @@ ram_restored:
> > .saved_sam9_lpr1:
> > .word 0
> >
> > +.saved_sam9_mdr:
> > + .word 0
> > +
> > +.saved_sam9_mdr1:
> > + .word 0
> > +
> > ENTRY(at91_slow_clock_sz)
> > .word .-at91_slow_clock
> > diff --git a/include/soc/at91/at91sam9_ddrsdr.h
> > b/include/soc/at91/at91sam9_ddrsdr.h
> > index 0210797abf2e..cd2c18787833 100644
> > --- a/include/soc/at91/at91sam9_ddrsdr.h
> > +++ b/include/soc/at91/at91sam9_ddrsdr.h
> > @@ -92,7 +92,7 @@
> > #define AT91_DDRSDRC_UPD_MR (3 << 20) /* Update
> load mode register and extended mode register */
> >
> > #define AT91_DDRSDRC_MDR 0x20 /* Memory Device Register */
> > -#define AT91_DDRSDRC_MD (3 << 0) /* Memory
> Device Type */
> > +#define AT91_DDRSDRC_MD (7 << 0) /* Memory
> Device Type */
> > #define AT91_DDRSDRC_MD_SDR 0
> > #define AT91_DDRSDRC_MD_LOW_POWER_SDR 1
> > #define AT91_DDRSDRC_MD_LOW_POWER_DDR 3
> >
>
>
> --
> Nicolas Ferre
Best Regards,
Wenyou Yang
More information about the linux-arm-kernel
mailing list