📄 denali_spd_ddr2.c
字号:
static void program_ddr0_10(unsigned long dimm_ranks[], unsigned long ranks){ unsigned long csmap; if (2 == ranks) { /* Both chip selects in use */ csmap = 0x03; } else { /* One chip select in use */ csmap = (1 == dimm_ranks[0]) ? 0x1 : 0x2; } mtsdram(DDR0_10, DDR0_10_WRITE_MODEREG_ENCODE(0x0) | DDR0_10_CS_MAP_ENCODE(csmap) | DDR0_10_OCD_ADJUST_PUP_CS_0_ENCODE(0));}static void program_ddr0_11(unsigned long sdram_freq){ unsigned long const t_xsnr_ps = 200000; /* 200 ns */ unsigned long t_xsnr_clk; debug("t_xsnr_ps = %d\n", t_xsnr_ps); t_xsnr_clk = (MULDIV64(sdram_freq, t_xsnr_ps, ONE_BILLION) + 999) / 1000; mtsdram(DDR0_11, DDR0_11_SREFRESH_ENCODE(0) | DDR0_11_TXSNR_ENCODE(t_xsnr_clk) | DDR0_11_TXSR_ENCODE(200));}static void program_ddr0_22(unsigned long dimm_ranks[], unsigned char const iic0_dimm_addr[], unsigned long num_dimm_banks, unsigned long width){#if defined(CONFIG_DDR_ECC) unsigned long dimm_num; unsigned long ecc_available = width >= 64; u32 ddr0_22 = DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(0x26) | DDR0_22_DQS_OUT_SHIFT_ENCODE(DQS_OUT_SHIFT) | DDR0_22_DLL_DQS_BYPASS_8_ENCODE(DLL_DQS_BYPASS); /* loop through all the DIMM slots on the board */ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { /* If a dimm is installed in a particular slot ... */ if (dimm_ranks[dimm_num]) { /* Check for ECC */ if (0 == (spd_read(iic0_dimm_addr[dimm_num], 11) & 0x02)) { ecc_available = FALSE; } } } if (ecc_available) { debug("ECC found on all DIMMs present\n"); mtsdram(DDR0_22, ddr0_22 | DDR0_22_CTRL_RAW_ENCODE(0x3)); } else { debug("ECC not found on some or all DIMMs present\n"); mtsdram(DDR0_22, ddr0_22 | DDR0_22_CTRL_RAW_ENCODE(0x0)); }#else mtsdram(DDR0_22, DDR0_22_CTRL_RAW_ENCODE(0x0) | DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(0x26) | DDR0_22_DQS_OUT_SHIFT_ENCODE(DQS_OUT_SHIFT) | DDR0_22_DLL_DQS_BYPASS_8_ENCODE(DLL_DQS_BYPASS));#endif /* defined(CONFIG_DDR_ECC) */}static void program_ddr0_24(unsigned long ranks){ u32 ddr0_24 = DDR0_24_RTT_PAD_TERMINATION_ENCODE(0x1) | /* 75 ohm */ DDR0_24_ODT_RD_MAP_CS1_ENCODE(0x0); if (2 == ranks) { /* Both chip selects in use */ ddr0_24 |= DDR0_24_ODT_WR_MAP_CS1_ENCODE(0x1) | DDR0_24_ODT_WR_MAP_CS0_ENCODE(0x2); } else { /* One chip select in use */ /* One of the two fields added to ddr0_24 is a "don't care" */ ddr0_24 |= DDR0_24_ODT_WR_MAP_CS1_ENCODE(0x2) | DDR0_24_ODT_WR_MAP_CS0_ENCODE(0x1); } mtsdram(DDR0_24, ddr0_24);}static void program_ddr0_26(unsigned long sdram_freq){ unsigned long const t_ref_ps = 7800000; /* 7.8 us. refresh */ /* TODO: check definition of tRAS_MAX */ unsigned long const t_ras_max_ps = 9 * t_ref_ps; unsigned long t_ras_max_clk; unsigned long t_ref_clk; /* Round down t_ras_max_clk and t_ref_clk */ debug("t_ras_max_ps = %d\n", t_ras_max_ps); t_ras_max_clk = MULDIV64(sdram_freq, t_ras_max_ps, ONE_BILLION) / 1000; debug("t_ref_ps = %d\n", t_ref_ps); t_ref_clk = MULDIV64(sdram_freq, t_ref_ps, ONE_BILLION) / 1000; mtsdram(DDR0_26, DDR0_26_TRAS_MAX_ENCODE(t_ras_max_clk) | DDR0_26_TREF_ENCODE(t_ref_clk));}static void program_ddr0_27(unsigned long sdram_freq){ unsigned long const t_init_ps = 200000000; /* 200 us. init */ unsigned long t_init_clk; debug("t_init_ps = %d\n", t_init_ps); t_init_clk = (MULDIV64(sdram_freq, t_init_ps, ONE_BILLION) + 999) / 1000; mtsdram(DDR0_27, DDR0_27_EMRS_DATA_ENCODE(0x0000) | DDR0_27_TINIT_ENCODE(t_init_clk));}static void program_ddr0_43(unsigned long dimm_ranks[], unsigned char const iic0_dimm_addr[], unsigned long num_dimm_banks, unsigned long sdram_freq, unsigned long cols, unsigned long banks){ unsigned long dimm_num; unsigned long t_wr_ps = 0; unsigned long t_wr_clk; u32 ddr0_43 = DDR0_43_APREBIT_ENCODE(10) | DDR0_43_COLUMN_SIZE_ENCODE(12 - cols) | DDR0_43_EIGHT_BANK_MODE_ENCODE(8 == banks ? 1 : 0); /*------------------------------------------------------------------ * Handle the timing. We need to find the worst case timing of all * the dimm modules installed. *-----------------------------------------------------------------*/ /* loop through all the DIMM slots on the board */ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { /* If a dimm is installed in a particular slot ... */ if (dimm_ranks[dimm_num]) { unsigned long ps; ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 36); t_wr_ps = max(t_wr_ps, ps); } } debug("t_wr_ps = %d\n", t_wr_ps); t_wr_clk = (MULDIV64(sdram_freq, t_wr_ps, ONE_BILLION) + 999) / 1000; mtsdram(DDR0_43, ddr0_43 | DDR0_43_TWR_ENCODE(t_wr_clk));}static void program_ddr0_44(unsigned long dimm_ranks[], unsigned char const iic0_dimm_addr[], unsigned long num_dimm_banks, unsigned long sdram_freq){ unsigned long dimm_num; unsigned long t_rcd_ps = 0; unsigned long t_rcd_clk; /*------------------------------------------------------------------ * Handle the timing. We need to find the worst case timing of all * the dimm modules installed. *-----------------------------------------------------------------*/ /* loop through all the DIMM slots on the board */ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { /* If a dimm is installed in a particular slot ... */ if (dimm_ranks[dimm_num]) { unsigned long ps; ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 29); t_rcd_ps = max(t_rcd_ps, ps); } } debug("t_rcd_ps = %d\n", t_rcd_ps); t_rcd_clk = (MULDIV64(sdram_freq, t_rcd_ps, ONE_BILLION) + 999) / 1000; mtsdram(DDR0_44, DDR0_44_TRCD_ENCODE(t_rcd_clk));}/*-----------------------------------------------------------------------------+ * initdram. Initializes the 440EPx/GPx 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 * .data sections. It also cannot call routines that require these sections. *-----------------------------------------------------------------------------*//*----------------------------------------------------------------------------- * 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 *-----------------------------------------------------------------------------*/phys_size_t initdram(int board_type){ unsigned char const iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; unsigned long dimm_ranks[MAXDIMMS]; unsigned long ranks; unsigned long rows; unsigned long banks; unsigned long cols; unsigned long width; unsigned long const sdram_freq = get_bus_freq(0); unsigned long const num_dimm_banks = sizeof(iic0_dimm_addr); /* on board dimm banks */ unsigned long cas_latency = 0; /* to quiet initialization warning */ unsigned long dram_size; debug("\nEntering initdram()\n"); /*------------------------------------------------------------------ * Stop the DDR-SDRAM controller. *-----------------------------------------------------------------*/ mtsdram(DDR0_02, DDR0_02_START_ENCODE(0)); /* * Make sure I2C controller is initialized * before continuing. */ /* switch to correct I2C bus */ I2C_SET_BUS(CFG_SPD_BUS_NUM); i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); /*------------------------------------------------------------------ * Clear out the serial presence detect buffers. * Perform IIC reads from the dimm. Fill in the spds. * Check to see if the dimm slots are populated *-----------------------------------------------------------------*/ get_spd_info(dimm_ranks, &ranks, iic0_dimm_addr, num_dimm_banks); /*------------------------------------------------------------------ * Check the frequency supported for the dimms plugged. *-----------------------------------------------------------------*/ check_frequency(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); /*------------------------------------------------------------------ * Check and get size information. *-----------------------------------------------------------------*/ get_dimm_size(dimm_ranks, iic0_dimm_addr, num_dimm_banks, &rows, &banks, &cols, &width); /*------------------------------------------------------------------ * Check the voltage type for the dimms plugged. *-----------------------------------------------------------------*/ check_voltage_type(dimm_ranks, iic0_dimm_addr, num_dimm_banks); /*------------------------------------------------------------------ * Program registers for SDRAM controller. *-----------------------------------------------------------------*/ mtsdram(DDR0_00, DDR0_00_DLL_INCREMENT_ENCODE(0x19) | DDR0_00_DLL_START_POINT_DECODE(0x0A)); mtsdram(DDR0_01, DDR0_01_PLB0_DB_CS_LOWER_ENCODE(0x01) | DDR0_01_PLB0_DB_CS_UPPER_ENCODE(0x00) | DDR0_01_INT_MASK_ENCODE(0xFF)); program_ddr0_03(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq, rows, &cas_latency); program_ddr0_04(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); program_ddr0_05(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); program_ddr0_06(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); /* * TODO: tFAW not found in SPD. Value of 13 taken from Sequoia * board SDRAM, but may be overly conservative. */ mtsdram(DDR0_07, DDR0_07_NO_CMD_INIT_ENCODE(0) | DDR0_07_TFAW_ENCODE(13) | DDR0_07_AUTO_REFRESH_MODE_ENCODE(1) | DDR0_07_AREFRESH_ENCODE(0)); mtsdram(DDR0_08, DDR0_08_WRLAT_ENCODE(cas_latency - 1) | DDR0_08_TCPD_ENCODE(200) | DDR0_08_DQS_N_EN_ENCODE(0) | DDR0_08_DDRII_ENCODE(1)); mtsdram(DDR0_09, DDR0_09_OCD_ADJUST_PDN_CS_0_ENCODE(0x00) | DDR0_09_RTT_0_ENCODE(0x1) | DDR0_09_WR_DQS_SHIFT_BYPASS_ENCODE(0x1D) | DDR0_09_WR_DQS_SHIFT_ENCODE(DQS_OUT_SHIFT - 0x20)); program_ddr0_10(dimm_ranks, ranks); program_ddr0_11(sdram_freq); mtsdram(DDR0_12, DDR0_12_TCKE_ENCODE(3)); mtsdram(DDR0_14, DDR0_14_DLL_BYPASS_MODE_ENCODE(0) | DDR0_14_REDUC_ENCODE(width <= 40 ? 1 : 0) | DDR0_14_REG_DIMM_ENABLE_ENCODE(0)); mtsdram(DDR0_17, DDR0_17_DLL_DQS_DELAY_0_ENCODE(DLL_DQS_DELAY)); mtsdram(DDR0_18, DDR0_18_DLL_DQS_DELAY_4_ENCODE(DLL_DQS_DELAY) | DDR0_18_DLL_DQS_DELAY_3_ENCODE(DLL_DQS_DELAY) | DDR0_18_DLL_DQS_DELAY_2_ENCODE(DLL_DQS_DELAY) | DDR0_18_DLL_DQS_DELAY_1_ENCODE(DLL_DQS_DELAY)); mtsdram(DDR0_19, DDR0_19_DLL_DQS_DELAY_8_ENCODE(DLL_DQS_DELAY) | DDR0_19_DLL_DQS_DELAY_7_ENCODE(DLL_DQS_DELAY) | DDR0_19_DLL_DQS_DELAY_6_ENCODE(DLL_DQS_DELAY) | DDR0_19_DLL_DQS_DELAY_5_ENCODE(DLL_DQS_DELAY)); mtsdram(DDR0_20, DDR0_20_DLL_DQS_BYPASS_3_ENCODE(DLL_DQS_BYPASS) | DDR0_20_DLL_DQS_BYPASS_2_ENCODE(DLL_DQS_BYPASS) | DDR0_20_DLL_DQS_BYPASS_1_ENCODE(DLL_DQS_BYPASS) | DDR0_20_DLL_DQS_BYPASS_0_ENCODE(DLL_DQS_BYPASS)); mtsdram(DDR0_21, DDR0_21_DLL_DQS_BYPASS_7_ENCODE(DLL_DQS_BYPASS) | DDR0_21_DLL_DQS_BYPASS_6_ENCODE(DLL_DQS_BYPASS) | DDR0_21_DLL_DQS_BYPASS_5_ENCODE(DLL_DQS_BYPASS) | DDR0_21_DLL_DQS_BYPASS_4_ENCODE(DLL_DQS_BYPASS)); program_ddr0_22(dimm_ranks, iic0_dimm_addr, num_dimm_banks, width); mtsdram(DDR0_23, DDR0_23_ODT_RD_MAP_CS0_ENCODE(0x0) | DDR0_23_FWC_ENCODE(0)); program_ddr0_24(ranks); program_ddr0_26(sdram_freq); program_ddr0_27(sdram_freq); mtsdram(DDR0_28, DDR0_28_EMRS3_DATA_ENCODE(0x0000) | DDR0_28_EMRS2_DATA_ENCODE(0x0000)); mtsdram(DDR0_31, DDR0_31_XOR_CHECK_BITS_ENCODE(0x0000)); mtsdram(DDR0_42, DDR0_42_ADDR_PINS_DECODE(14 - rows) | DDR0_42_CASLAT_LIN_GATE_ENCODE(2 * cas_latency)); program_ddr0_43(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq, cols, banks); program_ddr0_44(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); denali_sdram_register_dump(); dram_size = (width >= 64) ? 8 : 4; dram_size *= 1 << cols; dram_size *= banks; dram_size *= 1 << rows; dram_size *= ranks; debug("dram_size = %lu\n", dram_size); /* Start the SDRAM controler */ mtsdram(DDR0_02, DDR0_02_START_ENCODE(1)); denali_wait_for_dlllock();#if defined(CONFIG_DDR_DATA_EYE) /* * Map the first 1 MiB of memory in the TLB, and perform the data eye * search. */ program_tlb(0, CFG_SDRAM_BASE, TLB_1MB_SIZE, TLB_WORD2_I_ENABLE); denali_core_search_data_eye(); denali_sdram_register_dump(); remove_tlb(CFG_SDRAM_BASE, TLB_1MB_SIZE);#endif#if defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) program_tlb(0, CFG_SDRAM_BASE, dram_size, 0); sync(); /* Zero the memory */ debug("Zeroing SDRAM...");#if defined(CFG_MEM_TOP_HIDE) dcbz_area(CFG_SDRAM_BASE, dram_size - CFG_MEM_TOP_HIDE);#else#error Please define CFG_MEM_TOP_HIDE (see README) in your board config file#endif /* Write modified dcache lines back to memory */ clean_dcache_range(CFG_SDRAM_BASE, CFG_SDRAM_BASE + dram_size - CFG_MEM_TOP_HIDE); debug("Completed\n"); sync(); remove_tlb(CFG_SDRAM_BASE, dram_size);#if defined(CONFIG_DDR_ECC) /* * If ECC is enabled, clear and enable interrupts */ if (is_ecc_enabled()) { u32 val; sync(); /* Clear error status */ mfsdram(DDR0_00, val); mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL); /* Set 'int_mask' parameter to functionnal value */ mfsdram(DDR0_01, val); mtsdram(DDR0_01, (val & ~DDR0_01_INT_MASK_MASK) | DDR0_01_INT_MASK_ALL_OFF);#if defined(CONFIG_DDR_DATA_EYE) /* * Running denali_core_search_data_eye() when ECC is enabled * causes non-ECC machine checks. This clears them. */ print_mcsr(); mtspr(SPRN_MCSR, mfspr(SPRN_MCSR)); print_mcsr();#endif sync(); }#endif /* defined(CONFIG_DDR_ECC) */#endif /* defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) */ program_tlb(0, CFG_SDRAM_BASE, dram_size, MY_TLB_WORD2_I_ENABLE); return dram_size;}void board_add_ram_info(int use_default){ u32 val; printf(" (ECC"); if (!is_ecc_enabled()) { printf(" not"); } printf(" enabled, %ld MHz", (2 * get_bus_freq(0)) / 1000000); mfsdram(DDR0_03, val); printf(", CL%d)", DDR0_03_CASLAT_LIN_DECODE(val) >> 1);}#endif /* CONFIG_SPD_EEPROM */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -