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> 12*457e51cfSSimon Glass #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \ 13*457e51cfSSimon 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 215614e71bSYork Sun * enough. However we will get a warning from getenv_f for the later. 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 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 */ 7585614e71bSYork Sun if (getenv_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 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 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 */ 14025614e71bSYork Sun if (getenv_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