Arthur Heymans has uploaded a new change for review. ( https://review.coreboot.org/19874 )
Change subject: nb/intel/x4x/raminit: Support programming initials DD3 DLL setting ......................................................................
nb/intel/x4x/raminit: Support programming initials DD3 DLL setting
Due to shear amount of tables for default DLL settings used, they are mostly pushed to a new file to avoid cluttering up the raminit.
Change-Id: Ia79b216ad69a02d4706ffc74f867a85db3eb2d6c Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M src/northbridge/intel/x4x/Makefile.inc M src/northbridge/intel/x4x/raminit_ddr23.c A src/northbridge/intel/x4x/raminit_tables.c M src/northbridge/intel/x4x/x4x.h 4 files changed, 470 insertions(+), 136 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/74/19874/1
diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc index ae8d388..8b59dbf 100644 --- a/src/northbridge/intel/x4x/Makefile.inc +++ b/src/northbridge/intel/x4x/Makefile.inc @@ -22,6 +22,7 @@ romstage-y += ram_calc.c romstage-y += spd_ddr2_decode.c romstage-y += spd_ddr3_decode.c +romstage-y += raminit_tables.c
ramstage-y += acpi.c ramstage-y += ram_calc.c diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c index 4db29f5..673ebad 100644 --- a/src/northbridge/intel/x4x/raminit_ddr23.c +++ b/src/northbridge/intel/x4x/raminit_ddr23.c @@ -367,9 +367,10 @@ setting->tap; }
-static void dqsset(u8 ch, u8 lane, const struct dll_setting *setting) +void dqsset(u8 ch, u8 lane, const struct dll_setting *setting) { - MCHBAR32(0x400*ch + 0x5fc) = MCHBAR32(0x400*ch + 0x5fc) & ~(2 << (lane*4)); + MCHBAR32(0x400*ch + 0x5fc) = (MCHBAR32(0x400*ch + 0x5fc) & ~(2 << (lane*4))) + | (setting->coarse << ((lane * 4) + 1));
MCHBAR32(0x400*ch + 0x5b4) = (MCHBAR32(0x400*ch + 0x5b4) & ~(0x201 << lane)) | (setting->db_en << (9 + lane)) | @@ -411,10 +412,10 @@ setting->tap; }
-static void dqset(u8 ch, u8 lane, const struct dll_setting *setting) +void dqset(u8 ch, u8 lane, const struct dll_setting *setting) { - MCHBAR32(0x400*ch + 0x5fc) = MCHBAR32(0x400*ch + 0x5fc) & ~(1 << (lane*4)); - + MCHBAR32(0x400*ch + 0x5fc) = (MCHBAR32(0x400*ch + 0x5fc) & ~(1 << (lane*4))) | + (setting->coarse << (lane * 4)); MCHBAR32(0x400*ch + 0x5a4) = (MCHBAR32(0x400*ch + 0x5a4) & ~(0x201 << lane)) | (setting->db_en << (9 + lane)) | (setting->db_sel << lane); @@ -615,7 +616,12 @@ MCHBAR16(0x400*i + 0x25b) = ((s->selected_timings.tRP + trpmod) << 9) | s->selected_timings.tRFC;
- MCHBAR16(0x400*i + 0x260) = (MCHBAR16(0x400*i + 0x260) & ~0x3fe) | (100 << 1); + if (s->spd_type == DDR2) + MCHBAR16(0x400*i + 0x260) = + (MCHBAR16(0x400*i + 0x260) & ~0x3fe) | (100 << 1); + else + MCHBAR16(0x400*i + 0x260) = + (MCHBAR16(0x400*i + 0x260) & ~0x3fe) | (256 << 1); MCHBAR8(0x400*i + 0x264) = 0xff; MCHBAR8(0x400*i + 0x25d) = (MCHBAR8(0x400*i + 0x25d) & ~0x3f) | s->selected_timings.tRAS; @@ -668,17 +674,30 @@ MCHBAR8(0x400*i + 0x24c) = MCHBAR8(0x400*i + 0x24c) & ~0x3;
reg16 = 0; - switch (s->selected_timings.mem_clk) { - default: - case MEM_CLOCK_667MHz: - reg16 = 0x99; - break; - case MEM_CLOCK_800MHz: - if (s->selected_timings.CAS == 5) - reg16 = 0x19a; - else if (s->selected_timings.CAS == 6) - reg16 = 0x9a; - break; + if (s->spd_type == DDR2) { + switch (s->selected_timings.mem_clk) { + default: + case MEM_CLOCK_667MHz: + reg16 = 0x99; + break; + case MEM_CLOCK_800MHz: + if (s->selected_timings.CAS == 5) + reg16 = 0x19a; + else if (s->selected_timings.CAS == 6) + reg16 = 0x9a; + break; + } + } else { /* DDR3 */ + switch (s->selected_timings.mem_clk) { + default: + case MEM_CLOCK_800MHz: + case MEM_CLOCK_1066MHz: + reg16 = 1; + break; + case MEM_CLOCK_1333MHz: + reg16 = 2; + break; + } } reg16 &= 0x7; reg16 += twl + 9; @@ -715,8 +734,37 @@ MCHBAR8(0x12d) = (MCHBAR8(0x12d) & ~0xf) | reg8; MCHBAR8(0x12f) = 0x4c; reg32 = (1 << 31) | (0x80 << 14) | (1 << 13) | (0xa << 9); + if (s->spd_type == DDR3) { + MCHBAR8(0x114) = 0x42; + reg16 = (512 - MAX(5, s->selected_timings.tRFC + + 10000 / ddr2ps[s->selected_timings.mem_clk])) / 2; + reg16 &= 0x1ff; + reg32 = (reg16 << 22) | (0x80 << 14) | (0xa << 9); + } MCHBAR32(0x6c0) = (MCHBAR32(0x6c0) & ~0xffffff00) | reg32; MCHBAR8(0x6c4) = (MCHBAR8(0x6c4) & ~0x7) | 0x2; +} + +static void program_dll_clk_ctrl(int channel, const struct dll_setting *dll_settings) +{ + clkset0(channel, &dll_settings[CLKSET0]); + clkset1(channel, &dll_settings[CLKSET1]); + ctrlset0(channel, &dll_settings[CTRL0]); + ctrlset1(channel, &dll_settings[CTRL1]); + ctrlset2(channel, &dll_settings[CTRL2]); + ctrlset3(channel, &dll_settings[CTRL3]); + cmdset(channel, &dll_settings[CMD]); +} + +static void program_dq_dqs(u8 channel, const struct dll_setting dll_setting[23]) +{ + int lane; + for (lane = 0; lane < 8; lane++) { + dqsset(channel, lane, &dll_setting[DQS1 + lane]); + } + for (lane = 0; lane < 8; lane++) { + dqset(channel, lane, &dll_setting[DQ1 + lane]); + } }
static void program_dll(struct sysinfo *s) @@ -726,6 +774,9 @@ u32 reg32 = 0; u8 lane;
+ const u8 rank2clken[8] = { 0x04, 0x01, 0x20, 0x08, 0x01, 0x04, + 0x08, 0x10 }; + MCHBAR16(0x180) = (MCHBAR16(0x180) & ~0x7e06) | 0xc04; MCHBAR16(0x182) = (MCHBAR16(0x182) & ~0x3ff) | 0xc8; MCHBAR16(0x18a) = (MCHBAR16(0x18a) & ~0x1f1f) | 0x0f0f; @@ -734,10 +785,14 @@ switch (s->selected_timings.mem_clk) { default: case MEM_CLOCK_667MHz: + case MEM_CLOCK_1333MHz: reg16 = (0xa << 9) | 0xa; break; case MEM_CLOCK_800MHz: reg16 = (0x9 << 9) | 0x9; + break; + case MEM_CLOCK_1066MHz: + reg16 = (0x7 << 9) | 0x7; break; } MCHBAR16(0x19c) = (MCHBAR16(0x19c) & ~0x1e0f) | reg16; @@ -762,14 +817,29 @@ udelay(1); // 533ns
// ME related - MCHBAR32(0x1a0) = (MCHBAR32(0x1a0) & ~0x7ffffff) | 0x551803; + if (s->spd_type == DDR2) + MCHBAR32(0x1a0) = (MCHBAR32(0x1a0) & ~0x7ffffff) | 0x551803; + else /* DDR3 */ + MCHBAR32(0x1a0) = (MCHBAR32(0x1a0) & ~0x7ffffff) | 0x555801;
MCHBAR16(0x1b4) = MCHBAR16(0x1b4) & ~0x800; - MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0xf0; + if (s->spd_type == DDR2) { + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0xf0; + } else { /* DDR3 */ + reg8 = 0x9; /* 0x9 << 4 ?? */ + if (s->dimms[0].ranks == 2) + reg8 &= ~0x80; + if (s->dimms[3].ranks == 2) + reg8 &= ~0x10; + MCHBAR8(0x1a8) = (MCHBAR8(0x1a8) & ~0xf0) | reg8; + } +
FOR_EACH_CHANNEL(i) { reg16 = 0; - MCHBAR16(0x400*i + 0x59c) = MCHBAR16(0x400*i + 0x59c) & ~0x3000; + if ((s->spd_type == DDR3) && (i == 0)) + reg16 = (0x3 << 12); + MCHBAR16(0x400*i + 0x59c) = (MCHBAR16(0x400*i + 0x59c) & ~0x3000) | reg16;
reg32 = 0; FOR_EACH_RANK_IN_CHANNEL(r) { @@ -780,114 +850,82 @@ MCHBAR32(0x400*i + 0x59c) = (MCHBAR32(0x400*i + 0x59c) & ~0xfff) | reg32; MCHBAR8(0x400*i + 0x594) = MCHBAR8(0x400*i + 0x594) & ~1;
- if (!CHANNEL_IS_POPULATED(s->dimms, i)) { - printk(BIOS_DEBUG, "No dimms in channel %d\n", i); - reg8 = 0x3f; - } else if (ONLY_DIMMA_IS_POPULATED(s->dimms, i)) { - printk(BIOS_DEBUG, "DimmA populated only in channel %d\n", i); - reg8 = 0x38; - } else if (ONLY_DIMMB_IS_POPULATED(s->dimms, i)) { - printk(BIOS_DEBUG, "DimmB populated only in channel %d\n", i); - reg8 = 0x7; - } else if (BOTH_DIMMS_ARE_POPULATED(s->dimms, i)) { - printk(BIOS_DEBUG, "Both dimms populated in channel %d\n", i); - reg8 = 0; - } else { - die("Unhandled case\n"); - } - - //reg8 = 0x00; // FIXME don't switch on all clocks anyway - - MCHBAR32(0x400*i + 0x5a0) = (MCHBAR32(0x400*i + 0x5a0) & ~0x3f000000) | + if (s->spd_type == DDR2) { + if (!CHANNEL_IS_POPULATED(s->dimms, i)) { + printk(BIOS_DEBUG, "No dimms in channel %d\n", i); + reg8 = 0x3f; + } else if (ONLY_DIMMA_IS_POPULATED(s->dimms, i)) { + printk(BIOS_DEBUG, "DimmA populated only in channel %d\n", i); + reg8 = 0x38; + } else if (ONLY_DIMMB_IS_POPULATED(s->dimms, i)) { + printk(BIOS_DEBUG, "DimmB populated only in channel %d\n", i); + reg8 = 0x7; + } else if (BOTH_DIMMS_ARE_POPULATED(s->dimms, i)) { + printk(BIOS_DEBUG, "Both dimms populated in channel %d\n", i); + reg8 = 0; + } else { + die("Unhandled case\n"); + } + MCHBAR32(0x400*i + 0x5a0) = (MCHBAR32(0x400*i + 0x5a0) & ~0x3f000000) | ((u32)(reg8 << 24)); + } else { /* DDR3 */ + FOR_EACH_RANK_IN_CHANNEL(r) { + if (RANK_IS_POPULATED(s->dimms, i, r)) { + MCHBAR8(0x400 * i + 0x5a0 + 3) = MCHBAR8(0x400 * i + 0x5a0 + 3) + & ~rank2clken[r + i * 4]; + } + } + } } // END EACH CHANNEL
- MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 1; - MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x4; + if (s->spd_type == DDR2) { + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 1; + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x4; + } else { /* DDR3 */ + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~1; + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0x4; + }
// Update DLL timing MCHBAR8(0x1a4) = MCHBAR8(0x1a4) & ~0x80; MCHBAR8(0x1a4) = MCHBAR8(0x1a4) | 0x40; MCHBAR16(0x5f0) = (MCHBAR16(0x5f0) & ~0x400) | 0x400;
- const struct dll_setting dll_setting_667[23] = { - // tap pi db delay - {13, 0, 1, 0, 0}, - {4, 1, 0, 0, 0}, - {13, 0, 1, 0, 0}, - {4, 5, 0, 0, 0}, - {4, 1, 0, 0, 0}, - {4, 1, 0, 0, 0}, - {4, 1, 0, 0, 0}, - {1, 5, 1, 1, 1}, - {1, 6, 1, 1, 1}, - {2, 0, 1, 1, 1}, - {2, 1, 1, 1, 1}, - {2, 1, 1, 1, 1}, - {14, 6, 1, 0, 0}, - {14, 3, 1, 0, 0}, - {14, 0, 1, 0, 0}, - {9, 0, 0, 0, 1}, - {9, 1, 0, 0, 1}, - {9, 2, 0, 0, 1}, - {9, 2, 0, 0, 1}, - {9, 1, 0, 0, 1}, - {6, 4, 0, 0, 1}, - {6, 2, 0, 0, 1}, - {5, 4, 0, 0, 1} - }; - - const struct dll_setting dll_setting_800[23] = { - // tap pi db delay - {11, 5, 1, 0, 0}, - {0, 5, 1, 1, 0}, - {11, 5, 1, 0, 0}, - {1, 4, 1, 1, 0}, - {0, 5, 1, 1, 0}, - {0, 5, 1, 1, 0}, - {0, 5, 1, 1, 0}, - {2, 5, 1, 1, 1}, - {2, 6, 1, 1, 1}, - {3, 0, 1, 1, 1}, - {3, 0, 1, 1, 1}, - {3, 3, 1, 1, 1}, - {2, 0, 1, 1, 1}, - {1, 3, 1, 1, 1}, - {0, 3, 1, 1, 1}, - {9, 3, 0, 0, 1}, - {9, 4, 0, 0, 1}, - {9, 5, 0, 0, 1}, - {9, 6, 0, 0, 1}, - {10, 0, 0, 0, 1}, - {8, 1, 0, 0, 1}, - {7, 5, 0, 0, 1}, - {6, 2, 0, 0, 1} - }; - FOR_EACH_POPULATED_CHANNEL(s->dimms, i) { MCHBAR16(0x400*i + 0x5f0) = (MCHBAR16(0x400*i + 0x5f0) & ~0x3fc) | 0x3fc; MCHBAR32(0x400*i + 0x5fc) = MCHBAR32(0x400*i + 0x5fc) & ~0xcccccccc; - MCHBAR8(0x400*i + 0x5d9) = (MCHBAR8(0x400*i + 0x5d9) & ~0xf0) | 0x70; - MCHBAR16(0x400*i + 0x590) = (MCHBAR16(0x400*i + 0x590) & ~0xffff) | 0x5555; + if (s->spd_type == DDR2) { + MCHBAR8(0x400*i + 0x5d9) = (MCHBAR8(0x400*i + 0x5d9) + & ~0xf0) | 0x70; + MCHBAR16(0x400*i + 0x590) = (MCHBAR16(0x400*i + 0x590) + & ~0xffff) | 0x5555; + } else { + MCHBAR8(0x400*i + 0x5d9) = (MCHBAR8(0x400*i + 0x5d9) + & ~0xf0) | 0x60; + MCHBAR16(0x400*i + 0x590) = (MCHBAR16(0x400*i + 0x590) + & ~0xffff) | 0xa955; + } }
FOR_EACH_POPULATED_CHANNEL(s->dimms, i) { - if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz) { - clkset0(i, &dll_setting_667[CLKSET0]); - clkset1(i, &dll_setting_667[CLKSET1]); - ctrlset0(i, &dll_setting_667[CTRL0]); - ctrlset1(i, &dll_setting_667[CTRL1]); - ctrlset2(i, &dll_setting_667[CTRL2]); - ctrlset3(i, &dll_setting_667[CTRL3]); - cmdset(i, &dll_setting_667[CMD]); - } else { - clkset0(i, &dll_setting_800[CLKSET0]); - clkset1(i, &dll_setting_800[CLKSET1]); - ctrlset0(i, &dll_setting_800[CTRL0]); - ctrlset1(i, &dll_setting_800[CTRL1]); - ctrlset2(i, &dll_setting_800[CTRL2]); - ctrlset3(i, &dll_setting_800[CTRL3]); - cmdset(i, &dll_setting_800[CMD]); + if (s->spd_type == DDR2) { + if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz) + program_dll_clk_ctrl(i, ddr2_dll_setting_667); + else + program_dll_clk_ctrl(i, ddr2_dll_setting_800); + } else { /* DDR3 */ + switch (s->selected_timings.mem_clk) { + default: + case MEM_CLOCK_800MHz: + program_dll_clk_ctrl(i, ddr3_dll_setting_800[s->nmode - 1]); + break; + case MEM_CLOCK_1066MHz: + program_dll_clk_ctrl(i, ddr3_dll_setting_1066[s->nmode - 1]); + break; + case MEM_CLOCK_1333MHz: + program_dll_clk_ctrl(i, ddr3_dll_setting_1333[s->nmode - 1]); + break; + } } }
@@ -954,23 +992,38 @@ }
clk = 0x1a; + if (s->selected_timings.mem_clk == MEM_CLOCK_1333MHz) + clk = 0x18; if (async != 1) { reg8 = MCHBAR8(0x188) & 0x1e; - if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz && - s->selected_timings.fsb_clk == FSB_CLOCK_800MHz) { - clk = 0x10; - } else if (s->selected_timings.mem_clk == MEM_CLOCK_800MHz) { - clk = 0x10; - } else { + switch (s->selected_timings.mem_clk) { + case MEM_CLOCK_667MHz: clk = 0x1a; + if (s->selected_timings.fsb_clk == FSB_CLOCK_800MHz) + clk = 0x10; + break; + case MEM_CLOCK_800MHz: + case MEM_CLOCK_1066MHz: + clk = 0x10; + break; + case MEM_CLOCK_1333MHz: + clk = 0x18; + break; + default: + clk = 0x1a; + break; } } MCHBAR8(0x180) = MCHBAR8(0x180) & ~0x80;
- if ((s->selected_timings.fsb_clk == FSB_CLOCK_800MHz) && - (s->selected_timings.mem_clk == MEM_CLOCK_667MHz)) { + if ((s->spd_type == DDR3 && s->selected_timings.mem_clk == MEM_CLOCK_1066MHz) + || (s->spd_type == DDR2 && s->selected_timings.fsb_clk == FSB_CLOCK_800MHz + && s->selected_timings.mem_clk == MEM_CLOCK_667MHz)) { i = MCHBAR8(0x180) & 0xf; - i = (i + 10) % 14; + if (s->spd_type == DDR2) + i = (i + 10) % 14; + else /* DDR3 */ + i = (i + 3) % 12; MCHBAR8(0x1c8) = (MCHBAR8(0x1c8) & ~0x1f) | i; MCHBAR8(0x180) = MCHBAR8(0x180) | 0x10; while (MCHBAR8(0x180) & 0x10) @@ -991,11 +1044,26 @@ // Program DQ/DQS dll settings reg32 = 0; FOR_EACH_POPULATED_CHANNEL(s->dimms, i) { - for (lane = 0; lane < 8; lane++) { - if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz) - reg32 = 0x06db7777; - else if (s->selected_timings.mem_clk == MEM_CLOCK_800MHz) + switch (s->selected_timings.mem_clk) { + default: /* Should not happen */ + break; + case MEM_CLOCK_667MHz: + reg32 = 0x06db7777; + break; + case MEM_CLOCK_800MHz: + if (s->spd_type == DDR2) reg32 = 0x00007777; + else /* DDR3 */ + reg32 = 0x06db6666; + break; + case MEM_CLOCK_1066MHz: + reg32 = 0x06db5555; + break; + case MEM_CLOCK_1333MHz: + reg32 = 0x00007777; + break; + } + for (lane = 0; lane < 8; lane++) { MCHBAR32(0x400*i + 0x540 + lane*4) = (MCHBAR32(0x400*i + 0x540 + lane*4) & 0x0fffffff) | reg32; @@ -1003,16 +1071,24 @@ }
FOR_EACH_POPULATED_CHANNEL(s->dimms, i) { - if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz) { - for (lane = 0; lane < 8; lane++) - dqsset(i, lane, &dll_setting_667[DQS1+lane]); - for (lane = 0; lane < 8; lane++) - dqset(i, lane, &dll_setting_667[DQ1+lane]); - } else { - for (lane = 0; lane < 8; lane++) - dqsset(i, lane, &dll_setting_800[DQS1+lane]); - for (lane = 0; lane < 8; lane++) - dqset(i, lane, &dll_setting_800[DQ1+lane]); + switch (s->selected_timings.mem_clk) { + default: /* Should not happen */ + break; + case MEM_CLOCK_667MHz: + program_dq_dqs(i, ddr2_dll_setting_667); + break; + case MEM_CLOCK_800MHz: + if (s->spd_type == DDR2) + program_dq_dqs(i, ddr2_dll_setting_800); + else /* DDR3 */ + program_dq_dqs(i, ddr3_dll_setting_800[s->nmode - 1]); + break; + case MEM_CLOCK_1066MHz: + program_dq_dqs(i, ddr3_dll_setting_1066[s->nmode - 1]); + break; + case MEM_CLOCK_1333MHz: + program_dq_dqs(i, ddr3_dll_setting_1333[s->nmode - 1]); + break; } } } diff --git a/src/northbridge/intel/x4x/raminit_tables.c b/src/northbridge/intel/x4x/raminit_tables.c new file mode 100644 index 0000000..3349f62 --- /dev/null +++ b/src/northbridge/intel/x4x/raminit_tables.c @@ -0,0 +1,248 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 Arthur Heymans arthur@aheymans.xyz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <stdint.h> +#include "x4x.h" + +const struct dll_setting ddr2_dll_setting_667[23] = { + /* tap pi db delay */ + {13, 0, 1, 0, 0, 0}, + {4, 1, 0, 0, 0, 0}, + {13, 0, 1, 0, 0, 0}, + {4, 5, 0, 0, 0, 0}, + {4, 1, 0, 0, 0, 0}, + {4, 1, 0, 0, 0, 0}, + {4, 1, 0, 0, 0, 0}, + {1, 5, 1, 1, 1, 0}, + {1, 6, 1, 1, 1, 0}, + {2, 0, 1, 1, 1, 0}, + {2, 1, 1, 1, 1, 0}, + {2, 1, 1, 1, 1, 0}, + {14, 6, 1, 0, 0, 0}, + {14, 3, 1, 0, 0, 0}, + {14, 0, 1, 0, 0, 0}, + {9, 0, 0, 0, 1, 0}, + {9, 1, 0, 0, 1, 0}, + {9, 2, 0, 0, 1, 0}, + {9, 2, 0, 0, 1, 0}, + {9, 1, 0, 0, 1, 0}, + {6, 4, 0, 0, 1, 0}, + {6, 2, 0, 0, 1, 0}, + {5, 4, 0, 0, 1, 0} +}; + +const struct dll_setting ddr2_dll_setting_800[23] = { + /* tap pi db delay */ + {11, 5, 1, 0, 0, 0}, + {0, 5, 1, 1, 0, 0}, + {11, 5, 1, 0, 0, 0}, + {1, 4, 1, 1, 0, 0}, + {0, 5, 1, 1, 0, 0}, + {0, 5, 1, 1, 0, 0}, + {0, 5, 1, 1, 0, 0}, + {2, 5, 1, 1, 1, 0}, + {2, 6, 1, 1, 1, 0}, + {3, 0, 1, 1, 1, 0}, + {3, 0, 1, 1, 1, 0}, + {3, 3, 1, 1, 1, 0}, + {2, 0, 1, 1, 1, 0}, + {1, 3, 1, 1, 1, 0}, + {0, 3, 1, 1, 1, 0}, + {9, 3, 0, 0, 1, 0}, + {9, 4, 0, 0, 1, 0}, + {9, 5, 0, 0, 1, 0}, + {9, 6, 0, 0, 1, 0}, + {10, 0, 0, 0, 1, 0}, + {8, 1, 0, 0, 1, 0}, + {7, 5, 0, 0, 1, 0}, + {6, 2, 0, 0, 1, 0} +}; + +const struct dll_setting ddr3_dll_setting_800[2][23] = { + { /* 1N */ + /* tap pi db(2) delay coarse */ + {8, 2, 0, 0, 0, 0}, + {8, 4, 0, 0, 0, 0}, + {9, 5, 0, 0, 0, 0}, + {6, 1, 0, 0, 0, 0}, + {8, 4, 0, 0, 0, 0}, + {10, 0, 0, 0, 0, 0}, + {10, 0, 0, 0, 0, 0}, + {12, 0, 1, 0, 0, 0}, + {1, 1, 1, 1, 1, 0}, + {2, 4, 1, 1, 1, 0}, + {3, 5, 0, 0, 1, 0}, + {4, 3, 0, 0, 1, 0}, + {5, 2, 0, 0, 1, 0}, + {6, 1, 0, 0, 1, 0}, + {6, 4, 0, 0, 1, 0}, + {4, 1, 0, 0, 1, 0}, + {6, 4, 0, 0, 1, 0}, + {8, 1, 0, 0, 1, 0}, + {8, 6, 0, 0, 1, 0}, + {9, 5, 0, 0, 1, 0}, + {10, 2, 0, 0, 1, 0}, + {10, 6, 1, 0, 1, 0}, + {11, 4, 1, 0, 1, 0} }, + { /* 2N */ + {2, 2, 1, 1, 0, 0}, + {2, 4, 1, 1, 0, 0}, + {3, 5, 0, 0, 0, 0}, + {3, 2, 1, 1, 0, 0}, + {2, 4, 1, 1, 0, 0}, + {3, 6, 0, 0, 0, 0}, + {3, 6, 0, 0, 0, 0}, + {5, 6, 0, 0, 0, 0}, + {8, 0, 0, 0, 0, 0}, + {9, 4, 0, 0, 0, 0}, + {10, 4, 1, 0, 0, 0}, + {11, 3, 1, 0, 0, 0}, + {12, 1, 1, 0, 0, 0}, + {0, 1, 1, 1, 1, 0}, + {0, 3, 1, 1, 1, 0}, + {11, 0, 1, 0, 0, 0}, + {0, 3, 1, 1, 1, 0}, + {2, 1, 1, 1, 1, 0}, + {2, 5, 1, 1, 1, 0}, + {3, 5, 0, 0, 1, 0}, + {4, 2, 0, 0, 1, 0}, + {4, 6, 0, 0, 1, 0}, + {5, 4, 0, 0, 1, 0} + } +}; + +const struct dll_setting ddr3_dll_setting_1066[2][23] = { + { /* 1N */ + {8, 5, 0, 0, 0, 0}, + {7, 6, 0, 0, 0, 0}, + {10, 2, 1, 0, 0, 0}, + {0, 4, 4, 0, 0, 0}, + {7, 6, 0, 0, 0, 0}, + {9, 2, 1, 0, 0, 0}, + {9, 2, 1, 0, 0, 0}, + {2, 5, 1, 1, 1, 0}, + {5, 1, 0, 0, 1, 0}, + {6, 6, 0, 0, 1, 0}, + {8, 0, 0, 0, 1, 0}, + {8, 6, 0, 0, 1, 0}, + {9, 6, 1, 0, 1, 0}, + {10, 6, 1, 0, 1, 0}, + {0, 1, 1, 1, 0, 0}, + {6, 5, 0, 0, 1, 0}, + {9, 3, 1, 0, 1, 0}, + {0, 2, 1, 1, 0, 1}, + {1, 0, 1, 1, 0, 1}, + {2, 0, 1, 1, 0, 1}, + {2, 5, 1, 1, 0, 1}, + {3, 2, 0, 0, 0, 1}, + {4, 1, 0, 0, 0, 1}, }, + { /* 2N */ + {1, 5, 1, 1, 0, 0}, + {0, 6, 1, 1, 0, 0}, + {3, 2, 0, 0, 0, 0}, + {2, 6, 1, 1, 0, 0}, + {0, 6, 1, 1, 0, 0}, + {2, 2, 1, 1, 0, 0}, + {2, 2, 1, 1, 0, 0}, + {6, 4, 0, 0, 0, 0}, + {9, 1, 1, 0, 0, 0}, + {10, 6, 1, 0, 0, 0}, + {1, 0, 1, 1, 1, 0}, + {1, 6, 1, 1, 1, 0}, + {2, 5, 1, 1, 1, 0}, + {3, 5, 0, 0, 1, 0}, + {4, 1, 0, 0, 1, 0}, + {10, 5, 1, 0, 0, 0}, + {2, 3, 1, 1, 1, 0}, + {4, 1, 0, 0, 1, 0}, + {5, 0, 0, 0, 1, 0}, + {6, 0, 0, 0, 1, 0}, + {6, 5, 0, 0, 1, 0}, + {7, 2, 0, 0, 1, 0}, + {8, 1, 0, 0, 1, 0}, + } +}; +const struct dll_setting ddr3_dll_setting_1333[2][23] = { + { /* 1N */ + {8, 5, 0, 0, 0, 0}, + {9, 0, 1, 0, 0, 0}, + {10, 2, 1, 0, 0, 0}, + {0, 0, 1, 1, 0, 0}, + {9, 0, 1, 0, 0, 0}, + {10, 4, 1, 0, 0, 0}, + {10, 4, 1, 0, 0, 0}, + {2, 4, 1, 1, 1, 0}, + {5, 1, 0, 0, 1, 0}, + {6, 6, 0, 0, 1, 0}, + {8, 0, 0, 0, 1, 0}, + {8, 6, 0, 0, 1, 0}, + {9, 5, 1, 0, 1, 0}, + {10, 6, 1, 0, 1, 0}, + {0, 1, 1, 1, 0, 1}, + {6, 5, 0, 0, 1, 0}, + {9, 3, 1, 0, 1, 0}, + {0, 2, 1, 1, 0, 1}, + {1, 0, 1, 1, 0, 1}, + {2, 0, 1, 1, 0, 1}, + {2, 5, 1, 1, 0, 1}, + {3, 2, 0, 0, 0, 1}, + {4, 1, 0, 0, 0, 1}, }, + { /* 2N */ + {1, 6, 1, 1, 0, 0}, + {2, 2, 1, 1, 0, 0}, + {4, 2, 0, 0, 0, 0}, + {3, 1, 1, 1, 0, 0}, + {2, 2, 1, 1, 0, 0}, + {4, 5, 0, 0, 0, 0}, + {4, 5, 0, 0, 0, 0}, + {10, 4, 0, 0, 0, 0}, + {0, 3, 1, 1, 1, 0}, + {3, 2, 1, 1, 1, 0}, + {5, 0, 0, 0, 1, 0}, + {6, 1, 0, 0, 1, 0}, + {7, 4, 0, 0, 1, 0}, + {9, 2, 0, 0, 1, 0}, + {9, 6, 0, 0, 1, 0}, + {1, 3, 1, 1, 1, 0}, + {5, 6, 0, 0, 1, 0}, + {8, 5, 0, 0, 1, 0}, + {10, 2, 0, 0, 1, 0}, + {11, 1, 0, 0, 1, 0}, + {12, 3, 1, 0, 1, 0}, + {13, 6, 1, 0, 1, 0}, + {0, 3, 1, 1, 0, 1} + } +}; + +const u8 ddr3_emrs1_config[16][4] = { /* [Config][Rank] */ + {0x00, 0x00, 0x00, 0x00}, /* NC_NC */ + {0x11, 0x00, 0x00, 0x00}, /* 8S_NC */ + {0x11, 0x11, 0x00, 0x00}, /* 8D_NC */ + {0x11, 0x00, 0x00, 0x00}, /* 16S_NC */ + {0x00, 0x00, 0x11, 0x00}, /* NC_8S */ + {0x81, 0x00, 0x81, 0x00}, /* 8S_8S */ + {0x81, 0x81, 0x81, 0x00}, /* 8D_8S */ + {0x81, 0x00, 0x81, 0x00}, /* 16S_8S */ + {0x00, 0x00, 0x11, 0x11}, /* NC_8D */ + {0x81, 0x00, 0x81, 0x81}, /* 8S_8D */ + {0x81, 0x81, 0x81, 0x81}, /* 8D_8D */ + {0x81, 0x00, 0x81, 0x81}, /* 16S_8D */ + {0x00, 0x00, 0x11, 0x00}, /* NC_16S */ + {0x81, 0x00, 0x81, 0x00}, /* 8S_16S */ + {0x81, 0x81, 0x81, 0x00}, /* 8D_16S */ + {0x81, 0x00, 0x81, 0x00}, /* 16S_16S */ +}; diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index 34fef93..9ef07b3 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -355,6 +355,15 @@ struct abs_timings *saved_timings); int ddr3_save_dimminfo(u8 dimm_idx, u8 *raw_spd, struct abs_timings *saved_timings, struct sysinfo *s); +void dqsset(u8 ch, u8 lane, const struct dll_setting *setting); +void dqset(u8 ch, u8 lane, const struct dll_setting *setting); + +/* Look up tables Tables */ +extern const struct dll_setting ddr2_dll_setting_667[23]; +extern const struct dll_setting ddr2_dll_setting_800[23]; +extern const struct dll_setting ddr3_dll_setting_800[2][23]; +extern const struct dll_setting ddr3_dll_setting_1066[2][23]; +extern const struct dll_setting ddr3_dll_setting_1333[2][23];
struct acpi_rsdp;