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