1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Based on corenet_ds ddr code 4 */ 5 6 #include <common.h> 7 #include <i2c.h> 8 #include <hwconfig.h> 9 #include <asm/mmu.h> 10 #include <fsl_ddr_sdram.h> 11 #include <fsl_ddr_dimm_params.h> 12 #include <asm/fsl_law.h> 13 14 DECLARE_GLOBAL_DATA_PTR; 15 16 17 struct board_specific_parameters { 18 u32 n_ranks; 19 u32 datarate_mhz_high; 20 u32 clk_adjust; 21 u32 wrlvl_start; 22 u32 cpo; 23 u32 write_data_delay; 24 u32 force_2t; 25 }; 26 27 /* 28 * This table contains all valid speeds we want to override with board 29 * specific parameters. datarate_mhz_high values need to be in ascending order 30 * for each n_ranks group. 31 */ 32 static const struct board_specific_parameters udimm0[] = { 33 /* 34 * memory controller 0 35 * num| hi| clk| wrlvl | cpo |wrdata|2T 36 * ranks| mhz|adjst| start | |delay | 37 */ 38 {4, 850, 4, 6, 0xff, 2, 0}, 39 {4, 950, 5, 7, 0xff, 2, 0}, 40 {4, 1050, 5, 8, 0xff, 2, 0}, 41 {4, 1250, 5, 10, 0xff, 2, 0}, 42 {4, 1350, 5, 11, 0xff, 2, 0}, 43 {4, 1666, 5, 12, 0xff, 2, 0}, 44 {2, 850, 5, 6, 0xff, 2, 0}, 45 {2, 1050, 5, 7, 0xff, 2, 0}, 46 {2, 1250, 4, 6, 0xff, 2, 0}, 47 {2, 1350, 5, 7, 0xff, 2, 0}, 48 {2, 1666, 5, 8, 0xff, 2, 0}, 49 {1, 1250, 4, 6, 0xff, 2, 0}, 50 {1, 1335, 4, 7, 0xff, 2, 0}, 51 {1, 1666, 4, 8, 0xff, 2, 0}, 52 {} 53 }; 54 55 /* 56 * The two slots have slightly different timing. The center values are good 57 * for both slots. We use identical speed tables for them. In future use, if 58 * DIMMs have fewer center values that require two separated tables, copy the 59 * udimm0 table to udimm1 and make changes to clk_adjust and wrlvl_start. 60 */ 61 static const struct board_specific_parameters *udimms[] = { 62 udimm0, 63 udimm0, 64 }; 65 66 static const struct board_specific_parameters rdimm0[] = { 67 /* 68 * memory controller 0 69 * num| hi| clk| wrlvl | cpo |wrdata|2T 70 * ranks| mhz|adjst| start | |delay | 71 */ 72 {4, 850, 4, 6, 0xff, 2, 0}, 73 {4, 950, 5, 7, 0xff, 2, 0}, 74 {4, 1050, 5, 8, 0xff, 2, 0}, 75 {4, 1250, 5, 10, 0xff, 2, 0}, 76 {4, 1350, 5, 11, 0xff, 2, 0}, 77 {4, 1666, 5, 12, 0xff, 2, 0}, 78 {2, 850, 4, 6, 0xff, 2, 0}, 79 {2, 1050, 4, 7, 0xff, 2, 0}, 80 {2, 1666, 4, 8, 0xff, 2, 0}, 81 {1, 850, 4, 5, 0xff, 2, 0}, 82 {1, 950, 4, 7, 0xff, 2, 0}, 83 {1, 1666, 4, 8, 0xff, 2, 0}, 84 {} 85 }; 86 87 /* 88 * The two slots have slightly different timing. See comments above. 89 */ 90 static const struct board_specific_parameters *rdimms[] = { 91 rdimm0, 92 rdimm0, 93 }; 94 95 void fsl_ddr_board_options(memctl_options_t *popts, 96 dimm_params_t *pdimm, 97 unsigned int ctrl_num) 98 { 99 const struct board_specific_parameters *pbsp, *pbsp_highest = NULL; 100 ulong ddr_freq; 101 102 if (ctrl_num > 1) { 103 printf("Wrong parameter for controller number %d", ctrl_num); 104 return; 105 } 106 if (!pdimm->n_ranks) 107 return; 108 109 if (popts->registered_dimm_en) 110 pbsp = rdimms[ctrl_num]; 111 else 112 pbsp = udimms[ctrl_num]; 113 114 115 /* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr 116 * freqency and n_banks specified in board_specific_parameters table. 117 */ 118 ddr_freq = get_ddr_freq(0) / 1000000; 119 while (pbsp->datarate_mhz_high) { 120 if (pbsp->n_ranks == pdimm->n_ranks) { 121 if (ddr_freq <= pbsp->datarate_mhz_high) { 122 popts->cpo_override = pbsp->cpo; 123 popts->write_data_delay = 124 pbsp->write_data_delay; 125 popts->clk_adjust = pbsp->clk_adjust; 126 popts->wrlvl_start = pbsp->wrlvl_start; 127 popts->twot_en = pbsp->force_2t; 128 goto found; 129 } 130 pbsp_highest = pbsp; 131 } 132 pbsp++; 133 } 134 135 if (pbsp_highest) { 136 printf("Error: board specific timing not found for data rate %lu MT/s!\nTrying to use the highest speed (%u) parameters\n", 137 ddr_freq, pbsp_highest->datarate_mhz_high); 138 popts->cpo_override = pbsp_highest->cpo; 139 popts->write_data_delay = pbsp_highest->write_data_delay; 140 popts->clk_adjust = pbsp_highest->clk_adjust; 141 popts->wrlvl_start = pbsp_highest->wrlvl_start; 142 popts->twot_en = pbsp_highest->force_2t; 143 } else { 144 panic("DIMM is not supported by this board"); 145 } 146 found: 147 /* 148 * Factors to consider for half-strength driver enable: 149 * - number of DIMMs installed 150 */ 151 popts->half_strength_driver_enable = 0; 152 /* 153 * Write leveling override 154 */ 155 popts->wrlvl_override = 1; 156 popts->wrlvl_sample = 0xf; 157 158 /* 159 * Rtt and Rtt_WR override 160 */ 161 popts->rtt_override = 0; 162 163 /* Enable ZQ calibration */ 164 popts->zq_en = 1; 165 166 /* DHC_EN =1, ODT = 60 Ohm */ 167 popts->ddr_cdr1 = DDR_CDR1_DHC_EN; 168 } 169 170 int dram_init(void) 171 { 172 phys_size_t dram_size; 173 174 puts("Initializing...."); 175 176 if (!fsl_use_spd()) 177 panic("Cyrus only supports using SPD for DRAM\n"); 178 179 puts("using SPD\n"); 180 dram_size = fsl_ddr_sdram(); 181 182 dram_size = setup_ddr_tlbs(dram_size / 0x100000); 183 dram_size *= 0x100000; 184 185 debug(" DDR: "); 186 gd->ram_size = dram_size; 187 188 return 0; 189 } 190