From 7c2e5396a3d47c64eb5a553fe412aad4c0f8dc1b Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Sun, 24 Jul 2016 03:28:42 +1000 Subject: nb/intel/x4x: Fix CAS latency detection and max memory detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-on: https://review.coreboot.org/15818 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/northbridge/intel/x4x/raminit.c | 136 ++++++++++++------------------------ 1 file changed, 43 insertions(+), 93 deletions(-) (limited to 'src/northbridge/intel/x4x/raminit.c') 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 -- cgit v1.2.3