Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/22992
Change subject: nb/intel/x4x: Move decoding DDR2 SPD to separate file ......................................................................
nb/intel/x4x: Move decoding DDR2 SPD to separate file
This is needed to avoid type conflicts when decoding DDR3 when using functions in device/dram/ddr3.c.
Nothing functional is changed.
Change-Id: I965fb8261c14381a35b361df2a3b40a9ea192669 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, 163 insertions(+), 132 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/92/22992/1
diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc index 29ece07..ef9b991 100644 --- a/src/northbridge/intel/x4x/Makefile.inc +++ b/src/northbridge/intel/x4x/Makefile.inc @@ -23,6 +23,7 @@ romstage-y += rcven.c romstage-y += raminit_tables.c romstage-y += dq_dqs.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 3cd75be..81dcc1d 100644 --- a/src/northbridge/intel/x4x/raminit.c +++ b/src/northbridge/intel/x4x/raminit.c @@ -83,59 +83,8 @@ return CB_SUCCESS; }
-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 min_tCLK_cas[8]; - u32 cas_supported; -}; - #define CTRL_MIN_TCLK_DDR2 TCK_400MHZ
-static void select_cas_dramfreq_ddr2(struct sysinfo *s, - const struct abs_timings *saved_timings) -{ - u8 try_cas; - /* Currently only these CAS are supported */ - u8 cas_mask = SPD_CAS_LATENCY_DDR2_5 | SPD_CAS_LATENCY_DDR2_6; - - cas_mask &= saved_timings->cas_supported; - try_cas = spd_get_msbs(cas_mask); - - while (cas_mask & (1 << try_cas) && try_cas > 0) { - s->selected_timings.CAS = try_cas; - s->selected_timings.tclk = saved_timings->min_tCLK_cas[try_cas]; - if (s->selected_timings.tclk >= CTRL_MIN_TCLK_DDR2 && - saved_timings->min_tCLK_cas[try_cas] != - saved_timings->min_tCLK_cas[try_cas - 1]) - break; - try_cas--; - } - - - if ((s->selected_timings.CAS < 3) || (s->selected_timings.tclk == 0)) - die("Could not find common memory frequency and CAS\n"); - - switch (s->selected_timings.tclk) { - case TCK_200MHZ: - case TCK_266MHZ: - /* FIXME: this works on vendor BIOS */ - die("Selected dram 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; - } -}
static void mchinfo_ddr2(struct sysinfo *s) { @@ -160,87 +109,6 @@ 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) { - printk(BIOS_DEBUG, "Problems decoding SPD\n"); - return CB_ERR; - } - - if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) - dram_print_spd_ddr2(&decoded_dimm); - - if (!(decoded_dimm.width & (0x08 | 0x10))) { - - printk(BIOS_ERR, - "DIMM%d Unsupported width: x%d. Disabling dimm\n", - dimm_idx, s->dimms[dimm_idx].width); - return CB_ERR; - } - s->dimms[dimm_idx].width = (decoded_dimm.width >> 3) - 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' - * The formula is pagesize in KiB = width * 2^col_bits / 8. - */ - s->dimms[dimm_idx].page_size = decoded_dimm.width * - (1 << decoded_dimm.col_bits) / 8; - - switch (decoded_dimm.banks) { - case 4: - s->dimms[dimm_idx].n_banks = N_BANKS_4; - break; - case 8: - s->dimms[dimm_idx].n_banks = N_BANKS_8; - break; - default: - printk(BIOS_ERR, - "DIMM%d Unsupported #banks: x%d. Disabling dimm\n", - dimm_idx, decoded_dimm.banks); - return CB_ERR; - } - - 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++) { - if (!(saved_timings->cas_supported & (1 << i))) - saved_timings->min_tCLK_cas[i] = 0; - else - saved_timings->min_tCLK_cas[i] = - MAX(saved_timings->min_tCLK_cas[i], - decoded_dimm.cycle_time[i]); - } - s->dimms[dimm_idx].checksum = decoded_dimm.checksum; - return CB_SUCCESS; -} - static void select_discrete_timings(struct sysinfo *s, const struct abs_timings *timings) { 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..b3415f3 --- /dev/null +++ b/src/northbridge/intel/x4x/spd_ddr2_decode.c @@ -0,0 +1,144 @@ +/* + * 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 <stdint.h> +#include <arch/io.h> +#include <spd.h> +#include <types.h> +#include <console/console.h> +#include <device/dram/ddr2.h> +#include "x4x.h" + +#define CTRL_MIN_TCLK_DDR2 TCK_400MHZ + +void select_cas_dramfreq_ddr2(struct sysinfo *s, + const struct abs_timings *saved_timings) +{ + u8 try_cas; + /* Currently only these CAS are supported */ + u8 cas_mask = SPD_CAS_LATENCY_DDR2_5 | SPD_CAS_LATENCY_DDR2_6; + + cas_mask &= saved_timings->cas_supported; + try_cas = spd_get_msbs(cas_mask); + + while (cas_mask & (1 << try_cas) && try_cas > 0) { + s->selected_timings.CAS = try_cas; + s->selected_timings.tclk = saved_timings->min_tCLK_cas[try_cas]; + if (s->selected_timings.tclk >= CTRL_MIN_TCLK_DDR2 && + saved_timings->min_tCLK_cas[try_cas] != + saved_timings->min_tCLK_cas[try_cas - 1]) + break; + try_cas--; + } + + + if ((s->selected_timings.CAS < 3) || (s->selected_timings.tclk == 0)) + die("Could not find common memory frequency and CAS\n"); + + switch (s->selected_timings.tclk) { + case TCK_200MHZ: + case TCK_266MHZ: + /* FIXME: this works on vendor BIOS */ + die("Selected dram 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; + } +} + +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) { + printk(BIOS_DEBUG, "Problems decoding SPD\n"); + return CB_ERR; + } + + if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) + dram_print_spd_ddr2(&decoded_dimm); + + if (!(decoded_dimm.width & (0x08 | 0x10))) { + printk(BIOS_ERR, + "DIMM%d Unsupported width: x%d. Disabling dimm\n", + dimm_idx, s->dimms[dimm_idx].width); + return CB_ERR; + } + s->dimms[dimm_idx].width = (decoded_dimm.width >> 3) - 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' + * The formula is pagesize in KiB = width * 2^col_bits / 8 + */ + s->dimms[dimm_idx].page_size = decoded_dimm.width * + (1 << decoded_dimm.col_bits) / 8; + + switch (decoded_dimm.banks) { + case 4: + s->dimms[dimm_idx].n_banks = N_BANKS_4; + break; + case 8: + s->dimms[dimm_idx].n_banks = N_BANKS_8; + break; + default: + printk(BIOS_ERR, + "DIMM%d Unsupported #banks: x%d. Disabling dimm\n", + dimm_idx, decoded_dimm.banks); + return CB_ERR; + } + + 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++) { + if (!(saved_timings->cas_supported & (1 << i))) + saved_timings->min_tCLK_cas[i] = 0; + else + saved_timings->min_tCLK_cas[i] = + MAX(saved_timings->min_tCLK_cas[i], + decoded_dimm.cycle_time[i]); + } + s->dimms[dimm_idx].checksum = decoded_dimm.checksum; + return CB_SUCCESS; +} diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index b9e683b..4ac901c 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -354,6 +354,20 @@ CTRL3, };
+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 min_tCLK_cas[8]; + u32 cas_supported; +}; + #ifndef __BOOTBLOCK__ void x4x_early_init(void); void x4x_late_init(int s3resume); @@ -372,6 +386,10 @@ struct rt_dqs_setting *dqs_setting); int do_write_training(struct sysinfo *s); int do_read_training(struct sysinfo *s); +void select_cas_dramfreq_ddr2(struct sysinfo *s, + const struct abs_timings *saved_timings); +int ddr2_save_dimminfo(u8 dimm_idx, u8 *raw_spd, + struct abs_timings *saved_timings, struct sysinfo *s);
extern const struct dll_setting default_ddr2_667_ctrl[7]; extern const struct dll_setting default_ddr2_800_ctrl[7];