aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/intel/x4x/raminit_ddr2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge/intel/x4x/raminit_ddr2.c')
-rw-r--r--src/northbridge/intel/x4x/raminit_ddr2.c168
1 files changed, 90 insertions, 78 deletions
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index 336f77ec7d..866815f729 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -26,6 +26,7 @@
#else
#include <southbridge/intel/i82801jx/i82801jx.h>
#endif
+#include <string.h>
#include "iomap.h"
#include "x4x.h"
@@ -344,6 +345,24 @@ static void dqset(u8 ch, u8 lane, const struct dll_setting *setting)
}
}
+static void rt_set_dqs(u8 channel, u8 lane, u8 rank,
+ struct rt_dqs_setting *dqs_setting)
+{
+ u16 saved_tap = MCHBAR16(0x540 + 0x400 * channel + lane * 4);
+ u16 saved_pi = MCHBAR16(0x542 + 0x400 * channel + lane * 4);
+ printk(RAM_SPEW, "RT DQS: ch%d, L%d, %d.%d\n", channel, lane,
+ dqs_setting->tap,
+ dqs_setting->pi);
+
+ saved_tap &= ~(0xf << (rank * 4));
+ saved_tap |= dqs_setting->tap << (rank * 4);
+ MCHBAR16(0x540 + 0x400 * channel + lane * 4) = saved_tap;
+
+ saved_pi &= ~(0x7 << (rank * 3));
+ saved_pi |= dqs_setting->pi << (rank * 3);
+ MCHBAR16(0x542 + 0x400 * channel + lane * 4) = saved_pi;
+}
+
static void timings_ddr2(struct sysinfo *s)
{
u8 i;
@@ -574,7 +593,6 @@ static void dll_ddr2(struct sysinfo *s)
u8 i, j, r, reg8, clk, async = 0;
u16 reg16 = 0;
u32 reg32 = 0;
- u8 lane;
MCHBAR16(0x180) = (MCHBAR16(0x180) & ~0x7e06) | 0xc04;
MCHBAR16(0x182) = (MCHBAR16(0x182) & ~0x3ff) | 0xc8;
@@ -660,60 +678,6 @@ static void dll_ddr2(struct sysinfo *s)
MCHBAR8(0x1a4) = MCHBAR8(0x1a4) | 0x40;
MCHBAR16(0x5f0) = (MCHBAR16(0x5f0) & ~0x400) | 0x400;
- static 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}
- };
-
- static 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;
@@ -725,9 +689,9 @@ static void dll_ddr2(struct sysinfo *s)
const struct dll_setting *setting;
if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz)
- setting = dll_setting_667;
+ setting = default_ddr2_667_ctrl;
else
- setting = dll_setting_800;
+ setting = default_ddr2_800_ctrl;
clkset0(i, &setting[CLKSET0]);
clkset1(i, &setting[CLKSET1]);
@@ -834,32 +798,77 @@ static void dll_ddr2(struct sysinfo *s)
if (s->selected_timings.mem_clk == MEM_CLOCK_1333MHz)
MCHBAR8(0x18c) = MCHBAR8(0x18c) | 1;
+}
- // Program DQ/DQS dll settings
- reg32 = 0;
- FOR_EACH_POPULATED_CHANNEL(s->dimms, i) {
+static void select_default_dq_dqs_settings(struct sysinfo *s)
+{
+ int ch, lane;
+
+ FOR_EACH_POPULATED_CHANNEL(s->dimms, ch) {
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)
- reg32 = 0x00007777;
- MCHBAR32(0x400*i + 0x540 + lane*4) =
- (MCHBAR32(0x400*i + 0x540 + lane*4) & 0x0fffffff) |
- reg32;
+ switch (s->selected_timings.mem_clk) {
+ case MEM_CLOCK_667MHz:
+ memcpy(s->dqs_settings[ch],
+ default_ddr2_667_dqs,
+ sizeof(s->dqs_settings[ch]));
+ memcpy(s->dq_settings[ch],
+ default_ddr2_667_dq,
+ sizeof(s->dq_settings[ch]));
+ s->rt_dqs[ch][lane].tap = 7;
+ s->rt_dqs[ch][lane].pi = 2;
+ break;
+ case MEM_CLOCK_800MHz:
+ if (s->spd_type == DDR2) {
+ memcpy(s->dqs_settings[ch],
+ default_ddr2_800_dqs,
+ sizeof(s->dqs_settings[ch]));
+ memcpy(s->dq_settings[ch],
+ default_ddr2_800_dq,
+ sizeof(s->dq_settings[ch]));
+
+ s->rt_dqs[ch][lane].tap = 7;
+ s->rt_dqs[ch][lane].pi = 0;
+ } else { /* DDR3 */
+ /* TODO: DDR3 write DQ-DQS */
+ s->rt_dqs[ch][lane].tap = 6;
+ s->rt_dqs[ch][lane].pi = 2;
+ }
+ break;
+ case MEM_CLOCK_1066MHz:
+ /* TODO: DDR3 write DQ-DQS */
+ s->rt_dqs[ch][lane].tap = 5;
+ s->rt_dqs[ch][lane].pi = 2;
+ break;
+ case MEM_CLOCK_1333MHz:
+ /* TODO: DDR3 write DQ-DQS */
+ s->rt_dqs[ch][lane].tap = 7;
+ s->rt_dqs[ch][lane].pi = 0;
+ break;
+ default: /* not supported */
+ break;
+ }
}
}
+}
- 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]);
+/*
+ * It looks like only the RT DQS register for the first rank
+ * is used for all ranks. Just set all the 'unused' RT DQS registers
+ * to the same as rank 0, out of precaution.
+ */
+static void set_all_dq_dqs_dll_settings(struct sysinfo *s)
+{
+ // Program DQ/DQS dll settings
+ int ch, lane, rank;
+
+ FOR_EACH_POPULATED_CHANNEL(s->dimms, ch) {
+ for (lane = 0; lane < 8; lane++) {
+ FOR_EACH_RANK_IN_CHANNEL(rank) {
+ rt_set_dqs(ch, lane, rank,
+ &s->rt_dqs[ch][lane]);
+ }
+ dqsset(ch, lane, &s->dqs_settings[ch][lane]);
+ dqset(ch, lane, &s->dq_settings[ch][lane]);
}
}
}
@@ -1486,6 +1495,9 @@ void raminit_ddr2(struct sysinfo *s, int fast_boot)
// Program DLL
dll_ddr2(s);
+ if (!fast_boot)
+ select_default_dq_dqs_settings(s);
+ set_all_dq_dqs_dll_settings(s);
// RCOMP
if (s->boot_path != BOOT_PATH_WARM_RESET) {