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>
12457e51cfSSimon Glass #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \
13457e51cfSSimon Glass defined(CONFIG_ARM)
146e2941d7SSimon Glass #include <asm/arch/clock.h>
156e2941d7SSimon Glass #endif
165614e71bSYork Sun
175614e71bSYork Sun /*
185614e71bSYork Sun * Use our own stack based buffer before relocation to allow accessing longer
195614e71bSYork Sun * hwconfig strings that might be in the environment before we've relocated.
205614e71bSYork Sun * This is pretty fragile on both the use of stack and if the buffer is big
21*00caae6dSSimon Glass * enough. However we will get a warning from env_get_f() for the latter.
225614e71bSYork Sun */
235614e71bSYork Sun
245614e71bSYork Sun /* Board-specific functions defined in each board's ddr.c */
255614e71bSYork Sun extern void fsl_ddr_board_options(memctl_options_t *popts,
265614e71bSYork Sun dimm_params_t *pdimm,
275614e71bSYork Sun unsigned int ctrl_num);
285614e71bSYork Sun
295614e71bSYork Sun struct dynamic_odt {
305614e71bSYork Sun unsigned int odt_rd_cfg;
315614e71bSYork Sun unsigned int odt_wr_cfg;
325614e71bSYork Sun unsigned int odt_rtt_norm;
335614e71bSYork Sun unsigned int odt_rtt_wr;
345614e71bSYork Sun };
355614e71bSYork Sun
3619601dd9SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
3719601dd9SYork Sun /* Quad rank is not verified yet due availability.
3819601dd9SYork Sun * Replacing 20 OHM with 34 OHM since DDR4 doesn't have 20 OHM option
3919601dd9SYork Sun */
4097fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt single_Q[4] = {
4119601dd9SYork Sun { /* cs0 */
4219601dd9SYork Sun FSL_DDR_ODT_NEVER,
4319601dd9SYork Sun FSL_DDR_ODT_CS_AND_OTHER_DIMM,
4419601dd9SYork Sun DDR4_RTT_34_OHM, /* unverified */
4519601dd9SYork Sun DDR4_RTT_120_OHM
4619601dd9SYork Sun },
4719601dd9SYork Sun { /* cs1 */
4819601dd9SYork Sun FSL_DDR_ODT_NEVER,
4919601dd9SYork Sun FSL_DDR_ODT_NEVER,
5019601dd9SYork Sun DDR4_RTT_OFF,
5119601dd9SYork Sun DDR4_RTT_120_OHM
5219601dd9SYork Sun },
5319601dd9SYork Sun { /* cs2 */
5419601dd9SYork Sun FSL_DDR_ODT_NEVER,
5519601dd9SYork Sun FSL_DDR_ODT_CS_AND_OTHER_DIMM,
5619601dd9SYork Sun DDR4_RTT_34_OHM,
5719601dd9SYork Sun DDR4_RTT_120_OHM
5819601dd9SYork Sun },
5919601dd9SYork Sun { /* cs3 */
6019601dd9SYork Sun FSL_DDR_ODT_NEVER,
6119601dd9SYork Sun FSL_DDR_ODT_NEVER, /* tied high */
6219601dd9SYork Sun DDR4_RTT_OFF,
6319601dd9SYork Sun DDR4_RTT_120_OHM
6419601dd9SYork Sun }
6519601dd9SYork Sun };
6619601dd9SYork Sun
6797fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt single_D[4] = {
6819601dd9SYork Sun { /* cs0 */
6919601dd9SYork Sun FSL_DDR_ODT_NEVER,
7019601dd9SYork Sun FSL_DDR_ODT_ALL,
7119601dd9SYork Sun DDR4_RTT_40_OHM,
7219601dd9SYork Sun DDR4_RTT_OFF
7319601dd9SYork Sun },
7419601dd9SYork Sun { /* cs1 */
7519601dd9SYork Sun FSL_DDR_ODT_NEVER,
7619601dd9SYork Sun FSL_DDR_ODT_NEVER,
7719601dd9SYork Sun DDR4_RTT_OFF,
7819601dd9SYork Sun DDR4_RTT_OFF
7919601dd9SYork Sun },
8019601dd9SYork Sun {0, 0, 0, 0},
8119601dd9SYork Sun {0, 0, 0, 0}
8219601dd9SYork Sun };
8319601dd9SYork Sun
8497fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt single_S[4] = {
8519601dd9SYork Sun { /* cs0 */
8619601dd9SYork Sun FSL_DDR_ODT_NEVER,
8719601dd9SYork Sun FSL_DDR_ODT_ALL,
8819601dd9SYork Sun DDR4_RTT_40_OHM,
8919601dd9SYork Sun DDR4_RTT_OFF
9019601dd9SYork Sun },
9119601dd9SYork Sun {0, 0, 0, 0},
9219601dd9SYork Sun {0, 0, 0, 0},
9319601dd9SYork Sun {0, 0, 0, 0},
9419601dd9SYork Sun };
9519601dd9SYork Sun
9697fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_DD[4] = {
9719601dd9SYork Sun { /* cs0 */
9819601dd9SYork Sun FSL_DDR_ODT_NEVER,
9919601dd9SYork Sun FSL_DDR_ODT_SAME_DIMM,
10019601dd9SYork Sun DDR4_RTT_120_OHM,
10119601dd9SYork Sun DDR4_RTT_OFF
10219601dd9SYork Sun },
10319601dd9SYork Sun { /* cs1 */
10419601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
10519601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
10619601dd9SYork Sun DDR4_RTT_34_OHM,
10719601dd9SYork Sun DDR4_RTT_OFF
10819601dd9SYork Sun },
10919601dd9SYork Sun { /* cs2 */
11019601dd9SYork Sun FSL_DDR_ODT_NEVER,
11119601dd9SYork Sun FSL_DDR_ODT_SAME_DIMM,
11219601dd9SYork Sun DDR4_RTT_120_OHM,
11319601dd9SYork Sun DDR4_RTT_OFF
11419601dd9SYork Sun },
11519601dd9SYork Sun { /* cs3 */
11619601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
11719601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
11819601dd9SYork Sun DDR4_RTT_34_OHM,
11919601dd9SYork Sun DDR4_RTT_OFF
12019601dd9SYork Sun }
12119601dd9SYork Sun };
12219601dd9SYork Sun
12397fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_DS[4] = {
12419601dd9SYork Sun { /* cs0 */
12519601dd9SYork Sun FSL_DDR_ODT_NEVER,
12619601dd9SYork Sun FSL_DDR_ODT_SAME_DIMM,
12719601dd9SYork Sun DDR4_RTT_120_OHM,
12819601dd9SYork Sun DDR4_RTT_OFF
12919601dd9SYork Sun },
13019601dd9SYork Sun { /* cs1 */
13119601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
13219601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
13319601dd9SYork Sun DDR4_RTT_34_OHM,
13419601dd9SYork Sun DDR4_RTT_OFF
13519601dd9SYork Sun },
13619601dd9SYork Sun { /* cs2 */
13719601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
13819601dd9SYork Sun FSL_DDR_ODT_ALL,
13919601dd9SYork Sun DDR4_RTT_34_OHM,
14019601dd9SYork Sun DDR4_RTT_120_OHM
14119601dd9SYork Sun },
14219601dd9SYork Sun {0, 0, 0, 0}
14319601dd9SYork Sun };
14497fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_SD[4] = {
14519601dd9SYork Sun { /* cs0 */
14619601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
14719601dd9SYork Sun FSL_DDR_ODT_ALL,
14819601dd9SYork Sun DDR4_RTT_34_OHM,
14919601dd9SYork Sun DDR4_RTT_120_OHM
15019601dd9SYork Sun },
15119601dd9SYork Sun {0, 0, 0, 0},
15219601dd9SYork Sun { /* cs2 */
15319601dd9SYork Sun FSL_DDR_ODT_NEVER,
15419601dd9SYork Sun FSL_DDR_ODT_SAME_DIMM,
15519601dd9SYork Sun DDR4_RTT_120_OHM,
15619601dd9SYork Sun DDR4_RTT_OFF
15719601dd9SYork Sun },
15819601dd9SYork Sun { /* cs3 */
15919601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
16019601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
16119601dd9SYork Sun DDR4_RTT_34_OHM,
16219601dd9SYork Sun DDR4_RTT_OFF
16319601dd9SYork Sun }
16419601dd9SYork Sun };
16519601dd9SYork Sun
16697fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_SS[4] = {
16719601dd9SYork Sun { /* cs0 */
16819601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
16919601dd9SYork Sun FSL_DDR_ODT_ALL,
17019601dd9SYork Sun DDR4_RTT_34_OHM,
17119601dd9SYork Sun DDR4_RTT_120_OHM
17219601dd9SYork Sun },
17319601dd9SYork Sun {0, 0, 0, 0},
17419601dd9SYork Sun { /* cs2 */
17519601dd9SYork Sun FSL_DDR_ODT_OTHER_DIMM,
17619601dd9SYork Sun FSL_DDR_ODT_ALL,
17719601dd9SYork Sun DDR4_RTT_34_OHM,
17819601dd9SYork Sun DDR4_RTT_120_OHM
17919601dd9SYork Sun },
18019601dd9SYork Sun {0, 0, 0, 0}
18119601dd9SYork Sun };
18219601dd9SYork Sun
18397fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_D0[4] = {
18419601dd9SYork Sun { /* cs0 */
18519601dd9SYork Sun FSL_DDR_ODT_NEVER,
18619601dd9SYork Sun FSL_DDR_ODT_SAME_DIMM,
18719601dd9SYork Sun DDR4_RTT_40_OHM,
18819601dd9SYork Sun DDR4_RTT_OFF
18919601dd9SYork Sun },
19019601dd9SYork Sun { /* cs1 */
19119601dd9SYork Sun FSL_DDR_ODT_NEVER,
19219601dd9SYork Sun FSL_DDR_ODT_NEVER,
19319601dd9SYork Sun DDR4_RTT_OFF,
19419601dd9SYork Sun DDR4_RTT_OFF
19519601dd9SYork Sun },
19619601dd9SYork Sun {0, 0, 0, 0},
19719601dd9SYork Sun {0, 0, 0, 0}
19819601dd9SYork Sun };
19919601dd9SYork Sun
20097fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_0D[4] = {
20119601dd9SYork Sun {0, 0, 0, 0},
20219601dd9SYork Sun {0, 0, 0, 0},
20319601dd9SYork Sun { /* cs2 */
20419601dd9SYork Sun FSL_DDR_ODT_NEVER,
20519601dd9SYork Sun FSL_DDR_ODT_SAME_DIMM,
20619601dd9SYork Sun DDR4_RTT_40_OHM,
20719601dd9SYork Sun DDR4_RTT_OFF
20819601dd9SYork Sun },
20919601dd9SYork Sun { /* cs3 */
21019601dd9SYork Sun FSL_DDR_ODT_NEVER,
21119601dd9SYork Sun FSL_DDR_ODT_NEVER,
21219601dd9SYork Sun DDR4_RTT_OFF,
21319601dd9SYork Sun DDR4_RTT_OFF
21419601dd9SYork Sun }
21519601dd9SYork Sun };
21619601dd9SYork Sun
21797fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_S0[4] = {
21819601dd9SYork Sun { /* cs0 */
21919601dd9SYork Sun FSL_DDR_ODT_NEVER,
22019601dd9SYork Sun FSL_DDR_ODT_CS,
22119601dd9SYork Sun DDR4_RTT_40_OHM,
22219601dd9SYork Sun DDR4_RTT_OFF
22319601dd9SYork Sun },
22419601dd9SYork Sun {0, 0, 0, 0},
22519601dd9SYork Sun {0, 0, 0, 0},
22619601dd9SYork Sun {0, 0, 0, 0}
22719601dd9SYork Sun
22819601dd9SYork Sun };
22919601dd9SYork Sun
23097fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_0S[4] = {
23119601dd9SYork Sun {0, 0, 0, 0},
23219601dd9SYork Sun {0, 0, 0, 0},
23319601dd9SYork Sun { /* cs2 */
23419601dd9SYork Sun FSL_DDR_ODT_NEVER,
23519601dd9SYork Sun FSL_DDR_ODT_CS,
23619601dd9SYork Sun DDR4_RTT_40_OHM,
23719601dd9SYork Sun DDR4_RTT_OFF
23819601dd9SYork Sun },
23919601dd9SYork Sun {0, 0, 0, 0}
24019601dd9SYork Sun
24119601dd9SYork Sun };
24219601dd9SYork Sun
24397fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt odt_unknown[4] = {
24419601dd9SYork Sun { /* cs0 */
24519601dd9SYork Sun FSL_DDR_ODT_NEVER,
24619601dd9SYork Sun FSL_DDR_ODT_CS,
24719601dd9SYork Sun DDR4_RTT_120_OHM,
24819601dd9SYork Sun DDR4_RTT_OFF
24919601dd9SYork Sun },
25019601dd9SYork Sun { /* cs1 */
25119601dd9SYork Sun FSL_DDR_ODT_NEVER,
25219601dd9SYork Sun FSL_DDR_ODT_CS,
25319601dd9SYork Sun DDR4_RTT_120_OHM,
25419601dd9SYork Sun DDR4_RTT_OFF
25519601dd9SYork Sun },
25619601dd9SYork Sun { /* cs2 */
25719601dd9SYork Sun FSL_DDR_ODT_NEVER,
25819601dd9SYork Sun FSL_DDR_ODT_CS,
25919601dd9SYork Sun DDR4_RTT_120_OHM,
26019601dd9SYork Sun DDR4_RTT_OFF
26119601dd9SYork Sun },
26219601dd9SYork Sun { /* cs3 */
26319601dd9SYork Sun FSL_DDR_ODT_NEVER,
26419601dd9SYork Sun FSL_DDR_ODT_CS,
26519601dd9SYork Sun DDR4_RTT_120_OHM,
26619601dd9SYork Sun DDR4_RTT_OFF
26719601dd9SYork Sun }
26819601dd9SYork Sun };
26919601dd9SYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
27097fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt single_Q[4] = {
2715614e71bSYork Sun { /* cs0 */
2725614e71bSYork Sun FSL_DDR_ODT_NEVER,
2735614e71bSYork Sun FSL_DDR_ODT_CS_AND_OTHER_DIMM,
2745614e71bSYork Sun DDR3_RTT_20_OHM,
2755614e71bSYork Sun DDR3_RTT_120_OHM
2765614e71bSYork Sun },
2775614e71bSYork Sun { /* cs1 */
2785614e71bSYork Sun FSL_DDR_ODT_NEVER,
2795614e71bSYork Sun FSL_DDR_ODT_NEVER, /* tied high */
2805614e71bSYork Sun DDR3_RTT_OFF,
2815614e71bSYork Sun DDR3_RTT_120_OHM
2825614e71bSYork Sun },
2835614e71bSYork Sun { /* cs2 */
2845614e71bSYork Sun FSL_DDR_ODT_NEVER,
2855614e71bSYork Sun FSL_DDR_ODT_CS_AND_OTHER_DIMM,
2865614e71bSYork Sun DDR3_RTT_20_OHM,
2875614e71bSYork Sun DDR3_RTT_120_OHM
2885614e71bSYork Sun },
2895614e71bSYork Sun { /* cs3 */
2905614e71bSYork Sun FSL_DDR_ODT_NEVER,
2915614e71bSYork Sun FSL_DDR_ODT_NEVER, /* tied high */
2925614e71bSYork Sun DDR3_RTT_OFF,
2935614e71bSYork Sun DDR3_RTT_120_OHM
2945614e71bSYork Sun }
2955614e71bSYork Sun };
2965614e71bSYork Sun
29797fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt single_D[4] = {
2985614e71bSYork Sun { /* cs0 */
2995614e71bSYork Sun FSL_DDR_ODT_NEVER,
3005614e71bSYork Sun FSL_DDR_ODT_ALL,
3015614e71bSYork Sun DDR3_RTT_40_OHM,
3025614e71bSYork Sun DDR3_RTT_OFF
3035614e71bSYork Sun },
3045614e71bSYork Sun { /* cs1 */
3055614e71bSYork Sun FSL_DDR_ODT_NEVER,
3065614e71bSYork Sun FSL_DDR_ODT_NEVER,
3075614e71bSYork Sun DDR3_RTT_OFF,
3085614e71bSYork Sun DDR3_RTT_OFF
3095614e71bSYork Sun },
3105614e71bSYork Sun {0, 0, 0, 0},
3115614e71bSYork Sun {0, 0, 0, 0}
3125614e71bSYork Sun };
3135614e71bSYork Sun
31497fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt single_S[4] = {
3155614e71bSYork Sun { /* cs0 */
3165614e71bSYork Sun FSL_DDR_ODT_NEVER,
3175614e71bSYork Sun FSL_DDR_ODT_ALL,
3185614e71bSYork Sun DDR3_RTT_40_OHM,
3195614e71bSYork Sun DDR3_RTT_OFF
3205614e71bSYork Sun },
3215614e71bSYork Sun {0, 0, 0, 0},
3225614e71bSYork Sun {0, 0, 0, 0},
3235614e71bSYork Sun {0, 0, 0, 0},
3245614e71bSYork Sun };
3255614e71bSYork Sun
32697fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_DD[4] = {
3275614e71bSYork Sun { /* cs0 */
3285614e71bSYork Sun FSL_DDR_ODT_NEVER,
3295614e71bSYork Sun FSL_DDR_ODT_SAME_DIMM,
3305614e71bSYork Sun DDR3_RTT_120_OHM,
3315614e71bSYork Sun DDR3_RTT_OFF
3325614e71bSYork Sun },
3335614e71bSYork Sun { /* cs1 */
3345614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3355614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3365614e71bSYork Sun DDR3_RTT_30_OHM,
3375614e71bSYork Sun DDR3_RTT_OFF
3385614e71bSYork Sun },
3395614e71bSYork Sun { /* cs2 */
3405614e71bSYork Sun FSL_DDR_ODT_NEVER,
3415614e71bSYork Sun FSL_DDR_ODT_SAME_DIMM,
3425614e71bSYork Sun DDR3_RTT_120_OHM,
3435614e71bSYork Sun DDR3_RTT_OFF
3445614e71bSYork Sun },
3455614e71bSYork Sun { /* cs3 */
3465614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3475614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3485614e71bSYork Sun DDR3_RTT_30_OHM,
3495614e71bSYork Sun DDR3_RTT_OFF
3505614e71bSYork Sun }
3515614e71bSYork Sun };
3525614e71bSYork Sun
35397fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_DS[4] = {
3545614e71bSYork Sun { /* cs0 */
3555614e71bSYork Sun FSL_DDR_ODT_NEVER,
3565614e71bSYork Sun FSL_DDR_ODT_SAME_DIMM,
3575614e71bSYork Sun DDR3_RTT_120_OHM,
3585614e71bSYork Sun DDR3_RTT_OFF
3595614e71bSYork Sun },
3605614e71bSYork Sun { /* cs1 */
3615614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3625614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3635614e71bSYork Sun DDR3_RTT_30_OHM,
3645614e71bSYork Sun DDR3_RTT_OFF
3655614e71bSYork Sun },
3665614e71bSYork Sun { /* cs2 */
3675614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3685614e71bSYork Sun FSL_DDR_ODT_ALL,
3695614e71bSYork Sun DDR3_RTT_20_OHM,
3705614e71bSYork Sun DDR3_RTT_120_OHM
3715614e71bSYork Sun },
3725614e71bSYork Sun {0, 0, 0, 0}
3735614e71bSYork Sun };
37497fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_SD[4] = {
3755614e71bSYork Sun { /* cs0 */
3765614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3775614e71bSYork Sun FSL_DDR_ODT_ALL,
3785614e71bSYork Sun DDR3_RTT_20_OHM,
3795614e71bSYork Sun DDR3_RTT_120_OHM
3805614e71bSYork Sun },
3815614e71bSYork Sun {0, 0, 0, 0},
3825614e71bSYork Sun { /* cs2 */
3835614e71bSYork Sun FSL_DDR_ODT_NEVER,
3845614e71bSYork Sun FSL_DDR_ODT_SAME_DIMM,
3855614e71bSYork Sun DDR3_RTT_120_OHM,
3865614e71bSYork Sun DDR3_RTT_OFF
3875614e71bSYork Sun },
3885614e71bSYork Sun { /* cs3 */
3895614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3905614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3915614e71bSYork Sun DDR3_RTT_20_OHM,
3925614e71bSYork Sun DDR3_RTT_OFF
3935614e71bSYork Sun }
3945614e71bSYork Sun };
3955614e71bSYork Sun
39697fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_SS[4] = {
3975614e71bSYork Sun { /* cs0 */
3985614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
3995614e71bSYork Sun FSL_DDR_ODT_ALL,
4005614e71bSYork Sun DDR3_RTT_30_OHM,
4015614e71bSYork Sun DDR3_RTT_120_OHM
4025614e71bSYork Sun },
4035614e71bSYork Sun {0, 0, 0, 0},
4045614e71bSYork Sun { /* cs2 */
4055614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
4065614e71bSYork Sun FSL_DDR_ODT_ALL,
4075614e71bSYork Sun DDR3_RTT_30_OHM,
4085614e71bSYork Sun DDR3_RTT_120_OHM
4095614e71bSYork Sun },
4105614e71bSYork Sun {0, 0, 0, 0}
4115614e71bSYork Sun };
4125614e71bSYork Sun
41397fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_D0[4] = {
4145614e71bSYork Sun { /* cs0 */
4155614e71bSYork Sun FSL_DDR_ODT_NEVER,
4165614e71bSYork Sun FSL_DDR_ODT_SAME_DIMM,
4175614e71bSYork Sun DDR3_RTT_40_OHM,
4185614e71bSYork Sun DDR3_RTT_OFF
4195614e71bSYork Sun },
4205614e71bSYork Sun { /* cs1 */
4215614e71bSYork Sun FSL_DDR_ODT_NEVER,
4225614e71bSYork Sun FSL_DDR_ODT_NEVER,
4235614e71bSYork Sun DDR3_RTT_OFF,
4245614e71bSYork Sun DDR3_RTT_OFF
4255614e71bSYork Sun },
4265614e71bSYork Sun {0, 0, 0, 0},
4275614e71bSYork Sun {0, 0, 0, 0}
4285614e71bSYork Sun };
4295614e71bSYork Sun
43097fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_0D[4] = {
4315614e71bSYork Sun {0, 0, 0, 0},
4325614e71bSYork Sun {0, 0, 0, 0},
4335614e71bSYork Sun { /* cs2 */
4345614e71bSYork Sun FSL_DDR_ODT_NEVER,
4355614e71bSYork Sun FSL_DDR_ODT_SAME_DIMM,
4365614e71bSYork Sun DDR3_RTT_40_OHM,
4375614e71bSYork Sun DDR3_RTT_OFF
4385614e71bSYork Sun },
4395614e71bSYork Sun { /* cs3 */
4405614e71bSYork Sun FSL_DDR_ODT_NEVER,
4415614e71bSYork Sun FSL_DDR_ODT_NEVER,
4425614e71bSYork Sun DDR3_RTT_OFF,
4435614e71bSYork Sun DDR3_RTT_OFF
4445614e71bSYork Sun }
4455614e71bSYork Sun };
4465614e71bSYork Sun
44797fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_S0[4] = {
4485614e71bSYork Sun { /* cs0 */
4495614e71bSYork Sun FSL_DDR_ODT_NEVER,
4505614e71bSYork Sun FSL_DDR_ODT_CS,
4515614e71bSYork Sun DDR3_RTT_40_OHM,
4525614e71bSYork Sun DDR3_RTT_OFF
4535614e71bSYork Sun },
4545614e71bSYork Sun {0, 0, 0, 0},
4555614e71bSYork Sun {0, 0, 0, 0},
4565614e71bSYork Sun {0, 0, 0, 0}
4575614e71bSYork Sun
4585614e71bSYork Sun };
4595614e71bSYork Sun
46097fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_0S[4] = {
4615614e71bSYork Sun {0, 0, 0, 0},
4625614e71bSYork Sun {0, 0, 0, 0},
4635614e71bSYork Sun { /* cs2 */
4645614e71bSYork Sun FSL_DDR_ODT_NEVER,
4655614e71bSYork Sun FSL_DDR_ODT_CS,
4665614e71bSYork Sun DDR3_RTT_40_OHM,
4675614e71bSYork Sun DDR3_RTT_OFF
4685614e71bSYork Sun },
4695614e71bSYork Sun {0, 0, 0, 0}
4705614e71bSYork Sun
4715614e71bSYork Sun };
4725614e71bSYork Sun
47397fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt odt_unknown[4] = {
4745614e71bSYork Sun { /* cs0 */
4755614e71bSYork Sun FSL_DDR_ODT_NEVER,
4765614e71bSYork Sun FSL_DDR_ODT_CS,
4775614e71bSYork Sun DDR3_RTT_120_OHM,
4785614e71bSYork Sun DDR3_RTT_OFF
4795614e71bSYork Sun },
4805614e71bSYork Sun { /* cs1 */
4815614e71bSYork Sun FSL_DDR_ODT_NEVER,
4825614e71bSYork Sun FSL_DDR_ODT_CS,
4835614e71bSYork Sun DDR3_RTT_120_OHM,
4845614e71bSYork Sun DDR3_RTT_OFF
4855614e71bSYork Sun },
4865614e71bSYork Sun { /* cs2 */
4875614e71bSYork Sun FSL_DDR_ODT_NEVER,
4885614e71bSYork Sun FSL_DDR_ODT_CS,
4895614e71bSYork Sun DDR3_RTT_120_OHM,
4905614e71bSYork Sun DDR3_RTT_OFF
4915614e71bSYork Sun },
4925614e71bSYork Sun { /* cs3 */
4935614e71bSYork Sun FSL_DDR_ODT_NEVER,
4945614e71bSYork Sun FSL_DDR_ODT_CS,
4955614e71bSYork Sun DDR3_RTT_120_OHM,
4965614e71bSYork Sun DDR3_RTT_OFF
4975614e71bSYork Sun }
4985614e71bSYork Sun };
49919601dd9SYork Sun #else /* CONFIG_SYS_FSL_DDR3 */
50097fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt single_Q[4] = {
5015614e71bSYork Sun {0, 0, 0, 0},
5025614e71bSYork Sun {0, 0, 0, 0},
5035614e71bSYork Sun {0, 0, 0, 0},
5045614e71bSYork Sun {0, 0, 0, 0}
5055614e71bSYork Sun };
5065614e71bSYork Sun
50797fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt single_D[4] = {
5085614e71bSYork Sun { /* cs0 */
5095614e71bSYork Sun FSL_DDR_ODT_NEVER,
5105614e71bSYork Sun FSL_DDR_ODT_ALL,
5115614e71bSYork Sun DDR2_RTT_150_OHM,
5125614e71bSYork Sun DDR2_RTT_OFF
5135614e71bSYork Sun },
5145614e71bSYork Sun { /* cs1 */
5155614e71bSYork Sun FSL_DDR_ODT_NEVER,
5165614e71bSYork Sun FSL_DDR_ODT_NEVER,
5175614e71bSYork Sun DDR2_RTT_OFF,
5185614e71bSYork Sun DDR2_RTT_OFF
5195614e71bSYork Sun },
5205614e71bSYork Sun {0, 0, 0, 0},
5215614e71bSYork Sun {0, 0, 0, 0}
5225614e71bSYork Sun };
5235614e71bSYork Sun
52497fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt single_S[4] = {
5255614e71bSYork Sun { /* cs0 */
5265614e71bSYork Sun FSL_DDR_ODT_NEVER,
5275614e71bSYork Sun FSL_DDR_ODT_ALL,
5285614e71bSYork Sun DDR2_RTT_150_OHM,
5295614e71bSYork Sun DDR2_RTT_OFF
5305614e71bSYork Sun },
5315614e71bSYork Sun {0, 0, 0, 0},
5325614e71bSYork Sun {0, 0, 0, 0},
5335614e71bSYork Sun {0, 0, 0, 0},
5345614e71bSYork Sun };
5355614e71bSYork Sun
53697fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_DD[4] = {
5375614e71bSYork Sun { /* cs0 */
5385614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5395614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5405614e71bSYork Sun DDR2_RTT_75_OHM,
5415614e71bSYork Sun DDR2_RTT_OFF
5425614e71bSYork Sun },
5435614e71bSYork Sun { /* cs1 */
5445614e71bSYork Sun FSL_DDR_ODT_NEVER,
5455614e71bSYork Sun FSL_DDR_ODT_NEVER,
5465614e71bSYork Sun DDR2_RTT_OFF,
5475614e71bSYork Sun DDR2_RTT_OFF
5485614e71bSYork Sun },
5495614e71bSYork Sun { /* cs2 */
5505614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5515614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5525614e71bSYork Sun DDR2_RTT_75_OHM,
5535614e71bSYork Sun DDR2_RTT_OFF
5545614e71bSYork Sun },
5555614e71bSYork Sun { /* cs3 */
5565614e71bSYork Sun FSL_DDR_ODT_NEVER,
5575614e71bSYork Sun FSL_DDR_ODT_NEVER,
5585614e71bSYork Sun DDR2_RTT_OFF,
5595614e71bSYork Sun DDR2_RTT_OFF
5605614e71bSYork Sun }
5615614e71bSYork Sun };
5625614e71bSYork Sun
56397fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_DS[4] = {
5645614e71bSYork Sun { /* cs0 */
5655614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5665614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5675614e71bSYork Sun DDR2_RTT_75_OHM,
5685614e71bSYork Sun DDR2_RTT_OFF
5695614e71bSYork Sun },
5705614e71bSYork Sun { /* cs1 */
5715614e71bSYork Sun FSL_DDR_ODT_NEVER,
5725614e71bSYork Sun FSL_DDR_ODT_NEVER,
5735614e71bSYork Sun DDR2_RTT_OFF,
5745614e71bSYork Sun DDR2_RTT_OFF
5755614e71bSYork Sun },
5765614e71bSYork Sun { /* cs2 */
5775614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5785614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5795614e71bSYork Sun DDR2_RTT_75_OHM,
5805614e71bSYork Sun DDR2_RTT_OFF
5815614e71bSYork Sun },
5825614e71bSYork Sun {0, 0, 0, 0}
5835614e71bSYork Sun };
5845614e71bSYork Sun
58597fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_SD[4] = {
5865614e71bSYork Sun { /* cs0 */
5875614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5885614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5895614e71bSYork Sun DDR2_RTT_75_OHM,
5905614e71bSYork Sun DDR2_RTT_OFF
5915614e71bSYork Sun },
5925614e71bSYork Sun {0, 0, 0, 0},
5935614e71bSYork Sun { /* cs2 */
5945614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5955614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
5965614e71bSYork Sun DDR2_RTT_75_OHM,
5975614e71bSYork Sun DDR2_RTT_OFF
5985614e71bSYork Sun },
5995614e71bSYork Sun { /* cs3 */
6005614e71bSYork Sun FSL_DDR_ODT_NEVER,
6015614e71bSYork Sun FSL_DDR_ODT_NEVER,
6025614e71bSYork Sun DDR2_RTT_OFF,
6035614e71bSYork Sun DDR2_RTT_OFF
6045614e71bSYork Sun }
6055614e71bSYork Sun };
6065614e71bSYork Sun
60797fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_SS[4] = {
6085614e71bSYork Sun { /* cs0 */
6095614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
6105614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
6115614e71bSYork Sun DDR2_RTT_75_OHM,
6125614e71bSYork Sun DDR2_RTT_OFF
6135614e71bSYork Sun },
6145614e71bSYork Sun {0, 0, 0, 0},
6155614e71bSYork Sun { /* cs2 */
6165614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
6175614e71bSYork Sun FSL_DDR_ODT_OTHER_DIMM,
6185614e71bSYork Sun DDR2_RTT_75_OHM,
6195614e71bSYork Sun DDR2_RTT_OFF
6205614e71bSYork Sun },
6215614e71bSYork Sun {0, 0, 0, 0}
6225614e71bSYork Sun };
6235614e71bSYork Sun
62497fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_D0[4] = {
6255614e71bSYork Sun { /* cs0 */
6265614e71bSYork Sun FSL_DDR_ODT_NEVER,
6275614e71bSYork Sun FSL_DDR_ODT_ALL,
6285614e71bSYork Sun DDR2_RTT_150_OHM,
6295614e71bSYork Sun DDR2_RTT_OFF
6305614e71bSYork Sun },
6315614e71bSYork Sun { /* cs1 */
6325614e71bSYork Sun FSL_DDR_ODT_NEVER,
6335614e71bSYork Sun FSL_DDR_ODT_NEVER,
6345614e71bSYork Sun DDR2_RTT_OFF,
6355614e71bSYork Sun DDR2_RTT_OFF
6365614e71bSYork Sun },
6375614e71bSYork Sun {0, 0, 0, 0},
6385614e71bSYork Sun {0, 0, 0, 0}
6395614e71bSYork Sun };
6405614e71bSYork Sun
64197fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_0D[4] = {
6425614e71bSYork Sun {0, 0, 0, 0},
6435614e71bSYork Sun {0, 0, 0, 0},
6445614e71bSYork Sun { /* cs2 */
6455614e71bSYork Sun FSL_DDR_ODT_NEVER,
6465614e71bSYork Sun FSL_DDR_ODT_ALL,
6475614e71bSYork Sun DDR2_RTT_150_OHM,
6485614e71bSYork Sun DDR2_RTT_OFF
6495614e71bSYork Sun },
6505614e71bSYork Sun { /* cs3 */
6515614e71bSYork Sun FSL_DDR_ODT_NEVER,
6525614e71bSYork Sun FSL_DDR_ODT_NEVER,
6535614e71bSYork Sun DDR2_RTT_OFF,
6545614e71bSYork Sun DDR2_RTT_OFF
6555614e71bSYork Sun }
6565614e71bSYork Sun };
6575614e71bSYork Sun
65897fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_S0[4] = {
6595614e71bSYork Sun { /* cs0 */
6605614e71bSYork Sun FSL_DDR_ODT_NEVER,
6615614e71bSYork Sun FSL_DDR_ODT_CS,
6625614e71bSYork Sun DDR2_RTT_150_OHM,
6635614e71bSYork Sun DDR2_RTT_OFF
6645614e71bSYork Sun },
6655614e71bSYork Sun {0, 0, 0, 0},
6665614e71bSYork Sun {0, 0, 0, 0},
6675614e71bSYork Sun {0, 0, 0, 0}
6685614e71bSYork Sun
6695614e71bSYork Sun };
6705614e71bSYork Sun
67197fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt dual_0S[4] = {
6725614e71bSYork Sun {0, 0, 0, 0},
6735614e71bSYork Sun {0, 0, 0, 0},
6745614e71bSYork Sun { /* cs2 */
6755614e71bSYork Sun FSL_DDR_ODT_NEVER,
6765614e71bSYork Sun FSL_DDR_ODT_CS,
6775614e71bSYork Sun DDR2_RTT_150_OHM,
6785614e71bSYork Sun DDR2_RTT_OFF
6795614e71bSYork Sun },
6805614e71bSYork Sun {0, 0, 0, 0}
6815614e71bSYork Sun
6825614e71bSYork Sun };
6835614e71bSYork Sun
68497fbf26dSThomas Schaefer static __maybe_unused const struct dynamic_odt odt_unknown[4] = {
6855614e71bSYork Sun { /* cs0 */
6865614e71bSYork Sun FSL_DDR_ODT_NEVER,
6875614e71bSYork Sun FSL_DDR_ODT_CS,
6885614e71bSYork Sun DDR2_RTT_75_OHM,
6895614e71bSYork Sun DDR2_RTT_OFF
6905614e71bSYork Sun },
6915614e71bSYork Sun { /* cs1 */
6925614e71bSYork Sun FSL_DDR_ODT_NEVER,
6935614e71bSYork Sun FSL_DDR_ODT_NEVER,
6945614e71bSYork Sun DDR2_RTT_OFF,
6955614e71bSYork Sun DDR2_RTT_OFF
6965614e71bSYork Sun },
6975614e71bSYork Sun { /* cs2 */
6985614e71bSYork Sun FSL_DDR_ODT_NEVER,
6995614e71bSYork Sun FSL_DDR_ODT_CS,
7005614e71bSYork Sun DDR2_RTT_75_OHM,
7015614e71bSYork Sun DDR2_RTT_OFF
7025614e71bSYork Sun },
7035614e71bSYork Sun { /* cs3 */
7045614e71bSYork Sun FSL_DDR_ODT_NEVER,
7055614e71bSYork Sun FSL_DDR_ODT_NEVER,
7065614e71bSYork Sun DDR2_RTT_OFF,
7075614e71bSYork Sun DDR2_RTT_OFF
7085614e71bSYork Sun }
7095614e71bSYork Sun };
7105614e71bSYork Sun #endif
7115614e71bSYork Sun
7125614e71bSYork Sun /*
7135614e71bSYork Sun * Automatically seleect bank interleaving mode based on DIMMs
7145614e71bSYork Sun * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null.
7155614e71bSYork Sun * This function only deal with one or two slots per controller.
7165614e71bSYork Sun */
auto_bank_intlv(dimm_params_t * pdimm)7175614e71bSYork Sun static inline unsigned int auto_bank_intlv(dimm_params_t *pdimm)
7185614e71bSYork Sun {
7195614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
7205614e71bSYork Sun if (pdimm[0].n_ranks == 4)
7215614e71bSYork Sun return FSL_DDR_CS0_CS1_CS2_CS3;
7225614e71bSYork Sun else if (pdimm[0].n_ranks == 2)
7235614e71bSYork Sun return FSL_DDR_CS0_CS1;
7245614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
7255614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
7265614e71bSYork Sun if (pdimm[0].n_ranks == 4)
7275614e71bSYork Sun return FSL_DDR_CS0_CS1_CS2_CS3;
7285614e71bSYork Sun #endif
7295614e71bSYork Sun if (pdimm[0].n_ranks == 2) {
7305614e71bSYork Sun if (pdimm[1].n_ranks == 2)
7315614e71bSYork Sun return FSL_DDR_CS0_CS1_CS2_CS3;
7325614e71bSYork Sun else
7335614e71bSYork Sun return FSL_DDR_CS0_CS1;
7345614e71bSYork Sun }
7355614e71bSYork Sun #endif
7365614e71bSYork Sun return 0;
7375614e71bSYork Sun }
7385614e71bSYork Sun
populate_memctl_options(const common_timing_params_t * common_dimm,memctl_options_t * popts,dimm_params_t * pdimm,unsigned int ctrl_num)73956848428SYork Sun unsigned int populate_memctl_options(const common_timing_params_t *common_dimm,
7405614e71bSYork Sun memctl_options_t *popts,
7415614e71bSYork Sun dimm_params_t *pdimm,
7425614e71bSYork Sun unsigned int ctrl_num)
7435614e71bSYork Sun {
7445614e71bSYork Sun unsigned int i;
7455614e71bSYork Sun char buffer[HWCONFIG_BUFFER_SIZE];
7465614e71bSYork Sun char *buf = NULL;
74734e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || \
74834e026f9SYork Sun defined(CONFIG_SYS_FSL_DDR2) || \
74934e026f9SYork Sun defined(CONFIG_SYS_FSL_DDR4)
7505614e71bSYork Sun const struct dynamic_odt *pdodt = odt_unknown;
7515614e71bSYork Sun #endif
7525614e71bSYork Sun ulong ddr_freq;
7535614e71bSYork Sun
7545614e71bSYork Sun /*
7555614e71bSYork Sun * Extract hwconfig from environment since we have not properly setup
7565614e71bSYork Sun * the environment but need it for ddr config params
7575614e71bSYork Sun */
758*00caae6dSSimon Glass if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0)
7595614e71bSYork Sun buf = buffer;
7605614e71bSYork Sun
76134e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || \
76234e026f9SYork Sun defined(CONFIG_SYS_FSL_DDR2) || \
76334e026f9SYork Sun defined(CONFIG_SYS_FSL_DDR4)
7645614e71bSYork Sun /* Chip select options. */
765349689b8SYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
7665614e71bSYork Sun switch (pdimm[0].n_ranks) {
7675614e71bSYork Sun case 1:
7685614e71bSYork Sun pdodt = single_S;
7695614e71bSYork Sun break;
7705614e71bSYork Sun case 2:
7715614e71bSYork Sun pdodt = single_D;
7725614e71bSYork Sun break;
7735614e71bSYork Sun case 4:
7745614e71bSYork Sun pdodt = single_Q;
7755614e71bSYork Sun break;
7765614e71bSYork Sun }
777349689b8SYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
7785614e71bSYork Sun switch (pdimm[0].n_ranks) {
7795614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
7805614e71bSYork Sun case 4:
7815614e71bSYork Sun pdodt = single_Q;
7825614e71bSYork Sun if (pdimm[1].n_ranks)
783349689b8SYork Sun printf("Error: Quad- and Dual-rank DIMMs cannot be used together\n");
7845614e71bSYork Sun break;
7855614e71bSYork Sun #endif
7865614e71bSYork Sun case 2:
7875614e71bSYork Sun switch (pdimm[1].n_ranks) {
7885614e71bSYork Sun case 2:
7895614e71bSYork Sun pdodt = dual_DD;
7905614e71bSYork Sun break;
7915614e71bSYork Sun case 1:
7925614e71bSYork Sun pdodt = dual_DS;
7935614e71bSYork Sun break;
7945614e71bSYork Sun case 0:
7955614e71bSYork Sun pdodt = dual_D0;
7965614e71bSYork Sun break;
7975614e71bSYork Sun }
7985614e71bSYork Sun break;
7995614e71bSYork Sun case 1:
8005614e71bSYork Sun switch (pdimm[1].n_ranks) {
8015614e71bSYork Sun case 2:
8025614e71bSYork Sun pdodt = dual_SD;
8035614e71bSYork Sun break;
8045614e71bSYork Sun case 1:
8055614e71bSYork Sun pdodt = dual_SS;
8065614e71bSYork Sun break;
8075614e71bSYork Sun case 0:
8085614e71bSYork Sun pdodt = dual_S0;
8095614e71bSYork Sun break;
8105614e71bSYork Sun }
8115614e71bSYork Sun break;
8125614e71bSYork Sun case 0:
8135614e71bSYork Sun switch (pdimm[1].n_ranks) {
8145614e71bSYork Sun case 2:
8155614e71bSYork Sun pdodt = dual_0D;
8165614e71bSYork Sun break;
8175614e71bSYork Sun case 1:
8185614e71bSYork Sun pdodt = dual_0S;
8195614e71bSYork Sun break;
8205614e71bSYork Sun }
8215614e71bSYork Sun break;
8225614e71bSYork Sun }
823349689b8SYork Sun #endif /* CONFIG_DIMM_SLOTS_PER_CTLR */
824349689b8SYork Sun #endif /* CONFIG_SYS_FSL_DDR2, 3, 4 */
8255614e71bSYork Sun
8265614e71bSYork Sun /* Pick chip-select local options. */
8275614e71bSYork Sun for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
82834e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || \
82934e026f9SYork Sun defined(CONFIG_SYS_FSL_DDR2) || \
83034e026f9SYork Sun defined(CONFIG_SYS_FSL_DDR4)
8315614e71bSYork Sun popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg;
8325614e71bSYork Sun popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg;
8335614e71bSYork Sun popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm;
8345614e71bSYork Sun popts->cs_local_opts[i].odt_rtt_wr = pdodt[i].odt_rtt_wr;
8355614e71bSYork Sun #else
8365614e71bSYork Sun popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
8375614e71bSYork Sun popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
8385614e71bSYork Sun #endif
8395614e71bSYork Sun popts->cs_local_opts[i].auto_precharge = 0;
8405614e71bSYork Sun }
8415614e71bSYork Sun
8425614e71bSYork Sun /* Pick interleaving mode. */
8435614e71bSYork Sun
8445614e71bSYork Sun /*
8455614e71bSYork Sun * 0 = no interleaving
8465614e71bSYork Sun * 1 = interleaving between 2 controllers
8475614e71bSYork Sun */
8485614e71bSYork Sun popts->memctl_interleaving = 0;
8495614e71bSYork Sun
8505614e71bSYork Sun /*
8515614e71bSYork Sun * 0 = cacheline
8525614e71bSYork Sun * 1 = page
8535614e71bSYork Sun * 2 = (logical) bank
8545614e71bSYork Sun * 3 = superbank (only if CS interleaving is enabled)
8555614e71bSYork Sun */
8565614e71bSYork Sun popts->memctl_interleaving_mode = 0;
8575614e71bSYork Sun
8585614e71bSYork Sun /*
8595614e71bSYork Sun * 0: cacheline: bit 30 of the 36-bit physical addr selects the memctl
8605614e71bSYork Sun * 1: page: bit to the left of the column bits selects the memctl
8615614e71bSYork Sun * 2: bank: bit to the left of the bank bits selects the memctl
8625614e71bSYork Sun * 3: superbank: bit to the left of the chip select selects the memctl
8635614e71bSYork Sun *
8645614e71bSYork Sun * NOTE: ba_intlv (rank interleaving) is independent of memory
8655614e71bSYork Sun * controller interleaving; it is only within a memory controller.
8665614e71bSYork Sun * Must use superbank interleaving if rank interleaving is used and
8675614e71bSYork Sun * memory controller interleaving is enabled.
8685614e71bSYork Sun */
8695614e71bSYork Sun
8705614e71bSYork Sun /*
8715614e71bSYork Sun * 0 = no
8725614e71bSYork Sun * 0x40 = CS0,CS1
8735614e71bSYork Sun * 0x20 = CS2,CS3
8745614e71bSYork Sun * 0x60 = CS0,CS1 + CS2,CS3
8755614e71bSYork Sun * 0x04 = CS0,CS1,CS2,CS3
8765614e71bSYork Sun */
8775614e71bSYork Sun popts->ba_intlv_ctl = 0;
8785614e71bSYork Sun
8795614e71bSYork Sun /* Memory Organization Parameters */
88056848428SYork Sun popts->registered_dimm_en = common_dimm->all_dimms_registered;
8815614e71bSYork Sun
8825614e71bSYork Sun /* Operational Mode Paramters */
8835614e71bSYork Sun
8845614e71bSYork Sun /* Pick ECC modes */
8855614e71bSYork Sun popts->ecc_mode = 0; /* 0 = disabled, 1 = enabled */
8865614e71bSYork Sun #ifdef CONFIG_DDR_ECC
8875614e71bSYork Sun if (hwconfig_sub_f("fsl_ddr", "ecc", buf)) {
8885614e71bSYork Sun if (hwconfig_subarg_cmp_f("fsl_ddr", "ecc", "on", buf))
8895614e71bSYork Sun popts->ecc_mode = 1;
8905614e71bSYork Sun } else
8915614e71bSYork Sun popts->ecc_mode = 1;
8925614e71bSYork Sun #endif
893b06f6f2fSYork Sun /* 1 = use memory controler to init data */
894b06f6f2fSYork Sun popts->ecc_init_using_memctl = popts->ecc_mode ? 1 : 0;
8955614e71bSYork Sun
8965614e71bSYork Sun /*
8975614e71bSYork Sun * Choose DQS config
8985614e71bSYork Sun * 0 for DDR1
8995614e71bSYork Sun * 1 for DDR2
9005614e71bSYork Sun */
9015614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
9025614e71bSYork Sun popts->dqs_config = 0;
9035614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2) || defined(CONFIG_SYS_FSL_DDR3)
9045614e71bSYork Sun popts->dqs_config = 1;
9055614e71bSYork Sun #endif
9065614e71bSYork Sun
9075614e71bSYork Sun /* Choose self-refresh during sleep. */
9085614e71bSYork Sun popts->self_refresh_in_sleep = 1;
9095614e71bSYork Sun
9105614e71bSYork Sun /* Choose dynamic power management mode. */
9115614e71bSYork Sun popts->dynamic_power = 0;
9125614e71bSYork Sun
9135614e71bSYork Sun /*
9145614e71bSYork Sun * check first dimm for primary sdram width
9155614e71bSYork Sun * presuming all dimms are similar
9165614e71bSYork Sun * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
9175614e71bSYork Sun */
9185614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
9195614e71bSYork Sun if (pdimm[0].n_ranks != 0) {
9205614e71bSYork Sun if ((pdimm[0].data_width >= 64) && \
9215614e71bSYork Sun (pdimm[0].data_width <= 72))
9225614e71bSYork Sun popts->data_bus_width = 0;
9230e0de24bSxypron.glpk@gmx.de else if ((pdimm[0].data_width >= 32) && \
9245614e71bSYork Sun (pdimm[0].data_width <= 40))
9255614e71bSYork Sun popts->data_bus_width = 1;
9265614e71bSYork Sun else {
9275614e71bSYork Sun panic("Error: data width %u is invalid!\n",
9285614e71bSYork Sun pdimm[0].data_width);
9295614e71bSYork Sun }
9305614e71bSYork Sun }
9315614e71bSYork Sun #else
9325614e71bSYork Sun if (pdimm[0].n_ranks != 0) {
9335614e71bSYork Sun if (pdimm[0].primary_sdram_width == 64)
9345614e71bSYork Sun popts->data_bus_width = 0;
9355614e71bSYork Sun else if (pdimm[0].primary_sdram_width == 32)
9365614e71bSYork Sun popts->data_bus_width = 1;
9375614e71bSYork Sun else if (pdimm[0].primary_sdram_width == 16)
9385614e71bSYork Sun popts->data_bus_width = 2;
9395614e71bSYork Sun else {
9405614e71bSYork Sun panic("Error: primary sdram width %u is invalid!\n",
9415614e71bSYork Sun pdimm[0].primary_sdram_width);
9425614e71bSYork Sun }
9435614e71bSYork Sun }
9445614e71bSYork Sun #endif
9455614e71bSYork Sun
9465614e71bSYork Sun popts->x4_en = (pdimm[0].device_width == 4) ? 1 : 0;
9475614e71bSYork Sun
9485614e71bSYork Sun /* Choose burst length. */
94934e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
9505614e71bSYork Sun #if defined(CONFIG_E500MC)
9515614e71bSYork Sun popts->otf_burst_chop_en = 0; /* on-the-fly burst chop disable */
9525614e71bSYork Sun popts->burst_length = DDR_BL8; /* Fixed 8-beat burst len */
9535614e71bSYork Sun #else
9545614e71bSYork Sun if ((popts->data_bus_width == 1) || (popts->data_bus_width == 2)) {
9555614e71bSYork Sun /* 32-bit or 16-bit bus */
9565614e71bSYork Sun popts->otf_burst_chop_en = 0;
9575614e71bSYork Sun popts->burst_length = DDR_BL8;
9585614e71bSYork Sun } else {
9595614e71bSYork Sun popts->otf_burst_chop_en = 1; /* on-the-fly burst chop */
9605614e71bSYork Sun popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */
9615614e71bSYork Sun }
9625614e71bSYork Sun #endif
9635614e71bSYork Sun #else
9645614e71bSYork Sun popts->burst_length = DDR_BL4; /* has to be 4 for DDR2 */
9655614e71bSYork Sun #endif
9665614e71bSYork Sun
9675614e71bSYork Sun /* Choose ddr controller address mirror mode */
96834e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
9696b95be22SYork Sun for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
9706b95be22SYork Sun if (pdimm[i].n_ranks) {
9716b95be22SYork Sun popts->mirrored_dimm = pdimm[i].mirrored_dimm;
9726b95be22SYork Sun break;
9736b95be22SYork Sun }
9746b95be22SYork Sun }
9755614e71bSYork Sun #endif
9765614e71bSYork Sun
9775614e71bSYork Sun /* Global Timing Parameters. */
97803e664d8SYork Sun debug("mclk_ps = %u ps\n", get_memory_clk_period_ps(ctrl_num));
9795614e71bSYork Sun
9805614e71bSYork Sun /* Pick a caslat override. */
9815614e71bSYork Sun popts->cas_latency_override = 0;
9825614e71bSYork Sun popts->cas_latency_override_value = 3;
9835614e71bSYork Sun if (popts->cas_latency_override) {
9845614e71bSYork Sun debug("using caslat override value = %u\n",
9855614e71bSYork Sun popts->cas_latency_override_value);
9865614e71bSYork Sun }
9875614e71bSYork Sun
9885614e71bSYork Sun /* Decide whether to use the computed derated latency */
9895614e71bSYork Sun popts->use_derated_caslat = 0;
9905614e71bSYork Sun
9915614e71bSYork Sun /* Choose an additive latency. */
9925614e71bSYork Sun popts->additive_latency_override = 0;
9935614e71bSYork Sun popts->additive_latency_override_value = 3;
9945614e71bSYork Sun if (popts->additive_latency_override) {
9955614e71bSYork Sun debug("using additive latency override value = %u\n",
9965614e71bSYork Sun popts->additive_latency_override_value);
9975614e71bSYork Sun }
9985614e71bSYork Sun
9995614e71bSYork Sun /*
10005614e71bSYork Sun * 2T_EN setting
10015614e71bSYork Sun *
10025614e71bSYork Sun * Factors to consider for 2T_EN:
10035614e71bSYork Sun * - number of DIMMs installed
10045614e71bSYork Sun * - number of components, number of active ranks
10055614e71bSYork Sun * - how much time you want to spend playing around
10065614e71bSYork Sun */
10075614e71bSYork Sun popts->twot_en = 0;
10085614e71bSYork Sun popts->threet_en = 0;
10095614e71bSYork Sun
1010eb118807SShengzhou Liu /* for RDIMM and DDR4 UDIMM/discrete memory, address parity enable */
1011eb118807SShengzhou Liu if (popts->registered_dimm_en)
1012eb118807SShengzhou Liu popts->ap_en = 1; /* 0 = disable, 1 = enable */
1013eb118807SShengzhou Liu else
1014eb118807SShengzhou Liu popts->ap_en = 0; /* disabled for DDR4 UDIMM/discrete default */
1015eb118807SShengzhou Liu
1016eb118807SShengzhou Liu if (hwconfig_sub_f("fsl_ddr", "parity", buf)) {
1017eb118807SShengzhou Liu if (hwconfig_subarg_cmp_f("fsl_ddr", "parity", "on", buf)) {
1018eb118807SShengzhou Liu if (popts->registered_dimm_en ||
1019eb118807SShengzhou Liu (CONFIG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4))
10205614e71bSYork Sun popts->ap_en = 1;
1021eb118807SShengzhou Liu }
1022eb118807SShengzhou Liu }
10235614e71bSYork Sun
10245614e71bSYork Sun /*
10255614e71bSYork Sun * BSTTOPRE precharge interval
10265614e71bSYork Sun *
10275614e71bSYork Sun * Set this to 0 for global auto precharge
102834e026f9SYork Sun * The value of 0x100 has been used for DDR1, DDR2, DDR3.
102934e026f9SYork Sun * It is not wrong. Any value should be OK. The performance depends on
103056848428SYork Sun * applications. There is no one good value for all. One way to set
103156848428SYork Sun * is to use 1/4 of refint value.
10325614e71bSYork Sun */
103356848428SYork Sun popts->bstopre = picos_to_mclk(ctrl_num, common_dimm->refresh_rate_ps)
103456848428SYork Sun >> 2;
10355614e71bSYork Sun
10365614e71bSYork Sun /*
10375614e71bSYork Sun * Window for four activates -- tFAW
10385614e71bSYork Sun *
10395614e71bSYork Sun * FIXME: UM: applies only to DDR2/DDR3 with eight logical banks only
10405614e71bSYork Sun * FIXME: varies depending upon number of column addresses or data
10415614e71bSYork Sun * FIXME: width, was considering looking at pdimm->primary_sdram_width
10425614e71bSYork Sun */
10435614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
104403e664d8SYork Sun popts->tfaw_window_four_activates_ps = mclk_to_picos(ctrl_num, 1);
10455614e71bSYork Sun
10465614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
10475614e71bSYork Sun /*
10485614e71bSYork Sun * x4/x8; some datasheets have 35000
10495614e71bSYork Sun * x16 wide columns only? Use 50000?
10505614e71bSYork Sun */
10515614e71bSYork Sun popts->tfaw_window_four_activates_ps = 37500;
10525614e71bSYork Sun
105334e026f9SYork Sun #else
10545614e71bSYork Sun popts->tfaw_window_four_activates_ps = pdimm[0].tfaw_ps;
10555614e71bSYork Sun #endif
10565614e71bSYork Sun popts->zq_en = 0;
10575614e71bSYork Sun popts->wrlvl_en = 0;
105834e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
10595614e71bSYork Sun /*
10605614e71bSYork Sun * due to ddr3 dimm is fly-by topology
10615614e71bSYork Sun * we suggest to enable write leveling to
10625614e71bSYork Sun * meet the tQDSS under different loading.
10635614e71bSYork Sun */
10645614e71bSYork Sun popts->wrlvl_en = 1;
10655614e71bSYork Sun popts->zq_en = 1;
10665614e71bSYork Sun popts->wrlvl_override = 0;
10675614e71bSYork Sun #endif
10685614e71bSYork Sun
10695614e71bSYork Sun /*
10705614e71bSYork Sun * Check interleaving configuration from environment.
10715614e71bSYork Sun * Please refer to doc/README.fsl-ddr for the detail.
10725614e71bSYork Sun *
10735614e71bSYork Sun * If memory controller interleaving is enabled, then the data
10745614e71bSYork Sun * bus widths must be programmed identically for all memory controllers.
10755614e71bSYork Sun *
10766b1e1254SYork Sun * Attempt to set all controllers to the same chip select
10775614e71bSYork Sun * interleaving mode. It will do a best effort to get the
10785614e71bSYork Sun * requested ranks interleaved together such that the result
10795614e71bSYork Sun * should be a subset of the requested configuration.
10806b1e1254SYork Sun *
10816b1e1254SYork Sun * if CONFIG_SYS_FSL_DDR_INTLV_256B is defined, mandatory interleaving
10826b1e1254SYork Sun * with 256 Byte is enabled.
10835614e71bSYork Sun */
108451370d56SYork Sun #if (CONFIG_SYS_NUM_DDR_CTLRS > 1)
10855614e71bSYork Sun if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf))
10866b1e1254SYork Sun #ifdef CONFIG_SYS_FSL_DDR_INTLV_256B
10876b1e1254SYork Sun ;
10886b1e1254SYork Sun #else
10895614e71bSYork Sun goto done;
10906b1e1254SYork Sun #endif
10915614e71bSYork Sun if (pdimm[0].n_ranks == 0) {
10925614e71bSYork Sun printf("There is no rank on CS0 for controller %d.\n", ctrl_num);
10935614e71bSYork Sun popts->memctl_interleaving = 0;
10945614e71bSYork Sun goto done;
10955614e71bSYork Sun }
10965614e71bSYork Sun popts->memctl_interleaving = 1;
10976b1e1254SYork Sun #ifdef CONFIG_SYS_FSL_DDR_INTLV_256B
10986b1e1254SYork Sun popts->memctl_interleaving_mode = FSL_DDR_256B_INTERLEAVING;
10996b1e1254SYork Sun popts->memctl_interleaving = 1;
11006b1e1254SYork Sun debug("256 Byte interleaving\n");
1101349689b8SYork Sun #else
11025614e71bSYork Sun /*
11035614e71bSYork Sun * test null first. if CONFIG_HWCONFIG is not defined
11045614e71bSYork Sun * hwconfig_arg_cmp returns non-zero
11055614e71bSYork Sun */
11065614e71bSYork Sun if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv",
11075614e71bSYork Sun "null", buf)) {
11085614e71bSYork Sun popts->memctl_interleaving = 0;
11095614e71bSYork Sun debug("memory controller interleaving disabled.\n");
11105614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr",
11115614e71bSYork Sun "ctlr_intlv",
11125614e71bSYork Sun "cacheline", buf)) {
11135614e71bSYork Sun popts->memctl_interleaving_mode =
111451370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ?
11155614e71bSYork Sun 0 : FSL_DDR_CACHE_LINE_INTERLEAVING;
11165614e71bSYork Sun popts->memctl_interleaving =
111751370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ?
11185614e71bSYork Sun 0 : 1;
11195614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr",
11205614e71bSYork Sun "ctlr_intlv",
11215614e71bSYork Sun "page", buf)) {
11225614e71bSYork Sun popts->memctl_interleaving_mode =
112351370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ?
11245614e71bSYork Sun 0 : FSL_DDR_PAGE_INTERLEAVING;
11255614e71bSYork Sun popts->memctl_interleaving =
112651370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ?
11275614e71bSYork Sun 0 : 1;
11285614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr",
11295614e71bSYork Sun "ctlr_intlv",
11305614e71bSYork Sun "bank", buf)) {
11315614e71bSYork Sun popts->memctl_interleaving_mode =
113251370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ?
11335614e71bSYork Sun 0 : FSL_DDR_BANK_INTERLEAVING;
11345614e71bSYork Sun popts->memctl_interleaving =
113551370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ?
11365614e71bSYork Sun 0 : 1;
11375614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr",
11385614e71bSYork Sun "ctlr_intlv",
11395614e71bSYork Sun "superbank", buf)) {
11405614e71bSYork Sun popts->memctl_interleaving_mode =
114151370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ?
11425614e71bSYork Sun 0 : FSL_DDR_SUPERBANK_INTERLEAVING;
11435614e71bSYork Sun popts->memctl_interleaving =
114451370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ?
11455614e71bSYork Sun 0 : 1;
114651370d56SYork Sun #if (CONFIG_SYS_NUM_DDR_CTLRS == 3)
11475614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr",
11485614e71bSYork Sun "ctlr_intlv",
11495614e71bSYork Sun "3way_1KB", buf)) {
11505614e71bSYork Sun popts->memctl_interleaving_mode =
11515614e71bSYork Sun FSL_DDR_3WAY_1KB_INTERLEAVING;
11525614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr",
11535614e71bSYork Sun "ctlr_intlv",
11545614e71bSYork Sun "3way_4KB", buf)) {
11555614e71bSYork Sun popts->memctl_interleaving_mode =
11565614e71bSYork Sun FSL_DDR_3WAY_4KB_INTERLEAVING;
11575614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr",
11585614e71bSYork Sun "ctlr_intlv",
11595614e71bSYork Sun "3way_8KB", buf)) {
11605614e71bSYork Sun popts->memctl_interleaving_mode =
11615614e71bSYork Sun FSL_DDR_3WAY_8KB_INTERLEAVING;
116251370d56SYork Sun #elif (CONFIG_SYS_NUM_DDR_CTLRS == 4)
11635614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr",
11645614e71bSYork Sun "ctlr_intlv",
11655614e71bSYork Sun "4way_1KB", buf)) {
11665614e71bSYork Sun popts->memctl_interleaving_mode =
11675614e71bSYork Sun FSL_DDR_4WAY_1KB_INTERLEAVING;
11685614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr",
11695614e71bSYork Sun "ctlr_intlv",
11705614e71bSYork Sun "4way_4KB", buf)) {
11715614e71bSYork Sun popts->memctl_interleaving_mode =
11725614e71bSYork Sun FSL_DDR_4WAY_4KB_INTERLEAVING;
11735614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr",
11745614e71bSYork Sun "ctlr_intlv",
11755614e71bSYork Sun "4way_8KB", buf)) {
11765614e71bSYork Sun popts->memctl_interleaving_mode =
11775614e71bSYork Sun FSL_DDR_4WAY_8KB_INTERLEAVING;
11785614e71bSYork Sun #endif
11795614e71bSYork Sun } else {
11805614e71bSYork Sun popts->memctl_interleaving = 0;
11815614e71bSYork Sun printf("hwconfig has unrecognized parameter for ctlr_intlv.\n");
11825614e71bSYork Sun }
1183349689b8SYork Sun #endif /* CONFIG_SYS_FSL_DDR_INTLV_256B */
11845614e71bSYork Sun done:
118551370d56SYork Sun #endif /* CONFIG_SYS_NUM_DDR_CTLRS > 1 */
11865614e71bSYork Sun if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) &&
11875614e71bSYork Sun (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
11885614e71bSYork Sun /* test null first. if CONFIG_HWCONFIG is not defined,
11895614e71bSYork Sun * hwconfig_subarg_cmp_f returns non-zero */
11905614e71bSYork Sun if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
11915614e71bSYork Sun "null", buf))
11925614e71bSYork Sun debug("bank interleaving disabled.\n");
11935614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
11945614e71bSYork Sun "cs0_cs1", buf))
11955614e71bSYork Sun popts->ba_intlv_ctl = FSL_DDR_CS0_CS1;
11965614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
11975614e71bSYork Sun "cs2_cs3", buf))
11985614e71bSYork Sun popts->ba_intlv_ctl = FSL_DDR_CS2_CS3;
11995614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
12005614e71bSYork Sun "cs0_cs1_and_cs2_cs3", buf))
12015614e71bSYork Sun popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3;
12025614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
12035614e71bSYork Sun "cs0_cs1_cs2_cs3", buf))
12045614e71bSYork Sun popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3;
12055614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
12065614e71bSYork Sun "auto", buf))
12075614e71bSYork Sun popts->ba_intlv_ctl = auto_bank_intlv(pdimm);
12085614e71bSYork Sun else
12095614e71bSYork Sun printf("hwconfig has unrecognized parameter for bank_intlv.\n");
12105614e71bSYork Sun switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
12115614e71bSYork Sun case FSL_DDR_CS0_CS1_CS2_CS3:
12125614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
12135614e71bSYork Sun if (pdimm[0].n_ranks < 4) {
12145614e71bSYork Sun popts->ba_intlv_ctl = 0;
12155614e71bSYork Sun printf("Not enough bank(chip-select) for "
12165614e71bSYork Sun "CS0+CS1+CS2+CS3 on controller %d, "
12175614e71bSYork Sun "interleaving disabled!\n", ctrl_num);
12185614e71bSYork Sun }
12195614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
12205614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
12215614e71bSYork Sun if (pdimm[0].n_ranks == 4)
12225614e71bSYork Sun break;
12235614e71bSYork Sun #endif
12245614e71bSYork Sun if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) {
12255614e71bSYork Sun popts->ba_intlv_ctl = 0;
12265614e71bSYork Sun printf("Not enough bank(chip-select) for "
12275614e71bSYork Sun "CS0+CS1+CS2+CS3 on controller %d, "
12285614e71bSYork Sun "interleaving disabled!\n", ctrl_num);
12295614e71bSYork Sun }
12305614e71bSYork Sun if (pdimm[0].capacity != pdimm[1].capacity) {
12315614e71bSYork Sun popts->ba_intlv_ctl = 0;
12325614e71bSYork Sun printf("Not identical DIMM size for "
12335614e71bSYork Sun "CS0+CS1+CS2+CS3 on controller %d, "
12345614e71bSYork Sun "interleaving disabled!\n", ctrl_num);
12355614e71bSYork Sun }
12365614e71bSYork Sun #endif
12375614e71bSYork Sun break;
12385614e71bSYork Sun case FSL_DDR_CS0_CS1:
12395614e71bSYork Sun if (pdimm[0].n_ranks < 2) {
12405614e71bSYork Sun popts->ba_intlv_ctl = 0;
12415614e71bSYork Sun printf("Not enough bank(chip-select) for "
12425614e71bSYork Sun "CS0+CS1 on controller %d, "
12435614e71bSYork Sun "interleaving disabled!\n", ctrl_num);
12445614e71bSYork Sun }
12455614e71bSYork Sun break;
12465614e71bSYork Sun case FSL_DDR_CS2_CS3:
12475614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
12485614e71bSYork Sun if (pdimm[0].n_ranks < 4) {
12495614e71bSYork Sun popts->ba_intlv_ctl = 0;
12505614e71bSYork Sun printf("Not enough bank(chip-select) for CS2+CS3 "
12515614e71bSYork Sun "on controller %d, interleaving disabled!\n", ctrl_num);
12525614e71bSYork Sun }
12535614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
12545614e71bSYork Sun if (pdimm[1].n_ranks < 2) {
12555614e71bSYork Sun popts->ba_intlv_ctl = 0;
12565614e71bSYork Sun printf("Not enough bank(chip-select) for CS2+CS3 "
12575614e71bSYork Sun "on controller %d, interleaving disabled!\n", ctrl_num);
12585614e71bSYork Sun }
12595614e71bSYork Sun #endif
12605614e71bSYork Sun break;
12615614e71bSYork Sun case FSL_DDR_CS0_CS1_AND_CS2_CS3:
12625614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
12635614e71bSYork Sun if (pdimm[0].n_ranks < 4) {
12645614e71bSYork Sun popts->ba_intlv_ctl = 0;
12655614e71bSYork Sun printf("Not enough bank(CS) for CS0+CS1 and "
12665614e71bSYork Sun "CS2+CS3 on controller %d, "
12675614e71bSYork Sun "interleaving disabled!\n", ctrl_num);
12685614e71bSYork Sun }
12695614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
12705614e71bSYork Sun if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) {
12715614e71bSYork Sun popts->ba_intlv_ctl = 0;
12725614e71bSYork Sun printf("Not enough bank(CS) for CS0+CS1 and "
12735614e71bSYork Sun "CS2+CS3 on controller %d, "
12745614e71bSYork Sun "interleaving disabled!\n", ctrl_num);
12755614e71bSYork Sun }
12765614e71bSYork Sun #endif
12775614e71bSYork Sun break;
12785614e71bSYork Sun default:
12795614e71bSYork Sun popts->ba_intlv_ctl = 0;
12805614e71bSYork Sun break;
12815614e71bSYork Sun }
12825614e71bSYork Sun }
12835614e71bSYork Sun
12845614e71bSYork Sun if (hwconfig_sub_f("fsl_ddr", "addr_hash", buf)) {
12855614e71bSYork Sun if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", "null", buf))
12865614e71bSYork Sun popts->addr_hash = 0;
12875614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash",
12885614e71bSYork Sun "true", buf))
12895614e71bSYork Sun popts->addr_hash = 1;
12905614e71bSYork Sun }
12915614e71bSYork Sun
12925614e71bSYork Sun if (pdimm[0].n_ranks == 4)
12935614e71bSYork Sun popts->quad_rank_present = 1;
12945614e71bSYork Sun
129503e664d8SYork Sun ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
12965614e71bSYork Sun if (popts->registered_dimm_en) {
12975614e71bSYork Sun popts->rcw_override = 1;
12985614e71bSYork Sun popts->rcw_1 = 0x000a5a00;
12995614e71bSYork Sun if (ddr_freq <= 800)
13005614e71bSYork Sun popts->rcw_2 = 0x00000000;
13015614e71bSYork Sun else if (ddr_freq <= 1066)
13025614e71bSYork Sun popts->rcw_2 = 0x00100000;
13035614e71bSYork Sun else if (ddr_freq <= 1333)
13045614e71bSYork Sun popts->rcw_2 = 0x00200000;
13055614e71bSYork Sun else
13065614e71bSYork Sun popts->rcw_2 = 0x00300000;
13075614e71bSYork Sun }
13085614e71bSYork Sun
13095614e71bSYork Sun fsl_ddr_board_options(popts, pdimm, ctrl_num);
13105614e71bSYork Sun
13115614e71bSYork Sun return 0;
13125614e71bSYork Sun }
13135614e71bSYork Sun
check_interleaving_options(fsl_ddr_info_t * pinfo)13145614e71bSYork Sun void check_interleaving_options(fsl_ddr_info_t *pinfo)
13155614e71bSYork Sun {
13165614e71bSYork Sun int i, j, k, check_n_ranks, intlv_invalid = 0;
13175614e71bSYork Sun unsigned int check_intlv, check_n_row_addr, check_n_col_addr;
13185614e71bSYork Sun unsigned long long check_rank_density;
13195614e71bSYork Sun struct dimm_params_s *dimm;
13201d71efbbSYork Sun int first_ctrl = pinfo->first_ctrl;
13211d71efbbSYork Sun int last_ctrl = first_ctrl + pinfo->num_ctrls - 1;
13221d71efbbSYork Sun
13235614e71bSYork Sun /*
13245614e71bSYork Sun * Check if all controllers are configured for memory
13255614e71bSYork Sun * controller interleaving. Identical dimms are recommended. At least
13265614e71bSYork Sun * the size, row and col address should be checked.
13275614e71bSYork Sun */
13285614e71bSYork Sun j = 0;
13291d71efbbSYork Sun check_n_ranks = pinfo->dimm_params[first_ctrl][0].n_ranks;
13301d71efbbSYork Sun check_rank_density = pinfo->dimm_params[first_ctrl][0].rank_density;
13311d71efbbSYork Sun check_n_row_addr = pinfo->dimm_params[first_ctrl][0].n_row_addr;
13321d71efbbSYork Sun check_n_col_addr = pinfo->dimm_params[first_ctrl][0].n_col_addr;
13331d71efbbSYork Sun check_intlv = pinfo->memctl_opts[first_ctrl].memctl_interleaving_mode;
13341d71efbbSYork Sun for (i = first_ctrl; i <= last_ctrl; i++) {
13355614e71bSYork Sun dimm = &pinfo->dimm_params[i][0];
13365614e71bSYork Sun if (!pinfo->memctl_opts[i].memctl_interleaving) {
13375614e71bSYork Sun continue;
13385614e71bSYork Sun } else if (((check_rank_density != dimm->rank_density) ||
13395614e71bSYork Sun (check_n_ranks != dimm->n_ranks) ||
13405614e71bSYork Sun (check_n_row_addr != dimm->n_row_addr) ||
13415614e71bSYork Sun (check_n_col_addr != dimm->n_col_addr) ||
13425614e71bSYork Sun (check_intlv !=
13435614e71bSYork Sun pinfo->memctl_opts[i].memctl_interleaving_mode))){
13445614e71bSYork Sun intlv_invalid = 1;
13455614e71bSYork Sun break;
13465614e71bSYork Sun } else {
13475614e71bSYork Sun j++;
13485614e71bSYork Sun }
13495614e71bSYork Sun
13505614e71bSYork Sun }
13515614e71bSYork Sun if (intlv_invalid) {
13521d71efbbSYork Sun for (i = first_ctrl; i <= last_ctrl; i++)
13535614e71bSYork Sun pinfo->memctl_opts[i].memctl_interleaving = 0;
13545614e71bSYork Sun printf("Not all DIMMs are identical. "
13555614e71bSYork Sun "Memory controller interleaving disabled.\n");
13565614e71bSYork Sun } else {
13575614e71bSYork Sun switch (check_intlv) {
13586b1e1254SYork Sun case FSL_DDR_256B_INTERLEAVING:
13595614e71bSYork Sun case FSL_DDR_CACHE_LINE_INTERLEAVING:
13605614e71bSYork Sun case FSL_DDR_PAGE_INTERLEAVING:
13615614e71bSYork Sun case FSL_DDR_BANK_INTERLEAVING:
13625614e71bSYork Sun case FSL_DDR_SUPERBANK_INTERLEAVING:
136351370d56SYork Sun #if (3 == CONFIG_SYS_NUM_DDR_CTLRS)
13645614e71bSYork Sun k = 2;
1365349689b8SYork Sun #else
136651370d56SYork Sun k = CONFIG_SYS_NUM_DDR_CTLRS;
1367349689b8SYork Sun #endif
13685614e71bSYork Sun break;
13695614e71bSYork Sun case FSL_DDR_3WAY_1KB_INTERLEAVING:
13705614e71bSYork Sun case FSL_DDR_3WAY_4KB_INTERLEAVING:
13715614e71bSYork Sun case FSL_DDR_3WAY_8KB_INTERLEAVING:
13725614e71bSYork Sun case FSL_DDR_4WAY_1KB_INTERLEAVING:
13735614e71bSYork Sun case FSL_DDR_4WAY_4KB_INTERLEAVING:
13745614e71bSYork Sun case FSL_DDR_4WAY_8KB_INTERLEAVING:
13755614e71bSYork Sun default:
137651370d56SYork Sun k = CONFIG_SYS_NUM_DDR_CTLRS;
13775614e71bSYork Sun break;
13785614e71bSYork Sun }
13795614e71bSYork Sun debug("%d of %d controllers are interleaving.\n", j, k);
13805614e71bSYork Sun if (j && (j != k)) {
13811d71efbbSYork Sun for (i = first_ctrl; i <= last_ctrl; i++)
13825614e71bSYork Sun pinfo->memctl_opts[i].memctl_interleaving = 0;
13831d71efbbSYork Sun if ((last_ctrl - first_ctrl) > 1)
13841d71efbbSYork Sun puts("Not all controllers have compatible interleaving mode. All disabled.\n");
13855614e71bSYork Sun }
13865614e71bSYork Sun }
13875614e71bSYork Sun debug("Checking interleaving options completed\n");
13885614e71bSYork Sun }
13895614e71bSYork Sun
fsl_use_spd(void)13905614e71bSYork Sun int fsl_use_spd(void)
13915614e71bSYork Sun {
13925614e71bSYork Sun int use_spd = 0;
13935614e71bSYork Sun
13945614e71bSYork Sun #ifdef CONFIG_DDR_SPD
13955614e71bSYork Sun char buffer[HWCONFIG_BUFFER_SIZE];
13965614e71bSYork Sun char *buf = NULL;
13975614e71bSYork Sun
13985614e71bSYork Sun /*
13995614e71bSYork Sun * Extract hwconfig from environment since we have not properly setup
14005614e71bSYork Sun * the environment but need it for ddr config params
14015614e71bSYork Sun */
1402*00caae6dSSimon Glass if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0)
14035614e71bSYork Sun buf = buffer;
14045614e71bSYork Sun
14055614e71bSYork Sun /* if hwconfig is not enabled, or "sdram" is not defined, use spd */
14065614e71bSYork Sun if (hwconfig_sub_f("fsl_ddr", "sdram", buf)) {
14075614e71bSYork Sun if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", "spd", buf))
14085614e71bSYork Sun use_spd = 1;
14095614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram",
14105614e71bSYork Sun "fixed", buf))
14115614e71bSYork Sun use_spd = 0;
14125614e71bSYork Sun else
14135614e71bSYork Sun use_spd = 1;
14145614e71bSYork Sun } else
14155614e71bSYork Sun use_spd = 1;
14165614e71bSYork Sun #endif
14175614e71bSYork Sun
14185614e71bSYork Sun return use_spd;
14195614e71bSYork Sun }
1420