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