From 294eac79f313174abdf4f79abd263f39edb7ad54 Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Tue, 10 Nov 2020 22:14:54 +0800 Subject: haswell: use Broadwell mrc and refcode --- src/northbridge/intel/haswell/Makefile.inc | 2 + src/northbridge/intel/haswell/bdw_pei_data.h | 239 +++++++++++++++++++++++++++ src/northbridge/intel/haswell/raminit.c | 118 ++++++------- src/soc/intel/broadwell/refcode/Makefile.inc | 1 + 4 files changed, 304 insertions(+), 56 deletions(-) create mode 100644 src/northbridge/intel/haswell/bdw_pei_data.h diff --git a/src/northbridge/intel/haswell/Makefile.inc b/src/northbridge/intel/haswell/Makefile.inc index b2fd5307bf..b76c415828 100644 --- a/src/northbridge/intel/haswell/Makefile.inc +++ b/src/northbridge/intel/haswell/Makefile.inc @@ -20,6 +20,8 @@ romstage-y += report_platform.c smm-y += finalize.c +subdirs-y += ../../../soc/intel/broadwell/refcode + # We don't ship that, but booting without it is bound to fail cbfs-files-$(CONFIG_HAVE_MRC) += mrc.bin mrc.bin-file := $(call strip_quotes,$(CONFIG_MRC_FILE)) diff --git a/src/northbridge/intel/haswell/bdw_pei_data.h b/src/northbridge/intel/haswell/bdw_pei_data.h new file mode 100644 index 0000000000..76ec4b6eb8 --- /dev/null +++ b/src/northbridge/intel/haswell/bdw_pei_data.h @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef BDW_PEI_DATA_H +#define BDW_PEI_DATA_H + +#include + +#define BDW_PEI_VERSION 22 + +#define BDW_ABI_X86 __attribute__((regparm(0))) + +typedef void BDW_ABI_X86 (*bdw_tx_byte_func)(unsigned char byte); + +enum bdw_board_type { + BDW_CRB_MOBILE = 0, /* CRB Mobile */ + BDW_CRB_DESKTOP, /* CRB Desktop */ + BDW_USER1, /* SV mobile */ + BDW_USER2, /* SV desktop */ + BDW_USER3, /* SV server */ + BDW_ULT, /* ULT */ + BDW_CRB_EMBDEDDED, /* CRB Embedded */ + BDW_UNKNOWN, +}; + +#define BDW_MAX_USB2_PORTS 14 +#define BDW_MAX_USB3_PORTS 6 + +struct bdw_usb2_port_setting { + /* + * Usb Port Length: + * [16:4] = length in inches in octal format + * [3:0] = decimal point + */ + uint16_t length; + uint8_t enable; + uint8_t oc_pin; + uint8_t location; +} __packed; + +struct bdw_usb3_port_setting { + uint8_t enable; + uint8_t oc_pin; + /* + * Set to 0 if trace length is > 5 inches + * Set to 1 if trace length is <= 5 inches + */ + uint8_t fixed_eq; +} __packed; + +#define PEI_DIMM_INFO_SERIAL_SIZE 5 +#define PEI_DIMM_INFO_PART_NUMBER_SIZE 19 +#define PEI_DIMM_INFO_TOTAL 8 /* Maximum num of dimm is 8 */ + +/** + * This table is filled by the MRC blob and used to populate the mem_info + * struct, which is placed in CBMEM and then used to generate SMBIOS type + * 17 table(s) + * + * Values are specified according to the JEDEC SPD Standard. + */ +struct bdw_pei_dimm_info { + /* + * Size of the module in MiB. + */ + uint32_t dimm_size; + /* + * SMBIOS (not SPD) device type. + * + * See the smbios.h smbios_memory_device_type enum. + */ + uint16_t ddr_type; + uint16_t ddr_frequency; + uint8_t rank_per_dimm; + uint8_t channel_num; + uint8_t dimm_num; + uint8_t bank_locator; + /* + * The last byte is '\0' for the end of string. + * + * Even though the SPD spec defines this field as a byte array the value + * is passed directly to SMBIOS as a string, and thus must be printable + * ASCII. + */ + uint8_t serial[PEI_DIMM_INFO_SERIAL_SIZE]; + /* + * The last byte is '\0' for the end of string + * + * Must contain only printable ASCII. + */ + uint8_t module_part_number[PEI_DIMM_INFO_PART_NUMBER_SIZE]; + /* + * SPD Manufacturer ID + */ + uint16_t mod_id; + /* + * SPD Module Type. + * + * See spd.h for valid values. + * + * e.g., SPD_RDIMM, SPD_SODIMM, SPD_MICRO_DIMM + */ + uint8_t mod_type; + /* + * SPD bus width. + * + * Bits 0 - 2 encode the primary bus width: + * 0b000 = 8 bit width + * 0b001 = 16 bit width + * 0b010 = 32 bit width + * 0b011 = 64 bit width + * + * Bits 3 - 4 encode the extension bits (ECC): + * 0b00 = 0 extension bits + * 0b01 = 8 bit of ECC + * + * e.g., + * 64 bit bus with 8 bits of ECC (72 bits total): 0b1011 + * 64 bit bus with 0 bits of ECC (64 bits total): 0b0011 + * + * See the smbios.h smbios_memory_bus_width enum. + */ + uint8_t bus_width; +} __packed; + +struct bdw_pei_memory_info { + uint8_t dimm_cnt; + struct bdw_pei_dimm_info dimm[PEI_DIMM_INFO_TOTAL]; +} __packed; + +struct bdw_pei_data { + uint32_t pei_version; + + enum bdw_board_type board_type; + int boot_mode; + int ec_present; + int usbdebug; + + /* Base addresses */ + uint32_t pciexbar; + uint16_t smbusbar; + uint32_t xhcibar; + uint32_t ehcibar; + uint32_t gttbar; + uint32_t rcba; + uint32_t pmbase; + uint32_t gpiobase; + uint32_t temp_mmio_base; + uint32_t tseg_size; + + /* + * 0 = leave channel enabled + * 1 = disable dimm 0 on channel + * 2 = disable dimm 1 on channel + * 3 = disable dimm 0+1 on channel + */ + int dimm_channel0_disabled; + int dimm_channel1_disabled; + /* Set to 0 for memory down */ + uint8_t spd_addresses[4]; + /* Enable 2x Refresh Mode */ + int ddr_refresh_2x; + /* DQ pins are interleaved on board */ + int dq_pins_interleaved; + /* Limit DDR3 frequency */ + int max_ddr3_freq; + /* Disable self refresh */ + int disable_self_refresh; + /* Disable cmd power/CKEPD */ + int disable_cmd_pwr; + + /* USB port configuration */ + struct bdw_usb2_port_setting usb2_ports[BDW_MAX_USB2_PORTS]; + struct bdw_usb3_port_setting usb3_ports[BDW_MAX_USB3_PORTS]; + + /* + * USB3 board specific PHY tuning + */ + + /* Valid range: 0x69 - 0x80 */ + uint8_t usb3_txout_volt_dn_amp_adj[MAX_USB3_PORTS]; + /* Valid range: 0x80 - 0x9c */ + uint8_t usb3_txout_imp_sc_volt_amp_adj[MAX_USB3_PORTS]; + /* Valid range: 0x39 - 0x80 */ + uint8_t usb3_txout_de_emp_adj[MAX_USB3_PORTS]; + /* Valid range: 0x3d - 0x4a */ + uint8_t usb3_txout_imp_adj_volt_amp[MAX_USB3_PORTS]; + + /* Console output function */ + bdw_tx_byte_func tx_byte; + + /* + * DIMM SPD data for memory down configurations + * [CHANNEL][SLOT][SPD] + */ + uint8_t spd_data[2][2][512]; + + /* + * LPDDR3 DQ byte map + * [CHANNEL][ITERATION][2] + * + * Maps which PI clocks are used by what LPDDR DQ Bytes (from CPU side) + * DQByteMap[0] - ClkDQByteMap: + * - If clock is per rank, program to [0xFF, 0xFF] + * - If clock is shared by 2 ranks, program to [0xFF, 0] or [0, 0xFF] + * - If clock is shared by 2 ranks but does not go to all bytes, + * Entry[i] defines which DQ bytes Group i services + * DQByteMap[1] - CmdNDQByteMap: [0] is CmdN/CAA and [1] is CmdN/CAB + * DQByteMap[2] - CmdSDQByteMap: [0] is CmdS/CAA and [1] is CmdS/CAB + * DQByteMap[3] - CkeDQByteMap : [0] is CKE /CAA and [1] is CKE /CAB + * For DDR, DQByteMap[3:1] = [0xFF, 0] + * DQByteMap[4] - CtlDQByteMap : Always program to [0xFF, 0] + * since we have 1 CTL / rank + * DQByteMap[5] - CmdVDQByteMap: Always program to [0xFF, 0] + * since we have 1 CA Vref + */ + uint8_t dq_map[2][6][2]; + + /* + * LPDDR3 Map from CPU DQS pins to SDRAM DQS pins + * [CHANNEL][MAX_BYTES] + */ + uint8_t dqs_map[2][8]; + + /* Data read from flash and passed into MRC */ + const void *saved_data; + int saved_data_size; + + /* Disable use of saved data (can be set by mainboard) */ + int disable_saved_data; + + /* Data from MRC that should be saved to flash */ + void *data_to_save; + int data_to_save_size; + struct bdw_pei_memory_info meminfo; +} __packed; + +typedef struct pei_data PEI_DATA; + +#endif diff --git a/src/northbridge/intel/haswell/raminit.c b/src/northbridge/intel/haswell/raminit.c index 290e402fcb..da068bab7d 100644 --- a/src/northbridge/intel/haswell/raminit.c +++ b/src/northbridge/intel/haswell/raminit.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include +#include #include #include #include @@ -19,6 +20,8 @@ #include "raminit.h" #include "pei_data.h" #include "haswell.h" +#include +#include "bdw_pei_data.h" #define MRC_CACHE_VERSION 1 @@ -29,28 +32,6 @@ void save_mrc_data(struct pei_data *pei_data) pei_data->mrc_output_len); } -static void prepare_mrc_cache(struct pei_data *pei_data) -{ - size_t mrc_size; - - /* Preset just in case there is an error */ - pei_data->mrc_input = NULL; - pei_data->mrc_input_len = 0; - - pei_data->mrc_input = - mrc_cache_current_mmap_leak(MRC_TRAINING_DATA, - MRC_CACHE_VERSION, - &mrc_size); - if (!pei_data->mrc_input) - /* Error message printed in find_current_mrc_cache */ - return; - - pei_data->mrc_input_len = mrc_size; - - printk(BIOS_DEBUG, "%s: at %p, size %zx\n", __func__, - pei_data->mrc_input, mrc_size); -} - static const char *const ecc_decoder[] = { "inactive", "active on IO", @@ -98,6 +79,28 @@ static void report_memory_config(void) } } +static void BDW_ABI_X86 send_to_console(unsigned char b) +{ + console_tx_byte(b); +} + +static void broadwell_fill_pei_data(struct bdw_pei_data *pei_data) +{ + pei_data->pei_version = BDW_PEI_VERSION; + pei_data->board_type = BDW_ULT; + pei_data->usbdebug = CONFIG(USBDEBUG); + pei_data->pciexbar = MCFG_BASE_ADDRESS; + pei_data->smbusbar = SMBUS_BASE_ADDRESS; + pei_data->ehcibar = EARLY_EHCI_BAR; + pei_data->xhcibar = EARLY_XHCI_BAR; + pei_data->gttbar = EARLY_GTT_BAR; + pei_data->pmbase = ACPI_BASE_ADDRESS; + pei_data->gpiobase = GPIO_BASE_ADDRESS; + pei_data->tseg_size = CONFIG_SMM_TSEG_SIZE; + pei_data->temp_mmio_base = EARLY_TEMP_MMIO; + pei_data->tx_byte = &send_to_console; + pei_data->ddr_refresh_2x = 1; +} /** * Find PEI executable in coreboot filesystem and execute it. * @@ -105,44 +108,37 @@ static void report_memory_config(void) */ void sdram_initialize(struct pei_data *pei_data) { - int (*entry)(struct pei_data *pei_data) __attribute__((regparm(1))); - - uint32_t type = CBFS_TYPE_MRC; - struct cbfsf f; - - printk(BIOS_DEBUG, "Starting UEFI PEI System Agent\n"); - - /* - * Always pass in mrc_cache data. The driver will determine - * whether to use the data or not. - */ - prepare_mrc_cache(pei_data); - - /* If MRC data is not found, we cannot continue S3 resume */ - if (pei_data->boot_mode == 2 && !pei_data->mrc_input) { - post_code(POST_RESUME_FAILURE); - printk(BIOS_DEBUG, "Giving up in %s: No MRC data\n", __func__); - system_reset(); + int BDW_ABI_X86 mrc_entry(struct bdw_pei_data *); + int BDW_ABI_X86 refcode_entry(struct bdw_pei_data *); + + struct bdw_pei_data bdw_pei; + memset(&bdw_pei, 0, sizeof(bdw_pei)); + broadwell_fill_pei_data(&bdw_pei); + + bdw_pei.dimm_channel0_disabled = pei_data->dimm_channel0_disabled; + bdw_pei.dimm_channel1_disabled = pei_data->dimm_channel1_disabled; + bdw_pei.dq_pins_interleaved = pei_data->dq_pins_interleaved; + memcpy(bdw_pei.spd_addresses, pei_data->spd_addresses, sizeof(bdw_pei.spd_addresses)); + bdw_pei.disable_saved_data = 1; + bdw_pei.saved_data = NULL; + bdw_pei.saved_data_size = 0; + + for (int i = 0; i < BDW_MAX_USB2_PORTS; i++) { + bdw_pei.usb2_ports[i].length = pei_data->usb2_ports[i].length; + bdw_pei.usb2_ports[i].enable = pei_data->usb2_ports[i].enable; + bdw_pei.usb2_ports[i].oc_pin = pei_data->usb2_ports[i].over_current_pin; + bdw_pei.usb2_ports[i].location = pei_data->usb2_ports[i].location; } - /* Pass console handler in pei_data */ - pei_data->tx_byte = do_putchar; - - /* - * Locate and call UEFI System Agent binary. The binary needs to be at a fixed offset - * in the flash and can therefore only reside in the COREBOOT fmap region. - */ - if (cbfs_locate_file_in_region(&f, "COREBOOT", "mrc.bin", &type) < 0) - die("mrc.bin not found!"); + for (int i = 0; i < BDW_MAX_USB3_PORTS; i++) { + bdw_pei.usb3_ports[i].enable = pei_data->usb3_ports[i].enable; + bdw_pei.usb3_ports[i].oc_pin = pei_data->usb3_ports[i].over_current_pin; + } - /* We don't care about leaking the mapping */ - entry = rdev_mmap_full(&f.data); - if (entry) { - int rv = entry(pei_data); + printk(BIOS_DEBUG, "Starting UEFI PEI System Agent\n"); - /* The mrc.bin reconfigures USB, so usbdebug needs to be reinitialized */ - if (CONFIG(USBDEBUG_IN_PRE_RAM)) - usbdebug_hw_init(true); + if (true) { + int rv = mrc_entry(&bdw_pei); if (rv) { switch (rv) { @@ -158,6 +154,16 @@ void sdram_initialize(struct pei_data *pei_data) die_with_post_code(POST_INVALID_VENDOR_BINARY, "Nonzero MRC return value.\n"); } + + rv = refcode_entry(&bdw_pei); + + /* The mrc.bin reconfigures USB, so usbdebug needs to be reinitialized */ + if (CONFIG(USBDEBUG_IN_PRE_RAM)) + usbdebug_hw_init(true); + + if (rv) { + printk(BIOS_ERR, "refcode returns %d.\n", rv); + } } else { die("UEFI PEI System Agent not found.\n"); } diff --git a/src/soc/intel/broadwell/refcode/Makefile.inc b/src/soc/intel/broadwell/refcode/Makefile.inc index 3eca45f66d..2b815eaab9 100644 --- a/src/soc/intel/broadwell/refcode/Makefile.inc +++ b/src/soc/intel/broadwell/refcode/Makefile.inc @@ -1,5 +1,6 @@ romstage-libs += $(obj)/broadwell_mrc.o romstage-y += printk.c +romstage-libs += $(obj)/broadwell_refcode.o ramstage-libs += $(obj)/broadwell_refcode.o $(obj)/%.o: $(src)/soc/intel/broadwell/refcode/%.asm -- cgit v1.2.3