38f13ce4b2ec39ee30e71015bc044662f6b7e8aa
[platform/kernel/u-boot.git] / board / freescale / corenet_ds / ddr.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2009-2011 Freescale Semiconductor, Inc.
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 /*
18  * Fixed sdram init -- doesn't use serial presence detect.
19  */
20 extern fixed_ddr_parm_t fixed_ddr_parm_0[];
21 #if (CONFIG_SYS_NUM_DDR_CTLRS == 2)
22 extern fixed_ddr_parm_t fixed_ddr_parm_1[];
23 #endif
24
25 phys_size_t fixed_sdram(void)
26 {
27         int i;
28         char buf[32];
29         fsl_ddr_cfg_regs_t ddr_cfg_regs;
30         phys_size_t ddr_size;
31         unsigned int lawbar1_target_id;
32         ulong ddr_freq, ddr_freq_mhz;
33
34         ddr_freq = get_ddr_freq(0);
35         ddr_freq_mhz = ddr_freq / 1000000;
36
37         printf("Configuring DDR for %s MT/s data rate\n",
38                                 strmhz(buf, ddr_freq));
39
40         for (i = 0; fixed_ddr_parm_0[i].max_freq > 0; i++) {
41                 if ((ddr_freq_mhz > fixed_ddr_parm_0[i].min_freq) &&
42                    (ddr_freq_mhz <= fixed_ddr_parm_0[i].max_freq)) {
43                         memcpy(&ddr_cfg_regs,
44                                 fixed_ddr_parm_0[i].ddr_settings,
45                                 sizeof(ddr_cfg_regs));
46                         break;
47                 }
48         }
49
50         if (fixed_ddr_parm_0[i].max_freq == 0)
51                 panic("Unsupported DDR data rate %s MT/s data rate\n",
52                         strmhz(buf, ddr_freq));
53
54         ddr_size = (phys_size_t) CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
55         ddr_cfg_regs.ddr_cdr1 = DDR_CDR1_DHC_EN;
56         fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0, 0);
57
58 #if (CONFIG_SYS_NUM_DDR_CTLRS == 2)
59         memcpy(&ddr_cfg_regs,
60                 fixed_ddr_parm_1[i].ddr_settings,
61                 sizeof(ddr_cfg_regs));
62         ddr_cfg_regs.ddr_cdr1 = DDR_CDR1_DHC_EN;
63         fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 1, 0);
64 #endif
65
66         /*
67          * setup laws for DDR. If not interleaving, presuming half memory on
68          * DDR1 and the other half on DDR2
69          */
70         if (fixed_ddr_parm_0[i].ddr_settings->cs[0].config & 0x20000000) {
71                 if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE,
72                                  ddr_size,
73                                  LAW_TRGT_IF_DDR_INTRLV) < 0) {
74                         printf("ERROR setting Local Access Windows for DDR\n");
75                         return 0;
76                 }
77         } else {
78 #if (CONFIG_SYS_NUM_DDR_CTLRS == 2)
79                 /* We require both controllers have identical DIMMs */
80                 lawbar1_target_id = LAW_TRGT_IF_DDR_1;
81                 if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE,
82                                  ddr_size / 2,
83                                  lawbar1_target_id) < 0) {
84                         printf("ERROR setting Local Access Windows for DDR\n");
85                         return 0;
86                 }
87                 lawbar1_target_id = LAW_TRGT_IF_DDR_2;
88                 if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE + ddr_size / 2,
89                                  ddr_size / 2,
90                                  lawbar1_target_id) < 0) {
91                         printf("ERROR setting Local Access Windows for DDR\n");
92                         return 0;
93                 }
94 #else
95                 lawbar1_target_id = LAW_TRGT_IF_DDR_1;
96                 if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE,
97                                  ddr_size,
98                                  lawbar1_target_id) < 0) {
99                         printf("ERROR setting Local Access Windows for DDR\n");
100                         return 0;
101                 }
102 #endif
103         }
104         return ddr_size;
105 }
106
107 struct board_specific_parameters {
108         u32 n_ranks;
109         u32 datarate_mhz_high;
110         u32 clk_adjust;
111         u32 wrlvl_start;
112         u32 cpo;
113         u32 write_data_delay;
114         u32 force_2t;
115 };
116
117 /*
118  * This table contains all valid speeds we want to override with board
119  * specific parameters. datarate_mhz_high values need to be in ascending order
120  * for each n_ranks group.
121  */
122 static const struct board_specific_parameters udimm0[] = {
123         /*
124          * memory controller 0
125          *   num|  hi|  clk| wrlvl | cpo  |wrdata|2T
126          * ranks| mhz|adjst| start |      |delay |
127          */
128         {4,   850,    4,     6,   0xff,    2,  0},
129         {4,   950,    5,     7,   0xff,    2,  0},
130         {4,  1050,    5,     8,   0xff,    2,  0},
131         {4,  1250,    5,    10,   0xff,    2,  0},
132         {4,  1350,    5,    11,   0xff,    2,  0},
133         {4,  1666,    5,    12,   0xff,    2,  0},
134         {2,   850,    5,     6,   0xff,    2,  0},
135         {2,  1050,    5,     7,   0xff,    2,  0},
136         {2,  1250,    4,     6,   0xff,    2,  0},
137         {2,  1350,    5,     7,   0xff,    2,  0},
138         {2,  1666,    5,     8,   0xff,    2,  0},
139         {1,  1250,    4,     6,   0xff,    2,  0},
140         {1,  1335,    4,     7,   0xff,    2,  0},
141         {1,  1666,    4,     8,   0xff,    2,  0},
142         {}
143 };
144
145 /*
146  * The two slots have slightly different timing. The center values are good
147  * for both slots. We use identical speed tables for them. In future use, if
148  * DIMMs have fewer center values that require two separated tables, copy the
149  * udimm0 table to udimm1 and make changes to clk_adjust and wrlvl_start.
150  */
151 static const struct board_specific_parameters *udimms[] = {
152         udimm0,
153         udimm0,
154 };
155
156 static const struct board_specific_parameters rdimm0[] = {
157         /*
158          * memory controller 0
159          *   num|  hi|  clk| wrlvl | cpo  |wrdata|2T
160          * ranks| mhz|adjst| start |      |delay |
161          */
162         {4,   850,    4,     6,   0xff,    2,  0},
163         {4,   950,    5,     7,   0xff,    2,  0},
164         {4,  1050,    5,     8,   0xff,    2,  0},
165         {4,  1250,    5,    10,   0xff,    2,  0},
166         {4,  1350,    5,    11,   0xff,    2,  0},
167         {4,  1666,    5,    12,   0xff,    2,  0},
168         {2,   850,    4,     6,   0xff,    2,  0},
169         {2,  1050,    4,     7,   0xff,    2,  0},
170         {2,  1666,    4,     8,   0xff,    2,  0},
171         {1,   850,    4,     5,   0xff,    2,  0},
172         {1,   950,    4,     7,   0xff,    2,  0},
173         {1,  1666,    4,     8,   0xff,    2,  0},
174         {}
175 };
176
177 /*
178  * The two slots have slightly different timing. See comments above.
179  */
180 static const struct board_specific_parameters *rdimms[] = {
181         rdimm0,
182         rdimm0,
183 };
184
185 void fsl_ddr_board_options(memctl_options_t *popts,
186                                 dimm_params_t *pdimm,
187                                 unsigned int ctrl_num)
188 {
189         const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
190         ulong ddr_freq;
191
192         if (ctrl_num > 1) {
193                 printf("Wrong parameter for controller number %d", ctrl_num);
194                 return;
195         }
196         if (!pdimm->n_ranks)
197                 return;
198
199         if (popts->registered_dimm_en)
200                 pbsp = rdimms[ctrl_num];
201         else
202                 pbsp = udimms[ctrl_num];
203
204
205         /* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr
206          * freqency and n_banks specified in board_specific_parameters table.
207          */
208         ddr_freq = get_ddr_freq(0) / 1000000;
209         while (pbsp->datarate_mhz_high) {
210                 if (pbsp->n_ranks == pdimm->n_ranks) {
211                         if (ddr_freq <= pbsp->datarate_mhz_high) {
212                                 popts->cpo_override = pbsp->cpo;
213                                 popts->write_data_delay =
214                                         pbsp->write_data_delay;
215                                 popts->clk_adjust = pbsp->clk_adjust;
216                                 popts->wrlvl_start = pbsp->wrlvl_start;
217                                 popts->twot_en = pbsp->force_2t;
218                                 goto found;
219                         }
220                         pbsp_highest = pbsp;
221                 }
222                 pbsp++;
223         }
224
225         if (pbsp_highest) {
226                 printf("Error: board specific timing not found "
227                         "for data rate %lu MT/s!\n"
228                         "Trying to use the highest speed (%u) parameters\n",
229                         ddr_freq, pbsp_highest->datarate_mhz_high);
230                 popts->cpo_override = pbsp_highest->cpo;
231                 popts->write_data_delay = pbsp_highest->write_data_delay;
232                 popts->clk_adjust = pbsp_highest->clk_adjust;
233                 popts->wrlvl_start = pbsp_highest->wrlvl_start;
234                 popts->twot_en = pbsp_highest->force_2t;
235         } else {
236                 panic("DIMM is not supported by this board");
237         }
238 found:
239         /*
240          * Factors to consider for half-strength driver enable:
241          *      - number of DIMMs installed
242          */
243         popts->half_strength_driver_enable = 0;
244         /*
245          * Write leveling override
246          */
247         popts->wrlvl_override = 1;
248         popts->wrlvl_sample = 0xf;
249
250         /*
251          * Rtt and Rtt_WR override
252          */
253         popts->rtt_override = 0;
254
255         /* Enable ZQ calibration */
256         popts->zq_en = 1;
257
258         /* DHC_EN =1, ODT = 60 Ohm */
259         popts->ddr_cdr1 = DDR_CDR1_DHC_EN;
260 }
261
262 int dram_init(void)
263 {
264         phys_size_t dram_size;
265
266         puts("Initializing....");
267
268         if (fsl_use_spd()) {
269                 puts("using SPD\n");
270                 dram_size = fsl_ddr_sdram();
271         } else {
272                 puts("using fixed parameters\n");
273                 dram_size = fixed_sdram();
274         }
275
276         dram_size = setup_ddr_tlbs(dram_size / 0x100000);
277         dram_size *= 0x100000;
278
279         debug("    DDR: ");
280         gd->ram_size = dram_size;
281
282         return 0;
283 }