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

📄 denali_spd_ddr2.c

📁 uboot详细解读可用启动引导LINUX2.6内核
💻 C
📖 第 1 页 / 共 3 页
字号:
			  unsigned long num_dimm_banks,			  unsigned long *const rows,			  unsigned long *const banks,			  unsigned long *const cols, unsigned long *const width){	unsigned long dimm_num;	*rows = 0;	*banks = 0;	*cols = 0;	*width = 0;	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {		if (dimm_ranks[dimm_num]) {			unsigned long t;			/* Rows */			t = spd_read(iic0_dimm_addr[dimm_num], 3);			if (0 == *rows) {				*rows = t;			} else if (t != *rows) {				printf("ERROR: DRAM DIMM modules do not all "				       "have the same number of rows.\n\n");				spd_ddr_init_hang();			}			/* Banks */			t = spd_read(iic0_dimm_addr[dimm_num], 17);			if (0 == *banks) {				*banks = t;			} else if (t != *banks) {				printf("ERROR: DRAM DIMM modules do not all "				       "have the same number of banks.\n\n");				spd_ddr_init_hang();			}			/* Columns */			t = spd_read(iic0_dimm_addr[dimm_num], 4);			if (0 == *cols) {				*cols = t;			} else if (t != *cols) {				printf("ERROR: DRAM DIMM modules do not all "				       "have the same number of columns.\n\n");				spd_ddr_init_hang();			}			/* Data width */			t = spd_read(iic0_dimm_addr[dimm_num], 6);			if (0 == *width) {				*width = t;			} else if (t != *width) {				printf("ERROR: DRAM DIMM modules do not all "				       "have the same data width.\n\n");				spd_ddr_init_hang();			}		}	}	debug("Number of rows = %d\n", *rows);	debug("Number of columns = %d\n", *cols);	debug("Number of banks = %d\n", *banks);	debug("Data width = %d\n", *width);	if (*rows > 14) {		printf("ERROR: DRAM DIMM modules have %lu address rows.\n",		       *rows);		printf("Only modules with 14 or fewer rows are supported.\n\n");		spd_ddr_init_hang();	}	if (4 != *banks && 8 != *banks) {		printf("ERROR: DRAM DIMM modules have %lu banks.\n", *banks);		printf("Only modules with 4 or 8 banks are supported.\n\n");		spd_ddr_init_hang();	}	if (*cols > 12) {		printf("ERROR: DRAM DIMM modules have %lu address columns.\n",		       *cols);		printf("Only modules with 12 or fewer columns are "		       "supported.\n\n");		spd_ddr_init_hang();	}	if (32 != *width && 40 != *width && 64 != *width && 72 != *width) {		printf("ERROR: DRAM DIMM modules have a width of %lu bit.\n",		       *width);		printf("Only modules with widths of 32, 40, 64, and 72 bits "		       "are supported.\n\n");		spd_ddr_init_hang();	}}/*------------------------------------------------------------------ * Only 1.8V modules are supported.  This routine verifies this. *-----------------------------------------------------------------*/static void check_voltage_type(unsigned long dimm_ranks[],			       unsigned char const iic0_dimm_addr[],			       unsigned long num_dimm_banks){	unsigned long dimm_num;	unsigned long voltage_type;	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {		if (dimm_ranks[dimm_num]) {			voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8);			if (0x05 != voltage_type) {	/* 1.8V for DDR2 */				printf("ERROR: Slot %lu provides 1.8V for DDR2 "				       "DIMMs.\n", dimm_num);				switch (voltage_type) {				case 0x00:					printf("This DIMM is 5.0 Volt/TTL.\n");					break;				case 0x01:					printf("This DIMM is LVTTL.\n");					break;				case 0x02:					printf("This DIMM is 1.5 Volt.\n");					break;				case 0x03:					printf("This DIMM is 3.3 Volt/TTL.\n");					break;				case 0x04:					printf("This DIMM is 2.5 Volt.\n");					break;				default:					printf("This DIMM is an unknown "					       "voltage.\n");					break;				}				printf("Replace it with a 1.8V DDR2 DIMM.\n\n");				spd_ddr_init_hang();			}		}	}}static void program_ddr0_03(unsigned long dimm_ranks[],			    unsigned char const iic0_dimm_addr[],			    unsigned long num_dimm_banks,			    unsigned long sdram_freq,			    unsigned long rows, unsigned long *cas_latency){	unsigned long dimm_num;	unsigned long cas_index;	unsigned long cycle_2_0_clk;	unsigned long cycle_3_0_clk;	unsigned long cycle_4_0_clk;	unsigned long cycle_5_0_clk;	unsigned long max_2_0_tcyc_ps = 100;	unsigned long max_3_0_tcyc_ps = 100;	unsigned long max_4_0_tcyc_ps = 100;	unsigned long max_5_0_tcyc_ps = 100;	unsigned char cas_available = 0x3C;	/* value for DDR2 */	u32 ddr0_03 = DDR0_03_BSTLEN_ENCODE(0x2) | DDR0_03_INITAREF_ENCODE(0x2);	unsigned int const tcyc_addr[3] = { 9, 23, 25 };	/*------------------------------------------------------------------	 * Get the board configuration info.	 *-----------------------------------------------------------------*/	debug("sdram_freq = %d\n", sdram_freq);	/*------------------------------------------------------------------	 * 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 char const cas_bit =			    spd_read(iic0_dimm_addr[dimm_num], 18);			unsigned char cas_mask;			cas_available &= cas_bit;			for (cas_mask = 0x80; cas_mask; cas_mask >>= 1) {				if (cas_bit & cas_mask)					break;			}			debug("cas_bit (SPD byte 18) = %02X, cas_mask = %02X\n",			      cas_bit, cas_mask);			for (cas_index = 0; cas_index < 3;			     cas_mask >>= 1, cas_index++) {				unsigned long cycle_time_ps;				if (!(cas_available & cas_mask)) {					continue;				}				cycle_time_ps =				    get_tcyc(spd_read(iic0_dimm_addr[dimm_num],						      tcyc_addr[cas_index]));				debug("cas_index = %d: cycle_time_ps = %d\n",				      cas_index, cycle_time_ps);				/*				 * DDR2 devices use the following bitmask for CAS latency:				 *  Bit   7    6    5    4    3    2    1    0				 *       TBD  6.0  5.0  4.0  3.0  2.0  TBD  TBD				 */				switch (cas_mask) {				case 0x20:					max_5_0_tcyc_ps =					    max(max_5_0_tcyc_ps, cycle_time_ps);					break;				case 0x10:					max_4_0_tcyc_ps =					    max(max_4_0_tcyc_ps, cycle_time_ps);					break;				case 0x08:					max_3_0_tcyc_ps =					    max(max_3_0_tcyc_ps, cycle_time_ps);					break;				case 0x04:					max_2_0_tcyc_ps =					    max(max_2_0_tcyc_ps, cycle_time_ps);					break;				}			}		}	}	debug("cas_available (bit map) = 0x%02X\n", cas_available);	/*------------------------------------------------------------------	 * Set the SDRAM mode, SDRAM_MMODE	 *-----------------------------------------------------------------*/	/* add 10 here because of rounding problems */	cycle_2_0_clk = MULDIV64(ONE_BILLION, 1000, max_2_0_tcyc_ps) + 10;	cycle_3_0_clk = MULDIV64(ONE_BILLION, 1000, max_3_0_tcyc_ps) + 10;	cycle_4_0_clk = MULDIV64(ONE_BILLION, 1000, max_4_0_tcyc_ps) + 10;	cycle_5_0_clk = MULDIV64(ONE_BILLION, 1000, max_5_0_tcyc_ps) + 10;	debug("cycle_2_0_clk = %d\n", cycle_2_0_clk);	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 ((cas_available & 0x04) && (sdram_freq <= cycle_2_0_clk)) {		*cas_latency = 2;		ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x2) |		    DDR0_03_CASLAT_LIN_ENCODE(0x4);	} else if ((cas_available & 0x08) && (sdram_freq <= cycle_3_0_clk)) {		*cas_latency = 3;		ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x3) |		    DDR0_03_CASLAT_LIN_ENCODE(0x6);	} else if ((cas_available & 0x10) && (sdram_freq <= cycle_4_0_clk)) {		*cas_latency = 4;		ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x4) |		    DDR0_03_CASLAT_LIN_ENCODE(0x8);	} else if ((cas_available & 0x20) && (sdram_freq <= cycle_5_0_clk)) {		*cas_latency = 5;		ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x5) |		    DDR0_03_CASLAT_LIN_ENCODE(0xA);	} else {		printf("ERROR: Cannot find a supported CAS latency with the "		       "installed DIMMs.\n");		printf("Only DDR2 DIMMs with CAS latencies of 2.0, 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");		printf("sdram_freq=%ld cycle2=%ld cycle3=%ld cycle4=%ld "		       "cycle5=%ld\n\n", sdram_freq, cycle_2_0_clk,		       cycle_3_0_clk, cycle_4_0_clk, cycle_5_0_clk);		spd_ddr_init_hang();	}	debug("CAS latency = %d\n", *cas_latency);	mtsdram(DDR0_03, ddr0_03);}static void program_ddr0_04(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_rc_ps = 0;	unsigned long t_rrd_ps = 0;	unsigned long t_rtp_ps = 0;	unsigned long t_rc_clk;	unsigned long t_rrd_clk;	unsigned long t_rtp_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;			/* tRC */			ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 41);			switch (spd_read(iic0_dimm_addr[dimm_num], 40) >> 4) {			case 0x1:				ps += 250;				break;			case 0x2:				ps += 333;				break;			case 0x3:				ps += 500;				break;			case 0x4:				ps += 667;				break;			case 0x5:				ps += 750;				break;			}			t_rc_ps = max(t_rc_ps, ps);			/* tRRD */			ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 28);			t_rrd_ps = max(t_rrd_ps, ps);			/* tRTP */			ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 38);			t_rtp_ps = max(t_rtp_ps, ps);		}	}	debug("t_rc_ps  = %d\n", t_rc_ps);	t_rc_clk = (MULDIV64(sdram_freq, t_rc_ps, ONE_BILLION) + 999) / 1000;	debug("t_rrd_ps = %d\n", t_rrd_ps);	t_rrd_clk = (MULDIV64(sdram_freq, t_rrd_ps, ONE_BILLION) + 999) / 1000;	debug("t_rtp_ps = %d\n", t_rtp_ps);	t_rtp_clk = (MULDIV64(sdram_freq, t_rtp_ps, ONE_BILLION) + 999) / 1000;	mtsdram(DDR0_04, DDR0_04_TRC_ENCODE(t_rc_clk) |		DDR0_04_TRRD_ENCODE(t_rrd_clk) |		DDR0_04_TRTP_ENCODE(t_rtp_clk));}static void program_ddr0_05(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_rp_ps = 0;	unsigned long t_ras_ps = 0;	unsigned long t_rp_clk;	unsigned long t_ras_clk;	u32 ddr0_05 = DDR0_05_TMRD_ENCODE(0x2) | DDR0_05_TEMRS_ENCODE(0x2);	/*------------------------------------------------------------------	 * 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;			/* tRP */			ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 27);			t_rp_ps = max(t_rp_ps, ps);			/* tRAS */			ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 30);			t_ras_ps = max(t_ras_ps, ps);		}	}	debug("t_rp_ps  = %d\n", t_rp_ps);	t_rp_clk = (MULDIV64(sdram_freq, t_rp_ps, ONE_BILLION) + 999) / 1000;	debug("t_ras_ps = %d\n", t_ras_ps);	t_ras_clk = (MULDIV64(sdram_freq, t_ras_ps, ONE_BILLION) + 999) / 1000;	mtsdram(DDR0_05, ddr0_05 | DDR0_05_TRP_ENCODE(t_rp_clk) |		DDR0_05_TRAS_MIN_ENCODE(t_ras_clk));}static void program_ddr0_06(unsigned long dimm_ranks[],			    unsigned char const iic0_dimm_addr[],			    unsigned long num_dimm_banks,			    unsigned long sdram_freq){	unsigned long dimm_num;	unsigned char spd_40;	unsigned long t_wtr_ps = 0;	unsigned long t_rfc_ps = 0;	unsigned long t_wtr_clk;	unsigned long t_rfc_clk;	u32 ddr0_06 =	    DDR0_06_WRITEINTERP_ENCODE(0x1) | DDR0_06_TDLL_ENCODE(200);	/*------------------------------------------------------------------	 * 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;			/* tWTR */			ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 37);			t_wtr_ps = max(t_wtr_ps, ps);			/* tRFC */			ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 42);			spd_40 = spd_read(iic0_dimm_addr[dimm_num], 40);			ps += 256000 * (spd_40 & 0x01);			switch ((spd_40 & 0x0E) >> 1) {			case 0x1:				ps += 250;				break;			case 0x2:				ps += 333;				break;			case 0x3:				ps += 500;				break;			case 0x4:				ps += 667;				break;			case 0x5:				ps += 750;				break;			}			t_rfc_ps = max(t_rfc_ps, ps);		}	}	debug("t_wtr_ps = %d\n", t_wtr_ps);	t_wtr_clk = (MULDIV64(sdram_freq, t_wtr_ps, ONE_BILLION) + 999) / 1000;	debug("t_rfc_ps = %d\n", t_rfc_ps);	t_rfc_clk = (MULDIV64(sdram_freq, t_rfc_ps, ONE_BILLION) + 999) / 1000;	mtsdram(DDR0_06, ddr0_06 | DDR0_06_TWTR_ENCODE(t_wtr_clk) |		DDR0_06_TRFC_ENCODE(t_rfc_clk));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -