Non-destructive memory initialization in uboot

Use XOR Engine ECC Cleanup mode instead of just writing a default
value for all of RAM.

Re-enable ECC mode for Chimera

Change-Id: I796bde57ae54db9a82953582066845fb1d45a3f3
diff --git a/tools/marvell/bin_hdr/inc/ddr3_soc/a38x/ddr3_a38x_topology.h b/tools/marvell/bin_hdr/inc/ddr3_soc/a38x/ddr3_a38x_topology.h
index a56298e..3ac5580 100755
--- a/tools/marvell/bin_hdr/inc/ddr3_soc/a38x/ddr3_a38x_topology.h
+++ b/tools/marvell/bin_hdr/inc/ddr3_soc/a38x/ddr3_a38x_topology.h
@@ -133,7 +133,7 @@
     0x1, /* active interfaces */
     /*cs_mask, mirror, dqs_swap, ck_swap X PUPs                                     speed_bin             memory_device_width  mem_size     frequency  casL casWL      temperature */
 	{{{{0x1,0,0,0}, {0x1,0,0,0}, {0x1,0,0,0}, {0x1,0,0,0}, {0x1,0,0,0}}, SPEED_BIN_DDR_1600K, BUS_WIDTH_8 , MEM_2G, DDR_FREQ_400, 0 ,   0 , MV_HWS_TEMP_LOW}},
-    INTERFACE_BUS_MASK_32BIT  /* Buses mask */
+    INTERFACE_BUS_MASK_32BIT_ECC  /* Buses mask */
     }
 };
 
diff --git a/tools/marvell/bin_hdr/src_ddr/ddr3libv2/src/Os/gtOs/mvXor.c b/tools/marvell/bin_hdr/src_ddr/ddr3libv2/src/Os/gtOs/mvXor.c
index f02ae98..0541982 100755
--- a/tools/marvell/bin_hdr/src_ddr/ddr3libv2/src/Os/gtOs/mvXor.c
+++ b/tools/marvell/bin_hdr/src_ddr/ddr3libv2/src/Os/gtOs/mvXor.c
@@ -70,6 +70,11 @@
 #define DB(x)
 #endif
 
+#ifdef CONFIG_GFCH100
+/* Attempt to retain the SDRAM memory contents across reboots */
+#define NON_DESTRUCTIVE_ECC_INIT
+#endif
+
 static GT_U32 uiXorRegsCtrlBackup;
 static GT_U32 uiXorRegsBaseBackup[MAX_CS + 1];
 static GT_U32 uiXorRegsMaskBackup[MAX_CS + 1];
