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