ctrl_regs.c

来自「最新版的u-boot,2008-10-18发布」· C语言 代码 · 共 996 行 · 第 1/2 页

C
996
字号
	 * sdmode and esdmode passed in as part of common_dimm.	 */	/* Extended Mode Register */	unsigned int mrs = 0;		/* Mode Register Set */	unsigned int outputs = 0;	/* 0=Enabled, 1=Disabled */	unsigned int rdqs_en = 0;	/* RDQS Enable: 0=no, 1=yes */	unsigned int dqs_en = 0;	/* DQS# Enable: 0=enable, 1=disable */	unsigned int ocd = 0;		/* 0x0=OCD not supported,					   0x7=OCD default state */	unsigned int rtt;	unsigned int al;		/* Posted CAS# additive latency (AL) */	unsigned int ods = 0;		/* Output Drive Strength:						0 = Full strength (18ohm)						1 = Reduced strength (4ohm) */	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),						       1=Disable (Test/Debug) */	/* Mode Register (MR) */	unsigned int mr;	/* Mode Register Definition */	unsigned int pd;	/* Power-Down Mode */	unsigned int wr;	/* Write Recovery */	unsigned int dll_res;	/* DLL Reset */	unsigned int mode;	/* Normal=0 or Test=1 */	unsigned int caslat = 0;/* CAS# latency */	/* BT: Burst Type (0=Sequential, 1=Interleaved) */	unsigned int bt;	unsigned int bl;	/* BL: Burst Length */#if defined(CONFIG_FSL_DDR2)	const unsigned int mclk_ps = get_memory_clk_period_ps();#endif	rtt = fsl_ddr_get_rtt();	al = additive_latency;	esdmode = (0		| ((mrs & 0x3) << 14)		| ((outputs & 0x1) << 12)		| ((rdqs_en & 0x1) << 11)		| ((dqs_en & 0x1) << 10)		| ((ocd & 0x7) << 7)		| ((rtt & 0x2) << 5)   /* rtt field is split */		| ((al & 0x7) << 3)		| ((rtt & 0x1) << 2)   /* rtt field is split */		| ((ods & 0x1) << 1)		| ((dll_en & 0x1) << 0)		);	mr = 0;		 /* FIXME: CHECKME */	/*	 * 0 = Fast Exit (Normal)	 * 1 = Slow Exit (Low Power)	 */	pd = 0;#if defined(CONFIG_FSL_DDR1)	wr = 0;       /* Historical */#elif defined(CONFIG_FSL_DDR2)	wr = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps - 1;#else#error "Write tWR_auto for DDR3"#endif	dll_res = 0;	mode = 0;#if defined(CONFIG_FSL_DDR1)	if (1 <= cas_latency && cas_latency <= 4) {		unsigned char mode_caslat_table[4] = {			0x5,	/* 1.5 clocks */			0x2,	/* 2.0 clocks */			0x6,	/* 2.5 clocks */			0x3	/* 3.0 clocks */		};		caslat = mode_caslat_table[cas_latency - 1];	} else {		printf("Warning: unknown cas_latency %d\n", cas_latency);	}#elif defined(CONFIG_FSL_DDR2)	caslat = cas_latency;#else#error "Fix the mode CAS Latency for DDR3"#endif	bt = 0;	switch (popts->burst_length) {	case 4:		bl = 2;		break;	case 8:		bl = 3;		break;	default:		printf("Error: invalid burst length of %u specified. "			" Defaulting to 4 beats.\n",			popts->burst_length);		bl = 2;		break;	}	sdmode = (0		  | ((mr & 0x3) << 14)		  | ((pd & 0x1) << 12)		  | ((wr & 0x7) << 9)		  | ((dll_res & 0x1) << 8)		  | ((mode & 0x1) << 7)		  | ((caslat & 0x7) << 4)		  | ((bt & 0x1) << 3)		  | ((bl & 0x7) << 0)		  );	ddr->ddr_sdram_mode = (0			       | ((esdmode & 0xFFFF) << 16)			       | ((sdmode & 0xFFFF) << 0)			       );}/* DDR SDRAM Data Initialization (DDR_DATA_INIT) */static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr){	unsigned int init_value;	/* Initialization value */	init_value = 0xDEADBEEF;	ddr->ddr_data_init = init_value;}/* * DDR SDRAM Clock Control (DDR_SDRAM_CLK_CNTL) * The old controller on the 8540/60 doesn't have this register. * Hope it's OK to set it (to 0) anyway. */static void set_ddr_sdram_clk_cntl(fsl_ddr_cfg_regs_t *ddr,					 const memctl_options_t *popts){	unsigned int clk_adjust;	/* Clock adjust */	clk_adjust = popts->clk_adjust;	ddr->ddr_sdram_clk_cntl = (clk_adjust & 0xF) << 23;}/* DDR Initialization Address (DDR_INIT_ADDR) */static void set_ddr_init_addr(fsl_ddr_cfg_regs_t *ddr){	unsigned int init_addr = 0;	/* Initialization address */	ddr->ddr_init_addr = init_addr;}/* DDR Initialization Address (DDR_INIT_EXT_ADDR) */static void set_ddr_init_ext_addr(fsl_ddr_cfg_regs_t *ddr){	unsigned int uia = 0;	/* Use initialization address */	unsigned int init_ext_addr = 0;	/* Initialization address */	ddr->ddr_init_ext_addr = (0				  | ((uia & 0x1) << 31)				  | (init_ext_addr & 0xF)				  );}/* DDR SDRAM Timing Configuration 4 (TIMING_CFG_4) */static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr){	unsigned int rwt = 0; /* Read-to-write turnaround for same CS */	unsigned int wrt = 0; /* Write-to-read turnaround for same CS */	unsigned int rrt = 0; /* Read-to-read turnaround for same CS */	unsigned int wwt = 0; /* Write-to-write turnaround for same CS */	unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */	ddr->timing_cfg_4 = (0			     | ((rwt & 0xf) << 28)			     | ((wrt & 0xf) << 24)			     | ((rrt & 0xf) << 20)			     | ((wwt & 0xf) << 16)			     | (dll_lock & 0x3)			     );}/* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr){	unsigned int rodt_on = 0;	/* Read to ODT on */	unsigned int rodt_off = 0;	/* Read to ODT off */	unsigned int wodt_on = 0;	/* Write to ODT on */	unsigned int wodt_off = 0;	/* Write to ODT off */	ddr->timing_cfg_5 = (0			     | ((rodt_on & 0xf) << 24)			     | ((rodt_off & 0xf) << 20)			     | ((wodt_on & 0xf) << 12)			     | ((wodt_off & 0xf) << 8)			     );}/* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr){	unsigned int zq_en = 0;	/* ZQ Calibration Enable */	unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */	/* Normal Operation Full Calibration Time (tZQoper) */	unsigned int zqoper = 0;	/* Normal Operation Short Calibration Time (tZQCS) */	unsigned int zqcs = 0;	ddr->ddr_zq_cntl = (0			    | ((zq_en & 0x1) << 31)			    | ((zqinit & 0xF) << 24)			    | ((zqoper & 0xF) << 16)			    | ((zqcs & 0xF) << 8)			    );}/* DDR Write Leveling Control (DDR_WRLVL_CNTL) */static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr){	unsigned int wrlvl_en = 0; /* Write Leveling Enable */	/*	 * First DQS pulse rising edge after margining mode	 * is programmed (tWL_MRD)	 */	unsigned int wrlvl_mrd = 0;	/* ODT delay after margining mode is programmed (tWL_ODTEN) */	unsigned int wrlvl_odten = 0;	/* DQS/DQS_ delay after margining mode is programmed (tWL_DQSEN) */	unsigned int wrlvl_dqsen = 0;	/* WRLVL_SMPL: Write leveling sample time */	unsigned int wrlvl_smpl = 0;	/* WRLVL_WLR: Write leveling repeition time */	unsigned int wrlvl_wlr = 0;	/* WRLVL_START: Write leveling start time */	unsigned int wrlvl_start = 0;	ddr->ddr_wrlvl_cntl = (0			       | ((wrlvl_en & 0x1) << 31)			       | ((wrlvl_mrd & 0x7) << 24)			       | ((wrlvl_odten & 0x7) << 20)			       | ((wrlvl_dqsen & 0x7) << 16)			       | ((wrlvl_smpl & 0xf) << 12)			       | ((wrlvl_wlr & 0x7) << 8)			       | ((wrlvl_start & 0xF) << 0)			       );}/* DDR Self Refresh Counter (DDR_SR_CNTR) */static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr){	unsigned int sr_it = 0;	/* Self Refresh Idle Threshold */	ddr->ddr_sr_cntr = (sr_it & 0xF) << 16;}/* DDR Pre-Drive Conditioning Control (DDR_PD_CNTL) */static void set_ddr_pd_cntl(fsl_ddr_cfg_regs_t *ddr){	/* Termination value during pre-drive conditioning */	unsigned int tvpd = 0;	unsigned int pd_en = 0;		/* Pre-Drive Conditioning Enable */	unsigned int pdar = 0;		/* Pre-Drive After Read */	unsigned int pdaw = 0;		/* Pre-Drive After Write */	unsigned int pd_on = 0;		/* Pre-Drive Conditioning On */	unsigned int pd_off = 0;	/* Pre-Drive Conditioning Off */	ddr->ddr_pd_cntl = (0			    | ((pd_en & 0x1) << 31)			    | ((tvpd & 0x7) << 28)			    | ((pdar & 0x7F) << 20)			    | ((pdaw & 0x7F) << 12)			    | ((pd_on & 0x1F) << 6)			    | ((pd_off & 0x1F) << 0)			    );}/* DDR SDRAM Register Control Word 1 (DDR_SDRAM_RCW_1) */static void set_ddr_sdram_rcw_1(fsl_ddr_cfg_regs_t *ddr){	unsigned int rcw0 = 0;	/* RCW0: Register Control Word 0 */	unsigned int rcw1 = 0;	/* RCW1: Register Control Word 1 */	unsigned int rcw2 = 0;	/* RCW2: Register Control Word 2 */	unsigned int rcw3 = 0;	/* RCW3: Register Control Word 3 */	unsigned int rcw4 = 0;	/* RCW4: Register Control Word 4 */	unsigned int rcw5 = 0;	/* RCW5: Register Control Word 5 */	unsigned int rcw6 = 0;	/* RCW6: Register Control Word 6 */	unsigned int rcw7 = 0;	/* RCW7: Register Control Word 7 */	ddr->ddr_sdram_rcw_1 = (0				| ((rcw0 & 0xF) << 28)				| ((rcw1 & 0xF) << 24)				| ((rcw2 & 0xF) << 20)				| ((rcw3 & 0xF) << 16)				| ((rcw4 & 0xF) << 12)				| ((rcw5 & 0xF) << 8)				| ((rcw6 & 0xF) << 4)				| ((rcw7 & 0xF) << 0)				);}/* DDR SDRAM Register Control Word 2 (DDR_SDRAM_RCW_2) */static void set_ddr_sdram_rcw_2(fsl_ddr_cfg_regs_t *ddr){	unsigned int rcw8 = 0;	/* RCW0: Register Control Word 8 */	unsigned int rcw9 = 0;	/* RCW1: Register Control Word 9 */	unsigned int rcw10 = 0;	/* RCW2: Register Control Word 10 */	unsigned int rcw11 = 0;	/* RCW3: Register Control Word 11 */	unsigned int rcw12 = 0;	/* RCW4: Register Control Word 12 */	unsigned int rcw13 = 0;	/* RCW5: Register Control Word 13 */	unsigned int rcw14 = 0;	/* RCW6: Register Control Word 14 */	unsigned int rcw15 = 0;	/* RCW7: Register Control Word 15 */	ddr->ddr_sdram_rcw_2 = (0				| ((rcw8 & 0xF) << 28)				| ((rcw9 & 0xF) << 24)				| ((rcw10 & 0xF) << 20)				| ((rcw11 & 0xF) << 16)				| ((rcw12 & 0xF) << 12)				| ((rcw13 & 0xF) << 8)				| ((rcw14 & 0xF) << 4)				| ((rcw15 & 0xF) << 0)				);}unsigned intcheck_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr){	unsigned int res = 0;	/*	 * Check that DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] are	 * not set at the same time.	 */	if (ddr->ddr_sdram_cfg & 0x10000000	    && ddr->ddr_sdram_cfg & 0x00008000) {		printf("Error: DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] "				" should not be set at the same time.\n");		res++;	}	return res;}unsigned intcompute_fsl_memctl_config_regs(const memctl_options_t *popts,			       fsl_ddr_cfg_regs_t *ddr,			       const common_timing_params_t *common_dimm,			       const dimm_params_t *dimm_params,			       unsigned int dbw_cap_adj){	unsigned int i;	unsigned int cas_latency;	unsigned int additive_latency;	memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t));	if (common_dimm == NULL) {		printf("Error: subset DIMM params struct null pointer\n");		return 1;	}	/*	 * Process overrides first.	 *	 * FIXME: somehow add dereated caslat to this	 */	cas_latency = (popts->cas_latency_override)		? popts->cas_latency_override_value		: common_dimm->lowest_common_SPD_caslat;	additive_latency = (popts->additive_latency_override)		? popts->additive_latency_override_value		: common_dimm->additive_latency;	/* Chip Select Memory Bounds (CSn_BNDS) */	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {		phys_size_t sa = 0;		phys_size_t ea = 0;		if (popts->ba_intlv_ctl && i > 0) {			/* Don't set up boundaries if bank interleaving */			break;		}		if (dimm_params[i/2].n_ranks == 0) {			debug("Skipping setup of CS%u "				"because n_ranks on DIMM %u is 0\n", i, i/2);			continue;		}		if (popts->memctl_interleaving && popts->ba_intlv_ctl) {			/*			 * This works superbank 2CS			 * There are 2 memory controllers configured			 * identically, memory is interleaved between them,			 * and each controller uses rank interleaving within			 * itself. Therefore the starting and ending address			 * on each controller is twice the amount present on			 * each controller.			 */			ea = (2 * common_dimm->total_mem >> dbw_cap_adj) - 1;		}		else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) {			/*			 * If memory interleaving between controllers is NOT			 * enabled, the starting address for each memory			 * controller is distinct.  However, because rank			 * interleaving is enabled, the starting and ending			 * addresses of the total memory on that memory			 * controller needs to be programmed into its			 * respective CS0_BNDS.			 */			sa = common_dimm->base_address;			ea = sa + (common_dimm->total_mem >> dbw_cap_adj) - 1;		}		else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) {			/*			 * Only the rank on CS0 of each memory controller may			 * be used if memory controller interleaving is used			 * without rank interleaving within each memory			 * controller.  However, the ending address programmed			 * into each CS0 must be the sum of the amount of			 * memory in the two CS0 ranks.			 */			if (i == 0) {				unsigned long long rank_density						= dimm_params[0].rank_density;				ea = (2 * (rank_density >> dbw_cap_adj)) - 1;			}		}		else if (!popts->memctl_interleaving && !popts->ba_intlv_ctl) {			/*			 * No rank interleaving and no memory controller			 * interleaving.			 */			unsigned long long rank_density						= dimm_params[i/2].rank_density;			sa = dimm_params[i/2].base_address;			ea = sa + (rank_density >> dbw_cap_adj) - 1;			if (i&1) {				if ((dimm_params[i/2].n_ranks == 1)) {					/* Odd chip select, single-rank dimm */					sa = 0;					ea = 0;				} else {					/* Odd chip select, dual-rank DIMM */					sa += rank_density >> dbw_cap_adj;					ea += rank_density >> dbw_cap_adj;				}			}		}		sa >>= 24;		ea >>= 24;		ddr->cs[i].bnds = (0			| ((sa & 0xFFF) << 16)	/* starting address MSB */			| ((ea & 0xFFF) << 0)	/* ending address MSB */			);		set_csn_config(i, ddr, popts, dimm_params);		set_csn_config_2(i, ddr);	}#if defined(CONFIG_FSL_DDR2)	set_timing_cfg_0(ddr);#endif	set_timing_cfg_3(ddr, common_dimm);	set_timing_cfg_1(ddr, common_dimm, cas_latency);	set_timing_cfg_2(ddr, popts, common_dimm,				cas_latency, additive_latency);	set_ddr_sdram_cfg(ddr, popts, common_dimm);	set_ddr_sdram_cfg_2(ddr, popts);	set_ddr_sdram_mode(ddr, popts, common_dimm,				cas_latency, additive_latency);	set_ddr_sdram_mode_2(ddr);	set_ddr_sdram_interval(ddr, popts, common_dimm);	set_ddr_data_init(ddr);	set_ddr_sdram_clk_cntl(ddr, popts);	set_ddr_init_addr(ddr);	set_ddr_init_ext_addr(ddr);	set_timing_cfg_4(ddr);	set_timing_cfg_5(ddr);	set_ddr_zq_cntl(ddr);	set_ddr_wrlvl_cntl(ddr);	set_ddr_pd_cntl(ddr);	set_ddr_sr_cntr(ddr);	set_ddr_sdram_rcw_1(ddr);	set_ddr_sdram_rcw_2(ddr);	return check_fsl_memctl_config_regs(ddr);}

⌨️ 快捷键说明

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