From d24bd2517a2b847f773453eab0ee5b1c8ebc74ba Mon Sep 17 00:00:00 2001 From: Felix Radensky Date: Sun, 27 Sep 2009 23:56:12 +0200 Subject: ppc4xx: Reorganize DDR2 ECC handling Reorganize DDR2 ECC handling to use common code for SPD DIMMs and soldered SDRAM. Also, use common code to display SDRAM info (ECC, CAS latency) for SPD and soldered SDRAM variants. Signed-off-by: Felix Radensky Signed-off-by: Stefan Roese --- include/ppc405.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/ppc405.h b/include/ppc405.h index 5e5689781..8a4ba3faf 100644 --- a/include/ppc405.h +++ b/include/ppc405.h @@ -768,6 +768,10 @@ #define SDR0_SDCS_SDD (0x80000000 >> 31) +/* SDR0_SDSTP0 Serial Device Strap Register0 */ +#define SDR0_SDSTP0 0x0020 +#define SDR0_SDSTP0_PLB2xDV0_DECODE(n) ((((unsigned long)(n)) & 0x07)) + /* CUST0 Customer Configuration Register0 */ #define SDR0_CUST0 0x4000 #define SDR0_CUST0_MUX_E_N_G_MASK 0xC0000000 /* Mux_Emac_NDFC_GPIO */ -- cgit v1.2.3 From fb95169e39f2d03270bed552d27bbb02627a443e Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 28 Sep 2009 17:33:45 +0200 Subject: ppc4xx: Merge PPC4xx DDR and DDR2 ECC handling This patch merges the ECC handling (ECC parity byte writing) into one file (ecc.c) for all PPC4xx SDRAM controllers except for PPC440EPx/GRx. This exception is because only those PPC's use the completely different Denali SDRAM controller core. Previously we had two routines to generate/write the ECC parity bytes. With this patch we now only have one core function left. Tested on Kilauea (no ECC) and Katmai (with and without ECC). Signed-off-by: Stefan Roese Cc: Felix Radensky Cc: Grant Erickson Cc: Pieter Voorthuijsen --- cpu/ppc4xx/44x_spd_ddr2.c | 194 ++++-------------------------------- cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c | 6 +- cpu/ppc4xx/ecc.c | 167 +++++++++++++++++++++---------- cpu/ppc4xx/ecc.h | 52 +++++----- include/asm-ppc/ppc4xx-sdram.h | 7 +- include/ppc405.h | 4 - 6 files changed, 173 insertions(+), 257 deletions(-) (limited to 'include') diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c index 736e3cbe9..397530640 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 - * (C) Copyright 2007-2008 + * (C) Copyright 2007-2009 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * COPYRIGHT AMCC CORPORATION 2004 @@ -48,6 +48,8 @@ #include #include +#include "ecc.h" + #if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2) #define PPC4xx_IBM_DDR2_DUMP_REGISTER(mnemonic) \ @@ -93,24 +95,11 @@ void dcbz_area(u32 start_address, u32 num_bytes); #define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d)) -static unsigned long is_ecc_enabled(void); - -/*-----------------------------------------------------------------------------+ - * wait_ddr_idle - *-----------------------------------------------------------------------------*/ -static void wait_ddr_idle(void) -{ - u32 val; - - do { - mfsdram(SDRAM_MCSTAT, val); - } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT); -} - +#if !defined(CONFIG_NAND_SPL) /*-----------------------------------------------------------------------------+ * sdram_memsize *-----------------------------------------------------------------------------*/ -static phys_size_t sdram_memsize(void) +phys_size_t sdram_memsize(void) { phys_size_t mem_size; unsigned long mcopt2; @@ -183,6 +172,18 @@ static phys_size_t sdram_memsize(void) 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 *-----------------------------------------------------------------------------*/ @@ -198,12 +199,11 @@ void board_add_ram_info(int use_default) get_sys_info(&board_cfg); -#if defined(CONFIG_440) +#if defined(CONFIG_405EX) + val = board_cfg.freqPLB; +#else mfsdr(SDR0_DDR0, val); val = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(val), 1); -#else - mfsdr(SDR0_SDSTP0, val); - val = MULDIV64((board_cfg.freqPLB), SDR0_SDSTP0_PLB2xDV0_DECODE(val), 1); #endif printf(" enabled, %d MHz", (val * 2) / 1000000); @@ -211,112 +211,7 @@ void board_add_ram_info(int use_default) val = (val & SDRAM_MMODE_DCL_MASK) >> 4; printf(", CL%d)", val); } - -#ifdef CONFIG_DDR_ECC -/*-----------------------------------------------------------------------------+ - * 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); - -#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 = 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]); - } - } -#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 */ - - 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. - *-----------------------------------------------------------------------------*/ -static 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(); - - if (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, memsize, tlb_word2_i_value); - } - } -} -#endif /* CONFIG_DDR_ECC */ +#endif /* !CONFIG_NAND_SPL */ #if defined(CONFIG_SPD_EEPROM) @@ -439,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); @@ -2405,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. @@ -2989,21 +2864,6 @@ static void test(void) #else /* CONFIG_SPD_EEPROM */ -/*-----------------------------------------------------------------------------+ - * is_ecc_enabled - *-----------------------------------------------------------------------------*/ -static unsigned long is_ecc_enabled(void) -{ - unsigned long ecc; - unsigned long val; - - ecc = 0; - mfsdram(SDRAM_MCOPT1, val); - ecc = max(ecc, SDRAM_MCOPT1_MCHK_CHK_DECODE(val)); - - return ecc; -} - /*----------------------------------------------------------------------------- * Function: initdram * Description: Configures the PPC4xx IBM DDR1/DDR2 SDRAM memory controller. @@ -3225,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 91bf582d6..0283c91d8 100644 --- a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c +++ b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c @@ -42,6 +42,8 @@ #include #include +#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 3f989e7f5..f10560545 100644 --- a/cpu/ppc4xx/ecc.c +++ b/cpu/ppc4xx/ecc.c @@ -2,7 +2,7 @@ * Copyright (c) 2008 Nuovation System Designs, LLC * Grant Erickson * - * (C) Copyright 2005-2007 + * (C) Copyright 2005-2009 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * (C) Copyright 2002 @@ -42,81 +42,144 @@ #include #include #include +#include +#include #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 67c3bff87..b2588919e 100644 --- a/cpu/ppc4xx/ecc.h +++ b/cpu/ppc4xx/ecc.h @@ -2,7 +2,7 @@ * Copyright (c) 2008 Nuovation System Designs, LLC * Grant Erickson * - * Copyright (c) 2007 DENX Software Engineering, GmbH + * Copyright (c) 2007-2009 DENX Software Engineering, GmbH * Stefan Roese * * 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 b6182d4f2..92be514b4 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/ppc405.h b/include/ppc405.h index 8a4ba3faf..5e5689781 100644 --- a/include/ppc405.h +++ b/include/ppc405.h @@ -768,10 +768,6 @@ #define SDR0_SDCS_SDD (0x80000000 >> 31) -/* SDR0_SDSTP0 Serial Device Strap Register0 */ -#define SDR0_SDSTP0 0x0020 -#define SDR0_SDSTP0_PLB2xDV0_DECODE(n) ((((unsigned long)(n)) & 0x07)) - /* CUST0 Customer Configuration Register0 */ #define SDR0_CUST0 0x4000 #define SDR0_CUST0_MUX_E_N_G_MASK 0xC0000000 /* Mux_Emac_NDFC_GPIO */ -- cgit v1.2.3 From 3b4bd2d75c4b3c1a4570f47ffaaed66f56a78ff4 Mon Sep 17 00:00:00 2001 From: Matthias Fuchs Date: Wed, 30 Sep 2009 11:55:04 +0200 Subject: ppc4xx: Add SDRAM detection for PMC440 boards This patch adds support to detect the amount of DDR2 SDRAM on PMC440 modules. Detection is done by probing through a list of available and supported hardware configurations from 1GByte down to 256MB. The static TLB entry is replaced by dynamically created entries. Signed-off-by: Matthias Fuchs Signed-off-by: Stefan Roese --- board/esd/pmc440/init.S | 11 ++----- board/esd/pmc440/sdram.c | 82 ++++++++++++++++++++++++++++++++++-------------- include/configs/PMC440.h | 1 - 3 files changed, 61 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/board/esd/pmc440/init.S b/board/esd/pmc440/init.S index 26a8282ce..6585fed66 100644 --- a/board/esd/pmc440/init.S +++ b/board/esd/pmc440/init.S @@ -23,7 +23,7 @@ #include #include -/************************************************************************** +/* * 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 bb46ecce2..c3528bca4 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 #include #include +#include #include 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/include/configs/PMC440.h b/include/configs/PMC440.h index 012ae798d..d6e2f6bc5 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 -- cgit v1.2.3