diff options
-rw-r--r-- | board/esd/pmc440/init.S | 11 | ||||
-rw-r--r-- | board/esd/pmc440/sdram.c | 82 | ||||
-rw-r--r-- | cpu/ppc4xx/44x_spd_ddr2.c | 366 | ||||
-rw-r--r-- | cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c | 6 | ||||
-rw-r--r-- | cpu/ppc4xx/ecc.c | 167 | ||||
-rw-r--r-- | cpu/ppc4xx/ecc.h | 52 | ||||
-rw-r--r-- | include/asm-ppc/ppc4xx-sdram.h | 7 | ||||
-rw-r--r-- | include/configs/PMC440.h | 1 |
8 files changed, 341 insertions, 351 deletions
diff --git a/board/esd/pmc440/init.S b/board/esd/pmc440/init.S index 26a8282..6585fed 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 bb46ecc..c3528bc 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 2ab2336..3975306 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 91bf582..0283c91 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 3f989e7..f105605 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 67c3bff..b258891 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 b6182d4..92be514 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 012ae79..d6e2f6b 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 |