diff mbox

[U-Boot,2/2] driver/ddr/fsl: Revise workaround A008511 for A009803

Message ID 1472461453-34231-2-git-send-email-Shengzhou.Liu@nxp.com
State Accepted
Commit 4baa38c51a3187990a31519f8163519eda3890b5
Delegated to: York Sun
Headers show

Commit Message

Shengzhou Liu Aug. 29, 2016, 9:04 a.m. UTC
From: York Sun <york.sun@nxp.com>

DDR controller 5.2.1 has this erratum A008511 partially fixed.
The workaround needs to be adjusted to take advantage of Vref
training. This patch enables the training and force output
enable to be off.

Erratum A009803 requires the controller to be idel before enabling
address parity. It was combined with workaround for A008511. With
new A008511 flow, this flow needs to be changed to enabling
data init (D_INIT) after the address parity is enabled.

Signed-off-by: York Sun <york.sun@nxp.com>
---
 drivers/ddr/fsl/fsl_ddr_gen4.c | 83 ++++++++++++++++++++++++------------------
 1 file changed, 47 insertions(+), 36 deletions(-)

Comments

York Sun Sept. 20, 2016, 6 p.m. UTC | #1
On 08/29/2016 02:16 AM, Shengzhou Liu wrote:
> From: York Sun <york.sun@nxp.com>
>
> DDR controller 5.2.1 has this erratum A008511 partially fixed.
> The workaround needs to be adjusted to take advantage of Vref
> training. This patch enables the training and force output
> enable to be off.
>
> Erratum A009803 requires the controller to be idel before enabling
> address parity. It was combined with workaround for A008511. With
> new A008511 flow, this flow needs to be changed to enabling
> data init (D_INIT) after the address parity is enabled.
>
> Signed-off-by: York Sun <york.sun@nxp.com>
> ---

Added your signed-off-by.

Applied to fsl-qoriq master. Awaiting upstream. Thanks.

York
diff mbox

Patch

diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
index c2f8a8b..aaf7c02 100644
--- a/drivers/ddr/fsl/fsl_ddr_gen4.c
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -238,7 +238,6 @@  void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_A008511
 	/* Part 1 of 2 */
-	/* This erraum only applies to verion 5.2.0 */
 	if (fsl_ddr_get_version(ctrl_num) == 0x50200) {
 		/* Disable DRAM VRef training */
 		ddr_out32(&ddr->ddr_cdr2,
@@ -247,13 +246,25 @@  void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 		temp32 = ddr_in32(&ddr->debug[28]);
 		temp32 |= DDR_TX_BD_DIS;
 		ddr_out32(&ddr->debug[28], temp32);
-		/* Disable D_INIT */
-		ddr_out32(&ddr->sdram_cfg_2,
-			  regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
 		ddr_out32(&ddr->debug[25], 0x9000);
+	} else if (fsl_ddr_get_version(ctrl_num) == 0x50201) {
+		/* Output enable forced off */
+		ddr_out32(&ddr->debug[37], 1 << 31);
+		/* Enable Vref training */
+		ddr_out32(&ddr->ddr_cdr2,
+			  regs->ddr_cdr2 | DDR_CDR2_VREF_TRAIN_EN);
+	} else {
+		debug("Erratum A008511 doesn't apply.\n");
 	}
 #endif
 
+#if defined(CONFIG_SYS_FSL_ERRATUM_A009803) || \
+	defined(CONFIG_SYS_FSL_ERRATUM_A008511)
+	/* Disable D_INIT */
+	ddr_out32(&ddr->sdram_cfg_2,
+		  regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
+#endif
+
 #ifdef CONFIG_SYS_FSL_ERRATUM_A009801
 	temp32 = ddr_in32(&ddr->debug[25]);
 	temp32 &= ~DDR_CAS_TO_PRE_SUB_MASK;
@@ -331,21 +342,21 @@  step2:
 #if defined(CONFIG_SYS_FSL_ERRATUM_A008511) || \
 	defined(CONFIG_SYS_FSL_ERRATUM_A009803)
 	/* Part 2 of 2 */
-	/* This erraum only applies to verion 5.2.0 */
-	if (fsl_ddr_get_version(ctrl_num) == 0x50200) {
-		/* Wait for idle */
-		timeout = 40;
-		while (!(ddr_in32(&ddr->debug[1]) & 0x2) &&
-		       (timeout > 0)) {
-			udelay(1000);
-			timeout--;
-		}
-		if (timeout <= 0) {
-			printf("Controler %d timeout, debug_2 = %x\n",
-			       ctrl_num, ddr_in32(&ddr->debug[1]));
-		}
+	timeout = 40;
+	/* Wait for idle. D_INIT needs to be cleared earlier, or timeout */
+	while (!(ddr_in32(&ddr->debug[1]) & 0x2) &&
+	       (timeout > 0)) {
+		udelay(1000);
+		timeout--;
+	}
+	if (timeout <= 0) {
+		printf("Controler %d timeout, debug_2 = %x\n",
+		       ctrl_num, ddr_in32(&ddr->debug[1]));
+	}
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_A008511
+	/* This erraum only applies to verion 5.2.0 */
+	if (fsl_ddr_get_version(ctrl_num) == 0x50200) {
 		/* The vref setting sequence is different for range 2 */
 		if (regs->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2)
 			vref_seq = vref_seq2;
@@ -392,32 +403,32 @@  step2:
 			printf("Controler %d timeout, debug_2 = %x\n",
 			       ctrl_num, ddr_in32(&ddr->debug[1]));
 		}
-		/* Restore D_INIT */
-		ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+	}
 #endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_A009803
-		if (regs->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) {
-			/* if it's RDIMM */
-			if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) {
-				for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
-					if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN))
-						continue;
-					set_wait_for_bits_clear(&ddr->sdram_md_cntl,
-								MD_CNTL_MD_EN |
-								MD_CNTL_CS_SEL(i) |
-								0x070000ed,
-								MD_CNTL_MD_EN);
-					udelay(1);
-				}
+	if (regs->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) {
+		/* if it's RDIMM */
+		if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) {
+			for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+				if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN))
+					continue;
+				set_wait_for_bits_clear(&ddr->sdram_md_cntl,
+							MD_CNTL_MD_EN |
+							MD_CNTL_CS_SEL(i) |
+							0x070000ed,
+							MD_CNTL_MD_EN);
+				udelay(1);
 			}
-
-			ddr_out32(&ddr->err_disable,
-				  regs->err_disable & ~DDR_ERR_DISABLE_APED);
 		}
-#endif
+
+		ddr_out32(&ddr->err_disable,
+			  regs->err_disable & ~DDR_ERR_DISABLE_APED);
 	}
 #endif
+	/* Restore D_INIT */
+	ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+#endif
 
 	total_gb_size_per_controller = 0;
 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {