summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2016-07-24 03:28:42 +1000
committerKyösti Mälkki <kyosti.malkki@gmail.com>2016-07-27 11:40:33 +0200
commit7c2e5396a3d47c64eb5a553fe412aad4c0f8dc1b (patch)
treeab4b3ecab2082c10d962c4e25314d2287bcd2519
parent40d93494c3dcfe7850aed056e1ad9c4b285c0f5b (diff)
nb/intel/x4x: Fix CAS latency detection and max memory detection
Now hardcode maximum memory frequency capability to 800MHz, as all chipsets in x4x family support PC2-6400 according to the datasheet. CAS latency detection also relies on this, and has been cleaned up. Ram initialization does not work with FSB 1333MHz / DDR2 800MHz combination, so disable this combination for now, and reduce to 667MHz instead. Still don't know why this is the case, but FSB1333/667 works. These changes should now allow existing configurations to continue working, while providing support for previously unworking configurations, due to previous buggy CAS latency detection code. TESTED: on GA-G41M-ES2L CPU: E5200 @ 2.50GHz (FSB 800MHz) 2x 1GB 667MHz hynix worked @ 667 1x 2GB 800Mhz ARAM worked @ 800 1x 1GB 667Mhz StarRam worked @ 667 2x 2GB 800Mhz (generic) worked @ 800 Change-Id: I1ddd7827ee6fe3d4162ba0546f738a8f9decdf93 Signed-off-by: Damien Zammit <damien@zamaudio.com> Reviewed-on: https://review.coreboot.org/15818 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
-rw-r--r--src/northbridge/intel/x4x/raminit.c136
-rw-r--r--src/northbridge/intel/x4x/raminit_ddr2.c5
2 files changed, 45 insertions, 96 deletions
diff --git a/src/northbridge/intel/x4x/raminit.c b/src/northbridge/intel/x4x/raminit.c
index 9be2cd3d73..bc0af04c6f 100644
--- a/src/northbridge/intel/x4x/raminit.c
+++ b/src/northbridge/intel/x4x/raminit.c
@@ -111,10 +111,9 @@ static void sdram_read_spds(struct sysinfo *s)
s->dimms[i].chip_capacity = s->dimms[i].banks;
s->dimms[i].rows = s->dimms[i].spd_data[3];// - 12;
s->dimms[i].cols = s->dimms[i].spd_data[4];// - 9;
- s->dimms[i].cas_latencies = 0x70; // 6,5,4 CL
- s->dimms[i].cas_latencies &= s->dimms[i].spd_data[18];
+ s->dimms[i].cas_latencies = s->dimms[i].spd_data[18];
if (s->dimms[i].cas_latencies == 0)
- s->dimms[i].cas_latencies = 0x70;
+ s->dimms[i].cas_latencies = 0x60; // 6,5 CL
s->dimms[i].tAAmin = s->dimms[i].spd_data[26];
s->dimms[i].tCKmin = s->dimms[i].spd_data[25];
s->dimms[i].width = (s->dimms[i].spd_data[13] >> 3) - 1;
@@ -248,13 +247,6 @@ static void sdram_read_spds(struct sysinfo *s)
}
}
-static u8 lsbpos(u8 val) //Forward
-{
- u8 i;
- for (i = 0; (i < 8) && ((val & (1 << i)) == 0); i++);
- return i;
-}
-
static u8 msbpos(u8 val) //Reverse
{
u8 i;
@@ -264,8 +256,6 @@ static u8 msbpos(u8 val) //Reverse
static void mchinfo_ddr2(struct sysinfo *s)
{
- u8 capablefreq, maxfreq;
-
const u32 eax = cpuid_ext(0x04, 0).eax;
s->cores = ((eax >> 26) & 0x3f) + 1;
printk(BIOS_WARNING, "%d CPU cores\n", s->cores);
@@ -284,19 +274,7 @@ static void mchinfo_ddr2(struct sysinfo *s)
printk(BIOS_WARNING, "AMT enabled\n");
}
- maxfreq = MEM_CLOCK_800MHz;
- capablefreq = (u8)((pci_read_config16(PCI_DEV(0, 0, 0), 0xea) >> 4) & 0x3f);
- capablefreq &= 0x7;
- if (capablefreq)
- maxfreq = capablefreq + 1;
-
- if (maxfreq > MEM_CLOCK_800MHz)
- maxfreq = MEM_CLOCK_800MHz;
-
- if (maxfreq < MEM_CLOCK_667MHz)
- maxfreq = MEM_CLOCK_667MHz;
-
- s->max_ddr2_mhz = (maxfreq == MEM_CLOCK_800MHz) ? 800 : 667;
+ s->max_ddr2_mhz = 800; // All chipsets in x4x support up to 800MHz DDR2
printk(BIOS_WARNING, "Capable of DDR2 of %d MHz or lower\n", s->max_ddr2_mhz);
if (!(capid & (1<<(48-32)))) {
@@ -308,12 +286,15 @@ static void sdram_detect_ram_speed(struct sysinfo *s)
{
u8 i;
u8 commoncas = 0;
- u8 cas;
- u8 lowcas;
- u8 highcas;
+ u8 currcas;
+ u8 currfreq;
u8 maxfreq;
u8 freq = 0;
+ // spdidx,cycletime @CAS 5 6
+ u8 idx800[7][2] = {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {23,0x30}, {9,0x25}};
+ int found = 0;
+
// Find max FSB speed
switch (MCHBAR32(0xc00) & 0x7) {
case 0x0:
@@ -334,11 +315,13 @@ static void sdram_detect_ram_speed(struct sysinfo *s)
// Max RAM speed
if (s->spd_type == DDR2) {
- // Choose max memory frequency for MCH as previously detected
- freq = (s->max_ddr2_mhz == 800) ? MEM_CLOCK_800MHz : MEM_CLOCK_667MHz;
+ // FIXME: Limit memory speed to 667MHz if FSB is 1333MHz
+ maxfreq = (s->max_fsb == FSB_CLOCK_1333MHz)
+ ? MEM_CLOCK_667MHz : MEM_CLOCK_800MHz;
+
+ // Choose common CAS latency from {6,5}, 4 does not work
+ commoncas = 0x60;
- // Detect a common CAS latency (Choose from 6,5,4 CL)
- commoncas = 0x70;
FOR_EACH_POPULATED_DIMM(s->dimms, i) {
commoncas &= s->dimms[i].cas_latencies;
}
@@ -346,74 +329,41 @@ static void sdram_detect_ram_speed(struct sysinfo *s)
die("No common CAS among dimms\n");
}
- // Start with fastest common CAS
- cas = 0;
- highcas = msbpos(commoncas);
- lowcas = lsbpos(commoncas);
-
- while (cas == 0 && highcas >= lowcas) {
- FOR_EACH_POPULATED_DIMM(s->dimms, i) {
- switch (freq) {
- case MEM_CLOCK_800MHz:
- if ((s->dimms[i].spd_data[9] > 0x25) ||
- (s->dimms[i].spd_data[10] > 0x40)) {
- // CAS too fast, lower it
- highcas--;
- break;
- } else {
- cas = highcas;
- }
- break;
- case MEM_CLOCK_667MHz:
- default:
- if ((s->dimms[i].spd_data[9] > 0x30) ||
- (s->dimms[i].spd_data[10] > 0x45)) {
- // CAS too fast, lower it
- highcas--;
- break;
- } else {
- cas = highcas;
+ // Working from fastest to slowest,
+ // fast->slow 5@800 6@800 5@667
+ found = 0;
+ for (currcas = 5; currcas <= msbpos(commoncas); currcas++) {
+ currfreq = maxfreq;
+ if (currfreq == MEM_CLOCK_800MHz) {
+ found = 1;
+ FOR_EACH_POPULATED_DIMM(s->dimms, i) {
+ if (s->dimms[i].spd_data[idx800[currcas][0]] > idx800[currcas][1]) {
+ // this is too fast
+ found = 0;
}
- break;
}
+ if (found)
+ break;
}
}
- if (highcas < lowcas) {
- // Timings not supported by MCH, lower the frequency
- freq--;
- cas = 0;
- highcas = msbpos(commoncas);
- lowcas = lsbpos(commoncas);
- while (cas == 0 && highcas >= lowcas) {
- FOR_EACH_POPULATED_DIMM(s->dimms, i) {
- switch (freq) {
- case MEM_CLOCK_800MHz:
- if ((s->dimms[i].spd_data[23] > 0x25) ||
- (s->dimms[i].spd_data[24] > 0x40)) {
- // CAS too fast, lower it
- highcas--;
- break;
- } else {
- cas = highcas;
- }
- break;
- case MEM_CLOCK_667MHz:
- default:
- if ((s->dimms[i].spd_data[23] > 0x30) ||
- (s->dimms[i].spd_data[24] > 0x45)) {
- // CAS too fast, lower it
- highcas--;
- break;
- } else {
- cas = highcas;
- }
- break;
- }
+
+ if (!found) {
+ currcas = 5;
+ currfreq = MEM_CLOCK_667MHz;
+ found = 1;
+ FOR_EACH_POPULATED_DIMM(s->dimms, i) {
+ if (s->dimms[i].spd_data[9] > 0x30) {
+ // this is too fast
+ found = 0;
}
}
}
- s->selected_timings.mem_clk = freq;
- s->selected_timings.CAS = cas;
+
+ if (!found)
+ die("No valid CAS/frequencies detected\n");
+
+ s->selected_timings.mem_clk = currfreq;
+ s->selected_timings.CAS = currcas;
} else { // DDR3
// Limit frequency for MCH
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index 5acb12736b..5d457e6de1 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -293,11 +293,10 @@ static void launch_ddr2(struct sysinfo *s)
if (s->selected_timings.CAS == 5) {
launch2 = 0x00220201;
- } else if ((s->selected_timings.mem_clk == MEM_CLOCK_800MHz) &&
- (s->selected_timings.CAS == 6)) {
+ } else if (s->selected_timings.CAS == 6) {
launch2 = 0x00230302;
} else {
- die("Unsupported CAS & Frequency combination detected\n");
+ die("Unsupported CAS\n");
}
FOR_EACH_POPULATED_CHANNEL(s->dimms, i) {