xref: /openbmc/u-boot/drivers/ddr/fsl/ctrl_regs.c (revision 564e9383e53b567114bd3403246c0759a6d69c50)
15614e71bSYork Sun /*
2c0c32af0SYork Sun  * Copyright 2008-2016 Freescale Semiconductor, Inc.
3c0c32af0SYork Sun  * Copyright 2017-2018 NXP Semiconductor
45614e71bSYork Sun  *
55614e71bSYork Sun  * SPDX-License-Identifier:	GPL-2.0+
65614e71bSYork Sun  */
75614e71bSYork Sun 
85614e71bSYork Sun /*
902fb2761SShengzhou Liu  * Generic driver for Freescale DDR/DDR2/DDR3/DDR4 memory controller.
105614e71bSYork Sun  * Based on code from spd_sdram.c
115614e71bSYork Sun  * Author: James Yang [at freescale.com]
125614e71bSYork Sun  */
135614e71bSYork Sun 
145614e71bSYork Sun #include <common.h>
155614e71bSYork Sun #include <fsl_ddr_sdram.h>
1602fb2761SShengzhou Liu #include <fsl_errata.h>
175614e71bSYork Sun #include <fsl_ddr.h>
189a17eb5bSYork Sun #include <fsl_immap.h>
195614e71bSYork Sun #include <asm/io.h>
20457e51cfSSimon Glass #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \
21457e51cfSSimon Glass 	defined(CONFIG_ARM)
226e2941d7SSimon Glass #include <asm/arch/clock.h>
236e2941d7SSimon Glass #endif
245614e71bSYork Sun 
255614e71bSYork Sun /*
265614e71bSYork Sun  * Determine Rtt value.
275614e71bSYork Sun  *
285614e71bSYork Sun  * This should likely be either board or controller specific.
295614e71bSYork Sun  *
305614e71bSYork Sun  * Rtt(nominal) - DDR2:
315614e71bSYork Sun  *	0 = Rtt disabled
325614e71bSYork Sun  *	1 = 75 ohm
335614e71bSYork Sun  *	2 = 150 ohm
345614e71bSYork Sun  *	3 = 50 ohm
355614e71bSYork Sun  * Rtt(nominal) - DDR3:
365614e71bSYork Sun  *	0 = Rtt disabled
375614e71bSYork Sun  *	1 = 60 ohm
385614e71bSYork Sun  *	2 = 120 ohm
395614e71bSYork Sun  *	3 = 40 ohm
405614e71bSYork Sun  *	4 = 20 ohm
415614e71bSYork Sun  *	5 = 30 ohm
425614e71bSYork Sun  *
435614e71bSYork Sun  * FIXME: Apparently 8641 needs a value of 2
445614e71bSYork Sun  * FIXME: Old code seys if 667 MHz or higher, use 3 on 8572
455614e71bSYork Sun  *
465614e71bSYork Sun  * FIXME: There was some effort down this line earlier:
475614e71bSYork Sun  *
485614e71bSYork Sun  *	unsigned int i;
495614e71bSYork Sun  *	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL/2; i++) {
505614e71bSYork Sun  *		if (popts->dimmslot[i].num_valid_cs
515614e71bSYork Sun  *		    && (popts->cs_local_opts[2*i].odt_rd_cfg
525614e71bSYork Sun  *			|| popts->cs_local_opts[2*i].odt_wr_cfg)) {
535614e71bSYork Sun  *			rtt = 2;
545614e71bSYork Sun  *			break;
555614e71bSYork Sun  *		}
565614e71bSYork Sun  *	}
575614e71bSYork Sun  */
585614e71bSYork Sun static inline int fsl_ddr_get_rtt(void)
595614e71bSYork Sun {
605614e71bSYork Sun 	int rtt;
615614e71bSYork Sun 
625614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
635614e71bSYork Sun 	rtt = 0;
645614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
655614e71bSYork Sun 	rtt = 3;
665614e71bSYork Sun #else
675614e71bSYork Sun 	rtt = 0;
685614e71bSYork Sun #endif
695614e71bSYork Sun 
705614e71bSYork Sun 	return rtt;
715614e71bSYork Sun }
725614e71bSYork Sun 
7334e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
7434e026f9SYork Sun /*
7534e026f9SYork Sun  * compute CAS write latency according to DDR4 spec
7634e026f9SYork Sun  * CWL = 9 for <= 1600MT/s
7734e026f9SYork Sun  *       10 for <= 1866MT/s
7834e026f9SYork Sun  *       11 for <= 2133MT/s
7934e026f9SYork Sun  *       12 for <= 2400MT/s
8034e026f9SYork Sun  *       14 for <= 2667MT/s
8134e026f9SYork Sun  *       16 for <= 2933MT/s
8234e026f9SYork Sun  *       18 for higher
8334e026f9SYork Sun  */
8403e664d8SYork Sun static inline unsigned int compute_cas_write_latency(
8503e664d8SYork Sun 				const unsigned int ctrl_num)
8634e026f9SYork Sun {
8734e026f9SYork Sun 	unsigned int cwl;
8803e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
8934e026f9SYork Sun 	if (mclk_ps >= 1250)
9034e026f9SYork Sun 		cwl = 9;
9134e026f9SYork Sun 	else if (mclk_ps >= 1070)
9234e026f9SYork Sun 		cwl = 10;
9334e026f9SYork Sun 	else if (mclk_ps >= 935)
9434e026f9SYork Sun 		cwl = 11;
9534e026f9SYork Sun 	else if (mclk_ps >= 833)
9634e026f9SYork Sun 		cwl = 12;
9734e026f9SYork Sun 	else if (mclk_ps >= 750)
9834e026f9SYork Sun 		cwl = 14;
9934e026f9SYork Sun 	else if (mclk_ps >= 681)
10034e026f9SYork Sun 		cwl = 16;
10134e026f9SYork Sun 	else
10234e026f9SYork Sun 		cwl = 18;
10334e026f9SYork Sun 
10434e026f9SYork Sun 	return cwl;
10534e026f9SYork Sun }
10634e026f9SYork Sun #else
1075614e71bSYork Sun /*
1085614e71bSYork Sun  * compute the CAS write latency according to DDR3 spec
1095614e71bSYork Sun  * CWL = 5 if tCK >= 2.5ns
1105614e71bSYork Sun  *       6 if 2.5ns > tCK >= 1.875ns
1115614e71bSYork Sun  *       7 if 1.875ns > tCK >= 1.5ns
1125614e71bSYork Sun  *       8 if 1.5ns > tCK >= 1.25ns
1135614e71bSYork Sun  *       9 if 1.25ns > tCK >= 1.07ns
1145614e71bSYork Sun  *       10 if 1.07ns > tCK >= 0.935ns
1155614e71bSYork Sun  *       11 if 0.935ns > tCK >= 0.833ns
1165614e71bSYork Sun  *       12 if 0.833ns > tCK >= 0.75ns
1175614e71bSYork Sun  */
11803e664d8SYork Sun static inline unsigned int compute_cas_write_latency(
11903e664d8SYork Sun 				const unsigned int ctrl_num)
1205614e71bSYork Sun {
1215614e71bSYork Sun 	unsigned int cwl;
12203e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
1235614e71bSYork Sun 
1245614e71bSYork Sun 	if (mclk_ps >= 2500)
1255614e71bSYork Sun 		cwl = 5;
1265614e71bSYork Sun 	else if (mclk_ps >= 1875)
1275614e71bSYork Sun 		cwl = 6;
1285614e71bSYork Sun 	else if (mclk_ps >= 1500)
1295614e71bSYork Sun 		cwl = 7;
1305614e71bSYork Sun 	else if (mclk_ps >= 1250)
1315614e71bSYork Sun 		cwl = 8;
1325614e71bSYork Sun 	else if (mclk_ps >= 1070)
1335614e71bSYork Sun 		cwl = 9;
1345614e71bSYork Sun 	else if (mclk_ps >= 935)
1355614e71bSYork Sun 		cwl = 10;
1365614e71bSYork Sun 	else if (mclk_ps >= 833)
1375614e71bSYork Sun 		cwl = 11;
1385614e71bSYork Sun 	else if (mclk_ps >= 750)
1395614e71bSYork Sun 		cwl = 12;
1405614e71bSYork Sun 	else {
1415614e71bSYork Sun 		cwl = 12;
1425614e71bSYork Sun 		printf("Warning: CWL is out of range\n");
1435614e71bSYork Sun 	}
1445614e71bSYork Sun 	return cwl;
1455614e71bSYork Sun }
14634e026f9SYork Sun #endif
1475614e71bSYork Sun 
1485614e71bSYork Sun /* Chip Select Configuration (CSn_CONFIG) */
1495614e71bSYork Sun static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
1505614e71bSYork Sun 			       const memctl_options_t *popts,
1515614e71bSYork Sun 			       const dimm_params_t *dimm_params)
1525614e71bSYork Sun {
1535614e71bSYork Sun 	unsigned int cs_n_en = 0; /* Chip Select enable */
1545614e71bSYork Sun 	unsigned int intlv_en = 0; /* Memory controller interleave enable */
1555614e71bSYork Sun 	unsigned int intlv_ctl = 0; /* Interleaving control */
1565614e71bSYork Sun 	unsigned int ap_n_en = 0; /* Chip select n auto-precharge enable */
1575614e71bSYork Sun 	unsigned int odt_rd_cfg = 0; /* ODT for reads configuration */
1585614e71bSYork Sun 	unsigned int odt_wr_cfg = 0; /* ODT for writes configuration */
1595614e71bSYork Sun 	unsigned int ba_bits_cs_n = 0; /* Num of bank bits for SDRAM on CSn */
1605614e71bSYork Sun 	unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */
1615614e71bSYork Sun 	unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */
1625614e71bSYork Sun 	int go_config = 0;
16334e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
16434e026f9SYork Sun 	unsigned int bg_bits_cs_n = 0; /* Num of bank group bits */
16534e026f9SYork Sun #else
16634e026f9SYork Sun 	unsigned int n_banks_per_sdram_device;
16734e026f9SYork Sun #endif
1685614e71bSYork Sun 
1695614e71bSYork Sun 	/* Compute CS_CONFIG only for existing ranks of each DIMM.  */
1705614e71bSYork Sun 	switch (i) {
1715614e71bSYork Sun 	case 0:
1725614e71bSYork Sun 		if (dimm_params[dimm_number].n_ranks > 0) {
1735614e71bSYork Sun 			go_config = 1;
1745614e71bSYork Sun 			/* These fields only available in CS0_CONFIG */
1755614e71bSYork Sun 			if (!popts->memctl_interleaving)
1765614e71bSYork Sun 				break;
1775614e71bSYork Sun 			switch (popts->memctl_interleaving_mode) {
1786b1e1254SYork Sun 			case FSL_DDR_256B_INTERLEAVING:
1795614e71bSYork Sun 			case FSL_DDR_CACHE_LINE_INTERLEAVING:
1805614e71bSYork Sun 			case FSL_DDR_PAGE_INTERLEAVING:
1815614e71bSYork Sun 			case FSL_DDR_BANK_INTERLEAVING:
1825614e71bSYork Sun 			case FSL_DDR_SUPERBANK_INTERLEAVING:
1835614e71bSYork Sun 				intlv_en = popts->memctl_interleaving;
1845614e71bSYork Sun 				intlv_ctl = popts->memctl_interleaving_mode;
1855614e71bSYork Sun 				break;
1865614e71bSYork Sun 			default:
1875614e71bSYork Sun 				break;
1885614e71bSYork Sun 			}
1895614e71bSYork Sun 		}
1905614e71bSYork Sun 		break;
1915614e71bSYork Sun 	case 1:
1925614e71bSYork Sun 		if ((dimm_number == 0 && dimm_params[0].n_ranks > 1) || \
1935614e71bSYork Sun 		    (dimm_number == 1 && dimm_params[1].n_ranks > 0))
1945614e71bSYork Sun 			go_config = 1;
1955614e71bSYork Sun 		break;
1965614e71bSYork Sun 	case 2:
1975614e71bSYork Sun 		if ((dimm_number == 0 && dimm_params[0].n_ranks > 2) || \
1985614e71bSYork Sun 		   (dimm_number >= 1 && dimm_params[dimm_number].n_ranks > 0))
1995614e71bSYork Sun 			go_config = 1;
2005614e71bSYork Sun 		break;
2015614e71bSYork Sun 	case 3:
2025614e71bSYork Sun 		if ((dimm_number == 0 && dimm_params[0].n_ranks > 3) || \
2035614e71bSYork Sun 		    (dimm_number == 1 && dimm_params[1].n_ranks > 1) || \
2045614e71bSYork Sun 		    (dimm_number == 3 && dimm_params[3].n_ranks > 0))
2055614e71bSYork Sun 			go_config = 1;
2065614e71bSYork Sun 		break;
2075614e71bSYork Sun 	default:
2085614e71bSYork Sun 		break;
2095614e71bSYork Sun 	}
2105614e71bSYork Sun 	if (go_config) {
2115614e71bSYork Sun 		cs_n_en = 1;
2125614e71bSYork Sun 		ap_n_en = popts->cs_local_opts[i].auto_precharge;
2135614e71bSYork Sun 		odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg;
2145614e71bSYork Sun 		odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg;
21534e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
21634e026f9SYork Sun 		ba_bits_cs_n = dimm_params[dimm_number].bank_addr_bits;
21734e026f9SYork Sun 		bg_bits_cs_n = dimm_params[dimm_number].bank_group_bits;
21834e026f9SYork Sun #else
2195614e71bSYork Sun 		n_banks_per_sdram_device
2205614e71bSYork Sun 			= dimm_params[dimm_number].n_banks_per_sdram_device;
2215614e71bSYork Sun 		ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2;
22234e026f9SYork Sun #endif
2235614e71bSYork Sun 		row_bits_cs_n = dimm_params[dimm_number].n_row_addr - 12;
2245614e71bSYork Sun 		col_bits_cs_n = dimm_params[dimm_number].n_col_addr - 8;
2255614e71bSYork Sun 	}
2265614e71bSYork Sun 	ddr->cs[i].config = (0
2275614e71bSYork Sun 		| ((cs_n_en & 0x1) << 31)
2285614e71bSYork Sun 		| ((intlv_en & 0x3) << 29)
2295614e71bSYork Sun 		| ((intlv_ctl & 0xf) << 24)
2305614e71bSYork Sun 		| ((ap_n_en & 0x1) << 23)
2315614e71bSYork Sun 
2325614e71bSYork Sun 		/* XXX: some implementation only have 1 bit starting at left */
2335614e71bSYork Sun 		| ((odt_rd_cfg & 0x7) << 20)
2345614e71bSYork Sun 
2355614e71bSYork Sun 		/* XXX: Some implementation only have 1 bit starting at left */
2365614e71bSYork Sun 		| ((odt_wr_cfg & 0x7) << 16)
2375614e71bSYork Sun 
2385614e71bSYork Sun 		| ((ba_bits_cs_n & 0x3) << 14)
2395614e71bSYork Sun 		| ((row_bits_cs_n & 0x7) << 8)
24034e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
24134e026f9SYork Sun 		| ((bg_bits_cs_n & 0x3) << 4)
24234e026f9SYork Sun #endif
2435614e71bSYork Sun 		| ((col_bits_cs_n & 0x7) << 0)
2445614e71bSYork Sun 		);
2455614e71bSYork Sun 	debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config);
2465614e71bSYork Sun }
2475614e71bSYork Sun 
2485614e71bSYork Sun /* Chip Select Configuration 2 (CSn_CONFIG_2) */
2495614e71bSYork Sun /* FIXME: 8572 */
2505614e71bSYork Sun static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)
2515614e71bSYork Sun {
2525614e71bSYork Sun 	unsigned int pasr_cfg = 0;	/* Partial array self refresh config */
2535614e71bSYork Sun 
2545614e71bSYork Sun 	ddr->cs[i].config_2 = ((pasr_cfg & 7) << 24);
2555614e71bSYork Sun 	debug("FSLDDR: cs[%d]_config_2 = 0x%08x\n", i, ddr->cs[i].config_2);
2565614e71bSYork Sun }
2575614e71bSYork Sun 
2585614e71bSYork Sun /* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */
2595614e71bSYork Sun 
2605614e71bSYork Sun #if !defined(CONFIG_SYS_FSL_DDR1)
26184baed2aSYork Sun /*
26284baed2aSYork Sun  * Check DIMM configuration, return 2 if quad-rank or two dual-rank
26384baed2aSYork Sun  * Return 1 if other two slots configuration. Return 0 if single slot.
26484baed2aSYork Sun  */
2655614e71bSYork Sun static inline int avoid_odt_overlap(const dimm_params_t *dimm_params)
2665614e71bSYork Sun {
2675614e71bSYork Sun #if CONFIG_DIMM_SLOTS_PER_CTLR == 1
2685614e71bSYork Sun 	if (dimm_params[0].n_ranks == 4)
26984baed2aSYork Sun 		return 2;
2705614e71bSYork Sun #endif
2715614e71bSYork Sun 
2725614e71bSYork Sun #if CONFIG_DIMM_SLOTS_PER_CTLR == 2
2735614e71bSYork Sun 	if ((dimm_params[0].n_ranks == 2) &&
2745614e71bSYork Sun 		(dimm_params[1].n_ranks == 2))
27584baed2aSYork Sun 		return 2;
2765614e71bSYork Sun 
2775614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
2785614e71bSYork Sun 	if (dimm_params[0].n_ranks == 4)
27984baed2aSYork Sun 		return 2;
2805614e71bSYork Sun #endif
28184baed2aSYork Sun 
28284baed2aSYork Sun 	if ((dimm_params[0].n_ranks != 0) &&
28384baed2aSYork Sun 	    (dimm_params[2].n_ranks != 0))
28484baed2aSYork Sun 		return 1;
2855614e71bSYork Sun #endif
2865614e71bSYork Sun 	return 0;
2875614e71bSYork Sun }
2885614e71bSYork Sun 
2895614e71bSYork Sun /*
2905614e71bSYork Sun  * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0)
2915614e71bSYork Sun  *
2925614e71bSYork Sun  * Avoid writing for DDR I.  The new PQ38 DDR controller
2935614e71bSYork Sun  * dreams up non-zero default values to be backwards compatible.
2945614e71bSYork Sun  */
29503e664d8SYork Sun static void set_timing_cfg_0(const unsigned int ctrl_num,
29603e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
2975614e71bSYork Sun 				const memctl_options_t *popts,
2985614e71bSYork Sun 				const dimm_params_t *dimm_params)
2995614e71bSYork Sun {
3005614e71bSYork Sun 	unsigned char trwt_mclk = 0;   /* Read-to-write turnaround */
3015614e71bSYork Sun 	unsigned char twrt_mclk = 0;   /* Write-to-read turnaround */
3025614e71bSYork Sun 	/* 7.5 ns on -3E; 0 means WL - CL + BL/2 + 1 */
3035614e71bSYork Sun 	unsigned char trrt_mclk = 0;   /* Read-to-read turnaround */
3045614e71bSYork Sun 	unsigned char twwt_mclk = 0;   /* Write-to-write turnaround */
3055614e71bSYork Sun 
3065614e71bSYork Sun 	/* Active powerdown exit timing (tXARD and tXARDS). */
3075614e71bSYork Sun 	unsigned char act_pd_exit_mclk;
3085614e71bSYork Sun 	/* Precharge powerdown exit timing (tXP). */
3095614e71bSYork Sun 	unsigned char pre_pd_exit_mclk;
3105614e71bSYork Sun 	/* ODT powerdown exit timing (tAXPD). */
31134e026f9SYork Sun 	unsigned char taxpd_mclk = 0;
3125614e71bSYork Sun 	/* Mode register set cycle time (tMRD). */
3135614e71bSYork Sun 	unsigned char tmrd_mclk;
314bb578322SYork Sun #if defined(CONFIG_SYS_FSL_DDR4) || defined(CONFIG_SYS_FSL_DDR3)
31503e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
316bb578322SYork Sun #endif
3175614e71bSYork Sun 
31834e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
31934e026f9SYork Sun 	/* tXP=max(4nCK, 6ns) */
320b4141195SMasahiro Yamada 	int txp = max((int)mclk_ps * 4, 6000); /* unit=ps */
32166869f95SYork Sun 	unsigned int data_rate = get_ddr_freq(ctrl_num);
32266869f95SYork Sun 
32366869f95SYork Sun 	/* for faster clock, need more time for data setup */
32466869f95SYork Sun 	trwt_mclk = (data_rate/1000000 > 1900) ? 3 : 2;
3256c6e006aSYork Sun 
3266c6e006aSYork Sun 	/*
3276c6e006aSYork Sun 	 * for single quad-rank DIMM and two-slot DIMMs
3286c6e006aSYork Sun 	 * to avoid ODT overlap
3296c6e006aSYork Sun 	 */
3306c6e006aSYork Sun 	switch (avoid_odt_overlap(dimm_params)) {
3316c6e006aSYork Sun 	case 2:
3326c6e006aSYork Sun 		twrt_mclk = 2;
3336c6e006aSYork Sun 		twwt_mclk = 2;
3346c6e006aSYork Sun 		trrt_mclk = 2;
3356c6e006aSYork Sun 		break;
3366c6e006aSYork Sun 	default:
33734e026f9SYork Sun 		twrt_mclk = 1;
3386c6e006aSYork Sun 		twwt_mclk = 1;
3396c6e006aSYork Sun 		trrt_mclk = 0;
3406c6e006aSYork Sun 		break;
3416c6e006aSYork Sun 	}
3426c6e006aSYork Sun 
34303e664d8SYork Sun 	act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
34434e026f9SYork Sun 	pre_pd_exit_mclk = act_pd_exit_mclk;
34534e026f9SYork Sun 	/*
34634e026f9SYork Sun 	 * MRS_CYC = max(tMRD, tMOD)
34734e026f9SYork Sun 	 * tMRD = 8nCK, tMOD = max(24nCK, 15ns)
34834e026f9SYork Sun 	 */
34903e664d8SYork Sun 	tmrd_mclk = max(24U, picos_to_mclk(ctrl_num, 15000));
35034e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
35103e664d8SYork Sun 	unsigned int data_rate = get_ddr_freq(ctrl_num);
352bb578322SYork Sun 	int txp;
353938bbb60SYork Sun 	unsigned int ip_rev;
35484baed2aSYork Sun 	int odt_overlap;
3555614e71bSYork Sun 	/*
3565614e71bSYork Sun 	 * (tXARD and tXARDS). Empirical?
3575614e71bSYork Sun 	 * The DDR3 spec has not tXARD,
3585614e71bSYork Sun 	 * we use the tXP instead of it.
359bb578322SYork Sun 	 * tXP=max(3nCK, 7.5ns) for DDR3-800, 1066
360bb578322SYork Sun 	 *     max(3nCK, 6ns) for DDR3-1333, 1600, 1866, 2133
3615614e71bSYork Sun 	 * spec has not the tAXPD, we use
3625614e71bSYork Sun 	 * tAXPD=1, need design to confirm.
3635614e71bSYork Sun 	 */
364b4141195SMasahiro Yamada 	txp = max((int)mclk_ps * 3, (mclk_ps > 1540 ? 7500 : 6000));
365bb578322SYork Sun 
36666869f95SYork Sun 	ip_rev = fsl_ddr_get_version(ctrl_num);
367938bbb60SYork Sun 	if (ip_rev >= 0x40700) {
368938bbb60SYork Sun 		/*
369938bbb60SYork Sun 		 * MRS_CYC = max(tMRD, tMOD)
370938bbb60SYork Sun 		 * tMRD = 4nCK (8nCK for RDIMM)
371938bbb60SYork Sun 		 * tMOD = max(12nCK, 15ns)
372938bbb60SYork Sun 		 */
37303e664d8SYork Sun 		tmrd_mclk = max((unsigned int)12,
37403e664d8SYork Sun 				picos_to_mclk(ctrl_num, 15000));
375938bbb60SYork Sun 	} else {
376938bbb60SYork Sun 		/*
377938bbb60SYork Sun 		 * MRS_CYC = tMRD
378938bbb60SYork Sun 		 * tMRD = 4nCK (8nCK for RDIMM)
379938bbb60SYork Sun 		 */
380938bbb60SYork Sun 		if (popts->registered_dimm_en)
381938bbb60SYork Sun 			tmrd_mclk = 8;
382938bbb60SYork Sun 		else
3835614e71bSYork Sun 			tmrd_mclk = 4;
384938bbb60SYork Sun 	}
385938bbb60SYork Sun 
3865614e71bSYork Sun 	/* set the turnaround time */
3875614e71bSYork Sun 
3885614e71bSYork Sun 	/*
38984baed2aSYork Sun 	 * for single quad-rank DIMM and two-slot DIMMs
3905614e71bSYork Sun 	 * to avoid ODT overlap
3915614e71bSYork Sun 	 */
39284baed2aSYork Sun 	odt_overlap = avoid_odt_overlap(dimm_params);
39384baed2aSYork Sun 	switch (odt_overlap) {
39484baed2aSYork Sun 	case 2:
3955614e71bSYork Sun 		twwt_mclk = 2;
3965614e71bSYork Sun 		trrt_mclk = 1;
39784baed2aSYork Sun 		break;
39884baed2aSYork Sun 	case 1:
39984baed2aSYork Sun 		twwt_mclk = 1;
40084baed2aSYork Sun 		trrt_mclk = 0;
40184baed2aSYork Sun 		break;
40284baed2aSYork Sun 	default:
40384baed2aSYork Sun 		break;
4045614e71bSYork Sun 	}
40584baed2aSYork Sun 
4065614e71bSYork Sun 	/* for faster clock, need more time for data setup */
4075614e71bSYork Sun 	trwt_mclk = (data_rate/1000000 > 1800) ? 2 : 1;
4085614e71bSYork Sun 
4095614e71bSYork Sun 	if ((data_rate/1000000 > 1150) || (popts->memctl_interleaving))
4105614e71bSYork Sun 		twrt_mclk = 1;
4115614e71bSYork Sun 
4125614e71bSYork Sun 	if (popts->dynamic_power == 0) {	/* powerdown is not used */
4135614e71bSYork Sun 		act_pd_exit_mclk = 1;
4145614e71bSYork Sun 		pre_pd_exit_mclk = 1;
4155614e71bSYork Sun 		taxpd_mclk = 1;
4165614e71bSYork Sun 	} else {
4175614e71bSYork Sun 		/* act_pd_exit_mclk = tXARD, see above */
41803e664d8SYork Sun 		act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
4195614e71bSYork Sun 		/* Mode register MR0[A12] is '1' - fast exit */
4205614e71bSYork Sun 		pre_pd_exit_mclk = act_pd_exit_mclk;
4215614e71bSYork Sun 		taxpd_mclk = 1;
4225614e71bSYork Sun 	}
4235614e71bSYork Sun #else /* CONFIG_SYS_FSL_DDR2 */
4245614e71bSYork Sun 	/*
4255614e71bSYork Sun 	 * (tXARD and tXARDS). Empirical?
4265614e71bSYork Sun 	 * tXARD = 2 for DDR2
4275614e71bSYork Sun 	 * tXP=2
4285614e71bSYork Sun 	 * tAXPD=8
4295614e71bSYork Sun 	 */
4305614e71bSYork Sun 	act_pd_exit_mclk = 2;
4315614e71bSYork Sun 	pre_pd_exit_mclk = 2;
4325614e71bSYork Sun 	taxpd_mclk = 8;
4335614e71bSYork Sun 	tmrd_mclk = 2;
4345614e71bSYork Sun #endif
4355614e71bSYork Sun 
4365614e71bSYork Sun 	if (popts->trwt_override)
4375614e71bSYork Sun 		trwt_mclk = popts->trwt;
4385614e71bSYork Sun 
4395614e71bSYork Sun 	ddr->timing_cfg_0 = (0
4405614e71bSYork Sun 		| ((trwt_mclk & 0x3) << 30)	/* RWT */
4415614e71bSYork Sun 		| ((twrt_mclk & 0x3) << 28)	/* WRT */
4425614e71bSYork Sun 		| ((trrt_mclk & 0x3) << 26)	/* RRT */
4435614e71bSYork Sun 		| ((twwt_mclk & 0x3) << 24)	/* WWT */
444d4263b8aSYork Sun 		| ((act_pd_exit_mclk & 0xf) << 20)  /* ACT_PD_EXIT */
4455614e71bSYork Sun 		| ((pre_pd_exit_mclk & 0xF) << 16)  /* PRE_PD_EXIT */
4465614e71bSYork Sun 		| ((taxpd_mclk & 0xf) << 8)	/* ODT_PD_EXIT */
447d4263b8aSYork Sun 		| ((tmrd_mclk & 0x1f) << 0)	/* MRS_CYC */
4485614e71bSYork Sun 		);
4495614e71bSYork Sun 	debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
4505614e71bSYork Sun }
45184baed2aSYork Sun #endif	/* !defined(CONFIG_SYS_FSL_DDR1) */
4525614e71bSYork Sun 
4535614e71bSYork Sun /* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */
45403e664d8SYork Sun static void set_timing_cfg_3(const unsigned int ctrl_num,
45503e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
4565614e71bSYork Sun 			     const memctl_options_t *popts,
4575614e71bSYork Sun 			     const common_timing_params_t *common_dimm,
458d4263b8aSYork Sun 			     unsigned int cas_latency,
459d4263b8aSYork Sun 			     unsigned int additive_latency)
4605614e71bSYork Sun {
4615614e71bSYork Sun 	/* Extended precharge to activate interval (tRP) */
4625614e71bSYork Sun 	unsigned int ext_pretoact = 0;
4635614e71bSYork Sun 	/* Extended Activate to precharge interval (tRAS) */
4645614e71bSYork Sun 	unsigned int ext_acttopre = 0;
4655614e71bSYork Sun 	/* Extended activate to read/write interval (tRCD) */
4665614e71bSYork Sun 	unsigned int ext_acttorw = 0;
4675614e71bSYork Sun 	/* Extended refresh recovery time (tRFC) */
4685614e71bSYork Sun 	unsigned int ext_refrec;
4695614e71bSYork Sun 	/* Extended MCAS latency from READ cmd */
4705614e71bSYork Sun 	unsigned int ext_caslat = 0;
471d4263b8aSYork Sun 	/* Extended additive latency */
472d4263b8aSYork Sun 	unsigned int ext_add_lat = 0;
4735614e71bSYork Sun 	/* Extended last data to precharge interval (tWR) */
4745614e71bSYork Sun 	unsigned int ext_wrrec = 0;
4755614e71bSYork Sun 	/* Control Adjust */
4765614e71bSYork Sun 	unsigned int cntl_adj = 0;
4775614e71bSYork Sun 
47803e664d8SYork Sun 	ext_pretoact = picos_to_mclk(ctrl_num, common_dimm->trp_ps) >> 4;
47903e664d8SYork Sun 	ext_acttopre = picos_to_mclk(ctrl_num, common_dimm->tras_ps) >> 4;
48003e664d8SYork Sun 	ext_acttorw = picos_to_mclk(ctrl_num, common_dimm->trcd_ps) >> 4;
4815614e71bSYork Sun 	ext_caslat = (2 * cas_latency - 1) >> 4;
482d4263b8aSYork Sun 	ext_add_lat = additive_latency >> 4;
48334e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
48403e664d8SYork Sun 	ext_refrec = (picos_to_mclk(ctrl_num, common_dimm->trfc1_ps) - 8) >> 4;
48534e026f9SYork Sun #else
48603e664d8SYork Sun 	ext_refrec = (picos_to_mclk(ctrl_num, common_dimm->trfc_ps) - 8) >> 4;
4875614e71bSYork Sun 	/* ext_wrrec only deals with 16 clock and above, or 14 with OTF */
48834e026f9SYork Sun #endif
48903e664d8SYork Sun 	ext_wrrec = (picos_to_mclk(ctrl_num, common_dimm->twr_ps) +
4905614e71bSYork Sun 		(popts->otf_burst_chop_en ? 2 : 0)) >> 4;
4915614e71bSYork Sun 
4925614e71bSYork Sun 	ddr->timing_cfg_3 = (0
4935614e71bSYork Sun 		| ((ext_pretoact & 0x1) << 28)
4945614e71bSYork Sun 		| ((ext_acttopre & 0x3) << 24)
4955614e71bSYork Sun 		| ((ext_acttorw & 0x1) << 22)
496c0c32af0SYork Sun 		| ((ext_refrec & 0x3F) << 16)
4975614e71bSYork Sun 		| ((ext_caslat & 0x3) << 12)
498d4263b8aSYork Sun 		| ((ext_add_lat & 0x1) << 10)
4995614e71bSYork Sun 		| ((ext_wrrec & 0x1) << 8)
5005614e71bSYork Sun 		| ((cntl_adj & 0x7) << 0)
5015614e71bSYork Sun 		);
5025614e71bSYork Sun 	debug("FSLDDR: timing_cfg_3 = 0x%08x\n", ddr->timing_cfg_3);
5035614e71bSYork Sun }
5045614e71bSYork Sun 
5055614e71bSYork Sun /* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */
50603e664d8SYork Sun static void set_timing_cfg_1(const unsigned int ctrl_num,
50703e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
5085614e71bSYork Sun 			     const memctl_options_t *popts,
5095614e71bSYork Sun 			     const common_timing_params_t *common_dimm,
5105614e71bSYork Sun 			     unsigned int cas_latency)
5115614e71bSYork Sun {
5125614e71bSYork Sun 	/* Precharge-to-activate interval (tRP) */
5135614e71bSYork Sun 	unsigned char pretoact_mclk;
5145614e71bSYork Sun 	/* Activate to precharge interval (tRAS) */
5155614e71bSYork Sun 	unsigned char acttopre_mclk;
5165614e71bSYork Sun 	/*  Activate to read/write interval (tRCD) */
5175614e71bSYork Sun 	unsigned char acttorw_mclk;
5185614e71bSYork Sun 	/* CASLAT */
5195614e71bSYork Sun 	unsigned char caslat_ctrl;
5205614e71bSYork Sun 	/*  Refresh recovery time (tRFC) ; trfc_low */
5215614e71bSYork Sun 	unsigned char refrec_ctrl;
5225614e71bSYork Sun 	/* Last data to precharge minimum interval (tWR) */
5235614e71bSYork Sun 	unsigned char wrrec_mclk;
5245614e71bSYork Sun 	/* Activate-to-activate interval (tRRD) */
5255614e71bSYork Sun 	unsigned char acttoact_mclk;
5265614e71bSYork Sun 	/* Last write data pair to read command issue interval (tWTR) */
5275614e71bSYork Sun 	unsigned char wrtord_mclk;
52834e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
52934e026f9SYork Sun 	/* DDR4 supports 10, 12, 14, 16, 18, 20, 24 */
53034e026f9SYork Sun 	static const u8 wrrec_table[] = {
53134e026f9SYork Sun 		10, 10, 10, 10, 10,
53234e026f9SYork Sun 		10, 10, 10, 10, 10,
53334e026f9SYork Sun 		12, 12, 14, 14, 16,
53434e026f9SYork Sun 		16, 18, 18, 20, 20,
53534e026f9SYork Sun 		24, 24, 24, 24};
53634e026f9SYork Sun #else
5375614e71bSYork Sun 	/* DDR_SDRAM_MODE doesn't support 9,11,13,15 */
5385614e71bSYork Sun 	static const u8 wrrec_table[] = {
5395614e71bSYork Sun 		1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0};
54034e026f9SYork Sun #endif
5415614e71bSYork Sun 
54203e664d8SYork Sun 	pretoact_mclk = picos_to_mclk(ctrl_num, common_dimm->trp_ps);
54303e664d8SYork Sun 	acttopre_mclk = picos_to_mclk(ctrl_num, common_dimm->tras_ps);
54403e664d8SYork Sun 	acttorw_mclk = picos_to_mclk(ctrl_num, common_dimm->trcd_ps);
5455614e71bSYork Sun 
5465614e71bSYork Sun 	/*
5475614e71bSYork Sun 	 * Translate CAS Latency to a DDR controller field value:
5485614e71bSYork Sun 	 *
5495614e71bSYork Sun 	 *      CAS Lat DDR I   DDR II  Ctrl
5505614e71bSYork Sun 	 *      Clocks  SPD Bit SPD Bit Value
5515614e71bSYork Sun 	 *      ------- ------- ------- -----
5525614e71bSYork Sun 	 *      1.0     0               0001
5535614e71bSYork Sun 	 *      1.5     1               0010
5545614e71bSYork Sun 	 *      2.0     2       2       0011
5555614e71bSYork Sun 	 *      2.5     3               0100
5565614e71bSYork Sun 	 *      3.0     4       3       0101
5575614e71bSYork Sun 	 *      3.5     5               0110
5585614e71bSYork Sun 	 *      4.0             4       0111
5595614e71bSYork Sun 	 *      4.5                     1000
5605614e71bSYork Sun 	 *      5.0             5       1001
5615614e71bSYork Sun 	 */
5625614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
5635614e71bSYork Sun 	caslat_ctrl = (cas_latency + 1) & 0x07;
5645614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
5655614e71bSYork Sun 	caslat_ctrl = 2 * cas_latency - 1;
5665614e71bSYork Sun #else
5675614e71bSYork Sun 	/*
5685614e71bSYork Sun 	 * if the CAS latency more than 8 cycle,
5695614e71bSYork Sun 	 * we need set extend bit for it at
5705614e71bSYork Sun 	 * TIMING_CFG_3[EXT_CASLAT]
5715614e71bSYork Sun 	 */
57266869f95SYork Sun 	if (fsl_ddr_get_version(ctrl_num) <= 0x40400)
5735614e71bSYork Sun 		caslat_ctrl = 2 * cas_latency - 1;
57434e026f9SYork Sun 	else
57534e026f9SYork Sun 		caslat_ctrl = (cas_latency - 1) << 1;
5765614e71bSYork Sun #endif
5775614e71bSYork Sun 
57834e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
57903e664d8SYork Sun 	refrec_ctrl = picos_to_mclk(ctrl_num, common_dimm->trfc1_ps) - 8;
58003e664d8SYork Sun 	wrrec_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
58103e664d8SYork Sun 	acttoact_mclk = max(picos_to_mclk(ctrl_num, common_dimm->trrds_ps), 4U);
58203e664d8SYork Sun 	wrtord_mclk = max(2U, picos_to_mclk(ctrl_num, 2500));
583349689b8SYork Sun 	if ((wrrec_mclk < 1) || (wrrec_mclk > 24))
584349689b8SYork Sun 		printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
58534e026f9SYork Sun 	else
58634e026f9SYork Sun 		wrrec_mclk = wrrec_table[wrrec_mclk - 1];
58734e026f9SYork Sun #else
58803e664d8SYork Sun 	refrec_ctrl = picos_to_mclk(ctrl_num, common_dimm->trfc_ps) - 8;
58903e664d8SYork Sun 	wrrec_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
59003e664d8SYork Sun 	acttoact_mclk = picos_to_mclk(ctrl_num, common_dimm->trrd_ps);
59103e664d8SYork Sun 	wrtord_mclk = picos_to_mclk(ctrl_num, common_dimm->twtr_ps);
592349689b8SYork Sun 	if ((wrrec_mclk < 1) || (wrrec_mclk > 16))
593349689b8SYork Sun 		printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
5945614e71bSYork Sun 	else
5955614e71bSYork Sun 		wrrec_mclk = wrrec_table[wrrec_mclk - 1];
59634e026f9SYork Sun #endif
5975614e71bSYork Sun 	if (popts->otf_burst_chop_en)
5985614e71bSYork Sun 		wrrec_mclk += 2;
5995614e71bSYork Sun 
6005614e71bSYork Sun 	/*
6015614e71bSYork Sun 	 * JEDEC has min requirement for tRRD
6025614e71bSYork Sun 	 */
6035614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR3)
6045614e71bSYork Sun 	if (acttoact_mclk < 4)
6055614e71bSYork Sun 		acttoact_mclk = 4;
6065614e71bSYork Sun #endif
6075614e71bSYork Sun 	/*
6085614e71bSYork Sun 	 * JEDEC has some min requirements for tWTR
6095614e71bSYork Sun 	 */
6105614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR2)
6115614e71bSYork Sun 	if (wrtord_mclk < 2)
6125614e71bSYork Sun 		wrtord_mclk = 2;
6135614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
6145614e71bSYork Sun 	if (wrtord_mclk < 4)
6155614e71bSYork Sun 		wrtord_mclk = 4;
6165614e71bSYork Sun #endif
6175614e71bSYork Sun 	if (popts->otf_burst_chop_en)
6185614e71bSYork Sun 		wrtord_mclk += 2;
6195614e71bSYork Sun 
6205614e71bSYork Sun 	ddr->timing_cfg_1 = (0
6215614e71bSYork Sun 		| ((pretoact_mclk & 0x0F) << 28)
6225614e71bSYork Sun 		| ((acttopre_mclk & 0x0F) << 24)
6235614e71bSYork Sun 		| ((acttorw_mclk & 0xF) << 20)
6245614e71bSYork Sun 		| ((caslat_ctrl & 0xF) << 16)
6255614e71bSYork Sun 		| ((refrec_ctrl & 0xF) << 12)
6265614e71bSYork Sun 		| ((wrrec_mclk & 0x0F) << 8)
6275614e71bSYork Sun 		| ((acttoact_mclk & 0x0F) << 4)
6285614e71bSYork Sun 		| ((wrtord_mclk & 0x0F) << 0)
6295614e71bSYork Sun 		);
6305614e71bSYork Sun 	debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1);
6315614e71bSYork Sun }
6325614e71bSYork Sun 
6335614e71bSYork Sun /* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */
63403e664d8SYork Sun static void set_timing_cfg_2(const unsigned int ctrl_num,
63503e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
6365614e71bSYork Sun 			     const memctl_options_t *popts,
6375614e71bSYork Sun 			     const common_timing_params_t *common_dimm,
6385614e71bSYork Sun 			     unsigned int cas_latency,
6395614e71bSYork Sun 			     unsigned int additive_latency)
6405614e71bSYork Sun {
6415614e71bSYork Sun 	/* Additive latency */
6425614e71bSYork Sun 	unsigned char add_lat_mclk;
6435614e71bSYork Sun 	/* CAS-to-preamble override */
6445614e71bSYork Sun 	unsigned short cpo;
6455614e71bSYork Sun 	/* Write latency */
6465614e71bSYork Sun 	unsigned char wr_lat;
6475614e71bSYork Sun 	/*  Read to precharge (tRTP) */
6485614e71bSYork Sun 	unsigned char rd_to_pre;
6495614e71bSYork Sun 	/* Write command to write data strobe timing adjustment */
6505614e71bSYork Sun 	unsigned char wr_data_delay;
6515614e71bSYork Sun 	/* Minimum CKE pulse width (tCKE) */
6525614e71bSYork Sun 	unsigned char cke_pls;
6535614e71bSYork Sun 	/* Window for four activates (tFAW) */
6545614e71bSYork Sun 	unsigned short four_act;
655bb578322SYork Sun #ifdef CONFIG_SYS_FSL_DDR3
65603e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
657bb578322SYork Sun #endif
6585614e71bSYork Sun 
6595614e71bSYork Sun 	/* FIXME add check that this must be less than acttorw_mclk */
6605614e71bSYork Sun 	add_lat_mclk = additive_latency;
6615614e71bSYork Sun 	cpo = popts->cpo_override;
6625614e71bSYork Sun 
6635614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
6645614e71bSYork Sun 	/*
6655614e71bSYork Sun 	 * This is a lie.  It should really be 1, but if it is
6665614e71bSYork Sun 	 * set to 1, bits overlap into the old controller's
6675614e71bSYork Sun 	 * otherwise unused ACSM field.  If we leave it 0, then
6685614e71bSYork Sun 	 * the HW will magically treat it as 1 for DDR 1.  Oh Yea.
6695614e71bSYork Sun 	 */
6705614e71bSYork Sun 	wr_lat = 0;
6715614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
6725614e71bSYork Sun 	wr_lat = cas_latency - 1;
6735614e71bSYork Sun #else
67403e664d8SYork Sun 	wr_lat = compute_cas_write_latency(ctrl_num);
6755614e71bSYork Sun #endif
6765614e71bSYork Sun 
67734e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
67803e664d8SYork Sun 	rd_to_pre = picos_to_mclk(ctrl_num, 7500);
67934e026f9SYork Sun #else
68003e664d8SYork Sun 	rd_to_pre = picos_to_mclk(ctrl_num, common_dimm->trtp_ps);
68134e026f9SYork Sun #endif
6825614e71bSYork Sun 	/*
6835614e71bSYork Sun 	 * JEDEC has some min requirements for tRTP
6845614e71bSYork Sun 	 */
6855614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR2)
6865614e71bSYork Sun 	if (rd_to_pre  < 2)
6875614e71bSYork Sun 		rd_to_pre  = 2;
68834e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
6895614e71bSYork Sun 	if (rd_to_pre < 4)
6905614e71bSYork Sun 		rd_to_pre = 4;
6915614e71bSYork Sun #endif
6925614e71bSYork Sun 	if (popts->otf_burst_chop_en)
6935614e71bSYork Sun 		rd_to_pre += 2; /* according to UM */
6945614e71bSYork Sun 
6955614e71bSYork Sun 	wr_data_delay = popts->write_data_delay;
69634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
69734e026f9SYork Sun 	cpo = 0;
69803e664d8SYork Sun 	cke_pls = max(3U, picos_to_mclk(ctrl_num, 5000));
699bb578322SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
700bb578322SYork Sun 	/*
701bb578322SYork Sun 	 * cke pulse = max(3nCK, 7.5ns) for DDR3-800
702bb578322SYork Sun 	 *             max(3nCK, 5.625ns) for DDR3-1066, 1333
703bb578322SYork Sun 	 *             max(3nCK, 5ns) for DDR3-1600, 1866, 2133
704bb578322SYork Sun 	 */
70503e664d8SYork Sun 	cke_pls = max(3U, picos_to_mclk(ctrl_num, mclk_ps > 1870 ? 7500 :
706bb578322SYork Sun 					(mclk_ps > 1245 ? 5625 : 5000)));
70734e026f9SYork Sun #else
708bb578322SYork Sun 	cke_pls = FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR;
70934e026f9SYork Sun #endif
71003e664d8SYork Sun 	four_act = picos_to_mclk(ctrl_num,
71103e664d8SYork Sun 				 popts->tfaw_window_four_activates_ps);
7125614e71bSYork Sun 
7135614e71bSYork Sun 	ddr->timing_cfg_2 = (0
7145614e71bSYork Sun 		| ((add_lat_mclk & 0xf) << 28)
7155614e71bSYork Sun 		| ((cpo & 0x1f) << 23)
7165614e71bSYork Sun 		| ((wr_lat & 0xf) << 19)
7178936691bSYork Sun 		| (((wr_lat & 0x10) >> 4) << 18)
7185614e71bSYork Sun 		| ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT)
7195614e71bSYork Sun 		| ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT)
7205614e71bSYork Sun 		| ((cke_pls & 0x7) << 6)
7215614e71bSYork Sun 		| ((four_act & 0x3f) << 0)
7225614e71bSYork Sun 		);
7235614e71bSYork Sun 	debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2);
7245614e71bSYork Sun }
7255614e71bSYork Sun 
7265614e71bSYork Sun /* DDR SDRAM Register Control Word */
727*564e9383SYork Sun static void set_ddr_sdram_rcw(const unsigned int ctrl_num,
728*564e9383SYork Sun 			      fsl_ddr_cfg_regs_t *ddr,
7295614e71bSYork Sun 			      const memctl_options_t *popts,
7305614e71bSYork Sun 			      const common_timing_params_t *common_dimm)
7315614e71bSYork Sun {
732*564e9383SYork Sun 	unsigned int ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
733*564e9383SYork Sun 	unsigned int rc0a, rc0f;
734*564e9383SYork Sun 
7355614e71bSYork Sun 	if (common_dimm->all_dimms_registered &&
7365614e71bSYork Sun 	    !common_dimm->all_dimms_unbuffered)	{
7375614e71bSYork Sun 		if (popts->rcw_override) {
7385614e71bSYork Sun 			ddr->ddr_sdram_rcw_1 = popts->rcw_1;
7395614e71bSYork Sun 			ddr->ddr_sdram_rcw_2 = popts->rcw_2;
740426230a6SYork Sun 			ddr->ddr_sdram_rcw_3 = popts->rcw_3;
7415614e71bSYork Sun 		} else {
742*564e9383SYork Sun 			rc0a = ddr_freq > 3200 ? 0x7 :
743*564e9383SYork Sun 			       (ddr_freq > 2933 ? 0x6 :
744*564e9383SYork Sun 				(ddr_freq > 2666 ? 0x5 :
745*564e9383SYork Sun 				 (ddr_freq > 2400 ? 0x4 :
746*564e9383SYork Sun 				  (ddr_freq > 2133 ? 0x3 :
747*564e9383SYork Sun 				   (ddr_freq > 1866 ? 0x2 :
748*564e9383SYork Sun 				    (ddr_freq > 1600 ? 1 : 0))))));
749*564e9383SYork Sun 			rc0f = ddr_freq > 3200 ? 0x3 :
750*564e9383SYork Sun 			       (ddr_freq > 2400 ? 0x2 :
751*564e9383SYork Sun 				(ddr_freq > 2133 ? 0x1 : 0));
7525614e71bSYork Sun 			ddr->ddr_sdram_rcw_1 =
7535614e71bSYork Sun 				common_dimm->rcw[0] << 28 | \
7545614e71bSYork Sun 				common_dimm->rcw[1] << 24 | \
7555614e71bSYork Sun 				common_dimm->rcw[2] << 20 | \
7565614e71bSYork Sun 				common_dimm->rcw[3] << 16 | \
7575614e71bSYork Sun 				common_dimm->rcw[4] << 12 | \
7585614e71bSYork Sun 				common_dimm->rcw[5] << 8 | \
7595614e71bSYork Sun 				common_dimm->rcw[6] << 4 | \
7605614e71bSYork Sun 				common_dimm->rcw[7];
7615614e71bSYork Sun 			ddr->ddr_sdram_rcw_2 =
7625614e71bSYork Sun 				common_dimm->rcw[8] << 28 | \
7635614e71bSYork Sun 				common_dimm->rcw[9] << 24 | \
764*564e9383SYork Sun 				rc0a << 20 | \
7655614e71bSYork Sun 				common_dimm->rcw[11] << 16 | \
7665614e71bSYork Sun 				common_dimm->rcw[12] << 12 | \
7675614e71bSYork Sun 				common_dimm->rcw[13] << 8 | \
7685614e71bSYork Sun 				common_dimm->rcw[14] << 4 | \
769*564e9383SYork Sun 				rc0f;
770*564e9383SYork Sun 			ddr->ddr_sdram_rcw_3 =
771*564e9383SYork Sun 				((ddr_freq - 1260 + 19) / 20) << 8;
7725614e71bSYork Sun 		}
773426230a6SYork Sun 		debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n",
774426230a6SYork Sun 		      ddr->ddr_sdram_rcw_1);
775426230a6SYork Sun 		debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n",
776426230a6SYork Sun 		      ddr->ddr_sdram_rcw_2);
777426230a6SYork Sun 		debug("FSLDDR: ddr_sdram_rcw_3 = 0x%08x\n",
778426230a6SYork Sun 		      ddr->ddr_sdram_rcw_3);
7795614e71bSYork Sun 	}
7805614e71bSYork Sun }
7815614e71bSYork Sun 
7825614e71bSYork Sun /* DDR SDRAM control configuration (DDR_SDRAM_CFG) */
7835614e71bSYork Sun static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
7845614e71bSYork Sun 			       const memctl_options_t *popts,
7855614e71bSYork Sun 			       const common_timing_params_t *common_dimm)
7865614e71bSYork Sun {
7875614e71bSYork Sun 	unsigned int mem_en;		/* DDR SDRAM interface logic enable */
7885614e71bSYork Sun 	unsigned int sren;		/* Self refresh enable (during sleep) */
7895614e71bSYork Sun 	unsigned int ecc_en;		/* ECC enable. */
7905614e71bSYork Sun 	unsigned int rd_en;		/* Registered DIMM enable */
7915614e71bSYork Sun 	unsigned int sdram_type;	/* Type of SDRAM */
7925614e71bSYork Sun 	unsigned int dyn_pwr;		/* Dynamic power management mode */
7935614e71bSYork Sun 	unsigned int dbw;		/* DRAM dta bus width */
7945614e71bSYork Sun 	unsigned int eight_be = 0;	/* 8-beat burst enable, DDR2 is zero */
7955614e71bSYork Sun 	unsigned int ncap = 0;		/* Non-concurrent auto-precharge */
7965614e71bSYork Sun 	unsigned int threet_en;		/* Enable 3T timing */
7975614e71bSYork Sun 	unsigned int twot_en;		/* Enable 2T timing */
7985614e71bSYork Sun 	unsigned int ba_intlv_ctl;	/* Bank (CS) interleaving control */
7995614e71bSYork Sun 	unsigned int x32_en = 0;	/* x32 enable */
8005614e71bSYork Sun 	unsigned int pchb8 = 0;		/* precharge bit 8 enable */
8015614e71bSYork Sun 	unsigned int hse;		/* Global half strength override */
802d28cb671SYork Sun 	unsigned int acc_ecc_en = 0;	/* Accumulated ECC enable */
8035614e71bSYork Sun 	unsigned int mem_halt = 0;	/* memory controller halt */
8045614e71bSYork Sun 	unsigned int bi = 0;		/* Bypass initialization */
8055614e71bSYork Sun 
8065614e71bSYork Sun 	mem_en = 1;
8075614e71bSYork Sun 	sren = popts->self_refresh_in_sleep;
8085614e71bSYork Sun 	if (common_dimm->all_dimms_ecc_capable) {
8095614e71bSYork Sun 		/* Allow setting of ECC only if all DIMMs are ECC. */
8105614e71bSYork Sun 		ecc_en = popts->ecc_mode;
8115614e71bSYork Sun 	} else {
8125614e71bSYork Sun 		ecc_en = 0;
8135614e71bSYork Sun 	}
8145614e71bSYork Sun 
8155614e71bSYork Sun 	if (common_dimm->all_dimms_registered &&
8165614e71bSYork Sun 	    !common_dimm->all_dimms_unbuffered)	{
8175614e71bSYork Sun 		rd_en = 1;
8185614e71bSYork Sun 		twot_en = 0;
8195614e71bSYork Sun 	} else {
8205614e71bSYork Sun 		rd_en = 0;
8215614e71bSYork Sun 		twot_en = popts->twot_en;
8225614e71bSYork Sun 	}
8235614e71bSYork Sun 
8245614e71bSYork Sun 	sdram_type = CONFIG_FSL_SDRAM_TYPE;
8255614e71bSYork Sun 
8265614e71bSYork Sun 	dyn_pwr = popts->dynamic_power;
8275614e71bSYork Sun 	dbw = popts->data_bus_width;
8285614e71bSYork Sun 	/* 8-beat burst enable DDR-III case
8295614e71bSYork Sun 	 * we must clear it when use the on-the-fly mode,
8305614e71bSYork Sun 	 * must set it when use the 32-bits bus mode.
8315614e71bSYork Sun 	 */
83234e026f9SYork Sun 	if ((sdram_type == SDRAM_TYPE_DDR3) ||
83334e026f9SYork Sun 	    (sdram_type == SDRAM_TYPE_DDR4)) {
8345614e71bSYork Sun 		if (popts->burst_length == DDR_BL8)
8355614e71bSYork Sun 			eight_be = 1;
8365614e71bSYork Sun 		if (popts->burst_length == DDR_OTF)
8375614e71bSYork Sun 			eight_be = 0;
8385614e71bSYork Sun 		if (dbw == 0x1)
8395614e71bSYork Sun 			eight_be = 1;
8405614e71bSYork Sun 	}
8415614e71bSYork Sun 
8425614e71bSYork Sun 	threet_en = popts->threet_en;
8435614e71bSYork Sun 	ba_intlv_ctl = popts->ba_intlv_ctl;
8445614e71bSYork Sun 	hse = popts->half_strength_driver_enable;
8455614e71bSYork Sun 
846d28cb671SYork Sun 	/* set when ddr bus width < 64 */
847d28cb671SYork Sun 	acc_ecc_en = (dbw != 0 && ecc_en == 1) ? 1 : 0;
848d28cb671SYork Sun 
8495614e71bSYork Sun 	ddr->ddr_sdram_cfg = (0
8505614e71bSYork Sun 			| ((mem_en & 0x1) << 31)
8515614e71bSYork Sun 			| ((sren & 0x1) << 30)
8525614e71bSYork Sun 			| ((ecc_en & 0x1) << 29)
8535614e71bSYork Sun 			| ((rd_en & 0x1) << 28)
8545614e71bSYork Sun 			| ((sdram_type & 0x7) << 24)
8555614e71bSYork Sun 			| ((dyn_pwr & 0x1) << 21)
8565614e71bSYork Sun 			| ((dbw & 0x3) << 19)
8575614e71bSYork Sun 			| ((eight_be & 0x1) << 18)
8585614e71bSYork Sun 			| ((ncap & 0x1) << 17)
8595614e71bSYork Sun 			| ((threet_en & 0x1) << 16)
8605614e71bSYork Sun 			| ((twot_en & 0x1) << 15)
8615614e71bSYork Sun 			| ((ba_intlv_ctl & 0x7F) << 8)
8625614e71bSYork Sun 			| ((x32_en & 0x1) << 5)
8635614e71bSYork Sun 			| ((pchb8 & 0x1) << 4)
8645614e71bSYork Sun 			| ((hse & 0x1) << 3)
865d28cb671SYork Sun 			| ((acc_ecc_en & 0x1) << 2)
8665614e71bSYork Sun 			| ((mem_halt & 0x1) << 1)
8675614e71bSYork Sun 			| ((bi & 0x1) << 0)
8685614e71bSYork Sun 			);
8695614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_cfg = 0x%08x\n", ddr->ddr_sdram_cfg);
8705614e71bSYork Sun }
8715614e71bSYork Sun 
8725614e71bSYork Sun /* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */
87303e664d8SYork Sun static void set_ddr_sdram_cfg_2(const unsigned int ctrl_num,
87403e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
8755614e71bSYork Sun 			       const memctl_options_t *popts,
8765614e71bSYork Sun 			       const unsigned int unq_mrs_en)
8775614e71bSYork Sun {
8785614e71bSYork Sun 	unsigned int frc_sr = 0;	/* Force self refresh */
8795614e71bSYork Sun 	unsigned int sr_ie = 0;		/* Self-refresh interrupt enable */
8805614e71bSYork Sun 	unsigned int odt_cfg = 0;	/* ODT configuration */
8815614e71bSYork Sun 	unsigned int num_pr;		/* Number of posted refreshes */
8825614e71bSYork Sun 	unsigned int slow = 0;		/* DDR will be run less than 1250 */
8835614e71bSYork Sun 	unsigned int x4_en = 0;		/* x4 DRAM enable */
8845614e71bSYork Sun 	unsigned int obc_cfg;		/* On-The-Fly Burst Chop Cfg */
8855614e71bSYork Sun 	unsigned int ap_en;		/* Address Parity Enable */
8865614e71bSYork Sun 	unsigned int d_init;		/* DRAM data initialization */
8875614e71bSYork Sun 	unsigned int rcw_en = 0;	/* Register Control Word Enable */
8885614e71bSYork Sun 	unsigned int md_en = 0;		/* Mirrored DIMM Enable */
8895614e71bSYork Sun 	unsigned int qd_en = 0;		/* quad-rank DIMM Enable */
8905614e71bSYork Sun 	int i;
89134e026f9SYork Sun #ifndef CONFIG_SYS_FSL_DDR4
89234e026f9SYork Sun 	unsigned int dll_rst_dis = 1;	/* DLL reset disable */
89334e026f9SYork Sun 	unsigned int dqs_cfg;		/* DQS configuration */
8945614e71bSYork Sun 
8955614e71bSYork Sun 	dqs_cfg = popts->dqs_config;
89634e026f9SYork Sun #endif
8975614e71bSYork Sun 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
8985614e71bSYork Sun 		if (popts->cs_local_opts[i].odt_rd_cfg
8995614e71bSYork Sun 			|| popts->cs_local_opts[i].odt_wr_cfg) {
9005614e71bSYork Sun 			odt_cfg = SDRAM_CFG2_ODT_ONLY_READ;
9015614e71bSYork Sun 			break;
9025614e71bSYork Sun 		}
9035614e71bSYork Sun 	}
904e368c206SJoakim Tjernlund 	sr_ie = popts->self_refresh_interrupt_en;
905c0c32af0SYork Sun 	num_pr = popts->package_3ds + 1;
9065614e71bSYork Sun 
9075614e71bSYork Sun 	/*
9085614e71bSYork Sun 	 * 8572 manual says
9095614e71bSYork Sun 	 *     {TIMING_CFG_1[PRETOACT]
9105614e71bSYork Sun 	 *      + [DDR_SDRAM_CFG_2[NUM_PR]
9115614e71bSYork Sun 	 *        * ({EXT_REFREC || REFREC} + 8 + 2)]}
9125614e71bSYork Sun 	 *      << DDR_SDRAM_INTERVAL[REFINT]
9135614e71bSYork Sun 	 */
91434e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
9155614e71bSYork Sun 	obc_cfg = popts->otf_burst_chop_en;
9165614e71bSYork Sun #else
9175614e71bSYork Sun 	obc_cfg = 0;
9185614e71bSYork Sun #endif
9195614e71bSYork Sun 
9205614e71bSYork Sun #if (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7)
92103e664d8SYork Sun 	slow = get_ddr_freq(ctrl_num) < 1249000000;
9225614e71bSYork Sun #endif
9235614e71bSYork Sun 
924eb118807SShengzhou Liu 	if (popts->registered_dimm_en)
9255614e71bSYork Sun 		rcw_en = 1;
926eb118807SShengzhou Liu 
927eb118807SShengzhou Liu 	/* DDR4 can have address parity for UDIMM and discrete */
928eb118807SShengzhou Liu 	if ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) &&
929eb118807SShengzhou Liu 	    (!popts->registered_dimm_en)) {
9305614e71bSYork Sun 		ap_en = 0;
931eb118807SShengzhou Liu 	} else {
932eb118807SShengzhou Liu 		ap_en = popts->ap_en;
9335614e71bSYork Sun 	}
9345614e71bSYork Sun 
9355614e71bSYork Sun 	x4_en = popts->x4_en ? 1 : 0;
9365614e71bSYork Sun 
9375614e71bSYork Sun #if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
9385614e71bSYork Sun 	/* Use the DDR controller to auto initialize memory. */
9395614e71bSYork Sun 	d_init = popts->ecc_init_using_memctl;
9405614e71bSYork Sun 	ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE;
9415614e71bSYork Sun 	debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init);
9425614e71bSYork Sun #else
9435614e71bSYork Sun 	/* Memory will be initialized via DMA, or not at all. */
9445614e71bSYork Sun 	d_init = 0;
9455614e71bSYork Sun #endif
9465614e71bSYork Sun 
94734e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
9485614e71bSYork Sun 	md_en = popts->mirrored_dimm;
9495614e71bSYork Sun #endif
9505614e71bSYork Sun 	qd_en = popts->quad_rank_present ? 1 : 0;
9515614e71bSYork Sun 	ddr->ddr_sdram_cfg_2 = (0
9525614e71bSYork Sun 		| ((frc_sr & 0x1) << 31)
9535614e71bSYork Sun 		| ((sr_ie & 0x1) << 30)
95434e026f9SYork Sun #ifndef CONFIG_SYS_FSL_DDR4
9555614e71bSYork Sun 		| ((dll_rst_dis & 0x1) << 29)
9565614e71bSYork Sun 		| ((dqs_cfg & 0x3) << 26)
95734e026f9SYork Sun #endif
9585614e71bSYork Sun 		| ((odt_cfg & 0x3) << 21)
9595614e71bSYork Sun 		| ((num_pr & 0xf) << 12)
9605614e71bSYork Sun 		| ((slow & 1) << 11)
9615614e71bSYork Sun 		| (x4_en << 10)
9625614e71bSYork Sun 		| (qd_en << 9)
9635614e71bSYork Sun 		| (unq_mrs_en << 8)
9645614e71bSYork Sun 		| ((obc_cfg & 0x1) << 6)
9655614e71bSYork Sun 		| ((ap_en & 0x1) << 5)
9665614e71bSYork Sun 		| ((d_init & 0x1) << 4)
9675614e71bSYork Sun 		| ((rcw_en & 0x1) << 2)
9685614e71bSYork Sun 		| ((md_en & 0x1) << 0)
9695614e71bSYork Sun 		);
9705614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2);
9715614e71bSYork Sun }
9725614e71bSYork Sun 
97334e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
9745614e71bSYork Sun /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
97503e664d8SYork Sun static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
97603e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
9775614e71bSYork Sun 				const memctl_options_t *popts,
9785614e71bSYork Sun 				const common_timing_params_t *common_dimm,
9795614e71bSYork Sun 				const unsigned int unq_mrs_en)
9805614e71bSYork Sun {
9815614e71bSYork Sun 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
9825614e71bSYork Sun 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
9835614e71bSYork Sun 	int i;
98434e026f9SYork Sun 	unsigned int wr_crc = 0;	/* Disable */
9855614e71bSYork Sun 	unsigned int rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
9865614e71bSYork Sun 	unsigned int srt = 0;	/* self-refresh temerature, normal range */
98703e664d8SYork Sun 	unsigned int cwl = compute_cas_write_latency(ctrl_num) - 9;
98834e026f9SYork Sun 	unsigned int mpr = 0;	/* serial */
98934e026f9SYork Sun 	unsigned int wc_lat;
99003e664d8SYork Sun 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
9915614e71bSYork Sun 
9925614e71bSYork Sun 	if (popts->rtt_override)
9935614e71bSYork Sun 		rtt_wr = popts->rtt_wr_override_value;
9945614e71bSYork Sun 	else
9955614e71bSYork Sun 		rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
9965614e71bSYork Sun 
9975614e71bSYork Sun 	if (common_dimm->extended_op_srt)
9985614e71bSYork Sun 		srt = common_dimm->extended_op_srt;
9995614e71bSYork Sun 
10005614e71bSYork Sun 	esdmode2 = (0
100134e026f9SYork Sun 		| ((wr_crc & 0x1) << 12)
10025614e71bSYork Sun 		| ((rtt_wr & 0x3) << 9)
100334e026f9SYork Sun 		| ((srt & 0x3) << 6)
100434e026f9SYork Sun 		| ((cwl & 0x7) << 3));
100534e026f9SYork Sun 
100634e026f9SYork Sun 	if (mclk_ps >= 1250)
100734e026f9SYork Sun 		wc_lat = 0;
100834e026f9SYork Sun 	else if (mclk_ps >= 833)
100934e026f9SYork Sun 		wc_lat = 1;
101034e026f9SYork Sun 	else
101134e026f9SYork Sun 		wc_lat = 2;
101234e026f9SYork Sun 
101334e026f9SYork Sun 	esdmode3 = (0
101434e026f9SYork Sun 		| ((mpr & 0x3) << 11)
101534e026f9SYork Sun 		| ((wc_lat & 0x3) << 9));
101634e026f9SYork Sun 
10175614e71bSYork Sun 	ddr->ddr_sdram_mode_2 = (0
10185614e71bSYork Sun 				 | ((esdmode2 & 0xFFFF) << 16)
10195614e71bSYork Sun 				 | ((esdmode3 & 0xFFFF) << 0)
10205614e71bSYork Sun 				 );
10215614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
10225614e71bSYork Sun 
10235614e71bSYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
10245614e71bSYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
10255614e71bSYork Sun 			if (popts->rtt_override)
10265614e71bSYork Sun 				rtt_wr = popts->rtt_wr_override_value;
10275614e71bSYork Sun 			else
10285614e71bSYork Sun 				rtt_wr = popts->cs_local_opts[i].odt_rtt_wr;
10295614e71bSYork Sun 
10305614e71bSYork Sun 			esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
10315614e71bSYork Sun 			esdmode2 |= (rtt_wr & 0x3) << 9;
10325614e71bSYork Sun 			switch (i) {
10335614e71bSYork Sun 			case 1:
10345614e71bSYork Sun 				ddr->ddr_sdram_mode_4 = (0
10355614e71bSYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
10365614e71bSYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
10375614e71bSYork Sun 					);
10385614e71bSYork Sun 				break;
10395614e71bSYork Sun 			case 2:
10405614e71bSYork Sun 				ddr->ddr_sdram_mode_6 = (0
10415614e71bSYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
10425614e71bSYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
10435614e71bSYork Sun 					);
10445614e71bSYork Sun 				break;
10455614e71bSYork Sun 			case 3:
10465614e71bSYork Sun 				ddr->ddr_sdram_mode_8 = (0
10475614e71bSYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
10485614e71bSYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
10495614e71bSYork Sun 					);
10505614e71bSYork Sun 				break;
10515614e71bSYork Sun 			}
10525614e71bSYork Sun 		}
10535614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
10545614e71bSYork Sun 		      ddr->ddr_sdram_mode_4);
10555614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
10565614e71bSYork Sun 		      ddr->ddr_sdram_mode_6);
10575614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
10585614e71bSYork Sun 		      ddr->ddr_sdram_mode_8);
10595614e71bSYork Sun 	}
10605614e71bSYork Sun }
106134e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
106234e026f9SYork Sun /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
106303e664d8SYork Sun static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
106403e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
106534e026f9SYork Sun 				const memctl_options_t *popts,
106634e026f9SYork Sun 				const common_timing_params_t *common_dimm,
106734e026f9SYork Sun 				const unsigned int unq_mrs_en)
106834e026f9SYork Sun {
106934e026f9SYork Sun 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
107034e026f9SYork Sun 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
107134e026f9SYork Sun 	int i;
107234e026f9SYork Sun 	unsigned int rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
107334e026f9SYork Sun 	unsigned int srt = 0;	/* self-refresh temerature, normal range */
107434e026f9SYork Sun 	unsigned int asr = 0;	/* auto self-refresh disable */
107503e664d8SYork Sun 	unsigned int cwl = compute_cas_write_latency(ctrl_num) - 5;
107634e026f9SYork Sun 	unsigned int pasr = 0;	/* partial array self refresh disable */
107734e026f9SYork Sun 
107834e026f9SYork Sun 	if (popts->rtt_override)
107934e026f9SYork Sun 		rtt_wr = popts->rtt_wr_override_value;
108034e026f9SYork Sun 	else
108134e026f9SYork Sun 		rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
108234e026f9SYork Sun 
108334e026f9SYork Sun 	if (common_dimm->extended_op_srt)
108434e026f9SYork Sun 		srt = common_dimm->extended_op_srt;
108534e026f9SYork Sun 
108634e026f9SYork Sun 	esdmode2 = (0
108734e026f9SYork Sun 		| ((rtt_wr & 0x3) << 9)
108834e026f9SYork Sun 		| ((srt & 0x1) << 7)
108934e026f9SYork Sun 		| ((asr & 0x1) << 6)
109034e026f9SYork Sun 		| ((cwl & 0x7) << 3)
109134e026f9SYork Sun 		| ((pasr & 0x7) << 0));
109234e026f9SYork Sun 	ddr->ddr_sdram_mode_2 = (0
109334e026f9SYork Sun 				 | ((esdmode2 & 0xFFFF) << 16)
109434e026f9SYork Sun 				 | ((esdmode3 & 0xFFFF) << 0)
109534e026f9SYork Sun 				 );
109634e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
109734e026f9SYork Sun 
109834e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
109934e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
110034e026f9SYork Sun 			if (popts->rtt_override)
110134e026f9SYork Sun 				rtt_wr = popts->rtt_wr_override_value;
110234e026f9SYork Sun 			else
110334e026f9SYork Sun 				rtt_wr = popts->cs_local_opts[i].odt_rtt_wr;
110434e026f9SYork Sun 
110534e026f9SYork Sun 			esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
110634e026f9SYork Sun 			esdmode2 |= (rtt_wr & 0x3) << 9;
110734e026f9SYork Sun 			switch (i) {
110834e026f9SYork Sun 			case 1:
110934e026f9SYork Sun 				ddr->ddr_sdram_mode_4 = (0
111034e026f9SYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
111134e026f9SYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
111234e026f9SYork Sun 					);
111334e026f9SYork Sun 				break;
111434e026f9SYork Sun 			case 2:
111534e026f9SYork Sun 				ddr->ddr_sdram_mode_6 = (0
111634e026f9SYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
111734e026f9SYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
111834e026f9SYork Sun 					);
111934e026f9SYork Sun 				break;
112034e026f9SYork Sun 			case 3:
112134e026f9SYork Sun 				ddr->ddr_sdram_mode_8 = (0
112234e026f9SYork Sun 					| ((esdmode2 & 0xFFFF) << 16)
112334e026f9SYork Sun 					| ((esdmode3 & 0xFFFF) << 0)
112434e026f9SYork Sun 					);
112534e026f9SYork Sun 				break;
112634e026f9SYork Sun 			}
112734e026f9SYork Sun 		}
112834e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
112934e026f9SYork Sun 			ddr->ddr_sdram_mode_4);
113034e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
113134e026f9SYork Sun 			ddr->ddr_sdram_mode_6);
113234e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
113334e026f9SYork Sun 			ddr->ddr_sdram_mode_8);
113434e026f9SYork Sun 	}
113534e026f9SYork Sun }
113634e026f9SYork Sun 
113734e026f9SYork Sun #else /* for DDR2 and DDR1 */
113834e026f9SYork Sun /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
113903e664d8SYork Sun static void set_ddr_sdram_mode_2(const unsigned int ctrl_num,
114003e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
114134e026f9SYork Sun 				const memctl_options_t *popts,
114234e026f9SYork Sun 				const common_timing_params_t *common_dimm,
114334e026f9SYork Sun 				const unsigned int unq_mrs_en)
114434e026f9SYork Sun {
114534e026f9SYork Sun 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
114634e026f9SYork Sun 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
114734e026f9SYork Sun 
114834e026f9SYork Sun 	ddr->ddr_sdram_mode_2 = (0
114934e026f9SYork Sun 				 | ((esdmode2 & 0xFFFF) << 16)
115034e026f9SYork Sun 				 | ((esdmode3 & 0xFFFF) << 0)
115134e026f9SYork Sun 				 );
115234e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
115334e026f9SYork Sun }
115434e026f9SYork Sun #endif
115534e026f9SYork Sun 
115634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
115734e026f9SYork Sun /* DDR SDRAM Mode configuration 9 (DDR_SDRAM_MODE_9) */
115834e026f9SYork Sun static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
115934e026f9SYork Sun 				const memctl_options_t *popts,
116034e026f9SYork Sun 				const common_timing_params_t *common_dimm,
116134e026f9SYork Sun 				const unsigned int unq_mrs_en)
116234e026f9SYork Sun {
116334e026f9SYork Sun 	int i;
116434e026f9SYork Sun 	unsigned short esdmode4 = 0;	/* Extended SDRAM mode 4 */
116534e026f9SYork Sun 	unsigned short esdmode5;	/* Extended SDRAM mode 5 */
11666b95be22SYork Sun 	int rtt_park = 0;
11678a51429eSYork Sun 	bool four_cs = false;
1168eb118807SShengzhou Liu 	const unsigned int mclk_ps = get_memory_clk_period_ps(0);
116934e026f9SYork Sun 
11708a51429eSYork Sun #if CONFIG_CHIP_SELECTS_PER_CTRL == 4
11718a51429eSYork Sun 	if ((ddr->cs[0].config & SDRAM_CS_CONFIG_EN) &&
11728a51429eSYork Sun 	    (ddr->cs[1].config & SDRAM_CS_CONFIG_EN) &&
11738a51429eSYork Sun 	    (ddr->cs[2].config & SDRAM_CS_CONFIG_EN) &&
11748a51429eSYork Sun 	    (ddr->cs[3].config & SDRAM_CS_CONFIG_EN))
11758a51429eSYork Sun 		four_cs = true;
11768a51429eSYork Sun #endif
11776b95be22SYork Sun 	if (ddr->cs[0].config & SDRAM_CS_CONFIG_EN) {
11786b95be22SYork Sun 		esdmode5 = 0x00000500;	/* Data mask enable, RTT_PARK CS0 */
11798a51429eSYork Sun 		rtt_park = four_cs ? 0 : 1;
11806b95be22SYork Sun 	} else {
11816b95be22SYork Sun 		esdmode5 = 0x00000400;	/* Data mask enabled */
11826b95be22SYork Sun 	}
118334e026f9SYork Sun 
1184426230a6SYork Sun 	/*
1185426230a6SYork Sun 	 * For DDR3, set C/A latency if address parity is enabled.
1186426230a6SYork Sun 	 * For DDR4, set C/A latency for UDIMM only. For RDIMM the delay is
1187426230a6SYork Sun 	 * handled by register chip and RCW settings.
1188426230a6SYork Sun 	 */
1189426230a6SYork Sun 	if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) &&
1190426230a6SYork Sun 	    ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) ||
1191426230a6SYork Sun 	     !popts->registered_dimm_en)) {
1192eb118807SShengzhou Liu 		if (mclk_ps >= 935) {
1193eb118807SShengzhou Liu 			/* for DDR4-1600/1866/2133 */
1194eb118807SShengzhou Liu 			esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK;
1195eb118807SShengzhou Liu 		} else if (mclk_ps >= 833) {
1196eb118807SShengzhou Liu 			/* for DDR4-2400 */
1197eb118807SShengzhou Liu 			esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK;
1198eb118807SShengzhou Liu 		} else {
1199eb118807SShengzhou Liu 			printf("parity: mclk_ps = %d not supported\n", mclk_ps);
1200eb118807SShengzhou Liu 		}
1201eb118807SShengzhou Liu 	}
1202eb118807SShengzhou Liu 
120334e026f9SYork Sun 	ddr->ddr_sdram_mode_9 = (0
120434e026f9SYork Sun 				 | ((esdmode4 & 0xffff) << 16)
120534e026f9SYork Sun 				 | ((esdmode5 & 0xffff) << 0)
120634e026f9SYork Sun 				);
120766869f95SYork Sun 
12088a51429eSYork Sun 	/* Normally only the first enabled CS use 0x500, others use 0x400
12098a51429eSYork Sun 	 * But when four chip-selects are all enabled, all mode registers
12108a51429eSYork Sun 	 * need 0x500 to park.
12118a51429eSYork Sun 	 */
121266869f95SYork Sun 
1213c0c32af0SYork Sun 	debug("FSLDDR: ddr_sdram_mode_9 = 0x%08x\n", ddr->ddr_sdram_mode_9);
121434e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
121534e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
12166b95be22SYork Sun 			if (!rtt_park &&
12176b95be22SYork Sun 			    (ddr->cs[i].config & SDRAM_CS_CONFIG_EN)) {
12186b95be22SYork Sun 				esdmode5 |= 0x00000500;	/* RTT_PARK */
12198a51429eSYork Sun 				rtt_park = four_cs ? 0 : 1;
12206b95be22SYork Sun 			} else {
12216b95be22SYork Sun 				esdmode5 = 0x00000400;
12226b95be22SYork Sun 			}
1223eb118807SShengzhou Liu 
1224426230a6SYork Sun 			if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) &&
1225426230a6SYork Sun 			    ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) ||
1226426230a6SYork Sun 			     !popts->registered_dimm_en)) {
1227eb118807SShengzhou Liu 				if (mclk_ps >= 935) {
1228eb118807SShengzhou Liu 					/* for DDR4-1600/1866/2133 */
1229eb118807SShengzhou Liu 					esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK;
1230eb118807SShengzhou Liu 				} else if (mclk_ps >= 833) {
1231eb118807SShengzhou Liu 					/* for DDR4-2400 */
1232eb118807SShengzhou Liu 					esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK;
1233eb118807SShengzhou Liu 				} else {
1234eb118807SShengzhou Liu 					printf("parity: mclk_ps = %d not supported\n",
1235eb118807SShengzhou Liu 					       mclk_ps);
1236eb118807SShengzhou Liu 				}
1237eb118807SShengzhou Liu 			}
1238eb118807SShengzhou Liu 
123934e026f9SYork Sun 			switch (i) {
124034e026f9SYork Sun 			case 1:
124134e026f9SYork Sun 				ddr->ddr_sdram_mode_11 = (0
124234e026f9SYork Sun 					| ((esdmode4 & 0xFFFF) << 16)
124334e026f9SYork Sun 					| ((esdmode5 & 0xFFFF) << 0)
124434e026f9SYork Sun 					);
124534e026f9SYork Sun 				break;
124634e026f9SYork Sun 			case 2:
124734e026f9SYork Sun 				ddr->ddr_sdram_mode_13 = (0
124834e026f9SYork Sun 					| ((esdmode4 & 0xFFFF) << 16)
124934e026f9SYork Sun 					| ((esdmode5 & 0xFFFF) << 0)
125034e026f9SYork Sun 					);
125134e026f9SYork Sun 				break;
125234e026f9SYork Sun 			case 3:
125334e026f9SYork Sun 				ddr->ddr_sdram_mode_15 = (0
125434e026f9SYork Sun 					| ((esdmode4 & 0xFFFF) << 16)
125534e026f9SYork Sun 					| ((esdmode5 & 0xFFFF) << 0)
125634e026f9SYork Sun 					);
125734e026f9SYork Sun 				break;
125834e026f9SYork Sun 			}
125934e026f9SYork Sun 		}
126034e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_11 = 0x%08x\n",
126134e026f9SYork Sun 		      ddr->ddr_sdram_mode_11);
126234e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_13 = 0x%08x\n",
126334e026f9SYork Sun 		      ddr->ddr_sdram_mode_13);
126434e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_15 = 0x%08x\n",
126534e026f9SYork Sun 		      ddr->ddr_sdram_mode_15);
126634e026f9SYork Sun 	}
126734e026f9SYork Sun }
126834e026f9SYork Sun 
126934e026f9SYork Sun /* DDR SDRAM Mode configuration 10 (DDR_SDRAM_MODE_10) */
127003e664d8SYork Sun static void set_ddr_sdram_mode_10(const unsigned int ctrl_num,
127103e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
127234e026f9SYork Sun 				const memctl_options_t *popts,
127334e026f9SYork Sun 				const common_timing_params_t *common_dimm,
127434e026f9SYork Sun 				const unsigned int unq_mrs_en)
127534e026f9SYork Sun {
127634e026f9SYork Sun 	int i;
127734e026f9SYork Sun 	unsigned short esdmode6 = 0;	/* Extended SDRAM mode 6 */
127834e026f9SYork Sun 	unsigned short esdmode7 = 0;	/* Extended SDRAM mode 7 */
127903e664d8SYork Sun 	unsigned int tccdl_min = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps);
128034e026f9SYork Sun 
128134e026f9SYork Sun 	esdmode6 = ((tccdl_min - 4) & 0x7) << 10;
128234e026f9SYork Sun 
12830fb71974SYork Sun 	if (popts->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2)
12840fb71974SYork Sun 		esdmode6 |= 1 << 6;	/* Range 2 */
12850fb71974SYork Sun 
128634e026f9SYork Sun 	ddr->ddr_sdram_mode_10 = (0
128734e026f9SYork Sun 				 | ((esdmode6 & 0xffff) << 16)
128834e026f9SYork Sun 				 | ((esdmode7 & 0xffff) << 0)
128934e026f9SYork Sun 				);
1290c0c32af0SYork Sun 	debug("FSLDDR: ddr_sdram_mode_10 = 0x%08x\n", ddr->ddr_sdram_mode_10);
129134e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
129234e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
129334e026f9SYork Sun 			switch (i) {
129434e026f9SYork Sun 			case 1:
129534e026f9SYork Sun 				ddr->ddr_sdram_mode_12 = (0
129634e026f9SYork Sun 					| ((esdmode6 & 0xFFFF) << 16)
129734e026f9SYork Sun 					| ((esdmode7 & 0xFFFF) << 0)
129834e026f9SYork Sun 					);
129934e026f9SYork Sun 				break;
130034e026f9SYork Sun 			case 2:
130134e026f9SYork Sun 				ddr->ddr_sdram_mode_14 = (0
130234e026f9SYork Sun 					| ((esdmode6 & 0xFFFF) << 16)
130334e026f9SYork Sun 					| ((esdmode7 & 0xFFFF) << 0)
130434e026f9SYork Sun 					);
130534e026f9SYork Sun 				break;
130634e026f9SYork Sun 			case 3:
130734e026f9SYork Sun 				ddr->ddr_sdram_mode_16 = (0
130834e026f9SYork Sun 					| ((esdmode6 & 0xFFFF) << 16)
130934e026f9SYork Sun 					| ((esdmode7 & 0xFFFF) << 0)
131034e026f9SYork Sun 					);
131134e026f9SYork Sun 				break;
131234e026f9SYork Sun 			}
131334e026f9SYork Sun 		}
131434e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_12 = 0x%08x\n",
131534e026f9SYork Sun 		      ddr->ddr_sdram_mode_12);
131634e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_14 = 0x%08x\n",
131734e026f9SYork Sun 		      ddr->ddr_sdram_mode_14);
131834e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_16 = 0x%08x\n",
131934e026f9SYork Sun 		      ddr->ddr_sdram_mode_16);
132034e026f9SYork Sun 	}
132134e026f9SYork Sun }
132234e026f9SYork Sun 
132334e026f9SYork Sun #endif
13245614e71bSYork Sun 
13255614e71bSYork Sun /* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */
132603e664d8SYork Sun static void set_ddr_sdram_interval(const unsigned int ctrl_num,
132703e664d8SYork Sun 				fsl_ddr_cfg_regs_t *ddr,
13285614e71bSYork Sun 				const memctl_options_t *popts,
13295614e71bSYork Sun 				const common_timing_params_t *common_dimm)
13305614e71bSYork Sun {
13315614e71bSYork Sun 	unsigned int refint;	/* Refresh interval */
13325614e71bSYork Sun 	unsigned int bstopre;	/* Precharge interval */
13335614e71bSYork Sun 
133403e664d8SYork Sun 	refint = picos_to_mclk(ctrl_num, common_dimm->refresh_rate_ps);
13355614e71bSYork Sun 
13365614e71bSYork Sun 	bstopre = popts->bstopre;
13375614e71bSYork Sun 
13385614e71bSYork Sun 	/* refint field used 0x3FFF in earlier controllers */
13395614e71bSYork Sun 	ddr->ddr_sdram_interval = (0
13405614e71bSYork Sun 				   | ((refint & 0xFFFF) << 16)
13415614e71bSYork Sun 				   | ((bstopre & 0x3FFF) << 0)
13425614e71bSYork Sun 				   );
13435614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval);
13445614e71bSYork Sun }
13455614e71bSYork Sun 
134634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
13475614e71bSYork Sun /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
134803e664d8SYork Sun static void set_ddr_sdram_mode(const unsigned int ctrl_num,
134903e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
13505614e71bSYork Sun 			       const memctl_options_t *popts,
13515614e71bSYork Sun 			       const common_timing_params_t *common_dimm,
13525614e71bSYork Sun 			       unsigned int cas_latency,
13535614e71bSYork Sun 			       unsigned int additive_latency,
13545614e71bSYork Sun 			       const unsigned int unq_mrs_en)
13555614e71bSYork Sun {
135634e026f9SYork Sun 	int i;
135734e026f9SYork Sun 	unsigned short esdmode;		/* Extended SDRAM mode */
135834e026f9SYork Sun 	unsigned short sdmode;		/* SDRAM mode */
135934e026f9SYork Sun 
136034e026f9SYork Sun 	/* Mode Register - MR1 */
136134e026f9SYork Sun 	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
136234e026f9SYork Sun 	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
136334e026f9SYork Sun 	unsigned int rtt;
136434e026f9SYork Sun 	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
136534e026f9SYork Sun 	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
136634e026f9SYork Sun 	unsigned int dic = 0;		/* Output driver impedance, 40ohm */
136734e026f9SYork Sun 	unsigned int dll_en = 1;	/* DLL Enable  1=Enable (Normal),
136834e026f9SYork Sun 						       0=Disable (Test/Debug) */
136934e026f9SYork Sun 
137034e026f9SYork Sun 	/* Mode Register - MR0 */
137134e026f9SYork Sun 	unsigned int wr = 0;	/* Write Recovery */
137234e026f9SYork Sun 	unsigned int dll_rst;	/* DLL Reset */
137334e026f9SYork Sun 	unsigned int mode;	/* Normal=0 or Test=1 */
137434e026f9SYork Sun 	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
137534e026f9SYork Sun 	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
137634e026f9SYork Sun 	unsigned int bt;
137734e026f9SYork Sun 	unsigned int bl;	/* BL: Burst Length */
137834e026f9SYork Sun 
137934e026f9SYork Sun 	unsigned int wr_mclk;
138034e026f9SYork Sun 	/* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */
138134e026f9SYork Sun 	static const u8 wr_table[] = {
138234e026f9SYork Sun 		0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6};
138334e026f9SYork Sun 	/* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */
138434e026f9SYork Sun 	static const u8 cas_latency_table[] = {
138534e026f9SYork Sun 		0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
138634e026f9SYork Sun 		9, 9, 10, 10, 11, 11};
138734e026f9SYork Sun 
138834e026f9SYork Sun 	if (popts->rtt_override)
138934e026f9SYork Sun 		rtt = popts->rtt_override_value;
139034e026f9SYork Sun 	else
139134e026f9SYork Sun 		rtt = popts->cs_local_opts[0].odt_rtt_norm;
139234e026f9SYork Sun 
139334e026f9SYork Sun 	if (additive_latency == (cas_latency - 1))
139434e026f9SYork Sun 		al = 1;
139534e026f9SYork Sun 	if (additive_latency == (cas_latency - 2))
139634e026f9SYork Sun 		al = 2;
139734e026f9SYork Sun 
139834e026f9SYork Sun 	if (popts->quad_rank_present)
139934e026f9SYork Sun 		dic = 1;	/* output driver impedance 240/7 ohm */
140034e026f9SYork Sun 
140134e026f9SYork Sun 	/*
140234e026f9SYork Sun 	 * The esdmode value will also be used for writing
140334e026f9SYork Sun 	 * MR1 during write leveling for DDR3, although the
140434e026f9SYork Sun 	 * bits specifically related to the write leveling
140534e026f9SYork Sun 	 * scheme will be handled automatically by the DDR
140634e026f9SYork Sun 	 * controller. so we set the wrlvl_en = 0 here.
140734e026f9SYork Sun 	 */
140834e026f9SYork Sun 	esdmode = (0
140934e026f9SYork Sun 		| ((qoff & 0x1) << 12)
141034e026f9SYork Sun 		| ((tdqs_en & 0x1) << 11)
141134e026f9SYork Sun 		| ((rtt & 0x7) << 8)
141234e026f9SYork Sun 		| ((wrlvl_en & 0x1) << 7)
141334e026f9SYork Sun 		| ((al & 0x3) << 3)
141434e026f9SYork Sun 		| ((dic & 0x3) << 1)   /* DIC field is split */
141534e026f9SYork Sun 		| ((dll_en & 0x1) << 0)
141634e026f9SYork Sun 		);
141734e026f9SYork Sun 
141834e026f9SYork Sun 	/*
141934e026f9SYork Sun 	 * DLL control for precharge PD
142034e026f9SYork Sun 	 * 0=slow exit DLL off (tXPDLL)
142134e026f9SYork Sun 	 * 1=fast exit DLL on (tXP)
142234e026f9SYork Sun 	 */
142334e026f9SYork Sun 
142403e664d8SYork Sun 	wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
142534e026f9SYork Sun 	if (wr_mclk <= 24) {
142634e026f9SYork Sun 		wr = wr_table[wr_mclk - 10];
142734e026f9SYork Sun 	} else {
142834e026f9SYork Sun 		printf("Error: unsupported write recovery for mode register wr_mclk = %d\n",
142934e026f9SYork Sun 		       wr_mclk);
143034e026f9SYork Sun 	}
143134e026f9SYork Sun 
143234e026f9SYork Sun 	dll_rst = 0;	/* dll no reset */
143334e026f9SYork Sun 	mode = 0;	/* normal mode */
143434e026f9SYork Sun 
143534e026f9SYork Sun 	/* look up table to get the cas latency bits */
143634e026f9SYork Sun 	if (cas_latency >= 9 && cas_latency <= 24)
143734e026f9SYork Sun 		caslat = cas_latency_table[cas_latency - 9];
143834e026f9SYork Sun 	else
143934e026f9SYork Sun 		printf("Error: unsupported cas latency for mode register\n");
144034e026f9SYork Sun 
144134e026f9SYork Sun 	bt = 0;	/* Nibble sequential */
144234e026f9SYork Sun 
144334e026f9SYork Sun 	switch (popts->burst_length) {
144434e026f9SYork Sun 	case DDR_BL8:
144534e026f9SYork Sun 		bl = 0;
144634e026f9SYork Sun 		break;
144734e026f9SYork Sun 	case DDR_OTF:
144834e026f9SYork Sun 		bl = 1;
144934e026f9SYork Sun 		break;
145034e026f9SYork Sun 	case DDR_BC4:
145134e026f9SYork Sun 		bl = 2;
145234e026f9SYork Sun 		break;
145334e026f9SYork Sun 	default:
145434e026f9SYork Sun 		printf("Error: invalid burst length of %u specified. ",
145534e026f9SYork Sun 		       popts->burst_length);
145634e026f9SYork Sun 		puts("Defaulting to on-the-fly BC4 or BL8 beats.\n");
145734e026f9SYork Sun 		bl = 1;
145834e026f9SYork Sun 		break;
145934e026f9SYork Sun 	}
146034e026f9SYork Sun 
146134e026f9SYork Sun 	sdmode = (0
146234e026f9SYork Sun 		  | ((wr & 0x7) << 9)
146334e026f9SYork Sun 		  | ((dll_rst & 0x1) << 8)
146434e026f9SYork Sun 		  | ((mode & 0x1) << 7)
146534e026f9SYork Sun 		  | (((caslat >> 1) & 0x7) << 4)
146634e026f9SYork Sun 		  | ((bt & 0x1) << 3)
146734e026f9SYork Sun 		  | ((caslat & 1) << 2)
146834e026f9SYork Sun 		  | ((bl & 0x3) << 0)
146934e026f9SYork Sun 		  );
147034e026f9SYork Sun 
147134e026f9SYork Sun 	ddr->ddr_sdram_mode = (0
147234e026f9SYork Sun 			       | ((esdmode & 0xFFFF) << 16)
147334e026f9SYork Sun 			       | ((sdmode & 0xFFFF) << 0)
147434e026f9SYork Sun 			       );
147534e026f9SYork Sun 
147634e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
147734e026f9SYork Sun 
147834e026f9SYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
147934e026f9SYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
148034e026f9SYork Sun 			if (popts->rtt_override)
148134e026f9SYork Sun 				rtt = popts->rtt_override_value;
148234e026f9SYork Sun 			else
148334e026f9SYork Sun 				rtt = popts->cs_local_opts[i].odt_rtt_norm;
148434e026f9SYork Sun 
148534e026f9SYork Sun 			esdmode &= 0xF8FF;	/* clear bit 10,9,8 for rtt */
148634e026f9SYork Sun 			esdmode |= (rtt & 0x7) << 8;
148734e026f9SYork Sun 			switch (i) {
148834e026f9SYork Sun 			case 1:
148934e026f9SYork Sun 				ddr->ddr_sdram_mode_3 = (0
149034e026f9SYork Sun 				       | ((esdmode & 0xFFFF) << 16)
149134e026f9SYork Sun 				       | ((sdmode & 0xFFFF) << 0)
149234e026f9SYork Sun 				       );
149334e026f9SYork Sun 				break;
149434e026f9SYork Sun 			case 2:
149534e026f9SYork Sun 				ddr->ddr_sdram_mode_5 = (0
149634e026f9SYork Sun 				       | ((esdmode & 0xFFFF) << 16)
149734e026f9SYork Sun 				       | ((sdmode & 0xFFFF) << 0)
149834e026f9SYork Sun 				       );
149934e026f9SYork Sun 				break;
150034e026f9SYork Sun 			case 3:
150134e026f9SYork Sun 				ddr->ddr_sdram_mode_7 = (0
150234e026f9SYork Sun 				       | ((esdmode & 0xFFFF) << 16)
150334e026f9SYork Sun 				       | ((sdmode & 0xFFFF) << 0)
150434e026f9SYork Sun 				       );
150534e026f9SYork Sun 				break;
150634e026f9SYork Sun 			}
150734e026f9SYork Sun 		}
150834e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
150934e026f9SYork Sun 		      ddr->ddr_sdram_mode_3);
151034e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
151134e026f9SYork Sun 		      ddr->ddr_sdram_mode_5);
151234e026f9SYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
151334e026f9SYork Sun 		      ddr->ddr_sdram_mode_5);
151434e026f9SYork Sun 	}
151534e026f9SYork Sun }
151634e026f9SYork Sun 
151734e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
151834e026f9SYork Sun /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
151903e664d8SYork Sun static void set_ddr_sdram_mode(const unsigned int ctrl_num,
152003e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
152134e026f9SYork Sun 			       const memctl_options_t *popts,
152234e026f9SYork Sun 			       const common_timing_params_t *common_dimm,
152334e026f9SYork Sun 			       unsigned int cas_latency,
152434e026f9SYork Sun 			       unsigned int additive_latency,
152534e026f9SYork Sun 			       const unsigned int unq_mrs_en)
152634e026f9SYork Sun {
152734e026f9SYork Sun 	int i;
15285614e71bSYork Sun 	unsigned short esdmode;		/* Extended SDRAM mode */
15295614e71bSYork Sun 	unsigned short sdmode;		/* SDRAM mode */
15305614e71bSYork Sun 
15315614e71bSYork Sun 	/* Mode Register - MR1 */
15325614e71bSYork Sun 	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
15335614e71bSYork Sun 	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
15345614e71bSYork Sun 	unsigned int rtt;
15355614e71bSYork Sun 	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
15365614e71bSYork Sun 	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
15375614e71bSYork Sun 	unsigned int dic = 0;		/* Output driver impedance, 40ohm */
15385614e71bSYork Sun 	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
15395614e71bSYork Sun 						       1=Disable (Test/Debug) */
15405614e71bSYork Sun 
15415614e71bSYork Sun 	/* Mode Register - MR0 */
15425614e71bSYork Sun 	unsigned int dll_on;	/* DLL control for precharge PD, 0=off, 1=on */
15435614e71bSYork Sun 	unsigned int wr = 0;	/* Write Recovery */
15445614e71bSYork Sun 	unsigned int dll_rst;	/* DLL Reset */
15455614e71bSYork Sun 	unsigned int mode;	/* Normal=0 or Test=1 */
15465614e71bSYork Sun 	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
15475614e71bSYork Sun 	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
15485614e71bSYork Sun 	unsigned int bt;
15495614e71bSYork Sun 	unsigned int bl;	/* BL: Burst Length */
15505614e71bSYork Sun 
15515614e71bSYork Sun 	unsigned int wr_mclk;
15525614e71bSYork Sun 	/*
15535614e71bSYork Sun 	 * DDR_SDRAM_MODE doesn't support 9,11,13,15
15545614e71bSYork Sun 	 * Please refer JEDEC Standard No. 79-3E for Mode Register MR0
15555614e71bSYork Sun 	 * for this table
15565614e71bSYork Sun 	 */
15575614e71bSYork Sun 	static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
15585614e71bSYork Sun 
15595614e71bSYork Sun 	if (popts->rtt_override)
15605614e71bSYork Sun 		rtt = popts->rtt_override_value;
15615614e71bSYork Sun 	else
15625614e71bSYork Sun 		rtt = popts->cs_local_opts[0].odt_rtt_norm;
15635614e71bSYork Sun 
15645614e71bSYork Sun 	if (additive_latency == (cas_latency - 1))
15655614e71bSYork Sun 		al = 1;
15665614e71bSYork Sun 	if (additive_latency == (cas_latency - 2))
15675614e71bSYork Sun 		al = 2;
15685614e71bSYork Sun 
15695614e71bSYork Sun 	if (popts->quad_rank_present)
15705614e71bSYork Sun 		dic = 1;	/* output driver impedance 240/7 ohm */
15715614e71bSYork Sun 
15725614e71bSYork Sun 	/*
15735614e71bSYork Sun 	 * The esdmode value will also be used for writing
15745614e71bSYork Sun 	 * MR1 during write leveling for DDR3, although the
15755614e71bSYork Sun 	 * bits specifically related to the write leveling
15765614e71bSYork Sun 	 * scheme will be handled automatically by the DDR
15775614e71bSYork Sun 	 * controller. so we set the wrlvl_en = 0 here.
15785614e71bSYork Sun 	 */
15795614e71bSYork Sun 	esdmode = (0
15805614e71bSYork Sun 		| ((qoff & 0x1) << 12)
15815614e71bSYork Sun 		| ((tdqs_en & 0x1) << 11)
15825614e71bSYork Sun 		| ((rtt & 0x4) << 7)   /* rtt field is split */
15835614e71bSYork Sun 		| ((wrlvl_en & 0x1) << 7)
15845614e71bSYork Sun 		| ((rtt & 0x2) << 5)   /* rtt field is split */
15855614e71bSYork Sun 		| ((dic & 0x2) << 4)   /* DIC field is split */
15865614e71bSYork Sun 		| ((al & 0x3) << 3)
15875614e71bSYork Sun 		| ((rtt & 0x1) << 2)  /* rtt field is split */
15885614e71bSYork Sun 		| ((dic & 0x1) << 1)   /* DIC field is split */
15895614e71bSYork Sun 		| ((dll_en & 0x1) << 0)
15905614e71bSYork Sun 		);
15915614e71bSYork Sun 
15925614e71bSYork Sun 	/*
15935614e71bSYork Sun 	 * DLL control for precharge PD
15945614e71bSYork Sun 	 * 0=slow exit DLL off (tXPDLL)
15955614e71bSYork Sun 	 * 1=fast exit DLL on (tXP)
15965614e71bSYork Sun 	 */
15975614e71bSYork Sun 	dll_on = 1;
15985614e71bSYork Sun 
159903e664d8SYork Sun 	wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
16005614e71bSYork Sun 	if (wr_mclk <= 16) {
16015614e71bSYork Sun 		wr = wr_table[wr_mclk - 5];
16025614e71bSYork Sun 	} else {
16035614e71bSYork Sun 		printf("Error: unsupported write recovery for mode register "
16045614e71bSYork Sun 		       "wr_mclk = %d\n", wr_mclk);
16055614e71bSYork Sun 	}
16065614e71bSYork Sun 
16075614e71bSYork Sun 	dll_rst = 0;	/* dll no reset */
16085614e71bSYork Sun 	mode = 0;	/* normal mode */
16095614e71bSYork Sun 
16105614e71bSYork Sun 	/* look up table to get the cas latency bits */
16115614e71bSYork Sun 	if (cas_latency >= 5 && cas_latency <= 16) {
16125614e71bSYork Sun 		unsigned char cas_latency_table[] = {
16135614e71bSYork Sun 			0x2,	/* 5 clocks */
16145614e71bSYork Sun 			0x4,	/* 6 clocks */
16155614e71bSYork Sun 			0x6,	/* 7 clocks */
16165614e71bSYork Sun 			0x8,	/* 8 clocks */
16175614e71bSYork Sun 			0xa,	/* 9 clocks */
16185614e71bSYork Sun 			0xc,	/* 10 clocks */
16195614e71bSYork Sun 			0xe,	/* 11 clocks */
16205614e71bSYork Sun 			0x1,	/* 12 clocks */
16215614e71bSYork Sun 			0x3,	/* 13 clocks */
16225614e71bSYork Sun 			0x5,	/* 14 clocks */
16235614e71bSYork Sun 			0x7,	/* 15 clocks */
16245614e71bSYork Sun 			0x9,	/* 16 clocks */
16255614e71bSYork Sun 		};
16265614e71bSYork Sun 		caslat = cas_latency_table[cas_latency - 5];
16275614e71bSYork Sun 	} else {
16285614e71bSYork Sun 		printf("Error: unsupported cas latency for mode register\n");
16295614e71bSYork Sun 	}
16305614e71bSYork Sun 
16315614e71bSYork Sun 	bt = 0;	/* Nibble sequential */
16325614e71bSYork Sun 
16335614e71bSYork Sun 	switch (popts->burst_length) {
16345614e71bSYork Sun 	case DDR_BL8:
16355614e71bSYork Sun 		bl = 0;
16365614e71bSYork Sun 		break;
16375614e71bSYork Sun 	case DDR_OTF:
16385614e71bSYork Sun 		bl = 1;
16395614e71bSYork Sun 		break;
16405614e71bSYork Sun 	case DDR_BC4:
16415614e71bSYork Sun 		bl = 2;
16425614e71bSYork Sun 		break;
16435614e71bSYork Sun 	default:
16445614e71bSYork Sun 		printf("Error: invalid burst length of %u specified. "
16455614e71bSYork Sun 			" Defaulting to on-the-fly BC4 or BL8 beats.\n",
16465614e71bSYork Sun 			popts->burst_length);
16475614e71bSYork Sun 		bl = 1;
16485614e71bSYork Sun 		break;
16495614e71bSYork Sun 	}
16505614e71bSYork Sun 
16515614e71bSYork Sun 	sdmode = (0
16525614e71bSYork Sun 		  | ((dll_on & 0x1) << 12)
16535614e71bSYork Sun 		  | ((wr & 0x7) << 9)
16545614e71bSYork Sun 		  | ((dll_rst & 0x1) << 8)
16555614e71bSYork Sun 		  | ((mode & 0x1) << 7)
16565614e71bSYork Sun 		  | (((caslat >> 1) & 0x7) << 4)
16575614e71bSYork Sun 		  | ((bt & 0x1) << 3)
16585614e71bSYork Sun 		  | ((caslat & 1) << 2)
16595614e71bSYork Sun 		  | ((bl & 0x3) << 0)
16605614e71bSYork Sun 		  );
16615614e71bSYork Sun 
16625614e71bSYork Sun 	ddr->ddr_sdram_mode = (0
16635614e71bSYork Sun 			       | ((esdmode & 0xFFFF) << 16)
16645614e71bSYork Sun 			       | ((sdmode & 0xFFFF) << 0)
16655614e71bSYork Sun 			       );
16665614e71bSYork Sun 
16675614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
16685614e71bSYork Sun 
16695614e71bSYork Sun 	if (unq_mrs_en) {	/* unique mode registers are supported */
16705614e71bSYork Sun 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
16715614e71bSYork Sun 			if (popts->rtt_override)
16725614e71bSYork Sun 				rtt = popts->rtt_override_value;
16735614e71bSYork Sun 			else
16745614e71bSYork Sun 				rtt = popts->cs_local_opts[i].odt_rtt_norm;
16755614e71bSYork Sun 
16765614e71bSYork Sun 			esdmode &= 0xFDBB;	/* clear bit 9,6,2 */
16775614e71bSYork Sun 			esdmode |= (0
16785614e71bSYork Sun 				| ((rtt & 0x4) << 7)   /* rtt field is split */
16795614e71bSYork Sun 				| ((rtt & 0x2) << 5)   /* rtt field is split */
16805614e71bSYork Sun 				| ((rtt & 0x1) << 2)  /* rtt field is split */
16815614e71bSYork Sun 				);
16825614e71bSYork Sun 			switch (i) {
16835614e71bSYork Sun 			case 1:
16845614e71bSYork Sun 				ddr->ddr_sdram_mode_3 = (0
16855614e71bSYork Sun 				       | ((esdmode & 0xFFFF) << 16)
16865614e71bSYork Sun 				       | ((sdmode & 0xFFFF) << 0)
16875614e71bSYork Sun 				       );
16885614e71bSYork Sun 				break;
16895614e71bSYork Sun 			case 2:
16905614e71bSYork Sun 				ddr->ddr_sdram_mode_5 = (0
16915614e71bSYork Sun 				       | ((esdmode & 0xFFFF) << 16)
16925614e71bSYork Sun 				       | ((sdmode & 0xFFFF) << 0)
16935614e71bSYork Sun 				       );
16945614e71bSYork Sun 				break;
16955614e71bSYork Sun 			case 3:
16965614e71bSYork Sun 				ddr->ddr_sdram_mode_7 = (0
16975614e71bSYork Sun 				       | ((esdmode & 0xFFFF) << 16)
16985614e71bSYork Sun 				       | ((sdmode & 0xFFFF) << 0)
16995614e71bSYork Sun 				       );
17005614e71bSYork Sun 				break;
17015614e71bSYork Sun 			}
17025614e71bSYork Sun 		}
17035614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
17045614e71bSYork Sun 			ddr->ddr_sdram_mode_3);
17055614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
17065614e71bSYork Sun 			ddr->ddr_sdram_mode_5);
17075614e71bSYork Sun 		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
17085614e71bSYork Sun 			ddr->ddr_sdram_mode_5);
17095614e71bSYork Sun 	}
17105614e71bSYork Sun }
17115614e71bSYork Sun 
17125614e71bSYork Sun #else /* !CONFIG_SYS_FSL_DDR3 */
17135614e71bSYork Sun 
17145614e71bSYork Sun /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
171503e664d8SYork Sun static void set_ddr_sdram_mode(const unsigned int ctrl_num,
171603e664d8SYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
17175614e71bSYork Sun 			       const memctl_options_t *popts,
17185614e71bSYork Sun 			       const common_timing_params_t *common_dimm,
17195614e71bSYork Sun 			       unsigned int cas_latency,
17205614e71bSYork Sun 			       unsigned int additive_latency,
17215614e71bSYork Sun 			       const unsigned int unq_mrs_en)
17225614e71bSYork Sun {
17235614e71bSYork Sun 	unsigned short esdmode;		/* Extended SDRAM mode */
17245614e71bSYork Sun 	unsigned short sdmode;		/* SDRAM mode */
17255614e71bSYork Sun 
17265614e71bSYork Sun 	/*
17275614e71bSYork Sun 	 * FIXME: This ought to be pre-calculated in a
17285614e71bSYork Sun 	 * technology-specific routine,
17295614e71bSYork Sun 	 * e.g. compute_DDR2_mode_register(), and then the
17305614e71bSYork Sun 	 * sdmode and esdmode passed in as part of common_dimm.
17315614e71bSYork Sun 	 */
17325614e71bSYork Sun 
17335614e71bSYork Sun 	/* Extended Mode Register */
17345614e71bSYork Sun 	unsigned int mrs = 0;		/* Mode Register Set */
17355614e71bSYork Sun 	unsigned int outputs = 0;	/* 0=Enabled, 1=Disabled */
17365614e71bSYork Sun 	unsigned int rdqs_en = 0;	/* RDQS Enable: 0=no, 1=yes */
17375614e71bSYork Sun 	unsigned int dqs_en = 0;	/* DQS# Enable: 0=enable, 1=disable */
17385614e71bSYork Sun 	unsigned int ocd = 0;		/* 0x0=OCD not supported,
17395614e71bSYork Sun 					   0x7=OCD default state */
17405614e71bSYork Sun 	unsigned int rtt;
17415614e71bSYork Sun 	unsigned int al;		/* Posted CAS# additive latency (AL) */
17425614e71bSYork Sun 	unsigned int ods = 0;		/* Output Drive Strength:
17435614e71bSYork Sun 						0 = Full strength (18ohm)
17445614e71bSYork Sun 						1 = Reduced strength (4ohm) */
17455614e71bSYork Sun 	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
17465614e71bSYork Sun 						       1=Disable (Test/Debug) */
17475614e71bSYork Sun 
17485614e71bSYork Sun 	/* Mode Register (MR) */
17495614e71bSYork Sun 	unsigned int mr;	/* Mode Register Definition */
17505614e71bSYork Sun 	unsigned int pd;	/* Power-Down Mode */
17515614e71bSYork Sun 	unsigned int wr;	/* Write Recovery */
17525614e71bSYork Sun 	unsigned int dll_res;	/* DLL Reset */
17535614e71bSYork Sun 	unsigned int mode;	/* Normal=0 or Test=1 */
17545614e71bSYork Sun 	unsigned int caslat = 0;/* CAS# latency */
17555614e71bSYork Sun 	/* BT: Burst Type (0=Sequential, 1=Interleaved) */
17565614e71bSYork Sun 	unsigned int bt;
17575614e71bSYork Sun 	unsigned int bl;	/* BL: Burst Length */
17585614e71bSYork Sun 
17595614e71bSYork Sun 	dqs_en = !popts->dqs_config;
17605614e71bSYork Sun 	rtt = fsl_ddr_get_rtt();
17615614e71bSYork Sun 
17625614e71bSYork Sun 	al = additive_latency;
17635614e71bSYork Sun 
17645614e71bSYork Sun 	esdmode = (0
17655614e71bSYork Sun 		| ((mrs & 0x3) << 14)
17665614e71bSYork Sun 		| ((outputs & 0x1) << 12)
17675614e71bSYork Sun 		| ((rdqs_en & 0x1) << 11)
17685614e71bSYork Sun 		| ((dqs_en & 0x1) << 10)
17695614e71bSYork Sun 		| ((ocd & 0x7) << 7)
17705614e71bSYork Sun 		| ((rtt & 0x2) << 5)   /* rtt field is split */
17715614e71bSYork Sun 		| ((al & 0x7) << 3)
17725614e71bSYork Sun 		| ((rtt & 0x1) << 2)   /* rtt field is split */
17735614e71bSYork Sun 		| ((ods & 0x1) << 1)
17745614e71bSYork Sun 		| ((dll_en & 0x1) << 0)
17755614e71bSYork Sun 		);
17765614e71bSYork Sun 
17775614e71bSYork Sun 	mr = 0;		 /* FIXME: CHECKME */
17785614e71bSYork Sun 
17795614e71bSYork Sun 	/*
17805614e71bSYork Sun 	 * 0 = Fast Exit (Normal)
17815614e71bSYork Sun 	 * 1 = Slow Exit (Low Power)
17825614e71bSYork Sun 	 */
17835614e71bSYork Sun 	pd = 0;
17845614e71bSYork Sun 
17855614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
17865614e71bSYork Sun 	wr = 0;       /* Historical */
17875614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
178803e664d8SYork Sun 	wr = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
17895614e71bSYork Sun #endif
17905614e71bSYork Sun 	dll_res = 0;
17915614e71bSYork Sun 	mode = 0;
17925614e71bSYork Sun 
17935614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
17945614e71bSYork Sun 	if (1 <= cas_latency && cas_latency <= 4) {
17955614e71bSYork Sun 		unsigned char mode_caslat_table[4] = {
17965614e71bSYork Sun 			0x5,	/* 1.5 clocks */
17975614e71bSYork Sun 			0x2,	/* 2.0 clocks */
17985614e71bSYork Sun 			0x6,	/* 2.5 clocks */
17995614e71bSYork Sun 			0x3	/* 3.0 clocks */
18005614e71bSYork Sun 		};
18015614e71bSYork Sun 		caslat = mode_caslat_table[cas_latency - 1];
18025614e71bSYork Sun 	} else {
18035614e71bSYork Sun 		printf("Warning: unknown cas_latency %d\n", cas_latency);
18045614e71bSYork Sun 	}
18055614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
18065614e71bSYork Sun 	caslat = cas_latency;
18075614e71bSYork Sun #endif
18085614e71bSYork Sun 	bt = 0;
18095614e71bSYork Sun 
18105614e71bSYork Sun 	switch (popts->burst_length) {
18115614e71bSYork Sun 	case DDR_BL4:
18125614e71bSYork Sun 		bl = 2;
18135614e71bSYork Sun 		break;
18145614e71bSYork Sun 	case DDR_BL8:
18155614e71bSYork Sun 		bl = 3;
18165614e71bSYork Sun 		break;
18175614e71bSYork Sun 	default:
18185614e71bSYork Sun 		printf("Error: invalid burst length of %u specified. "
18195614e71bSYork Sun 			" Defaulting to 4 beats.\n",
18205614e71bSYork Sun 			popts->burst_length);
18215614e71bSYork Sun 		bl = 2;
18225614e71bSYork Sun 		break;
18235614e71bSYork Sun 	}
18245614e71bSYork Sun 
18255614e71bSYork Sun 	sdmode = (0
18265614e71bSYork Sun 		  | ((mr & 0x3) << 14)
18275614e71bSYork Sun 		  | ((pd & 0x1) << 12)
18285614e71bSYork Sun 		  | ((wr & 0x7) << 9)
18295614e71bSYork Sun 		  | ((dll_res & 0x1) << 8)
18305614e71bSYork Sun 		  | ((mode & 0x1) << 7)
18315614e71bSYork Sun 		  | ((caslat & 0x7) << 4)
18325614e71bSYork Sun 		  | ((bt & 0x1) << 3)
18335614e71bSYork Sun 		  | ((bl & 0x7) << 0)
18345614e71bSYork Sun 		  );
18355614e71bSYork Sun 
18365614e71bSYork Sun 	ddr->ddr_sdram_mode = (0
18375614e71bSYork Sun 			       | ((esdmode & 0xFFFF) << 16)
18385614e71bSYork Sun 			       | ((sdmode & 0xFFFF) << 0)
18395614e71bSYork Sun 			       );
18405614e71bSYork Sun 	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
18415614e71bSYork Sun }
18425614e71bSYork Sun #endif
18435614e71bSYork Sun 
18445614e71bSYork Sun /* DDR SDRAM Data Initialization (DDR_DATA_INIT) */
18455614e71bSYork Sun static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr)
18465614e71bSYork Sun {
18475614e71bSYork Sun 	unsigned int init_value;	/* Initialization value */
18485614e71bSYork Sun 
18495614e71bSYork Sun #ifdef CONFIG_MEM_INIT_VALUE
18505614e71bSYork Sun 	init_value = CONFIG_MEM_INIT_VALUE;
18515614e71bSYork Sun #else
18525614e71bSYork Sun 	init_value = 0xDEADBEEF;
18535614e71bSYork Sun #endif
18545614e71bSYork Sun 	ddr->ddr_data_init = init_value;
18555614e71bSYork Sun }
18565614e71bSYork Sun 
18575614e71bSYork Sun /*
18585614e71bSYork Sun  * DDR SDRAM Clock Control (DDR_SDRAM_CLK_CNTL)
18595614e71bSYork Sun  * The old controller on the 8540/60 doesn't have this register.
18605614e71bSYork Sun  * Hope it's OK to set it (to 0) anyway.
18615614e71bSYork Sun  */
18625614e71bSYork Sun static void set_ddr_sdram_clk_cntl(fsl_ddr_cfg_regs_t *ddr,
18635614e71bSYork Sun 					 const memctl_options_t *popts)
18645614e71bSYork Sun {
18655614e71bSYork Sun 	unsigned int clk_adjust;	/* Clock adjust */
1866d7c865bdSCurt Brune 	unsigned int ss_en = 0;		/* Source synchronous enable */
18675614e71bSYork Sun 
18683c3d8ab5SYork Sun #if defined(CONFIG_ARCH_MPC8541) || defined(CONFIG_ARCH_MPC8555)
1869d7c865bdSCurt Brune 	/* Per FSL Application Note: AN2805 */
1870d7c865bdSCurt Brune 	ss_en = 1;
1871d7c865bdSCurt Brune #endif
1872d8e5163aSShengzhou Liu 	if (fsl_ddr_get_version(0) >= 0x40701) {
1873d8e5163aSShengzhou Liu 		/* clk_adjust in 5-bits on T-series and LS-series */
1874d8e5163aSShengzhou Liu 		clk_adjust = (popts->clk_adjust & 0x1F) << 22;
1875d8e5163aSShengzhou Liu 	} else {
1876d8e5163aSShengzhou Liu 		/* clk_adjust in 4-bits on earlier MPC85xx and P-series */
1877d8e5163aSShengzhou Liu 		clk_adjust = (popts->clk_adjust & 0xF) << 23;
1878d8e5163aSShengzhou Liu 	}
1879d8e5163aSShengzhou Liu 
1880d7c865bdSCurt Brune 	ddr->ddr_sdram_clk_cntl = (0
1881d7c865bdSCurt Brune 				   | ((ss_en & 0x1) << 31)
1882d8e5163aSShengzhou Liu 				   | clk_adjust
1883d7c865bdSCurt Brune 				   );
18845614e71bSYork Sun 	debug("FSLDDR: clk_cntl = 0x%08x\n", ddr->ddr_sdram_clk_cntl);
18855614e71bSYork Sun }
18865614e71bSYork Sun 
18875614e71bSYork Sun /* DDR Initialization Address (DDR_INIT_ADDR) */
18885614e71bSYork Sun static void set_ddr_init_addr(fsl_ddr_cfg_regs_t *ddr)
18895614e71bSYork Sun {
18905614e71bSYork Sun 	unsigned int init_addr = 0;	/* Initialization address */
18915614e71bSYork Sun 
18925614e71bSYork Sun 	ddr->ddr_init_addr = init_addr;
18935614e71bSYork Sun }
18945614e71bSYork Sun 
18955614e71bSYork Sun /* DDR Initialization Address (DDR_INIT_EXT_ADDR) */
18965614e71bSYork Sun static void set_ddr_init_ext_addr(fsl_ddr_cfg_regs_t *ddr)
18975614e71bSYork Sun {
18985614e71bSYork Sun 	unsigned int uia = 0;	/* Use initialization address */
18995614e71bSYork Sun 	unsigned int init_ext_addr = 0;	/* Initialization address */
19005614e71bSYork Sun 
19015614e71bSYork Sun 	ddr->ddr_init_ext_addr = (0
19025614e71bSYork Sun 				  | ((uia & 0x1) << 31)
19035614e71bSYork Sun 				  | (init_ext_addr & 0xF)
19045614e71bSYork Sun 				  );
19055614e71bSYork Sun }
19065614e71bSYork Sun 
19075614e71bSYork Sun /* DDR SDRAM Timing Configuration 4 (TIMING_CFG_4) */
19085614e71bSYork Sun static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr,
19095614e71bSYork Sun 				const memctl_options_t *popts)
19105614e71bSYork Sun {
19115614e71bSYork Sun 	unsigned int rwt = 0; /* Read-to-write turnaround for same CS */
19125614e71bSYork Sun 	unsigned int wrt = 0; /* Write-to-read turnaround for same CS */
19135614e71bSYork Sun 	unsigned int rrt = 0; /* Read-to-read turnaround for same CS */
19145614e71bSYork Sun 	unsigned int wwt = 0; /* Write-to-write turnaround for same CS */
19156c6e006aSYork Sun 	unsigned int trwt_mclk = 0;	/* ext_rwt */
19165614e71bSYork Sun 	unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */
19175614e71bSYork Sun 
191834e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
19195614e71bSYork Sun 	if (popts->burst_length == DDR_BL8) {
19205614e71bSYork Sun 		/* We set BL/2 for fixed BL8 */
19215614e71bSYork Sun 		rrt = 0;	/* BL/2 clocks */
19225614e71bSYork Sun 		wwt = 0;	/* BL/2 clocks */
19235614e71bSYork Sun 	} else {
19245614e71bSYork Sun 		/* We need to set BL/2 + 2 to BC4 and OTF */
19255614e71bSYork Sun 		rrt = 2;	/* BL/2 + 2 clocks */
19265614e71bSYork Sun 		wwt = 2;	/* BL/2 + 2 clocks */
19275614e71bSYork Sun 	}
192834e026f9SYork Sun #endif
192934e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
193034e026f9SYork Sun 	dll_lock = 2;	/* tDLLK = 1024 clocks */
193134e026f9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
19325614e71bSYork Sun 	dll_lock = 1;	/* tDLLK = 512 clocks from spec */
19335614e71bSYork Sun #endif
19346c6e006aSYork Sun 
19356c6e006aSYork Sun 	if (popts->trwt_override)
19366c6e006aSYork Sun 		trwt_mclk = popts->trwt;
19376c6e006aSYork Sun 
19385614e71bSYork Sun 	ddr->timing_cfg_4 = (0
19395614e71bSYork Sun 			     | ((rwt & 0xf) << 28)
19405614e71bSYork Sun 			     | ((wrt & 0xf) << 24)
19415614e71bSYork Sun 			     | ((rrt & 0xf) << 20)
19425614e71bSYork Sun 			     | ((wwt & 0xf) << 16)
19436c6e006aSYork Sun 			     | ((trwt_mclk & 0xc) << 12)
19445614e71bSYork Sun 			     | (dll_lock & 0x3)
19455614e71bSYork Sun 			     );
19465614e71bSYork Sun 	debug("FSLDDR: timing_cfg_4 = 0x%08x\n", ddr->timing_cfg_4);
19475614e71bSYork Sun }
19485614e71bSYork Sun 
19495614e71bSYork Sun /* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */
19505614e71bSYork Sun static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency)
19515614e71bSYork Sun {
19525614e71bSYork Sun 	unsigned int rodt_on = 0;	/* Read to ODT on */
19535614e71bSYork Sun 	unsigned int rodt_off = 0;	/* Read to ODT off */
19545614e71bSYork Sun 	unsigned int wodt_on = 0;	/* Write to ODT on */
19555614e71bSYork Sun 	unsigned int wodt_off = 0;	/* Write to ODT off */
19565614e71bSYork Sun 
195734e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
195834e026f9SYork Sun 	unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
195934e026f9SYork Sun 			      ((ddr->timing_cfg_2 & 0x00040000) >> 14);
19605614e71bSYork Sun 	/* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
196134e026f9SYork Sun 	if (cas_latency >= wr_lat)
196234e026f9SYork Sun 		rodt_on = cas_latency - wr_lat + 1;
19635614e71bSYork Sun 	rodt_off = 4;	/*  4 clocks */
19645614e71bSYork Sun 	wodt_on = 1;	/*  1 clocks */
19655614e71bSYork Sun 	wodt_off = 4;	/*  4 clocks */
19665614e71bSYork Sun #endif
19675614e71bSYork Sun 
19685614e71bSYork Sun 	ddr->timing_cfg_5 = (0
19695614e71bSYork Sun 			     | ((rodt_on & 0x1f) << 24)
19705614e71bSYork Sun 			     | ((rodt_off & 0x7) << 20)
19715614e71bSYork Sun 			     | ((wodt_on & 0x1f) << 12)
19725614e71bSYork Sun 			     | ((wodt_off & 0x7) << 8)
19735614e71bSYork Sun 			     );
19745614e71bSYork Sun 	debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5);
19755614e71bSYork Sun }
19765614e71bSYork Sun 
197734e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
197834e026f9SYork Sun static void set_timing_cfg_6(fsl_ddr_cfg_regs_t *ddr)
197934e026f9SYork Sun {
198034e026f9SYork Sun 	unsigned int hs_caslat = 0;
198134e026f9SYork Sun 	unsigned int hs_wrlat = 0;
198234e026f9SYork Sun 	unsigned int hs_wrrec = 0;
198334e026f9SYork Sun 	unsigned int hs_clkadj = 0;
198434e026f9SYork Sun 	unsigned int hs_wrlvl_start = 0;
198534e026f9SYork Sun 
198634e026f9SYork Sun 	ddr->timing_cfg_6 = (0
198734e026f9SYork Sun 			     | ((hs_caslat & 0x1f) << 24)
198834e026f9SYork Sun 			     | ((hs_wrlat & 0x1f) << 19)
198934e026f9SYork Sun 			     | ((hs_wrrec & 0x1f) << 12)
199034e026f9SYork Sun 			     | ((hs_clkadj & 0x1f) << 6)
199134e026f9SYork Sun 			     | ((hs_wrlvl_start & 0x1f) << 0)
199234e026f9SYork Sun 			    );
199334e026f9SYork Sun 	debug("FSLDDR: timing_cfg_6 = 0x%08x\n", ddr->timing_cfg_6);
199434e026f9SYork Sun }
199534e026f9SYork Sun 
199603e664d8SYork Sun static void set_timing_cfg_7(const unsigned int ctrl_num,
199703e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
1998426230a6SYork Sun 			     const memctl_options_t *popts,
199934e026f9SYork Sun 			     const common_timing_params_t *common_dimm)
200034e026f9SYork Sun {
200134e026f9SYork Sun 	unsigned int txpr, tcksre, tcksrx;
2002eb118807SShengzhou Liu 	unsigned int cke_rst, cksre, cksrx, par_lat = 0, cs_to_cmd;
2003eb118807SShengzhou Liu 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
200434e026f9SYork Sun 
200503e664d8SYork Sun 	txpr = max(5U, picos_to_mclk(ctrl_num, common_dimm->trfc1_ps + 10000));
200603e664d8SYork Sun 	tcksre = max(5U, picos_to_mclk(ctrl_num, 10000));
200703e664d8SYork Sun 	tcksrx = max(5U, picos_to_mclk(ctrl_num, 10000));
2008eb118807SShengzhou Liu 
2009426230a6SYork Sun 	if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN &&
2010426230a6SYork Sun 	    CONFIG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4) {
2011426230a6SYork Sun 		/* for DDR4 only */
2012c0c32af0SYork Sun 		par_lat = (ddr->ddr_sdram_rcw_2 & 0xf) + 1;
2013426230a6SYork Sun 		debug("PAR_LAT = %u for mclk_ps = %d\n", par_lat, mclk_ps);
2014eb118807SShengzhou Liu 	}
2015eb118807SShengzhou Liu 
201634e026f9SYork Sun 	cs_to_cmd = 0;
201734e026f9SYork Sun 
201834e026f9SYork Sun 	if (txpr <= 200)
201934e026f9SYork Sun 		cke_rst = 0;
202034e026f9SYork Sun 	else if (txpr <= 256)
202134e026f9SYork Sun 		cke_rst = 1;
202234e026f9SYork Sun 	else if (txpr <= 512)
202334e026f9SYork Sun 		cke_rst = 2;
202434e026f9SYork Sun 	else
202534e026f9SYork Sun 		cke_rst = 3;
202634e026f9SYork Sun 
202734e026f9SYork Sun 	if (tcksre <= 19)
202834e026f9SYork Sun 		cksre = tcksre - 5;
202934e026f9SYork Sun 	else
203034e026f9SYork Sun 		cksre = 15;
203134e026f9SYork Sun 
203234e026f9SYork Sun 	if (tcksrx <= 19)
203334e026f9SYork Sun 		cksrx = tcksrx - 5;
203434e026f9SYork Sun 	else
203534e026f9SYork Sun 		cksrx = 15;
203634e026f9SYork Sun 
203734e026f9SYork Sun 	ddr->timing_cfg_7 = (0
203834e026f9SYork Sun 			     | ((cke_rst & 0x3) << 28)
203934e026f9SYork Sun 			     | ((cksre & 0xf) << 24)
204034e026f9SYork Sun 			     | ((cksrx & 0xf) << 20)
204134e026f9SYork Sun 			     | ((par_lat & 0xf) << 16)
204234e026f9SYork Sun 			     | ((cs_to_cmd & 0xf) << 4)
204334e026f9SYork Sun 			    );
204434e026f9SYork Sun 	debug("FSLDDR: timing_cfg_7 = 0x%08x\n", ddr->timing_cfg_7);
204534e026f9SYork Sun }
204634e026f9SYork Sun 
204703e664d8SYork Sun static void set_timing_cfg_8(const unsigned int ctrl_num,
204803e664d8SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
204934e026f9SYork Sun 			     const memctl_options_t *popts,
205034e026f9SYork Sun 			     const common_timing_params_t *common_dimm,
205134e026f9SYork Sun 			     unsigned int cas_latency)
205234e026f9SYork Sun {
2053426230a6SYork Sun 	int rwt_bg, wrt_bg, rrt_bg, wwt_bg;
205434e026f9SYork Sun 	unsigned int acttoact_bg, wrtord_bg, pre_all_rec;
2055426230a6SYork Sun 	int tccdl = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps);
2056426230a6SYork Sun 	int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
205734e026f9SYork Sun 		      ((ddr->timing_cfg_2 & 0x00040000) >> 14);
205834e026f9SYork Sun 
205934e026f9SYork Sun 	rwt_bg = cas_latency + 2 + 4 - wr_lat;
206034e026f9SYork Sun 	if (rwt_bg < tccdl)
206134e026f9SYork Sun 		rwt_bg = tccdl - rwt_bg;
206234e026f9SYork Sun 	else
206334e026f9SYork Sun 		rwt_bg = 0;
206434e026f9SYork Sun 
206534e026f9SYork Sun 	wrt_bg = wr_lat + 4 + 1 - cas_latency;
206634e026f9SYork Sun 	if (wrt_bg < tccdl)
206734e026f9SYork Sun 		wrt_bg = tccdl - wrt_bg;
206834e026f9SYork Sun 	else
206934e026f9SYork Sun 		wrt_bg = 0;
207034e026f9SYork Sun 
207134e026f9SYork Sun 	if (popts->burst_length == DDR_BL8) {
207234e026f9SYork Sun 		rrt_bg = tccdl - 4;
207334e026f9SYork Sun 		wwt_bg = tccdl - 4;
207434e026f9SYork Sun 	} else {
207534e026f9SYork Sun 		rrt_bg = tccdl - 2;
2076dc1437afSYork Sun 		wwt_bg = tccdl - 2;
207734e026f9SYork Sun 	}
207834e026f9SYork Sun 
207903e664d8SYork Sun 	acttoact_bg = picos_to_mclk(ctrl_num, common_dimm->trrdl_ps);
208003e664d8SYork Sun 	wrtord_bg = max(4U, picos_to_mclk(ctrl_num, 7500));
20813d75ec95SYork Sun 	if (popts->otf_burst_chop_en)
20823d75ec95SYork Sun 		wrtord_bg += 2;
20833d75ec95SYork Sun 
208434e026f9SYork Sun 	pre_all_rec = 0;
208534e026f9SYork Sun 
208634e026f9SYork Sun 	ddr->timing_cfg_8 = (0
208734e026f9SYork Sun 			     | ((rwt_bg & 0xf) << 28)
208834e026f9SYork Sun 			     | ((wrt_bg & 0xf) << 24)
208934e026f9SYork Sun 			     | ((rrt_bg & 0xf) << 20)
209034e026f9SYork Sun 			     | ((wwt_bg & 0xf) << 16)
209134e026f9SYork Sun 			     | ((acttoact_bg & 0xf) << 12)
209234e026f9SYork Sun 			     | ((wrtord_bg & 0xf) << 8)
209334e026f9SYork Sun 			     | ((pre_all_rec & 0x1f) << 0)
209434e026f9SYork Sun 			    );
209534e026f9SYork Sun 
209634e026f9SYork Sun 	debug("FSLDDR: timing_cfg_8 = 0x%08x\n", ddr->timing_cfg_8);
209734e026f9SYork Sun }
209834e026f9SYork Sun 
2099c0c32af0SYork Sun static void set_timing_cfg_9(const unsigned int ctrl_num,
2100c0c32af0SYork Sun 			     fsl_ddr_cfg_regs_t *ddr,
2101c0c32af0SYork Sun 			     const memctl_options_t *popts,
2102c0c32af0SYork Sun 			     const common_timing_params_t *common_dimm)
210334e026f9SYork Sun {
2104c0c32af0SYork Sun 	unsigned int refrec_cid_mclk = 0;
2105c0c32af0SYork Sun 	unsigned int acttoact_cid_mclk = 0;
2106c0c32af0SYork Sun 
2107c0c32af0SYork Sun 	if (popts->package_3ds) {
2108c0c32af0SYork Sun 		refrec_cid_mclk =
2109c0c32af0SYork Sun 			picos_to_mclk(ctrl_num, common_dimm->trfc_slr_ps);
2110c0c32af0SYork Sun 		acttoact_cid_mclk = 4U;	/* tRRDS_slr */
2111c0c32af0SYork Sun 	}
2112c0c32af0SYork Sun 
2113c0c32af0SYork Sun 	ddr->timing_cfg_9 = (refrec_cid_mclk & 0x3ff) << 16	|
2114c0c32af0SYork Sun 			    (acttoact_cid_mclk & 0xf) << 8;
2115c0c32af0SYork Sun 
211634e026f9SYork Sun 	debug("FSLDDR: timing_cfg_9 = 0x%08x\n", ddr->timing_cfg_9);
211734e026f9SYork Sun }
211834e026f9SYork Sun 
2119f80d6472SYork Sun /* This function needs to be called after set_ddr_sdram_cfg() is called */
212034e026f9SYork Sun static void set_ddr_dq_mapping(fsl_ddr_cfg_regs_t *ddr,
212134e026f9SYork Sun 			       const dimm_params_t *dimm_params)
212234e026f9SYork Sun {
2123f80d6472SYork Sun 	unsigned int acc_ecc_en = (ddr->ddr_sdram_cfg >> 2) & 0x1;
21246b95be22SYork Sun 	int i;
2125f80d6472SYork Sun 
21266b95be22SYork Sun 	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
21276b95be22SYork Sun 		if (dimm_params[i].n_ranks)
21286b95be22SYork Sun 			break;
21296b95be22SYork Sun 	}
21306b95be22SYork Sun 	if (i >= CONFIG_DIMM_SLOTS_PER_CTLR) {
21316b95be22SYork Sun 		puts("DDR error: no DIMM found!\n");
21326b95be22SYork Sun 		return;
21336b95be22SYork Sun 	}
213434e026f9SYork Sun 
21356b95be22SYork Sun 	ddr->dq_map_0 = ((dimm_params[i].dq_mapping[0] & 0x3F) << 26) |
21366b95be22SYork Sun 			((dimm_params[i].dq_mapping[1] & 0x3F) << 20) |
21376b95be22SYork Sun 			((dimm_params[i].dq_mapping[2] & 0x3F) << 14) |
21386b95be22SYork Sun 			((dimm_params[i].dq_mapping[3] & 0x3F) << 8) |
21396b95be22SYork Sun 			((dimm_params[i].dq_mapping[4] & 0x3F) << 2);
214034e026f9SYork Sun 
21416b95be22SYork Sun 	ddr->dq_map_1 = ((dimm_params[i].dq_mapping[5] & 0x3F) << 26) |
21426b95be22SYork Sun 			((dimm_params[i].dq_mapping[6] & 0x3F) << 20) |
21436b95be22SYork Sun 			((dimm_params[i].dq_mapping[7] & 0x3F) << 14) |
21446b95be22SYork Sun 			((dimm_params[i].dq_mapping[10] & 0x3F) << 8) |
21456b95be22SYork Sun 			((dimm_params[i].dq_mapping[11] & 0x3F) << 2);
21466b95be22SYork Sun 
21476b95be22SYork Sun 	ddr->dq_map_2 = ((dimm_params[i].dq_mapping[12] & 0x3F) << 26) |
21486b95be22SYork Sun 			((dimm_params[i].dq_mapping[13] & 0x3F) << 20) |
21496b95be22SYork Sun 			((dimm_params[i].dq_mapping[14] & 0x3F) << 14) |
21506b95be22SYork Sun 			((dimm_params[i].dq_mapping[15] & 0x3F) << 8) |
21516b95be22SYork Sun 			((dimm_params[i].dq_mapping[16] & 0x3F) << 2);
215234e026f9SYork Sun 
2153f80d6472SYork Sun 	/* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */
21546b95be22SYork Sun 	ddr->dq_map_3 = ((dimm_params[i].dq_mapping[17] & 0x3F) << 26) |
21556b95be22SYork Sun 			((dimm_params[i].dq_mapping[8] & 0x3F) << 20) |
2156f80d6472SYork Sun 			(acc_ecc_en ? 0 :
21576b95be22SYork Sun 			 (dimm_params[i].dq_mapping[9] & 0x3F) << 14) |
21586b95be22SYork Sun 			dimm_params[i].dq_mapping_ors;
215934e026f9SYork Sun 
216034e026f9SYork Sun 	debug("FSLDDR: dq_map_0 = 0x%08x\n", ddr->dq_map_0);
216134e026f9SYork Sun 	debug("FSLDDR: dq_map_1 = 0x%08x\n", ddr->dq_map_1);
216234e026f9SYork Sun 	debug("FSLDDR: dq_map_2 = 0x%08x\n", ddr->dq_map_2);
216334e026f9SYork Sun 	debug("FSLDDR: dq_map_3 = 0x%08x\n", ddr->dq_map_3);
216434e026f9SYork Sun }
216534e026f9SYork Sun static void set_ddr_sdram_cfg_3(fsl_ddr_cfg_regs_t *ddr,
216634e026f9SYork Sun 			       const memctl_options_t *popts)
216734e026f9SYork Sun {
216834e026f9SYork Sun 	int rd_pre;
216934e026f9SYork Sun 
217034e026f9SYork Sun 	rd_pre = popts->quad_rank_present ? 1 : 0;
217134e026f9SYork Sun 
217234e026f9SYork Sun 	ddr->ddr_sdram_cfg_3 = (rd_pre & 0x1) << 16;
2173426230a6SYork Sun 	/* Disable MRS on parity error for RDIMMs */
2174426230a6SYork Sun 	ddr->ddr_sdram_cfg_3 |= popts->registered_dimm_en ? 1 : 0;
217534e026f9SYork Sun 
2176c0c32af0SYork Sun 	if (popts->package_3ds) {	/* only 2,4,8 are supported */
2177c0c32af0SYork Sun 		if ((popts->package_3ds + 1) & 0x1) {
2178c0c32af0SYork Sun 			printf("Error: Unsupported 3DS DIMM with %d die\n",
2179c0c32af0SYork Sun 			       popts->package_3ds + 1);
2180c0c32af0SYork Sun 		} else {
2181c0c32af0SYork Sun 			ddr->ddr_sdram_cfg_3 |= ((popts->package_3ds + 1) >> 1)
2182c0c32af0SYork Sun 						<< 4;
2183c0c32af0SYork Sun 		}
2184c0c32af0SYork Sun 	}
2185c0c32af0SYork Sun 
218634e026f9SYork Sun 	debug("FSLDDR: ddr_sdram_cfg_3 = 0x%08x\n", ddr->ddr_sdram_cfg_3);
218734e026f9SYork Sun }
218834e026f9SYork Sun #endif	/* CONFIG_SYS_FSL_DDR4 */
218934e026f9SYork Sun 
21905614e71bSYork Sun /* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */
21915614e71bSYork Sun static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
21925614e71bSYork Sun {
21935614e71bSYork Sun 	unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */
21945614e71bSYork Sun 	/* Normal Operation Full Calibration Time (tZQoper) */
21955614e71bSYork Sun 	unsigned int zqoper = 0;
21965614e71bSYork Sun 	/* Normal Operation Short Calibration Time (tZQCS) */
21975614e71bSYork Sun 	unsigned int zqcs = 0;
219834e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
219934e026f9SYork Sun 	unsigned int zqcs_init;
220034e026f9SYork Sun #endif
22015614e71bSYork Sun 
22025614e71bSYork Sun 	if (zq_en) {
220334e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
220434e026f9SYork Sun 		zqinit = 10;	/* 1024 clocks */
220534e026f9SYork Sun 		zqoper = 9;	/* 512 clocks */
220634e026f9SYork Sun 		zqcs = 7;	/* 128 clocks */
220734e026f9SYork Sun 		zqcs_init = 5;	/* 1024 refresh sequences */
220834e026f9SYork Sun #else
22095614e71bSYork Sun 		zqinit = 9;	/* 512 clocks */
22105614e71bSYork Sun 		zqoper = 8;	/* 256 clocks */
22115614e71bSYork Sun 		zqcs = 6;	/* 64 clocks */
221234e026f9SYork Sun #endif
22135614e71bSYork Sun 	}
22145614e71bSYork Sun 
22155614e71bSYork Sun 	ddr->ddr_zq_cntl = (0
22165614e71bSYork Sun 			    | ((zq_en & 0x1) << 31)
22175614e71bSYork Sun 			    | ((zqinit & 0xF) << 24)
22185614e71bSYork Sun 			    | ((zqoper & 0xF) << 16)
22195614e71bSYork Sun 			    | ((zqcs & 0xF) << 8)
222034e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
222134e026f9SYork Sun 			    | ((zqcs_init & 0xF) << 0)
222234e026f9SYork Sun #endif
22235614e71bSYork Sun 			    );
22245614e71bSYork Sun 	debug("FSLDDR: zq_cntl = 0x%08x\n", ddr->ddr_zq_cntl);
22255614e71bSYork Sun }
22265614e71bSYork Sun 
22275614e71bSYork Sun /* DDR Write Leveling Control (DDR_WRLVL_CNTL) */
22285614e71bSYork Sun static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en,
22295614e71bSYork Sun 				const memctl_options_t *popts)
22305614e71bSYork Sun {
22315614e71bSYork Sun 	/*
22325614e71bSYork Sun 	 * First DQS pulse rising edge after margining mode
22335614e71bSYork Sun 	 * is programmed (tWL_MRD)
22345614e71bSYork Sun 	 */
22355614e71bSYork Sun 	unsigned int wrlvl_mrd = 0;
22365614e71bSYork Sun 	/* ODT delay after margining mode is programmed (tWL_ODTEN) */
22375614e71bSYork Sun 	unsigned int wrlvl_odten = 0;
22385614e71bSYork Sun 	/* DQS/DQS_ delay after margining mode is programmed (tWL_DQSEN) */
22395614e71bSYork Sun 	unsigned int wrlvl_dqsen = 0;
22405614e71bSYork Sun 	/* WRLVL_SMPL: Write leveling sample time */
22415614e71bSYork Sun 	unsigned int wrlvl_smpl = 0;
22425614e71bSYork Sun 	/* WRLVL_WLR: Write leveling repeition time */
22435614e71bSYork Sun 	unsigned int wrlvl_wlr = 0;
22445614e71bSYork Sun 	/* WRLVL_START: Write leveling start time */
22455614e71bSYork Sun 	unsigned int wrlvl_start = 0;
22465614e71bSYork Sun 
22475614e71bSYork Sun 	/* suggest enable write leveling for DDR3 due to fly-by topology */
22485614e71bSYork Sun 	if (wrlvl_en) {
22495614e71bSYork Sun 		/* tWL_MRD min = 40 nCK, we set it 64 */
22505614e71bSYork Sun 		wrlvl_mrd = 0x6;
22515614e71bSYork Sun 		/* tWL_ODTEN 128 */
22525614e71bSYork Sun 		wrlvl_odten = 0x7;
22535614e71bSYork Sun 		/* tWL_DQSEN min = 25 nCK, we set it 32 */
22545614e71bSYork Sun 		wrlvl_dqsen = 0x5;
22555614e71bSYork Sun 		/*
22565614e71bSYork Sun 		 * Write leveling sample time at least need 6 clocks
22575614e71bSYork Sun 		 * higher than tWLO to allow enough time for progagation
22585614e71bSYork Sun 		 * delay and sampling the prime data bits.
22595614e71bSYork Sun 		 */
22605614e71bSYork Sun 		wrlvl_smpl = 0xf;
22615614e71bSYork Sun 		/*
22625614e71bSYork Sun 		 * Write leveling repetition time
22635614e71bSYork Sun 		 * at least tWLO + 6 clocks clocks
22645614e71bSYork Sun 		 * we set it 64
22655614e71bSYork Sun 		 */
22665614e71bSYork Sun 		wrlvl_wlr = 0x6;
22675614e71bSYork Sun 		/*
22685614e71bSYork Sun 		 * Write leveling start time
22695614e71bSYork Sun 		 * The value use for the DQS_ADJUST for the first sample
22705614e71bSYork Sun 		 * when write leveling is enabled. It probably needs to be
227162a3b7ddSRobert P. J. Day 		 * overridden per platform.
22725614e71bSYork Sun 		 */
22735614e71bSYork Sun 		wrlvl_start = 0x8;
22745614e71bSYork Sun 		/*
22755614e71bSYork Sun 		 * Override the write leveling sample and start time
22765614e71bSYork Sun 		 * according to specific board
22775614e71bSYork Sun 		 */
22785614e71bSYork Sun 		if (popts->wrlvl_override) {
22795614e71bSYork Sun 			wrlvl_smpl = popts->wrlvl_sample;
22805614e71bSYork Sun 			wrlvl_start = popts->wrlvl_start;
22815614e71bSYork Sun 		}
22825614e71bSYork Sun 	}
22835614e71bSYork Sun 
22845614e71bSYork Sun 	ddr->ddr_wrlvl_cntl = (0
22855614e71bSYork Sun 			       | ((wrlvl_en & 0x1) << 31)
22865614e71bSYork Sun 			       | ((wrlvl_mrd & 0x7) << 24)
22875614e71bSYork Sun 			       | ((wrlvl_odten & 0x7) << 20)
22885614e71bSYork Sun 			       | ((wrlvl_dqsen & 0x7) << 16)
22895614e71bSYork Sun 			       | ((wrlvl_smpl & 0xf) << 12)
22905614e71bSYork Sun 			       | ((wrlvl_wlr & 0x7) << 8)
22915614e71bSYork Sun 			       | ((wrlvl_start & 0x1F) << 0)
22925614e71bSYork Sun 			       );
22935614e71bSYork Sun 	debug("FSLDDR: wrlvl_cntl = 0x%08x\n", ddr->ddr_wrlvl_cntl);
22945614e71bSYork Sun 	ddr->ddr_wrlvl_cntl_2 = popts->wrlvl_ctl_2;
22955614e71bSYork Sun 	debug("FSLDDR: wrlvl_cntl_2 = 0x%08x\n", ddr->ddr_wrlvl_cntl_2);
22965614e71bSYork Sun 	ddr->ddr_wrlvl_cntl_3 = popts->wrlvl_ctl_3;
22975614e71bSYork Sun 	debug("FSLDDR: wrlvl_cntl_3 = 0x%08x\n", ddr->ddr_wrlvl_cntl_3);
22985614e71bSYork Sun 
22995614e71bSYork Sun }
23005614e71bSYork Sun 
23015614e71bSYork Sun /* DDR Self Refresh Counter (DDR_SR_CNTR) */
23025614e71bSYork Sun static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr, unsigned int sr_it)
23035614e71bSYork Sun {
23045614e71bSYork Sun 	/* Self Refresh Idle Threshold */
23055614e71bSYork Sun 	ddr->ddr_sr_cntr = (sr_it & 0xF) << 16;
23065614e71bSYork Sun }
23075614e71bSYork Sun 
23085614e71bSYork Sun static void set_ddr_eor(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
23095614e71bSYork Sun {
23105614e71bSYork Sun 	if (popts->addr_hash) {
23115614e71bSYork Sun 		ddr->ddr_eor = 0x40000000;	/* address hash enable */
23125614e71bSYork Sun 		puts("Address hashing enabled.\n");
23135614e71bSYork Sun 	}
23145614e71bSYork Sun }
23155614e71bSYork Sun 
23165614e71bSYork Sun static void set_ddr_cdr1(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
23175614e71bSYork Sun {
23185614e71bSYork Sun 	ddr->ddr_cdr1 = popts->ddr_cdr1;
23195614e71bSYork Sun 	debug("FSLDDR: ddr_cdr1 = 0x%08x\n", ddr->ddr_cdr1);
23205614e71bSYork Sun }
23215614e71bSYork Sun 
23225614e71bSYork Sun static void set_ddr_cdr2(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
23235614e71bSYork Sun {
23245614e71bSYork Sun 	ddr->ddr_cdr2 = popts->ddr_cdr2;
23255614e71bSYork Sun 	debug("FSLDDR: ddr_cdr2 = 0x%08x\n", ddr->ddr_cdr2);
23265614e71bSYork Sun }
23275614e71bSYork Sun 
23285614e71bSYork Sun unsigned int
23295614e71bSYork Sun check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
23305614e71bSYork Sun {
23315614e71bSYork Sun 	unsigned int res = 0;
23325614e71bSYork Sun 
23335614e71bSYork Sun 	/*
23345614e71bSYork Sun 	 * Check that DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] are
23355614e71bSYork Sun 	 * not set at the same time.
23365614e71bSYork Sun 	 */
23375614e71bSYork Sun 	if (ddr->ddr_sdram_cfg & 0x10000000
23385614e71bSYork Sun 	    && ddr->ddr_sdram_cfg & 0x00008000) {
23395614e71bSYork Sun 		printf("Error: DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] "
23405614e71bSYork Sun 				" should not be set at the same time.\n");
23415614e71bSYork Sun 		res++;
23425614e71bSYork Sun 	}
23435614e71bSYork Sun 
23445614e71bSYork Sun 	return res;
23455614e71bSYork Sun }
23465614e71bSYork Sun 
23475614e71bSYork Sun unsigned int
234803e664d8SYork Sun compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
234903e664d8SYork Sun 			       const memctl_options_t *popts,
23505614e71bSYork Sun 			       fsl_ddr_cfg_regs_t *ddr,
23515614e71bSYork Sun 			       const common_timing_params_t *common_dimm,
23525614e71bSYork Sun 			       const dimm_params_t *dimm_params,
23535614e71bSYork Sun 			       unsigned int dbw_cap_adj,
23545614e71bSYork Sun 			       unsigned int size_only)
23555614e71bSYork Sun {
23565614e71bSYork Sun 	unsigned int i;
23575614e71bSYork Sun 	unsigned int cas_latency;
23585614e71bSYork Sun 	unsigned int additive_latency;
23595614e71bSYork Sun 	unsigned int sr_it;
23605614e71bSYork Sun 	unsigned int zq_en;
23615614e71bSYork Sun 	unsigned int wrlvl_en;
23625614e71bSYork Sun 	unsigned int ip_rev = 0;
23635614e71bSYork Sun 	unsigned int unq_mrs_en = 0;
23645614e71bSYork Sun 	int cs_en = 1;
236502fb2761SShengzhou Liu #ifdef CONFIG_SYS_FSL_ERRATUM_A009942
236602fb2761SShengzhou Liu 	unsigned int ddr_freq;
236702fb2761SShengzhou Liu #endif
236802fb2761SShengzhou Liu #if (defined(CONFIG_SYS_FSL_ERRATUM_A008378) && \
236902fb2761SShengzhou Liu 	defined(CONFIG_SYS_FSL_DDRC_GEN4)) || \
237002fb2761SShengzhou Liu 	defined(CONFIG_SYS_FSL_ERRATUM_A009942)
237102fb2761SShengzhou Liu 	struct ccsr_ddr __iomem *ddrc;
237202fb2761SShengzhou Liu 
237302fb2761SShengzhou Liu 	switch (ctrl_num) {
237402fb2761SShengzhou Liu 	case 0:
237502fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR_ADDR;
237602fb2761SShengzhou Liu 		break;
237751370d56SYork Sun #if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 1)
237802fb2761SShengzhou Liu 	case 1:
237902fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR2_ADDR;
238002fb2761SShengzhou Liu 		break;
238102fb2761SShengzhou Liu #endif
238251370d56SYork Sun #if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 2)
238302fb2761SShengzhou Liu 	case 2:
238402fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR3_ADDR;
238502fb2761SShengzhou Liu 		break;
238602fb2761SShengzhou Liu #endif
238751370d56SYork Sun #if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 3)
238802fb2761SShengzhou Liu 	case 3:
238902fb2761SShengzhou Liu 		ddrc = (void *)CONFIG_SYS_FSL_DDR4_ADDR;
239002fb2761SShengzhou Liu 		break;
239102fb2761SShengzhou Liu #endif
239202fb2761SShengzhou Liu 	default:
239302fb2761SShengzhou Liu 		printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num);
239402fb2761SShengzhou Liu 		return 1;
239502fb2761SShengzhou Liu 	}
239602fb2761SShengzhou Liu #endif
23975614e71bSYork Sun 
23985614e71bSYork Sun 	memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t));
23995614e71bSYork Sun 
24005614e71bSYork Sun 	if (common_dimm == NULL) {
24015614e71bSYork Sun 		printf("Error: subset DIMM params struct null pointer\n");
24025614e71bSYork Sun 		return 1;
24035614e71bSYork Sun 	}
24045614e71bSYork Sun 
24055614e71bSYork Sun 	/*
24065614e71bSYork Sun 	 * Process overrides first.
24075614e71bSYork Sun 	 *
24085614e71bSYork Sun 	 * FIXME: somehow add dereated caslat to this
24095614e71bSYork Sun 	 */
24105614e71bSYork Sun 	cas_latency = (popts->cas_latency_override)
24115614e71bSYork Sun 		? popts->cas_latency_override_value
241234e026f9SYork Sun 		: common_dimm->lowest_common_spd_caslat;
24135614e71bSYork Sun 
24145614e71bSYork Sun 	additive_latency = (popts->additive_latency_override)
24155614e71bSYork Sun 		? popts->additive_latency_override_value
24165614e71bSYork Sun 		: common_dimm->additive_latency;
24175614e71bSYork Sun 
24185614e71bSYork Sun 	sr_it = (popts->auto_self_refresh_en)
24195614e71bSYork Sun 		? popts->sr_it
24205614e71bSYork Sun 		: 0;
24215614e71bSYork Sun 	/* ZQ calibration */
24225614e71bSYork Sun 	zq_en = (popts->zq_en) ? 1 : 0;
24235614e71bSYork Sun 	/* write leveling */
24245614e71bSYork Sun 	wrlvl_en = (popts->wrlvl_en) ? 1 : 0;
24255614e71bSYork Sun 
24265614e71bSYork Sun 	/* Chip Select Memory Bounds (CSn_BNDS) */
24275614e71bSYork Sun 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
24285614e71bSYork Sun 		unsigned long long ea, sa;
24295614e71bSYork Sun 		unsigned int cs_per_dimm
24305614e71bSYork Sun 			= CONFIG_CHIP_SELECTS_PER_CTRL / CONFIG_DIMM_SLOTS_PER_CTLR;
24315614e71bSYork Sun 		unsigned int dimm_number
24325614e71bSYork Sun 			= i / cs_per_dimm;
24335614e71bSYork Sun 		unsigned long long rank_density
24345614e71bSYork Sun 			= dimm_params[dimm_number].rank_density >> dbw_cap_adj;
24355614e71bSYork Sun 
24365614e71bSYork Sun 		if (dimm_params[dimm_number].n_ranks == 0) {
24375614e71bSYork Sun 			debug("Skipping setup of CS%u "
24385614e71bSYork Sun 				"because n_ranks on DIMM %u is 0\n", i, dimm_number);
24395614e71bSYork Sun 			continue;
24405614e71bSYork Sun 		}
24415614e71bSYork Sun 		if (popts->memctl_interleaving) {
24425614e71bSYork Sun 			switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
24435614e71bSYork Sun 			case FSL_DDR_CS0_CS1_CS2_CS3:
24445614e71bSYork Sun 				break;
24455614e71bSYork Sun 			case FSL_DDR_CS0_CS1:
24465614e71bSYork Sun 			case FSL_DDR_CS0_CS1_AND_CS2_CS3:
24475614e71bSYork Sun 				if (i > 1)
24485614e71bSYork Sun 					cs_en = 0;
24495614e71bSYork Sun 				break;
24505614e71bSYork Sun 			case FSL_DDR_CS2_CS3:
24515614e71bSYork Sun 			default:
24525614e71bSYork Sun 				if (i > 0)
24535614e71bSYork Sun 					cs_en = 0;
24545614e71bSYork Sun 				break;
24555614e71bSYork Sun 			}
24565614e71bSYork Sun 			sa = common_dimm->base_address;
24575614e71bSYork Sun 			ea = sa + common_dimm->total_mem - 1;
24585614e71bSYork Sun 		} else if (!popts->memctl_interleaving) {
24595614e71bSYork Sun 			/*
24605614e71bSYork Sun 			 * If memory interleaving between controllers is NOT
24615614e71bSYork Sun 			 * enabled, the starting address for each memory
24625614e71bSYork Sun 			 * controller is distinct.  However, because rank
24635614e71bSYork Sun 			 * interleaving is enabled, the starting and ending
24645614e71bSYork Sun 			 * addresses of the total memory on that memory
24655614e71bSYork Sun 			 * controller needs to be programmed into its
24665614e71bSYork Sun 			 * respective CS0_BNDS.
24675614e71bSYork Sun 			 */
24685614e71bSYork Sun 			switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
24695614e71bSYork Sun 			case FSL_DDR_CS0_CS1_CS2_CS3:
24705614e71bSYork Sun 				sa = common_dimm->base_address;
24715614e71bSYork Sun 				ea = sa + common_dimm->total_mem - 1;
24725614e71bSYork Sun 				break;
24735614e71bSYork Sun 			case FSL_DDR_CS0_CS1_AND_CS2_CS3:
24745614e71bSYork Sun 				if ((i >= 2) && (dimm_number == 0)) {
24755614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address +
24765614e71bSYork Sun 					      2 * rank_density;
24775614e71bSYork Sun 					ea = sa + 2 * rank_density - 1;
24785614e71bSYork Sun 				} else {
24795614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address;
24805614e71bSYork Sun 					ea = sa + 2 * rank_density - 1;
24815614e71bSYork Sun 				}
24825614e71bSYork Sun 				break;
24835614e71bSYork Sun 			case FSL_DDR_CS0_CS1:
24845614e71bSYork Sun 				if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
24855614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address;
24865614e71bSYork Sun 					ea = sa + rank_density - 1;
24875614e71bSYork Sun 					if (i != 1)
24885614e71bSYork Sun 						sa += (i % cs_per_dimm) * rank_density;
24895614e71bSYork Sun 					ea += (i % cs_per_dimm) * rank_density;
24905614e71bSYork Sun 				} else {
24915614e71bSYork Sun 					sa = 0;
24925614e71bSYork Sun 					ea = 0;
24935614e71bSYork Sun 				}
24945614e71bSYork Sun 				if (i == 0)
24955614e71bSYork Sun 					ea += rank_density;
24965614e71bSYork Sun 				break;
24975614e71bSYork Sun 			case FSL_DDR_CS2_CS3:
24985614e71bSYork Sun 				if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
24995614e71bSYork Sun 					sa = dimm_params[dimm_number].base_address;
25005614e71bSYork Sun 					ea = sa + rank_density - 1;
25015614e71bSYork Sun 					if (i != 3)
25025614e71bSYork Sun 						sa += (i % cs_per_dimm) * rank_density;
25035614e71bSYork Sun 					ea += (i % cs_per_dimm) * rank_density;
25045614e71bSYork Sun 				} else {
25055614e71bSYork Sun 					sa = 0;
25065614e71bSYork Sun 					ea = 0;
25075614e71bSYork Sun 				}
25085614e71bSYork Sun 				if (i == 2)
25095614e71bSYork Sun 					ea += (rank_density >> dbw_cap_adj);
25105614e71bSYork Sun 				break;
25115614e71bSYork Sun 			default:  /* No bank(chip-select) interleaving */
25125614e71bSYork Sun 				sa = dimm_params[dimm_number].base_address;
25135614e71bSYork Sun 				ea = sa + rank_density - 1;
25145614e71bSYork Sun 				if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
25155614e71bSYork Sun 					sa += (i % cs_per_dimm) * rank_density;
25165614e71bSYork Sun 					ea += (i % cs_per_dimm) * rank_density;
25175614e71bSYork Sun 				} else {
25185614e71bSYork Sun 					sa = 0;
25195614e71bSYork Sun 					ea = 0;
25205614e71bSYork Sun 				}
25215614e71bSYork Sun 				break;
25225614e71bSYork Sun 			}
25235614e71bSYork Sun 		}
25245614e71bSYork Sun 
25255614e71bSYork Sun 		sa >>= 24;
25265614e71bSYork Sun 		ea >>= 24;
25275614e71bSYork Sun 
25285614e71bSYork Sun 		if (cs_en) {
25295614e71bSYork Sun 			ddr->cs[i].bnds = (0
2530d4263b8aSYork Sun 				| ((sa & 0xffff) << 16) /* starting address */
2531d4263b8aSYork Sun 				| ((ea & 0xffff) << 0)	/* ending address */
25325614e71bSYork Sun 				);
25335614e71bSYork Sun 		} else {
25345614e71bSYork Sun 			/* setting bnds to 0xffffffff for inactive CS */
25355614e71bSYork Sun 			ddr->cs[i].bnds = 0xffffffff;
25365614e71bSYork Sun 		}
25375614e71bSYork Sun 
25385614e71bSYork Sun 		debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds);
25395614e71bSYork Sun 		set_csn_config(dimm_number, i, ddr, popts, dimm_params);
25405614e71bSYork Sun 		set_csn_config_2(i, ddr);
25415614e71bSYork Sun 	}
25425614e71bSYork Sun 
25435614e71bSYork Sun 	/*
25445614e71bSYork Sun 	 * In the case we only need to compute the ddr sdram size, we only need
25455614e71bSYork Sun 	 * to set csn registers, so return from here.
25465614e71bSYork Sun 	 */
25475614e71bSYork Sun 	if (size_only)
25485614e71bSYork Sun 		return 0;
25495614e71bSYork Sun 
25505614e71bSYork Sun 	set_ddr_eor(ddr, popts);
25515614e71bSYork Sun 
25525614e71bSYork Sun #if !defined(CONFIG_SYS_FSL_DDR1)
255303e664d8SYork Sun 	set_timing_cfg_0(ctrl_num, ddr, popts, dimm_params);
25545614e71bSYork Sun #endif
25555614e71bSYork Sun 
255603e664d8SYork Sun 	set_timing_cfg_3(ctrl_num, ddr, popts, common_dimm, cas_latency,
2557d4263b8aSYork Sun 			 additive_latency);
255803e664d8SYork Sun 	set_timing_cfg_1(ctrl_num, ddr, popts, common_dimm, cas_latency);
255903e664d8SYork Sun 	set_timing_cfg_2(ctrl_num, ddr, popts, common_dimm,
25605614e71bSYork Sun 			 cas_latency, additive_latency);
25615614e71bSYork Sun 
25625614e71bSYork Sun 	set_ddr_cdr1(ddr, popts);
25635614e71bSYork Sun 	set_ddr_cdr2(ddr, popts);
25645614e71bSYork Sun 	set_ddr_sdram_cfg(ddr, popts, common_dimm);
256566869f95SYork Sun 	ip_rev = fsl_ddr_get_version(ctrl_num);
25665614e71bSYork Sun 	if (ip_rev > 0x40400)
25675614e71bSYork Sun 		unq_mrs_en = 1;
25685614e71bSYork Sun 
2569f80d6472SYork Sun 	if ((ip_rev > 0x40700) && (popts->cswl_override != 0))
2570ef87cab6SYork Sun 		ddr->debug[18] = popts->cswl_override;
2571ef87cab6SYork Sun 
257203e664d8SYork Sun 	set_ddr_sdram_cfg_2(ctrl_num, ddr, popts, unq_mrs_en);
257303e664d8SYork Sun 	set_ddr_sdram_mode(ctrl_num, ddr, popts, common_dimm,
25745614e71bSYork Sun 			   cas_latency, additive_latency, unq_mrs_en);
257503e664d8SYork Sun 	set_ddr_sdram_mode_2(ctrl_num, ddr, popts, common_dimm, unq_mrs_en);
257634e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
257734e026f9SYork Sun 	set_ddr_sdram_mode_9(ddr, popts, common_dimm, unq_mrs_en);
257803e664d8SYork Sun 	set_ddr_sdram_mode_10(ctrl_num, ddr, popts, common_dimm, unq_mrs_en);
257934e026f9SYork Sun #endif
2580*564e9383SYork Sun 	set_ddr_sdram_rcw(ctrl_num, ddr, popts, common_dimm);
2581*564e9383SYork Sun 
258203e664d8SYork Sun 	set_ddr_sdram_interval(ctrl_num, ddr, popts, common_dimm);
25835614e71bSYork Sun 	set_ddr_data_init(ddr);
25845614e71bSYork Sun 	set_ddr_sdram_clk_cntl(ddr, popts);
25855614e71bSYork Sun 	set_ddr_init_addr(ddr);
25865614e71bSYork Sun 	set_ddr_init_ext_addr(ddr);
25875614e71bSYork Sun 	set_timing_cfg_4(ddr, popts);
25885614e71bSYork Sun 	set_timing_cfg_5(ddr, cas_latency);
258934e026f9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
259034e026f9SYork Sun 	set_ddr_sdram_cfg_3(ddr, popts);
259134e026f9SYork Sun 	set_timing_cfg_6(ddr);
2592426230a6SYork Sun 	set_timing_cfg_7(ctrl_num, ddr, popts, common_dimm);
259303e664d8SYork Sun 	set_timing_cfg_8(ctrl_num, ddr, popts, common_dimm, cas_latency);
2594c0c32af0SYork Sun 	set_timing_cfg_9(ctrl_num, ddr, popts, common_dimm);
259534e026f9SYork Sun 	set_ddr_dq_mapping(ddr, dimm_params);
259634e026f9SYork Sun #endif
25975614e71bSYork Sun 
25985614e71bSYork Sun 	set_ddr_zq_cntl(ddr, zq_en);
25995614e71bSYork Sun 	set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts);
26005614e71bSYork Sun 
26015614e71bSYork Sun 	set_ddr_sr_cntr(ddr, sr_it);
26025614e71bSYork Sun 
26035614e71bSYork Sun #ifdef CONFIG_SYS_FSL_DDR_EMU
26045614e71bSYork Sun 	/* disble DDR training for emulator */
26055614e71bSYork Sun 	ddr->debug[2] = 0x00000400;
26061f3402e7SYork Sun 	ddr->debug[4] = 0xff800800;
26071f3402e7SYork Sun 	ddr->debug[5] = 0x08000800;
26081f3402e7SYork Sun 	ddr->debug[6] = 0x08000800;
26091f3402e7SYork Sun 	ddr->debug[7] = 0x08000800;
26101f3402e7SYork Sun 	ddr->debug[8] = 0x08000800;
26115614e71bSYork Sun #endif
26129855b3beSYork Sun #ifdef CONFIG_SYS_FSL_ERRATUM_A004508
26139855b3beSYork Sun 	if ((ip_rev >= 0x40000) && (ip_rev < 0x40400))
26149855b3beSYork Sun 		ddr->debug[2] |= 0x00000200;	/* set bit 22 */
26159855b3beSYork Sun #endif
26169855b3beSYork Sun 
261702fb2761SShengzhou Liu #if defined(CONFIG_SYS_FSL_ERRATUM_A008378) && defined(CONFIG_SYS_FSL_DDRC_GEN4)
261802fb2761SShengzhou Liu 	/* Erratum applies when accumulated ECC is used, or DBI is enabled */
261902fb2761SShengzhou Liu #define IS_ACC_ECC_EN(v) ((v) & 0x4)
262002fb2761SShengzhou Liu #define IS_DBI(v) ((((v) >> 12) & 0x3) == 0x2)
262102fb2761SShengzhou Liu 	if (has_erratum_a008378()) {
262202fb2761SShengzhou Liu 		if (IS_ACC_ECC_EN(ddr->ddr_sdram_cfg) ||
262302fb2761SShengzhou Liu 		    IS_DBI(ddr->ddr_sdram_cfg_3)) {
262402fb2761SShengzhou Liu 			ddr->debug[28] = ddr_in32(&ddrc->debug[28]);
262502fb2761SShengzhou Liu 			ddr->debug[28] |= (0x9 << 20);
262602fb2761SShengzhou Liu 		}
262702fb2761SShengzhou Liu 	}
262802fb2761SShengzhou Liu #endif
262902fb2761SShengzhou Liu 
263002fb2761SShengzhou Liu #ifdef CONFIG_SYS_FSL_ERRATUM_A009942
263102fb2761SShengzhou Liu 	ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
263202fb2761SShengzhou Liu 	ddr->debug[28] |= ddr_in32(&ddrc->debug[28]);
263302fb2761SShengzhou Liu 	ddr->debug[28] &= 0xff0fff00;
263402fb2761SShengzhou Liu 	if (ddr_freq <= 1333)
263502fb2761SShengzhou Liu 		ddr->debug[28] |= 0x0080006a;
263602fb2761SShengzhou Liu 	else if (ddr_freq <= 1600)
263702fb2761SShengzhou Liu 		ddr->debug[28] |= 0x0070006f;
263802fb2761SShengzhou Liu 	else if (ddr_freq <= 1867)
263902fb2761SShengzhou Liu 		ddr->debug[28] |= 0x00700076;
264002fb2761SShengzhou Liu 	else if (ddr_freq <= 2133)
264102fb2761SShengzhou Liu 		ddr->debug[28] |= 0x0060007b;
264202fb2761SShengzhou Liu 	if (popts->cpo_sample)
264302fb2761SShengzhou Liu 		ddr->debug[28] = (ddr->debug[28] & 0xffffff00) |
264402fb2761SShengzhou Liu 				  popts->cpo_sample;
264502fb2761SShengzhou Liu #endif
264602fb2761SShengzhou Liu 
26475614e71bSYork Sun 	return check_fsl_memctl_config_regs(ddr);
26485614e71bSYork Sun }
264902fb2761SShengzhou Liu 
265002fb2761SShengzhou Liu #ifdef CONFIG_SYS_FSL_ERRATUM_A009942
265102fb2761SShengzhou Liu /*
265202fb2761SShengzhou Liu  * This additional workaround of A009942 checks the condition to determine if
265302fb2761SShengzhou Liu  * the CPO value set by the existing A009942 workaround needs to be updated.
265402fb2761SShengzhou Liu  * If need, print a warning to prompt user reconfigure DDR debug_29[24:31] with
265502fb2761SShengzhou Liu  * expected optimal value, the optimal value is highly board dependent.
265602fb2761SShengzhou Liu  */
265702fb2761SShengzhou Liu void erratum_a009942_check_cpo(void)
265802fb2761SShengzhou Liu {
265902fb2761SShengzhou Liu 	struct ccsr_ddr __iomem *ddr =
266002fb2761SShengzhou Liu 		(struct ccsr_ddr __iomem *)(CONFIG_SYS_FSL_DDR_ADDR);
266102fb2761SShengzhou Liu 	u32 cpo, cpo_e, cpo_o, cpo_target, cpo_optimal;
266202fb2761SShengzhou Liu 	u32 cpo_min = ddr_in32(&ddr->debug[9]) >> 24;
266302fb2761SShengzhou Liu 	u32 cpo_max = cpo_min;
266402fb2761SShengzhou Liu 	u32 sdram_cfg, i, tmp, lanes, ddr_type;
266502fb2761SShengzhou Liu 	bool update_cpo = false, has_ecc = false;
266602fb2761SShengzhou Liu 
266702fb2761SShengzhou Liu 	sdram_cfg = ddr_in32(&ddr->sdram_cfg);
266802fb2761SShengzhou Liu 	if (sdram_cfg & SDRAM_CFG_32_BE)
266902fb2761SShengzhou Liu 		lanes = 4;
267002fb2761SShengzhou Liu 	else if (sdram_cfg & SDRAM_CFG_16_BE)
267102fb2761SShengzhou Liu 		lanes = 2;
267202fb2761SShengzhou Liu 	else
267302fb2761SShengzhou Liu 		lanes = 8;
267402fb2761SShengzhou Liu 
267502fb2761SShengzhou Liu 	if (sdram_cfg & SDRAM_CFG_ECC_EN)
267602fb2761SShengzhou Liu 		has_ecc = true;
267702fb2761SShengzhou Liu 
267802fb2761SShengzhou Liu 	/* determine the maximum and minimum CPO values */
267902fb2761SShengzhou Liu 	for (i = 9; i < 9 + lanes / 2; i++) {
268002fb2761SShengzhou Liu 		cpo = ddr_in32(&ddr->debug[i]);
268102fb2761SShengzhou Liu 		cpo_e = cpo >> 24;
268202fb2761SShengzhou Liu 		cpo_o = (cpo >> 8) & 0xff;
268302fb2761SShengzhou Liu 		tmp = min(cpo_e, cpo_o);
268402fb2761SShengzhou Liu 		if (tmp < cpo_min)
268502fb2761SShengzhou Liu 			cpo_min = tmp;
268602fb2761SShengzhou Liu 		tmp = max(cpo_e, cpo_o);
268702fb2761SShengzhou Liu 		if (tmp > cpo_max)
268802fb2761SShengzhou Liu 			cpo_max = tmp;
268902fb2761SShengzhou Liu 	}
269002fb2761SShengzhou Liu 
269102fb2761SShengzhou Liu 	if (has_ecc) {
269202fb2761SShengzhou Liu 		cpo = ddr_in32(&ddr->debug[13]);
269302fb2761SShengzhou Liu 		cpo = cpo >> 24;
269402fb2761SShengzhou Liu 		if (cpo < cpo_min)
269502fb2761SShengzhou Liu 			cpo_min = cpo;
269602fb2761SShengzhou Liu 		if (cpo > cpo_max)
269702fb2761SShengzhou Liu 			cpo_max = cpo;
269802fb2761SShengzhou Liu 	}
269902fb2761SShengzhou Liu 
270002fb2761SShengzhou Liu 	cpo_target = ddr_in32(&ddr->debug[28]) & 0xff;
270102fb2761SShengzhou Liu 	cpo_optimal = ((cpo_max + cpo_min) >> 1) + 0x27;
270202fb2761SShengzhou Liu 	debug("cpo_optimal = 0x%x, cpo_target = 0x%x\n", cpo_optimal,
270302fb2761SShengzhou Liu 	      cpo_target);
270402fb2761SShengzhou Liu 	debug("cpo_max = 0x%x, cpo_min = 0x%x\n", cpo_max, cpo_min);
270502fb2761SShengzhou Liu 
270602fb2761SShengzhou Liu 	ddr_type = (sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
270702fb2761SShengzhou Liu 		    SDRAM_CFG_SDRAM_TYPE_SHIFT;
270802fb2761SShengzhou Liu 	if (ddr_type == SDRAM_TYPE_DDR4)
270902fb2761SShengzhou Liu 		update_cpo = (cpo_min + 0x3b) < cpo_target ? true : false;
271002fb2761SShengzhou Liu 	else if (ddr_type == SDRAM_TYPE_DDR3)
271102fb2761SShengzhou Liu 		update_cpo = (cpo_min + 0x3f) < cpo_target ? true : false;
271202fb2761SShengzhou Liu 
271302fb2761SShengzhou Liu 	if (update_cpo) {
271402fb2761SShengzhou Liu 		printf("WARN: pls set popts->cpo_sample = 0x%x ", cpo_optimal);
271502fb2761SShengzhou Liu 		printf("in <board>/ddr.c to optimize cpo\n");
271602fb2761SShengzhou Liu 	}
271702fb2761SShengzhou Liu }
271802fb2761SShengzhou Liu #endif
2719