xref: /openbmc/u-boot/drivers/ddr/fsl/ctrl_regs.c (revision 6e2941d787819ae1221d7f8295fa67d2ba94a913)
15614e71bSYork Sun /*
234e026f9SYork Sun  * Copyright 2008-2014 Freescale Semiconductor, Inc.
35614e71bSYork Sun  *
45614e71bSYork Sun  * SPDX-License-Identifier:	GPL-2.0+
55614e71bSYork Sun  */
65614e71bSYork Sun 
75614e71bSYork Sun /*
802fb2761SShengzhou Liu  * Generic driver for Freescale DDR/DDR2/DDR3/DDR4 memory controller.
95614e71bSYork Sun  * Based on code from spd_sdram.c
105614e71bSYork Sun  * Author: James Yang [at freescale.com]
115614e71bSYork Sun  */
125614e71bSYork Sun 
135614e71bSYork Sun #include <common.h>
145614e71bSYork Sun #include <fsl_ddr_sdram.h>
1502fb2761SShengzhou Liu #include <fsl_errata.h>
165614e71bSYork Sun #include <fsl_ddr.h>
179a17eb5bSYork Sun #include <fsl_immap.h>
185614e71bSYork Sun #include <asm/io.h>
19*6e2941d7SSimon Glass #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3)
20*6e2941d7SSimon Glass #include <asm/arch/clock.h>
21*6e2941d7SSimon Glass #endif
225614e71bSYork Sun 
235614e71bSYork Sun /*
245614e71bSYork Sun  * Determine Rtt value.
255614e71bSYork Sun  *
265614e71bSYork Sun  * This should likely be either board or controller specific.
275614e71bSYork Sun  *
285614e71bSYork Sun  * Rtt(nominal) - DDR2:
295614e71bSYork Sun  *	0 = Rtt disabled
305614e71bSYork Sun  *	1 = 75 ohm
315614e71bSYork Sun  *	2 = 150 ohm
325614e71bSYork Sun  *	3 = 50 ohm
335614e71bSYork Sun  * Rtt(nominal) - DDR3:
345614e71bSYork Sun  *	0 = Rtt disabled
355614e71bSYork Sun  *	1 = 60 ohm
365614e71bSYork Sun  *	2 = 120 ohm
375614e71bSYork Sun  *	3 = 40 ohm
385614e71bSYork Sun  *	4 = 20 ohm
395614e71bSYork Sun  *	5 = 30 ohm
405614e71bSYork Sun  *
415614e71bSYork Sun  * FIXME: Apparently 8641 needs a value of 2
425614e71bSYork Sun  * FIXME: Old code seys if 667 MHz or higher, use 3 on 8572
435614e71bSYork Sun  *
445614e71bSYork Sun  * FIXME: There was some effort down this line earlier:
455614e71bSYork Sun  *
465614e71bSYork Sun  *	unsigned int i;
475614e71bSYork Sun  *	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL/2; i++) {
485614e71bSYork Sun  *		if (popts->dimmslot[i].num_valid_cs
495614e71bSYork Sun  *		    && (popts->cs_local_opts[2*i].odt_rd_cfg
505614e71bSYork Sun  *			|| popts->cs_local_opts[2*i].odt_wr_cfg)) {
515614e71bSYork Sun  *			rtt = 2;
525614e71bSYork Sun  *			break;
535614e71bSYork Sun  *		}
545614e71bSYork Sun  *	}
555614e71bSYork Sun  */
565614e71bSYork Sun static inline int fsl_ddr_get_rtt(void)
575614e71bSYork Sun {
585614e71bSYork Sun 	int rtt;
595614e71bSYork Sun 
605614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
615614e71bSYork Sun 	rtt = 0;
625614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
635614e71bSYork Sun 	rtt = 3;
645614e71bSYork Sun #else
655614e71bSYork Sun 	rtt = 0;
665614e71bSYork Sun #endif
675614e71bSYork Sun 
685614e71bSYork Sun 	return rtt;
695614e71bSYork Sun }
705614e71bSYork Sun 
7134e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
7234e026f9SYork Sun /*
7334e026f9SYork Sun  * compute CAS write latency according to DDR4 spec
7434e026f9SYork Sun  * CWL = 9 for <= 1600MT/s
7534e026f9SYork Sun  *       10 for <= 1866MT/s
7634e026f9SYork Sun  *       11 for <= 2133MT/s
7734e026f9SYork Sun  *       12 for <= 2400MT/s
7834e026f9SYork Sun  *       14 for <= 2667MT/s
7934e026f9SYork Sun  *       16 for <= 2933MT/s
8034e026f9SYork Sun  *       18 for higher
8134e026f9SYork Sun  */
8203e664d8SYork Sun static inline unsigned int compute_cas_write_latency(
8303e664d8SYork Sun 				const unsigned int ctrl_num)
8434e026f9SYork Sun {
8534e026f9SYork Sun 	unsigned int cwl;
8603e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
8734e026f9SYork Sun 	if (mclk_ps >= 1250)
8834e026f9SYork Sun 		cwl = 9;
8934e026f9SYork Sun 	else if (mclk_ps >= 1070)
9034e026f9SYork Sun 		cwl = 10;
9134e026f9SYork Sun 	else if (mclk_ps >= 935)
9234e026f9SYork Sun 		cwl = 11;
9334e026f9SYork Sun 	else if (mclk_ps >= 833)
9434e026f9SYork Sun 		cwl = 12;
9534e026f9SYork Sun 	else if (mclk_ps >= 750)
9634e026f9SYork Sun 		cwl = 14;
9734e026f9SYork Sun 	else if (mclk_ps >= 681)
9834e026f9SYork Sun 		cwl = 16;
9934e026f9SYork Sun 	else
10034e026f9SYork Sun 		cwl = 18;
10134e026f9SYork Sun 
10234e026f9SYork Sun 	return cwl;
10334e026f9SYork Sun }
10434e026f9SYork Sun #else
1055614e71bSYork Sun /*
1065614e71bSYork Sun  * compute the CAS write latency according to DDR3 spec
1075614e71bSYork Sun  * CWL = 5 if tCK >= 2.5ns
1085614e71bSYork Sun  *       6 if 2.5ns > tCK >= 1.875ns
1095614e71bSYork Sun  *       7 if 1.875ns > tCK >= 1.5ns
1105614e71bSYork Sun  *       8 if 1.5ns > tCK >= 1.25ns
1115614e71bSYork Sun  *       9 if 1.25ns > tCK >= 1.07ns
1125614e71bSYork Sun  *       10 if 1.07ns > tCK >= 0.935ns
1135614e71bSYork Sun  *       11 if 0.935ns > tCK >= 0.833ns
1145614e71bSYork Sun  *       12 if 0.833ns > tCK >= 0.75ns
1155614e71bSYork Sun  */
11603e664d8SYork Sun static inline unsigned int compute_cas_write_latency(
11703e664d8SYork Sun 				const unsigned int ctrl_num)
1185614e71bSYork Sun {
1195614e71bSYork Sun 	unsigned int cwl;
12003e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
1215614e71bSYork Sun 
1225614e71bSYork Sun 	if (mclk_ps >= 2500)
1235614e71bSYork Sun 		cwl = 5;
1245614e71bSYork Sun 	else if (mclk_ps >= 1875)
1255614e71bSYork Sun 		cwl = 6;
1265614e71bSYork Sun 	else if (mclk_ps >= 1500)
1275614e71bSYork Sun 		cwl = 7;
1285614e71bSYork Sun 	else if (mclk_ps >= 1250)
1295614e71bSYork Sun 		cwl = 8;
1305614e71bSYork Sun 	else if (mclk_ps >= 1070)
1315614e71bSYork Sun 		cwl = 9;
1325614e71bSYork Sun 	else if (mclk_ps >= 935)
1335614e71bSYork Sun 		cwl = 10;
1345614e71bSYork Sun 	else if (mclk_ps >= 833)
1355614e71bSYork Sun 		cwl = 11;
1365614e71bSYork Sun 	else if (mclk_ps >= 750)
1375614e71bSYork Sun 		cwl = 12;
1385614e71bSYork Sun 	else {
1395614e71bSYork Sun 		cwl = 12;
1405614e71bSYork Sun 		printf("Warning: CWL is out of range\n");
1415614e71bSYork Sun 	}
1425614e71bSYork Sun 	return cwl;
1435614e71bSYork Sun }
14434e026f9SYork Sun #endif
1455614e71bSYork Sun 
1465614e71bSYork Sun /* Chip Select Configuration (CSn_CONFIG) */
1475614e71bSYork Sun static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
1485614e71bSYork Sun 			       const memctl_options_t *popts,
1495614e71bSYork Sun 			       const dimm_params_t *dimm_params)
1505614e71bSYork Sun {
1515614e71bSYork Sun 	unsigned int cs_n_en = 0; /* Chip Select enable */
1525614e71bSYork Sun 	unsigned int intlv_en = 0; /* Memory controller interleave enable */
1535614e71bSYork Sun 	unsigned int intlv_ctl = 0; /* Interleaving control */
1545614e71bSYork Sun 	unsigned int ap_n_en = 0; /* Chip select n auto-precharge enable */
1555614e71bSYork Sun 	unsigned int odt_rd_cfg = 0; /* ODT for reads configuration */
1565614e71bSYork Sun 	unsigned int odt_wr_cfg = 0; /* ODT for writes configuration */
1575614e71bSYork Sun 	unsigned int ba_bits_cs_n = 0; /* Num of bank bits for SDRAM on CSn */
1585614e71bSYork Sun 	unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */
1595614e71bSYork Sun 	unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */
1605614e71bSYork Sun 	int go_config = 0;
16134e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
16234e026f9SYork Sun 	unsigned int bg_bits_cs_n = 0; /* Num of bank group bits */
16334e026f9SYork Sun #else
16434e026f9SYork Sun 	unsigned int n_banks_per_sdram_device;
16534e026f9SYork Sun #endif
1665614e71bSYork Sun 
1675614e71bSYork Sun 	/* Compute CS_CONFIG only for existing ranks of each DIMM.  */
1685614e71bSYork Sun 	switch (i) {
1695614e71bSYork Sun 	case 0:
1705614e71bSYork Sun 		if (dimm_params[dimm_number].n_ranks > 0) {
1715614e71bSYork Sun 			go_config = 1;
1725614e71bSYork Sun 			/* These fields only available in CS0_CONFIG */
1735614e71bSYork Sun 			if (!popts->memctl_interleaving)
1745614e71bSYork Sun 				break;
1755614e71bSYork Sun 			switch (popts->memctl_interleaving_mode) {
1766b1e1254SYork Sun 			case FSL_DDR_256B_INTERLEAVING:
1775614e71bSYork Sun 			case FSL_DDR_CACHE_LINE_INTERLEAVING:
1785614e71bSYork Sun 			case FSL_DDR_PAGE_INTERLEAVING:
1795614e71bSYork Sun 			case FSL_DDR_BANK_INTERLEAVING:
1805614e71bSYork Sun 			case FSL_DDR_SUPERBANK_INTERLEAVING:
1815614e71bSYork Sun 				intlv_en = popts->memctl_interleaving;
1825614e71bSYork Sun 				intlv_ctl = popts->memctl_interleaving_mode;
1835614e71bSYork Sun 				break;
1845614e71bSYork Sun 			default:
1855614e71bSYork Sun 				break;
1865614e71bSYork Sun 			}
1875614e71bSYork Sun 		}
1885614e71bSYork Sun 		break;
1895614e71bSYork Sun 	case 1:
1905614e71bSYork Sun 		if ((dimm_number == 0 && dimm_params[0].n_ranks > 1) || \
1915614e71bSYork Sun 		    (dimm_number == 1 && dimm_params[1].n_ranks > 0))
1925614e71bSYork Sun 			go_config = 1;
1935614e71bSYork Sun 		break;
1945614e71bSYork Sun 	case 2:
1955614e71bSYork Sun 		if ((dimm_number == 0 && dimm_params[0].n_ranks > 2) || \
1965614e71bSYork Sun 		   (dimm_number >= 1 && dimm_params[dimm_number].n_ranks > 0))
1975614e71bSYork Sun 			go_config = 1;
1985614e71bSYork Sun 		break;
1995614e71bSYork Sun 	case 3:
2005614e71bSYork Sun 		if ((dimm_number == 0 && dimm_params[0].n_ranks > 3) || \
2015614e71bSYork Sun 		    (dimm_number == 1 && dimm_params[1].n_ranks > 1) || \
2025614e71bSYork Sun 		    (dimm_number == 3 && dimm_params[3].n_ranks > 0))
2035614e71bSYork Sun 			go_config = 1;
2045614e71bSYork Sun 		break;
2055614e71bSYork Sun 	default:
2065614e71bSYork Sun 		break;
2075614e71bSYork Sun 	}
2085614e71bSYork Sun 	if (go_config) {
2095614e71bSYork Sun 		cs_n_en = 1;
2105614e71bSYork Sun 		ap_n_en = popts->cs_local_opts[i].auto_precharge;
2115614e71bSYork Sun 		odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg;
2125614e71bSYork Sun 		odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg;
21334e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
21434e026f9SYork Sun 		ba_bits_cs_n = dimm_params[dimm_number].bank_addr_bits;
21534e026f9SYork Sun 		bg_bits_cs_n = dimm_params[dimm_number].bank_group_bits;
21634e026f9SYork Sun #else
2175614e71bSYork Sun 		n_banks_per_sdram_device
2185614e71bSYork Sun 			= dimm_params[dimm_number].n_banks_per_sdram_device;
2195614e71bSYork Sun 		ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2;
22034e026f9SYork Sun #endif
2215614e71bSYork Sun 		row_bits_cs_n = dimm_params[dimm_number].n_row_addr - 12;
2225614e71bSYork Sun 		col_bits_cs_n = dimm_params[dimm_number].n_col_addr - 8;
2235614e71bSYork Sun 	}
2245614e71bSYork Sun 	ddr->cs[i].config = (0
2255614e71bSYork Sun 		| ((cs_n_en & 0x1) << 31)
2265614e71bSYork Sun 		| ((intlv_en & 0x3) << 29)
2275614e71bSYork Sun 		| ((intlv_ctl & 0xf) << 24)
2285614e71bSYork Sun 		| ((ap_n_en & 0x1) << 23)
2295614e71bSYork Sun 
2305614e71bSYork Sun 		/* XXX: some implementation only have 1 bit starting at left */
2315614e71bSYork Sun 		| ((odt_rd_cfg & 0x7) << 20)
2325614e71bSYork Sun 
2335614e71bSYork Sun 		/* XXX: Some implementation only have 1 bit starting at left */
2345614e71bSYork Sun 		| ((odt_wr_cfg & 0x7) << 16)
2355614e71bSYork Sun 
2365614e71bSYork Sun 		| ((ba_bits_cs_n & 0x3) << 14)
2375614e71bSYork Sun 		| ((row_bits_cs_n & 0x7) << 8)
23834e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
23934e026f9SYork Sun 		| ((bg_bits_cs_n & 0x3) << 4)
24034e026f9SYork Sun #endif
2415614e71bSYork Sun 		| ((col_bits_cs_n & 0x7) << 0)
2425614e71bSYork Sun 		);
2435614e71bSYork Sun 	debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config);
2445614e71bSYork Sun }
2455614e71bSYork Sun 
2465614e71bSYork Sun /* Chip Select Configuration 2 (CSn_CONFIG_2) */
2475614e71bSYork Sun /* FIXME: 8572 */
2485614e71bSYork Sun static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)
2495614e71bSYork Sun {
2505614e71bSYork Sun 	unsigned int pasr_cfg = 0;	/* Partial array self refresh config */
2515614e71bSYork Sun 
2525614e71bSYork Sun 	ddr->cs[i].config_2 = ((pasr_cfg & 7) << 24);
2535614e71bSYork Sun 	debug("FSLDDR: cs[%d]_config_2 = 0x%08x\n", i, ddr->cs[i].config_2);
2545614e71bSYork Sun }
2555614e71bSYork Sun 
2565614e71bSYork Sun /* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */
2575614e71bSYork Sun 
2585614e71bSYork Sun #if !defined(CONFIG_SYS_FSL_DDR1)
25984baed2aSYork Sun /*
26084baed2aSYork Sun  * Check DIMM configuration, return 2 if quad-rank or two dual-rank
26184baed2aSYork Sun  * Return 1 if other two slots configuration. Return 0 if single slot.
26284baed2aSYork Sun  */
2635614e71bSYork Sun static inline int avoid_odt_overlap(const dimm_params_t *dimm_params)
2645614e71bSYork Sun {
2655614e71bSYork Sun #if CONFIG_DIMM_SLOTS_PER_CTLR == 1
2665614e71bSYork Sun 	if (dimm_params[0].n_ranks == 4)
26784baed2aSYork Sun 		return 2;
2685614e71bSYork Sun #endif
2695614e71bSYork Sun 
2705614e71bSYork Sun #if CONFIG_DIMM_SLOTS_PER_CTLR == 2
2715614e71bSYork Sun 	if ((dimm_params[0].n_ranks == 2) &&
2725614e71bSYork Sun 		(dimm_params[1].n_ranks == 2))
27384baed2aSYork Sun 		return 2;
2745614e71bSYork Sun 
2755614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
2765614e71bSYork Sun 	if (dimm_params[0].n_ranks == 4)
27784baed2aSYork Sun 		return 2;
2785614e71bSYork Sun #endif
27984baed2aSYork Sun 
28084baed2aSYork Sun 	if ((dimm_params[0].n_ranks != 0) &&
28184baed2aSYork Sun 	    (dimm_params[2].n_ranks != 0))
28284baed2aSYork Sun 		return 1;
2835614e71bSYork Sun #endif
2845614e71bSYork Sun 	return 0;
2855614e71bSYork Sun }
2865614e71bSYork Sun 
2875614e71bSYork Sun /*
2885614e71bSYork Sun  * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0)
2895614e71bSYork Sun  *
2905614e71bSYork Sun  * Avoid writing for DDR I.  The new PQ38 DDR controller
2915614e71bSYork Sun  * dreams up non-zero default values to be backwards compatible.
2925614e71bSYork Sun  */
29303e664d8SYork Sun static void set_timing_cfg_0(const unsigned int ctrl_num,
29403e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
2955614e71bSYork Sun 				const memctl_options_t *popts,
2965614e71bSYork Sun 				const dimm_params_t *dimm_params)
2975614e71bSYork Sun {
2985614e71bSYork Sun 	unsigned char trwt_mclk = 0;   /* Read-to-write turnaround */
2995614e71bSYork Sun 	unsigned char twrt_mclk = 0;   /* Write-to-read turnaround */
3005614e71bSYork Sun 	/* 7.5 ns on -3E; 0 means WL - CL + BL/2 + 1 */
3015614e71bSYork Sun 	unsigned char trrt_mclk = 0;   /* Read-to-read turnaround */
3025614e71bSYork Sun 	unsigned char twwt_mclk = 0;   /* Write-to-write turnaround */
3035614e71bSYork Sun 
3045614e71bSYork Sun 	/* Active powerdown exit timing (tXARD and tXARDS). */
3055614e71bSYork Sun 	unsigned char act_pd_exit_mclk;
3065614e71bSYork Sun 	/* Precharge powerdown exit timing (tXP). */
3075614e71bSYork Sun 	unsigned char pre_pd_exit_mclk;
3085614e71bSYork Sun 	/* ODT powerdown exit timing (tAXPD). */
30934e026f9SYork Sun 	unsigned char taxpd_mclk = 0;
3105614e71bSYork Sun 	/* Mode register set cycle time (tMRD). */
3115614e71bSYork Sun 	unsigned char tmrd_mclk;
312bb578322SYork Sun #if defined(CONFIG_SYS_FSL_DDR4) || defined(CONFIG_SYS_FSL_DDR3)
31303e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
314bb578322SYork Sun #endif
3155614e71bSYork Sun 
31634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
31734e026f9SYork Sun 	/* tXP=max(4nCK, 6ns) */
318b4141195SMasahiro Yamada 	int txp = max((int)mclk_ps * 4, 6000); /* unit=ps */
31966869f95SYork Sun 	unsigned int data_rate = get_ddr_freq(ctrl_num);
32066869f95SYork Sun 
32166869f95SYork Sun 	/* for faster clock, need more time for data setup */
32266869f95SYork Sun 	trwt_mclk = (data_rate/1000000 > 1900) ? 3 : 2;
3236c6e006aSYork Sun 
3246c6e006aSYork Sun 	/*
3256c6e006aSYork Sun 	 * for single quad-rank DIMM and two-slot DIMMs
3266c6e006aSYork Sun 	 * to avoid ODT overlap
3276c6e006aSYork Sun 	 */
3286c6e006aSYork Sun 	switch (avoid_odt_overlap(dimm_params)) {
3296c6e006aSYork Sun 	case 2:
3306c6e006aSYork Sun 		twrt_mclk = 2;
3316c6e006aSYork Sun 		twwt_mclk = 2;
3326c6e006aSYork Sun 		trrt_mclk = 2;
3336c6e006aSYork Sun 		break;
3346c6e006aSYork Sun 	default:
33534e026f9SYork Sun 		twrt_mclk = 1;
3366c6e006aSYork Sun 		twwt_mclk = 1;
3376c6e006aSYork Sun 		trrt_mclk = 0;
3386c6e006aSYork Sun 		break;
3396c6e006aSYork Sun 	}
3406c6e006aSYork Sun 
34103e664d8SYork Sun 	act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
34234e026f9SYork Sun 	pre_pd_exit_mclk = act_pd_exit_mclk;
34334e026f9SYork Sun 	/*
34434e026f9SYork Sun 	 * MRS_CYC = max(tMRD, tMOD)
34534e026f9SYork Sun 	 * tMRD = 8nCK, tMOD = max(24nCK, 15ns)
34634e026f9SYork Sun 	 */
34703e664d8SYork Sun 	tmrd_mclk = max(24U, picos_to_mclk(ctrl_num, 15000));
34834e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
34903e664d8SYork Sun 	unsigned int data_rate = get_ddr_freq(ctrl_num);
350bb578322SYork Sun 	int txp;
351938bbb60SYork Sun 	unsigned int ip_rev;
35284baed2aSYork Sun 	int odt_overlap;
3535614e71bSYork Sun 	/*
3545614e71bSYork Sun 	 * (tXARD and tXARDS). Empirical?
3555614e71bSYork Sun 	 * The DDR3 spec has not tXARD,
3565614e71bSYork Sun 	 * we use the tXP instead of it.
357bb578322SYork Sun 	 * tXP=max(3nCK, 7.5ns) for DDR3-800, 1066
358bb578322SYork Sun 	 *     max(3nCK, 6ns) for DDR3-1333, 1600, 1866, 2133
3595614e71bSYork Sun 	 * spec has not the tAXPD, we use
3605614e71bSYork Sun 	 * tAXPD=1, need design to confirm.
3615614e71bSYork Sun 	 */
362b4141195SMasahiro Yamada 	txp = max((int)mclk_ps * 3, (mclk_ps > 1540 ? 7500 : 6000));
363bb578322SYork Sun 
36466869f95SYork Sun 	ip_rev = fsl_ddr_get_version(ctrl_num);
365938bbb60SYork Sun 	if (ip_rev >= 0x40700) {
366938bbb60SYork Sun 		/*
367938bbb60SYork Sun 		 * MRS_CYC = max(tMRD, tMOD)
368938bbb60SYork Sun 		 * tMRD = 4nCK (8nCK for RDIMM)
369938bbb60SYork Sun 		 * tMOD = max(12nCK, 15ns)
370938bbb60SYork Sun 		 */
37103e664d8SYork Sun 		tmrd_mclk = max((unsigned int)12,
37203e664d8SYork Sun 				picos_to_mclk(ctrl_num, 15000));
373938bbb60SYork Sun 	} else {
374938bbb60SYork Sun 		/*
375938bbb60SYork Sun 		 * MRS_CYC = tMRD
376938bbb60SYork Sun 		 * tMRD = 4nCK (8nCK for RDIMM)
377938bbb60SYork Sun 		 */
378938bbb60SYork Sun 		if (popts->registered_dimm_en)
379938bbb60SYork Sun 			tmrd_mclk = 8;
380938bbb60SYork Sun 		else
3815614e71bSYork Sun 			tmrd_mclk = 4;
382938bbb60SYork Sun 	}
383938bbb60SYork Sun 
3845614e71bSYork Sun 	/* set the turnaround time */
3855614e71bSYork Sun 
3865614e71bSYork Sun 	/*
38784baed2aSYork Sun 	 * for single quad-rank DIMM and two-slot DIMMs
3885614e71bSYork Sun 	 * to avoid ODT overlap
3895614e71bSYork Sun 	 */
39084baed2aSYork Sun 	odt_overlap = avoid_odt_overlap(dimm_params);
39184baed2aSYork Sun 	switch (odt_overlap) {
39284baed2aSYork Sun 	case 2:
3935614e71bSYork Sun 		twwt_mclk = 2;
3945614e71bSYork Sun 		trrt_mclk = 1;
39584baed2aSYork Sun 		break;
39684baed2aSYork Sun 	case 1:
39784baed2aSYork Sun 		twwt_mclk = 1;
39884baed2aSYork Sun 		trrt_mclk = 0;
39984baed2aSYork Sun 		break;
40084baed2aSYork Sun 	default:
40184baed2aSYork Sun 		break;
4025614e71bSYork Sun 	}
40384baed2aSYork Sun 
4045614e71bSYork Sun 	/* for faster clock, need more time for data setup */
4055614e71bSYork Sun 	trwt_mclk = (data_rate/1000000 > 1800) ? 2 : 1;
4065614e71bSYork Sun 
4075614e71bSYork Sun 	if ((data_rate/1000000 > 1150) || (popts->memctl_interleaving))
4085614e71bSYork Sun 		twrt_mclk = 1;
4095614e71bSYork Sun 
4105614e71bSYork Sun 	if (popts->dynamic_power == 0) {	/* powerdown is not used */
4115614e71bSYork Sun 		act_pd_exit_mclk = 1;
4125614e71bSYork Sun 		pre_pd_exit_mclk = 1;
4135614e71bSYork Sun 		taxpd_mclk = 1;
4145614e71bSYork Sun 	} else {
4155614e71bSYork Sun 		/* act_pd_exit_mclk = tXARD, see above */
41603e664d8SYork Sun 		act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
4175614e71bSYork Sun 		/* Mode register MR0[A12] is '1' - fast exit */
4185614e71bSYork Sun 		pre_pd_exit_mclk = act_pd_exit_mclk;
4195614e71bSYork Sun 		taxpd_mclk = 1;
4205614e71bSYork Sun 	}
4215614e71bSYork Sun #else /* CONFIG_SYS_FSL_DDR2 */
4225614e71bSYork Sun 	/*
4235614e71bSYork Sun 	 * (tXARD and tXARDS). Empirical?
4245614e71bSYork Sun 	 * tXARD = 2 for DDR2
4255614e71bSYork Sun 	 * tXP=2
4265614e71bSYork Sun 	 * tAXPD=8
4275614e71bSYork Sun 	 */
4285614e71bSYork Sun 	act_pd_exit_mclk = 2;
4295614e71bSYork Sun 	pre_pd_exit_mclk = 2;
4305614e71bSYork Sun 	taxpd_mclk = 8;
4315614e71bSYork Sun 	tmrd_mclk = 2;
4325614e71bSYork Sun #endif
4335614e71bSYork Sun 
4345614e71bSYork Sun 	if (popts->trwt_override)
4355614e71bSYork Sun 		trwt_mclk = popts->trwt;
4365614e71bSYork Sun 
4375614e71bSYork Sun 	ddr->timing_cfg_0 = (0
4385614e71bSYork Sun 		| ((trwt_mclk & 0x3) << 30)	/* RWT */
4395614e71bSYork Sun 		| ((twrt_mclk & 0x3) << 28)	/* WRT */
4405614e71bSYork Sun 		| ((trrt_mclk & 0x3) << 26)	/* RRT */
4415614e71bSYork Sun 		| ((twwt_mclk & 0x3) << 24)	/* WWT */
442d4263b8aSYork Sun 		| ((act_pd_exit_mclk & 0xf) << 20)  /* ACT_PD_EXIT */
4435614e71bSYork Sun 		| ((pre_pd_exit_mclk & 0xF) << 16)  /* PRE_PD_EXIT */
4445614e71bSYork Sun 		| ((taxpd_mclk & 0xf) << 8)	/* ODT_PD_EXIT */
445d4263b8aSYork Sun 		| ((tmrd_mclk & 0x1f) << 0)	/* MRS_CYC */
4465614e71bSYork Sun 		);
4475614e71bSYork Sun 	debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
4485614e71bSYork Sun }
44984baed2aSYork Sun #endif	/* !defined(CONFIG_SYS_FSL_DDR1) */
4505614e71bSYork Sun 
4515614e71bSYork Sun /* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */
45203e664d8SYork Sun static void set_timing_cfg_3(const unsigned int ctrl_num,
45303e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
4545614e71bSYork Sun 			     const memctl_options_t *popts,
4555614e71bSYork Sun 			     const common_timing_params_t *common_dimm,
456d4263b8aSYork Sun 			     unsigned int cas_latency,
457d4263b8aSYork Sun 			     unsigned int additive_latency)
4585614e71bSYork Sun {
4595614e71bSYork Sun 	/* Extended precharge to activate interval (tRP) */
4605614e71bSYork Sun 	unsigned int ext_pretoact = 0;
4615614e71bSYork Sun 	/* Extended Activate to precharge interval (tRAS) */
4625614e71bSYork Sun 	unsigned int ext_acttopre = 0;
4635614e71bSYork Sun 	/* Extended activate to read/write interval (tRCD) */
4645614e71bSYork Sun 	unsigned int ext_acttorw = 0;
4655614e71bSYork Sun 	/* Extended refresh recovery time (tRFC) */
4665614e71bSYork Sun 	unsigned int ext_refrec;
4675614e71bSYork Sun 	/* Extended MCAS latency from READ cmd */
4685614e71bSYork Sun 	unsigned int ext_caslat = 0;
469d4263b8aSYork Sun 	/* Extended additive latency */
470d4263b8aSYork Sun 	unsigned int ext_add_lat = 0;
4715614e71bSYork Sun 	/* Extended last data to precharge interval (tWR) */
4725614e71bSYork Sun 	unsigned int ext_wrrec = 0;
4735614e71bSYork Sun 	/* Control Adjust */
4745614e71bSYork Sun 	unsigned int cntl_adj = 0;
4755614e71bSYork Sun 
47603e664d8SYork Sun 	ext_pretoact = picos_to_mclk(ctrl_num, common_dimm->trp_ps) >> 4;
47703e664d8SYork Sun 	ext_acttopre = picos_to_mclk(ctrl_num, common_dimm->tras_ps) >> 4;
47803e664d8SYork Sun 	ext_acttorw = picos_to_mclk(ctrl_num, common_dimm->trcd_ps) >> 4;
4795614e71bSYork Sun 	ext_caslat = (2 * cas_latency - 1) >> 4;
480d4263b8aSYork Sun 	ext_add_lat = additive_latency >> 4;
48134e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
48203e664d8SYork Sun 	ext_refrec = (picos_to_mclk(ctrl_num, common_dimm->trfc1_ps) - 8) >> 4;
48334e026f9SYork Sun #else
48403e664d8SYork Sun 	ext_refrec = (picos_to_mclk(ctrl_num, common_dimm->trfc_ps) - 8) >> 4;
4855614e71bSYork Sun 	/* ext_wrrec only deals with 16 clock and above, or 14 with OTF */
48634e026f9SYork Sun #endif
48703e664d8SYork Sun 	ext_wrrec = (picos_to_mclk(ctrl_num, common_dimm->twr_ps) +
4885614e71bSYork Sun 		(popts->otf_burst_chop_en ? 2 : 0)) >> 4;
4895614e71bSYork Sun 
4905614e71bSYork Sun 	ddr->timing_cfg_3 = (0
4915614e71bSYork Sun 		| ((ext_pretoact & 0x1) << 28)
4925614e71bSYork Sun 		| ((ext_acttopre & 0x3) << 24)
4935614e71bSYork Sun 		| ((ext_acttorw & 0x1) << 22)
4945614e71bSYork Sun 		| ((ext_refrec & 0x1F) << 16)
4955614e71bSYork Sun 		| ((ext_caslat & 0x3) << 12)
496d4263b8aSYork Sun 		| ((ext_add_lat & 0x1) << 10)
4975614e71bSYork Sun 		| ((ext_wrrec & 0x1) << 8)
4985614e71bSYork Sun 		| ((cntl_adj & 0x7) << 0)
4995614e71bSYork Sun 		);
5005614e71bSYork Sun 	debug("FSLDDR: timing_cfg_3 = 0x%08x\n", ddr->timing_cfg_3);
5015614e71bSYork Sun }
5025614e71bSYork Sun 
5035614e71bSYork Sun /* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */
50403e664d8SYork Sun static void set_timing_cfg_1(const unsigned int ctrl_num,
50503e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
5065614e71bSYork Sun 			     const memctl_options_t *popts,
5075614e71bSYork Sun 			     const common_timing_params_t *common_dimm,
5085614e71bSYork Sun 			     unsigned int cas_latency)
5095614e71bSYork Sun {
5105614e71bSYork Sun 	/* Precharge-to-activate interval (tRP) */
5115614e71bSYork Sun 	unsigned char pretoact_mclk;
5125614e71bSYork Sun 	/* Activate to precharge interval (tRAS) */
5135614e71bSYork Sun 	unsigned char acttopre_mclk;
5145614e71bSYork Sun 	/*  Activate to read/write interval (tRCD) */
5155614e71bSYork Sun 	unsigned char acttorw_mclk;
5165614e71bSYork Sun 	/* CASLAT */
5175614e71bSYork Sun 	unsigned char caslat_ctrl;
5185614e71bSYork Sun 	/*  Refresh recovery time (tRFC) ; trfc_low */
5195614e71bSYork Sun 	unsigned char refrec_ctrl;
5205614e71bSYork Sun 	/* Last data to precharge minimum interval (tWR) */
5215614e71bSYork Sun 	unsigned char wrrec_mclk;
5225614e71bSYork Sun 	/* Activate-to-activate interval (tRRD) */
5235614e71bSYork Sun 	unsigned char acttoact_mclk;
5245614e71bSYork Sun 	/* Last write data pair to read command issue interval (tWTR) */
5255614e71bSYork Sun 	unsigned char wrtord_mclk;
52634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
52734e026f9SYork Sun 	/* DDR4 supports 10, 12, 14, 16, 18, 20, 24 */
52834e026f9SYork Sun 	static const u8 wrrec_table[] = {
52934e026f9SYork Sun 		10, 10, 10, 10, 10,
53034e026f9SYork Sun 		10, 10, 10, 10, 10,
53134e026f9SYork Sun 		12, 12, 14, 14, 16,
53234e026f9SYork Sun 		16, 18, 18, 20, 20,
53334e026f9SYork Sun 		24, 24, 24, 24};
53434e026f9SYork Sun #else
5355614e71bSYork Sun 	/* DDR_SDRAM_MODE doesn't support 9,11,13,15 */
5365614e71bSYork Sun 	static const u8 wrrec_table[] = {
5375614e71bSYork Sun 		1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0};
53834e026f9SYork Sun #endif
5395614e71bSYork Sun 
54003e664d8SYork Sun 	pretoact_mclk = picos_to_mclk(ctrl_num, common_dimm->trp_ps);
54103e664d8SYork Sun 	acttopre_mclk = picos_to_mclk(ctrl_num, common_dimm->tras_ps);
54203e664d8SYork Sun 	acttorw_mclk = picos_to_mclk(ctrl_num, common_dimm->trcd_ps);
5435614e71bSYork Sun 
5445614e71bSYork Sun 	/*
5455614e71bSYork Sun 	 * Translate CAS Latency to a DDR controller field value:
5465614e71bSYork Sun 	 *
5475614e71bSYork Sun 	 *      CAS Lat DDR I   DDR II  Ctrl
5485614e71bSYork Sun 	 *      Clocks  SPD Bit SPD Bit Value
5495614e71bSYork Sun 	 *      ------- ------- ------- -----
5505614e71bSYork Sun 	 *      1.0     0               0001
5515614e71bSYork Sun 	 *      1.5     1               0010
5525614e71bSYork Sun 	 *      2.0     2       2       0011
5535614e71bSYork Sun 	 *      2.5     3               0100
5545614e71bSYork Sun 	 *      3.0     4       3       0101
5555614e71bSYork Sun 	 *      3.5     5               0110
5565614e71bSYork Sun 	 *      4.0             4       0111
5575614e71bSYork Sun 	 *      4.5                     1000
5585614e71bSYork Sun 	 *      5.0             5       1001
5595614e71bSYork Sun 	 */
5605614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
5615614e71bSYork Sun 	caslat_ctrl = (cas_latency + 1) & 0x07;
5625614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
5635614e71bSYork Sun 	caslat_ctrl = 2 * cas_latency - 1;
5645614e71bSYork Sun #else
5655614e71bSYork Sun 	/*
5665614e71bSYork Sun 	 * if the CAS latency more than 8 cycle,
5675614e71bSYork Sun 	 * we need set extend bit for it at
5685614e71bSYork Sun 	 * TIMING_CFG_3[EXT_CASLAT]
5695614e71bSYork Sun 	 */
57066869f95SYork Sun 	if (fsl_ddr_get_version(ctrl_num) <= 0x40400)
5715614e71bSYork Sun 		caslat_ctrl = 2 * cas_latency - 1;
57234e026f9SYork Sun 	else
57334e026f9SYork Sun 		caslat_ctrl = (cas_latency - 1) << 1;
5745614e71bSYork Sun #endif
5755614e71bSYork Sun 
57634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
57703e664d8SYork Sun 	refrec_ctrl = picos_to_mclk(ctrl_num, common_dimm->trfc1_ps) - 8;
57803e664d8SYork Sun 	wrrec_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
57903e664d8SYork Sun 	acttoact_mclk = max(picos_to_mclk(ctrl_num, common_dimm->trrds_ps), 4U);
58003e664d8SYork Sun 	wrtord_mclk = max(2U, picos_to_mclk(ctrl_num, 2500));
581349689b8SYork Sun 	if ((wrrec_mclk < 1) || (wrrec_mclk > 24))
582349689b8SYork Sun 		printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
58334e026f9SYork Sun 	else
58434e026f9SYork Sun 		wrrec_mclk = wrrec_table[wrrec_mclk - 1];
58534e026f9SYork Sun #else
58603e664d8SYork Sun 	refrec_ctrl = picos_to_mclk(ctrl_num, common_dimm->trfc_ps) - 8;
58703e664d8SYork Sun 	wrrec_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
58803e664d8SYork Sun 	acttoact_mclk = picos_to_mclk(ctrl_num, common_dimm->trrd_ps);
58903e664d8SYork Sun 	wrtord_mclk = picos_to_mclk(ctrl_num, common_dimm->twtr_ps);
590349689b8SYork Sun 	if ((wrrec_mclk < 1) || (wrrec_mclk > 16))
591349689b8SYork Sun 		printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
5925614e71bSYork Sun 	else
5935614e71bSYork Sun 		wrrec_mclk = wrrec_table[wrrec_mclk - 1];
59434e026f9SYork Sun #endif
5955614e71bSYork Sun 	if (popts->otf_burst_chop_en)
5965614e71bSYork Sun 		wrrec_mclk += 2;
5975614e71bSYork Sun 
5985614e71bSYork Sun 	/*
5995614e71bSYork Sun 	 * JEDEC has min requirement for tRRD
6005614e71bSYork Sun 	 */
6015614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR3)
6025614e71bSYork Sun 	if (acttoact_mclk < 4)
6035614e71bSYork Sun 		acttoact_mclk = 4;
6045614e71bSYork Sun #endif
6055614e71bSYork Sun 	/*
6065614e71bSYork Sun 	 * JEDEC has some min requirements for tWTR
6075614e71bSYork Sun 	 */
6085614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR2)
6095614e71bSYork Sun 	if (wrtord_mclk < 2)
6105614e71bSYork Sun 		wrtord_mclk = 2;
6115614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
6125614e71bSYork Sun 	if (wrtord_mclk < 4)
6135614e71bSYork Sun 		wrtord_mclk = 4;
6145614e71bSYork Sun #endif
6155614e71bSYork Sun 	if (popts->otf_burst_chop_en)
6165614e71bSYork Sun 		wrtord_mclk += 2;
6175614e71bSYork Sun 
6185614e71bSYork Sun 	ddr->timing_cfg_1 = (0
6195614e71bSYork Sun 		| ((pretoact_mclk & 0x0F) << 28)
6205614e71bSYork Sun 		| ((acttopre_mclk & 0x0F) << 24)
6215614e71bSYork Sun 		| ((acttorw_mclk & 0xF) << 20)
6225614e71bSYork Sun 		| ((caslat_ctrl & 0xF) << 16)
6235614e71bSYork Sun 		| ((refrec_ctrl & 0xF) << 12)
6245614e71bSYork Sun 		| ((wrrec_mclk & 0x0F) << 8)
6255614e71bSYork Sun 		| ((acttoact_mclk & 0x0F) << 4)
6265614e71bSYork Sun 		| ((wrtord_mclk & 0x0F) << 0)
6275614e71bSYork Sun 		);
6285614e71bSYork Sun 	debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1);
6295614e71bSYork Sun }
6305614e71bSYork Sun 
6315614e71bSYork Sun /* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */
63203e664d8SYork Sun static void set_timing_cfg_2(const unsigned int ctrl_num,
63303e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
6345614e71bSYork Sun 			     const memctl_options_t *popts,
6355614e71bSYork Sun 			     const common_timing_params_t *common_dimm,
6365614e71bSYork Sun 			     unsigned int cas_latency,
6375614e71bSYork Sun 			     unsigned int additive_latency)
6385614e71bSYork Sun {
6395614e71bSYork Sun 	/* Additive latency */
6405614e71bSYork Sun 	unsigned char add_lat_mclk;
6415614e71bSYork Sun 	/* CAS-to-preamble override */
6425614e71bSYork Sun 	unsigned short cpo;
6435614e71bSYork Sun 	/* Write latency */
6445614e71bSYork Sun 	unsigned char wr_lat;
6455614e71bSYork Sun 	/*  Read to precharge (tRTP) */
6465614e71bSYork Sun 	unsigned char rd_to_pre;
6475614e71bSYork Sun 	/* Write command to write data strobe timing adjustment */
6485614e71bSYork Sun 	unsigned char wr_data_delay;
6495614e71bSYork Sun 	/* Minimum CKE pulse width (tCKE) */
6505614e71bSYork Sun 	unsigned char cke_pls;
6515614e71bSYork Sun 	/* Window for four activates (tFAW) */
6525614e71bSYork Sun 	unsigned short four_act;
653bb578322SYork Sun #ifdef CONFIG_SYS_FSL_DDR3
65403e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
655bb578322SYork Sun #endif
6565614e71bSYork Sun 
6575614e71bSYork Sun 	/* FIXME add check that this must be less than acttorw_mclk */
6585614e71bSYork Sun 	add_lat_mclk = additive_latency;
6595614e71bSYork Sun 	cpo = popts->cpo_override;
6605614e71bSYork Sun 
6615614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
6625614e71bSYork Sun 	/*
6635614e71bSYork Sun 	 * This is a lie.  It should really be 1, but if it is
6645614e71bSYork Sun 	 * set to 1, bits overlap into the old controller's
6655614e71bSYork Sun 	 * otherwise unused ACSM field.  If we leave it 0, then
6665614e71bSYork Sun 	 * the HW will magically treat it as 1 for DDR 1.  Oh Yea.
6675614e71bSYork Sun 	 */
6685614e71bSYork Sun 	wr_lat = 0;
6695614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
6705614e71bSYork Sun 	wr_lat = cas_latency - 1;
6715614e71bSYork Sun #else
67203e664d8SYork Sun 	wr_lat = compute_cas_write_latency(ctrl_num);
6735614e71bSYork Sun #endif
6745614e71bSYork Sun 
67534e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
67603e664d8SYork Sun 	rd_to_pre = picos_to_mclk(ctrl_num, 7500);
67734e026f9SYork Sun #else
67803e664d8SYork Sun 	rd_to_pre = picos_to_mclk(ctrl_num, common_dimm->trtp_ps);
67934e026f9SYork Sun #endif
6805614e71bSYork Sun 	/*
6815614e71bSYork Sun 	 * JEDEC has some min requirements for tRTP
6825614e71bSYork Sun 	 */
6835614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR2)
6845614e71bSYork Sun 	if (rd_to_pre  < 2)
6855614e71bSYork Sun 		rd_to_pre  = 2;
68634e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
6875614e71bSYork Sun 	if (rd_to_pre < 4)
6885614e71bSYork Sun 		rd_to_pre = 4;
6895614e71bSYork Sun #endif
6905614e71bSYork Sun 	if (popts->otf_burst_chop_en)
6915614e71bSYork Sun 		rd_to_pre += 2; /* according to UM */
6925614e71bSYork Sun 
6935614e71bSYork Sun 	wr_data_delay = popts->write_data_delay;
69434e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
69534e026f9SYork Sun 	cpo = 0;
69603e664d8SYork Sun 	cke_pls = max(3U, picos_to_mclk(ctrl_num, 5000));
697bb578322SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
698bb578322SYork Sun 	/*
699bb578322SYork Sun 	 * cke pulse = max(3nCK, 7.5ns) for DDR3-800
700bb578322SYork Sun 	 *             max(3nCK, 5.625ns) for DDR3-1066, 1333
701bb578322SYork Sun 	 *             max(3nCK, 5ns) for DDR3-1600, 1866, 2133
702bb578322SYork Sun 	 */
70303e664d8SYork Sun 	cke_pls = max(3U, picos_to_mclk(ctrl_num, mclk_ps > 1870 ? 7500 :
704bb578322SYork Sun 					(mclk_ps > 1245 ? 5625 : 5000)));
70534e026f9SYork Sun #else
706bb578322SYork Sun 	cke_pls = FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR;
70734e026f9SYork Sun #endif
70803e664d8SYork Sun 	four_act = picos_to_mclk(ctrl_num,
70903e664d8SYork Sun 				 popts->tfaw_window_four_activates_ps);
7105614e71bSYork Sun 
7115614e71bSYork Sun 	ddr->timing_cfg_2 = (0
7125614e71bSYork Sun 		| ((add_lat_mclk & 0xf) << 28)
7135614e71bSYork Sun 		| ((cpo & 0x1f) << 23)
7145614e71bSYork Sun 		| ((wr_lat & 0xf) << 19)
7158936691bSYork Sun 		| (((wr_lat & 0x10) >> 4) << 18)
7165614e71bSYork Sun 		| ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT)
7175614e71bSYork Sun 		| ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT)
7185614e71bSYork Sun 		| ((cke_pls & 0x7) << 6)
7195614e71bSYork Sun 		| ((four_act & 0x3f) << 0)
7205614e71bSYork Sun 		);
7215614e71bSYork Sun 	debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2);
7225614e71bSYork Sun }
7235614e71bSYork Sun 
7245614e71bSYork Sun /* DDR SDRAM Register Control Word */
7255614e71bSYork Sun static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
7265614e71bSYork Sun 			       const memctl_options_t *popts,
7275614e71bSYork Sun 			       const common_timing_params_t *common_dimm)
7285614e71bSYork Sun {
7295614e71bSYork Sun 	if (common_dimm->all_dimms_registered &&
7305614e71bSYork Sun 	    !common_dimm->all_dimms_unbuffered)	{
7315614e71bSYork Sun 		if (popts->rcw_override) {
7325614e71bSYork Sun 			ddr->ddr_sdram_rcw_1 = popts->rcw_1;
7335614e71bSYork Sun 			ddr->ddr_sdram_rcw_2 = popts->rcw_2;
7345614e71bSYork Sun 		} else {
7355614e71bSYork Sun 			ddr->ddr_sdram_rcw_1 =
7365614e71bSYork Sun 				common_dimm->rcw[0] << 28 | \
7375614e71bSYork Sun 				common_dimm->rcw[1] << 24 | \
7385614e71bSYork Sun 				common_dimm->rcw[2] << 20 | \
7395614e71bSYork Sun 				common_dimm->rcw[3] << 16 | \
7405614e71bSYork Sun 				common_dimm->rcw[4] << 12 | \
7415614e71bSYork Sun 				common_dimm->rcw[5] << 8 | \
7425614e71bSYork Sun 				common_dimm->rcw[6] << 4 | \
7435614e71bSYork Sun 				common_dimm->rcw[7];
7445614e71bSYork Sun 			ddr->ddr_sdram_rcw_2 =
7455614e71bSYork Sun 				common_dimm->rcw[8] << 28 | \
7465614e71bSYork Sun 				common_dimm->rcw[9] << 24 | \
7475614e71bSYork Sun 				common_dimm->rcw[10] << 20 | \
7485614e71bSYork Sun 				common_dimm->rcw[11] << 16 | \
7495614e71bSYork Sun 				common_dimm->rcw[12] << 12 | \
7505614e71bSYork Sun 				common_dimm->rcw[13] << 8 | \
7515614e71bSYork Sun 				common_dimm->rcw[14] << 4 | \
7525614e71bSYork Sun 				common_dimm->rcw[15];
7535614e71bSYork Sun 		}
7545614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n", ddr->ddr_sdram_rcw_1);
7555614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n", ddr->ddr_sdram_rcw_2);
7565614e71bSYork Sun 	}
7575614e71bSYork Sun }
7585614e71bSYork Sun 
7595614e71bSYork Sun /* DDR SDRAM control configuration (DDR_SDRAM_CFG) */
7605614e71bSYork Sun static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
7615614e71bSYork Sun 			       const memctl_options_t *popts,
7625614e71bSYork Sun 			       const common_timing_params_t *common_dimm)
7635614e71bSYork Sun {
7645614e71bSYork Sun 	unsigned int mem_en;		/* DDR SDRAM interface logic enable */
7655614e71bSYork Sun 	unsigned int sren;		/* Self refresh enable (during sleep) */
7665614e71bSYork Sun 	unsigned int ecc_en;		/* ECC enable. */
7675614e71bSYork Sun 	unsigned int rd_en;		/* Registered DIMM enable */
7685614e71bSYork Sun 	unsigned int sdram_type;	/* Type of SDRAM */
7695614e71bSYork Sun 	unsigned int dyn_pwr;		/* Dynamic power management mode */
7705614e71bSYork Sun 	unsigned int dbw;		/* DRAM dta bus width */
7715614e71bSYork Sun 	unsigned int eight_be = 0;	/* 8-beat burst enable, DDR2 is zero */
7725614e71bSYork Sun 	unsigned int ncap = 0;		/* Non-concurrent auto-precharge */
7735614e71bSYork Sun 	unsigned int threet_en;		/* Enable 3T timing */
7745614e71bSYork Sun 	unsigned int twot_en;		/* Enable 2T timing */
7755614e71bSYork Sun 	unsigned int ba_intlv_ctl;	/* Bank (CS) interleaving control */
7765614e71bSYork Sun 	unsigned int x32_en = 0;	/* x32 enable */
7775614e71bSYork Sun 	unsigned int pchb8 = 0;		/* precharge bit 8 enable */
7785614e71bSYork Sun 	unsigned int hse;		/* Global half strength override */
779d28cb671SYork Sun 	unsigned int acc_ecc_en = 0;	/* Accumulated ECC enable */
7805614e71bSYork Sun 	unsigned int mem_halt = 0;	/* memory controller halt */
7815614e71bSYork Sun 	unsigned int bi = 0;		/* Bypass initialization */
7825614e71bSYork Sun 
7835614e71bSYork Sun 	mem_en = 1;
7845614e71bSYork Sun 	sren = popts->self_refresh_in_sleep;
7855614e71bSYork Sun 	if (common_dimm->all_dimms_ecc_capable) {
7865614e71bSYork Sun 		/* Allow setting of ECC only if all DIMMs are ECC. */
7875614e71bSYork Sun 		ecc_en = popts->ecc_mode;
7885614e71bSYork Sun 	} else {
7895614e71bSYork Sun 		ecc_en = 0;
7905614e71bSYork Sun 	}
7915614e71bSYork Sun 
7925614e71bSYork Sun 	if (common_dimm->all_dimms_registered &&
7935614e71bSYork Sun 	    !common_dimm->all_dimms_unbuffered)	{
7945614e71bSYork Sun 		rd_en = 1;
7955614e71bSYork Sun 		twot_en = 0;
7965614e71bSYork Sun 	} else {
7975614e71bSYork Sun 		rd_en = 0;
7985614e71bSYork Sun 		twot_en = popts->twot_en;
7995614e71bSYork Sun 	}
8005614e71bSYork Sun 
8015614e71bSYork Sun 	sdram_type = CONFIG_FSL_SDRAM_TYPE;
8025614e71bSYork Sun 
8035614e71bSYork Sun 	dyn_pwr = popts->dynamic_power;
8045614e71bSYork Sun 	dbw = popts->data_bus_width;
8055614e71bSYork Sun 	/* 8-beat burst enable DDR-III case
8065614e71bSYork Sun 	 * we must clear it when use the on-the-fly mode,
8075614e71bSYork Sun 	 * must set it when use the 32-bits bus mode.
8085614e71bSYork Sun 	 */
80934e026f9SYork Sun 	if ((sdram_type == SDRAM_TYPE_DDR3) ||
81034e026f9SYork Sun 	    (sdram_type == SDRAM_TYPE_DDR4)) {
8115614e71bSYork Sun 		if (popts->burst_length == DDR_BL8)
8125614e71bSYork Sun 			eight_be = 1;
8135614e71bSYork Sun 		if (popts->burst_length == DDR_OTF)
8145614e71bSYork Sun 			eight_be = 0;
8155614e71bSYork Sun 		if (dbw == 0x1)
8165614e71bSYork Sun 			eight_be = 1;
8175614e71bSYork Sun 	}
8185614e71bSYork Sun 
8195614e71bSYork Sun 	threet_en = popts->threet_en;
8205614e71bSYork Sun 	ba_intlv_ctl = popts->ba_intlv_ctl;
8215614e71bSYork Sun 	hse = popts->half_strength_driver_enable;
8225614e71bSYork Sun 
823d28cb671SYork Sun 	/* set when ddr bus width < 64 */
824d28cb671SYork Sun 	acc_ecc_en = (dbw != 0 && ecc_en == 1) ? 1 : 0;
825d28cb671SYork Sun 
8265614e71bSYork Sun 	ddr->ddr_sdram_cfg = (0
8275614e71bSYork Sun 			| ((mem_en & 0x1) << 31)
8285614e71bSYork Sun 			| ((sren & 0x1) << 30)
8295614e71bSYork Sun 			| ((ecc_en & 0x1) << 29)
8305614e71bSYork Sun 			| ((rd_en & 0x1) << 28)
8315614e71bSYork Sun 			| ((sdram_type & 0x7) << 24)
8325614e71bSYork Sun 			| ((dyn_pwr & 0x1) << 21)
8335614e71bSYork Sun 			| ((dbw & 0x3) << 19)
8345614e71bSYork Sun 			| ((eight_be & 0x1) << 18)
8355614e71bSYork Sun 			| ((ncap & 0x1) << 17)
8365614e71bSYork Sun 			| ((threet_en & 0x1) << 16)
8375614e71bSYork Sun 			| ((twot_en & 0x1) << 15)
8385614e71bSYork Sun 			| ((ba_intlv_ctl & 0x7F) << 8)
8395614e71bSYork Sun 			| ((x32_en & 0x1) << 5)
8405614e71bSYork Sun 			| ((pchb8 & 0x1) << 4)
8415614e71bSYork Sun 			| ((hse & 0x1) << 3)
842d28cb671SYork Sun 			| ((acc_ecc_en & 0x1) << 2)
8435614e71bSYork Sun 			| ((mem_halt & 0x1) << 1)
8445614e71bSYork Sun 			| ((bi & 0x1) << 0)
8455614e71bSYork Sun 			);
8465614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_cfg = 0x%08x\n", ddr->ddr_sdram_cfg);
8475614e71bSYork Sun }
8485614e71bSYork Sun 
8495614e71bSYork Sun /* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */
85003e664d8SYork Sun static void set_ddr_sdram_cfg_2(const unsigned int ctrl_num,
85103e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
8525614e71bSYork Sun 			       const memctl_options_t *popts,
8535614e71bSYork Sun 			       const unsigned int unq_mrs_en)
8545614e71bSYork Sun {
8555614e71bSYork Sun 	unsigned int frc_sr = 0;	/* Force self refresh */
8565614e71bSYork Sun 	unsigned int sr_ie = 0;		/* Self-refresh interrupt enable */
8575614e71bSYork Sun 	unsigned int odt_cfg = 0;	/* ODT configuration */
8585614e71bSYork Sun 	unsigned int num_pr;		/* Number of posted refreshes */
8595614e71bSYork Sun 	unsigned int slow = 0;		/* DDR will be run less than 1250 */
8605614e71bSYork Sun 	unsigned int x4_en = 0;		/* x4 DRAM enable */
8615614e71bSYork Sun 	unsigned int obc_cfg;		/* On-The-Fly Burst Chop Cfg */
8625614e71bSYork Sun 	unsigned int ap_en;		/* Address Parity Enable */
8635614e71bSYork Sun 	unsigned int d_init;		/* DRAM data initialization */
8645614e71bSYork Sun 	unsigned int rcw_en = 0;	/* Register Control Word Enable */
8655614e71bSYork Sun 	unsigned int md_en = 0;		/* Mirrored DIMM Enable */
8665614e71bSYork Sun 	unsigned int qd_en = 0;		/* quad-rank DIMM Enable */
8675614e71bSYork Sun 	int i;
86834e026f9SYork Sun #ifndef CONFIG_SYS_FSL_DDR4
86934e026f9SYork Sun 	unsigned int dll_rst_dis = 1;	/* DLL reset disable */
87034e026f9SYork Sun 	unsigned int dqs_cfg;		/* DQS configuration */
8715614e71bSYork Sun 
8725614e71bSYork Sun 	dqs_cfg = popts->dqs_config;
87334e026f9SYork Sun #endif
8745614e71bSYork Sun 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
8755614e71bSYork Sun 		if (popts->cs_local_opts[i].odt_rd_cfg
8765614e71bSYork Sun 			|| popts->cs_local_opts[i].odt_wr_cfg) {
8775614e71bSYork Sun 			odt_cfg = SDRAM_CFG2_ODT_ONLY_READ;
8785614e71bSYork Sun 			break;
8795614e71bSYork Sun 		}
8805614e71bSYork Sun 	}
881e368c206SJoakim Tjernlund 	sr_ie = popts->self_refresh_interrupt_en;
8825614e71bSYork Sun 	num_pr = 1;	/* Make this configurable */
8835614e71bSYork Sun 
8845614e71bSYork Sun 	/*
8855614e71bSYork Sun 	 * 8572 manual says
8865614e71bSYork Sun 	 *     {TIMING_CFG_1[PRETOACT]
8875614e71bSYork Sun 	 *      + [DDR_SDRAM_CFG_2[NUM_PR]
8885614e71bSYork Sun 	 *        * ({EXT_REFREC || REFREC} + 8 + 2)]}
8895614e71bSYork Sun 	 *      << DDR_SDRAM_INTERVAL[REFINT]
8905614e71bSYork Sun 	 */
89134e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
8925614e71bSYork Sun 	obc_cfg = popts->otf_burst_chop_en;
8935614e71bSYork Sun #else
8945614e71bSYork Sun 	obc_cfg = 0;
8955614e71bSYork Sun #endif
8965614e71bSYork Sun 
8975614e71bSYork Sun #if (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7)
89803e664d8SYork Sun 	slow = get_ddr_freq(ctrl_num) < 1249000000;
8995614e71bSYork Sun #endif
9005614e71bSYork Sun 
901eb118807SShengzhou Liu 	if (popts->registered_dimm_en)
9025614e71bSYork Sun 		rcw_en = 1;
903eb118807SShengzhou Liu 
904eb118807SShengzhou Liu 	/* DDR4 can have address parity for UDIMM and discrete */
905eb118807SShengzhou Liu 	if ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) &&
906eb118807SShengzhou Liu 	    (!popts->registered_dimm_en)) {
9075614e71bSYork Sun 		ap_en = 0;
908eb118807SShengzhou Liu 	} else {
909eb118807SShengzhou Liu 		ap_en = popts->ap_en;
9105614e71bSYork Sun 	}
9115614e71bSYork Sun 
9125614e71bSYork Sun 	x4_en = popts->x4_en ? 1 : 0;
9135614e71bSYork Sun 
9145614e71bSYork Sun #if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
9155614e71bSYork Sun 	/* Use the DDR controller to auto initialize memory. */
9165614e71bSYork Sun 	d_init = popts->ecc_init_using_memctl;
9175614e71bSYork Sun 	ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE;
9185614e71bSYork Sun 	debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init);
9195614e71bSYork Sun #else
9205614e71bSYork Sun 	/* Memory will be initialized via DMA, or not at all. */
9215614e71bSYork Sun 	d_init = 0;
9225614e71bSYork Sun #endif
9235614e71bSYork Sun 
92434e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
9255614e71bSYork Sun 	md_en = popts->mirrored_dimm;
9265614e71bSYork Sun #endif
9275614e71bSYork Sun 	qd_en = popts->quad_rank_present ? 1 : 0;
9285614e71bSYork Sun 	ddr->ddr_sdram_cfg_2 = (0
9295614e71bSYork Sun 		| ((frc_sr & 0x1) << 31)
9305614e71bSYork Sun 		| ((sr_ie & 0x1) << 30)
93134e026f9SYork Sun #ifndef CONFIG_SYS_FSL_DDR4
9325614e71bSYork Sun 		| ((dll_rst_dis & 0x1) << 29)
9335614e71bSYork Sun 		| ((dqs_cfg & 0x3) << 26)
93434e026f9SYork Sun #endif
9355614e71bSYork Sun 		| ((odt_cfg & 0x3) << 21)
9365614e71bSYork Sun 		| ((num_pr & 0xf) << 12)
9375614e71bSYork Sun 		| ((slow & 1) << 11)
9385614e71bSYork Sun 		| (x4_en << 10)
9395614e71bSYork Sun 		| (qd_en << 9)
9405614e71bSYork Sun 		| (unq_mrs_en << 8)
9415614e71bSYork Sun 		| ((obc_cfg & 0x1) << 6)
9425614e71bSYork Sun 		| ((ap_en & 0x1) << 5)
9435614e71bSYork Sun 		| ((d_init & 0x1) << 4)
9445614e71bSYork Sun 		| ((rcw_en & 0x1) << 2)
9455614e71bSYork Sun 		| ((md_en & 0x1) << 0)
9465614e71bSYork Sun 		);
9475614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2);
9485614e71bSYork Sun }
9495614e71bSYork Sun 
95034e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
9515614e71bSYork Sun /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
95203e664d8SYork Sun static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
95303e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
9545614e71bSYork Sun 				const memctl_options_t *popts,
9555614e71bSYork Sun 				const common_timing_params_t *common_dimm,
9565614e71bSYork Sun 				const unsigned int unq_mrs_en)
9575614e71bSYork Sun {
9585614e71bSYork Sun 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
9595614e71bSYork Sun 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
9605614e71bSYork Sun 	int i;
96134e026f9SYork Sun 	unsigned int wr_crc = 0;	/* Disable */
9625614e71bSYork Sun 	unsigned int rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
9635614e71bSYork Sun 	unsigned int srt = 0;	/* self-refresh temerature, normal range */
96403e664d8SYork Sun 	unsigned int cwl = compute_cas_write_latency(ctrl_num) - 9;
96534e026f9SYork Sun 	unsigned int mpr = 0;	/* serial */
96634e026f9SYork Sun 	unsigned int wc_lat;
96703e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
9685614e71bSYork Sun 
9695614e71bSYork Sun 	if (popts->rtt_override)
9705614e71bSYork Sun 		rtt_wr = popts->rtt_wr_override_value;
9715614e71bSYork Sun 	else
9725614e71bSYork Sun 		rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
9735614e71bSYork Sun 
9745614e71bSYork Sun 	if (common_dimm->extended_op_srt)
9755614e71bSYork Sun 		srt = common_dimm->extended_op_srt;
9765614e71bSYork Sun 
9775614e71bSYork Sun 	esdmode2 = (0
97834e026f9SYork Sun 		| ((wr_crc & 0x1) << 12)
9795614e71bSYork Sun 		| ((rtt_wr & 0x3) << 9)
98034e026f9SYork Sun 		| ((srt & 0x3) << 6)
98134e026f9SYork Sun 		| ((cwl & 0x7) << 3));
98234e026f9SYork Sun 
98334e026f9SYork Sun 	if (mclk_ps >= 1250)
98434e026f9SYork Sun 		wc_lat = 0;
98534e026f9SYork Sun 	else if (mclk_ps >= 833)
98634e026f9SYork Sun 		wc_lat = 1;
98734e026f9SYork Sun 	else
98834e026f9SYork Sun 		wc_lat = 2;
98934e026f9SYork Sun 
99034e026f9SYork Sun 	esdmode3 = (0
99134e026f9SYork Sun 		| ((mpr & 0x3) << 11)
99234e026f9SYork Sun 		| ((wc_lat & 0x3) << 9));
99334e026f9SYork Sun 
9945614e71bSYork Sun 	ddr->ddr_sdram_mode_2 = (0
9955614e71bSYork Sun 				 | ((esdmode2 & 0xFFFF) << 16)
9965614e71bSYork Sun 				 | ((esdmode3 & 0xFFFF) << 0)
9975614e71bSYork Sun 				 );
9985614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
9995614e71bSYork Sun 
10005614e71bSYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
10015614e71bSYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
10025614e71bSYork Sun 			if (popts->rtt_override)
10035614e71bSYork Sun 				rtt_wr = popts->rtt_wr_override_value;
10045614e71bSYork Sun 			else
10055614e71bSYork Sun 				rtt_wr = popts->cs_local_opts[i].odt_rtt_wr;
10065614e71bSYork Sun 
10075614e71bSYork Sun 			esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
10085614e71bSYork Sun 			esdmode2 |= (rtt_wr & 0x3) << 9;
10095614e71bSYork Sun 			switch (i) {
10105614e71bSYork Sun 			case 1:
10115614e71bSYork Sun 				ddr->ddr_sdram_mode_4 = (0
10125614e71bSYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
10135614e71bSYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
10145614e71bSYork Sun 					);
10155614e71bSYork Sun 				break;
10165614e71bSYork Sun 			case 2:
10175614e71bSYork Sun 				ddr->ddr_sdram_mode_6 = (0
10185614e71bSYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
10195614e71bSYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
10205614e71bSYork Sun 					);
10215614e71bSYork Sun 				break;
10225614e71bSYork Sun 			case 3:
10235614e71bSYork Sun 				ddr->ddr_sdram_mode_8 = (0
10245614e71bSYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
10255614e71bSYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
10265614e71bSYork Sun 					);
10275614e71bSYork Sun 				break;
10285614e71bSYork Sun 			}
10295614e71bSYork Sun 		}
10305614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
10315614e71bSYork Sun 		      ddr->ddr_sdram_mode_4);
10325614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
10335614e71bSYork Sun 		      ddr->ddr_sdram_mode_6);
10345614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
10355614e71bSYork Sun 		      ddr->ddr_sdram_mode_8);
10365614e71bSYork Sun 	}
10375614e71bSYork Sun }
103834e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
103934e026f9SYork Sun /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
104003e664d8SYork Sun static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
104103e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
104234e026f9SYork Sun 				const memctl_options_t *popts,
104334e026f9SYork Sun 				const common_timing_params_t *common_dimm,
104434e026f9SYork Sun 				const unsigned int unq_mrs_en)
104534e026f9SYork Sun {
104634e026f9SYork Sun 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
104734e026f9SYork Sun 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
104834e026f9SYork Sun 	int i;
104934e026f9SYork Sun 	unsigned int rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
105034e026f9SYork Sun 	unsigned int srt = 0;	/* self-refresh temerature, normal range */
105134e026f9SYork Sun 	unsigned int asr = 0;	/* auto self-refresh disable */
105203e664d8SYork Sun 	unsigned int cwl = compute_cas_write_latency(ctrl_num) - 5;
105334e026f9SYork Sun 	unsigned int pasr = 0;	/* partial array self refresh disable */
105434e026f9SYork Sun 
105534e026f9SYork Sun 	if (popts->rtt_override)
105634e026f9SYork Sun 		rtt_wr = popts->rtt_wr_override_value;
105734e026f9SYork Sun 	else
105834e026f9SYork Sun 		rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
105934e026f9SYork Sun 
106034e026f9SYork Sun 	if (common_dimm->extended_op_srt)
106134e026f9SYork Sun 		srt = common_dimm->extended_op_srt;
106234e026f9SYork Sun 
106334e026f9SYork Sun 	esdmode2 = (0
106434e026f9SYork Sun 		| ((rtt_wr & 0x3) << 9)
106534e026f9SYork Sun 		| ((srt & 0x1) << 7)
106634e026f9SYork Sun 		| ((asr & 0x1) << 6)
106734e026f9SYork Sun 		| ((cwl & 0x7) << 3)
106834e026f9SYork Sun 		| ((pasr & 0x7) << 0));
106934e026f9SYork Sun 	ddr->ddr_sdram_mode_2 = (0
107034e026f9SYork Sun 				 | ((esdmode2 & 0xFFFF) << 16)
107134e026f9SYork Sun 				 | ((esdmode3 & 0xFFFF) << 0)
107234e026f9SYork Sun 				 );
107334e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
107434e026f9SYork Sun 
107534e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
107634e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
107734e026f9SYork Sun 			if (popts->rtt_override)
107834e026f9SYork Sun 				rtt_wr = popts->rtt_wr_override_value;
107934e026f9SYork Sun 			else
108034e026f9SYork Sun 				rtt_wr = popts->cs_local_opts[i].odt_rtt_wr;
108134e026f9SYork Sun 
108234e026f9SYork Sun 			esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
108334e026f9SYork Sun 			esdmode2 |= (rtt_wr & 0x3) << 9;
108434e026f9SYork Sun 			switch (i) {
108534e026f9SYork Sun 			case 1:
108634e026f9SYork Sun 				ddr->ddr_sdram_mode_4 = (0
108734e026f9SYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
108834e026f9SYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
108934e026f9SYork Sun 					);
109034e026f9SYork Sun 				break;
109134e026f9SYork Sun 			case 2:
109234e026f9SYork Sun 				ddr->ddr_sdram_mode_6 = (0
109334e026f9SYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
109434e026f9SYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
109534e026f9SYork Sun 					);
109634e026f9SYork Sun 				break;
109734e026f9SYork Sun 			case 3:
109834e026f9SYork Sun 				ddr->ddr_sdram_mode_8 = (0
109934e026f9SYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
110034e026f9SYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
110134e026f9SYork Sun 					);
110234e026f9SYork Sun 				break;
110334e026f9SYork Sun 			}
110434e026f9SYork Sun 		}
110534e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
110634e026f9SYork Sun 			ddr->ddr_sdram_mode_4);
110734e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
110834e026f9SYork Sun 			ddr->ddr_sdram_mode_6);
110934e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
111034e026f9SYork Sun 			ddr->ddr_sdram_mode_8);
111134e026f9SYork Sun 	}
111234e026f9SYork Sun }
111334e026f9SYork Sun 
111434e026f9SYork Sun #else /* for DDR2 and DDR1 */
111534e026f9SYork Sun /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
111603e664d8SYork Sun static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
111703e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
111834e026f9SYork Sun 				const memctl_options_t *popts,
111934e026f9SYork Sun 				const common_timing_params_t *common_dimm,
112034e026f9SYork Sun 				const unsigned int unq_mrs_en)
112134e026f9SYork Sun {
112234e026f9SYork Sun 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
112334e026f9SYork Sun 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
112434e026f9SYork Sun 
112534e026f9SYork Sun 	ddr->ddr_sdram_mode_2 = (0
112634e026f9SYork Sun 				 | ((esdmode2 & 0xFFFF) << 16)
112734e026f9SYork Sun 				 | ((esdmode3 & 0xFFFF) << 0)
112834e026f9SYork Sun 				 );
112934e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
113034e026f9SYork Sun }
113134e026f9SYork Sun #endif
113234e026f9SYork Sun 
113334e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
113434e026f9SYork Sun /* DDR SDRAM Mode configuration 9 (DDR_SDRAM_MODE_9) */
113534e026f9SYork Sun static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
113634e026f9SYork Sun 				const memctl_options_t *popts,
113734e026f9SYork Sun 				const common_timing_params_t *common_dimm,
113834e026f9SYork Sun 				const unsigned int unq_mrs_en)
113934e026f9SYork Sun {
114034e026f9SYork Sun 	int i;
114134e026f9SYork Sun 	unsigned short esdmode4 = 0;	/* Extended SDRAM mode 4 */
114234e026f9SYork Sun 	unsigned short esdmode5;	/* Extended SDRAM mode 5 */
11436b95be22SYork Sun 	int rtt_park = 0;
11448a51429eSYork Sun 	bool four_cs = false;
1145eb118807SShengzhou Liu 	const unsigned int mclk_ps = get_memory_clk_period_ps(0);
114634e026f9SYork Sun 
11478a51429eSYork Sun #if CONFIG_CHIP_SELECTS_PER_CTRL == 4
11488a51429eSYork Sun 	if ((ddr->cs[0].config & SDRAM_CS_CONFIG_EN) &&
11498a51429eSYork Sun 	    (ddr->cs[1].config & SDRAM_CS_CONFIG_EN) &&
11508a51429eSYork Sun 	    (ddr->cs[2].config & SDRAM_CS_CONFIG_EN) &&
11518a51429eSYork Sun 	    (ddr->cs[3].config & SDRAM_CS_CONFIG_EN))
11528a51429eSYork Sun 		four_cs = true;
11538a51429eSYork Sun #endif
11546b95be22SYork Sun 	if (ddr->cs[0].config & SDRAM_CS_CONFIG_EN) {
11556b95be22SYork Sun 		esdmode5 = 0x00000500;	/* Data mask enable, RTT_PARK CS0 */
11568a51429eSYork Sun 		rtt_park = four_cs ? 0 : 1;
11576b95be22SYork Sun 	} else {
11586b95be22SYork Sun 		esdmode5 = 0x00000400;	/* Data mask enabled */
11596b95be22SYork Sun 	}
116034e026f9SYork Sun 
1161eb118807SShengzhou Liu 	/* set command/address parity latency */
1162eb118807SShengzhou Liu 	if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) {
1163eb118807SShengzhou Liu 		if (mclk_ps >= 935) {
1164eb118807SShengzhou Liu 			/* for DDR4-1600/1866/2133 */
1165eb118807SShengzhou Liu 			esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK;
1166eb118807SShengzhou Liu 		} else if (mclk_ps >= 833) {
1167eb118807SShengzhou Liu 			/* for DDR4-2400 */
1168eb118807SShengzhou Liu 			esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK;
1169eb118807SShengzhou Liu 		} else {
1170eb118807SShengzhou Liu 			printf("parity: mclk_ps = %d not supported\n", mclk_ps);
1171eb118807SShengzhou Liu 		}
1172eb118807SShengzhou Liu 	}
1173eb118807SShengzhou Liu 
117434e026f9SYork Sun 	ddr->ddr_sdram_mode_9 = (0
117534e026f9SYork Sun 				 | ((esdmode4 & 0xffff) << 16)
117634e026f9SYork Sun 				 | ((esdmode5 & 0xffff) << 0)
117734e026f9SYork Sun 				);
117866869f95SYork Sun 
11798a51429eSYork Sun 	/* Normally only the first enabled CS use 0x500, others use 0x400
11808a51429eSYork Sun 	 * But when four chip-selects are all enabled, all mode registers
11818a51429eSYork Sun 	 * need 0x500 to park.
11828a51429eSYork Sun 	 */
118366869f95SYork Sun 
118434e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode_9) = 0x%08x\n", ddr->ddr_sdram_mode_9);
118534e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
118634e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
11876b95be22SYork Sun 			if (!rtt_park &&
11886b95be22SYork Sun 			    (ddr->cs[i].config & SDRAM_CS_CONFIG_EN)) {
11896b95be22SYork Sun 				esdmode5 |= 0x00000500;	/* RTT_PARK */
11908a51429eSYork Sun 				rtt_park = four_cs ? 0 : 1;
11916b95be22SYork Sun 			} else {
11926b95be22SYork Sun 				esdmode5 = 0x00000400;
11936b95be22SYork Sun 			}
1194eb118807SShengzhou Liu 
1195eb118807SShengzhou Liu 			if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) {
1196eb118807SShengzhou Liu 				if (mclk_ps >= 935) {
1197eb118807SShengzhou Liu 					/* for DDR4-1600/1866/2133 */
1198eb118807SShengzhou Liu 					esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK;
1199eb118807SShengzhou Liu 				} else if (mclk_ps >= 833) {
1200eb118807SShengzhou Liu 					/* for DDR4-2400 */
1201eb118807SShengzhou Liu 					esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK;
1202eb118807SShengzhou Liu 				} else {
1203eb118807SShengzhou Liu 					printf("parity: mclk_ps = %d not supported\n",
1204eb118807SShengzhou Liu 					       mclk_ps);
1205eb118807SShengzhou Liu 				}
1206eb118807SShengzhou Liu 			}
1207eb118807SShengzhou Liu 
120834e026f9SYork Sun 			switch (i) {
120934e026f9SYork Sun 			case 1:
121034e026f9SYork Sun 				ddr->ddr_sdram_mode_11 = (0
121134e026f9SYork Sun 					| ((esdmode4 & 0xFFFF) << 16)
121234e026f9SYork Sun 					| ((esdmode5 & 0xFFFF) << 0)
121334e026f9SYork Sun 					);
121434e026f9SYork Sun 				break;
121534e026f9SYork Sun 			case 2:
121634e026f9SYork Sun 				ddr->ddr_sdram_mode_13 = (0
121734e026f9SYork Sun 					| ((esdmode4 & 0xFFFF) << 16)
121834e026f9SYork Sun 					| ((esdmode5 & 0xFFFF) << 0)
121934e026f9SYork Sun 					);
122034e026f9SYork Sun 				break;
122134e026f9SYork Sun 			case 3:
122234e026f9SYork Sun 				ddr->ddr_sdram_mode_15 = (0
122334e026f9SYork Sun 					| ((esdmode4 & 0xFFFF) << 16)
122434e026f9SYork Sun 					| ((esdmode5 & 0xFFFF) << 0)
122534e026f9SYork Sun 					);
122634e026f9SYork Sun 				break;
122734e026f9SYork Sun 			}
122834e026f9SYork Sun 		}
122934e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_11 = 0x%08x\n",
123034e026f9SYork Sun 		      ddr->ddr_sdram_mode_11);
123134e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_13 = 0x%08x\n",
123234e026f9SYork Sun 		      ddr->ddr_sdram_mode_13);
123334e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_15 = 0x%08x\n",
123434e026f9SYork Sun 		      ddr->ddr_sdram_mode_15);
123534e026f9SYork Sun 	}
123634e026f9SYork Sun }
123734e026f9SYork Sun 
123834e026f9SYork Sun /* DDR SDRAM Mode configuration 10 (DDR_SDRAM_MODE_10) */
123903e664d8SYork Sun static void set_ddr_sdram_mode_10(const unsigned int ctrl_num,
124003e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
124134e026f9SYork Sun 				const memctl_options_t *popts,
124234e026f9SYork Sun 				const common_timing_params_t *common_dimm,
124334e026f9SYork Sun 				const unsigned int unq_mrs_en)
124434e026f9SYork Sun {
124534e026f9SYork Sun 	int i;
124634e026f9SYork Sun 	unsigned short esdmode6 = 0;	/* Extended SDRAM mode 6 */
124734e026f9SYork Sun 	unsigned short esdmode7 = 0;	/* Extended SDRAM mode 7 */
124803e664d8SYork Sun 	unsigned int tccdl_min = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps);
124934e026f9SYork Sun 
125034e026f9SYork Sun 	esdmode6 = ((tccdl_min - 4) & 0x7) << 10;
125134e026f9SYork Sun 
12520fb71974SYork Sun 	if (popts->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2)
12530fb71974SYork Sun 		esdmode6 |= 1 << 6;	/* Range 2 */
12540fb71974SYork Sun 
125534e026f9SYork Sun 	ddr->ddr_sdram_mode_10 = (0
125634e026f9SYork Sun 				 | ((esdmode6 & 0xffff) << 16)
125734e026f9SYork Sun 				 | ((esdmode7 & 0xffff) << 0)
125834e026f9SYork Sun 				);
125934e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode_10) = 0x%08x\n", ddr->ddr_sdram_mode_10);
126034e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
126134e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
126234e026f9SYork Sun 			switch (i) {
126334e026f9SYork Sun 			case 1:
126434e026f9SYork Sun 				ddr->ddr_sdram_mode_12 = (0
126534e026f9SYork Sun 					| ((esdmode6 & 0xFFFF) << 16)
126634e026f9SYork Sun 					| ((esdmode7 & 0xFFFF) << 0)
126734e026f9SYork Sun 					);
126834e026f9SYork Sun 				break;
126934e026f9SYork Sun 			case 2:
127034e026f9SYork Sun 				ddr->ddr_sdram_mode_14 = (0
127134e026f9SYork Sun 					| ((esdmode6 & 0xFFFF) << 16)
127234e026f9SYork Sun 					| ((esdmode7 & 0xFFFF) << 0)
127334e026f9SYork Sun 					);
127434e026f9SYork Sun 				break;
127534e026f9SYork Sun 			case 3:
127634e026f9SYork Sun 				ddr->ddr_sdram_mode_16 = (0
127734e026f9SYork Sun 					| ((esdmode6 & 0xFFFF) << 16)
127834e026f9SYork Sun 					| ((esdmode7 & 0xFFFF) << 0)
127934e026f9SYork Sun 					);
128034e026f9SYork Sun 				break;
128134e026f9SYork Sun 			}
128234e026f9SYork Sun 		}
128334e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_12 = 0x%08x\n",
128434e026f9SYork Sun 		      ddr->ddr_sdram_mode_12);
128534e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_14 = 0x%08x\n",
128634e026f9SYork Sun 		      ddr->ddr_sdram_mode_14);
128734e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_16 = 0x%08x\n",
128834e026f9SYork Sun 		      ddr->ddr_sdram_mode_16);
128934e026f9SYork Sun 	}
129034e026f9SYork Sun }
129134e026f9SYork Sun 
129234e026f9SYork Sun #endif
12935614e71bSYork Sun 
12945614e71bSYork Sun /* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */
129503e664d8SYork Sun static void set_ddr_sdram_interval(const unsigned int ctrl_num,
129603e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
12975614e71bSYork Sun 				const memctl_options_t *popts,
12985614e71bSYork Sun 				const common_timing_params_t *common_dimm)
12995614e71bSYork Sun {
13005614e71bSYork Sun 	unsigned int refint;	/* Refresh interval */
13015614e71bSYork Sun 	unsigned int bstopre;	/* Precharge interval */
13025614e71bSYork Sun 
130303e664d8SYork Sun 	refint = picos_to_mclk(ctrl_num, common_dimm->refresh_rate_ps);
13045614e71bSYork Sun 
13055614e71bSYork Sun 	bstopre = popts->bstopre;
13065614e71bSYork Sun 
13075614e71bSYork Sun 	/* refint field used 0x3FFF in earlier controllers */
13085614e71bSYork Sun 	ddr->ddr_sdram_interval = (0
13095614e71bSYork Sun 				   | ((refint & 0xFFFF) << 16)
13105614e71bSYork Sun 				   | ((bstopre & 0x3FFF) << 0)
13115614e71bSYork Sun 				   );
13125614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval);
13135614e71bSYork Sun }
13145614e71bSYork Sun 
131534e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
13165614e71bSYork Sun /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
131703e664d8SYork Sun static void set_ddr_sdram_mode(const unsigned int ctrl_num,
131803e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
13195614e71bSYork Sun 			       const memctl_options_t *popts,
13205614e71bSYork Sun 			       const common_timing_params_t *common_dimm,
13215614e71bSYork Sun 			       unsigned int cas_latency,
13225614e71bSYork Sun 			       unsigned int additive_latency,
13235614e71bSYork Sun 			       const unsigned int unq_mrs_en)
13245614e71bSYork Sun {
132534e026f9SYork Sun 	int i;
132634e026f9SYork Sun 	unsigned short esdmode;		/* Extended SDRAM mode */
132734e026f9SYork Sun 	unsigned short sdmode;		/* SDRAM mode */
132834e026f9SYork Sun 
132934e026f9SYork Sun 	/* Mode Register - MR1 */
133034e026f9SYork Sun 	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
133134e026f9SYork Sun 	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
133234e026f9SYork Sun 	unsigned int rtt;
133334e026f9SYork Sun 	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
133434e026f9SYork Sun 	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
133534e026f9SYork Sun 	unsigned int dic = 0;		/* Output driver impedance, 40ohm */
133634e026f9SYork Sun 	unsigned int dll_en = 1;	/* DLL Enable  1=Enable (Normal),
133734e026f9SYork Sun 						       0=Disable (Test/Debug) */
133834e026f9SYork Sun 
133934e026f9SYork Sun 	/* Mode Register - MR0 */
134034e026f9SYork Sun 	unsigned int wr = 0;	/* Write Recovery */
134134e026f9SYork Sun 	unsigned int dll_rst;	/* DLL Reset */
134234e026f9SYork Sun 	unsigned int mode;	/* Normal=0 or Test=1 */
134334e026f9SYork Sun 	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
134434e026f9SYork Sun 	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
134534e026f9SYork Sun 	unsigned int bt;
134634e026f9SYork Sun 	unsigned int bl;	/* BL: Burst Length */
134734e026f9SYork Sun 
134834e026f9SYork Sun 	unsigned int wr_mclk;
134934e026f9SYork Sun 	/* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */
135034e026f9SYork Sun 	static const u8 wr_table[] = {
135134e026f9SYork Sun 		0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6};
135234e026f9SYork Sun 	/* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */
135334e026f9SYork Sun 	static const u8 cas_latency_table[] = {
135434e026f9SYork Sun 		0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
135534e026f9SYork Sun 		9, 9, 10, 10, 11, 11};
135634e026f9SYork Sun 
135734e026f9SYork Sun 	if (popts->rtt_override)
135834e026f9SYork Sun 		rtt = popts->rtt_override_value;
135934e026f9SYork Sun 	else
136034e026f9SYork Sun 		rtt = popts->cs_local_opts[0].odt_rtt_norm;
136134e026f9SYork Sun 
136234e026f9SYork Sun 	if (additive_latency == (cas_latency - 1))
136334e026f9SYork Sun 		al = 1;
136434e026f9SYork Sun 	if (additive_latency == (cas_latency - 2))
136534e026f9SYork Sun 		al = 2;
136634e026f9SYork Sun 
136734e026f9SYork Sun 	if (popts->quad_rank_present)
136834e026f9SYork Sun 		dic = 1;	/* output driver impedance 240/7 ohm */
136934e026f9SYork Sun 
137034e026f9SYork Sun 	/*
137134e026f9SYork Sun 	 * The esdmode value will also be used for writing
137234e026f9SYork Sun 	 * MR1 during write leveling for DDR3, although the
137334e026f9SYork Sun 	 * bits specifically related to the write leveling
137434e026f9SYork Sun 	 * scheme will be handled automatically by the DDR
137534e026f9SYork Sun 	 * controller. so we set the wrlvl_en = 0 here.
137634e026f9SYork Sun 	 */
137734e026f9SYork Sun 	esdmode = (0
137834e026f9SYork Sun 		| ((qoff & 0x1) << 12)
137934e026f9SYork Sun 		| ((tdqs_en & 0x1) << 11)
138034e026f9SYork Sun 		| ((rtt & 0x7) << 8)
138134e026f9SYork Sun 		| ((wrlvl_en & 0x1) << 7)
138234e026f9SYork Sun 		| ((al & 0x3) << 3)
138334e026f9SYork Sun 		| ((dic & 0x3) << 1)   /* DIC field is split */
138434e026f9SYork Sun 		| ((dll_en & 0x1) << 0)
138534e026f9SYork Sun 		);
138634e026f9SYork Sun 
138734e026f9SYork Sun 	/*
138834e026f9SYork Sun 	 * DLL control for precharge PD
138934e026f9SYork Sun 	 * 0=slow exit DLL off (tXPDLL)
139034e026f9SYork Sun 	 * 1=fast exit DLL on (tXP)
139134e026f9SYork Sun 	 */
139234e026f9SYork Sun 
139303e664d8SYork Sun 	wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
139434e026f9SYork Sun 	if (wr_mclk <= 24) {
139534e026f9SYork Sun 		wr = wr_table[wr_mclk - 10];
139634e026f9SYork Sun 	} else {
139734e026f9SYork Sun 		printf("Error: unsupported write recovery for mode register wr_mclk = %d\n",
139834e026f9SYork Sun 		       wr_mclk);
139934e026f9SYork Sun 	}
140034e026f9SYork Sun 
140134e026f9SYork Sun 	dll_rst = 0;	/* dll no reset */
140234e026f9SYork Sun 	mode = 0;	/* normal mode */
140334e026f9SYork Sun 
140434e026f9SYork Sun 	/* look up table to get the cas latency bits */
140534e026f9SYork Sun 	if (cas_latency >= 9 && cas_latency <= 24)
140634e026f9SYork Sun 		caslat = cas_latency_table[cas_latency - 9];
140734e026f9SYork Sun 	else
140834e026f9SYork Sun 		printf("Error: unsupported cas latency for mode register\n");
140934e026f9SYork Sun 
141034e026f9SYork Sun 	bt = 0;	/* Nibble sequential */
141134e026f9SYork Sun 
141234e026f9SYork Sun 	switch (popts->burst_length) {
141334e026f9SYork Sun 	case DDR_BL8:
141434e026f9SYork Sun 		bl = 0;
141534e026f9SYork Sun 		break;
141634e026f9SYork Sun 	case DDR_OTF:
141734e026f9SYork Sun 		bl = 1;
141834e026f9SYork Sun 		break;
141934e026f9SYork Sun 	case DDR_BC4:
142034e026f9SYork Sun 		bl = 2;
142134e026f9SYork Sun 		break;
142234e026f9SYork Sun 	default:
142334e026f9SYork Sun 		printf("Error: invalid burst length of %u specified. ",
142434e026f9SYork Sun 		       popts->burst_length);
142534e026f9SYork Sun 		puts("Defaulting to on-the-fly BC4 or BL8 beats.\n");
142634e026f9SYork Sun 		bl = 1;
142734e026f9SYork Sun 		break;
142834e026f9SYork Sun 	}
142934e026f9SYork Sun 
143034e026f9SYork Sun 	sdmode = (0
143134e026f9SYork Sun 		  | ((wr & 0x7) << 9)
143234e026f9SYork Sun 		  | ((dll_rst & 0x1) << 8)
143334e026f9SYork Sun 		  | ((mode & 0x1) << 7)
143434e026f9SYork Sun 		  | (((caslat >> 1) & 0x7) << 4)
143534e026f9SYork Sun 		  | ((bt & 0x1) << 3)
143634e026f9SYork Sun 		  | ((caslat & 1) << 2)
143734e026f9SYork Sun 		  | ((bl & 0x3) << 0)
143834e026f9SYork Sun 		  );
143934e026f9SYork Sun 
144034e026f9SYork Sun 	ddr->ddr_sdram_mode = (0
144134e026f9SYork Sun 			       | ((esdmode & 0xFFFF) << 16)
144234e026f9SYork Sun 			       | ((sdmode & 0xFFFF) << 0)
144334e026f9SYork Sun 			       );
144434e026f9SYork Sun 
144534e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
144634e026f9SYork Sun 
144734e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
144834e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
144934e026f9SYork Sun 			if (popts->rtt_override)
145034e026f9SYork Sun 				rtt = popts->rtt_override_value;
145134e026f9SYork Sun 			else
145234e026f9SYork Sun 				rtt = popts->cs_local_opts[i].odt_rtt_norm;
145334e026f9SYork Sun 
145434e026f9SYork Sun 			esdmode &= 0xF8FF;	/* clear bit 10,9,8 for rtt */
145534e026f9SYork Sun 			esdmode |= (rtt & 0x7) << 8;
145634e026f9SYork Sun 			switch (i) {
145734e026f9SYork Sun 			case 1:
145834e026f9SYork Sun 				ddr->ddr_sdram_mode_3 = (0
145934e026f9SYork Sun 				       | ((esdmode & 0xFFFF) << 16)
146034e026f9SYork Sun 				       | ((sdmode & 0xFFFF) << 0)
146134e026f9SYork Sun 				       );
146234e026f9SYork Sun 				break;
146334e026f9SYork Sun 			case 2:
146434e026f9SYork Sun 				ddr->ddr_sdram_mode_5 = (0
146534e026f9SYork Sun 				       | ((esdmode & 0xFFFF) << 16)
146634e026f9SYork Sun 				       | ((sdmode & 0xFFFF) << 0)
146734e026f9SYork Sun 				       );
146834e026f9SYork Sun 				break;
146934e026f9SYork Sun 			case 3:
147034e026f9SYork Sun 				ddr->ddr_sdram_mode_7 = (0
147134e026f9SYork Sun 				       | ((esdmode & 0xFFFF) << 16)
147234e026f9SYork Sun 				       | ((sdmode & 0xFFFF) << 0)
147334e026f9SYork Sun 				       );
147434e026f9SYork Sun 				break;
147534e026f9SYork Sun 			}
147634e026f9SYork Sun 		}
147734e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
147834e026f9SYork Sun 		      ddr->ddr_sdram_mode_3);
147934e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
148034e026f9SYork Sun 		      ddr->ddr_sdram_mode_5);
148134e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
148234e026f9SYork Sun 		      ddr->ddr_sdram_mode_5);
148334e026f9SYork Sun 	}
148434e026f9SYork Sun }
148534e026f9SYork Sun 
148634e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
148734e026f9SYork Sun /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
148803e664d8SYork Sun static void set_ddr_sdram_mode(const unsigned int ctrl_num,
148903e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
149034e026f9SYork Sun 			       const memctl_options_t *popts,
149134e026f9SYork Sun 			       const common_timing_params_t *common_dimm,
149234e026f9SYork Sun 			       unsigned int cas_latency,
149334e026f9SYork Sun 			       unsigned int additive_latency,
149434e026f9SYork Sun 			       const unsigned int unq_mrs_en)
149534e026f9SYork Sun {
149634e026f9SYork Sun 	int i;
14975614e71bSYork Sun 	unsigned short esdmode;		/* Extended SDRAM mode */
14985614e71bSYork Sun 	unsigned short sdmode;		/* SDRAM mode */
14995614e71bSYork Sun 
15005614e71bSYork Sun 	/* Mode Register - MR1 */
15015614e71bSYork Sun 	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
15025614e71bSYork Sun 	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
15035614e71bSYork Sun 	unsigned int rtt;
15045614e71bSYork Sun 	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
15055614e71bSYork Sun 	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
15065614e71bSYork Sun 	unsigned int dic = 0;		/* Output driver impedance, 40ohm */
15075614e71bSYork Sun 	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
15085614e71bSYork Sun 						       1=Disable (Test/Debug) */
15095614e71bSYork Sun 
15105614e71bSYork Sun 	/* Mode Register - MR0 */
15115614e71bSYork Sun 	unsigned int dll_on;	/* DLL control for precharge PD, 0=off, 1=on */
15125614e71bSYork Sun 	unsigned int wr = 0;	/* Write Recovery */
15135614e71bSYork Sun 	unsigned int dll_rst;	/* DLL Reset */
15145614e71bSYork Sun 	unsigned int mode;	/* Normal=0 or Test=1 */
15155614e71bSYork Sun 	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
15165614e71bSYork Sun 	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
15175614e71bSYork Sun 	unsigned int bt;
15185614e71bSYork Sun 	unsigned int bl;	/* BL: Burst Length */
15195614e71bSYork Sun 
15205614e71bSYork Sun 	unsigned int wr_mclk;
15215614e71bSYork Sun 	/*
15225614e71bSYork Sun 	 * DDR_SDRAM_MODE doesn't support 9,11,13,15
15235614e71bSYork Sun 	 * Please refer JEDEC Standard No. 79-3E for Mode Register MR0
15245614e71bSYork Sun 	 * for this table
15255614e71bSYork Sun 	 */
15265614e71bSYork Sun 	static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
15275614e71bSYork Sun 
15285614e71bSYork Sun 	if (popts->rtt_override)
15295614e71bSYork Sun 		rtt = popts->rtt_override_value;
15305614e71bSYork Sun 	else
15315614e71bSYork Sun 		rtt = popts->cs_local_opts[0].odt_rtt_norm;
15325614e71bSYork Sun 
15335614e71bSYork Sun 	if (additive_latency == (cas_latency - 1))
15345614e71bSYork Sun 		al = 1;
15355614e71bSYork Sun 	if (additive_latency == (cas_latency - 2))
15365614e71bSYork Sun 		al = 2;
15375614e71bSYork Sun 
15385614e71bSYork Sun 	if (popts->quad_rank_present)
15395614e71bSYork Sun 		dic = 1;	/* output driver impedance 240/7 ohm */
15405614e71bSYork Sun 
15415614e71bSYork Sun 	/*
15425614e71bSYork Sun 	 * The esdmode value will also be used for writing
15435614e71bSYork Sun 	 * MR1 during write leveling for DDR3, although the
15445614e71bSYork Sun 	 * bits specifically related to the write leveling
15455614e71bSYork Sun 	 * scheme will be handled automatically by the DDR
15465614e71bSYork Sun 	 * controller. so we set the wrlvl_en = 0 here.
15475614e71bSYork Sun 	 */
15485614e71bSYork Sun 	esdmode = (0
15495614e71bSYork Sun 		| ((qoff & 0x1) << 12)
15505614e71bSYork Sun 		| ((tdqs_en & 0x1) << 11)
15515614e71bSYork Sun 		| ((rtt & 0x4) << 7)   /* rtt field is split */
15525614e71bSYork Sun 		| ((wrlvl_en & 0x1) << 7)
15535614e71bSYork Sun 		| ((rtt & 0x2) << 5)   /* rtt field is split */
15545614e71bSYork Sun 		| ((dic & 0x2) << 4)   /* DIC field is split */
15555614e71bSYork Sun 		| ((al & 0x3) << 3)
15565614e71bSYork Sun 		| ((rtt & 0x1) << 2)  /* rtt field is split */
15575614e71bSYork Sun 		| ((dic & 0x1) << 1)   /* DIC field is split */
15585614e71bSYork Sun 		| ((dll_en & 0x1) << 0)
15595614e71bSYork Sun 		);
15605614e71bSYork Sun 
15615614e71bSYork Sun 	/*
15625614e71bSYork Sun 	 * DLL control for precharge PD
15635614e71bSYork Sun 	 * 0=slow exit DLL off (tXPDLL)
15645614e71bSYork Sun 	 * 1=fast exit DLL on (tXP)
15655614e71bSYork Sun 	 */
15665614e71bSYork Sun 	dll_on = 1;
15675614e71bSYork Sun 
156803e664d8SYork Sun 	wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
15695614e71bSYork Sun 	if (wr_mclk <= 16) {
15705614e71bSYork Sun 		wr = wr_table[wr_mclk - 5];
15715614e71bSYork Sun 	} else {
15725614e71bSYork Sun 		printf("Error: unsupported write recovery for mode register "
15735614e71bSYork Sun 		       "wr_mclk = %d\n", wr_mclk);
15745614e71bSYork Sun 	}
15755614e71bSYork Sun 
15765614e71bSYork Sun 	dll_rst = 0;	/* dll no reset */
15775614e71bSYork Sun 	mode = 0;	/* normal mode */
15785614e71bSYork Sun 
15795614e71bSYork Sun 	/* look up table to get the cas latency bits */
15805614e71bSYork Sun 	if (cas_latency >= 5 && cas_latency <= 16) {
15815614e71bSYork Sun 		unsigned char cas_latency_table[] = {
15825614e71bSYork Sun 			0x2,	/* 5 clocks */
15835614e71bSYork Sun 			0x4,	/* 6 clocks */
15845614e71bSYork Sun 			0x6,	/* 7 clocks */
15855614e71bSYork Sun 			0x8,	/* 8 clocks */
15865614e71bSYork Sun 			0xa,	/* 9 clocks */
15875614e71bSYork Sun 			0xc,	/* 10 clocks */
15885614e71bSYork Sun 			0xe,	/* 11 clocks */
15895614e71bSYork Sun 			0x1,	/* 12 clocks */
15905614e71bSYork Sun 			0x3,	/* 13 clocks */
15915614e71bSYork Sun 			0x5,	/* 14 clocks */
15925614e71bSYork Sun 			0x7,	/* 15 clocks */
15935614e71bSYork Sun 			0x9,	/* 16 clocks */
15945614e71bSYork Sun 		};
15955614e71bSYork Sun 		caslat = cas_latency_table[cas_latency - 5];
15965614e71bSYork Sun 	} else {
15975614e71bSYork Sun 		printf("Error: unsupported cas latency for mode register\n");
15985614e71bSYork Sun 	}
15995614e71bSYork Sun 
16005614e71bSYork Sun 	bt = 0;	/* Nibble sequential */
16015614e71bSYork Sun 
16025614e71bSYork Sun 	switch (popts->burst_length) {
16035614e71bSYork Sun 	case DDR_BL8:
16045614e71bSYork Sun 		bl = 0;
16055614e71bSYork Sun 		break;
16065614e71bSYork Sun 	case DDR_OTF:
16075614e71bSYork Sun 		bl = 1;
16085614e71bSYork Sun 		break;
16095614e71bSYork Sun 	case DDR_BC4:
16105614e71bSYork Sun 		bl = 2;
16115614e71bSYork Sun 		break;
16125614e71bSYork Sun 	default:
16135614e71bSYork Sun 		printf("Error: invalid burst length of %u specified. "
16145614e71bSYork Sun 			" Defaulting to on-the-fly BC4 or BL8 beats.\n",
16155614e71bSYork Sun 			popts->burst_length);
16165614e71bSYork Sun 		bl = 1;
16175614e71bSYork Sun 		break;
16185614e71bSYork Sun 	}
16195614e71bSYork Sun 
16205614e71bSYork Sun 	sdmode = (0
16215614e71bSYork Sun 		  | ((dll_on & 0x1) << 12)
16225614e71bSYork Sun 		  | ((wr & 0x7) << 9)
16235614e71bSYork Sun 		  | ((dll_rst & 0x1) << 8)
16245614e71bSYork Sun 		  | ((mode & 0x1) << 7)
16255614e71bSYork Sun 		  | (((caslat >> 1) & 0x7) << 4)
16265614e71bSYork Sun 		  | ((bt & 0x1) << 3)
16275614e71bSYork Sun 		  | ((caslat & 1) << 2)
16285614e71bSYork Sun 		  | ((bl & 0x3) << 0)
16295614e71bSYork Sun 		  );
16305614e71bSYork Sun 
16315614e71bSYork Sun 	ddr->ddr_sdram_mode = (0
16325614e71bSYork Sun 			       | ((esdmode & 0xFFFF) << 16)
16335614e71bSYork Sun 			       | ((sdmode & 0xFFFF) << 0)
16345614e71bSYork Sun 			       );
16355614e71bSYork Sun 
16365614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
16375614e71bSYork Sun 
16385614e71bSYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
16395614e71bSYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
16405614e71bSYork Sun 			if (popts->rtt_override)
16415614e71bSYork Sun 				rtt = popts->rtt_override_value;
16425614e71bSYork Sun 			else
16435614e71bSYork Sun 				rtt = popts->cs_local_opts[i].odt_rtt_norm;
16445614e71bSYork Sun 
16455614e71bSYork Sun 			esdmode &= 0xFDBB;	/* clear bit 9,6,2 */
16465614e71bSYork Sun 			esdmode |= (0
16475614e71bSYork Sun 				| ((rtt & 0x4) << 7)   /* rtt field is split */
16485614e71bSYork Sun 				| ((rtt & 0x2) << 5)   /* rtt field is split */
16495614e71bSYork Sun 				| ((rtt & 0x1) << 2)  /* rtt field is split */
16505614e71bSYork Sun 				);
16515614e71bSYork Sun 			switch (i) {
16525614e71bSYork Sun 			case 1:
16535614e71bSYork Sun 				ddr->ddr_sdram_mode_3 = (0
16545614e71bSYork Sun 				       | ((esdmode & 0xFFFF) << 16)
16555614e71bSYork Sun 				       | ((sdmode & 0xFFFF) << 0)
16565614e71bSYork Sun 				       );
16575614e71bSYork Sun 				break;
16585614e71bSYork Sun 			case 2:
16595614e71bSYork Sun 				ddr->ddr_sdram_mode_5 = (0
16605614e71bSYork Sun 				       | ((esdmode & 0xFFFF) << 16)
16615614e71bSYork Sun 				       | ((sdmode & 0xFFFF) << 0)
16625614e71bSYork Sun 				       );
16635614e71bSYork Sun 				break;
16645614e71bSYork Sun 			case 3:
16655614e71bSYork Sun 				ddr->ddr_sdram_mode_7 = (0
16665614e71bSYork Sun 				       | ((esdmode & 0xFFFF) << 16)
16675614e71bSYork Sun 				       | ((sdmode & 0xFFFF) << 0)
16685614e71bSYork Sun 				       );
16695614e71bSYork Sun 				break;
16705614e71bSYork Sun 			}
16715614e71bSYork Sun 		}
16725614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
16735614e71bSYork Sun 			ddr->ddr_sdram_mode_3);
16745614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
16755614e71bSYork Sun 			ddr->ddr_sdram_mode_5);
16765614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
16775614e71bSYork Sun 			ddr->ddr_sdram_mode_5);
16785614e71bSYork Sun 	}
16795614e71bSYork Sun }
16805614e71bSYork Sun 
16815614e71bSYork Sun #else /* !CONFIG_SYS_FSL_DDR3 */
16825614e71bSYork Sun 
16835614e71bSYork Sun /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
168403e664d8SYork Sun static void set_ddr_sdram_mode(const unsigned int ctrl_num,
168503e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
16865614e71bSYork Sun 			       const memctl_options_t *popts,
16875614e71bSYork Sun 			       const common_timing_params_t *common_dimm,
16885614e71bSYork Sun 			       unsigned int cas_latency,
16895614e71bSYork Sun 			       unsigned int additive_latency,
16905614e71bSYork Sun 			       const unsigned int unq_mrs_en)
16915614e71bSYork Sun {
16925614e71bSYork Sun 	unsigned short esdmode;		/* Extended SDRAM mode */
16935614e71bSYork Sun 	unsigned short sdmode;		/* SDRAM mode */
16945614e71bSYork Sun 
16955614e71bSYork Sun 	/*
16965614e71bSYork Sun 	 * FIXME: This ought to be pre-calculated in a
16975614e71bSYork Sun 	 * technology-specific routine,
16985614e71bSYork Sun 	 * e.g. compute_DDR2_mode_register(), and then the
16995614e71bSYork Sun 	 * sdmode and esdmode passed in as part of common_dimm.
17005614e71bSYork Sun 	 */
17015614e71bSYork Sun 
17025614e71bSYork Sun 	/* Extended Mode Register */
17035614e71bSYork Sun 	unsigned int mrs = 0;		/* Mode Register Set */
17045614e71bSYork Sun 	unsigned int outputs = 0;	/* 0=Enabled, 1=Disabled */
17055614e71bSYork Sun 	unsigned int rdqs_en = 0;	/* RDQS Enable: 0=no, 1=yes */
17065614e71bSYork Sun 	unsigned int dqs_en = 0;	/* DQS# Enable: 0=enable, 1=disable */
17075614e71bSYork Sun 	unsigned int ocd = 0;		/* 0x0=OCD not supported,
17085614e71bSYork Sun 					   0x7=OCD default state */
17095614e71bSYork Sun 	unsigned int rtt;
17105614e71bSYork Sun 	unsigned int al;		/* Posted CAS# additive latency (AL) */
17115614e71bSYork Sun 	unsigned int ods = 0;		/* Output Drive Strength:
17125614e71bSYork Sun 						0 = Full strength (18ohm)
17135614e71bSYork Sun 						1 = Reduced strength (4ohm) */
17145614e71bSYork Sun 	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
17155614e71bSYork Sun 						       1=Disable (Test/Debug) */
17165614e71bSYork Sun 
17175614e71bSYork Sun 	/* Mode Register (MR) */
17185614e71bSYork Sun 	unsigned int mr;	/* Mode Register Definition */
17195614e71bSYork Sun 	unsigned int pd;	/* Power-Down Mode */
17205614e71bSYork Sun 	unsigned int wr;	/* Write Recovery */
17215614e71bSYork Sun 	unsigned int dll_res;	/* DLL Reset */
17225614e71bSYork Sun 	unsigned int mode;	/* Normal=0 or Test=1 */
17235614e71bSYork Sun 	unsigned int caslat = 0;/* CAS# latency */
17245614e71bSYork Sun 	/* BT: Burst Type (0=Sequential, 1=Interleaved) */
17255614e71bSYork Sun 	unsigned int bt;
17265614e71bSYork Sun 	unsigned int bl;	/* BL: Burst Length */
17275614e71bSYork Sun 
17285614e71bSYork Sun 	dqs_en = !popts->dqs_config;
17295614e71bSYork Sun 	rtt = fsl_ddr_get_rtt();
17305614e71bSYork Sun 
17315614e71bSYork Sun 	al = additive_latency;
17325614e71bSYork Sun 
17335614e71bSYork Sun 	esdmode = (0
17345614e71bSYork Sun 		| ((mrs & 0x3) << 14)
17355614e71bSYork Sun 		| ((outputs & 0x1) << 12)
17365614e71bSYork Sun 		| ((rdqs_en & 0x1) << 11)
17375614e71bSYork Sun 		| ((dqs_en & 0x1) << 10)
17385614e71bSYork Sun 		| ((ocd & 0x7) << 7)
17395614e71bSYork Sun 		| ((rtt & 0x2) << 5)   /* rtt field is split */
17405614e71bSYork Sun 		| ((al & 0x7) << 3)
17415614e71bSYork Sun 		| ((rtt & 0x1) << 2)   /* rtt field is split */
17425614e71bSYork Sun 		| ((ods & 0x1) << 1)
17435614e71bSYork Sun 		| ((dll_en & 0x1) << 0)
17445614e71bSYork Sun 		);
17455614e71bSYork Sun 
17465614e71bSYork Sun 	mr = 0;		 /* FIXME: CHECKME */
17475614e71bSYork Sun 
17485614e71bSYork Sun 	/*
17495614e71bSYork Sun 	 * 0 = Fast Exit (Normal)
17505614e71bSYork Sun 	 * 1 = Slow Exit (Low Power)
17515614e71bSYork Sun 	 */
17525614e71bSYork Sun 	pd = 0;
17535614e71bSYork Sun 
17545614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
17555614e71bSYork Sun 	wr = 0;       /* Historical */
17565614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
175703e664d8SYork Sun 	wr = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
17585614e71bSYork Sun #endif
17595614e71bSYork Sun 	dll_res = 0;
17605614e71bSYork Sun 	mode = 0;
17615614e71bSYork Sun 
17625614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
17635614e71bSYork Sun 	if (1 <= cas_latency && cas_latency <= 4) {
17645614e71bSYork Sun 		unsigned char mode_caslat_table[4] = {
17655614e71bSYork Sun 			0x5,	/* 1.5 clocks */
17665614e71bSYork Sun 			0x2,	/* 2.0 clocks */
17675614e71bSYork Sun 			0x6,	/* 2.5 clocks */
17685614e71bSYork Sun 			0x3	/* 3.0 clocks */
17695614e71bSYork Sun 		};
17705614e71bSYork Sun 		caslat = mode_caslat_table[cas_latency - 1];
17715614e71bSYork Sun 	} else {
17725614e71bSYork Sun 		printf("Warning: unknown cas_latency %d\n", cas_latency);
17735614e71bSYork Sun 	}
17745614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
17755614e71bSYork Sun 	caslat = cas_latency;
17765614e71bSYork Sun #endif
17775614e71bSYork Sun 	bt = 0;
17785614e71bSYork Sun 
17795614e71bSYork Sun 	switch (popts->burst_length) {
17805614e71bSYork Sun 	case DDR_BL4:
17815614e71bSYork Sun 		bl = 2;
17825614e71bSYork Sun 		break;
17835614e71bSYork Sun 	case DDR_BL8:
17845614e71bSYork Sun 		bl = 3;
17855614e71bSYork Sun 		break;
17865614e71bSYork Sun 	default:
17875614e71bSYork Sun 		printf("Error: invalid burst length of %u specified. "
17885614e71bSYork Sun 			" Defaulting to 4 beats.\n",
17895614e71bSYork Sun 			popts->burst_length);
17905614e71bSYork Sun 		bl = 2;
17915614e71bSYork Sun 		break;
17925614e71bSYork Sun 	}
17935614e71bSYork Sun 
17945614e71bSYork Sun 	sdmode = (0
17955614e71bSYork Sun 		  | ((mr & 0x3) << 14)
17965614e71bSYork Sun 		  | ((pd & 0x1) << 12)
17975614e71bSYork Sun 		  | ((wr & 0x7) << 9)
17985614e71bSYork Sun 		  | ((dll_res & 0x1) << 8)
17995614e71bSYork Sun 		  | ((mode & 0x1) << 7)
18005614e71bSYork Sun 		  | ((caslat & 0x7) << 4)
18015614e71bSYork Sun 		  | ((bt & 0x1) << 3)
18025614e71bSYork Sun 		  | ((bl & 0x7) << 0)
18035614e71bSYork Sun 		  );
18045614e71bSYork Sun 
18055614e71bSYork Sun 	ddr->ddr_sdram_mode = (0
18065614e71bSYork Sun 			       | ((esdmode & 0xFFFF) << 16)
18075614e71bSYork Sun 			       | ((sdmode & 0xFFFF) << 0)
18085614e71bSYork Sun 			       );
18095614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
18105614e71bSYork Sun }
18115614e71bSYork Sun #endif
18125614e71bSYork Sun 
18135614e71bSYork Sun /* DDR SDRAM Data Initialization (DDR_DATA_INIT) */
18145614e71bSYork Sun static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr)
18155614e71bSYork Sun {
18165614e71bSYork Sun 	unsigned int init_value;	/* Initialization value */
18175614e71bSYork Sun 
18185614e71bSYork Sun #ifdef CONFIG_MEM_INIT_VALUE
18195614e71bSYork Sun 	init_value = CONFIG_MEM_INIT_VALUE;
18205614e71bSYork Sun #else
18215614e71bSYork Sun 	init_value = 0xDEADBEEF;
18225614e71bSYork Sun #endif
18235614e71bSYork Sun 	ddr->ddr_data_init = init_value;
18245614e71bSYork Sun }
18255614e71bSYork Sun 
18265614e71bSYork Sun /*
18275614e71bSYork Sun  * DDR SDRAM Clock Control (DDR_SDRAM_CLK_CNTL)
18285614e71bSYork Sun  * The old controller on the 8540/60 doesn't have this register.
18295614e71bSYork Sun  * Hope it's OK to set it (to 0) anyway.
18305614e71bSYork Sun  */
18315614e71bSYork Sun static void set_ddr_sdram_clk_cntl(fsl_ddr_cfg_regs_t *ddr,
18325614e71bSYork Sun 					 const memctl_options_t *popts)
18335614e71bSYork Sun {
18345614e71bSYork Sun 	unsigned int clk_adjust;	/* Clock adjust */
1835d7c865bdSCurt Brune 	unsigned int ss_en = 0;		/* Source synchronous enable */
18365614e71bSYork Sun 
18373c3d8ab5SYork Sun #if defined(CONFIG_ARCH_MPC8541) || defined(CONFIG_ARCH_MPC8555)
1838d7c865bdSCurt Brune 	/* Per FSL Application Note: AN2805 */
1839d7c865bdSCurt Brune 	ss_en = 1;
1840d7c865bdSCurt Brune #endif
1841d8e5163aSShengzhou Liu 	if (fsl_ddr_get_version(0) >= 0x40701) {
1842d8e5163aSShengzhou Liu 		/* clk_adjust in 5-bits on T-series and LS-series */
1843d8e5163aSShengzhou Liu 		clk_adjust = (popts->clk_adjust & 0x1F) << 22;
1844d8e5163aSShengzhou Liu 	} else {
1845d8e5163aSShengzhou Liu 		/* clk_adjust in 4-bits on earlier MPC85xx and P-series */
1846d8e5163aSShengzhou Liu 		clk_adjust = (popts->clk_adjust & 0xF) << 23;
1847d8e5163aSShengzhou Liu 	}
1848d8e5163aSShengzhou Liu 
1849d7c865bdSCurt Brune 	ddr->ddr_sdram_clk_cntl = (0
1850d7c865bdSCurt Brune 				   | ((ss_en & 0x1) << 31)
1851d8e5163aSShengzhou Liu 				   | clk_adjust
1852d7c865bdSCurt Brune 				   );
18535614e71bSYork Sun 	debug("FSLDDR: clk_cntl = 0x%08x\n", ddr->ddr_sdram_clk_cntl);
18545614e71bSYork Sun }
18555614e71bSYork Sun 
18565614e71bSYork Sun /* DDR Initialization Address (DDR_INIT_ADDR) */
18575614e71bSYork Sun static void set_ddr_init_addr(fsl_ddr_cfg_regs_t *ddr)
18585614e71bSYork Sun {
18595614e71bSYork Sun 	unsigned int init_addr = 0;	/* Initialization address */
18605614e71bSYork Sun 
18615614e71bSYork Sun 	ddr->ddr_init_addr = init_addr;
18625614e71bSYork Sun }
18635614e71bSYork Sun 
18645614e71bSYork Sun /* DDR Initialization Address (DDR_INIT_EXT_ADDR) */
18655614e71bSYork Sun static void set_ddr_init_ext_addr(fsl_ddr_cfg_regs_t *ddr)
18665614e71bSYork Sun {
18675614e71bSYork Sun 	unsigned int uia = 0;	/* Use initialization address */
18685614e71bSYork Sun 	unsigned int init_ext_addr = 0;	/* Initialization address */
18695614e71bSYork Sun 
18705614e71bSYork Sun 	ddr->ddr_init_ext_addr = (0
18715614e71bSYork Sun 				  | ((uia & 0x1) << 31)
18725614e71bSYork Sun 				  | (init_ext_addr & 0xF)
18735614e71bSYork Sun 				  );
18745614e71bSYork Sun }
18755614e71bSYork Sun 
18765614e71bSYork Sun /* DDR SDRAM Timing Configuration 4 (TIMING_CFG_4) */
18775614e71bSYork Sun static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr,
18785614e71bSYork Sun 				const memctl_options_t *popts)
18795614e71bSYork Sun {
18805614e71bSYork Sun 	unsigned int rwt = 0; /* Read-to-write turnaround for same CS */
18815614e71bSYork Sun 	unsigned int wrt = 0; /* Write-to-read turnaround for same CS */
18825614e71bSYork Sun 	unsigned int rrt = 0; /* Read-to-read turnaround for same CS */
18835614e71bSYork Sun 	unsigned int wwt = 0; /* Write-to-write turnaround for same CS */
18846c6e006aSYork Sun 	unsigned int trwt_mclk = 0;	/* ext_rwt */
18855614e71bSYork Sun 	unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */
18865614e71bSYork Sun 
188734e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
18885614e71bSYork Sun 	if (popts->burst_length == DDR_BL8) {
18895614e71bSYork Sun 		/* We set BL/2 for fixed BL8 */
18905614e71bSYork Sun 		rrt = 0;	/* BL/2 clocks */
18915614e71bSYork Sun 		wwt = 0;	/* BL/2 clocks */
18925614e71bSYork Sun 	} else {
18935614e71bSYork Sun 		/* We need to set BL/2 + 2 to BC4 and OTF */
18945614e71bSYork Sun 		rrt = 2;	/* BL/2 + 2 clocks */
18955614e71bSYork Sun 		wwt = 2;	/* BL/2 + 2 clocks */
18965614e71bSYork Sun 	}
189734e026f9SYork Sun #endif
189834e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
189934e026f9SYork Sun 	dll_lock = 2;	/* tDLLK = 1024 clocks */
190034e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
19015614e71bSYork Sun 	dll_lock = 1;	/* tDLLK = 512 clocks from spec */
19025614e71bSYork Sun #endif
19036c6e006aSYork Sun 
19046c6e006aSYork Sun 	if (popts->trwt_override)
19056c6e006aSYork Sun 		trwt_mclk = popts->trwt;
19066c6e006aSYork Sun 
19075614e71bSYork Sun 	ddr->timing_cfg_4 = (0
19085614e71bSYork Sun 			     | ((rwt & 0xf) << 28)
19095614e71bSYork Sun 			     | ((wrt & 0xf) << 24)
19105614e71bSYork Sun 			     | ((rrt & 0xf) << 20)
19115614e71bSYork Sun 			     | ((wwt & 0xf) << 16)
19126c6e006aSYork Sun 			     | ((trwt_mclk & 0xc) << 12)
19135614e71bSYork Sun 			     | (dll_lock & 0x3)
19145614e71bSYork Sun 			     );
19155614e71bSYork Sun 	debug("FSLDDR: timing_cfg_4 = 0x%08x\n", ddr->timing_cfg_4);
19165614e71bSYork Sun }
19175614e71bSYork Sun 
19185614e71bSYork Sun /* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */
19195614e71bSYork Sun static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency)
19205614e71bSYork Sun {
19215614e71bSYork Sun 	unsigned int rodt_on = 0;	/* Read to ODT on */
19225614e71bSYork Sun 	unsigned int rodt_off = 0;	/* Read to ODT off */
19235614e71bSYork Sun 	unsigned int wodt_on = 0;	/* Write to ODT on */
19245614e71bSYork Sun 	unsigned int wodt_off = 0;	/* Write to ODT off */
19255614e71bSYork Sun 
192634e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
192734e026f9SYork Sun 	unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
192834e026f9SYork Sun 			      ((ddr->timing_cfg_2 & 0x00040000) >> 14);
19295614e71bSYork Sun 	/* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
193034e026f9SYork Sun 	if (cas_latency >= wr_lat)
193134e026f9SYork Sun 		rodt_on = cas_latency - wr_lat + 1;
19325614e71bSYork Sun 	rodt_off = 4;	/*  4 clocks */
19335614e71bSYork Sun 	wodt_on = 1;	/*  1 clocks */
19345614e71bSYork Sun 	wodt_off = 4;	/*  4 clocks */
19355614e71bSYork Sun #endif
19365614e71bSYork Sun 
19375614e71bSYork Sun 	ddr->timing_cfg_5 = (0
19385614e71bSYork Sun 			     | ((rodt_on & 0x1f) << 24)
19395614e71bSYork Sun 			     | ((rodt_off & 0x7) << 20)
19405614e71bSYork Sun 			     | ((wodt_on & 0x1f) << 12)
19415614e71bSYork Sun 			     | ((wodt_off & 0x7) << 8)
19425614e71bSYork Sun 			     );
19435614e71bSYork Sun 	debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5);
19445614e71bSYork Sun }
19455614e71bSYork Sun 
194634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
194734e026f9SYork Sun static void set_timing_cfg_6(fsl_ddr_cfg_regs_t *ddr)
194834e026f9SYork Sun {
194934e026f9SYork Sun 	unsigned int hs_caslat = 0;
195034e026f9SYork Sun 	unsigned int hs_wrlat = 0;
195134e026f9SYork Sun 	unsigned int hs_wrrec = 0;
195234e026f9SYork Sun 	unsigned int hs_clkadj = 0;
195334e026f9SYork Sun 	unsigned int hs_wrlvl_start = 0;
195434e026f9SYork Sun 
195534e026f9SYork Sun 	ddr->timing_cfg_6 = (0
195634e026f9SYork Sun 			     | ((hs_caslat & 0x1f) << 24)
195734e026f9SYork Sun 			     | ((hs_wrlat & 0x1f) << 19)
195834e026f9SYork Sun 			     | ((hs_wrrec & 0x1f) << 12)
195934e026f9SYork Sun 			     | ((hs_clkadj & 0x1f) << 6)
196034e026f9SYork Sun 			     | ((hs_wrlvl_start & 0x1f) << 0)
196134e026f9SYork Sun 			    );
196234e026f9SYork Sun 	debug("FSLDDR: timing_cfg_6 = 0x%08x\n", ddr->timing_cfg_6);
196334e026f9SYork Sun }
196434e026f9SYork Sun 
196503e664d8SYork Sun static void set_timing_cfg_7(const unsigned int ctrl_num,
196603e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
196734e026f9SYork Sun 			     const common_timing_params_t *common_dimm)
196834e026f9SYork Sun {
196934e026f9SYork Sun 	unsigned int txpr, tcksre, tcksrx;
1970eb118807SShengzhou Liu 	unsigned int cke_rst, cksre, cksrx, par_lat = 0, cs_to_cmd;
1971eb118807SShengzhou Liu 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
197234e026f9SYork Sun 
197303e664d8SYork Sun 	txpr = max(5U, picos_to_mclk(ctrl_num, common_dimm->trfc1_ps + 10000));
197403e664d8SYork Sun 	tcksre = max(5U, picos_to_mclk(ctrl_num, 10000));
197503e664d8SYork Sun 	tcksrx = max(5U, picos_to_mclk(ctrl_num, 10000));
1976eb118807SShengzhou Liu 
1977eb118807SShengzhou Liu 	if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) {
1978eb118807SShengzhou Liu 		if (mclk_ps >= 935) {
1979eb118807SShengzhou Liu 			/* parity latency 4 clocks in case of 1600/1866/2133 */
1980eb118807SShengzhou Liu 			par_lat = 4;
1981eb118807SShengzhou Liu 		} else if (mclk_ps >= 833) {
1982eb118807SShengzhou Liu 			/* parity latency 5 clocks for DDR4-2400 */
1983eb118807SShengzhou Liu 			par_lat = 5;
1984eb118807SShengzhou Liu 		} else {
1985eb118807SShengzhou Liu 			printf("parity: mclk_ps = %d not supported\n", mclk_ps);
1986eb118807SShengzhou Liu 		}
1987eb118807SShengzhou Liu 	}
1988eb118807SShengzhou Liu 
198934e026f9SYork Sun 	cs_to_cmd = 0;
199034e026f9SYork Sun 
199134e026f9SYork Sun 	if (txpr <= 200)
199234e026f9SYork Sun 		cke_rst = 0;
199334e026f9SYork Sun 	else if (txpr <= 256)
199434e026f9SYork Sun 		cke_rst = 1;
199534e026f9SYork Sun 	else if (txpr <= 512)
199634e026f9SYork Sun 		cke_rst = 2;
199734e026f9SYork Sun 	else
199834e026f9SYork Sun 		cke_rst = 3;
199934e026f9SYork Sun 
200034e026f9SYork Sun 	if (tcksre <= 19)
200134e026f9SYork Sun 		cksre = tcksre - 5;
200234e026f9SYork Sun 	else
200334e026f9SYork Sun 		cksre = 15;
200434e026f9SYork Sun 
200534e026f9SYork Sun 	if (tcksrx <= 19)
200634e026f9SYork Sun 		cksrx = tcksrx - 5;
200734e026f9SYork Sun 	else
200834e026f9SYork Sun 		cksrx = 15;
200934e026f9SYork Sun 
201034e026f9SYork Sun 	ddr->timing_cfg_7 = (0
201134e026f9SYork Sun 			     | ((cke_rst & 0x3) << 28)
201234e026f9SYork Sun 			     | ((cksre & 0xf) << 24)
201334e026f9SYork Sun 			     | ((cksrx & 0xf) << 20)
201434e026f9SYork Sun 			     | ((par_lat & 0xf) << 16)
201534e026f9SYork Sun 			     | ((cs_to_cmd & 0xf) << 4)
201634e026f9SYork Sun 			    );
201734e026f9SYork Sun 	debug("FSLDDR: timing_cfg_7 = 0x%08x\n", ddr->timing_cfg_7);
201834e026f9SYork Sun }
201934e026f9SYork Sun 
202003e664d8SYork Sun static void set_timing_cfg_8(const unsigned int ctrl_num,
202103e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
202234e026f9SYork Sun 			     const memctl_options_t *popts,
202334e026f9SYork Sun 			     const common_timing_params_t *common_dimm,
202434e026f9SYork Sun 			     unsigned int cas_latency)
202534e026f9SYork Sun {
202634e026f9SYork Sun 	unsigned int rwt_bg, wrt_bg, rrt_bg, wwt_bg;
202734e026f9SYork Sun 	unsigned int acttoact_bg, wrtord_bg, pre_all_rec;
202803e664d8SYork Sun 	unsigned int tccdl = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps);
202934e026f9SYork Sun 	unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
203034e026f9SYork Sun 			      ((ddr->timing_cfg_2 & 0x00040000) >> 14);
203134e026f9SYork Sun 
203234e026f9SYork Sun 	rwt_bg = cas_latency + 2 + 4 - wr_lat;
203334e026f9SYork Sun 	if (rwt_bg < tccdl)
203434e026f9SYork Sun 		rwt_bg = tccdl - rwt_bg;
203534e026f9SYork Sun 	else
203634e026f9SYork Sun 		rwt_bg = 0;
203734e026f9SYork Sun 
203834e026f9SYork Sun 	wrt_bg = wr_lat + 4 + 1 - cas_latency;
203934e026f9SYork Sun 	if (wrt_bg < tccdl)
204034e026f9SYork Sun 		wrt_bg = tccdl - wrt_bg;
204134e026f9SYork Sun 	else
204234e026f9SYork Sun 		wrt_bg = 0;
204334e026f9SYork Sun 
204434e026f9SYork Sun 	if (popts->burst_length == DDR_BL8) {
204534e026f9SYork Sun 		rrt_bg = tccdl - 4;
204634e026f9SYork Sun 		wwt_bg = tccdl - 4;
204734e026f9SYork Sun 	} else {
204834e026f9SYork Sun 		rrt_bg = tccdl - 2;
2049dc1437afSYork Sun 		wwt_bg = tccdl - 2;
205034e026f9SYork Sun 	}
205134e026f9SYork Sun 
205203e664d8SYork Sun 	acttoact_bg = picos_to_mclk(ctrl_num, common_dimm->trrdl_ps);
205303e664d8SYork Sun 	wrtord_bg = max(4U, picos_to_mclk(ctrl_num, 7500));
20543d75ec95SYork Sun 	if (popts->otf_burst_chop_en)
20553d75ec95SYork Sun 		wrtord_bg += 2;
20563d75ec95SYork Sun 
205734e026f9SYork Sun 	pre_all_rec = 0;
205834e026f9SYork Sun 
205934e026f9SYork Sun 	ddr->timing_cfg_8 = (0
206034e026f9SYork Sun 			     | ((rwt_bg & 0xf) << 28)
206134e026f9SYork Sun 			     | ((wrt_bg & 0xf) << 24)
206234e026f9SYork Sun 			     | ((rrt_bg & 0xf) << 20)
206334e026f9SYork Sun 			     | ((wwt_bg & 0xf) << 16)
206434e026f9SYork Sun 			     | ((acttoact_bg & 0xf) << 12)
206534e026f9SYork Sun 			     | ((wrtord_bg & 0xf) << 8)
206634e026f9SYork Sun 			     | ((pre_all_rec & 0x1f) << 0)
206734e026f9SYork Sun 			    );
206834e026f9SYork Sun 
206934e026f9SYork Sun 	debug("FSLDDR: timing_cfg_8 = 0x%08x\n", ddr->timing_cfg_8);
207034e026f9SYork Sun }
207134e026f9SYork Sun 
207234e026f9SYork Sun static void set_timing_cfg_9(fsl_ddr_cfg_regs_t *ddr)
207334e026f9SYork Sun {
207434e026f9SYork Sun 	ddr->timing_cfg_9 = 0;
207534e026f9SYork Sun 	debug("FSLDDR: timing_cfg_9 = 0x%08x\n", ddr->timing_cfg_9);
207634e026f9SYork Sun }
207734e026f9SYork Sun 
2078f80d6472SYork Sun /* This function needs to be called after set_ddr_sdram_cfg() is called */
207934e026f9SYork Sun static void set_ddr_dq_mapping(fsl_ddr_cfg_regs_t *ddr,
208034e026f9SYork Sun 			       const dimm_params_t *dimm_params)
208134e026f9SYork Sun {
2082f80d6472SYork Sun 	unsigned int acc_ecc_en = (ddr->ddr_sdram_cfg >> 2) & 0x1;
20836b95be22SYork Sun 	int i;
2084f80d6472SYork Sun 
20856b95be22SYork Sun 	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
20866b95be22SYork Sun 		if (dimm_params[i].n_ranks)
20876b95be22SYork Sun 			break;
20886b95be22SYork Sun 	}
20896b95be22SYork Sun 	if (i >= CONFIG_DIMM_SLOTS_PER_CTLR) {
20906b95be22SYork Sun 		puts("DDR error: no DIMM found!\n");
20916b95be22SYork Sun 		return;
20926b95be22SYork Sun 	}
209334e026f9SYork Sun 
20946b95be22SYork Sun 	ddr->dq_map_0 = ((dimm_params[i].dq_mapping[0] & 0x3F) << 26) |
20956b95be22SYork Sun 			((dimm_params[i].dq_mapping[1] & 0x3F) << 20) |
20966b95be22SYork Sun 			((dimm_params[i].dq_mapping[2] & 0x3F) << 14) |
20976b95be22SYork Sun 			((dimm_params[i].dq_mapping[3] & 0x3F) << 8) |
20986b95be22SYork Sun 			((dimm_params[i].dq_mapping[4] & 0x3F) << 2);
209934e026f9SYork Sun 
21006b95be22SYork Sun 	ddr->dq_map_1 = ((dimm_params[i].dq_mapping[5] & 0x3F) << 26) |
21016b95be22SYork Sun 			((dimm_params[i].dq_mapping[6] & 0x3F) << 20) |
21026b95be22SYork Sun 			((dimm_params[i].dq_mapping[7] & 0x3F) << 14) |
21036b95be22SYork Sun 			((dimm_params[i].dq_mapping[10] & 0x3F) << 8) |
21046b95be22SYork Sun 			((dimm_params[i].dq_mapping[11] & 0x3F) << 2);
21056b95be22SYork Sun 
21066b95be22SYork Sun 	ddr->dq_map_2 = ((dimm_params[i].dq_mapping[12] & 0x3F) << 26) |
21076b95be22SYork Sun 			((dimm_params[i].dq_mapping[13] & 0x3F) << 20) |
21086b95be22SYork Sun 			((dimm_params[i].dq_mapping[14] & 0x3F) << 14) |
21096b95be22SYork Sun 			((dimm_params[i].dq_mapping[15] & 0x3F) << 8) |
21106b95be22SYork Sun 			((dimm_params[i].dq_mapping[16] & 0x3F) << 2);
211134e026f9SYork Sun 
2112f80d6472SYork Sun 	/* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */
21136b95be22SYork Sun 	ddr->dq_map_3 = ((dimm_params[i].dq_mapping[17] & 0x3F) << 26) |
21146b95be22SYork Sun 			((dimm_params[i].dq_mapping[8] & 0x3F) << 20) |
2115f80d6472SYork Sun 			(acc_ecc_en ? 0 :
21166b95be22SYork Sun 			 (dimm_params[i].dq_mapping[9] & 0x3F) << 14) |
21176b95be22SYork Sun 			dimm_params[i].dq_mapping_ors;
211834e026f9SYork Sun 
211934e026f9SYork Sun 	debug("FSLDDR: dq_map_0 = 0x%08x\n", ddr->dq_map_0);
212034e026f9SYork Sun 	debug("FSLDDR: dq_map_1 = 0x%08x\n", ddr->dq_map_1);
212134e026f9SYork Sun 	debug("FSLDDR: dq_map_2 = 0x%08x\n", ddr->dq_map_2);
212234e026f9SYork Sun 	debug("FSLDDR: dq_map_3 = 0x%08x\n", ddr->dq_map_3);
212334e026f9SYork Sun }
212434e026f9SYork Sun static void set_ddr_sdram_cfg_3(fsl_ddr_cfg_regs_t *ddr,
212534e026f9SYork Sun 			       const memctl_options_t *popts)
212634e026f9SYork Sun {
212734e026f9SYork Sun 	int rd_pre;
212834e026f9SYork Sun 
212934e026f9SYork Sun 	rd_pre = popts->quad_rank_present ? 1 : 0;
213034e026f9SYork Sun 
213134e026f9SYork Sun 	ddr->ddr_sdram_cfg_3 = (rd_pre & 0x1) << 16;
213234e026f9SYork Sun 
213334e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_cfg_3 = 0x%08x\n", ddr->ddr_sdram_cfg_3);
213434e026f9SYork Sun }
213534e026f9SYork Sun #endif	/* CONFIG_SYS_FSL_DDR4 */
213634e026f9SYork Sun 
21375614e71bSYork Sun /* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */
21385614e71bSYork Sun static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
21395614e71bSYork Sun {
21405614e71bSYork Sun 	unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */
21415614e71bSYork Sun 	/* Normal Operation Full Calibration Time (tZQoper) */
21425614e71bSYork Sun 	unsigned int zqoper = 0;
21435614e71bSYork Sun 	/* Normal Operation Short Calibration Time (tZQCS) */
21445614e71bSYork Sun 	unsigned int zqcs = 0;
214534e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
214634e026f9SYork Sun 	unsigned int zqcs_init;
214734e026f9SYork Sun #endif
21485614e71bSYork Sun 
21495614e71bSYork Sun 	if (zq_en) {
215034e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
215134e026f9SYork Sun 		zqinit = 10;	/* 1024 clocks */
215234e026f9SYork Sun 		zqoper = 9;	/* 512 clocks */
215334e026f9SYork Sun 		zqcs = 7;	/* 128 clocks */
215434e026f9SYork Sun 		zqcs_init = 5;	/* 1024 refresh sequences */
215534e026f9SYork Sun #else
21565614e71bSYork Sun 		zqinit = 9;	/* 512 clocks */
21575614e71bSYork Sun 		zqoper = 8;	/* 256 clocks */
21585614e71bSYork Sun 		zqcs = 6;	/* 64 clocks */
215934e026f9SYork Sun #endif
21605614e71bSYork Sun 	}
21615614e71bSYork Sun 
21625614e71bSYork Sun 	ddr->ddr_zq_cntl = (0
21635614e71bSYork Sun 			    | ((zq_en & 0x1) << 31)
21645614e71bSYork Sun 			    | ((zqinit & 0xF) << 24)
21655614e71bSYork Sun 			    | ((zqoper & 0xF) << 16)
21665614e71bSYork Sun 			    | ((zqcs & 0xF) << 8)
216734e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
216834e026f9SYork Sun 			    | ((zqcs_init & 0xF) << 0)
216934e026f9SYork Sun #endif
21705614e71bSYork Sun 			    );
21715614e71bSYork Sun 	debug("FSLDDR: zq_cntl = 0x%08x\n", ddr->ddr_zq_cntl);
21725614e71bSYork Sun }
21735614e71bSYork Sun 
21745614e71bSYork Sun /* DDR Write Leveling Control (DDR_WRLVL_CNTL) */
21755614e71bSYork Sun static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en,
21765614e71bSYork Sun 				const memctl_options_t *popts)
21775614e71bSYork Sun {
21785614e71bSYork Sun 	/*
21795614e71bSYork Sun 	 * First DQS pulse rising edge after margining mode
21805614e71bSYork Sun 	 * is programmed (tWL_MRD)
21815614e71bSYork Sun 	 */
21825614e71bSYork Sun 	unsigned int wrlvl_mrd = 0;
21835614e71bSYork Sun 	/* ODT delay after margining mode is programmed (tWL_ODTEN) */
21845614e71bSYork Sun 	unsigned int wrlvl_odten = 0;
21855614e71bSYork Sun 	/* DQS/DQS_ delay after margining mode is programmed (tWL_DQSEN) */
21865614e71bSYork Sun 	unsigned int wrlvl_dqsen = 0;
21875614e71bSYork Sun 	/* WRLVL_SMPL: Write leveling sample time */
21885614e71bSYork Sun 	unsigned int wrlvl_smpl = 0;
21895614e71bSYork Sun 	/* WRLVL_WLR: Write leveling repeition time */
21905614e71bSYork Sun 	unsigned int wrlvl_wlr = 0;
21915614e71bSYork Sun 	/* WRLVL_START: Write leveling start time */
21925614e71bSYork Sun 	unsigned int wrlvl_start = 0;
21935614e71bSYork Sun 
21945614e71bSYork Sun 	/* suggest enable write leveling for DDR3 due to fly-by topology */
21955614e71bSYork Sun 	if (wrlvl_en) {
21965614e71bSYork Sun 		/* tWL_MRD min = 40 nCK, we set it 64 */
21975614e71bSYork Sun 		wrlvl_mrd = 0x6;
21985614e71bSYork Sun 		/* tWL_ODTEN 128 */
21995614e71bSYork Sun 		wrlvl_odten = 0x7;
22005614e71bSYork Sun 		/* tWL_DQSEN min = 25 nCK, we set it 32 */
22015614e71bSYork Sun 		wrlvl_dqsen = 0x5;
22025614e71bSYork Sun 		/*
22035614e71bSYork Sun 		 * Write leveling sample time at least need 6 clocks
22045614e71bSYork Sun 		 * higher than tWLO to allow enough time for progagation
22055614e71bSYork Sun 		 * delay and sampling the prime data bits.
22065614e71bSYork Sun 		 */
22075614e71bSYork Sun 		wrlvl_smpl = 0xf;
22085614e71bSYork Sun 		/*
22095614e71bSYork Sun 		 * Write leveling repetition time
22105614e71bSYork Sun 		 * at least tWLO + 6 clocks clocks
22115614e71bSYork Sun 		 * we set it 64
22125614e71bSYork Sun 		 */
22135614e71bSYork Sun 		wrlvl_wlr = 0x6;
22145614e71bSYork Sun 		/*
22155614e71bSYork Sun 		 * Write leveling start time
22165614e71bSYork Sun 		 * The value use for the DQS_ADJUST for the first sample
22175614e71bSYork Sun 		 * when write leveling is enabled. It probably needs to be
221862a3b7ddSRobert P. J. Day 		 * overridden per platform.
22195614e71bSYork Sun 		 */
22205614e71bSYork Sun 		wrlvl_start = 0x8;
22215614e71bSYork Sun 		/*
22225614e71bSYork Sun 		 * Override the write leveling sample and start time
22235614e71bSYork Sun 		 * according to specific board
22245614e71bSYork Sun 		 */
22255614e71bSYork Sun 		if (popts->wrlvl_override) {
22265614e71bSYork Sun 			wrlvl_smpl = popts->wrlvl_sample;
22275614e71bSYork Sun 			wrlvl_start = popts->wrlvl_start;
22285614e71bSYork Sun 		}
22295614e71bSYork Sun 	}
22305614e71bSYork Sun 
22315614e71bSYork Sun 	ddr->ddr_wrlvl_cntl = (0
22325614e71bSYork Sun 			       | ((wrlvl_en & 0x1) << 31)
22335614e71bSYork Sun 			       | ((wrlvl_mrd & 0x7) << 24)
22345614e71bSYork Sun 			       | ((wrlvl_odten & 0x7) << 20)
22355614e71bSYork Sun 			       | ((wrlvl_dqsen & 0x7) << 16)
22365614e71bSYork Sun 			       | ((wrlvl_smpl & 0xf) << 12)
22375614e71bSYork Sun 			       | ((wrlvl_wlr & 0x7) << 8)
22385614e71bSYork Sun 			       | ((wrlvl_start & 0x1F) << 0)
22395614e71bSYork Sun 			       );
22405614e71bSYork Sun 	debug("FSLDDR: wrlvl_cntl = 0x%08x\n", ddr->ddr_wrlvl_cntl);
22415614e71bSYork Sun 	ddr->ddr_wrlvl_cntl_2 = popts->wrlvl_ctl_2;
22425614e71bSYork Sun 	debug("FSLDDR: wrlvl_cntl_2 = 0x%08x\n", ddr->ddr_wrlvl_cntl_2);
22435614e71bSYork Sun 	ddr->ddr_wrlvl_cntl_3 = popts->wrlvl_ctl_3;
22445614e71bSYork Sun 	debug("FSLDDR: wrlvl_cntl_3 = 0x%08x\n", ddr->ddr_wrlvl_cntl_3);
22455614e71bSYork Sun 
22465614e71bSYork Sun }
22475614e71bSYork Sun 
22485614e71bSYork Sun /* DDR Self Refresh Counter (DDR_SR_CNTR) */
22495614e71bSYork Sun static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr, unsigned int sr_it)
22505614e71bSYork Sun {
22515614e71bSYork Sun 	/* Self Refresh Idle Threshold */
22525614e71bSYork Sun 	ddr->ddr_sr_cntr = (sr_it & 0xF) << 16;
22535614e71bSYork Sun }
22545614e71bSYork Sun 
22555614e71bSYork Sun static void set_ddr_eor(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
22565614e71bSYork Sun {
22575614e71bSYork Sun 	if (popts->addr_hash) {
22585614e71bSYork Sun 		ddr->ddr_eor = 0x40000000;	/* address hash enable */
22595614e71bSYork Sun 		puts("Address hashing enabled.\n");
22605614e71bSYork Sun 	}
22615614e71bSYork Sun }
22625614e71bSYork Sun 
22635614e71bSYork Sun static void set_ddr_cdr1(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
22645614e71bSYork Sun {
22655614e71bSYork Sun 	ddr->ddr_cdr1 = popts->ddr_cdr1;
22665614e71bSYork Sun 	debug("FSLDDR: ddr_cdr1 = 0x%08x\n", ddr->ddr_cdr1);
22675614e71bSYork Sun }
22685614e71bSYork Sun 
22695614e71bSYork Sun static void set_ddr_cdr2(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
22705614e71bSYork Sun {
22715614e71bSYork Sun 	ddr->ddr_cdr2 = popts->ddr_cdr2;
22725614e71bSYork Sun 	debug("FSLDDR: ddr_cdr2 = 0x%08x\n", ddr->ddr_cdr2);
22735614e71bSYork Sun }
22745614e71bSYork Sun 
22755614e71bSYork Sun unsigned int
22765614e71bSYork Sun check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
22775614e71bSYork Sun {
22785614e71bSYork Sun 	unsigned int res = 0;
22795614e71bSYork Sun 
22805614e71bSYork Sun 	/*
22815614e71bSYork Sun 	 * Check that DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] are
22825614e71bSYork Sun 	 * not set at the same time.
22835614e71bSYork Sun 	 */
22845614e71bSYork Sun 	if (ddr->ddr_sdram_cfg & 0x10000000
22855614e71bSYork Sun 	    && ddr->ddr_sdram_cfg & 0x00008000) {
22865614e71bSYork Sun 		printf("Error: DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] "
22875614e71bSYork Sun 				" should not be set at the same time.\n");
22885614e71bSYork Sun 		res++;
22895614e71bSYork Sun 	}
22905614e71bSYork Sun 
22915614e71bSYork Sun 	return res;
22925614e71bSYork Sun }
22935614e71bSYork Sun 
22945614e71bSYork Sun unsigned int
229503e664d8SYork Sun compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
229603e664d8SYork Sun 			       const memctl_options_t *popts,
22975614e71bSYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
22985614e71bSYork Sun 			       const common_timing_params_t *common_dimm,
22995614e71bSYork Sun 			       const dimm_params_t *dimm_params,
23005614e71bSYork Sun 			       unsigned int dbw_cap_adj,
23015614e71bSYork Sun 			       unsigned int size_only)
23025614e71bSYork Sun {
23035614e71bSYork Sun 	unsigned int i;
23045614e71bSYork Sun 	unsigned int cas_latency;
23055614e71bSYork Sun 	unsigned int additive_latency;
23065614e71bSYork Sun 	unsigned int sr_it;
23075614e71bSYork Sun 	unsigned int zq_en;
23085614e71bSYork Sun 	unsigned int wrlvl_en;
23095614e71bSYork Sun 	unsigned int ip_rev = 0;
23105614e71bSYork Sun 	unsigned int unq_mrs_en = 0;
23115614e71bSYork Sun 	int cs_en = 1;
231202fb2761SShengzhou Liu #ifdef CONFIG_SYS_FSL_ERRATUM_A009942
231302fb2761SShengzhou Liu 	unsigned int ddr_freq;
231402fb2761SShengzhou Liu #endif
231502fb2761SShengzhou Liu #if (defined(CONFIG_SYS_FSL_ERRATUM_A008378) && \
231602fb2761SShengzhou Liu 	defined(CONFIG_SYS_FSL_DDRC_GEN4)) || \
231702fb2761SShengzhou Liu 	defined(CONFIG_SYS_FSL_ERRATUM_A009942)
231802fb2761SShengzhou Liu 	struct ccsr_ddr __iomem *ddrc;
231902fb2761SShengzhou Liu 
232002fb2761SShengzhou Liu 	switch (ctrl_num) {
232102fb2761SShengzhou Liu 	case 0:
232202fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR_ADDR;
232302fb2761SShengzhou Liu 		break;
232451370d56SYork Sun #if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 1)
232502fb2761SShengzhou Liu 	case 1:
232602fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR2_ADDR;
232702fb2761SShengzhou Liu 		break;
232802fb2761SShengzhou Liu #endif
232951370d56SYork Sun #if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 2)
233002fb2761SShengzhou Liu 	case 2:
233102fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR3_ADDR;
233202fb2761SShengzhou Liu 		break;
233302fb2761SShengzhou Liu #endif
233451370d56SYork Sun #if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 3)
233502fb2761SShengzhou Liu 	case 3:
233602fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR4_ADDR;
233702fb2761SShengzhou Liu 		break;
233802fb2761SShengzhou Liu #endif
233902fb2761SShengzhou Liu 	default:
234002fb2761SShengzhou Liu 		printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num);
234102fb2761SShengzhou Liu 		return 1;
234202fb2761SShengzhou Liu 	}
234302fb2761SShengzhou Liu #endif
23445614e71bSYork Sun 
23455614e71bSYork Sun 	memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t));
23465614e71bSYork Sun 
23475614e71bSYork Sun 	if (common_dimm == NULL) {
23485614e71bSYork Sun 		printf("Error: subset DIMM params struct null pointer\n");
23495614e71bSYork Sun 		return 1;
23505614e71bSYork Sun 	}
23515614e71bSYork Sun 
23525614e71bSYork Sun 	/*
23535614e71bSYork Sun 	 * Process overrides first.
23545614e71bSYork Sun 	 *
23555614e71bSYork Sun 	 * FIXME: somehow add dereated caslat to this
23565614e71bSYork Sun 	 */
23575614e71bSYork Sun 	cas_latency = (popts->cas_latency_override)
23585614e71bSYork Sun 		? popts->cas_latency_override_value
235934e026f9SYork Sun 		: common_dimm->lowest_common_spd_caslat;
23605614e71bSYork Sun 
23615614e71bSYork Sun 	additive_latency = (popts->additive_latency_override)
23625614e71bSYork Sun 		? popts->additive_latency_override_value
23635614e71bSYork Sun 		: common_dimm->additive_latency;
23645614e71bSYork Sun 
23655614e71bSYork Sun 	sr_it = (popts->auto_self_refresh_en)
23665614e71bSYork Sun 		? popts->sr_it
23675614e71bSYork Sun 		: 0;
23685614e71bSYork Sun 	/* ZQ calibration */
23695614e71bSYork Sun 	zq_en = (popts->zq_en) ? 1 : 0;
23705614e71bSYork Sun 	/* write leveling */
23715614e71bSYork Sun 	wrlvl_en = (popts->wrlvl_en) ? 1 : 0;
23725614e71bSYork Sun 
23735614e71bSYork Sun 	/* Chip Select Memory Bounds (CSn_BNDS) */
23745614e71bSYork Sun 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
23755614e71bSYork Sun 		unsigned long long ea, sa;
23765614e71bSYork Sun 		unsigned int cs_per_dimm
23775614e71bSYork Sun 			= CONFIG_CHIP_SELECTS_PER_CTRL / CONFIG_DIMM_SLOTS_PER_CTLR;
23785614e71bSYork Sun 		unsigned int dimm_number
23795614e71bSYork Sun 			= i / cs_per_dimm;
23805614e71bSYork Sun 		unsigned long long rank_density
23815614e71bSYork Sun 			= dimm_params[dimm_number].rank_density >> dbw_cap_adj;
23825614e71bSYork Sun 
23835614e71bSYork Sun 		if (dimm_params[dimm_number].n_ranks == 0) {
23845614e71bSYork Sun 			debug("Skipping setup of CS%u "
23855614e71bSYork Sun 				"because n_ranks on DIMM %u is 0\n", i, dimm_number);
23865614e71bSYork Sun 			continue;
23875614e71bSYork Sun 		}
23885614e71bSYork Sun 		if (popts->memctl_interleaving) {
23895614e71bSYork Sun 			switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
23905614e71bSYork Sun 			case FSL_DDR_CS0_CS1_CS2_CS3:
23915614e71bSYork Sun 				break;
23925614e71bSYork Sun 			case FSL_DDR_CS0_CS1:
23935614e71bSYork Sun 			case FSL_DDR_CS0_CS1_AND_CS2_CS3:
23945614e71bSYork Sun 				if (i > 1)
23955614e71bSYork Sun 					cs_en = 0;
23965614e71bSYork Sun 				break;
23975614e71bSYork Sun 			case FSL_DDR_CS2_CS3:
23985614e71bSYork Sun 			default:
23995614e71bSYork Sun 				if (i > 0)
24005614e71bSYork Sun 					cs_en = 0;
24015614e71bSYork Sun 				break;
24025614e71bSYork Sun 			}
24035614e71bSYork Sun 			sa = common_dimm->base_address;
24045614e71bSYork Sun 			ea = sa + common_dimm->total_mem - 1;
24055614e71bSYork Sun 		} else if (!popts->memctl_interleaving) {
24065614e71bSYork Sun 			/*
24075614e71bSYork Sun 			 * If memory interleaving between controllers is NOT
24085614e71bSYork Sun 			 * enabled, the starting address for each memory
24095614e71bSYork Sun 			 * controller is distinct.  However, because rank
24105614e71bSYork Sun 			 * interleaving is enabled, the starting and ending
24115614e71bSYork Sun 			 * addresses of the total memory on that memory
24125614e71bSYork Sun 			 * controller needs to be programmed into its
24135614e71bSYork Sun 			 * respective CS0_BNDS.
24145614e71bSYork Sun 			 */
24155614e71bSYork Sun 			switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
24165614e71bSYork Sun 			case FSL_DDR_CS0_CS1_CS2_CS3:
24175614e71bSYork Sun 				sa = common_dimm->base_address;
24185614e71bSYork Sun 				ea = sa + common_dimm->total_mem - 1;
24195614e71bSYork Sun 				break;
24205614e71bSYork Sun 			case FSL_DDR_CS0_CS1_AND_CS2_CS3:
24215614e71bSYork Sun 				if ((i >= 2) && (dimm_number == 0)) {
24225614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address +
24235614e71bSYork Sun 					      2 * rank_density;
24245614e71bSYork Sun 					ea = sa + 2 * rank_density - 1;
24255614e71bSYork Sun 				} else {
24265614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address;
24275614e71bSYork Sun 					ea = sa + 2 * rank_density - 1;
24285614e71bSYork Sun 				}
24295614e71bSYork Sun 				break;
24305614e71bSYork Sun 			case FSL_DDR_CS0_CS1:
24315614e71bSYork Sun 				if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
24325614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address;
24335614e71bSYork Sun 					ea = sa + rank_density - 1;
24345614e71bSYork Sun 					if (i != 1)
24355614e71bSYork Sun 						sa += (i % cs_per_dimm) * rank_density;
24365614e71bSYork Sun 					ea += (i % cs_per_dimm) * rank_density;
24375614e71bSYork Sun 				} else {
24385614e71bSYork Sun 					sa = 0;
24395614e71bSYork Sun 					ea = 0;
24405614e71bSYork Sun 				}
24415614e71bSYork Sun 				if (i == 0)
24425614e71bSYork Sun 					ea += rank_density;
24435614e71bSYork Sun 				break;
24445614e71bSYork Sun 			case FSL_DDR_CS2_CS3:
24455614e71bSYork Sun 				if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
24465614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address;
24475614e71bSYork Sun 					ea = sa + rank_density - 1;
24485614e71bSYork Sun 					if (i != 3)
24495614e71bSYork Sun 						sa += (i % cs_per_dimm) * rank_density;
24505614e71bSYork Sun 					ea += (i % cs_per_dimm) * rank_density;
24515614e71bSYork Sun 				} else {
24525614e71bSYork Sun 					sa = 0;
24535614e71bSYork Sun 					ea = 0;
24545614e71bSYork Sun 				}
24555614e71bSYork Sun 				if (i == 2)
24565614e71bSYork Sun 					ea += (rank_density >> dbw_cap_adj);
24575614e71bSYork Sun 				break;
24585614e71bSYork Sun 			default:  /* No bank(chip-select) interleaving */
24595614e71bSYork Sun 				sa = dimm_params[dimm_number].base_address;
24605614e71bSYork Sun 				ea = sa + rank_density - 1;
24615614e71bSYork Sun 				if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
24625614e71bSYork Sun 					sa += (i % cs_per_dimm) * rank_density;
24635614e71bSYork Sun 					ea += (i % cs_per_dimm) * rank_density;
24645614e71bSYork Sun 				} else {
24655614e71bSYork Sun 					sa = 0;
24665614e71bSYork Sun 					ea = 0;
24675614e71bSYork Sun 				}
24685614e71bSYork Sun 				break;
24695614e71bSYork Sun 			}
24705614e71bSYork Sun 		}
24715614e71bSYork Sun 
24725614e71bSYork Sun 		sa >>= 24;
24735614e71bSYork Sun 		ea >>= 24;
24745614e71bSYork Sun 
24755614e71bSYork Sun 		if (cs_en) {
24765614e71bSYork Sun 			ddr->cs[i].bnds = (0
2477d4263b8aSYork Sun 				| ((sa & 0xffff) << 16) /* starting address */
2478d4263b8aSYork Sun 				| ((ea & 0xffff) << 0)	/* ending address */
24795614e71bSYork Sun 				);
24805614e71bSYork Sun 		} else {
24815614e71bSYork Sun 			/* setting bnds to 0xffffffff for inactive CS */
24825614e71bSYork Sun 			ddr->cs[i].bnds = 0xffffffff;
24835614e71bSYork Sun 		}
24845614e71bSYork Sun 
24855614e71bSYork Sun 		debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds);
24865614e71bSYork Sun 		set_csn_config(dimm_number, i, ddr, popts, dimm_params);
24875614e71bSYork Sun 		set_csn_config_2(i, ddr);
24885614e71bSYork Sun 	}
24895614e71bSYork Sun 
24905614e71bSYork Sun 	/*
24915614e71bSYork Sun 	 * In the case we only need to compute the ddr sdram size, we only need
24925614e71bSYork Sun 	 * to set csn registers, so return from here.
24935614e71bSYork Sun 	 */
24945614e71bSYork Sun 	if (size_only)
24955614e71bSYork Sun 		return 0;
24965614e71bSYork Sun 
24975614e71bSYork Sun 	set_ddr_eor(ddr, popts);
24985614e71bSYork Sun 
24995614e71bSYork Sun #if !defined(CONFIG_SYS_FSL_DDR1)
250003e664d8SYork Sun 	set_timing_cfg_0(ctrl_num, ddr, popts, dimm_params);
25015614e71bSYork Sun #endif
25025614e71bSYork Sun 
250303e664d8SYork Sun 	set_timing_cfg_3(ctrl_num, ddr, popts, common_dimm, cas_latency,
2504d4263b8aSYork Sun 			 additive_latency);
250503e664d8SYork Sun 	set_timing_cfg_1(ctrl_num, ddr, popts, common_dimm, cas_latency);
250603e664d8SYork Sun 	set_timing_cfg_2(ctrl_num, ddr, popts, common_dimm,
25075614e71bSYork Sun 			 cas_latency, additive_latency);
25085614e71bSYork Sun 
25095614e71bSYork Sun 	set_ddr_cdr1(ddr, popts);
25105614e71bSYork Sun 	set_ddr_cdr2(ddr, popts);
25115614e71bSYork Sun 	set_ddr_sdram_cfg(ddr, popts, common_dimm);
251266869f95SYork Sun 	ip_rev = fsl_ddr_get_version(ctrl_num);
25135614e71bSYork Sun 	if (ip_rev > 0x40400)
25145614e71bSYork Sun 		unq_mrs_en = 1;
25155614e71bSYork Sun 
2516f80d6472SYork Sun 	if ((ip_rev > 0x40700) && (popts->cswl_override != 0))
2517ef87cab6SYork Sun 		ddr->debug[18] = popts->cswl_override;
2518ef87cab6SYork Sun 
251903e664d8SYork Sun 	set_ddr_sdram_cfg_2(ctrl_num, ddr, popts, unq_mrs_en);
252003e664d8SYork Sun 	set_ddr_sdram_mode(ctrl_num, ddr, popts, common_dimm,
25215614e71bSYork Sun 			   cas_latency, additive_latency, unq_mrs_en);
252203e664d8SYork Sun 	set_ddr_sdram_mode_2(ctrl_num, ddr, popts, common_dimm, unq_mrs_en);
252334e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
252434e026f9SYork Sun 	set_ddr_sdram_mode_9(ddr, popts, common_dimm, unq_mrs_en);
252503e664d8SYork Sun 	set_ddr_sdram_mode_10(ctrl_num, ddr, popts, common_dimm, unq_mrs_en);
252634e026f9SYork Sun #endif
252703e664d8SYork Sun 	set_ddr_sdram_interval(ctrl_num, ddr, popts, common_dimm);
25285614e71bSYork Sun 	set_ddr_data_init(ddr);
25295614e71bSYork Sun 	set_ddr_sdram_clk_cntl(ddr, popts);
25305614e71bSYork Sun 	set_ddr_init_addr(ddr);
25315614e71bSYork Sun 	set_ddr_init_ext_addr(ddr);
25325614e71bSYork Sun 	set_timing_cfg_4(ddr, popts);
25335614e71bSYork Sun 	set_timing_cfg_5(ddr, cas_latency);
253434e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
253534e026f9SYork Sun 	set_ddr_sdram_cfg_3(ddr, popts);
253634e026f9SYork Sun 	set_timing_cfg_6(ddr);
253703e664d8SYork Sun 	set_timing_cfg_7(ctrl_num, ddr, common_dimm);
253803e664d8SYork Sun 	set_timing_cfg_8(ctrl_num, ddr, popts, common_dimm, cas_latency);
253934e026f9SYork Sun 	set_timing_cfg_9(ddr);
254034e026f9SYork Sun 	set_ddr_dq_mapping(ddr, dimm_params);
254134e026f9SYork Sun #endif
25425614e71bSYork Sun 
25435614e71bSYork Sun 	set_ddr_zq_cntl(ddr, zq_en);
25445614e71bSYork Sun 	set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts);
25455614e71bSYork Sun 
25465614e71bSYork Sun 	set_ddr_sr_cntr(ddr, sr_it);
25475614e71bSYork Sun 
25485614e71bSYork Sun 	set_ddr_sdram_rcw(ddr, popts, common_dimm);
25495614e71bSYork Sun 
25505614e71bSYork Sun #ifdef CONFIG_SYS_FSL_DDR_EMU
25515614e71bSYork Sun 	/* disble DDR training for emulator */
25525614e71bSYork Sun 	ddr->debug[2] = 0x00000400;
25531f3402e7SYork Sun 	ddr->debug[4] = 0xff800800;
25541f3402e7SYork Sun 	ddr->debug[5] = 0x08000800;
25551f3402e7SYork Sun 	ddr->debug[6] = 0x08000800;
25561f3402e7SYork Sun 	ddr->debug[7] = 0x08000800;
25571f3402e7SYork Sun 	ddr->debug[8] = 0x08000800;
25585614e71bSYork Sun #endif
25599855b3beSYork Sun #ifdef CONFIG_SYS_FSL_ERRATUM_A004508
25609855b3beSYork Sun 	if ((ip_rev >= 0x40000) && (ip_rev < 0x40400))
25619855b3beSYork Sun 		ddr->debug[2] |= 0x00000200;	/* set bit 22 */
25629855b3beSYork Sun #endif
25639855b3beSYork Sun 
256402fb2761SShengzhou Liu #if defined(CONFIG_SYS_FSL_ERRATUM_A008378) && defined(CONFIG_SYS_FSL_DDRC_GEN4)
256502fb2761SShengzhou Liu 	/* Erratum applies when accumulated ECC is used, or DBI is enabled */
256602fb2761SShengzhou Liu #define IS_ACC_ECC_EN(v) ((v) & 0x4)
256702fb2761SShengzhou Liu #define IS_DBI(v) ((((v) >> 12) & 0x3) == 0x2)
256802fb2761SShengzhou Liu 	if (has_erratum_a008378()) {
256902fb2761SShengzhou Liu 		if (IS_ACC_ECC_EN(ddr->ddr_sdram_cfg) ||
257002fb2761SShengzhou Liu 		    IS_DBI(ddr->ddr_sdram_cfg_3)) {
257102fb2761SShengzhou Liu 			ddr->debug[28] = ddr_in32(&ddrc->debug[28]);
257202fb2761SShengzhou Liu 			ddr->debug[28] |= (0x9 << 20);
257302fb2761SShengzhou Liu 		}
257402fb2761SShengzhou Liu 	}
257502fb2761SShengzhou Liu #endif
257602fb2761SShengzhou Liu 
257702fb2761SShengzhou Liu #ifdef CONFIG_SYS_FSL_ERRATUM_A009942
257802fb2761SShengzhou Liu 	ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
257902fb2761SShengzhou Liu 	ddr->debug[28] |= ddr_in32(&ddrc->debug[28]);
258002fb2761SShengzhou Liu 	ddr->debug[28] &= 0xff0fff00;
258102fb2761SShengzhou Liu 	if (ddr_freq <= 1333)
258202fb2761SShengzhou Liu 		ddr->debug[28] |= 0x0080006a;
258302fb2761SShengzhou Liu 	else if (ddr_freq <= 1600)
258402fb2761SShengzhou Liu 		ddr->debug[28] |= 0x0070006f;
258502fb2761SShengzhou Liu 	else if (ddr_freq <= 1867)
258602fb2761SShengzhou Liu 		ddr->debug[28] |= 0x00700076;
258702fb2761SShengzhou Liu 	else if (ddr_freq <= 2133)
258802fb2761SShengzhou Liu 		ddr->debug[28] |= 0x0060007b;
258902fb2761SShengzhou Liu 	if (popts->cpo_sample)
259002fb2761SShengzhou Liu 		ddr->debug[28] = (ddr->debug[28] & 0xffffff00) |
259102fb2761SShengzhou Liu 				  popts->cpo_sample;
259202fb2761SShengzhou Liu #endif
259302fb2761SShengzhou Liu 
25945614e71bSYork Sun 	return check_fsl_memctl_config_regs(ddr);
25955614e71bSYork Sun }
259602fb2761SShengzhou Liu 
259702fb2761SShengzhou Liu #ifdef CONFIG_SYS_FSL_ERRATUM_A009942
259802fb2761SShengzhou Liu /*
259902fb2761SShengzhou Liu  * This additional workaround of A009942 checks the condition to determine if
260002fb2761SShengzhou Liu  * the CPO value set by the existing A009942 workaround needs to be updated.
260102fb2761SShengzhou Liu  * If need, print a warning to prompt user reconfigure DDR debug_29[24:31] with
260202fb2761SShengzhou Liu  * expected optimal value, the optimal value is highly board dependent.
260302fb2761SShengzhou Liu  */
260402fb2761SShengzhou Liu void erratum_a009942_check_cpo(void)
260502fb2761SShengzhou Liu {
260602fb2761SShengzhou Liu 	struct ccsr_ddr __iomem *ddr =
260702fb2761SShengzhou Liu 		(struct ccsr_ddr __iomem *)(CONFIG_SYS_FSL_DDR_ADDR);
260802fb2761SShengzhou Liu 	u32 cpo, cpo_e, cpo_o, cpo_target, cpo_optimal;
260902fb2761SShengzhou Liu 	u32 cpo_min = ddr_in32(&ddr->debug[9]) >> 24;
261002fb2761SShengzhou Liu 	u32 cpo_max = cpo_min;
261102fb2761SShengzhou Liu 	u32 sdram_cfg, i, tmp, lanes, ddr_type;
261202fb2761SShengzhou Liu 	bool update_cpo = false, has_ecc = false;
261302fb2761SShengzhou Liu 
261402fb2761SShengzhou Liu 	sdram_cfg = ddr_in32(&ddr->sdram_cfg);
261502fb2761SShengzhou Liu 	if (sdram_cfg & SDRAM_CFG_32_BE)
261602fb2761SShengzhou Liu 		lanes = 4;
261702fb2761SShengzhou Liu 	else if (sdram_cfg & SDRAM_CFG_16_BE)
261802fb2761SShengzhou Liu 		lanes = 2;
261902fb2761SShengzhou Liu 	else
262002fb2761SShengzhou Liu 		lanes = 8;
262102fb2761SShengzhou Liu 
262202fb2761SShengzhou Liu 	if (sdram_cfg & SDRAM_CFG_ECC_EN)
262302fb2761SShengzhou Liu 		has_ecc = true;
262402fb2761SShengzhou Liu 
262502fb2761SShengzhou Liu 	/* determine the maximum and minimum CPO values */
262602fb2761SShengzhou Liu 	for (i = 9; i < 9 + lanes / 2; i++) {
262702fb2761SShengzhou Liu 		cpo = ddr_in32(&ddr->debug[i]);
262802fb2761SShengzhou Liu 		cpo_e = cpo >> 24;
262902fb2761SShengzhou Liu 		cpo_o = (cpo >> 8) & 0xff;
263002fb2761SShengzhou Liu 		tmp = min(cpo_e, cpo_o);
263102fb2761SShengzhou Liu 		if (tmp < cpo_min)
263202fb2761SShengzhou Liu 			cpo_min = tmp;
263302fb2761SShengzhou Liu 		tmp = max(cpo_e, cpo_o);
263402fb2761SShengzhou Liu 		if (tmp > cpo_max)
263502fb2761SShengzhou Liu 			cpo_max = tmp;
263602fb2761SShengzhou Liu 	}
263702fb2761SShengzhou Liu 
263802fb2761SShengzhou Liu 	if (has_ecc) {
263902fb2761SShengzhou Liu 		cpo = ddr_in32(&ddr->debug[13]);
264002fb2761SShengzhou Liu 		cpo = cpo >> 24;
264102fb2761SShengzhou Liu 		if (cpo < cpo_min)
264202fb2761SShengzhou Liu 			cpo_min = cpo;
264302fb2761SShengzhou Liu 		if (cpo > cpo_max)
264402fb2761SShengzhou Liu 			cpo_max = cpo;
264502fb2761SShengzhou Liu 	}
264602fb2761SShengzhou Liu 
264702fb2761SShengzhou Liu 	cpo_target = ddr_in32(&ddr->debug[28]) & 0xff;
264802fb2761SShengzhou Liu 	cpo_optimal = ((cpo_max + cpo_min) >> 1) + 0x27;
264902fb2761SShengzhou Liu 	debug("cpo_optimal = 0x%x, cpo_target = 0x%x\n", cpo_optimal,
265002fb2761SShengzhou Liu 	      cpo_target);
265102fb2761SShengzhou Liu 	debug("cpo_max = 0x%x, cpo_min = 0x%x\n", cpo_max, cpo_min);
265202fb2761SShengzhou Liu 
265302fb2761SShengzhou Liu 	ddr_type = (sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
265402fb2761SShengzhou Liu 		    SDRAM_CFG_SDRAM_TYPE_SHIFT;
265502fb2761SShengzhou Liu 	if (ddr_type == SDRAM_TYPE_DDR4)
265602fb2761SShengzhou Liu 		update_cpo = (cpo_min + 0x3b) < cpo_target ? true : false;
265702fb2761SShengzhou Liu 	else if (ddr_type == SDRAM_TYPE_DDR3)
265802fb2761SShengzhou Liu 		update_cpo = (cpo_min + 0x3f) < cpo_target ? true : false;
265902fb2761SShengzhou Liu 
266002fb2761SShengzhou Liu 	if (update_cpo) {
266102fb2761SShengzhou Liu 		printf("WARN: pls set popts->cpo_sample = 0x%x ", cpo_optimal);
266202fb2761SShengzhou Liu 		printf("in <board>/ddr.c to optimize cpo\n");
266302fb2761SShengzhou Liu 	}
266402fb2761SShengzhou Liu }
266502fb2761SShengzhou Liu #endif
2666