ARM: imx: ddr: Add missing PHY reset
authorMarek Vasut <marex@denx.de>
Sat, 30 May 2020 00:14:48 +0000 (02:14 +0200)
committerStefano Babic <sbabic@denx.de>
Mon, 8 Jun 2020 08:42:54 +0000 (10:42 +0200)
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@denx.de>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: NXP i.MX U-Boot Team <uboot-imx@nxp.com>
Cc: Peng Fan <peng.fan@nxp.com>
Cc: Stefano Babic <sbabic@denx.de>
arch/arm/include/asm/arch-mx7/imx-regs.h
arch/arm/mach-imx/mx7/ddr.c

index 95238dcaa84c445869a510d96ce971578cc454b4..f37419c07f1885608e7e776b99b75aef13f9299c 100644 (file)
@@ -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
index 9713835bf275a0edfcf2e7bdbf2bc7b91a76ab84..d1e10a678870ef7a61d81533a0c7b553eb166f3a 100644 (file)
@@ -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);
@@ -71,7 +87,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 */