1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <commonlib/helpers.h>
6 #include "raminit_common.h"
7 #include "raminit_tables.h"
8 #include "sandybridge.h"
10 /* FIXME: no support for 3-channel chipsets */
12 /* Number of programmed IOSAV subsequences. */
13 static unsigned int ssq_count
= 0;
15 void iosav_write_sequence(const int ch
, const struct iosav_ssq
*seq
, const unsigned int length
)
17 for (unsigned int i
= 0; i
< length
; i
++) {
18 mchbar_write32(IOSAV_n_SP_CMD_CTRL_ch(ch
, i
), seq
[i
].sp_cmd_ctrl
.raw
);
19 mchbar_write32(IOSAV_n_SUBSEQ_CTRL_ch(ch
, i
), seq
[i
].subseq_ctrl
.raw
);
20 mchbar_write32(IOSAV_n_SP_CMD_ADDR_ch(ch
, i
), seq
[i
].sp_cmd_addr
.raw
);
21 mchbar_write32(IOSAV_n_ADDR_UPDATE_ch(ch
, i
), seq
[i
].addr_update
.raw
);
27 void iosav_run_queue(const int ch
, const u8 loops
, const u8 as_timer
)
29 /* Should never happen */
33 mchbar_write32(IOSAV_SEQ_CTL_ch(ch
), loops
| (ssq_count
- 1) << 18 | as_timer
<< 22);
36 void wait_for_iosav(int channel
)
39 if (mchbar_read32(IOSAV_STATUS_ch(channel
)) & 0x50)
44 void iosav_run_once_and_wait(const int ch
)
46 iosav_run_queue(ch
, 1, 0);
50 void iosav_write_zqcs_sequence(int channel
, int slotrank
, u32 gap
, u32 post
, u32 wrap
)
52 const struct iosav_ssq sequence
[] = {
53 /* DRAM command ZQCS */
56 .command
= IOSAV_ZQCS
,
61 .post_ssq_wait
= post
,
62 .data_direction
= SSQ_NA
,
75 iosav_write_sequence(channel
, sequence
, ARRAY_SIZE(sequence
));
78 void iosav_write_prea_sequence(int channel
, int slotrank
, u32 post
, u32 wrap
)
80 const struct iosav_ssq sequence
[] = {
81 /* DRAM command PREA */
90 .post_ssq_wait
= post
,
91 .data_direction
= SSQ_NA
,
104 iosav_write_sequence(channel
, sequence
, ARRAY_SIZE(sequence
));
107 void iosav_write_read_mpr_sequence(
108 int channel
, int slotrank
, u32 tMOD
, u32 loops
, u32 gap
, u32 loops2
, u32 post2
)
110 const struct iosav_ssq sequence
[] = {
114 * Write MR3 MPR enable. In this mode only RD and RDA
115 * are allowed, and all reads return a predefined pattern.
119 .command
= IOSAV_MRS
,
125 .post_ssq_wait
= tMOD
,
126 .data_direction
= SSQ_NA
,
135 /* DRAM command RD */
142 .cmd_executions
= loops
,
143 .cmd_delay_gap
= gap
,
145 .data_direction
= SSQ_RD
,
154 /* DRAM command RD */
161 .cmd_executions
= loops2
,
163 .post_ssq_wait
= post2
,
164 .data_direction
= SSQ_NA
,
176 * Write MR3 MPR disable.
180 .command
= IOSAV_MRS
,
186 .post_ssq_wait
= tMOD
,
187 .data_direction
= SSQ_NA
,
197 iosav_write_sequence(channel
, sequence
, ARRAY_SIZE(sequence
));
200 void iosav_write_prea_act_read_sequence(ramctr_timing
*ctrl
, int channel
, int slotrank
)
202 const struct iosav_ssq sequence
[] = {
203 /* DRAM command PREA */
206 .command
= IOSAV_PRE
,
212 .post_ssq_wait
= ctrl
->tRP
,
213 .data_direction
= SSQ_NA
,
225 /* DRAM command ACT */
228 .command
= IOSAV_ACT
,
233 .cmd_delay_gap
= MAX(ctrl
->tRRD
, (ctrl
->tFAW
>> 2) + 1),
234 .post_ssq_wait
= ctrl
->CAS
,
235 .data_direction
= SSQ_NA
,
248 /* DRAM command RD */
255 .cmd_executions
= 500,
257 .post_ssq_wait
= MAX(ctrl
->tRTP
, 8),
258 .data_direction
= SSQ_RD
,
271 /* DRAM command PREA */
274 .command
= IOSAV_PRE
,
280 .post_ssq_wait
= ctrl
->tRP
,
281 .data_direction
= SSQ_NA
,
294 iosav_write_sequence(channel
, sequence
, ARRAY_SIZE(sequence
));
297 void iosav_write_jedec_write_leveling_sequence(
298 ramctr_timing
*ctrl
, int channel
, int slotrank
, int bank
, u32 mr1reg
)
300 /* First DQS/DQS# rising edge after write leveling mode is programmed */
301 const u32 tWLMRD
= 40;
303 const struct iosav_ssq sequence
[] = {
304 /* DRAM command MRS: enable DQs on this slotrank */
307 .command
= IOSAV_MRS
,
313 .post_ssq_wait
= tWLMRD
,
314 .data_direction
= SSQ_NA
,
323 /* DRAM command NOP */
326 .command
= IOSAV_NOP
,
332 .post_ssq_wait
= ctrl
->CWL
+ ctrl
->tWLO
,
333 .data_direction
= SSQ_WR
,
342 /* DRAM command NOP */
345 .command
= IOSAV_NOP_ALT
,
351 .post_ssq_wait
= ctrl
->CAS
+ 38,
352 .data_direction
= SSQ_RD
,
361 /* DRAM command MRS: disable DQs on this slotrank */
364 .command
= IOSAV_MRS
,
370 .post_ssq_wait
= ctrl
->tMOD
,
371 .data_direction
= SSQ_NA
,
374 .address
= mr1reg
| 1 << 12,
381 iosav_write_sequence(channel
, sequence
, ARRAY_SIZE(sequence
));
384 void iosav_write_misc_write_sequence(ramctr_timing
*ctrl
, int channel
, int slotrank
,
385 u32 gap0
, u32 loops0
, u32 gap1
, u32 loops2
, u32 wrap2
)
387 const struct iosav_ssq sequence
[] = {
388 /* DRAM command ACT */
391 .command
= IOSAV_ACT
,
395 .cmd_executions
= loops0
,
396 .cmd_delay_gap
= gap0
,
397 .post_ssq_wait
= ctrl
->tRCD
,
398 .data_direction
= SSQ_NA
,
407 .inc_bank
= loops0
== 1 ? 0 : 1,
408 .addr_wrap
= loops0
== 1 ? 0 : 18,
411 /* DRAM command NOP */
414 .command
= IOSAV_NOP
,
419 .cmd_delay_gap
= gap1
,
421 .data_direction
= SSQ_WR
,
433 /* DRAM command WR */
440 .cmd_executions
= loops2
,
443 .data_direction
= SSQ_WR
,
456 /* DRAM command NOP */
459 .command
= IOSAV_NOP
,
465 .post_ssq_wait
= ctrl
->CWL
+ ctrl
->tWTR
+ 5,
466 .data_direction
= SSQ_WR
,
479 iosav_write_sequence(channel
, sequence
, ARRAY_SIZE(sequence
));
482 void iosav_write_command_training_sequence(
483 ramctr_timing
*ctrl
, int channel
, int slotrank
, unsigned int address
)
485 const struct iosav_ssq sequence
[] = {
486 /* DRAM command ACT */
489 .command
= IOSAV_ACT
,
494 .cmd_delay_gap
= MAX(ctrl
->tRRD
, (ctrl
->tFAW
>> 2) + 1),
495 .post_ssq_wait
= ctrl
->tRCD
,
496 .data_direction
= SSQ_NA
,
509 /* DRAM command WR */
516 .cmd_executions
= 32,
518 .post_ssq_wait
= ctrl
->CWL
+ ctrl
->tWTR
+ 8,
519 .data_direction
= SSQ_WR
,
534 /* DRAM command RD */
541 .cmd_executions
= 32,
543 .post_ssq_wait
= MAX(ctrl
->tRTP
, 8),
544 .data_direction
= SSQ_RD
,
559 /* DRAM command PRE */
562 .command
= IOSAV_PRE
,
569 .data_direction
= SSQ_NA
,
582 iosav_write_sequence(channel
, sequence
, ARRAY_SIZE(sequence
));
585 void iosav_write_data_write_sequence(ramctr_timing
*ctrl
, int channel
, int slotrank
)
587 const struct iosav_ssq sequence
[] = {
588 /* DRAM command ACT */
591 .command
= IOSAV_ACT
,
596 .cmd_delay_gap
= MAX(ctrl
->tRRD
, (ctrl
->tFAW
>> 2) + 1),
597 .post_ssq_wait
= ctrl
->tRCD
,
598 .data_direction
= SSQ_NA
,
611 /* DRAM command WR */
618 .cmd_executions
= 32,
620 .post_ssq_wait
= ctrl
->CWL
+ ctrl
->tWTR
+ 8,
621 .data_direction
= SSQ_WR
,
634 /* DRAM command RD */
641 .cmd_executions
= 32,
643 .post_ssq_wait
= MAX(ctrl
->tRTP
, 8),
644 .data_direction
= SSQ_RD
,
657 /* DRAM command PRE */
660 .command
= IOSAV_PRE
,
666 .post_ssq_wait
= ctrl
->tRP
,
667 .data_direction
= SSQ_NA
,
677 iosav_write_sequence(channel
, sequence
, ARRAY_SIZE(sequence
));
680 void iosav_write_aggressive_write_read_sequence(ramctr_timing
*ctrl
, int channel
, int slotrank
)
682 const struct iosav_ssq sequence
[] = {
683 /* DRAM command ACT */
686 .command
= IOSAV_ACT
,
691 .cmd_delay_gap
= MAX((ctrl
->tFAW
>> 2) + 1, ctrl
->tRRD
),
692 .post_ssq_wait
= ctrl
->tRCD
,
693 .data_direction
= SSQ_NA
,
706 /* DRAM command WR */
713 .cmd_executions
= 480,
715 .post_ssq_wait
= ctrl
->tWTR
+ ctrl
->CWL
+ 8,
716 .data_direction
= SSQ_WR
,
729 /* DRAM command RD */
736 .cmd_executions
= 480,
738 .post_ssq_wait
= MAX(ctrl
->tRTP
, 8),
739 .data_direction
= SSQ_RD
,
752 /* DRAM command PRE */
755 .command
= IOSAV_PRE
,
761 .post_ssq_wait
= ctrl
->tRP
,
762 .data_direction
= SSQ_NA
,
772 iosav_write_sequence(channel
, sequence
, ARRAY_SIZE(sequence
));
775 void iosav_write_memory_test_sequence(ramctr_timing
*ctrl
, int channel
, int slotrank
)
777 const struct iosav_ssq sequence
[] = {
778 /* DRAM command ACT */
781 .command
= IOSAV_ACT
,
788 .data_direction
= SSQ_NA
,
801 /* DRAM command WR */
808 .cmd_executions
= 100,
811 .data_direction
= SSQ_WR
,
824 /* DRAM command RD */
831 .cmd_executions
= 100,
834 .data_direction
= SSQ_RD
,
847 /* DRAM command PRE */
850 .command
= IOSAV_PRE
,
857 .data_direction
= SSQ_NA
,
870 iosav_write_sequence(channel
, sequence
, ARRAY_SIZE(sequence
));