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

📄 spd_sdram.c

📁 linux下的BOOT程序原码,有需要的可以来下,保证好用
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright 2004 Freescale Semiconductor. * (C) Copyright 2003 Motorola Inc. * Xianghua Xiao (X.Xiao@motorola.com) * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <asm/processor.h>#include <i2c.h>#include <spd.h>#include <asm/mmu.h>#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)extern void dma_init(void);extern uint dma_check(void);extern int dma_xfer(void *dest, uint count, void *src);#endif#ifdef CONFIG_SPD_EEPROM#ifndef	CFG_READ_SPD#define CFG_READ_SPD	i2c_read#endifstatic unsigned int setup_laws_and_tlbs(unsigned int memsize);/* * Convert picoseconds into clock cycles (rounding up if needed). */intpicos_to_clk(int picos){	int clks;	clks = picos / (2000000000 / (get_bus_freq(0) / 1000));	if (picos % (2000000000 / (get_bus_freq(0) / 1000)) != 0) {		clks++;	}	return clks;}/* * Calculate the Density of each Physical Rank. * Returned size is in bytes. * * Study these table from Byte 31 of JEDEC SPD Spec. * *		DDR I	DDR II *	Bit	Size	Size *	---	-----	------ *	7 high	512MB	512MB *	6	256MB	256MB *	5	128MB	128MB *	4	 64MB	 16GB *	3	 32MB	  8GB *	2	 16MB	  4GB *	1	  2GB	  2GB *	0 low	  1GB	  1GB * * Reorder Table to be linear by stripping the bottom * 2 or 5 bits off and shifting them up to the top. */unsigned intcompute_banksize(unsigned int mem_type, unsigned char row_dens){	unsigned int bsize;	if (mem_type == SPD_MEMTYPE_DDR) {		/* Bottom 2 bits up to the top. */		bsize = ((row_dens >> 2) | ((row_dens & 3) << 6)) << 24;		debug("DDR: DDR I rank density = 0x%08x\n", bsize);	} else {		/* Bottom 5 bits up to the top. */		bsize = ((row_dens >> 5) | ((row_dens & 31) << 3)) << 27;		debug("DDR: DDR II rank density = 0x%08x\n", bsize);	}	return bsize;}/* * Convert a two-nibble BCD value into a cycle time. * While the spec calls for nano-seconds, picos are returned. * * This implements the tables for bytes 9, 23 and 25 for both * DDR I and II.  No allowance for distinguishing the invalid * fields absent for DDR I yet present in DDR II is made. * (That is, cycle times of .25, .33, .66 and .75 ns are * allowed for both DDR II and I.) */unsigned intconvert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val){	/*	 * Table look up the lower nibble, allow DDR I & II.	 */	unsigned int tenths_ps[16] = {		0,		100,		200,		300,		400,		500,		600,		700,		800,		900,		250,		330,	/* FIXME: Is 333 better/valid? */		660,	/* FIXME: Is 667 better/valid? */		750,		0,	/* undefined */		0	/* undefined */	};	unsigned int whole_ns = (spd_val & 0xF0) >> 4;	unsigned int tenth_ns = spd_val & 0x0F;	unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns];	return ps;}long intspd_sdram(void){	volatile immap_t *immap = (immap_t *)CFG_IMMR;	volatile ccsr_ddr_t *ddr = &immap->im_ddr;	volatile ccsr_gur_t *gur = &immap->im_gur;	spd_eeprom_t spd;	unsigned int n_ranks;	unsigned int rank_density;	unsigned int odt_rd_cfg, odt_wr_cfg;	unsigned int odt_cfg, mode_odt_enable;	unsigned int dqs_cfg;	unsigned char twr_clk, twtr_clk, twr_auto_clk;	unsigned int tCKmin_ps, tCKmax_ps;	unsigned int max_data_rate, effective_data_rate;	unsigned int busfreq;	unsigned sdram_cfg;	unsigned int memsize;	unsigned char caslat, caslat_ctrl;	unsigned int trfc, trfc_clk, trfc_low, trfc_high;	unsigned int trcd_clk;	unsigned int trtp_clk;	unsigned char cke_min_clk;	unsigned char add_lat;	unsigned char wr_lat;	unsigned char wr_data_delay;	unsigned char four_act;	unsigned char cpo;	unsigned char burst_len;	unsigned int mode_caslat;	unsigned char sdram_type;	unsigned char d_init;	/*	 * Read SPD information.	 */	CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) &spd, sizeof(spd));	/*	 * Check for supported memory module types.	 */	if (spd.mem_type != SPD_MEMTYPE_DDR &&	    spd.mem_type != SPD_MEMTYPE_DDR2) {		printf("Unable to locate DDR I or DDR II module.\n"		       "    Fundamental memory type is 0x%0x\n",		       spd.mem_type);		return 0;	}	/*	 * These test gloss over DDR I and II differences in interpretation	 * of bytes 3 and 4, but irrelevantly.  Multiple asymmetric banks	 * are not supported on DDR I; and not encoded on DDR II.	 *	 * Also note that the 8548 controller can support:	 *    12 <= nrow <= 16	 * and	 *     8 <= ncol <= 11 (still, for DDR)	 *     6 <= ncol <=  9 (for FCRAM)	 */	if (spd.nrow_addr < 12 || spd.nrow_addr > 14) {		printf("DDR: Unsupported number of Row Addr lines: %d.\n",		       spd.nrow_addr);		return 0;	}	if (spd.ncol_addr < 8 || spd.ncol_addr > 11) {		printf("DDR: Unsupported number of Column Addr lines: %d.\n",		       spd.ncol_addr);		return 0;	}	/*	 * Determine the number of physical banks controlled by	 * different Chip Select signals.  This is not quite the	 * same as the number of DIMM modules on the board.  Feh.	 */	if (spd.mem_type == SPD_MEMTYPE_DDR) {		n_ranks = spd.nrows;	} else {		n_ranks = (spd.nrows & 0x7) + 1;	}	debug("DDR: number of ranks = %d\n", n_ranks);	if (n_ranks > 2) {		printf("DDR: Only 2 chip selects are supported: %d\n",		       n_ranks);		return 0;	}	/*	 * Adjust DDR II IO voltage biasing.  It just makes it work.	 */	if (spd.mem_type == SPD_MEMTYPE_DDR2) {		gur->ddrioovcr = (0				  | 0x80000000		/* Enable */				  | 0x10000000		/* VSEL to 1.8V */				  );	}	/*	 * Determine the size of each Rank in bytes.	 */	rank_density = compute_banksize(spd.mem_type, spd.row_dens);	/*	 * Eg: Bounds: 0x0000_0000 to 0x0f000_0000	first 256 Meg	 */	ddr->cs0_bnds = (rank_density >> 24) - 1;	/*	 * ODT configuration recommendation from DDR Controller Chapter.	 */	odt_rd_cfg = 0;			/* Never assert ODT */	odt_wr_cfg = 0;			/* Never assert ODT */	if (spd.mem_type == SPD_MEMTYPE_DDR2) {		odt_wr_cfg = 1;		/* Assert ODT on writes to CS0 */#if 0		/* FIXME: How to determine the number of dimm modules? */		if (n_dimm_modules == 2) {			odt_rd_cfg = 1;	/* Assert ODT on reads to CS0 */		}#endif	}	ddr->cs0_config = ( 1 << 31			    | (odt_rd_cfg << 20)			    | (odt_wr_cfg << 16)			    | (spd.nrow_addr - 12) << 8			    | (spd.ncol_addr - 8) );	debug("\n");	debug("DDR: cs0_bnds   = 0x%08x\n", ddr->cs0_bnds);	debug("DDR: cs0_config = 0x%08x\n", ddr->cs0_config);	if (n_ranks == 2) {		/*		 * Eg: Bounds: 0x0f00_0000 to 0x1e0000_0000, second 256 Meg		 */		ddr->cs1_bnds = ( (rank_density >> 8)				  | ((rank_density >> (24 - 1)) - 1) );		ddr->cs1_config = ( 1<<31				    | (odt_rd_cfg << 20)				    | (odt_wr_cfg << 16)				    | (spd.nrow_addr - 12) << 8				    | (spd.ncol_addr - 8) );		debug("DDR: cs1_bnds   = 0x%08x\n", ddr->cs1_bnds);		debug("DDR: cs1_config = 0x%08x\n", ddr->cs1_config);	}	/*	 * Find the largest CAS by locating the highest 1 bit	 * in the spd.cas_lat field.  Translate it to a DDR	 * controller field value:	 *	 *	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 */	effective_data_rate = max_data_rate;	if (busfreq < 90) {		/* DDR rate out-of-range */		puts("DDR: platform frequency is not fit for DDR rate\n");		return 0;	} else if (90 <= busfreq && busfreq < 230 && max_data_rate >= 230) {		/*		 * busfreq 90~230 range, treated as DDR 200.		 */		effective_data_rate = 200;		if (spd.clk_cycle3 == 0xa0)	/* 10 ns */			caslat -= 2;		else if (spd.clk_cycle2 == 0xa0)			caslat--;	} else if (230 <= busfreq && busfreq < 280 && max_data_rate >= 280) {		/*		 * busfreq 230~280 range, treated as DDR 266.		 */		effective_data_rate = 266;		if (spd.clk_cycle3 == 0x75)	/* 7.5 ns */			caslat -= 2;		else if (spd.clk_cycle2 == 0x75)			caslat--;	} else if (280 <= busfreq && busfreq < 350 && max_data_rate >= 350) {		/*		 * busfreq 280~350 range, treated as DDR 333.		 */		effective_data_rate = 333;		if (spd.clk_cycle3 == 0x60)	/* 6.0 ns */			caslat -= 2;		else if (spd.clk_cycle2 == 0x60)			caslat--;	} else if (350 <= busfreq && busfreq < 460 && max_data_rate >= 460) {		/*		 * busfreq 350~460 range, treated as DDR 400.		 */		effective_data_rate = 400;		if (spd.clk_cycle3 == 0x50)	/* 5.0 ns */			caslat -= 2;		else if (spd.clk_cycle2 == 0x50)			caslat--;	} else if (460 <= busfreq && busfreq < 560 && max_data_rate >= 560) {		/*		 * busfreq 460~560 range, treated as DDR 533.		 */		effective_data_rate = 533;		if (spd.clk_cycle3 == 0x3D)	/* 3.75 ns */			caslat -= 2;		else if (spd.clk_cycle2 == 0x3D)			caslat--;	} else if (560 <= busfreq && busfreq < 700 && max_data_rate >= 700) {		/*		 * busfreq 560~700 range, treated as DDR 667.		 */		effective_data_rate = 667;		if (spd.clk_cycle3 == 0x30)	/* 3.0 ns */			caslat -= 2;		else if (spd.clk_cycle2 == 0x30)			caslat--;	} else if (700 <= busfreq) {		/*		 * DDR rate out-of-range		 */		printf("DDR: Bus freq %d MHz is not fit for DDR rate %d MHz\n",		     busfreq, max_data_rate);		return 0;	}	/*	 * 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: effective data rate is %d MHz\n", effective_data_rate);	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 */			);#if 0		ddr->timing_cfg_0 |= 0xaa000000;	/* extra cycles */#endif		debug("DDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);	} else {#if 0		/*		 * Force extra cycles with 0xaa bits.		 * Incidentally supply the dreamt-up backwards compat value!		 */		ddr->timing_cfg_0 = 0x00110105;	/* backwards compat value */		ddr->timing_cfg_0 |= 0xaa000000;	/* extra cycles */		debug("DDR: HACK timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);#endif	}	/*	 * 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;	 */

⌨️ 快捷键说明

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