@@ -226,6 +231,98 @@
 }
 
 /*******************************************************************************
+* mvXorEccClean - .
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*       destPtr -
+*
+* OUTPUT:
+*       None.
+*
+* RETURN:
+*
+*******************************************************************************/
+GT_STATUS mvXorEccClean(GT_U32 chan, MV_XOR_ECC *pXorEccConfig)
+{
+	MV_U32 tClkCycles;
+	MV_U32 temp;
+
+	/* Parameter checking   */
+	if (chan >= MV_XOR_MAX_CHAN) {
+		DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n", __func__, chan));
+		return MV_BAD_PARAM;
+	}
+	if (NULL == pXorEccConfig) {
+		DB(mvOsPrintf("%s: ERR. pXorEccConfig is NULL pointer\n", __func__));
+		return MV_BAD_PTR;
+	}
+	if (MV_ACTIVE == mvXorStateGet(chan)) {
+		DB(mvOsPrintf("%s: ERR. Channel is already active\n", __func__));
+		return MV_BUSY;
+	}
+	if ((pXorEccConfig->sectorSize < XETMCR_SECTION_SIZE_MIN_VALUE) ||
+	    (pXorEccConfig->sectorSize > XETMCR_SECTION_SIZE_MAX_VALUE)) {
+		DB(mvOsPrintf("%s: ERR. sectorSize must be between %d to %d\n",
+			      __func__, XETMCR_SECTION_SIZE_MIN_VALUE, XETMCR_SECTION_SIZE_MAX_VALUE));
+		return MV_BAD_PARAM;
+	}
+	if ((pXorEccConfig->blockSize < XEXBSR_BLOCK_SIZE_MIN_VALUE) ||
+	    (pXorEccConfig->blockSize > XEXBSR_BLOCK_SIZE_MAX_VALUE)) {
+		DB(mvOsPrintf("%s: ERR. Block size must be between %d to %ul\n",
+			      __func__, XEXBSR_BLOCK_SIZE_MIN_VALUE, XEXBSR_BLOCK_SIZE_MAX_VALUE));
+		return MV_BAD_PARAM;
+	}
+
+#ifndef NON_DESTRUCTIVE_ECC_INIT
+	if (0x0 == pXorEccConfig->destPtr) {
+		DB(mvOsPrintf("%s: ERR. destPtr is NULL pointer\n", __func__));
+		return MV_BAD_PARAM;
+	}
+#endif
+
+	/* set the operation mode to ECC */
+	temp = MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+	temp &= ~XEXCR_OPERATION_MODE_MASK;
+	temp |= XEXCR_OPERATION_MODE_ECC;
+	MV_REG_WRITE(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
+
+	/* update the TimerEn bit in the XOR Engine Timer Mode
+	   Control Register (XETMCR) */
+	if (pXorEccConfig->periodicEnable)
+		MV_REG_BIT_SET(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)), XETMCR_TIMER_EN_MASK);
+	else
+		MV_REG_BIT_RESET(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)), XETMCR_TIMER_EN_MASK);
+
+	/* update the SectionSizeCtrl bit in the XOR Engine Timer Mode Control
+	   Register (XETMCR) */
+	temp = MV_REG_READ(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)));
+	temp &= ~XETMCR_SECTION_SIZE_CTRL_MASK;
+	temp |= (pXorEccConfig->sectorSize << XETMCR_SECTION_SIZE_CTRL_OFFS);
+	MV_REG_WRITE(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)), temp);
+
+	/* update the DstPtr field in the XOR Engine [0..1] Destination Pointer
+	   Register (XExDPR0) */
+	MV_REG_WRITE(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), pXorEccConfig->destPtr);
+
+	/* update the BlockSize field in the XOR Engine[0..1] Block Size
+	   Registers (XExBSR) */
+	MV_REG_WRITE(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)), pXorEccConfig->blockSize);
+
+	/* update the XOR Engine Timer Mode Initial Value Register (XETMIVR) */
+	tClkCycles = pXorEccConfig->tClkTicks;
+	MV_REG_WRITE(XOR_TIMER_MODE_INIT_VAL_REG(XOR_UNIT(chan)), tClkCycles);
+
+	/* start transfer */
+	MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)), XEXACTR_XESTART_MASK);
+
+	return MV_OK;
+}
+
+
+/*******************************************************************************
 * mvXorMemInit -
 *
 * DESCRIPTION:
@@ -413,23 +510,54 @@
 *******************************************************************************/
 MV_VOID	ddr3NewTipEccScrub()
 {
-	MV_U32 cs_c,max_cs;
-	MV_U32 uiCsEna = 0;
+    MV_U32 cs_c,max_cs;
+    MV_U32 uiCsEna = 0;
+#ifdef NON_DESTRUCTIVE_ECC_INIT
+    mvPrintf("DDR Training Sequence - Start non-destructive scrubbing \n");
+#else
     mvPrintf("DDR Training Sequence - Start scrubbing \n");
+#endif
 
-	max_cs = mvHwsDdr3TipMaxCSGet(0);
-	for (cs_c = 0; cs_c < max_cs; cs_c++)
-		uiCsEna |= 1 << cs_c;
+    max_cs = mvHwsDdr3TipMaxCSGet(0);
+    for (cs_c = 0; cs_c < max_cs; cs_c++)
+        uiCsEna |= 1 << cs_c;
 
-	mvSysXorInit(max_cs, uiCsEna, 0x80000000, 0);
+    mvSysXorInit(max_cs, uiCsEna, 0x80000000, 0);
 
-	mvXorMemInit(0, 0x00000000, 0x80000000, 0xdeadbeef, 0xdeadbeef);
+#ifdef NON_DESTRUCTIVE_ECC_INIT
+    /* Use XOR Engine ECC cleanup mode to initialize ECC bits */
+    GT_U32 destination;
+    GT_U32 original_sdram_config;
+    MV_XOR_ECC ecc_configuration;
+
+    original_sdram_config = MV_REG_READ(REG_SDRAM_CONFIG_ADDR);
+    /* Enable bit 19 - Ignore ECC errors */
+    MV_REG_WRITE(REG_SDRAM_CONFIG_ADDR, original_sdram_config | BIT19);
+
+    /* Process up to 3GB of RAM */
+    for (destination = 0; destination < 0xc0000000; destination += 0x40000000) {
+        /* memory RMW ECC engine */
+        ecc_configuration.destPtr = destination;
+        ecc_configuration.blockSize = 0x40000000;  /* 1GB */
+        ecc_configuration.periodicEnable = 0;      /* not enabled */
+        ecc_configuration.tClkTicks = 0;           /* not enabled */
+        ecc_configuration.sectorSize = 30;         /* 1GB sector size */
+
+        GT_STATUS status = mvXorEccClean(0, &ecc_configuration);
+        while (mvXorStateGet(0) != MV_IDLE);
+    }
+
+    MV_REG_WRITE(REG_SDRAM_CONFIG_ADDR, original_sdram_config);
+#else
+    /* Use XOR Engine Memory Initialization to set the contents of RAM */
+    mvXorMemInit(0, 0x00000000, 0x80000000, 0x0ecc0ecc, 0x0ecc0ecc);
     /* wait for previous transfer completion */
     while (mvXorStateGet(0) != MV_IDLE);
 
-	mvXorMemInit(0, 0x80000000, 0x40000000, 0xdeadbeef, 0xdeadbeef);
+    mvXorMemInit(0, 0x80000000, 0x40000000, 0x0ecc0ecc, 0x0ecc0ecc);
     /* wait for previous transfer completion */
     while (mvXorStateGet(0) != MV_IDLE);
+#endif
 
     /* Return XOR State */
     mvSysXorFinish();