Skip to content
Snippets Groups Projects
ctrl_regs.c 69.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • 			esdmode2 |= (rtt_wr & 0x3) << 9;
    			switch (i) {
    			case 1:
    				ddr->ddr_sdram_mode_4 = (0
    					| ((esdmode2 & 0xFFFF) << 16)
    					| ((esdmode3 & 0xFFFF) << 0)
    					);
    				break;
    			case 2:
    				ddr->ddr_sdram_mode_6 = (0
    					| ((esdmode2 & 0xFFFF) << 16)
    					| ((esdmode3 & 0xFFFF) << 0)
    					);
    				break;
    			case 3:
    				ddr->ddr_sdram_mode_8 = (0
    					| ((esdmode2 & 0xFFFF) << 16)
    					| ((esdmode3 & 0xFFFF) << 0)
    					);
    				break;
    			}
    		}
    		debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_4);
    		debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_6);
    		debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_8);
    	}
    }
    #elif defined(CONFIG_SYS_FSL_DDR3)
    /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
    
    static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
    				fsl_ddr_cfg_regs_t *ddr,
    
    				const memctl_options_t *popts,
    				const common_timing_params_t *common_dimm,
    				const unsigned int unq_mrs_en)
    {
    	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
    	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
    
    	unsigned int rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
    
    	unsigned int srt = 0;	/* self-refresh temerature, normal range */
    	unsigned int asr = 0;	/* auto self-refresh disable */
    
    	unsigned int cwl = compute_cas_write_latency(ctrl_num) - 5;
    
    	unsigned int pasr = 0;	/* partial array self refresh disable */
    
    
    	if (popts->rtt_override)
    		rtt_wr = popts->rtt_wr_override_value;
    
    	else
    		rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
    
    
    	if (common_dimm->extended_op_srt)
    		srt = common_dimm->extended_op_srt;
    
    
    	esdmode2 = (0
    		| ((rtt_wr & 0x3) << 9)
    		| ((srt & 0x1) << 7)
    		| ((asr & 0x1) << 6)
    		| ((cwl & 0x7) << 3)
    		| ((pasr & 0x7) << 0));
    
    	ddr->ddr_sdram_mode_2 = (0
    				 | ((esdmode2 & 0xFFFF) << 16)
    				 | ((esdmode3 & 0xFFFF) << 0)
    				 );
    
    	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
    
    
    	if (unq_mrs_en) {	/* unique mode registers are supported */
    
    		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
    
    			if (popts->rtt_override)
    				rtt_wr = popts->rtt_wr_override_value;
    			else
    				rtt_wr = popts->cs_local_opts[i].odt_rtt_wr;
    
    			esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
    			esdmode2 |= (rtt_wr & 0x3) << 9;
    			switch (i) {
    			case 1:
    				ddr->ddr_sdram_mode_4 = (0
    					| ((esdmode2 & 0xFFFF) << 16)
    					| ((esdmode3 & 0xFFFF) << 0)
    					);
    				break;
    			case 2:
    				ddr->ddr_sdram_mode_6 = (0
    					| ((esdmode2 & 0xFFFF) << 16)
    					| ((esdmode3 & 0xFFFF) << 0)
    					);
    				break;
    			case 3:
    				ddr->ddr_sdram_mode_8 = (0
    					| ((esdmode2 & 0xFFFF) << 16)
    					| ((esdmode3 & 0xFFFF) << 0)
    					);
    				break;
    			}
    		}
    		debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
    			ddr->ddr_sdram_mode_4);
    		debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
    			ddr->ddr_sdram_mode_6);
    		debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
    			ddr->ddr_sdram_mode_8);
    	}
    
    }
    
    #else /* for DDR2 and DDR1 */
    /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
    
    static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
    				fsl_ddr_cfg_regs_t *ddr,
    
    				const memctl_options_t *popts,
    				const common_timing_params_t *common_dimm,
    				const unsigned int unq_mrs_en)
    {
    	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
    	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
    
    	ddr->ddr_sdram_mode_2 = (0
    				 | ((esdmode2 & 0xFFFF) << 16)
    				 | ((esdmode3 & 0xFFFF) << 0)
    				 );
    	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
    }
    
    
    #ifdef CONFIG_SYS_FSL_DDR4
    /* DDR SDRAM Mode configuration 9 (DDR_SDRAM_MODE_9) */
    static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
    				const memctl_options_t *popts,
    				const common_timing_params_t *common_dimm,
    				const unsigned int unq_mrs_en)
    {
    	int i;
    	unsigned short esdmode4 = 0;	/* Extended SDRAM mode 4 */
    	unsigned short esdmode5;	/* Extended SDRAM mode 5 */
    
    	bool four_cs = false;
    
    #if CONFIG_CHIP_SELECTS_PER_CTRL == 4
    	if ((ddr->cs[0].config & SDRAM_CS_CONFIG_EN) &&
    	    (ddr->cs[1].config & SDRAM_CS_CONFIG_EN) &&
    	    (ddr->cs[2].config & SDRAM_CS_CONFIG_EN) &&
    	    (ddr->cs[3].config & SDRAM_CS_CONFIG_EN))
    		four_cs = true;
    #endif
    
    	if (ddr->cs[0].config & SDRAM_CS_CONFIG_EN) {
    		esdmode5 = 0x00000500;	/* Data mask enable, RTT_PARK CS0 */
    
    		rtt_park = four_cs ? 0 : 1;
    
    	} else {
    		esdmode5 = 0x00000400;	/* Data mask enabled */
    	}
    
    
    	ddr->ddr_sdram_mode_9 = (0
    				 | ((esdmode4 & 0xffff) << 16)
    				 | ((esdmode5 & 0xffff) << 0)
    				);
    
    	/* Normally only the first enabled CS use 0x500, others use 0x400
    	 * But when four chip-selects are all enabled, all mode registers
    	 * need 0x500 to park.
    	 */
    
    	debug("FSLDDR: ddr_sdram_mode_9) = 0x%08x\n", ddr->ddr_sdram_mode_9);
    	if (unq_mrs_en) {	/* unique mode registers are supported */
    		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
    
    			if (!rtt_park &&
    			    (ddr->cs[i].config & SDRAM_CS_CONFIG_EN)) {
    				esdmode5 |= 0x00000500;	/* RTT_PARK */
    
    				rtt_park = four_cs ? 0 : 1;
    
    			} else {
    				esdmode5 = 0x00000400;
    			}
    
    			switch (i) {
    			case 1:
    				ddr->ddr_sdram_mode_11 = (0
    					| ((esdmode4 & 0xFFFF) << 16)
    					| ((esdmode5 & 0xFFFF) << 0)
    					);
    				break;
    			case 2:
    				ddr->ddr_sdram_mode_13 = (0
    					| ((esdmode4 & 0xFFFF) << 16)
    					| ((esdmode5 & 0xFFFF) << 0)
    					);
    				break;
    			case 3:
    				ddr->ddr_sdram_mode_15 = (0
    					| ((esdmode4 & 0xFFFF) << 16)
    					| ((esdmode5 & 0xFFFF) << 0)
    					);
    				break;
    			}
    		}
    		debug("FSLDDR: ddr_sdram_mode_11 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_11);
    		debug("FSLDDR: ddr_sdram_mode_13 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_13);
    		debug("FSLDDR: ddr_sdram_mode_15 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_15);
    	}
    }
    
    /* DDR SDRAM Mode configuration 10 (DDR_SDRAM_MODE_10) */
    
    static void set_ddr_sdram_mode_10(const unsigned int ctrl_num,
    				fsl_ddr_cfg_regs_t *ddr,
    
    				const memctl_options_t *popts,
    				const common_timing_params_t *common_dimm,
    				const unsigned int unq_mrs_en)
    {
    	int i;
    	unsigned short esdmode6 = 0;	/* Extended SDRAM mode 6 */
    	unsigned short esdmode7 = 0;	/* Extended SDRAM mode 7 */
    
    	unsigned int tccdl_min = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps);
    
    
    	esdmode6 = ((tccdl_min - 4) & 0x7) << 10;
    
    
    	if (popts->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2)
    		esdmode6 |= 1 << 6;	/* Range 2 */
    
    
    	ddr->ddr_sdram_mode_10 = (0
    				 | ((esdmode6 & 0xffff) << 16)
    				 | ((esdmode7 & 0xffff) << 0)
    				);
    	debug("FSLDDR: ddr_sdram_mode_10) = 0x%08x\n", ddr->ddr_sdram_mode_10);
    	if (unq_mrs_en) {	/* unique mode registers are supported */
    		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
    			switch (i) {
    			case 1:
    				ddr->ddr_sdram_mode_12 = (0
    					| ((esdmode6 & 0xFFFF) << 16)
    					| ((esdmode7 & 0xFFFF) << 0)
    					);
    				break;
    			case 2:
    				ddr->ddr_sdram_mode_14 = (0
    					| ((esdmode6 & 0xFFFF) << 16)
    					| ((esdmode7 & 0xFFFF) << 0)
    					);
    				break;
    			case 3:
    				ddr->ddr_sdram_mode_16 = (0
    					| ((esdmode6 & 0xFFFF) << 16)
    					| ((esdmode7 & 0xFFFF) << 0)
    					);
    				break;
    			}
    		}
    		debug("FSLDDR: ddr_sdram_mode_12 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_12);
    		debug("FSLDDR: ddr_sdram_mode_14 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_14);
    		debug("FSLDDR: ddr_sdram_mode_16 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_16);
    	}
    
    /* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */
    
    static void set_ddr_sdram_interval(const unsigned int ctrl_num,
    				fsl_ddr_cfg_regs_t *ddr,
    				const memctl_options_t *popts,
    				const common_timing_params_t *common_dimm)
    
    {
    	unsigned int refint;	/* Refresh interval */
    	unsigned int bstopre;	/* Precharge interval */
    
    
    	refint = picos_to_mclk(ctrl_num, common_dimm->refresh_rate_ps);
    
    
    	bstopre = popts->bstopre;
    
    	/* refint field used 0x3FFF in earlier controllers */
    	ddr->ddr_sdram_interval = (0
    				   | ((refint & 0xFFFF) << 16)
    				   | ((bstopre & 0x3FFF) << 0)
    				   );
    
    	debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval);
    
    #ifdef CONFIG_SYS_FSL_DDR4
    
    /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
    
    static void set_ddr_sdram_mode(const unsigned int ctrl_num,
    			       fsl_ddr_cfg_regs_t *ddr,
    
    			       const memctl_options_t *popts,
    			       const common_timing_params_t *common_dimm,
    			       unsigned int cas_latency,
    
    			       unsigned int additive_latency,
    			       const unsigned int unq_mrs_en)
    
    	int i;
    	unsigned short esdmode;		/* Extended SDRAM mode */
    	unsigned short sdmode;		/* SDRAM mode */
    
    	/* Mode Register - MR1 */
    	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
    	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
    	unsigned int rtt;
    	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
    	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
    	unsigned int dic = 0;		/* Output driver impedance, 40ohm */
    	unsigned int dll_en = 1;	/* DLL Enable  1=Enable (Normal),
    						       0=Disable (Test/Debug) */
    
    	/* Mode Register - MR0 */
    	unsigned int wr = 0;	/* Write Recovery */
    	unsigned int dll_rst;	/* DLL Reset */
    	unsigned int mode;	/* Normal=0 or Test=1 */
    	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
    	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
    	unsigned int bt;
    	unsigned int bl;	/* BL: Burst Length */
    
    	unsigned int wr_mclk;
    	/* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */
    	static const u8 wr_table[] = {
    		0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6};
    	/* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */
    	static const u8 cas_latency_table[] = {
    		0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
    		9, 9, 10, 10, 11, 11};
    
    	if (popts->rtt_override)
    		rtt = popts->rtt_override_value;
    	else
    		rtt = popts->cs_local_opts[0].odt_rtt_norm;
    
    	if (additive_latency == (cas_latency - 1))
    		al = 1;
    	if (additive_latency == (cas_latency - 2))
    		al = 2;
    
    	if (popts->quad_rank_present)
    		dic = 1;	/* output driver impedance 240/7 ohm */
    
    	/*
    	 * The esdmode value will also be used for writing
    	 * MR1 during write leveling for DDR3, although the
    	 * bits specifically related to the write leveling
    	 * scheme will be handled automatically by the DDR
    	 * controller. so we set the wrlvl_en = 0 here.
    	 */
    	esdmode = (0
    		| ((qoff & 0x1) << 12)
    		| ((tdqs_en & 0x1) << 11)
    		| ((rtt & 0x7) << 8)
    		| ((wrlvl_en & 0x1) << 7)
    		| ((al & 0x3) << 3)
    		| ((dic & 0x3) << 1)   /* DIC field is split */
    		| ((dll_en & 0x1) << 0)
    		);
    
    	/*
    	 * DLL control for precharge PD
    	 * 0=slow exit DLL off (tXPDLL)
    	 * 1=fast exit DLL on (tXP)
    	 */
    
    
    	wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
    
    	if (wr_mclk <= 24) {
    		wr = wr_table[wr_mclk - 10];
    	} else {
    		printf("Error: unsupported write recovery for mode register wr_mclk = %d\n",
    		       wr_mclk);
    	}
    
    	dll_rst = 0;	/* dll no reset */
    	mode = 0;	/* normal mode */
    
    	/* look up table to get the cas latency bits */
    	if (cas_latency >= 9 && cas_latency <= 24)
    		caslat = cas_latency_table[cas_latency - 9];
    	else
    		printf("Error: unsupported cas latency for mode register\n");
    
    	bt = 0;	/* Nibble sequential */
    
    	switch (popts->burst_length) {
    	case DDR_BL8:
    		bl = 0;
    		break;
    	case DDR_OTF:
    		bl = 1;
    		break;
    	case DDR_BC4:
    		bl = 2;
    		break;
    	default:
    		printf("Error: invalid burst length of %u specified. ",
    		       popts->burst_length);
    		puts("Defaulting to on-the-fly BC4 or BL8 beats.\n");
    		bl = 1;
    		break;
    	}
    
    	sdmode = (0
    		  | ((wr & 0x7) << 9)
    		  | ((dll_rst & 0x1) << 8)
    		  | ((mode & 0x1) << 7)
    		  | (((caslat >> 1) & 0x7) << 4)
    		  | ((bt & 0x1) << 3)
    		  | ((caslat & 1) << 2)
    		  | ((bl & 0x3) << 0)
    		  );
    
    	ddr->ddr_sdram_mode = (0
    			       | ((esdmode & 0xFFFF) << 16)
    			       | ((sdmode & 0xFFFF) << 0)
    			       );
    
    	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
    
    	if (unq_mrs_en) {	/* unique mode registers are supported */
    		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
    			if (popts->rtt_override)
    				rtt = popts->rtt_override_value;
    			else
    				rtt = popts->cs_local_opts[i].odt_rtt_norm;
    
    			esdmode &= 0xF8FF;	/* clear bit 10,9,8 for rtt */
    			esdmode |= (rtt & 0x7) << 8;
    			switch (i) {
    			case 1:
    				ddr->ddr_sdram_mode_3 = (0
    				       | ((esdmode & 0xFFFF) << 16)
    				       | ((sdmode & 0xFFFF) << 0)
    				       );
    				break;
    			case 2:
    				ddr->ddr_sdram_mode_5 = (0
    				       | ((esdmode & 0xFFFF) << 16)
    				       | ((sdmode & 0xFFFF) << 0)
    				       );
    				break;
    			case 3:
    				ddr->ddr_sdram_mode_7 = (0
    				       | ((esdmode & 0xFFFF) << 16)
    				       | ((sdmode & 0xFFFF) << 0)
    				       );
    				break;
    			}
    		}
    		debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_3);
    		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_5);
    		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
    		      ddr->ddr_sdram_mode_5);
    	}
    }
    
    #elif defined(CONFIG_SYS_FSL_DDR3)
    /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
    
    static void set_ddr_sdram_mode(const unsigned int ctrl_num,
    			       fsl_ddr_cfg_regs_t *ddr,
    
    			       const memctl_options_t *popts,
    			       const common_timing_params_t *common_dimm,
    			       unsigned int cas_latency,
    			       unsigned int additive_latency,
    			       const unsigned int unq_mrs_en)
    {
    	int i;
    
    	unsigned short esdmode;		/* Extended SDRAM mode */
    	unsigned short sdmode;		/* SDRAM mode */
    
    	/* Mode Register - MR1 */
    	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
    	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
    	unsigned int rtt;
    	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
    	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
    
    	unsigned int dic = 0;		/* Output driver impedance, 40ohm */
    
    	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
    						       1=Disable (Test/Debug) */
    
    	/* Mode Register - MR0 */
    	unsigned int dll_on;	/* DLL control for precharge PD, 0=off, 1=on */
    
    	unsigned int wr = 0;	/* Write Recovery */
    
    	unsigned int dll_rst;	/* DLL Reset */
    	unsigned int mode;	/* Normal=0 or Test=1 */
    	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
    	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
    	unsigned int bt;
    	unsigned int bl;	/* BL: Burst Length */
    
    	unsigned int wr_mclk;
    
    	/*
    	 * DDR_SDRAM_MODE doesn't support 9,11,13,15
    	 * Please refer JEDEC Standard No. 79-3E for Mode Register MR0
    	 * for this table
    	 */
    	static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
    
    
    	if (popts->rtt_override)
    		rtt = popts->rtt_override_value;
    
    	else
    		rtt = popts->cs_local_opts[0].odt_rtt_norm;
    
    
    	if (additive_latency == (cas_latency - 1))
    		al = 1;
    	if (additive_latency == (cas_latency - 2))
    		al = 2;
    
    
    	if (popts->quad_rank_present)
    		dic = 1;	/* output driver impedance 240/7 ohm */
    
    
    	/*
    	 * The esdmode value will also be used for writing
    	 * MR1 during write leveling for DDR3, although the
    	 * bits specifically related to the write leveling
    	 * scheme will be handled automatically by the DDR
    	 * controller. so we set the wrlvl_en = 0 here.
    	 */
    	esdmode = (0
    		| ((qoff & 0x1) << 12)
    		| ((tdqs_en & 0x1) << 11)
    
    		| ((rtt & 0x4) << 7)   /* rtt field is split */
    
    		| ((wrlvl_en & 0x1) << 7)
    
    		| ((rtt & 0x2) << 5)   /* rtt field is split */
    		| ((dic & 0x2) << 4)   /* DIC field is split */
    
    		| ((al & 0x3) << 3)
    
    		| ((rtt & 0x1) << 2)  /* rtt field is split */
    
    		| ((dic & 0x1) << 1)   /* DIC field is split */
    		| ((dll_en & 0x1) << 0)
    		);
    
    	/*
    	 * DLL control for precharge PD
    	 * 0=slow exit DLL off (tXPDLL)
    	 * 1=fast exit DLL on (tXP)
    	 */
    	dll_on = 1;
    
    	wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
    
    	if (wr_mclk <= 16) {
    		wr = wr_table[wr_mclk - 5];
    	} else {
    		printf("Error: unsupported write recovery for mode register "
    		       "wr_mclk = %d\n", wr_mclk);
    	}
    
    	dll_rst = 0;	/* dll no reset */
    	mode = 0;	/* normal mode */
    
    	/* look up table to get the cas latency bits */
    
    	if (cas_latency >= 5 && cas_latency <= 16) {
    		unsigned char cas_latency_table[] = {
    
    			0x2,	/* 5 clocks */
    			0x4,	/* 6 clocks */
    			0x6,	/* 7 clocks */
    			0x8,	/* 8 clocks */
    			0xa,	/* 9 clocks */
    			0xc,	/* 10 clocks */
    
    			0xe,	/* 11 clocks */
    			0x1,	/* 12 clocks */
    			0x3,	/* 13 clocks */
    			0x5,	/* 14 clocks */
    			0x7,	/* 15 clocks */
    			0x9,	/* 16 clocks */
    
    		};
    		caslat = cas_latency_table[cas_latency - 5];
    
    	} else {
    		printf("Error: unsupported cas latency for mode register\n");
    
    	bt = 0;	/* Nibble sequential */
    
    	switch (popts->burst_length) {
    	case DDR_BL8:
    		bl = 0;
    		break;
    	case DDR_OTF:
    		bl = 1;
    		break;
    	case DDR_BC4:
    		bl = 2;
    		break;
    	default:
    		printf("Error: invalid burst length of %u specified. "
    			" Defaulting to on-the-fly BC4 or BL8 beats.\n",
    			popts->burst_length);
    		bl = 1;
    		break;
    	}
    
    	sdmode = (0
    		  | ((dll_on & 0x1) << 12)
    		  | ((wr & 0x7) << 9)
    		  | ((dll_rst & 0x1) << 8)
    		  | ((mode & 0x1) << 7)
    		  | (((caslat >> 1) & 0x7) << 4)
    		  | ((bt & 0x1) << 3)
    
    		  | ((bl & 0x3) << 0)
    		  );
    
    	ddr->ddr_sdram_mode = (0
    			       | ((esdmode & 0xFFFF) << 16)
    			       | ((sdmode & 0xFFFF) << 0)
    			       );
    
    	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
    
    
    	if (unq_mrs_en) {	/* unique mode registers are supported */
    
    		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
    
    			if (popts->rtt_override)
    				rtt = popts->rtt_override_value;
    			else
    				rtt = popts->cs_local_opts[i].odt_rtt_norm;
    
    			esdmode &= 0xFDBB;	/* clear bit 9,6,2 */
    			esdmode |= (0
    				| ((rtt & 0x4) << 7)   /* rtt field is split */
    				| ((rtt & 0x2) << 5)   /* rtt field is split */
    				| ((rtt & 0x1) << 2)  /* rtt field is split */
    				);
    			switch (i) {
    			case 1:
    				ddr->ddr_sdram_mode_3 = (0
    				       | ((esdmode & 0xFFFF) << 16)
    				       | ((sdmode & 0xFFFF) << 0)
    				       );
    				break;
    			case 2:
    				ddr->ddr_sdram_mode_5 = (0
    				       | ((esdmode & 0xFFFF) << 16)
    				       | ((sdmode & 0xFFFF) << 0)
    				       );
    				break;
    			case 3:
    				ddr->ddr_sdram_mode_7 = (0
    				       | ((esdmode & 0xFFFF) << 16)
    				       | ((sdmode & 0xFFFF) << 0)
    				       );
    				break;
    			}
    		}
    		debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
    			ddr->ddr_sdram_mode_3);
    		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
    			ddr->ddr_sdram_mode_5);
    		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
    			ddr->ddr_sdram_mode_5);
    	}
    
    #else /* !CONFIG_SYS_FSL_DDR3 */
    
    /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
    
    static void set_ddr_sdram_mode(const unsigned int ctrl_num,
    			       fsl_ddr_cfg_regs_t *ddr,
    
    			       const memctl_options_t *popts,
    			       const common_timing_params_t *common_dimm,
    			       unsigned int cas_latency,
    
    			       unsigned int additive_latency,
    			       const unsigned int unq_mrs_en)
    
    {
    	unsigned short esdmode;		/* Extended SDRAM mode */
    	unsigned short sdmode;		/* SDRAM mode */
    
    	/*
    	 * FIXME: This ought to be pre-calculated in a
    	 * technology-specific routine,
    	 * e.g. compute_DDR2_mode_register(), and then the
    	 * 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 */
    
    
    	dqs_en = !popts->dqs_config;
    
    	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_SYS_FSL_DDR1)
    
    	wr = 0;       /* Historical */
    
    #elif defined(CONFIG_SYS_FSL_DDR2)
    
    	wr = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
    
    #if defined(CONFIG_SYS_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_SYS_FSL_DDR2)
    
    	caslat = cas_latency;
    #endif
    	bt = 0;
    
    	switch (popts->burst_length) {
    
    	case DDR_BL4:
    
    	case DDR_BL8:
    
    		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)
    			       );
    
    	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
    
    
    /* 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 */
    
    
    #ifdef CONFIG_MEM_INIT_VALUE
    	init_value = CONFIG_MEM_INIT_VALUE;
    #else
    
    	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 */
    
    	unsigned int ss_en = 0;		/* Source synchronous enable */
    
    #if defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
    	/* Per FSL Application Note: AN2805 */
    	ss_en = 1;
    #endif
    
    	clk_adjust = popts->clk_adjust;
    
    	ddr->ddr_sdram_clk_cntl = (0
    				   | ((ss_en & 0x1) << 31)
    				   | ((clk_adjust & 0xF) << 23)
    				   );
    
    	debug("FSLDDR: clk_cntl = 0x%08x\n", ddr->ddr_sdram_clk_cntl);
    
    }
    
    /* 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,
    				const memctl_options_t *popts)
    
    {
    	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 trwt_mclk = 0;	/* ext_rwt */
    
    	unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */
    
    
    #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
    
    	if (popts->burst_length == DDR_BL8) {
    		/* We set BL/2 for fixed BL8 */
    		rrt = 0;	/* BL/2 clocks */
    		wwt = 0;	/* BL/2 clocks */
    	} else {
    		/* We need to set BL/2 + 2 to BC4 and OTF */
    		rrt = 2;	/* BL/2 + 2 clocks */
    		wwt = 2;	/* BL/2 + 2 clocks */
    	}
    
    #endif
    #ifdef CONFIG_SYS_FSL_DDR4
    	dll_lock = 2;	/* tDLLK = 1024 clocks */
    #elif defined(CONFIG_SYS_FSL_DDR3)
    
    	dll_lock = 1;	/* tDLLK = 512 clocks from spec */
    #endif
    
    
    	if (popts->trwt_override)
    		trwt_mclk = popts->trwt;
    
    
    	ddr->timing_cfg_4 = (0
    			     | ((rwt & 0xf) << 28)
    			     | ((wrt & 0xf) << 24)
    			     | ((rrt & 0xf) << 20)
    			     | ((wwt & 0xf) << 16)
    
    			     | ((trwt_mclk & 0xc) << 12)
    
    	debug("FSLDDR: timing_cfg_4 = 0x%08x\n", ddr->timing_cfg_4);
    
    }
    
    /* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */
    
    static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency)
    
    {
    	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 */
    
    
    #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
    	unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
    			      ((ddr->timing_cfg_2 & 0x00040000) >> 14);
    
    	/* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
    
    	if (cas_latency >= wr_lat)
    		rodt_on = cas_latency - wr_lat + 1;
    
    	rodt_off = 4;	/*  4 clocks */
    
    	wodt_on = 1;	/*  1 clocks */
    
    	wodt_off = 4;	/*  4 clocks */
    #endif
    
    
    			     | ((rodt_on & 0x1f) << 24)
    			     | ((rodt_off & 0x7) << 20)
    			     | ((wodt_on & 0x1f) << 12)
    			     | ((wodt_off & 0x7) << 8)
    
    	debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5);
    
    #ifdef CONFIG_SYS_FSL_DDR4
    static void set_timing_cfg_6(fsl_ddr_cfg_regs_t *ddr)
    {
    	unsigned int hs_caslat = 0;
    	unsigned int hs_wrlat = 0;
    	unsigned int hs_wrrec = 0;
    	unsigned int hs_clkadj = 0;
    	unsigned int hs_wrlvl_start = 0;
    
    	ddr->timing_cfg_6 = (0
    			     | ((hs_caslat & 0x1f) << 24)
    			     | ((hs_wrlat & 0x1f) << 19)
    			     | ((hs_wrrec & 0x1f) << 12)
    			     | ((hs_clkadj & 0x1f) << 6)
    			     | ((hs_wrlvl_start & 0x1f) << 0)
    			    );
    	debug("FSLDDR: timing_cfg_6 = 0x%08x\n", ddr->timing_cfg_6);
    }
    
    
    static void set_timing_cfg_7(const unsigned int ctrl_num,
    			     fsl_ddr_cfg_regs_t *ddr,
    			     const common_timing_params_t *common_dimm)
    
    {
    	unsigned int txpr, tcksre, tcksrx;
    	unsigned int cke_rst, cksre, cksrx, par_lat, cs_to_cmd;
    
    
    	txpr = max(5U, picos_to_mclk(ctrl_num, common_dimm->trfc1_ps + 10000));
    	tcksre = max(5U, picos_to_mclk(ctrl_num, 10000));
    	tcksrx = max(5U, picos_to_mclk(ctrl_num, 10000));
    
    	par_lat = 0;
    	cs_to_cmd = 0;
    
    	if (txpr <= 200)
    		cke_rst = 0;
    	else if (txpr <= 256)
    		cke_rst = 1;
    	else if (txpr <= 512)
    		cke_rst = 2;
    	else
    		cke_rst = 3;
    
    	if (tcksre <= 19)
    		cksre = tcksre - 5;
    	else
    		cksre = 15;
    
    	if (tcksrx <= 19)
    		cksrx = tcksrx - 5;
    	else
    		cksrx = 15;
    
    	ddr->timing_cfg_7 = (0
    			     | ((cke_rst & 0x3) << 28)
    			     | ((cksre & 0xf) << 24)
    			     | ((cksrx & 0xf) << 20)
    			     | ((par_lat & 0xf) << 16)
    			     | ((cs_to_cmd & 0xf) << 4)
    			    );
    	debug("FSLDDR: timing_cfg_7 = 0x%08x\n", ddr->timing_cfg_7);
    }
    
    
    static void set_timing_cfg_8(const unsigned int ctrl_num,
    			     fsl_ddr_cfg_regs_t *ddr,
    
    			     const memctl_options_t *popts,
    			     const common_timing_params_t *common_dimm,
    			     unsigned int cas_latency)
    {
    	unsigned int rwt_bg, wrt_bg, rrt_bg, wwt_bg;
    	unsigned int acttoact_bg, wrtord_bg, pre_all_rec;
    
    	unsigned int tccdl = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps);
    
    	unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
    			      ((ddr->timing_cfg_2 & 0x00040000) >> 14);
    
    	rwt_bg = cas_latency + 2 + 4 - wr_lat;
    	if (rwt_bg < tccdl)
    		rwt_bg = tccdl - rwt_bg;
    	else
    		rwt_bg = 0;
    
    	wrt_bg = wr_lat + 4 + 1 - cas_latency;
    	if (wrt_bg < tccdl)
    		wrt_bg = tccdl - wrt_bg;
    	else
    		wrt_bg = 0;
    
    	if (popts->burst_length == DDR_BL8) {
    		rrt_bg = tccdl - 4;
    		wwt_bg = tccdl - 4;
    	} else {
    		rrt_bg = tccdl - 2;
    
    	acttoact_bg = picos_to_mclk(ctrl_num, common_dimm->trrdl_ps);
    	wrtord_bg = max(4U, picos_to_mclk(ctrl_num, 7500));
    
    	if (popts->otf_burst_chop_en)
    		wrtord_bg += 2;