Skip to content
Snippets Groups Projects
Commit 4c8d1ecc authored by Marian Balakowicz's avatar Marian Balakowicz
Browse files

Add support for ECC DDR initialization on MPC83xx.

parent 61f25155
No related branches found
No related tags found
No related merge requests found
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
Changes since U-Boot 1.1.4: Changes since U-Boot 1.1.4:
====================================================================== ======================================================================
* Add support for ECC DDR initialization on MPC83xx.
* Add DMA support for MPC83xx. * Add DMA support for MPC83xx.
* Add sync in do_reset() routine for MPC83xx after RPR register * Add sync in do_reset() routine for MPC83xx after RPR register
......
...@@ -63,12 +63,16 @@ picos_to_clk(int picos) ...@@ -63,12 +63,16 @@ picos_to_clk(int picos)
return clks; return clks;
} }
unsigned int unsigned int banksize(unsigned char row_dens)
banksize(unsigned char row_dens)
{ {
return ((row_dens >> 2) | ((row_dens & 3) << 6)) << 24; return ((row_dens >> 2) | ((row_dens & 3) << 6)) << 24;
} }
int read_spd(uint addr)
{
return ((int) addr);
}
long int spd_sdram(int(read_spd)(uint addr)) long int spd_sdram(int(read_spd)(uint addr))
{ {
volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
...@@ -84,7 +88,7 @@ long int spd_sdram(int(read_spd)(uint addr)) ...@@ -84,7 +88,7 @@ long int spd_sdram(int(read_spd)(uint addr))
#warning Current spd_sdram does not fit its usage... adjust implementation or API... #warning Current spd_sdram does not fit its usage... adjust implementation or API...
CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd)); CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd));
if (spd.nrows > 2) { if (spd.nrows > 2) {
puts("DDR:Only two chip selects are supported on ADS.\n"); puts("DDR:Only two chip selects are supported on ADS.\n");
return 0; return 0;
...@@ -282,8 +286,13 @@ long int spd_sdram(int(read_spd)(uint addr)) ...@@ -282,8 +286,13 @@ long int spd_sdram(int(read_spd)(uint addr))
*/ */
#if defined(CONFIG_DDR_ECC) #if defined(CONFIG_DDR_ECC)
if (spd.config == 0x02) { if (spd.config == 0x02) {
ddr->err_disable = 0x0000000d; /* disable error detection */
ddr->err_sbe = 0x00ff0000; ddr->err_disable = ~ECC_ERROR_ENABLE;
/* set single bit error threshold to maximum value,
* reset counter to zero */
ddr->err_sbe = (255 << ECC_ERROR_MAN_SBET_SHIFT) |
(0 << ECC_ERROR_MAN_SBEC_SHIFT);
} }
debug("DDR:err_disable=0x%08x\n", ddr->err_disable); debug("DDR:err_disable=0x%08x\n", ddr->err_disable);
debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe); debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe);
...@@ -297,7 +306,8 @@ long int spd_sdram(int(read_spd)(uint addr)) ...@@ -297,7 +306,8 @@ long int spd_sdram(int(read_spd)(uint addr))
* CLK_ADJST = 2-MCK/MCK_B, is lauched 1/2 of one SDRAM * CLK_ADJST = 2-MCK/MCK_B, is lauched 1/2 of one SDRAM
* clock cycle after address/command * clock cycle after address/command
*/ */
ddr->sdram_clk_cntl = 0x82000000; /*ddr->sdram_clk_cntl = 0x82000000;*/
ddr->sdram_clk_cntl = (DDR_SDRAM_CLK_CNTL_SS_EN|DDR_SDRAM_CLK_CNTL_CLK_ADJUST_05);
/* /*
* Figure out the settings for the sdram_cfg register. Build up * Figure out the settings for the sdram_cfg register. Build up
...@@ -324,7 +334,7 @@ long int spd_sdram(int(read_spd)(uint addr)) ...@@ -324,7 +334,7 @@ long int spd_sdram(int(read_spd)(uint addr))
* If the user wanted ECC (enabled via sdram_cfg[2]) * If the user wanted ECC (enabled via sdram_cfg[2])
*/ */
if (spd.config == 0x02) { if (spd.config == 0x02) {
tmp |= 0x20000000; tmp |= SDRAM_CFG_ECC_EN;
} }
#endif #endif
...@@ -348,29 +358,87 @@ long int spd_sdram(int(read_spd)(uint addr)) ...@@ -348,29 +358,87 @@ long int spd_sdram(int(read_spd)(uint addr))
#if defined(CONFIG_DDR_ECC) #if defined(CONFIG_DDR_ECC)
/* /*
* Initialize all of memory for ECC, then enable errors. * Use timebase counter, get_timer() is not availabe
* at this point of initialization yet.
*/ */
static __inline__ unsigned long get_tbms (void)
{
unsigned long tbl;
unsigned long tbu1, tbu2;
unsigned long ms;
unsigned long long tmp;
ulong tbclk = get_tbclk();
/* get the timebase ticks */
do {
asm volatile ("mftbu %0":"=r" (tbu1):);
asm volatile ("mftb %0":"=r" (tbl):);
asm volatile ("mftbu %0":"=r" (tbu2):);
} while (tbu1 != tbu2);
/* convert ticks to ms */
tmp = (unsigned long long)(tbu1);
tmp = (tmp << 32);
tmp += (unsigned long long)(tbl);
ms = tmp/(tbclk/1000);
return ms;
}
void /*
ddr_enable_ecc(unsigned int dram_size) * Initialize all of memory for ECC, then enable errors.
*/
//#define CONFIG_DDR_ECC_INIT_VIA_DMA
void ddr_enable_ecc(unsigned int dram_size)
{ {
#ifndef FIXME uint *p;
uint *p = 0;
uint i = 0;
volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
volatile ccsr_ddr_t *ddr= &immap->im_ddr; volatile ddr8349_t *ddr = &immap->ddr;
unsigned long t_start, t_end;
#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
uint i;
#endif
debug("Initialize a Cachline in DRAM\n");
icache_enable();
#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
/* Initialise DMA for direct Transfers */
dma_init(); dma_init();
#endif
for (*p = 0; p < (uint *)(8 * 1024); p++) { t_start = get_tbms();
#if !defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
debug("DDR init: Cache flush method\n");
for (p = 0; p < (uint *)(dram_size); p++) {
if (((unsigned int)p & 0x1f) == 0) { if (((unsigned int)p & 0x1f) == 0) {
ppcDcbz((unsigned long) p); ppcDcbz((unsigned long) p);
} }
/* write pattern to cache and flush */
*p = (unsigned int)0xdeadbeef; *p = (unsigned int)0xdeadbeef;
if (((unsigned int)p & 0x1c) == 0x1c) { if (((unsigned int)p & 0x1c) == 0x1c) {
ppcDcbf((unsigned long) p); ppcDcbf((unsigned long) p);
} }
} }
#else
printf("DDR init: DMA method\n");
for (p = 0; p < (uint *)(8 * 1024); p++) {
/* zero one data cache line */
if (((unsigned int)p & 0x1f) == 0) {
ppcDcbz((unsigned long)p);
}
/* write pattern to it and flush */
*p = (unsigned int)0xdeadbeef;
if (((unsigned int)p & 0x1c) == 0x1c) {
ppcDcbf((unsigned long)p);
}
}
/* 8K */ /* 8K */
dma_xfer((uint *)0x2000, 0x2000, (uint *)0); dma_xfer((uint *)0x2000, 0x2000, (uint *)0);
...@@ -396,13 +464,31 @@ ddr_enable_ecc(unsigned int dram_size) ...@@ -396,13 +464,31 @@ ddr_enable_ecc(unsigned int dram_size)
for (i = 1; i < dram_size / 0x800000; i++) { for (i = 1; i < dram_size / 0x800000; i++) {
dma_xfer((uint *)(0x800000*i), 0x800000, (uint *)0); dma_xfer((uint *)(0x800000*i), 0x800000, (uint *)0);
} }
/*
* Enable errors for ECC.
*/
ddr->err_disable = 0x00000000;
asm("sync;isync");
#endif #endif
}
t_end = get_tbms();
icache_disable();
debug("\nREADY!!\n");
debug("ddr init duration: %ld ms\n", t_end - t_start);
/* Clear All ECC Errors */
if ((ddr->err_detect & ECC_ERROR_DETECT_MME) == ECC_ERROR_DETECT_MME)
ddr->err_detect |= ECC_ERROR_DETECT_MME;
if ((ddr->err_detect & ECC_ERROR_DETECT_MBE) == ECC_ERROR_DETECT_MBE)
ddr->err_detect |= ECC_ERROR_DETECT_MBE;
if ((ddr->err_detect & ECC_ERROR_DETECT_SBE) == ECC_ERROR_DETECT_SBE)
ddr->err_detect |= ECC_ERROR_DETECT_SBE;
if ((ddr->err_detect & ECC_ERROR_DETECT_MSE) == ECC_ERROR_DETECT_MSE)
ddr->err_detect |= ECC_ERROR_DETECT_MSE;
/* Disable ECC-Interrupts */
ddr->err_int_en &= ECC_ERR_INT_DISABLE;
/* Enable errors for ECC */
ddr->err_disable &= ECC_ERROR_ENABLE;
__asm__ __volatile__ ("sync");
__asm__ __volatile__ ("isync");
}
#endif /* CONFIG_DDR_ECC */ #endif /* CONFIG_DDR_ECC */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment