summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/northbridge/intel/sandybridge/mchbar_regs.h37
-rw-r--r--src/northbridge/intel/sandybridge/raminit_common.c17
-rw-r--r--src/northbridge/intel/sandybridge/raminit_common.h57
3 files changed, 104 insertions, 7 deletions
diff --git a/src/northbridge/intel/sandybridge/mchbar_regs.h b/src/northbridge/intel/sandybridge/mchbar_regs.h
index 446861b4b7..0edfd5354a 100644
--- a/src/northbridge/intel/sandybridge/mchbar_regs.h
+++ b/src/northbridge/intel/sandybridge/mchbar_regs.h
@@ -213,12 +213,37 @@
((rate) << 12) | \
((xors) << 16))
-#define IOSAV_SUBSEQUENCE(ch, n, cmd, ranksel, reps, gap, post, dir, addr, rowbits, bank, rank, addr_1, addr_8, upd_bank, upd_rank, wrap, lfsr, rate, xors) \
- do { \
- MCHBAR32(IOSAV_n_SP_CMD_CTRL_ch(ch, n)) = (cmd) | ((ranksel) << 16); \
- MCHBAR32(IOSAV_n_SUBSEQ_CTRL_ch(ch, n)) = SUBSEQ_CTRL(reps, gap, post, dir); \
- MCHBAR32(IOSAV_n_SP_CMD_ADDR_ch(ch, n)) = SP_CMD_ADDR(addr, rowbits, bank, rank); \
- MCHBAR32(IOSAV_n_ADDR_UPDATE_ch(ch, n)) = ADDR_UPDATE(addr_1, addr_8, upd_bank, upd_rank, wrap, lfsr, rate, xors); \
+#define IOSAV_SUBSEQUENCE(ch, n, cmd, ranksel, reps, gap, post, dir, addr, row_bits, bank_addr, rank_addr, addr_1, addr_8, upd_bank, upd_rank, wrap, lfsr, rate, xors) \
+ do { \
+ const struct iosav_ssq ssq = { \
+ .sp_cmd_ctrl = { \
+ .command = cmd, \
+ .ranksel_ap = ranksel, \
+ }, \
+ .subseq_ctrl = { \
+ .cmd_executions = reps, \
+ .cmd_delay_gap = gap, \
+ .post_ssq_wait = post, \
+ .data_direction = dir, \
+ }, \
+ .sp_cmd_addr = { \
+ .address = addr, \
+ .rowbits = row_bits, \
+ .bank = bank_addr, \
+ .rank = rank_addr, \
+ }, \
+ .addr_update = { \
+ .inc_addr_1 = addr_1, \
+ .inc_addr_8 = addr_8, \
+ .inc_bank = upd_bank, \
+ .inc_rank = upd_rank, \
+ .addr_wrap = wrap, \
+ .lfsr_upd = lfsr, \
+ .upd_rate = rate, \
+ .lfsr_xors = xors, \
+ }, \
+ }; \
+ iosav_write_ssq(ch, n, &ssq); \
} while (0)
/* Indexed register helper macros */
diff --git a/src/northbridge/intel/sandybridge/raminit_common.c b/src/northbridge/intel/sandybridge/raminit_common.c
index d66a0f0ed3..c4bf5ff50e 100644
--- a/src/northbridge/intel/sandybridge/raminit_common.c
+++ b/src/northbridge/intel/sandybridge/raminit_common.c
@@ -17,10 +17,25 @@
/* FIXME: no support for 3-channel chipsets */
+/* Number of programmed IOSAV subsequences. */
+static unsigned int ssq_count = 0;
+
+static void iosav_write_ssq(const int ch, const int n, const struct iosav_ssq *ssq)
+{
+ MCHBAR32(IOSAV_n_SP_CMD_CTRL_ch(ch, ssq_count)) = ssq->sp_cmd_ctrl.raw;
+ MCHBAR32(IOSAV_n_SUBSEQ_CTRL_ch(ch, ssq_count)) = ssq->subseq_ctrl.raw;
+ MCHBAR32(IOSAV_n_SP_CMD_ADDR_ch(ch, ssq_count)) = ssq->sp_cmd_addr.raw;
+ MCHBAR32(IOSAV_n_ADDR_UPDATE_ch(ch, ssq_count)) = ssq->addr_update.raw;
+
+ ssq_count++;
+}
+
/* length: [1..4] */
static void iosav_run_queue(const int ch, const u8 loops, const u8 length, const u8 as_timer)
{
- MCHBAR32(IOSAV_SEQ_CTL_ch(ch)) = loops | ((length - 1) << 18) | (as_timer << 22);
+ MCHBAR32(IOSAV_SEQ_CTL_ch(ch)) = loops | ((ssq_count - 1) << 18) | (as_timer << 22);
+
+ ssq_count = 0;
}
static void iosav_run_once(const int ch, const u8 length)
diff --git a/src/northbridge/intel/sandybridge/raminit_common.h b/src/northbridge/intel/sandybridge/raminit_common.h
index c544cdebaf..6e76cbc0bb 100644
--- a/src/northbridge/intel/sandybridge/raminit_common.h
+++ b/src/northbridge/intel/sandybridge/raminit_common.h
@@ -34,6 +34,63 @@
#define IOSAV_WR (0xf201)
#define IOSAV_NOP (0xf207)
+struct iosav_ssq {
+ /* IOSAV_n_SP_CMD_CTRL */
+ union {
+ struct {
+ u32 command : 16;
+ u32 ranksel_ap : 2;
+ u32 : 14;
+ };
+ u32 raw;
+ } sp_cmd_ctrl;
+
+ /* IOSAV_n_SUBSEQ_CTRL */
+ union {
+ struct {
+ u32 cmd_executions : 9;
+ u32 : 1;
+ u32 cmd_delay_gap : 5;
+ u32 : 1;
+ u32 post_ssq_wait : 9;
+ u32 : 1;
+ u32 data_direction : 2;
+ u32 : 4;
+ };
+ u32 raw;
+ } subseq_ctrl;
+
+ /* IOSAV_n_SP_CMD_ADDR */
+ union {
+ struct {
+ u32 address : 16;
+ u32 rowbits : 3;
+ u32 : 1;
+ u32 bank : 3;
+ u32 : 1;
+ u32 rank : 2;
+ u32 : 6;
+ };
+ u32 raw;
+ } sp_cmd_addr;
+
+ /* IOSAV_n_ADDR_UPDATE */
+ union {
+ struct {
+ u32 inc_addr_1 : 1;
+ u32 inc_addr_8 : 1;
+ u32 inc_bank : 1;
+ u32 inc_rank : 2;
+ u32 addr_wrap : 5;
+ u32 lfsr_upd : 2;
+ u32 upd_rate : 4;
+ u32 lfsr_xors : 2;
+ u32 : 14;
+ };
+ u32 raw;
+ } addr_update;
+};
+
/* FIXME: Vendor BIOS uses 64 but our algorithms are less
performant and even 1 seems to be enough in practice. */
#define NUM_PATTERNS 4