1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright 2008 Freescale Semiconductor, Inc. 4 */ 5 6 #include <common.h> 7 8 #include <fsl_ddr_sdram.h> 9 #include <fsl_ddr_dimm_params.h> 10 11 struct board_specific_parameters { 12 u32 n_ranks; 13 u32 datarate_mhz_high; 14 u32 clk_adjust; 15 u32 cpo; 16 u32 write_data_delay; 17 u32 force_2t; 18 }; 19 20 /* 21 * This table contains all valid speeds we want to override with board 22 * specific parameters. datarate_mhz_high values need to be in ascending order 23 * for each n_ranks group. 24 * 25 * For DDR2 DIMM, all combinations of clk_adjust and write_data_delay have been 26 * tested. For RDIMM, clk_adjust = 4 and write_data_delay = 3 is optimized for 27 * all clocks from 400MT/s to 800MT/s, verified with Kingston KVR800D2D8P6/2G. 28 * For UDIMM, clk_adjust = 8 and write_delay = 5 is optimized for all clocks 29 * from 400MT/s to 800MT/s, verified with Micron MT18HTF25672AY-800E1. 30 * 31 * CPO value doesn't matter if workaround for errata 111 and 134 enabled. 32 */ 33 static const struct board_specific_parameters udimm0[] = { 34 /* 35 * memory controller 0 36 * num| hi| clk| cpo|wrdata|2T 37 * ranks| mhz|adjst| | delay| 38 */ 39 {2, 333, 8, 7, 5, 0}, 40 {2, 400, 8, 9, 5, 0}, 41 {2, 549, 8, 11, 5, 0}, 42 {2, 680, 8, 10, 5, 0}, 43 {2, 850, 8, 12, 5, 1}, 44 {1, 333, 6, 7, 3, 0}, 45 {1, 400, 6, 9, 3, 0}, 46 {1, 549, 6, 11, 3, 0}, 47 {1, 680, 1, 10, 5, 0}, 48 {1, 850, 1, 12, 5, 0}, 49 {} 50 }; 51 52 static const struct board_specific_parameters udimm1[] = { 53 /* 54 * memory controller 1 55 * num| hi| clk| cpo|wrdata|2T 56 * ranks| mhz|adjst| | delay| 57 */ 58 {2, 333, 8, 7, 5, 0}, 59 {2, 400, 8, 9, 5, 0}, 60 {2, 549, 8, 11, 5, 0}, 61 {2, 680, 8, 11, 5, 0}, 62 {2, 850, 8, 13, 5, 1}, 63 {1, 333, 6, 7, 3, 0}, 64 {1, 400, 6, 9, 3, 0}, 65 {1, 549, 6, 11, 3, 0}, 66 {1, 680, 1, 11, 6, 0}, 67 {1, 850, 1, 13, 6, 0}, 68 {} 69 }; 70 71 static const struct board_specific_parameters *udimms[] = { 72 udimm0, 73 udimm1, 74 }; 75 76 static const struct board_specific_parameters rdimm0[] = { 77 /* 78 * memory controller 0 79 * num| hi| clk| cpo|wrdata|2T 80 * ranks| mhz|adjst| | delay| 81 */ 82 {2, 333, 4, 7, 3, 0}, 83 {2, 400, 4, 9, 3, 0}, 84 {2, 549, 4, 11, 3, 0}, 85 {2, 680, 4, 10, 3, 0}, 86 {2, 850, 4, 12, 3, 1}, 87 {} 88 }; 89 90 static const struct board_specific_parameters rdimm1[] = { 91 /* 92 * memory controller 1 93 * num| hi| clk| cpo|wrdata|2T 94 * ranks| mhz|adjst| | delay| 95 */ 96 {2, 333, 4, 7, 3, 0}, 97 {2, 400, 4, 9, 3, 0}, 98 {2, 549, 4, 11, 3, 0}, 99 {2, 680, 4, 11, 3, 0}, 100 {2, 850, 4, 13, 3, 1}, 101 {} 102 }; 103 104 static const struct board_specific_parameters *rdimms[] = { 105 rdimm0, 106 rdimm1, 107 }; 108 109 void fsl_ddr_board_options(memctl_options_t *popts, 110 dimm_params_t *pdimm, 111 unsigned int ctrl_num) 112 { 113 const struct board_specific_parameters *pbsp, *pbsp_highest = NULL; 114 ulong ddr_freq; 115 116 if (ctrl_num > 1) { 117 printf("Wrong parameter for controller number %d", ctrl_num); 118 return; 119 } 120 if (!pdimm->n_ranks) 121 return; 122 123 if (popts->registered_dimm_en) 124 pbsp = rdimms[ctrl_num]; 125 else 126 pbsp = udimms[ctrl_num]; 127 128 /* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr 129 * freqency and n_banks specified in board_specific_parameters table. 130 */ 131 ddr_freq = get_ddr_freq(0) / 1000000; 132 while (pbsp->datarate_mhz_high) { 133 if (pbsp->n_ranks == pdimm->n_ranks) { 134 if (ddr_freq <= pbsp->datarate_mhz_high) { 135 popts->clk_adjust = pbsp->clk_adjust; 136 popts->cpo_override = pbsp->cpo; 137 popts->write_data_delay = 138 pbsp->write_data_delay; 139 popts->twot_en = pbsp->force_2t; 140 goto found; 141 } 142 pbsp_highest = pbsp; 143 } 144 pbsp++; 145 } 146 147 if (pbsp_highest) { 148 printf("Error: board specific timing not found " 149 "for data rate %lu MT/s!\n" 150 "Trying to use the highest speed (%u) parameters\n", 151 ddr_freq, pbsp_highest->datarate_mhz_high); 152 popts->clk_adjust = pbsp->clk_adjust; 153 popts->cpo_override = pbsp->cpo; 154 popts->write_data_delay = pbsp->write_data_delay; 155 popts->twot_en = pbsp->force_2t; 156 } else { 157 panic("DIMM is not supported by this board"); 158 } 159 160 found: 161 /* 162 * Factors to consider for half-strength driver enable: 163 * - number of DIMMs installed 164 */ 165 popts->half_strength_driver_enable = 0; 166 } 167