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