nb/intel/gm45: Split DDR2 JEDEC init out
Split JEDEC init into common and DDR3 specific parts and add the DDR2 specific init code. This also replaces raw `mchbar_clrsetbits32` calls with a dedicated `jedec_command` function. TEST: DDR2 systems boot (with the rest of the patch train) - Tested on a Dell Latitude E6400 - Tested on a Compal JHL90 TEST: Ensure DDR3 systems still boot - Tested on a Thinkpad X200 Change-Id: I7a57549887c0323e5babbf18f691183412a99ba9 Signed-off-by: Nico Huber <nico.h@gmx.de> Reviewed-on: https://review.coreboot.org/c/coreboot/+/34827 Reviewed-by: Angel Pons <th3fanbus@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
0c314f9c7e
commit
c9847884ff
|
@ -243,6 +243,7 @@ enum {
|
|||
#define DCC_CMD_SHIFT 16
|
||||
#define DCC_CMD_MASK (7 << DCC_CMD_SHIFT)
|
||||
#define DCC_CMD_NOP (1 << DCC_CMD_SHIFT)
|
||||
#define DCC_CMD_ABP (2 << DCC_CMD_SHIFT)
|
||||
/* For mode register mr0: */
|
||||
#define DCC_SET_MREG (3 << DCC_CMD_SHIFT)
|
||||
/* For extended mode registers mr1 to mr3: */
|
||||
|
@ -252,6 +253,7 @@ enum {
|
|||
#define DCC_SET_EREGx(x) ((DCC_SET_EREG | \
|
||||
(((x) - 1) << DCC_SET_EREG_SHIFT)) & \
|
||||
DCC_SET_EREG_MASK)
|
||||
#define DCC_CMD_CBR (6 << DCC_CMD_SHIFT)
|
||||
|
||||
/* Per channel DRAM Row Attribute registers (32-bit) */
|
||||
#define CxDRA_MCHBAR(x) (0x1208 + ((x) * 0x0100))
|
||||
|
|
|
@ -1697,28 +1697,19 @@ static void memory_io_init(const mem_clock_t ddr3clock,
|
|||
ddr3_read_io_init(ddr3clock, dimms, sff);
|
||||
}
|
||||
|
||||
static void jedec_init(const timings_t *const timings,
|
||||
const dimminfo_t *const dimms)
|
||||
static void jedec_command(const uintptr_t rankaddr, const u32 cmd, const u32 val)
|
||||
{
|
||||
mchbar_clrsetbits32(DCC_MCHBAR, DCC_SET_EREG_MASK, cmd);
|
||||
read32p(rankaddr | val);
|
||||
}
|
||||
|
||||
static void jedec_init_ddr3(const timings_t *const timings,
|
||||
const dimminfo_t *const dimms)
|
||||
{
|
||||
if ((timings->tWR < 5) || (timings->tWR > 12))
|
||||
die("tWR value unsupported in Jedec initialization.\n");
|
||||
|
||||
/* Pre-jedec settings */
|
||||
mchbar_setbits32(0x40, 1 << 1);
|
||||
mchbar_setbits32(0x230, 3 << 1);
|
||||
mchbar_setbits32(0x238, 3 << 24);
|
||||
mchbar_setbits32(0x23c, 3 << 24);
|
||||
|
||||
/* Normal write pointer operation */
|
||||
mchbar_setbits32(0x14f0, 1 << 9);
|
||||
mchbar_setbits32(0x15f0, 1 << 9);
|
||||
|
||||
mchbar_clrsetbits32(DCC_MCHBAR, DCC_CMD_MASK, DCC_CMD_NOP);
|
||||
|
||||
pci_and_config8(PCI_DEV(0, 0, 0), 0xf0, ~(1 << 2));
|
||||
|
||||
pci_or_config8(PCI_DEV(0, 0, 0), 0xf0, 1 << 2);
|
||||
udelay(2);
|
||||
|
||||
/* 5 6 7 8 9 10 11 12 */
|
||||
static const u8 wr_lut[] = { 1, 2, 3, 4, 5, 5, 6, 6 };
|
||||
|
@ -1736,18 +1727,82 @@ static void jedec_init(const timings_t *const timings,
|
|||
/* We won't do this in dual-interleaved mode,
|
||||
so don't care about the offset.
|
||||
Mirrored ranks aren't taken into account here. */
|
||||
const u32 rankaddr = raminit_get_rank_addr(ch, r);
|
||||
printk(BIOS_DEBUG, "JEDEC init @0x%08x\n", rankaddr);
|
||||
mchbar_clrsetbits32(DCC_MCHBAR, DCC_SET_EREG_MASK, DCC_SET_EREGx(2));
|
||||
read32p(rankaddr | WL);
|
||||
mchbar_clrsetbits32(DCC_MCHBAR, DCC_SET_EREG_MASK, DCC_SET_EREGx(3));
|
||||
read32p(rankaddr);
|
||||
mchbar_clrsetbits32(DCC_MCHBAR, DCC_SET_EREG_MASK, DCC_SET_EREGx(1));
|
||||
read32p(rankaddr | ODT_120OHMS | ODS_34OHMS);
|
||||
mchbar_clrsetbits32(DCC_MCHBAR, DCC_CMD_MASK, DCC_SET_MREG);
|
||||
read32p(rankaddr | WR | DLL1 | CAS | INTERLEAVED);
|
||||
mchbar_clrsetbits32(DCC_MCHBAR, DCC_CMD_MASK, DCC_SET_MREG);
|
||||
read32p(rankaddr | WR | CAS | INTERLEAVED);
|
||||
const uintptr_t rankaddr = raminit_get_rank_addr(ch, r);
|
||||
printk(BIOS_DEBUG, "JEDEC init @0x%08x\n", (u32)rankaddr);
|
||||
|
||||
jedec_command(rankaddr, DCC_SET_EREGx(2), WL);
|
||||
jedec_command(rankaddr, DCC_SET_EREGx(3), 0);
|
||||
jedec_command(rankaddr, DCC_SET_EREGx(1), ODT_120OHMS | ODS_34OHMS);
|
||||
jedec_command(rankaddr, DCC_SET_MREG, WR | DLL1 | CAS | INTERLEAVED);
|
||||
jedec_command(rankaddr, DCC_SET_MREG, WR | CAS | INTERLEAVED);
|
||||
}
|
||||
}
|
||||
|
||||
static void jedec_init_ddr2(const timings_t *const timings,
|
||||
const dimminfo_t *const dimms)
|
||||
{
|
||||
/* All bit offsets are off by 3 (2^3 bytes bus width). */
|
||||
|
||||
/* Mode Register (MR) settings */
|
||||
const int WR = ((timings->tWR - 1) & 7) << 12;
|
||||
const int DLLreset = 1 << 11;
|
||||
const int CAS = (timings->CAS & 7) << 7;
|
||||
const int BTinterleaved = 1 << 6;
|
||||
const int BL8 = 3 << 3;
|
||||
|
||||
/* Extended Mode Register 1 (EMR1) */
|
||||
const int OCDdefault = 7 << 10;
|
||||
const int ODT_150OHMS = 1 << 9 | 0 << 5;
|
||||
|
||||
int ch, r;
|
||||
FOR_EACH_POPULATED_RANK(dimms, ch, r) {
|
||||
/* We won't do this in dual-interleaved mode,
|
||||
so don't care about the offset.
|
||||
Mirrored ranks aren't taken into account here. */
|
||||
const uintptr_t rankaddr = raminit_get_rank_addr(ch, r);
|
||||
printk(BIOS_DEBUG, "JEDEC init @0x%08x\n", (u32)rankaddr);
|
||||
|
||||
jedec_command(rankaddr, DCC_CMD_ABP, 0);
|
||||
jedec_command(rankaddr, DCC_SET_EREGx(2), 0);
|
||||
jedec_command(rankaddr, DCC_SET_EREGx(3), 0);
|
||||
jedec_command(rankaddr, DCC_SET_EREGx(1), ODT_150OHMS);
|
||||
jedec_command(rankaddr, DCC_SET_MREG, WR | DLLreset | CAS | BTinterleaved | BL8);
|
||||
jedec_command(rankaddr, DCC_CMD_ABP, 0);
|
||||
jedec_command(rankaddr, DCC_CMD_CBR, 0);
|
||||
udelay(1);
|
||||
read32((void *)(rankaddr));
|
||||
|
||||
jedec_command(rankaddr, DCC_SET_MREG, WR | CAS | BTinterleaved | BL8);
|
||||
jedec_command(rankaddr, DCC_SET_EREGx(1), OCDdefault | ODT_150OHMS);
|
||||
jedec_command(rankaddr, DCC_SET_EREGx(1), ODT_150OHMS);
|
||||
}
|
||||
}
|
||||
|
||||
static void jedec_init(const int spd_type,
|
||||
const timings_t *const timings,
|
||||
const dimminfo_t *const dimms)
|
||||
{
|
||||
/* Pre-jedec settings */
|
||||
mchbar_setbits32(0x40, 1 << 1);
|
||||
mchbar_setbits32(0x230, 3 << 1);
|
||||
mchbar_setbits32(0x238, 3 << 24);
|
||||
mchbar_setbits32(0x23c, 3 << 24);
|
||||
|
||||
/* Normal write pointer operation */
|
||||
mchbar_setbits32(0x14f0, 1 << 9);
|
||||
mchbar_setbits32(0x15f0, 1 << 9);
|
||||
|
||||
mchbar_clrsetbits32(DCC_MCHBAR, DCC_CMD_MASK, DCC_CMD_NOP);
|
||||
|
||||
pci_and_config8(PCI_DEV(0, 0, 0), 0xf0, ~(1 << 2));
|
||||
|
||||
pci_or_config8(PCI_DEV(0, 0, 0), 0xf0, 1 << 2);
|
||||
udelay(2);
|
||||
|
||||
if (spd_type == DDR2) {
|
||||
jedec_init_ddr2(timings, dimms);
|
||||
} else if (spd_type == DDR3) {
|
||||
jedec_init_ddr3(timings, dimms);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1920,7 +1975,7 @@ void raminit(sysinfo_t *const sysinfo, const int s3resume)
|
|||
prejedec_memory_map(dimms, timings->channel_mode);
|
||||
if (!s3resume)
|
||||
/* Perform JEDEC initialization of DIMMS. */
|
||||
jedec_init(timings, dimms);
|
||||
jedec_init(sysinfo->spd_type, timings, dimms);
|
||||
/* Some programming steps after JEDEC initialization. */
|
||||
post_jedec_sequence(sysinfo->cores);
|
||||
|
||||
|
|
Loading…
Reference in New Issue