xref: /openbmc/u-boot/drivers/ddr/fsl/options.c (revision 349689b8)
15614e71bSYork Sun /*
234e026f9SYork Sun  * Copyright 2008, 2010-2014 Freescale Semiconductor, Inc.
35614e71bSYork Sun  *
45614e71bSYork Sun  * SPDX-License-Identifier:	GPL-2.0+
55614e71bSYork Sun  */
65614e71bSYork Sun 
75614e71bSYork Sun #include <common.h>
85614e71bSYork Sun #include <hwconfig.h>
95614e71bSYork Sun #include <fsl_ddr_sdram.h>
105614e71bSYork Sun 
115614e71bSYork Sun #include <fsl_ddr.h>
125614e71bSYork Sun 
135614e71bSYork Sun /*
145614e71bSYork Sun  * Use our own stack based buffer before relocation to allow accessing longer
155614e71bSYork Sun  * hwconfig strings that might be in the environment before we've relocated.
165614e71bSYork Sun  * This is pretty fragile on both the use of stack and if the buffer is big
175614e71bSYork Sun  * enough. However we will get a warning from getenv_f for the later.
185614e71bSYork Sun  */
195614e71bSYork Sun 
205614e71bSYork Sun /* Board-specific functions defined in each board's ddr.c */
215614e71bSYork Sun extern void fsl_ddr_board_options(memctl_options_t *popts,
225614e71bSYork Sun 		dimm_params_t *pdimm,
235614e71bSYork Sun 		unsigned int ctrl_num);
245614e71bSYork Sun 
255614e71bSYork Sun struct dynamic_odt {
265614e71bSYork Sun 	unsigned int odt_rd_cfg;
275614e71bSYork Sun 	unsigned int odt_wr_cfg;
285614e71bSYork Sun 	unsigned int odt_rtt_norm;
295614e71bSYork Sun 	unsigned int odt_rtt_wr;
305614e71bSYork Sun };
315614e71bSYork Sun 
3234e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
335614e71bSYork Sun static const struct dynamic_odt single_Q[4] = {
345614e71bSYork Sun 	{	/* cs0 */
355614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
365614e71bSYork Sun 		FSL_DDR_ODT_CS_AND_OTHER_DIMM,
375614e71bSYork Sun 		DDR3_RTT_20_OHM,
385614e71bSYork Sun 		DDR3_RTT_120_OHM
395614e71bSYork Sun 	},
405614e71bSYork Sun 	{	/* cs1 */
415614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
425614e71bSYork Sun 		FSL_DDR_ODT_NEVER,	/* tied high */
435614e71bSYork Sun 		DDR3_RTT_OFF,
445614e71bSYork Sun 		DDR3_RTT_120_OHM
455614e71bSYork Sun 	},
465614e71bSYork Sun 	{	/* cs2 */
475614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
485614e71bSYork Sun 		FSL_DDR_ODT_CS_AND_OTHER_DIMM,
495614e71bSYork Sun 		DDR3_RTT_20_OHM,
505614e71bSYork Sun 		DDR3_RTT_120_OHM
515614e71bSYork Sun 	},
525614e71bSYork Sun 	{	/* cs3 */
535614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
545614e71bSYork Sun 		FSL_DDR_ODT_NEVER,	/* tied high */
555614e71bSYork Sun 		DDR3_RTT_OFF,
565614e71bSYork Sun 		DDR3_RTT_120_OHM
575614e71bSYork Sun 	}
585614e71bSYork Sun };
595614e71bSYork Sun 
605614e71bSYork Sun static const struct dynamic_odt single_D[4] = {
615614e71bSYork Sun 	{	/* cs0 */
625614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
635614e71bSYork Sun 		FSL_DDR_ODT_ALL,
645614e71bSYork Sun 		DDR3_RTT_40_OHM,
655614e71bSYork Sun 		DDR3_RTT_OFF
665614e71bSYork Sun 	},
675614e71bSYork Sun 	{	/* cs1 */
685614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
695614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
705614e71bSYork Sun 		DDR3_RTT_OFF,
715614e71bSYork Sun 		DDR3_RTT_OFF
725614e71bSYork Sun 	},
735614e71bSYork Sun 	{0, 0, 0, 0},
745614e71bSYork Sun 	{0, 0, 0, 0}
755614e71bSYork Sun };
765614e71bSYork Sun 
775614e71bSYork Sun static const struct dynamic_odt single_S[4] = {
785614e71bSYork Sun 	{	/* cs0 */
795614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
805614e71bSYork Sun 		FSL_DDR_ODT_ALL,
815614e71bSYork Sun 		DDR3_RTT_40_OHM,
825614e71bSYork Sun 		DDR3_RTT_OFF
835614e71bSYork Sun 	},
845614e71bSYork Sun 	{0, 0, 0, 0},
855614e71bSYork Sun 	{0, 0, 0, 0},
865614e71bSYork Sun 	{0, 0, 0, 0},
875614e71bSYork Sun };
885614e71bSYork Sun 
895614e71bSYork Sun static const struct dynamic_odt dual_DD[4] = {
905614e71bSYork Sun 	{	/* cs0 */
915614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
925614e71bSYork Sun 		FSL_DDR_ODT_SAME_DIMM,
935614e71bSYork Sun 		DDR3_RTT_120_OHM,
945614e71bSYork Sun 		DDR3_RTT_OFF
955614e71bSYork Sun 	},
965614e71bSYork Sun 	{	/* cs1 */
975614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
985614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
995614e71bSYork Sun 		DDR3_RTT_30_OHM,
1005614e71bSYork Sun 		DDR3_RTT_OFF
1015614e71bSYork Sun 	},
1025614e71bSYork Sun 	{	/* cs2 */
1035614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
1045614e71bSYork Sun 		FSL_DDR_ODT_SAME_DIMM,
1055614e71bSYork Sun 		DDR3_RTT_120_OHM,
1065614e71bSYork Sun 		DDR3_RTT_OFF
1075614e71bSYork Sun 	},
1085614e71bSYork Sun 	{	/* cs3 */
1095614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
1105614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
1115614e71bSYork Sun 		DDR3_RTT_30_OHM,
1125614e71bSYork Sun 		DDR3_RTT_OFF
1135614e71bSYork Sun 	}
1145614e71bSYork Sun };
1155614e71bSYork Sun 
1165614e71bSYork Sun static const struct dynamic_odt dual_DS[4] = {
1175614e71bSYork Sun 	{	/* cs0 */
1185614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
1195614e71bSYork Sun 		FSL_DDR_ODT_SAME_DIMM,
1205614e71bSYork Sun 		DDR3_RTT_120_OHM,
1215614e71bSYork Sun 		DDR3_RTT_OFF
1225614e71bSYork Sun 	},
1235614e71bSYork Sun 	{	/* cs1 */
1245614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
1255614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
1265614e71bSYork Sun 		DDR3_RTT_30_OHM,
1275614e71bSYork Sun 		DDR3_RTT_OFF
1285614e71bSYork Sun 	},
1295614e71bSYork Sun 	{	/* cs2 */
1305614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
1315614e71bSYork Sun 		FSL_DDR_ODT_ALL,
1325614e71bSYork Sun 		DDR3_RTT_20_OHM,
1335614e71bSYork Sun 		DDR3_RTT_120_OHM
1345614e71bSYork Sun 	},
1355614e71bSYork Sun 	{0, 0, 0, 0}
1365614e71bSYork Sun };
1375614e71bSYork Sun static const struct dynamic_odt dual_SD[4] = {
1385614e71bSYork Sun 	{	/* cs0 */
1395614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
1405614e71bSYork Sun 		FSL_DDR_ODT_ALL,
1415614e71bSYork Sun 		DDR3_RTT_20_OHM,
1425614e71bSYork Sun 		DDR3_RTT_120_OHM
1435614e71bSYork Sun 	},
1445614e71bSYork Sun 	{0, 0, 0, 0},
1455614e71bSYork Sun 	{	/* cs2 */
1465614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
1475614e71bSYork Sun 		FSL_DDR_ODT_SAME_DIMM,
1485614e71bSYork Sun 		DDR3_RTT_120_OHM,
1495614e71bSYork Sun 		DDR3_RTT_OFF
1505614e71bSYork Sun 	},
1515614e71bSYork Sun 	{	/* cs3 */
1525614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
1535614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
1545614e71bSYork Sun 		DDR3_RTT_20_OHM,
1555614e71bSYork Sun 		DDR3_RTT_OFF
1565614e71bSYork Sun 	}
1575614e71bSYork Sun };
1585614e71bSYork Sun 
1595614e71bSYork Sun static const struct dynamic_odt dual_SS[4] = {
1605614e71bSYork Sun 	{	/* cs0 */
1615614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
1625614e71bSYork Sun 		FSL_DDR_ODT_ALL,
1635614e71bSYork Sun 		DDR3_RTT_30_OHM,
1645614e71bSYork Sun 		DDR3_RTT_120_OHM
1655614e71bSYork Sun 	},
1665614e71bSYork Sun 	{0, 0, 0, 0},
1675614e71bSYork Sun 	{	/* cs2 */
1685614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
1695614e71bSYork Sun 		FSL_DDR_ODT_ALL,
1705614e71bSYork Sun 		DDR3_RTT_30_OHM,
1715614e71bSYork Sun 		DDR3_RTT_120_OHM
1725614e71bSYork Sun 	},
1735614e71bSYork Sun 	{0, 0, 0, 0}
1745614e71bSYork Sun };
1755614e71bSYork Sun 
1765614e71bSYork Sun static const struct dynamic_odt dual_D0[4] = {
1775614e71bSYork Sun 	{	/* cs0 */
1785614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
1795614e71bSYork Sun 		FSL_DDR_ODT_SAME_DIMM,
1805614e71bSYork Sun 		DDR3_RTT_40_OHM,
1815614e71bSYork Sun 		DDR3_RTT_OFF
1825614e71bSYork Sun 	},
1835614e71bSYork Sun 	{	/* cs1 */
1845614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
1855614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
1865614e71bSYork Sun 		DDR3_RTT_OFF,
1875614e71bSYork Sun 		DDR3_RTT_OFF
1885614e71bSYork Sun 	},
1895614e71bSYork Sun 	{0, 0, 0, 0},
1905614e71bSYork Sun 	{0, 0, 0, 0}
1915614e71bSYork Sun };
1925614e71bSYork Sun 
1935614e71bSYork Sun static const struct dynamic_odt dual_0D[4] = {
1945614e71bSYork Sun 	{0, 0, 0, 0},
1955614e71bSYork Sun 	{0, 0, 0, 0},
1965614e71bSYork Sun 	{	/* cs2 */
1975614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
1985614e71bSYork Sun 		FSL_DDR_ODT_SAME_DIMM,
1995614e71bSYork Sun 		DDR3_RTT_40_OHM,
2005614e71bSYork Sun 		DDR3_RTT_OFF
2015614e71bSYork Sun 	},
2025614e71bSYork Sun 	{	/* cs3 */
2035614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2045614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2055614e71bSYork Sun 		DDR3_RTT_OFF,
2065614e71bSYork Sun 		DDR3_RTT_OFF
2075614e71bSYork Sun 	}
2085614e71bSYork Sun };
2095614e71bSYork Sun 
2105614e71bSYork Sun static const struct dynamic_odt dual_S0[4] = {
2115614e71bSYork Sun 	{	/* cs0 */
2125614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2135614e71bSYork Sun 		FSL_DDR_ODT_CS,
2145614e71bSYork Sun 		DDR3_RTT_40_OHM,
2155614e71bSYork Sun 		DDR3_RTT_OFF
2165614e71bSYork Sun 	},
2175614e71bSYork Sun 	{0, 0, 0, 0},
2185614e71bSYork Sun 	{0, 0, 0, 0},
2195614e71bSYork Sun 	{0, 0, 0, 0}
2205614e71bSYork Sun 
2215614e71bSYork Sun };
2225614e71bSYork Sun 
2235614e71bSYork Sun static const struct dynamic_odt dual_0S[4] = {
2245614e71bSYork Sun 	{0, 0, 0, 0},
2255614e71bSYork Sun 	{0, 0, 0, 0},
2265614e71bSYork Sun 	{	/* cs2 */
2275614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2285614e71bSYork Sun 		FSL_DDR_ODT_CS,
2295614e71bSYork Sun 		DDR3_RTT_40_OHM,
2305614e71bSYork Sun 		DDR3_RTT_OFF
2315614e71bSYork Sun 	},
2325614e71bSYork Sun 	{0, 0, 0, 0}
2335614e71bSYork Sun 
2345614e71bSYork Sun };
2355614e71bSYork Sun 
2365614e71bSYork Sun static const struct dynamic_odt odt_unknown[4] = {
2375614e71bSYork Sun 	{	/* cs0 */
2385614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2395614e71bSYork Sun 		FSL_DDR_ODT_CS,
2405614e71bSYork Sun 		DDR3_RTT_120_OHM,
2415614e71bSYork Sun 		DDR3_RTT_OFF
2425614e71bSYork Sun 	},
2435614e71bSYork Sun 	{	/* cs1 */
2445614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2455614e71bSYork Sun 		FSL_DDR_ODT_CS,
2465614e71bSYork Sun 		DDR3_RTT_120_OHM,
2475614e71bSYork Sun 		DDR3_RTT_OFF
2485614e71bSYork Sun 	},
2495614e71bSYork Sun 	{	/* cs2 */
2505614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2515614e71bSYork Sun 		FSL_DDR_ODT_CS,
2525614e71bSYork Sun 		DDR3_RTT_120_OHM,
2535614e71bSYork Sun 		DDR3_RTT_OFF
2545614e71bSYork Sun 	},
2555614e71bSYork Sun 	{	/* cs3 */
2565614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2575614e71bSYork Sun 		FSL_DDR_ODT_CS,
2585614e71bSYork Sun 		DDR3_RTT_120_OHM,
2595614e71bSYork Sun 		DDR3_RTT_OFF
2605614e71bSYork Sun 	}
2615614e71bSYork Sun };
26234e026f9SYork Sun #else	/* CONFIG_SYS_FSL_DDR3 || CONFIG_SYS_FSL_DDR4 */
2635614e71bSYork Sun static const struct dynamic_odt single_Q[4] = {
2645614e71bSYork Sun 	{0, 0, 0, 0},
2655614e71bSYork Sun 	{0, 0, 0, 0},
2665614e71bSYork Sun 	{0, 0, 0, 0},
2675614e71bSYork Sun 	{0, 0, 0, 0}
2685614e71bSYork Sun };
2695614e71bSYork Sun 
2705614e71bSYork Sun static const struct dynamic_odt single_D[4] = {
2715614e71bSYork Sun 	{	/* cs0 */
2725614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2735614e71bSYork Sun 		FSL_DDR_ODT_ALL,
2745614e71bSYork Sun 		DDR2_RTT_150_OHM,
2755614e71bSYork Sun 		DDR2_RTT_OFF
2765614e71bSYork Sun 	},
2775614e71bSYork Sun 	{	/* cs1 */
2785614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2795614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2805614e71bSYork Sun 		DDR2_RTT_OFF,
2815614e71bSYork Sun 		DDR2_RTT_OFF
2825614e71bSYork Sun 	},
2835614e71bSYork Sun 	{0, 0, 0, 0},
2845614e71bSYork Sun 	{0, 0, 0, 0}
2855614e71bSYork Sun };
2865614e71bSYork Sun 
2875614e71bSYork Sun static const struct dynamic_odt single_S[4] = {
2885614e71bSYork Sun 	{	/* cs0 */
2895614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
2905614e71bSYork Sun 		FSL_DDR_ODT_ALL,
2915614e71bSYork Sun 		DDR2_RTT_150_OHM,
2925614e71bSYork Sun 		DDR2_RTT_OFF
2935614e71bSYork Sun 	},
2945614e71bSYork Sun 	{0, 0, 0, 0},
2955614e71bSYork Sun 	{0, 0, 0, 0},
2965614e71bSYork Sun 	{0, 0, 0, 0},
2975614e71bSYork Sun };
2985614e71bSYork Sun 
2995614e71bSYork Sun static const struct dynamic_odt dual_DD[4] = {
3005614e71bSYork Sun 	{	/* cs0 */
3015614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3025614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3035614e71bSYork Sun 		DDR2_RTT_75_OHM,
3045614e71bSYork Sun 		DDR2_RTT_OFF
3055614e71bSYork Sun 	},
3065614e71bSYork Sun 	{	/* cs1 */
3075614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3085614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3095614e71bSYork Sun 		DDR2_RTT_OFF,
3105614e71bSYork Sun 		DDR2_RTT_OFF
3115614e71bSYork Sun 	},
3125614e71bSYork Sun 	{	/* cs2 */
3135614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3145614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3155614e71bSYork Sun 		DDR2_RTT_75_OHM,
3165614e71bSYork Sun 		DDR2_RTT_OFF
3175614e71bSYork Sun 	},
3185614e71bSYork Sun 	{	/* cs3 */
3195614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3205614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3215614e71bSYork Sun 		DDR2_RTT_OFF,
3225614e71bSYork Sun 		DDR2_RTT_OFF
3235614e71bSYork Sun 	}
3245614e71bSYork Sun };
3255614e71bSYork Sun 
3265614e71bSYork Sun static const struct dynamic_odt dual_DS[4] = {
3275614e71bSYork Sun 	{	/* cs0 */
3285614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3295614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3305614e71bSYork Sun 		DDR2_RTT_75_OHM,
3315614e71bSYork Sun 		DDR2_RTT_OFF
3325614e71bSYork Sun 	},
3335614e71bSYork Sun 	{	/* cs1 */
3345614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3355614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3365614e71bSYork Sun 		DDR2_RTT_OFF,
3375614e71bSYork Sun 		DDR2_RTT_OFF
3385614e71bSYork Sun 	},
3395614e71bSYork Sun 	{	/* cs2 */
3405614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3415614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3425614e71bSYork Sun 		DDR2_RTT_75_OHM,
3435614e71bSYork Sun 		DDR2_RTT_OFF
3445614e71bSYork Sun 	},
3455614e71bSYork Sun 	{0, 0, 0, 0}
3465614e71bSYork Sun };
3475614e71bSYork Sun 
3485614e71bSYork Sun static const struct dynamic_odt dual_SD[4] = {
3495614e71bSYork Sun 	{	/* cs0 */
3505614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3515614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3525614e71bSYork Sun 		DDR2_RTT_75_OHM,
3535614e71bSYork Sun 		DDR2_RTT_OFF
3545614e71bSYork Sun 	},
3555614e71bSYork Sun 	{0, 0, 0, 0},
3565614e71bSYork Sun 	{	/* cs2 */
3575614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3585614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3595614e71bSYork Sun 		DDR2_RTT_75_OHM,
3605614e71bSYork Sun 		DDR2_RTT_OFF
3615614e71bSYork Sun 	},
3625614e71bSYork Sun 	{	/* cs3 */
3635614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3645614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3655614e71bSYork Sun 		DDR2_RTT_OFF,
3665614e71bSYork Sun 		DDR2_RTT_OFF
3675614e71bSYork Sun 	}
3685614e71bSYork Sun };
3695614e71bSYork Sun 
3705614e71bSYork Sun static const struct dynamic_odt dual_SS[4] = {
3715614e71bSYork Sun 	{	/* cs0 */
3725614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3735614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3745614e71bSYork Sun 		DDR2_RTT_75_OHM,
3755614e71bSYork Sun 		DDR2_RTT_OFF
3765614e71bSYork Sun 	},
3775614e71bSYork Sun 	{0, 0, 0, 0},
3785614e71bSYork Sun 	{	/* cs2 */
3795614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3805614e71bSYork Sun 		FSL_DDR_ODT_OTHER_DIMM,
3815614e71bSYork Sun 		DDR2_RTT_75_OHM,
3825614e71bSYork Sun 		DDR2_RTT_OFF
3835614e71bSYork Sun 	},
3845614e71bSYork Sun 	{0, 0, 0, 0}
3855614e71bSYork Sun };
3865614e71bSYork Sun 
3875614e71bSYork Sun static const struct dynamic_odt dual_D0[4] = {
3885614e71bSYork Sun 	{	/* cs0 */
3895614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3905614e71bSYork Sun 		FSL_DDR_ODT_ALL,
3915614e71bSYork Sun 		DDR2_RTT_150_OHM,
3925614e71bSYork Sun 		DDR2_RTT_OFF
3935614e71bSYork Sun 	},
3945614e71bSYork Sun 	{	/* cs1 */
3955614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3965614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
3975614e71bSYork Sun 		DDR2_RTT_OFF,
3985614e71bSYork Sun 		DDR2_RTT_OFF
3995614e71bSYork Sun 	},
4005614e71bSYork Sun 	{0, 0, 0, 0},
4015614e71bSYork Sun 	{0, 0, 0, 0}
4025614e71bSYork Sun };
4035614e71bSYork Sun 
4045614e71bSYork Sun static const struct dynamic_odt dual_0D[4] = {
4055614e71bSYork Sun 	{0, 0, 0, 0},
4065614e71bSYork Sun 	{0, 0, 0, 0},
4075614e71bSYork Sun 	{	/* cs2 */
4085614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4095614e71bSYork Sun 		FSL_DDR_ODT_ALL,
4105614e71bSYork Sun 		DDR2_RTT_150_OHM,
4115614e71bSYork Sun 		DDR2_RTT_OFF
4125614e71bSYork Sun 	},
4135614e71bSYork Sun 	{	/* cs3 */
4145614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4155614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4165614e71bSYork Sun 		DDR2_RTT_OFF,
4175614e71bSYork Sun 		DDR2_RTT_OFF
4185614e71bSYork Sun 	}
4195614e71bSYork Sun };
4205614e71bSYork Sun 
4215614e71bSYork Sun static const struct dynamic_odt dual_S0[4] = {
4225614e71bSYork Sun 	{	/* cs0 */
4235614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4245614e71bSYork Sun 		FSL_DDR_ODT_CS,
4255614e71bSYork Sun 		DDR2_RTT_150_OHM,
4265614e71bSYork Sun 		DDR2_RTT_OFF
4275614e71bSYork Sun 	},
4285614e71bSYork Sun 	{0, 0, 0, 0},
4295614e71bSYork Sun 	{0, 0, 0, 0},
4305614e71bSYork Sun 	{0, 0, 0, 0}
4315614e71bSYork Sun 
4325614e71bSYork Sun };
4335614e71bSYork Sun 
4345614e71bSYork Sun static const struct dynamic_odt dual_0S[4] = {
4355614e71bSYork Sun 	{0, 0, 0, 0},
4365614e71bSYork Sun 	{0, 0, 0, 0},
4375614e71bSYork Sun 	{	/* cs2 */
4385614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4395614e71bSYork Sun 		FSL_DDR_ODT_CS,
4405614e71bSYork Sun 		DDR2_RTT_150_OHM,
4415614e71bSYork Sun 		DDR2_RTT_OFF
4425614e71bSYork Sun 	},
4435614e71bSYork Sun 	{0, 0, 0, 0}
4445614e71bSYork Sun 
4455614e71bSYork Sun };
4465614e71bSYork Sun 
4475614e71bSYork Sun static const struct dynamic_odt odt_unknown[4] = {
4485614e71bSYork Sun 	{	/* cs0 */
4495614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4505614e71bSYork Sun 		FSL_DDR_ODT_CS,
4515614e71bSYork Sun 		DDR2_RTT_75_OHM,
4525614e71bSYork Sun 		DDR2_RTT_OFF
4535614e71bSYork Sun 	},
4545614e71bSYork Sun 	{	/* cs1 */
4555614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4565614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4575614e71bSYork Sun 		DDR2_RTT_OFF,
4585614e71bSYork Sun 		DDR2_RTT_OFF
4595614e71bSYork Sun 	},
4605614e71bSYork Sun 	{	/* cs2 */
4615614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4625614e71bSYork Sun 		FSL_DDR_ODT_CS,
4635614e71bSYork Sun 		DDR2_RTT_75_OHM,
4645614e71bSYork Sun 		DDR2_RTT_OFF
4655614e71bSYork Sun 	},
4665614e71bSYork Sun 	{	/* cs3 */
4675614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4685614e71bSYork Sun 		FSL_DDR_ODT_NEVER,
4695614e71bSYork Sun 		DDR2_RTT_OFF,
4705614e71bSYork Sun 		DDR2_RTT_OFF
4715614e71bSYork Sun 	}
4725614e71bSYork Sun };
4735614e71bSYork Sun #endif
4745614e71bSYork Sun 
4755614e71bSYork Sun /*
4765614e71bSYork Sun  * Automatically seleect bank interleaving mode based on DIMMs
4775614e71bSYork Sun  * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null.
4785614e71bSYork Sun  * This function only deal with one or two slots per controller.
4795614e71bSYork Sun  */
4805614e71bSYork Sun static inline unsigned int auto_bank_intlv(dimm_params_t *pdimm)
4815614e71bSYork Sun {
4825614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
4835614e71bSYork Sun 	if (pdimm[0].n_ranks == 4)
4845614e71bSYork Sun 		return FSL_DDR_CS0_CS1_CS2_CS3;
4855614e71bSYork Sun 	else if (pdimm[0].n_ranks == 2)
4865614e71bSYork Sun 		return FSL_DDR_CS0_CS1;
4875614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
4885614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
4895614e71bSYork Sun 	if (pdimm[0].n_ranks == 4)
4905614e71bSYork Sun 		return FSL_DDR_CS0_CS1_CS2_CS3;
4915614e71bSYork Sun #endif
4925614e71bSYork Sun 	if (pdimm[0].n_ranks == 2) {
4935614e71bSYork Sun 		if (pdimm[1].n_ranks == 2)
4945614e71bSYork Sun 			return FSL_DDR_CS0_CS1_CS2_CS3;
4955614e71bSYork Sun 		else
4965614e71bSYork Sun 			return FSL_DDR_CS0_CS1;
4975614e71bSYork Sun 	}
4985614e71bSYork Sun #endif
4995614e71bSYork Sun 	return 0;
5005614e71bSYork Sun }
5015614e71bSYork Sun 
5025614e71bSYork Sun unsigned int populate_memctl_options(int all_dimms_registered,
5035614e71bSYork Sun 			memctl_options_t *popts,
5045614e71bSYork Sun 			dimm_params_t *pdimm,
5055614e71bSYork Sun 			unsigned int ctrl_num)
5065614e71bSYork Sun {
5075614e71bSYork Sun 	unsigned int i;
5085614e71bSYork Sun 	char buffer[HWCONFIG_BUFFER_SIZE];
5095614e71bSYork Sun 	char *buf = NULL;
51034e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || \
51134e026f9SYork Sun 	defined(CONFIG_SYS_FSL_DDR2) || \
51234e026f9SYork Sun 	defined(CONFIG_SYS_FSL_DDR4)
5135614e71bSYork Sun 	const struct dynamic_odt *pdodt = odt_unknown;
5145614e71bSYork Sun #endif
5155614e71bSYork Sun 	ulong ddr_freq;
5165614e71bSYork Sun 
5175614e71bSYork Sun 	/*
5185614e71bSYork Sun 	 * Extract hwconfig from environment since we have not properly setup
5195614e71bSYork Sun 	 * the environment but need it for ddr config params
5205614e71bSYork Sun 	 */
5215614e71bSYork Sun 	if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
5225614e71bSYork Sun 		buf = buffer;
5235614e71bSYork Sun 
52434e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || \
52534e026f9SYork Sun 	defined(CONFIG_SYS_FSL_DDR2) || \
52634e026f9SYork Sun 	defined(CONFIG_SYS_FSL_DDR4)
5275614e71bSYork Sun 	/* Chip select options. */
528*349689b8SYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
5295614e71bSYork Sun 	switch (pdimm[0].n_ranks) {
5305614e71bSYork Sun 	case 1:
5315614e71bSYork Sun 		pdodt = single_S;
5325614e71bSYork Sun 		break;
5335614e71bSYork Sun 	case 2:
5345614e71bSYork Sun 		pdodt = single_D;
5355614e71bSYork Sun 		break;
5365614e71bSYork Sun 	case 4:
5375614e71bSYork Sun 		pdodt = single_Q;
5385614e71bSYork Sun 		break;
5395614e71bSYork Sun 	}
540*349689b8SYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
5415614e71bSYork Sun 	switch (pdimm[0].n_ranks) {
5425614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
5435614e71bSYork Sun 	case 4:
5445614e71bSYork Sun 		pdodt = single_Q;
5455614e71bSYork Sun 		if (pdimm[1].n_ranks)
546*349689b8SYork Sun 			printf("Error: Quad- and Dual-rank DIMMs cannot be used together\n");
5475614e71bSYork Sun 		break;
5485614e71bSYork Sun #endif
5495614e71bSYork Sun 	case 2:
5505614e71bSYork Sun 		switch (pdimm[1].n_ranks) {
5515614e71bSYork Sun 		case 2:
5525614e71bSYork Sun 			pdodt = dual_DD;
5535614e71bSYork Sun 			break;
5545614e71bSYork Sun 		case 1:
5555614e71bSYork Sun 			pdodt = dual_DS;
5565614e71bSYork Sun 			break;
5575614e71bSYork Sun 		case 0:
5585614e71bSYork Sun 			pdodt = dual_D0;
5595614e71bSYork Sun 			break;
5605614e71bSYork Sun 		}
5615614e71bSYork Sun 		break;
5625614e71bSYork Sun 	case 1:
5635614e71bSYork Sun 		switch (pdimm[1].n_ranks) {
5645614e71bSYork Sun 		case 2:
5655614e71bSYork Sun 			pdodt = dual_SD;
5665614e71bSYork Sun 			break;
5675614e71bSYork Sun 		case 1:
5685614e71bSYork Sun 			pdodt = dual_SS;
5695614e71bSYork Sun 			break;
5705614e71bSYork Sun 		case 0:
5715614e71bSYork Sun 			pdodt = dual_S0;
5725614e71bSYork Sun 			break;
5735614e71bSYork Sun 		}
5745614e71bSYork Sun 		break;
5755614e71bSYork Sun 	case 0:
5765614e71bSYork Sun 		switch (pdimm[1].n_ranks) {
5775614e71bSYork Sun 		case 2:
5785614e71bSYork Sun 			pdodt = dual_0D;
5795614e71bSYork Sun 			break;
5805614e71bSYork Sun 		case 1:
5815614e71bSYork Sun 			pdodt = dual_0S;
5825614e71bSYork Sun 			break;
5835614e71bSYork Sun 		}
5845614e71bSYork Sun 		break;
5855614e71bSYork Sun 	}
586*349689b8SYork Sun #endif	/* CONFIG_DIMM_SLOTS_PER_CTLR */
587*349689b8SYork Sun #endif	/* CONFIG_SYS_FSL_DDR2, 3, 4 */
5885614e71bSYork Sun 
5895614e71bSYork Sun 	/* Pick chip-select local options. */
5905614e71bSYork Sun 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
59134e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || \
59234e026f9SYork Sun 	defined(CONFIG_SYS_FSL_DDR2) || \
59334e026f9SYork Sun 	defined(CONFIG_SYS_FSL_DDR4)
5945614e71bSYork Sun 		popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg;
5955614e71bSYork Sun 		popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg;
5965614e71bSYork Sun 		popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm;
5975614e71bSYork Sun 		popts->cs_local_opts[i].odt_rtt_wr = pdodt[i].odt_rtt_wr;
5985614e71bSYork Sun #else
5995614e71bSYork Sun 		popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
6005614e71bSYork Sun 		popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
6015614e71bSYork Sun #endif
6025614e71bSYork Sun 		popts->cs_local_opts[i].auto_precharge = 0;
6035614e71bSYork Sun 	}
6045614e71bSYork Sun 
6055614e71bSYork Sun 	/* Pick interleaving mode. */
6065614e71bSYork Sun 
6075614e71bSYork Sun 	/*
6085614e71bSYork Sun 	 * 0 = no interleaving
6095614e71bSYork Sun 	 * 1 = interleaving between 2 controllers
6105614e71bSYork Sun 	 */
6115614e71bSYork Sun 	popts->memctl_interleaving = 0;
6125614e71bSYork Sun 
6135614e71bSYork Sun 	/*
6145614e71bSYork Sun 	 * 0 = cacheline
6155614e71bSYork Sun 	 * 1 = page
6165614e71bSYork Sun 	 * 2 = (logical) bank
6175614e71bSYork Sun 	 * 3 = superbank (only if CS interleaving is enabled)
6185614e71bSYork Sun 	 */
6195614e71bSYork Sun 	popts->memctl_interleaving_mode = 0;
6205614e71bSYork Sun 
6215614e71bSYork Sun 	/*
6225614e71bSYork Sun 	 * 0: cacheline: bit 30 of the 36-bit physical addr selects the memctl
6235614e71bSYork Sun 	 * 1: page:      bit to the left of the column bits selects the memctl
6245614e71bSYork Sun 	 * 2: bank:      bit to the left of the bank bits selects the memctl
6255614e71bSYork Sun 	 * 3: superbank: bit to the left of the chip select selects the memctl
6265614e71bSYork Sun 	 *
6275614e71bSYork Sun 	 * NOTE: ba_intlv (rank interleaving) is independent of memory
6285614e71bSYork Sun 	 * controller interleaving; it is only within a memory controller.
6295614e71bSYork Sun 	 * Must use superbank interleaving if rank interleaving is used and
6305614e71bSYork Sun 	 * memory controller interleaving is enabled.
6315614e71bSYork Sun 	 */
6325614e71bSYork Sun 
6335614e71bSYork Sun 	/*
6345614e71bSYork Sun 	 * 0 = no
6355614e71bSYork Sun 	 * 0x40 = CS0,CS1
6365614e71bSYork Sun 	 * 0x20 = CS2,CS3
6375614e71bSYork Sun 	 * 0x60 = CS0,CS1 + CS2,CS3
6385614e71bSYork Sun 	 * 0x04 = CS0,CS1,CS2,CS3
6395614e71bSYork Sun 	 */
6405614e71bSYork Sun 	popts->ba_intlv_ctl = 0;
6415614e71bSYork Sun 
6425614e71bSYork Sun 	/* Memory Organization Parameters */
6435614e71bSYork Sun 	popts->registered_dimm_en = all_dimms_registered;
6445614e71bSYork Sun 
6455614e71bSYork Sun 	/* Operational Mode Paramters */
6465614e71bSYork Sun 
6475614e71bSYork Sun 	/* Pick ECC modes */
6485614e71bSYork Sun 	popts->ecc_mode = 0;		  /* 0 = disabled, 1 = enabled */
6495614e71bSYork Sun #ifdef CONFIG_DDR_ECC
6505614e71bSYork Sun 	if (hwconfig_sub_f("fsl_ddr", "ecc", buf)) {
6515614e71bSYork Sun 		if (hwconfig_subarg_cmp_f("fsl_ddr", "ecc", "on", buf))
6525614e71bSYork Sun 			popts->ecc_mode = 1;
6535614e71bSYork Sun 	} else
6545614e71bSYork Sun 		popts->ecc_mode = 1;
6555614e71bSYork Sun #endif
6565614e71bSYork Sun 	popts->ecc_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */
6575614e71bSYork Sun 
6585614e71bSYork Sun 	/*
6595614e71bSYork Sun 	 * Choose DQS config
6605614e71bSYork Sun 	 * 0 for DDR1
6615614e71bSYork Sun 	 * 1 for DDR2
6625614e71bSYork Sun 	 */
6635614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
6645614e71bSYork Sun 	popts->dqs_config = 0;
6655614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2) || defined(CONFIG_SYS_FSL_DDR3)
6665614e71bSYork Sun 	popts->dqs_config = 1;
6675614e71bSYork Sun #endif
6685614e71bSYork Sun 
6695614e71bSYork Sun 	/* Choose self-refresh during sleep. */
6705614e71bSYork Sun 	popts->self_refresh_in_sleep = 1;
6715614e71bSYork Sun 
6725614e71bSYork Sun 	/* Choose dynamic power management mode. */
6735614e71bSYork Sun 	popts->dynamic_power = 0;
6745614e71bSYork Sun 
6755614e71bSYork Sun 	/*
6765614e71bSYork Sun 	 * check first dimm for primary sdram width
6775614e71bSYork Sun 	 * presuming all dimms are similar
6785614e71bSYork Sun 	 * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
6795614e71bSYork Sun 	 */
6805614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
6815614e71bSYork Sun 	if (pdimm[0].n_ranks != 0) {
6825614e71bSYork Sun 		if ((pdimm[0].data_width >= 64) && \
6835614e71bSYork Sun 			(pdimm[0].data_width <= 72))
6845614e71bSYork Sun 			popts->data_bus_width = 0;
6855614e71bSYork Sun 		else if ((pdimm[0].data_width >= 32) || \
6865614e71bSYork Sun 			(pdimm[0].data_width <= 40))
6875614e71bSYork Sun 			popts->data_bus_width = 1;
6885614e71bSYork Sun 		else {
6895614e71bSYork Sun 			panic("Error: data width %u is invalid!\n",
6905614e71bSYork Sun 				pdimm[0].data_width);
6915614e71bSYork Sun 		}
6925614e71bSYork Sun 	}
6935614e71bSYork Sun #else
6945614e71bSYork Sun 	if (pdimm[0].n_ranks != 0) {
6955614e71bSYork Sun 		if (pdimm[0].primary_sdram_width == 64)
6965614e71bSYork Sun 			popts->data_bus_width = 0;
6975614e71bSYork Sun 		else if (pdimm[0].primary_sdram_width == 32)
6985614e71bSYork Sun 			popts->data_bus_width = 1;
6995614e71bSYork Sun 		else if (pdimm[0].primary_sdram_width == 16)
7005614e71bSYork Sun 			popts->data_bus_width = 2;
7015614e71bSYork Sun 		else {
7025614e71bSYork Sun 			panic("Error: primary sdram width %u is invalid!\n",
7035614e71bSYork Sun 				pdimm[0].primary_sdram_width);
7045614e71bSYork Sun 		}
7055614e71bSYork Sun 	}
7065614e71bSYork Sun #endif
7075614e71bSYork Sun 
7085614e71bSYork Sun 	popts->x4_en = (pdimm[0].device_width == 4) ? 1 : 0;
7095614e71bSYork Sun 
7105614e71bSYork Sun 	/* Choose burst length. */
71134e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
7125614e71bSYork Sun #if defined(CONFIG_E500MC)
7135614e71bSYork Sun 	popts->otf_burst_chop_en = 0;	/* on-the-fly burst chop disable */
7145614e71bSYork Sun 	popts->burst_length = DDR_BL8;	/* Fixed 8-beat burst len */
7155614e71bSYork Sun #else
7165614e71bSYork Sun 	if ((popts->data_bus_width == 1) || (popts->data_bus_width == 2)) {
7175614e71bSYork Sun 		/* 32-bit or 16-bit bus */
7185614e71bSYork Sun 		popts->otf_burst_chop_en = 0;
7195614e71bSYork Sun 		popts->burst_length = DDR_BL8;
7205614e71bSYork Sun 	} else {
7215614e71bSYork Sun 		popts->otf_burst_chop_en = 1;	/* on-the-fly burst chop */
7225614e71bSYork Sun 		popts->burst_length = DDR_OTF;	/* on-the-fly BC4 and BL8 */
7235614e71bSYork Sun 	}
7245614e71bSYork Sun #endif
7255614e71bSYork Sun #else
7265614e71bSYork Sun 	popts->burst_length = DDR_BL4;	/* has to be 4 for DDR2 */
7275614e71bSYork Sun #endif
7285614e71bSYork Sun 
7295614e71bSYork Sun 	/* Choose ddr controller address mirror mode */
73034e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
7315614e71bSYork Sun 	popts->mirrored_dimm = pdimm[0].mirrored_dimm;
7325614e71bSYork Sun #endif
7335614e71bSYork Sun 
7345614e71bSYork Sun 	/* Global Timing Parameters. */
7355614e71bSYork Sun 	debug("mclk_ps = %u ps\n", get_memory_clk_period_ps());
7365614e71bSYork Sun 
7375614e71bSYork Sun 	/* Pick a caslat override. */
7385614e71bSYork Sun 	popts->cas_latency_override = 0;
7395614e71bSYork Sun 	popts->cas_latency_override_value = 3;
7405614e71bSYork Sun 	if (popts->cas_latency_override) {
7415614e71bSYork Sun 		debug("using caslat override value = %u\n",
7425614e71bSYork Sun 		       popts->cas_latency_override_value);
7435614e71bSYork Sun 	}
7445614e71bSYork Sun 
7455614e71bSYork Sun 	/* Decide whether to use the computed derated latency */
7465614e71bSYork Sun 	popts->use_derated_caslat = 0;
7475614e71bSYork Sun 
7485614e71bSYork Sun 	/* Choose an additive latency. */
7495614e71bSYork Sun 	popts->additive_latency_override = 0;
7505614e71bSYork Sun 	popts->additive_latency_override_value = 3;
7515614e71bSYork Sun 	if (popts->additive_latency_override) {
7525614e71bSYork Sun 		debug("using additive latency override value = %u\n",
7535614e71bSYork Sun 		       popts->additive_latency_override_value);
7545614e71bSYork Sun 	}
7555614e71bSYork Sun 
7565614e71bSYork Sun 	/*
7575614e71bSYork Sun 	 * 2T_EN setting
7585614e71bSYork Sun 	 *
7595614e71bSYork Sun 	 * Factors to consider for 2T_EN:
7605614e71bSYork Sun 	 *	- number of DIMMs installed
7615614e71bSYork Sun 	 *	- number of components, number of active ranks
7625614e71bSYork Sun 	 *	- how much time you want to spend playing around
7635614e71bSYork Sun 	 */
7645614e71bSYork Sun 	popts->twot_en = 0;
7655614e71bSYork Sun 	popts->threet_en = 0;
7665614e71bSYork Sun 
7675614e71bSYork Sun 	/* for RDIMM, address parity enable */
7685614e71bSYork Sun 	popts->ap_en = 1;
7695614e71bSYork Sun 
7705614e71bSYork Sun 	/*
7715614e71bSYork Sun 	 * BSTTOPRE precharge interval
7725614e71bSYork Sun 	 *
7735614e71bSYork Sun 	 * Set this to 0 for global auto precharge
77434e026f9SYork Sun 	 * The value of 0x100 has been used for DDR1, DDR2, DDR3.
77534e026f9SYork Sun 	 * It is not wrong. Any value should be OK. The performance depends on
77634e026f9SYork Sun 	 * applications. There is no one good value for all.
7775614e71bSYork Sun 	 */
7785614e71bSYork Sun 	popts->bstopre = 0x100;
7795614e71bSYork Sun 
7805614e71bSYork Sun 	/* Minimum CKE pulse width -- tCKE(MIN) */
7815614e71bSYork Sun 	popts->tcke_clock_pulse_width_ps
7825614e71bSYork Sun 		= mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR);
7835614e71bSYork Sun 
7845614e71bSYork Sun 	/*
7855614e71bSYork Sun 	 * Window for four activates -- tFAW
7865614e71bSYork Sun 	 *
7875614e71bSYork Sun 	 * FIXME: UM: applies only to DDR2/DDR3 with eight logical banks only
7885614e71bSYork Sun 	 * FIXME: varies depending upon number of column addresses or data
7895614e71bSYork Sun 	 * FIXME: width, was considering looking at pdimm->primary_sdram_width
7905614e71bSYork Sun 	 */
7915614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
7925614e71bSYork Sun 	popts->tfaw_window_four_activates_ps = mclk_to_picos(1);
7935614e71bSYork Sun 
7945614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
7955614e71bSYork Sun 	/*
7965614e71bSYork Sun 	 * x4/x8;  some datasheets have 35000
7975614e71bSYork Sun 	 * x16 wide columns only?  Use 50000?
7985614e71bSYork Sun 	 */
7995614e71bSYork Sun 	popts->tfaw_window_four_activates_ps = 37500;
8005614e71bSYork Sun 
80134e026f9SYork Sun #else
8025614e71bSYork Sun 	popts->tfaw_window_four_activates_ps = pdimm[0].tfaw_ps;
8035614e71bSYork Sun #endif
8045614e71bSYork Sun 	popts->zq_en = 0;
8055614e71bSYork Sun 	popts->wrlvl_en = 0;
80634e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
8075614e71bSYork Sun 	/*
8085614e71bSYork Sun 	 * due to ddr3 dimm is fly-by topology
8095614e71bSYork Sun 	 * we suggest to enable write leveling to
8105614e71bSYork Sun 	 * meet the tQDSS under different loading.
8115614e71bSYork Sun 	 */
8125614e71bSYork Sun 	popts->wrlvl_en = 1;
8135614e71bSYork Sun 	popts->zq_en = 1;
8145614e71bSYork Sun 	popts->wrlvl_override = 0;
8155614e71bSYork Sun #endif
8165614e71bSYork Sun 
8175614e71bSYork Sun 	/*
8185614e71bSYork Sun 	 * Check interleaving configuration from environment.
8195614e71bSYork Sun 	 * Please refer to doc/README.fsl-ddr for the detail.
8205614e71bSYork Sun 	 *
8215614e71bSYork Sun 	 * If memory controller interleaving is enabled, then the data
8225614e71bSYork Sun 	 * bus widths must be programmed identically for all memory controllers.
8235614e71bSYork Sun 	 *
8246b1e1254SYork Sun 	 * Attempt to set all controllers to the same chip select
8255614e71bSYork Sun 	 * interleaving mode. It will do a best effort to get the
8265614e71bSYork Sun 	 * requested ranks interleaved together such that the result
8275614e71bSYork Sun 	 * should be a subset of the requested configuration.
8286b1e1254SYork Sun 	 *
8296b1e1254SYork Sun 	 * if CONFIG_SYS_FSL_DDR_INTLV_256B is defined, mandatory interleaving
8306b1e1254SYork Sun 	 * with 256 Byte is enabled.
8315614e71bSYork Sun 	 */
8325614e71bSYork Sun #if (CONFIG_NUM_DDR_CONTROLLERS > 1)
8335614e71bSYork Sun 	if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf))
8346b1e1254SYork Sun #ifdef CONFIG_SYS_FSL_DDR_INTLV_256B
8356b1e1254SYork Sun 		;
8366b1e1254SYork Sun #else
8375614e71bSYork Sun 		goto done;
8386b1e1254SYork Sun #endif
8395614e71bSYork Sun 	if (pdimm[0].n_ranks == 0) {
8405614e71bSYork Sun 		printf("There is no rank on CS0 for controller %d.\n", ctrl_num);
8415614e71bSYork Sun 		popts->memctl_interleaving = 0;
8425614e71bSYork Sun 		goto done;
8435614e71bSYork Sun 	}
8445614e71bSYork Sun 	popts->memctl_interleaving = 1;
8456b1e1254SYork Sun #ifdef CONFIG_SYS_FSL_DDR_INTLV_256B
8466b1e1254SYork Sun 	popts->memctl_interleaving_mode = FSL_DDR_256B_INTERLEAVING;
8476b1e1254SYork Sun 	popts->memctl_interleaving = 1;
8486b1e1254SYork Sun 	debug("256 Byte interleaving\n");
849*349689b8SYork Sun #else
8505614e71bSYork Sun 	/*
8515614e71bSYork Sun 	 * test null first. if CONFIG_HWCONFIG is not defined
8525614e71bSYork Sun 	 * hwconfig_arg_cmp returns non-zero
8535614e71bSYork Sun 	 */
8545614e71bSYork Sun 	if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv",
8555614e71bSYork Sun 				    "null", buf)) {
8565614e71bSYork Sun 		popts->memctl_interleaving = 0;
8575614e71bSYork Sun 		debug("memory controller interleaving disabled.\n");
8585614e71bSYork Sun 	} else if (hwconfig_subarg_cmp_f("fsl_ddr",
8595614e71bSYork Sun 					"ctlr_intlv",
8605614e71bSYork Sun 					"cacheline", buf)) {
8615614e71bSYork Sun 		popts->memctl_interleaving_mode =
8625614e71bSYork Sun 			((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
8635614e71bSYork Sun 			0 : FSL_DDR_CACHE_LINE_INTERLEAVING;
8645614e71bSYork Sun 		popts->memctl_interleaving =
8655614e71bSYork Sun 			((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
8665614e71bSYork Sun 			0 : 1;
8675614e71bSYork Sun 	} else if (hwconfig_subarg_cmp_f("fsl_ddr",
8685614e71bSYork Sun 					"ctlr_intlv",
8695614e71bSYork Sun 					"page", buf)) {
8705614e71bSYork Sun 		popts->memctl_interleaving_mode =
8715614e71bSYork Sun 			((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
8725614e71bSYork Sun 			0 : FSL_DDR_PAGE_INTERLEAVING;
8735614e71bSYork Sun 		popts->memctl_interleaving =
8745614e71bSYork Sun 			((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
8755614e71bSYork Sun 			0 : 1;
8765614e71bSYork Sun 	} else if (hwconfig_subarg_cmp_f("fsl_ddr",
8775614e71bSYork Sun 					"ctlr_intlv",
8785614e71bSYork Sun 					"bank", buf)) {
8795614e71bSYork Sun 		popts->memctl_interleaving_mode =
8805614e71bSYork Sun 			((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
8815614e71bSYork Sun 			0 : FSL_DDR_BANK_INTERLEAVING;
8825614e71bSYork Sun 		popts->memctl_interleaving =
8835614e71bSYork Sun 			((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
8845614e71bSYork Sun 			0 : 1;
8855614e71bSYork Sun 	} else if (hwconfig_subarg_cmp_f("fsl_ddr",
8865614e71bSYork Sun 					"ctlr_intlv",
8875614e71bSYork Sun 					"superbank", buf)) {
8885614e71bSYork Sun 		popts->memctl_interleaving_mode =
8895614e71bSYork Sun 			((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
8905614e71bSYork Sun 			0 : FSL_DDR_SUPERBANK_INTERLEAVING;
8915614e71bSYork Sun 		popts->memctl_interleaving =
8925614e71bSYork Sun 			((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
8935614e71bSYork Sun 			0 : 1;
8945614e71bSYork Sun #if (CONFIG_NUM_DDR_CONTROLLERS == 3)
8955614e71bSYork Sun 	} else if (hwconfig_subarg_cmp_f("fsl_ddr",
8965614e71bSYork Sun 					"ctlr_intlv",
8975614e71bSYork Sun 					"3way_1KB", buf)) {
8985614e71bSYork Sun 		popts->memctl_interleaving_mode =
8995614e71bSYork Sun 			FSL_DDR_3WAY_1KB_INTERLEAVING;
9005614e71bSYork Sun 	} else if (hwconfig_subarg_cmp_f("fsl_ddr",
9015614e71bSYork Sun 					"ctlr_intlv",
9025614e71bSYork Sun 					"3way_4KB", buf)) {
9035614e71bSYork Sun 		popts->memctl_interleaving_mode =
9045614e71bSYork Sun 			FSL_DDR_3WAY_4KB_INTERLEAVING;
9055614e71bSYork Sun 	} else if (hwconfig_subarg_cmp_f("fsl_ddr",
9065614e71bSYork Sun 					"ctlr_intlv",
9075614e71bSYork Sun 					"3way_8KB", buf)) {
9085614e71bSYork Sun 		popts->memctl_interleaving_mode =
9095614e71bSYork Sun 			FSL_DDR_3WAY_8KB_INTERLEAVING;
9105614e71bSYork Sun #elif (CONFIG_NUM_DDR_CONTROLLERS == 4)
9115614e71bSYork Sun 	} else if (hwconfig_subarg_cmp_f("fsl_ddr",
9125614e71bSYork Sun 					"ctlr_intlv",
9135614e71bSYork Sun 					"4way_1KB", buf)) {
9145614e71bSYork Sun 		popts->memctl_interleaving_mode =
9155614e71bSYork Sun 			FSL_DDR_4WAY_1KB_INTERLEAVING;
9165614e71bSYork Sun 	} else if (hwconfig_subarg_cmp_f("fsl_ddr",
9175614e71bSYork Sun 					"ctlr_intlv",
9185614e71bSYork Sun 					"4way_4KB", buf)) {
9195614e71bSYork Sun 		popts->memctl_interleaving_mode =
9205614e71bSYork Sun 			FSL_DDR_4WAY_4KB_INTERLEAVING;
9215614e71bSYork Sun 	} else if (hwconfig_subarg_cmp_f("fsl_ddr",
9225614e71bSYork Sun 					"ctlr_intlv",
9235614e71bSYork Sun 					"4way_8KB", buf)) {
9245614e71bSYork Sun 		popts->memctl_interleaving_mode =
9255614e71bSYork Sun 			FSL_DDR_4WAY_8KB_INTERLEAVING;
9265614e71bSYork Sun #endif
9275614e71bSYork Sun 	} else {
9285614e71bSYork Sun 		popts->memctl_interleaving = 0;
9295614e71bSYork Sun 		printf("hwconfig has unrecognized parameter for ctlr_intlv.\n");
9305614e71bSYork Sun 	}
931*349689b8SYork Sun #endif	/* CONFIG_SYS_FSL_DDR_INTLV_256B */
9325614e71bSYork Sun done:
933*349689b8SYork Sun #endif /* CONFIG_NUM_DDR_CONTROLLERS > 1 */
9345614e71bSYork Sun 	if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) &&
9355614e71bSYork Sun 		(CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
9365614e71bSYork Sun 		/* test null first. if CONFIG_HWCONFIG is not defined,
9375614e71bSYork Sun 		 * hwconfig_subarg_cmp_f returns non-zero */
9385614e71bSYork Sun 		if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
9395614e71bSYork Sun 					    "null", buf))
9405614e71bSYork Sun 			debug("bank interleaving disabled.\n");
9415614e71bSYork Sun 		else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
9425614e71bSYork Sun 						 "cs0_cs1", buf))
9435614e71bSYork Sun 			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1;
9445614e71bSYork Sun 		else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
9455614e71bSYork Sun 						 "cs2_cs3", buf))
9465614e71bSYork Sun 			popts->ba_intlv_ctl = FSL_DDR_CS2_CS3;
9475614e71bSYork Sun 		else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
9485614e71bSYork Sun 						 "cs0_cs1_and_cs2_cs3", buf))
9495614e71bSYork Sun 			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3;
9505614e71bSYork Sun 		else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
9515614e71bSYork Sun 						 "cs0_cs1_cs2_cs3", buf))
9525614e71bSYork Sun 			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3;
9535614e71bSYork Sun 		else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
9545614e71bSYork Sun 						"auto", buf))
9555614e71bSYork Sun 			popts->ba_intlv_ctl = auto_bank_intlv(pdimm);
9565614e71bSYork Sun 		else
9575614e71bSYork Sun 			printf("hwconfig has unrecognized parameter for bank_intlv.\n");
9585614e71bSYork Sun 		switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
9595614e71bSYork Sun 		case FSL_DDR_CS0_CS1_CS2_CS3:
9605614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
9615614e71bSYork Sun 			if (pdimm[0].n_ranks < 4) {
9625614e71bSYork Sun 				popts->ba_intlv_ctl = 0;
9635614e71bSYork Sun 				printf("Not enough bank(chip-select) for "
9645614e71bSYork Sun 					"CS0+CS1+CS2+CS3 on controller %d, "
9655614e71bSYork Sun 					"interleaving disabled!\n", ctrl_num);
9665614e71bSYork Sun 			}
9675614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
9685614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
9695614e71bSYork Sun 			if (pdimm[0].n_ranks == 4)
9705614e71bSYork Sun 				break;
9715614e71bSYork Sun #endif
9725614e71bSYork Sun 			if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) {
9735614e71bSYork Sun 				popts->ba_intlv_ctl = 0;
9745614e71bSYork Sun 				printf("Not enough bank(chip-select) for "
9755614e71bSYork Sun 					"CS0+CS1+CS2+CS3 on controller %d, "
9765614e71bSYork Sun 					"interleaving disabled!\n", ctrl_num);
9775614e71bSYork Sun 			}
9785614e71bSYork Sun 			if (pdimm[0].capacity != pdimm[1].capacity) {
9795614e71bSYork Sun 				popts->ba_intlv_ctl = 0;
9805614e71bSYork Sun 				printf("Not identical DIMM size for "
9815614e71bSYork Sun 					"CS0+CS1+CS2+CS3 on controller %d, "
9825614e71bSYork Sun 					"interleaving disabled!\n", ctrl_num);
9835614e71bSYork Sun 			}
9845614e71bSYork Sun #endif
9855614e71bSYork Sun 			break;
9865614e71bSYork Sun 		case FSL_DDR_CS0_CS1:
9875614e71bSYork Sun 			if (pdimm[0].n_ranks < 2) {
9885614e71bSYork Sun 				popts->ba_intlv_ctl = 0;
9895614e71bSYork Sun 				printf("Not enough bank(chip-select) for "
9905614e71bSYork Sun 					"CS0+CS1 on controller %d, "
9915614e71bSYork Sun 					"interleaving disabled!\n", ctrl_num);
9925614e71bSYork Sun 			}
9935614e71bSYork Sun 			break;
9945614e71bSYork Sun 		case FSL_DDR_CS2_CS3:
9955614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
9965614e71bSYork Sun 			if (pdimm[0].n_ranks < 4) {
9975614e71bSYork Sun 				popts->ba_intlv_ctl = 0;
9985614e71bSYork Sun 				printf("Not enough bank(chip-select) for CS2+CS3 "
9995614e71bSYork Sun 					"on controller %d, interleaving disabled!\n", ctrl_num);
10005614e71bSYork Sun 			}
10015614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
10025614e71bSYork Sun 			if (pdimm[1].n_ranks < 2) {
10035614e71bSYork Sun 				popts->ba_intlv_ctl = 0;
10045614e71bSYork Sun 				printf("Not enough bank(chip-select) for CS2+CS3 "
10055614e71bSYork Sun 					"on controller %d, interleaving disabled!\n", ctrl_num);
10065614e71bSYork Sun 			}
10075614e71bSYork Sun #endif
10085614e71bSYork Sun 			break;
10095614e71bSYork Sun 		case FSL_DDR_CS0_CS1_AND_CS2_CS3:
10105614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
10115614e71bSYork Sun 			if (pdimm[0].n_ranks < 4) {
10125614e71bSYork Sun 				popts->ba_intlv_ctl = 0;
10135614e71bSYork Sun 				printf("Not enough bank(CS) for CS0+CS1 and "
10145614e71bSYork Sun 					"CS2+CS3 on controller %d, "
10155614e71bSYork Sun 					"interleaving disabled!\n", ctrl_num);
10165614e71bSYork Sun 			}
10175614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
10185614e71bSYork Sun 			if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) {
10195614e71bSYork Sun 				popts->ba_intlv_ctl = 0;
10205614e71bSYork Sun 				printf("Not enough bank(CS) for CS0+CS1 and "
10215614e71bSYork Sun 					"CS2+CS3 on controller %d, "
10225614e71bSYork Sun 					"interleaving disabled!\n", ctrl_num);
10235614e71bSYork Sun 			}
10245614e71bSYork Sun #endif
10255614e71bSYork Sun 			break;
10265614e71bSYork Sun 		default:
10275614e71bSYork Sun 			popts->ba_intlv_ctl = 0;
10285614e71bSYork Sun 			break;
10295614e71bSYork Sun 		}
10305614e71bSYork Sun 	}
10315614e71bSYork Sun 
10325614e71bSYork Sun 	if (hwconfig_sub_f("fsl_ddr", "addr_hash", buf)) {
10335614e71bSYork Sun 		if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", "null", buf))
10345614e71bSYork Sun 			popts->addr_hash = 0;
10355614e71bSYork Sun 		else if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash",
10365614e71bSYork Sun 					       "true", buf))
10375614e71bSYork Sun 			popts->addr_hash = 1;
10385614e71bSYork Sun 	}
10395614e71bSYork Sun 
10405614e71bSYork Sun 	if (pdimm[0].n_ranks == 4)
10415614e71bSYork Sun 		popts->quad_rank_present = 1;
10425614e71bSYork Sun 
10435614e71bSYork Sun 	ddr_freq = get_ddr_freq(0) / 1000000;
10445614e71bSYork Sun 	if (popts->registered_dimm_en) {
10455614e71bSYork Sun 		popts->rcw_override = 1;
10465614e71bSYork Sun 		popts->rcw_1 = 0x000a5a00;
10475614e71bSYork Sun 		if (ddr_freq <= 800)
10485614e71bSYork Sun 			popts->rcw_2 = 0x00000000;
10495614e71bSYork Sun 		else if (ddr_freq <= 1066)
10505614e71bSYork Sun 			popts->rcw_2 = 0x00100000;
10515614e71bSYork Sun 		else if (ddr_freq <= 1333)
10525614e71bSYork Sun 			popts->rcw_2 = 0x00200000;
10535614e71bSYork Sun 		else
10545614e71bSYork Sun 			popts->rcw_2 = 0x00300000;
10555614e71bSYork Sun 	}
10565614e71bSYork Sun 
10575614e71bSYork Sun 	fsl_ddr_board_options(popts, pdimm, ctrl_num);
10585614e71bSYork Sun 
10595614e71bSYork Sun 	return 0;
10605614e71bSYork Sun }
10615614e71bSYork Sun 
10625614e71bSYork Sun void check_interleaving_options(fsl_ddr_info_t *pinfo)
10635614e71bSYork Sun {
10645614e71bSYork Sun 	int i, j, k, check_n_ranks, intlv_invalid = 0;
10655614e71bSYork Sun 	unsigned int check_intlv, check_n_row_addr, check_n_col_addr;
10665614e71bSYork Sun 	unsigned long long check_rank_density;
10675614e71bSYork Sun 	struct dimm_params_s *dimm;
10685614e71bSYork Sun 	/*
10695614e71bSYork Sun 	 * Check if all controllers are configured for memory
10705614e71bSYork Sun 	 * controller interleaving. Identical dimms are recommended. At least
10715614e71bSYork Sun 	 * the size, row and col address should be checked.
10725614e71bSYork Sun 	 */
10735614e71bSYork Sun 	j = 0;
10745614e71bSYork Sun 	check_n_ranks = pinfo->dimm_params[0][0].n_ranks;
10755614e71bSYork Sun 	check_rank_density = pinfo->dimm_params[0][0].rank_density;
10765614e71bSYork Sun 	check_n_row_addr =  pinfo->dimm_params[0][0].n_row_addr;
10775614e71bSYork Sun 	check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr;
10785614e71bSYork Sun 	check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode;
10795614e71bSYork Sun 	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
10805614e71bSYork Sun 		dimm = &pinfo->dimm_params[i][0];
10815614e71bSYork Sun 		if (!pinfo->memctl_opts[i].memctl_interleaving) {
10825614e71bSYork Sun 			continue;
10835614e71bSYork Sun 		} else if (((check_rank_density != dimm->rank_density) ||
10845614e71bSYork Sun 		     (check_n_ranks != dimm->n_ranks) ||
10855614e71bSYork Sun 		     (check_n_row_addr != dimm->n_row_addr) ||
10865614e71bSYork Sun 		     (check_n_col_addr != dimm->n_col_addr) ||
10875614e71bSYork Sun 		     (check_intlv !=
10885614e71bSYork Sun 			pinfo->memctl_opts[i].memctl_interleaving_mode))){
10895614e71bSYork Sun 			intlv_invalid = 1;
10905614e71bSYork Sun 			break;
10915614e71bSYork Sun 		} else {
10925614e71bSYork Sun 			j++;
10935614e71bSYork Sun 		}
10945614e71bSYork Sun 
10955614e71bSYork Sun 	}
10965614e71bSYork Sun 	if (intlv_invalid) {
10975614e71bSYork Sun 		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
10985614e71bSYork Sun 			pinfo->memctl_opts[i].memctl_interleaving = 0;
10995614e71bSYork Sun 		printf("Not all DIMMs are identical. "
11005614e71bSYork Sun 			"Memory controller interleaving disabled.\n");
11015614e71bSYork Sun 	} else {
11025614e71bSYork Sun 		switch (check_intlv) {
11036b1e1254SYork Sun 		case FSL_DDR_256B_INTERLEAVING:
11045614e71bSYork Sun 		case FSL_DDR_CACHE_LINE_INTERLEAVING:
11055614e71bSYork Sun 		case FSL_DDR_PAGE_INTERLEAVING:
11065614e71bSYork Sun 		case FSL_DDR_BANK_INTERLEAVING:
11075614e71bSYork Sun 		case FSL_DDR_SUPERBANK_INTERLEAVING:
1108*349689b8SYork Sun #if (3 == CONFIG_NUM_DDR_CONTROLLERS)
11095614e71bSYork Sun 				k = 2;
1110*349689b8SYork Sun #else
11115614e71bSYork Sun 				k = CONFIG_NUM_DDR_CONTROLLERS;
1112*349689b8SYork Sun #endif
11135614e71bSYork Sun 			break;
11145614e71bSYork Sun 		case FSL_DDR_3WAY_1KB_INTERLEAVING:
11155614e71bSYork Sun 		case FSL_DDR_3WAY_4KB_INTERLEAVING:
11165614e71bSYork Sun 		case FSL_DDR_3WAY_8KB_INTERLEAVING:
11175614e71bSYork Sun 		case FSL_DDR_4WAY_1KB_INTERLEAVING:
11185614e71bSYork Sun 		case FSL_DDR_4WAY_4KB_INTERLEAVING:
11195614e71bSYork Sun 		case FSL_DDR_4WAY_8KB_INTERLEAVING:
11205614e71bSYork Sun 		default:
11215614e71bSYork Sun 			k = CONFIG_NUM_DDR_CONTROLLERS;
11225614e71bSYork Sun 			break;
11235614e71bSYork Sun 		}
11245614e71bSYork Sun 		debug("%d of %d controllers are interleaving.\n", j, k);
11255614e71bSYork Sun 		if (j && (j != k)) {
11265614e71bSYork Sun 			for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
11275614e71bSYork Sun 				pinfo->memctl_opts[i].memctl_interleaving = 0;
11285614e71bSYork Sun 			printf("Not all controllers have compatible "
11295614e71bSYork Sun 				"interleaving mode. All disabled.\n");
11305614e71bSYork Sun 		}
11315614e71bSYork Sun 	}
11325614e71bSYork Sun 	debug("Checking interleaving options completed\n");
11335614e71bSYork Sun }
11345614e71bSYork Sun 
11355614e71bSYork Sun int fsl_use_spd(void)
11365614e71bSYork Sun {
11375614e71bSYork Sun 	int use_spd = 0;
11385614e71bSYork Sun 
11395614e71bSYork Sun #ifdef CONFIG_DDR_SPD
11405614e71bSYork Sun 	char buffer[HWCONFIG_BUFFER_SIZE];
11415614e71bSYork Sun 	char *buf = NULL;
11425614e71bSYork Sun 
11435614e71bSYork Sun 	/*
11445614e71bSYork Sun 	 * Extract hwconfig from environment since we have not properly setup
11455614e71bSYork Sun 	 * the environment but need it for ddr config params
11465614e71bSYork Sun 	 */
11475614e71bSYork Sun 	if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
11485614e71bSYork Sun 		buf = buffer;
11495614e71bSYork Sun 
11505614e71bSYork Sun 	/* if hwconfig is not enabled, or "sdram" is not defined, use spd */
11515614e71bSYork Sun 	if (hwconfig_sub_f("fsl_ddr", "sdram", buf)) {
11525614e71bSYork Sun 		if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", "spd", buf))
11535614e71bSYork Sun 			use_spd = 1;
11545614e71bSYork Sun 		else if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram",
11555614e71bSYork Sun 					       "fixed", buf))
11565614e71bSYork Sun 			use_spd = 0;
11575614e71bSYork Sun 		else
11585614e71bSYork Sun 			use_spd = 1;
11595614e71bSYork Sun 	} else
11605614e71bSYork Sun 		use_spd = 1;
11615614e71bSYork Sun #endif
11625614e71bSYork Sun 
11635614e71bSYork Sun 	return use_spd;
11645614e71bSYork Sun }
1165