diff options
Diffstat (limited to 'cpu/ppc4xx')
-rw-r--r-- | cpu/ppc4xx/44x_spd_ddr2.c | 456 |
1 files changed, 249 insertions, 207 deletions
diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c index 2ab2336..736e3cb 100644 --- a/cpu/ppc4xx/44x_spd_ddr2.c +++ b/cpu/ppc4xx/44x_spd_ddr2.c @@ -48,8 +48,6 @@ #include <asm/mmu.h> #include <asm/cache.h> -#include "ecc.h" - #if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2) #define PPC4xx_IBM_DDR2_DUMP_REGISTER(mnemonic) \ @@ -86,8 +84,240 @@ /* 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)) + +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); +} + +/*-----------------------------------------------------------------------------+ + * 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) { +#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; +} + +/*-----------------------------------------------------------------------------+ + * 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_440) + 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); + + mfsdram(SDRAM_MMODE, val); + 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 */ + #if defined(CONFIG_SPD_EEPROM) /*-----------------------------------------------------------------------------+ @@ -105,14 +335,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) @@ -257,15 +483,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 +500,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 +513,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 +791,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 @@ -2305,9 +2433,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 +2446,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 @@ -2962,6 +2989,21 @@ 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. @@ -3106,7 +3148,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) |