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

📄 44x_spd_ddr2.c

📁 u-boot1.3德国DENX小组开发的用于多种嵌入式CPU的bootloader
💻 C
📖 第 1 页 / 共 5 页
字号:
		case DDR_CAS_4:			cas = 4 << 4;			break;		case DDR_CAS_5:			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: 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 ();		}		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");		spd_ddr_init_hang ();	}}/*------------------------------------------------------------------ * This routine programs the SDRAM_MMODE register. * the selected_cas is an output parameter, that will be passed * by caller to call the above program_initplr( ) *-----------------------------------------------------------------*/static void program_mode(unsigned long *dimm_populated,			 unsigned char *iic0_dimm_addr,			 unsigned long num_dimm_banks,			 ddr_cas_id_t *selected_cas,			 int *write_recovery){	unsigned long dimm_num;	unsigned long sdram_ddr1;	unsigned long t_wr_ns;	unsigned long t_wr_clk;	unsigned long cas_bit;	unsigned long cas_index;	unsigned long sdram_freq;	unsigned long ddr_check;	unsigned long mmode;	unsigned long tcyc_reg;	unsigned long cycle_2_0_clk;	unsigned long cycle_2_5_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_ns_x_100;	unsigned long max_2_5_tcyc_ns_x_100;	unsigned long max_3_0_tcyc_ns_x_100;	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;	unsigned char cas_2_0_available;	unsigned char cas_2_5_available;	unsigned char cas_3_0_available;	unsigned char cas_4_0_available;	unsigned char cas_5_0_available;	unsigned long sdr_ddrpll;	/*------------------------------------------------------------------	 * Get the board configuration info.	 *-----------------------------------------------------------------*/	get_sys_info(&board_cfg);	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	 * the dimm modules installed.	 *-----------------------------------------------------------------*/	t_wr_ns = 0;	cas_2_0_available = TRUE;	cas_2_5_available = TRUE;	cas_3_0_available = TRUE;	cas_4_0_available = TRUE;	cas_5_0_available = TRUE;	max_2_0_tcyc_ns_x_100 = 10;	max_2_5_tcyc_ns_x_100 = 10;	max_3_0_tcyc_ns_x_100 = 10;	max_4_0_tcyc_ns_x_100 = 10;	max_5_0_tcyc_ns_x_100 = 10;	sdram_ddr1 = TRUE;	/* 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_populated[dimm_num] != SDRAM_NONE) {			if (dimm_populated[dimm_num] == SDRAM_DDR1)				sdram_ddr1 = TRUE;			else				sdram_ddr1 = FALSE;			/* 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++) {				switch (cas_index) {				case 0:					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9);					break;				case 1:					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23);					break;				default:					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25);					break;				}				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;					} else {						printf("ERROR: SPD reported Tcyc is incorrect for DIMM "						       "in slot %d\n", (unsigned int)dimm_num);						spd_ddr_init_hang ();					}				} else {					/* Convert from hex to decimal */					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 */			/* supported for a particular DIMM. */			cas_index = 0;			if (sdram_ddr1) {				/*				 * DDR devices use the following bitmask for CAS latency:				 *  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]);					cas_index++;				} else {					if (cas_index != 0)						cas_index++;					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]);					cas_index++;				} else {					if (cas_index != 0)						cas_index++;					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]);					cas_index++;				} else {					if (cas_index != 0)						cas_index++;					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]);					cas_index++;				} else {					if (cas_index != 0)						cas_index++;					cas_2_0_available = FALSE;				}			} else {				/*				 * 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				 */				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)						cas_index++;					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]);					cas_index++;				} else {					if (cas_index != 0)						cas_index++;					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]);					cas_index++;				} else {					if (cas_index != 0)						cas_index++;					cas_3_0_available = FALSE;				}			}		}	}	/*------------------------------------------------------------------	 * Set the SDRAM mode, SDRAM_MMODE	 *-----------------------------------------------------------------*/	mfsdram(SDRAM_MMODE, mmode);	mmode = mmode & ~(SDRAM_MMODE_WR_MASK | SDRAM_MMODE_DCL_MASK);	/* 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)) {			mmode |= SDRAM_MMODE_DCL_DDR1_2_0_CLK;			*selected_cas = DDR_CAS_2;		} else if ((cas_2_5_available == TRUE) && (sdram_freq <= cycle_2_5_clk)) {			mmode |= SDRAM_MMODE_DCL_DDR1_2_5_CLK;			*selected_cas = DDR_CAS_2_5;		} else if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) {			mmode |= SDRAM_MMODE_DCL_DDR1_3_0_CLK;			*selected_cas = DDR_CAS_3;		} else {			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");			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;		} else if ((cas_4_0_available == TRUE) && (sdram_freq <= cycle_4_0_clk)) {			mmode |= SDRAM_MMODE_DCL_DDR2_4_0_CLK;			*selected_cas = DDR_CAS_4;		} else if ((cas_5_0_available == TRUE) && (sdram_freq <= cycle_5_0_clk)) {			mmode |= SDRAM_MMODE_DCL_DDR2_5_0_CLK;			*selected_cas = DDR_CAS_5;		} 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");			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 ();		}	}	if (sdram_ddr1 == TRUE)		mmode |= SDRAM_MMODE_WR_DDR1;	else {		/* 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_populated[dimm_num] != SDRAM_NONE)				t_wr_ns = max(t_wr_ns,					      spd_read(iic0_dimm_addr[dimm_num], 36) >> 2);		}		/*		 * convert from nanoseconds to ddr clocks		 * round up if necessary		 */		t_wr_clk = MULDIV64(sdram_freq, t_wr_ns, ONE_BILLION);		ddr_check = MULDIV64(ONE_BILLION, t_wr_clk, t_wr_ns);		if (sdram_freq != ddr_check)			t_wr_clk++;		switch (t_wr_clk) {		case 0:		case 1:		case 2:		case 3:			mmode |= SDRAM_MMODE_WR_DDR2_3_CYC;			break;		case 4:			mmode |= SDRAM_MMODE_WR_DDR2_4_CYC;			break;		case 5:			mmode |= SDRAM_MMODE_WR_DDR2_5_CYC;			break;		default:			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);}/*-----------------------------------------------------------------------------+ * program_rtr. *-----------------------------------------------------------------------------*/static void program_rtr(unsigned long *dimm_populated,			unsigned char *iic0_dimm_addr,			unsigned long num_dimm_banks){	PPC440_SYS_INFO board_cfg;	unsigned long max_refresh_rate;	unsigned long dimm_num;	unsigned long refresh_rate_type;	unsigned long refresh_rate;	unsigned long rint;

⌨️ 快捷键说明

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