X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=cpu%2Fppc4xx%2F44x_spd_ddr2.c;h=e19929437e2d4d0c389ada193fa64274da40c6be;hb=85dc2a7f82d11e17f0ca2a448118aed7f7a4b85d;hp=6cff3a2e1a96fbf101185753766efc4019f92a36;hpb=eb41db6d22cbaec87bd33aea8dc014614da42235;p=oweals%2Fu-boot.git diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c index 6cff3a2e1a..e19929437e 100644 --- a/cpu/ppc4xx/44x_spd_ddr2.c +++ b/cpu/ppc4xx/44x_spd_ddr2.c @@ -34,6 +34,7 @@ #endif #include +#include #include #include #include @@ -43,19 +44,22 @@ #if defined(CONFIG_SPD_EEPROM) && \ (defined(CONFIG_440SP) || defined(CONFIG_440SPE)) +/*-----------------------------------------------------------------------------+ + * Defines + *-----------------------------------------------------------------------------*/ #ifndef TRUE -#define TRUE 1 +#define TRUE 1 #endif #ifndef FALSE -#define FALSE 0 +#define FALSE 0 #endif #define SDRAM_DDR1 1 #define SDRAM_DDR2 2 #define SDRAM_NONE 0 -#define MAXDIMMS 2 -#define MAXRANKS 4 +#define MAXDIMMS 2 +#define MAXRANKS 4 #define MAXBXCF 4 #define MAX_SPD_BYTES 256 /* Max number of bytes on the DIMM's SPD EEPROM */ @@ -63,16 +67,97 @@ #define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d)) -#if defined(DEBUG) -static void ppc440sp_sdram_register_dump(void); -#endif +#define CMD_NOP (7 << 19) +#define CMD_PRECHARGE (2 << 19) +#define CMD_REFRESH (1 << 19) +#define CMD_EMR (0 << 19) +#define CMD_READ (5 << 19) +#define CMD_WRITE (4 << 19) + +#define SELECT_MR (0 << 16) +#define SELECT_EMR (1 << 16) +#define SELECT_EMR2 (2 << 16) +#define SELECT_EMR3 (3 << 16) + +/* MR */ +#define DLL_RESET 0x00000100 + +#define WRITE_RECOV_2 (1 << 9) +#define WRITE_RECOV_3 (2 << 9) +#define WRITE_RECOV_4 (3 << 9) +#define WRITE_RECOV_5 (4 << 9) +#define WRITE_RECOV_6 (5 << 9) + +#define BURST_LEN_4 0x00000002 + +/* EMR */ +#define ODT_0_OHM 0x00000000 +#define ODT_50_OHM 0x00000044 +#define ODT_75_OHM 0x00000004 +#define ODT_150_OHM 0x00000040 + +#define ODS_FULL 0x00000000 +#define ODS_REDUCED 0x00000002 + +/* defines for ODT (On Die Termination) of the 440SP(e) DDR2 controller */ +#define ODT_EB0R (0x80000000 >> 8) +#define ODT_EB0W (0x80000000 >> 7) +#define CALC_ODT_R(n) (ODT_EB0R << (n << 1)) +#define CALC_ODT_W(n) (ODT_EB0W << (n << 1)) +#define CALC_ODT_RW(n) (CALC_ODT_R(n) | CALC_ODT_W(n)) -/*-----------------------------------------------------------------------------+ - * Defines - *-----------------------------------------------------------------------------*/ /* Defines for the Read Cycle Delay test */ -#define NUMMEMTESTS 8 -#define NUMMEMWORDS 8 +#define NUMMEMTESTS 8 +#define NUMMEMWORDS 8 +#define NUMLOOPS 64 /* memory test loops */ + +#undef CONFIG_ECC_ERROR_RESET /* test-only: see description below, at check_ecc() */ + +/* + * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory + * region. Right now the cache should still be disabled in U-Boot because of the + * EMAC driver, that need it's buffer descriptor to be located in non cached + * memory. + * + * If at some time this restriction doesn't apply anymore, just define + * CONFIG_4xx_DCACHE in the board config file and this code should setup + * everything correctly. + */ +#ifdef CONFIG_4xx_DCACHE +#define MY_TLB_WORD2_I_ENABLE 0 /* enable caching on SDRAM */ +#else +#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */ +#endif + +/* + * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed + */ +void __spd_ddr_init_hang (void) +{ + hang (); +} +void spd_ddr_init_hang (void) __attribute__((weak, alias("__spd_ddr_init_hang"))); + +/* + * To provide an interface for board specific config values in this common + * DDR setup code, we implement he "weak" default functions here. They return + * the default value back to the caller. + * + * Please see include/configs/yucca.h for an example fora board specific + * implementation. + */ +u32 __ddr_wrdtr(u32 default_val) +{ + return default_val; +} +u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr"))); + +u32 __ddr_clktr(u32 default_val) +{ + return default_val; +} +u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr"))); + /* Private Structure Definitions */ @@ -89,7 +174,6 @@ typedef enum ddr_cas_id { * Prototypes *-----------------------------------------------------------------------------*/ static unsigned long sdram_memsize(void); -void program_tlb(u32 start, u32 size); static void get_spd_info(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks); @@ -114,7 +198,8 @@ static void program_codt(unsigned long *dimm_populated, static void program_mode(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks, - ddr_cas_id_t *selected_cas); + ddr_cas_id_t *selected_cas, + int *write_recovery); static void program_tr(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks); @@ -130,22 +215,30 @@ static void program_copt1(unsigned long *dimm_populated, static void program_initplr(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks, - ddr_cas_id_t selected_cas); + 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 num_dimm_banks, + unsigned long tlb_word2_i_value); static void program_ecc_addr(unsigned long start_address, - unsigned long num_bytes); - -#ifdef HARD_CODED_DQS /* calibration test with hardvalues */ -static void test(void); -#else -static void DQS_calibration_process(void); + unsigned long num_bytes, + unsigned long tlb_word2_i_value); #endif static void program_DQS_calibration(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks); +#ifdef HARD_CODED_DQS /* calibration test with hardvalues */ +static void test(void); +#else +static void DQS_calibration_process(void); +#endif +static void ppc440sp_sdram_register_dump(void); +int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +void dcbz_area(u32 start_address, u32 num_bytes); +void dflush(void); static u32 mfdcr_any(u32 dcr) { @@ -192,15 +285,6 @@ static void mtdcr_any(u32 dcr, u32 val) } } -static void wait_ddr_idle(void) -{ - u32 val; - - do { - mfsdram(SDRAM_MCSTAT, val); - } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT); -} - static unsigned char spd_read(uchar chip, uint addr) { unsigned char data[2]; @@ -235,7 +319,7 @@ static unsigned long sdram_memsize(void) && ((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 < 4; i++) { + 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) { @@ -291,23 +375,24 @@ static unsigned long sdram_memsize(void) * .data sections. It also cannot call routines that require these sections. *-----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- - * Function: initdram + * Function: initdram * Description: Configures SDRAM memory banks for DDR operation. - * Auto Memory Configuration option reads the DDR SDRAM EEPROMs - * via the IIC bus and then configures the DDR SDRAM memory - * banks appropriately. If Auto Memory Configuration is - * not used, it is assumed that no DIMM is plugged + * Auto Memory Configuration option reads the DDR SDRAM EEPROMs + * via the IIC bus and then configures the DDR SDRAM memory + * banks appropriately. If Auto Memory Configuration is + * not used, it is assumed that no DIMM is plugged *-----------------------------------------------------------------------------*/ long int initdram(int board_type) { + unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; unsigned char spd0[MAX_SPD_BYTES]; unsigned char spd1[MAX_SPD_BYTES]; unsigned char *dimm_spd[MAXDIMMS]; unsigned long dimm_populated[MAXDIMMS]; - unsigned char iic0_dimm_addr[MAXDIMMS]; unsigned long num_dimm_banks; /* on board dimm banks */ unsigned long val; ddr_cas_id_t selected_cas; + int write_recovery; unsigned long dram_size = 0; num_dimm_banks = sizeof(iic0_dimm_addr); @@ -318,16 +403,10 @@ long int initdram(int board_type) dimm_spd[0] = spd0; dimm_spd[1] = spd1; - /*------------------------------------------------------------------ - * Set up an array of iic0 dimm addresses. - *-----------------------------------------------------------------*/ - iic0_dimm_addr[0] = IIC0_DIMM0_ADDR; - iic0_dimm_addr[1] = IIC0_DIMM1_ADDR; - /*------------------------------------------------------------------ * Reset the DDR-SDRAM controller. *-----------------------------------------------------------------*/ - mtsdr(SDR0_SRST, 0x00200000); + mtsdr(SDR0_SRST, (0x80000000 >> 10)); mtsdr(SDR0_SRST, 0x00000000); /* @@ -399,20 +478,22 @@ long int initdram(int board_type) /*------------------------------------------------------------------ * Program SDRAM mode register. *-----------------------------------------------------------------*/ - program_mode(dimm_populated, iic0_dimm_addr, num_dimm_banks, &selected_cas); + program_mode(dimm_populated, iic0_dimm_addr, num_dimm_banks, + &selected_cas, &write_recovery); /*------------------------------------------------------------------ * Set the SDRAM Write Data/DM/DQS Clock Timing Reg *-----------------------------------------------------------------*/ mfsdram(SDRAM_WRDTR, val); mtsdram(SDRAM_WRDTR, (val & ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) | - (SDRAM_WRDTR_LLWP_1_CYC | SDRAM_WRDTR_WTR_90_DEG_ADV)); + ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | SDRAM_WRDTR_WTR_90_DEG_ADV)); /*------------------------------------------------------------------ * Set the SDRAM Clock Timing Register *-----------------------------------------------------------------*/ mfsdram(SDRAM_CLKTR, val); - mtsdram(SDRAM_CLKTR, (val & ~SDRAM_CLKTR_CLKP_MASK) | SDRAM_CLKTR_CLKP_0_DEG); + mtsdram(SDRAM_CLKTR, (val & ~SDRAM_CLKTR_CLKP_MASK) | + ddr_clktr(SDRAM_CLKTR_CLKP_0_DEG)); /*------------------------------------------------------------------ * Program the BxCF registers. @@ -432,13 +513,13 @@ long int initdram(int board_type) (val & ~(SDRAM_MEMODE_DIC_MASK | SDRAM_MEMODE_DLL_MASK | SDRAM_MEMODE_RTT_MASK | SDRAM_MEMODE_DQS_MASK)) | (SDRAM_MEMODE_DIC_NORMAL | SDRAM_MEMODE_DLL_ENABLE - | SDRAM_MEMODE_RTT_75OHM | SDRAM_MEMODE_DQS_ENABLE)); + | SDRAM_MEMODE_RTT_150OHM | SDRAM_MEMODE_DQS_ENABLE)); /*------------------------------------------------------------------ * Program Initialization preload registers. *-----------------------------------------------------------------*/ program_initplr(dimm_populated, iic0_dimm_addr, num_dimm_banks, - selected_cas); + selected_cas, write_recovery); /*------------------------------------------------------------------ * Delay to ensure 200usec have elapsed since reset. @@ -471,24 +552,35 @@ long int initdram(int board_type) dram_size = sdram_memsize(); /* and program tlb entries for this size (dynamic) */ - program_tlb(0, dram_size); -#if 1 /* TODO: ECC support will come later */ - /*------------------------------------------------------------------ - * If ecc is enabled, initialize the parity bits. - *-----------------------------------------------------------------*/ - program_ecc(dimm_populated, iic0_dimm_addr, num_dimm_banks); -#endif + /* + * Program TLB entries with caches enabled, for best performace + * while auto-calibrating and ECC generation + */ + program_tlb(0, 0, dram_size, 0); /*------------------------------------------------------------------ * DQS calibration. *-----------------------------------------------------------------*/ program_DQS_calibration(dimm_populated, iic0_dimm_addr, num_dimm_banks); -#ifdef DEBUG - ppc440sp_sdram_register_dump(); +#ifdef CONFIG_DDR_ECC + /*------------------------------------------------------------------ + * If ecc is enabled, initialize the parity bits. + *-----------------------------------------------------------------*/ + program_ecc(dimm_populated, iic0_dimm_addr, num_dimm_banks, 0); #endif + /* + * Now after initialization (auto-calibration and ECC generation) + * remove the TLB entries with caches enabled and program again with + * desired cache functionality + */ + remove_tlb(0, dram_size); + program_tlb(0, 0, dram_size, MY_TLB_WORD2_I_ENABLE); + + ppc440sp_sdram_register_dump(); + return dram_size; } @@ -525,19 +617,30 @@ static void get_spd_info(unsigned long *dimm_populated, if (dimm_found == FALSE) { printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); } } -#ifdef CONFIG_ADD_RAM_INFO void board_add_ram_info(int use_default) { - if (is_ecc_enabled()) - puts(" (ECC enabled)"); - else - puts(" (ECC not enabled)"); + 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); } -#endif /*------------------------------------------------------------------ * For the memory DIMMs installed, this routine verifies that they @@ -559,42 +662,42 @@ static void check_mem_type(unsigned long *dimm_populated, "slot %d.\n", (unsigned int)dimm_num); printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); break; case 2: printf("ERROR: EDO DIMM detected in slot %d.\n", (unsigned int)dimm_num); printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); break; case 3: printf("ERROR: Pipelined Nibble DIMM detected in slot %d.\n", (unsigned int)dimm_num); printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); break; case 4: printf("ERROR: SDRAM DIMM detected in slot %d.\n", (unsigned int)dimm_num); printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); break; case 5: printf("ERROR: Multiplexed ROM DIMM detected in slot %d.\n", (unsigned int)dimm_num); printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); break; case 6: printf("ERROR: SGRAM DIMM detected in slot %d.\n", (unsigned int)dimm_num); printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); break; case 7: debug("DIMM slot %d: DDR1 SDRAM detected\n", dimm_num); @@ -609,7 +712,7 @@ static void check_mem_type(unsigned long *dimm_populated, (unsigned int)dimm_num); printf("Only DDR1 and DDR2 SDRAM DIMMs are supported.\n"); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); break; } } @@ -619,7 +722,7 @@ static void check_mem_type(unsigned long *dimm_populated, && (dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_populated[dimm_num-1] != dimm_populated[dimm_num])) { printf("ERROR: DIMM's DDR1 and DDR2 type can not be mixed.\n"); - hang(); + spd_ddr_init_hang (); } } } @@ -638,14 +741,14 @@ static void check_frequency(unsigned long *dimm_populated, unsigned long calc_cycle_time; unsigned long sdram_freq; unsigned long sdr_ddrpll; - PPC440_SYS_INFO board_cfg; + PPC4xx_SYS_INFO board_cfg; /*------------------------------------------------------------------ * Get the board configuration info. *-----------------------------------------------------------------*/ get_sys_info(&board_cfg); - mfsdr(sdr_ddr0, sdr_ddrpll); + mfsdr(SDR0_DDR0, sdr_ddrpll); sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); /* @@ -679,6 +782,7 @@ static void check_frequency(unsigned long *dimm_populated, else cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + ((tcyc_reg & 0x0F)*10); + debug("cycle_time=%d [10 picoseconds]\n", cycle_time); if (cycle_time > (calc_cycle_time + 10)) { /* @@ -693,7 +797,7 @@ static void check_frequency(unsigned long *dimm_populated, (unsigned int)(calc_cycle_time*10)); printf("Replace the DIMM, or change DDR frequency via " "strapping bits.\n\n"); - hang(); + spd_ddr_init_hang (); } } } @@ -725,7 +829,7 @@ static void check_rank_number(unsigned long *dimm_populated, "slot %d is not supported.\n", dimm_rank, dimm_num); printf("Only %d ranks are supported for all DIMM.\n", MAXRANKS); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); } else total_rank += dimm_rank; } @@ -734,7 +838,7 @@ static void check_rank_number(unsigned long *dimm_populated, "for all slots.\n", (unsigned int)total_rank); printf("Only %d ranks are supported for all DIMM.\n", MAXRANKS); printf("Remove one of the DIMM modules.\n\n"); - hang(); + spd_ddr_init_hang (); } } } @@ -759,28 +863,28 @@ static void check_voltage_type(unsigned long *dimm_populated, printf("This DIMM is 5.0 Volt/TTL.\n"); printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", (unsigned int)dimm_num); - hang(); + spd_ddr_init_hang (); break; case 0x01: printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); printf("This DIMM is LVTTL.\n"); printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", (unsigned int)dimm_num); - hang(); + spd_ddr_init_hang (); break; case 0x02: printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); printf("This DIMM is 1.5 Volt.\n"); printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", (unsigned int)dimm_num); - hang(); + spd_ddr_init_hang (); break; case 0x03: printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); printf("This DIMM is 3.3 Volt/TTL.\n"); printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", (unsigned int)dimm_num); - hang(); + spd_ddr_init_hang (); break; case 0x04: /* 2.5 Voltage only for DDR1 */ @@ -792,7 +896,7 @@ static void check_voltage_type(unsigned long *dimm_populated, printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", (unsigned int)dimm_num); - hang(); + spd_ddr_init_hang (); break; } } @@ -820,7 +924,11 @@ static void program_copt1(unsigned long *dimm_populated, unsigned long ddrtype; unsigned long val; +#ifdef CONFIG_DDR_ECC ecc_enabled = TRUE; +#else + ecc_enabled = FALSE; +#endif dimm_32bit = FALSE; dimm_64bit = FALSE; buf0 = FALSE; @@ -931,13 +1039,13 @@ static void program_copt1(unsigned long *dimm_populated, if ((dimm_populated[0] != SDRAM_NONE) && (dimm_populated[1] != SDRAM_NONE)) { if (buf0 != buf1) { printf("ERROR: DIMM's buffered/unbuffered, registered, clocking don't match.\n"); - hang(); + spd_ddr_init_hang (); } } if ((dimm_64bit == TRUE) && (dimm_32bit == TRUE)) { printf("ERROR: Cannot mix 32 bit and 64 bit DDR-SDRAM DIMMs together.\n"); - hang(); + spd_ddr_init_hang (); } else if ((dimm_64bit == TRUE) && (dimm_32bit == FALSE)) { mcopt1 |= SDRAM_MCOPT1_DMWD_64; @@ -945,7 +1053,7 @@ static void program_copt1(unsigned long *dimm_populated, mcopt1 |= SDRAM_MCOPT1_DMWD_32; } else { printf("ERROR: Please install only 32 or 64 bit DDR-SDRAM DIMMs.\n\n"); - hang(); + spd_ddr_init_hang (); } if (ecc_enabled == TRUE) @@ -996,8 +1104,8 @@ static void program_codt(unsigned long *dimm_populated, dimm_type = SDRAM_DDR1; } - total_rank += dimm_rank; - total_dimm ++; + total_rank += dimm_rank; + total_dimm++; if ((dimm_num == 0) && (total_dimm == 1)) firstSlot = TRUE; else @@ -1008,52 +1116,53 @@ static void program_codt(unsigned long *dimm_populated, codt |= SDRAM_CODT_DQS_1_8_V_DDR2; if ((total_dimm == 1) && (firstSlot == TRUE)) { if (total_rank == 1) { - codt |= 0x00800000; - modt0 = 0x01000000; + codt |= CALC_ODT_R(0); + modt0 = CALC_ODT_W(0); modt1 = 0x00000000; modt2 = 0x00000000; modt3 = 0x00000000; } if (total_rank == 2) { - codt |= 0x02800000; - modt0 = 0x06000000; - modt1 = 0x01800000; + codt |= CALC_ODT_R(0) | CALC_ODT_R(1); + modt0 = CALC_ODT_W(0); + modt1 = CALC_ODT_W(0); modt2 = 0x00000000; modt3 = 0x00000000; } - } else { + } else if ((total_dimm == 1) && (firstSlot != TRUE)) { if (total_rank == 1) { - codt |= 0x00800000; - modt0 = 0x01000000; + codt |= CALC_ODT_R(2); + modt0 = 0x00000000; modt1 = 0x00000000; - modt2 = 0x00000000; + modt2 = CALC_ODT_W(2); modt3 = 0x00000000; } if (total_rank == 2) { - codt |= 0x02800000; - modt0 = 0x06000000; - modt1 = 0x01800000; - modt2 = 0x00000000; - modt3 = 0x00000000; + codt |= CALC_ODT_R(2) | CALC_ODT_R(3); + modt0 = 0x00000000; + modt1 = 0x00000000; + modt2 = CALC_ODT_W(2); + modt3 = CALC_ODT_W(2); } } if (total_dimm == 2) { if (total_rank == 2) { - codt |= 0x08800000; - modt0 = 0x18000000; + codt |= CALC_ODT_R(0) | CALC_ODT_R(2); + modt0 = CALC_ODT_RW(2); modt1 = 0x00000000; - modt2 = 0x01800000; + modt2 = CALC_ODT_RW(0); modt3 = 0x00000000; } if (total_rank == 4) { - codt |= 0x2a800000; - modt0 = 0x18000000; - modt1 = 0x18000000; - modt2 = 0x01800000; - modt3 = 0x01800000; + codt |= CALC_ODT_R(0) | CALC_ODT_R(1) | + CALC_ODT_R(2) | CALC_ODT_R(3); + modt0 = CALC_ODT_RW(2); + modt1 = 0x00000000; + modt2 = CALC_ODT_RW(0); + modt3 = 0x00000000; } } - } else { + } else { codt |= SDRAM_CODT_DQS_2_5_V_DDR1; modt0 = 0x00000000; modt1 = 0x00000000; @@ -1092,13 +1201,23 @@ static void program_codt(unsigned long *dimm_populated, static void program_initplr(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks, - ddr_cas_id_t selected_cas) + ddr_cas_id_t selected_cas, + int write_recovery) { - unsigned long MR_CAS_value = 0; + u32 cas = 0; + u32 odt = 0; + u32 ods = 0; + u32 mr; + u32 wr; + u32 emr; + u32 emr2; + u32 emr3; + int dimm_num; + int total_dimm = 0; /****************************************************** ** Assumption: if more than one DIMM, all DIMMs are the same - ** as already checked in check_memory_type + ** as already checked in check_memory_type ******************************************************/ if ((dimm_populated[0] == SDRAM_DDR1) || (dimm_populated[1] == SDRAM_DDR1)) { @@ -1112,44 +1231,93 @@ static void program_initplr(unsigned long *dimm_populated, mtsdram(SDRAM_INITPLR7, 0x81000062); } else if ((dimm_populated[0] == SDRAM_DDR2) || (dimm_populated[1] == SDRAM_DDR2)) { switch (selected_cas) { - /* - * The CAS latency is a field of the Mode Reg - * that need to be set from caller input. - * CAS bits in Mode Reg are starting at bit 4 at least for the Micron DDR2 - * this is the reason of the shift. - */ case DDR_CAS_3: - MR_CAS_value = 3 << 4; + cas = 3 << 4; break; case DDR_CAS_4: - MR_CAS_value = 4 << 4; + cas = 4 << 4; break; case DDR_CAS_5: - MR_CAS_value = 5 << 4; + cas = 5 << 4; + break; + default: + printf("ERROR: ucode error on selected_cas value %d", selected_cas); + spd_ddr_init_hang (); + break; + } + +#if 0 + /* + * ToDo - Still a problem with the write recovery: + * On the Corsair CM2X512-5400C4 module, setting write recovery + * in the INITPLR reg to the value calculated in program_mode() + * results in not correctly working DDR2 memory (crash after + * relocation). + * + * So for now, set the write recovery to 3. This seems to work + * on the Corair module too. + * + * 2007-03-01, sr + */ + switch (write_recovery) { + case 3: + wr = WRITE_RECOV_3; + break; + case 4: + wr = WRITE_RECOV_4; + break; + case 5: + wr = WRITE_RECOV_5; + break; + case 6: + wr = WRITE_RECOV_6; break; default: - printf("ERROR: ucode error on selected_cas value %d", (unsigned char)selected_cas); - hang(); + printf("ERROR: write recovery not support (%d)", write_recovery); + spd_ddr_init_hang (); break; } +#else + wr = WRITE_RECOV_3; /* test-only, see description above */ +#endif + + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) + if (dimm_populated[dimm_num] != SDRAM_NONE) + total_dimm++; + if (total_dimm == 1) { + odt = ODT_150_OHM; + ods = ODS_FULL; + } else if (total_dimm == 2) { + odt = ODT_75_OHM; + ods = ODS_REDUCED; + } else { + printf("ERROR: Unsupported number of DIMM's (%d)", total_dimm); + spd_ddr_init_hang (); + } - mtsdram(SDRAM_INITPLR0, 0xB5380000); /* NOP */ - mtsdram(SDRAM_INITPLR1, 0x82100400); /* precharge 8 DDR clock cycle */ - mtsdram(SDRAM_INITPLR2, 0x80820000); /* EMR2 */ - mtsdram(SDRAM_INITPLR3, 0x80830000); /* EMR3 */ - mtsdram(SDRAM_INITPLR4, 0x80810000); /* EMR DLL ENABLE */ - mtsdram(SDRAM_INITPLR5, 0x80800502 | MR_CAS_value); /* MR w/ DLL reset */ - mtsdram(SDRAM_INITPLR6, 0x82100400); /* precharge 8 DDR clock cycle */ - mtsdram(SDRAM_INITPLR7, 0x8a080000); /* Refresh 50 DDR clock cycle */ - mtsdram(SDRAM_INITPLR8, 0x8a080000); /* Refresh 50 DDR clock cycle */ - mtsdram(SDRAM_INITPLR9, 0x8a080000); /* Refresh 50 DDR clock cycle */ - mtsdram(SDRAM_INITPLR10, 0x8a080000); /* Refresh 50 DDR clock cycle */ - mtsdram(SDRAM_INITPLR11, 0x80800402 | MR_CAS_value); /* MR w/o DLL reset */ - mtsdram(SDRAM_INITPLR12, 0x80810380); /* EMR OCD Default */ - mtsdram(SDRAM_INITPLR13, 0x80810000); /* EMR OCD Exit */ + mr = CMD_EMR | SELECT_MR | BURST_LEN_4 | wr | cas; + emr = CMD_EMR | SELECT_EMR | odt | ods; + emr2 = CMD_EMR | SELECT_EMR2; + emr3 = CMD_EMR | SELECT_EMR3; + mtsdram(SDRAM_INITPLR0, 0xB5000000 | CMD_NOP); /* NOP */ + udelay(1000); + mtsdram(SDRAM_INITPLR1, 0x82000400 | CMD_PRECHARGE); /* precharge 8 DDR clock cycle */ + mtsdram(SDRAM_INITPLR2, 0x80800000 | emr2); /* EMR2 */ + mtsdram(SDRAM_INITPLR3, 0x80800000 | emr3); /* EMR3 */ + mtsdram(SDRAM_INITPLR4, 0x80800000 | emr); /* EMR DLL ENABLE */ + mtsdram(SDRAM_INITPLR5, 0x80800000 | mr | DLL_RESET); /* MR w/ DLL reset */ + udelay(1000); + mtsdram(SDRAM_INITPLR6, 0x82000400 | CMD_PRECHARGE); /* precharge 8 DDR clock cycle */ + mtsdram(SDRAM_INITPLR7, 0x8a000000 | CMD_REFRESH); /* Refresh 50 DDR clock cycle */ + mtsdram(SDRAM_INITPLR8, 0x8a000000 | CMD_REFRESH); /* Refresh 50 DDR clock cycle */ + mtsdram(SDRAM_INITPLR9, 0x8a000000 | CMD_REFRESH); /* Refresh 50 DDR clock cycle */ + mtsdram(SDRAM_INITPLR10, 0x8a000000 | CMD_REFRESH); /* Refresh 50 DDR clock cycle */ + mtsdram(SDRAM_INITPLR11, 0x80000000 | mr); /* MR w/o DLL reset */ + mtsdram(SDRAM_INITPLR12, 0x80800380 | emr); /* EMR OCD Default */ + mtsdram(SDRAM_INITPLR13, 0x80800000 | emr); /* EMR OCD Exit */ } else { printf("ERROR: ucode error as unknown DDR type in program_initplr"); - hang(); + spd_ddr_init_hang (); } } @@ -1161,7 +1329,8 @@ static void program_initplr(unsigned long *dimm_populated, static void program_mode(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks, - ddr_cas_id_t *selected_cas) + ddr_cas_id_t *selected_cas, + int *write_recovery) { unsigned long dimm_num; unsigned long sdram_ddr1; @@ -1184,7 +1353,7 @@ static void program_mode(unsigned long *dimm_populated, unsigned long max_4_0_tcyc_ns_x_100; unsigned long max_5_0_tcyc_ns_x_100; unsigned long cycle_time_ns_x_100[3]; - PPC440_SYS_INFO board_cfg; + PPC4xx_SYS_INFO board_cfg; unsigned char cas_2_0_available; unsigned char cas_2_5_available; unsigned char cas_3_0_available; @@ -1197,8 +1366,9 @@ static void program_mode(unsigned long *dimm_populated, *-----------------------------------------------------------------*/ get_sys_info(&board_cfg); - mfsdr(sdr_ddr0, sdr_ddrpll); + mfsdr(SDR0_DDR0, sdr_ddrpll); sdram_freq = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(sdr_ddrpll), 1); + debug("sdram_freq=%d\n", sdram_freq); /*------------------------------------------------------------------ * Handle the timing. We need to find the worst case timing of all @@ -1228,6 +1398,7 @@ static void program_mode(unsigned long *dimm_populated, /* t_wr_ns = max(t_wr_ns, (unsigned long)dimm_spd[dimm_num][36] >> 2); */ /* not used in this loop. */ cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18); + debug("cas_bit[SPD byte 18]=%02x\n", cas_bit); /* For a particular DIMM, grab the three CAS values it supports */ for (cas_index = 0; cas_index < 3; cas_index++) { @@ -1246,17 +1417,21 @@ static void program_mode(unsigned long *dimm_populated, if ((tcyc_reg & 0x0F) >= 10) { if ((tcyc_reg & 0x0F) == 0x0D) { /* Convert from hex to decimal */ - cycle_time_ns_x_100[cas_index] = (((tcyc_reg & 0xF0) >> 4) * 100) + 75; + cycle_time_ns_x_100[cas_index] = + (((tcyc_reg & 0xF0) >> 4) * 100) + 75; } else { printf("ERROR: SPD reported Tcyc is incorrect for DIMM " "in slot %d\n", (unsigned int)dimm_num); - hang(); + spd_ddr_init_hang (); } } else { /* Convert from hex to decimal */ - cycle_time_ns_x_100[cas_index] = (((tcyc_reg & 0xF0) >> 4) * 100) + + cycle_time_ns_x_100[cas_index] = + (((tcyc_reg & 0xF0) >> 4) * 100) + ((tcyc_reg & 0x0F)*10); } + debug("cas_index=%d: cycle_time_ns_x_100=%d\n", cas_index, + cycle_time_ns_x_100[cas_index]); } /* The rest of this routine determines if CAS 2.0, 2.5, 3.0, 4.0 and 5.0 are */ @@ -1269,8 +1444,10 @@ static void program_mode(unsigned long *dimm_populated, * Bit 7 6 5 4 3 2 1 0 * TBD 4.0 3.5 3.0 2.5 2.0 1.5 1.0 */ - if (((cas_bit & 0x40) == 0x40) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { - max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); + if (((cas_bit & 0x40) == 0x40) && (cas_index < 3) && + (cycle_time_ns_x_100[cas_index] != 0)) { + max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, + cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) @@ -1278,8 +1455,10 @@ static void program_mode(unsigned long *dimm_populated, cas_4_0_available = FALSE; } - if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { - max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); + if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && + (cycle_time_ns_x_100[cas_index] != 0)) { + max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, + cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) @@ -1287,8 +1466,10 @@ static void program_mode(unsigned long *dimm_populated, cas_3_0_available = FALSE; } - if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { - max_2_5_tcyc_ns_x_100 = max(max_2_5_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); + if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && + (cycle_time_ns_x_100[cas_index] != 0)) { + max_2_5_tcyc_ns_x_100 = max(max_2_5_tcyc_ns_x_100, + cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) @@ -1296,8 +1477,10 @@ static void program_mode(unsigned long *dimm_populated, cas_2_5_available = FALSE; } - if (((cas_bit & 0x04) == 0x04) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { - max_2_0_tcyc_ns_x_100 = max(max_2_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); + if (((cas_bit & 0x04) == 0x04) && (cas_index < 3) && + (cycle_time_ns_x_100[cas_index] != 0)) { + max_2_0_tcyc_ns_x_100 = max(max_2_0_tcyc_ns_x_100, + cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) @@ -1310,8 +1493,10 @@ static void program_mode(unsigned long *dimm_populated, * Bit 7 6 5 4 3 2 1 0 * TBD 6.0 5.0 4.0 3.0 2.0 TBD TBD */ - if (((cas_bit & 0x20) == 0x20) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { - max_5_0_tcyc_ns_x_100 = max(max_5_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); + if (((cas_bit & 0x20) == 0x20) && (cas_index < 3) && + (cycle_time_ns_x_100[cas_index] != 0)) { + max_5_0_tcyc_ns_x_100 = max(max_5_0_tcyc_ns_x_100, + cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) @@ -1319,8 +1504,10 @@ static void program_mode(unsigned long *dimm_populated, cas_5_0_available = FALSE; } - if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { - max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); + if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && + (cycle_time_ns_x_100[cas_index] != 0)) { + max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, + cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) @@ -1328,8 +1515,10 @@ static void program_mode(unsigned long *dimm_populated, cas_4_0_available = FALSE; } - if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { - max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); + if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && + (cycle_time_ns_x_100[cas_index] != 0)) { + max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, + cycle_time_ns_x_100[cas_index]); cas_index++; } else { if (cas_index != 0) @@ -1346,11 +1535,15 @@ static void program_mode(unsigned long *dimm_populated, mfsdram(SDRAM_MMODE, mmode); mmode = mmode & ~(SDRAM_MMODE_WR_MASK | SDRAM_MMODE_DCL_MASK); - cycle_2_0_clk = MULDIV64(ONE_BILLION, 100, max_2_0_tcyc_ns_x_100); - cycle_2_5_clk = MULDIV64(ONE_BILLION, 100, max_2_5_tcyc_ns_x_100); - cycle_3_0_clk = MULDIV64(ONE_BILLION, 100, max_3_0_tcyc_ns_x_100); - cycle_4_0_clk = MULDIV64(ONE_BILLION, 100, max_4_0_tcyc_ns_x_100); - cycle_5_0_clk = MULDIV64(ONE_BILLION, 100, max_5_0_tcyc_ns_x_100); + /* add 10 here because of rounding problems */ + cycle_2_0_clk = MULDIV64(ONE_BILLION, 100, max_2_0_tcyc_ns_x_100) + 10; + cycle_2_5_clk = MULDIV64(ONE_BILLION, 100, max_2_5_tcyc_ns_x_100) + 10; + cycle_3_0_clk = MULDIV64(ONE_BILLION, 100, max_3_0_tcyc_ns_x_100) + 10; + cycle_4_0_clk = MULDIV64(ONE_BILLION, 100, max_4_0_tcyc_ns_x_100) + 10; + cycle_5_0_clk = MULDIV64(ONE_BILLION, 100, max_5_0_tcyc_ns_x_100) + 10; + debug("cycle_3_0_clk=%d\n", cycle_3_0_clk); + debug("cycle_4_0_clk=%d\n", cycle_4_0_clk); + debug("cycle_5_0_clk=%d\n", cycle_5_0_clk); if (sdram_ddr1 == TRUE) { /* DDR1 */ if ((cas_2_0_available == TRUE) && (sdram_freq <= cycle_2_0_clk)) { @@ -1366,9 +1559,12 @@ static void program_mode(unsigned long *dimm_populated, printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n"); printf("Only DIMMs DDR1 with CAS latencies of 2.0, 2.5, and 3.0 are supported.\n"); printf("Make sure the PLB speed is within the supported range of the DIMMs.\n\n"); - hang(); + spd_ddr_init_hang (); } } else { /* DDR2 */ + debug("cas_3_0_available=%d\n", cas_3_0_available); + debug("cas_4_0_available=%d\n", cas_4_0_available); + debug("cas_5_0_available=%d\n", cas_5_0_available); if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) { mmode |= SDRAM_MMODE_DCL_DDR2_3_0_CLK; *selected_cas = DDR_CAS_3; @@ -1381,8 +1577,12 @@ static void program_mode(unsigned long *dimm_populated, } else { printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n"); printf("Only DIMMs DDR2 with CAS latencies of 3.0, 4.0, and 5.0 are supported.\n"); - printf("Make sure the PLB speed is within the supported range of the DIMMs.\n\n"); - hang(); + printf("Make sure the PLB speed is within the supported range of the DIMMs.\n"); + printf("cas3=%d cas4=%d cas5=%d\n", + cas_3_0_available, cas_4_0_available, cas_5_0_available); + printf("sdram_freq=%d cycle3=%d cycle4=%d cycle5=%d\n\n", + sdram_freq, cycle_3_0_clk, cycle_4_0_clk, cycle_5_0_clk); + spd_ddr_init_hang (); } } @@ -1424,8 +1624,12 @@ static void program_mode(unsigned long *dimm_populated, mmode |= SDRAM_MMODE_WR_DDR2_6_CYC; break; } + *write_recovery = t_wr_clk; } + debug("CAS latency = %d\n", *selected_cas); + debug("Write recovery = %d\n", *write_recovery); + mtsdram(SDRAM_MMODE, mmode); } @@ -1436,7 +1640,7 @@ static void program_rtr(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks) { - PPC440_SYS_INFO board_cfg; + PPC4xx_SYS_INFO board_cfg; unsigned long max_refresh_rate; unsigned long dimm_num; unsigned long refresh_rate_type; @@ -1454,7 +1658,7 @@ static void program_rtr(unsigned long *dimm_populated, /*------------------------------------------------------------------ * Set the SDRAM Refresh Timing Register, SDRAM_RTR *-----------------------------------------------------------------*/ - mfsdr(sdr_ddr0, sdr_ddrpll); + mfsdr(SDR0_DDR0, sdr_ddrpll); sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); max_refresh_rate = 0; @@ -1487,7 +1691,7 @@ static void program_rtr(unsigned long *dimm_populated, printf("ERROR: DIMM %d unsupported refresh rate/type.\n", (unsigned int)dimm_num); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); break; } @@ -1533,14 +1737,14 @@ static void program_tr(unsigned long *dimm_populated, unsigned long sdram_freq; unsigned long sdr_ddrpll; - PPC440_SYS_INFO board_cfg; + PPC4xx_SYS_INFO board_cfg; /*------------------------------------------------------------------ * Get the board configuration info. *-----------------------------------------------------------------*/ get_sys_info(&board_cfg); - mfsdr(sdr_ddr0, sdr_ddrpll); + mfsdr(SDR0_DDR0, sdr_ddrpll); sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); /*------------------------------------------------------------------ @@ -1844,14 +2048,10 @@ static void program_bxcf(unsigned long *dimm_populated, /*------------------------------------------------------------------ * Set the BxCF regs. First, wipe out the bank config registers. *-----------------------------------------------------------------*/ - mtdcr(SDRAMC_CFGADDR, SDRAM_MB0CF); - mtdcr(SDRAMC_CFGDATA, 0x00000000); - mtdcr(SDRAMC_CFGADDR, SDRAM_MB1CF); - mtdcr(SDRAMC_CFGDATA, 0x00000000); - mtdcr(SDRAMC_CFGADDR, SDRAM_MB2CF); - mtdcr(SDRAMC_CFGDATA, 0x00000000); - mtdcr(SDRAMC_CFGADDR, SDRAM_MB3CF); - mtdcr(SDRAMC_CFGDATA, 0x00000000); + mtsdram(SDRAM_MB0CF, 0x00000000); + mtsdram(SDRAM_MB1CF, 0x00000000); + mtsdram(SDRAM_MB2CF, 0x00000000); + mtsdram(SDRAM_MB3CF, 0x00000000); mode = SDRAM_BXCF_M_BE_ENABLE; @@ -1895,7 +2095,7 @@ static void program_bxcf(unsigned long *dimm_populated, printf("ERROR: Unsupported value for number of " "column addresses: %d.\n", (unsigned int)num_col_addr); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); } } @@ -1903,8 +2103,9 @@ static void program_bxcf(unsigned long *dimm_populated, bank_0_populated = 1; for (ind_rank = 0; ind_rank < num_ranks; ind_rank++) { - mtdcr(SDRAMC_CFGADDR, SDRAM_MB0CF + ((dimm_num + bank_0_populated + ind_rank) << 2)); - mtdcr(SDRAMC_CFGDATA, mode); + mtsdram(SDRAM_MB0CF + + ((dimm_num + bank_0_populated + ind_rank) << 2), + mode); } } } @@ -1948,7 +2149,7 @@ static void program_memory_queue(unsigned long *dimm_populated, * Set the sizes *-----------------------------------------------------------------*/ baseadd_size = 0; - rank_size_bytes = 1024 * 1024 * rank_size_id; + rank_size_bytes = 4 * 1024 * 1024 * rank_size_id; switch (rank_size_id) { case 0x02: baseadd_size |= SDRAM_RXBAS_SDSZ_8; @@ -1977,7 +2178,7 @@ static void program_memory_queue(unsigned long *dimm_populated, printf("ERROR: Unsupported value for the banksize: %d.\n", (unsigned int)rank_size_id); printf("Replace the DIMM module with a supported DIMM.\n\n"); - hang(); + spd_ddr_init_hang (); } if ((dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_num == 1)) @@ -1985,8 +2186,8 @@ static void program_memory_queue(unsigned long *dimm_populated, for (i = 0; i < num_ranks; i++) { mtdcr_any(rank_reg+i+dimm_num+bank_0_populated, - (rank_base_addr & SDRAM_RXBAS_SDBA_MASK) | - baseadd_size); + (SDRAM_RXBAS_SDBA_ENCODE(rank_base_addr) | + baseadd_size)); rank_base_addr += rank_size_bytes; } } @@ -2009,15 +2210,29 @@ static unsigned long is_ecc_enabled(void) ecc = max(ecc, SDRAM_MCOPT1_MCHK_CHK_DECODE(val)); } - return(ecc); + return ecc; +} + +static void blank_string(int size) +{ + int i; + + for (i=0; i> 1); + /*------------------------------------------------------------------ * Make sure we found the valid read passing window. Halt if not *-----------------------------------------------------------------*/ if (window_found == FALSE) { - printf("ERROR: Cannot determine a common read delay for the " + if (rqfd_start < SDRAM_RQDC_RQFD_MAX) { + putc('\b'); + putc(slash[loopi++ % 8]); + + /* try again from with a different RQFD start value */ + rqfd_start++; + goto calibration_loop; + } + + printf("\nERROR: Cannot determine a common read delay for the " "DIMM(s) installed.\n"); debug("%s[%d] ERROR : \n", __FUNCTION__,__LINE__); - hang(); + ppc440sp_sdram_register_dump(); + spd_ddr_init_hang (); } - rqfd_average = ((max_start + max_end) >> 1); + blank_string(strlen(str)); if (rqfd_average < 0) rqfd_average = 0; @@ -2435,12 +2735,6 @@ static void DQS_calibration_process(void) if (rqfd_average > SDRAM_RQDC_RQFD_MAX) rqfd_average = SDRAM_RQDC_RQFD_MAX; - /*------------------------------------------------------------------ - * Restore the ECC variable to what it originally was - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_MCOPT1, val); - mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) | ecc_temp); - mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | SDRAM_RQDC_RQFD_ENCODE(rqfd_average)); @@ -2586,7 +2880,7 @@ static void test(void) if (window_found == FALSE) { printf("ERROR: Cannot determine a common read delay for the " "DIMM(s) installed.\n"); - hang(); + spd_ddr_init_hang (); } /*------------------------------------------------------------------ @@ -2755,5 +3049,9 @@ static void ppc440sp_sdram_register_dump(void) dcr_data = mfdcr(SDRAM_R3BAS); printf(" MQ3_B0BAS = 0x%08X\n", dcr_data); } +#else +static void ppc440sp_sdram_register_dump(void) +{ +} #endif #endif /* CONFIG_SPD_EEPROM */