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();