xref: /openbmc/u-boot/drivers/ddr/fsl/ctrl_regs.c (revision 426230a65f2dd62c3b6c1509e9775d5500db20d3)
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>
19457e51cfSSimon Glass #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \
20457e51cfSSimon Glass 	defined(CONFIG_ARM)
216e2941d7SSimon Glass #include <asm/arch/clock.h>
226e2941d7SSimon Glass #endif
235614e71bSYork Sun 
245614e71bSYork Sun /*
255614e71bSYork Sun  * Determine Rtt value.
265614e71bSYork Sun  *
275614e71bSYork Sun  * This should likely be either board or controller specific.
285614e71bSYork Sun  *
295614e71bSYork Sun  * Rtt(nominal) - DDR2:
305614e71bSYork Sun  *	0 = Rtt disabled
315614e71bSYork Sun  *	1 = 75 ohm
325614e71bSYork Sun  *	2 = 150 ohm
335614e71bSYork Sun  *	3 = 50 ohm
345614e71bSYork Sun  * Rtt(nominal) - DDR3:
355614e71bSYork Sun  *	0 = Rtt disabled
365614e71bSYork Sun  *	1 = 60 ohm
375614e71bSYork Sun  *	2 = 120 ohm
385614e71bSYork Sun  *	3 = 40 ohm
395614e71bSYork Sun  *	4 = 20 ohm
405614e71bSYork Sun  *	5 = 30 ohm
415614e71bSYork Sun  *
425614e71bSYork Sun  * FIXME: Apparently 8641 needs a value of 2
435614e71bSYork Sun  * FIXME: Old code seys if 667 MHz or higher, use 3 on 8572
445614e71bSYork Sun  *
455614e71bSYork Sun  * FIXME: There was some effort down this line earlier:
465614e71bSYork Sun  *
475614e71bSYork Sun  *	unsigned int i;
485614e71bSYork Sun  *	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL/2; i++) {
495614e71bSYork Sun  *		if (popts->dimmslot[i].num_valid_cs
505614e71bSYork Sun  *		    && (popts->cs_local_opts[2*i].odt_rd_cfg
515614e71bSYork Sun  *			|| popts->cs_local_opts[2*i].odt_wr_cfg)) {
525614e71bSYork Sun  *			rtt = 2;
535614e71bSYork Sun  *			break;
545614e71bSYork Sun  *		}
555614e71bSYork Sun  *	}
565614e71bSYork Sun  */
575614e71bSYork Sun static inline int fsl_ddr_get_rtt(void)
585614e71bSYork Sun {
595614e71bSYork Sun 	int rtt;
605614e71bSYork Sun 
615614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
625614e71bSYork Sun 	rtt = 0;
635614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
645614e71bSYork Sun 	rtt = 3;
655614e71bSYork Sun #else
665614e71bSYork Sun 	rtt = 0;
675614e71bSYork Sun #endif
685614e71bSYork Sun 
695614e71bSYork Sun 	return rtt;
705614e71bSYork Sun }
715614e71bSYork Sun 
7234e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
7334e026f9SYork Sun /*
7434e026f9SYork Sun  * compute CAS write latency according to DDR4 spec
7534e026f9SYork Sun  * CWL = 9 for <= 1600MT/s
7634e026f9SYork Sun  *       10 for <= 1866MT/s
7734e026f9SYork Sun  *       11 for <= 2133MT/s
7834e026f9SYork Sun  *       12 for <= 2400MT/s
7934e026f9SYork Sun  *       14 for <= 2667MT/s
8034e026f9SYork Sun  *       16 for <= 2933MT/s
8134e026f9SYork Sun  *       18 for higher
8234e026f9SYork Sun  */
8303e664d8SYork Sun static inline unsigned int compute_cas_write_latency(
8403e664d8SYork Sun 				const unsigned int ctrl_num)
8534e026f9SYork Sun {
8634e026f9SYork Sun 	unsigned int cwl;
8703e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
8834e026f9SYork Sun 	if (mclk_ps >= 1250)
8934e026f9SYork Sun 		cwl = 9;
9034e026f9SYork Sun 	else if (mclk_ps >= 1070)
9134e026f9SYork Sun 		cwl = 10;
9234e026f9SYork Sun 	else if (mclk_ps >= 935)
9334e026f9SYork Sun 		cwl = 11;
9434e026f9SYork Sun 	else if (mclk_ps >= 833)
9534e026f9SYork Sun 		cwl = 12;
9634e026f9SYork Sun 	else if (mclk_ps >= 750)
9734e026f9SYork Sun 		cwl = 14;
9834e026f9SYork Sun 	else if (mclk_ps >= 681)
9934e026f9SYork Sun 		cwl = 16;
10034e026f9SYork Sun 	else
10134e026f9SYork Sun 		cwl = 18;
10234e026f9SYork Sun 
10334e026f9SYork Sun 	return cwl;
10434e026f9SYork Sun }
10534e026f9SYork Sun #else
1065614e71bSYork Sun /*
1075614e71bSYork Sun  * compute the CAS write latency according to DDR3 spec
1085614e71bSYork Sun  * CWL = 5 if tCK >= 2.5ns
1095614e71bSYork Sun  *       6 if 2.5ns > tCK >= 1.875ns
1105614e71bSYork Sun  *       7 if 1.875ns > tCK >= 1.5ns
1115614e71bSYork Sun  *       8 if 1.5ns > tCK >= 1.25ns
1125614e71bSYork Sun  *       9 if 1.25ns > tCK >= 1.07ns
1135614e71bSYork Sun  *       10 if 1.07ns > tCK >= 0.935ns
1145614e71bSYork Sun  *       11 if 0.935ns > tCK >= 0.833ns
1155614e71bSYork Sun  *       12 if 0.833ns > tCK >= 0.75ns
1165614e71bSYork Sun  */
11703e664d8SYork Sun static inline unsigned int compute_cas_write_latency(
11803e664d8SYork Sun 				const unsigned int ctrl_num)
1195614e71bSYork Sun {
1205614e71bSYork Sun 	unsigned int cwl;
12103e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
1225614e71bSYork Sun 
1235614e71bSYork Sun 	if (mclk_ps >= 2500)
1245614e71bSYork Sun 		cwl = 5;
1255614e71bSYork Sun 	else if (mclk_ps >= 1875)
1265614e71bSYork Sun 		cwl = 6;
1275614e71bSYork Sun 	else if (mclk_ps >= 1500)
1285614e71bSYork Sun 		cwl = 7;
1295614e71bSYork Sun 	else if (mclk_ps >= 1250)
1305614e71bSYork Sun 		cwl = 8;
1315614e71bSYork Sun 	else if (mclk_ps >= 1070)
1325614e71bSYork Sun 		cwl = 9;
1335614e71bSYork Sun 	else if (mclk_ps >= 935)
1345614e71bSYork Sun 		cwl = 10;
1355614e71bSYork Sun 	else if (mclk_ps >= 833)
1365614e71bSYork Sun 		cwl = 11;
1375614e71bSYork Sun 	else if (mclk_ps >= 750)
1385614e71bSYork Sun 		cwl = 12;
1395614e71bSYork Sun 	else {
1405614e71bSYork Sun 		cwl = 12;
1415614e71bSYork Sun 		printf("Warning: CWL is out of range\n");
1425614e71bSYork Sun 	}
1435614e71bSYork Sun 	return cwl;
1445614e71bSYork Sun }
14534e026f9SYork Sun #endif
1465614e71bSYork Sun 
1475614e71bSYork Sun /* Chip Select Configuration (CSn_CONFIG) */
1485614e71bSYork Sun static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
1495614e71bSYork Sun 			       const memctl_options_t *popts,
1505614e71bSYork Sun 			       const dimm_params_t *dimm_params)
1515614e71bSYork Sun {
1525614e71bSYork Sun 	unsigned int cs_n_en = 0; /* Chip Select enable */
1535614e71bSYork Sun 	unsigned int intlv_en = 0; /* Memory controller interleave enable */
1545614e71bSYork Sun 	unsigned int intlv_ctl = 0; /* Interleaving control */
1555614e71bSYork Sun 	unsigned int ap_n_en = 0; /* Chip select n auto-precharge enable */
1565614e71bSYork Sun 	unsigned int odt_rd_cfg = 0; /* ODT for reads configuration */
1575614e71bSYork Sun 	unsigned int odt_wr_cfg = 0; /* ODT for writes configuration */
1585614e71bSYork Sun 	unsigned int ba_bits_cs_n = 0; /* Num of bank bits for SDRAM on CSn */
1595614e71bSYork Sun 	unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */
1605614e71bSYork Sun 	unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */
1615614e71bSYork Sun 	int go_config = 0;
16234e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
16334e026f9SYork Sun 	unsigned int bg_bits_cs_n = 0; /* Num of bank group bits */
16434e026f9SYork Sun #else
16534e026f9SYork Sun 	unsigned int n_banks_per_sdram_device;
16634e026f9SYork Sun #endif
1675614e71bSYork Sun 
1685614e71bSYork Sun 	/* Compute CS_CONFIG only for existing ranks of each DIMM.  */
1695614e71bSYork Sun 	switch (i) {
1705614e71bSYork Sun 	case 0:
1715614e71bSYork Sun 		if (dimm_params[dimm_number].n_ranks > 0) {
1725614e71bSYork Sun 			go_config = 1;
1735614e71bSYork Sun 			/* These fields only available in CS0_CONFIG */
1745614e71bSYork Sun 			if (!popts->memctl_interleaving)
1755614e71bSYork Sun 				break;
1765614e71bSYork Sun 			switch (popts->memctl_interleaving_mode) {
1776b1e1254SYork Sun 			case FSL_DDR_256B_INTERLEAVING:
1785614e71bSYork Sun 			case FSL_DDR_CACHE_LINE_INTERLEAVING:
1795614e71bSYork Sun 			case FSL_DDR_PAGE_INTERLEAVING:
1805614e71bSYork Sun 			case FSL_DDR_BANK_INTERLEAVING:
1815614e71bSYork Sun 			case FSL_DDR_SUPERBANK_INTERLEAVING:
1825614e71bSYork Sun 				intlv_en = popts->memctl_interleaving;
1835614e71bSYork Sun 				intlv_ctl = popts->memctl_interleaving_mode;
1845614e71bSYork Sun 				break;
1855614e71bSYork Sun 			default:
1865614e71bSYork Sun 				break;
1875614e71bSYork Sun 			}
1885614e71bSYork Sun 		}
1895614e71bSYork Sun 		break;
1905614e71bSYork Sun 	case 1:
1915614e71bSYork Sun 		if ((dimm_number == 0 && dimm_params[0].n_ranks > 1) || \
1925614e71bSYork Sun 		    (dimm_number == 1 && dimm_params[1].n_ranks > 0))
1935614e71bSYork Sun 			go_config = 1;
1945614e71bSYork Sun 		break;
1955614e71bSYork Sun 	case 2:
1965614e71bSYork Sun 		if ((dimm_number == 0 && dimm_params[0].n_ranks > 2) || \
1975614e71bSYork Sun 		   (dimm_number >= 1 && dimm_params[dimm_number].n_ranks > 0))
1985614e71bSYork Sun 			go_config = 1;
1995614e71bSYork Sun 		break;
2005614e71bSYork Sun 	case 3:
2015614e71bSYork Sun 		if ((dimm_number == 0 && dimm_params[0].n_ranks > 3) || \
2025614e71bSYork Sun 		    (dimm_number == 1 && dimm_params[1].n_ranks > 1) || \
2035614e71bSYork Sun 		    (dimm_number == 3 && dimm_params[3].n_ranks > 0))
2045614e71bSYork Sun 			go_config = 1;
2055614e71bSYork Sun 		break;
2065614e71bSYork Sun 	default:
2075614e71bSYork Sun 		break;
2085614e71bSYork Sun 	}
2095614e71bSYork Sun 	if (go_config) {
2105614e71bSYork Sun 		cs_n_en = 1;
2115614e71bSYork Sun 		ap_n_en = popts->cs_local_opts[i].auto_precharge;
2125614e71bSYork Sun 		odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg;
2135614e71bSYork Sun 		odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg;
21434e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
21534e026f9SYork Sun 		ba_bits_cs_n = dimm_params[dimm_number].bank_addr_bits;
21634e026f9SYork Sun 		bg_bits_cs_n = dimm_params[dimm_number].bank_group_bits;
21734e026f9SYork Sun #else
2185614e71bSYork Sun 		n_banks_per_sdram_device
2195614e71bSYork Sun 			= dimm_params[dimm_number].n_banks_per_sdram_device;
2205614e71bSYork Sun 		ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2;
22134e026f9SYork Sun #endif
2225614e71bSYork Sun 		row_bits_cs_n = dimm_params[dimm_number].n_row_addr - 12;
2235614e71bSYork Sun 		col_bits_cs_n = dimm_params[dimm_number].n_col_addr - 8;
2245614e71bSYork Sun 	}
2255614e71bSYork Sun 	ddr->cs[i].config = (0
2265614e71bSYork Sun 		| ((cs_n_en & 0x1) << 31)
2275614e71bSYork Sun 		| ((intlv_en & 0x3) << 29)
2285614e71bSYork Sun 		| ((intlv_ctl & 0xf) << 24)
2295614e71bSYork Sun 		| ((ap_n_en & 0x1) << 23)
2305614e71bSYork Sun 
2315614e71bSYork Sun 		/* XXX: some implementation only have 1 bit starting at left */
2325614e71bSYork Sun 		| ((odt_rd_cfg & 0x7) << 20)
2335614e71bSYork Sun 
2345614e71bSYork Sun 		/* XXX: Some implementation only have 1 bit starting at left */
2355614e71bSYork Sun 		| ((odt_wr_cfg & 0x7) << 16)
2365614e71bSYork Sun 
2375614e71bSYork Sun 		| ((ba_bits_cs_n & 0x3) << 14)
2385614e71bSYork Sun 		| ((row_bits_cs_n & 0x7) << 8)
23934e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
24034e026f9SYork Sun 		| ((bg_bits_cs_n & 0x3) << 4)
24134e026f9SYork Sun #endif
2425614e71bSYork Sun 		| ((col_bits_cs_n & 0x7) << 0)
2435614e71bSYork Sun 		);
2445614e71bSYork Sun 	debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config);
2455614e71bSYork Sun }
2465614e71bSYork Sun 
2475614e71bSYork Sun /* Chip Select Configuration 2 (CSn_CONFIG_2) */
2485614e71bSYork Sun /* FIXME: 8572 */
2495614e71bSYork Sun static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)
2505614e71bSYork Sun {
2515614e71bSYork Sun 	unsigned int pasr_cfg = 0;	/* Partial array self refresh config */
2525614e71bSYork Sun 
2535614e71bSYork Sun 	ddr->cs[i].config_2 = ((pasr_cfg & 7) << 24);
2545614e71bSYork Sun 	debug("FSLDDR: cs[%d]_config_2 = 0x%08x\n", i, ddr->cs[i].config_2);
2555614e71bSYork Sun }
2565614e71bSYork Sun 
2575614e71bSYork Sun /* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */
2585614e71bSYork Sun 
2595614e71bSYork Sun #if !defined(CONFIG_SYS_FSL_DDR1)
26084baed2aSYork Sun /*
26184baed2aSYork Sun  * Check DIMM configuration, return 2 if quad-rank or two dual-rank
26284baed2aSYork Sun  * Return 1 if other two slots configuration. Return 0 if single slot.
26384baed2aSYork Sun  */
2645614e71bSYork Sun static inline int avoid_odt_overlap(const dimm_params_t *dimm_params)
2655614e71bSYork Sun {
2665614e71bSYork Sun #if CONFIG_DIMM_SLOTS_PER_CTLR == 1
2675614e71bSYork Sun 	if (dimm_params[0].n_ranks == 4)
26884baed2aSYork Sun 		return 2;
2695614e71bSYork Sun #endif
2705614e71bSYork Sun 
2715614e71bSYork Sun #if CONFIG_DIMM_SLOTS_PER_CTLR == 2
2725614e71bSYork Sun 	if ((dimm_params[0].n_ranks == 2) &&
2735614e71bSYork Sun 		(dimm_params[1].n_ranks == 2))
27484baed2aSYork Sun 		return 2;
2755614e71bSYork Sun 
2765614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
2775614e71bSYork Sun 	if (dimm_params[0].n_ranks == 4)
27884baed2aSYork Sun 		return 2;
2795614e71bSYork Sun #endif
28084baed2aSYork Sun 
28184baed2aSYork Sun 	if ((dimm_params[0].n_ranks != 0) &&
28284baed2aSYork Sun 	    (dimm_params[2].n_ranks != 0))
28384baed2aSYork Sun 		return 1;
2845614e71bSYork Sun #endif
2855614e71bSYork Sun 	return 0;
2865614e71bSYork Sun }
2875614e71bSYork Sun 
2885614e71bSYork Sun /*
2895614e71bSYork Sun  * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0)
2905614e71bSYork Sun  *
2915614e71bSYork Sun  * Avoid writing for DDR I.  The new PQ38 DDR controller
2925614e71bSYork Sun  * dreams up non-zero default values to be backwards compatible.
2935614e71bSYork Sun  */
29403e664d8SYork Sun static void set_timing_cfg_0(const unsigned int ctrl_num,
29503e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
2965614e71bSYork Sun 				const memctl_options_t *popts,
2975614e71bSYork Sun 				const dimm_params_t *dimm_params)
2985614e71bSYork Sun {
2995614e71bSYork Sun 	unsigned char trwt_mclk = 0;   /* Read-to-write turnaround */
3005614e71bSYork Sun 	unsigned char twrt_mclk = 0;   /* Write-to-read turnaround */
3015614e71bSYork Sun 	/* 7.5 ns on -3E; 0 means WL - CL + BL/2 + 1 */
3025614e71bSYork Sun 	unsigned char trrt_mclk = 0;   /* Read-to-read turnaround */
3035614e71bSYork Sun 	unsigned char twwt_mclk = 0;   /* Write-to-write turnaround */
3045614e71bSYork Sun 
3055614e71bSYork Sun 	/* Active powerdown exit timing (tXARD and tXARDS). */
3065614e71bSYork Sun 	unsigned char act_pd_exit_mclk;
3075614e71bSYork Sun 	/* Precharge powerdown exit timing (tXP). */
3085614e71bSYork Sun 	unsigned char pre_pd_exit_mclk;
3095614e71bSYork Sun 	/* ODT powerdown exit timing (tAXPD). */
31034e026f9SYork Sun 	unsigned char taxpd_mclk = 0;
3115614e71bSYork Sun 	/* Mode register set cycle time (tMRD). */
3125614e71bSYork Sun 	unsigned char tmrd_mclk;
313bb578322SYork Sun #if defined(CONFIG_SYS_FSL_DDR4) || defined(CONFIG_SYS_FSL_DDR3)
31403e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
315bb578322SYork Sun #endif
3165614e71bSYork Sun 
31734e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
31834e026f9SYork Sun 	/* tXP=max(4nCK, 6ns) */
319b4141195SMasahiro Yamada 	int txp = max((int)mclk_ps * 4, 6000); /* unit=ps */
32066869f95SYork Sun 	unsigned int data_rate = get_ddr_freq(ctrl_num);
32166869f95SYork Sun 
32266869f95SYork Sun 	/* for faster clock, need more time for data setup */
32366869f95SYork Sun 	trwt_mclk = (data_rate/1000000 > 1900) ? 3 : 2;
3246c6e006aSYork Sun 
3256c6e006aSYork Sun 	/*
3266c6e006aSYork Sun 	 * for single quad-rank DIMM and two-slot DIMMs
3276c6e006aSYork Sun 	 * to avoid ODT overlap
3286c6e006aSYork Sun 	 */
3296c6e006aSYork Sun 	switch (avoid_odt_overlap(dimm_params)) {
3306c6e006aSYork Sun 	case 2:
3316c6e006aSYork Sun 		twrt_mclk = 2;
3326c6e006aSYork Sun 		twwt_mclk = 2;
3336c6e006aSYork Sun 		trrt_mclk = 2;
3346c6e006aSYork Sun 		break;
3356c6e006aSYork Sun 	default:
33634e026f9SYork Sun 		twrt_mclk = 1;
3376c6e006aSYork Sun 		twwt_mclk = 1;
3386c6e006aSYork Sun 		trrt_mclk = 0;
3396c6e006aSYork Sun 		break;
3406c6e006aSYork Sun 	}
3416c6e006aSYork Sun 
34203e664d8SYork Sun 	act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
34334e026f9SYork Sun 	pre_pd_exit_mclk = act_pd_exit_mclk;
34434e026f9SYork Sun 	/*
34534e026f9SYork Sun 	 * MRS_CYC = max(tMRD, tMOD)
34634e026f9SYork Sun 	 * tMRD = 8nCK, tMOD = max(24nCK, 15ns)
34734e026f9SYork Sun 	 */
34803e664d8SYork Sun 	tmrd_mclk = max(24U, picos_to_mclk(ctrl_num, 15000));
34934e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
35003e664d8SYork Sun 	unsigned int data_rate = get_ddr_freq(ctrl_num);
351bb578322SYork Sun 	int txp;
352938bbb60SYork Sun 	unsigned int ip_rev;
35384baed2aSYork Sun 	int odt_overlap;
3545614e71bSYork Sun 	/*
3555614e71bSYork Sun 	 * (tXARD and tXARDS). Empirical?
3565614e71bSYork Sun 	 * The DDR3 spec has not tXARD,
3575614e71bSYork Sun 	 * we use the tXP instead of it.
358bb578322SYork Sun 	 * tXP=max(3nCK, 7.5ns) for DDR3-800, 1066
359bb578322SYork Sun 	 *     max(3nCK, 6ns) for DDR3-1333, 1600, 1866, 2133
3605614e71bSYork Sun 	 * spec has not the tAXPD, we use
3615614e71bSYork Sun 	 * tAXPD=1, need design to confirm.
3625614e71bSYork Sun 	 */
363b4141195SMasahiro Yamada 	txp = max((int)mclk_ps * 3, (mclk_ps > 1540 ? 7500 : 6000));
364bb578322SYork Sun 
36566869f95SYork Sun 	ip_rev = fsl_ddr_get_version(ctrl_num);
366938bbb60SYork Sun 	if (ip_rev >= 0x40700) {
367938bbb60SYork Sun 		/*
368938bbb60SYork Sun 		 * MRS_CYC = max(tMRD, tMOD)
369938bbb60SYork Sun 		 * tMRD = 4nCK (8nCK for RDIMM)
370938bbb60SYork Sun 		 * tMOD = max(12nCK, 15ns)
371938bbb60SYork Sun 		 */
37203e664d8SYork Sun 		tmrd_mclk = max((unsigned int)12,
37303e664d8SYork Sun 				picos_to_mclk(ctrl_num, 15000));
374938bbb60SYork Sun 	} else {
375938bbb60SYork Sun 		/*
376938bbb60SYork Sun 		 * MRS_CYC = tMRD
377938bbb60SYork Sun 		 * tMRD = 4nCK (8nCK for RDIMM)
378938bbb60SYork Sun 		 */
379938bbb60SYork Sun 		if (popts->registered_dimm_en)
380938bbb60SYork Sun 			tmrd_mclk = 8;
381938bbb60SYork Sun 		else
3825614e71bSYork Sun 			tmrd_mclk = 4;
383938bbb60SYork Sun 	}
384938bbb60SYork Sun 
3855614e71bSYork Sun 	/* set the turnaround time */
3865614e71bSYork Sun 
3875614e71bSYork Sun 	/*
38884baed2aSYork Sun 	 * for single quad-rank DIMM and two-slot DIMMs
3895614e71bSYork Sun 	 * to avoid ODT overlap
3905614e71bSYork Sun 	 */
39184baed2aSYork Sun 	odt_overlap = avoid_odt_overlap(dimm_params);
39284baed2aSYork Sun 	switch (odt_overlap) {
39384baed2aSYork Sun 	case 2:
3945614e71bSYork Sun 		twwt_mclk = 2;
3955614e71bSYork Sun 		trrt_mclk = 1;
39684baed2aSYork Sun 		break;
39784baed2aSYork Sun 	case 1:
39884baed2aSYork Sun 		twwt_mclk = 1;
39984baed2aSYork Sun 		trrt_mclk = 0;
40084baed2aSYork Sun 		break;
40184baed2aSYork Sun 	default:
40284baed2aSYork Sun 		break;
4035614e71bSYork Sun 	}
40484baed2aSYork Sun 
4055614e71bSYork Sun 	/* for faster clock, need more time for data setup */
4065614e71bSYork Sun 	trwt_mclk = (data_rate/1000000 > 1800) ? 2 : 1;
4075614e71bSYork Sun 
4085614e71bSYork Sun 	if ((data_rate/1000000 > 1150) || (popts->memctl_interleaving))
4095614e71bSYork Sun 		twrt_mclk = 1;
4105614e71bSYork Sun 
4115614e71bSYork Sun 	if (popts->dynamic_power == 0) {	/* powerdown is not used */
4125614e71bSYork Sun 		act_pd_exit_mclk = 1;
4135614e71bSYork Sun 		pre_pd_exit_mclk = 1;
4145614e71bSYork Sun 		taxpd_mclk = 1;
4155614e71bSYork Sun 	} else {
4165614e71bSYork Sun 		/* act_pd_exit_mclk = tXARD, see above */
41703e664d8SYork Sun 		act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
4185614e71bSYork Sun 		/* Mode register MR0[A12] is '1' - fast exit */
4195614e71bSYork Sun 		pre_pd_exit_mclk = act_pd_exit_mclk;
4205614e71bSYork Sun 		taxpd_mclk = 1;
4215614e71bSYork Sun 	}
4225614e71bSYork Sun #else /* CONFIG_SYS_FSL_DDR2 */
4235614e71bSYork Sun 	/*
4245614e71bSYork Sun 	 * (tXARD and tXARDS). Empirical?
4255614e71bSYork Sun 	 * tXARD = 2 for DDR2
4265614e71bSYork Sun 	 * tXP=2
4275614e71bSYork Sun 	 * tAXPD=8
4285614e71bSYork Sun 	 */
4295614e71bSYork Sun 	act_pd_exit_mclk = 2;
4305614e71bSYork Sun 	pre_pd_exit_mclk = 2;
4315614e71bSYork Sun 	taxpd_mclk = 8;
4325614e71bSYork Sun 	tmrd_mclk = 2;
4335614e71bSYork Sun #endif
4345614e71bSYork Sun 
4355614e71bSYork Sun 	if (popts->trwt_override)
4365614e71bSYork Sun 		trwt_mclk = popts->trwt;
4375614e71bSYork Sun 
4385614e71bSYork Sun 	ddr->timing_cfg_0 = (0
4395614e71bSYork Sun 		| ((trwt_mclk & 0x3) << 30)	/* RWT */
4405614e71bSYork Sun 		| ((twrt_mclk & 0x3) << 28)	/* WRT */
4415614e71bSYork Sun 		| ((trrt_mclk & 0x3) << 26)	/* RRT */
4425614e71bSYork Sun 		| ((twwt_mclk & 0x3) << 24)	/* WWT */
443d4263b8aSYork Sun 		| ((act_pd_exit_mclk & 0xf) << 20)  /* ACT_PD_EXIT */
4445614e71bSYork Sun 		| ((pre_pd_exit_mclk & 0xF) << 16)  /* PRE_PD_EXIT */
4455614e71bSYork Sun 		| ((taxpd_mclk & 0xf) << 8)	/* ODT_PD_EXIT */
446d4263b8aSYork Sun 		| ((tmrd_mclk & 0x1f) << 0)	/* MRS_CYC */
4475614e71bSYork Sun 		);
4485614e71bSYork Sun 	debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
4495614e71bSYork Sun }
45084baed2aSYork Sun #endif	/* !defined(CONFIG_SYS_FSL_DDR1) */
4515614e71bSYork Sun 
4525614e71bSYork Sun /* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */
45303e664d8SYork Sun static void set_timing_cfg_3(const unsigned int ctrl_num,
45403e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
4555614e71bSYork Sun 			     const memctl_options_t *popts,
4565614e71bSYork Sun 			     const common_timing_params_t *common_dimm,
457d4263b8aSYork Sun 			     unsigned int cas_latency,
458d4263b8aSYork Sun 			     unsigned int additive_latency)
4595614e71bSYork Sun {
4605614e71bSYork Sun 	/* Extended precharge to activate interval (tRP) */
4615614e71bSYork Sun 	unsigned int ext_pretoact = 0;
4625614e71bSYork Sun 	/* Extended Activate to precharge interval (tRAS) */
4635614e71bSYork Sun 	unsigned int ext_acttopre = 0;
4645614e71bSYork Sun 	/* Extended activate to read/write interval (tRCD) */
4655614e71bSYork Sun 	unsigned int ext_acttorw = 0;
4665614e71bSYork Sun 	/* Extended refresh recovery time (tRFC) */
4675614e71bSYork Sun 	unsigned int ext_refrec;
4685614e71bSYork Sun 	/* Extended MCAS latency from READ cmd */
4695614e71bSYork Sun 	unsigned int ext_caslat = 0;
470d4263b8aSYork Sun 	/* Extended additive latency */
471d4263b8aSYork Sun 	unsigned int ext_add_lat = 0;
4725614e71bSYork Sun 	/* Extended last data to precharge interval (tWR) */
4735614e71bSYork Sun 	unsigned int ext_wrrec = 0;
4745614e71bSYork Sun 	/* Control Adjust */
4755614e71bSYork Sun 	unsigned int cntl_adj = 0;
4765614e71bSYork Sun 
47703e664d8SYork Sun 	ext_pretoact = picos_to_mclk(ctrl_num, common_dimm->trp_ps) >> 4;
47803e664d8SYork Sun 	ext_acttopre = picos_to_mclk(ctrl_num, common_dimm->tras_ps) >> 4;
47903e664d8SYork Sun 	ext_acttorw = picos_to_mclk(ctrl_num, common_dimm->trcd_ps) >> 4;
4805614e71bSYork Sun 	ext_caslat = (2 * cas_latency - 1) >> 4;
481d4263b8aSYork Sun 	ext_add_lat = additive_latency >> 4;
48234e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
48303e664d8SYork Sun 	ext_refrec = (picos_to_mclk(ctrl_num, common_dimm->trfc1_ps) - 8) >> 4;
48434e026f9SYork Sun #else
48503e664d8SYork Sun 	ext_refrec = (picos_to_mclk(ctrl_num, common_dimm->trfc_ps) - 8) >> 4;
4865614e71bSYork Sun 	/* ext_wrrec only deals with 16 clock and above, or 14 with OTF */
48734e026f9SYork Sun #endif
48803e664d8SYork Sun 	ext_wrrec = (picos_to_mclk(ctrl_num, common_dimm->twr_ps) +
4895614e71bSYork Sun 		(popts->otf_burst_chop_en ? 2 : 0)) >> 4;
4905614e71bSYork Sun 
4915614e71bSYork Sun 	ddr->timing_cfg_3 = (0
4925614e71bSYork Sun 		| ((ext_pretoact & 0x1) << 28)
4935614e71bSYork Sun 		| ((ext_acttopre & 0x3) << 24)
4945614e71bSYork Sun 		| ((ext_acttorw & 0x1) << 22)
4955614e71bSYork Sun 		| ((ext_refrec & 0x1F) << 16)
4965614e71bSYork Sun 		| ((ext_caslat & 0x3) << 12)
497d4263b8aSYork Sun 		| ((ext_add_lat & 0x1) << 10)
4985614e71bSYork Sun 		| ((ext_wrrec & 0x1) << 8)
4995614e71bSYork Sun 		| ((cntl_adj & 0x7) << 0)
5005614e71bSYork Sun 		);
5015614e71bSYork Sun 	debug("FSLDDR: timing_cfg_3 = 0x%08x\n", ddr->timing_cfg_3);
5025614e71bSYork Sun }
5035614e71bSYork Sun 
5045614e71bSYork Sun /* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */
50503e664d8SYork Sun static void set_timing_cfg_1(const unsigned int ctrl_num,
50603e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
5075614e71bSYork Sun 			     const memctl_options_t *popts,
5085614e71bSYork Sun 			     const common_timing_params_t *common_dimm,
5095614e71bSYork Sun 			     unsigned int cas_latency)
5105614e71bSYork Sun {
5115614e71bSYork Sun 	/* Precharge-to-activate interval (tRP) */
5125614e71bSYork Sun 	unsigned char pretoact_mclk;
5135614e71bSYork Sun 	/* Activate to precharge interval (tRAS) */
5145614e71bSYork Sun 	unsigned char acttopre_mclk;
5155614e71bSYork Sun 	/*  Activate to read/write interval (tRCD) */
5165614e71bSYork Sun 	unsigned char acttorw_mclk;
5175614e71bSYork Sun 	/* CASLAT */
5185614e71bSYork Sun 	unsigned char caslat_ctrl;
5195614e71bSYork Sun 	/*  Refresh recovery time (tRFC) ; trfc_low */
5205614e71bSYork Sun 	unsigned char refrec_ctrl;
5215614e71bSYork Sun 	/* Last data to precharge minimum interval (tWR) */
5225614e71bSYork Sun 	unsigned char wrrec_mclk;
5235614e71bSYork Sun 	/* Activate-to-activate interval (tRRD) */
5245614e71bSYork Sun 	unsigned char acttoact_mclk;
5255614e71bSYork Sun 	/* Last write data pair to read command issue interval (tWTR) */
5265614e71bSYork Sun 	unsigned char wrtord_mclk;
52734e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
52834e026f9SYork Sun 	/* DDR4 supports 10, 12, 14, 16, 18, 20, 24 */
52934e026f9SYork Sun 	static const u8 wrrec_table[] = {
53034e026f9SYork Sun 		10, 10, 10, 10, 10,
53134e026f9SYork Sun 		10, 10, 10, 10, 10,
53234e026f9SYork Sun 		12, 12, 14, 14, 16,
53334e026f9SYork Sun 		16, 18, 18, 20, 20,
53434e026f9SYork Sun 		24, 24, 24, 24};
53534e026f9SYork Sun #else
5365614e71bSYork Sun 	/* DDR_SDRAM_MODE doesn't support 9,11,13,15 */
5375614e71bSYork Sun 	static const u8 wrrec_table[] = {
5385614e71bSYork Sun 		1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0};
53934e026f9SYork Sun #endif
5405614e71bSYork Sun 
54103e664d8SYork Sun 	pretoact_mclk = picos_to_mclk(ctrl_num, common_dimm->trp_ps);
54203e664d8SYork Sun 	acttopre_mclk = picos_to_mclk(ctrl_num, common_dimm->tras_ps);
54303e664d8SYork Sun 	acttorw_mclk = picos_to_mclk(ctrl_num, common_dimm->trcd_ps);
5445614e71bSYork Sun 
5455614e71bSYork Sun 	/*
5465614e71bSYork Sun 	 * Translate CAS Latency to a DDR controller field value:
5475614e71bSYork Sun 	 *
5485614e71bSYork Sun 	 *      CAS Lat DDR I   DDR II  Ctrl
5495614e71bSYork Sun 	 *      Clocks  SPD Bit SPD Bit Value
5505614e71bSYork Sun 	 *      ------- ------- ------- -----
5515614e71bSYork Sun 	 *      1.0     0               0001
5525614e71bSYork Sun 	 *      1.5     1               0010
5535614e71bSYork Sun 	 *      2.0     2       2       0011
5545614e71bSYork Sun 	 *      2.5     3               0100
5555614e71bSYork Sun 	 *      3.0     4       3       0101
5565614e71bSYork Sun 	 *      3.5     5               0110
5575614e71bSYork Sun 	 *      4.0             4       0111
5585614e71bSYork Sun 	 *      4.5                     1000
5595614e71bSYork Sun 	 *      5.0             5       1001
5605614e71bSYork Sun 	 */
5615614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
5625614e71bSYork Sun 	caslat_ctrl = (cas_latency + 1) & 0x07;
5635614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
5645614e71bSYork Sun 	caslat_ctrl = 2 * cas_latency - 1;
5655614e71bSYork Sun #else
5665614e71bSYork Sun 	/*
5675614e71bSYork Sun 	 * if the CAS latency more than 8 cycle,
5685614e71bSYork Sun 	 * we need set extend bit for it at
5695614e71bSYork Sun 	 * TIMING_CFG_3[EXT_CASLAT]
5705614e71bSYork Sun 	 */
57166869f95SYork Sun 	if (fsl_ddr_get_version(ctrl_num) <= 0x40400)
5725614e71bSYork Sun 		caslat_ctrl = 2 * cas_latency - 1;
57334e026f9SYork Sun 	else
57434e026f9SYork Sun 		caslat_ctrl = (cas_latency - 1) << 1;
5755614e71bSYork Sun #endif
5765614e71bSYork Sun 
57734e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
57803e664d8SYork Sun 	refrec_ctrl = picos_to_mclk(ctrl_num, common_dimm->trfc1_ps) - 8;
57903e664d8SYork Sun 	wrrec_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
58003e664d8SYork Sun 	acttoact_mclk = max(picos_to_mclk(ctrl_num, common_dimm->trrds_ps), 4U);
58103e664d8SYork Sun 	wrtord_mclk = max(2U, picos_to_mclk(ctrl_num, 2500));
582349689b8SYork Sun 	if ((wrrec_mclk < 1) || (wrrec_mclk > 24))
583349689b8SYork Sun 		printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
58434e026f9SYork Sun 	else
58534e026f9SYork Sun 		wrrec_mclk = wrrec_table[wrrec_mclk - 1];
58634e026f9SYork Sun #else
58703e664d8SYork Sun 	refrec_ctrl = picos_to_mclk(ctrl_num, common_dimm->trfc_ps) - 8;
58803e664d8SYork Sun 	wrrec_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
58903e664d8SYork Sun 	acttoact_mclk = picos_to_mclk(ctrl_num, common_dimm->trrd_ps);
59003e664d8SYork Sun 	wrtord_mclk = picos_to_mclk(ctrl_num, common_dimm->twtr_ps);
591349689b8SYork Sun 	if ((wrrec_mclk < 1) || (wrrec_mclk > 16))
592349689b8SYork Sun 		printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
5935614e71bSYork Sun 	else
5945614e71bSYork Sun 		wrrec_mclk = wrrec_table[wrrec_mclk - 1];
59534e026f9SYork Sun #endif
5965614e71bSYork Sun 	if (popts->otf_burst_chop_en)
5975614e71bSYork Sun 		wrrec_mclk += 2;
5985614e71bSYork Sun 
5995614e71bSYork Sun 	/*
6005614e71bSYork Sun 	 * JEDEC has min requirement for tRRD
6015614e71bSYork Sun 	 */
6025614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR3)
6035614e71bSYork Sun 	if (acttoact_mclk < 4)
6045614e71bSYork Sun 		acttoact_mclk = 4;
6055614e71bSYork Sun #endif
6065614e71bSYork Sun 	/*
6075614e71bSYork Sun 	 * JEDEC has some min requirements for tWTR
6085614e71bSYork Sun 	 */
6095614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR2)
6105614e71bSYork Sun 	if (wrtord_mclk < 2)
6115614e71bSYork Sun 		wrtord_mclk = 2;
6125614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
6135614e71bSYork Sun 	if (wrtord_mclk < 4)
6145614e71bSYork Sun 		wrtord_mclk = 4;
6155614e71bSYork Sun #endif
6165614e71bSYork Sun 	if (popts->otf_burst_chop_en)
6175614e71bSYork Sun 		wrtord_mclk += 2;
6185614e71bSYork Sun 
6195614e71bSYork Sun 	ddr->timing_cfg_1 = (0
6205614e71bSYork Sun 		| ((pretoact_mclk & 0x0F) << 28)
6215614e71bSYork Sun 		| ((acttopre_mclk & 0x0F) << 24)
6225614e71bSYork Sun 		| ((acttorw_mclk & 0xF) << 20)
6235614e71bSYork Sun 		| ((caslat_ctrl & 0xF) << 16)
6245614e71bSYork Sun 		| ((refrec_ctrl & 0xF) << 12)
6255614e71bSYork Sun 		| ((wrrec_mclk & 0x0F) << 8)
6265614e71bSYork Sun 		| ((acttoact_mclk & 0x0F) << 4)
6275614e71bSYork Sun 		| ((wrtord_mclk & 0x0F) << 0)
6285614e71bSYork Sun 		);
6295614e71bSYork Sun 	debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1);
6305614e71bSYork Sun }
6315614e71bSYork Sun 
6325614e71bSYork Sun /* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */
63303e664d8SYork Sun static void set_timing_cfg_2(const unsigned int ctrl_num,
63403e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
6355614e71bSYork Sun 			     const memctl_options_t *popts,
6365614e71bSYork Sun 			     const common_timing_params_t *common_dimm,
6375614e71bSYork Sun 			     unsigned int cas_latency,
6385614e71bSYork Sun 			     unsigned int additive_latency)
6395614e71bSYork Sun {
6405614e71bSYork Sun 	/* Additive latency */
6415614e71bSYork Sun 	unsigned char add_lat_mclk;
6425614e71bSYork Sun 	/* CAS-to-preamble override */
6435614e71bSYork Sun 	unsigned short cpo;
6445614e71bSYork Sun 	/* Write latency */
6455614e71bSYork Sun 	unsigned char wr_lat;
6465614e71bSYork Sun 	/*  Read to precharge (tRTP) */
6475614e71bSYork Sun 	unsigned char rd_to_pre;
6485614e71bSYork Sun 	/* Write command to write data strobe timing adjustment */
6495614e71bSYork Sun 	unsigned char wr_data_delay;
6505614e71bSYork Sun 	/* Minimum CKE pulse width (tCKE) */
6515614e71bSYork Sun 	unsigned char cke_pls;
6525614e71bSYork Sun 	/* Window for four activates (tFAW) */
6535614e71bSYork Sun 	unsigned short four_act;
654bb578322SYork Sun #ifdef CONFIG_SYS_FSL_DDR3
65503e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
656bb578322SYork Sun #endif
6575614e71bSYork Sun 
6585614e71bSYork Sun 	/* FIXME add check that this must be less than acttorw_mclk */
6595614e71bSYork Sun 	add_lat_mclk = additive_latency;
6605614e71bSYork Sun 	cpo = popts->cpo_override;
6615614e71bSYork Sun 
6625614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
6635614e71bSYork Sun 	/*
6645614e71bSYork Sun 	 * This is a lie.  It should really be 1, but if it is
6655614e71bSYork Sun 	 * set to 1, bits overlap into the old controller's
6665614e71bSYork Sun 	 * otherwise unused ACSM field.  If we leave it 0, then
6675614e71bSYork Sun 	 * the HW will magically treat it as 1 for DDR 1.  Oh Yea.
6685614e71bSYork Sun 	 */
6695614e71bSYork Sun 	wr_lat = 0;
6705614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
6715614e71bSYork Sun 	wr_lat = cas_latency - 1;
6725614e71bSYork Sun #else
67303e664d8SYork Sun 	wr_lat = compute_cas_write_latency(ctrl_num);
6745614e71bSYork Sun #endif
6755614e71bSYork Sun 
67634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
67703e664d8SYork Sun 	rd_to_pre = picos_to_mclk(ctrl_num, 7500);
67834e026f9SYork Sun #else
67903e664d8SYork Sun 	rd_to_pre = picos_to_mclk(ctrl_num, common_dimm->trtp_ps);
68034e026f9SYork Sun #endif
6815614e71bSYork Sun 	/*
6825614e71bSYork Sun 	 * JEDEC has some min requirements for tRTP
6835614e71bSYork Sun 	 */
6845614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR2)
6855614e71bSYork Sun 	if (rd_to_pre  < 2)
6865614e71bSYork Sun 		rd_to_pre  = 2;
68734e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
6885614e71bSYork Sun 	if (rd_to_pre < 4)
6895614e71bSYork Sun 		rd_to_pre = 4;
6905614e71bSYork Sun #endif
6915614e71bSYork Sun 	if (popts->otf_burst_chop_en)
6925614e71bSYork Sun 		rd_to_pre += 2; /* according to UM */
6935614e71bSYork Sun 
6945614e71bSYork Sun 	wr_data_delay = popts->write_data_delay;
69534e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
69634e026f9SYork Sun 	cpo = 0;
69703e664d8SYork Sun 	cke_pls = max(3U, picos_to_mclk(ctrl_num, 5000));
698bb578322SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
699bb578322SYork Sun 	/*
700bb578322SYork Sun 	 * cke pulse = max(3nCK, 7.5ns) for DDR3-800
701bb578322SYork Sun 	 *             max(3nCK, 5.625ns) for DDR3-1066, 1333
702bb578322SYork Sun 	 *             max(3nCK, 5ns) for DDR3-1600, 1866, 2133
703bb578322SYork Sun 	 */
70403e664d8SYork Sun 	cke_pls = max(3U, picos_to_mclk(ctrl_num, mclk_ps > 1870 ? 7500 :
705bb578322SYork Sun 					(mclk_ps > 1245 ? 5625 : 5000)));
70634e026f9SYork Sun #else
707bb578322SYork Sun 	cke_pls = FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR;
70834e026f9SYork Sun #endif
70903e664d8SYork Sun 	four_act = picos_to_mclk(ctrl_num,
71003e664d8SYork Sun 				 popts->tfaw_window_four_activates_ps);
7115614e71bSYork Sun 
7125614e71bSYork Sun 	ddr->timing_cfg_2 = (0
7135614e71bSYork Sun 		| ((add_lat_mclk & 0xf) << 28)
7145614e71bSYork Sun 		| ((cpo & 0x1f) << 23)
7155614e71bSYork Sun 		| ((wr_lat & 0xf) << 19)
7168936691bSYork Sun 		| (((wr_lat & 0x10) >> 4) << 18)
7175614e71bSYork Sun 		| ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT)
7185614e71bSYork Sun 		| ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT)
7195614e71bSYork Sun 		| ((cke_pls & 0x7) << 6)
7205614e71bSYork Sun 		| ((four_act & 0x3f) << 0)
7215614e71bSYork Sun 		);
7225614e71bSYork Sun 	debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2);
7235614e71bSYork Sun }
7245614e71bSYork Sun 
7255614e71bSYork Sun /* DDR SDRAM Register Control Word */
7265614e71bSYork Sun static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
7275614e71bSYork Sun 			       const memctl_options_t *popts,
7285614e71bSYork Sun 			       const common_timing_params_t *common_dimm)
7295614e71bSYork Sun {
7305614e71bSYork Sun 	if (common_dimm->all_dimms_registered &&
7315614e71bSYork Sun 	    !common_dimm->all_dimms_unbuffered)	{
7325614e71bSYork Sun 		if (popts->rcw_override) {
7335614e71bSYork Sun 			ddr->ddr_sdram_rcw_1 = popts->rcw_1;
7345614e71bSYork Sun 			ddr->ddr_sdram_rcw_2 = popts->rcw_2;
735*426230a6SYork Sun 			ddr->ddr_sdram_rcw_3 = popts->rcw_3;
7365614e71bSYork Sun 		} else {
7375614e71bSYork Sun 			ddr->ddr_sdram_rcw_1 =
7385614e71bSYork Sun 				common_dimm->rcw[0] << 28 | \
7395614e71bSYork Sun 				common_dimm->rcw[1] << 24 | \
7405614e71bSYork Sun 				common_dimm->rcw[2] << 20 | \
7415614e71bSYork Sun 				common_dimm->rcw[3] << 16 | \
7425614e71bSYork Sun 				common_dimm->rcw[4] << 12 | \
7435614e71bSYork Sun 				common_dimm->rcw[5] << 8 | \
7445614e71bSYork Sun 				common_dimm->rcw[6] << 4 | \
7455614e71bSYork Sun 				common_dimm->rcw[7];
7465614e71bSYork Sun 			ddr->ddr_sdram_rcw_2 =
7475614e71bSYork Sun 				common_dimm->rcw[8] << 28 | \
7485614e71bSYork Sun 				common_dimm->rcw[9] << 24 | \
7495614e71bSYork Sun 				common_dimm->rcw[10] << 20 | \
7505614e71bSYork Sun 				common_dimm->rcw[11] << 16 | \
7515614e71bSYork Sun 				common_dimm->rcw[12] << 12 | \
7525614e71bSYork Sun 				common_dimm->rcw[13] << 8 | \
7535614e71bSYork Sun 				common_dimm->rcw[14] << 4 | \
7545614e71bSYork Sun 				common_dimm->rcw[15];
7555614e71bSYork Sun 		}
756*426230a6SYork Sun 		debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n",
757*426230a6SYork Sun 		      ddr->ddr_sdram_rcw_1);
758*426230a6SYork Sun 		debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n",
759*426230a6SYork Sun 		      ddr->ddr_sdram_rcw_2);
760*426230a6SYork Sun 		debug("FSLDDR: ddr_sdram_rcw_3 = 0x%08x\n",
761*426230a6SYork Sun 		      ddr->ddr_sdram_rcw_3);
7625614e71bSYork Sun 	}
7635614e71bSYork Sun }
7645614e71bSYork Sun 
7655614e71bSYork Sun /* DDR SDRAM control configuration (DDR_SDRAM_CFG) */
7665614e71bSYork Sun static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
7675614e71bSYork Sun 			       const memctl_options_t *popts,
7685614e71bSYork Sun 			       const common_timing_params_t *common_dimm)
7695614e71bSYork Sun {
7705614e71bSYork Sun 	unsigned int mem_en;		/* DDR SDRAM interface logic enable */
7715614e71bSYork Sun 	unsigned int sren;		/* Self refresh enable (during sleep) */
7725614e71bSYork Sun 	unsigned int ecc_en;		/* ECC enable. */
7735614e71bSYork Sun 	unsigned int rd_en;		/* Registered DIMM enable */
7745614e71bSYork Sun 	unsigned int sdram_type;	/* Type of SDRAM */
7755614e71bSYork Sun 	unsigned int dyn_pwr;		/* Dynamic power management mode */
7765614e71bSYork Sun 	unsigned int dbw;		/* DRAM dta bus width */
7775614e71bSYork Sun 	unsigned int eight_be = 0;	/* 8-beat burst enable, DDR2 is zero */
7785614e71bSYork Sun 	unsigned int ncap = 0;		/* Non-concurrent auto-precharge */
7795614e71bSYork Sun 	unsigned int threet_en;		/* Enable 3T timing */
7805614e71bSYork Sun 	unsigned int twot_en;		/* Enable 2T timing */
7815614e71bSYork Sun 	unsigned int ba_intlv_ctl;	/* Bank (CS) interleaving control */
7825614e71bSYork Sun 	unsigned int x32_en = 0;	/* x32 enable */
7835614e71bSYork Sun 	unsigned int pchb8 = 0;		/* precharge bit 8 enable */
7845614e71bSYork Sun 	unsigned int hse;		/* Global half strength override */
785d28cb671SYork Sun 	unsigned int acc_ecc_en = 0;	/* Accumulated ECC enable */
7865614e71bSYork Sun 	unsigned int mem_halt = 0;	/* memory controller halt */
7875614e71bSYork Sun 	unsigned int bi = 0;		/* Bypass initialization */
7885614e71bSYork Sun 
7895614e71bSYork Sun 	mem_en = 1;
7905614e71bSYork Sun 	sren = popts->self_refresh_in_sleep;
7915614e71bSYork Sun 	if (common_dimm->all_dimms_ecc_capable) {
7925614e71bSYork Sun 		/* Allow setting of ECC only if all DIMMs are ECC. */
7935614e71bSYork Sun 		ecc_en = popts->ecc_mode;
7945614e71bSYork Sun 	} else {
7955614e71bSYork Sun 		ecc_en = 0;
7965614e71bSYork Sun 	}
7975614e71bSYork Sun 
7985614e71bSYork Sun 	if (common_dimm->all_dimms_registered &&
7995614e71bSYork Sun 	    !common_dimm->all_dimms_unbuffered)	{
8005614e71bSYork Sun 		rd_en = 1;
8015614e71bSYork Sun 		twot_en = 0;
8025614e71bSYork Sun 	} else {
8035614e71bSYork Sun 		rd_en = 0;
8045614e71bSYork Sun 		twot_en = popts->twot_en;
8055614e71bSYork Sun 	}
8065614e71bSYork Sun 
8075614e71bSYork Sun 	sdram_type = CONFIG_FSL_SDRAM_TYPE;
8085614e71bSYork Sun 
8095614e71bSYork Sun 	dyn_pwr = popts->dynamic_power;
8105614e71bSYork Sun 	dbw = popts->data_bus_width;
8115614e71bSYork Sun 	/* 8-beat burst enable DDR-III case
8125614e71bSYork Sun 	 * we must clear it when use the on-the-fly mode,
8135614e71bSYork Sun 	 * must set it when use the 32-bits bus mode.
8145614e71bSYork Sun 	 */
81534e026f9SYork Sun 	if ((sdram_type == SDRAM_TYPE_DDR3) ||
81634e026f9SYork Sun 	    (sdram_type == SDRAM_TYPE_DDR4)) {
8175614e71bSYork Sun 		if (popts->burst_length == DDR_BL8)
8185614e71bSYork Sun 			eight_be = 1;
8195614e71bSYork Sun 		if (popts->burst_length == DDR_OTF)
8205614e71bSYork Sun 			eight_be = 0;
8215614e71bSYork Sun 		if (dbw == 0x1)
8225614e71bSYork Sun 			eight_be = 1;
8235614e71bSYork Sun 	}
8245614e71bSYork Sun 
8255614e71bSYork Sun 	threet_en = popts->threet_en;
8265614e71bSYork Sun 	ba_intlv_ctl = popts->ba_intlv_ctl;
8275614e71bSYork Sun 	hse = popts->half_strength_driver_enable;
8285614e71bSYork Sun 
829d28cb671SYork Sun 	/* set when ddr bus width < 64 */
830d28cb671SYork Sun 	acc_ecc_en = (dbw != 0 && ecc_en == 1) ? 1 : 0;
831d28cb671SYork Sun 
8325614e71bSYork Sun 	ddr->ddr_sdram_cfg = (0
8335614e71bSYork Sun 			| ((mem_en & 0x1) << 31)
8345614e71bSYork Sun 			| ((sren & 0x1) << 30)
8355614e71bSYork Sun 			| ((ecc_en & 0x1) << 29)
8365614e71bSYork Sun 			| ((rd_en & 0x1) << 28)
8375614e71bSYork Sun 			| ((sdram_type & 0x7) << 24)
8385614e71bSYork Sun 			| ((dyn_pwr & 0x1) << 21)
8395614e71bSYork Sun 			| ((dbw & 0x3) << 19)
8405614e71bSYork Sun 			| ((eight_be & 0x1) << 18)
8415614e71bSYork Sun 			| ((ncap & 0x1) << 17)
8425614e71bSYork Sun 			| ((threet_en & 0x1) << 16)
8435614e71bSYork Sun 			| ((twot_en & 0x1) << 15)
8445614e71bSYork Sun 			| ((ba_intlv_ctl & 0x7F) << 8)
8455614e71bSYork Sun 			| ((x32_en & 0x1) << 5)
8465614e71bSYork Sun 			| ((pchb8 & 0x1) << 4)
8475614e71bSYork Sun 			| ((hse & 0x1) << 3)
848d28cb671SYork Sun 			| ((acc_ecc_en & 0x1) << 2)
8495614e71bSYork Sun 			| ((mem_halt & 0x1) << 1)
8505614e71bSYork Sun 			| ((bi & 0x1) << 0)
8515614e71bSYork Sun 			);
8525614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_cfg = 0x%08x\n", ddr->ddr_sdram_cfg);
8535614e71bSYork Sun }
8545614e71bSYork Sun 
8555614e71bSYork Sun /* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */
85603e664d8SYork Sun static void set_ddr_sdram_cfg_2(const unsigned int ctrl_num,
85703e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
8585614e71bSYork Sun 			       const memctl_options_t *popts,
8595614e71bSYork Sun 			       const unsigned int unq_mrs_en)
8605614e71bSYork Sun {
8615614e71bSYork Sun 	unsigned int frc_sr = 0;	/* Force self refresh */
8625614e71bSYork Sun 	unsigned int sr_ie = 0;		/* Self-refresh interrupt enable */
8635614e71bSYork Sun 	unsigned int odt_cfg = 0;	/* ODT configuration */
8645614e71bSYork Sun 	unsigned int num_pr;		/* Number of posted refreshes */
8655614e71bSYork Sun 	unsigned int slow = 0;		/* DDR will be run less than 1250 */
8665614e71bSYork Sun 	unsigned int x4_en = 0;		/* x4 DRAM enable */
8675614e71bSYork Sun 	unsigned int obc_cfg;		/* On-The-Fly Burst Chop Cfg */
8685614e71bSYork Sun 	unsigned int ap_en;		/* Address Parity Enable */
8695614e71bSYork Sun 	unsigned int d_init;		/* DRAM data initialization */
8705614e71bSYork Sun 	unsigned int rcw_en = 0;	/* Register Control Word Enable */
8715614e71bSYork Sun 	unsigned int md_en = 0;		/* Mirrored DIMM Enable */
8725614e71bSYork Sun 	unsigned int qd_en = 0;		/* quad-rank DIMM Enable */
8735614e71bSYork Sun 	int i;
87434e026f9SYork Sun #ifndef CONFIG_SYS_FSL_DDR4
87534e026f9SYork Sun 	unsigned int dll_rst_dis = 1;	/* DLL reset disable */
87634e026f9SYork Sun 	unsigned int dqs_cfg;		/* DQS configuration */
8775614e71bSYork Sun 
8785614e71bSYork Sun 	dqs_cfg = popts->dqs_config;
87934e026f9SYork Sun #endif
8805614e71bSYork Sun 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
8815614e71bSYork Sun 		if (popts->cs_local_opts[i].odt_rd_cfg
8825614e71bSYork Sun 			|| popts->cs_local_opts[i].odt_wr_cfg) {
8835614e71bSYork Sun 			odt_cfg = SDRAM_CFG2_ODT_ONLY_READ;
8845614e71bSYork Sun 			break;
8855614e71bSYork Sun 		}
8865614e71bSYork Sun 	}
887e368c206SJoakim Tjernlund 	sr_ie = popts->self_refresh_interrupt_en;
8885614e71bSYork Sun 	num_pr = 1;	/* Make this configurable */
8895614e71bSYork Sun 
8905614e71bSYork Sun 	/*
8915614e71bSYork Sun 	 * 8572 manual says
8925614e71bSYork Sun 	 *     {TIMING_CFG_1[PRETOACT]
8935614e71bSYork Sun 	 *      + [DDR_SDRAM_CFG_2[NUM_PR]
8945614e71bSYork Sun 	 *        * ({EXT_REFREC || REFREC} + 8 + 2)]}
8955614e71bSYork Sun 	 *      << DDR_SDRAM_INTERVAL[REFINT]
8965614e71bSYork Sun 	 */
89734e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
8985614e71bSYork Sun 	obc_cfg = popts->otf_burst_chop_en;
8995614e71bSYork Sun #else
9005614e71bSYork Sun 	obc_cfg = 0;
9015614e71bSYork Sun #endif
9025614e71bSYork Sun 
9035614e71bSYork Sun #if (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7)
90403e664d8SYork Sun 	slow = get_ddr_freq(ctrl_num) < 1249000000;
9055614e71bSYork Sun #endif
9065614e71bSYork Sun 
907eb118807SShengzhou Liu 	if (popts->registered_dimm_en)
9085614e71bSYork Sun 		rcw_en = 1;
909eb118807SShengzhou Liu 
910eb118807SShengzhou Liu 	/* DDR4 can have address parity for UDIMM and discrete */
911eb118807SShengzhou Liu 	if ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) &&
912eb118807SShengzhou Liu 	    (!popts->registered_dimm_en)) {
9135614e71bSYork Sun 		ap_en = 0;
914eb118807SShengzhou Liu 	} else {
915eb118807SShengzhou Liu 		ap_en = popts->ap_en;
9165614e71bSYork Sun 	}
9175614e71bSYork Sun 
9185614e71bSYork Sun 	x4_en = popts->x4_en ? 1 : 0;
9195614e71bSYork Sun 
9205614e71bSYork Sun #if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
9215614e71bSYork Sun 	/* Use the DDR controller to auto initialize memory. */
9225614e71bSYork Sun 	d_init = popts->ecc_init_using_memctl;
9235614e71bSYork Sun 	ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE;
9245614e71bSYork Sun 	debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init);
9255614e71bSYork Sun #else
9265614e71bSYork Sun 	/* Memory will be initialized via DMA, or not at all. */
9275614e71bSYork Sun 	d_init = 0;
9285614e71bSYork Sun #endif
9295614e71bSYork Sun 
93034e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
9315614e71bSYork Sun 	md_en = popts->mirrored_dimm;
9325614e71bSYork Sun #endif
9335614e71bSYork Sun 	qd_en = popts->quad_rank_present ? 1 : 0;
9345614e71bSYork Sun 	ddr->ddr_sdram_cfg_2 = (0
9355614e71bSYork Sun 		| ((frc_sr & 0x1) << 31)
9365614e71bSYork Sun 		| ((sr_ie & 0x1) << 30)
93734e026f9SYork Sun #ifndef CONFIG_SYS_FSL_DDR4
9385614e71bSYork Sun 		| ((dll_rst_dis & 0x1) << 29)
9395614e71bSYork Sun 		| ((dqs_cfg & 0x3) << 26)
94034e026f9SYork Sun #endif
9415614e71bSYork Sun 		| ((odt_cfg & 0x3) << 21)
9425614e71bSYork Sun 		| ((num_pr & 0xf) << 12)
9435614e71bSYork Sun 		| ((slow & 1) << 11)
9445614e71bSYork Sun 		| (x4_en << 10)
9455614e71bSYork Sun 		| (qd_en << 9)
9465614e71bSYork Sun 		| (unq_mrs_en << 8)
9475614e71bSYork Sun 		| ((obc_cfg & 0x1) << 6)
9485614e71bSYork Sun 		| ((ap_en & 0x1) << 5)
9495614e71bSYork Sun 		| ((d_init & 0x1) << 4)
9505614e71bSYork Sun 		| ((rcw_en & 0x1) << 2)
9515614e71bSYork Sun 		| ((md_en & 0x1) << 0)
9525614e71bSYork Sun 		);
9535614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2);
9545614e71bSYork Sun }
9555614e71bSYork Sun 
95634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
9575614e71bSYork Sun /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
95803e664d8SYork Sun static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
95903e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
9605614e71bSYork Sun 				const memctl_options_t *popts,
9615614e71bSYork Sun 				const common_timing_params_t *common_dimm,
9625614e71bSYork Sun 				const unsigned int unq_mrs_en)
9635614e71bSYork Sun {
9645614e71bSYork Sun 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
9655614e71bSYork Sun 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
9665614e71bSYork Sun 	int i;
96734e026f9SYork Sun 	unsigned int wr_crc = 0;	/* Disable */
9685614e71bSYork Sun 	unsigned int rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
9695614e71bSYork Sun 	unsigned int srt = 0;	/* self-refresh temerature, normal range */
97003e664d8SYork Sun 	unsigned int cwl = compute_cas_write_latency(ctrl_num) - 9;
97134e026f9SYork Sun 	unsigned int mpr = 0;	/* serial */
97234e026f9SYork Sun 	unsigned int wc_lat;
97303e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
9745614e71bSYork Sun 
9755614e71bSYork Sun 	if (popts->rtt_override)
9765614e71bSYork Sun 		rtt_wr = popts->rtt_wr_override_value;
9775614e71bSYork Sun 	else
9785614e71bSYork Sun 		rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
9795614e71bSYork Sun 
9805614e71bSYork Sun 	if (common_dimm->extended_op_srt)
9815614e71bSYork Sun 		srt = common_dimm->extended_op_srt;
9825614e71bSYork Sun 
9835614e71bSYork Sun 	esdmode2 = (0
98434e026f9SYork Sun 		| ((wr_crc & 0x1) << 12)
9855614e71bSYork Sun 		| ((rtt_wr & 0x3) << 9)
98634e026f9SYork Sun 		| ((srt & 0x3) << 6)
98734e026f9SYork Sun 		| ((cwl & 0x7) << 3));
98834e026f9SYork Sun 
98934e026f9SYork Sun 	if (mclk_ps >= 1250)
99034e026f9SYork Sun 		wc_lat = 0;
99134e026f9SYork Sun 	else if (mclk_ps >= 833)
99234e026f9SYork Sun 		wc_lat = 1;
99334e026f9SYork Sun 	else
99434e026f9SYork Sun 		wc_lat = 2;
99534e026f9SYork Sun 
99634e026f9SYork Sun 	esdmode3 = (0
99734e026f9SYork Sun 		| ((mpr & 0x3) << 11)
99834e026f9SYork Sun 		| ((wc_lat & 0x3) << 9));
99934e026f9SYork Sun 
10005614e71bSYork Sun 	ddr->ddr_sdram_mode_2 = (0
10015614e71bSYork Sun 				 | ((esdmode2 & 0xFFFF) << 16)
10025614e71bSYork Sun 				 | ((esdmode3 & 0xFFFF) << 0)
10035614e71bSYork Sun 				 );
10045614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
10055614e71bSYork Sun 
10065614e71bSYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
10075614e71bSYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
10085614e71bSYork Sun 			if (popts->rtt_override)
10095614e71bSYork Sun 				rtt_wr = popts->rtt_wr_override_value;
10105614e71bSYork Sun 			else
10115614e71bSYork Sun 				rtt_wr = popts->cs_local_opts[i].odt_rtt_wr;
10125614e71bSYork Sun 
10135614e71bSYork Sun 			esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
10145614e71bSYork Sun 			esdmode2 |= (rtt_wr & 0x3) << 9;
10155614e71bSYork Sun 			switch (i) {
10165614e71bSYork Sun 			case 1:
10175614e71bSYork Sun 				ddr->ddr_sdram_mode_4 = (0
10185614e71bSYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
10195614e71bSYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
10205614e71bSYork Sun 					);
10215614e71bSYork Sun 				break;
10225614e71bSYork Sun 			case 2:
10235614e71bSYork Sun 				ddr->ddr_sdram_mode_6 = (0
10245614e71bSYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
10255614e71bSYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
10265614e71bSYork Sun 					);
10275614e71bSYork Sun 				break;
10285614e71bSYork Sun 			case 3:
10295614e71bSYork Sun 				ddr->ddr_sdram_mode_8 = (0
10305614e71bSYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
10315614e71bSYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
10325614e71bSYork Sun 					);
10335614e71bSYork Sun 				break;
10345614e71bSYork Sun 			}
10355614e71bSYork Sun 		}
10365614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
10375614e71bSYork Sun 		      ddr->ddr_sdram_mode_4);
10385614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
10395614e71bSYork Sun 		      ddr->ddr_sdram_mode_6);
10405614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
10415614e71bSYork Sun 		      ddr->ddr_sdram_mode_8);
10425614e71bSYork Sun 	}
10435614e71bSYork Sun }
104434e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
104534e026f9SYork Sun /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
104603e664d8SYork Sun static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
104703e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
104834e026f9SYork Sun 				const memctl_options_t *popts,
104934e026f9SYork Sun 				const common_timing_params_t *common_dimm,
105034e026f9SYork Sun 				const unsigned int unq_mrs_en)
105134e026f9SYork Sun {
105234e026f9SYork Sun 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
105334e026f9SYork Sun 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
105434e026f9SYork Sun 	int i;
105534e026f9SYork Sun 	unsigned int rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
105634e026f9SYork Sun 	unsigned int srt = 0;	/* self-refresh temerature, normal range */
105734e026f9SYork Sun 	unsigned int asr = 0;	/* auto self-refresh disable */
105803e664d8SYork Sun 	unsigned int cwl = compute_cas_write_latency(ctrl_num) - 5;
105934e026f9SYork Sun 	unsigned int pasr = 0;	/* partial array self refresh disable */
106034e026f9SYork Sun 
106134e026f9SYork Sun 	if (popts->rtt_override)
106234e026f9SYork Sun 		rtt_wr = popts->rtt_wr_override_value;
106334e026f9SYork Sun 	else
106434e026f9SYork Sun 		rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
106534e026f9SYork Sun 
106634e026f9SYork Sun 	if (common_dimm->extended_op_srt)
106734e026f9SYork Sun 		srt = common_dimm->extended_op_srt;
106834e026f9SYork Sun 
106934e026f9SYork Sun 	esdmode2 = (0
107034e026f9SYork Sun 		| ((rtt_wr & 0x3) << 9)
107134e026f9SYork Sun 		| ((srt & 0x1) << 7)
107234e026f9SYork Sun 		| ((asr & 0x1) << 6)
107334e026f9SYork Sun 		| ((cwl & 0x7) << 3)
107434e026f9SYork Sun 		| ((pasr & 0x7) << 0));
107534e026f9SYork Sun 	ddr->ddr_sdram_mode_2 = (0
107634e026f9SYork Sun 				 | ((esdmode2 & 0xFFFF) << 16)
107734e026f9SYork Sun 				 | ((esdmode3 & 0xFFFF) << 0)
107834e026f9SYork Sun 				 );
107934e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
108034e026f9SYork Sun 
108134e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
108234e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
108334e026f9SYork Sun 			if (popts->rtt_override)
108434e026f9SYork Sun 				rtt_wr = popts->rtt_wr_override_value;
108534e026f9SYork Sun 			else
108634e026f9SYork Sun 				rtt_wr = popts->cs_local_opts[i].odt_rtt_wr;
108734e026f9SYork Sun 
108834e026f9SYork Sun 			esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
108934e026f9SYork Sun 			esdmode2 |= (rtt_wr & 0x3) << 9;
109034e026f9SYork Sun 			switch (i) {
109134e026f9SYork Sun 			case 1:
109234e026f9SYork Sun 				ddr->ddr_sdram_mode_4 = (0
109334e026f9SYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
109434e026f9SYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
109534e026f9SYork Sun 					);
109634e026f9SYork Sun 				break;
109734e026f9SYork Sun 			case 2:
109834e026f9SYork Sun 				ddr->ddr_sdram_mode_6 = (0
109934e026f9SYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
110034e026f9SYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
110134e026f9SYork Sun 					);
110234e026f9SYork Sun 				break;
110334e026f9SYork Sun 			case 3:
110434e026f9SYork Sun 				ddr->ddr_sdram_mode_8 = (0
110534e026f9SYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
110634e026f9SYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
110734e026f9SYork Sun 					);
110834e026f9SYork Sun 				break;
110934e026f9SYork Sun 			}
111034e026f9SYork Sun 		}
111134e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
111234e026f9SYork Sun 			ddr->ddr_sdram_mode_4);
111334e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
111434e026f9SYork Sun 			ddr->ddr_sdram_mode_6);
111534e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
111634e026f9SYork Sun 			ddr->ddr_sdram_mode_8);
111734e026f9SYork Sun 	}
111834e026f9SYork Sun }
111934e026f9SYork Sun 
112034e026f9SYork Sun #else /* for DDR2 and DDR1 */
112134e026f9SYork Sun /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
112203e664d8SYork Sun static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
112303e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
112434e026f9SYork Sun 				const memctl_options_t *popts,
112534e026f9SYork Sun 				const common_timing_params_t *common_dimm,
112634e026f9SYork Sun 				const unsigned int unq_mrs_en)
112734e026f9SYork Sun {
112834e026f9SYork Sun 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
112934e026f9SYork Sun 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
113034e026f9SYork Sun 
113134e026f9SYork Sun 	ddr->ddr_sdram_mode_2 = (0
113234e026f9SYork Sun 				 | ((esdmode2 & 0xFFFF) << 16)
113334e026f9SYork Sun 				 | ((esdmode3 & 0xFFFF) << 0)
113434e026f9SYork Sun 				 );
113534e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
113634e026f9SYork Sun }
113734e026f9SYork Sun #endif
113834e026f9SYork Sun 
113934e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
114034e026f9SYork Sun /* DDR SDRAM Mode configuration 9 (DDR_SDRAM_MODE_9) */
114134e026f9SYork Sun static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
114234e026f9SYork Sun 				const memctl_options_t *popts,
114334e026f9SYork Sun 				const common_timing_params_t *common_dimm,
114434e026f9SYork Sun 				const unsigned int unq_mrs_en)
114534e026f9SYork Sun {
114634e026f9SYork Sun 	int i;
114734e026f9SYork Sun 	unsigned short esdmode4 = 0;	/* Extended SDRAM mode 4 */
114834e026f9SYork Sun 	unsigned short esdmode5;	/* Extended SDRAM mode 5 */
11496b95be22SYork Sun 	int rtt_park = 0;
11508a51429eSYork Sun 	bool four_cs = false;
1151eb118807SShengzhou Liu 	const unsigned int mclk_ps = get_memory_clk_period_ps(0);
115234e026f9SYork Sun 
11538a51429eSYork Sun #if CONFIG_CHIP_SELECTS_PER_CTRL == 4
11548a51429eSYork Sun 	if ((ddr->cs[0].config & SDRAM_CS_CONFIG_EN) &&
11558a51429eSYork Sun 	    (ddr->cs[1].config & SDRAM_CS_CONFIG_EN) &&
11568a51429eSYork Sun 	    (ddr->cs[2].config & SDRAM_CS_CONFIG_EN) &&
11578a51429eSYork Sun 	    (ddr->cs[3].config & SDRAM_CS_CONFIG_EN))
11588a51429eSYork Sun 		four_cs = true;
11598a51429eSYork Sun #endif
11606b95be22SYork Sun 	if (ddr->cs[0].config & SDRAM_CS_CONFIG_EN) {
11616b95be22SYork Sun 		esdmode5 = 0x00000500;	/* Data mask enable, RTT_PARK CS0 */
11628a51429eSYork Sun 		rtt_park = four_cs ? 0 : 1;
11636b95be22SYork Sun 	} else {
11646b95be22SYork Sun 		esdmode5 = 0x00000400;	/* Data mask enabled */
11656b95be22SYork Sun 	}
116634e026f9SYork Sun 
1167*426230a6SYork Sun 	/*
1168*426230a6SYork Sun 	 * For DDR3, set C/A latency if address parity is enabled.
1169*426230a6SYork Sun 	 * For DDR4, set C/A latency for UDIMM only. For RDIMM the delay is
1170*426230a6SYork Sun 	 * handled by register chip and RCW settings.
1171*426230a6SYork Sun 	 */
1172*426230a6SYork Sun 	if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) &&
1173*426230a6SYork Sun 	    ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) ||
1174*426230a6SYork Sun 	     !popts->registered_dimm_en)) {
1175eb118807SShengzhou Liu 		if (mclk_ps >= 935) {
1176eb118807SShengzhou Liu 			/* for DDR4-1600/1866/2133 */
1177eb118807SShengzhou Liu 			esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK;
1178eb118807SShengzhou Liu 		} else if (mclk_ps >= 833) {
1179eb118807SShengzhou Liu 			/* for DDR4-2400 */
1180eb118807SShengzhou Liu 			esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK;
1181eb118807SShengzhou Liu 		} else {
1182eb118807SShengzhou Liu 			printf("parity: mclk_ps = %d not supported\n", mclk_ps);
1183eb118807SShengzhou Liu 		}
1184eb118807SShengzhou Liu 	}
1185eb118807SShengzhou Liu 
118634e026f9SYork Sun 	ddr->ddr_sdram_mode_9 = (0
118734e026f9SYork Sun 				 | ((esdmode4 & 0xffff) << 16)
118834e026f9SYork Sun 				 | ((esdmode5 & 0xffff) << 0)
118934e026f9SYork Sun 				);
119066869f95SYork Sun 
11918a51429eSYork Sun 	/* Normally only the first enabled CS use 0x500, others use 0x400
11928a51429eSYork Sun 	 * But when four chip-selects are all enabled, all mode registers
11938a51429eSYork Sun 	 * need 0x500 to park.
11948a51429eSYork Sun 	 */
119566869f95SYork Sun 
119634e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode_9) = 0x%08x\n", ddr->ddr_sdram_mode_9);
119734e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
119834e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
11996b95be22SYork Sun 			if (!rtt_park &&
12006b95be22SYork Sun 			    (ddr->cs[i].config & SDRAM_CS_CONFIG_EN)) {
12016b95be22SYork Sun 				esdmode5 |= 0x00000500;	/* RTT_PARK */
12028a51429eSYork Sun 				rtt_park = four_cs ? 0 : 1;
12036b95be22SYork Sun 			} else {
12046b95be22SYork Sun 				esdmode5 = 0x00000400;
12056b95be22SYork Sun 			}
1206eb118807SShengzhou Liu 
1207*426230a6SYork Sun 			if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) &&
1208*426230a6SYork Sun 			    ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) ||
1209*426230a6SYork Sun 			     !popts->registered_dimm_en)) {
1210eb118807SShengzhou Liu 				if (mclk_ps >= 935) {
1211eb118807SShengzhou Liu 					/* for DDR4-1600/1866/2133 */
1212eb118807SShengzhou Liu 					esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK;
1213eb118807SShengzhou Liu 				} else if (mclk_ps >= 833) {
1214eb118807SShengzhou Liu 					/* for DDR4-2400 */
1215eb118807SShengzhou Liu 					esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK;
1216eb118807SShengzhou Liu 				} else {
1217eb118807SShengzhou Liu 					printf("parity: mclk_ps = %d not supported\n",
1218eb118807SShengzhou Liu 					       mclk_ps);
1219eb118807SShengzhou Liu 				}
1220eb118807SShengzhou Liu 			}
1221eb118807SShengzhou Liu 
122234e026f9SYork Sun 			switch (i) {
122334e026f9SYork Sun 			case 1:
122434e026f9SYork Sun 				ddr->ddr_sdram_mode_11 = (0
122534e026f9SYork Sun 					| ((esdmode4 & 0xFFFF) << 16)
122634e026f9SYork Sun 					| ((esdmode5 & 0xFFFF) << 0)
122734e026f9SYork Sun 					);
122834e026f9SYork Sun 				break;
122934e026f9SYork Sun 			case 2:
123034e026f9SYork Sun 				ddr->ddr_sdram_mode_13 = (0
123134e026f9SYork Sun 					| ((esdmode4 & 0xFFFF) << 16)
123234e026f9SYork Sun 					| ((esdmode5 & 0xFFFF) << 0)
123334e026f9SYork Sun 					);
123434e026f9SYork Sun 				break;
123534e026f9SYork Sun 			case 3:
123634e026f9SYork Sun 				ddr->ddr_sdram_mode_15 = (0
123734e026f9SYork Sun 					| ((esdmode4 & 0xFFFF) << 16)
123834e026f9SYork Sun 					| ((esdmode5 & 0xFFFF) << 0)
123934e026f9SYork Sun 					);
124034e026f9SYork Sun 				break;
124134e026f9SYork Sun 			}
124234e026f9SYork Sun 		}
124334e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_11 = 0x%08x\n",
124434e026f9SYork Sun 		      ddr->ddr_sdram_mode_11);
124534e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_13 = 0x%08x\n",
124634e026f9SYork Sun 		      ddr->ddr_sdram_mode_13);
124734e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_15 = 0x%08x\n",
124834e026f9SYork Sun 		      ddr->ddr_sdram_mode_15);
124934e026f9SYork Sun 	}
125034e026f9SYork Sun }
125134e026f9SYork Sun 
125234e026f9SYork Sun /* DDR SDRAM Mode configuration 10 (DDR_SDRAM_MODE_10) */
125303e664d8SYork Sun static void set_ddr_sdram_mode_10(const unsigned int ctrl_num,
125403e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
125534e026f9SYork Sun 				const memctl_options_t *popts,
125634e026f9SYork Sun 				const common_timing_params_t *common_dimm,
125734e026f9SYork Sun 				const unsigned int unq_mrs_en)
125834e026f9SYork Sun {
125934e026f9SYork Sun 	int i;
126034e026f9SYork Sun 	unsigned short esdmode6 = 0;	/* Extended SDRAM mode 6 */
126134e026f9SYork Sun 	unsigned short esdmode7 = 0;	/* Extended SDRAM mode 7 */
126203e664d8SYork Sun 	unsigned int tccdl_min = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps);
126334e026f9SYork Sun 
126434e026f9SYork Sun 	esdmode6 = ((tccdl_min - 4) & 0x7) << 10;
126534e026f9SYork Sun 
12660fb71974SYork Sun 	if (popts->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2)
12670fb71974SYork Sun 		esdmode6 |= 1 << 6;	/* Range 2 */
12680fb71974SYork Sun 
126934e026f9SYork Sun 	ddr->ddr_sdram_mode_10 = (0
127034e026f9SYork Sun 				 | ((esdmode6 & 0xffff) << 16)
127134e026f9SYork Sun 				 | ((esdmode7 & 0xffff) << 0)
127234e026f9SYork Sun 				);
127334e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode_10) = 0x%08x\n", ddr->ddr_sdram_mode_10);
127434e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
127534e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
127634e026f9SYork Sun 			switch (i) {
127734e026f9SYork Sun 			case 1:
127834e026f9SYork Sun 				ddr->ddr_sdram_mode_12 = (0
127934e026f9SYork Sun 					| ((esdmode6 & 0xFFFF) << 16)
128034e026f9SYork Sun 					| ((esdmode7 & 0xFFFF) << 0)
128134e026f9SYork Sun 					);
128234e026f9SYork Sun 				break;
128334e026f9SYork Sun 			case 2:
128434e026f9SYork Sun 				ddr->ddr_sdram_mode_14 = (0
128534e026f9SYork Sun 					| ((esdmode6 & 0xFFFF) << 16)
128634e026f9SYork Sun 					| ((esdmode7 & 0xFFFF) << 0)
128734e026f9SYork Sun 					);
128834e026f9SYork Sun 				break;
128934e026f9SYork Sun 			case 3:
129034e026f9SYork Sun 				ddr->ddr_sdram_mode_16 = (0
129134e026f9SYork Sun 					| ((esdmode6 & 0xFFFF) << 16)
129234e026f9SYork Sun 					| ((esdmode7 & 0xFFFF) << 0)
129334e026f9SYork Sun 					);
129434e026f9SYork Sun 				break;
129534e026f9SYork Sun 			}
129634e026f9SYork Sun 		}
129734e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_12 = 0x%08x\n",
129834e026f9SYork Sun 		      ddr->ddr_sdram_mode_12);
129934e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_14 = 0x%08x\n",
130034e026f9SYork Sun 		      ddr->ddr_sdram_mode_14);
130134e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_16 = 0x%08x\n",
130234e026f9SYork Sun 		      ddr->ddr_sdram_mode_16);
130334e026f9SYork Sun 	}
130434e026f9SYork Sun }
130534e026f9SYork Sun 
130634e026f9SYork Sun #endif
13075614e71bSYork Sun 
13085614e71bSYork Sun /* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */
130903e664d8SYork Sun static void set_ddr_sdram_interval(const unsigned int ctrl_num,
131003e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
13115614e71bSYork Sun 				const memctl_options_t *popts,
13125614e71bSYork Sun 				const common_timing_params_t *common_dimm)
13135614e71bSYork Sun {
13145614e71bSYork Sun 	unsigned int refint;	/* Refresh interval */
13155614e71bSYork Sun 	unsigned int bstopre;	/* Precharge interval */
13165614e71bSYork Sun 
131703e664d8SYork Sun 	refint = picos_to_mclk(ctrl_num, common_dimm->refresh_rate_ps);
13185614e71bSYork Sun 
13195614e71bSYork Sun 	bstopre = popts->bstopre;
13205614e71bSYork Sun 
13215614e71bSYork Sun 	/* refint field used 0x3FFF in earlier controllers */
13225614e71bSYork Sun 	ddr->ddr_sdram_interval = (0
13235614e71bSYork Sun 				   | ((refint & 0xFFFF) << 16)
13245614e71bSYork Sun 				   | ((bstopre & 0x3FFF) << 0)
13255614e71bSYork Sun 				   );
13265614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval);
13275614e71bSYork Sun }
13285614e71bSYork Sun 
132934e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
13305614e71bSYork Sun /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
133103e664d8SYork Sun static void set_ddr_sdram_mode(const unsigned int ctrl_num,
133203e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
13335614e71bSYork Sun 			       const memctl_options_t *popts,
13345614e71bSYork Sun 			       const common_timing_params_t *common_dimm,
13355614e71bSYork Sun 			       unsigned int cas_latency,
13365614e71bSYork Sun 			       unsigned int additive_latency,
13375614e71bSYork Sun 			       const unsigned int unq_mrs_en)
13385614e71bSYork Sun {
133934e026f9SYork Sun 	int i;
134034e026f9SYork Sun 	unsigned short esdmode;		/* Extended SDRAM mode */
134134e026f9SYork Sun 	unsigned short sdmode;		/* SDRAM mode */
134234e026f9SYork Sun 
134334e026f9SYork Sun 	/* Mode Register - MR1 */
134434e026f9SYork Sun 	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
134534e026f9SYork Sun 	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
134634e026f9SYork Sun 	unsigned int rtt;
134734e026f9SYork Sun 	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
134834e026f9SYork Sun 	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
134934e026f9SYork Sun 	unsigned int dic = 0;		/* Output driver impedance, 40ohm */
135034e026f9SYork Sun 	unsigned int dll_en = 1;	/* DLL Enable  1=Enable (Normal),
135134e026f9SYork Sun 						       0=Disable (Test/Debug) */
135234e026f9SYork Sun 
135334e026f9SYork Sun 	/* Mode Register - MR0 */
135434e026f9SYork Sun 	unsigned int wr = 0;	/* Write Recovery */
135534e026f9SYork Sun 	unsigned int dll_rst;	/* DLL Reset */
135634e026f9SYork Sun 	unsigned int mode;	/* Normal=0 or Test=1 */
135734e026f9SYork Sun 	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
135834e026f9SYork Sun 	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
135934e026f9SYork Sun 	unsigned int bt;
136034e026f9SYork Sun 	unsigned int bl;	/* BL: Burst Length */
136134e026f9SYork Sun 
136234e026f9SYork Sun 	unsigned int wr_mclk;
136334e026f9SYork Sun 	/* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */
136434e026f9SYork Sun 	static const u8 wr_table[] = {
136534e026f9SYork Sun 		0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6};
136634e026f9SYork Sun 	/* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */
136734e026f9SYork Sun 	static const u8 cas_latency_table[] = {
136834e026f9SYork Sun 		0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
136934e026f9SYork Sun 		9, 9, 10, 10, 11, 11};
137034e026f9SYork Sun 
137134e026f9SYork Sun 	if (popts->rtt_override)
137234e026f9SYork Sun 		rtt = popts->rtt_override_value;
137334e026f9SYork Sun 	else
137434e026f9SYork Sun 		rtt = popts->cs_local_opts[0].odt_rtt_norm;
137534e026f9SYork Sun 
137634e026f9SYork Sun 	if (additive_latency == (cas_latency - 1))
137734e026f9SYork Sun 		al = 1;
137834e026f9SYork Sun 	if (additive_latency == (cas_latency - 2))
137934e026f9SYork Sun 		al = 2;
138034e026f9SYork Sun 
138134e026f9SYork Sun 	if (popts->quad_rank_present)
138234e026f9SYork Sun 		dic = 1;	/* output driver impedance 240/7 ohm */
138334e026f9SYork Sun 
138434e026f9SYork Sun 	/*
138534e026f9SYork Sun 	 * The esdmode value will also be used for writing
138634e026f9SYork Sun 	 * MR1 during write leveling for DDR3, although the
138734e026f9SYork Sun 	 * bits specifically related to the write leveling
138834e026f9SYork Sun 	 * scheme will be handled automatically by the DDR
138934e026f9SYork Sun 	 * controller. so we set the wrlvl_en = 0 here.
139034e026f9SYork Sun 	 */
139134e026f9SYork Sun 	esdmode = (0
139234e026f9SYork Sun 		| ((qoff & 0x1) << 12)
139334e026f9SYork Sun 		| ((tdqs_en & 0x1) << 11)
139434e026f9SYork Sun 		| ((rtt & 0x7) << 8)
139534e026f9SYork Sun 		| ((wrlvl_en & 0x1) << 7)
139634e026f9SYork Sun 		| ((al & 0x3) << 3)
139734e026f9SYork Sun 		| ((dic & 0x3) << 1)   /* DIC field is split */
139834e026f9SYork Sun 		| ((dll_en & 0x1) << 0)
139934e026f9SYork Sun 		);
140034e026f9SYork Sun 
140134e026f9SYork Sun 	/*
140234e026f9SYork Sun 	 * DLL control for precharge PD
140334e026f9SYork Sun 	 * 0=slow exit DLL off (tXPDLL)
140434e026f9SYork Sun 	 * 1=fast exit DLL on (tXP)
140534e026f9SYork Sun 	 */
140634e026f9SYork Sun 
140703e664d8SYork Sun 	wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
140834e026f9SYork Sun 	if (wr_mclk <= 24) {
140934e026f9SYork Sun 		wr = wr_table[wr_mclk - 10];
141034e026f9SYork Sun 	} else {
141134e026f9SYork Sun 		printf("Error: unsupported write recovery for mode register wr_mclk = %d\n",
141234e026f9SYork Sun 		       wr_mclk);
141334e026f9SYork Sun 	}
141434e026f9SYork Sun 
141534e026f9SYork Sun 	dll_rst = 0;	/* dll no reset */
141634e026f9SYork Sun 	mode = 0;	/* normal mode */
141734e026f9SYork Sun 
141834e026f9SYork Sun 	/* look up table to get the cas latency bits */
141934e026f9SYork Sun 	if (cas_latency >= 9 && cas_latency <= 24)
142034e026f9SYork Sun 		caslat = cas_latency_table[cas_latency - 9];
142134e026f9SYork Sun 	else
142234e026f9SYork Sun 		printf("Error: unsupported cas latency for mode register\n");
142334e026f9SYork Sun 
142434e026f9SYork Sun 	bt = 0;	/* Nibble sequential */
142534e026f9SYork Sun 
142634e026f9SYork Sun 	switch (popts->burst_length) {
142734e026f9SYork Sun 	case DDR_BL8:
142834e026f9SYork Sun 		bl = 0;
142934e026f9SYork Sun 		break;
143034e026f9SYork Sun 	case DDR_OTF:
143134e026f9SYork Sun 		bl = 1;
143234e026f9SYork Sun 		break;
143334e026f9SYork Sun 	case DDR_BC4:
143434e026f9SYork Sun 		bl = 2;
143534e026f9SYork Sun 		break;
143634e026f9SYork Sun 	default:
143734e026f9SYork Sun 		printf("Error: invalid burst length of %u specified. ",
143834e026f9SYork Sun 		       popts->burst_length);
143934e026f9SYork Sun 		puts("Defaulting to on-the-fly BC4 or BL8 beats.\n");
144034e026f9SYork Sun 		bl = 1;
144134e026f9SYork Sun 		break;
144234e026f9SYork Sun 	}
144334e026f9SYork Sun 
144434e026f9SYork Sun 	sdmode = (0
144534e026f9SYork Sun 		  | ((wr & 0x7) << 9)
144634e026f9SYork Sun 		  | ((dll_rst & 0x1) << 8)
144734e026f9SYork Sun 		  | ((mode & 0x1) << 7)
144834e026f9SYork Sun 		  | (((caslat >> 1) & 0x7) << 4)
144934e026f9SYork Sun 		  | ((bt & 0x1) << 3)
145034e026f9SYork Sun 		  | ((caslat & 1) << 2)
145134e026f9SYork Sun 		  | ((bl & 0x3) << 0)
145234e026f9SYork Sun 		  );
145334e026f9SYork Sun 
145434e026f9SYork Sun 	ddr->ddr_sdram_mode = (0
145534e026f9SYork Sun 			       | ((esdmode & 0xFFFF) << 16)
145634e026f9SYork Sun 			       | ((sdmode & 0xFFFF) << 0)
145734e026f9SYork Sun 			       );
145834e026f9SYork Sun 
145934e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
146034e026f9SYork Sun 
146134e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
146234e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
146334e026f9SYork Sun 			if (popts->rtt_override)
146434e026f9SYork Sun 				rtt = popts->rtt_override_value;
146534e026f9SYork Sun 			else
146634e026f9SYork Sun 				rtt = popts->cs_local_opts[i].odt_rtt_norm;
146734e026f9SYork Sun 
146834e026f9SYork Sun 			esdmode &= 0xF8FF;	/* clear bit 10,9,8 for rtt */
146934e026f9SYork Sun 			esdmode |= (rtt & 0x7) << 8;
147034e026f9SYork Sun 			switch (i) {
147134e026f9SYork Sun 			case 1:
147234e026f9SYork Sun 				ddr->ddr_sdram_mode_3 = (0
147334e026f9SYork Sun 				       | ((esdmode & 0xFFFF) << 16)
147434e026f9SYork Sun 				       | ((sdmode & 0xFFFF) << 0)
147534e026f9SYork Sun 				       );
147634e026f9SYork Sun 				break;
147734e026f9SYork Sun 			case 2:
147834e026f9SYork Sun 				ddr->ddr_sdram_mode_5 = (0
147934e026f9SYork Sun 				       | ((esdmode & 0xFFFF) << 16)
148034e026f9SYork Sun 				       | ((sdmode & 0xFFFF) << 0)
148134e026f9SYork Sun 				       );
148234e026f9SYork Sun 				break;
148334e026f9SYork Sun 			case 3:
148434e026f9SYork Sun 				ddr->ddr_sdram_mode_7 = (0
148534e026f9SYork Sun 				       | ((esdmode & 0xFFFF) << 16)
148634e026f9SYork Sun 				       | ((sdmode & 0xFFFF) << 0)
148734e026f9SYork Sun 				       );
148834e026f9SYork Sun 				break;
148934e026f9SYork Sun 			}
149034e026f9SYork Sun 		}
149134e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
149234e026f9SYork Sun 		      ddr->ddr_sdram_mode_3);
149334e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
149434e026f9SYork Sun 		      ddr->ddr_sdram_mode_5);
149534e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
149634e026f9SYork Sun 		      ddr->ddr_sdram_mode_5);
149734e026f9SYork Sun 	}
149834e026f9SYork Sun }
149934e026f9SYork Sun 
150034e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
150134e026f9SYork Sun /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
150203e664d8SYork Sun static void set_ddr_sdram_mode(const unsigned int ctrl_num,
150303e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
150434e026f9SYork Sun 			       const memctl_options_t *popts,
150534e026f9SYork Sun 			       const common_timing_params_t *common_dimm,
150634e026f9SYork Sun 			       unsigned int cas_latency,
150734e026f9SYork Sun 			       unsigned int additive_latency,
150834e026f9SYork Sun 			       const unsigned int unq_mrs_en)
150934e026f9SYork Sun {
151034e026f9SYork Sun 	int i;
15115614e71bSYork Sun 	unsigned short esdmode;		/* Extended SDRAM mode */
15125614e71bSYork Sun 	unsigned short sdmode;		/* SDRAM mode */
15135614e71bSYork Sun 
15145614e71bSYork Sun 	/* Mode Register - MR1 */
15155614e71bSYork Sun 	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
15165614e71bSYork Sun 	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
15175614e71bSYork Sun 	unsigned int rtt;
15185614e71bSYork Sun 	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
15195614e71bSYork Sun 	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
15205614e71bSYork Sun 	unsigned int dic = 0;		/* Output driver impedance, 40ohm */
15215614e71bSYork Sun 	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
15225614e71bSYork Sun 						       1=Disable (Test/Debug) */
15235614e71bSYork Sun 
15245614e71bSYork Sun 	/* Mode Register - MR0 */
15255614e71bSYork Sun 	unsigned int dll_on;	/* DLL control for precharge PD, 0=off, 1=on */
15265614e71bSYork Sun 	unsigned int wr = 0;	/* Write Recovery */
15275614e71bSYork Sun 	unsigned int dll_rst;	/* DLL Reset */
15285614e71bSYork Sun 	unsigned int mode;	/* Normal=0 or Test=1 */
15295614e71bSYork Sun 	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
15305614e71bSYork Sun 	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
15315614e71bSYork Sun 	unsigned int bt;
15325614e71bSYork Sun 	unsigned int bl;	/* BL: Burst Length */
15335614e71bSYork Sun 
15345614e71bSYork Sun 	unsigned int wr_mclk;
15355614e71bSYork Sun 	/*
15365614e71bSYork Sun 	 * DDR_SDRAM_MODE doesn't support 9,11,13,15
15375614e71bSYork Sun 	 * Please refer JEDEC Standard No. 79-3E for Mode Register MR0
15385614e71bSYork Sun 	 * for this table
15395614e71bSYork Sun 	 */
15405614e71bSYork Sun 	static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
15415614e71bSYork Sun 
15425614e71bSYork Sun 	if (popts->rtt_override)
15435614e71bSYork Sun 		rtt = popts->rtt_override_value;
15445614e71bSYork Sun 	else
15455614e71bSYork Sun 		rtt = popts->cs_local_opts[0].odt_rtt_norm;
15465614e71bSYork Sun 
15475614e71bSYork Sun 	if (additive_latency == (cas_latency - 1))
15485614e71bSYork Sun 		al = 1;
15495614e71bSYork Sun 	if (additive_latency == (cas_latency - 2))
15505614e71bSYork Sun 		al = 2;
15515614e71bSYork Sun 
15525614e71bSYork Sun 	if (popts->quad_rank_present)
15535614e71bSYork Sun 		dic = 1;	/* output driver impedance 240/7 ohm */
15545614e71bSYork Sun 
15555614e71bSYork Sun 	/*
15565614e71bSYork Sun 	 * The esdmode value will also be used for writing
15575614e71bSYork Sun 	 * MR1 during write leveling for DDR3, although the
15585614e71bSYork Sun 	 * bits specifically related to the write leveling
15595614e71bSYork Sun 	 * scheme will be handled automatically by the DDR
15605614e71bSYork Sun 	 * controller. so we set the wrlvl_en = 0 here.
15615614e71bSYork Sun 	 */
15625614e71bSYork Sun 	esdmode = (0
15635614e71bSYork Sun 		| ((qoff & 0x1) << 12)
15645614e71bSYork Sun 		| ((tdqs_en & 0x1) << 11)
15655614e71bSYork Sun 		| ((rtt & 0x4) << 7)   /* rtt field is split */
15665614e71bSYork Sun 		| ((wrlvl_en & 0x1) << 7)
15675614e71bSYork Sun 		| ((rtt & 0x2) << 5)   /* rtt field is split */
15685614e71bSYork Sun 		| ((dic & 0x2) << 4)   /* DIC field is split */
15695614e71bSYork Sun 		| ((al & 0x3) << 3)
15705614e71bSYork Sun 		| ((rtt & 0x1) << 2)  /* rtt field is split */
15715614e71bSYork Sun 		| ((dic & 0x1) << 1)   /* DIC field is split */
15725614e71bSYork Sun 		| ((dll_en & 0x1) << 0)
15735614e71bSYork Sun 		);
15745614e71bSYork Sun 
15755614e71bSYork Sun 	/*
15765614e71bSYork Sun 	 * DLL control for precharge PD
15775614e71bSYork Sun 	 * 0=slow exit DLL off (tXPDLL)
15785614e71bSYork Sun 	 * 1=fast exit DLL on (tXP)
15795614e71bSYork Sun 	 */
15805614e71bSYork Sun 	dll_on = 1;
15815614e71bSYork Sun 
158203e664d8SYork Sun 	wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
15835614e71bSYork Sun 	if (wr_mclk <= 16) {
15845614e71bSYork Sun 		wr = wr_table[wr_mclk - 5];
15855614e71bSYork Sun 	} else {
15865614e71bSYork Sun 		printf("Error: unsupported write recovery for mode register "
15875614e71bSYork Sun 		       "wr_mclk = %d\n", wr_mclk);
15885614e71bSYork Sun 	}
15895614e71bSYork Sun 
15905614e71bSYork Sun 	dll_rst = 0;	/* dll no reset */
15915614e71bSYork Sun 	mode = 0;	/* normal mode */
15925614e71bSYork Sun 
15935614e71bSYork Sun 	/* look up table to get the cas latency bits */
15945614e71bSYork Sun 	if (cas_latency >= 5 && cas_latency <= 16) {
15955614e71bSYork Sun 		unsigned char cas_latency_table[] = {
15965614e71bSYork Sun 			0x2,	/* 5 clocks */
15975614e71bSYork Sun 			0x4,	/* 6 clocks */
15985614e71bSYork Sun 			0x6,	/* 7 clocks */
15995614e71bSYork Sun 			0x8,	/* 8 clocks */
16005614e71bSYork Sun 			0xa,	/* 9 clocks */
16015614e71bSYork Sun 			0xc,	/* 10 clocks */
16025614e71bSYork Sun 			0xe,	/* 11 clocks */
16035614e71bSYork Sun 			0x1,	/* 12 clocks */
16045614e71bSYork Sun 			0x3,	/* 13 clocks */
16055614e71bSYork Sun 			0x5,	/* 14 clocks */
16065614e71bSYork Sun 			0x7,	/* 15 clocks */
16075614e71bSYork Sun 			0x9,	/* 16 clocks */
16085614e71bSYork Sun 		};
16095614e71bSYork Sun 		caslat = cas_latency_table[cas_latency - 5];
16105614e71bSYork Sun 	} else {
16115614e71bSYork Sun 		printf("Error: unsupported cas latency for mode register\n");
16125614e71bSYork Sun 	}
16135614e71bSYork Sun 
16145614e71bSYork Sun 	bt = 0;	/* Nibble sequential */
16155614e71bSYork Sun 
16165614e71bSYork Sun 	switch (popts->burst_length) {
16175614e71bSYork Sun 	case DDR_BL8:
16185614e71bSYork Sun 		bl = 0;
16195614e71bSYork Sun 		break;
16205614e71bSYork Sun 	case DDR_OTF:
16215614e71bSYork Sun 		bl = 1;
16225614e71bSYork Sun 		break;
16235614e71bSYork Sun 	case DDR_BC4:
16245614e71bSYork Sun 		bl = 2;
16255614e71bSYork Sun 		break;
16265614e71bSYork Sun 	default:
16275614e71bSYork Sun 		printf("Error: invalid burst length of %u specified. "
16285614e71bSYork Sun 			" Defaulting to on-the-fly BC4 or BL8 beats.\n",
16295614e71bSYork Sun 			popts->burst_length);
16305614e71bSYork Sun 		bl = 1;
16315614e71bSYork Sun 		break;
16325614e71bSYork Sun 	}
16335614e71bSYork Sun 
16345614e71bSYork Sun 	sdmode = (0
16355614e71bSYork Sun 		  | ((dll_on & 0x1) << 12)
16365614e71bSYork Sun 		  | ((wr & 0x7) << 9)
16375614e71bSYork Sun 		  | ((dll_rst & 0x1) << 8)
16385614e71bSYork Sun 		  | ((mode & 0x1) << 7)
16395614e71bSYork Sun 		  | (((caslat >> 1) & 0x7) << 4)
16405614e71bSYork Sun 		  | ((bt & 0x1) << 3)
16415614e71bSYork Sun 		  | ((caslat & 1) << 2)
16425614e71bSYork Sun 		  | ((bl & 0x3) << 0)
16435614e71bSYork Sun 		  );
16445614e71bSYork Sun 
16455614e71bSYork Sun 	ddr->ddr_sdram_mode = (0
16465614e71bSYork Sun 			       | ((esdmode & 0xFFFF) << 16)
16475614e71bSYork Sun 			       | ((sdmode & 0xFFFF) << 0)
16485614e71bSYork Sun 			       );
16495614e71bSYork Sun 
16505614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
16515614e71bSYork Sun 
16525614e71bSYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
16535614e71bSYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
16545614e71bSYork Sun 			if (popts->rtt_override)
16555614e71bSYork Sun 				rtt = popts->rtt_override_value;
16565614e71bSYork Sun 			else
16575614e71bSYork Sun 				rtt = popts->cs_local_opts[i].odt_rtt_norm;
16585614e71bSYork Sun 
16595614e71bSYork Sun 			esdmode &= 0xFDBB;	/* clear bit 9,6,2 */
16605614e71bSYork Sun 			esdmode |= (0
16615614e71bSYork Sun 				| ((rtt & 0x4) << 7)   /* rtt field is split */
16625614e71bSYork Sun 				| ((rtt & 0x2) << 5)   /* rtt field is split */
16635614e71bSYork Sun 				| ((rtt & 0x1) << 2)  /* rtt field is split */
16645614e71bSYork Sun 				);
16655614e71bSYork Sun 			switch (i) {
16665614e71bSYork Sun 			case 1:
16675614e71bSYork Sun 				ddr->ddr_sdram_mode_3 = (0
16685614e71bSYork Sun 				       | ((esdmode & 0xFFFF) << 16)
16695614e71bSYork Sun 				       | ((sdmode & 0xFFFF) << 0)
16705614e71bSYork Sun 				       );
16715614e71bSYork Sun 				break;
16725614e71bSYork Sun 			case 2:
16735614e71bSYork Sun 				ddr->ddr_sdram_mode_5 = (0
16745614e71bSYork Sun 				       | ((esdmode & 0xFFFF) << 16)
16755614e71bSYork Sun 				       | ((sdmode & 0xFFFF) << 0)
16765614e71bSYork Sun 				       );
16775614e71bSYork Sun 				break;
16785614e71bSYork Sun 			case 3:
16795614e71bSYork Sun 				ddr->ddr_sdram_mode_7 = (0
16805614e71bSYork Sun 				       | ((esdmode & 0xFFFF) << 16)
16815614e71bSYork Sun 				       | ((sdmode & 0xFFFF) << 0)
16825614e71bSYork Sun 				       );
16835614e71bSYork Sun 				break;
16845614e71bSYork Sun 			}
16855614e71bSYork Sun 		}
16865614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
16875614e71bSYork Sun 			ddr->ddr_sdram_mode_3);
16885614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
16895614e71bSYork Sun 			ddr->ddr_sdram_mode_5);
16905614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
16915614e71bSYork Sun 			ddr->ddr_sdram_mode_5);
16925614e71bSYork Sun 	}
16935614e71bSYork Sun }
16945614e71bSYork Sun 
16955614e71bSYork Sun #else /* !CONFIG_SYS_FSL_DDR3 */
16965614e71bSYork Sun 
16975614e71bSYork Sun /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
169803e664d8SYork Sun static void set_ddr_sdram_mode(const unsigned int ctrl_num,
169903e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
17005614e71bSYork Sun 			       const memctl_options_t *popts,
17015614e71bSYork Sun 			       const common_timing_params_t *common_dimm,
17025614e71bSYork Sun 			       unsigned int cas_latency,
17035614e71bSYork Sun 			       unsigned int additive_latency,
17045614e71bSYork Sun 			       const unsigned int unq_mrs_en)
17055614e71bSYork Sun {
17065614e71bSYork Sun 	unsigned short esdmode;		/* Extended SDRAM mode */
17075614e71bSYork Sun 	unsigned short sdmode;		/* SDRAM mode */
17085614e71bSYork Sun 
17095614e71bSYork Sun 	/*
17105614e71bSYork Sun 	 * FIXME: This ought to be pre-calculated in a
17115614e71bSYork Sun 	 * technology-specific routine,
17125614e71bSYork Sun 	 * e.g. compute_DDR2_mode_register(), and then the
17135614e71bSYork Sun 	 * sdmode and esdmode passed in as part of common_dimm.
17145614e71bSYork Sun 	 */
17155614e71bSYork Sun 
17165614e71bSYork Sun 	/* Extended Mode Register */
17175614e71bSYork Sun 	unsigned int mrs = 0;		/* Mode Register Set */
17185614e71bSYork Sun 	unsigned int outputs = 0;	/* 0=Enabled, 1=Disabled */
17195614e71bSYork Sun 	unsigned int rdqs_en = 0;	/* RDQS Enable: 0=no, 1=yes */
17205614e71bSYork Sun 	unsigned int dqs_en = 0;	/* DQS# Enable: 0=enable, 1=disable */
17215614e71bSYork Sun 	unsigned int ocd = 0;		/* 0x0=OCD not supported,
17225614e71bSYork Sun 					   0x7=OCD default state */
17235614e71bSYork Sun 	unsigned int rtt;
17245614e71bSYork Sun 	unsigned int al;		/* Posted CAS# additive latency (AL) */
17255614e71bSYork Sun 	unsigned int ods = 0;		/* Output Drive Strength:
17265614e71bSYork Sun 						0 = Full strength (18ohm)
17275614e71bSYork Sun 						1 = Reduced strength (4ohm) */
17285614e71bSYork Sun 	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
17295614e71bSYork Sun 						       1=Disable (Test/Debug) */
17305614e71bSYork Sun 
17315614e71bSYork Sun 	/* Mode Register (MR) */
17325614e71bSYork Sun 	unsigned int mr;	/* Mode Register Definition */
17335614e71bSYork Sun 	unsigned int pd;	/* Power-Down Mode */
17345614e71bSYork Sun 	unsigned int wr;	/* Write Recovery */
17355614e71bSYork Sun 	unsigned int dll_res;	/* DLL Reset */
17365614e71bSYork Sun 	unsigned int mode;	/* Normal=0 or Test=1 */
17375614e71bSYork Sun 	unsigned int caslat = 0;/* CAS# latency */
17385614e71bSYork Sun 	/* BT: Burst Type (0=Sequential, 1=Interleaved) */
17395614e71bSYork Sun 	unsigned int bt;
17405614e71bSYork Sun 	unsigned int bl;	/* BL: Burst Length */
17415614e71bSYork Sun 
17425614e71bSYork Sun 	dqs_en = !popts->dqs_config;
17435614e71bSYork Sun 	rtt = fsl_ddr_get_rtt();
17445614e71bSYork Sun 
17455614e71bSYork Sun 	al = additive_latency;
17465614e71bSYork Sun 
17475614e71bSYork Sun 	esdmode = (0
17485614e71bSYork Sun 		| ((mrs & 0x3) << 14)
17495614e71bSYork Sun 		| ((outputs & 0x1) << 12)
17505614e71bSYork Sun 		| ((rdqs_en & 0x1) << 11)
17515614e71bSYork Sun 		| ((dqs_en & 0x1) << 10)
17525614e71bSYork Sun 		| ((ocd & 0x7) << 7)
17535614e71bSYork Sun 		| ((rtt & 0x2) << 5)   /* rtt field is split */
17545614e71bSYork Sun 		| ((al & 0x7) << 3)
17555614e71bSYork Sun 		| ((rtt & 0x1) << 2)   /* rtt field is split */
17565614e71bSYork Sun 		| ((ods & 0x1) << 1)
17575614e71bSYork Sun 		| ((dll_en & 0x1) << 0)
17585614e71bSYork Sun 		);
17595614e71bSYork Sun 
17605614e71bSYork Sun 	mr = 0;		 /* FIXME: CHECKME */
17615614e71bSYork Sun 
17625614e71bSYork Sun 	/*
17635614e71bSYork Sun 	 * 0 = Fast Exit (Normal)
17645614e71bSYork Sun 	 * 1 = Slow Exit (Low Power)
17655614e71bSYork Sun 	 */
17665614e71bSYork Sun 	pd = 0;
17675614e71bSYork Sun 
17685614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
17695614e71bSYork Sun 	wr = 0;       /* Historical */
17705614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
177103e664d8SYork Sun 	wr = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
17725614e71bSYork Sun #endif
17735614e71bSYork Sun 	dll_res = 0;
17745614e71bSYork Sun 	mode = 0;
17755614e71bSYork Sun 
17765614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
17775614e71bSYork Sun 	if (1 <= cas_latency && cas_latency <= 4) {
17785614e71bSYork Sun 		unsigned char mode_caslat_table[4] = {
17795614e71bSYork Sun 			0x5,	/* 1.5 clocks */
17805614e71bSYork Sun 			0x2,	/* 2.0 clocks */
17815614e71bSYork Sun 			0x6,	/* 2.5 clocks */
17825614e71bSYork Sun 			0x3	/* 3.0 clocks */
17835614e71bSYork Sun 		};
17845614e71bSYork Sun 		caslat = mode_caslat_table[cas_latency - 1];
17855614e71bSYork Sun 	} else {
17865614e71bSYork Sun 		printf("Warning: unknown cas_latency %d\n", cas_latency);
17875614e71bSYork Sun 	}
17885614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
17895614e71bSYork Sun 	caslat = cas_latency;
17905614e71bSYork Sun #endif
17915614e71bSYork Sun 	bt = 0;
17925614e71bSYork Sun 
17935614e71bSYork Sun 	switch (popts->burst_length) {
17945614e71bSYork Sun 	case DDR_BL4:
17955614e71bSYork Sun 		bl = 2;
17965614e71bSYork Sun 		break;
17975614e71bSYork Sun 	case DDR_BL8:
17985614e71bSYork Sun 		bl = 3;
17995614e71bSYork Sun 		break;
18005614e71bSYork Sun 	default:
18015614e71bSYork Sun 		printf("Error: invalid burst length of %u specified. "
18025614e71bSYork Sun 			" Defaulting to 4 beats.\n",
18035614e71bSYork Sun 			popts->burst_length);
18045614e71bSYork Sun 		bl = 2;
18055614e71bSYork Sun 		break;
18065614e71bSYork Sun 	}
18075614e71bSYork Sun 
18085614e71bSYork Sun 	sdmode = (0
18095614e71bSYork Sun 		  | ((mr & 0x3) << 14)
18105614e71bSYork Sun 		  | ((pd & 0x1) << 12)
18115614e71bSYork Sun 		  | ((wr & 0x7) << 9)
18125614e71bSYork Sun 		  | ((dll_res & 0x1) << 8)
18135614e71bSYork Sun 		  | ((mode & 0x1) << 7)
18145614e71bSYork Sun 		  | ((caslat & 0x7) << 4)
18155614e71bSYork Sun 		  | ((bt & 0x1) << 3)
18165614e71bSYork Sun 		  | ((bl & 0x7) << 0)
18175614e71bSYork Sun 		  );
18185614e71bSYork Sun 
18195614e71bSYork Sun 	ddr->ddr_sdram_mode = (0
18205614e71bSYork Sun 			       | ((esdmode & 0xFFFF) << 16)
18215614e71bSYork Sun 			       | ((sdmode & 0xFFFF) << 0)
18225614e71bSYork Sun 			       );
18235614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
18245614e71bSYork Sun }
18255614e71bSYork Sun #endif
18265614e71bSYork Sun 
18275614e71bSYork Sun /* DDR SDRAM Data Initialization (DDR_DATA_INIT) */
18285614e71bSYork Sun static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr)
18295614e71bSYork Sun {
18305614e71bSYork Sun 	unsigned int init_value;	/* Initialization value */
18315614e71bSYork Sun 
18325614e71bSYork Sun #ifdef CONFIG_MEM_INIT_VALUE
18335614e71bSYork Sun 	init_value = CONFIG_MEM_INIT_VALUE;
18345614e71bSYork Sun #else
18355614e71bSYork Sun 	init_value = 0xDEADBEEF;
18365614e71bSYork Sun #endif
18375614e71bSYork Sun 	ddr->ddr_data_init = init_value;
18385614e71bSYork Sun }
18395614e71bSYork Sun 
18405614e71bSYork Sun /*
18415614e71bSYork Sun  * DDR SDRAM Clock Control (DDR_SDRAM_CLK_CNTL)
18425614e71bSYork Sun  * The old controller on the 8540/60 doesn't have this register.
18435614e71bSYork Sun  * Hope it's OK to set it (to 0) anyway.
18445614e71bSYork Sun  */
18455614e71bSYork Sun static void set_ddr_sdram_clk_cntl(fsl_ddr_cfg_regs_t *ddr,
18465614e71bSYork Sun 					 const memctl_options_t *popts)
18475614e71bSYork Sun {
18485614e71bSYork Sun 	unsigned int clk_adjust;	/* Clock adjust */
1849d7c865bdSCurt Brune 	unsigned int ss_en = 0;		/* Source synchronous enable */
18505614e71bSYork Sun 
18513c3d8ab5SYork Sun #if defined(CONFIG_ARCH_MPC8541) || defined(CONFIG_ARCH_MPC8555)
1852d7c865bdSCurt Brune 	/* Per FSL Application Note: AN2805 */
1853d7c865bdSCurt Brune 	ss_en = 1;
1854d7c865bdSCurt Brune #endif
1855d8e5163aSShengzhou Liu 	if (fsl_ddr_get_version(0) >= 0x40701) {
1856d8e5163aSShengzhou Liu 		/* clk_adjust in 5-bits on T-series and LS-series */
1857d8e5163aSShengzhou Liu 		clk_adjust = (popts->clk_adjust & 0x1F) << 22;
1858d8e5163aSShengzhou Liu 	} else {
1859d8e5163aSShengzhou Liu 		/* clk_adjust in 4-bits on earlier MPC85xx and P-series */
1860d8e5163aSShengzhou Liu 		clk_adjust = (popts->clk_adjust & 0xF) << 23;
1861d8e5163aSShengzhou Liu 	}
1862d8e5163aSShengzhou Liu 
1863d7c865bdSCurt Brune 	ddr->ddr_sdram_clk_cntl = (0
1864d7c865bdSCurt Brune 				   | ((ss_en & 0x1) << 31)
1865d8e5163aSShengzhou Liu 				   | clk_adjust
1866d7c865bdSCurt Brune 				   );
18675614e71bSYork Sun 	debug("FSLDDR: clk_cntl = 0x%08x\n", ddr->ddr_sdram_clk_cntl);
18685614e71bSYork Sun }
18695614e71bSYork Sun 
18705614e71bSYork Sun /* DDR Initialization Address (DDR_INIT_ADDR) */
18715614e71bSYork Sun static void set_ddr_init_addr(fsl_ddr_cfg_regs_t *ddr)
18725614e71bSYork Sun {
18735614e71bSYork Sun 	unsigned int init_addr = 0;	/* Initialization address */
18745614e71bSYork Sun 
18755614e71bSYork Sun 	ddr->ddr_init_addr = init_addr;
18765614e71bSYork Sun }
18775614e71bSYork Sun 
18785614e71bSYork Sun /* DDR Initialization Address (DDR_INIT_EXT_ADDR) */
18795614e71bSYork Sun static void set_ddr_init_ext_addr(fsl_ddr_cfg_regs_t *ddr)
18805614e71bSYork Sun {
18815614e71bSYork Sun 	unsigned int uia = 0;	/* Use initialization address */
18825614e71bSYork Sun 	unsigned int init_ext_addr = 0;	/* Initialization address */
18835614e71bSYork Sun 
18845614e71bSYork Sun 	ddr->ddr_init_ext_addr = (0
18855614e71bSYork Sun 				  | ((uia & 0x1) << 31)
18865614e71bSYork Sun 				  | (init_ext_addr & 0xF)
18875614e71bSYork Sun 				  );
18885614e71bSYork Sun }
18895614e71bSYork Sun 
18905614e71bSYork Sun /* DDR SDRAM Timing Configuration 4 (TIMING_CFG_4) */
18915614e71bSYork Sun static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr,
18925614e71bSYork Sun 				const memctl_options_t *popts)
18935614e71bSYork Sun {
18945614e71bSYork Sun 	unsigned int rwt = 0; /* Read-to-write turnaround for same CS */
18955614e71bSYork Sun 	unsigned int wrt = 0; /* Write-to-read turnaround for same CS */
18965614e71bSYork Sun 	unsigned int rrt = 0; /* Read-to-read turnaround for same CS */
18975614e71bSYork Sun 	unsigned int wwt = 0; /* Write-to-write turnaround for same CS */
18986c6e006aSYork Sun 	unsigned int trwt_mclk = 0;	/* ext_rwt */
18995614e71bSYork Sun 	unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */
19005614e71bSYork Sun 
190134e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
19025614e71bSYork Sun 	if (popts->burst_length == DDR_BL8) {
19035614e71bSYork Sun 		/* We set BL/2 for fixed BL8 */
19045614e71bSYork Sun 		rrt = 0;	/* BL/2 clocks */
19055614e71bSYork Sun 		wwt = 0;	/* BL/2 clocks */
19065614e71bSYork Sun 	} else {
19075614e71bSYork Sun 		/* We need to set BL/2 + 2 to BC4 and OTF */
19085614e71bSYork Sun 		rrt = 2;	/* BL/2 + 2 clocks */
19095614e71bSYork Sun 		wwt = 2;	/* BL/2 + 2 clocks */
19105614e71bSYork Sun 	}
191134e026f9SYork Sun #endif
191234e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
191334e026f9SYork Sun 	dll_lock = 2;	/* tDLLK = 1024 clocks */
191434e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
19155614e71bSYork Sun 	dll_lock = 1;	/* tDLLK = 512 clocks from spec */
19165614e71bSYork Sun #endif
19176c6e006aSYork Sun 
19186c6e006aSYork Sun 	if (popts->trwt_override)
19196c6e006aSYork Sun 		trwt_mclk = popts->trwt;
19206c6e006aSYork Sun 
19215614e71bSYork Sun 	ddr->timing_cfg_4 = (0
19225614e71bSYork Sun 			     | ((rwt & 0xf) << 28)
19235614e71bSYork Sun 			     | ((wrt & 0xf) << 24)
19245614e71bSYork Sun 			     | ((rrt & 0xf) << 20)
19255614e71bSYork Sun 			     | ((wwt & 0xf) << 16)
19266c6e006aSYork Sun 			     | ((trwt_mclk & 0xc) << 12)
19275614e71bSYork Sun 			     | (dll_lock & 0x3)
19285614e71bSYork Sun 			     );
19295614e71bSYork Sun 	debug("FSLDDR: timing_cfg_4 = 0x%08x\n", ddr->timing_cfg_4);
19305614e71bSYork Sun }
19315614e71bSYork Sun 
19325614e71bSYork Sun /* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */
19335614e71bSYork Sun static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency)
19345614e71bSYork Sun {
19355614e71bSYork Sun 	unsigned int rodt_on = 0;	/* Read to ODT on */
19365614e71bSYork Sun 	unsigned int rodt_off = 0;	/* Read to ODT off */
19375614e71bSYork Sun 	unsigned int wodt_on = 0;	/* Write to ODT on */
19385614e71bSYork Sun 	unsigned int wodt_off = 0;	/* Write to ODT off */
19395614e71bSYork Sun 
194034e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
194134e026f9SYork Sun 	unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
194234e026f9SYork Sun 			      ((ddr->timing_cfg_2 & 0x00040000) >> 14);
19435614e71bSYork Sun 	/* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
194434e026f9SYork Sun 	if (cas_latency >= wr_lat)
194534e026f9SYork Sun 		rodt_on = cas_latency - wr_lat + 1;
19465614e71bSYork Sun 	rodt_off = 4;	/*  4 clocks */
19475614e71bSYork Sun 	wodt_on = 1;	/*  1 clocks */
19485614e71bSYork Sun 	wodt_off = 4;	/*  4 clocks */
19495614e71bSYork Sun #endif
19505614e71bSYork Sun 
19515614e71bSYork Sun 	ddr->timing_cfg_5 = (0
19525614e71bSYork Sun 			     | ((rodt_on & 0x1f) << 24)
19535614e71bSYork Sun 			     | ((rodt_off & 0x7) << 20)
19545614e71bSYork Sun 			     | ((wodt_on & 0x1f) << 12)
19555614e71bSYork Sun 			     | ((wodt_off & 0x7) << 8)
19565614e71bSYork Sun 			     );
19575614e71bSYork Sun 	debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5);
19585614e71bSYork Sun }
19595614e71bSYork Sun 
196034e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
196134e026f9SYork Sun static void set_timing_cfg_6(fsl_ddr_cfg_regs_t *ddr)
196234e026f9SYork Sun {
196334e026f9SYork Sun 	unsigned int hs_caslat = 0;
196434e026f9SYork Sun 	unsigned int hs_wrlat = 0;
196534e026f9SYork Sun 	unsigned int hs_wrrec = 0;
196634e026f9SYork Sun 	unsigned int hs_clkadj = 0;
196734e026f9SYork Sun 	unsigned int hs_wrlvl_start = 0;
196834e026f9SYork Sun 
196934e026f9SYork Sun 	ddr->timing_cfg_6 = (0
197034e026f9SYork Sun 			     | ((hs_caslat & 0x1f) << 24)
197134e026f9SYork Sun 			     | ((hs_wrlat & 0x1f) << 19)
197234e026f9SYork Sun 			     | ((hs_wrrec & 0x1f) << 12)
197334e026f9SYork Sun 			     | ((hs_clkadj & 0x1f) << 6)
197434e026f9SYork Sun 			     | ((hs_wrlvl_start & 0x1f) << 0)
197534e026f9SYork Sun 			    );
197634e026f9SYork Sun 	debug("FSLDDR: timing_cfg_6 = 0x%08x\n", ddr->timing_cfg_6);
197734e026f9SYork Sun }
197834e026f9SYork Sun 
197903e664d8SYork Sun static void set_timing_cfg_7(const unsigned int ctrl_num,
198003e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
1981*426230a6SYork Sun 			     const memctl_options_t *popts,
198234e026f9SYork Sun 			     const common_timing_params_t *common_dimm)
198334e026f9SYork Sun {
198434e026f9SYork Sun 	unsigned int txpr, tcksre, tcksrx;
1985eb118807SShengzhou Liu 	unsigned int cke_rst, cksre, cksrx, par_lat = 0, cs_to_cmd;
1986eb118807SShengzhou Liu 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
198734e026f9SYork Sun 
198803e664d8SYork Sun 	txpr = max(5U, picos_to_mclk(ctrl_num, common_dimm->trfc1_ps + 10000));
198903e664d8SYork Sun 	tcksre = max(5U, picos_to_mclk(ctrl_num, 10000));
199003e664d8SYork Sun 	tcksrx = max(5U, picos_to_mclk(ctrl_num, 10000));
1991eb118807SShengzhou Liu 
1992*426230a6SYork Sun 	if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN &&
1993*426230a6SYork Sun 	    CONFIG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4) {
1994*426230a6SYork Sun 		/* for DDR4 only */
1995*426230a6SYork Sun 		par_lat = (popts->rcw_2 & 0xf) + 1;
1996*426230a6SYork Sun 		debug("PAR_LAT = %u for mclk_ps = %d\n", par_lat, mclk_ps);
1997eb118807SShengzhou Liu 	}
1998eb118807SShengzhou Liu 
199934e026f9SYork Sun 	cs_to_cmd = 0;
200034e026f9SYork Sun 
200134e026f9SYork Sun 	if (txpr <= 200)
200234e026f9SYork Sun 		cke_rst = 0;
200334e026f9SYork Sun 	else if (txpr <= 256)
200434e026f9SYork Sun 		cke_rst = 1;
200534e026f9SYork Sun 	else if (txpr <= 512)
200634e026f9SYork Sun 		cke_rst = 2;
200734e026f9SYork Sun 	else
200834e026f9SYork Sun 		cke_rst = 3;
200934e026f9SYork Sun 
201034e026f9SYork Sun 	if (tcksre <= 19)
201134e026f9SYork Sun 		cksre = tcksre - 5;
201234e026f9SYork Sun 	else
201334e026f9SYork Sun 		cksre = 15;
201434e026f9SYork Sun 
201534e026f9SYork Sun 	if (tcksrx <= 19)
201634e026f9SYork Sun 		cksrx = tcksrx - 5;
201734e026f9SYork Sun 	else
201834e026f9SYork Sun 		cksrx = 15;
201934e026f9SYork Sun 
202034e026f9SYork Sun 	ddr->timing_cfg_7 = (0
202134e026f9SYork Sun 			     | ((cke_rst & 0x3) << 28)
202234e026f9SYork Sun 			     | ((cksre & 0xf) << 24)
202334e026f9SYork Sun 			     | ((cksrx & 0xf) << 20)
202434e026f9SYork Sun 			     | ((par_lat & 0xf) << 16)
202534e026f9SYork Sun 			     | ((cs_to_cmd & 0xf) << 4)
202634e026f9SYork Sun 			    );
202734e026f9SYork Sun 	debug("FSLDDR: timing_cfg_7 = 0x%08x\n", ddr->timing_cfg_7);
202834e026f9SYork Sun }
202934e026f9SYork Sun 
203003e664d8SYork Sun static void set_timing_cfg_8(const unsigned int ctrl_num,
203103e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
203234e026f9SYork Sun 			     const memctl_options_t *popts,
203334e026f9SYork Sun 			     const common_timing_params_t *common_dimm,
203434e026f9SYork Sun 			     unsigned int cas_latency)
203534e026f9SYork Sun {
2036*426230a6SYork Sun 	int rwt_bg, wrt_bg, rrt_bg, wwt_bg;
203734e026f9SYork Sun 	unsigned int acttoact_bg, wrtord_bg, pre_all_rec;
2038*426230a6SYork Sun 	int tccdl = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps);
2039*426230a6SYork Sun 	int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
204034e026f9SYork Sun 		      ((ddr->timing_cfg_2 & 0x00040000) >> 14);
204134e026f9SYork Sun 
204234e026f9SYork Sun 	rwt_bg = cas_latency + 2 + 4 - wr_lat;
204334e026f9SYork Sun 	if (rwt_bg < tccdl)
204434e026f9SYork Sun 		rwt_bg = tccdl - rwt_bg;
204534e026f9SYork Sun 	else
204634e026f9SYork Sun 		rwt_bg = 0;
204734e026f9SYork Sun 
204834e026f9SYork Sun 	wrt_bg = wr_lat + 4 + 1 - cas_latency;
204934e026f9SYork Sun 	if (wrt_bg < tccdl)
205034e026f9SYork Sun 		wrt_bg = tccdl - wrt_bg;
205134e026f9SYork Sun 	else
205234e026f9SYork Sun 		wrt_bg = 0;
205334e026f9SYork Sun 
205434e026f9SYork Sun 	if (popts->burst_length == DDR_BL8) {
205534e026f9SYork Sun 		rrt_bg = tccdl - 4;
205634e026f9SYork Sun 		wwt_bg = tccdl - 4;
205734e026f9SYork Sun 	} else {
205834e026f9SYork Sun 		rrt_bg = tccdl - 2;
2059dc1437afSYork Sun 		wwt_bg = tccdl - 2;
206034e026f9SYork Sun 	}
206134e026f9SYork Sun 
206203e664d8SYork Sun 	acttoact_bg = picos_to_mclk(ctrl_num, common_dimm->trrdl_ps);
206303e664d8SYork Sun 	wrtord_bg = max(4U, picos_to_mclk(ctrl_num, 7500));
20643d75ec95SYork Sun 	if (popts->otf_burst_chop_en)
20653d75ec95SYork Sun 		wrtord_bg += 2;
20663d75ec95SYork Sun 
206734e026f9SYork Sun 	pre_all_rec = 0;
206834e026f9SYork Sun 
206934e026f9SYork Sun 	ddr->timing_cfg_8 = (0
207034e026f9SYork Sun 			     | ((rwt_bg & 0xf) << 28)
207134e026f9SYork Sun 			     | ((wrt_bg & 0xf) << 24)
207234e026f9SYork Sun 			     | ((rrt_bg & 0xf) << 20)
207334e026f9SYork Sun 			     | ((wwt_bg & 0xf) << 16)
207434e026f9SYork Sun 			     | ((acttoact_bg & 0xf) << 12)
207534e026f9SYork Sun 			     | ((wrtord_bg & 0xf) << 8)
207634e026f9SYork Sun 			     | ((pre_all_rec & 0x1f) << 0)
207734e026f9SYork Sun 			    );
207834e026f9SYork Sun 
207934e026f9SYork Sun 	debug("FSLDDR: timing_cfg_8 = 0x%08x\n", ddr->timing_cfg_8);
208034e026f9SYork Sun }
208134e026f9SYork Sun 
208234e026f9SYork Sun static void set_timing_cfg_9(fsl_ddr_cfg_regs_t *ddr)
208334e026f9SYork Sun {
208434e026f9SYork Sun 	ddr->timing_cfg_9 = 0;
208534e026f9SYork Sun 	debug("FSLDDR: timing_cfg_9 = 0x%08x\n", ddr->timing_cfg_9);
208634e026f9SYork Sun }
208734e026f9SYork Sun 
2088f80d6472SYork Sun /* This function needs to be called after set_ddr_sdram_cfg() is called */
208934e026f9SYork Sun static void set_ddr_dq_mapping(fsl_ddr_cfg_regs_t *ddr,
209034e026f9SYork Sun 			       const dimm_params_t *dimm_params)
209134e026f9SYork Sun {
2092f80d6472SYork Sun 	unsigned int acc_ecc_en = (ddr->ddr_sdram_cfg >> 2) & 0x1;
20936b95be22SYork Sun 	int i;
2094f80d6472SYork Sun 
20956b95be22SYork Sun 	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
20966b95be22SYork Sun 		if (dimm_params[i].n_ranks)
20976b95be22SYork Sun 			break;
20986b95be22SYork Sun 	}
20996b95be22SYork Sun 	if (i >= CONFIG_DIMM_SLOTS_PER_CTLR) {
21006b95be22SYork Sun 		puts("DDR error: no DIMM found!\n");
21016b95be22SYork Sun 		return;
21026b95be22SYork Sun 	}
210334e026f9SYork Sun 
21046b95be22SYork Sun 	ddr->dq_map_0 = ((dimm_params[i].dq_mapping[0] & 0x3F) << 26) |
21056b95be22SYork Sun 			((dimm_params[i].dq_mapping[1] & 0x3F) << 20) |
21066b95be22SYork Sun 			((dimm_params[i].dq_mapping[2] & 0x3F) << 14) |
21076b95be22SYork Sun 			((dimm_params[i].dq_mapping[3] & 0x3F) << 8) |
21086b95be22SYork Sun 			((dimm_params[i].dq_mapping[4] & 0x3F) << 2);
210934e026f9SYork Sun 
21106b95be22SYork Sun 	ddr->dq_map_1 = ((dimm_params[i].dq_mapping[5] & 0x3F) << 26) |
21116b95be22SYork Sun 			((dimm_params[i].dq_mapping[6] & 0x3F) << 20) |
21126b95be22SYork Sun 			((dimm_params[i].dq_mapping[7] & 0x3F) << 14) |
21136b95be22SYork Sun 			((dimm_params[i].dq_mapping[10] & 0x3F) << 8) |
21146b95be22SYork Sun 			((dimm_params[i].dq_mapping[11] & 0x3F) << 2);
21156b95be22SYork Sun 
21166b95be22SYork Sun 	ddr->dq_map_2 = ((dimm_params[i].dq_mapping[12] & 0x3F) << 26) |
21176b95be22SYork Sun 			((dimm_params[i].dq_mapping[13] & 0x3F) << 20) |
21186b95be22SYork Sun 			((dimm_params[i].dq_mapping[14] & 0x3F) << 14) |
21196b95be22SYork Sun 			((dimm_params[i].dq_mapping[15] & 0x3F) << 8) |
21206b95be22SYork Sun 			((dimm_params[i].dq_mapping[16] & 0x3F) << 2);
212134e026f9SYork Sun 
2122f80d6472SYork Sun 	/* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */
21236b95be22SYork Sun 	ddr->dq_map_3 = ((dimm_params[i].dq_mapping[17] & 0x3F) << 26) |
21246b95be22SYork Sun 			((dimm_params[i].dq_mapping[8] & 0x3F) << 20) |
2125f80d6472SYork Sun 			(acc_ecc_en ? 0 :
21266b95be22SYork Sun 			 (dimm_params[i].dq_mapping[9] & 0x3F) << 14) |
21276b95be22SYork Sun 			dimm_params[i].dq_mapping_ors;
212834e026f9SYork Sun 
212934e026f9SYork Sun 	debug("FSLDDR: dq_map_0 = 0x%08x\n", ddr->dq_map_0);
213034e026f9SYork Sun 	debug("FSLDDR: dq_map_1 = 0x%08x\n", ddr->dq_map_1);
213134e026f9SYork Sun 	debug("FSLDDR: dq_map_2 = 0x%08x\n", ddr->dq_map_2);
213234e026f9SYork Sun 	debug("FSLDDR: dq_map_3 = 0x%08x\n", ddr->dq_map_3);
213334e026f9SYork Sun }
213434e026f9SYork Sun static void set_ddr_sdram_cfg_3(fsl_ddr_cfg_regs_t *ddr,
213534e026f9SYork Sun 			       const memctl_options_t *popts)
213634e026f9SYork Sun {
213734e026f9SYork Sun 	int rd_pre;
213834e026f9SYork Sun 
213934e026f9SYork Sun 	rd_pre = popts->quad_rank_present ? 1 : 0;
214034e026f9SYork Sun 
214134e026f9SYork Sun 	ddr->ddr_sdram_cfg_3 = (rd_pre & 0x1) << 16;
2142*426230a6SYork Sun 	/* Disable MRS on parity error for RDIMMs */
2143*426230a6SYork Sun 	ddr->ddr_sdram_cfg_3 |= popts->registered_dimm_en ? 1 : 0;
214434e026f9SYork Sun 
214534e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_cfg_3 = 0x%08x\n", ddr->ddr_sdram_cfg_3);
214634e026f9SYork Sun }
214734e026f9SYork Sun #endif	/* CONFIG_SYS_FSL_DDR4 */
214834e026f9SYork Sun 
21495614e71bSYork Sun /* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */
21505614e71bSYork Sun static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
21515614e71bSYork Sun {
21525614e71bSYork Sun 	unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */
21535614e71bSYork Sun 	/* Normal Operation Full Calibration Time (tZQoper) */
21545614e71bSYork Sun 	unsigned int zqoper = 0;
21555614e71bSYork Sun 	/* Normal Operation Short Calibration Time (tZQCS) */
21565614e71bSYork Sun 	unsigned int zqcs = 0;
215734e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
215834e026f9SYork Sun 	unsigned int zqcs_init;
215934e026f9SYork Sun #endif
21605614e71bSYork Sun 
21615614e71bSYork Sun 	if (zq_en) {
216234e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
216334e026f9SYork Sun 		zqinit = 10;	/* 1024 clocks */
216434e026f9SYork Sun 		zqoper = 9;	/* 512 clocks */
216534e026f9SYork Sun 		zqcs = 7;	/* 128 clocks */
216634e026f9SYork Sun 		zqcs_init = 5;	/* 1024 refresh sequences */
216734e026f9SYork Sun #else
21685614e71bSYork Sun 		zqinit = 9;	/* 512 clocks */
21695614e71bSYork Sun 		zqoper = 8;	/* 256 clocks */
21705614e71bSYork Sun 		zqcs = 6;	/* 64 clocks */
217134e026f9SYork Sun #endif
21725614e71bSYork Sun 	}
21735614e71bSYork Sun 
21745614e71bSYork Sun 	ddr->ddr_zq_cntl = (0
21755614e71bSYork Sun 			    | ((zq_en & 0x1) << 31)
21765614e71bSYork Sun 			    | ((zqinit & 0xF) << 24)
21775614e71bSYork Sun 			    | ((zqoper & 0xF) << 16)
21785614e71bSYork Sun 			    | ((zqcs & 0xF) << 8)
217934e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
218034e026f9SYork Sun 			    | ((zqcs_init & 0xF) << 0)
218134e026f9SYork Sun #endif
21825614e71bSYork Sun 			    );
21835614e71bSYork Sun 	debug("FSLDDR: zq_cntl = 0x%08x\n", ddr->ddr_zq_cntl);
21845614e71bSYork Sun }
21855614e71bSYork Sun 
21865614e71bSYork Sun /* DDR Write Leveling Control (DDR_WRLVL_CNTL) */
21875614e71bSYork Sun static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en,
21885614e71bSYork Sun 				const memctl_options_t *popts)
21895614e71bSYork Sun {
21905614e71bSYork Sun 	/*
21915614e71bSYork Sun 	 * First DQS pulse rising edge after margining mode
21925614e71bSYork Sun 	 * is programmed (tWL_MRD)
21935614e71bSYork Sun 	 */
21945614e71bSYork Sun 	unsigned int wrlvl_mrd = 0;
21955614e71bSYork Sun 	/* ODT delay after margining mode is programmed (tWL_ODTEN) */
21965614e71bSYork Sun 	unsigned int wrlvl_odten = 0;
21975614e71bSYork Sun 	/* DQS/DQS_ delay after margining mode is programmed (tWL_DQSEN) */
21985614e71bSYork Sun 	unsigned int wrlvl_dqsen = 0;
21995614e71bSYork Sun 	/* WRLVL_SMPL: Write leveling sample time */
22005614e71bSYork Sun 	unsigned int wrlvl_smpl = 0;
22015614e71bSYork Sun 	/* WRLVL_WLR: Write leveling repeition time */
22025614e71bSYork Sun 	unsigned int wrlvl_wlr = 0;
22035614e71bSYork Sun 	/* WRLVL_START: Write leveling start time */
22045614e71bSYork Sun 	unsigned int wrlvl_start = 0;
22055614e71bSYork Sun 
22065614e71bSYork Sun 	/* suggest enable write leveling for DDR3 due to fly-by topology */
22075614e71bSYork Sun 	if (wrlvl_en) {
22085614e71bSYork Sun 		/* tWL_MRD min = 40 nCK, we set it 64 */
22095614e71bSYork Sun 		wrlvl_mrd = 0x6;
22105614e71bSYork Sun 		/* tWL_ODTEN 128 */
22115614e71bSYork Sun 		wrlvl_odten = 0x7;
22125614e71bSYork Sun 		/* tWL_DQSEN min = 25 nCK, we set it 32 */
22135614e71bSYork Sun 		wrlvl_dqsen = 0x5;
22145614e71bSYork Sun 		/*
22155614e71bSYork Sun 		 * Write leveling sample time at least need 6 clocks
22165614e71bSYork Sun 		 * higher than tWLO to allow enough time for progagation
22175614e71bSYork Sun 		 * delay and sampling the prime data bits.
22185614e71bSYork Sun 		 */
22195614e71bSYork Sun 		wrlvl_smpl = 0xf;
22205614e71bSYork Sun 		/*
22215614e71bSYork Sun 		 * Write leveling repetition time
22225614e71bSYork Sun 		 * at least tWLO + 6 clocks clocks
22235614e71bSYork Sun 		 * we set it 64
22245614e71bSYork Sun 		 */
22255614e71bSYork Sun 		wrlvl_wlr = 0x6;
22265614e71bSYork Sun 		/*
22275614e71bSYork Sun 		 * Write leveling start time
22285614e71bSYork Sun 		 * The value use for the DQS_ADJUST for the first sample
22295614e71bSYork Sun 		 * when write leveling is enabled. It probably needs to be
223062a3b7ddSRobert P. J. Day 		 * overridden per platform.
22315614e71bSYork Sun 		 */
22325614e71bSYork Sun 		wrlvl_start = 0x8;
22335614e71bSYork Sun 		/*
22345614e71bSYork Sun 		 * Override the write leveling sample and start time
22355614e71bSYork Sun 		 * according to specific board
22365614e71bSYork Sun 		 */
22375614e71bSYork Sun 		if (popts->wrlvl_override) {
22385614e71bSYork Sun 			wrlvl_smpl = popts->wrlvl_sample;
22395614e71bSYork Sun 			wrlvl_start = popts->wrlvl_start;
22405614e71bSYork Sun 		}
22415614e71bSYork Sun 	}
22425614e71bSYork Sun 
22435614e71bSYork Sun 	ddr->ddr_wrlvl_cntl = (0
22445614e71bSYork Sun 			       | ((wrlvl_en & 0x1) << 31)
22455614e71bSYork Sun 			       | ((wrlvl_mrd & 0x7) << 24)
22465614e71bSYork Sun 			       | ((wrlvl_odten & 0x7) << 20)
22475614e71bSYork Sun 			       | ((wrlvl_dqsen & 0x7) << 16)
22485614e71bSYork Sun 			       | ((wrlvl_smpl & 0xf) << 12)
22495614e71bSYork Sun 			       | ((wrlvl_wlr & 0x7) << 8)
22505614e71bSYork Sun 			       | ((wrlvl_start & 0x1F) << 0)
22515614e71bSYork Sun 			       );
22525614e71bSYork Sun 	debug("FSLDDR: wrlvl_cntl = 0x%08x\n", ddr->ddr_wrlvl_cntl);
22535614e71bSYork Sun 	ddr->ddr_wrlvl_cntl_2 = popts->wrlvl_ctl_2;
22545614e71bSYork Sun 	debug("FSLDDR: wrlvl_cntl_2 = 0x%08x\n", ddr->ddr_wrlvl_cntl_2);
22555614e71bSYork Sun 	ddr->ddr_wrlvl_cntl_3 = popts->wrlvl_ctl_3;
22565614e71bSYork Sun 	debug("FSLDDR: wrlvl_cntl_3 = 0x%08x\n", ddr->ddr_wrlvl_cntl_3);
22575614e71bSYork Sun 
22585614e71bSYork Sun }
22595614e71bSYork Sun 
22605614e71bSYork Sun /* DDR Self Refresh Counter (DDR_SR_CNTR) */
22615614e71bSYork Sun static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr, unsigned int sr_it)
22625614e71bSYork Sun {
22635614e71bSYork Sun 	/* Self Refresh Idle Threshold */
22645614e71bSYork Sun 	ddr->ddr_sr_cntr = (sr_it & 0xF) << 16;
22655614e71bSYork Sun }
22665614e71bSYork Sun 
22675614e71bSYork Sun static void set_ddr_eor(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
22685614e71bSYork Sun {
22695614e71bSYork Sun 	if (popts->addr_hash) {
22705614e71bSYork Sun 		ddr->ddr_eor = 0x40000000;	/* address hash enable */
22715614e71bSYork Sun 		puts("Address hashing enabled.\n");
22725614e71bSYork Sun 	}
22735614e71bSYork Sun }
22745614e71bSYork Sun 
22755614e71bSYork Sun static void set_ddr_cdr1(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
22765614e71bSYork Sun {
22775614e71bSYork Sun 	ddr->ddr_cdr1 = popts->ddr_cdr1;
22785614e71bSYork Sun 	debug("FSLDDR: ddr_cdr1 = 0x%08x\n", ddr->ddr_cdr1);
22795614e71bSYork Sun }
22805614e71bSYork Sun 
22815614e71bSYork Sun static void set_ddr_cdr2(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
22825614e71bSYork Sun {
22835614e71bSYork Sun 	ddr->ddr_cdr2 = popts->ddr_cdr2;
22845614e71bSYork Sun 	debug("FSLDDR: ddr_cdr2 = 0x%08x\n", ddr->ddr_cdr2);
22855614e71bSYork Sun }
22865614e71bSYork Sun 
22875614e71bSYork Sun unsigned int
22885614e71bSYork Sun check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
22895614e71bSYork Sun {
22905614e71bSYork Sun 	unsigned int res = 0;
22915614e71bSYork Sun 
22925614e71bSYork Sun 	/*
22935614e71bSYork Sun 	 * Check that DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] are
22945614e71bSYork Sun 	 * not set at the same time.
22955614e71bSYork Sun 	 */
22965614e71bSYork Sun 	if (ddr->ddr_sdram_cfg & 0x10000000
22975614e71bSYork Sun 	    && ddr->ddr_sdram_cfg & 0x00008000) {
22985614e71bSYork Sun 		printf("Error: DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] "
22995614e71bSYork Sun 				" should not be set at the same time.\n");
23005614e71bSYork Sun 		res++;
23015614e71bSYork Sun 	}
23025614e71bSYork Sun 
23035614e71bSYork Sun 	return res;
23045614e71bSYork Sun }
23055614e71bSYork Sun 
23065614e71bSYork Sun unsigned int
230703e664d8SYork Sun compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
230803e664d8SYork Sun 			       const memctl_options_t *popts,
23095614e71bSYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
23105614e71bSYork Sun 			       const common_timing_params_t *common_dimm,
23115614e71bSYork Sun 			       const dimm_params_t *dimm_params,
23125614e71bSYork Sun 			       unsigned int dbw_cap_adj,
23135614e71bSYork Sun 			       unsigned int size_only)
23145614e71bSYork Sun {
23155614e71bSYork Sun 	unsigned int i;
23165614e71bSYork Sun 	unsigned int cas_latency;
23175614e71bSYork Sun 	unsigned int additive_latency;
23185614e71bSYork Sun 	unsigned int sr_it;
23195614e71bSYork Sun 	unsigned int zq_en;
23205614e71bSYork Sun 	unsigned int wrlvl_en;
23215614e71bSYork Sun 	unsigned int ip_rev = 0;
23225614e71bSYork Sun 	unsigned int unq_mrs_en = 0;
23235614e71bSYork Sun 	int cs_en = 1;
232402fb2761SShengzhou Liu #ifdef CONFIG_SYS_FSL_ERRATUM_A009942
232502fb2761SShengzhou Liu 	unsigned int ddr_freq;
232602fb2761SShengzhou Liu #endif
232702fb2761SShengzhou Liu #if (defined(CONFIG_SYS_FSL_ERRATUM_A008378) && \
232802fb2761SShengzhou Liu 	defined(CONFIG_SYS_FSL_DDRC_GEN4)) || \
232902fb2761SShengzhou Liu 	defined(CONFIG_SYS_FSL_ERRATUM_A009942)
233002fb2761SShengzhou Liu 	struct ccsr_ddr __iomem *ddrc;
233102fb2761SShengzhou Liu 
233202fb2761SShengzhou Liu 	switch (ctrl_num) {
233302fb2761SShengzhou Liu 	case 0:
233402fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR_ADDR;
233502fb2761SShengzhou Liu 		break;
233651370d56SYork Sun #if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 1)
233702fb2761SShengzhou Liu 	case 1:
233802fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR2_ADDR;
233902fb2761SShengzhou Liu 		break;
234002fb2761SShengzhou Liu #endif
234151370d56SYork Sun #if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 2)
234202fb2761SShengzhou Liu 	case 2:
234302fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR3_ADDR;
234402fb2761SShengzhou Liu 		break;
234502fb2761SShengzhou Liu #endif
234651370d56SYork Sun #if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 3)
234702fb2761SShengzhou Liu 	case 3:
234802fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR4_ADDR;
234902fb2761SShengzhou Liu 		break;
235002fb2761SShengzhou Liu #endif
235102fb2761SShengzhou Liu 	default:
235202fb2761SShengzhou Liu 		printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num);
235302fb2761SShengzhou Liu 		return 1;
235402fb2761SShengzhou Liu 	}
235502fb2761SShengzhou Liu #endif
23565614e71bSYork Sun 
23575614e71bSYork Sun 	memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t));
23585614e71bSYork Sun 
23595614e71bSYork Sun 	if (common_dimm == NULL) {
23605614e71bSYork Sun 		printf("Error: subset DIMM params struct null pointer\n");
23615614e71bSYork Sun 		return 1;
23625614e71bSYork Sun 	}
23635614e71bSYork Sun 
23645614e71bSYork Sun 	/*
23655614e71bSYork Sun 	 * Process overrides first.
23665614e71bSYork Sun 	 *
23675614e71bSYork Sun 	 * FIXME: somehow add dereated caslat to this
23685614e71bSYork Sun 	 */
23695614e71bSYork Sun 	cas_latency = (popts->cas_latency_override)
23705614e71bSYork Sun 		? popts->cas_latency_override_value
237134e026f9SYork Sun 		: common_dimm->lowest_common_spd_caslat;
23725614e71bSYork Sun 
23735614e71bSYork Sun 	additive_latency = (popts->additive_latency_override)
23745614e71bSYork Sun 		? popts->additive_latency_override_value
23755614e71bSYork Sun 		: common_dimm->additive_latency;
23765614e71bSYork Sun 
23775614e71bSYork Sun 	sr_it = (popts->auto_self_refresh_en)
23785614e71bSYork Sun 		? popts->sr_it
23795614e71bSYork Sun 		: 0;
23805614e71bSYork Sun 	/* ZQ calibration */
23815614e71bSYork Sun 	zq_en = (popts->zq_en) ? 1 : 0;
23825614e71bSYork Sun 	/* write leveling */
23835614e71bSYork Sun 	wrlvl_en = (popts->wrlvl_en) ? 1 : 0;
23845614e71bSYork Sun 
23855614e71bSYork Sun 	/* Chip Select Memory Bounds (CSn_BNDS) */
23865614e71bSYork Sun 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
23875614e71bSYork Sun 		unsigned long long ea, sa;
23885614e71bSYork Sun 		unsigned int cs_per_dimm
23895614e71bSYork Sun 			= CONFIG_CHIP_SELECTS_PER_CTRL / CONFIG_DIMM_SLOTS_PER_CTLR;
23905614e71bSYork Sun 		unsigned int dimm_number
23915614e71bSYork Sun 			= i / cs_per_dimm;
23925614e71bSYork Sun 		unsigned long long rank_density
23935614e71bSYork Sun 			= dimm_params[dimm_number].rank_density >> dbw_cap_adj;
23945614e71bSYork Sun 
23955614e71bSYork Sun 		if (dimm_params[dimm_number].n_ranks == 0) {
23965614e71bSYork Sun 			debug("Skipping setup of CS%u "
23975614e71bSYork Sun 				"because n_ranks on DIMM %u is 0\n", i, dimm_number);
23985614e71bSYork Sun 			continue;
23995614e71bSYork Sun 		}
24005614e71bSYork Sun 		if (popts->memctl_interleaving) {
24015614e71bSYork Sun 			switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
24025614e71bSYork Sun 			case FSL_DDR_CS0_CS1_CS2_CS3:
24035614e71bSYork Sun 				break;
24045614e71bSYork Sun 			case FSL_DDR_CS0_CS1:
24055614e71bSYork Sun 			case FSL_DDR_CS0_CS1_AND_CS2_CS3:
24065614e71bSYork Sun 				if (i > 1)
24075614e71bSYork Sun 					cs_en = 0;
24085614e71bSYork Sun 				break;
24095614e71bSYork Sun 			case FSL_DDR_CS2_CS3:
24105614e71bSYork Sun 			default:
24115614e71bSYork Sun 				if (i > 0)
24125614e71bSYork Sun 					cs_en = 0;
24135614e71bSYork Sun 				break;
24145614e71bSYork Sun 			}
24155614e71bSYork Sun 			sa = common_dimm->base_address;
24165614e71bSYork Sun 			ea = sa + common_dimm->total_mem - 1;
24175614e71bSYork Sun 		} else if (!popts->memctl_interleaving) {
24185614e71bSYork Sun 			/*
24195614e71bSYork Sun 			 * If memory interleaving between controllers is NOT
24205614e71bSYork Sun 			 * enabled, the starting address for each memory
24215614e71bSYork Sun 			 * controller is distinct.  However, because rank
24225614e71bSYork Sun 			 * interleaving is enabled, the starting and ending
24235614e71bSYork Sun 			 * addresses of the total memory on that memory
24245614e71bSYork Sun 			 * controller needs to be programmed into its
24255614e71bSYork Sun 			 * respective CS0_BNDS.
24265614e71bSYork Sun 			 */
24275614e71bSYork Sun 			switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
24285614e71bSYork Sun 			case FSL_DDR_CS0_CS1_CS2_CS3:
24295614e71bSYork Sun 				sa = common_dimm->base_address;
24305614e71bSYork Sun 				ea = sa + common_dimm->total_mem - 1;
24315614e71bSYork Sun 				break;
24325614e71bSYork Sun 			case FSL_DDR_CS0_CS1_AND_CS2_CS3:
24335614e71bSYork Sun 				if ((i >= 2) && (dimm_number == 0)) {
24345614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address +
24355614e71bSYork Sun 					      2 * rank_density;
24365614e71bSYork Sun 					ea = sa + 2 * rank_density - 1;
24375614e71bSYork Sun 				} else {
24385614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address;
24395614e71bSYork Sun 					ea = sa + 2 * rank_density - 1;
24405614e71bSYork Sun 				}
24415614e71bSYork Sun 				break;
24425614e71bSYork Sun 			case FSL_DDR_CS0_CS1:
24435614e71bSYork Sun 				if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
24445614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address;
24455614e71bSYork Sun 					ea = sa + rank_density - 1;
24465614e71bSYork Sun 					if (i != 1)
24475614e71bSYork Sun 						sa += (i % cs_per_dimm) * rank_density;
24485614e71bSYork Sun 					ea += (i % cs_per_dimm) * rank_density;
24495614e71bSYork Sun 				} else {
24505614e71bSYork Sun 					sa = 0;
24515614e71bSYork Sun 					ea = 0;
24525614e71bSYork Sun 				}
24535614e71bSYork Sun 				if (i == 0)
24545614e71bSYork Sun 					ea += rank_density;
24555614e71bSYork Sun 				break;
24565614e71bSYork Sun 			case FSL_DDR_CS2_CS3:
24575614e71bSYork Sun 				if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
24585614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address;
24595614e71bSYork Sun 					ea = sa + rank_density - 1;
24605614e71bSYork Sun 					if (i != 3)
24615614e71bSYork Sun 						sa += (i % cs_per_dimm) * rank_density;
24625614e71bSYork Sun 					ea += (i % cs_per_dimm) * rank_density;
24635614e71bSYork Sun 				} else {
24645614e71bSYork Sun 					sa = 0;
24655614e71bSYork Sun 					ea = 0;
24665614e71bSYork Sun 				}
24675614e71bSYork Sun 				if (i == 2)
24685614e71bSYork Sun 					ea += (rank_density >> dbw_cap_adj);
24695614e71bSYork Sun 				break;
24705614e71bSYork Sun 			default:  /* No bank(chip-select) interleaving */
24715614e71bSYork Sun 				sa = dimm_params[dimm_number].base_address;
24725614e71bSYork Sun 				ea = sa + rank_density - 1;
24735614e71bSYork Sun 				if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
24745614e71bSYork Sun 					sa += (i % cs_per_dimm) * rank_density;
24755614e71bSYork Sun 					ea += (i % cs_per_dimm) * rank_density;
24765614e71bSYork Sun 				} else {
24775614e71bSYork Sun 					sa = 0;
24785614e71bSYork Sun 					ea = 0;
24795614e71bSYork Sun 				}
24805614e71bSYork Sun 				break;
24815614e71bSYork Sun 			}
24825614e71bSYork Sun 		}
24835614e71bSYork Sun 
24845614e71bSYork Sun 		sa >>= 24;
24855614e71bSYork Sun 		ea >>= 24;
24865614e71bSYork Sun 
24875614e71bSYork Sun 		if (cs_en) {
24885614e71bSYork Sun 			ddr->cs[i].bnds = (0
2489d4263b8aSYork Sun 				| ((sa & 0xffff) << 16) /* starting address */
2490d4263b8aSYork Sun 				| ((ea & 0xffff) << 0)	/* ending address */
24915614e71bSYork Sun 				);
24925614e71bSYork Sun 		} else {
24935614e71bSYork Sun 			/* setting bnds to 0xffffffff for inactive CS */
24945614e71bSYork Sun 			ddr->cs[i].bnds = 0xffffffff;
24955614e71bSYork Sun 		}
24965614e71bSYork Sun 
24975614e71bSYork Sun 		debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds);
24985614e71bSYork Sun 		set_csn_config(dimm_number, i, ddr, popts, dimm_params);
24995614e71bSYork Sun 		set_csn_config_2(i, ddr);
25005614e71bSYork Sun 	}
25015614e71bSYork Sun 
25025614e71bSYork Sun 	/*
25035614e71bSYork Sun 	 * In the case we only need to compute the ddr sdram size, we only need
25045614e71bSYork Sun 	 * to set csn registers, so return from here.
25055614e71bSYork Sun 	 */
25065614e71bSYork Sun 	if (size_only)
25075614e71bSYork Sun 		return 0;
25085614e71bSYork Sun 
25095614e71bSYork Sun 	set_ddr_eor(ddr, popts);
25105614e71bSYork Sun 
25115614e71bSYork Sun #if !defined(CONFIG_SYS_FSL_DDR1)
251203e664d8SYork Sun 	set_timing_cfg_0(ctrl_num, ddr, popts, dimm_params);
25135614e71bSYork Sun #endif
25145614e71bSYork Sun 
251503e664d8SYork Sun 	set_timing_cfg_3(ctrl_num, ddr, popts, common_dimm, cas_latency,
2516d4263b8aSYork Sun 			 additive_latency);
251703e664d8SYork Sun 	set_timing_cfg_1(ctrl_num, ddr, popts, common_dimm, cas_latency);
251803e664d8SYork Sun 	set_timing_cfg_2(ctrl_num, ddr, popts, common_dimm,
25195614e71bSYork Sun 			 cas_latency, additive_latency);
25205614e71bSYork Sun 
25215614e71bSYork Sun 	set_ddr_cdr1(ddr, popts);
25225614e71bSYork Sun 	set_ddr_cdr2(ddr, popts);
25235614e71bSYork Sun 	set_ddr_sdram_cfg(ddr, popts, common_dimm);
252466869f95SYork Sun 	ip_rev = fsl_ddr_get_version(ctrl_num);
25255614e71bSYork Sun 	if (ip_rev > 0x40400)
25265614e71bSYork Sun 		unq_mrs_en = 1;
25275614e71bSYork Sun 
2528f80d6472SYork Sun 	if ((ip_rev > 0x40700) && (popts->cswl_override != 0))
2529ef87cab6SYork Sun 		ddr->debug[18] = popts->cswl_override;
2530ef87cab6SYork Sun 
253103e664d8SYork Sun 	set_ddr_sdram_cfg_2(ctrl_num, ddr, popts, unq_mrs_en);
253203e664d8SYork Sun 	set_ddr_sdram_mode(ctrl_num, ddr, popts, common_dimm,
25335614e71bSYork Sun 			   cas_latency, additive_latency, unq_mrs_en);
253403e664d8SYork Sun 	set_ddr_sdram_mode_2(ctrl_num, ddr, popts, common_dimm, unq_mrs_en);
253534e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
253634e026f9SYork Sun 	set_ddr_sdram_mode_9(ddr, popts, common_dimm, unq_mrs_en);
253703e664d8SYork Sun 	set_ddr_sdram_mode_10(ctrl_num, ddr, popts, common_dimm, unq_mrs_en);
253834e026f9SYork Sun #endif
253903e664d8SYork Sun 	set_ddr_sdram_interval(ctrl_num, ddr, popts, common_dimm);
25405614e71bSYork Sun 	set_ddr_data_init(ddr);
25415614e71bSYork Sun 	set_ddr_sdram_clk_cntl(ddr, popts);
25425614e71bSYork Sun 	set_ddr_init_addr(ddr);
25435614e71bSYork Sun 	set_ddr_init_ext_addr(ddr);
25445614e71bSYork Sun 	set_timing_cfg_4(ddr, popts);
25455614e71bSYork Sun 	set_timing_cfg_5(ddr, cas_latency);
254634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
254734e026f9SYork Sun 	set_ddr_sdram_cfg_3(ddr, popts);
254834e026f9SYork Sun 	set_timing_cfg_6(ddr);
2549*426230a6SYork Sun 	set_timing_cfg_7(ctrl_num, ddr, popts, common_dimm);
255003e664d8SYork Sun 	set_timing_cfg_8(ctrl_num, ddr, popts, common_dimm, cas_latency);
255134e026f9SYork Sun 	set_timing_cfg_9(ddr);
255234e026f9SYork Sun 	set_ddr_dq_mapping(ddr, dimm_params);
255334e026f9SYork Sun #endif
25545614e71bSYork Sun 
25555614e71bSYork Sun 	set_ddr_zq_cntl(ddr, zq_en);
25565614e71bSYork Sun 	set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts);
25575614e71bSYork Sun 
25585614e71bSYork Sun 	set_ddr_sr_cntr(ddr, sr_it);
25595614e71bSYork Sun 
25605614e71bSYork Sun 	set_ddr_sdram_rcw(ddr, popts, common_dimm);
25615614e71bSYork Sun 
25625614e71bSYork Sun #ifdef CONFIG_SYS_FSL_DDR_EMU
25635614e71bSYork Sun 	/* disble DDR training for emulator */
25645614e71bSYork Sun 	ddr->debug[2] = 0x00000400;
25651f3402e7SYork Sun 	ddr->debug[4] = 0xff800800;
25661f3402e7SYork Sun 	ddr->debug[5] = 0x08000800;
25671f3402e7SYork Sun 	ddr->debug[6] = 0x08000800;
25681f3402e7SYork Sun 	ddr->debug[7] = 0x08000800;
25691f3402e7SYork Sun 	ddr->debug[8] = 0x08000800;
25705614e71bSYork Sun #endif
25719855b3beSYork Sun #ifdef CONFIG_SYS_FSL_ERRATUM_A004508
25729855b3beSYork Sun 	if ((ip_rev >= 0x40000) && (ip_rev < 0x40400))
25739855b3beSYork Sun 		ddr->debug[2] |= 0x00000200;	/* set bit 22 */
25749855b3beSYork Sun #endif
25759855b3beSYork Sun 
257602fb2761SShengzhou Liu #if defined(CONFIG_SYS_FSL_ERRATUM_A008378) && defined(CONFIG_SYS_FSL_DDRC_GEN4)
257702fb2761SShengzhou Liu 	/* Erratum applies when accumulated ECC is used, or DBI is enabled */
257802fb2761SShengzhou Liu #define IS_ACC_ECC_EN(v) ((v) & 0x4)
257902fb2761SShengzhou Liu #define IS_DBI(v) ((((v) >> 12) & 0x3) == 0x2)
258002fb2761SShengzhou Liu 	if (has_erratum_a008378()) {
258102fb2761SShengzhou Liu 		if (IS_ACC_ECC_EN(ddr->ddr_sdram_cfg) ||
258202fb2761SShengzhou Liu 		    IS_DBI(ddr->ddr_sdram_cfg_3)) {
258302fb2761SShengzhou Liu 			ddr->debug[28] = ddr_in32(&ddrc->debug[28]);
258402fb2761SShengzhou Liu 			ddr->debug[28] |= (0x9 << 20);
258502fb2761SShengzhou Liu 		}
258602fb2761SShengzhou Liu 	}
258702fb2761SShengzhou Liu #endif
258802fb2761SShengzhou Liu 
258902fb2761SShengzhou Liu #ifdef CONFIG_SYS_FSL_ERRATUM_A009942
259002fb2761SShengzhou Liu 	ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
259102fb2761SShengzhou Liu 	ddr->debug[28] |= ddr_in32(&ddrc->debug[28]);
259202fb2761SShengzhou Liu 	ddr->debug[28] &= 0xff0fff00;
259302fb2761SShengzhou Liu 	if (ddr_freq <= 1333)
259402fb2761SShengzhou Liu 		ddr->debug[28] |= 0x0080006a;
259502fb2761SShengzhou Liu 	else if (ddr_freq <= 1600)
259602fb2761SShengzhou Liu 		ddr->debug[28] |= 0x0070006f;
259702fb2761SShengzhou Liu 	else if (ddr_freq <= 1867)
259802fb2761SShengzhou Liu 		ddr->debug[28] |= 0x00700076;
259902fb2761SShengzhou Liu 	else if (ddr_freq <= 2133)
260002fb2761SShengzhou Liu 		ddr->debug[28] |= 0x0060007b;
260102fb2761SShengzhou Liu 	if (popts->cpo_sample)
260202fb2761SShengzhou Liu 		ddr->debug[28] = (ddr->debug[28] & 0xffffff00) |
260302fb2761SShengzhou Liu 				  popts->cpo_sample;
260402fb2761SShengzhou Liu #endif
260502fb2761SShengzhou Liu 
26065614e71bSYork Sun 	return check_fsl_memctl_config_regs(ddr);
26075614e71bSYork Sun }
260802fb2761SShengzhou Liu 
260902fb2761SShengzhou Liu #ifdef CONFIG_SYS_FSL_ERRATUM_A009942
261002fb2761SShengzhou Liu /*
261102fb2761SShengzhou Liu  * This additional workaround of A009942 checks the condition to determine if
261202fb2761SShengzhou Liu  * the CPO value set by the existing A009942 workaround needs to be updated.
261302fb2761SShengzhou Liu  * If need, print a warning to prompt user reconfigure DDR debug_29[24:31] with
261402fb2761SShengzhou Liu  * expected optimal value, the optimal value is highly board dependent.
261502fb2761SShengzhou Liu  */
261602fb2761SShengzhou Liu void erratum_a009942_check_cpo(void)
261702fb2761SShengzhou Liu {
261802fb2761SShengzhou Liu 	struct ccsr_ddr __iomem *ddr =
261902fb2761SShengzhou Liu 		(struct ccsr_ddr __iomem *)(CONFIG_SYS_FSL_DDR_ADDR);
262002fb2761SShengzhou Liu 	u32 cpo, cpo_e, cpo_o, cpo_target, cpo_optimal;
262102fb2761SShengzhou Liu 	u32 cpo_min = ddr_in32(&ddr->debug[9]) >> 24;
262202fb2761SShengzhou Liu 	u32 cpo_max = cpo_min;
262302fb2761SShengzhou Liu 	u32 sdram_cfg, i, tmp, lanes, ddr_type;
262402fb2761SShengzhou Liu 	bool update_cpo = false, has_ecc = false;
262502fb2761SShengzhou Liu 
262602fb2761SShengzhou Liu 	sdram_cfg = ddr_in32(&ddr->sdram_cfg);
262702fb2761SShengzhou Liu 	if (sdram_cfg & SDRAM_CFG_32_BE)
262802fb2761SShengzhou Liu 		lanes = 4;
262902fb2761SShengzhou Liu 	else if (sdram_cfg & SDRAM_CFG_16_BE)
263002fb2761SShengzhou Liu 		lanes = 2;
263102fb2761SShengzhou Liu 	else
263202fb2761SShengzhou Liu 		lanes = 8;
263302fb2761SShengzhou Liu 
263402fb2761SShengzhou Liu 	if (sdram_cfg & SDRAM_CFG_ECC_EN)
263502fb2761SShengzhou Liu 		has_ecc = true;
263602fb2761SShengzhou Liu 
263702fb2761SShengzhou Liu 	/* determine the maximum and minimum CPO values */
263802fb2761SShengzhou Liu 	for (i = 9; i < 9 + lanes / 2; i++) {
263902fb2761SShengzhou Liu 		cpo = ddr_in32(&ddr->debug[i]);
264002fb2761SShengzhou Liu 		cpo_e = cpo >> 24;
264102fb2761SShengzhou Liu 		cpo_o = (cpo >> 8) & 0xff;
264202fb2761SShengzhou Liu 		tmp = min(cpo_e, cpo_o);
264302fb2761SShengzhou Liu 		if (tmp < cpo_min)
264402fb2761SShengzhou Liu 			cpo_min = tmp;
264502fb2761SShengzhou Liu 		tmp = max(cpo_e, cpo_o);
264602fb2761SShengzhou Liu 		if (tmp > cpo_max)
264702fb2761SShengzhou Liu 			cpo_max = tmp;
264802fb2761SShengzhou Liu 	}
264902fb2761SShengzhou Liu 
265002fb2761SShengzhou Liu 	if (has_ecc) {
265102fb2761SShengzhou Liu 		cpo = ddr_in32(&ddr->debug[13]);
265202fb2761SShengzhou Liu 		cpo = cpo >> 24;
265302fb2761SShengzhou Liu 		if (cpo < cpo_min)
265402fb2761SShengzhou Liu 			cpo_min = cpo;
265502fb2761SShengzhou Liu 		if (cpo > cpo_max)
265602fb2761SShengzhou Liu 			cpo_max = cpo;
265702fb2761SShengzhou Liu 	}
265802fb2761SShengzhou Liu 
265902fb2761SShengzhou Liu 	cpo_target = ddr_in32(&ddr->debug[28]) & 0xff;
266002fb2761SShengzhou Liu 	cpo_optimal = ((cpo_max + cpo_min) >> 1) + 0x27;
266102fb2761SShengzhou Liu 	debug("cpo_optimal = 0x%x, cpo_target = 0x%x\n", cpo_optimal,
266202fb2761SShengzhou Liu 	      cpo_target);
266302fb2761SShengzhou Liu 	debug("cpo_max = 0x%x, cpo_min = 0x%x\n", cpo_max, cpo_min);
266402fb2761SShengzhou Liu 
266502fb2761SShengzhou Liu 	ddr_type = (sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
266602fb2761SShengzhou Liu 		    SDRAM_CFG_SDRAM_TYPE_SHIFT;
266702fb2761SShengzhou Liu 	if (ddr_type == SDRAM_TYPE_DDR4)
266802fb2761SShengzhou Liu 		update_cpo = (cpo_min + 0x3b) < cpo_target ? true : false;
266902fb2761SShengzhou Liu 	else if (ddr_type == SDRAM_TYPE_DDR3)
267002fb2761SShengzhou Liu 		update_cpo = (cpo_min + 0x3f) < cpo_target ? true : false;
267102fb2761SShengzhou Liu 
267202fb2761SShengzhou Liu 	if (update_cpo) {
267302fb2761SShengzhou Liu 		printf("WARN: pls set popts->cpo_sample = 0x%x ", cpo_optimal);
267402fb2761SShengzhou Liu 		printf("in <board>/ddr.c to optimize cpo\n");
267502fb2761SShengzhou Liu 	}
267602fb2761SShengzhou Liu }
267702fb2761SShengzhou Liu #endif
2678