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

📄 spd_sdram.c

📁 u-boot-1.1.6 源码包
💻 C
📖 第 1 页 / 共 2 页
字号:
	 */	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? */	}	/*	 * Empirically set ~MCAS-to-preamble override for DDR 2.	 * Your milage will vary.	 */	cpo = 0;	if (spd.mem_type == SPD_MEMTYPE_DDR2) {		if (effective_data_rate == 266 || effective_data_rate == 333) {			cpo = 0x7;		/* READ_LAT + 5/4 */		} else if (effective_data_rate == 400) {			cpo = 0x9;		/* READ_LAT + 7/4 */		} else {			/* Pure speculation */			cpo = 0xb;		}	}	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 Lenght 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 =		(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);	/*	 * 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("sync;isync;msync");	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 */			    | (odt_cfg << 21)	/* ODT */			    | (d_init << 4)	/* D_INIT auto init DDR */			    );	debug("DDR: sdram_cfg_2  = 0x%08x\n", ddr->sdram_cfg_2);#ifdef MPC85xx_DDR_SDRAM_CLK_CNTL	/*	 * Setup the clock control.	 * SDRAM_CLK_CNTL[0] = Source synchronous enable == 1	 * SDRAM_CLK_CNTL[5-7] = Clock Adjust	 *	0110	3/4 cycle late	 *	0111	7/8 cycle late	 */	if (spd.mem_type == SPD_MEMTYPE_DDR)		clk_adjust = 0x6;	else		clk_adjust = 0x7;	ddr->sdram_clk_cntl = (0			       | 0x80000000			       | (clk_adjust << 23)			       );	debug("DDR: sdram_clk_cntl = 0x%08x\n", ddr->sdram_clk_cntl);#endif	/*	 * Figure out the settings for the sdram_cfg register.	 * Build up the entire register in 'sdram_cfg' before writing	 * since the write into the register will actually enable the	 * memory controller; all settings must be done before enabling.	 *	 * sdram_cfg[0]   = 1 (ddr sdram logic enable)	 * sdram_cfg[1]   = 1 (self-refresh-enable)	 * sdram_cfg[5:7] = (SDRAM type = DDR SDRAM)	 *			010 DDR 1 SDRAM	 *			011 DDR 2 SDRAM	 */	sdram_type = (spd.mem_type == SPD_MEMTYPE_DDR) ? 2 : 3;	sdram_cfg = (0		     | (1 << 31)			/* Enable */		     | (1 << 30)			/* Self refresh */		     | (sdram_type << 24)		/* SDRAM type */		     );	/*	 * sdram_cfg[3] = RD_EN - registered DIMM enable	 *   A value of 0x26 indicates micron registered DIMMS (micron.com)	 */	if (spd.mem_type == SPD_MEMTYPE_DDR && spd.mod_attr == 0x26) {		sdram_cfg |= 0x10000000;		/* RD_EN */	}#if defined(CONFIG_DDR_ECC)	/*	 * If the user wanted ECC (enabled via sdram_cfg[2])	 */	if (spd.config == 0x02) {		sdram_cfg |= 0x20000000;		/* ECC_EN */	}#endif	/*	 * REV1 uses 1T timing.	 * REV2 may use 1T or 2T as configured by the user.	 */	{		uint pvr = get_pvr();		if (pvr != PVR_85xx_REV1) {#if defined(CONFIG_DDR_2T_TIMING)			/*			 * Enable 2T timing by setting sdram_cfg[16].			 */			sdram_cfg |= 0x8000;		/* 2T_EN */#endif		}	}	/*	 * 200 painful micro-seconds must elapse between	 * the DDR clock setup and the DDR config enable.	 */	udelay(200);	/*	 * Go!	 */	ddr->sdram_cfg = sdram_cfg;	asm("sync;isync;msync");	udelay(500);	debug("DDR: sdram_cfg   = 0x%08x\n", ddr->sdram_cfg);#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)	/*	 * Poll until memory is initialized.	 * 512 Meg at 400 might hit this 200 times or so.	 */	while ((ddr->sdram_cfg_2 & (d_init << 4)) != 0) {		udelay(1000);	}#endif	/*	 * Figure out memory size in Megabytes.	 */	memsize = n_ranks * rank_density / 0x100000;	/*	 * Establish Local Access Window and TLB mappings for DDR memory.	 */	memsize = setup_laws_and_tlbs(memsize);	if (memsize == 0) {		return 0;	}	return memsize * 1024 * 1024;}/* * Setup Local Access Window and TLB1 mappings for the requested * amount of memory.  Returns the amount of memory actually mapped * (usually the original request size), or 0 on error. */static unsigned intsetup_laws_and_tlbs(unsigned int memsize){	volatile immap_t *immap = (immap_t *)CFG_IMMR;	volatile ccsr_local_ecm_t *ecm = &immap->im_local_ecm;	unsigned int tlb_size;	unsigned int law_size;	unsigned int ram_tlb_index;	unsigned int ram_tlb_address;	/*	 * Determine size of each TLB1 entry.	 */	switch (memsize) {	case 16:	case 32:		tlb_size = BOOKE_PAGESZ_16M;		break;	case 64:	case 128:		tlb_size = BOOKE_PAGESZ_64M;		break;	case 256:	case 512:	case 1024:	case 2048:		tlb_size = BOOKE_PAGESZ_256M;		break;	default:		puts("DDR: only 16M,32M,64M,128M,256M,512M,1G and 2G are supported.\n");		/*		 * The memory was not able to be mapped.		 */		return 0;		break;	}	/*	 * Configure DDR TLB1 entries.	 * Starting at TLB1 8, use no more than 8 TLB1 entries.	 */	ram_tlb_index = 8;	ram_tlb_address = (unsigned int)CFG_DDR_SDRAM_BASE;	while (ram_tlb_address < (memsize * 1024 * 1024)	      && ram_tlb_index < 16) {		mtspr(MAS0, TLB1_MAS0(1, ram_tlb_index, 0));		mtspr(MAS1, TLB1_MAS1(1, 1, 0, 0, tlb_size));		mtspr(MAS2, TLB1_MAS2(E500_TLB_EPN(ram_tlb_address),				      0, 0, 0, 0, 0, 0, 0, 0));		mtspr(MAS3, TLB1_MAS3(E500_TLB_RPN(ram_tlb_address),				      0, 0, 0, 0, 0, 1, 0, 1, 0, 1));		asm volatile("isync;msync;tlbwe;isync");		debug("DDR: MAS0=0x%08x\n", TLB1_MAS0(1, ram_tlb_index, 0));		debug("DDR: MAS1=0x%08x\n", TLB1_MAS1(1, 1, 0, 0, tlb_size));		debug("DDR: MAS2=0x%08x\n",		      TLB1_MAS2(E500_TLB_EPN(ram_tlb_address),				0, 0, 0, 0, 0, 0, 0, 0));		debug("DDR: MAS3=0x%08x\n",		      TLB1_MAS3(E500_TLB_RPN(ram_tlb_address),				0, 0, 0, 0, 0, 1, 0, 1, 0, 1));		ram_tlb_address += (0x1000 << ((tlb_size - 1) * 2));		ram_tlb_index++;	}	/*	 * First supported LAW size is 16M, at LAWAR_SIZE_16M == 23.  Fnord.	 */	law_size = 19 + __ilog2(memsize);	/*	 * Set up LAWBAR for all of DDR.	 */	ecm->lawbar1 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff);	ecm->lawar1 = (LAWAR_EN		       | LAWAR_TRGT_IF_DDR		       | (LAWAR_SIZE & law_size));	debug("DDR: LAWBAR1=0x%08x\n", ecm->lawbar1);	debug("DDR: LARAR1=0x%08x\n", ecm->lawar1);	/*	 * Confirm that the requested amount of memory was mapped.	 */	return memsize;}#endif /* CONFIG_SPD_EEPROM */#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)/* * Initialize all of memory for ECC, then enable errors. */voidddr_enable_ecc(unsigned int dram_size){	uint *p = 0;	uint i = 0;	volatile immap_t *immap = (immap_t *)CFG_IMMR;	volatile ccsr_ddr_t *ddr= &immap->im_ddr;	dma_init();	for (*p = 0; p < (uint *)(8 * 1024); p++) {		if (((unsigned int)p & 0x1f) == 0) {			ppcDcbz((unsigned long) p);		}		*p = (unsigned int)CONFIG_MEM_INIT_VALUE;		if (((unsigned int)p & 0x1c) == 0x1c) {			ppcDcbf((unsigned long) p);		}	}	dma_xfer((uint *)0x002000, 0x002000, (uint *)0); /* 8K */	dma_xfer((uint *)0x004000, 0x004000, (uint *)0); /* 16K */	dma_xfer((uint *)0x008000, 0x008000, (uint *)0); /* 32K */	dma_xfer((uint *)0x010000, 0x010000, (uint *)0); /* 64K */	dma_xfer((uint *)0x020000, 0x020000, (uint *)0); /* 128k */	dma_xfer((uint *)0x040000, 0x040000, (uint *)0); /* 256k */	dma_xfer((uint *)0x080000, 0x080000, (uint *)0); /* 512k */	dma_xfer((uint *)0x100000, 0x100000, (uint *)0); /* 1M */	dma_xfer((uint *)0x200000, 0x200000, (uint *)0); /* 2M */	dma_xfer((uint *)0x400000, 0x400000, (uint *)0); /* 4M */	for (i = 1; i < dram_size / 0x800000; i++) {		dma_xfer((uint *)(0x800000*i), 0x800000, (uint *)0);	}	/*	 * Enable errors for ECC.	 */	debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);	ddr->err_disable = 0x00000000;	asm("sync;isync;msync");	debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);}#endif	/* CONFIG_DDR_ECC  && ! CONFIG_ECC_INIT_VIA_DDRCONTROLLER */

⌨️ 快捷键说明

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