⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 denali_spd_ddr2.c

📁 uboot详细解读可用启动引导LINUX2.6内核
💻 C
📖 第 1 页 / 共 3 页
字号:
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 + -