nb/intel/sandybridge: Redefine IOSAV_SUBSEQUENCE

Instead of directly writing values to the IOSAV registers, use a struct
and some helper functions to provide a cleaner interface for the IOSAV.
Having IOSAV_SUBSEQUENCE refer to a static function is weird, but we
will remove this macro in a follow-up that does not change the binary.

Tested on Asus P8Z77-V LX2, still boots.

Change-Id: I73f13c18a739c5586a7415966f9017c2335fdfd1
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/40980
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
Angel Pons 2020-05-02 21:48:46 +02:00
parent 2be5900087
commit d5b780c5b1
3 changed files with 104 additions and 7 deletions

View File

@ -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) \
#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 { \
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); \
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 */

View File

@ -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)

View File

@ -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