X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=cpu%2Fppc4xx%2F44x_spd_ddr2.c;h=ec76b718bccb1f2b86215259bc16f20f80f9d8fc;hb=d9ee843d54c54776e1fdb86336ce554906a87331;hp=67ba5bdef24f76716ee817e1d7b382c2ce91840f;hpb=b8685affe614ccf5f4ec66252b30e2e524d18948;p=u-boot diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c index 67ba5bdef2..ec76b718bc 100644 --- a/cpu/ppc4xx/44x_spd_ddr2.c +++ b/cpu/ppc4xx/44x_spd_ddr2.c @@ -1,9 +1,12 @@ /* * cpu/ppc4xx/44x_spd_ddr2.c * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a - * DDR2 controller (non Denali Core). Those are 440SP/SPe. + * DDR2 controller (non Denali Core). Those currently are: * - * (C) Copyright 2007 + * 405: 405EX + * 440/460: 440SP/440SPe/460EX/460GT + * + * (C) Copyright 2007-2008 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * COPYRIGHT AMCC CORPORATION 2004 @@ -40,9 +43,11 @@ #include #include #include +#include #if defined(CONFIG_SPD_EEPROM) && \ - (defined(CONFIG_440SP) || defined(CONFIG_440SPE)) + (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_460EX) || defined(CONFIG_460GT)) /*-----------------------------------------------------------------------------+ * Defines @@ -111,8 +116,6 @@ #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 @@ -120,10 +123,10 @@ * memory. * * If at some time this restriction doesn't apply anymore, just define - * CFG_ENABLE_SDRAM_CACHE in the board config file and this code should setup + * CONFIG_4xx_DCACHE in the board config file and this code should setup * everything correctly. */ -#ifdef CFG_ENABLE_SDRAM_CACHE +#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 */ @@ -238,7 +241,6 @@ static void DQS_calibration_process(void); 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) { @@ -389,9 +391,9 @@ long int initdram(int board_type) unsigned char spd1[MAX_SPD_BYTES]; unsigned char *dimm_spd[MAXDIMMS]; unsigned long dimm_populated[MAXDIMMS]; - unsigned long num_dimm_banks; /* on board dimm banks */ + unsigned long num_dimm_banks; /* on board dimm banks */ unsigned long val; - ddr_cas_id_t selected_cas; + ddr_cas_id_t selected_cas = DDR_CAS_5; /* preset to silence compiler */ int write_recovery; unsigned long dram_size = 0; @@ -581,6 +583,13 @@ long int initdram(int board_type) ppc440sp_sdram_register_dump(); + /* + * Clear potential errors resulting from auto-calibration. + * If not done, then we could get an interrupt later on when + * exceptions are enabled. + */ + set_mcsr(get_mcsr()); + return dram_size; } @@ -623,7 +632,7 @@ static void get_spd_info(unsigned long *dimm_populated, void board_add_ram_info(int use_default) { - PPC440_SYS_INFO board_cfg; + PPC4xx_SYS_INFO board_cfg; u32 val; if (is_ecc_enabled()) @@ -741,7 +750,7 @@ 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. @@ -1353,7 +1362,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; @@ -1640,7 +1649,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; @@ -1737,7 +1746,7 @@ 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. @@ -2048,14 +2057,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; @@ -2076,7 +2081,7 @@ static void program_bxcf(unsigned long *dimm_populated, if (num_banks == 4) ind = 0; else - ind = 5; + ind = 5 << 8; switch (num_col_addr) { case 0x08: mode |= (SDRAM_BXCF_M_AM_0 + ind); @@ -2107,8 +2112,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); } } } @@ -2130,6 +2136,7 @@ static void program_memory_queue(unsigned long *dimm_populated, unsigned long baseadd_size; unsigned long i; unsigned long bank_0_populated = 0; + unsigned long total_size = 0; /*------------------------------------------------------------------ * Reset the rank_base_address. @@ -2152,28 +2159,38 @@ static void program_memory_queue(unsigned long *dimm_populated, * Set the sizes *-----------------------------------------------------------------*/ baseadd_size = 0; - rank_size_bytes = 4 * 1024 * 1024 * rank_size_id; switch (rank_size_id) { + case 0x01: + baseadd_size |= SDRAM_RXBAS_SDSZ_1024; + total_size = 1024; + break; case 0x02: - baseadd_size |= SDRAM_RXBAS_SDSZ_8; + baseadd_size |= SDRAM_RXBAS_SDSZ_2048; + total_size = 2048; break; case 0x04: - baseadd_size |= SDRAM_RXBAS_SDSZ_16; + baseadd_size |= SDRAM_RXBAS_SDSZ_4096; + total_size = 4096; break; case 0x08: baseadd_size |= SDRAM_RXBAS_SDSZ_32; + total_size = 32; break; case 0x10: baseadd_size |= SDRAM_RXBAS_SDSZ_64; + total_size = 64; break; case 0x20: baseadd_size |= SDRAM_RXBAS_SDSZ_128; + total_size = 128; break; case 0x40: baseadd_size |= SDRAM_RXBAS_SDSZ_256; + total_size = 256; break; case 0x80: baseadd_size |= SDRAM_RXBAS_SDSZ_512; + total_size = 512; break; default: printf("DDR-SDRAM: DIMM %d memory queue configuration.\n", @@ -2183,6 +2200,7 @@ static void program_memory_queue(unsigned long *dimm_populated, printf("Replace the DIMM module with a supported DIMM.\n\n"); spd_ddr_init_hang (); } + rank_size_bytes = total_size << 20; if ((dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_num == 1)) bank_0_populated = 1; @@ -2195,6 +2213,19 @@ static void program_memory_queue(unsigned long *dimm_populated, } } } + +#if defined(CONFIG_460EX) || defined(CONFIG_460GT) + /* + * Enable high bandwidth access on 460EX/GT. + * This should/could probably be done on other + * PPC's too, like 440SPe. + * This is currently not used, but with this setup + * it is possible to use it later on in e.g. the Linux + * EMAC driver for performance gain. + */ + mtdcr(SDRAM_PLBADDULL, 0x00000000); /* MQ0_BAUL */ + mtdcr(SDRAM_PLBADDUHB, 0x00000008); /* MQ0_BAUH */ +#endif } /*-----------------------------------------------------------------------------+ @@ -2271,39 +2302,6 @@ static void program_ecc(unsigned long *dimm_populated, return; } -#ifdef CONFIG_ECC_ERROR_RESET -/* - * Check for ECC errors and reset board upon any error here - * - * On the Katmai 440SPe eval board, from time to time, the first - * lword write access after DDR2 initializazion with ECC checking - * enabled, leads to an ECC error. I couldn't find a configuration - * without this happening. On my board with the current setup it - * happens about 1 from 10 times. - * - * The ECC modules used for testing are: - * - Kingston ValueRAM KVR667D2E5/512 (tested with 1 and 2 DIMM's) - * - * This has to get fixed for the Katmai and tested for the other - * board (440SP/440SPe) that will eventually use this code in the - * future. - * - * 2007-03-01, sr - */ -static void check_ecc(void) -{ - u32 val; - - mfsdram(SDRAM_ECCCR, val); - if (val != 0) { - printf("\nECC error: MCIF0_ECCES=%08lx MQ0_ESL=%08lx address=%08lx\n", - val, mfdcr(0x4c), mfdcr(0x4e)); - printf("ECC error occured, resetting board...\n"); - do_reset(NULL, 0, 0, NULL); - } -} -#endif - static void wait_ddr_idle(void) { u32 val; @@ -2360,7 +2358,8 @@ static void program_ecc_addr(unsigned long start_address, } else { /* ECC bit set method for cached memory */ dcbz_area(start_address, num_bytes); - dflush(); + /* Write modified dcache lines back to memory */ + clean_dcache_range(start_address, start_address + num_bytes); } blank_string(strlen(str)); @@ -2378,15 +2377,6 @@ static void program_ecc_addr(unsigned long start_address, sync(); eieio(); wait_ddr_idle(); - -#ifdef CONFIG_ECC_ERROR_RESET - /* - * One write to 0 is enough to trigger this ECC error - * (see description above) - */ - out_be32(0, 0x12345678); - check_ecc(); -#endif } } #endif @@ -2412,17 +2402,10 @@ static void program_DQS_calibration(unsigned long *dimm_populated, * Read sample cycle auto-update enable *-----------------------------------------------------------------*/ - /* - * Modified for the Katmai platform: with some DIMMs, the DDR2 - * controller automatically selects the T2 read cycle, but this - * proves unreliable. Go ahead and force the DDR2 controller - * to use the T4 sample and disable the automatic update of the - * RDSS field. - */ mfsdram(SDRAM_RDCC, val); mtsdram(SDRAM_RDCC, (val & ~(SDRAM_RDCC_RDSS_MASK | SDRAM_RDCC_RSAE_MASK)) - | (SDRAM_RDCC_RDSS_T4 | SDRAM_RDCC_RSAE_DISABLE)); + | SDRAM_RDCC_RSAE_ENABLE); /*------------------------------------------------------------------ * Program RQDC register @@ -2515,10 +2498,7 @@ static void DQS_calibration_process(void) { unsigned long rfdc_reg; unsigned long rffd; - unsigned long rqdc_reg; - unsigned long rqfd; unsigned long val; - long rqfd_average; long rffd_average; long max_start; long min_end; @@ -2536,10 +2516,14 @@ static void DQS_calibration_process(void) long max_end; unsigned char fail_found; unsigned char pass_found; +#if !defined(CONFIG_DDR_RQDC_FIXED) + u32 rqdc_reg; + u32 rqfd; u32 rqfd_start; + u32 rqfd_average; + int loopi = 0; char str[] = "Auto calibration -"; char slash[] = "\\|/-\\|/-"; - int loopi = 0; /*------------------------------------------------------------------ * Test to determine the best read clock delay tuning bits. @@ -2574,6 +2558,16 @@ calibration_loop: mfsdram(SDRAM_RQDC, rqdc_reg); mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | SDRAM_RQDC_RQFD_ENCODE(rqfd_start)); +#else /* CONFIG_DDR_RQDC_FIXED */ + /* + * On Katmai the complete auto-calibration somehow doesn't seem to + * produce the best results, meaning optimal values for RQFD/RFFD. + * This was discovered by GDA using a high bandwidth scope, + * analyzing the DDR2 signals. GDA provided a fixed value for RQFD, + * so now on Katmai "only" RFFD is auto-calibrated. + */ + mtsdram(SDRAM_RQDC, CONFIG_DDR_RQDC_FIXED); +#endif /* CONFIG_DDR_RQDC_FIXED */ max_start = 0; min_end = 0; @@ -2658,6 +2652,7 @@ calibration_loop: /* now fix RFDC[RFFD] found and find RQDC[RQFD] */ mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average)); +#if !defined(CONFIG_DDR_RQDC_FIXED) max_pass_length = 0; max_start = 0; max_end = 0; @@ -2730,8 +2725,6 @@ calibration_loop: spd_ddr_init_hang (); } - blank_string(strlen(str)); - if (rqfd_average < 0) rqfd_average = 0; @@ -2742,12 +2735,31 @@ calibration_loop: (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | SDRAM_RQDC_RQFD_ENCODE(rqfd_average)); + blank_string(strlen(str)); +#endif /* CONFIG_DDR_RQDC_FIXED */ + + /* + * Now complete RDSS configuration as mentioned on page 7 of the AMCC + * PowerPC440SP/SPe DDR2 application note: + * "DDR1/DDR2 Initialization Sequence and Dynamic Tuning" + */ + mfsdram(SDRAM_RTSR, val); + if ((val & SDRAM_RTSR_TRK1SM_MASK) == SDRAM_RTSR_TRK1SM_ATPLS1) { + mfsdram(SDRAM_RDCC, val); + if ((val & SDRAM_RDCC_RDSS_MASK) != SDRAM_RDCC_RDSS_T4) { + val += 0x40000000; + mtsdram(SDRAM_RDCC, val); + } + } + mfsdram(SDRAM_DLCR, val); debug("%s[%d] DLCR: 0x%08X\n", __FUNCTION__, __LINE__, val); mfsdram(SDRAM_RQDC, val); debug("%s[%d] RQDC: 0x%08X\n", __FUNCTION__, __LINE__, val); mfsdram(SDRAM_RFDC, val); debug("%s[%d] RFDC: 0x%08X\n", __FUNCTION__, __LINE__, val); + mfsdram(SDRAM_RDCC, val); + debug("%s[%d] RDCC: 0x%08X\n", __FUNCTION__, __LINE__, val); } #else /* calibration test with hardvalues */ /*-----------------------------------------------------------------------------+