2 * Copyright 2008 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: GPL-2.0
9 #include <fsl_ddr_sdram.h>
10 #include <fsl_ddr_dimm_params.h>
12 struct board_specific_parameters {
14 u32 datarate_mhz_high;
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.
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.
32 * CPO value doesn't matter if workaround for errata 111 and 134 enabled.
34 static const struct board_specific_parameters udimm0[] = {
37 * num| hi| clk| cpo|wrdata|2T
38 * ranks| mhz|adjst| | delay|
42 {2, 549, 8, 11, 5, 0},
43 {2, 680, 8, 10, 5, 0},
44 {2, 850, 8, 12, 5, 1},
47 {1, 549, 6, 11, 3, 0},
48 {1, 680, 1, 10, 5, 0},
49 {1, 850, 1, 12, 5, 0},
53 static const struct board_specific_parameters udimm1[] = {
56 * num| hi| clk| cpo|wrdata|2T
57 * ranks| mhz|adjst| | delay|
61 {2, 549, 8, 11, 5, 0},
62 {2, 680, 8, 11, 5, 0},
63 {2, 850, 8, 13, 5, 1},
66 {1, 549, 6, 11, 3, 0},
67 {1, 680, 1, 11, 6, 0},
68 {1, 850, 1, 13, 6, 0},
72 static const struct board_specific_parameters *udimms[] = {
77 static const struct board_specific_parameters rdimm0[] = {
80 * num| hi| clk| cpo|wrdata|2T
81 * ranks| mhz|adjst| | delay|
85 {2, 549, 4, 11, 3, 0},
86 {2, 680, 4, 10, 3, 0},
87 {2, 850, 4, 12, 3, 1},
91 static const struct board_specific_parameters rdimm1[] = {
94 * num| hi| clk| cpo|wrdata|2T
95 * ranks| mhz|adjst| | delay|
99 {2, 549, 4, 11, 3, 0},
100 {2, 680, 4, 11, 3, 0},
101 {2, 850, 4, 13, 3, 1},
105 static const struct board_specific_parameters *rdimms[] = {
110 void fsl_ddr_board_options(memctl_options_t *popts,
111 dimm_params_t *pdimm,
112 unsigned int ctrl_num)
114 const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
118 printf("Wrong parameter for controller number %d", ctrl_num);
124 if (popts->registered_dimm_en)
125 pbsp = rdimms[ctrl_num];
127 pbsp = udimms[ctrl_num];
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.
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;
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;
158 panic("DIMM is not supported by this board");
163 * Factors to consider for half-strength driver enable:
164 * - number of DIMMs installed
166 popts->half_strength_driver_enable = 0;