blob: cd7e95e61d002139e358e68ee57b8217a5759881 [file] [log] [blame]
Lukasz Majewski548cc102018-12-05 17:04:02 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * ddrmc DDR3 calibration code for NXP's VF610
4 *
5 * Copyright (C) 2018 DENX Software Engineering
6 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
7 *
8 */
9/* #define DEBUG */
10#include <common.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060011#include <log.h>
Lukasz Majewski548cc102018-12-05 17:04:02 +010012#include <asm/io.h>
13#include <asm/arch/imx-regs.h>
14#include <linux/bitmap.h>
15
16#include "ddrmc-vf610-calibration.h"
17
18/*
19 * Documents:
20 *
21 * [1] "Vybrid: About DDR leveling feature on DDRMC."
22 * https://community.nxp.com/thread/395323
23 *
24 * [2] VFxxx Controller Reference Manual, Rev. 0, 10/2016
25 *
26 *
27 * NOTE
28 * ====
29 *
30 * NXP recommends setting 'fixed' parameters instead of performing the
31 * training at each boot.
32 *
33 * Use those functions to determine those values on new HW, read the
34 * calculated value from registers and add them to the board specific
35 * struct ddrmc_cr_setting.
36 *
37 * SW leveling supported operations - CR93[SW_LVL_MODE]:
38 *
39 * - 0x0 (b'00) - No leveling
40 *
41 * - 0x1 (b'01) - WRLVL_DL_X - It is not recommended to perform this tuning
42 * on HW designs utilizing non-flyback topology
43 * (Single DDR3 with x16).
44 * Instead the WRLVL_DL_0/1 fields shall be set
45 * based on trace length differences from their
46 * layout.
47 * Mismatches up to 25% or tCK (clock period) are
48 * allowed, so the value in the filed doesn’t have
49 * to be very accurate.
50 *
51 * - 0x2 (b'10) - RDLVL_DL_0/1 - refers to adjusting the DQS strobe in relation
52 * to the DQ signals so that the strobe edge is
53 * centered in the window of valid read data.
54 *
55 * - 0x3 (b'11) - RDLVL_GTDL_0/1 - refers to the delay the PHY uses to un-gate
56 * the Read DQS strobe pad from the time that the
57 * PHY enables the pad to input the strobe signal.
58 *
59 */
60static int ddr_cal_get_first_edge_index(unsigned long *bmap, enum edge e,
61 int samples, int start, int max)
62{
63 int i, ret = -1;
64
65 /*
66 * We look only for the first value (and filter out
67 * some wrong data)
68 */
69 switch (e) {
70 case RISING_EDGE:
71 for (i = start; i <= max - samples; i++) {
72 if (test_bit(i, bmap)) {
73 if (!test_bit(i - 1, bmap) &&
74 test_bit(i + 1, bmap) &&
75 test_bit(i + 2, bmap) &&
76 test_bit(i + 3, bmap)) {
77 return i;
78 }
79 }
80 }
81 break;
82 case FALLING_EDGE:
83 for (i = start; i <= max - samples; i++) {
84 if (!test_bit(i, bmap)) {
85 if (test_bit(i - 1, bmap) &&
86 test_bit(i - 2, bmap) &&
87 test_bit(i - 3, bmap)) {
88 return i;
89 }
90 }
91 }
92 }
93
94 return ret;
95}
96
97static void bitmap_print(unsigned long *bmap, int max)
98{
99 int i;
100
101 debug("BITMAP [0x%p]:\n", bmap);
102 for (i = 0; i <= max; i++) {
103 debug("%d ", test_bit(i, bmap) ? 1 : 0);
104 if (i && (i % 32) == (32 - 1))
105 debug("\n");
106 }
107 debug("\n");
108}
109
110#define sw_leveling_op_done \
111 while (!(readl(&ddrmr->cr[94]) & DDRMC_CR94_SWLVL_OP_DONE))
112
113#define sw_leveling_load_value \
114 do { clrsetbits_le32(&ddrmr->cr[93], DDRMC_CR93_SWLVL_LOAD, \
115 DDRMC_CR93_SWLVL_LOAD); } while (0)
116
117#define sw_leveling_start \
118 do { clrsetbits_le32(&ddrmr->cr[93], DDRMC_CR93_SWLVL_START, \
119 DDRMC_CR93_SWLVL_START); } while (0)
120
121#define sw_leveling_exit \
122 do { clrsetbits_le32(&ddrmr->cr[94], DDRMC_CR94_SWLVL_EXIT, \
123 DDRMC_CR94_SWLVL_EXIT); } while (0)
124
125/*
126 * RDLVL_DL calibration:
127 *
128 * NXP is _NOT_ recommending performing the leveling at each
129 * boot. Instead - one shall run this procedure on new boards
130 * and then use hardcoded values.
131 *
132 */
133static int ddrmc_cal_dqs_to_dq(struct ddrmr_regs *ddrmr)
134{
135 DECLARE_BITMAP(rdlvl_rsp, DDRMC_DQS_DQ_MAX_DELAY + 1);
136 int rdlvl_dl_0_min = -1, rdlvl_dl_0_max = -1;
137 int rdlvl_dl_1_min = -1, rdlvl_dl_1_max = -1;
138 int rdlvl_dl_0, rdlvl_dl_1;
139 u8 swlvl_rsp;
140 u32 tmp;
141 int i;
142
143 /* Read defaults */
144 u16 rdlvl_dl_0_def =
145 (readl(&ddrmr->cr[105]) >> DDRMC_CR105_RDLVL_DL_0_OFF) & 0xFFFF;
146 u16 rdlvl_dl_1_def = readl(&ddrmr->cr[110]) & 0xFFFF;
147
148 debug("\nRDLVL: ======================\n");
149 debug("RDLVL: DQS to DQ (RDLVL)\n");
150
151 debug("RDLVL: RDLVL_DL_0_DFL:\t 0x%x\n", rdlvl_dl_0_def);
152 debug("RDLVL: RDLVL_DL_1_DFL:\t 0x%x\n", rdlvl_dl_1_def);
153
154 /*
155 * Set/Read setup for calibration
156 *
157 * Values necessary for leveling from Vybrid RM [2] - page 1600
158 */
159 writel(0x40703030, &ddrmr->cr[144]);
160 writel(0x40, &ddrmr->cr[145]);
161 writel(0x40, &ddrmr->cr[146]);
162
163 tmp = readl(&ddrmr->cr[144]);
164 debug("RDLVL: PHY_RDLVL_RES:\t 0x%x\n", (tmp >> 24) & 0xFF);// set 0x40
165 debug("RDLVL: PHY_RDLV_LOAD:\t 0x%x\n", (tmp >> 16) & 0xFF);// set 0x70
166 debug("RDLVL: PHY_RDLV_DLL:\t 0x%x\n", (tmp >> 8) & 0xFF); // set 0x30
167 debug("RDLVL: PHY_RDLV_EN:\t 0x%x\n", tmp & 0xFF); //set 0x30
168
169 tmp = readl(&ddrmr->cr[145]);
170 debug("RDLVL: PHY_RDLV_RR:\t 0x%x\n", tmp & 0x3FF); //set 0x40
171
172 tmp = readl(&ddrmr->cr[146]);
173 debug("RDLVL: PHY_RDLV_RESP:\t 0x%x\n", tmp); //set 0x40
174
175 /*
176 * Program/read the leveling edge RDLVL_EDGE = 0
177 *
178 * 0x00 is the correct output on SWLVL_RSP_X
179 * If by any chance 1s are visible -> wrong number read
180 */
181 clrbits_le32(&ddrmr->cr[101], DDRMC_CR101_PHY_RDLVL_EDGE);
182
183 tmp = readl(&ddrmr->cr[101]);
184 debug("RDLVL: PHY_RDLVL_EDGE:\t 0x%x\n",
185 (tmp >> DDRMC_CR101_PHY_RDLVL_EDGE_OFF) & 0x1); //set 0
186
187 /* Program Leveling mode - CR93[SW_LVL_MODE] to ’b10 */
188 clrsetbits_le32(&ddrmr->cr[93], DDRMC_CR93_SW_LVL_MODE(0x3),
189 DDRMC_CR93_SW_LVL_MODE(0x2));
190 tmp = readl(&ddrmr->cr[93]);
191 debug("RDLVL: SW_LVL_MODE:\t 0x%x\n",
192 (tmp >> DDRMC_CR93_SW_LVL_MODE_OFF) & 0x3);
193
194 /* Start procedure - CR93[SWLVL_START] to ’b1 */
195 sw_leveling_start;
196
197 /* Poll CR94[SWLVL_OP_DONE] */
198 sw_leveling_op_done;
199
200 /*
201 * Program delays for RDLVL_DL_0
202 *
203 * The procedure is to increase the delay values from 0 to 0xFF
204 * and read the response from the DDRMC
205 */
206 debug("\nRDLVL: ---> RDLVL_DL_0\n");
207 bitmap_zero(rdlvl_rsp, DDRMC_DQS_DQ_MAX_DELAY + 1);
208
209 for (i = 0; i <= DDRMC_DQS_DQ_MAX_DELAY; i++) {
210 clrsetbits_le32(&ddrmr->cr[105],
211 0xFFFF << DDRMC_CR105_RDLVL_DL_0_OFF,
212 i << DDRMC_CR105_RDLVL_DL_0_OFF);
213
214 /* Load values CR93[SWLVL_LOAD] to ’b1 */
215 sw_leveling_load_value;
216
217 /* Poll CR94[SWLVL_OP_DONE] */
218 sw_leveling_op_done;
219
220 /*
221 * Read Responses - SWLVL_RESP_0
222 *
223 * The 0x00 (correct response when PHY_RDLVL_EDGE = 0)
224 * -> 1 in the bit vector
225 */
226 swlvl_rsp = (readl(&ddrmr->cr[94]) >>
227 DDRMC_CR94_SWLVL_RESP_0_OFF) & 0xF;
228 if (swlvl_rsp == 0)
229 generic_set_bit(i, rdlvl_rsp);
230 }
231
232 bitmap_print(rdlvl_rsp, DDRMC_DQS_DQ_MAX_DELAY);
233
234 /*
235 * First test for rising edge 0x0 -> 0x1 in bitmap
236 */
237 rdlvl_dl_0_min = ddr_cal_get_first_edge_index(rdlvl_rsp, RISING_EDGE,
238 N_SAMPLES, N_SAMPLES,
239 DDRMC_DQS_DQ_MAX_DELAY);
240
241 /*
242 * Secondly test for falling edge 0x1 -> 0x0 in bitmap
243 */
244 rdlvl_dl_0_max = ddr_cal_get_first_edge_index(rdlvl_rsp, FALLING_EDGE,
245 N_SAMPLES, rdlvl_dl_0_min,
246 DDRMC_DQS_DQ_MAX_DELAY);
247
248 debug("RDLVL: DL_0 min: %d [0x%x] DL_0 max: %d [0x%x]\n",
249 rdlvl_dl_0_min, rdlvl_dl_0_min, rdlvl_dl_0_max, rdlvl_dl_0_max);
250 rdlvl_dl_0 = (rdlvl_dl_0_max - rdlvl_dl_0_min) / 2;
251
252 if (rdlvl_dl_0_max == -1 || rdlvl_dl_0_min == -1 || rdlvl_dl_0 <= 0) {
253 debug("RDLVL: The DQS to DQ delay cannot be found!\n");
254 debug("RDLVL: Using default - slice 0: %d!\n", rdlvl_dl_0_def);
255 rdlvl_dl_0 = rdlvl_dl_0_def;
256 }
257
258 debug("\nRDLVL: ---> RDLVL_DL_1\n");
259 bitmap_zero(rdlvl_rsp, DDRMC_DQS_DQ_MAX_DELAY + 1);
260
261 for (i = 0; i <= DDRMC_DQS_DQ_MAX_DELAY; i++) {
262 clrsetbits_le32(&ddrmr->cr[110],
263 0xFFFF << DDRMC_CR110_RDLVL_DL_1_OFF,
264 i << DDRMC_CR110_RDLVL_DL_1_OFF);
265
266 /* Load values CR93[SWLVL_LOAD] to ’b1 */
267 sw_leveling_load_value;
268
269 /* Poll CR94[SWLVL_OP_DONE] */
270 sw_leveling_op_done;
271
272 /*
273 * Read Responses - SWLVL_RESP_1
274 *
275 * The 0x00 (correct response when PHY_RDLVL_EDGE = 0)
276 * -> 1 in the bit vector
277 */
278 swlvl_rsp = (readl(&ddrmr->cr[95]) >>
279 DDRMC_CR95_SWLVL_RESP_1_OFF) & 0xF;
280 if (swlvl_rsp == 0)
281 generic_set_bit(i, rdlvl_rsp);
282 }
283
284 bitmap_print(rdlvl_rsp, DDRMC_DQS_DQ_MAX_DELAY);
285
286 /*
287 * First test for rising edge 0x0 -> 0x1 in bitmap
288 */
289 rdlvl_dl_1_min = ddr_cal_get_first_edge_index(rdlvl_rsp, RISING_EDGE,
290 N_SAMPLES, N_SAMPLES,
291 DDRMC_DQS_DQ_MAX_DELAY);
292
293 /*
294 * Secondly test for falling edge 0x1 -> 0x0 in bitmap
295 */
296 rdlvl_dl_1_max = ddr_cal_get_first_edge_index(rdlvl_rsp, FALLING_EDGE,
297 N_SAMPLES, rdlvl_dl_1_min,
298 DDRMC_DQS_DQ_MAX_DELAY);
299
300 debug("RDLVL: DL_1 min: %d [0x%x] DL_1 max: %d [0x%x]\n",
301 rdlvl_dl_1_min, rdlvl_dl_1_min, rdlvl_dl_1_max, rdlvl_dl_1_max);
302 rdlvl_dl_1 = (rdlvl_dl_1_max - rdlvl_dl_1_min) / 2;
303
304 if (rdlvl_dl_1_max == -1 || rdlvl_dl_1_min == -1 || rdlvl_dl_1 <= 0) {
305 debug("RDLVL: The DQS to DQ delay cannot be found!\n");
306 debug("RDLVL: Using default - slice 1: %d!\n", rdlvl_dl_1_def);
307 rdlvl_dl_1 = rdlvl_dl_1_def;
308 }
309
310 debug("RDLVL: CALIBRATED: rdlvl_dl_0: 0x%x\t rdlvl_dl_1: 0x%x\n",
311 rdlvl_dl_0, rdlvl_dl_1);
312
313 /* Write new delay values */
314 writel(DDRMC_CR105_RDLVL_DL_0(rdlvl_dl_0), &ddrmr->cr[105]);
315 writel(DDRMC_CR110_RDLVL_DL_1(rdlvl_dl_1), &ddrmr->cr[110]);
316
317 sw_leveling_load_value;
318 sw_leveling_op_done;
319
320 /* Exit procedure - CR94[SWLVL_EXIT] to ’b1 */
321 sw_leveling_exit;
322
323 /* Poll CR94[SWLVL_OP_DONE] */
324 sw_leveling_op_done;
325
326 return 0;
327}
328
329/*
330 * WRLVL_DL calibration:
331 *
332 * For non-flyback memory architecture - where one have a single DDR3 x16
333 * memory - it is NOT necessary to perform "Write Leveling"
334 * [3] 'Vybrid DDR3 write leveling' https://community.nxp.com/thread/429362
335 *
336 */
337
338int ddrmc_calibration(struct ddrmr_regs *ddrmr)
339{
340 ddrmc_cal_dqs_to_dq(ddrmr);
341
342 return 0;
343}