1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 25614e71bSYork Sun /* 3c0c32af0SYork Sun * Copyright 2008, 2010-2016 Freescale Semiconductor, Inc. 4c0c32af0SYork Sun * Copyright 2017-2018 NXP Semiconductor 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 2100caae6dSSimon 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 */ 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 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 752564e9383SYork Sun #if (CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) 7535614e71bSYork Sun ulong ddr_freq; 754564e9383SYork Sun #endif 7555614e71bSYork Sun 7565614e71bSYork Sun /* 7575614e71bSYork Sun * Extract hwconfig from environment since we have not properly setup 7585614e71bSYork Sun * the environment but need it for ddr config params 7595614e71bSYork Sun */ 76000caae6dSSimon Glass if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0) 7615614e71bSYork Sun buf = buffer; 7625614e71bSYork Sun 76334e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || \ 76434e026f9SYork Sun defined(CONFIG_SYS_FSL_DDR2) || \ 76534e026f9SYork Sun defined(CONFIG_SYS_FSL_DDR4) 7665614e71bSYork Sun /* Chip select options. */ 767349689b8SYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) 7685614e71bSYork Sun switch (pdimm[0].n_ranks) { 7695614e71bSYork Sun case 1: 7705614e71bSYork Sun pdodt = single_S; 7715614e71bSYork Sun break; 7725614e71bSYork Sun case 2: 7735614e71bSYork Sun pdodt = single_D; 7745614e71bSYork Sun break; 7755614e71bSYork Sun case 4: 7765614e71bSYork Sun pdodt = single_Q; 7775614e71bSYork Sun break; 7785614e71bSYork Sun } 779349689b8SYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) 7805614e71bSYork Sun switch (pdimm[0].n_ranks) { 7815614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE 7825614e71bSYork Sun case 4: 7835614e71bSYork Sun pdodt = single_Q; 7845614e71bSYork Sun if (pdimm[1].n_ranks) 785349689b8SYork Sun printf("Error: Quad- and Dual-rank DIMMs cannot be used together\n"); 7865614e71bSYork Sun break; 7875614e71bSYork Sun #endif 7885614e71bSYork Sun case 2: 7895614e71bSYork Sun switch (pdimm[1].n_ranks) { 7905614e71bSYork Sun case 2: 7915614e71bSYork Sun pdodt = dual_DD; 7925614e71bSYork Sun break; 7935614e71bSYork Sun case 1: 7945614e71bSYork Sun pdodt = dual_DS; 7955614e71bSYork Sun break; 7965614e71bSYork Sun case 0: 7975614e71bSYork Sun pdodt = dual_D0; 7985614e71bSYork Sun break; 7995614e71bSYork Sun } 8005614e71bSYork Sun break; 8015614e71bSYork Sun case 1: 8025614e71bSYork Sun switch (pdimm[1].n_ranks) { 8035614e71bSYork Sun case 2: 8045614e71bSYork Sun pdodt = dual_SD; 8055614e71bSYork Sun break; 8065614e71bSYork Sun case 1: 8075614e71bSYork Sun pdodt = dual_SS; 8085614e71bSYork Sun break; 8095614e71bSYork Sun case 0: 8105614e71bSYork Sun pdodt = dual_S0; 8115614e71bSYork Sun break; 8125614e71bSYork Sun } 8135614e71bSYork Sun break; 8145614e71bSYork Sun case 0: 8155614e71bSYork Sun switch (pdimm[1].n_ranks) { 8165614e71bSYork Sun case 2: 8175614e71bSYork Sun pdodt = dual_0D; 8185614e71bSYork Sun break; 8195614e71bSYork Sun case 1: 8205614e71bSYork Sun pdodt = dual_0S; 8215614e71bSYork Sun break; 8225614e71bSYork Sun } 8235614e71bSYork Sun break; 8245614e71bSYork Sun } 825349689b8SYork Sun #endif /* CONFIG_DIMM_SLOTS_PER_CTLR */ 826349689b8SYork Sun #endif /* CONFIG_SYS_FSL_DDR2, 3, 4 */ 8275614e71bSYork Sun 8285614e71bSYork Sun /* Pick chip-select local options. */ 8295614e71bSYork Sun for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { 83034e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || \ 83134e026f9SYork Sun defined(CONFIG_SYS_FSL_DDR2) || \ 83234e026f9SYork Sun defined(CONFIG_SYS_FSL_DDR4) 8335614e71bSYork Sun popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg; 8345614e71bSYork Sun popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg; 8355614e71bSYork Sun popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm; 8365614e71bSYork Sun popts->cs_local_opts[i].odt_rtt_wr = pdodt[i].odt_rtt_wr; 8375614e71bSYork Sun #else 8385614e71bSYork Sun popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER; 8395614e71bSYork Sun popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS; 8405614e71bSYork Sun #endif 8415614e71bSYork Sun popts->cs_local_opts[i].auto_precharge = 0; 8425614e71bSYork Sun } 8435614e71bSYork Sun 8445614e71bSYork Sun /* Pick interleaving mode. */ 8455614e71bSYork Sun 8465614e71bSYork Sun /* 8475614e71bSYork Sun * 0 = no interleaving 8485614e71bSYork Sun * 1 = interleaving between 2 controllers 8495614e71bSYork Sun */ 8505614e71bSYork Sun popts->memctl_interleaving = 0; 8515614e71bSYork Sun 8525614e71bSYork Sun /* 8535614e71bSYork Sun * 0 = cacheline 8545614e71bSYork Sun * 1 = page 8555614e71bSYork Sun * 2 = (logical) bank 8565614e71bSYork Sun * 3 = superbank (only if CS interleaving is enabled) 8575614e71bSYork Sun */ 8585614e71bSYork Sun popts->memctl_interleaving_mode = 0; 8595614e71bSYork Sun 8605614e71bSYork Sun /* 8615614e71bSYork Sun * 0: cacheline: bit 30 of the 36-bit physical addr selects the memctl 8625614e71bSYork Sun * 1: page: bit to the left of the column bits selects the memctl 8635614e71bSYork Sun * 2: bank: bit to the left of the bank bits selects the memctl 8645614e71bSYork Sun * 3: superbank: bit to the left of the chip select selects the memctl 8655614e71bSYork Sun * 8665614e71bSYork Sun * NOTE: ba_intlv (rank interleaving) is independent of memory 8675614e71bSYork Sun * controller interleaving; it is only within a memory controller. 8685614e71bSYork Sun * Must use superbank interleaving if rank interleaving is used and 8695614e71bSYork Sun * memory controller interleaving is enabled. 8705614e71bSYork Sun */ 8715614e71bSYork Sun 8725614e71bSYork Sun /* 8735614e71bSYork Sun * 0 = no 8745614e71bSYork Sun * 0x40 = CS0,CS1 8755614e71bSYork Sun * 0x20 = CS2,CS3 8765614e71bSYork Sun * 0x60 = CS0,CS1 + CS2,CS3 8775614e71bSYork Sun * 0x04 = CS0,CS1,CS2,CS3 8785614e71bSYork Sun */ 8795614e71bSYork Sun popts->ba_intlv_ctl = 0; 8805614e71bSYork Sun 8815614e71bSYork Sun /* Memory Organization Parameters */ 88256848428SYork Sun popts->registered_dimm_en = common_dimm->all_dimms_registered; 8835614e71bSYork Sun 8845614e71bSYork Sun /* Operational Mode Paramters */ 8855614e71bSYork Sun 8865614e71bSYork Sun /* Pick ECC modes */ 8875614e71bSYork Sun popts->ecc_mode = 0; /* 0 = disabled, 1 = enabled */ 8885614e71bSYork Sun #ifdef CONFIG_DDR_ECC 8895614e71bSYork Sun if (hwconfig_sub_f("fsl_ddr", "ecc", buf)) { 8905614e71bSYork Sun if (hwconfig_subarg_cmp_f("fsl_ddr", "ecc", "on", buf)) 8915614e71bSYork Sun popts->ecc_mode = 1; 8925614e71bSYork Sun } else 8935614e71bSYork Sun popts->ecc_mode = 1; 8945614e71bSYork Sun #endif 895b06f6f2fSYork Sun /* 1 = use memory controler to init data */ 896b06f6f2fSYork Sun popts->ecc_init_using_memctl = popts->ecc_mode ? 1 : 0; 8975614e71bSYork Sun 8985614e71bSYork Sun /* 8995614e71bSYork Sun * Choose DQS config 9005614e71bSYork Sun * 0 for DDR1 9015614e71bSYork Sun * 1 for DDR2 9025614e71bSYork Sun */ 9035614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1) 9045614e71bSYork Sun popts->dqs_config = 0; 9055614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2) || defined(CONFIG_SYS_FSL_DDR3) 9065614e71bSYork Sun popts->dqs_config = 1; 9075614e71bSYork Sun #endif 9085614e71bSYork Sun 9095614e71bSYork Sun /* Choose self-refresh during sleep. */ 9105614e71bSYork Sun popts->self_refresh_in_sleep = 1; 9115614e71bSYork Sun 9125614e71bSYork Sun /* Choose dynamic power management mode. */ 9135614e71bSYork Sun popts->dynamic_power = 0; 9145614e71bSYork Sun 9155614e71bSYork Sun /* 9165614e71bSYork Sun * check first dimm for primary sdram width 9175614e71bSYork Sun * presuming all dimms are similar 9185614e71bSYork Sun * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit 9195614e71bSYork Sun */ 9205614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2) 9215614e71bSYork Sun if (pdimm[0].n_ranks != 0) { 9225614e71bSYork Sun if ((pdimm[0].data_width >= 64) && \ 9235614e71bSYork Sun (pdimm[0].data_width <= 72)) 9245614e71bSYork Sun popts->data_bus_width = 0; 9250e0de24bSxypron.glpk@gmx.de else if ((pdimm[0].data_width >= 32) && \ 9265614e71bSYork Sun (pdimm[0].data_width <= 40)) 9275614e71bSYork Sun popts->data_bus_width = 1; 9285614e71bSYork Sun else { 9295614e71bSYork Sun panic("Error: data width %u is invalid!\n", 9305614e71bSYork Sun pdimm[0].data_width); 9315614e71bSYork Sun } 9325614e71bSYork Sun } 9335614e71bSYork Sun #else 9345614e71bSYork Sun if (pdimm[0].n_ranks != 0) { 9355614e71bSYork Sun if (pdimm[0].primary_sdram_width == 64) 9365614e71bSYork Sun popts->data_bus_width = 0; 9375614e71bSYork Sun else if (pdimm[0].primary_sdram_width == 32) 9385614e71bSYork Sun popts->data_bus_width = 1; 9395614e71bSYork Sun else if (pdimm[0].primary_sdram_width == 16) 9405614e71bSYork Sun popts->data_bus_width = 2; 9415614e71bSYork Sun else { 9425614e71bSYork Sun panic("Error: primary sdram width %u is invalid!\n", 9435614e71bSYork Sun pdimm[0].primary_sdram_width); 9445614e71bSYork Sun } 9455614e71bSYork Sun } 9465614e71bSYork Sun #endif 9475614e71bSYork Sun 9485614e71bSYork Sun popts->x4_en = (pdimm[0].device_width == 4) ? 1 : 0; 9495614e71bSYork Sun 9505614e71bSYork Sun /* Choose burst length. */ 95134e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) 9525614e71bSYork Sun #if defined(CONFIG_E500MC) 9535614e71bSYork Sun popts->otf_burst_chop_en = 0; /* on-the-fly burst chop disable */ 9545614e71bSYork Sun popts->burst_length = DDR_BL8; /* Fixed 8-beat burst len */ 9555614e71bSYork Sun #else 9565614e71bSYork Sun if ((popts->data_bus_width == 1) || (popts->data_bus_width == 2)) { 9575614e71bSYork Sun /* 32-bit or 16-bit bus */ 9585614e71bSYork Sun popts->otf_burst_chop_en = 0; 9595614e71bSYork Sun popts->burst_length = DDR_BL8; 9605614e71bSYork Sun } else { 9615614e71bSYork Sun popts->otf_burst_chop_en = 1; /* on-the-fly burst chop */ 9625614e71bSYork Sun popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */ 9635614e71bSYork Sun } 9645614e71bSYork Sun #endif 9655614e71bSYork Sun #else 9665614e71bSYork Sun popts->burst_length = DDR_BL4; /* has to be 4 for DDR2 */ 9675614e71bSYork Sun #endif 9685614e71bSYork Sun 9695614e71bSYork Sun /* Choose ddr controller address mirror mode */ 97034e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) 9716b95be22SYork Sun for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { 9726b95be22SYork Sun if (pdimm[i].n_ranks) { 9736b95be22SYork Sun popts->mirrored_dimm = pdimm[i].mirrored_dimm; 9746b95be22SYork Sun break; 9756b95be22SYork Sun } 9766b95be22SYork Sun } 9775614e71bSYork Sun #endif 9785614e71bSYork Sun 9795614e71bSYork Sun /* Global Timing Parameters. */ 98003e664d8SYork Sun debug("mclk_ps = %u ps\n", get_memory_clk_period_ps(ctrl_num)); 9815614e71bSYork Sun 9825614e71bSYork Sun /* Pick a caslat override. */ 9835614e71bSYork Sun popts->cas_latency_override = 0; 9845614e71bSYork Sun popts->cas_latency_override_value = 3; 9855614e71bSYork Sun if (popts->cas_latency_override) { 9865614e71bSYork Sun debug("using caslat override value = %u\n", 9875614e71bSYork Sun popts->cas_latency_override_value); 9885614e71bSYork Sun } 9895614e71bSYork Sun 9905614e71bSYork Sun /* Decide whether to use the computed derated latency */ 9915614e71bSYork Sun popts->use_derated_caslat = 0; 9925614e71bSYork Sun 9935614e71bSYork Sun /* Choose an additive latency. */ 9945614e71bSYork Sun popts->additive_latency_override = 0; 9955614e71bSYork Sun popts->additive_latency_override_value = 3; 9965614e71bSYork Sun if (popts->additive_latency_override) { 9975614e71bSYork Sun debug("using additive latency override value = %u\n", 9985614e71bSYork Sun popts->additive_latency_override_value); 9995614e71bSYork Sun } 10005614e71bSYork Sun 10015614e71bSYork Sun /* 10025614e71bSYork Sun * 2T_EN setting 10035614e71bSYork Sun * 10045614e71bSYork Sun * Factors to consider for 2T_EN: 10055614e71bSYork Sun * - number of DIMMs installed 10065614e71bSYork Sun * - number of components, number of active ranks 10075614e71bSYork Sun * - how much time you want to spend playing around 10085614e71bSYork Sun */ 10095614e71bSYork Sun popts->twot_en = 0; 10105614e71bSYork Sun popts->threet_en = 0; 10115614e71bSYork Sun 1012eb118807SShengzhou Liu /* for RDIMM and DDR4 UDIMM/discrete memory, address parity enable */ 1013eb118807SShengzhou Liu if (popts->registered_dimm_en) 1014eb118807SShengzhou Liu popts->ap_en = 1; /* 0 = disable, 1 = enable */ 1015eb118807SShengzhou Liu else 1016eb118807SShengzhou Liu popts->ap_en = 0; /* disabled for DDR4 UDIMM/discrete default */ 1017eb118807SShengzhou Liu 1018eb118807SShengzhou Liu if (hwconfig_sub_f("fsl_ddr", "parity", buf)) { 1019eb118807SShengzhou Liu if (hwconfig_subarg_cmp_f("fsl_ddr", "parity", "on", buf)) { 1020eb118807SShengzhou Liu if (popts->registered_dimm_en || 1021eb118807SShengzhou Liu (CONFIG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4)) 10225614e71bSYork Sun popts->ap_en = 1; 1023eb118807SShengzhou Liu } 1024eb118807SShengzhou Liu } 10255614e71bSYork Sun 10265614e71bSYork Sun /* 10275614e71bSYork Sun * BSTTOPRE precharge interval 10285614e71bSYork Sun * 10295614e71bSYork Sun * Set this to 0 for global auto precharge 103034e026f9SYork Sun * The value of 0x100 has been used for DDR1, DDR2, DDR3. 103134e026f9SYork Sun * It is not wrong. Any value should be OK. The performance depends on 103256848428SYork Sun * applications. There is no one good value for all. One way to set 103356848428SYork Sun * is to use 1/4 of refint value. 10345614e71bSYork Sun */ 103556848428SYork Sun popts->bstopre = picos_to_mclk(ctrl_num, common_dimm->refresh_rate_ps) 103656848428SYork Sun >> 2; 10375614e71bSYork Sun 10385614e71bSYork Sun /* 10395614e71bSYork Sun * Window for four activates -- tFAW 10405614e71bSYork Sun * 10415614e71bSYork Sun * FIXME: UM: applies only to DDR2/DDR3 with eight logical banks only 10425614e71bSYork Sun * FIXME: varies depending upon number of column addresses or data 10435614e71bSYork Sun * FIXME: width, was considering looking at pdimm->primary_sdram_width 10445614e71bSYork Sun */ 10455614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1) 104603e664d8SYork Sun popts->tfaw_window_four_activates_ps = mclk_to_picos(ctrl_num, 1); 10475614e71bSYork Sun 10485614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2) 10495614e71bSYork Sun /* 10505614e71bSYork Sun * x4/x8; some datasheets have 35000 10515614e71bSYork Sun * x16 wide columns only? Use 50000? 10525614e71bSYork Sun */ 10535614e71bSYork Sun popts->tfaw_window_four_activates_ps = 37500; 10545614e71bSYork Sun 105534e026f9SYork Sun #else 10565614e71bSYork Sun popts->tfaw_window_four_activates_ps = pdimm[0].tfaw_ps; 10575614e71bSYork Sun #endif 10585614e71bSYork Sun popts->zq_en = 0; 10595614e71bSYork Sun popts->wrlvl_en = 0; 106034e026f9SYork Sun #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) 10615614e71bSYork Sun /* 10625614e71bSYork Sun * due to ddr3 dimm is fly-by topology 10635614e71bSYork Sun * we suggest to enable write leveling to 10645614e71bSYork Sun * meet the tQDSS under different loading. 10655614e71bSYork Sun */ 10665614e71bSYork Sun popts->wrlvl_en = 1; 10675614e71bSYork Sun popts->zq_en = 1; 10685614e71bSYork Sun popts->wrlvl_override = 0; 10695614e71bSYork Sun #endif 10705614e71bSYork Sun 10715614e71bSYork Sun /* 10725614e71bSYork Sun * Check interleaving configuration from environment. 10735614e71bSYork Sun * Please refer to doc/README.fsl-ddr for the detail. 10745614e71bSYork Sun * 10755614e71bSYork Sun * If memory controller interleaving is enabled, then the data 10765614e71bSYork Sun * bus widths must be programmed identically for all memory controllers. 10775614e71bSYork Sun * 10786b1e1254SYork Sun * Attempt to set all controllers to the same chip select 10795614e71bSYork Sun * interleaving mode. It will do a best effort to get the 10805614e71bSYork Sun * requested ranks interleaved together such that the result 10815614e71bSYork Sun * should be a subset of the requested configuration. 10826b1e1254SYork Sun * 10836b1e1254SYork Sun * if CONFIG_SYS_FSL_DDR_INTLV_256B is defined, mandatory interleaving 10846b1e1254SYork Sun * with 256 Byte is enabled. 10855614e71bSYork Sun */ 108651370d56SYork Sun #if (CONFIG_SYS_NUM_DDR_CTLRS > 1) 10875614e71bSYork Sun if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf)) 10886b1e1254SYork Sun #ifdef CONFIG_SYS_FSL_DDR_INTLV_256B 10896b1e1254SYork Sun ; 10906b1e1254SYork Sun #else 10915614e71bSYork Sun goto done; 10926b1e1254SYork Sun #endif 10935614e71bSYork Sun if (pdimm[0].n_ranks == 0) { 10945614e71bSYork Sun printf("There is no rank on CS0 for controller %d.\n", ctrl_num); 10955614e71bSYork Sun popts->memctl_interleaving = 0; 10965614e71bSYork Sun goto done; 10975614e71bSYork Sun } 10985614e71bSYork Sun popts->memctl_interleaving = 1; 10996b1e1254SYork Sun #ifdef CONFIG_SYS_FSL_DDR_INTLV_256B 11006b1e1254SYork Sun popts->memctl_interleaving_mode = FSL_DDR_256B_INTERLEAVING; 11016b1e1254SYork Sun popts->memctl_interleaving = 1; 11026b1e1254SYork Sun debug("256 Byte interleaving\n"); 1103349689b8SYork Sun #else 11045614e71bSYork Sun /* 11055614e71bSYork Sun * test null first. if CONFIG_HWCONFIG is not defined 11065614e71bSYork Sun * hwconfig_arg_cmp returns non-zero 11075614e71bSYork Sun */ 11085614e71bSYork Sun if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", 11095614e71bSYork Sun "null", buf)) { 11105614e71bSYork Sun popts->memctl_interleaving = 0; 11115614e71bSYork Sun debug("memory controller interleaving disabled.\n"); 11125614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr", 11135614e71bSYork Sun "ctlr_intlv", 11145614e71bSYork Sun "cacheline", buf)) { 11155614e71bSYork Sun popts->memctl_interleaving_mode = 111651370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ? 11175614e71bSYork Sun 0 : FSL_DDR_CACHE_LINE_INTERLEAVING; 11185614e71bSYork Sun popts->memctl_interleaving = 111951370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ? 11205614e71bSYork Sun 0 : 1; 11215614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr", 11225614e71bSYork Sun "ctlr_intlv", 11235614e71bSYork Sun "page", buf)) { 11245614e71bSYork Sun popts->memctl_interleaving_mode = 112551370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ? 11265614e71bSYork Sun 0 : FSL_DDR_PAGE_INTERLEAVING; 11275614e71bSYork Sun popts->memctl_interleaving = 112851370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ? 11295614e71bSYork Sun 0 : 1; 11305614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr", 11315614e71bSYork Sun "ctlr_intlv", 11325614e71bSYork Sun "bank", buf)) { 11335614e71bSYork Sun popts->memctl_interleaving_mode = 113451370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ? 11355614e71bSYork Sun 0 : FSL_DDR_BANK_INTERLEAVING; 11365614e71bSYork Sun popts->memctl_interleaving = 113751370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ? 11385614e71bSYork Sun 0 : 1; 11395614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr", 11405614e71bSYork Sun "ctlr_intlv", 11415614e71bSYork Sun "superbank", buf)) { 11425614e71bSYork Sun popts->memctl_interleaving_mode = 114351370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ? 11445614e71bSYork Sun 0 : FSL_DDR_SUPERBANK_INTERLEAVING; 11455614e71bSYork Sun popts->memctl_interleaving = 114651370d56SYork Sun ((CONFIG_SYS_NUM_DDR_CTLRS == 3) && ctrl_num == 2) ? 11475614e71bSYork Sun 0 : 1; 114851370d56SYork Sun #if (CONFIG_SYS_NUM_DDR_CTLRS == 3) 11495614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr", 11505614e71bSYork Sun "ctlr_intlv", 11515614e71bSYork Sun "3way_1KB", buf)) { 11525614e71bSYork Sun popts->memctl_interleaving_mode = 11535614e71bSYork Sun FSL_DDR_3WAY_1KB_INTERLEAVING; 11545614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr", 11555614e71bSYork Sun "ctlr_intlv", 11565614e71bSYork Sun "3way_4KB", buf)) { 11575614e71bSYork Sun popts->memctl_interleaving_mode = 11585614e71bSYork Sun FSL_DDR_3WAY_4KB_INTERLEAVING; 11595614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr", 11605614e71bSYork Sun "ctlr_intlv", 11615614e71bSYork Sun "3way_8KB", buf)) { 11625614e71bSYork Sun popts->memctl_interleaving_mode = 11635614e71bSYork Sun FSL_DDR_3WAY_8KB_INTERLEAVING; 116451370d56SYork Sun #elif (CONFIG_SYS_NUM_DDR_CTLRS == 4) 11655614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr", 11665614e71bSYork Sun "ctlr_intlv", 11675614e71bSYork Sun "4way_1KB", buf)) { 11685614e71bSYork Sun popts->memctl_interleaving_mode = 11695614e71bSYork Sun FSL_DDR_4WAY_1KB_INTERLEAVING; 11705614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr", 11715614e71bSYork Sun "ctlr_intlv", 11725614e71bSYork Sun "4way_4KB", buf)) { 11735614e71bSYork Sun popts->memctl_interleaving_mode = 11745614e71bSYork Sun FSL_DDR_4WAY_4KB_INTERLEAVING; 11755614e71bSYork Sun } else if (hwconfig_subarg_cmp_f("fsl_ddr", 11765614e71bSYork Sun "ctlr_intlv", 11775614e71bSYork Sun "4way_8KB", buf)) { 11785614e71bSYork Sun popts->memctl_interleaving_mode = 11795614e71bSYork Sun FSL_DDR_4WAY_8KB_INTERLEAVING; 11805614e71bSYork Sun #endif 11815614e71bSYork Sun } else { 11825614e71bSYork Sun popts->memctl_interleaving = 0; 11835614e71bSYork Sun printf("hwconfig has unrecognized parameter for ctlr_intlv.\n"); 11845614e71bSYork Sun } 1185349689b8SYork Sun #endif /* CONFIG_SYS_FSL_DDR_INTLV_256B */ 11865614e71bSYork Sun done: 118751370d56SYork Sun #endif /* CONFIG_SYS_NUM_DDR_CTLRS > 1 */ 11885614e71bSYork Sun if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) && 11895614e71bSYork Sun (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) { 11905614e71bSYork Sun /* test null first. if CONFIG_HWCONFIG is not defined, 11915614e71bSYork Sun * hwconfig_subarg_cmp_f returns non-zero */ 11925614e71bSYork Sun if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", 11935614e71bSYork Sun "null", buf)) 11945614e71bSYork Sun debug("bank interleaving disabled.\n"); 11955614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", 11965614e71bSYork Sun "cs0_cs1", buf)) 11975614e71bSYork Sun popts->ba_intlv_ctl = FSL_DDR_CS0_CS1; 11985614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", 11995614e71bSYork Sun "cs2_cs3", buf)) 12005614e71bSYork Sun popts->ba_intlv_ctl = FSL_DDR_CS2_CS3; 12015614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", 12025614e71bSYork Sun "cs0_cs1_and_cs2_cs3", buf)) 12035614e71bSYork Sun popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3; 12045614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", 12055614e71bSYork Sun "cs0_cs1_cs2_cs3", buf)) 12065614e71bSYork Sun popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3; 12075614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", 12085614e71bSYork Sun "auto", buf)) 12095614e71bSYork Sun popts->ba_intlv_ctl = auto_bank_intlv(pdimm); 12105614e71bSYork Sun else 12115614e71bSYork Sun printf("hwconfig has unrecognized parameter for bank_intlv.\n"); 12125614e71bSYork Sun switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { 12135614e71bSYork Sun case FSL_DDR_CS0_CS1_CS2_CS3: 12145614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) 12155614e71bSYork Sun if (pdimm[0].n_ranks < 4) { 12165614e71bSYork Sun popts->ba_intlv_ctl = 0; 12175614e71bSYork Sun printf("Not enough bank(chip-select) for " 12185614e71bSYork Sun "CS0+CS1+CS2+CS3 on controller %d, " 12195614e71bSYork Sun "interleaving disabled!\n", ctrl_num); 12205614e71bSYork Sun } 12215614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) 12225614e71bSYork Sun #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE 12235614e71bSYork Sun if (pdimm[0].n_ranks == 4) 12245614e71bSYork Sun break; 12255614e71bSYork Sun #endif 12265614e71bSYork Sun if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) { 12275614e71bSYork Sun popts->ba_intlv_ctl = 0; 12285614e71bSYork Sun printf("Not enough bank(chip-select) for " 12295614e71bSYork Sun "CS0+CS1+CS2+CS3 on controller %d, " 12305614e71bSYork Sun "interleaving disabled!\n", ctrl_num); 12315614e71bSYork Sun } 12325614e71bSYork Sun if (pdimm[0].capacity != pdimm[1].capacity) { 12335614e71bSYork Sun popts->ba_intlv_ctl = 0; 12345614e71bSYork Sun printf("Not identical DIMM size for " 12355614e71bSYork Sun "CS0+CS1+CS2+CS3 on controller %d, " 12365614e71bSYork Sun "interleaving disabled!\n", ctrl_num); 12375614e71bSYork Sun } 12385614e71bSYork Sun #endif 12395614e71bSYork Sun break; 12405614e71bSYork Sun case FSL_DDR_CS0_CS1: 12415614e71bSYork Sun if (pdimm[0].n_ranks < 2) { 12425614e71bSYork Sun popts->ba_intlv_ctl = 0; 12435614e71bSYork Sun printf("Not enough bank(chip-select) for " 12445614e71bSYork Sun "CS0+CS1 on controller %d, " 12455614e71bSYork Sun "interleaving disabled!\n", ctrl_num); 12465614e71bSYork Sun } 12475614e71bSYork Sun break; 12485614e71bSYork Sun case FSL_DDR_CS2_CS3: 12495614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) 12505614e71bSYork Sun if (pdimm[0].n_ranks < 4) { 12515614e71bSYork Sun popts->ba_intlv_ctl = 0; 12525614e71bSYork Sun printf("Not enough bank(chip-select) for CS2+CS3 " 12535614e71bSYork Sun "on controller %d, interleaving disabled!\n", ctrl_num); 12545614e71bSYork Sun } 12555614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) 12565614e71bSYork Sun if (pdimm[1].n_ranks < 2) { 12575614e71bSYork Sun popts->ba_intlv_ctl = 0; 12585614e71bSYork Sun printf("Not enough bank(chip-select) for CS2+CS3 " 12595614e71bSYork Sun "on controller %d, interleaving disabled!\n", ctrl_num); 12605614e71bSYork Sun } 12615614e71bSYork Sun #endif 12625614e71bSYork Sun break; 12635614e71bSYork Sun case FSL_DDR_CS0_CS1_AND_CS2_CS3: 12645614e71bSYork Sun #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) 12655614e71bSYork Sun if (pdimm[0].n_ranks < 4) { 12665614e71bSYork Sun popts->ba_intlv_ctl = 0; 12675614e71bSYork Sun printf("Not enough bank(CS) for CS0+CS1 and " 12685614e71bSYork Sun "CS2+CS3 on controller %d, " 12695614e71bSYork Sun "interleaving disabled!\n", ctrl_num); 12705614e71bSYork Sun } 12715614e71bSYork Sun #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) 12725614e71bSYork Sun if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) { 12735614e71bSYork Sun popts->ba_intlv_ctl = 0; 12745614e71bSYork Sun printf("Not enough bank(CS) for CS0+CS1 and " 12755614e71bSYork Sun "CS2+CS3 on controller %d, " 12765614e71bSYork Sun "interleaving disabled!\n", ctrl_num); 12775614e71bSYork Sun } 12785614e71bSYork Sun #endif 12795614e71bSYork Sun break; 12805614e71bSYork Sun default: 12815614e71bSYork Sun popts->ba_intlv_ctl = 0; 12825614e71bSYork Sun break; 12835614e71bSYork Sun } 12845614e71bSYork Sun } 12855614e71bSYork Sun 12865614e71bSYork Sun if (hwconfig_sub_f("fsl_ddr", "addr_hash", buf)) { 12875614e71bSYork Sun if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", "null", buf)) 12885614e71bSYork Sun popts->addr_hash = 0; 12895614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", 12905614e71bSYork Sun "true", buf)) 12915614e71bSYork Sun popts->addr_hash = 1; 12925614e71bSYork Sun } 12935614e71bSYork Sun 12945614e71bSYork Sun if (pdimm[0].n_ranks == 4) 12955614e71bSYork Sun popts->quad_rank_present = 1; 12965614e71bSYork Sun 1297c0c32af0SYork Sun popts->package_3ds = pdimm->package_3ds; 1298c0c32af0SYork Sun 1299564e9383SYork Sun #if (CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) 130003e664d8SYork Sun ddr_freq = get_ddr_freq(ctrl_num) / 1000000; 13015614e71bSYork Sun if (popts->registered_dimm_en) { 13025614e71bSYork Sun popts->rcw_override = 1; 13035614e71bSYork Sun popts->rcw_1 = 0x000a5a00; 13045614e71bSYork Sun if (ddr_freq <= 800) 13055614e71bSYork Sun popts->rcw_2 = 0x00000000; 13065614e71bSYork Sun else if (ddr_freq <= 1066) 13075614e71bSYork Sun popts->rcw_2 = 0x00100000; 13085614e71bSYork Sun else if (ddr_freq <= 1333) 13095614e71bSYork Sun popts->rcw_2 = 0x00200000; 13105614e71bSYork Sun else 13115614e71bSYork Sun popts->rcw_2 = 0x00300000; 13125614e71bSYork Sun } 1313564e9383SYork Sun #endif 13145614e71bSYork Sun 13155614e71bSYork Sun fsl_ddr_board_options(popts, pdimm, ctrl_num); 13165614e71bSYork Sun 13175614e71bSYork Sun return 0; 13185614e71bSYork Sun } 13195614e71bSYork Sun 13205614e71bSYork Sun void check_interleaving_options(fsl_ddr_info_t *pinfo) 13215614e71bSYork Sun { 13225614e71bSYork Sun int i, j, k, check_n_ranks, intlv_invalid = 0; 13235614e71bSYork Sun unsigned int check_intlv, check_n_row_addr, check_n_col_addr; 13245614e71bSYork Sun unsigned long long check_rank_density; 13255614e71bSYork Sun struct dimm_params_s *dimm; 13261d71efbbSYork Sun int first_ctrl = pinfo->first_ctrl; 13271d71efbbSYork Sun int last_ctrl = first_ctrl + pinfo->num_ctrls - 1; 13281d71efbbSYork Sun 13295614e71bSYork Sun /* 13305614e71bSYork Sun * Check if all controllers are configured for memory 13315614e71bSYork Sun * controller interleaving. Identical dimms are recommended. At least 13325614e71bSYork Sun * the size, row and col address should be checked. 13335614e71bSYork Sun */ 13345614e71bSYork Sun j = 0; 13351d71efbbSYork Sun check_n_ranks = pinfo->dimm_params[first_ctrl][0].n_ranks; 13361d71efbbSYork Sun check_rank_density = pinfo->dimm_params[first_ctrl][0].rank_density; 13371d71efbbSYork Sun check_n_row_addr = pinfo->dimm_params[first_ctrl][0].n_row_addr; 13381d71efbbSYork Sun check_n_col_addr = pinfo->dimm_params[first_ctrl][0].n_col_addr; 13391d71efbbSYork Sun check_intlv = pinfo->memctl_opts[first_ctrl].memctl_interleaving_mode; 13401d71efbbSYork Sun for (i = first_ctrl; i <= last_ctrl; i++) { 13415614e71bSYork Sun dimm = &pinfo->dimm_params[i][0]; 13425614e71bSYork Sun if (!pinfo->memctl_opts[i].memctl_interleaving) { 13435614e71bSYork Sun continue; 13445614e71bSYork Sun } else if (((check_rank_density != dimm->rank_density) || 13455614e71bSYork Sun (check_n_ranks != dimm->n_ranks) || 13465614e71bSYork Sun (check_n_row_addr != dimm->n_row_addr) || 13475614e71bSYork Sun (check_n_col_addr != dimm->n_col_addr) || 13485614e71bSYork Sun (check_intlv != 13495614e71bSYork Sun pinfo->memctl_opts[i].memctl_interleaving_mode))){ 13505614e71bSYork Sun intlv_invalid = 1; 13515614e71bSYork Sun break; 13525614e71bSYork Sun } else { 13535614e71bSYork Sun j++; 13545614e71bSYork Sun } 13555614e71bSYork Sun 13565614e71bSYork Sun } 13575614e71bSYork Sun if (intlv_invalid) { 13581d71efbbSYork Sun for (i = first_ctrl; i <= last_ctrl; i++) 13595614e71bSYork Sun pinfo->memctl_opts[i].memctl_interleaving = 0; 13605614e71bSYork Sun printf("Not all DIMMs are identical. " 13615614e71bSYork Sun "Memory controller interleaving disabled.\n"); 13625614e71bSYork Sun } else { 13635614e71bSYork Sun switch (check_intlv) { 13646b1e1254SYork Sun case FSL_DDR_256B_INTERLEAVING: 13655614e71bSYork Sun case FSL_DDR_CACHE_LINE_INTERLEAVING: 13665614e71bSYork Sun case FSL_DDR_PAGE_INTERLEAVING: 13675614e71bSYork Sun case FSL_DDR_BANK_INTERLEAVING: 13685614e71bSYork Sun case FSL_DDR_SUPERBANK_INTERLEAVING: 136951370d56SYork Sun #if (3 == CONFIG_SYS_NUM_DDR_CTLRS) 13705614e71bSYork Sun k = 2; 1371349689b8SYork Sun #else 137251370d56SYork Sun k = CONFIG_SYS_NUM_DDR_CTLRS; 1373349689b8SYork Sun #endif 13745614e71bSYork Sun break; 13755614e71bSYork Sun case FSL_DDR_3WAY_1KB_INTERLEAVING: 13765614e71bSYork Sun case FSL_DDR_3WAY_4KB_INTERLEAVING: 13775614e71bSYork Sun case FSL_DDR_3WAY_8KB_INTERLEAVING: 13785614e71bSYork Sun case FSL_DDR_4WAY_1KB_INTERLEAVING: 13795614e71bSYork Sun case FSL_DDR_4WAY_4KB_INTERLEAVING: 13805614e71bSYork Sun case FSL_DDR_4WAY_8KB_INTERLEAVING: 13815614e71bSYork Sun default: 138251370d56SYork Sun k = CONFIG_SYS_NUM_DDR_CTLRS; 13835614e71bSYork Sun break; 13845614e71bSYork Sun } 13855614e71bSYork Sun debug("%d of %d controllers are interleaving.\n", j, k); 13865614e71bSYork Sun if (j && (j != k)) { 13871d71efbbSYork Sun for (i = first_ctrl; i <= last_ctrl; i++) 13885614e71bSYork Sun pinfo->memctl_opts[i].memctl_interleaving = 0; 13891d71efbbSYork Sun if ((last_ctrl - first_ctrl) > 1) 13901d71efbbSYork Sun puts("Not all controllers have compatible interleaving mode. All disabled.\n"); 13915614e71bSYork Sun } 13925614e71bSYork Sun } 13935614e71bSYork Sun debug("Checking interleaving options completed\n"); 13945614e71bSYork Sun } 13955614e71bSYork Sun 13965614e71bSYork Sun int fsl_use_spd(void) 13975614e71bSYork Sun { 13985614e71bSYork Sun int use_spd = 0; 13995614e71bSYork Sun 14005614e71bSYork Sun #ifdef CONFIG_DDR_SPD 14015614e71bSYork Sun char buffer[HWCONFIG_BUFFER_SIZE]; 14025614e71bSYork Sun char *buf = NULL; 14035614e71bSYork Sun 14045614e71bSYork Sun /* 14055614e71bSYork Sun * Extract hwconfig from environment since we have not properly setup 14065614e71bSYork Sun * the environment but need it for ddr config params 14075614e71bSYork Sun */ 140800caae6dSSimon Glass if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0) 14095614e71bSYork Sun buf = buffer; 14105614e71bSYork Sun 14115614e71bSYork Sun /* if hwconfig is not enabled, or "sdram" is not defined, use spd */ 14125614e71bSYork Sun if (hwconfig_sub_f("fsl_ddr", "sdram", buf)) { 14135614e71bSYork Sun if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", "spd", buf)) 14145614e71bSYork Sun use_spd = 1; 14155614e71bSYork Sun else if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", 14165614e71bSYork Sun "fixed", buf)) 14175614e71bSYork Sun use_spd = 0; 14185614e71bSYork Sun else 14195614e71bSYork Sun use_spd = 1; 14205614e71bSYork Sun } else 14215614e71bSYork Sun use_spd = 1; 14225614e71bSYork Sun #endif 14235614e71bSYork Sun 14245614e71bSYork Sun return use_spd; 14255614e71bSYork Sun } 1426