blob: c8cd7c3ceaf74a75b2944c76c24c311435086c9f [file] [log] [blame]
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2/*
3 * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
4 */
Patrick Delaunay753f5362020-11-06 19:01:36 +01005
6#define LOG_CATEGORY UCLASS_RAM
7
Patrick Delaunay2f91e612019-04-10 14:09:29 +02008#include <common.h>
9#include <console.h>
10#include <clk.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Patrick Delaunay2f91e612019-04-10 14:09:29 +020012#include <ram.h>
Simon Glass274e0b02020-05-10 11:39:56 -060013#include <rand.h>
Patrick Delaunay2f91e612019-04-10 14:09:29 +020014#include <reset.h>
15#include <asm/io.h>
Patrick Delaunay131ec952020-03-06 11:14:08 +010016#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060017#include <linux/delay.h>
Patrick Delaunay0cd380b2020-03-06 11:14:06 +010018#include <linux/iopoll.h>
Patrick Delaunay2f91e612019-04-10 14:09:29 +020019
20#include "stm32mp1_ddr_regs.h"
21#include "stm32mp1_ddr.h"
22#include "stm32mp1_tests.h"
23
24#define MAX_DQS_PHASE_IDX _144deg
25#define MAX_DQS_UNIT_IDX 7
26#define MAX_GSL_IDX 5
27#define MAX_GPS_IDX 3
28
29/* Number of bytes used in this SW. ( min 1--> max 4). */
30#define NUM_BYTES 4
31
32enum dqs_phase_enum {
33 _36deg = 0,
34 _54deg = 1,
35 _72deg = 2,
36 _90deg = 3,
37 _108deg = 4,
38 _126deg = 5,
39 _144deg = 6
40};
41
42/* BIST Result struct */
43struct BIST_result {
44 /* Overall test result:
45 * 0 Fail (any bit failed) ,
46 * 1 Success (All bits success)
47 */
48 bool test_result;
49 /* 1: true, all fail / 0: False, not all bits fail */
50 bool all_bits_fail;
51 bool bit_i_test_result[8]; /* 0 fail / 1 success */
52};
53
54/* a struct that defines tuning parameters of a byte. */
55struct tuning_position {
56 u8 phase; /* DQS phase */
57 u8 unit; /* DQS unit delay */
58 u32 bits_delay; /* Bits deskew in this byte */
59};
60
61/* 36deg, 54deg, 72deg, 90deg, 108deg, 126deg, 144deg */
62const u8 dx_dll_phase[7] = {3, 2, 1, 0, 14, 13, 12};
63
64static u8 BIST_error_max = 1;
65static u32 BIST_seed = 0x1234ABCD;
66
67static u8 get_nb_bytes(struct stm32mp1_ddrctl *ctl)
68{
69 u32 data_bus = readl(&ctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK;
70 u8 nb_bytes = NUM_BYTES;
71
72 switch (data_bus) {
73 case DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF:
74 nb_bytes /= 2;
75 break;
76 case DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER:
77 nb_bytes /= 4;
78 break;
79 default:
80 break;
81 }
82
83 return nb_bytes;
84}
85
Patrick Delaunay131ec952020-03-06 11:14:08 +010086static u8 get_nb_bank(struct stm32mp1_ddrctl *ctl)
87{
88 /* Count bank address bits */
89 u8 bits = 0;
90 u32 reg, val;
91
92 reg = readl(&ctl->addrmap1);
93 /* addrmap1.addrmap_bank_b1 */
94 val = (reg & GENMASK(5, 0)) >> 0;
95 if (val <= 31)
96 bits++;
97 /* addrmap1.addrmap_bank_b2 */
98 val = (reg & GENMASK(13, 8)) >> 8;
99 if (val <= 31)
100 bits++;
101 /* addrmap1.addrmap_bank_b3 */
102 val = (reg & GENMASK(21, 16)) >> 16;
103 if (val <= 31)
104 bits++;
105
106 return bits;
107}
108
109static u8 get_nb_col(struct stm32mp1_ddrctl *ctl)
110{
111 u8 bits;
112 u32 reg, val;
113
114 /* Count column address bits, start at 2 for b0 and b1 (fixed) */
115 bits = 2;
116
117 reg = readl(&ctl->addrmap2);
118 /* addrmap2.addrmap_col_b2 */
119 val = (reg & GENMASK(3, 0)) >> 0;
120 if (val <= 7)
121 bits++;
122 /* addrmap2.addrmap_col_b3 */
123 val = (reg & GENMASK(11, 8)) >> 8;
124 if (val <= 7)
125 bits++;
126 /* addrmap2.addrmap_col_b4 */
127 val = (reg & GENMASK(19, 16)) >> 16;
128 if (val <= 7)
129 bits++;
130 /* addrmap2.addrmap_col_b5 */
131 val = (reg & GENMASK(27, 24)) >> 24;
132 if (val <= 7)
133 bits++;
134
135 reg = readl(&ctl->addrmap3);
136 /* addrmap3.addrmap_col_b6 */
137 val = (reg & GENMASK(3, 0)) >> 0;
138 if (val <= 7)
139 bits++;
140 /* addrmap3.addrmap_col_b7 */
141 val = (reg & GENMASK(11, 8)) >> 8;
142 if (val <= 7)
143 bits++;
144 /* addrmap3.addrmap_col_b8 */
145 val = (reg & GENMASK(19, 16)) >> 16;
146 if (val <= 7)
147 bits++;
148 /* addrmap3.addrmap_col_b9 */
149 val = (reg & GENMASK(27, 24)) >> 24;
150 if (val <= 7)
151 bits++;
152
153 reg = readl(&ctl->addrmap4);
154 /* addrmap4.addrmap_col_b10 */
155 val = (reg & GENMASK(3, 0)) >> 0;
156 if (val <= 7)
157 bits++;
158 /* addrmap4.addrmap_col_b11 */
159 val = (reg & GENMASK(11, 8)) >> 8;
160 if (val <= 7)
161 bits++;
162
163 return bits;
164}
165
166static u8 get_nb_row(struct stm32mp1_ddrctl *ctl)
167{
168 /* Count row address bits */
169 u8 bits = 0;
170 u32 reg, val;
171
172 reg = readl(&ctl->addrmap5);
173 /* addrmap5.addrmap_row_b0 */
174 val = (reg & GENMASK(3, 0)) >> 0;
175 if (val <= 11)
176 bits++;
177 /* addrmap5.addrmap_row_b1 */
178 val = (reg & GENMASK(11, 8)) >> 8;
179 if (val <= 11)
180 bits++;
181 /* addrmap5.addrmap_row_b2_10 */
182 val = (reg & GENMASK(19, 16)) >> 16;
183 if (val <= 11)
184 bits += 9;
185 else
186 printf("warning: addrmap5.addrmap_row_b2_10 not supported\n");
187 /* addrmap5.addrmap_row_b11 */
188 val = (reg & GENMASK(27, 24)) >> 24;
189 if (val <= 11)
190 bits++;
191
192 reg = readl(&ctl->addrmap6);
193 /* addrmap6.addrmap_row_b12 */
194 val = (reg & GENMASK(3, 0)) >> 0;
195 if (val <= 7)
196 bits++;
197 /* addrmap6.addrmap_row_b13 */
198 val = (reg & GENMASK(11, 8)) >> 8;
199 if (val <= 7)
200 bits++;
201 /* addrmap6.addrmap_row_b14 */
202 val = (reg & GENMASK(19, 16)) >> 16;
203 if (val <= 7)
204 bits++;
205 /* addrmap6.addrmap_row_b15 */
206 val = (reg & GENMASK(27, 24)) >> 24;
207 if (val <= 7)
208 bits++;
209
210 return bits;
211}
212
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200213static void itm_soft_reset(struct stm32mp1_ddrphy *phy)
214{
215 stm32mp1_ddrphy_init(phy, DDRPHYC_PIR_ITMSRST);
216}
217
218/* Read DQ unit delay register and provides the retrieved value for DQS
219 * We are assuming that we have the same delay when clocking
220 * by DQS and when clocking by DQSN
221 */
222static u8 DQ_unit_index(struct stm32mp1_ddrphy *phy, u8 byte, u8 bit)
223{
224 u32 index;
225 u32 addr = DXNDQTR(phy, byte);
226
227 /* We are assuming that we have the same delay when clocking by DQS
228 * and when clocking by DQSN : use only the low bits
229 */
230 index = (readl(addr) >> DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit))
231 & DDRPHYC_DXNDQTR_DQDLY_LOW_MASK;
232
Patrick Delaunay753f5362020-11-06 19:01:36 +0100233 log_debug("[%x]: %x => DQ unit index = %x\n", addr, readl(addr), index);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200234
235 return index;
236}
237
238/* Sets the DQS phase delay for a byte lane.
239 *phase delay is specified by giving the index of the desired delay
240 * in the dx_dll_phase array.
241 */
242static void DQS_phase_delay(struct stm32mp1_ddrphy *phy, u8 byte, u8 phase_idx)
243{
244 u8 sdphase_val = 0;
245
246 /* Write DXNDLLCR.SDPHASE = dx_dll_phase(phase_index); */
247 sdphase_val = dx_dll_phase[phase_idx];
248 clrsetbits_le32(DXNDLLCR(phy, byte),
249 DDRPHYC_DXNDLLCR_SDPHASE_MASK,
250 sdphase_val << DDRPHYC_DXNDLLCR_SDPHASE_SHIFT);
251}
252
253/* Sets the DQS unit delay for a byte lane.
254 * unit delay is specified by giving the index of the desired delay
255 * for dgsdly and dqsndly (same value).
256 */
257static void DQS_unit_delay(struct stm32mp1_ddrphy *phy,
258 u8 byte, u8 unit_dly_idx)
259{
260 /* Write the same value in DXNDQSTR.DQSDLY and DXNDQSTR.DQSNDLY */
261 clrsetbits_le32(DXNDQSTR(phy, byte),
262 DDRPHYC_DXNDQSTR_DQSDLY_MASK |
263 DDRPHYC_DXNDQSTR_DQSNDLY_MASK,
264 (unit_dly_idx << DDRPHYC_DXNDQSTR_DQSDLY_SHIFT) |
265 (unit_dly_idx << DDRPHYC_DXNDQSTR_DQSNDLY_SHIFT));
266
267 /* After changing this value, an ITM soft reset (PIR.ITMSRST=1,
268 * plus PIR.INIT=1) must be issued.
269 */
270 stm32mp1_ddrphy_init(phy, DDRPHYC_PIR_ITMSRST);
271}
272
273/* Sets the DQ unit delay for a bit line in particular byte lane.
274 * unit delay is specified by giving the desired delay
275 */
276static void set_DQ_unit_delay(struct stm32mp1_ddrphy *phy,
277 u8 byte, u8 bit,
278 u8 dq_delay_index)
279{
280 u8 dq_bit_delay_val = dq_delay_index | (dq_delay_index << 2);
281
282 /* same value on delay for clock DQ an DQS_b */
283 clrsetbits_le32(DXNDQTR(phy, byte),
284 DDRPHYC_DXNDQTR_DQDLY_MASK
285 << DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit),
286 dq_bit_delay_val << DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit));
287}
288
289static void set_r0dgsl_delay(struct stm32mp1_ddrphy *phy,
290 u8 byte, u8 r0dgsl_idx)
291{
292 clrsetbits_le32(DXNDQSTR(phy, byte),
293 DDRPHYC_DXNDQSTR_R0DGSL_MASK,
294 r0dgsl_idx << DDRPHYC_DXNDQSTR_R0DGSL_SHIFT);
295}
296
297static void set_r0dgps_delay(struct stm32mp1_ddrphy *phy,
298 u8 byte, u8 r0dgps_idx)
299{
300 clrsetbits_le32(DXNDQSTR(phy, byte),
301 DDRPHYC_DXNDQSTR_R0DGPS_MASK,
302 r0dgps_idx << DDRPHYC_DXNDQSTR_R0DGPS_SHIFT);
303}
304
305/* Basic BIST configuration for data lane tests. */
Patrick Delaunay131ec952020-03-06 11:14:08 +0100306static void config_BIST(struct stm32mp1_ddrctl *ctl,
307 struct stm32mp1_ddrphy *phy)
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200308{
Patrick Delaunay131ec952020-03-06 11:14:08 +0100309 u8 nb_bank = get_nb_bank(ctl);
310 u8 nb_row = get_nb_row(ctl);
311 u8 nb_col = get_nb_col(ctl);
312
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200313 /* Selects the SDRAM bank address to be used during BIST. */
314 u32 bbank = 0;
315 /* Selects the SDRAM row address to be used during BIST. */
316 u32 brow = 0;
317 /* Selects the SDRAM column address to be used during BIST. */
318 u32 bcol = 0;
319 /* Selects the value by which the SDRAM address is incremented
320 * for each write/read access.
321 */
322 u32 bainc = 0x00000008;
323 /* Specifies the maximum SDRAM rank to be used during BIST.
324 * The default value is set to maximum ranks minus 1.
325 * must be 0 with single rank
326 */
327 u32 bmrank = 0;
328 /* Selects the SDRAM rank to be used during BIST.
329 * must be 0 with single rank
330 */
331 u32 brank = 0;
Patrick Delaunay131ec952020-03-06 11:14:08 +0100332
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200333 /* Specifies the maximum SDRAM bank address to be used during
334 * BIST before the address & increments to the next rank.
335 */
Patrick Delaunay131ec952020-03-06 11:14:08 +0100336 u32 bmbank = (1 << nb_bank) - 1;
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200337 /* Specifies the maximum SDRAM row address to be used during
338 * BIST before the address & increments to the next bank.
339 */
Patrick Delaunay131ec952020-03-06 11:14:08 +0100340 u32 bmrow = (1 << nb_row) - 1;
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200341 /* Specifies the maximum SDRAM column address to be used during
342 * BIST before the address & increments to the next row.
343 */
Patrick Delaunay131ec952020-03-06 11:14:08 +0100344 u32 bmcol = (1 << nb_col) - 1;
345
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200346 u32 bmode_conf = 0x00000001; /* DRam mode */
347 u32 bdxen_conf = 0x00000001; /* BIST on Data byte */
348 u32 bdpat_conf = 0x00000002; /* Select LFSR pattern */
349
350 /*Setup BIST for DRAM mode, and LFSR-random data pattern.*/
351 /*Write BISTRR.BMODE = 1?b1;*/
352 /*Write BISTRR.BDXEN = 1?b1;*/
353 /*Write BISTRR.BDPAT = 2?b10;*/
354
355 /* reset BIST */
356 writel(0x3, &phy->bistrr);
357
358 writel((bmode_conf << 3) | (bdxen_conf << 14) | (bdpat_conf << 17),
359 &phy->bistrr);
360
361 /*Setup BIST Word Count*/
362 /*Write BISTWCR.BWCNT = 16?b0008;*/
363 writel(0x00000200, &phy->bistwcr); /* A multiple of BL/2 */
364
365 writel(bcol | (brow << 12) | (bbank << 28), &phy->bistar0);
366 writel(brank | (bmrank << 2) | (bainc << 4), &phy->bistar1);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200367 writel(bmcol | (bmrow << 12) | (bmbank << 28), &phy->bistar2);
368}
369
370/* Select the Byte lane to be tested by BIST. */
371static void BIST_datx8_sel(struct stm32mp1_ddrphy *phy, u8 datx8)
372{
373 clrsetbits_le32(&phy->bistrr,
374 DDRPHYC_BISTRR_BDXSEL_MASK,
375 datx8 << DDRPHYC_BISTRR_BDXSEL_SHIFT);
376
377 /*(For example, selecting Byte Lane 3, BISTRR.BDXSEL = 4?b0011)*/
378 /* Write BISTRR.BDXSEL = datx8; */
379}
380
381/* Perform BIST Write_Read test on a byte lane and return test result. */
382static void BIST_test(struct stm32mp1_ddrphy *phy, u8 byte,
383 struct BIST_result *bist)
384{
385 bool result = true; /* BIST_SUCCESS */
386 u32 cnt = 0;
387 u32 error = 0;
Patrick Delaunay0cd380b2020-03-06 11:14:06 +0100388 u32 val;
389 int ret;
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200390
391 bist->test_result = true;
392
393run:
394 itm_soft_reset(phy);
395
396 /*Perform BIST Reset*/
397 /* Write BISTRR.BINST = 3?b011; */
398 clrsetbits_le32(&phy->bistrr,
399 0x00000007,
400 0x00000003);
401
402 /*Re-seed LFSR*/
403 /* Write BISTLSR.SEED = 32'h1234ABCD; */
404 if (BIST_seed)
405 writel(BIST_seed, &phy->bistlsr);
406 else
407 writel(rand(), &phy->bistlsr);
408
409 /* some delay to reset BIST */
Patrick Delaunay6cdc1202020-03-06 11:14:10 +0100410 udelay(10);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200411
412 /*Perform BIST Run*/
413 clrsetbits_le32(&phy->bistrr,
414 0x00000007,
415 0x00000001);
416 /* Write BISTRR.BINST = 3?b001; */
417
Patrick Delaunay0cd380b2020-03-06 11:14:06 +0100418 /* poll on BISTGSR.BDONE and wait max 1000 us */
419 ret = readl_poll_timeout(&phy->bistgsr, val,
420 val & DDRPHYC_BISTGSR_BDDONE, 1000);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200421
Patrick Delaunay0cd380b2020-03-06 11:14:06 +0100422 if (ret < 0) {
423 printf("warning: BIST timeout\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200424 result = false; /* BIST_FAIL; */
Patrick Delaunay0cd380b2020-03-06 11:14:06 +0100425 /*Perform BIST Stop */
426 clrsetbits_le32(&phy->bistrr, 0x00000007, 0x00000002);
427 } else {
428 /*Check if received correct number of words*/
429 /* if (Read BISTWCSR.DXWCNT = Read BISTWCR.BWCNT) */
430 if (((readl(&phy->bistwcsr)) >> DDRPHYC_BISTWCSR_DXWCNT_SHIFT)
431 == readl(&phy->bistwcr)) {
432 /*Determine if there is a data comparison error*/
433 /* if (Read BISTGSR.BDXERR = 1?b0) */
434 if (readl(&phy->bistgsr) & DDRPHYC_BISTGSR_BDXERR)
435 result = false; /* BIST_FAIL; */
436 else
437 result = true; /* BIST_SUCCESS; */
438 } else {
439 result = false; /* BIST_FAIL; */
440 }
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200441 }
442
443 /* loop while success */
444 cnt++;
445 if (result && cnt != 1000)
446 goto run;
447
448 if (!result)
449 error++;
450
451 if (error < BIST_error_max) {
452 if (cnt != 1000)
453 goto run;
454 bist->test_result = true;
455 } else {
456 bist->test_result = false;
457 }
458}
459
460/* After running the deskew algo, this function applies the new DQ delays
461 * by reading them from the array "deskew_delay"and writing in PHY registers.
462 * The bits that are not deskewed parfectly (too much skew on them,
463 * or data eye very wide) are marked in the array deskew_non_converge.
464 */
465static void apply_deskew_results(struct stm32mp1_ddrphy *phy, u8 byte,
466 u8 deskew_delay[NUM_BYTES][8],
467 u8 deskew_non_converge[NUM_BYTES][8])
468{
469 u8 bit_i;
470 u8 index;
471
472 for (bit_i = 0; bit_i < 8; bit_i++) {
473 set_DQ_unit_delay(phy, byte, bit_i, deskew_delay[byte][bit_i]);
474 index = DQ_unit_index(phy, byte, bit_i);
Patrick Delaunay753f5362020-11-06 19:01:36 +0100475 log_debug("Byte %d ; bit %d : The new DQ delay (%d) index=%d [delta=%d, 3 is the default]",
476 byte, bit_i, deskew_delay[byte][bit_i],
477 index, index - 3);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200478 printf("Byte %d, bit %d, DQ delay = %d",
479 byte, bit_i, deskew_delay[byte][bit_i]);
480 if (deskew_non_converge[byte][bit_i] == 1)
Patrick Delaunay753f5362020-11-06 19:01:36 +0100481 log_debug(" - not converged : still more skew");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200482 printf("\n");
483 }
484}
485
486/* DQ Bit de-skew algorithm.
487 * Deskews data lines as much as possible.
488 * 1. Add delay to DQS line until finding the failure
489 * (normally a hold time violation)
490 * 2. Reduce DQS line by small steps until finding the very first time
491 * we go back to "Pass" condition.
492 * 3. For each DQ line, Reduce DQ delay until finding the very first failure
493 * (normally a hold time fail)
494 * 4. When all bits are at their first failure delay, we can consider them
495 * aligned.
496 * Handle conrer situation (Can't find Pass-fail, or fail-pass transitions
497 * at any step)
498 * TODO Provide a return Status. Improve doc
499 */
500static enum test_result bit_deskew(struct stm32mp1_ddrctl *ctl,
501 struct stm32mp1_ddrphy *phy, char *string)
502{
503 /* New DQ delay value (index), set during Deskew algo */
504 u8 deskew_delay[NUM_BYTES][8];
505 /*If there is still skew on a bit, mark this bit. */
506 u8 deskew_non_converge[NUM_BYTES][8];
507 struct BIST_result result;
508 s8 dqs_unit_delay_index = 0;
509 u8 datx8 = 0;
510 u8 bit_i = 0;
511 s8 phase_idx = 0;
512 s8 bit_i_delay_index = 0;
513 u8 success = 0;
514 struct tuning_position last_right_ok;
515 u8 force_stop = 0;
516 u8 fail_found;
517 u8 error = 0;
518 u8 nb_bytes = get_nb_bytes(ctl);
519 /* u8 last_pass_dqs_unit = 0; */
520
521 memset(deskew_delay, 0, sizeof(deskew_delay));
522 memset(deskew_non_converge, 0, sizeof(deskew_non_converge));
523
524 /*Disable DQS Drift Compensation*/
525 clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP);
526 /*Disable all bytes*/
527 /* Disable automatic power down of DLL and IOs when disabling
528 * a byte (To avoid having to add programming and delay
529 * for a DLL re-lock when later re-enabling a disabled Byte Lane)
530 */
531 clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_PDDISDX);
532
533 /* Disable all data bytes */
534 clrbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN);
535 clrbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN);
536 clrbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN);
537 clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
538
539 /* Config the BIST block */
Patrick Delaunay131ec952020-03-06 11:14:08 +0100540 config_BIST(ctl, phy);
Patrick Delaunay753f5362020-11-06 19:01:36 +0100541 log_debug("BIST Config done.\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200542
543 /* Train each byte */
544 for (datx8 = 0; datx8 < nb_bytes; datx8++) {
545 if (ctrlc()) {
546 sprintf(string, "interrupted at byte %d/%d, error=%d",
547 datx8 + 1, nb_bytes, error);
548 return TEST_FAILED;
549 }
Patrick Delaunay753f5362020-11-06 19:01:36 +0100550 log_debug("\n======================\n");
551 log_debug("Start deskew byte %d .\n", datx8);
552 log_debug("======================\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200553 /* Enable Byte (DXNGCR, bit DXEN) */
554 setbits_le32(DXNGCR(phy, datx8), DDRPHYC_DXNGCR_DXEN);
555
556 /* Select the byte lane for comparison of read data */
557 BIST_datx8_sel(phy, datx8);
558
559 /* Set all DQDLYn to maximum value. All bits within the byte
560 * will be delayed with DQSTR = 2 instead of max = 3
561 * to avoid inter bits fail influence
562 */
563 writel(0xAAAAAAAA, DXNDQTR(phy, datx8));
564
565 /* Set the DQS phase delay to 90 DEG (default).
566 * What is defined here is the index of the desired config
567 * in the PHASE array.
568 */
569 phase_idx = _90deg;
570
571 /* Set DQS unit delay to the max value. */
572 dqs_unit_delay_index = MAX_DQS_UNIT_IDX;
573 DQS_unit_delay(phy, datx8, dqs_unit_delay_index);
574 DQS_phase_delay(phy, datx8, phase_idx);
575
576 /* Issue a DLL soft reset */
577 clrbits_le32(DXNDLLCR(phy, datx8), DDRPHYC_DXNDLLCR_DLLSRST);
578 setbits_le32(DXNDLLCR(phy, datx8), DDRPHYC_DXNDLLCR_DLLSRST);
579
580 /* Test this typical init condition */
581 BIST_test(phy, datx8, &result);
582 success = result.test_result;
583
584 /* If the test pass in this typical condition,
585 * start the algo with it.
586 * Else, look for Pass init condition
587 */
588 if (!success) {
Patrick Delaunay753f5362020-11-06 19:01:36 +0100589 log_debug("Fail at init condtion. Let's look for a good init condition.\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200590 success = 0; /* init */
591 /* Make sure we start with a PASS condition before
592 * looking for a fail condition.
593 * Find the first PASS PHASE condition
594 */
595
596 /* escape if we find a PASS */
Patrick Delaunay753f5362020-11-06 19:01:36 +0100597 log_debug("increase Phase idx\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200598 while (!success && (phase_idx <= MAX_DQS_PHASE_IDX)) {
599 DQS_phase_delay(phy, datx8, phase_idx);
600 BIST_test(phy, datx8, &result);
601 success = result.test_result;
602 phase_idx++;
603 }
604 /* if ended with success
605 * ==>> Restore the fist success condition
606 */
607 if (success)
608 phase_idx--; /* because it ended with ++ */
609 }
610 if (ctrlc()) {
611 sprintf(string, "interrupted at byte %d/%d, error=%d",
612 datx8 + 1, nb_bytes, error);
613 return TEST_FAILED;
614 }
615 /* We couldn't find a successful condition, its seems
616 * we have hold violation, lets try reduce DQS_unit Delay
617 */
618 if (!success) {
619 /* We couldn't find a successful condition, its seems
620 * we have hold violation, lets try reduce DQS_unit
621 * Delay
622 */
Patrick Delaunay753f5362020-11-06 19:01:36 +0100623 log_debug("Still fail. Try decrease DQS Unit delay\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200624
625 phase_idx = 0;
626 dqs_unit_delay_index = 0;
627 DQS_phase_delay(phy, datx8, phase_idx);
628
629 /* escape if we find a PASS */
630 while (!success &&
631 (dqs_unit_delay_index <=
632 MAX_DQS_UNIT_IDX)) {
633 DQS_unit_delay(phy, datx8,
634 dqs_unit_delay_index);
635 BIST_test(phy, datx8, &result);
636 success = result.test_result;
637 dqs_unit_delay_index++;
638 }
639 if (success) {
640 /* Restore the first success condition*/
641 dqs_unit_delay_index--;
642 /* last_pass_dqs_unit = dqs_unit_delay_index;*/
643 DQS_unit_delay(phy, datx8,
644 dqs_unit_delay_index);
645 } else {
646 /* No need to continue,
647 * there is no pass region.
648 */
649 force_stop = 1;
650 }
651 }
652
653 /* There is an initial PASS condition
654 * Look for the first failing condition by PHASE stepping.
655 * This part of the algo can finish without converging.
656 */
657 if (force_stop) {
658 printf("Result: Failed ");
659 printf("[Cannot Deskew lines, ");
660 printf("there is no PASS region]\n");
661 error++;
662 continue;
663 }
664 if (ctrlc()) {
665 sprintf(string, "interrupted at byte %d/%d, error=%d",
666 datx8 + 1, nb_bytes, error);
667 return TEST_FAILED;
668 }
669
Patrick Delaunay753f5362020-11-06 19:01:36 +0100670 log_debug("there is a pass region for phase idx %d\n",
671 phase_idx);
672 log_debug("Step1: Find the first failing condition\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200673 /* Look for the first failing condition by PHASE stepping.
674 * This part of the algo can finish without converging.
675 */
676
677 /* escape if we find a fail (hold time violation)
678 * condition at any bit or if out of delay range.
679 */
680 while (success && (phase_idx <= MAX_DQS_PHASE_IDX)) {
681 DQS_phase_delay(phy, datx8, phase_idx);
682 BIST_test(phy, datx8, &result);
683 success = result.test_result;
684 phase_idx++;
685 }
686 if (ctrlc()) {
687 sprintf(string, "interrupted at byte %d/%d, error=%d",
688 datx8 + 1, nb_bytes, error);
689 return TEST_FAILED;
690 }
691
692 /* if the loop ended with a failing condition at any bit,
693 * lets look for the first previous success condition by unit
694 * stepping (minimal delay)
695 */
696 if (!success) {
Patrick Delaunay753f5362020-11-06 19:01:36 +0100697 log_debug("Fail region (PHASE) found phase idx %d\n",
698 phase_idx);
699 log_debug("Let's look for first success by DQS Unit steps\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200700 /* This part, the algo always converge */
701 phase_idx--;
702
703 /* escape if we find a success condition
704 * or if out of delay range.
705 */
706 while (!success && dqs_unit_delay_index >= 0) {
707 DQS_unit_delay(phy, datx8,
708 dqs_unit_delay_index);
709 BIST_test(phy, datx8, &result);
710 success = result.test_result;
711 dqs_unit_delay_index--;
712 }
713 /* if the loop ended with a success condition,
714 * the last delay Right OK (before hold violation)
715 * condition is then defined as following:
716 */
717 if (success) {
718 /* Hold the dely parameters of the the last
719 * delay Right OK condition.
720 * -1 to get back to current condition
721 */
722 last_right_ok.phase = phase_idx;
723 /*+1 to get back to current condition */
724 last_right_ok.unit = dqs_unit_delay_index + 1;
725 last_right_ok.bits_delay = 0xFFFFFFFF;
Patrick Delaunay753f5362020-11-06 19:01:36 +0100726 log_debug("Found %d\n", dqs_unit_delay_index);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200727 } else {
728 /* the last OK condition is then with the
729 * previous phase_idx.
730 * -2 instead of -1 because at the last
731 * iteration of the while(),
732 * we incremented phase_idx
733 */
734 last_right_ok.phase = phase_idx - 1;
735 /* Nominal+1. Because we want the previous
736 * delay after reducing the phase delay.
737 */
738 last_right_ok.unit = 1;
739 last_right_ok.bits_delay = 0xFFFFFFFF;
Patrick Delaunay753f5362020-11-06 19:01:36 +0100740 log_debug("Not Found : try previous phase %d\n",
741 phase_idx - 1);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200742
743 DQS_phase_delay(phy, datx8, phase_idx - 1);
744 dqs_unit_delay_index = 0;
745 success = true;
746 while (success &&
747 (dqs_unit_delay_index <
748 MAX_DQS_UNIT_IDX)) {
749 DQS_unit_delay(phy, datx8,
750 dqs_unit_delay_index);
751 BIST_test(phy, datx8, &result);
752 success = result.test_result;
753 dqs_unit_delay_index++;
Patrick Delaunay753f5362020-11-06 19:01:36 +0100754 log_debug("dqs_unit_delay_index = %d, result = %d\n",
755 dqs_unit_delay_index, success);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200756 }
757
758 if (!success) {
759 last_right_ok.unit =
760 dqs_unit_delay_index - 1;
761 } else {
762 last_right_ok.unit = 0;
Patrick Delaunay753f5362020-11-06 19:01:36 +0100763 log_debug("ERROR: failed region not FOUND");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200764 }
765 }
766 } else {
767 /* we can't find a failing condition at all bits
768 * ==> Just hold the last test condition
769 * (the max DQS delay)
770 * which is the most likely,
771 * the closest to a hold violation
772 * If we can't find a Fail condition after
773 * the Pass region, stick at this position
774 * In order to have max chances to find a fail
775 * when reducing DQ delays.
776 */
777 last_right_ok.phase = MAX_DQS_PHASE_IDX;
778 last_right_ok.unit = MAX_DQS_UNIT_IDX;
779 last_right_ok.bits_delay = 0xFFFFFFFF;
Patrick Delaunay753f5362020-11-06 19:01:36 +0100780 log_debug("Can't find the a fail condition\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200781 }
782
783 /* step 2:
784 * if we arrive at this stage, it means that we found the last
785 * Right OK condition (by tweeking the DQS delay). Or we simply
786 * pushed DQS delay to the max
787 * This means that by reducing the delay on some DQ bits,
788 * we should find a failing condition.
789 */
790 printf("Byte %d, DQS unit = %d, phase = %d\n",
791 datx8, last_right_ok.unit, last_right_ok.phase);
Patrick Delaunay753f5362020-11-06 19:01:36 +0100792 log_debug("Step2, unit = %d, phase = %d, bits delay=%x\n",
793 last_right_ok.unit, last_right_ok.phase,
794 last_right_ok.bits_delay);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200795
796 /* Restore the last_right_ok condtion. */
797 DQS_unit_delay(phy, datx8, last_right_ok.unit);
798 DQS_phase_delay(phy, datx8, last_right_ok.phase);
799 writel(last_right_ok.bits_delay, DXNDQTR(phy, datx8));
800
801 /* train each bit
802 * reduce delay on each bit, and perform a write/read test
803 * and stop at the very first time it fails.
804 * the goal is the find the first failing condition
805 * for each bit.
806 * When we achieve this condition< for all the bits,
807 * we are sure they are aligned (+/- step resolution)
808 */
809 fail_found = 0;
810 for (bit_i = 0; bit_i < 8; bit_i++) {
811 if (ctrlc()) {
812 sprintf(string,
813 "interrupted at byte %d/%d, error=%d",
814 datx8 + 1, nb_bytes, error);
815 return error;
816 }
Patrick Delaunay753f5362020-11-06 19:01:36 +0100817 log_debug("deskewing bit %d:\n", bit_i);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200818 success = 1; /* init */
819 /* Set all DQDLYn to maximum value.
820 * Only bit_i will be down-delayed
821 * ==> if we have a fail, it will be definitely
822 * from bit_i
823 */
824 writel(0xFFFFFFFF, DXNDQTR(phy, datx8));
825 /* Arriving at this stage,
826 * we have a success condition with delay = 3;
827 */
828 bit_i_delay_index = 3;
829
830 /* escape if bit delay is out of range or
831 * if a fatil occurs
832 */
833 while ((bit_i_delay_index >= 0) && success) {
834 set_DQ_unit_delay(phy, datx8,
835 bit_i,
836 bit_i_delay_index);
837 BIST_test(phy, datx8, &result);
838 success = result.test_result;
839 bit_i_delay_index--;
840 }
841
842 /* if escape with a fail condition
843 * ==> save this position for bit_i
844 */
845 if (!success) {
846 /* save the delay position.
847 * Add 1 because the while loop ended with a --,
848 * and that we need to hold the last success
849 * delay
850 */
851 deskew_delay[datx8][bit_i] =
852 bit_i_delay_index + 2;
853 if (deskew_delay[datx8][bit_i] > 3)
854 deskew_delay[datx8][bit_i] = 3;
855
856 /* A flag that states we found at least a fail
857 * at one bit.
858 */
859 fail_found = 1;
Patrick Delaunay753f5362020-11-06 19:01:36 +0100860 log_debug("Fail found on bit %d, for delay = %d => deskew[%d][%d] = %d\n",
861 bit_i, bit_i_delay_index + 1,
862 datx8, bit_i,
863 deskew_delay[datx8][bit_i]);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200864 } else {
865 /* if we can find a success condition by
866 * back-delaying this bit, just set the delay
867 * to 0 (the best deskew
868 * possible) and mark the bit.
869 */
870 deskew_delay[datx8][bit_i] = 0;
871 /* set a flag that will be used later
872 * in the report.
873 */
874 deskew_non_converge[datx8][bit_i] = 1;
Patrick Delaunay753f5362020-11-06 19:01:36 +0100875 log_debug("Fail not found on bit %d => deskew[%d][%d] = %d\n",
876 bit_i, datx8, bit_i,
877 deskew_delay[datx8][bit_i]);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200878 }
879 }
Patrick Delaunay753f5362020-11-06 19:01:36 +0100880 log_debug("**********byte %d tuning complete************\n",
881 datx8);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200882 /* If we can't find any failure by back delaying DQ lines,
883 * hold the default values
884 */
885 if (!fail_found) {
886 for (bit_i = 0; bit_i < 8; bit_i++)
887 deskew_delay[datx8][bit_i] = 0;
Patrick Delaunay753f5362020-11-06 19:01:36 +0100888 log_debug("The Deskew algorithm can't converge, there is too much margin in your design. Good job!\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200889 }
890
891 apply_deskew_results(phy, datx8, deskew_delay,
892 deskew_non_converge);
893 /* Restore nominal value for DQS delay */
894 DQS_phase_delay(phy, datx8, 3);
895 DQS_unit_delay(phy, datx8, 3);
896 /* disable byte after byte bits deskew */
897 clrbits_le32(DXNGCR(phy, datx8), DDRPHYC_DXNGCR_DXEN);
898 } /* end of byte deskew */
899
900 /* re-enable all data bytes */
901 setbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN);
902 setbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN);
903 setbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN);
904 setbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
905
906 if (error) {
907 sprintf(string, "error = %d", error);
908 return TEST_FAILED;
909 }
910
911 return TEST_PASSED;
912} /* end function */
913
914/* Trim DQS timings and set it in the centre of data eye.
915 * Look for a PPPPF region, then look for a FPPP region and finally select
916 * the mid of the FPPPPPF region
917 */
918static enum test_result eye_training(struct stm32mp1_ddrctl *ctl,
919 struct stm32mp1_ddrphy *phy, char *string)
920{
921 /*Stores the DQS trim values (PHASE index, unit index) */
922 u8 eye_training_val[NUM_BYTES][2];
923 u8 byte = 0;
924 struct BIST_result result;
925 s8 dqs_unit_delay_index = 0;
926 s8 phase_idx = 0;
927 s8 dqs_unit_delay_index_pass = 0;
928 s8 phase_idx_pass = 0;
929 u8 success = 0;
930 u8 left_phase_bound_found, right_phase_bound_found;
931 u8 left_unit_bound_found, right_unit_bound_found;
932 u8 left_bound_found, right_bound_found;
933 struct tuning_position left_bound, right_bound;
934 u8 error = 0;
935 u8 nb_bytes = get_nb_bytes(ctl);
936
937 /*Disable DQS Drift Compensation*/
938 clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP);
939 /*Disable all bytes*/
940 /* Disable automatic power down of DLL and IOs when disabling a byte
941 * (To avoid having to add programming and delay
942 * for a DLL re-lock when later re-enabling a disabled Byte Lane)
943 */
944 clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_PDDISDX);
945
946 /*Disable all data bytes */
947 clrbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN);
948 clrbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN);
949 clrbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN);
950 clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
951
952 /* Config the BIST block */
Patrick Delaunay131ec952020-03-06 11:14:08 +0100953 config_BIST(ctl, phy);
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200954
955 for (byte = 0; byte < nb_bytes; byte++) {
956 if (ctrlc()) {
957 sprintf(string, "interrupted at byte %d/%d, error=%d",
958 byte + 1, nb_bytes, error);
959 return TEST_FAILED;
960 }
961 right_bound.phase = 0;
962 right_bound.unit = 0;
963
964 left_bound.phase = 0;
965 left_bound.unit = 0;
966
967 left_phase_bound_found = 0;
968 right_phase_bound_found = 0;
969
970 left_unit_bound_found = 0;
971 right_unit_bound_found = 0;
972
973 left_bound_found = 0;
974 right_bound_found = 0;
975
976 /* Enable Byte (DXNGCR, bit DXEN) */
977 setbits_le32(DXNGCR(phy, byte), DDRPHYC_DXNGCR_DXEN);
978
979 /* Select the byte lane for comparison of read data */
980 BIST_datx8_sel(phy, byte);
981
982 /* Set DQS phase delay to the nominal value. */
983 phase_idx = _90deg;
984 phase_idx_pass = phase_idx;
985
986 /* Set DQS unit delay to the nominal value. */
987 dqs_unit_delay_index = 3;
988 dqs_unit_delay_index_pass = dqs_unit_delay_index;
989 success = 0;
990
Patrick Delaunay753f5362020-11-06 19:01:36 +0100991 log_debug("STEP0: Find Init delay\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +0200992 /* STEP0: Find Init delay: a delay that put the system
993 * in a "Pass" condition then (TODO) update
994 * dqs_unit_delay_index_pass & phase_idx_pass
995 */
996 DQS_unit_delay(phy, byte, dqs_unit_delay_index);
997 DQS_phase_delay(phy, byte, phase_idx);
998 BIST_test(phy, byte, &result);
999 success = result.test_result;
1000 /* If we have a fail in the nominal condition */
1001 if (!success) {
1002 /* Look at the left */
1003 while (phase_idx >= 0 && !success) {
1004 phase_idx--;
1005 DQS_phase_delay(phy, byte, phase_idx);
1006 BIST_test(phy, byte, &result);
1007 success = result.test_result;
1008 }
1009 }
1010 if (!success) {
1011 /* if we can't find pass condition,
1012 * then look at the right
1013 */
1014 phase_idx = _90deg;
1015 while (phase_idx <= MAX_DQS_PHASE_IDX &&
1016 !success) {
1017 phase_idx++;
1018 DQS_phase_delay(phy, byte,
1019 phase_idx);
1020 BIST_test(phy, byte, &result);
1021 success = result.test_result;
1022 }
1023 }
1024 /* save the pass condition */
1025 if (success) {
1026 phase_idx_pass = phase_idx;
1027 } else {
1028 printf("Result: Failed ");
1029 printf("[Cannot DQS timings, ");
1030 printf("there is no PASS region]\n");
1031 error++;
1032 continue;
1033 }
1034
1035 if (ctrlc()) {
1036 sprintf(string, "interrupted at byte %d/%d, error=%d",
1037 byte + 1, nb_bytes, error);
1038 return TEST_FAILED;
1039 }
Patrick Delaunay753f5362020-11-06 19:01:36 +01001040 log_debug("STEP1: Find LEFT PHASE DQS Bound\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001041 /* STEP1: Find LEFT PHASE DQS Bound */
1042 while ((phase_idx >= 0) &&
1043 (phase_idx <= MAX_DQS_PHASE_IDX) &&
1044 !left_phase_bound_found) {
1045 DQS_unit_delay(phy, byte,
1046 dqs_unit_delay_index);
1047 DQS_phase_delay(phy, byte,
1048 phase_idx);
1049 BIST_test(phy, byte, &result);
1050 success = result.test_result;
1051
1052 /*TODO: Manage the case were at the beginning
1053 * there is already a fail
1054 */
1055 if (!success) {
1056 /* the last pass condition */
1057 left_bound.phase = ++phase_idx;
1058 left_phase_bound_found = 1;
1059 } else if (success) {
1060 phase_idx--;
1061 }
1062 }
1063 if (!left_phase_bound_found) {
1064 left_bound.phase = 0;
1065 phase_idx = 0;
1066 }
1067 /* If not found, lets take 0 */
1068
1069 if (ctrlc()) {
1070 sprintf(string, "interrupted at byte %d/%d, error=%d",
1071 byte + 1, nb_bytes, error);
1072 return TEST_FAILED;
1073 }
Patrick Delaunay753f5362020-11-06 19:01:36 +01001074 log_debug("STEP2: Find UNIT left bound\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001075 /* STEP2: Find UNIT left bound */
1076 while ((dqs_unit_delay_index >= 0) &&
1077 !left_unit_bound_found) {
1078 DQS_unit_delay(phy, byte,
1079 dqs_unit_delay_index);
1080 DQS_phase_delay(phy, byte, phase_idx);
1081 BIST_test(phy, byte, &result);
1082 success = result.test_result;
1083 if (!success) {
1084 left_bound.unit =
1085 ++dqs_unit_delay_index;
1086 left_unit_bound_found = 1;
1087 left_bound_found = 1;
1088 } else if (success) {
1089 dqs_unit_delay_index--;
1090 }
1091 }
1092
1093 /* If not found, lets take 0 */
1094 if (!left_unit_bound_found)
1095 left_bound.unit = 0;
1096
1097 if (ctrlc()) {
1098 sprintf(string, "interrupted at byte %d/%d, error=%d",
1099 byte + 1, nb_bytes, error);
1100 return TEST_FAILED;
1101 }
Patrick Delaunay753f5362020-11-06 19:01:36 +01001102 log_debug("STEP3: Find PHase right bound\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001103 /* STEP3: Find PHase right bound, start with "pass"
1104 * condition
1105 */
1106
1107 /* Set DQS phase delay to the pass value. */
1108 phase_idx = phase_idx_pass;
1109
1110 /* Set DQS unit delay to the pass value. */
1111 dqs_unit_delay_index = dqs_unit_delay_index_pass;
1112
1113 while ((phase_idx <= MAX_DQS_PHASE_IDX) &&
1114 !right_phase_bound_found) {
1115 DQS_unit_delay(phy, byte,
1116 dqs_unit_delay_index);
1117 DQS_phase_delay(phy, byte, phase_idx);
1118 BIST_test(phy, byte, &result);
1119 success = result.test_result;
1120 if (!success) {
1121 /* the last pass condition */
1122 right_bound.phase = --phase_idx;
1123 right_phase_bound_found = 1;
1124 } else if (success) {
1125 phase_idx++;
1126 }
1127 }
1128
1129 /* If not found, lets take the max value */
1130 if (!right_phase_bound_found) {
1131 right_bound.phase = MAX_DQS_PHASE_IDX;
1132 phase_idx = MAX_DQS_PHASE_IDX;
1133 }
1134
1135 if (ctrlc()) {
1136 sprintf(string, "interrupted at byte %d/%d, error=%d",
1137 byte + 1, nb_bytes, error);
1138 return TEST_FAILED;
1139 }
Patrick Delaunay753f5362020-11-06 19:01:36 +01001140 log_debug("STEP4: Find UNIT right bound\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001141 /* STEP4: Find UNIT right bound */
1142 while ((dqs_unit_delay_index <= MAX_DQS_UNIT_IDX) &&
1143 !right_unit_bound_found) {
1144 DQS_unit_delay(phy, byte,
1145 dqs_unit_delay_index);
1146 DQS_phase_delay(phy, byte, phase_idx);
1147 BIST_test(phy, byte, &result);
1148 success = result.test_result;
1149 if (!success) {
1150 right_bound.unit =
1151 --dqs_unit_delay_index;
1152 right_unit_bound_found = 1;
1153 right_bound_found = 1;
1154 } else if (success) {
1155 dqs_unit_delay_index++;
1156 }
1157 }
1158 /* If not found, lets take the max value */
1159 if (!right_unit_bound_found)
1160 right_bound.unit = MAX_DQS_UNIT_IDX;
1161
1162 /* If we found a regular FAil Pass FAil pattern
1163 * FFPPPPPPFF
1164 * OR PPPPPFF Or FFPPPPP
1165 */
1166
1167 if (left_bound_found || right_bound_found) {
1168 eye_training_val[byte][0] = (right_bound.phase +
1169 left_bound.phase) / 2;
1170 eye_training_val[byte][1] = (right_bound.unit +
1171 left_bound.unit) / 2;
1172
1173 /* If we already lost 1/2PHASE Tuning,
1174 * let's try to recover by ++ on unit
1175 */
1176 if (((right_bound.phase + left_bound.phase) % 2 == 1) &&
1177 eye_training_val[byte][1] != MAX_DQS_UNIT_IDX)
1178 eye_training_val[byte][1]++;
Patrick Delaunay753f5362020-11-06 19:01:36 +01001179 log_debug("** found phase : %d - %d & unit %d - %d\n",
1180 right_bound.phase, left_bound.phase,
1181 right_bound.unit, left_bound.unit);
1182 log_debug("** calculating mid region: phase: %d unit: %d (nominal is 3)\n",
1183 eye_training_val[byte][0],
1184 eye_training_val[byte][1]);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001185 } else {
1186 /* PPPPPPPPPP, we're already good.
1187 * Set nominal values.
1188 */
1189 eye_training_val[byte][0] = 3;
1190 eye_training_val[byte][1] = 3;
1191 }
1192 DQS_phase_delay(phy, byte, eye_training_val[byte][0]);
1193 DQS_unit_delay(phy, byte, eye_training_val[byte][1]);
1194
1195 printf("Byte %d, DQS unit = %d, phase = %d\n",
1196 byte,
1197 eye_training_val[byte][1],
1198 eye_training_val[byte][0]);
1199 }
1200
1201 if (error) {
1202 sprintf(string, "error = %d", error);
1203 return TEST_FAILED;
1204 }
1205
1206 return TEST_PASSED;
1207}
1208
1209static void display_reg_results(struct stm32mp1_ddrphy *phy, u8 byte)
1210{
1211 u8 i = 0;
1212
1213 printf("Byte %d Dekew result, bit0 delay, bit1 delay...bit8 delay\n ",
1214 byte);
1215
1216 for (i = 0; i < 8; i++)
1217 printf("%d ", DQ_unit_index(phy, byte, i));
1218 printf("\n");
1219
1220 printf("dxndllcr: [%08x] val:%08x\n",
1221 DXNDLLCR(phy, byte),
1222 readl(DXNDLLCR(phy, byte)));
1223 printf("dxnqdstr: [%08x] val:%08x\n",
1224 DXNDQSTR(phy, byte),
1225 readl(DXNDQSTR(phy, byte)));
1226 printf("dxndqtr: [%08x] val:%08x\n",
1227 DXNDQTR(phy, byte),
1228 readl(DXNDQTR(phy, byte)));
1229}
1230
1231/* analyse the dgs gating log table, and determine the midpoint.*/
1232static u8 set_midpoint_read_dqs_gating(struct stm32mp1_ddrphy *phy, u8 byte,
1233 u8 dqs_gating[NUM_BYTES]
1234 [MAX_GSL_IDX + 1]
1235 [MAX_GPS_IDX + 1])
1236{
1237 /* stores the dqs gate values (gsl index, gps index) */
1238 u8 dqs_gate_values[NUM_BYTES][2];
1239 u8 gsl_idx, gps_idx = 0;
1240 u8 left_bound_idx[2] = {0, 0};
1241 u8 right_bound_idx[2] = {0, 0};
1242 u8 left_bound_found = 0;
1243 u8 right_bound_found = 0;
1244 u8 intermittent = 0;
1245 u8 value;
1246
1247 for (gsl_idx = 0; gsl_idx <= MAX_GSL_IDX; gsl_idx++) {
1248 for (gps_idx = 0; gps_idx <= MAX_GPS_IDX; gps_idx++) {
1249 value = dqs_gating[byte][gsl_idx][gps_idx];
1250 if (value == 1 && left_bound_found == 0) {
1251 left_bound_idx[0] = gsl_idx;
1252 left_bound_idx[1] = gps_idx;
1253 left_bound_found = 1;
1254 } else if (value == 0 &&
1255 left_bound_found == 1 &&
1256 !right_bound_found) {
1257 if (gps_idx == 0) {
1258 right_bound_idx[0] = gsl_idx - 1;
1259 right_bound_idx[1] = MAX_GPS_IDX;
1260 } else {
1261 right_bound_idx[0] = gsl_idx;
1262 right_bound_idx[1] = gps_idx - 1;
1263 }
1264 right_bound_found = 1;
1265 } else if (value == 1 &&
1266 right_bound_found == 1) {
1267 intermittent = 1;
1268 }
1269 }
1270 }
1271
1272 /* if only ppppppp is found, there is no mid region. */
1273 if (left_bound_idx[0] == 0 && left_bound_idx[1] == 0 &&
1274 right_bound_idx[0] == 0 && right_bound_idx[1] == 0)
1275 intermittent = 1;
1276
1277 /*if we found a regular fail pass fail pattern ffppppppff
1278 * or pppppff or ffppppp
1279 */
1280 if (!intermittent) {
1281 /*if we found a regular fail pass fail pattern ffppppppff
1282 * or pppppff or ffppppp
1283 */
1284 if (left_bound_found || right_bound_found) {
Patrick Delaunay753f5362020-11-06 19:01:36 +01001285 log_debug("idx0(%d): %d %d idx1(%d) : %d %d\n",
1286 left_bound_found,
1287 right_bound_idx[0], left_bound_idx[0],
1288 right_bound_found,
1289 right_bound_idx[1], left_bound_idx[1]);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001290 dqs_gate_values[byte][0] =
1291 (right_bound_idx[0] + left_bound_idx[0]) / 2;
1292 dqs_gate_values[byte][1] =
1293 (right_bound_idx[1] + left_bound_idx[1]) / 2;
1294 /* if we already lost 1/2gsl tuning,
1295 * let's try to recover by ++ on gps
1296 */
1297 if (((right_bound_idx[0] +
1298 left_bound_idx[0]) % 2 == 1) &&
1299 dqs_gate_values[byte][1] != MAX_GPS_IDX)
1300 dqs_gate_values[byte][1]++;
1301 /* if we already lost 1/2gsl tuning and gps is on max*/
1302 else if (((right_bound_idx[0] +
1303 left_bound_idx[0]) % 2 == 1) &&
1304 dqs_gate_values[byte][1] == MAX_GPS_IDX) {
1305 dqs_gate_values[byte][1] = 0;
1306 dqs_gate_values[byte][0]++;
1307 }
1308 /* if we have gsl left and write limit too close
1309 * (difference=1)
1310 */
1311 if (((right_bound_idx[0] - left_bound_idx[0]) == 1)) {
1312 dqs_gate_values[byte][1] = (left_bound_idx[1] +
1313 right_bound_idx[1] +
1314 4) / 2;
1315 if (dqs_gate_values[byte][1] >= 4) {
1316 dqs_gate_values[byte][0] =
1317 right_bound_idx[0];
1318 dqs_gate_values[byte][1] -= 4;
1319 } else {
1320 dqs_gate_values[byte][0] =
1321 left_bound_idx[0];
1322 }
1323 }
Patrick Delaunay753f5362020-11-06 19:01:36 +01001324 log_debug("*******calculating mid region: system latency: %d phase: %d********\n",
1325 dqs_gate_values[byte][0],
1326 dqs_gate_values[byte][1]);
1327 log_debug("*******the nominal values were system latency: 0 phase: 2*******\n");
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001328 }
1329 } else {
1330 /* if intermitant, restore defaut values */
Patrick Delaunay753f5362020-11-06 19:01:36 +01001331 log_debug("dqs gating:no regular fail/pass/fail found. defaults values restored.\n");
Patrick Delaunay030df3b2020-03-06 11:14:04 +01001332 dqs_gate_values[byte][0] = 0;
1333 dqs_gate_values[byte][1] = 2;
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001334 }
Patrick Delaunay030df3b2020-03-06 11:14:04 +01001335 set_r0dgsl_delay(phy, byte, dqs_gate_values[byte][0]);
1336 set_r0dgps_delay(phy, byte, dqs_gate_values[byte][1]);
1337 printf("Byte %d, R0DGSL = %d, R0DGPS = %d\n",
1338 byte, dqs_gate_values[byte][0], dqs_gate_values[byte][1]);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001339
1340 /* return 0 if intermittent or if both left_bound
1341 * and right_bound are not found
1342 */
1343 return !(intermittent || (left_bound_found && right_bound_found));
1344}
1345
1346static enum test_result read_dqs_gating(struct stm32mp1_ddrctl *ctl,
1347 struct stm32mp1_ddrphy *phy,
1348 char *string)
1349{
1350 /* stores the log of pass/fail */
1351 u8 dqs_gating[NUM_BYTES][MAX_GSL_IDX + 1][MAX_GPS_IDX + 1];
1352 u8 byte, gsl_idx, gps_idx = 0;
1353 struct BIST_result result;
1354 u8 success = 0;
1355 u8 nb_bytes = get_nb_bytes(ctl);
1356
1357 memset(dqs_gating, 0x0, sizeof(dqs_gating));
1358
1359 /*disable dqs drift compensation*/
1360 clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP);
1361 /*disable all bytes*/
1362 /* disable automatic power down of dll and ios when disabling a byte
1363 * (to avoid having to add programming and delay
1364 * for a dll re-lock when later re-enabling a disabled byte lane)
1365 */
1366 clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_PDDISDX);
1367
1368 /* disable all data bytes */
1369 clrbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN);
1370 clrbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN);
1371 clrbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN);
1372 clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
1373
1374 /* config the bist block */
Patrick Delaunay131ec952020-03-06 11:14:08 +01001375 config_BIST(ctl, phy);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001376
1377 for (byte = 0; byte < nb_bytes; byte++) {
1378 if (ctrlc()) {
1379 sprintf(string, "interrupted at byte %d/%d",
1380 byte + 1, nb_bytes);
1381 return TEST_FAILED;
1382 }
1383 /* enable byte x (dxngcr, bit dxen) */
1384 setbits_le32(DXNGCR(phy, byte), DDRPHYC_DXNGCR_DXEN);
1385
1386 /* select the byte lane for comparison of read data */
1387 BIST_datx8_sel(phy, byte);
1388 for (gsl_idx = 0; gsl_idx <= MAX_GSL_IDX; gsl_idx++) {
1389 for (gps_idx = 0; gps_idx <= MAX_GPS_IDX; gps_idx++) {
1390 if (ctrlc()) {
1391 sprintf(string,
1392 "interrupted at byte %d/%d",
1393 byte + 1, nb_bytes);
1394 return TEST_FAILED;
1395 }
1396 /* write cfg to dxndqstr */
1397 set_r0dgsl_delay(phy, byte, gsl_idx);
1398 set_r0dgps_delay(phy, byte, gps_idx);
1399
1400 BIST_test(phy, byte, &result);
1401 success = result.test_result;
1402 if (success)
1403 dqs_gating[byte][gsl_idx][gps_idx] = 1;
1404 itm_soft_reset(phy);
1405 }
1406 }
1407 set_midpoint_read_dqs_gating(phy, byte, dqs_gating);
1408 /* dummy reads */
1409 readl(0xc0000000);
1410 readl(0xc0000000);
1411 }
1412
1413 /* re-enable drift compensation */
1414 /* setbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP); */
1415 return TEST_PASSED;
1416}
1417
1418/****************************************************************
1419 * TEST
1420 ****************************************************************
1421 */
1422static enum test_result do_read_dqs_gating(struct stm32mp1_ddrctl *ctl,
1423 struct stm32mp1_ddrphy *phy,
1424 char *string, int argc,
1425 char *argv[])
1426{
1427 u32 rfshctl3 = readl(&ctl->rfshctl3);
1428 u32 pwrctl = readl(&ctl->pwrctl);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001429 u32 derateen = readl(&ctl->derateen);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001430 enum test_result res;
1431
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001432 writel(0x0, &ctl->derateen);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001433 stm32mp1_refresh_disable(ctl);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001434
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001435 res = read_dqs_gating(ctl, phy, string);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001436
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001437 stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001438 writel(derateen, &ctl->derateen);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001439
1440 return res;
1441}
1442
1443static enum test_result do_bit_deskew(struct stm32mp1_ddrctl *ctl,
1444 struct stm32mp1_ddrphy *phy,
1445 char *string, int argc, char *argv[])
1446{
1447 u32 rfshctl3 = readl(&ctl->rfshctl3);
1448 u32 pwrctl = readl(&ctl->pwrctl);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001449 u32 derateen = readl(&ctl->derateen);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001450 enum test_result res;
1451
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001452 writel(0x0, &ctl->derateen);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001453 stm32mp1_refresh_disable(ctl);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001454
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001455 res = bit_deskew(ctl, phy, string);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001456
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001457 stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001458 writel(derateen, &ctl->derateen);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001459
1460 return res;
1461}
1462
1463static enum test_result do_eye_training(struct stm32mp1_ddrctl *ctl,
1464 struct stm32mp1_ddrphy *phy,
1465 char *string, int argc, char *argv[])
1466{
1467 u32 rfshctl3 = readl(&ctl->rfshctl3);
1468 u32 pwrctl = readl(&ctl->pwrctl);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001469 u32 derateen = readl(&ctl->derateen);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001470 enum test_result res;
1471
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001472 writel(0x0, &ctl->derateen);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001473 stm32mp1_refresh_disable(ctl);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001474
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001475 res = eye_training(ctl, phy, string);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001476
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001477 stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl);
Patrick Delaunay656d2a92020-03-06 11:14:07 +01001478 writel(derateen, &ctl->derateen);
Patrick Delaunay2f91e612019-04-10 14:09:29 +02001479
1480 return res;
1481}
1482
1483static enum test_result do_display(struct stm32mp1_ddrctl *ctl,
1484 struct stm32mp1_ddrphy *phy,
1485 char *string, int argc, char *argv[])
1486{
1487 int byte;
1488 u8 nb_bytes = get_nb_bytes(ctl);
1489
1490 for (byte = 0; byte < nb_bytes; byte++)
1491 display_reg_results(phy, byte);
1492
1493 return TEST_PASSED;
1494}
1495
1496static enum test_result do_bist_config(struct stm32mp1_ddrctl *ctl,
1497 struct stm32mp1_ddrphy *phy,
1498 char *string, int argc, char *argv[])
1499{
1500 unsigned long value;
1501
1502 if (argc > 0) {
1503 if (strict_strtoul(argv[0], 0, &value) < 0) {
1504 sprintf(string, "invalid nbErr %s", argv[0]);
1505 return TEST_FAILED;
1506 }
1507 BIST_error_max = value;
1508 }
1509 if (argc > 1) {
1510 if (strict_strtoul(argv[1], 0, &value) < 0) {
1511 sprintf(string, "invalid Seed %s", argv[1]);
1512 return TEST_FAILED;
1513 }
1514 BIST_seed = value;
1515 }
1516 printf("Bist.nbErr = %d\n", BIST_error_max);
1517 if (BIST_seed)
1518 printf("Bist.Seed = 0x%x\n", BIST_seed);
1519 else
1520 printf("Bist.Seed = random\n");
1521
1522 return TEST_PASSED;
1523}
1524
1525/****************************************************************
1526 * TEST Description
1527 ****************************************************************
1528 */
1529
1530const struct test_desc tuning[] = {
1531 {do_read_dqs_gating, "Read DQS gating",
1532 "software read DQS Gating", "", 0 },
1533 {do_bit_deskew, "Bit de-skew", "", "", 0 },
1534 {do_eye_training, "Eye Training", "or DQS training", "", 0 },
1535 {do_display, "Display registers", "", "", 0 },
1536 {do_bist_config, "Bist config", "[nbErr] [seed]",
1537 "configure Bist test", 2},
1538};
1539
1540const int tuning_nb = ARRAY_SIZE(tuning);