From d2d432760d2199d0e8558fdd9d1789b8131abcf7 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 1 Jun 2007 15:09:50 +0200 Subject: ppc4xx: 44x DDR driver code cleanup and small fix for Bamboo Signed-off-by: Stefan Roese --- cpu/ppc4xx/44x_spd_ddr.c | 341 +++++++++++++++++++++++------------------------ 1 file changed, 166 insertions(+), 175 deletions(-) (limited to 'cpu') diff --git a/cpu/ppc4xx/44x_spd_ddr.c b/cpu/ppc4xx/44x_spd_ddr.c index 10b4c18978..c500d3f242 100644 --- a/cpu/ppc4xx/44x_spd_ddr.c +++ b/cpu/ppc4xx/44x_spd_ddr.c @@ -20,7 +20,7 @@ * Jun Gu, Artesyn Technology, jung@artesyncp.com * Support for AMCC 440 based on OpenBIOS draminit.c from IBM. * - * (C) Copyright 2005 + * (C) Copyright 2005-2007 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * See file CREDITS for list of people who contributed to this @@ -42,6 +42,11 @@ * MA 02111-1307 USA */ +/* define DEBUG for debugging output (obviously ;-)) */ +#if 0 +#define DEBUG +#endif + #include #include #include @@ -246,25 +251,6 @@ #define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */ #endif -const unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = { - {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF}, - {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x00000000}, - {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0x55555555, 0x55555555}, - {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0xAAAAAAAA, 0xAAAAAAAA}, - {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0x5A5A5A5A, 0x5A5A5A5A}, - {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0xA5A5A5A5, 0xA5A5A5A5}, - {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, - 0x55AA55AA, 0x55AA55AA}, - {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0xAA55AA55, 0xAA55AA55} -}; - /* bank_parms is used to sort the bank sizes by descending order */ struct bank_param { unsigned long cr; @@ -278,46 +264,37 @@ extern unsigned char cfg_simulate_spd_eeprom[128]; #endif void program_tlb(u32 start, u32 size, u32 tlb_word2_i_value); -unsigned char spd_read(uchar chip, uint addr); - -void get_spd_info(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks); - -void check_mem_type -(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks); - -void check_volt_type -(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks); - -void program_cfg0(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks); - -void program_cfg1(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks); - -void program_rtr (unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks); - -void program_tr0 (unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks); - -void program_tr1 (void); - -void program_ecc (unsigned long num_bytes); +static unsigned char spd_read(uchar chip, uint addr); +static void get_spd_info(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks); +static void check_mem_type(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks); +static void check_volt_type(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks); +static void program_cfg0(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks); +static void program_cfg1(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks); +static void program_rtr(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks); +static void program_tr0(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks); +static void program_tr1(void); + +#ifdef CONFIG_DDR_ECC +static void program_ecc(unsigned long num_bytes); +#endif -unsigned -long program_bxcr(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks); +static unsigned long program_bxcr(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks); /* * This function is reading data from the DIMM module EEPROM over the SPD bus @@ -328,7 +305,6 @@ long program_bxcr(unsigned long* dimm_populated, * BUG: Don't handle ECC memory * BUG: A few values in the TR register is currently hardcoded */ - long int spd_sdram(void) { unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; unsigned long dimm_populated[sizeof(iic0_dimm_addr)]; @@ -421,9 +397,8 @@ long int spd_sdram(void) { */ while (1) { mfsdram(mem_mcsts, mcsts); - if ((mcsts & SDRAM_MCSTS_MRSC) != 0) { + if ((mcsts & SDRAM_MCSTS_MRSC) != 0) break; - } } /* @@ -431,14 +406,17 @@ long int spd_sdram(void) { */ program_tr1(); +#ifdef CONFIG_DDR_ECC /* - * if ECC is enabled, initialize parity bits + * If ecc is enabled, initialize the parity bits. */ + program_ecc(total_size); +#endif return total_size; } -unsigned char spd_read(uchar chip, uint addr) +static unsigned char spd_read(uchar chip, uint addr) { unsigned char data[2]; @@ -460,9 +438,9 @@ unsigned char spd_read(uchar chip, uint addr) return 0; } -void get_spd_info(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks) +static void get_spd_info(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks) { unsigned long dimm_num; unsigned long dimm_found; @@ -480,14 +458,10 @@ void get_spd_info(unsigned long* dimm_populated, if ((num_of_bytes != 0) && (total_size != 0)) { dimm_populated[dimm_num] = TRUE; dimm_found = TRUE; -#if 0 - printf("DIMM slot %lu: populated\n", dimm_num); -#endif + debug("DIMM slot %lu: populated\n", dimm_num); } else { dimm_populated[dimm_num] = FALSE; -#if 0 - printf("DIMM slot %lu: Not populated\n", dimm_num); -#endif + debug("DIMM slot %lu: Not populated\n", dimm_num); } } @@ -497,9 +471,9 @@ void get_spd_info(unsigned long* dimm_populated, } } -void check_mem_type(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks) +static void check_mem_type(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks) { unsigned long dimm_num; unsigned char dimm_type; @@ -509,9 +483,7 @@ void check_mem_type(unsigned long* dimm_populated, dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2); switch (dimm_type) { case 7: -#if 0 - printf("DIMM slot %lu: DDR SDRAM detected\n", dimm_num); -#endif + debug("DIMM slot %lu: DDR SDRAM detected\n", dimm_num); break; default: printf("ERROR: Unsupported DIMM detected in slot %lu.\n", @@ -525,10 +497,9 @@ void check_mem_type(unsigned long* dimm_populated, } } - -void check_volt_type(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks) +static void check_volt_type(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks) { unsigned long dimm_num; unsigned long voltage_type; @@ -541,18 +512,16 @@ void check_volt_type(unsigned long* dimm_populated, dimm_num); hang(); } else { -#if 0 - printf("DIMM %lu voltage level supported.\n", dimm_num); -#endif + debug("DIMM %lu voltage level supported.\n", dimm_num); } break; } } } -void program_cfg0(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks) +static void program_cfg0(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks) { unsigned long dimm_num; unsigned long cfg0; @@ -640,9 +609,9 @@ void program_cfg0(unsigned long* dimm_populated, mtsdram(mem_cfg0, cfg0); } -void program_cfg1(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks) +static void program_cfg1(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks) { unsigned long cfg1; mfsdram(mem_cfg1, cfg1); @@ -658,9 +627,9 @@ void program_cfg1(unsigned long* dimm_populated, mtsdram(mem_cfg1, cfg1); } -void program_rtr (unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks) +static void program_rtr(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks) { unsigned long dimm_num; unsigned long bus_period_x_10; @@ -676,7 +645,6 @@ void program_rtr (unsigned long* dimm_populated, get_sys_info(&sys_info); bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10); - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { if (dimm_populated[dimm_num] == TRUE) { refresh_rate_type = 0x7F & spd_read(iic0_dimm_addr[dimm_num], 12); @@ -719,9 +687,9 @@ void program_rtr (unsigned long* dimm_populated, mtsdram(mem_rtr, sdram_rtr); } -void program_tr0 (unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks) +static void program_tr0(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks) { unsigned long dimm_num; unsigned long tr0; @@ -1001,13 +969,73 @@ void program_tr0 (unsigned long* dimm_populated, break; } -#if 0 - printf("tr0: %x\n", tr0); -#endif + debug("tr0: %x\n", tr0); mtsdram(mem_tr0, tr0); } -void program_tr1 (void) +static int short_mem_test(void) +{ + unsigned long i, j; + unsigned long bxcr_num; + unsigned long *membase; + const unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = { + {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}, + {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000}, + {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, + 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555}, + {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, + 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA}, + {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, + 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A}, + {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, + 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5}, + {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, + 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA}, + {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, + 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55}}; + + for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) { + mtdcr(memcfga, mem_b0cr + (bxcr_num << 2)); + if ((mfdcr(memcfgd) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) { + /* Bank is enabled */ + membase = (unsigned long*) + (mfdcr(memcfgd) & SDRAM_BXCR_SDBA_MASK); + + /* + * Run the short memory test + */ + for (i = 0; i < NUMMEMTESTS; i++) { + for (j = 0; j < NUMMEMWORDS; j++) { + membase[j] = test[i][j]; + ppcDcbf((unsigned long)&(membase[j])); + } + + for (j = 0; j < NUMMEMWORDS; j++) { + if (membase[j] != test[i][j]) { + ppcDcbf((unsigned long)&(membase[j])); + return 0; + } + ppcDcbf((unsigned long)&(membase[j])); + } + + if (j < NUMMEMWORDS) + return 0; + } + + /* + * see if the rdclt value passed + */ + if (i < NUMMEMTESTS) + return 0; + } + } + + return 1; +} + +static void program_tr1(void) { unsigned long tr0; unsigned long tr1; @@ -1015,8 +1043,7 @@ void program_tr1 (void) unsigned long ecc_temp; unsigned long dlycal; unsigned long dly_val; - unsigned long i, j, k; - unsigned long bxcr_num; + unsigned long k; unsigned long max_pass_length; unsigned long current_pass_length; unsigned long current_fail_length; @@ -1029,7 +1056,6 @@ void program_tr1 (void) unsigned char window_found; unsigned char fail_found; unsigned char pass_found; - unsigned long * membase; PPC440_SYS_INFO sys_info; /* @@ -1079,55 +1105,16 @@ void program_tr1 (void) window_found = FALSE; fail_found = FALSE; pass_found = FALSE; -#ifdef DEBUG - printf("Starting memory test "); -#endif + debug("Starting memory test "); + for (k = 0; k < NUMHALFCYCLES; k++) { - for (rdclt = 0; rdclt < dly_val; rdclt++) { + for (rdclt = 0; rdclt < dly_val; rdclt++) { /* * Set the timing reg for the test. */ mtsdram(mem_tr1, (tr1 | SDRAM_TR1_RDCT_ENCODE(rdclt))); - for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) { - mtdcr(memcfga, mem_b0cr + (bxcr_num<<2)); - if ((mfdcr(memcfgd) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) { - /* Bank is enabled */ - membase = (unsigned long*) - (mfdcr(memcfgd) & SDRAM_BXCR_SDBA_MASK); - - /* - * Run the short memory test - */ - for (i = 0; i < NUMMEMTESTS; i++) { - for (j = 0; j < NUMMEMWORDS; j++) { - membase[j] = test[i][j]; - ppcDcbf((unsigned long)&(membase[j])); - } - - for (j = 0; j < NUMMEMWORDS; j++) { - if (membase[j] != test[i][j]) { - ppcDcbf((unsigned long)&(membase[j])); - break; - } - ppcDcbf((unsigned long)&(membase[j])); - } - - if (j < NUMMEMWORDS) { - break; - } - } - - /* - * see if the rdclt value passed - */ - if (i < NUMMEMTESTS) { - break; - } - } - } - - if (bxcr_num == MAXBXCR) { + if (short_mem_test()) { if (fail_found == TRUE) { pass_found = TRUE; if (current_pass_length == 0) { @@ -1157,9 +1144,8 @@ void program_tr1 (void) } } } -#ifdef DEBUG - printf("."); -#endif + debug("."); + if (window_found == TRUE) { break; } @@ -1167,9 +1153,7 @@ void program_tr1 (void) tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK; rdclt_offset += dly_val; } -#ifdef DEBUG - printf("\n"); -#endif + debug("\n"); /* * make sure we find the window @@ -1218,18 +1202,17 @@ void program_tr1 (void) } tr1 |= SDRAM_TR1_RDCT_ENCODE(rdclt_average); -#if 0 - printf("tr1: %x\n", tr1); -#endif + debug("tr1: %x\n", tr1); + /* * program SDRAM Timing Register 1 TR1 */ mtsdram(mem_tr1, tr1); } -unsigned long program_bxcr(unsigned long* dimm_populated, - unsigned char* iic0_dimm_addr, - unsigned long num_dimm_banks) +static unsigned long program_bxcr(unsigned long *dimm_populated, + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks) { unsigned long dimm_num; unsigned long bank_base_addr; @@ -1262,8 +1245,8 @@ unsigned long program_bxcr(unsigned long* dimm_populated, #ifdef CONFIG_BAMBOO /* * This next section is hardware dependent and must be programmed - * to match the hardware. For bammboo, the following holds... - * 1. SDRAM0_B0CR: Bank 0 of dimm 0 ctrl_bank_num : 0 + * to match the hardware. For bamboo, the following holds... + * 1. SDRAM0_B0CR: Bank 0 of dimm 0 ctrl_bank_num : 0 (soldered onboard) * 2. SDRAM0_B1CR: Bank 0 of dimm 1 ctrl_bank_num : 1 * 3. SDRAM0_B2CR: Bank 1 of dimm 1 ctrl_bank_num : 1 * 4. SDRAM0_B3CR: Bank 0 of dimm 2 ctrl_bank_num : 3 @@ -1273,10 +1256,12 @@ unsigned long program_bxcr(unsigned long* dimm_populated, ctrl_bank_num[1] = 1; ctrl_bank_num[2] = 3; #else + /* + * Ocotea, Ebony and the other IBM/AMCC eval boards have + * 2 DIMM slots with each max 2 banks + */ ctrl_bank_num[0] = 0; - ctrl_bank_num[1] = 1; - ctrl_bank_num[2] = 2; - ctrl_bank_num[3] = 3; + ctrl_bank_num[1] = 2; #endif /* @@ -1290,6 +1275,8 @@ unsigned long program_bxcr(unsigned long* dimm_populated, num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4); num_banks = spd_read(iic0_dimm_addr[dimm_num], 5); bank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31); + debug("DIMM%d: row=%d col=%d banks=%d\n", dimm_num, + num_row_addr, num_col_addr, num_banks); /* * Set the SDRAM0_BxCR regs @@ -1354,9 +1341,12 @@ unsigned long program_bxcr(unsigned long* dimm_populated, cr |= SDRAM_BXCR_SDBE; for (i = 0; i < num_banks; i++) { - bank_parms[ctrl_bank_num[dimm_num]+i+dimm_num].bank_size_bytes = - (4 * 1024 * 1024) * bank_size_id; - bank_parms[ctrl_bank_num[dimm_num]+i+dimm_num].cr = cr; + bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes = + (4 << 20) * bank_size_id; + bank_parms[ctrl_bank_num[dimm_num]+i].cr = cr; + debug("DIMM%d-bank %d (SDRAM0_B%dCR): bank_size_bytes=%d\n", + dimm_num, i, ctrl_bank_num[dimm_num]+i, + bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes); } } } @@ -1400,13 +1390,15 @@ unsigned long program_bxcr(unsigned long* dimm_populated, bank_parms[sorted_bank_num[bx_cr_num]].cr; mtdcr(memcfgd, temp); bank_base_addr += bank_parms[sorted_bank_num[bx_cr_num]].bank_size_bytes; + debug("SDRAM0_B%dCR=0x%08lx\n", sorted_bank_num[bx_cr_num], temp); } } return(bank_base_addr); } -void program_ecc (unsigned long num_bytes) +#ifdef CONFIG_DDR_ECC +static void program_ecc(unsigned long num_bytes) { unsigned long bank_base_addr; unsigned long current_address; @@ -1425,14 +1417,12 @@ void program_ecc (unsigned long num_bytes) bank_base_addr = CFG_SDRAM_BASE; if ((cfg0 & SDRAM_CFG0_MCHK_MASK) != SDRAM_CFG0_MCHK_NON) { - mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | - SDRAM_CFG0_MCHK_GEN); + mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_GEN); - if ((cfg0 & SDRAM_CFG0_DMWD_MASK) == SDRAM_CFG0_DMWD_32) { + if ((cfg0 & SDRAM_CFG0_DMWD_MASK) == SDRAM_CFG0_DMWD_32) address_increment = 4; - } else { + else address_increment = 8; - } current_address = (unsigned long)(bank_base_addr); end_address = (unsigned long)(bank_base_addr) + num_bytes; @@ -1446,4 +1436,5 @@ void program_ecc (unsigned long num_bytes) SDRAM_CFG0_MCHK_CHK); } } +#endif /* CONFIG_DDR_ECC */ #endif /* CONFIG_SPD_EEPROM */ -- cgit v1.2.1