coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
raminit_iosav.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <commonlib/helpers.h>
4 #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. */
14 static unsigned int ssq_count = 0;
15 
16 void iosav_write_sequence(const int ch, const struct iosav_ssq *seq, const unsigned int length)
17 {
18  for (unsigned int i = 0; i < length; i++) {
19  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);
23  }
24 
25  ssq_count = length;
26 }
27 
28 void iosav_run_queue(const int ch, const u8 loops, const u8 as_timer)
29 {
30  /* Should never happen */
31  if (ssq_count == 0)
32  return;
33 
34  mchbar_write32(IOSAV_SEQ_CTL_ch(ch), loops | (ssq_count - 1) << 18 | as_timer << 22);
35 }
36 
37 void wait_for_iosav(int channel)
38 {
39  while (1) {
40  if (mchbar_read32(IOSAV_STATUS_ch(channel)) & 0x50)
41  return;
42  }
43 }
44 
45 void iosav_run_once_and_wait(const int ch)
46 {
47  iosav_run_queue(ch, 1, 0);
49 }
50 
51 void iosav_write_zqcs_sequence(int channel, int slotrank, u32 gap, u32 post, u32 wrap)
52 {
53  const struct iosav_ssq sequence[] = {
54  /* DRAM command ZQCS */
55  [0] = {
56  .sp_cmd_ctrl = {
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  };
76  iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
77 }
78 
79 void iosav_write_prea_sequence(int channel, int slotrank, u32 post, u32 wrap)
80 {
81  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 = {
95  .address = 1 << 10,
96  .rowbits = 6,
97  .bank = 0,
98  .rank = slotrank,
99  },
100  .addr_update = {
101  .addr_wrap = wrap,
102  },
103  },
104  };
105  iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
106 }
107 
109  int channel, int slotrank, u32 tMOD, u32 loops, u32 gap, u32 loops2, u32 post2)
110 {
111  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  };
198  iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
199 }
200 
201 void 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 = {
217  .address = 1 << 10,
218  .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 = {
285  .address = 1 << 10,
286  .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 
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 
385 void iosav_write_misc_write_sequence(ramctr_timing *ctrl, int channel, int slotrank,
386  u32 gap0, u32 loops0, u32 gap1, u32 loops2, u32 wrap2)
387 {
388  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  };
480  iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
481 }
482 
484  ramctr_timing *ctrl, int channel, int slotrank, unsigned int address)
485 {
486  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 = {
573  .address = 1 << 10,
574  .rowbits = 6,
575  .bank = 0,
576  .rank = slotrank,
577  },
578  .addr_update = {
579  .addr_wrap = 18,
580  },
581  },
582  };
583  iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
584 }
585 
586 void iosav_write_data_write_sequence(ramctr_timing *ctrl, int channel, int slotrank)
587 {
588  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 = {
671  .address = 1 << 10,
672  .rowbits = 6,
673  .bank = 0,
674  .rank = slotrank,
675  },
676  },
677  };
678  iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
679 }
680 
681 void iosav_write_aggressive_write_read_sequence(ramctr_timing *ctrl, int channel, int slotrank)
682 {
683  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 = {
766  .address = 1 << 10,
767  .rowbits = 6,
768  .bank = 0,
769  .rank = slotrank,
770  },
771  },
772  };
773  iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
774 }
775 
776 void iosav_write_memory_test_sequence(ramctr_timing *ctrl, int channel, int slotrank)
777 {
778  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 = {
861  .address = 1 << 10,
862  .rowbits = 6,
863  .bank = 0,
864  .rank = slotrank,
865  },
866  .addr_update = {
867  .addr_wrap = 18,
868  },
869  },
870  };
871  iosav_write_sequence(channel, sequence, ARRAY_SIZE(sequence));
872 }
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define MAX(a, b)
Definition: helpers.h:40
static __always_inline void mchbar_write32(const uintptr_t offset, const uint32_t value)
Definition: fixed_bars.h:36
static __always_inline uint32_t mchbar_read32(const uintptr_t offset)
Definition: fixed_bars.h:21
uint64_t length
Definition: fw_cfg_if.h:1
uint64_t address
Definition: fw_cfg_if.h:0
static struct dramc_channel const ch[2]
#define IOSAV_ACT
#define IOSAV_RD
#define SSQ_WR
#define IOSAV_NOP
#define SSQ_NA
#define IOSAV_MRS
#define IOSAV_WR
#define SSQ_RD
#define IOSAV_ZQCS
#define IOSAV_NOP_ALT
#define IOSAV_PRE
void iosav_write_prea_sequence(int channel, int slotrank, u32 post, u32 wrap)
Definition: raminit_iosav.c:79
void iosav_run_queue(const int ch, const u8 loops, const u8 as_timer)
Definition: raminit_iosav.c:28
void iosav_write_aggressive_write_read_sequence(ramctr_timing *ctrl, int channel, int slotrank)
void iosav_write_command_training_sequence(ramctr_timing *ctrl, int channel, int slotrank, unsigned int address)
void iosav_write_memory_test_sequence(ramctr_timing *ctrl, int channel, int slotrank)
void iosav_write_read_mpr_sequence(int channel, int slotrank, u32 tMOD, u32 loops, u32 gap, u32 loops2, u32 post2)
static unsigned int ssq_count
Definition: raminit_iosav.c:14
void iosav_write_zqcs_sequence(int channel, int slotrank, u32 gap, u32 post, u32 wrap)
Definition: raminit_iosav.c:51
void iosav_write_misc_write_sequence(ramctr_timing *ctrl, int channel, int slotrank, u32 gap0, u32 loops0, u32 gap1, u32 loops2, u32 wrap2)
void iosav_run_once_and_wait(const int ch)
Definition: raminit_iosav.c:45
void iosav_write_prea_act_read_sequence(ramctr_timing *ctrl, int channel, int slotrank)
void wait_for_iosav(int channel)
Definition: raminit_iosav.c:37
void iosav_write_sequence(const int ch, const struct iosav_ssq *seq, const unsigned int length)
Definition: raminit_iosav.c:16
void iosav_write_data_write_sequence(ramctr_timing *ctrl, int channel, int slotrank)
void iosav_write_jedec_write_leveling_sequence(ramctr_timing *ctrl, int channel, int slotrank, int bank, u32 mr1reg)
#define IOSAV_n_ADDR_UPDATE_ch(ch, y)
Definition: mchbar.h:366
#define IOSAV_n_SUBSEQ_CTRL_ch(ch, y)
Definition: mchbar.h:368
#define IOSAV_n_SP_CMD_ADDR_ch(ch, y)
Definition: mchbar.h:365
#define IOSAV_SEQ_CTL_ch(ch)
Definition: mchbar.h:372
#define IOSAV_STATUS_ch(ch)
Definition: mchbar.h:374
#define IOSAV_n_SP_CMD_CTRL_ch(ch, y)
Definition: mchbar.h:367
uint32_t u32
Definition: stdint.h:51
uint8_t u8
Definition: stdint.h:45
union iosav_ssq::@334 sp_cmd_ctrl