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