blob: 12a3be6806cc697b6fa17253938cc081a922a785 [file] [log] [blame]
Angel Pons1c505f82020-11-11 20:55:35 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <commonlib/helpers.h>
Angel Pons1c505f82020-11-11 20:55:35 +01004#include <types.h>
5
6#include "raminit_native.h"
7#include "raminit_common.h"
8#include "raminit_tables.h"
9#include "sandybridge.h"
10
11/* FIXME: no support for 3-channel chipsets */
12
13/* Number of programmed IOSAV subsequences. */
14static unsigned int ssq_count = 0;
15
Angel Pons8f0757e2020-11-11 23:03:36 +010016void iosav_write_sequence(const int ch, const struct iosav_ssq *seq, const unsigned int length)
Angel Pons1c505f82020-11-11 20:55:35 +010017{
Angel Pons8f0757e2020-11-11 23:03:36 +010018 for (unsigned int i = 0; i < length; i++) {
Angel Pons66780a02021-03-26 13:33:22 +010019 mchbar_write32(IOSAV_n_SP_CMD_CTRL_ch(ch, i), seq[i].sp_cmd_ctrl.raw);
20 mchbar_write32(IOSAV_n_SUBSEQ_CTRL_ch(ch, i), seq[i].subseq_ctrl.raw);
21 mchbar_write32(IOSAV_n_SP_CMD_ADDR_ch(ch, i), seq[i].sp_cmd_addr.raw);
22 mchbar_write32(IOSAV_n_ADDR_UPDATE_ch(ch, i), seq[i].addr_update.raw);
Angel Pons8f0757e2020-11-11 23:03:36 +010023 }
Angel Pons1c505f82020-11-11 20:55:35 +010024
Angel Pons8f0757e2020-11-11 23:03:36 +010025 ssq_count = length;
Angel Pons1c505f82020-11-11 20:55:35 +010026}
27
28void iosav_run_queue(const int ch, const u8 loops, const u8 as_timer)
29{
Angel Pons8f0757e2020-11-11 23:03:36 +010030 /* Should never happen */
31 if (ssq_count == 0)
32 return;
Angel Pons1c505f82020-11-11 20:55:35 +010033
Angel Pons66780a02021-03-26 13:33:22 +010034 mchbar_write32(IOSAV_SEQ_CTL_ch(ch), loops | (ssq_count - 1) << 18 | as_timer << 22);
Angel Pons1c505f82020-11-11 20:55:35 +010035}
36
Angel Pons1c505f82020-11-11 20:55:35 +010037void wait_for_iosav(int channel)
38{
39 while (1) {
Angel Pons66780a02021-03-26 13:33:22 +010040 if (mchbar_read32(IOSAV_STATUS_ch(channel)) & 0x50)
Angel Pons1c505f82020-11-11 20:55:35 +010041 return;
42 }
43}
Angel Ponsffd50152020-11-12 11:03:10 +010044
Angel Ponsa853e7a2020-12-07 12:28:38 +010045void iosav_run_once_and_wait(const int ch)
46{
Angel Pons9f4ed3b2020-12-07 12:34:36 +010047 iosav_run_queue(ch, 1, 0);
Angel Ponsa853e7a2020-12-07 12:28:38 +010048 wait_for_iosav(ch);
49}
50
Angel Ponsffd50152020-11-12 11:03:10 +010051void iosav_write_zqcs_sequence(int channel, int slotrank, u32 gap, u32 post, u32 wrap)
52{
Angel Pons9f58bb22020-11-12 11:56:07 +010053 const struct iosav_ssq sequence[] = {
54 /* DRAM command ZQCS */
55 [0] = {
56 .sp_cmd_ctrl = {
57 .command = IOSAV_ZQCS,
58 },
59 .subseq_ctrl = {
60 .cmd_executions = 1,
61 .cmd_delay_gap = gap,
62 .post_ssq_wait = post,
63 .data_direction = SSQ_NA,
64 },
65 .sp_cmd_addr = {
66 .address = 0,
67 .rowbits = 6,
68 .bank = 0,
69 .rank = slotrank,
70 },
71 .addr_update = {
72 .addr_wrap = wrap,
73 },
74 },
75 };
Angel Ponsffd50152020-11-12 11:03:10 +010076 iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
77}
78
79void iosav_write_prea_sequence(int channel, int slotrank, u32 post, u32 wrap)
80{
Angel Pons9f58bb22020-11-12 11:56:07 +010081 const struct iosav_ssq sequence[] = {
82 /* DRAM command PREA */
83 [0] = {
84 .sp_cmd_ctrl = {
85 .command = IOSAV_PRE,
86 .ranksel_ap = 1,
87 },
88 .subseq_ctrl = {
89 .cmd_executions = 1,
90 .cmd_delay_gap = 3,
91 .post_ssq_wait = post,
92 .data_direction = SSQ_NA,
93 },
94 .sp_cmd_addr = {
Angel Pons5db1b152020-12-13 16:37:53 +010095 .address = 1 << 10,
Angel Pons9f58bb22020-11-12 11:56:07 +010096 .rowbits = 6,
97 .bank = 0,
98 .rank = slotrank,
99 },
100 .addr_update = {
101 .addr_wrap = wrap,
102 },
103 },
104 };
Angel Ponsffd50152020-11-12 11:03:10 +0100105 iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
106}
107
108void iosav_write_read_mpr_sequence(
109 int channel, int slotrank, u32 tMOD, u32 loops, u32 gap, u32 loops2, u32 post2)
110{
Angel Pons9f58bb22020-11-12 11:56:07 +0100111 const struct iosav_ssq sequence[] = {
112 /*
113 * DRAM command MRS
114 *
115 * Write MR3 MPR enable. In this mode only RD and RDA
116 * are allowed, and all reads return a predefined pattern.
117 */
118 [0] = {
119 .sp_cmd_ctrl = {
120 .command = IOSAV_MRS,
121 .ranksel_ap = 1,
122 },
123 .subseq_ctrl = {
124 .cmd_executions = 1,
125 .cmd_delay_gap = 3,
126 .post_ssq_wait = tMOD,
127 .data_direction = SSQ_NA,
128 },
129 .sp_cmd_addr = {
130 .address = 4,
131 .rowbits = 6,
132 .bank = 3,
133 .rank = slotrank,
134 },
135 },
136 /* DRAM command RD */
137 [1] = {
138 .sp_cmd_ctrl = {
139 .command = IOSAV_RD,
140 .ranksel_ap = 1,
141 },
142 .subseq_ctrl = {
143 .cmd_executions = loops,
144 .cmd_delay_gap = gap,
145 .post_ssq_wait = 4,
146 .data_direction = SSQ_RD,
147 },
148 .sp_cmd_addr = {
149 .address = 0,
150 .rowbits = 0,
151 .bank = 0,
152 .rank = slotrank,
153 },
154 },
155 /* DRAM command RD */
156 [2] = {
157 .sp_cmd_ctrl = {
158 .command = IOSAV_RD,
159 .ranksel_ap = 1,
160 },
161 .subseq_ctrl = {
162 .cmd_executions = loops2,
163 .cmd_delay_gap = 4,
164 .post_ssq_wait = post2,
165 .data_direction = SSQ_NA,
166 },
167 .sp_cmd_addr = {
168 .address = 0,
169 .rowbits = 6,
170 .bank = 0,
171 .rank = slotrank,
172 },
173 },
174 /*
175 * DRAM command MRS
176 *
177 * Write MR3 MPR disable.
178 */
179 [3] = {
180 .sp_cmd_ctrl = {
181 .command = IOSAV_MRS,
182 .ranksel_ap = 1,
183 },
184 .subseq_ctrl = {
185 .cmd_executions = 1,
186 .cmd_delay_gap = 3,
187 .post_ssq_wait = tMOD,
188 .data_direction = SSQ_NA,
189 },
190 .sp_cmd_addr = {
191 .address = 0,
192 .rowbits = 6,
193 .bank = 3,
194 .rank = slotrank,
195 },
196 },
197 };
Angel Ponsffd50152020-11-12 11:03:10 +0100198 iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
199}
200
Angel Pons801a5cb2020-11-15 15:48:29 +0100201void iosav_write_prea_act_read_sequence(ramctr_timing *ctrl, int channel, int slotrank)
202{
203 const struct iosav_ssq sequence[] = {
204 /* DRAM command PREA */
205 [0] = {
206 .sp_cmd_ctrl = {
207 .command = IOSAV_PRE,
208 .ranksel_ap = 1,
209 },
210 .subseq_ctrl = {
211 .cmd_executions = 1,
212 .cmd_delay_gap = 3,
213 .post_ssq_wait = ctrl->tRP,
214 .data_direction = SSQ_NA,
215 },
216 .sp_cmd_addr = {
Angel Pons5db1b152020-12-13 16:37:53 +0100217 .address = 1 << 10,
Angel Pons801a5cb2020-11-15 15:48:29 +0100218 .rowbits = 6,
219 .bank = 0,
220 .rank = slotrank,
221 },
222 .addr_update = {
223 .addr_wrap = 18,
224 },
225 },
226 /* DRAM command ACT */
227 [1] = {
228 .sp_cmd_ctrl = {
229 .command = IOSAV_ACT,
230 .ranksel_ap = 1,
231 },
232 .subseq_ctrl = {
233 .cmd_executions = 8,
234 .cmd_delay_gap = MAX(ctrl->tRRD, (ctrl->tFAW >> 2) + 1),
235 .post_ssq_wait = ctrl->CAS,
236 .data_direction = SSQ_NA,
237 },
238 .sp_cmd_addr = {
239 .address = 0,
240 .rowbits = 6,
241 .bank = 0,
242 .rank = slotrank,
243 },
244 .addr_update = {
245 .inc_bank = 1,
246 .addr_wrap = 18,
247 },
248 },
249 /* DRAM command RD */
250 [2] = {
251 .sp_cmd_ctrl = {
252 .command = IOSAV_RD,
253 .ranksel_ap = 1,
254 },
255 .subseq_ctrl = {
256 .cmd_executions = 500,
257 .cmd_delay_gap = 4,
258 .post_ssq_wait = MAX(ctrl->tRTP, 8),
259 .data_direction = SSQ_RD,
260 },
261 .sp_cmd_addr = {
262 .address = 0,
263 .rowbits = 0,
264 .bank = 0,
265 .rank = slotrank,
266 },
267 .addr_update = {
268 .inc_addr_8 = 1,
269 .addr_wrap = 18,
270 },
271 },
272 /* DRAM command PREA */
273 [3] = {
274 .sp_cmd_ctrl = {
275 .command = IOSAV_PRE,
276 .ranksel_ap = 1,
277 },
278 .subseq_ctrl = {
279 .cmd_executions = 1,
280 .cmd_delay_gap = 3,
281 .post_ssq_wait = ctrl->tRP,
282 .data_direction = SSQ_NA,
283 },
284 .sp_cmd_addr = {
Angel Pons5db1b152020-12-13 16:37:53 +0100285 .address = 1 << 10,
Angel Pons801a5cb2020-11-15 15:48:29 +0100286 .rowbits = 6,
287 .bank = 0,
288 .rank = slotrank,
289 },
290 .addr_update = {
291 .addr_wrap = 18,
292 },
293 },
294 };
295 iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
296}
297
Angel Pons94267212020-11-14 16:49:29 +0100298void iosav_write_jedec_write_leveling_sequence(
299 ramctr_timing *ctrl, int channel, int slotrank, int bank, u32 mr1reg)
300{
301 /* First DQS/DQS# rising edge after write leveling mode is programmed */
302 const u32 tWLMRD = 40;
303
304 const struct iosav_ssq sequence[] = {
305 /* DRAM command MRS: enable DQs on this slotrank */
306 [0] = {
307 .sp_cmd_ctrl = {
308 .command = IOSAV_MRS,
309 .ranksel_ap = 1,
310 },
311 .subseq_ctrl = {
312 .cmd_executions = 1,
313 .cmd_delay_gap = 3,
314 .post_ssq_wait = tWLMRD,
315 .data_direction = SSQ_NA,
316 },
317 .sp_cmd_addr = {
318 .address = mr1reg,
319 .rowbits = 6,
320 .bank = bank,
321 .rank = slotrank,
322 },
323 },
324 /* DRAM command NOP */
325 [1] = {
326 .sp_cmd_ctrl = {
327 .command = IOSAV_NOP,
328 .ranksel_ap = 1,
329 },
330 .subseq_ctrl = {
331 .cmd_executions = 1,
332 .cmd_delay_gap = 3,
333 .post_ssq_wait = ctrl->CWL + ctrl->tWLO,
334 .data_direction = SSQ_WR,
335 },
336 .sp_cmd_addr = {
337 .address = 8,
338 .rowbits = 0,
339 .bank = 0,
340 .rank = slotrank,
341 },
342 },
343 /* DRAM command NOP */
344 [2] = {
345 .sp_cmd_ctrl = {
346 .command = IOSAV_NOP_ALT,
347 .ranksel_ap = 1,
348 },
349 .subseq_ctrl = {
350 .cmd_executions = 1,
351 .cmd_delay_gap = 3,
352 .post_ssq_wait = ctrl->CAS + 38,
353 .data_direction = SSQ_RD,
354 },
355 .sp_cmd_addr = {
356 .address = 4,
357 .rowbits = 0,
358 .bank = 0,
359 .rank = slotrank,
360 },
361 },
362 /* DRAM command MRS: disable DQs on this slotrank */
363 [3] = {
364 .sp_cmd_ctrl = {
365 .command = IOSAV_MRS,
366 .ranksel_ap = 1,
367 },
368 .subseq_ctrl = {
369 .cmd_executions = 1,
370 .cmd_delay_gap = 3,
371 .post_ssq_wait = ctrl->tMOD,
372 .data_direction = SSQ_NA,
373 },
374 .sp_cmd_addr = {
375 .address = mr1reg | 1 << 12,
376 .rowbits = 6,
377 .bank = bank,
378 .rank = slotrank,
379 },
380 },
381 };
382 iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
383}
384
Angel Ponsffd50152020-11-12 11:03:10 +0100385void iosav_write_misc_write_sequence(ramctr_timing *ctrl, int channel, int slotrank,
386 u32 gap0, u32 loops0, u32 gap1, u32 loops2, u32 wrap2)
387{
Angel Pons9f58bb22020-11-12 11:56:07 +0100388 const struct iosav_ssq sequence[] = {
389 /* DRAM command ACT */
390 [0] = {
391 .sp_cmd_ctrl = {
392 .command = IOSAV_ACT,
393 .ranksel_ap = 1,
394 },
395 .subseq_ctrl = {
396 .cmd_executions = loops0,
397 .cmd_delay_gap = gap0,
398 .post_ssq_wait = ctrl->tRCD,
399 .data_direction = SSQ_NA,
400 },
401 .sp_cmd_addr = {
402 .address = 0,
403 .rowbits = 6,
404 .bank = 0,
405 .rank = slotrank,
406 },
407 .addr_update = {
408 .inc_bank = loops0 == 1 ? 0 : 1,
409 .addr_wrap = loops0 == 1 ? 0 : 18,
410 },
411 },
412 /* DRAM command NOP */
413 [1] = {
414 .sp_cmd_ctrl = {
415 .command = IOSAV_NOP,
416 .ranksel_ap = 1,
417 },
418 .subseq_ctrl = {
419 .cmd_executions = 1,
420 .cmd_delay_gap = gap1,
421 .post_ssq_wait = 4,
422 .data_direction = SSQ_WR,
423 },
424 .sp_cmd_addr = {
425 .address = 8,
426 .rowbits = 0,
427 .bank = 0,
428 .rank = slotrank,
429 },
430 .addr_update = {
431 .addr_wrap = 31,
432 },
433 },
434 /* DRAM command WR */
435 [2] = {
436 .sp_cmd_ctrl = {
437 .command = IOSAV_WR,
438 .ranksel_ap = 1,
439 },
440 .subseq_ctrl = {
441 .cmd_executions = loops2,
442 .cmd_delay_gap = 4,
443 .post_ssq_wait = 4,
444 .data_direction = SSQ_WR,
445 },
446 .sp_cmd_addr = {
447 .address = 0,
448 .rowbits = 0,
449 .bank = 0,
450 .rank = slotrank,
451 },
452 .addr_update = {
453 .inc_addr_8 = 1,
454 .addr_wrap = wrap2,
455 },
456 },
457 /* DRAM command NOP */
458 [3] = {
459 .sp_cmd_ctrl = {
460 .command = IOSAV_NOP,
461 .ranksel_ap = 1,
462 },
463 .subseq_ctrl = {
464 .cmd_executions = 1,
465 .cmd_delay_gap = 3,
466 .post_ssq_wait = ctrl->CWL + ctrl->tWTR + 5,
467 .data_direction = SSQ_WR,
468 },
469 .sp_cmd_addr = {
470 .address = 8,
471 .rowbits = 0,
472 .bank = 0,
473 .rank = slotrank,
474 },
475 .addr_update = {
476 .addr_wrap = 31,
477 },
478 },
479 };
Angel Ponsffd50152020-11-12 11:03:10 +0100480 iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
481}
482
483void iosav_write_command_training_sequence(
484 ramctr_timing *ctrl, int channel, int slotrank, unsigned int address)
485{
Angel Pons9f58bb22020-11-12 11:56:07 +0100486 const struct iosav_ssq sequence[] = {
487 /* DRAM command ACT */
488 [0] = {
489 .sp_cmd_ctrl = {
490 .command = IOSAV_ACT,
491 .ranksel_ap = 1,
492 },
493 .subseq_ctrl = {
494 .cmd_executions = 8,
495 .cmd_delay_gap = MAX(ctrl->tRRD, (ctrl->tFAW >> 2) + 1),
496 .post_ssq_wait = ctrl->tRCD,
497 .data_direction = SSQ_NA,
498 },
499 .sp_cmd_addr = {
500 .address = address,
501 .rowbits = 6,
502 .bank = 0,
503 .rank = slotrank,
504 },
505 .addr_update = {
506 .inc_bank = 1,
507 .addr_wrap = 18,
508 },
509 },
510 /* DRAM command WR */
511 [1] = {
512 .sp_cmd_ctrl = {
513 .command = IOSAV_WR,
514 .ranksel_ap = 1,
515 },
516 .subseq_ctrl = {
517 .cmd_executions = 32,
518 .cmd_delay_gap = 4,
519 .post_ssq_wait = ctrl->CWL + ctrl->tWTR + 8,
520 .data_direction = SSQ_WR,
521 },
522 .sp_cmd_addr = {
523 .address = 0,
524 .rowbits = 0,
525 .bank = 0,
526 .rank = slotrank,
527 },
528 .addr_update = {
529 .inc_addr_8 = 1,
530 .addr_wrap = 18,
531 .lfsr_upd = 3,
532 .lfsr_xors = 2,
533 },
534 },
535 /* DRAM command RD */
536 [2] = {
537 .sp_cmd_ctrl = {
538 .command = IOSAV_RD,
539 .ranksel_ap = 1,
540 },
541 .subseq_ctrl = {
542 .cmd_executions = 32,
543 .cmd_delay_gap = 4,
544 .post_ssq_wait = MAX(ctrl->tRTP, 8),
545 .data_direction = SSQ_RD,
546 },
547 .sp_cmd_addr = {
548 .address = 0,
549 .rowbits = 0,
550 .bank = 0,
551 .rank = slotrank,
552 },
553 .addr_update = {
554 .inc_addr_8 = 1,
555 .addr_wrap = 18,
556 .lfsr_upd = 3,
557 .lfsr_xors = 2,
558 },
559 },
560 /* DRAM command PRE */
561 [3] = {
562 .sp_cmd_ctrl = {
563 .command = IOSAV_PRE,
564 .ranksel_ap = 1,
565 },
566 .subseq_ctrl = {
567 .cmd_executions = 1,
568 .cmd_delay_gap = 4,
569 .post_ssq_wait = 15,
570 .data_direction = SSQ_NA,
571 },
572 .sp_cmd_addr = {
Angel Pons5db1b152020-12-13 16:37:53 +0100573 .address = 1 << 10,
Angel Pons9f58bb22020-11-12 11:56:07 +0100574 .rowbits = 6,
575 .bank = 0,
576 .rank = slotrank,
577 },
578 .addr_update = {
579 .addr_wrap = 18,
580 },
581 },
582 };
Angel Ponsffd50152020-11-12 11:03:10 +0100583 iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
584}
585
586void iosav_write_data_write_sequence(ramctr_timing *ctrl, int channel, int slotrank)
587{
Angel Pons9f58bb22020-11-12 11:56:07 +0100588 const struct iosav_ssq sequence[] = {
589 /* DRAM command ACT */
590 [0] = {
591 .sp_cmd_ctrl = {
592 .command = IOSAV_ACT,
593 .ranksel_ap = 1,
594 },
595 .subseq_ctrl = {
596 .cmd_executions = 4,
597 .cmd_delay_gap = MAX(ctrl->tRRD, (ctrl->tFAW >> 2) + 1),
598 .post_ssq_wait = ctrl->tRCD,
599 .data_direction = SSQ_NA,
600 },
601 .sp_cmd_addr = {
602 .address = 0,
603 .rowbits = 6,
604 .bank = 0,
605 .rank = slotrank,
606 },
607 .addr_update = {
608 .inc_bank = 0,
609 .addr_wrap = 18,
610 },
611 },
612 /* DRAM command WR */
613 [1] = {
614 .sp_cmd_ctrl = {
615 .command = IOSAV_WR,
616 .ranksel_ap = 1,
617 },
618 .subseq_ctrl = {
619 .cmd_executions = 32,
620 .cmd_delay_gap = 20,
621 .post_ssq_wait = ctrl->CWL + ctrl->tWTR + 8,
622 .data_direction = SSQ_WR,
623 },
624 .sp_cmd_addr = {
625 .address = 0,
626 .rowbits = 0,
627 .bank = 0,
628 .rank = slotrank,
629 },
630 .addr_update = {
631 .inc_addr_8 = 1,
632 .addr_wrap = 18,
633 },
634 },
635 /* DRAM command RD */
636 [2] = {
637 .sp_cmd_ctrl = {
638 .command = IOSAV_RD,
639 .ranksel_ap = 1,
640 },
641 .subseq_ctrl = {
642 .cmd_executions = 32,
643 .cmd_delay_gap = 20,
644 .post_ssq_wait = MAX(ctrl->tRTP, 8),
645 .data_direction = SSQ_RD,
646 },
647 .sp_cmd_addr = {
648 .address = 0,
649 .rowbits = 0,
650 .bank = 0,
651 .rank = slotrank,
652 },
653 .addr_update = {
654 .inc_addr_8 = 1,
655 .addr_wrap = 18,
656 },
657 },
658 /* DRAM command PRE */
659 [3] = {
660 .sp_cmd_ctrl = {
661 .command = IOSAV_PRE,
662 .ranksel_ap = 1,
663 },
664 .subseq_ctrl = {
665 .cmd_executions = 1,
666 .cmd_delay_gap = 3,
667 .post_ssq_wait = ctrl->tRP,
668 .data_direction = SSQ_NA,
669 },
670 .sp_cmd_addr = {
Angel Pons5db1b152020-12-13 16:37:53 +0100671 .address = 1 << 10,
Angel Pons9f58bb22020-11-12 11:56:07 +0100672 .rowbits = 6,
673 .bank = 0,
674 .rank = slotrank,
675 },
676 },
677 };
Angel Ponsffd50152020-11-12 11:03:10 +0100678 iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
679}
680
681void iosav_write_aggressive_write_read_sequence(ramctr_timing *ctrl, int channel, int slotrank)
682{
Angel Pons9f58bb22020-11-12 11:56:07 +0100683 const struct iosav_ssq sequence[] = {
684 /* DRAM command ACT */
685 [0] = {
686 .sp_cmd_ctrl = {
687 .command = IOSAV_ACT,
688 .ranksel_ap = 1,
689 },
690 .subseq_ctrl = {
691 .cmd_executions = 4,
692 .cmd_delay_gap = MAX((ctrl->tFAW >> 2) + 1, ctrl->tRRD),
693 .post_ssq_wait = ctrl->tRCD,
694 .data_direction = SSQ_NA,
695 },
696 .sp_cmd_addr = {
697 .address = 0,
698 .rowbits = 6,
699 .bank = 0,
700 .rank = slotrank,
701 },
702 .addr_update = {
703 .inc_bank = 1,
704 .addr_wrap = 18,
705 },
706 },
707 /* DRAM command WR */
708 [1] = {
709 .sp_cmd_ctrl = {
710 .command = IOSAV_WR,
711 .ranksel_ap = 1,
712 },
713 .subseq_ctrl = {
714 .cmd_executions = 480,
715 .cmd_delay_gap = 4,
716 .post_ssq_wait = ctrl->tWTR + ctrl->CWL + 8,
717 .data_direction = SSQ_WR,
718 },
719 .sp_cmd_addr = {
720 .address = 0,
721 .rowbits = 0,
722 .bank = 0,
723 .rank = slotrank,
724 },
725 .addr_update = {
726 .inc_addr_8 = 1,
727 .addr_wrap = 18,
728 },
729 },
730 /* DRAM command RD */
731 [2] = {
732 .sp_cmd_ctrl = {
733 .command = IOSAV_RD,
734 .ranksel_ap = 1,
735 },
736 .subseq_ctrl = {
737 .cmd_executions = 480,
738 .cmd_delay_gap = 4,
739 .post_ssq_wait = MAX(ctrl->tRTP, 8),
740 .data_direction = SSQ_RD,
741 },
742 .sp_cmd_addr = {
743 .address = 0,
744 .rowbits = 0,
745 .bank = 0,
746 .rank = slotrank,
747 },
748 .addr_update = {
749 .inc_addr_8 = 1,
750 .addr_wrap = 18,
751 },
752 },
753 /* DRAM command PRE */
754 [3] = {
755 .sp_cmd_ctrl = {
756 .command = IOSAV_PRE,
757 .ranksel_ap = 1,
758 },
759 .subseq_ctrl = {
760 .cmd_executions = 1,
761 .cmd_delay_gap = 4,
762 .post_ssq_wait = ctrl->tRP,
763 .data_direction = SSQ_NA,
764 },
765 .sp_cmd_addr = {
Angel Pons5db1b152020-12-13 16:37:53 +0100766 .address = 1 << 10,
Angel Pons9f58bb22020-11-12 11:56:07 +0100767 .rowbits = 6,
768 .bank = 0,
769 .rank = slotrank,
770 },
771 },
772 };
Angel Ponsffd50152020-11-12 11:03:10 +0100773 iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
774}
775
776void iosav_write_memory_test_sequence(ramctr_timing *ctrl, int channel, int slotrank)
777{
Angel Pons9f58bb22020-11-12 11:56:07 +0100778 const struct iosav_ssq sequence[] = {
779 /* DRAM command ACT */
780 [0] = {
781 .sp_cmd_ctrl = {
782 .command = IOSAV_ACT,
783 .ranksel_ap = 1,
784 },
785 .subseq_ctrl = {
786 .cmd_executions = 4,
787 .cmd_delay_gap = 8,
788 .post_ssq_wait = 40,
789 .data_direction = SSQ_NA,
790 },
791 .sp_cmd_addr = {
792 .address = 0,
793 .rowbits = 6,
794 .bank = 0,
795 .rank = slotrank,
796 },
797 .addr_update = {
798 .inc_bank = 1,
799 .addr_wrap = 18,
800 },
801 },
802 /* DRAM command WR */
803 [1] = {
804 .sp_cmd_ctrl = {
805 .command = IOSAV_WR,
806 .ranksel_ap = 1,
807 },
808 .subseq_ctrl = {
809 .cmd_executions = 100,
810 .cmd_delay_gap = 4,
811 .post_ssq_wait = 40,
812 .data_direction = SSQ_WR,
813 },
814 .sp_cmd_addr = {
815 .address = 0,
816 .rowbits = 0,
817 .bank = 0,
818 .rank = slotrank,
819 },
820 .addr_update = {
821 .inc_addr_8 = 1,
822 .addr_wrap = 18,
823 },
824 },
825 /* DRAM command RD */
826 [2] = {
827 .sp_cmd_ctrl = {
828 .command = IOSAV_RD,
829 .ranksel_ap = 1,
830 },
831 .subseq_ctrl = {
832 .cmd_executions = 100,
833 .cmd_delay_gap = 4,
834 .post_ssq_wait = 40,
835 .data_direction = SSQ_RD,
836 },
837 .sp_cmd_addr = {
838 .address = 0,
839 .rowbits = 0,
840 .bank = 0,
841 .rank = slotrank,
842 },
843 .addr_update = {
844 .inc_addr_8 = 1,
845 .addr_wrap = 18,
846 },
847 },
848 /* DRAM command PRE */
849 [3] = {
850 .sp_cmd_ctrl = {
851 .command = IOSAV_PRE,
852 .ranksel_ap = 1,
853 },
854 .subseq_ctrl = {
855 .cmd_executions = 1,
856 .cmd_delay_gap = 3,
857 .post_ssq_wait = 40,
858 .data_direction = SSQ_NA,
859 },
860 .sp_cmd_addr = {
Angel Pons5db1b152020-12-13 16:37:53 +0100861 .address = 1 << 10,
Angel Pons9f58bb22020-11-12 11:56:07 +0100862 .rowbits = 6,
863 .bank = 0,
864 .rank = slotrank,
865 },
866 .addr_update = {
867 .addr_wrap = 18,
868 },
869 },
870 };
Angel Ponsffd50152020-11-12 11:03:10 +0100871 iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
872}