diff mbox series

ARM: imx: ddr: Add missing PHY reset

Message ID 20200530001448.797312-1-marex@denx.de
State Accepted
Commit 0e06d63d195670f5181958f43216d7106c05357f
Headers show
Series ARM: imx: ddr: Add missing PHY reset | expand

Commit Message

Marek Vasut May 30, 2020, 12:14 a.m. UTC
The iMX7D RM 9.2.4.9.3 Power removal flow Table 9-11. Re-enabling power
explicitly says both the DDR controller and the PHY must be reset in the
correct sequence. Currently the code only resets the controller. This
leads to a misbehavior where the system brings the DRAM up after reboot,
but the DRAM is unstable. Add the missing reset.

The easiest way to trigger this is by triggering WDT without having the
WDT assert WDOG_B signal, i.e. mw.w 0x30280000 0x25 .

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: NXP i.MX U-Boot Team <uboot-imx at nxp.com>
Cc: Peng Fan <peng.fan at nxp.com>
Cc: Stefano Babic <sbabic at denx.de>
---
 arch/arm/include/asm/arch-mx7/imx-regs.h |  1 +
 arch/arm/mach-imx/mx7/ddr.c              | 22 +++++++++++++++++++---
 2 files changed, 20 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/arch/arm/include/asm/arch-mx7/imx-regs.h b/arch/arm/include/asm/arch-mx7/imx-regs.h
index 95238dcaa8..f37419c07f 100644
--- a/arch/arm/include/asm/arch-mx7/imx-regs.h
+++ b/arch/arm/include/asm/arch-mx7/imx-regs.h
@@ -274,6 +274,7 @@  struct src {
 
 #define SRC_DDRC_RCR_DDRC_CORE_RST_OFFSET	1
 #define SRC_DDRC_RCR_DDRC_CORE_RST_MASK		(1 << 1)
+#define SRC_DDRC_RCR_DDRC_PRST_MASK		(1 << 0)
 
 /* GPR0 Bit Fields */
 #define IOMUXC_GPR_GPR0_DMAREQ_MUX_SEL0_MASK     0x1u
diff --git a/arch/arm/mach-imx/mx7/ddr.c b/arch/arm/mach-imx/mx7/ddr.c
index 9ffd8c6c66..45954ed1ed 100644
--- a/arch/arm/mach-imx/mx7/ddr.c
+++ b/arch/arm/mach-imx/mx7/ddr.c
@@ -13,6 +13,7 @@ 
 #include <asm/arch/crm_regs.h>
 #include <asm/arch/mx7-ddr.h>
 #include <common.h>
+#include <linux/delay.h>
 
 /*
  * Routine: mx7_dram_cfg
@@ -37,8 +38,23 @@  void mx7_dram_cfg(struct ddrc *ddrc_regs_val, struct ddrc_mp *ddrc_mp_val,
 		(struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
 	int i;
 
-	/* Assert DDR Controller preset and DDR PHY reset */
-	writel(SRC_DDRC_RCR_DDRC_CORE_RST_MASK, &src_regs->ddrc_rcr);
+	/*
+	 * iMX7D RM 9.2.4.9.3 Power removal flow Table 9-11. Re-enabling power
+	 * row 2 says "Reset controller / PHY by driving core_ddrc_rst = 0 ,
+	 * aresetn_n = 0, presetn = 0. That means reset everything.
+	 */
+	writel(SRC_DDRC_RCR_DDRC_CORE_RST_MASK | SRC_DDRC_RCR_DDRC_PRST_MASK,
+	       &src_regs->ddrc_rcr);
+
+	/*
+	 * iMX7D RM 6.2.7.26 SRC_DDRC_RCR says wait 30 cycles (of unknown).
+	 * If we assume this is 30 cycles at 100 MHz (about the rate of a
+	 * DRAM bus), that's 300 nS, so waiting 10 uS is more then plenty.
+	 */
+	udelay(10);
+
+	/* De-assert DDR Controller 'preset' and DDR PHY reset */
+	clrbits_le32(&src_regs->ddrc_rcr, SRC_DDRC_RCR_DDRC_PRST_MASK);
 
 	/* DDR controller configuration */
 	writel(ddrc_regs_val->mstr, &ddrc_regs->mstr);
@@ -72,7 +88,7 @@  void mx7_dram_cfg(struct ddrc *ddrc_regs_val, struct ddrc_mp *ddrc_mp_val,
 	writel(ddrc_regs_val->odtcfg, &ddrc_regs->odtcfg);
 	writel(ddrc_regs_val->odtmap, &ddrc_regs->odtmap);
 
-	/* De-assert DDR Controller preset and DDR PHY reset */
+	/* De-assert DDR Controller 'core_ddrc_rstn' and 'aresetn' */
 	clrbits_le32(&src_regs->ddrc_rcr, SRC_DDRC_RCR_DDRC_CORE_RST_MASK);
 
 	/* PHY configuration */