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

📄 spd_sdram.c

📁 UBOOT 源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	 *	 *	CAS Lat	DDR I	DDR II	Ctrl	 *	Clocks	SPD Bit	SPD Bit	Value	 *	-------	-------	-------	-----	 *	1.0	0		0001	 *	1.5	1		0010	 *	2.0	2	2	0011	 *	2.5	3		0100	 *	3.0	4	3	0101	 *	3.5	5		0110	 *	4.0		4	0111	 *	4.5			1000	 *	5.0		5	1001	 */	caslat = __ilog2(spd.cas_lat);	if ((spd.mem_type == SPD_MEMTYPE_DDR)	    && (caslat > 5)) {		printf("DDR I: Invalid SPD CAS Latency: 0x%x.\n", spd.cas_lat);		return 0;	} else if (spd.mem_type == SPD_MEMTYPE_DDR2		   && (caslat < 2 || caslat > 5)) {		printf("DDR II: Invalid SPD CAS Latency: 0x%x.\n",		       spd.cas_lat);		return 0;	}	debug("DDR: caslat SPD bit is %d\n", caslat);	/*	 * Calculate the Maximum Data Rate based on the Minimum Cycle time.	 * The SPD clk_cycle field (tCKmin) is measured in tenths of	 * nanoseconds and represented as BCD.	 */	tCKmin_ps = convert_bcd_tenths_to_cycle_time_ps(spd.clk_cycle);	debug("DDR: tCKmin = %d ps\n", tCKmin_ps);	/*	 * Double-data rate, scaled 1000 to picoseconds, and back down to MHz.	 */	max_data_rate = 2 * 1000 * 1000 / tCKmin_ps;	debug("DDR: Module max data rate = %d Mhz\n", max_data_rate);	/*	 * Adjust the CAS Latency to allow for bus speeds that	 * are slower than the DDR module.	 */	busfreq = get_bus_freq(0) / 1000000;	/* MHz */	tCycle_ps = convert_bcd_tenths_to_cycle_time_ps(spd.clk_cycle3);	modfreq = 2 * 1000 * 1000 / tCycle_ps;	if ((spd.mem_type == SPD_MEMTYPE_DDR2) && (busfreq < 266)) {		printf("DDR: platform frequency too low for correct DDR2 controller operation\n");		return 0;	} else if (busfreq < 90) {		printf("DDR: platform frequency too low for correct DDR1 operation\n");		return 0;	}	if ((busfreq <= modfreq) && (spd.cas_lat & (1 << (caslat - 2)))) {		caslat -= 2;	} else {		tCycle_ps = convert_bcd_tenths_to_cycle_time_ps(spd.clk_cycle2);		modfreq = 2 * 1000 * 1000 / tCycle_ps;		if ((busfreq <= modfreq) && (spd.cas_lat & (1 << (caslat - 1))))			caslat -= 1;		else if (busfreq > max_data_rate) {			printf("DDR: Bus freq %d MHz is not fit for DDR rate %d MHz\n",		     	busfreq, max_data_rate);			return 0;		}	}	/*	 * Empirically set ~MCAS-to-preamble override for DDR 2.	 * Your milage will vary.	 */	cpo = 0;	if (spd.mem_type == SPD_MEMTYPE_DDR2) {		if (busfreq <= 333) {			cpo = 0x7;		} else if (busfreq <= 400) {			cpo = 0x9;		} else {			cpo = 0xa;		}	}	/*	 * Convert caslat clocks to DDR controller value.	 * Force caslat_ctrl to be DDR Controller field-sized.	 */	if (spd.mem_type == SPD_MEMTYPE_DDR) {		caslat_ctrl = (caslat + 1) & 0x07;	} else {		caslat_ctrl =  (2 * caslat - 1) & 0x0f;	}	debug("DDR: caslat SPD bit is %d, controller field is 0x%x\n",	      caslat, caslat_ctrl);	/*	 * Timing Config 0.	 * Avoid writing for DDR I.  The new PQ38 DDR controller	 * dreams up non-zero default values to be backwards compatible.	 */	if (spd.mem_type == SPD_MEMTYPE_DDR2) {		unsigned char taxpd_clk = 8;		/* By the book. */		unsigned char tmrd_clk = 2;		/* By the book. */		unsigned char act_pd_exit = 2;		/* Empirical? */		unsigned char pre_pd_exit = 6;		/* Empirical? */		ddr->timing_cfg_0 = (0			| ((act_pd_exit & 0x7) << 20)	/* ACT_PD_EXIT */			| ((pre_pd_exit & 0x7) << 16)	/* PRE_PD_EXIT */			| ((taxpd_clk & 0xf) << 8)	/* ODT_PD_EXIT */			| ((tmrd_clk & 0xf) << 0)	/* MRS_CYC */			);		debug("DDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);	}	/*	 * Some Timing Config 1 values now.	 * Sneak Extended Refresh Recovery in here too.	 */	/*	 * For DDR I, WRREC(Twr) and WRTORD(Twtr) are not in SPD,	 * use conservative value.	 * For DDR II, they are bytes 36 and 37, in quarter nanos.	 */	if (spd.mem_type == SPD_MEMTYPE_DDR) {		twr_clk = 3;	/* Clocks */		twtr_clk = 1;	/* Clocks */	} else {		twr_clk = picos_to_clk(spd.twr * 250);		twtr_clk = picos_to_clk(spd.twtr * 250);	}	/*	 * Calculate Trfc, in picos.	 * DDR I:  Byte 42 straight up in ns.	 * DDR II: Byte 40 and 42 swizzled some, in ns.	 */	if (spd.mem_type == SPD_MEMTYPE_DDR) {		trfc = spd.trfc * 1000;		/* up to ps */	} else {		unsigned int byte40_table_ps[8] = {			0,			250,			330,			500,			660,			750,			0,			0		};		trfc = (((spd.trctrfc_ext & 0x1) * 256) + spd.trfc) * 1000			+ byte40_table_ps[(spd.trctrfc_ext >> 1) & 0x7];	}	trfc_clk = picos_to_clk(trfc);	/*	 * Trcd, Byte 29, from quarter nanos to ps and clocks.	 */	trcd_clk = picos_to_clk(spd.trcd * 250) & 0x7;	/*	 * Convert trfc_clk to DDR controller fields.  DDR I should	 * fit in the REFREC field (16-19) of TIMING_CFG_1, but the	 * 8548 controller has an extended REFREC field of three bits.	 * The controller automatically adds 8 clocks to this value,	 * so preadjust it down 8 first before splitting it up.	 */	trfc_low = (trfc_clk - 8) & 0xf;	trfc_high = ((trfc_clk - 8) >> 4) & 0x3;	/*	 * Sneak in some Extended Refresh Recovery.	 */	ddr->ext_refrec = (trfc_high << 16);	debug("DDR: ext_refrec = 0x%08x\n", ddr->ext_refrec);	ddr->timing_cfg_1 =	    (0	     | ((picos_to_clk(spd.trp * 250) & 0x07) << 28)	/* PRETOACT */	     | ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24)	/* ACTTOPRE */	     | (trcd_clk << 20)					/* ACTTORW */	     | (caslat_ctrl << 16)				/* CASLAT */	     | (trfc_low << 12)					/* REFEC */	     | ((twr_clk & 0x07) << 8)				/* WRRREC */	     | ((picos_to_clk(spd.trrd * 250) & 0x07) << 4)	/* ACTTOACT */	     | ((twtr_clk & 0x07) << 0)				/* WRTORD */	     );	debug("DDR: timing_cfg_1  = 0x%08x\n", ddr->timing_cfg_1);	/*	 * Timing_Config_2	 * Was: 0x00000800;	 */	/*	 * Additive Latency	 * For DDR I, 0.	 * For DDR II, with ODT enabled, use "a value" less than ACTTORW,	 * which comes from Trcd, and also note that:	 *	add_lat + caslat must be >= 4	 */	add_lat = 0;	if (spd.mem_type == SPD_MEMTYPE_DDR2	    && (odt_wr_cfg || odt_rd_cfg)	    && (caslat < 4)) {		add_lat = 4 - caslat;		if (add_lat >= trcd_clk) {			add_lat = trcd_clk - 1;		}	}	/*	 * Write Data Delay	 * Historically 0x2 == 4/8 clock delay.	 * Empirically, 0x3 == 6/8 clock delay is suggested for DDR I 266.	 */	wr_data_delay = 3;	/*	 * Write Latency	 * Read to Precharge	 * Minimum CKE Pulse Width.	 * Four Activate Window	 */	if (spd.mem_type == SPD_MEMTYPE_DDR) {		/*		 * This is a lie.  It should really be 1, but if it is		 * set to 1, bits overlap into the old controller's		 * otherwise unused ACSM field.  If we leave it 0, then		 * the HW will magically treat it as 1 for DDR 1.  Oh Yea.		 */		wr_lat = 0;		trtp_clk = 2;		/* By the book. */		cke_min_clk = 1;	/* By the book. */		four_act = 1;		/* By the book. */	} else {		wr_lat = caslat - 1;		/* Convert SPD value from quarter nanos to picos. */		trtp_clk = picos_to_clk(spd.trtp * 250);		cke_min_clk = 3;	/* By the book. */		four_act = picos_to_clk(37500);	/* By the book. 1k pages? */	}	ddr->timing_cfg_2 = (0		| ((add_lat & 0x7) << 28)		/* ADD_LAT */		| ((cpo & 0x1f) << 23)			/* CPO */		| ((wr_lat & 0x7) << 19)		/* WR_LAT */		| ((trtp_clk & 0x7) << 13)		/* RD_TO_PRE */		| ((wr_data_delay & 0x7) << 10)		/* WR_DATA_DELAY */		| ((cke_min_clk & 0x7) << 6)		/* CKE_PLS */		| ((four_act & 0x1f) << 0)		/* FOUR_ACT */		);	debug("DDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2);	/*	 * Determine the Mode Register Set.	 *	 * This is nominally part specific, but it appears to be	 * consistent for all DDR I devices, and for all DDR II devices.	 *	 *     caslat must be programmed	 *     burst length is always 4	 *     burst type is sequential	 *	 * For DDR I:	 *     operating mode is "normal"	 *	 * For DDR II:	 *     other stuff	 */	mode_caslat = 0;	/*	 * Table lookup from DDR I or II Device Operation Specs.	 */	if (spd.mem_type == SPD_MEMTYPE_DDR) {		if (1 <= caslat && caslat <= 4) {			unsigned char mode_caslat_table[4] = {				0x5,	/* 1.5 clocks */				0x2,	/* 2.0 clocks */				0x6,	/* 2.5 clocks */				0x3	/* 3.0 clocks */			};			mode_caslat = mode_caslat_table[caslat - 1];		} else {			puts("DDR I: Only CAS Latencies of 1.5, 2.0, "			     "2.5 and 3.0 clocks are supported.\n");			return 0;		}	} else {		if (2 <= caslat && caslat <= 5) {			mode_caslat = caslat;		} else {			puts("DDR II: Only CAS Latencies of 2.0, 3.0, "			     "4.0 and 5.0 clocks are supported.\n");			return 0;		}	}	/*	 * Encoded Burst Length of 4.	 */	burst_len = 2;			/* Fiat. */	if (spd.mem_type == SPD_MEMTYPE_DDR) {		twr_auto_clk = 0;	/* Historical */	} else {		/*		 * Determine tCK max in picos.  Grab tWR and convert to picos.		 * Auto-precharge write recovery is:		 *	WR = roundup(tWR_ns/tCKmax_ns).		 *		 * Ponder: Is twr_auto_clk different than twr_clk?		 */		tCKmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd.tckmax);		twr_auto_clk = (spd.twr * 250 + tCKmax_ps - 1) / tCKmax_ps;	}	/*	 * Mode Reg in bits 16 ~ 31,	 * Extended Mode Reg 1 in bits 0 ~ 15.	 */	mode_odt_enable = 0x0;			/* Default disabled */	if (odt_wr_cfg || odt_rd_cfg) {		/*		 * Bits 6 and 2 in Extended MRS(1)		 * Bit 2 == 0x04 == 75 Ohm, with 2 DIMM modules.		 * Bit 6 == 0x40 == 150 Ohm, with 1 DIMM module.		 */		mode_odt_enable = 0x40;		/* 150 Ohm */	}	ddr->sdram_mode_1 =		(0		 | (add_lat << (16 + 3))	/* Additive Latency in EMRS1 */		 | (mode_odt_enable << 16)	/* ODT Enable in EMRS1 */		 | (twr_auto_clk << 9)		/* Write Recovery Autopre */		 | (mode_caslat << 4)		/* caslat */		 | (burst_len << 0)		/* Burst length */		 );	debug("DDR: sdram_mode   = 0x%08x\n", ddr->sdram_mode_1);	/*	 * Clear EMRS2 and EMRS3.	 */	ddr->sdram_mode_2 = 0;	debug("DDR: sdram_mode_2 = 0x%08x\n", ddr->sdram_mode_2);	/*	 * Determine Refresh Rate.	 */	refresh_clk = determine_refresh_rate(spd.refresh & 0x7);	/*	 * Set BSTOPRE to 0x100 for page mode	 * If auto-charge is used, set BSTOPRE = 0	 */	ddr->sdram_interval =		(0		 | (refresh_clk & 0x3fff) << 16		 | 0x100		 );	debug("DDR: sdram_interval = 0x%08x\n", ddr->sdram_interval);	/*	 * Is this an ECC DDR chip?	 * But don't mess with it if the DDR controller will init mem.	 */#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)	if (spd.config == 0x02) {		ddr->err_disable = 0x0000000d;		ddr->err_sbe = 0x00ff0000;	}	debug("DDR: err_disable = 0x%08x\n", ddr->err_disable);	debug("DDR: err_sbe = 0x%08x\n", ddr->err_sbe);#endif	asm volatile("sync;isync");	udelay(500);	/*	 * SDRAM Cfg 2	 */	/*	 * When ODT is enabled, Chap 9 suggests asserting ODT to	 * internal IOs only during reads.	 */	odt_cfg = 0;	if (odt_rd_cfg | odt_wr_cfg) {		odt_cfg = 0x2;		/* ODT to IOs during reads */	}	/*	 * Try to use differential DQS with DDR II.	 */	if (spd.mem_type == SPD_MEMTYPE_DDR) {		dqs_cfg = 0;		/* No Differential DQS for DDR I */	} else {		dqs_cfg = 0x1;		/* Differential DQS for DDR II */	}#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)	/*	 * Use the DDR controller to auto initialize memory.	 */	d_init = 1;	ddr->sdram_data_init = CONFIG_MEM_INIT_VALUE;	debug("DDR: ddr_data_init = 0x%08x\n", ddr->sdram_data_init);#else	/*	 * Memory will be initialized via DMA, or not at all.	 */	d_init = 0;#endif	ddr->sdram_cfg_2 = (0			    | (dqs_cfg << 26)	/* Differential DQS */

⌨️ 快捷键说明

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