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

📄 spd_sdram.c

📁 u-boot-1.1.6 源码包
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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#endif/* * Only one of the following three should be 1; others should be 0 * By default the cache line interleaving is selected if * the CONFIG_DDR_INTERLEAVE flag is defined */#define CFG_PAGE_INTERLEAVING		0#define CFG_BANK_INTERLEAVING		0#define CFG_SUPER_BANK_INTERLEAVING	0/* * 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,		660,		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;}/* * Determine Refresh Rate.  Ignore self refresh bit on DDR I. * Table from SPD Spec, Byte 12, converted to picoseconds and * filled in with "default" normal values. */unsigned int determine_refresh_rate(unsigned int spd_refresh){	unsigned int refresh_time_ns[8] = {		15625000,	/* 0 Normal    1.00x */		3900000,	/* 1 Reduced    .25x */		7800000,	/* 2 Extended   .50x */		31300000,	/* 3 Extended  2.00x */		62500000,	/* 4 Extended  4.00x */		125000000,	/* 5 Extended  8.00x */		15625000,	/* 6 Normal    1.00x  filler */		15625000,	/* 7 Normal    1.00x  filler */	};	return picos_to_clk(refresh_time_ns[spd_refresh & 0x7]);}long intspd_init(unsigned char i2c_address, unsigned int ddr_num,	 unsigned int dimm_num, unsigned int start_addr){	volatile immap_t *immap = (immap_t *)CFG_IMMR;	volatile ccsr_ddr_t *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 refresh_clk;#ifdef MPC86xx_DDR_SDRAM_CLK_CNTL	unsigned char clk_adjust;#endif	unsigned int dqs_cfg;	unsigned char twr_clk, twtr_clk, twr_auto_clk;	unsigned int tCKmin_ps, tCKmax_ps;	unsigned int max_data_rate;	unsigned int busfreq;	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 d_init;	unsigned int tCycle_ps, modfreq;	if (ddr_num == 1)		ddr = &immap->im_ddr1;	else		ddr = &immap->im_ddr2;	/*	 * Read SPD information.	 */	debug("Performing SPD read at I2C address 0x%02lx\n",i2c_address);	memset((void *)&spd, 0, sizeof(spd));	CFG_READ_SPD(i2c_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) {		debug("Warning: Unable to locate DDR I or DDR II module for DIMM %d of DDR controller %d.\n"		      "         Fundamental memory type is 0x%0x\n",		      dimm_num,		      ddr_num,		      spd.mem_type);		return 0;	}	debug("\nFound memory of type 0x%02lx  ", spd.mem_type);	if (spd.mem_type == SPD_MEMTYPE_DDR)		debug("DDR I\n");	else		debug("DDR II\n");	/*	 * 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);	debug("Start address for this controller is 0x%08lx\n", start_addr);	/*	 * 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 */	}#ifdef CONFIG_DDR_INTERLEAVE	if (dimm_num != 1) {		printf("For interleaving memory on HPCN, need to use DIMM 1 for DDR Controller %d !\n", ddr_num);		return 0;	} else {		/*		 * Since interleaved memory only uses CS0, the		 * memory sticks have to be identical in size and quantity		 * of ranks.  That essentially gives double the size on		 * one rank, i.e on CS0 for both controllers put together.		 * Confirm this???		 */		rank_density *= 2;		/*		 * Eg: Bounds: 0x0000_0000 to 0x0f000_0000	first 256 Meg		 */		start_addr = 0;		ddr->cs0_bnds = (start_addr >> 8)			| (((start_addr + rank_density - 1) >> 24));		/*		 * Default interleaving mode to cache-line interleaving.		 */		ddr->cs0_config = ( 1 << 31#if	(CFG_PAGE_INTERLEAVING == 1)				    | (PAGE_INTERLEAVING)#elif	(CFG_BANK_INTERLEAVING == 1)				    | (BANK_INTERLEAVING)#elif	(CFG_SUPER_BANK_INTERLEAVING == 1)				    | (SUPER_BANK_INTERLEAVING)#else				    | (CACHE_LINE_INTERLEAVING)#endif				    | (odt_rd_cfg << 20)				    | (odt_wr_cfg << 16)				    | (spd.nrow_addr - 12) << 8				    | (spd.ncol_addr - 8) );		debug("DDR: cs0_bnds   = 0x%08x\n", ddr->cs0_bnds);		debug("DDR: cs0_config = 0x%08x\n", ddr->cs0_config);		/*		 * Adjustment for dual rank memory to get correct memory		 * size (return value of this function).		 */		if (n_ranks == 2) {			n_ranks = 1;			rank_density /= 2;		} else {			rank_density /= 2;		}	}#else	/* CONFIG_DDR_INTERLEAVE */	if (dimm_num == 1) {		/*		 * Eg: Bounds: 0x0000_0000 to 0x0f000_0000	first 256 Meg		 */		ddr->cs0_bnds = (start_addr >> 8)			| (((start_addr + rank_density - 1) >> 24));		ddr->cs0_config = ( 1 << 31				    | (odt_rd_cfg << 20)				    | (odt_wr_cfg << 16)				    | (spd.nrow_addr - 12) << 8				    | (spd.ncol_addr - 8) );		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: 0x1000_0000 to 0x1f00_0000,			 * second 256 Meg			 */			ddr->cs1_bnds = (((start_addr + rank_density) >> 8)					| (( start_addr + 2*rank_density - 1)					   >> 24));			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);		}	} else {		/*		 * This is the 2nd DIMM slot for this controller		 */		/*		 * Eg: Bounds: 0x0000_0000 to 0x0f000_0000	first 256 Meg		 */		ddr->cs2_bnds = (start_addr >> 8)			| (((start_addr + rank_density - 1) >> 24));		ddr->cs2_config = ( 1 << 31				    | (odt_rd_cfg << 20)				    | (odt_wr_cfg << 16)				    | (spd.nrow_addr - 12) << 8				    | (spd.ncol_addr - 8) );		debug("DDR: cs2_bnds   = 0x%08x\n", ddr->cs2_bnds);		debug("DDR: cs2_config = 0x%08x\n", ddr->cs2_config);		if (n_ranks == 2) {			/*			 * Eg: Bounds: 0x1000_0000 to 0x1f00_0000,			 * second 256 Meg			 */			ddr->cs3_bnds = (((start_addr + rank_density) >> 8)					| (( start_addr + 2*rank_density - 1)					   >> 24));			ddr->cs3_config = ( 1<<31					    | (odt_rd_cfg << 20)					    | (odt_wr_cfg << 16)					    | (spd.nrow_addr - 12) << 8					    | (spd.ncol_addr - 8) );			debug("DDR: cs3_bnds   = 0x%08x\n", ddr->cs3_bnds);			debug("DDR: cs3_config = 0x%08x\n", ddr->cs3_config);		}	}#endif /* CONFIG_DDR_INTERLEAVE */	/*	 * Find the largest CAS by locating the highest 1 bit	 * in the spd.cas_lat field.  Translate it to a DDR	 * controller field value:

⌨️ 快捷键说明

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