Arthur Heymans has uploaded a new change for review. ( https://review.coreboot.org/19868 )
Change subject: nb/x4x/raminit: Split of DDR2 specific functions to its own file ......................................................................
nb/x4x/raminit: Split of DDR2 specific functions to its own file
Headers for device/dram/ddr2 and ddr3 conflict so the easy solution is have separate files for functions that use those.
Change-Id: I3ab281f4d8fcce3ef3cf8e355e7ea7286c73e4ff Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M src/northbridge/intel/x4x/Makefile.inc M src/northbridge/intel/x4x/raminit.c A src/northbridge/intel/x4x/spd_ddr2_decode.c M src/northbridge/intel/x4x/x4x.h 4 files changed, 161 insertions(+), 138 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/68/19868/1
diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc index 34d9b0f..b433810 100644 --- a/src/northbridge/intel/x4x/Makefile.inc +++ b/src/northbridge/intel/x4x/Makefile.inc @@ -20,6 +20,7 @@ romstage-y += raminit.c romstage-y += raminit_ddr2.c romstage-y += ram_calc.c +romstage-y += spd_ddr2_decode.c
ramstage-y += acpi.c ramstage-y += ram_calc.c diff --git a/src/northbridge/intel/x4x/raminit.c b/src/northbridge/intel/x4x/raminit.c index 67e9a1b..7e69b4c 100644 --- a/src/northbridge/intel/x4x/raminit.c +++ b/src/northbridge/intel/x4x/raminit.c @@ -28,71 +28,10 @@ #include <pc80/mc146818rtc.h> #include <spd.h> #include <string.h> -#include <device/dram/ddr2.h>
static inline int spd_read_byte(unsigned int device, unsigned int address) { return smbus_read_byte(device, address); -} - -struct abs_timings { - u32 min_tclk; - u32 min_tRAS; - u32 min_tRP; - u32 min_tRCD; - u32 min_tWR; - u32 min_tRFC; - u32 min_tWTR; - u32 min_tRRD; - u32 min_tRTP; - u32 tCLK_cas[TOTAL_DIMMS][8]; - u32 cas_supported; -}; - -static void select_cas_dramfreq_ddr2(struct sysinfo *s, - struct abs_timings *saved_timings) -{ - u8 selected_cas; - u8 cas_mask = SPD_CAS_LATENCY_DDR2_5 | SPD_CAS_LATENCY_DDR2_6; - u32 common_min_tclk[8]; - u32 common_tCLK; - - cas_mask &= saved_timings->cas_supported; - get_common_min_tclk(cas_mask, TOTAL_DIMMS, common_min_tclk, - saved_timings->tCLK_cas); - /* On this northbridge the highest DDR2 frequency is 800MHz */ - common_tCLK = get_common_freq_cas(cas_mask, common_min_tclk, - &selected_cas, TCK_400MHZ); - - if (common_tCLK == 0) - die("Could not find common memory frequency and CAS\n"); - - s->selected_timings.CAS = selected_cas; - s->selected_timings.tclk = common_tCLK; - - switch (s->selected_timings.tclk) { - case TCK_200MHZ: - case TCK_266MHZ: - /* FIXME: this works on vendor BIOS */ - die("Selected dran frequency not supported\n"); - case TCK_333MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_667MHz; - break; - case TCK_400MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_800MHz; - break; - } - - switch (s->selected_timings.tclk) { - case TCK_200MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_400MHz; break; - case TCK_266MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_533MHz; break; - case TCK_333MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_667MHz; break; - case TCK_400MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_800MHz; break; - } }
static void mchinfo_ddr2(struct sysinfo *s) @@ -111,85 +50,8 @@ if (!(capid & (1<<(56-32)))) printk(BIOS_WARNING, "AMT enabled\n");
- 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)))) printk(BIOS_WARNING, "VT-d enabled\n"); -} - -static int ddr2_save_dimminfo(u8 dimm_idx, u8 *raw_spd, - struct abs_timings *saved_timings, struct sysinfo *s) -{ - struct dimm_attr_st decoded_dimm; - int i; - - if (spd_decode_ddr2(&decoded_dimm, raw_spd) != SPD_STATUS_OK) - return 1; - - if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) - dram_print_spd_ddr2(&decoded_dimm); - - /* - * Used to be content of spd byte 62 which does not make - * that much sense. - */ - s->dimms[dimm_idx].width = decoded_dimm.width; - if (!(s->dimms[dimm_idx].width & (0x8 | 0x10))) { - printk(BIOS_ERR, "DIMM%d Unsupported width: x%d. Disabling dimm\n", - dimm_idx, s->dimms[dimm_idx].width); - return 1; - } - /* - * This boils down to: - * "Except for the x16 configuration, all DDR2 devices have a - * 1KB page size. For the x16 configuration, the page size is 2KB - * for all densities except the 256Mb device, which has a 1KB page size." - * Micron, 'TN-47-16 Designing for High-Density DDR2 Memory' - */ - s->dimms[dimm_idx].page_size = s->dimms[dimm_idx].width * - (1 << decoded_dimm.col_bits); - - switch (decoded_dimm.banks) { - case 4: - s->dimms[dimm_idx].n_banks = 0; - break; - case 8: - s->dimms[dimm_idx].n_banks = 1; - break; - default: - printk(BIOS_ERR, "DIMM%d Unsupported #banks: x%d. Disabling dimm\n", - dimm_idx, decoded_dimm.banks); - return 1; - } - - s->dimms[dimm_idx].ranks = decoded_dimm.ranks; - s->dimms[dimm_idx].rows = decoded_dimm.row_bits; - s->dimms[dimm_idx].cols = decoded_dimm.col_bits; - - saved_timings->cas_supported &= decoded_dimm.cas_supported; - - saved_timings->min_tRAS = - MAX(saved_timings->min_tRAS, decoded_dimm.tRAS); - saved_timings->min_tRP = - MAX(saved_timings->min_tRP, decoded_dimm.tRP); - saved_timings->min_tRCD = - MAX(saved_timings->min_tRCD, decoded_dimm.tRCD); - saved_timings->min_tWR = - MAX(saved_timings->min_tWR, decoded_dimm.tWR); - saved_timings->min_tRFC = - MAX(saved_timings->min_tRFC, decoded_dimm.tRFC); - saved_timings->min_tWTR = - MAX(saved_timings->min_tWTR, decoded_dimm.tWTR); - saved_timings->min_tRRD = - MAX(saved_timings->min_tRRD, decoded_dimm.tRRD); - saved_timings->min_tRTP = - MAX(saved_timings->min_tRTP, decoded_dimm.tRTP); - for (i = 0; i < 8; i++) { - saved_timings->tCLK_cas[dimm_idx][i] = - decoded_dimm.cycle_time[i]; - } - return 0; }
static void select_discrete_timings(struct sysinfo *s, diff --git a/src/northbridge/intel/x4x/spd_ddr2_decode.c b/src/northbridge/intel/x4x/spd_ddr2_decode.c new file mode 100644 index 0000000..938aab7 --- /dev/null +++ b/src/northbridge/intel/x4x/spd_ddr2_decode.c @@ -0,0 +1,142 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Damien Zammit damien@zamaudio.com + * 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 <console/console.h> +#include <device/dram/ddr2.h> +#include "x4x.h" + +void select_cas_dramfreq_ddr2(struct sysinfo *s, + struct abs_timings *saved_timings) +{ + u8 selected_cas; + u8 cas_mask = SPD_CAS_LATENCY_DDR2_5 | SPD_CAS_LATENCY_DDR2_6; + u32 common_min_tclk[8]; + u32 common_tCLK; + + cas_mask &= saved_timings->cas_supported; + get_common_min_tclk(cas_mask, TOTAL_DIMMS, common_min_tclk, + saved_timings->tCLK_cas); + /* On this northbridge the highest DDR2 frequency is 800MHz */ + common_tCLK = get_common_freq_cas(cas_mask, common_min_tclk, + &selected_cas, TCK_400MHZ); + + if (common_tCLK == 0) + die("Could not find common memory frequency and CAS\n"); + + s->selected_timings.CAS = selected_cas; + s->selected_timings.tclk = common_tCLK; + + switch (s->selected_timings.tclk) { + case TCK_200MHZ: + case TCK_266MHZ: + /* FIXME: this works on vendor BIOS */ + die("Selected dran frequency not supported\n"); + case TCK_333MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_667MHz; + break; + case TCK_400MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_800MHz; + break; + } + + switch (s->selected_timings.tclk) { + case TCK_200MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_400MHz; break; + case TCK_266MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_533MHz; break; + case TCK_333MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_667MHz; break; + case TCK_400MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_800MHz; break; + } +} + +int ddr2_save_dimminfo(u8 dimm_idx, u8 *raw_spd, + struct abs_timings *saved_timings, struct sysinfo *s) +{ + struct dimm_attr_st decoded_dimm; + int i; + + if (spd_decode_ddr2(&decoded_dimm, raw_spd) != SPD_STATUS_OK) + return 1; + + if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) + dram_print_spd_ddr2(&decoded_dimm); + + /* + * Used to be content of spd byte 62 which does not make + * that much sense. + */ + s->dimms[dimm_idx].width = decoded_dimm.width; + if (!(s->dimms[dimm_idx].width & (0x8 | 0x10))) { + printk(BIOS_ERR, "DIMM%d Unsupported width: x%d. Disabling dimm\n", + dimm_idx, s->dimms[dimm_idx].width); + return 1; + } + /* + * This boils down to: + * "Except for the x16 configuration, all DDR2 devices have a + * 1KB page size. For the x16 configuration, the page size is 2KB + * for all densities except the 256Mb device, which has a 1KB + * page size." + * Micron, 'TN-47-16 Designing for High-Density DDR2 Memory' + */ + s->dimms[dimm_idx].page_size = s->dimms[dimm_idx].width * + (1 << decoded_dimm.col_bits); + + switch (decoded_dimm.banks) { + case 4: + s->dimms[dimm_idx].n_banks = 0; + break; + case 8: + s->dimms[dimm_idx].n_banks = 1; + break; + default: + printk(BIOS_ERR, "DIMM%d Unsupported #banks: x%d. Disabling dimm\n", + dimm_idx, decoded_dimm.banks); + return 1; + } + + s->dimms[dimm_idx].ranks = decoded_dimm.ranks; + s->dimms[dimm_idx].rows = decoded_dimm.row_bits; + s->dimms[dimm_idx].cols = decoded_dimm.col_bits; + + saved_timings->cas_supported &= decoded_dimm.cas_supported; + + saved_timings->min_tRAS = + MAX(saved_timings->min_tRAS, decoded_dimm.tRAS); + saved_timings->min_tRP = + MAX(saved_timings->min_tRP, decoded_dimm.tRP); + saved_timings->min_tRCD = + MAX(saved_timings->min_tRCD, decoded_dimm.tRCD); + saved_timings->min_tWR = + MAX(saved_timings->min_tWR, decoded_dimm.tWR); + saved_timings->min_tRFC = + MAX(saved_timings->min_tRFC, decoded_dimm.tRFC); + saved_timings->min_tWTR = + MAX(saved_timings->min_tWTR, decoded_dimm.tWTR); + saved_timings->min_tRRD = + MAX(saved_timings->min_tRRD, decoded_dimm.tRRD); + saved_timings->min_tRTP = + MAX(saved_timings->min_tRTP, decoded_dimm.tRTP); + for (i = 0; i < 8; i++) { + saved_timings->tCLK_cas[dimm_idx][i] = + decoded_dimm.cycle_time[i]; + } + return 0; +} diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index 06d88ee..fc7fbfe 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -321,6 +321,20 @@ DQ8 };
+struct abs_timings { + u32 min_tclk; + u32 min_tRAS; + u32 min_tRP; + u32 min_tRCD; + u32 min_tWR; + u32 min_tRFC; + u32 min_tWTR; + u32 min_tRRD; + u32 min_tRTP; + u32 tCLK_cas[TOTAL_DIMMS][8]; + u32 cas_supported; +}; + #ifndef __BOOTBLOCK__ void x4x_early_init(void); void x4x_late_init(int s3resume); @@ -331,6 +345,10 @@ void raminit_ddr2(struct sysinfo *); u32 fsb2mhz(u32 speed); u32 ddr2mhz(u32 speed); +void select_cas_dramfreq_ddr2(struct sysinfo *s, + struct abs_timings *saved_timings); +int ddr2_save_dimminfo(u8 dimm_idx, u8 *raw_spd, + struct abs_timings *saved_timings, struct sysinfo *s);
struct acpi_rsdp; #ifndef __SIMPLE_DEVICE__