summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/esd/pmc440/init.S11
-rw-r--r--board/esd/pmc440/sdram.c82
-rw-r--r--cpu/ppc4xx/44x_spd_ddr2.c366
-rw-r--r--cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c6
-rw-r--r--cpu/ppc4xx/ecc.c167
-rw-r--r--cpu/ppc4xx/ecc.h52
-rw-r--r--include/asm-ppc/ppc4xx-sdram.h7
-rw-r--r--include/configs/PMC440.h1
8 files changed, 341 insertions, 351 deletions
diff --git a/board/esd/pmc440/init.S b/board/esd/pmc440/init.S
index 26a8282cec..6585fed664 100644
--- a/board/esd/pmc440/init.S
+++ b/board/esd/pmc440/init.S
@@ -23,7 +23,7 @@
#include <asm-ppc/mmu.h>
#include <config.h>
-/**************************************************************************
+/*
* TLB TABLE
*
* This table is used by the cpu boot code to setup the initial tlb
@@ -32,7 +32,7 @@
*
* Pointer to the table is returned in r1
*
- *************************************************************************/
+ */
.section .bootpg,"ax"
.globl tlbtab
@@ -49,12 +49,7 @@ tlbtab:
tlbentry( CONFIG_SYS_NAND_BOOT_SPL_SRC, SZ_4K, CONFIG_SYS_NAND_BOOT_SPL_SRC, 1, AC_R|AC_W|AC_X|SA_G )
#endif
- /* TLB-entry for DDR SDRAM (Up to 2GB) */
-#ifdef CONFIG_4xx_DCACHE
- tlbentry( CONFIG_SYS_SDRAM_BASE, SZ_256M, CONFIG_SYS_SDRAM_BASE, 0, AC_R|AC_W|AC_X|SA_G)
-#else
- tlbentry( CONFIG_SYS_SDRAM_BASE, SZ_256M, CONFIG_SYS_SDRAM_BASE, 0, AC_R|AC_W|AC_X|SA_G|SA_I )
-#endif
+ /* TLB entries for DDR2 SDRAM are generated dynamically */
#ifdef CONFIG_SYS_INIT_RAM_DCACHE
/* TLB-entry for init-ram in dcache (SA_I must be turned off!) */
diff --git a/board/esd/pmc440/sdram.c b/board/esd/pmc440/sdram.c
index bb46ecce2e..c3528bca4b 100644
--- a/board/esd/pmc440/sdram.c
+++ b/board/esd/pmc440/sdram.c
@@ -1,4 +1,7 @@
/*
+ * (C) Copyright 2009
+ * Matthias Fuchs, esd gmbh, matthias.fuchs@esd.eu
+ *
* (C) Copyright 2006
* Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com
* Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com
@@ -31,33 +34,30 @@
#include <common.h>
#include <asm/processor.h>
#include <asm/io.h>
+#include <asm/mmu.h>
#include <ppc440.h>
extern int denali_wait_for_dlllock(void);
extern void denali_core_search_data_eye(void);
+struct sdram_conf_s {
+ ulong size;
+ int rows;
+ int banks;
+};
-#if defined(CONFIG_NAND_SPL)
-/* Using cpu/ppc4xx/speed.c to calculate the bus frequency is too big
- * for the 4k NAND boot image so define bus_frequency to 133MHz here
- * which is save for the refresh counter setup.
- */
-#define get_bus_freq(val) 133000000
-#endif
+struct sdram_conf_s sdram_conf[] = {
+ {(1024 << 20), 14, 8}, /* 1GByte: 4x2GBit, 14x10, 8 banks */
+ {(512 << 20), 13, 8}, /* 512MByte: 4x1GBit, 13x10, 8 banks */
+ {(256 << 20), 13, 4}, /* 256MByte: 4x512MBit, 13x10, 4 banks */
+};
-/*************************************************************************
- *
+/*
* initdram -- 440EPx's DDR controller is a DENALI Core
- *
- ************************************************************************/
-phys_size_t initdram (int board_type)
+ */
+int initdram_by_rb(int rows, int banks)
{
-#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
-#if !defined(CONFIG_NAND_SPL)
ulong speed = get_bus_freq(0);
-#else
- ulong speed = 133333333; /* 133MHz is on the safe side */
-#endif
mtsdram(DDR0_02, 0x00000000);
@@ -89,21 +89,25 @@ phys_size_t initdram (int board_type)
mtsdram(DDR0_27, 0x0000682B);
mtsdram(DDR0_28, 0x00000000);
mtsdram(DDR0_31, 0x00000000);
- mtsdram(DDR0_42, 0x01000006);
- mtsdram(DDR0_43, 0x030A0200);
+
+ mtsdram(DDR0_42,
+ DDR0_42_ADDR_PINS_DECODE(14 - rows) |
+ 0x00000006);
+ mtsdram(DDR0_43,
+ DDR0_43_EIGHT_BANK_MODE_ENCODE(8 == banks ? 1 : 0) |
+ 0x030A0200);
+
mtsdram(DDR0_44, 0x00000003);
mtsdram(DDR0_02, 0x00000001);
denali_wait_for_dlllock();
-#endif /* #ifndef CONFIG_NAND_U_BOOT */
#ifdef CONFIG_DDR_DATA_EYE
- /* -----------------------------------------------------------+
+ /*
* Perform data eye search if requested.
- * ----------------------------------------------------------*/
+ */
denali_core_search_data_eye();
#endif
-
/*
* Clear possible errors resulting from data-eye-search.
* If not done, then we could get an interrupt later on when
@@ -111,5 +115,35 @@ phys_size_t initdram (int board_type)
*/
set_mcsr(get_mcsr());
- return (CONFIG_SYS_MBYTES_SDRAM << 20);
+ return 0;
+}
+
+phys_size_t initdram(int board_type)
+{
+ phys_size_t size;
+ int n;
+
+ /* go through supported memory configurations */
+ for (n = 0; n < ARRAY_SIZE(sdram_conf); n++) {
+ size = sdram_conf[n].size;
+
+ /* program TLB entries */
+ program_tlb(0, CONFIG_SYS_SDRAM_BASE, size,
+ TLB_WORD2_I_ENABLE);
+
+ /*
+ * setup denali core
+ */
+ initdram_by_rb(sdram_conf[n].rows,
+ sdram_conf[n].banks);
+
+ /* check for suitable configuration */
+ if (get_ram_size(CONFIG_SYS_SDRAM_BASE, size) == size)
+ return size;
+
+ /* delete TLB entries */
+ remove_tlb(CONFIG_SYS_SDRAM_BASE, size);
+ }
+
+ return 0;
}
diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c
index 2ab23365a5..3975306400 100644
--- a/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/cpu/ppc4xx/44x_spd_ddr2.c
@@ -9,7 +9,7 @@
* Copyright (c) 2008 Nuovation System Designs, LLC
* Grant Erickson <gerickson@nuovations.com>
- * (C) Copyright 2007-2008
+ * (C) Copyright 2007-2009
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* COPYRIGHT AMCC CORPORATION 2004
@@ -86,8 +86,133 @@
/* disable caching on SDRAM */
#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE
#endif /* CONFIG_4xx_DCACHE */
+
+void dcbz_area(u32 start_address, u32 num_bytes);
#endif /* CONFIG_440 */
+#define MAXRANKS 4
+#define MAXBXCF 4
+
+#define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
+
+#if !defined(CONFIG_NAND_SPL)
+/*-----------------------------------------------------------------------------+
+ * sdram_memsize
+ *-----------------------------------------------------------------------------*/
+phys_size_t sdram_memsize(void)
+{
+ phys_size_t mem_size;
+ unsigned long mcopt2;
+ unsigned long mcstat;
+ unsigned long mb0cf;
+ unsigned long sdsz;
+ unsigned long i;
+
+ mem_size = 0;
+
+ mfsdram(SDRAM_MCOPT2, mcopt2);
+ mfsdram(SDRAM_MCSTAT, mcstat);
+
+ /* DDR controller must be enabled and not in self-refresh. */
+ /* Otherwise memsize is zero. */
+ if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
+ && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
+ && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
+ == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
+ for (i = 0; i < MAXBXCF; i++) {
+ mfsdram(SDRAM_MB0CF + (i << 2), mb0cf);
+ /* Banks enabled */
+ if ((mb0cf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
+#if defined(CONFIG_440)
+ sdsz = mfdcr_any(SDRAM_R0BAS + i) & SDRAM_RXBAS_SDSZ_MASK;
+#else
+ sdsz = mb0cf & SDRAM_RXBAS_SDSZ_MASK;
+#endif
+ switch(sdsz) {
+ case SDRAM_RXBAS_SDSZ_8:
+ mem_size+=8;
+ break;
+ case SDRAM_RXBAS_SDSZ_16:
+ mem_size+=16;
+ break;
+ case SDRAM_RXBAS_SDSZ_32:
+ mem_size+=32;
+ break;
+ case SDRAM_RXBAS_SDSZ_64:
+ mem_size+=64;
+ break;
+ case SDRAM_RXBAS_SDSZ_128:
+ mem_size+=128;
+ break;
+ case SDRAM_RXBAS_SDSZ_256:
+ mem_size+=256;
+ break;
+ case SDRAM_RXBAS_SDSZ_512:
+ mem_size+=512;
+ break;
+ case SDRAM_RXBAS_SDSZ_1024:
+ mem_size+=1024;
+ break;
+ case SDRAM_RXBAS_SDSZ_2048:
+ mem_size+=2048;
+ break;
+ case SDRAM_RXBAS_SDSZ_4096:
+ mem_size+=4096;
+ break;
+ default:
+ printf("WARNING: Unsupported bank size (SDSZ=0x%lx)!\n"
+ , sdsz);
+ mem_size=0;
+ break;
+ }
+ }
+ }
+ }
+
+ return mem_size << 20;
+}
+
+/*-----------------------------------------------------------------------------+
+ * is_ecc_enabled
+ *-----------------------------------------------------------------------------*/
+static unsigned long is_ecc_enabled(void)
+{
+ unsigned long val;
+
+ mfsdram(SDRAM_MCOPT1, val);
+
+ return SDRAM_MCOPT1_MCHK_CHK_DECODE(val);
+}
+
+/*-----------------------------------------------------------------------------+
+ * board_add_ram_info
+ *-----------------------------------------------------------------------------*/
+void board_add_ram_info(int use_default)
+{
+ PPC4xx_SYS_INFO board_cfg;
+ u32 val;
+
+ if (is_ecc_enabled())
+ puts(" (ECC");
+ else
+ puts(" (ECC not");
+
+ get_sys_info(&board_cfg);
+
+#if defined(CONFIG_405EX)
+ val = board_cfg.freqPLB;
+#else
+ mfsdr(SDR0_DDR0, val);
+ val = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(val), 1);
+#endif
+ printf(" enabled, %d MHz", (val * 2) / 1000000);
+
+ mfsdram(SDRAM_MMODE, val);
+ val = (val & SDRAM_MMODE_DCL_MASK) >> 4;
+ printf(", CL%d)", val);
+}
+#endif /* !CONFIG_NAND_SPL */
+
#if defined(CONFIG_SPD_EEPROM)
/*-----------------------------------------------------------------------------+
@@ -105,14 +230,10 @@
#define SDRAM_NONE 0
#define MAXDIMMS 2
-#define MAXRANKS 4
-#define MAXBXCF 4
#define MAX_SPD_BYTES 256 /* Max number of bytes on the DIMM's SPD EEPROM */
#define ONE_BILLION 1000000000
-#define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
-
#define CMD_NOP (7 << 19)
#define CMD_PRECHARGE (2 << 19)
#define CMD_REFRESH (1 << 19)
@@ -213,7 +334,6 @@ typedef enum ddr_cas_id {
/*-----------------------------------------------------------------------------+
* Prototypes
*-----------------------------------------------------------------------------*/
-static phys_size_t sdram_memsize(void);
static void get_spd_info(unsigned long *dimm_populated,
unsigned char *iic0_dimm_addr,
unsigned long num_dimm_banks);
@@ -257,15 +377,11 @@ static void program_initplr(unsigned long *dimm_populated,
unsigned long num_dimm_banks,
ddr_cas_id_t selected_cas,
int write_recovery);
-static unsigned long is_ecc_enabled(void);
#ifdef CONFIG_DDR_ECC
static void program_ecc(unsigned long *dimm_populated,
unsigned char *iic0_dimm_addr,
unsigned long num_dimm_banks,
unsigned long tlb_word2_i_value);
-static void program_ecc_addr(unsigned long start_address,
- unsigned long num_bytes,
- unsigned long tlb_word2_i_value);
#endif
#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
static void program_DQS_calibration(unsigned long *dimm_populated,
@@ -278,7 +394,6 @@ static void DQS_calibration_process(void);
#endif
#endif
int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
-void dcbz_area(u32 start_address, u32 num_bytes);
static unsigned char spd_read(uchar chip, uint addr)
{
@@ -292,79 +407,6 @@ static unsigned char spd_read(uchar chip, uint addr)
}
/*-----------------------------------------------------------------------------+
- * sdram_memsize
- *-----------------------------------------------------------------------------*/
-static phys_size_t sdram_memsize(void)
-{
- phys_size_t mem_size;
- unsigned long mcopt2;
- unsigned long mcstat;
- unsigned long mb0cf;
- unsigned long sdsz;
- unsigned long i;
-
- mem_size = 0;
-
- mfsdram(SDRAM_MCOPT2, mcopt2);
- mfsdram(SDRAM_MCSTAT, mcstat);
-
- /* DDR controller must be enabled and not in self-refresh. */
- /* Otherwise memsize is zero. */
- if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
- && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
- && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
- == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
- for (i = 0; i < MAXBXCF; i++) {
- mfsdram(SDRAM_MB0CF + (i << 2), mb0cf);
- /* Banks enabled */
- if ((mb0cf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
- sdsz = mfdcr_any(SDRAM_R0BAS + i) & SDRAM_RXBAS_SDSZ_MASK;
-
- switch(sdsz) {
- case SDRAM_RXBAS_SDSZ_8:
- mem_size+=8;
- break;
- case SDRAM_RXBAS_SDSZ_16:
- mem_size+=16;
- break;
- case SDRAM_RXBAS_SDSZ_32:
- mem_size+=32;
- break;
- case SDRAM_RXBAS_SDSZ_64:
- mem_size+=64;
- break;
- case SDRAM_RXBAS_SDSZ_128:
- mem_size+=128;
- break;
- case SDRAM_RXBAS_SDSZ_256:
- mem_size+=256;
- break;
- case SDRAM_RXBAS_SDSZ_512:
- mem_size+=512;
- break;
- case SDRAM_RXBAS_SDSZ_1024:
- mem_size+=1024;
- break;
- case SDRAM_RXBAS_SDSZ_2048:
- mem_size+=2048;
- break;
- case SDRAM_RXBAS_SDSZ_4096:
- mem_size+=4096;
- break;
- default:
- printf("WARNING: Unsupported bank size (SDSZ=0x%lx)!\n"
- , sdsz);
- mem_size=0;
- break;
- }
- }
- }
- }
-
- return mem_size << 20;
-}
-
-/*-----------------------------------------------------------------------------+
* initdram. Initializes the 440SP Memory Queue and DDR SDRAM controller.
* Note: This routine runs from flash with a stack set up in the chip's
* sram space. It is important that the routine does not require .sbss, .bss or
@@ -643,26 +685,6 @@ static void get_spd_info(unsigned long *dimm_populated,
}
}
-void board_add_ram_info(int use_default)
-{
- PPC4xx_SYS_INFO board_cfg;
- u32 val;
-
- if (is_ecc_enabled())
- puts(" (ECC");
- else
- puts(" (ECC not");
-
- get_sys_info(&board_cfg);
-
- mfsdr(SDR0_DDR0, val);
- val = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(val), 1);
- printf(" enabled, %d MHz", (val * 2) / 1000000);
-
- mfsdram(SDRAM_MMODE, val);
- val = (val & SDRAM_MMODE_DCL_MASK) >> 4;
- printf(", CL%d)", val);
-}
/*------------------------------------------------------------------
* For the memory DIMMs installed, this routine verifies that they
@@ -2277,25 +2299,6 @@ static void program_memory_queue(unsigned long *dimm_populated,
#endif
}
-/*-----------------------------------------------------------------------------+
- * is_ecc_enabled.
- *-----------------------------------------------------------------------------*/
-static unsigned long is_ecc_enabled(void)
-{
- unsigned long dimm_num;
- unsigned long ecc;
- unsigned long val;
-
- ecc = 0;
- /* loop through all the DIMM slots on the board */
- for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) {
- mfsdram(SDRAM_MCOPT1, val);
- ecc = max(ecc, SDRAM_MCOPT1_MCHK_CHK_DECODE(val));
- }
-
- return ecc;
-}
-
#ifdef CONFIG_DDR_ECC
/*-----------------------------------------------------------------------------+
* program_ecc.
@@ -2305,9 +2308,6 @@ static void program_ecc(unsigned long *dimm_populated,
unsigned long num_dimm_banks,
unsigned long tlb_word2_i_value)
{
- unsigned long mcopt1;
- unsigned long mcopt2;
- unsigned long mcstat;
unsigned long dimm_num;
unsigned long ecc;
@@ -2321,105 +2321,7 @@ static void program_ecc(unsigned long *dimm_populated,
if (ecc == 0)
return;
- if (sdram_memsize() > CONFIG_MAX_MEM_MAPPED) {
- printf("\nWarning: Can't enable ECC on systems with more than 2GB of SDRAM!\n");
- return;
- }
-
- mfsdram(SDRAM_MCOPT1, mcopt1);
- mfsdram(SDRAM_MCOPT2, mcopt2);
-
- if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
- /* DDR controller must be enabled and not in self-refresh. */
- mfsdram(SDRAM_MCSTAT, mcstat);
- if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
- && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
- && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
- == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
-
- program_ecc_addr(0, sdram_memsize(), tlb_word2_i_value);
- }
- }
-
- return;
-}
-
-static void wait_ddr_idle(void)
-{
- u32 val;
-
- do {
- mfsdram(SDRAM_MCSTAT, val);
- } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT);
-}
-
-/*-----------------------------------------------------------------------------+
- * program_ecc_addr.
- *-----------------------------------------------------------------------------*/
-static void program_ecc_addr(unsigned long start_address,
- unsigned long num_bytes,
- unsigned long tlb_word2_i_value)
-{
- unsigned long current_address;
- unsigned long end_address;
- unsigned long address_increment;
- unsigned long mcopt1;
- char str[] = "ECC generation -";
- char slash[] = "\\|/-\\|/-";
- int loop = 0;
- int loopi = 0;
-
- current_address = start_address;
- mfsdram(SDRAM_MCOPT1, mcopt1);
- if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
- mtsdram(SDRAM_MCOPT1,
- (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_GEN);
- sync();
- eieio();
- wait_ddr_idle();
-
- puts(str);
- if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) {
- /* ECC bit set method for non-cached memory */
- if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32)
- address_increment = 4;
- else
- address_increment = 8;
- end_address = current_address + num_bytes;
-
- while (current_address < end_address) {
- *((unsigned long *)current_address) = 0x00000000;
- current_address += address_increment;
-
- if ((loop++ % (2 << 20)) == 0) {
- putc('\b');
- putc(slash[loopi++ % 8]);
- }
- }
-
- } else {
- /* ECC bit set method for cached memory */
- dcbz_area(start_address, num_bytes);
- /* Write modified dcache lines back to memory */
- clean_dcache_range(start_address, start_address + num_bytes);
- }
-
- blank_string(strlen(str));
-
- sync();
- eieio();
- wait_ddr_idle();
-
- /* clear ECC error repoting registers */
- mtsdram(SDRAM_ECCCR, 0xffffffff);
- mtdcr(0x4c, 0xffffffff);
-
- mtsdram(SDRAM_MCOPT1,
- (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK_REP);
- sync();
- eieio();
- wait_ddr_idle();
- }
+ do_program_ecc(tlb_word2_i_value);
}
#endif
@@ -3106,7 +3008,7 @@ phys_size_t initdram(int board_type)
#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
#if defined(CONFIG_DDR_ECC)
- ecc_init(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MBYTES_SDRAM << 20);
+ do_program_ecc(0);
#endif /* defined(CONFIG_DDR_ECC) */
#if defined(CONFIG_440)
@@ -3183,18 +3085,6 @@ void mtdcr_any(u32 dcr, u32 val)
}
}
#endif /* defined(CONFIG_440) */
-
-void blank_string(int size)
-{
- int i;
-
- for (i = 0; i < size; i++)
- putc('\b');
- for (i = 0; i < size; i++)
- putc(' ');
- for (i = 0; i < size; i++)
- putc('\b');
-}
#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
inline void ppc4xx_ibm_ddr2_register_dump(void)
diff --git a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
index 91bf582d6e..0283c91d84 100644
--- a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
+++ b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
@@ -42,6 +42,8 @@
#include <asm/io.h>
#include <asm/processor.h>
+#include "ecc.h"
+
#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
/*
@@ -177,7 +179,7 @@ static u32 *get_membase(int bxcr_num)
static inline void ecc_clear_status_reg(void)
{
- mtsdram(SDRAM_ECCCR, 0xffffffff);
+ mtsdram(SDRAM_ECCES, 0xffffffff);
#if defined(SDRAM_R0BAS)
mtdcr(SDRAM_ERRSTATLL, 0xffffffff);
#endif
@@ -210,7 +212,7 @@ static int ecc_check_status_reg(void)
* ecc error, then don't count
* this as a passing value
*/
- mfsdram(SDRAM_ECCCR, ecc_status);
+ mfsdram(SDRAM_ECCES, ecc_status);
if (ecc_status != 0x00000000) {
/* clear on error */
ecc_clear_status_reg();
diff --git a/cpu/ppc4xx/ecc.c b/cpu/ppc4xx/ecc.c
index 3f989e7f59..f105605459 100644
--- a/cpu/ppc4xx/ecc.c
+++ b/cpu/ppc4xx/ecc.c
@@ -2,7 +2,7 @@
* Copyright (c) 2008 Nuovation System Designs, LLC
* Grant Erickson <gerickson@nuovations.com>
*
- * (C) Copyright 2005-2007
+ * (C) Copyright 2005-2009
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* (C) Copyright 2002
@@ -42,81 +42,144 @@
#include <ppc_defs.h>
#include <asm/processor.h>
#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
#include "ecc.h"
#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) || \
defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
#if defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC)
+
+#if defined(CONFIG_405EX)
/*
- * void ecc_init()
- *
- * Description:
- * This routine initializes a range of DRAM ECC memory with known
- * data and enables ECC checking.
- *
- * TO DO:
- * - Improve performance by utilizing cache.
- * - Further generalize to make usable by other 4xx variants (e.g.
- * 440EPx, et al).
- *
- * Input(s):
- * start - A pointer to the start of memory covered by ECC requiring
- * initialization.
- * size - The size, in bytes, of the memory covered by ECC requiring
- * initialization.
- *
- * Output(s):
- * start - A pointer to the start of memory covered by ECC with
- * CONFIG_SYS_ECC_PATTERN written to all locations and ECC data
- * primed.
- *
- * Returns:
- * N/A
+ * Currently only 405EX uses 16bit data bus width as an alternative
+ * option to 32bit data width (SDRAM0_MCOPT1_WDTH)
*/
-void ecc_init(unsigned long * const start, unsigned long size)
+#define SDRAM_DATA_ALT_WIDTH 2
+#else
+#define SDRAM_DATA_ALT_WIDTH 8
+#endif
+
+static void wait_ddr_idle(void)
{
- const unsigned long pattern = CONFIG_SYS_ECC_PATTERN;
- unsigned long * const end = (unsigned long * const)((long)start + size);
- unsigned long * current = start;
+ u32 val;
+
+ do {
+ mfsdram(SDRAM_MCSTAT, val);
+ } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT);
+}
+
+static void program_ecc_addr(unsigned long start_address,
+ unsigned long num_bytes,
+ unsigned long tlb_word2_i_value)
+{
+ unsigned long current_address;
+ unsigned long end_address;
+ unsigned long address_increment;
unsigned long mcopt1;
- long increment;
+ char str[] = "ECC generation -";
+ char slash[] = "\\|/-\\|/-";
+ int loop = 0;
+ int loopi = 0;
- if (start >= end)
- return;
+ current_address = start_address;
+ mfsdram(SDRAM_MCOPT1, mcopt1);
+ if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
+ mtsdram(SDRAM_MCOPT1,
+ (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_GEN);
+ sync();
+ eieio();
+ wait_ddr_idle();
+
+ puts(str);
- mfsdram(SDRAM_ECC_CFG, mcopt1);
+#ifdef CONFIG_440
+ if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) {
+#endif
+ /* ECC bit set method for non-cached memory */
+ if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32)
+ address_increment = 4;
+ else
+ address_increment = SDRAM_DATA_ALT_WIDTH;
+ end_address = current_address + num_bytes;
- /* Enable ECC generation without checking or reporting */
+ while (current_address < end_address) {
+ *((unsigned long *)current_address) = 0;
+ current_address += address_increment;
- mtsdram(SDRAM_ECC_CFG, ((mcopt1 & ~SDRAM_ECC_CFG_MCHK_MASK) |
- SDRAM_ECC_CFG_MCHK_GEN));
+ if ((loop++ % (2 << 20)) == 0) {
+ putc('\b');
+ putc(slash[loopi++ % 8]);
+ }
+ }
+#ifdef CONFIG_440
+ } else {
+ /* ECC bit set method for cached memory */
+ dcbz_area(start_address, num_bytes);
+ /* Write modified dcache lines back to memory */
+ clean_dcache_range(start_address, start_address + num_bytes);
+ }
+#endif /* CONFIG_440 */
- increment = sizeof(u32);
+ blank_string(strlen(str));
-#if defined(CONFIG_440)
+ sync();
+ eieio();
+ wait_ddr_idle();
+
+ /* clear ECC error repoting registers */
+ mtsdram(SDRAM_ECCES, 0xffffffff);
+ mtdcr(0x4c, 0xffffffff);
+
+ mtsdram(SDRAM_MCOPT1,
+ (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK_REP);
+ sync();
+ eieio();
+ wait_ddr_idle();
+ }
+}
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
+void ecc_init(unsigned long * const start, unsigned long size)
+{
/*
- * Look at the geometry of SDRAM (data width) to determine whether we
- * can skip words when writing.
+ * Init ECC with cache disabled (on PPC's with IBM DDR
+ * controller (non DDR2), not tested with cache enabled yet
*/
+ program_ecc_addr((u32)start, size, TLB_WORD2_I_ENABLE);
+}
+#endif
- if ((mcopt1 & SDRAM_ECC_CFG_DMWD_MASK) != SDRAM_ECC_CFG_DMWD_32)
- increment = sizeof(u64);
-#endif /* defined(CONFIG_440) */
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+void do_program_ecc(unsigned long tlb_word2_i_value)
+{
+ unsigned long mcopt1;
+ unsigned long mcopt2;
+ unsigned long mcstat;
+ phys_size_t memsize = sdram_memsize();
- while (current < end) {
- *current = pattern;
- current = (unsigned long *)((long)current + increment);
+ if (memsize > CONFIG_MAX_MEM_MAPPED) {
+ printf("\nWarning: Can't enable ECC on systems with more than 2GB of SDRAM!\n");
+ return;
}
- /* Wait until the writes are finished. */
+ mfsdram(SDRAM_MCOPT1, mcopt1);
+ mfsdram(SDRAM_MCOPT2, mcopt2);
- sync();
+ if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
+ /* DDR controller must be enabled and not in self-refresh. */
+ mfsdram(SDRAM_MCSTAT, mcstat);
+ if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
+ && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
+ && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
+ == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
- /* Enable ECC generation with checking and no reporting */
-
- mtsdram(SDRAM_ECC_CFG, ((mcopt1 & ~SDRAM_ECC_CFG_MCHK_MASK) |
- SDRAM_ECC_CFG_MCHK_CHK));
+ program_ecc_addr(0, memsize, tlb_word2_i_value);
+ }
+ }
}
+#endif
+
#endif /* defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) */
#endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)... */
diff --git a/cpu/ppc4xx/ecc.h b/cpu/ppc4xx/ecc.h
index 67c3bff878..b2588919eb 100644
--- a/cpu/ppc4xx/ecc.h
+++ b/cpu/ppc4xx/ecc.h
@@ -2,7 +2,7 @@
* Copyright (c) 2008 Nuovation System Designs, LLC
* Grant Erickson <gerickson@nuovations.com>
*
- * Copyright (c) 2007 DENX Software Engineering, GmbH
+ * Copyright (c) 2007-2009 DENX Software Engineering, GmbH
* Stefan Roese <sr@denx.de>
*
* See file CREDITS for list of people who contributed to this
@@ -25,18 +25,13 @@
*
* Description:
* This file implements ECC initialization for PowerPC processors
- * using the SDRAM DDR2 controller, including the 405EX(r),
- * 440SP(E), 460EX and 460GT.
+ * using the IBM SDRAM DDR1 & DDR2 controller.
*
*/
#ifndef _ECC_H_
#define _ECC_H_
-#if !defined(CONFIG_SYS_ECC_PATTERN)
-#define CONFIG_SYS_ECC_PATTERN 0x00000000
-#endif /* !defined(CONFIG_SYS_ECC_PATTERN) */
-
/*
* Since the IBM DDR controller used on 440GP/GX/EP/GR is not register
* compatible to the IBM DDR/2 controller used on 405EX/440SP/SPe/460EX/GT
@@ -46,24 +41,35 @@
/* For 440GP/GX/EP/GR */
#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
-#define SDRAM_ECC_CFG SDRAM_CFG0
-#define SDRAM_ECC_CFG_MCHK_MASK SDRAM_CFG0_MCHK_MASK
-#define SDRAM_ECC_CFG_MCHK_GEN SDRAM_CFG0_MCHK_GEN
-#define SDRAM_ECC_CFG_MCHK_CHK SDRAM_CFG0_MCHK_CHK
-#define SDRAM_ECC_CFG_DMWD_MASK SDRAM_CFG0_DMWD_MASK
-#define SDRAM_ECC_CFG_DMWD_32 SDRAM_CFG0_DMWD_32
-#endif
+#define SDRAM_MCOPT1 SDRAM_CFG0
+#define SDRAM_MCOPT1_MCHK_MASK SDRAM_CFG0_MCHK_MASK
+#define SDRAM_MCOPT1_MCHK_NON SDRAM_CFG0_MCHK_NON
+#define SDRAM_MCOPT1_MCHK_GEN SDRAM_CFG0_MCHK_GEN
+#define SDRAM_MCOPT1_MCHK_CHK SDRAM_CFG0_MCHK_CHK
+#define SDRAM_MCOPT1_MCHK_CHK_REP SDRAM_CFG0_MCHK_CHK
+#define SDRAM_MCOPT1_DMWD_MASK SDRAM_CFG0_DMWD_MASK
+#define SDRAM_MCOPT1_DMWD_32 SDRAM_CFG0_DMWD_32
+
+#define SDRAM_MCSTAT SDRAM0_MCSTS
+#define SDRAM_MCSTAT_IDLE_MASK SDRAM_MCSTS_CIS
+#define SDRAM_MCSTAT_IDLE_NOT SDRAM_MCSTS_IDLE_NOT
-/* For 405EX/440SP/SPe/460EX/GT */
-#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
-#define SDRAM_ECC_CFG SDRAM_MCOPT1
-#define SDRAM_ECC_CFG_MCHK_MASK SDRAM_MCOPT1_MCHK_MASK
-#define SDRAM_ECC_CFG_MCHK_GEN SDRAM_MCOPT1_MCHK_GEN
-#define SDRAM_ECC_CFG_MCHK_CHK SDRAM_MCOPT1_MCHK_CHK
-#define SDRAM_ECC_CFG_DMWD_MASK SDRAM_MCOPT1_DMWD_MASK
-#define SDRAM_ECC_CFG_DMWD_32 SDRAM_MCOPT1_DMWD_32
+#define SDRAM_ECCES SDRAM0_ECCESR
#endif
-extern void ecc_init(unsigned long * const start, unsigned long size);
+void ecc_init(unsigned long * const start, unsigned long size);
+void do_program_ecc(unsigned long tlb_word2_i_value);
+
+static void inline blank_string(int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ putc('\b');
+ for (i = 0; i < size; i++)
+ putc(' ');
+ for (i = 0; i < size; i++)
+ putc('\b');
+}
#endif /* _ECC_H_ */
diff --git a/include/asm-ppc/ppc4xx-sdram.h b/include/asm-ppc/ppc4xx-sdram.h
index b6182d4f21..92be514b40 100644
--- a/include/asm-ppc/ppc4xx-sdram.h
+++ b/include/asm-ppc/ppc4xx-sdram.h
@@ -117,6 +117,7 @@
#define SDRAM_MCSTS_MRSC 0x80000000
#define SDRAM_MCSTS_SRMS 0x40000000
#define SDRAM_MCSTS_CIS 0x20000000
+#define SDRAM_MCSTS_IDLE_NOT 0x00000000 /* Mem contr not idle */
/*
* SDRAM Refresh Timer Register
@@ -416,8 +417,7 @@
#define SDRAM_SDTR3 0x87 /* DDR SDRAM timing 3 */
#define SDRAM_MMODE 0x88 /* memory mode */
#define SDRAM_MEMODE 0x89 /* memory extended mode */
-#define SDRAM_ECCCR 0x98 /* ECC error status */
-#define SDRAM_ECCES SDRAM_ECCCR
+#define SDRAM_ECCES 0x98 /* ECC error status */
#define SDRAM_CID 0xA4 /* core ID */
#ifndef CONFIG_405EX
#define SDRAM_RID 0xA8 /* revision ID */
@@ -1397,7 +1397,6 @@
/*
* Prototypes
*/
-void inline blank_string(int size);
inline void ppc4xx_ibm_ddr2_register_dump(void);
u32 mfdcr_any(u32);
void mtdcr_any(u32, u32);
@@ -1405,6 +1404,8 @@ u32 ddr_wrdtr(u32);
u32 ddr_clktr(u32);
void spd_ddr_init_hang(void);
u32 DQS_autocalibration(void);
+phys_size_t sdram_memsize(void);
+void dcbz_area(u32 start_address, u32 num_bytes);
#endif /* __ASSEMBLY__ */
#endif /* _PPC4xx_SDRAM_H_ */
diff --git a/include/configs/PMC440.h b/include/configs/PMC440.h
index 012ae798d1..d6e2f6bc5e 100644
--- a/include/configs/PMC440.h
+++ b/include/configs/PMC440.h
@@ -215,7 +215,6 @@
/*-----------------------------------------------------------------------
* DDR SDRAM
*----------------------------------------------------------------------*/
-#define CONFIG_SYS_MBYTES_SDRAM (256) /* 256MB */
#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
#define CONFIG_DDR_DATA_EYE /* use DDR2 optimization */
#endif