From 32851c6df794d194d1c1f4c0cf987ac66c8b5e8a Mon Sep 17 00:00:00 2001 From: T Michael Turney Date: Tue, 23 Apr 2019 13:47:04 -0700 Subject: [PATCH 001/107] sdm845: Select VBOOT_MIGRATE_WORKING_DATA, now required Change-Id: Idebbbd89de05d949e6f953aa49d8662d64383d1a Signed-off-by: T Michael Turney Reviewed-on: https://review.coreboot.org/c/coreboot/+/32449 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/soc/qualcomm/sdm845/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/soc/qualcomm/sdm845/Kconfig b/src/soc/qualcomm/sdm845/Kconfig index ba064889f0..ffb95cb4cd 100644 --- a/src/soc/qualcomm/sdm845/Kconfig +++ b/src/soc/qualcomm/sdm845/Kconfig @@ -18,6 +18,7 @@ config VBOOT select VBOOT_RETURN_FROM_VERSTAGE select VBOOT_MUST_REQUEST_DISPLAY select VBOOT_STARTS_IN_BOOTBLOCK + select VBOOT_MIGRATE_WORKING_DATA config SDM845_QSPI bool From 7a3e46d767890f502b09771e19decc5033e27079 Mon Sep 17 00:00:00 2001 From: T Michael Turney Date: Thu, 21 Mar 2019 14:21:26 -0700 Subject: [PATCH 002/107] qualcomm: Add QCLib interface support to common/ Change-Id: I38d086c379a3c2f54d1603a2fed5b33860f7f4d7 Signed-off-by: T Michael Turney Reviewed-on: https://review.coreboot.org/c/coreboot/+/32288 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/soc/qualcomm/common/Kconfig | 5 + .../qualcomm/common/include/soc/mmu_common.h | 31 +++ .../common/include/soc/qclib_common.h | 76 ++++++ .../common/include/soc/symbols_common.h | 25 ++ src/soc/qualcomm/common/mmu.c | 26 ++ src/soc/qualcomm/common/qclib.c | 227 ++++++++++++++++++ 6 files changed, 390 insertions(+) create mode 100644 src/soc/qualcomm/common/Kconfig create mode 100644 src/soc/qualcomm/common/include/soc/mmu_common.h create mode 100644 src/soc/qualcomm/common/include/soc/qclib_common.h create mode 100644 src/soc/qualcomm/common/include/soc/symbols_common.h create mode 100644 src/soc/qualcomm/common/mmu.c create mode 100644 src/soc/qualcomm/common/qclib.c diff --git a/src/soc/qualcomm/common/Kconfig b/src/soc/qualcomm/common/Kconfig new file mode 100644 index 0000000000..f3d12629fb --- /dev/null +++ b/src/soc/qualcomm/common/Kconfig @@ -0,0 +1,5 @@ + +config QC_SDI_ENABLE + bool + default n + prompt "Debug Build: enable SDI" diff --git a/src/soc/qualcomm/common/include/soc/mmu_common.h b/src/soc/qualcomm/common/include/soc/mmu_common.h new file mode 100644 index 0000000000..ee781224bd --- /dev/null +++ b/src/soc/qualcomm/common/include/soc/mmu_common.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _SOC_QUALCOMM_MMU_COMMON_H_ +#define _SOC_QUALCOMM_MMU_COMMON_H_ + +#include +#include + +#define CACHED_RAM (MA_MEM | MA_S | MA_RW) +#define UNCACHED_RAM (MA_MEM | MA_S | MA_RW | MA_MEM_NC) +#define DEV_MEM (MA_DEV | MA_S | MA_RW) + +static struct region * const ddr_region = (struct region *)_ddr_information; + +void soc_mmu_dram_config_post_dram_init(void); +void qc_mmu_dram_config_post_dram_init(void *ddr_base, size_t ddr_size); + +#endif /* _SOC_QUALCOMM_MMU_COMMON_H_ */ diff --git a/src/soc/qualcomm/common/include/soc/qclib_common.h b/src/soc/qualcomm/common/include/soc/qclib_common.h new file mode 100644 index 0000000000..19ec083bfd --- /dev/null +++ b/src/soc/qualcomm/common/include/soc/qclib_common.h @@ -0,0 +1,76 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _SOC_QUALCOMM_QCLIB_COMMON_H__ +#define _SOC_QUALCOMM_QCLIB_COMMON_H__ + +/* coreboot & QCLib I/F definitions */ + +/* string field lengths */ +#define QCLIB_MAGIC_NUMBER_LENGTH 8 +#define QCLIB_FMAP_NAME_LENGTH 24 +#define QCLIB_TE_NAME_LENGTH 24 + +/* FMAP_REGION names */ +#define QCLIB_FR_DDR_TRAINING_DATA "RO_DDR_TRAINING" +#define QCLIB_FR_LIMITS_CFG_DATA "RO_LIMITS_CFG" + +/* TE_NAME (table entry name) */ +#define QCLIB_TE_DDR_INFORMATION "ddr_information" +#define QCLIB_TE_QCLIB_LOG_BUFFER "qclib_log_buffer" +#define QCLIB_TE_DCB_SETTINGS "dcb_settings" +#define QCLIB_TE_CDT_SETTINGS "cdt_settings" +#define QCLIB_TE_PMIC_SETTINGS "pmic_settings" +#define QCLIB_TE_DDR_TRAINING_DATA "ddr_training_data" +#define QCLIB_TE_LIMITS_CFG_DATA "limits_cfg_data" +#define QCLIB_TE_QCSDI "qcsdi" + +/* BA_BMASK_VALUES (blob_attributes bit mask values) */ +#define QCLIB_BA_SAVE_TO_STORAGE 0x00000001 + +struct qclib_cb_if_table_entry { + char name[QCLIB_TE_NAME_LENGTH]; /* 0x00 TE_NAME */ + uint64_t blob_address; /* 0x18 blob addr in SRAM */ + uint32_t size; /* 0x20 blob size in SRAM */ + uint32_t blob_attributes; /* 0x24 BA_BMASK_VALUES */ +}; + +/* GA_BMASK_VALUES (global_attributes bit mask values) */ +#define QCLIB_GA_ENABLE_UART_LOGGING 0x00000001 + +#define QCLIB_INTERFACE_VERSION 0x00000001 +#define QCLIB_MAX_NUMBER_OF_ENTRIES 16 + +#define QCLIB_MAGIC_NUMBER "QCLIB_CB" + +struct qclib_cb_if_table { + char magic[8]; /* 0x00 */ + uint32_t version; /* 0x08 */ + uint32_t num_entries; /* 0x0C */ + uint32_t max_entries; /* 0x10 */ + uint32_t global_attributes; /* 0x14 */ + uint64_t reserved; /* 0x18 */ + struct qclib_cb_if_table_entry + te[QCLIB_MAX_NUMBER_OF_ENTRIES]; /* 0x20 */ +}; + +extern struct qclib_cb_if_table qclib_cb_if_table; + +void qclib_add_if_table_entry(const char *name, void *base, + uint32_t size, uint32_t attrs); +void qclib_load_and_run(void); +int qclib_soc_blob_load(void); + +#endif // _SOC_QUALCOMM_QCLIB_COMMON_H_ diff --git a/src/soc/qualcomm/common/include/soc/symbols_common.h b/src/soc/qualcomm/common/include/soc/symbols_common.h new file mode 100644 index 0000000000..ffa535c493 --- /dev/null +++ b/src/soc/qualcomm/common/include/soc/symbols_common.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#ifndef _SOC_QUALCOMM_SYMBOLS_COMMON_H_ +#define _SOC_QUALCOMM_SYMBOLS_COMMON_H_ + +#include + +DECLARE_REGION(ddr_training); +DECLARE_REGION(qclib_serial_log); +DECLARE_REGION(ddr_information); + +#endif // _SOC_QUALCOMM_SYMBOLS_COMMON_H_ diff --git a/src/soc/qualcomm/common/mmu.c b/src/soc/qualcomm/common/mmu.c new file mode 100644 index 0000000000..79d2eb7271 --- /dev/null +++ b/src/soc/qualcomm/common/mmu.c @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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 +#include +#include + +__weak void soc_mmu_dram_config_post_dram_init(void) { /* no-op */ } + +void qc_mmu_dram_config_post_dram_init(void *ddr_base, size_t ddr_size) +{ + mmu_config_range((void *)ddr_base, ddr_size, CACHED_RAM); + soc_mmu_dram_config_post_dram_init(); +} diff --git a/src/soc/qualcomm/common/qclib.c b/src/soc/qualcomm/common/qclib.c new file mode 100644 index 0000000000..1fd79b57b5 --- /dev/null +++ b/src/soc/qualcomm/common/qclib.c @@ -0,0 +1,227 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct qclib_cb_if_table qclib_cb_if_table = { + .magic = QCLIB_MAGIC_NUMBER, + .version = QCLIB_INTERFACE_VERSION, + .num_entries = 0, + .max_entries = QCLIB_MAX_NUMBER_OF_ENTRIES, + .global_attributes = 0, + .reserved = 0, +}; + +void qclib_add_if_table_entry(const char *name, void *base, + uint32_t size, uint32_t attrs) +{ + struct qclib_cb_if_table_entry *te = + &qclib_cb_if_table.te[qclib_cb_if_table.num_entries++]; + assert(qclib_cb_if_table.num_entries <= qclib_cb_if_table.max_entries); + strncpy(te->name, name, sizeof(te->name)); + te->blob_address = (uintptr_t)base; + te->size = size; + te->blob_attributes = attrs; +} + +static void write_ddr_information(struct qclib_cb_if_table_entry *te) +{ + uint64_t ddr_size; + + /* Save DDR info in SRAM region to share with ramstage */ + ddr_region->offset = te->blob_address; + ddr_size = te->size; + ddr_region->size = ddr_size * MiB; + + /* Use DDR info to configure MMU */ + qc_mmu_dram_config_post_dram_init((void *)ddr_region->offset, + (size_t)ddr_region->size); +} + +static void write_qclib_log_to_cbmemc(struct qclib_cb_if_table_entry *te) +{ + int i; + char *ptr = (char *)te->blob_address; + + for (i = 0; i < te->size; i++) + __cbmemc_tx_byte(*ptr++); +} + +static void write_table_entry(struct qclib_cb_if_table_entry *te) +{ + + if (!strncmp(QCLIB_TE_DDR_INFORMATION, te->name, + sizeof(te->name))) { + + write_ddr_information(te); + + } else if (!strncmp(QCLIB_TE_DDR_TRAINING_DATA, te->name, + sizeof(te->name))) { + + assert(fmap_overwrite_area(QCLIB_FR_DDR_TRAINING_DATA, + (const void *)te->blob_address, te->size)); + + } else if (!strncmp(QCLIB_TE_LIMITS_CFG_DATA, te->name, + sizeof(te->name))) { + + assert(fmap_overwrite_area(QCLIB_FR_LIMITS_CFG_DATA, + (const void *)te->blob_address, te->size)); + + } else if (!strncmp(QCLIB_TE_QCLIB_LOG_BUFFER, te->name, + sizeof(te->name))) { + + write_qclib_log_to_cbmemc(te); + + } else { + + printk(BIOS_WARNING, "%s write not implemented\n", te->name); + printk(BIOS_WARNING, " blob_address[%llx]..size[%x]\n", + te->blob_address, te->size); + + } +} + +static void dump_te_table(void) +{ + struct qclib_cb_if_table_entry *te; + int i; + + for (i = 0; i < qclib_cb_if_table.num_entries; i++) { + te = &qclib_cb_if_table.te[i]; + printk(BIOS_DEBUG, "[%s][%llx][%x][%x]\n", + te->name, te->blob_address, + te->size, te->blob_attributes); + } +} + +__weak int qclib_soc_blob_load(void) { return 0; } + +void qclib_load_and_run(void) +{ + int i; + ssize_t ssize; + struct mmu_context pre_qclib_mmu_context; + + /* zero ddr_information SRAM region, needs new data each boot */ + memset(ddr_region, 0, sizeof(struct region)); + + /* output area, QCLib copies console log buffer out */ + if (IS_ENABLED(CONFIG_CONSOLE_CBMEM)) + qclib_add_if_table_entry(QCLIB_TE_QCLIB_LOG_BUFFER, + _qclib_serial_log, + REGION_SIZE(qclib_serial_log), 0); + + /* output area, QCLib fills in DDR details */ + qclib_add_if_table_entry(QCLIB_TE_DDR_INFORMATION, NULL, 0, 0); + + /* Attempt to load DDR Training Blob */ + ssize = fmap_read_area(QCLIB_FR_DDR_TRAINING_DATA, _ddr_training, + REGION_SIZE(ddr_training)); + if (ssize < 0) + goto fail; + qclib_add_if_table_entry(QCLIB_TE_DDR_TRAINING_DATA, + _ddr_training, ssize, 0); + + /* hook for SoC specific binary blob loads */ + if (qclib_soc_blob_load()) { + printk(BIOS_ERR, "qclib_soc_blob_load failed\n"); + goto fail; + } + + /* Enable QCLib serial output, based on Kconfig */ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL)) + qclib_cb_if_table.global_attributes = + QCLIB_GA_ENABLE_UART_LOGGING; + + if (IS_ENABLED(CONFIG_QC_SDI_ENABLE)) { + struct prog qcsdi = + PROG_INIT(PROG_REFCODE, CONFIG_CBFS_PREFIX "/qcsdi"); + + /* Attempt to load QCSDI elf */ + if (prog_locate(&qcsdi)) + goto fail; + + if (cbfs_prog_stage_load(&qcsdi)) + goto fail; + + qclib_add_if_table_entry(QCLIB_TE_QCSDI, prog_entry(&qcsdi), + prog_size(&qcsdi), 0); + printk(BIOS_INFO, "qcsdi.entry[%p]\n", qcsdi.entry); + } + + dump_te_table(); + + /* Attempt to load QCLib elf */ + struct prog qclib = + PROG_INIT(PROG_REFCODE, CONFIG_CBFS_PREFIX "/qclib"); + + if (prog_locate(&qclib)) + goto fail; + + if (cbfs_prog_stage_load(&qclib)) + goto fail; + + prog_set_entry(&qclib, prog_entry(&qclib), &qclib_cb_if_table); + + printk(BIOS_DEBUG, "\n\n\nQCLib is about to Initialize DDR\n"); + printk(BIOS_DEBUG, "Global Attributes[%x]..Table Entries Count[%d]\n", + qclib_cb_if_table.global_attributes, + qclib_cb_if_table.num_entries); + printk(BIOS_DEBUG, "Jumping to QCLib code at %p(%p)\n", + prog_entry(&qclib), prog_entry_arg(&qclib)); + + /* back-up mmu context before disabling mmu and executing qclib */ + mmu_save_context(&pre_qclib_mmu_context); + /* disable mmu before jumping to qclib. mmu_disable also + flushes and invalidates caches before disabling mmu. */ + mmu_disable(); + + prog_run(&qclib); + + /* Before returning, QCLib flushes cache and disables mmu. + Explicitly disable mmu (flush, invalidate and disable mmu) + before re-enabling mmu with backed-up mmu context */ + mmu_disable(); + mmu_restore_context(&pre_qclib_mmu_context); + mmu_enable(); + + /* step through I/F table, handling return values */ + for (i = 0; i < qclib_cb_if_table.num_entries; i++) + if (qclib_cb_if_table.te[i].blob_attributes & + QCLIB_BA_SAVE_TO_STORAGE) + write_table_entry(&qclib_cb_if_table.te[i]); + + /* confirm that we received valid ddr information from QCLib */ + assert((uintptr_t)_dram == region_offset(ddr_region) && + region_sz(ddr_region) >= (u8 *)cbmem_top() - _dram); + + printk(BIOS_DEBUG, "QCLib completed\n\n\n"); + + return; + +fail: + die("Couldn't run QCLib.\n"); +} From c0fe0b28a9461e963d6dff5d91cf70231dcae0e8 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Mon, 26 Mar 2018 15:13:36 -0700 Subject: [PATCH 003/107] sdm845: Add USB support on cheza platform This patch adds code to initialize two USB DWC3.0 controllers and its associated QUSB V2 10nm PHYs to the SDM845 SOC, and uses them to initialize USB3.0 on the cheza mainboard. Synopsis controller initialization and configuration sequences taken from USB 3.0 HPG chapter 2.2 and refer PHY HPG chapter 10.2 for QUSB phy programming. Includes Super speed mode support. TEST=USB keypad and mass-storage device enumeration tested with this patch Change-Id: I475a7757239acb8ef22a4d61afd59b304a7f0acc Signed-off-by: Chandana Kishori Chiluveru Reviewed-on: https://review.coreboot.org/c/coreboot/+/25213 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/mainboard/google/cheza/mainboard.c | 14 + src/mainboard/google/cheza/romstage.c | 11 + src/soc/qualcomm/sdm845/Makefile.inc | 2 + .../qualcomm/sdm845/include/soc/addressmap.h | 19 + src/soc/qualcomm/sdm845/include/soc/clock.h | 33 +- src/soc/qualcomm/sdm845/include/soc/efuse.h | 30 + src/soc/qualcomm/sdm845/include/soc/usb.h | 96 ++ src/soc/qualcomm/sdm845/usb.c | 915 ++++++++++++++++++ 8 files changed, 1114 insertions(+), 6 deletions(-) create mode 100644 src/soc/qualcomm/sdm845/include/soc/efuse.h create mode 100644 src/soc/qualcomm/sdm845/include/soc/usb.h create mode 100644 src/soc/qualcomm/sdm845/usb.c diff --git a/src/mainboard/google/cheza/mainboard.c b/src/mainboard/google/cheza/mainboard.c index cb4f5d061a..42adf56c79 100644 --- a/src/mainboard/google/cheza/mainboard.c +++ b/src/mainboard/google/cheza/mainboard.c @@ -16,9 +16,23 @@ #include #include #include +#include +#include + +static struct usb_board_data usb1_board_data = { + .pll_bias_control_2 = 0x28, + .imp_ctrl1 = 0x08, + .port_tune1 = 0x20, +}; static void setup_usb(void) { + /* + * Primary USB is used only for DP functionality on cheza platform. + * Hence Setting up only Secondary USB DWC3 controller. + */ + setup_usb_host1(&usb1_board_data); + gpio_output(GPIO(120), 1); /* Deassert HUB_RST_L to enable hub. */ } diff --git a/src/mainboard/google/cheza/romstage.c b/src/mainboard/google/cheza/romstage.c index ad8506193d..7b7da4ce8c 100644 --- a/src/mainboard/google/cheza/romstage.c +++ b/src/mainboard/google/cheza/romstage.c @@ -14,7 +14,18 @@ */ #include +#include + +static void prepare_usb(void) +{ + /* + * Do DWC3 core and phy reset. Kick these resets + * off early so they get at least 1ms to settle. + */ + reset_usb1(); +} void platform_romstage_main(void) { + prepare_usb(); } diff --git a/src/soc/qualcomm/sdm845/Makefile.inc b/src/soc/qualcomm/sdm845/Makefile.inc index 896ae58e5f..d099bff717 100644 --- a/src/soc/qualcomm/sdm845/Makefile.inc +++ b/src/soc/qualcomm/sdm845/Makefile.inc @@ -24,6 +24,7 @@ romstage-y += timer.c romstage-y += gpio.c romstage-y += clock.c romstage-$(CONFIG_SDM845_QSPI) += qspi.c +romstage-y += usb.c ################################################################################ ramstage-y += soc.c @@ -33,6 +34,7 @@ ramstage-y += timer.c ramstage-y += gpio.c ramstage-y += clock.c ramstage-$(CONFIG_SDM845_QSPI) += qspi.c +ramstage-y += usb.c ################################################################################ diff --git a/src/soc/qualcomm/sdm845/include/soc/addressmap.h b/src/soc/qualcomm/sdm845/include/soc/addressmap.h index 5a94e23e96..bf4b30b32b 100644 --- a/src/soc/qualcomm/sdm845/include/soc/addressmap.h +++ b/src/soc/qualcomm/sdm845/include/soc/addressmap.h @@ -25,4 +25,23 @@ #define GCC_BASE 0x00100000 #define AOSS_CC_BASE 0x0C2F0000 +/* + * USB BASE ADDRESSES + */ +#define QFPROM_BASE 0x00780000 +#define QUSB_PRIM_PHY_BASE 0x088e2000 +#define QUSB_PRIM_PHY_DIG_BASE 0x088e2200 +#define QUSB_SEC_PHY_BASE 0x088e3000 +#define QUSB_SEC_PHY_DIG_BASE 0x088e3200 +#define QMP_PHY_QSERDES_COM_REG_BASE 0x088e9000 +#define QMP_PHY_QSERDES_TX_REG_BASE 0x088e9200 +#define QMP_PHY_QSERDES_RX_REG_BASE 0x088e9400 +#define QMP_PHY_PCS_REG_BASE 0x088e9c00 +#define QMP_UNIPHY_QSERDES_COM_REG_BASE 0x088eb000 +#define QMP_UNIPHY_QSERDES_TX_REG_BASE 0x088eb200 +#define QMP_UNIPHY_QSERDES_RX_REG_BASE 0x088eb400 +#define QMP_UNIPHY_PCS_REG_BASE 0x088eb800 +#define USB_HOST0_DWC3_BASE 0x0a60c100 +#define USB_HOST1_DWC3_BASE 0x0a80c100 + #endif /* __SOC_QUALCOMM_SDM845_ADDRESS_MAP_H__ */ diff --git a/src/soc/qualcomm/sdm845/include/soc/clock.h b/src/soc/qualcomm/sdm845/include/soc/clock.h index 9f0533f33f..6aee9c14f3 100644 --- a/src/soc/qualcomm/sdm845/include/soc/clock.h +++ b/src/soc/qualcomm/sdm845/include/soc/clock.h @@ -74,7 +74,14 @@ struct sdm845_gpll { struct sdm845_gcc { struct sdm845_gpll gpll0; - u8 _res0[0x17000 - 0x1000]; + u8 _res0[0xf000 - 0x1000]; + u32 usb30_prim_bcr; + u8 _res1[0x10000 - 0xf004]; + u32 usb30_sec_bcr; + u8 _res2[0x12000 - 0x10004]; + u32 qusb2phy_prim_bcr; + u32 qusb2phy_sec_bcr; + u8 _res3[0x17000 - 0x12008]; u32 qup_wrap0_bcr; u32 qup_wrap0_m_ahb_cbcr; u32 qup_wrap0_s_ahb_cbcr; @@ -82,9 +89,9 @@ struct sdm845_gcc { u32 qup_wrap0_core_cdivr; u32 qup_wrap0_core_2x_cbcr; struct sdm845_rcg qup_wrap0_core_2x; - u8 _res1[0x17030 - 0x17020]; + u8 _res4[0x17030 - 0x17020]; struct sdm845_qupv3_clock qup_wrap0_s[8]; - u8 _res2[0x18000 - 0x179b0]; + u8 _res5[0x18000 - 0x179b0]; u32 qup_wrap1_bcr; u32 qup_wrap1_core_2x_cbcr; u32 qup_wrap1_core_cbcr; @@ -92,14 +99,28 @@ struct sdm845_gcc { u32 qup_wrap1_s_ahb_cbcr; struct sdm845_qupv3_clock qup_wrap1_s[8]; u32 qup_wrap1_core_cdivr; - u8 _res4[0x4B000 - 0x18998]; + u8 _res6[0x4B000 - 0x18998]; u32 qspi_cnoc_ahb_cbcr; u32 qspi_core_cbcr; struct sdm845_rcg qspi_core; - u8 _res5[0x5200c-0x4b010]; + u8 _res7[0x50000-0x4b010]; + u32 usb3_phy_prim_bcr; + u32 usb3phy_phy_prim_bcr; + u32 usb3_dp_phy_prim_bcr; + u32 usb3_phy_sec_bcr; + u32 usb3phy_phy_sec_bcr; + u8 _res8[0x5200c-0x50014]; u32 apcs_clk_br_en1; - u8 _res6[0x1000000-0x52010]; + u8 _res9[0x1000000-0x52010]; }; +check_member(sdm845_gcc, usb30_prim_bcr, 0xf000); +check_member(sdm845_gcc, usb30_sec_bcr, 0x10000); +check_member(sdm845_gcc, qusb2phy_prim_bcr, 0x12000); +check_member(sdm845_gcc, qusb2phy_sec_bcr, 0x12004); +check_member(sdm845_gcc, usb3phy_phy_prim_bcr, 0x50004); +check_member(sdm845_gcc, usb3_phy_prim_bcr, 0x50000); +check_member(sdm845_gcc, usb3_phy_sec_bcr, 0x5000c); +check_member(sdm845_gcc, usb3phy_phy_sec_bcr, 0x50010); check_member(sdm845_gcc, apcs_clk_br_en1, 0x5200c); struct sdm845_aoss { diff --git a/src/soc/qualcomm/sdm845/include/soc/efuse.h b/src/soc/qualcomm/sdm845/include/soc/efuse.h new file mode 100644 index 0000000000..309193cf43 --- /dev/null +++ b/src/soc/qualcomm/sdm845/include/soc/efuse.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2018 Qualcomm Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + */ + +#ifndef __SOC_QUALCOMM_SDM845_EFUSE_ADDRESS_MAP_H__ +#define __SOC_QUALCOMM_SDM845_EFUSE_ADDRESS_MAP_H__ + +/** + * USB EFUSE registers + */ +struct qfprom_corr { + u8 rsvd[0x41E8 - 0x0]; + u32 qusb_hstx_trim_lsb; + u32 qusb_hstx_trim_msb; +}; + +check_member(qfprom_corr, qusb_hstx_trim_lsb, 0x41E8); +check_member(qfprom_corr, qusb_hstx_trim_msb, 0x41EC); +#endif /* __SOC_QUALCOMM_SDM845_EFUSE_ADDRESS_MAP_H__ */ diff --git a/src/soc/qualcomm/sdm845/include/soc/usb.h b/src/soc/qualcomm/sdm845/include/soc/usb.h new file mode 100644 index 0000000000..b657676763 --- /dev/null +++ b/src/soc/qualcomm/sdm845/include/soc/usb.h @@ -0,0 +1,96 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2018 Qualcomm Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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 + +#ifndef _SDM845_USB_H_ +#define _SDM845_USB_H_ + +/* QSCRATCH_GENERAL_CFG register bit offset */ +#define PIPE_UTMI_CLK_SEL BIT(0) +#define PIPE3_PHYSTATUS_SW BIT(3) +#define PIPE_UTMI_CLK_DIS BIT(8) + +/* Global USB3 Control Registers */ +#define DWC3_GUSB3PIPECTL_DELAYP1TRANS BIT(18) +#define DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX BIT(27) +#define DWC3_GCTL_PRTCAPDIR(n) ((n) << 12) +#define DWC3_GCTL_PRTCAP_OTG 3 +#define DWC3_GCTL_PRTCAP_HOST 1 + +/* Global USB2 PHY Configuration Register */ +#define DWC3_GUSB2PHYCFG_USBTRDTIM(n) ((n) << 10) +#define DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK DWC3_GUSB2PHYCFG_USBTRDTIM(0xf) +#define DWC3_GUSB2PHYCFG_PHYIF(n) ((n) << 3) +#define DWC3_GUSB2PHYCFG_PHYIF_MASK DWC3_GUSB2PHYCFG_PHYIF(1) +#define USBTRDTIM_UTMI_8_BIT 9 +#define UTMI_PHYIF_8_BIT 0 + +#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) +#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) +#define DWC3_GCTL_DISSCRAMBLE (1 << 3) +#define DWC3_GCTL_U2EXIT_LFPS (1 << 2) +#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) + +#define PORT_TUNE1_MASK 0xf0 + +/* QUSB2PHY_PWR_CTRL1 register related bits */ +#define POWER_DOWN BIT(0) + +/* DEBUG_CTRL2 register value to program VSTATUS MUX for PHY status */ +#define DEBUG_CTRL2_MUX_PLL_LOCK_STATUS 0x4 + +/* STAT5 register bits */ +#define VSTATUS_PLL_LOCK_STATUS_MASK BIT(0) + +/* QUSB PHY register values */ +#define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x03 +#define QUSB2PHY_PLL_CLOCK_INVERTERS 0x7c +#define QUSB2PHY_PLL_CMODE 0x80 +#define QUSB2PHY_PLL_LOCK_DELAY 0x0a +#define QUSB2PHY_PLL_DIGITAL_TIMERS_TWO 0x19 +#define QUSB2PHY_PLL_BIAS_CONTROL_1 0x40 +#define QUSB2PHY_PLL_BIAS_CONTROL_2 0x20 +#define QUSB2PHY_PWR_CTRL2 0x21 +#define QUSB2PHY_IMP_CTRL1 0x0 +#define QUSB2PHY_IMP_CTRL2 0x58 +#define QUSB2PHY_PORT_TUNE1 0x30 +#define QUSB2PHY_PORT_TUNE2 0x29 +#define QUSB2PHY_PORT_TUNE3 0xca +#define QUSB2PHY_PORT_TUNE4 0x04 +#define QUSB2PHY_PORT_TUNE5 0x03 +#define QUSB2PHY_CHG_CTRL2 0x0 + +/* USB3PHY_PCIE_USB3_PCS_PCS_STATUS bit */ +#define USB3_PCS_PHYSTATUS BIT(6) + +struct usb_board_data { + /* Register values going to override from the boardfile */ + u32 pll_bias_control_2; + u32 imp_ctrl1; + u32 port_tune1; +}; + +struct qmp_phy_init_tbl { + u32 *address; + u32 val; +}; + +void setup_usb_host0(struct usb_board_data *data); +void setup_usb_host1(struct usb_board_data *data); +/* Call reset_ before setup_ */ +void reset_usb0(void); +void reset_usb1(void); + +#endif /* _SDM845_USB_H_ */ diff --git a/src/soc/qualcomm/sdm845/usb.c b/src/soc/qualcomm/sdm845/usb.c new file mode 100644 index 0000000000..c7d65e6b42 --- /dev/null +++ b/src/soc/qualcomm/sdm845/usb.c @@ -0,0 +1,915 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2018 Qualcomm Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct usb_qusb_phy_dig { + u8 rsvd1[16]; + u32 pwr_ctrl1; + u32 pwr_ctrl2; + u8 rsvd2[8]; + u32 imp_ctrl1; + u32 imp_ctrl2; + u8 rsvd3[20]; + u32 chg_ctrl2; + u32 tune1; + u32 tune2; + u32 tune3; + u32 tune4; + u32 tune5; + u8 rsvd4[44]; + u32 debug_ctrl2; + u8 rsvd5[28]; + u32 debug_stat5; +}; +check_member(usb_qusb_phy_dig, tune5, 0x50); +check_member(usb_qusb_phy_dig, debug_ctrl2, 0x80); +check_member(usb_qusb_phy_dig, debug_stat5, 0xA0); + +struct usb_qusb_phy_pll { + u8 rsvd0[4]; + u32 analog_controls_two; + u8 rsvd1[36]; + u32 cmode; + u8 rsvd2[132]; + u32 dig_tim; + u8 rsvd3[204]; + u32 lock_delay; + u8 rsvd4[4]; + u32 clock_inverters; + u8 rsvd5[4]; + u32 bias_ctrl_1; + u32 bias_ctrl_2; +}; +check_member(usb_qusb_phy_pll, cmode, 0x2C); +check_member(usb_qusb_phy_pll, bias_ctrl_2, 0x198); +check_member(usb_qusb_phy_pll, dig_tim, 0xB4); + +/* Only for QMP V3 PHY - QSERDES COM registers */ +struct usb3_phy_qserdes_com_reg_layout { + u8 _reserved1[16]; + u32 com_ssc_en_center; + u32 com_ssc_adj_per1; + u32 com_ssc_adj_per2; + u32 com_ssc_per1; + u32 com_ssc_per2; + u32 com_ssc_step_size1; + u32 com_ssc_step_size2; + u8 _reserved2[8]; + u32 com_bias_en_clkbuflr_en; + u32 com_sys_clk_enable1; + u32 com_sys_clk_ctrl; + u32 com_sysclk_buf_enable; + u32 com_pll_en; + u32 com_pll_ivco; + u8 _reserved3[20]; + u32 com_cp_ctrl_mode0; + u8 _reserved4[4]; + u32 com_pll_rctrl_mode0; + u8 _reserved5[4]; + u32 com_pll_cctrl_mode0; + u8 _reserved6[12]; + u32 com_sysclk_en_sel; + u8 _reserved7[8]; + u32 com_resetsm_ctrl2; + u32 com_lock_cmp_en; + u32 com_lock_cmp_cfg; + u32 com_lock_cmp1_mode0; + u32 com_lock_cmp2_mode0; + u32 com_lock_cmp3_mode0; + u8 _reserved8[12]; + u32 com_dec_start_mode0; + u8 _reserved9[4]; + u32 com_div_frac_start1_mode0; + u32 com_div_frac_start2_mode0; + u32 com_div_frac_start3_mode0; + u8 _reserved10[20]; + u32 com_integloop_gain0_mode0; + u32 com_integloop_gain1_mode0; + u8 _reserved11[16]; + u32 com_vco_tune_map; + u32 com_vco_tune1_mode0; + u32 com_vco_tune2_mode0; + u8 _reserved12[60]; + u32 com_clk_select; + u32 com_hsclk_sel; + u8 _reserved13[8]; + u32 com_coreclk_div_mode0; + u8 _reserved14[8]; + u32 com_core_clk_en; + u32 com_c_ready_status; + u32 com_cmn_config; + u32 com_cmn_rate_override; + u32 com_svs_mode_clk_sel; +}; +check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_en_center, 0x010); +check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_adj_per1, 0x014); +check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_adj_per2, 0x018); +check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_per1, 0x01c); +check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_per2, 0x020); +check_member(usb3_phy_qserdes_com_reg_layout, com_bias_en_clkbuflr_en, 0x034); +check_member(usb3_phy_qserdes_com_reg_layout, com_pll_ivco, 0x048); +check_member(usb3_phy_qserdes_com_reg_layout, com_cp_ctrl_mode0, 0x060); +check_member(usb3_phy_qserdes_com_reg_layout, com_sysclk_en_sel, 0x080); +check_member(usb3_phy_qserdes_com_reg_layout, com_resetsm_ctrl2, 0x08c); +check_member(usb3_phy_qserdes_com_reg_layout, com_dec_start_mode0, 0x0b0); +check_member(usb3_phy_qserdes_com_reg_layout, com_div_frac_start1_mode0, 0x0b8); +check_member(usb3_phy_qserdes_com_reg_layout, com_integloop_gain0_mode0, 0x0d8); +check_member(usb3_phy_qserdes_com_reg_layout, com_vco_tune_map, 0x0f0); +check_member(usb3_phy_qserdes_com_reg_layout, com_clk_select, 0x138); +check_member(usb3_phy_qserdes_com_reg_layout, com_coreclk_div_mode0, 0x148); +check_member(usb3_phy_qserdes_com_reg_layout, com_core_clk_en, 0x154); +check_member(usb3_phy_qserdes_com_reg_layout, com_svs_mode_clk_sel, 0x164); + +/* Only for QMP V3 PHY - TX registers */ +struct usb3_phy_qserdes_tx_reg_layout { + u8 _reserved1[68]; + u32 tx_res_code_lane_offset_tx; + u32 tx_res_code_lane_offset_rx; + u8 _reserved2[20]; + u32 tx_highz_drvr_en; + u8 _reserved3[40]; + u32 tx_lane_mode_1; + u8 _reserved4[20]; + u32 tx_rcv_detect_lvl_2; +}; +check_member(usb3_phy_qserdes_tx_reg_layout, tx_res_code_lane_offset_tx, 0x044); +check_member(usb3_phy_qserdes_tx_reg_layout, tx_res_code_lane_offset_rx, 0x048); +check_member(usb3_phy_qserdes_tx_reg_layout, tx_highz_drvr_en, 0x060); +check_member(usb3_phy_qserdes_tx_reg_layout, tx_lane_mode_1, 0x08c); +check_member(usb3_phy_qserdes_tx_reg_layout, tx_rcv_detect_lvl_2, 0x0a4); + +/* Only for QMP V3 PHY - RX registers */ +struct usb3_phy_qserdes_rx_reg_layout { + u8 _reserved1[8]; + u32 rx_ucdr_fo_gain; + u32 rx_ucdr_so_gain_half; + u8 _reserved2[32]; + u32 rx_ucdr_fastlock_fo_gain; + u32 rx_ucdr_so_saturtn_and_en; + u8 _reserved3[12]; + u32 rx_ucdr_pi_cntrls; + u8 _reserved4[120]; + u32 rx_vga_cal_ctrl2; + u8 _reserved5[16]; + u32 rx_rx_equ_adap_ctrl2; + u32 rx_rx_equ_adap_ctrl3; + u32 rx_rx_equ_adap_ctrl4; + u8 _reserved6[24]; + u32 rx_rx_eq_offset_adap_ctrl1; + u32 rx_rx_offset_adap_ctrl2; + u32 rx_sigdet_enables; + u32 rx_sigdet_ctrl; + u8 _reserved7[4]; + u32 rx_sigdet_deglitch_ctrl; + u32 rx_rx_band; + u8 _reserved8[80]; + u32 rx_rx_mode_00; +}; +check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_fo_gain, 0x008); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_so_gain_half, 0x00c); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_fastlock_fo_gain, 0x030); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_so_saturtn_and_en, 0x034); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_pi_cntrls, 0x044); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_vga_cal_ctrl2, 0x0c0); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adap_ctrl2, 0x0d4); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adap_ctrl3, 0x0d8); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adap_ctrl4, 0x0dc); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_eq_offset_adap_ctrl1, 0x0f8); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_offset_adap_ctrl2, 0x0fc); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_sigdet_enables, 0x100); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_sigdet_ctrl, 0x104); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_sigdet_deglitch_ctrl, 0x10c); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_band, 0x110); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_00, 0x164); + +/* Only for QMP V3 PHY - PCS registers */ +struct usb3_phy_pcs_reg_layout { + u32 pcs_sw_reset; + u32 pcs_power_down_control; + u32 pcs_start_control; + u32 pcs_txmgn_v0; + u32 pcs_txmgn_v1; + u32 pcs_txmgn_v2; + u32 pcs_txmgn_v3; + u32 pcs_txmgn_v4; + u32 pcs_txmgn_ls; + u32 pcs_txdeemph_m6db_v0; + u32 pcs_txdeemph_m3p5db_v0; + u32 pcs_txdeemph_m6db_v1; + u32 pcs_txdeemph_m3p5db_v1; + u32 pcs_txdeemph_m6db_v2; + u32 pcs_txdeemph_m3p5db_v2; + u32 pcs_txdeemph_m6db_v3; + u32 pcs_txdeemph_m3p5db_v3; + u32 pcs_txdeemph_m6db_v4; + u32 pcs_txdeemph_m3p5db_v4; + u32 pcs_txdeemph_m6db_ls; + u32 pcs_txdeemph_m3p5db_ls; + u8 _reserved1[8]; + u32 pcs_rate_slew_cntrl; + u8 _reserved2[4]; + u32 pcs_power_state_config2; + u8 _reserved3[8]; + u32 pcs_rcvr_dtct_dly_p1u2_l; + u32 pcs_rcvr_dtct_dly_p1u2_h; + u32 pcs_rcvr_dtct_dly_u3_l; + u32 pcs_rcvr_dtct_dly_u3_h; + u32 pcs_lock_detect_config1; + u32 pcs_lock_detect_config2; + u32 pcs_lock_detect_config3; + u32 pcs_tsync_rsync_time; + u8 _reserved4[16]; + u32 pcs_pwrup_reset_dly_time_auxclk; + u8 _reserved5[12]; + u32 pcs_lfps_ecstart_eqtlock; + u8 _reserved6[4]; + u32 pcs_rxeqtraining_wait_time; + u32 pcs_rxeqtraining_run_time; + u8 _reserved7[4]; + u32 pcs_fll_ctrl1; + u32 pcs_fll_ctrl2; + u32 pcs_fll_cnt_val_l; + u32 pcs_fll_cnt_val_h_tol; + u32 pcs_fll_man_code; + u32 pcs_autonomous_mode_ctrl; + u8 _reserved8[152]; + u32 pcs_ready_status; + u8 _reserved9[96]; + u32 pcs_rx_sigdet_lvl; + u8 _reserved10[48]; + u32 pcs_refgen_req_config1; + u32 pcs_refgen_req_config2; +}; +check_member(usb3_phy_pcs_reg_layout, pcs_sw_reset, 0x000); +check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_v0, 0x00c); +check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_v1, 0x010); +check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_v2, 0x014); +check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_v3, 0x018); +check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_v4, 0x01c); +check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_ls, 0x020); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_v0, 0x024); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_v0, 0x028); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_v1, 0x02c); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_v1, 0x030); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_v2, 0x034); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_v2, 0x038); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_v3, 0x03c); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_v3, 0x040); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_v4, 0x044); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_v4, 0x048); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_ls, 0x04c); +check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_ls, 0x050); +check_member(usb3_phy_pcs_reg_layout, pcs_rate_slew_cntrl, 0x05c); +check_member(usb3_phy_pcs_reg_layout, pcs_power_state_config2, 0x064); +check_member(usb3_phy_pcs_reg_layout, pcs_rcvr_dtct_dly_p1u2_l, 0x070); +check_member(usb3_phy_pcs_reg_layout, pcs_rcvr_dtct_dly_p1u2_h, 0x074); +check_member(usb3_phy_pcs_reg_layout, pcs_rcvr_dtct_dly_u3_l, 0x078); +check_member(usb3_phy_pcs_reg_layout, pcs_rcvr_dtct_dly_u3_h, 0x07c); +check_member(usb3_phy_pcs_reg_layout, pcs_lock_detect_config1, 0x080); +check_member(usb3_phy_pcs_reg_layout, pcs_lock_detect_config2, 0x084); +check_member(usb3_phy_pcs_reg_layout, pcs_lock_detect_config3, 0x088); +check_member(usb3_phy_pcs_reg_layout, pcs_pwrup_reset_dly_time_auxclk, 0x0a0); +check_member(usb3_phy_pcs_reg_layout, pcs_rxeqtraining_wait_time, 0x0b8); +check_member(usb3_phy_pcs_reg_layout, pcs_fll_cnt_val_h_tol, 0x0d0); +check_member(usb3_phy_pcs_reg_layout, pcs_autonomous_mode_ctrl, 0x0d8); +check_member(usb3_phy_pcs_reg_layout, pcs_ready_status, 0x174); +check_member(usb3_phy_pcs_reg_layout, pcs_refgen_req_config2, 0x210); + +static struct usb3_phy_qserdes_com_reg_layout *const qserdes_com_reg_layout = + (void *)QMP_PHY_QSERDES_COM_REG_BASE; +static struct usb3_phy_qserdes_tx_reg_layout *const qserdes_tx_reg_layout = + (void *)QMP_PHY_QSERDES_TX_REG_BASE; +static struct usb3_phy_qserdes_rx_reg_layout *const qserdes_rx_reg_layout = + (void *)QMP_PHY_QSERDES_RX_REG_BASE; +static struct usb3_phy_pcs_reg_layout *const pcs_reg_layout = + (void *)QMP_PHY_PCS_REG_BASE; + +static struct usb3_phy_qserdes_com_reg_layout *const + uniphy_qserdes_com_reg_layout = + (void *)QMP_UNIPHY_QSERDES_COM_REG_BASE; +static struct usb3_phy_qserdes_tx_reg_layout + *const uniphy_qserdes_tx_reg_layout = + (void *)QMP_UNIPHY_QSERDES_TX_REG_BASE; +static struct usb3_phy_qserdes_rx_reg_layout + *const uniphy_qserdes_rx_reg_layout = + (void *)QMP_UNIPHY_QSERDES_RX_REG_BASE; +static struct usb3_phy_pcs_reg_layout *const uniphy_pcs_reg_layout = + (void *)QMP_UNIPHY_PCS_REG_BASE; + +struct usb_dwc3 { + u32 sbuscfg0; + u32 sbuscfg1; + u32 txthrcfg; + u32 rxthrcfg; + u32 ctl; + u32 pmsts; + u32 sts; + u32 uctl1; + u32 snpsid; + u32 gpio; + u32 uid; + u32 uctl; + u64 buserraddr; + u64 prtbimap; + u8 reserved1[32]; + u32 dbgfifospace; + u32 dbgltssm; + u32 dbglnmcc; + u32 dbgbmu; + u32 dbglspmux; + u32 dbglsp; + u32 dbgepinfo0; + u32 dbgepinfo1; + u64 prtbimap_hs; + u64 prtbimap_fs; + u8 reserved2[112]; + u32 usb2phycfg; + u8 reserved3[60]; + u32 usb2i2cctl; + u8 reserved4[60]; + u32 usb2phyacc; + u8 reserved5[60]; + u32 usb3pipectl; + u8 reserved6[60]; +}; +check_member(usb_dwc3, usb3pipectl, 0x1c0); + +static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = { + {&qserdes_com_reg_layout->com_pll_ivco, 0x07}, + {&qserdes_com_reg_layout->com_sysclk_en_sel, 0x14}, + {&qserdes_com_reg_layout->com_bias_en_clkbuflr_en, 0x08}, + {&qserdes_com_reg_layout->com_clk_select, 0x30}, + {&qserdes_com_reg_layout->com_sys_clk_ctrl, 0x02}, + {&qserdes_com_reg_layout->com_resetsm_ctrl2, 0x08}, + {&qserdes_com_reg_layout->com_cmn_config, 0x16}, + {&qserdes_com_reg_layout->com_svs_mode_clk_sel, 0x01}, + {&qserdes_com_reg_layout->com_hsclk_sel, 0x80}, + {&qserdes_com_reg_layout->com_dec_start_mode0, 0x82}, + {&qserdes_com_reg_layout->com_div_frac_start1_mode0, 0xab}, + {&qserdes_com_reg_layout->com_div_frac_start2_mode0, 0xea}, + {&qserdes_com_reg_layout->com_div_frac_start3_mode0, 0x02}, + {&qserdes_com_reg_layout->com_cp_ctrl_mode0, 0x06}, + {&qserdes_com_reg_layout->com_pll_rctrl_mode0, 0x16}, + {&qserdes_com_reg_layout->com_pll_cctrl_mode0, 0x36}, + {&qserdes_com_reg_layout->com_integloop_gain1_mode0, 0x00}, + {&qserdes_com_reg_layout->com_integloop_gain0_mode0, 0x3f}, + {&qserdes_com_reg_layout->com_vco_tune2_mode0, 0x01}, + {&qserdes_com_reg_layout->com_vco_tune1_mode0, 0xc9}, + {&qserdes_com_reg_layout->com_coreclk_div_mode0, 0x0a}, + {&qserdes_com_reg_layout->com_lock_cmp3_mode0, 0x00}, + {&qserdes_com_reg_layout->com_lock_cmp2_mode0, 0x34}, + {&qserdes_com_reg_layout->com_lock_cmp1_mode0, 0x15}, + {&qserdes_com_reg_layout->com_lock_cmp_en, 0x04}, + {&qserdes_com_reg_layout->com_core_clk_en, 0x00}, + {&qserdes_com_reg_layout->com_lock_cmp_cfg, 0x00}, + {&qserdes_com_reg_layout->com_vco_tune_map, 0x00}, + {&qserdes_com_reg_layout->com_sysclk_buf_enable, 0x0a}, + {&qserdes_com_reg_layout->com_ssc_en_center, 0x01}, + {&qserdes_com_reg_layout->com_ssc_per1, 0x31}, + {&qserdes_com_reg_layout->com_ssc_per2, 0x01}, + {&qserdes_com_reg_layout->com_ssc_adj_per1, 0x00}, + {&qserdes_com_reg_layout->com_ssc_adj_per2, 0x00}, + {&qserdes_com_reg_layout->com_ssc_step_size1, 0x85}, + {&qserdes_com_reg_layout->com_ssc_step_size2, 0x07}, +}; + +static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = { + {&qserdes_tx_reg_layout->tx_highz_drvr_en, 0x10}, + {&qserdes_tx_reg_layout->tx_rcv_detect_lvl_2, 0x12}, + {&qserdes_tx_reg_layout->tx_lane_mode_1, 0x16}, + {&qserdes_tx_reg_layout->tx_res_code_lane_offset_rx, 0x09}, + {&qserdes_tx_reg_layout->tx_res_code_lane_offset_tx, 0x06}, +}; + +static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = { + {&qserdes_rx_reg_layout->rx_ucdr_fastlock_fo_gain, 0x0b}, + {&qserdes_rx_reg_layout->rx_rx_equ_adap_ctrl2, 0x0f}, + {&qserdes_rx_reg_layout->rx_rx_equ_adap_ctrl3, 0x4e}, + {&qserdes_rx_reg_layout->rx_rx_equ_adap_ctrl4, 0x18}, + {&qserdes_rx_reg_layout->rx_rx_eq_offset_adap_ctrl1, 0x77}, + {&qserdes_rx_reg_layout->rx_rx_offset_adap_ctrl2, 0x80}, + {&qserdes_rx_reg_layout->rx_sigdet_ctrl, 0x03}, + {&qserdes_rx_reg_layout->rx_sigdet_deglitch_ctrl, 0x16}, + {&qserdes_rx_reg_layout->rx_ucdr_so_saturtn_and_en, 0x75}, + {&qserdes_rx_reg_layout->rx_ucdr_pi_cntrls, 0x80}, + {&qserdes_rx_reg_layout->rx_ucdr_fo_gain, 0x0a}, + {&qserdes_rx_reg_layout->rx_ucdr_so_gain_half, 0x06}, + {&qserdes_rx_reg_layout->rx_sigdet_enables, 0x00}, +}; + +static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = { + /* FLL settings */ + {&pcs_reg_layout->pcs_fll_ctrl2, 0x83}, + {&pcs_reg_layout->pcs_fll_cnt_val_l, 0x09}, + {&pcs_reg_layout->pcs_fll_cnt_val_h_tol, 0xa2}, + {&pcs_reg_layout->pcs_fll_man_code, 0x40}, + {&pcs_reg_layout->pcs_fll_ctrl1, 0x02}, + + /* Lock Det settings */ + {&pcs_reg_layout->pcs_lock_detect_config1, 0xd1}, + {&pcs_reg_layout->pcs_lock_detect_config2, 0x1f}, + {&pcs_reg_layout->pcs_lock_detect_config3, 0x47}, + {&pcs_reg_layout->pcs_power_state_config2, 0x1b}, + + {&pcs_reg_layout->pcs_rx_sigdet_lvl, 0xba}, + {&pcs_reg_layout->pcs_txmgn_v0, 0x9f}, + {&pcs_reg_layout->pcs_txmgn_v1, 0x9f}, + {&pcs_reg_layout->pcs_txmgn_v2, 0xb7}, + {&pcs_reg_layout->pcs_txmgn_v3, 0x4e}, + {&pcs_reg_layout->pcs_txmgn_v4, 0x65}, + {&pcs_reg_layout->pcs_txmgn_ls, 0x6b}, + {&pcs_reg_layout->pcs_txdeemph_m6db_v0, 0x15}, + {&pcs_reg_layout->pcs_txdeemph_m3p5db_v0, 0x0d}, + {&pcs_reg_layout->pcs_txdeemph_m6db_v1, 0x15}, + {&pcs_reg_layout->pcs_txdeemph_m3p5db_v1, 0x0d}, + {&pcs_reg_layout->pcs_txdeemph_m6db_v2, 0x15}, + {&pcs_reg_layout->pcs_txdeemph_m3p5db_v2, 0x0d}, + {&pcs_reg_layout->pcs_txdeemph_m6db_v3, 0x15}, + {&pcs_reg_layout->pcs_txdeemph_m3p5db_v3, 0x1d}, + {&pcs_reg_layout->pcs_txdeemph_m6db_v4, 0x15}, + {&pcs_reg_layout->pcs_txdeemph_m3p5db_v4, 0x0d}, + {&pcs_reg_layout->pcs_txdeemph_m6db_ls, 0x15}, + {&pcs_reg_layout->pcs_txdeemph_m3p5db_ls, 0x0d}, + {&pcs_reg_layout->pcs_rate_slew_cntrl, 0x02}, + {&pcs_reg_layout->pcs_pwrup_reset_dly_time_auxclk, 0x04}, + {&pcs_reg_layout->pcs_tsync_rsync_time, 0x44}, + {&pcs_reg_layout->pcs_rcvr_dtct_dly_p1u2_l, 0xe7}, + {&pcs_reg_layout->pcs_rcvr_dtct_dly_p1u2_h, 0x03}, + {&pcs_reg_layout->pcs_rcvr_dtct_dly_u3_l, 0x40}, + {&pcs_reg_layout->pcs_rcvr_dtct_dly_u3_h, 0x00}, + {&pcs_reg_layout->pcs_rxeqtraining_wait_time, 0x75}, + {&pcs_reg_layout->pcs_lfps_ecstart_eqtlock, 0x86}, + {&pcs_reg_layout->pcs_rxeqtraining_run_time, 0x13}, +}; + +static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_serdes_tbl[] = { + {&uniphy_qserdes_com_reg_layout->com_pll_ivco, 0x07}, + {&uniphy_qserdes_com_reg_layout->com_sysclk_en_sel, 0x14}, + {&uniphy_qserdes_com_reg_layout->com_bias_en_clkbuflr_en, 0x04}, + {&uniphy_qserdes_com_reg_layout->com_clk_select, 0x30}, + {&uniphy_qserdes_com_reg_layout->com_sys_clk_ctrl, 0x02}, + {&uniphy_qserdes_com_reg_layout->com_resetsm_ctrl2, 0x08}, + {&uniphy_qserdes_com_reg_layout->com_cmn_config, 0x06}, + {&uniphy_qserdes_com_reg_layout->com_svs_mode_clk_sel, 0x01}, + {&uniphy_qserdes_com_reg_layout->com_hsclk_sel, 0x80}, + {&uniphy_qserdes_com_reg_layout->com_dec_start_mode0, 0x82}, + {&uniphy_qserdes_com_reg_layout->com_div_frac_start1_mode0, 0xab}, + {&uniphy_qserdes_com_reg_layout->com_div_frac_start2_mode0, 0xea}, + {&uniphy_qserdes_com_reg_layout->com_div_frac_start3_mode0, 0x02}, + {&uniphy_qserdes_com_reg_layout->com_cp_ctrl_mode0, 0x06}, + {&uniphy_qserdes_com_reg_layout->com_pll_rctrl_mode0, 0x16}, + {&uniphy_qserdes_com_reg_layout->com_pll_cctrl_mode0, 0x36}, + {&uniphy_qserdes_com_reg_layout->com_integloop_gain1_mode0, 0x00}, + {&uniphy_qserdes_com_reg_layout->com_integloop_gain0_mode0, 0x3f}, + {&uniphy_qserdes_com_reg_layout->com_vco_tune2_mode0, 0x01}, + {&uniphy_qserdes_com_reg_layout->com_vco_tune1_mode0, 0xc9}, + {&uniphy_qserdes_com_reg_layout->com_coreclk_div_mode0, 0x0a}, + {&uniphy_qserdes_com_reg_layout->com_lock_cmp3_mode0, 0x00}, + {&uniphy_qserdes_com_reg_layout->com_lock_cmp2_mode0, 0x34}, + {&uniphy_qserdes_com_reg_layout->com_lock_cmp1_mode0, 0x15}, + {&uniphy_qserdes_com_reg_layout->com_lock_cmp_en, 0x04}, + {&uniphy_qserdes_com_reg_layout->com_core_clk_en, 0x00}, + {&uniphy_qserdes_com_reg_layout->com_lock_cmp_cfg, 0x00}, + {&uniphy_qserdes_com_reg_layout->com_vco_tune_map, 0x00}, + {&uniphy_qserdes_com_reg_layout->com_sysclk_buf_enable, 0x0a}, + {&uniphy_qserdes_com_reg_layout->com_ssc_en_center, 0x01}, + {&uniphy_qserdes_com_reg_layout->com_ssc_per1, 0x31}, + {&uniphy_qserdes_com_reg_layout->com_ssc_per2, 0x01}, + {&uniphy_qserdes_com_reg_layout->com_ssc_adj_per1, 0x00}, + {&uniphy_qserdes_com_reg_layout->com_ssc_adj_per2, 0x00}, + {&uniphy_qserdes_com_reg_layout->com_ssc_step_size1, 0x85}, + {&uniphy_qserdes_com_reg_layout->com_ssc_step_size2, 0x07}, +}; + +static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_tx_tbl[] = { + {&uniphy_qserdes_tx_reg_layout->tx_highz_drvr_en, 0x10}, + {&uniphy_qserdes_tx_reg_layout->tx_rcv_detect_lvl_2, 0x12}, + {&uniphy_qserdes_tx_reg_layout->tx_lane_mode_1, 0xc6}, + {&uniphy_qserdes_tx_reg_layout->tx_res_code_lane_offset_rx, 0x06}, + {&uniphy_qserdes_tx_reg_layout->tx_res_code_lane_offset_tx, 0x06}, +}; + +static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_rx_tbl[] = { + {&uniphy_qserdes_rx_reg_layout->rx_vga_cal_ctrl2, 0x0c}, + {&uniphy_qserdes_rx_reg_layout->rx_rx_mode_00, 0x50}, + {&uniphy_qserdes_rx_reg_layout->rx_ucdr_fastlock_fo_gain, 0x0b}, + {&uniphy_qserdes_rx_reg_layout->rx_rx_equ_adap_ctrl2, 0x0e}, + {&uniphy_qserdes_rx_reg_layout->rx_rx_equ_adap_ctrl3, 0x4e}, + {&uniphy_qserdes_rx_reg_layout->rx_rx_equ_adap_ctrl4, 0x18}, + {&uniphy_qserdes_rx_reg_layout->rx_rx_eq_offset_adap_ctrl1, 0x77}, + {&uniphy_qserdes_rx_reg_layout->rx_rx_offset_adap_ctrl2, 0x80}, + {&uniphy_qserdes_rx_reg_layout->rx_sigdet_ctrl, 0x03}, + {&uniphy_qserdes_rx_reg_layout->rx_sigdet_deglitch_ctrl, 0x1c}, + {&uniphy_qserdes_rx_reg_layout->rx_ucdr_so_saturtn_and_en, 0x75}, + {&uniphy_qserdes_rx_reg_layout->rx_ucdr_pi_cntrls, 0x80}, + {&uniphy_qserdes_rx_reg_layout->rx_ucdr_fo_gain, 0x0a}, + {&uniphy_qserdes_rx_reg_layout->rx_ucdr_so_gain_half, 0x06}, + {&uniphy_qserdes_rx_reg_layout->rx_sigdet_enables, 0x00}, +}; + +static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = { + /* FLL settings */ + {&uniphy_pcs_reg_layout->pcs_fll_ctrl2, 0x83}, + {&uniphy_pcs_reg_layout->pcs_fll_cnt_val_l, 0x09}, + {&uniphy_pcs_reg_layout->pcs_fll_cnt_val_h_tol, 0xa2}, + {&uniphy_pcs_reg_layout->pcs_fll_man_code, 0x40}, + {&uniphy_pcs_reg_layout->pcs_fll_ctrl1, 0x02}, + + /* Lock Det settings */ + {&uniphy_pcs_reg_layout->pcs_lock_detect_config1, 0xd1}, + {&uniphy_pcs_reg_layout->pcs_lock_detect_config2, 0x1f}, + {&uniphy_pcs_reg_layout->pcs_lock_detect_config3, 0x47}, + {&uniphy_pcs_reg_layout->pcs_power_state_config2, 0x1b}, + + {&uniphy_pcs_reg_layout->pcs_rx_sigdet_lvl, 0xba}, + {&uniphy_pcs_reg_layout->pcs_txmgn_v0, 0x9f}, + {&uniphy_pcs_reg_layout->pcs_txmgn_v1, 0x9f}, + {&uniphy_pcs_reg_layout->pcs_txmgn_v2, 0xb5}, + {&uniphy_pcs_reg_layout->pcs_txmgn_v3, 0x4c}, + {&uniphy_pcs_reg_layout->pcs_txmgn_v4, 0x64}, + {&uniphy_pcs_reg_layout->pcs_txmgn_ls, 0x6a}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m6db_v0, 0x15}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m3p5db_v0, 0x0d}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m6db_v1, 0x15}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m3p5db_v1, 0x0d}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m6db_v2, 0x15}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m3p5db_v2, 0x0d}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m6db_v3, 0x15}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m3p5db_v3, 0x1d}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m6db_v4, 0x15}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m3p5db_v4, 0x0d}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m6db_ls, 0x15}, + {&uniphy_pcs_reg_layout->pcs_txdeemph_m3p5db_ls, 0x0d}, + {&uniphy_pcs_reg_layout->pcs_rate_slew_cntrl, 0x02}, + {&uniphy_pcs_reg_layout->pcs_pwrup_reset_dly_time_auxclk, 0x04}, + {&uniphy_pcs_reg_layout->pcs_tsync_rsync_time, 0x44}, + {&uniphy_pcs_reg_layout->pcs_rcvr_dtct_dly_p1u2_l, 0xe7}, + {&uniphy_pcs_reg_layout->pcs_rcvr_dtct_dly_p1u2_h, 0x03}, + {&uniphy_pcs_reg_layout->pcs_rcvr_dtct_dly_u3_l, 0x40}, + {&uniphy_pcs_reg_layout->pcs_rcvr_dtct_dly_u3_h, 0x00}, + {&uniphy_pcs_reg_layout->pcs_rxeqtraining_wait_time, 0x75}, + {&uniphy_pcs_reg_layout->pcs_lfps_ecstart_eqtlock, 0x86}, + {&uniphy_pcs_reg_layout->pcs_rxeqtraining_run_time, 0x13}, + {&uniphy_pcs_reg_layout->pcs_refgen_req_config1, 0x21}, + {&uniphy_pcs_reg_layout->pcs_refgen_req_config2, 0x60}, +}; + +struct usb_dwc3_cfg { + struct usb_dwc3 *usb_host_dwc3; + struct usb_qusb_phy_pll *qusb_phy_pll; + struct usb_qusb_phy_dig *qusb_phy_dig; + /* Init sequence for QMP PHY blocks - serdes, tx, rx, pcs */ + const struct qmp_phy_init_tbl *serdes_tbl; + int serdes_tbl_num; + const struct qmp_phy_init_tbl *tx_tbl; + int tx_tbl_num; + const struct qmp_phy_init_tbl *rx_tbl; + int rx_tbl_num; + const struct qmp_phy_init_tbl *pcs_tbl; + int pcs_tbl_num; + struct usb3_phy_pcs_reg_layout *qmp_pcs_reg; + + u32 *usb3_bcr; + u32 *qusb2phy_bcr; + u32 *gcc_usb3phy_bcr_reg; + u32 *gcc_qmpphy_bcr_reg; + struct usb_board_data *board_data; + u32 efuse_offset; +}; + +static struct usb_dwc3_cfg usb_port0 = { + .usb_host_dwc3 = (void *)USB_HOST0_DWC3_BASE, + .qusb_phy_pll = (void *)QUSB_PRIM_PHY_BASE, + .qusb_phy_dig = (void *)QUSB_PRIM_PHY_DIG_BASE, + .serdes_tbl = qmp_v3_usb3_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), + .tx_tbl = qmp_v3_usb3_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), + .rx_tbl = qmp_v3_usb3_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), + .pcs_tbl = qmp_v3_usb3_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), + .qmp_pcs_reg = (void *)QMP_PHY_PCS_REG_BASE, + .usb3_bcr = &gcc->usb30_prim_bcr, + .qusb2phy_bcr = &gcc->qusb2phy_prim_bcr, + .gcc_usb3phy_bcr_reg = &gcc->usb3_dp_phy_prim_bcr, + .gcc_qmpphy_bcr_reg = &gcc->usb3_phy_prim_bcr, + .efuse_offset = 25, +}; +static struct usb_dwc3_cfg usb_port1 = { + .usb_host_dwc3 = (void *)USB_HOST1_DWC3_BASE, + .qusb_phy_pll = (void *)QUSB_SEC_PHY_BASE, + .qusb_phy_dig = (void *)QUSB_SEC_PHY_DIG_BASE, + .serdes_tbl = qmp_v3_usb3_uniphy_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_serdes_tbl), + .tx_tbl = qmp_v3_usb3_uniphy_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_tx_tbl), + .rx_tbl = qmp_v3_usb3_uniphy_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_rx_tbl), + .pcs_tbl = qmp_v3_usb3_uniphy_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_pcs_tbl), + .qmp_pcs_reg = (void *)QMP_UNIPHY_PCS_REG_BASE, + .usb3_bcr = &gcc->usb30_sec_bcr, + .qusb2phy_bcr = &gcc->qusb2phy_sec_bcr, + .gcc_usb3phy_bcr_reg = &gcc->usb3phy_phy_sec_bcr, + .gcc_qmpphy_bcr_reg = &gcc->usb3_phy_sec_bcr, + .efuse_offset = 30, +}; + +static struct qfprom_corr * const qfprom_corr_efuse = (void *)QFPROM_BASE; + +static void reset_usb(struct usb_dwc3_cfg *dwc3) +{ + /* Assert Core reset */ + clock_reset_bcr(dwc3->usb3_bcr, 1); + + /* Assert QUSB PHY reset */ + clock_reset_bcr(dwc3->qusb2phy_bcr, 1); + + /* Assert QMP PHY reset */ + clock_reset_bcr(dwc3->gcc_usb3phy_bcr_reg, 1); + clock_reset_bcr(dwc3->gcc_qmpphy_bcr_reg, 1); +} + +void reset_usb0(void) +{ + /* Before Resetting PHY, put Core in Reset */ + printk(BIOS_INFO, "Starting DWC3 and PHY resets for USB(0)\n"); + + reset_usb(&usb_port0); +} + +void reset_usb1(void) +{ + /* Before Resetting PHY, put Core in Reset */ + printk(BIOS_INFO, "Starting DWC3 and PHY resets for USB(1)\n"); + + reset_usb(&usb_port1); +} +/* + * Update board specific PHY tuning override values that specified from + * board file. + */ +static void qusb2_phy_override_phy_params(struct usb_dwc3_cfg *dwc3) +{ + /* Override preemphasis value */ + write32(&dwc3->qusb_phy_dig->tune1, + dwc3->board_data->port_tune1); + + /* Override BIAS_CTRL_2 to reduce the TX swing overshooting. */ + write32(&dwc3->qusb_phy_pll->bias_ctrl_2, + dwc3->board_data->pll_bias_control_2); + + /* Override IMP_RES_OFFSET value */ + write32(&dwc3->qusb_phy_dig->imp_ctrl1, + dwc3->board_data->imp_ctrl1); +} + +/* + * Fetches HS Tx tuning value from efuse register and sets the + * QUSB2PHY_PORT_TUNE1/2 register. + * For error case, skip setting the value and use the default value. + */ +static void qusb2_phy_set_tune_param(struct usb_dwc3_cfg *dwc3) +{ + /* + * Efuse registers 4 bit value specifies tuning for HSTX + * output current in TUNE1 Register. Hence Extract 4 bits from + * EFUSE at correct position. + */ + + const int efuse_bits = 4; + int bit_pos = dwc3->efuse_offset; + + u32 bit_mask = (1 << efuse_bits) - 1; + u32 tune_val = + (read32(&qfprom_corr_efuse->qusb_hstx_trim_lsb) >> bit_pos) + & bit_mask; + + if (bit_pos + efuse_bits > 32) { + /* + * Value split between two EFUSE registers, + * get the second part. + */ + int done_bits = 32 - bit_pos; + + bit_mask = (1 << (efuse_bits - done_bits)) - 1; + tune_val |= + (read32(&qfprom_corr_efuse->qusb_hstx_trim_msb) & + bit_mask) << done_bits; + } + + /* + * if efuse reg is updated (i.e non-zero) then use it to program + * tune parameters. + */ + if (tune_val) + clrsetbits_le32(&dwc3->qusb_phy_dig->tune1, + PORT_TUNE1_MASK, tune_val << 4); +} + +static void tune_phy(struct usb_dwc3_cfg *dwc3, struct usb_qusb_phy_dig *phy) +{ + write32(&phy->pwr_ctrl2, QUSB2PHY_PWR_CTRL2); + /* IMP_CTRL1: Control the impedance reduction */ + write32(&phy->imp_ctrl1, QUSB2PHY_IMP_CTRL1); + /* IMP_CTRL2: Impedance offset/mapping slope */ + write32(&phy->imp_ctrl2, QUSB2PHY_IMP_CTRL1); + write32(&phy->chg_ctrl2, QUSB2PHY_IMP_CTRL2); + /* + * TUNE1: Sets HS Impedance to approx 45 ohms + * then override with efuse value. + */ + write32(&phy->tune1, QUSB2PHY_PORT_TUNE1); + /* TUNE2: Tuning for HS Disconnect Level */ + write32(&phy->tune2, QUSB2PHY_PORT_TUNE2); + /* TUNE3: Tune squelch range */ + write32(&phy->tune3, QUSB2PHY_PORT_TUNE3); + /* TUNE4: Sets EOP_DLY(Squelch rising edge to linestate falling edge) */ + write32(&phy->tune4, QUSB2PHY_PORT_TUNE4); + write32(&phy->tune5, QUSB2PHY_PORT_TUNE5); + + if (dwc3->board_data) { + /* Override board specific PHY tuning values */ + qusb2_phy_override_phy_params(dwc3); + + /* Set efuse value for tuning the PHY */ + qusb2_phy_set_tune_param(dwc3); + } +} + +static void hs_qusb_phy_init(struct usb_dwc3_cfg *dwc3) +{ + /* PWR_CTRL: set the power down bit to disable the PHY */ + setbits_le32(&dwc3->qusb_phy_dig->pwr_ctrl1, POWER_DOWN); + + write32(&dwc3->qusb_phy_pll->analog_controls_two, + QUSB2PHY_PLL_ANALOG_CONTROLS_TWO); + write32(&dwc3->qusb_phy_pll->clock_inverters, + QUSB2PHY_PLL_CLOCK_INVERTERS); + write32(&dwc3->qusb_phy_pll->cmode, + QUSB2PHY_PLL_CMODE); + write32(&dwc3->qusb_phy_pll->lock_delay, + QUSB2PHY_PLL_LOCK_DELAY); + write32(&dwc3->qusb_phy_pll->dig_tim, + QUSB2PHY_PLL_DIGITAL_TIMERS_TWO); + write32(&dwc3->qusb_phy_pll->bias_ctrl_1, + QUSB2PHY_PLL_BIAS_CONTROL_1); + write32(&dwc3->qusb_phy_pll->bias_ctrl_2, + QUSB2PHY_PLL_BIAS_CONTROL_2); + + tune_phy(dwc3, dwc3->qusb_phy_dig); + + /* PWR_CTRL1: Clear the power down bit to enable the PHY */ + clrbits_le32(&dwc3->qusb_phy_dig->pwr_ctrl1, POWER_DOWN); + + write32(&dwc3->qusb_phy_dig->debug_ctrl2, + DEBUG_CTRL2_MUX_PLL_LOCK_STATUS); + + /* + * DEBUG_STAT5: wait for 160uS for PLL lock; + * vstatus[0] changes from 0 to 1. + */ + long lock_us = wait_us(160, read32(&dwc3->qusb_phy_dig->debug_stat5) & + VSTATUS_PLL_LOCK_STATUS_MASK); + if (!lock_us) + printk(BIOS_ERR, "ERROR: QUSB PHY PLL LOCK fails\n"); + else + printk(BIOS_DEBUG, "QUSB PHY initialized and locked in %ldus\n", + lock_us); +} + +static void qcom_qmp_phy_configure(const struct qmp_phy_init_tbl tbl[], + int num) +{ + int i; + const struct qmp_phy_init_tbl *t = tbl; + + if (!t) + return; + + for (i = 0; i < num; i++, t++) + write32(t->address, t->val); +} + +static void ss_qmp_phy_init(struct usb_dwc3_cfg *dwc3) +{ + /* power up USB3 PHY */ + write32(&dwc3->qmp_pcs_reg->pcs_power_down_control, 0x01); + + /* Serdes configuration */ + qcom_qmp_phy_configure(dwc3->serdes_tbl, dwc3->serdes_tbl_num); + /* Tx, Rx, and PCS configurations */ + qcom_qmp_phy_configure(dwc3->tx_tbl, dwc3->tx_tbl_num); + qcom_qmp_phy_configure(dwc3->rx_tbl, dwc3->rx_tbl_num); + qcom_qmp_phy_configure(dwc3->pcs_tbl, dwc3->pcs_tbl_num); + + /* perform software reset of PCS/Serdes */ + write32(&dwc3->qmp_pcs_reg->pcs_sw_reset, 0x00); + /* start PCS/Serdes to operation mode */ + write32(&dwc3->qmp_pcs_reg->pcs_start_control, 0x03); + + /* + * Wait for PHY initialization to be done + * PCS_STATUS: wait for 1ms for PHY STATUS; + * SW can continuously check for PHYSTATUS = 1.b0. + */ + long lock_us = wait_us(1000, + !(read32(&dwc3->qmp_pcs_reg->pcs_ready_status) & + USB3_PCS_PHYSTATUS)); + if (!lock_us) + printk(BIOS_ERR, "ERROR: QMP PHY PLL LOCK fails:\n"); + else + printk(BIOS_DEBUG, "QMP PHY initialized and locked in %ldus\n", + lock_us); +} + +static void setup_dwc3(struct usb_dwc3 *dwc3) +{ + /* core exits U1/U2/U3 only in PHY power state P1/P2/P3 respectively */ + clrsetbits_le32(&dwc3->usb3pipectl, + DWC3_GUSB3PIPECTL_DELAYP1TRANS, + DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX); + + /* + * Configure USB phy interface of DWC3 core. + * 1. Select UTMI+ PHY with 16-bit interface. + * 2. Set USBTRDTIM to the corresponding value + * according to the UTMI+ PHY interface. + */ + clrsetbits_le32(&dwc3->usb2phycfg, + (DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK | + DWC3_GUSB2PHYCFG_PHYIF_MASK), + (DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | + DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT))); + + clrsetbits_le32(&dwc3->ctl, (DWC3_GCTL_SCALEDOWN_MASK | + DWC3_GCTL_DISSCRAMBLE), + DWC3_GCTL_U2EXIT_LFPS | DWC3_GCTL_DSBLCLKGTNG); + + /* configure controller in Host mode */ + clrsetbits_le32(&dwc3->ctl, (DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)), + DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST)); + printk(BIOS_SPEW, "Configure USB in Host mode\n"); +} + +/* Initialization of DWC3 Core and PHY */ +static void setup_usb_host(struct usb_dwc3_cfg *dwc3, + struct usb_board_data *board_data) +{ + dwc3->board_data = board_data; + + /* Clear core reset. */ + clock_reset_bcr(dwc3->usb3_bcr, 0); + + /* Clear QUSB PHY reset. */ + clock_reset_bcr(dwc3->qusb2phy_bcr, 0); + + /* Initialize QUSB PHY */ + hs_qusb_phy_init(dwc3); + + /* Clear QMP PHY resets. */ + clock_reset_bcr(dwc3->gcc_usb3phy_bcr_reg, 0); + clock_reset_bcr(dwc3->gcc_qmpphy_bcr_reg, 0); + + /* Initialize QMP PHY */ + ss_qmp_phy_init(dwc3); + + setup_dwc3(dwc3->usb_host_dwc3); + + printk(BIOS_INFO, "DWC3 and PHY setup finished\n"); +} + +void setup_usb_host0(struct usb_board_data *board_data) +{ + printk(BIOS_INFO, "Setting up USB HOST0 controller.\n"); + setup_usb_host(&usb_port0, board_data); +} + +void setup_usb_host1(struct usb_board_data *board_data) +{ + printk(BIOS_INFO, "Setting up USB HOST1 controller.\n"); + setup_usb_host(&usb_port1, board_data); +} From 82d73e2d5a44bee097d02d41a450f5bfd703bd5b Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Tue, 30 Apr 2019 13:13:40 +0800 Subject: [PATCH 004/107] nb/intel/haswell: correct a typo in Kconfig Change-Id: I115e065ce11946b85571e7233203be68c1789d70 Signed-off-by: Joel Kitching Reviewed-on: https://review.coreboot.org/c/coreboot/+/32518 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner Reviewed-by: Angel Pons --- src/northbridge/intel/haswell/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/northbridge/intel/haswell/Kconfig b/src/northbridge/intel/haswell/Kconfig index 8c1e0b18f7..e1067c5949 100644 --- a/src/northbridge/intel/haswell/Kconfig +++ b/src/northbridge/intel/haswell/Kconfig @@ -37,7 +37,7 @@ config HASWELL_VBOOT_IN_BOOTBLOCK Haswell can either start verstage in a separate stage right after the bootblock has run or it can start it after romstage for compatibility reasons. - Haswell however uses a mrc.bin to initialse memory which + Haswell however uses a mrc.bin to initialize memory which needs to be located at a fixed offset. Therefore even with a separate verstage starting after the bootblock that same binary is used meaning a jump is made from RW to the RO region From aa0929d101ddfb9e64d8febd2bd31ce1037e62ff Mon Sep 17 00:00:00 2001 From: Gaggery Tsai Date: Tue, 8 Jan 2019 15:13:25 -0800 Subject: [PATCH 005/107] mb/google/poppy/variant/atlas: enable USB acpi Main objective for this change is to export the bluetooth reset gpio to the kernel for use in an rf-kill operation. To do so, we enable USB acpi and define all of the USB2 devices, which includes bluetooth's reset gpio information. BUG=b:122540489 BRANCH=None TEST=emerge-atlas coreboot chromeos-bootimage $cat sys/firmware/acpi/tables/SSDT > /tmp/ssdt.dat & retrieve ssdt.dat from DUT & $iasl -d ./ssdt.dat & check the HS03 node is with "reset-gpio" under _DSD object Change-Id: I411ef707782655361bd1b8ac2b914b8ae64defeb Signed-off-by: Gaggery Tsai Reviewed-on: https://review.coreboot.org/c/coreboot/+/30754 Tested-by: build bot (Jenkins) Reviewed-by: Nick Vaccaro Reviewed-by: Paul Menzel Reviewed-by: Caveh Jalali --- src/mainboard/google/poppy/Kconfig | 1 + .../google/poppy/variants/atlas/devicetree.cb | 25 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/mainboard/google/poppy/Kconfig b/src/mainboard/google/poppy/Kconfig index 419b10eb3d..b7f479f888 100644 --- a/src/mainboard/google/poppy/Kconfig +++ b/src/mainboard/google/poppy/Kconfig @@ -151,6 +151,7 @@ config VARIANT_SPECIFIC_OPTIONS_ATLAS select DRIVERS_I2C_MAX98373 select DRIVERS_I2C_DA7219 select DRIVERS_SPI_ACPI + select DRIVERS_USB_ACPI select EXCLUDE_NATIVE_SD_INTERFACE select MAINBOARD_HAS_SPI_TPM_CR50 select VARIANT_HAS_CAMERA_ACPI diff --git a/src/mainboard/google/poppy/variants/atlas/devicetree.cb b/src/mainboard/google/poppy/variants/atlas/devicetree.cb index ad79bcab0e..1ea28a0e5f 100644 --- a/src/mainboard/google/poppy/variants/atlas/devicetree.cb +++ b/src/mainboard/google/poppy/variants/atlas/devicetree.cb @@ -265,7 +265,30 @@ chip soc/intel/skylake device pci 00.0 on end # Host Bridge device pci 02.0 on end # Integrated Graphics Device device pci 13.0 off end # Integrated Sensor Hub - device pci 14.0 on end # USB xHCI + device pci 14.0 on + chip drivers/usb/acpi + register "desc" = ""Root Hub"" + register "type" = "UPC_TYPE_HUB" + device usb 0.0 on + chip drivers/usb/acpi + register "desc" = ""USB Type C Port 1"" + register "type" = "UPC_TYPE_C_USB2_SS_SWITCH" + device usb 2.0 on end + end + chip drivers/usb/acpi + register "desc" = ""Bluetooth"" + register "type" = "UPC_TYPE_INTERNAL" + register "reset_gpio" = "ACPI_GPIO_OUTPUT_ACTIVE_LOW(GPP_E2)" + device usb 2.2 on end + end + chip drivers/usb/acpi + register "desc" = ""USB Type C Port 2"" + register "type" = "UPC_TYPE_C_USB2_SS_SWITCH" + device usb 2.4 on end + end + end + end + end # USB xHCI device pci 14.1 on end # USB xDCI (OTG) device pci 14.2 on end # Thermal Subsystem device pci 15.0 on From b242de5bfc99ef2b63d21a9d1bd9f19bf79ee687 Mon Sep 17 00:00:00 2001 From: Nathan_chen Date: Tue, 30 Apr 2019 16:11:35 +0800 Subject: [PATCH 006/107] mb/google/arcada: Add settings for noise mitgation Enable acoustic noise mitgation for arcada platform, the slow slew rates for Ia and Gt are fast time dived by 8. BUG=b:131144464 TEST=waveform test and hardware validation result pass. Signed-off-by: nathan chen Change-Id: I395b2fc527705ab207325cfd7147e6af5f300fce Reviewed-on: https://review.coreboot.org/c/coreboot/+/32521 Tested-by: build bot (Jenkins) Reviewed-by: Lijian Zhao --- src/mainboard/google/sarien/variants/arcada/devicetree.cb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mainboard/google/sarien/variants/arcada/devicetree.cb b/src/mainboard/google/sarien/variants/arcada/devicetree.cb index cf64c4bb89..77bd82a64b 100644 --- a/src/mainboard/google/sarien/variants/arcada/devicetree.cb +++ b/src/mainboard/google/sarien/variants/arcada/devicetree.cb @@ -37,10 +37,10 @@ chip soc/intel/cannonlake register "tdp_pl2_override" = "51" register "Device4Enable" = "1" register "AcousticNoiseMitigation" = "1" - register "SlowSlewRateForIa" = "0" - register "SlowSlewRateForGt" = "0" + register "SlowSlewRateForIa" = "2" + register "SlowSlewRateForGt" = "2" register "SlowSlewRateForSa" = "0" - register "SlowSlewRateForFivr" = "0" + register "SlowSlewRateForFivr" = "2" # Enable eDP device register "DdiPortEdp" = "1" # Enable HPD for DDI ports B/C From 8c99a4859e7830fd1cac0b729fc29412cd773b75 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Fri, 3 May 2019 10:49:51 -0500 Subject: [PATCH 007/107] Makefile.inc: Update fsp submodule for all FSP platforms Rather than selectively update the fsp submodule based on FSP version or platform selection, update it when building for any FSP-enabled platform, so all have latest version available. Change-Id: If07d55828a1863623e04a4ecdd1514c3cb6d9c11 Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/32526 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- Makefile.inc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Makefile.inc b/Makefile.inc index fc04a16fad..a9aaaed783 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -196,14 +196,11 @@ ifeq ($(CONFIG_USE_BLOBS),y) # this is necessary because 3rdparty/blobs is update=none, and so is ignored # unless explicitly requested and enabled through --checkout forgetthis:=$(if $(GIT),$(shell git submodule update --init --checkout 3rdparty/blobs)) -ifeq ($(CONFIG_PLATFORM_USES_FSP2_0),y) +ifeq ($(CONFIG_PLATFORM_USES_FSP1_0)$(CONFIG_PLATFORM_USES_FSP1_1)$(CONFIG_PLATFORM_USES_FSP2_0),y) +# this is necessary because 3rdparty/fsp is update=none, and so is ignored +# unless explicitly requested and enabled through --checkout forgetthis:=$(if $(GIT),$(shell git submodule update --init --checkout 3rdparty/fsp)) endif -ifeq ($(CONFIG_PLATFORM_USES_FSP1_0),y) -ifeq ($(CONFIG_SOC_INTEL_FSP_BROADWELL_DE),y) -forgetthis:=$(if $(GIT),$(shell git submodule update --init --checkout 3rdparty/fsp)) -endif -endif endif UPDATED_SUBMODULES:=1 COREBOOT_EXPORTS += UPDATED_SUBMODULES From fd7440d23126a0133e2563849fceec55a772de80 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Tue, 23 Apr 2019 12:21:17 -0500 Subject: [PATCH 008/107] soc/intel/braswell: add default option to use public FSP The current Braswell FSP 1.1 header in vendorcode/intel, for which there is no publicly available FSP binary, contains silicon init UPDs which are not found in the publicly available header/binary in the FSP Github repo. This prevents new boards from being added which use the public Braswell FSP header/binary. To resolve this, move the UPDs not found in the public header from the soc's chip.c to ramstage.c for the boards which use them. Add a Kconfig option to use the current non-public FSP header and select it for boards which need it (google/cyan variants); set the public FSP option as the default. Use the Kconfig option to set FSP_HEADER_PATH to ensure the correct header is used. Test: build google/cyan and intel/strago using non-public and public FSP header/binaries respectively. Change-Id: I43cf18b98c844175a87b61fdbe4b0b24484e5702 Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/32381 Tested-by: build bot (Jenkins) Reviewed-by: Frans Hendriks Reviewed-by: Nico Huber --- src/mainboard/google/cyan/Kconfig | 1 + .../google/cyan/variants/celes/devicetree.cb | 6 ---- .../google/cyan/variants/celes/ramstage.c | 7 +++++ .../google/cyan/variants/kefka/Makefile.inc | 1 + .../google/cyan/variants/kefka/devicetree.cb | 7 ----- .../google/cyan/variants/kefka/ramstage.c | 30 +++++++++++++++++++ .../google/cyan/variants/relm/devicetree.cb | 7 ----- .../google/cyan/variants/relm/ramstage.c | 8 +++++ src/soc/intel/braswell/Kconfig | 14 +++++++++ src/soc/intel/braswell/Makefile.inc | 2 +- src/soc/intel/braswell/chip.c | 25 ---------------- src/soc/intel/braswell/chip.h | 5 ---- 12 files changed, 62 insertions(+), 51 deletions(-) create mode 100644 src/mainboard/google/cyan/variants/kefka/ramstage.c diff --git a/src/mainboard/google/cyan/Kconfig b/src/mainboard/google/cyan/Kconfig index b3c6790e57..aac14c06c3 100644 --- a/src/mainboard/google/cyan/Kconfig +++ b/src/mainboard/google/cyan/Kconfig @@ -16,6 +16,7 @@ config BOARD_GOOGLE_BASEBOARD_CYAN select HAVE_ACPI_RESUME select PCIEXP_L1_SUB_STATE if !BOARD_GOOGLE_CYAN select SYSTEM_TYPE_LAPTOP + select USE_GOOGLE_FSP if BOARD_GOOGLE_BASEBOARD_CYAN diff --git a/src/mainboard/google/cyan/variants/celes/devicetree.cb b/src/mainboard/google/cyan/variants/celes/devicetree.cb index 2e708af0d6..a1ab510810 100644 --- a/src/mainboard/google/cyan/variants/celes/devicetree.cb +++ b/src/mainboard/google/cyan/variants/celes/devicetree.cb @@ -73,12 +73,6 @@ chip soc/intel/braswell register "ISPEnable" = "0" # Disable IUNIT register "ISPPciDevConfig" = "3" register "PcdSdDetectChk" = "0" # Disable SD card detect - # Follow Intel recommendation to set BSW D-stepping PERPORTRXISET 2 (low strength) - register "D0Usb2Port0PerPortRXISet" = "2" - register "D0Usb2Port1PerPortRXISet" = "2" - register "D0Usb2Port2PerPortRXISet" = "2" - register "D0Usb2Port3PerPortRXISet" = "2" - register "D0Usb2Port4PerPortRXISet" = "2" # LPE audio codec settings register "lpe_codec_clk_src" = "LPE_CLK_SRC_XTAL" # 19.2MHz clock diff --git a/src/mainboard/google/cyan/variants/celes/ramstage.c b/src/mainboard/google/cyan/variants/celes/ramstage.c index 88b17f5da7..6c522a1d0c 100644 --- a/src/mainboard/google/cyan/variants/celes/ramstage.c +++ b/src/mainboard/google/cyan/variants/celes/ramstage.c @@ -19,29 +19,36 @@ void board_silicon_USB2_override(SILICON_INIT_UPD *params) { if (SocStepping() >= SocD0) { + //Follow Intel recommendation to set + //BSW D-stepping PERPORTRXISET 2 (low strength) params->Usb2Port0PerPortPeTxiSet = 7; params->Usb2Port0PerPortTxiSet = 0; params->Usb2Port0IUsbTxEmphasisEn = 3; params->Usb2Port0PerPortTxPeHalf = 1; + params->D0Usb2Port0PerPortRXISet = 2; params->Usb2Port1PerPortPeTxiSet = 7; params->Usb2Port1PerPortTxiSet = 0; params->Usb2Port1IUsbTxEmphasisEn = 3; params->Usb2Port1PerPortTxPeHalf = 1; + params->D0Usb2Port1PerPortRXISet = 2; params->Usb2Port2PerPortPeTxiSet = 7; params->Usb2Port2PerPortTxiSet = 6; params->Usb2Port2IUsbTxEmphasisEn = 3; params->Usb2Port2PerPortTxPeHalf = 1; + params->D0Usb2Port2PerPortRXISet = 2; params->Usb2Port3PerPortPeTxiSet = 7; params->Usb2Port3PerPortTxiSet = 6; params->Usb2Port3IUsbTxEmphasisEn = 3; params->Usb2Port3PerPortTxPeHalf = 1; + params->D0Usb2Port3PerPortRXISet = 2; params->Usb2Port4PerPortPeTxiSet = 7; params->Usb2Port4PerPortTxiSet = 6; params->Usb2Port4IUsbTxEmphasisEn = 3; params->Usb2Port4PerPortTxPeHalf = 1; + params->D0Usb2Port4PerPortRXISet = 2; } } diff --git a/src/mainboard/google/cyan/variants/kefka/Makefile.inc b/src/mainboard/google/cyan/variants/kefka/Makefile.inc index 5e94e715fa..7799e8d2b3 100644 --- a/src/mainboard/google/cyan/variants/kefka/Makefile.inc +++ b/src/mainboard/google/cyan/variants/kefka/Makefile.inc @@ -18,6 +18,7 @@ romstage-y += romstage.c romstage-y += spd_util.c ramstage-y += gpio.c +ramstage-y += ramstage.c SPD_BIN = $(obj)/spd.bin diff --git a/src/mainboard/google/cyan/variants/kefka/devicetree.cb b/src/mainboard/google/cyan/variants/kefka/devicetree.cb index 1ce056f32e..807dbcb2fe 100644 --- a/src/mainboard/google/cyan/variants/kefka/devicetree.cb +++ b/src/mainboard/google/cyan/variants/kefka/devicetree.cb @@ -80,13 +80,6 @@ chip soc/intel/braswell register "I2C5Frequency" = "1" register "I2C6Frequency" = "1" - # Follow Intel recommendation to set BSW D-stepping PERPORTRXISET 2 (low strength) - register "D0Usb2Port0PerPortRXISet" = "2" - register "D0Usb2Port1PerPortRXISet" = "2" - register "D0Usb2Port2PerPortRXISet" = "2" - register "D0Usb2Port3PerPortRXISet" = "2" - register "D0Usb2Port4PerPortRXISet" = "2" - # LPE audio codec settings register "lpe_codec_clk_src" = "LPE_CLK_SRC_XTAL" # 19.2MHz clock diff --git a/src/mainboard/google/cyan/variants/kefka/ramstage.c b/src/mainboard/google/cyan/variants/kefka/ramstage.c new file mode 100644 index 0000000000..d790708cce --- /dev/null +++ b/src/mainboard/google/cyan/variants/kefka/ramstage.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Intel Corporation + * + * 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; version 2 of the License. + * + * 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 + +void board_silicon_USB2_override(SILICON_INIT_UPD *params) +{ + if (SocStepping() >= SocD0) { + + //Follow Intel recommendation to set + //BSW D-stepping PERPORTRXISET 2 (low strength) + params->D0Usb2Port0PerPortRXISet = 2; + params->D0Usb2Port1PerPortRXISet = 2; + params->D0Usb2Port2PerPortRXISet = 2; + params->D0Usb2Port3PerPortRXISet = 2; + params->D0Usb2Port4PerPortRXISet = 2; + } +} diff --git a/src/mainboard/google/cyan/variants/relm/devicetree.cb b/src/mainboard/google/cyan/variants/relm/devicetree.cb index 65e662c5dd..e1bbb0ac5b 100644 --- a/src/mainboard/google/cyan/variants/relm/devicetree.cb +++ b/src/mainboard/google/cyan/variants/relm/devicetree.cb @@ -80,13 +80,6 @@ chip soc/intel/braswell register "I2C5Frequency" = "1" register "I2C6Frequency" = "1" - # Follow Intel recommendation to set BSW D-stepping PERPORTRXISET 2 (low strength) - register "D0Usb2Port0PerPortRXISet" = "2" - register "D0Usb2Port1PerPortRXISet" = "2" - register "D0Usb2Port2PerPortRXISet" = "2" - register "D0Usb2Port3PerPortRXISet" = "2" - register "D0Usb2Port4PerPortRXISet" = "2" - # LPE audio codec settings register "lpe_codec_clk_src" = "LPE_CLK_SRC_XTAL" # 19.2MHz clock diff --git a/src/mainboard/google/cyan/variants/relm/ramstage.c b/src/mainboard/google/cyan/variants/relm/ramstage.c index 27f9dfa241..3fbd2aebd9 100644 --- a/src/mainboard/google/cyan/variants/relm/ramstage.c +++ b/src/mainboard/google/cyan/variants/relm/ramstage.c @@ -36,5 +36,13 @@ void board_silicon_USB2_override(SILICON_INIT_UPD *params) params->Usb2Port3PerPortTxiSet = 0; params->Usb2Port3IUsbTxEmphasisEn = 2; params->Usb2Port3PerPortTxPeHalf = 1; + + //Follow Intel recommendation to set + //BSW D-stepping PERPORTRXISET 2 (low strength) + params->D0Usb2Port0PerPortRXISet = 2; + params->D0Usb2Port1PerPortRXISet = 2; + params->D0Usb2Port2PerPortRXISet = 2; + params->D0Usb2Port3PerPortRXISet = 2; + params->D0Usb2Port4PerPortRXISet = 2; } } diff --git a/src/soc/intel/braswell/Kconfig b/src/soc/intel/braswell/Kconfig index a0c07084b8..ed5c9728a3 100644 --- a/src/soc/intel/braswell/Kconfig +++ b/src/soc/intel/braswell/Kconfig @@ -135,4 +135,18 @@ config DISABLE_HPET Enable this to disable the HPET support Solves the Linux MP-BIOS bug timer not connected. +config USE_GOOGLE_FSP + bool + help + Select this to use Google's custom Braswell FSP header/binary + instead of the public release on Github. Only google/cyan + variants require this; all other boards should use the public release. + +config FSP_HEADER_PATH + string + default "$(src)/vendorcode/intel/fsp/fsp1_1/braswell" if USE_GOOGLE_FSP + default "3rdparty/fsp/BraswellFspBinPkg/Include/" + help + Location of FSP header file FspUpdVpd.h + endif diff --git a/src/soc/intel/braswell/Makefile.inc b/src/soc/intel/braswell/Makefile.inc index a538f7daff..a7ed4c5388 100644 --- a/src/soc/intel/braswell/Makefile.inc +++ b/src/soc/intel/braswell/Makefile.inc @@ -56,7 +56,7 @@ smm-y += tsc_freq.c CPPFLAGS_common += -I$(src)/soc/intel/braswell/ CPPFLAGS_common += -I$(src)/soc/intel/braswell/include -CPPFLAGS_common += -I$(src)/vendorcode/intel/fsp/fsp1_1/braswell +CPPFLAGS_common += -I$(call strip_quotes,$(CONFIG_FSP_HEADER_PATH)) CPPFLAGS_common += -I3rdparty/blobs/mainboard/$(MAINBOARDDIR) diff --git a/src/soc/intel/braswell/chip.c b/src/soc/intel/braswell/chip.c index 4be13cdea3..900b2f33fd 100644 --- a/src/soc/intel/braswell/chip.c +++ b/src/soc/intel/braswell/chip.c @@ -129,36 +129,26 @@ void soc_silicon_init_params(SILICON_INIT_UPD *params) params->Usb2Port0PerPortTxiSet = config->Usb2Port0PerPortTxiSet; params->Usb2Port0IUsbTxEmphasisEn = config->Usb2Port0IUsbTxEmphasisEn; params->Usb2Port0PerPortTxPeHalf = config->Usb2Port0PerPortTxPeHalf; - if (config->D0Usb2Port0PerPortRXISet != 0) - params->D0Usb2Port0PerPortRXISet = config->D0Usb2Port0PerPortRXISet; params->Usb2Port1PerPortPeTxiSet = config->Usb2Port1PerPortPeTxiSet; params->Usb2Port1PerPortTxiSet = config->Usb2Port1PerPortTxiSet; params->Usb2Port1IUsbTxEmphasisEn = config->Usb2Port1IUsbTxEmphasisEn; params->Usb2Port1PerPortTxPeHalf = config->Usb2Port1PerPortTxPeHalf; - if (config->D0Usb2Port1PerPortRXISet != 0) - params->D0Usb2Port1PerPortRXISet = config->D0Usb2Port1PerPortRXISet; params->Usb2Port2PerPortPeTxiSet = config->Usb2Port2PerPortPeTxiSet; params->Usb2Port2PerPortTxiSet = config->Usb2Port2PerPortTxiSet; params->Usb2Port2IUsbTxEmphasisEn = config->Usb2Port2IUsbTxEmphasisEn; params->Usb2Port2PerPortTxPeHalf = config->Usb2Port2PerPortTxPeHalf; - if (config->D0Usb2Port2PerPortRXISet != 0) - params->D0Usb2Port2PerPortRXISet = config->D0Usb2Port2PerPortRXISet; params->Usb2Port3PerPortPeTxiSet = config->Usb2Port3PerPortPeTxiSet; params->Usb2Port3PerPortTxiSet = config->Usb2Port3PerPortTxiSet; params->Usb2Port3IUsbTxEmphasisEn = config->Usb2Port3IUsbTxEmphasisEn; params->Usb2Port3PerPortTxPeHalf = config->Usb2Port3PerPortTxPeHalf; - if (config->D0Usb2Port3PerPortRXISet != 0) - params->D0Usb2Port3PerPortRXISet = config->D0Usb2Port3PerPortRXISet; params->Usb2Port4PerPortPeTxiSet = config->Usb2Port4PerPortPeTxiSet; params->Usb2Port4PerPortTxiSet = config->Usb2Port4PerPortTxiSet; params->Usb2Port4IUsbTxEmphasisEn = config->Usb2Port4IUsbTxEmphasisEn; params->Usb2Port4PerPortTxPeHalf = config->Usb2Port4PerPortTxPeHalf; - if (config->D0Usb2Port4PerPortRXISet != 0) - params->D0Usb2Port4PerPortRXISet = config->D0Usb2Port4PerPortRXISet; params->Usb3Lane0Ow2tapgen2deemph3p5 = config->Usb3Lane0Ow2tapgen2deemph3p5; @@ -266,9 +256,6 @@ void soc_display_silicon_init_params(const SILICON_INIT_UPD *old, fsp_display_upd_value("Usb2Port0PerPortTxPeHalf", 1, old->Usb2Port0PerPortTxPeHalf, new->Usb2Port0PerPortTxPeHalf); - fsp_display_upd_value("D0Usb2Port0PerPortRXISet", 1, - old->D0Usb2Port0PerPortRXISet, - new->D0Usb2Port0PerPortRXISet); fsp_display_upd_value("Usb2Port1PerPortPeTxiSet", 1, old->Usb2Port1PerPortPeTxiSet, new->Usb2Port1PerPortPeTxiSet); @@ -281,9 +268,6 @@ void soc_display_silicon_init_params(const SILICON_INIT_UPD *old, fsp_display_upd_value("Usb2Port1PerPortTxPeHalf", 1, old->Usb2Port1PerPortTxPeHalf, new->Usb2Port1PerPortTxPeHalf); - fsp_display_upd_value("D0Usb2Port1PerPortRXISet", 1, - old->D0Usb2Port1PerPortRXISet, - new->D0Usb2Port1PerPortRXISet); fsp_display_upd_value("Usb2Port2PerPortPeTxiSet", 1, old->Usb2Port2PerPortPeTxiSet, new->Usb2Port2PerPortPeTxiSet); @@ -296,9 +280,6 @@ void soc_display_silicon_init_params(const SILICON_INIT_UPD *old, fsp_display_upd_value("Usb2Port2PerPortTxPeHalf", 1, old->Usb2Port2PerPortTxPeHalf, new->Usb2Port2PerPortTxPeHalf); - fsp_display_upd_value("D0Usb2Port2PerPortRXISet", 1, - old->D0Usb2Port2PerPortRXISet, - new->D0Usb2Port2PerPortRXISet); fsp_display_upd_value("Usb2Port3PerPortPeTxiSet", 1, old->Usb2Port3PerPortPeTxiSet, new->Usb2Port3PerPortPeTxiSet); @@ -311,9 +292,6 @@ void soc_display_silicon_init_params(const SILICON_INIT_UPD *old, fsp_display_upd_value("Usb2Port3PerPortTxPeHalf", 1, old->Usb2Port3PerPortTxPeHalf, new->Usb2Port3PerPortTxPeHalf); - fsp_display_upd_value("D0Usb2Port3PerPortRXISet", 1, - old->D0Usb2Port3PerPortRXISet, - new->D0Usb2Port3PerPortRXISet); fsp_display_upd_value("Usb2Port4PerPortPeTxiSet", 1, old->Usb2Port4PerPortPeTxiSet, new->Usb2Port4PerPortPeTxiSet); @@ -326,9 +304,6 @@ void soc_display_silicon_init_params(const SILICON_INIT_UPD *old, fsp_display_upd_value("Usb2Port4PerPortTxPeHalf", 1, old->Usb2Port4PerPortTxPeHalf, new->Usb2Port4PerPortTxPeHalf); - fsp_display_upd_value("D0Usb2Port4PerPortRXISet", 1, - old->D0Usb2Port4PerPortRXISet, - new->D0Usb2Port4PerPortRXISet); fsp_display_upd_value("Usb3Lane0Ow2tapgen2deemph3p5", 1, old->Usb3Lane0Ow2tapgen2deemph3p5, new->Usb3Lane0Ow2tapgen2deemph3p5); diff --git a/src/soc/intel/braswell/chip.h b/src/soc/intel/braswell/chip.h index 4afaf44417..bb06dd595a 100644 --- a/src/soc/intel/braswell/chip.h +++ b/src/soc/intel/braswell/chip.h @@ -172,11 +172,6 @@ struct soc_intel_braswell_config { UINT8 I2C4Frequency; UINT8 I2C5Frequency; UINT8 I2C6Frequency; - UINT8 D0Usb2Port0PerPortRXISet; /*setting for D0 stepping SOC*/ - UINT8 D0Usb2Port1PerPortRXISet; /*setting for D0 stepping SOC*/ - UINT8 D0Usb2Port2PerPortRXISet; /*setting for D0 stepping SOC*/ - UINT8 D0Usb2Port3PerPortRXISet; /*setting for D0 stepping SOC*/ - UINT8 D0Usb2Port4PerPortRXISet; /*setting for D0 stepping SOC*/ }; extern struct chip_operations soc_intel_braswell_ops; From 61309e39b3c4545f47c9107a0e0ddaedef854505 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Tue, 23 Apr 2019 12:21:17 -0500 Subject: [PATCH 009/107] drivers/fsp 1.1: clean up Kconfig options Now that support has been added for using the public FSP repo for Braswell platform, clean up Kconfig options and set sane defaults when using it. The following changes have been made: - add option to use the 3rdparty/fsp repo for Braswell platform - reorder FSP 1.1 Kconfig entries for improved flow/readability - set the default path for the FSP binary based on use of FSP repo and platform - set the CBFS location for the FSP binary based on platform Change-Id: Ie2f732bf0ac4d4551908caa56360b8bb2869b4c7 Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/32535 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/drivers/intel/fsp1_1/Kconfig | 40 +++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/drivers/intel/fsp1_1/Kconfig b/src/drivers/intel/fsp1_1/Kconfig index 2575577ba4..a8658ec7e6 100644 --- a/src/drivers/intel/fsp1_1/Kconfig +++ b/src/drivers/intel/fsp1_1/Kconfig @@ -25,8 +25,14 @@ if PLATFORM_USES_FSP1_1 comment "Intel FSP 1.1" +config FSP_USE_REPO + bool "Use FSP binary from 3rdparty/fsp repo" + select HAVE_FSP_BIN + depends on SOC_INTEL_BRASWELL && !USE_GOOGLE_FSP + default y + config HAVE_FSP_BIN - bool "Should the Intel FSP binary be added to the flash image" + bool "Add Intel FSP binary to flash image" help Select this option to add an Intel FSP binary to the resulting coreboot image. @@ -34,6 +40,25 @@ config HAVE_FSP_BIN Note: Without this binary, coreboot builds relying on the FSP will not boot +config FSP_FILE + string + prompt "Intel FSP binary path and filename" if !FSP_USE_REPO + depends on HAVE_FSP_BIN + default "3rdparty/fsp/BraswellFspBinPkg/FspBin/BSWFSP.fd" if FSP_USE_REPO + default "" + help + The path and filename of the Intel FSP binary for this platform. + +config FSP_LOC + hex "Intel FSP Binary location in CBFS" + default 0xfff6e000 if SOC_INTEL_BRASWELL && USE_GOOGLE_FSP + default 0xfff20000 if SOC_INTEL_BRASWELL + default 0xffee0000 if SOC_INTEL_SKYLAKE + help + The location in CBFS that the FSP is located. This must match the + value that is set in the FSP binary. If the FSP needs to be moved, + rebase the FSP with Intel's BCT (tool). + config CPU_MICROCODE_CBFS_LEN hex "Microcode update region length in bytes" default 0x0 @@ -47,19 +72,6 @@ config CPU_MICROCODE_CBFS_LOC The location (base address) in CBFS that contains the microcode update binary. -config FSP_FILE - string "Intel FSP binary path and filename" - help - The path and filename of the Intel FSP binary for this platform. - -config FSP_LOC - hex "Intel FSP Binary location in CBFS" - default 0xffee0000 - help - The location in CBFS that the FSP is located. This must match the - value that is set in the FSP binary. If the FSP needs to be moved, - rebase the FSP with Intel's BCT (tool). - config DISPLAY_HOBS bool "Display hand-off-blocks (HOBs)" default n From 101098c41a047184e3eceabca2c1baa11141f36e Mon Sep 17 00:00:00 2001 From: T Michael Turney Date: Tue, 1 May 2018 15:59:37 -0700 Subject: [PATCH 010/107] sdm845: Combine BB with QC-Sec for ROM boot TEST=build & run Change-Id: I222a56f1c9b74856a1e1ff8132bab5e041672c5d Signed-off-by: T Michael Turney Reviewed-on: https://review.coreboot.org/c/coreboot/+/25207 Reviewed-by: Julius Werner Tested-by: build bot (Jenkins) --- src/soc/qualcomm/ipq40xx/Kconfig | 2 +- src/soc/qualcomm/ipq40xx/mbn_header.h | 2 +- src/soc/qualcomm/ipq806x/Makefile.inc | 4 +- src/soc/qualcomm/ipq806x/mbn_header.h | 2 +- util/{ipqheader => qualcomm}/createxbl.py | 33 ++- util/{ipqheader => qualcomm}/ipqheader.py | 0 util/{ipqheader => qualcomm}/mbn_tools.py | 13 +- util/{ipqheader => qualcomm}/mbncat.py | 0 util/qualcomm/qgpt.py | 234 ++++++++++++++++++++++ 9 files changed, 276 insertions(+), 14 deletions(-) rename util/{ipqheader => qualcomm}/createxbl.py (96%) rename util/{ipqheader => qualcomm}/ipqheader.py (100%) rename util/{ipqheader => qualcomm}/mbn_tools.py (99%) rename util/{ipqheader => qualcomm}/mbncat.py (100%) create mode 100755 util/qualcomm/qgpt.py diff --git a/src/soc/qualcomm/ipq40xx/Kconfig b/src/soc/qualcomm/ipq40xx/Kconfig index 72e05faf22..90744d5285 100644 --- a/src/soc/qualcomm/ipq40xx/Kconfig +++ b/src/soc/qualcomm/ipq40xx/Kconfig @@ -47,7 +47,7 @@ config SBL_ELF config SBL_UTIL_PATH depends on USE_BLOBS string "Path for utils to combine SBL_ELF and bootblock" - default "util/ipqheader" + default "util/qualcomm" help Path for utils to combine SBL_ELF and bootblock diff --git a/src/soc/qualcomm/ipq40xx/mbn_header.h b/src/soc/qualcomm/ipq40xx/mbn_header.h index cedcf12584..a48de1c883 100644 --- a/src/soc/qualcomm/ipq40xx/mbn_header.h +++ b/src/soc/qualcomm/ipq40xx/mbn_header.h @@ -18,7 +18,7 @@ #include -/* QCA firmware blob header gleaned from util/ipqheader/ipqheader.py */ +/* QCA firmware blob header gleaned from util/qualcomm/ipqheader.py */ struct mbn_header { u32 mbn_type; diff --git a/src/soc/qualcomm/ipq806x/Makefile.inc b/src/soc/qualcomm/ipq806x/Makefile.inc index 8a428b2f0d..1fd134a7b3 100644 --- a/src/soc/qualcomm/ipq806x/Makefile.inc +++ b/src/soc/qualcomm/ipq806x/Makefile.inc @@ -62,14 +62,14 @@ ifeq ($(CONFIG_USE_BLOBS),y) # Add MBN header to allow SBL3 to start coreboot bootblock $(objcbfs)/bootblock.mbn: $(objcbfs)/bootblock.raw.bin @printf " ADD MBN $(subst $(obj)/,,$(@))\n" - ./util/ipqheader/ipqheader.py $(call loadaddr,bootblock) $< $@.tmp + ./util/qualcomm/ipqheader.py $(call loadaddr,bootblock) $< $@.tmp @mv $@.tmp $@ # Create a complete bootblock which will start up the system $(objcbfs)/bootblock.bin: $(call strip_quotes,$(CONFIG_SBL_BLOB)) \ $(objcbfs)/bootblock.mbn @printf " MBNCAT $(subst $(obj)/,,$(@))\n" - @util/ipqheader/mbncat.py -o $@.tmp $^ + @util/qualcomm/mbncat.py -o $@.tmp $^ @mv $@.tmp $@ endif diff --git a/src/soc/qualcomm/ipq806x/mbn_header.h b/src/soc/qualcomm/ipq806x/mbn_header.h index 1e6a32f732..c7b38d3a81 100644 --- a/src/soc/qualcomm/ipq806x/mbn_header.h +++ b/src/soc/qualcomm/ipq806x/mbn_header.h @@ -18,7 +18,7 @@ #include -/* Qualcomm firmware blob header gleaned from util/ipqheader/ipqheader.py */ +/* Qualcomm firmware blob header gleaned from util/qualcomm/ipqheader.py */ struct mbn_header { u32 mbn_type; diff --git a/util/ipqheader/createxbl.py b/util/qualcomm/createxbl.py similarity index 96% rename from util/ipqheader/createxbl.py rename to util/qualcomm/createxbl.py index 1efd8bac0c..4a218544c0 100755 --- a/util/ipqheader/createxbl.py +++ b/util/qualcomm/createxbl.py @@ -6,7 +6,7 @@ # GENERAL DESCRIPTION # Concatentates XBL segments into one ELF image # -# Copyright (c) 2016, The Linux Foundation. All rights reserved. +# Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -44,6 +44,7 @@ # # when who what, where, why # -------- --- ------------------------------------------------------ +# 03/26/18 tv Added -e to enable extended MBNV5 support # 09/04/15 et Added -x and -d to embed xbl_sec ELF # 02/11/15 ck Fixed missing elf type check in ZI OOB feature # 11/04/14 ck Updated calls to mbn_tools functions @@ -205,6 +206,11 @@ def main(): else: zi_oob_enabled = True + if options.elf_inp_xbl_sec: + is_ext_mbn_v5 = True + else: + is_ext_mbn_v5 = False + mbn_type = 'elf' header_format = 'reg' @@ -237,7 +243,8 @@ def main(): is_elf2_64_bit, is_elf_xbl_sec_64_bit, is_out_elf_64_bit, - zi_oob_enabled) + zi_oob_enabled, + is_ext_mbn_v5) # Hash the image if user did not explicitly say not to @@ -262,6 +269,7 @@ def main(): target_hash, target_hash_hd, image_header_secflag, + is_ext_mbn_v5, elf_file_name = source_elf) if rv: raise RuntimeError, "Failed to create image header for hash segment" @@ -296,7 +304,8 @@ def merge_elfs(env, is_elf2_64_bit, is_elf_xbl_sec_64_bit, is_out_elf_64_bit, - zi_oob_enabled): + zi_oob_enabled, + is_ext_mbn_v5): [elf_header1, phdr_table1] = \ mbn_tools.preprocess_elf_file(elf_in_file_name1) @@ -654,7 +663,12 @@ def merge_elfs(env, new_phdr.p_paddr = phys_virt_addr new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec) new_phdr.p_memsz = new_phdr.p_filesz - new_phdr.p_flags = 0x5 + if is_ext_mbn_v5 == True: + new_phdr.p_flags = (0x5 | + (mbn_tools.MI_PBT_XBL_SEC_SEGMENT << + mbn_tools.MI_PBT_FLAG_SEGMENT_TYPE_SHIFT)); + else: + new_phdr.p_flags = 0x5 new_phdr.p_align = 0x1000 else: # Converting from 64 to 32 elf requires data size validation @@ -663,18 +677,23 @@ def merge_elfs(env, new_phdr = mbn_tools.Elf32_Phdr('\0' * ELF32_PHDR_SIZE) new_phdr.p_type = 0x1 # new_phdr.p_offset = segment_offset - new_phdr.p_flags = 0x5 + if is_ext_mbn_v5 == True: + new_phdr.p_flags = (0x5 | + (mbn_tools.MI_PBT_XBL_SEC_SEGMENT << + mbn_tools.MI_PBT_FLAG_SEGMENT_TYPE_SHIFT)); + else: + new_phdr.p_flags = 0x5 new_phdr.p_align = 0x1000 if phys_virt_addr > 0xFFFFFFFF: if zi_oob_enabled == False or curr_phdr.p_filesz != 0: - print "ERROR: File xbl_sec VAddr or PAddr is too large for conversion." + print "ERROR: File xbl_sec VAddr or PAddr is too big for conversion." exit() new_phdr.p_vaddr = phys_virt_addr new_phdr.p_paddr = phys_virt_addr if os.path.getsize(elf_in_file_xbl_sec) > 0xFFFFFFFF: - print "ERROR: File xbl_sec Filesz is too large for conversion." + print "ERROR: File xbl_sec Filesz is too big for conversion." exit() new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec) new_phdr.p_memsz = new_phdr.p_filesz diff --git a/util/ipqheader/ipqheader.py b/util/qualcomm/ipqheader.py similarity index 100% rename from util/ipqheader/ipqheader.py rename to util/qualcomm/ipqheader.py diff --git a/util/ipqheader/mbn_tools.py b/util/qualcomm/mbn_tools.py similarity index 99% rename from util/ipqheader/mbn_tools.py rename to util/qualcomm/mbn_tools.py index c66afda7b5..12dc210cac 100755 --- a/util/ipqheader/mbn_tools.py +++ b/util/qualcomm/mbn_tools.py @@ -6,7 +6,7 @@ # GENERAL DESCRIPTION # Contains all MBN Utilities for image generation # -# Copyright (c) 2016, The Linux Foundation. All rights reserved. +# Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -41,6 +41,7 @@ # # when who what, where, why # -------- --- --------------------------------------------------------- +# 03/22/18 thiru Added support for extended MBNV5. # 06/06/13 yliong CR 497042: Signed and encrypted image is corrupted. MRC features. # 03/18/13 dhaval Add support for hashing elf segments with SHA256 and # sync up to mpss, adsp mbn-tools @@ -166,6 +167,7 @@ MI_PBT_HASH_SEGMENT = 0x2 MI_PBT_BOOT_SEGMENT = 0x3 MI_PBT_L4BSP_SEGMENT = 0x4 MI_PBT_SWAPPED_SEGMENT = 0x5 +MI_PBT_XBL_SEC_SEGMENT = 0x5 MI_PBT_SWAP_POOL_SEGMENT = 0x6 MI_PBT_PHDR_SEGMENT = 0x7 @@ -902,6 +904,7 @@ def image_header(env, gen_dict, code_file_name, output_file_name, secure_type, + is_ext_mbn_v5, header_format = 'reg', requires_preamble = False, preamble_file_name = None, @@ -989,6 +992,12 @@ def image_header(env, gen_dict, boot_header.cert_chain_ptr = image_dest + code_size + signature_size boot_header.cert_chain_size = cert_chain_size + if is_ext_mbn_v5 == True: + # If platform image integrity check is enabled + boot_header.flash_parti_ver = 5 # version + boot_header.image_src = 0 # sig_size_qc + boot_header.image_dest_ptr = 0 # cert_chain_size_qc + # If preamble is required, output the preamble file and update the boot_header if requires_preamble is True: boot_header = image_preamble(gen_dict, preamble_file_name, boot_header, num_of_pages) @@ -2051,7 +2060,7 @@ def get_hash_address(elf_file_name): curr_phdr = phdr_table[i] if curr_phdr.p_paddr > last_paddr: # Skip the demand paging segment as it would be outside the physical RAM location - if MI_PBT_SEGMENT_TYPE_VALUE(curr_phdr.p_flags) != MI_PBT_SWAPPED_SEGMENT: + if MI_PBT_SEGMENT_TYPE_VALUE(curr_phdr.p_flags) != MI_PBT_XBL_SEC_SEGMENT: last_paddr = curr_phdr.p_paddr; last_paddr_segment = i; diff --git a/util/ipqheader/mbncat.py b/util/qualcomm/mbncat.py similarity index 100% rename from util/ipqheader/mbncat.py rename to util/qualcomm/mbncat.py diff --git a/util/qualcomm/qgpt.py b/util/qualcomm/qgpt.py new file mode 100755 index 0000000000..51018361e1 --- /dev/null +++ b/util/qualcomm/qgpt.py @@ -0,0 +1,234 @@ +#!/usr/bin/python +#============================================================================ +# +#/** @file qgpt.py +# +# GENERAL DESCRIPTION +# Generates QCom GPT header for wrapping Bootblock +# +# Copyright (c) 2018, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#**/ +# + +import os +import math +import random +import re +import struct +import sys +import tempfile + +from binascii import crc32 +from optparse import OptionParser +from types import * + + +def UpdateMBR(options, GPTBlobBuffer): + i = 0x1BE + GPTBlobBuffer[i + 0] = 0x00 # not bootable + GPTBlobBuffer[i + 1] = 0x00 # head + GPTBlobBuffer[i + 2] = 0x01 # sector + GPTBlobBuffer[i + 3] = 0x00 # cylinder + GPTBlobBuffer[i + 4] = 0xEE # type + GPTBlobBuffer[i + 5] = 0xFF # head + GPTBlobBuffer[i + 6] = 0xFF # sector + GPTBlobBuffer[i + 7] = 0xFF # cylinder + GPTBlobBuffer[i + 8:i + 8 + 4] = [0x01, 0x00, 0x00, 0x00] + + GPTBlobBuffer[i + 12:i + 16] = [0x00, 0x0f, 0x00, 0x00] + + # magic byte for MBR partitioning - always at this location regardless of + # options.sector + GPTBlobBuffer[510:512] = [0x55, 0xAA] + return i + + +def UpdatePartitionEntry(options, GPTBlobBuffer): + + i = 2 * options.sector_size + # GUID of Boot Block + GPTBlobBuffer[i:i + 16] = [0x2c, 0xba, 0xa0, 0xde, 0xdd, 0xcb, 0x05, 0x48, + 0xb4, 0xf9, 0xf4, 0x28, 0x25, 0x1c, 0x3e, 0x98] + i += 16 + + #This is to set Unique Partition GUID. Below Hex Value is : 00ChezaBootblock00 + GPTBlobBuffer[i:i + 16] = [0x00, 0x43, 0x68, 0x65, 0x7a, 0x61, 0x42, 0x6f, + 0x6f, 0x74, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x00] + i += 16 + + # LBA of BootBlock Start Content + GPTBlobBuffer[i:i + 8] = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + i += 8 + + # End LBA of BootBlock Content + GPTBlobBuffer[i] = options.end_lba & 0xFF + GPTBlobBuffer[i+1] = (options.end_lba>>8) & 0xFF + GPTBlobBuffer[i+2] = (options.end_lba>>16) & 0xFF + GPTBlobBuffer[i+3] = (options.end_lba>>24) & 0xFF + GPTBlobBuffer[i+4] = (options.end_lba>>32) & 0xFF + GPTBlobBuffer[i+5] = (options.end_lba>>40) & 0xFF + GPTBlobBuffer[i+6] = (options.end_lba>>48) & 0xFF + GPTBlobBuffer[i+7] = (options.end_lba>>56) & 0xFF + i += 8 + + # Attributes + GPTBlobBuffer[i:i + 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + i += 8 + + # Label + GPTBlobBuffer[i:i + 17] = [0x62, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x74, 0x00, + 0x62, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x6b] + + return i + +def UpdateGPTHeader(options, GPTBlobBuffer): + + i = options.sector_size + # Signature and Revision and HeaderSize i.e. "EFI PART" and 00 00 01 00 + # and 5C 00 00 00 + GPTBlobBuffer[i:i + 16] = [0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54, + 0x00, 0x00, 0x01, 0x00, 0x5C, 0x00, 0x00, 0x00] + i += 16 + + # CRC is zeroed out till calculated later + GPTBlobBuffer[i:i + 4] = [0x00, 0x00, 0x00, 0x00] + i += 4 + + # Reserved, set to 0 + GPTBlobBuffer[i:i + 4] = [0x00, 0x00, 0x00, 0x00] + i += 4 + + # Current LBA + GPTBlobBuffer[i:i + 8] = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + i += 8 + + # Backup LBA, No Backup Gpt Used + GPTBlobBuffer[i:i + 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + i += 8 + + # First Usuable LBA (qc_sec + bootblock location) + GPTBlobBuffer[i:i + 8] = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + i += 8 + + # Last Usuable LBA (qc_sec + bootblock end location) + GPTBlobBuffer[i] = options.end_lba & 0xFF + GPTBlobBuffer[i+1] = (options.end_lba>>8) & 0xFF + GPTBlobBuffer[i+2] = (options.end_lba>>16) & 0xFF + GPTBlobBuffer[i+3] = (options.end_lba>>24) & 0xFF + GPTBlobBuffer[i+4] = (options.end_lba>>32) & 0xFF + GPTBlobBuffer[i+5] = (options.end_lba>>40) & 0xFF + GPTBlobBuffer[i+6] = (options.end_lba>>48) & 0xFF + GPTBlobBuffer[i+7] = (options.end_lba>>56) & 0xFF + i += 8 + + # GUID + GPTBlobBuffer[i:i + 16] = [0x32,0x1B,0x10,0x98,0xE2,0xBB,0xF2,0x4B, + 0xA0,0x6E,0x2B,0xB3,0x3D,0x00,0x0C,0x20] + i += 16 + + # Partition Table Entry LBA + GPTBlobBuffer[i:i + 8] = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + i += 8 + + # Number of Partition Entries + GPTBlobBuffer[i:i + 4] = [0x01, 0x00, 0x00, 0x00] + i += 4 + + # Size of One Partition Entry + GPTBlobBuffer[i:i + 4] = [0x80, 0x00, 0x00, 0x00] + i += 4 + + # CRC of Partition Entry + + PartEntry = GPTBlobBuffer[options.sector_size*2:options.sector_size*2 + 128] + CalcEntryCRC = crc32(''.join(struct.pack("B", x) for x in PartEntry)) + + GPTBlobBuffer[i] = CalcEntryCRC & 0xFF + GPTBlobBuffer[i+1] = (CalcEntryCRC>>8) & 0xFF + GPTBlobBuffer[i+2] = (CalcEntryCRC>>16) & 0xFF + GPTBlobBuffer[i+3] = (CalcEntryCRC>>24) & 0xFF + i += 4 + + # CRC of Partition Table Header + GPTHeader = GPTBlobBuffer[options.sector_size:options.sector_size + 92] + CalcEntryCRC = crc32(''.join(struct.pack("B", x) for x in GPTHeader)) + i = options.sector_size + 16 + + GPTBlobBuffer[i] = CalcEntryCRC & 0xFF + GPTBlobBuffer[i+1] = (CalcEntryCRC>>8) & 0xFF + GPTBlobBuffer[i+2] = (CalcEntryCRC>>16) & 0xFF + GPTBlobBuffer[i+3] = (CalcEntryCRC>>24) & 0xFF + + return i + + +if __name__ == '__main__': + usage = 'usage: %prog [OPTIONS] INFILE OUTFILE\n\n' + \ + 'Packages IMAGE in a GPT format.' + parser = OptionParser(usage) + parser.add_option('-s', type="int", dest='sector_size', default=4096, + help='Sector size in bytes [Default:4096(4KB)]', + metavar='SIZE') + + (options, args) = parser.parse_args() + if len(args) != 2: + print("Invalid arguments! Exiting...\n") + parser.print_help() + sys.exit(1) + + if options.sector_size != 4096 and options.sector_size != 512: + print("Invalid Sector Size") + sys.exit(1) + + options.inputfile = args[0] + options.outputfile = args[1] + + with open(options.inputfile, 'r+') as fin: + bb_buffer = fin.read() + + # Round up to next sector if bootblock size not evenly divisible + options.end_lba = ((len(bb_buffer) + options.sector_size - 1) / + options.sector_size) + # Add 3 sectors for MBR, GPT header and GPT partition entry + options.end_lba += 3 + # Subtract one because this is last usable LBA, not amount of LBAs + options.end_lba -= 1 + + GPTBlobBuffer = [0] * (options.sector_size*3) #Size of MBR+GPT+PART_ENTRY + + UpdateMBR(options, GPTBlobBuffer) + + UpdatePartitionEntry(options, GPTBlobBuffer) + + UpdateGPTHeader(options, GPTBlobBuffer) + + with open(options.outputfile, 'wb') as fout: + for b in GPTBlobBuffer: + fout.write(struct.pack("B", b)) + fout.write(bb_buffer) From bd0b51c0be1ec2c9a5f02de3c13108c13941e2c2 Mon Sep 17 00:00:00 2001 From: T Michael Turney Date: Thu, 21 Mar 2019 14:20:52 -0700 Subject: [PATCH 011/107] sdm845: Add QCLib to RomStage to perform IP init CB acts as I/O handler for QCLib (e.g. DDR training data) This interface allows bi-directional data flow between CB and QCLib Tested and working interfaces: DDR Training data QCLib serial console output DDR Information (base & size) limits cfg data TEST=build & run Change-Id: I073186674a1a593547d1ee1d15c7cd4fd8ad5bc1 Signed-off-by: T Michael Turney Reviewed-on: https://review.coreboot.org/c/coreboot/+/25208 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/mainboard/google/cheza/chromeos.fmd | 11 ++-- src/mainboard/google/cheza/romstage.c | 4 ++ src/soc/qualcomm/sdm845/Makefile.inc | 5 ++ .../qualcomm/sdm845/include/soc/memlayout.ld | 21 +++++--- src/soc/qualcomm/sdm845/include/soc/mmu.h | 2 - src/soc/qualcomm/sdm845/include/soc/symbols.h | 4 +- src/soc/qualcomm/sdm845/mmu.c | 5 +- src/soc/qualcomm/sdm845/qclib.c | 50 +++++++++++++++++++ src/soc/qualcomm/sdm845/soc.c | 4 +- 9 files changed, 84 insertions(+), 22 deletions(-) create mode 100644 src/soc/qualcomm/sdm845/qclib.c diff --git a/src/mainboard/google/cheza/chromeos.fmd b/src/mainboard/google/cheza/chromeos.fmd index 71e85562d6..b0d2d99996 100644 --- a/src/mainboard/google/cheza/chromeos.fmd +++ b/src/mainboard/google/cheza/chromeos.fmd @@ -24,16 +24,15 @@ FLASH@0x0 8M { RO_FRID 0x100 } RO_VPD(PRESERVE) 16K - # TODO(hungte): Remove RO_PRESERVE. - RO_PRESERVE(PRESERVE) { - RO_DDR_TRAINING 8K - RO_FSG - } + RO_DDR_TRAINING(PRESERVE) 8K + RO_LIMITS_CFG(PRESERVE) 4K + RO_FSG(PRESERVE) } RW_VPD(PRESERVE) 32K RW_NVRAM(PRESERVE) 16K - RW_DDR_TRAINING 8K + RW_DDR_TRAINING(PRESERVE) 8K + RW_LIMITS_CFG(PRESERVE) 4K RW_ELOG(PRESERVE) 4K RW_SHARED 4K { SHARED_DATA diff --git a/src/mainboard/google/cheza/romstage.c b/src/mainboard/google/cheza/romstage.c index 7b7da4ce8c..de737b1159 100644 --- a/src/mainboard/google/cheza/romstage.c +++ b/src/mainboard/google/cheza/romstage.c @@ -15,6 +15,7 @@ #include #include +#include static void prepare_usb(void) { @@ -28,4 +29,7 @@ static void prepare_usb(void) void platform_romstage_main(void) { prepare_usb(); + + /* QCLib: DDR init & train */ + qclib_load_and_run(); } diff --git a/src/soc/qualcomm/sdm845/Makefile.inc b/src/soc/qualcomm/sdm845/Makefile.inc index d099bff717..78b3568a8b 100644 --- a/src/soc/qualcomm/sdm845/Makefile.inc +++ b/src/soc/qualcomm/sdm845/Makefile.inc @@ -25,6 +25,10 @@ romstage-y += gpio.c romstage-y += clock.c romstage-$(CONFIG_SDM845_QSPI) += qspi.c romstage-y += usb.c +romstage-y += ../common/qclib.c +romstage-y += qclib.c +romstage-y += ../common/mmu.c +romstage-y += mmu.c ################################################################################ ramstage-y += soc.c @@ -39,6 +43,7 @@ ramstage-y += usb.c ################################################################################ CPPFLAGS_common += -Isrc/soc/qualcomm/sdm845/include +CPPFLAGS_common += -Isrc/soc/qualcomm/common/include $(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin @printf "Generating: $(subst $(obj)/,,$(@))\n" diff --git a/src/soc/qualcomm/sdm845/include/soc/memlayout.ld b/src/soc/qualcomm/sdm845/include/soc/memlayout.ld index 7063c6910e..b1b633317f 100644 --- a/src/soc/qualcomm/sdm845/include/soc/memlayout.ld +++ b/src/soc/qualcomm/sdm845/include/soc/memlayout.ld @@ -28,11 +28,12 @@ SECTIONS { SSRAM_START(0x14680000) OVERLAP_VERSTAGE_ROMSTAGE(0x14680000, 100K) - DMA_COHERENT(0x14699000, 0x2000) + DMA_COHERENT(0x14699000, 8K) + REGION(qcsdi, 0x146AC000, 44K, 4K) SSRAM_END(0x146C0000) BSRAM_START(0x14800000) - REGION(fw_reserved2, 0x14800000, 0x16000, 4096) + REGION(fw_reserved2, 0x14800000, 0x16000, 0x1000) BOOTBLOCK(0x14816000, 40K) TTB(0x14820000, 56K) VBOOT2_WORK(0x1482E000, 12K) @@ -40,15 +41,19 @@ SECTIONS TIMESTAMP(0x14836000, 1K) PRERAM_CBMEM_CONSOLE(0x14836400, 32K) PRERAM_CBFS_CACHE(0x1483E400, 70K) - REGION(bsram_unused, 0x1484FC00, 0xA2400, 0x100) - REGION(qclib, 0x148F2000, 0x80000, 4096) - REGION(dcb, 0x14972000, 0x4000, 4096) - REGION(pmic, 0x14976000, 0xA000, 4096) + REGION(bsram_unused, 0x1484FC00, 0x9E300, 0x100) + REGION(ddr_information, 0x148EDF00, 256, 256) + REGION(limits_cfg, 0x148EE000, 4K, 4K) + REGION(qclib_serial_log, 0x148EF000, 4K, 4K) + REGION(ddr_training, 0x148F0000, 8K, 4K) + REGION(qclib, 0x148F2000, 512K, 4K) + REGION(dcb, 0x14972000, 16K, 4K) + REGION(pmic, 0x14976000, 40K, 4K) BSRAM_END(0x14980000) DRAM_START(0x80000000) /* Various hardware/software subsystems make use of this area */ - REGION(dram_reserved, 0x85000000, 0x1A800000, 4096) + REGION(dram_reserved, 0x85000000, 0x1A800000, 0x1000) POSTRAM_CBFS_CACHE(0x9F800000, 384K) - RAMSTAGE(0x9F860000, 128K) + RAMSTAGE(0x9F860000, 2M) } diff --git a/src/soc/qualcomm/sdm845/include/soc/mmu.h b/src/soc/qualcomm/sdm845/include/soc/mmu.h index 299700a63f..c9883bc0bf 100644 --- a/src/soc/qualcomm/sdm845/include/soc/mmu.h +++ b/src/soc/qualcomm/sdm845/include/soc/mmu.h @@ -16,8 +16,6 @@ #ifndef _SOC_QUALCOMM_SDM845_MMU_H__ #define _SOC_QUALCOMM_SDM845_MMU_H__ -#define DRAMSIZE4GB 0x100000000 - void sdm845_mmu_init(void); #endif // _SOC_QUALCOMM_SDM845_MMU_H_ diff --git a/src/soc/qualcomm/sdm845/include/soc/symbols.h b/src/soc/qualcomm/sdm845/include/soc/symbols.h index 1c14c03d01..e7bf1b2aea 100644 --- a/src/soc/qualcomm/sdm845/include/soc/symbols.h +++ b/src/soc/qualcomm/sdm845/include/soc/symbols.h @@ -17,10 +17,12 @@ #define _SOC_QUALCOMM_SDM845_SYMBOLS_H_ #include -#include DECLARE_REGION(ssram) DECLARE_REGION(bsram) DECLARE_REGION(dram_reserved) +DECLARE_REGION(dcb); +DECLARE_REGION(pmic); +DECLARE_REGION(limits_cfg); #endif // _SOC_QUALCOMM_SDM845_SYMBOLS_H_ diff --git a/src/soc/qualcomm/sdm845/mmu.c b/src/soc/qualcomm/sdm845/mmu.c index ef6c058ab3..ec5fa55de2 100644 --- a/src/soc/qualcomm/sdm845/mmu.c +++ b/src/soc/qualcomm/sdm845/mmu.c @@ -17,12 +17,9 @@ #include #include #include +#include #include -#define CACHED_RAM (MA_MEM | MA_S | MA_RW) -#define UNCACHED_RAM (MA_MEM | MA_S | MA_RW | MA_MEM_NC) -#define DEV_MEM (MA_DEV | MA_S | MA_RW) - void sdm845_mmu_init(void) { mmu_init(); diff --git a/src/soc/qualcomm/sdm845/qclib.c b/src/soc/qualcomm/sdm845/qclib.c new file mode 100644 index 0000000000..9c05452c9e --- /dev/null +++ b/src/soc/qualcomm/sdm845/qclib.c @@ -0,0 +1,50 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include + +int qclib_soc_blob_load(void) +{ + size_t size; + ssize_t ssize; + + /* Attempt to load PMICCFG Blob */ + size = cbfs_boot_load_file(CONFIG_CBFS_PREFIX "/pmiccfg", + _pmic, REGION_SIZE(pmic), CBFS_TYPE_RAW); + if (!size) + return -1; + qclib_add_if_table_entry(QCLIB_TE_PMIC_SETTINGS, _pmic, size, 0); + + /* Attempt to load DCB Blob */ + size = cbfs_boot_load_file(CONFIG_CBFS_PREFIX "/dcb", + _dcb, REGION_SIZE(dcb), CBFS_TYPE_RAW); + if (!size) + return -1; + qclib_add_if_table_entry(QCLIB_TE_DCB_SETTINGS, _dcb, size, 0); + + /* Attempt to load Limits Config Blob */ + ssize = fmap_read_area(QCLIB_FR_LIMITS_CFG_DATA, _limits_cfg, + REGION_SIZE(limits_cfg)); + if (ssize < 0) + return -1; + qclib_add_if_table_entry(QCLIB_TE_LIMITS_CFG_DATA, + _limits_cfg, ssize, 0); + + return 0; +} diff --git a/src/soc/qualcomm/sdm845/soc.c b/src/soc/qualcomm/sdm845/soc.c index bc7235f3ed..ef283c0eae 100644 --- a/src/soc/qualcomm/sdm845/soc.c +++ b/src/soc/qualcomm/sdm845/soc.c @@ -16,11 +16,13 @@ #include #include #include +#include #include static void soc_read_resources(struct device *dev) { - ram_resource(dev, 0, (uintptr_t)_dram / KiB, DRAMSIZE4GB / KiB); + ram_resource(dev, 0, (uintptr_t)ddr_region->offset / KiB, + ddr_region->size / KiB); reserved_ram_resource(dev, 1, (uintptr_t)_dram_reserved / KiB, REGION_SIZE(dram_reserved) / KiB); } From a88041c04315cd2875cdf71e8070a6c7faa355a3 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Tue, 23 Apr 2019 12:16:33 +0200 Subject: [PATCH 012/107] mainboard/google/cyan/acpi: Serialize _CRS method IASL reports warning 'Control Method should be made Serialized'. Change _CRS method to Serialized. BUG=N/A TEST=Build Google Banon and Google Cyan Change-Id: Iffa097a2100cfa91efa3b617311500b83f839bce Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/32331 Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier --- src/mainboard/google/cyan/acpi/codec_maxim.asl | 2 +- src/mainboard/google/cyan/acpi/codec_realtek.asl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainboard/google/cyan/acpi/codec_maxim.asl b/src/mainboard/google/cyan/acpi/codec_maxim.asl index 81bec16ea5..b412551a4a 100644 --- a/src/mainboard/google/cyan/acpi/codec_maxim.asl +++ b/src/mainboard/google/cyan/acpi/codec_maxim.asl @@ -35,7 +35,7 @@ Scope (\_SB.PCI0.I2C2) } }) - Method(_CRS, 0x0, NotSerialized) + Method(_CRS, 0x0, Serialized) { Name(SBUF,ResourceTemplate () { diff --git a/src/mainboard/google/cyan/acpi/codec_realtek.asl b/src/mainboard/google/cyan/acpi/codec_realtek.asl index 4a1d48de7b..d697aace3e 100644 --- a/src/mainboard/google/cyan/acpi/codec_realtek.asl +++ b/src/mainboard/google/cyan/acpi/codec_realtek.asl @@ -26,7 +26,7 @@ Scope (\_SB.PCI0.I2C5) Name (_DDN, AUDIO_CODEC_DDN) Name (_UID, 1) - Method(_CRS, 0x0, NotSerialized) + Method(_CRS, 0x0, Serialized) { Name(SBUF,ResourceTemplate () { From e6bf51fb221db651c271115b32f1308983d20987 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Wed, 1 May 2019 10:48:31 +0200 Subject: [PATCH 013/107] {soc, southbridge} : Correct typo in comment BUG=N/A TEST=N/A Change-Id: I1b207e0b77bac8860ba7501378297c1f3604141c Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/32453 Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- src/soc/intel/braswell/southcluster.c | 2 +- src/southbridge/intel/bd82x6x/pch.c | 2 +- src/southbridge/intel/lynxpoint/pch.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/soc/intel/braswell/southcluster.c b/src/soc/intel/braswell/southcluster.c index 000790d9a6..bf9f689c2a 100644 --- a/src/soc/intel/braswell/southcluster.c +++ b/src/soc/intel/braswell/southcluster.c @@ -347,7 +347,7 @@ static void sc_init(struct device *dev) * Common code for the south cluster devices. */ -/* Set bit in function disble register to hide this device. */ +/* Set bit in function disable register to hide this device. */ static void sc_disable_devfn(struct device *dev) { void *func_dis = (void *)(PMC_BASE_ADDRESS + FUNC_DIS); diff --git a/src/southbridge/intel/bd82x6x/pch.c b/src/southbridge/intel/bd82x6x/pch.c index 746c11a2e3..f8540af451 100644 --- a/src/southbridge/intel/bd82x6x/pch.c +++ b/src/southbridge/intel/bd82x6x/pch.c @@ -144,7 +144,7 @@ void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue) } #ifndef __SMM__ -/* Set bit in Function Disble register to hide this device */ +/* Set bit in function disable register to hide this device */ static void pch_hide_devfn(unsigned devfn) { switch (devfn) { diff --git a/src/southbridge/intel/lynxpoint/pch.c b/src/southbridge/intel/lynxpoint/pch.c index 5cf67aa238..a57bae311d 100644 --- a/src/southbridge/intel/lynxpoint/pch.c +++ b/src/southbridge/intel/lynxpoint/pch.c @@ -100,7 +100,7 @@ static void pch_enable_d3hot(struct device *dev) pci_write_config32(dev, PCH_PCS, reg32); } -/* Set bit in Function Disble register to hide this device */ +/* Set bit in function disable register to hide this device */ void pch_disable_devfn(struct device *dev) { switch (dev->path.pci.devfn) { From 73c312fce591928e3709a733b78ce6826f8e1a2d Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Fri, 3 May 2019 16:32:30 -0500 Subject: [PATCH 014/107] src/Kconfig: remove duplicate entry for drivers/fsp1_0/Kconfig The entry for drivers/intel/fsp1_0/Kconfig was added under the chipset menu before addtional FSP versions were added, and the drivers/*/*/Kconfig entry added to support them. This results in the fsp1_0 Kconfig items being duplicated in the Chipset and Generic Drivers menus. Remove the chipset entry since it's no longer needed. Test: select FSP 1.0 mainboard (e.g. intel/minnowmax) in menuconfig, observe FSP 1.0 Kconfig entries listed only under Generic Drivers menu. Signed-off-by: Matt DeVillier Change-Id: If1e78fb9259b1a46d308db829881eb3b3d17cf40 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32565 Reviewed-by: Furquan Shaikh Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- src/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Kconfig b/src/Kconfig index 90c724ebb5..05875b6327 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -370,8 +370,6 @@ source "src/superio/*/*/Kconfig" comment "Embedded Controllers" source "src/ec/acpi/Kconfig" source "src/ec/*/*/Kconfig" -# FIXME move to vendorcode -source "src/drivers/intel/fsp1_0/Kconfig" source "src/southbridge/intel/common/firmware/Kconfig" source "src/vendorcode/*/Kconfig" From 29a1a0857a637651595dc6109dc24243f353cadf Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 5 May 2019 08:34:55 +0200 Subject: [PATCH 015/107] mb/msi/ms7707: Remove MAINBOARD_PCI_SUBSYSTEM_{DEVICE_ID,VENDOR_ID} References to MAINBOARD_PCI_SUBSYSTEM_{DEVICE_ID,VENDOR_ID} were removed. Change-Id: I70ef22aac165a19663749f76449907482b761316 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32605 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph Reviewed-by: Angel Pons Reviewed-by: Nico Huber --- src/mainboard/msi/ms7707/Kconfig | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/mainboard/msi/ms7707/Kconfig b/src/mainboard/msi/ms7707/Kconfig index 45ff73e57a..4923bbfdea 100644 --- a/src/mainboard/msi/ms7707/Kconfig +++ b/src/mainboard/msi/ms7707/Kconfig @@ -22,14 +22,6 @@ config MAINBOARD_PART_NUMBER string default "MS-7707" -config MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID - hex - default 0x7707 - -config MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID - hex - default 0x1462 - config DRAM_RESET_GATE_GPIO int default 60 From 42065f8f94b910972fb5e7f3f1952a908b94ffc1 Mon Sep 17 00:00:00 2001 From: Werner Zeh Date: Thu, 2 May 2019 12:45:21 +0200 Subject: [PATCH 016/107] mb/siemens/mc_apl2: Limit SD-Card speed to DDR50 Due to PCB limitations the SD-Card interface is not able to operate with the highest frequency reliably. The OS driver will switch to the highest mode if a SD-Card is attached which supports this high frequency mode. In order to work around this PCB limitation disable the high frequency modes in the controller capabilities (SDR104 and HS400 mode) and leave SDR50 and DDR50 enabled. Change-Id: Ia5fed5fb70b027de34170b49620927614a00fb7a Signed-off-by: Werner Zeh Reviewed-on: https://review.coreboot.org/c/coreboot/+/32542 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- .../mc_apl1/variants/mc_apl2/mainboard.c | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/mainboard/siemens/mc_apl1/variants/mc_apl2/mainboard.c b/src/mainboard/siemens/mc_apl1/variants/mc_apl2/mainboard.c index 0c2418ad27..f52091bced 100644 --- a/src/mainboard/siemens/mc_apl1/variants/mc_apl2/mainboard.c +++ b/src/mainboard/siemens/mc_apl1/variants/mc_apl2/mainboard.c @@ -23,6 +23,11 @@ #include #include #include +#include + +#define SD_CAP_BYP 0x810 +#define SD_CAP_BYP_EN 0x5A +#define SD_CAP_BYP_REG1 0x814 void variant_mainboard_final(void) { @@ -36,6 +41,21 @@ void variant_mainboard_final(void) cmd |= PCI_COMMAND_MASTER; pci_write_config16(dev, PCI_COMMAND, cmd); } + + /* Reduce SD-Card speed to DDR50 because of PCB constraints. */ + dev = pcidev_path_on_root(PCH_DEVFN_SDCARD); + if (dev) { + uint32_t reg; + struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (!res) + return; + + write32(res2mmio(res, SD_CAP_BYP, 0), SD_CAP_BYP_EN); + reg = read32(res2mmio(res, SD_CAP_BYP_REG1, 0)); + /* Disable HS400 and SDR104, keep SDR50 and DDR50 modes. */ + reg &= ~0x20005800; + write32(res2mmio(res, SD_CAP_BYP_REG1, 0), reg); + } } static void wait_for_legacy_dev(void *unused) From 43fc38943da7839d2fe83bf7ca1b9c509c327dc0 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Fri, 26 Apr 2019 14:50:32 +0200 Subject: [PATCH 017/107] mainboard/intel/strago/acpi: Serialize _CRS method IASL reports warning 'Control Method should be made Serialized'. Change _CRS method to Serialized. BUG=N/A TEST=Build Intel Strago Change-Id: I63a7e1caab19360a9a5831458311d5a83fdf52d1 Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/32468 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- src/mainboard/intel/strago/acpi/mainboard.asl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainboard/intel/strago/acpi/mainboard.asl b/src/mainboard/intel/strago/acpi/mainboard.asl index 68ac133eec..1d5437bbf2 100644 --- a/src/mainboard/intel/strago/acpi/mainboard.asl +++ b/src/mainboard/intel/strago/acpi/mainboard.asl @@ -74,7 +74,7 @@ Scope (\_SB.PCI0.I2C1) Name (_UID, 5) Name (ISTP, 0) /* TouchScreen */ - Method(_CRS, 0x0, NotSerialized) + Method(_CRS, 0x0, Serialized) { Name (BUF0, ResourceTemplate () { @@ -120,7 +120,7 @@ Scope (\_SB.PCI0.I2C5) Name (_DDN, AUDIO_CODEC_DDN) Name (_UID, 1) - Method(_CRS, 0x0, NotSerialized) + Method(_CRS, 0x0, Serialized) { Name(SBUF,ResourceTemplate () { From 85b2ed5438d5d42d00519114e385bf3ae2d56e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ky=C3=B6sti=20M=C3=A4lkki?= Date: Thu, 14 Jun 2018 06:57:05 +0300 Subject: [PATCH 018/107] soc/amd/common: Introduce module_dispatch() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change removes all the separate entrypoint dispatch functions as they all share the same pattern. Furthermore, none of the function definitions under vendorcode binaryPI/AGESA.c file have proper declarations, the ones compiler picks up from AGESA.h are for the internal implementations and with sanely organized headerfiles would not be exposed outside the build of AGESA at all. Change-Id: I0b72badc007565740c93b58743cfd048e8b42775 Signed-off-by: Kyösti Mälkki Reviewed-on: https://review.coreboot.org/c/coreboot/+/31485 Reviewed-by: Nico Huber Reviewed-by: Paul Menzel Tested-by: build bot (Jenkins) --- src/soc/amd/common/block/pi/agesawrapper.c | 55 +++++-- .../amd/pi/00670F00/binaryPI/AGESA.c | 154 ------------------ 2 files changed, 39 insertions(+), 170 deletions(-) diff --git a/src/soc/amd/common/block/pi/agesawrapper.c b/src/soc/amd/common/block/pi/agesawrapper.c index 0570b5a3ee..5f58346625 100644 --- a/src/soc/amd/common/block/pi/agesawrapper.c +++ b/src/soc/amd/common/block/pi/agesawrapper.c @@ -41,8 +41,34 @@ static void *AcpiAlib; static void *AcpiIvrs; static void *AcpiCrat; +static AGESA_STATUS module_dispatch(AGESA_STRUCT_NAME func, + AMD_CONFIG_PARAMS *StdHeader) +{ + MODULE_ENTRY dispatcher = agesa_get_dispatcher(); + + if (!dispatcher) + return AGESA_UNSUPPORTED; + + StdHeader->Func = func; + return dispatcher(StdHeader); +} + +static AGESA_STATUS amd_dispatch(void *Params) +{ + AMD_CONFIG_PARAMS *StdHeader = Params; + return module_dispatch(StdHeader->Func, StdHeader); +} + +AGESA_STATUS amd_late_run_ap_task(AP_EXE_PARAMS *ApExeParams) +{ + AMD_CONFIG_PARAMS *StdHeader = (void *)ApExeParams; + return module_dispatch(AMD_LATE_RUN_AP_TASK, StdHeader); +} + static void *create_struct(AMD_INTERFACE_PARAMS *interface_struct) { + AMD_CONFIG_PARAMS *StdHeader; + /* Should clone entire StdHeader here. */ interface_struct->StdHeader.CalloutPtr = &GetBiosCallout; @@ -57,7 +83,9 @@ static void *create_struct(AMD_INTERFACE_PARAMS *interface_struct) if (!interface_struct->NewStructPtr) /* Avoid NULL pointer usage */ die("No AGESA structure created"); - return interface_struct->NewStructPtr; + StdHeader = interface_struct->NewStructPtr; + StdHeader->Func = interface_struct->AgesaFunctionName; + return StdHeader; } static AGESA_STATUS amd_init_reset(void) @@ -76,7 +104,7 @@ static AGESA_STATUS amd_init_reset(void) SetFchResetParams(&ResetParams->FchInterface); timestamp_add_now(TS_AGESA_INIT_RESET_START); - status = AmdInitReset(ResetParams); + status = amd_dispatch(ResetParams); timestamp_add_now(TS_AGESA_INIT_RESET_DONE); AmdReleaseStruct(&AmdParamStruct); @@ -97,7 +125,7 @@ static AGESA_STATUS amd_init_early(void) OemCustomizeInitEarly(EarlyParams); timestamp_add_now(TS_AGESA_INIT_EARLY_START); - status = AmdInitEarly(EarlyParams); + status = amd_dispatch(EarlyParams); timestamp_add_now(TS_AGESA_INIT_EARLY_DONE); AmdReleaseStruct(&AmdParamStruct); @@ -162,7 +190,7 @@ static AGESA_STATUS amd_init_post(void) ); timestamp_add_now(TS_AGESA_INIT_POST_START); - status = AmdInitPost(PostParams); + status = amd_dispatch(PostParams); timestamp_add_now(TS_AGESA_INIT_POST_DONE); /* @@ -205,7 +233,7 @@ static AGESA_STATUS amd_init_env(void) SetNbEnvParams(&EnvParams->GnbEnvConfiguration); timestamp_add_now(TS_AGESA_INIT_ENV_START); - status = AmdInitEnv(EnvParams); + status = amd_dispatch(EnvParams); timestamp_add_now(TS_AGESA_INIT_ENV_DONE); AmdReleaseStruct(&AmdParamStruct); @@ -256,7 +284,7 @@ static AGESA_STATUS amd_init_mid(void) SetNbMidParams(&MidParams->GnbMidConfiguration); timestamp_add_now(TS_AGESA_INIT_MID_START); - status = AmdInitMid(MidParams); + status = amd_dispatch(MidParams); timestamp_add_now(TS_AGESA_INIT_MID_DONE); AmdReleaseStruct(&AmdParamStruct); @@ -286,7 +314,7 @@ static AGESA_STATUS amd_init_late(void) } timestamp_add_now(TS_AGESA_INIT_LATE_START); - Status = AmdInitLate(LateParams); + Status = amd_dispatch(LateParams); timestamp_add_now(TS_AGESA_INIT_LATE_DONE); DmiTable = LateParams->DmiTable; @@ -309,11 +337,6 @@ static AGESA_STATUS amd_init_late(void) return Status; } -AGESA_STATUS amd_late_run_ap_task(AP_EXE_PARAMS *ApExeParams) -{ - return AmdLateRunApTask(ApExeParams); -} - static AGESA_STATUS amd_init_rtb(void) { AGESA_STATUS Status; @@ -325,7 +348,7 @@ static AGESA_STATUS amd_init_rtb(void) AMD_RTB_PARAMS *RtbParams = create_struct(&AmdParamStruct); timestamp_add_now(TS_AGESA_INIT_RTB_START); - Status = AmdInitRtb(RtbParams); + Status = amd_dispatch(RtbParams); timestamp_add_now(TS_AGESA_INIT_RTB_DONE); if (save_s3_info(RtbParams->S3DataBlock.NvStorage, @@ -354,7 +377,7 @@ static AGESA_STATUS amd_init_resume(void) InitResumeParams->S3DataBlock.NvStorageSize = nv_size; timestamp_add_now(TS_AGESA_INIT_RESUME_START); - status = AmdInitResume(InitResumeParams); + status = amd_dispatch(InitResumeParams); timestamp_add_now(TS_AGESA_INIT_RESUME_DONE); AmdReleaseStruct(&AmdParamStruct); @@ -382,7 +405,7 @@ static AGESA_STATUS amd_s3late_restore(void) S3LateParams->S3DataBlock.VolatileStorageSize = vol_size; timestamp_add_now(TS_AGESA_S3_LATE_START); - Status = AmdS3LateRestore(S3LateParams); + Status = amd_dispatch(S3LateParams); timestamp_add_now(TS_AGESA_S3_LATE_DONE); AmdReleaseStruct(&AmdParamStruct); @@ -408,7 +431,7 @@ static AGESA_STATUS amd_s3final_restore(void) S3FinalParams->S3DataBlock.VolatileStorageSize = vol_size; timestamp_add_now(TS_AGESA_S3_FINAL_START); - Status = AmdS3FinalRestore(S3FinalParams); + Status = amd_dispatch(S3FinalParams); timestamp_add_now(TS_AGESA_S3_FINAL_DONE); AmdReleaseStruct(&AmdParamStruct); diff --git a/src/vendorcode/amd/pi/00670F00/binaryPI/AGESA.c b/src/vendorcode/amd/pi/00670F00/binaryPI/AGESA.c index 2efee4eb62..e17cedcb64 100644 --- a/src/vendorcode/amd/pi/00670F00/binaryPI/AGESA.c +++ b/src/vendorcode/amd/pi/00670F00/binaryPI/AGESA.c @@ -72,157 +72,3 @@ AmdReleaseStruct ( if (!Dispatcher) return AGESA_UNSUPPORTED; return Dispatcher(InterfaceParams); } - -/********************************************************************** - * Interface call: AmdInitReset - **********************************************************************/ -AGESA_STATUS -AmdInitReset ( - IN OUT AMD_RESET_PARAMS *ResetParams - ) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - ResetParams->StdHeader.Func = AMD_INIT_RESET; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(ResetParams); -} - -/********************************************************************** - * Interface call: AmdInitEarly - **********************************************************************/ -AGESA_STATUS -AmdInitEarly ( - IN OUT AMD_EARLY_PARAMS *EarlyParams - ) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - EarlyParams->StdHeader.Func = AMD_INIT_EARLY; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(EarlyParams); -} - -/********************************************************************** - * Interface call: AmdInitPost - **********************************************************************/ -AGESA_STATUS -AmdInitPost ( - IN OUT AMD_POST_PARAMS *PostParams ///< Amd Cpu init param - ) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - PostParams->StdHeader.Func = AMD_INIT_POST; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(PostParams); -} - -/********************************************************************** - * Interface call: AmdInitEnv - **********************************************************************/ -AGESA_STATUS -AmdInitEnv ( - IN OUT AMD_ENV_PARAMS *EnvParams - ) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - EnvParams->StdHeader.Func = AMD_INIT_ENV; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(EnvParams); -} - -/********************************************************************** - * Interface call: AmdInitMid - **********************************************************************/ -AGESA_STATUS -AmdInitMid ( - IN OUT AMD_MID_PARAMS *MidParams - ) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - MidParams->StdHeader.Func = AMD_INIT_MID; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(MidParams); -} - -/********************************************************************** - * Interface call: AmdInitLate - **********************************************************************/ -AGESA_STATUS -AmdInitLate ( - IN OUT AMD_LATE_PARAMS *LateParams - ) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - LateParams->StdHeader.Func = AMD_INIT_LATE; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(LateParams); -} - -/********************************************************************** - * Interface call: AmdInitResume - **********************************************************************/ -AGESA_STATUS -AmdInitResume ( - IN AMD_RESUME_PARAMS *ResumeParams - ) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - ResumeParams->StdHeader.Func = AMD_INIT_RESUME; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(ResumeParams); -} - -/********************************************************************** - * Interface call: AmdS3LateRestore - **********************************************************************/ -AGESA_STATUS -AmdS3LateRestore ( - IN OUT AMD_S3LATE_PARAMS *S3LateParams - ) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - S3LateParams->StdHeader.Func = AMD_S3LATE_RESTORE; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(S3LateParams); -} - -/********************************************************************** - * Interface call: AmdS3FinalRestore - **********************************************************************/ -AGESA_STATUS -AmdS3FinalRestore ( - IN OUT AMD_S3FINAL_PARAMS *S3FinalParams - ) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - S3FinalParams->StdHeader.Func = AMD_S3FINAL_RESTORE; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(S3FinalParams); -} - -/********************************************************************** - * Interface call: AmdInitRtb - **********************************************************************/ -AGESA_STATUS -AmdInitRtb ( - IN OUT AMD_RTB_PARAMS *AmdInitRtbParams - ) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - AmdInitRtbParams->StdHeader.Func = AMD_INIT_RTB; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(AmdInitRtbParams); -} - -/********************************************************************** - * Interface call: AmdLateRunApTask - **********************************************************************/ -AGESA_STATUS -AmdLateRunApTask ( - IN AP_EXE_PARAMS *AmdApExeParams -) -{ - MODULE_ENTRY Dispatcher = agesa_get_dispatcher(); - AmdApExeParams->StdHeader.Func = AMD_LATE_RUN_AP_TASK; - if (!Dispatcher) return AGESA_UNSUPPORTED; - return Dispatcher(AmdApExeParams); -} From 683e77e479d7204bdfaf4d9b468901aafe5225e3 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Mon, 29 Apr 2019 13:29:36 +0200 Subject: [PATCH 019/107] drivers/intel/fsp1_1/cache_as_ram.inc: Reduce max line length to 80 Cosmetic change to reduce line length to 80 max. BUG=NA TEST=Build Portwell PQ7-M107 Change-Id: Ib537592c0a6a3fffc85622e6b74ad5ec8041e7dc Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/32509 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- src/drivers/intel/fsp1_1/cache_as_ram.inc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/drivers/intel/fsp1_1/cache_as_ram.inc b/src/drivers/intel/fsp1_1/cache_as_ram.inc index 48fcb8f39f..fa5c40677b 100644 --- a/src/drivers/intel/fsp1_1/cache_as_ram.inc +++ b/src/drivers/intel/fsp1_1/cache_as_ram.inc @@ -24,9 +24,8 @@ * performs the final stage of initialization. */ - -#define LHLT_DELAY 0x50000 /* I/O delay between post codes on failure */ - +/* I/O delay between post codes on failure */ +#define LHLT_DELAY 0x50000 /* * Per FSP1.1 specs, following registers are preserved: * EBX, EDI, ESI, EBP, MM0, MM1 @@ -165,8 +164,8 @@ halt1: * 0x01 - FV signature, "_FVH" not present * 0x02 - FFS GUID not present * 0x03 - FSP INFO Header not found - * 0x04 - ImageBase does not equal CONFIG_FSP_LOC - Is the FSP rebased to - * a different location, or does it need to be? + * 0x04 - ImageBase does not equal CONFIG_FSP_LOC - Is the FSP rebased + * to a different location, or does it need to be? * 0x05 - FSP INFO Header signature "FSPH" not found * 0x06 - FSP Image ID is not the expected ID. */ @@ -181,7 +180,8 @@ halt2: * 0x02 - FSP_INVALID_PARAMETER: Input parameters are invalid. * 0x03 - FSP_UNSUPPORTED: The FSP calling conditions were not met. * 0x07 - FSP_DEVICE_ERROR: Temp RAM initialization failed - * 0x0E - FSP_NOT_FOUND: No valid microcode was found in the microcode region. + * 0x0E - FSP_NOT_FOUND: No valid microcode was found in the microcode + * region. * 0x14 - FSP_ALREADY_STARTED: Temp RAM initialization has been invoked */ movb $0xBB, %ah @@ -213,7 +213,7 @@ CAR_init_params: .long CONFIG_CPU_MICROCODE_CBFS_LOC /* Microcode Location */ .long CONFIG_CPU_MICROCODE_CBFS_LEN /* Microcode Length */ .long 0xFFFFFFFF - CONFIG_ROM_SIZE + 1 /* Firmware Location */ - .long CONFIG_ROM_SIZE /* Total Firmware Length */ + .long CONFIG_ROM_SIZE /* Firmware Length */ CAR_init_stack: .long CAR_init_done From 95f8884c955de7a2f46d7a324079f18208093157 Mon Sep 17 00:00:00 2001 From: Tim Wawrzynczak Date: Fri, 26 Apr 2019 14:54:58 -0600 Subject: [PATCH 020/107] soc/intel/common: Add new PAD_CFG macro. Added macro named PAD_CFG_GPI_GPIO_DRIVER_SCI, for pads that need to be configured as GPI, GPIO Driver mode, and SCI interrupt. Also remove PAD_IRQ_CFG_DUAL_ROUTE macro (subsumed by PAD_CFG_GPI_IRQ_WAKE). BUG=none BRANCH=none TEST=Compiles Change-Id: I0332c64e2fa62ce29c772444606adbfdf9c9afc4 Signed-off-by: Tim Wawrzynczak Reviewed-on: https://review.coreboot.org/c/coreboot/+/32485 Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/soc/intel/common/block/include/intelblocks/gpio_defs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/soc/intel/common/block/include/intelblocks/gpio_defs.h b/src/soc/intel/common/block/include/intelblocks/gpio_defs.h index 91d8f00a89..e1ddd4babb 100644 --- a/src/soc/intel/common/block/include/intelblocks/gpio_defs.h +++ b/src/soc/intel/common/block/include/intelblocks/gpio_defs.h @@ -391,6 +391,13 @@ PAD_IOSSTATE(TxDRxE)) #if CONFIG(SOC_INTEL_COMMON_BLOCK_GPIO_DUAL_ROUTE_SUPPORT) +/* GPI, GPIO Driver, SCI interrupt */ +#define PAD_CFG_GPI_GPIO_DRIVER_SCI(pad, pull, rst, trig, inv) \ + _PAD_CFG_STRUCT(pad, \ + PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \ + PAD_IRQ_CFG(SCI, trig, inv), \ + PAD_PULL(pull) | PAD_CFG1_GPIO_DRIVER | PAD_IOSSTATE(TxDRxE)) + #define PAD_CFG_GPI_DUAL_ROUTE(pad, pull, rst, trig, inv, route1, route2) \ _PAD_CFG_STRUCT(pad, \ PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \ From 939440c48ba47401679dd65930464649398b78db Mon Sep 17 00:00:00 2001 From: Tim Wawrzynczak Date: Fri, 26 Apr 2019 15:03:33 -0600 Subject: [PATCH 021/107] soc/intel/cannonlake: Add GPIO dual-route support. Select SOC_INTEL_COMMON_BLOCK_GPIO_DUAL_ROUTE_SUPPORT in Kconfig BUG=none BRANCH=none TEST=compiles Change-Id: If5f59ea50c13bd1f279637e281468e6d0312dbab Signed-off-by: Tim Wawrzynczak Reviewed-on: https://review.coreboot.org/c/coreboot/+/32486 Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/soc/intel/cannonlake/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig index 6759b7ff99..c06b91eb48 100644 --- a/src/soc/intel/cannonlake/Kconfig +++ b/src/soc/intel/cannonlake/Kconfig @@ -90,6 +90,7 @@ config CPU_SPECIFIC_OPTIONS select SOC_INTEL_COMMON_BLOCK_CHIP_CONFIG select SOC_INTEL_COMMON_BLOCK_CPU select SOC_INTEL_COMMON_BLOCK_CPU_MPINIT + select SOC_INTEL_COMMON_BLOCK_GPIO_DUAL_ROUTE_SUPPORT select SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2 select SOC_INTEL_COMMON_BLOCK_HDA select SOC_INTEL_COMMON_BLOCK_SA From 3fe7c44d501d64cfcc5cd79fbc02f7071bdfda4b Mon Sep 17 00:00:00 2001 From: Tim Wawrzynczak Date: Fri, 26 Apr 2019 15:26:15 -0600 Subject: [PATCH 022/107] mainboard/google/hatch: Enable PEN_EJECT_L as wake & notify source. Updated GPP_A8 to be a GPI and SCI source, to support both wake and notifications. BUG=b:128941098 BRANCH=none TEST=Compiles, simulated pen eject with PCH_INT_L signal. Both evtest and waking from s0ix confirm this works. The output of /proc/interrupts confirms the correct interrupt is triggered. Change-Id: I080fb3cbfb3e2f55209ca31824b00ca820d70f78 Signed-off-by: Tim Wawrzynczak Reviewed-on: https://review.coreboot.org/c/coreboot/+/32487 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/mainboard/google/hatch/variants/baseboard/gpio.c | 4 ++-- src/mainboard/google/hatch/variants/hatch/overridetree.cb | 4 +++- src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/mainboard/google/hatch/variants/baseboard/gpio.c b/src/mainboard/google/hatch/variants/baseboard/gpio.c index 198d930aba..32526cc74b 100644 --- a/src/mainboard/google/hatch/variants/baseboard/gpio.c +++ b/src/mainboard/google/hatch/variants/baseboard/gpio.c @@ -30,8 +30,8 @@ static const struct pad_config gpio_table[] = { PAD_CFG_GPI_INT(GPP_A6, NONE, PLTRST, LEVEL), /* A7 : PP3300_SOC_A */ PAD_NC(GPP_A7, NONE), - /* A8 : EMR_GARAGE_DET */ - PAD_CFG_GPI_GPIO_DRIVER(GPP_A8, NONE, DEEP), + /* A8 : PEN_GARAGE_DET_L */ + PAD_CFG_GPI_GPIO_DRIVER_SCI(GPP_A8, NONE, DEEP, LEVEL, NONE), /* A9 : ESPI_CLK */ /* A10 : FPMCU_PCH_BOOT1 */ PAD_CFG_GPO(GPP_A10, 0, DEEP), diff --git a/src/mainboard/google/hatch/variants/hatch/overridetree.cb b/src/mainboard/google/hatch/variants/hatch/overridetree.cb index 4b1b8d85f2..42752e68f1 100644 --- a/src/mainboard/google/hatch/variants/hatch/overridetree.cb +++ b/src/mainboard/google/hatch/variants/hatch/overridetree.cb @@ -86,7 +86,9 @@ chip soc/intel/cannonlake end chip drivers/generic/gpio_keys register "name" = ""PENH"" - register "gpio" = "ACPI_GPIO_INPUT_ACTIVE_HIGH(GPP_A8)" + register "gpio" = "ACPI_GPIO_IRQ_EDGE_BOTH(GPP_A8)" + register "key.wake" = "GPE0_DW0_08" + register "key.wakeup_event_action" = "EV_ACT_ASSERTED" register "key.dev_name" = ""EJCT"" register "key.linux_code" = "SW_PEN_INSERTED" register "key.linux_input_type" = "EV_SW" diff --git a/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb b/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb index c5d5964663..115a513038 100644 --- a/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb +++ b/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb @@ -71,7 +71,9 @@ chip soc/intel/cannonlake end chip drivers/generic/gpio_keys register "name" = ""PENH"" - register "gpio" = "ACPI_GPIO_INPUT_ACTIVE_HIGH(GPP_A8)" + register "gpio" = "ACPI_GPIO_IRQ_EDGE_BOTH(GPP_A8)" + register "key.wake" = "GPE0_DW0_08" + register "key.wakeup_event_action" = "EV_ACT_ASSERTED" register "key.dev_name" = ""EJCT"" register "key.linux_code" = "SW_PEN_INSERTED" register "key.linux_input_type" = "EV_SW" From b75f493ed7fafb6a933a3f47e1e90803b18fcb65 Mon Sep 17 00:00:00 2001 From: Tristan Shieh Date: Mon, 29 Apr 2019 09:12:54 +0800 Subject: [PATCH 023/107] mediatek/mt8183: Wait 200us for voltages to settle When we increase voltages, it takes 200us for voltages to stablize. BUG=b:80501386 BRANCH=none Test=Boots correctly on Kukui Change-Id: I5f32035693b6084dbe763411c612ae5d1f7c9e48 Signed-off-by: Tristan Shieh Reviewed-on: https://review.coreboot.org/c/coreboot/+/32498 Tested-by: build bot (Jenkins) Reviewed-by: You-Cheng Syu Reviewed-by: Julius Werner --- src/soc/mediatek/mt8183/mt6358.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/soc/mediatek/mt8183/mt6358.c b/src/soc/mediatek/mt8183/mt6358.c index 8162e3aaf1..705424337f 100644 --- a/src/soc/mediatek/mt8183/mt6358.c +++ b/src/soc/mediatek/mt8183/mt6358.c @@ -16,6 +16,7 @@ #include #include #include +#include static struct pmic_setting init_setting[] = { /* [15:0]: TMA_KEY */ @@ -775,13 +776,18 @@ static void mt6358_lp_setting(void) void mt6358_init(void) { + struct stopwatch voltage_settled; + if (pwrap_init()) die("ERROR - Failed to initialize pmic wrap!"); pmic_set_power_hold(true); pmic_wdt_set(); mt6358_init_setting(); + stopwatch_init_usecs_expire(&voltage_settled, 200); wk_sleep_voltage_by_ddr(); wk_power_down_seq(); mt6358_lp_setting(); + while (!stopwatch_expired(&voltage_settled)) + /* wait for voltages to settle */; } From 0dd6b55a7e8cb8fbc8c1c0188d9d4bd91a4e7813 Mon Sep 17 00:00:00 2001 From: Tristan Shieh Date: Fri, 26 Apr 2019 12:32:12 +0800 Subject: [PATCH 024/107] google/kukui: Raise the CPU frequency Run CPU at the highest freqency (1989MHz) to speed up the boot time. BUG=b:80501386 BRANCH=none Test=Boots correctly on Kukui Change-Id: I703ffcb99367f87e6792a72485f5634e0505e5ac Signed-off-by: Tristan Shieh Reviewed-on: https://review.coreboot.org/c/coreboot/+/32466 Reviewed-by: Angel Pons Reviewed-by: Hung-Te Lin Reviewed-by: Julius Werner Tested-by: build bot (Jenkins) --- src/mainboard/google/kukui/romstage.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mainboard/google/kukui/romstage.c b/src/mainboard/google/kukui/romstage.c index 81ae9c538d..baaca43b90 100644 --- a/src/mainboard/google/kukui/romstage.c +++ b/src/mainboard/google/kukui/romstage.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "early_init.h" @@ -28,6 +29,7 @@ void platform_romstage_main(void) mainboard_early_init(); mt6358_init(); + mt_pll_raise_ca53_freq(1989 * MHz); rtc_boot(); mt_mem_init(get_sdram_config()); mtk_mmu_after_dram(); From 72a9091a0efce1835a94f0ba0b10f62c78af70e2 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Sun, 24 Mar 2019 17:35:55 +0100 Subject: [PATCH 025/107] sb/intel/bd82x6x: Use common/rcba.h Make use of: * southbridge/intel/common/rcba.h * southbridge/intel/common/pmbase.c * defines in pch.h Get rid of dependency to DEFAULT_RCBA. Tested on Lenovo T520 (Intel Sandy Bridge). Still boots to OS, no errors visible in dmesg. Change-Id: I879fce6a5bb80499e1986e618a1422a7aaa3a0c0 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/32066 Reviewed-by: HAOUAS Elyes Reviewed-by: Arthur Heymans Tested-by: build bot (Jenkins) --- src/southbridge/intel/bd82x6x/early_usb.c | 32 ++++++++++------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/southbridge/intel/bd82x6x/early_usb.c b/src/southbridge/intel/bd82x6x/early_usb.c index 17919af53a..955737e2a8 100644 --- a/src/southbridge/intel/bd82x6x/early_usb.c +++ b/src/southbridge/intel/bd82x6x/early_usb.c @@ -19,6 +19,9 @@ #include #include #include +#include +#include + #include "pch.h" void early_usb_init(const struct southbridge_usb_port *portmap) @@ -32,46 +35,39 @@ void early_usb_init(const struct southbridge_usb_port *portmap) 0x2000094a, 0x2000035f, 0x20000f53, 0x20000357, 0x20000353 }; int i; - /* Activate PMBAR. */ - pci_write_config32(PCI_DEV(0, 0x1f, 0), PMBASE, DEFAULT_PMBASE | 1); - pci_write_config32(PCI_DEV(0, 0x1f, 0), PMBASE + 4, 0); - /* Enable ACPI BAR */ - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0x44 /* ACPI_CNTL */, 0x80); /* Unlock registers. */ - outw(inw(DEFAULT_PMBASE | UPRWC) | UPRWC_WR_EN, - DEFAULT_PMBASE | UPRWC); + write_pmbase16(UPRWC, read_pmbase16(UPRWC) | UPRWC_WR_EN); for (i = 0; i < 14; i++) - write32(DEFAULT_RCBABASE + (0x3500 + 4 * i), - currents[portmap[i].current]); + RCBA32(0x3500 + 4 * i) = currents[portmap[i].current]; for (i = 0; i < 10; i++) - write32(DEFAULT_RCBABASE + (0x3538 + 4 * i), 0); + RCBA32(0x3538 + 4 * i) = 0; for (i = 0; i < 8; i++) - write32(DEFAULT_RCBABASE + (0x3560 + 4 * i), rcba_dump[i]); + RCBA32(0x3560 + 4 * i) = rcba_dump[i]; for (i = 0; i < 8; i++) - write32(DEFAULT_RCBABASE + (0x3580 + 4 * i), 0); + RCBA32(0x3580 + 4 * i) = 0; reg32 = 0; for (i = 0; i < 14; i++) if (!portmap[i].enabled) reg32 |= (1 << i); - write32(DEFAULT_RCBABASE + USBPDO, reg32); + RCBA32(USBPDO) = reg32; reg32 = 0; for (i = 0; i < 8; i++) if (portmap[i].enabled && portmap[i].oc_pin >= 0) reg32 |= (1 << (i + 8 * portmap[i].oc_pin)); - write32(DEFAULT_RCBABASE + USBOCM1, reg32); + RCBA32(USBOCM1) = reg32; reg32 = 0; for (i = 8; i < 14; i++) if (portmap[i].enabled && portmap[i].oc_pin >= 4) reg32 |= (1 << (i - 8 + 8 * (portmap[i].oc_pin - 4))); - write32(DEFAULT_RCBABASE + USBOCM2, reg32); + RCBA32(USBOCM2) = reg32; for (i = 0; i < 22; i++) - write32(DEFAULT_RCBABASE + (0x35a8 + 4 * i), 0); + RCBA32(0x35a8 + 4 * i) = 0; - pci_write_config32(PCI_DEV(0, 0x14, 0), 0xe4, 0x00000000); + pci_write_config32(PCH_XHCI_DEV, 0xe4, 0x00000000); /* Relock registers. */ - outw(0, DEFAULT_PMBASE | UPRWC); + write_pmbase16(UPRWC, 0); } From 4998becda3e3e8033a84599158e180217e39d1bc Mon Sep 17 00:00:00 2001 From: Marius Genheimer Date: Tue, 30 Apr 2019 00:04:32 +0200 Subject: [PATCH 026/107] soc/skylake: Add missing PCH IDs Added IDs for: - H170 - Z170 - Q170 - Q150 - B150 Used documents: - 332690-005EN Tested on Gigabyte GA-Z170N-WIFI Change-Id: If20a2b764afa02785a97948893dbc5b5f60aff60 Signed-off-by: Marius Genheimer Reviewed-on: https://review.coreboot.org/c/coreboot/+/32517 Reviewed-by: Patrick Rudolph Reviewed-by: Angel Pons Reviewed-by: Felix Singer Tested-by: build bot (Jenkins) --- src/include/device/pci_ids.h | 5 +++++ src/soc/intel/common/block/lpc/lpc.c | 5 +++++ src/soc/intel/skylake/bootblock/report_platform.c | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h index 85bd6c3864..64539510ce 100644 --- a/src/include/device/pci_ids.h +++ b/src/include/device/pci_ids.h @@ -2689,6 +2689,11 @@ #define PCI_DEVICE_ID_INTEL_SPT_LP_U_BASE 0x9d43 #define PCI_DEVICE_ID_INTEL_SPT_LP_U_PREMIUM 0x9d48 #define PCI_DEVICE_ID_INTEL_SPT_LP_Y_PREMIUM 0x9d46 +#define PCI_DEVICE_ID_INTEL_SPT_H_H170 0xa144 +#define PCI_DEVICE_ID_INTEL_SPT_H_Z170 0xa145 +#define PCI_DEVICE_ID_INTEL_SPT_H_Q170 0xa146 +#define PCI_DEVICE_ID_INTEL_SPT_H_Q150 0xa147 +#define PCI_DEVICE_ID_INTEL_SPT_H_B150 0xa148 #define PCI_DEVICE_ID_INTEL_SPT_H_C236 0xa150 #define PCI_DEVICE_ID_INTEL_SPT_H_PREMIUM 0xa14e #define PCI_DEVICE_ID_INTEL_SPT_H_H110 0xa143 diff --git a/src/soc/intel/common/block/lpc/lpc.c b/src/soc/intel/common/block/lpc/lpc.c index d5f76f3a7b..43b3522431 100644 --- a/src/soc/intel/common/block/lpc/lpc.c +++ b/src/soc/intel/common/block/lpc/lpc.c @@ -127,6 +127,11 @@ static const unsigned short pci_device_ids[] = { PCI_DEVICE_ID_INTEL_SPT_H_C236, PCI_DEVICE_ID_INTEL_SPT_H_PREMIUM, PCI_DEVICE_ID_INTEL_SPT_H_H110, + PCI_DEVICE_ID_INTEL_SPT_H_H170, + PCI_DEVICE_ID_INTEL_SPT_H_Z170, + PCI_DEVICE_ID_INTEL_SPT_H_Q170, + PCI_DEVICE_ID_INTEL_SPT_H_Q150, + PCI_DEVICE_ID_INTEL_SPT_H_B150, PCI_DEVICE_ID_INTEL_SPT_H_QM170, PCI_DEVICE_ID_INTEL_SPT_H_HM175, PCI_DEVICE_ID_INTEL_SPT_H_QM175, diff --git a/src/soc/intel/skylake/bootblock/report_platform.c b/src/soc/intel/skylake/bootblock/report_platform.c index f79343508b..de845c7854 100644 --- a/src/soc/intel/skylake/bootblock/report_platform.c +++ b/src/soc/intel/skylake/bootblock/report_platform.c @@ -71,6 +71,11 @@ static struct { { PCI_DEVICE_ID_INTEL_SPT_LP_Y_PREMIUM, "Skylake-Y Premium" }, { PCI_DEVICE_ID_INTEL_SPT_H_PREMIUM, "Skylake PCH-H Premium" }, { PCI_DEVICE_ID_INTEL_SPT_H_H110, "Skylake PCH-H H110" }, + { PCI_DEVICE_ID_INTEL_SPT_H_H170, "Skylake PCH-H H170" }, + { PCI_DEVICE_ID_INTEL_SPT_H_Z170, "Skylake PCH-H Z170" }, + { PCI_DEVICE_ID_INTEL_SPT_H_Q170, "Skylake PCH-H Q170" }, + { PCI_DEVICE_ID_INTEL_SPT_H_Q150, "Skylake PCH-H Q150" }, + { PCI_DEVICE_ID_INTEL_SPT_H_B150, "Skylake PCH-H B150" }, { PCI_DEVICE_ID_INTEL_SPT_H_C236, "Skylake PCH-H C236" }, { PCI_DEVICE_ID_INTEL_SPT_H_QM170, "Skylake PCH-H QM170" }, { PCI_DEVICE_ID_INTEL_SPT_H_HM175, "Skylake PCH-H HM175" }, From 5471be69b9168d3dbceac064522522a97ed1a0db Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Mon, 29 Apr 2019 15:05:08 +0200 Subject: [PATCH 027/107] soc/intel/braswell/Makefile.inc: Remove commented-out line cpu_microcode_bins is commented out. Remove this line. BUG=NA TEST=Portwell PQ7-M107 Change-Id: Ic398d232bea84a765fce940ef876916a873e561f Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/32510 Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- src/soc/intel/braswell/Makefile.inc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/soc/intel/braswell/Makefile.inc b/src/soc/intel/braswell/Makefile.inc index a7ed4c5388..a2b7ee5e67 100644 --- a/src/soc/intel/braswell/Makefile.inc +++ b/src/soc/intel/braswell/Makefile.inc @@ -52,8 +52,6 @@ smm-y += smihandler.c smm-y += spi.c smm-y += tsc_freq.c -# cpu_microcode_bins += ??? - CPPFLAGS_common += -I$(src)/soc/intel/braswell/ CPPFLAGS_common += -I$(src)/soc/intel/braswell/include CPPFLAGS_common += -I$(call strip_quotes,$(CONFIG_FSP_HEADER_PATH)) From fb0fa7643eab9d81626c375a1b3b8d11138dd979 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Tue, 30 Apr 2019 17:27:40 -0600 Subject: [PATCH 028/107] sb/amd/rs780: Use 32 bit variable to avoid truncation The {read,write}_index functions expect a 32 bit value, as do the bitwise operations. Found-by: Coverity Scan #1229584 Signed-off-by: Jacob Garber Change-Id: Idc2bc46c899d5a4e8b089644dca076a88d97dd7c Reviewed-on: https://review.coreboot.org/c/coreboot/+/32528 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes --- src/southbridge/amd/rs780/ht.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/southbridge/amd/rs780/ht.c b/src/southbridge/amd/rs780/ht.c index 94df2337c1..8943fc1300 100644 --- a/src/southbridge/amd/rs780/ht.c +++ b/src/southbridge/amd/rs780/ht.c @@ -24,24 +24,24 @@ void avoid_lpc_dma_deadlock(struct device *nb_dev, struct device *sb_dev) { struct device *cpu_f0; - u8 reg; + u32 reg32; cpu_f0 = pcidev_on_root(0x18, 0); set_nbcfg_enable_bits(cpu_f0, 0x68, 3 << 21, 1 << 21); - reg = nbpcie_p_read_index(sb_dev, 0x10); - reg |= 0x100; /* bit9=1 */ - nbpcie_p_write_index(sb_dev, 0x10, reg); + reg32 = nbpcie_p_read_index(sb_dev, 0x10); + reg32 |= 0x100; /* bit9=1 */ + nbpcie_p_write_index(sb_dev, 0x10, reg32); - reg = nbpcie_p_read_index(nb_dev, 0x10); - reg |= 0x100; /* bit9=1 */ - nbpcie_p_write_index(nb_dev, 0x10, reg); + reg32 = nbpcie_p_read_index(nb_dev, 0x10); + reg32 |= 0x100; /* bit9=1 */ + nbpcie_p_write_index(nb_dev, 0x10, reg32); /* Enable NP protocol over PCIE for memory-mapped writes targeting LPC * Set this bit to avoid a deadlock condition. */ - reg = htiu_read_index(nb_dev, 0x6); - reg |= 0x1000000; /* bit26 */ - htiu_write_index(nb_dev, 0x6, reg); + reg32 = htiu_read_index(nb_dev, 0x6); + reg32 |= 0x1000000; /* bit26 */ + htiu_write_index(nb_dev, 0x6, reg32); } static void pcie_init(struct device *dev) From 32f48a2d56af951186538b6f6bcb136736f11254 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Thu, 2 May 2019 21:21:42 +0200 Subject: [PATCH 029/107] mb/google: Remove unused 'include ' Change-Id: Ib96c317391745fa5afea785e3c7441124b3fc252 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32547 Tested-by: build bot (Jenkins) Reviewed-by: Lijian Zhao --- src/mainboard/google/beltino/mainboard.c | 3 +-- src/mainboard/google/link/i915.c | 7 +++---- src/mainboard/google/stout/mainboard.c | 6 +++--- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/mainboard/google/beltino/mainboard.c b/src/mainboard/google/beltino/mainboard.c index e0fd105eb1..7bda2f6694 100644 --- a/src/mainboard/google/beltino/mainboard.c +++ b/src/mainboard/google/beltino/mainboard.c @@ -14,7 +14,6 @@ * GNU General Public License for more details. */ -#include #include #include #include @@ -25,8 +24,8 @@ #include #include #include -#include "onboard.h" +#include "onboard.h" void mainboard_suspend_resume(void) { diff --git a/src/mainboard/google/link/i915.c b/src/mainboard/google/link/i915.c index e09785d825..12d424cde0 100644 --- a/src/mainboard/google/link/i915.c +++ b/src/mainboard/google/link/i915.c @@ -25,19 +25,18 @@ #include #include #include -#include "onboard.h" -#include "ec.h" #include #include -#include #include #include - #include #include #include #include #include + +#include "ec.h" +#include "onboard.h" #include "i915io.h" enum { diff --git a/src/mainboard/google/stout/mainboard.c b/src/mainboard/google/stout/mainboard.c index 5f51a6b8bc..05de8cb63d 100644 --- a/src/mainboard/google/stout/mainboard.c +++ b/src/mainboard/google/stout/mainboard.c @@ -22,14 +22,14 @@ #include #include #include -#include "onboard.h" -#include "ec.h" #include -#include #include #include #include +#include "ec.h" +#include "onboard.h" + void mainboard_suspend_resume(void) { /* Stout EC needs to be put back in ACPI mode */ From 6a4a026e13ae7fa981243498df9db41a53a54096 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Mon, 29 Apr 2019 16:03:12 -0500 Subject: [PATCH 030/107] purism/librem_skl: remove 13v3 target, clean up Kconfig Remove the Librem 13v3 as a separate board; instead build a single firmware image for the 13 v2/v3 boards. Clean up Kconfig options: - remove entries for 13v3 board - fold entries into a single line where possible - remove redundant MAINBOARD_VERSION option (will default to 1.0) - remove unused microcode length/location (only needed for FSP CAR) Test: build/boot Librem 13 v2/v3 boards with same image Change-Id: Ic09b8ec5c576f4c4c48ef30ee3f60a4c2c286cd3 Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/32515 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/mainboard/purism/librem_skl/Kconfig | 38 ++++---------------- src/mainboard/purism/librem_skl/Kconfig.name | 6 +--- 2 files changed, 7 insertions(+), 37 deletions(-) diff --git a/src/mainboard/purism/librem_skl/Kconfig b/src/mainboard/purism/librem_skl/Kconfig index 965318f565..2372b9d280 100644 --- a/src/mainboard/purism/librem_skl/Kconfig +++ b/src/mainboard/purism/librem_skl/Kconfig @@ -19,11 +19,8 @@ config IRQ_SLOT_COUNT config VARIANT_DIR string - default "librem13v2" if BOARD_PURISM_LIBREM13_V2 - default "librem13v2" if BOARD_PURISM_LIBREM13_V3 - default "librem15v3" if BOARD_PURISM_LIBREM15_V3 - default "librem13v2" if BOARD_PURISM_LIBREM13_V4 - default "librem15v3" if BOARD_PURISM_LIBREM15_V4 + default "librem13v2" if BOARD_PURISM_LIBREM13_V2 || BOARD_PURISM_LIBREM13_V4 + default "librem15v3" if BOARD_PURISM_LIBREM15_V3 || BOARD_PURISM_LIBREM15_V4 config MAINBOARD_VENDOR string @@ -31,28 +28,16 @@ config MAINBOARD_VENDOR config MAINBOARD_FAMILY string - default "Librem 13" if BOARD_PURISM_LIBREM13_V2 - default "Librem 13" if BOARD_PURISM_LIBREM13_V3 - default "Librem 15" if BOARD_PURISM_LIBREM15_V3 - default "Librem 13" if BOARD_PURISM_LIBREM13_V4 - default "Librem 15" if BOARD_PURISM_LIBREM15_V4 + default "Librem 13" if BOARD_PURISM_LIBREM13_V2 || BOARD_PURISM_LIBREM13_V4 + default "Librem 15" if BOARD_PURISM_LIBREM15_V3 || BOARD_PURISM_LIBREM15_V4 config MAINBOARD_PART_NUMBER string default "Librem 13 v2" if BOARD_PURISM_LIBREM13_V2 - default "Librem 13 v2" if BOARD_PURISM_LIBREM13_V3 default "Librem 15 v3" if BOARD_PURISM_LIBREM15_V3 default "Librem 13 v4" if BOARD_PURISM_LIBREM13_V4 default "Librem 15 v4" if BOARD_PURISM_LIBREM15_V4 -config MAINBOARD_VERSION - string - default "2.0" if BOARD_PURISM_LIBREM13_V2 - default "3.0" if BOARD_PURISM_LIBREM13_V3 - default "3.0" if BOARD_PURISM_LIBREM15_V3 - default "4.0" if BOARD_PURISM_LIBREM13_V4 - default "4.0" if BOARD_PURISM_LIBREM15_V4 - config MAINBOARD_DIR string default "purism/librem_skl" @@ -67,11 +52,8 @@ config MAX_CPUS config VGA_BIOS_ID string - default "8086,1916" if BOARD_PURISM_LIBREM13_V2 - default "8086,1916" if BOARD_PURISM_LIBREM13_V3 - default "8086,1916" if BOARD_PURISM_LIBREM15_V3 - default "8086,5916" if BOARD_PURISM_LIBREM13_V4 - default "8086,5916" if BOARD_PURISM_LIBREM15_V4 + default "8086,1916" if BOARD_PURISM_LIBREM13_V2 || BOARD_PURISM_LIBREM15_V3 + default "8086,5916" if BOARD_PURISM_LIBREM13_V4 || BOARD_PURISM_LIBREM15_V4 config DIMM_MAX int @@ -81,14 +63,6 @@ config DIMM_SPD_SIZE int default 512 -config CPU_MICROCODE_CBFS_LEN - hex - default 0x18000 - -config CPU_MICROCODE_CBFS_LOC - hex - default 0xFFE115A0 - config CBFS_SIZE hex default 0xe00000 diff --git a/src/mainboard/purism/librem_skl/Kconfig.name b/src/mainboard/purism/librem_skl/Kconfig.name index 5b82de7435..b0dac3e338 100644 --- a/src/mainboard/purism/librem_skl/Kconfig.name +++ b/src/mainboard/purism/librem_skl/Kconfig.name @@ -1,9 +1,5 @@ config BOARD_PURISM_LIBREM13_V2 - bool "Librem 13 v2" - select BOARD_PURISM_BASEBOARD_LIBREM_SKL - -config BOARD_PURISM_LIBREM13_V3 - bool "Librem 13 v3" + bool "Librem 13 v2/v3" select BOARD_PURISM_BASEBOARD_LIBREM_SKL config BOARD_PURISM_LIBREM15_V3 From 9d3fa7a22985a2ae080a8e36c89107691d15174f Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Wed, 1 May 2019 18:44:54 -0700 Subject: [PATCH 031/107] spd_bin: Do not depend CONFIG_DIMM_MAX on CONFIG_GENERIC_SPD_BIN I can't claim that I really understand what this code does, but it looks like there are platforms that use code from lib/spd_bin.c without enabling CONFIG_GENERIC_SPD_BIN. Some functions in that file contain references to CONFIG_DIMM_MAX, so that option probably shouldn't depend on CONFIG_GENERIC_SPD_BIN. Change-Id: I041c52b6bd255e9a9920e5a101165ba5fc5fa6f3 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32548 Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Kconfig b/src/Kconfig index 05875b6327..b4898bd456 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -1153,7 +1153,6 @@ config GENERIC_SPD_BIN config DIMM_MAX int default 4 - depends on GENERIC_SPD_BIN help Total number of memory DIMM slots available on motherboard. It is multiplication of number of channel to number of DIMMs per From 7c712bbb6c969ae7014707bfddedd821035a2171 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Wed, 1 May 2019 16:51:20 -0700 Subject: [PATCH 032/107] Fix code that would trip -Wtype-limits This patch fixes up all code that would throw a -Wtype-limits warning. This sometimes involves eliminating unnecessary checks, adding a few odd but harmless casts or just pragma'ing out the warning for a whole file -- I tried to find the path of least resistance. I think the overall benefit of the warning outweighs the occasional weirdness. Change-Id: Iacd37eb1fad388d9db7267ceccb03e6dcf1ad0d2 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32537 Reviewed-by: Paul Menzel Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/console/vtxprintf.c | 8 +++++--- src/drivers/intel/fsp2_0/ppi/mp_service_ppi.c | 9 --------- src/drivers/pc80/rtc/mc146818rtc.c | 3 +++ src/drivers/spi/spi_flash.c | 2 +- src/mainboard/google/foster/pmic.c | 16 ---------------- src/mainboard/google/octopus/romstage.c | 2 +- .../google/octopus/variants/baseboard/memory.c | 2 +- src/mainboard/google/smaug/pmic.c | 16 ---------------- src/soc/intel/broadwell/lpc.c | 2 +- src/soc/qualcomm/ipq40xx/qup.c | 3 +-- src/soc/qualcomm/ipq40xx/spi.c | 4 ++-- src/soc/qualcomm/ipq806x/qup.c | 3 +-- src/soc/qualcomm/ipq806x/spi.c | 4 ++-- src/soc/rockchip/common/spi.c | 6 +++--- src/soc/samsung/exynos5420/spi.c | 2 +- src/southbridge/intel/lynxpoint/lpc.c | 2 +- .../amd/agesa/f12/Proc/GNB/Nb/NbSmuLib.c | 1 - .../amd/agesa/f14/Proc/GNB/Nb/NbSmuLib.c | 1 - .../f15tn/Proc/CPU/Family/0x15/TN/cpuF15TnDmi.c | 2 +- .../Proc/IDS/Family/0x15/TN/IdsF15TnAllService.c | 3 +++ .../f16kb/Proc/CPU/Family/0x16/KB/F16KbDmi.c | 2 +- .../Proc/IDS/Family/0x16/KB/IdsF16KbAllService.c | 3 +++ .../amd/agesa/f16kb/Proc/Mem/Ps/mpmaxfreq.c | 2 +- 23 files changed, 32 insertions(+), 66 deletions(-) diff --git a/src/console/vtxprintf.c b/src/console/vtxprintf.c index 043a1dae37..f42ed6d077 100644 --- a/src/console/vtxprintf.c +++ b/src/console/vtxprintf.c @@ -56,8 +56,10 @@ static int number(void (*tx_byte)(unsigned char byte, void *data), int count = 0; #ifdef SUPPORT_64BIT_INTS unsigned long long num = inum; + long long snum = num; #else - unsigned long num = (long)inum; + unsigned long num = (unsigned long)inum; + long snum = (long)num; if (num != inum) { /* Alert user to an incorrect result by printing #^!. */ @@ -76,9 +78,9 @@ static int number(void (*tx_byte)(unsigned char byte, void *data), c = (type & ZEROPAD) ? '0' : ' '; sign = 0; if (type & SIGN) { - if ((signed long long)num < 0) { + if (snum < 0) { sign = '-'; - num = -num; + num = -snum; size--; } else if (type & PLUS) { sign = '+'; diff --git a/src/drivers/intel/fsp2_0/ppi/mp_service_ppi.c b/src/drivers/intel/fsp2_0/ppi/mp_service_ppi.c index e26701b099..cdc98e06de 100644 --- a/src/drivers/intel/fsp2_0/ppi/mp_service_ppi.c +++ b/src/drivers/intel/fsp2_0/ppi/mp_service_ppi.c @@ -45,9 +45,6 @@ static efi_return_status_t mp_get_processor_info(const efi_uintn_t processor_number, efi_processor_information *processor_info_buffer) { - if (cpu_index() < 0) - return FSP_DEVICE_ERROR; - if (processor_info_buffer == NULL) return FSP_INVALID_PARAMETER; @@ -71,9 +68,6 @@ static efi_return_status_t mp_startup_all_aps(const efi_ap_procedure procedure, efi_boolean_t ignored3, efi_uintn_t timeout_usec, void *argument) { - if (cpu_index() < 0) - return FSP_DEVICE_ERROR; - if (procedure == NULL) return FSP_INVALID_PARAMETER; @@ -91,9 +85,6 @@ static efi_return_status_t mp_startup_this_ap(const efi_ap_procedure procedure, efi_uintn_t processor_number, efi_uintn_t timeout_usec, void *argument) { - if (cpu_index() < 0) - return FSP_DEVICE_ERROR; - if (processor_number > get_cpu_count()) return FSP_NOT_FOUND; diff --git a/src/drivers/pc80/rtc/mc146818rtc.c b/src/drivers/pc80/rtc/mc146818rtc.c index 99079b985e..6e37cd2f78 100644 --- a/src/drivers/pc80/rtc/mc146818rtc.c +++ b/src/drivers/pc80/rtc/mc146818rtc.c @@ -39,6 +39,9 @@ #define LB_CKS_LOC 0 #endif +/* Don't warn for checking >= LB_CKS_RANGE_START even though it may be 0. */ +#pragma GCC diagnostic ignored "-Wtype-limits" + #include #if (defined(__PRE_RAM__) && \ diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c index fc831c3e9c..ae1d2efb22 100644 --- a/src/drivers/spi/spi_flash.c +++ b/src/drivers/spi/spi_flash.c @@ -339,7 +339,7 @@ int spi_flash_generic_probe(const struct spi_slave *spi, printk(BIOS_INFO, "Manufacturer: %02x\n", *idp); /* search the table for matches in shift and id */ - for (i = 0; i < ARRAY_SIZE(flashes); ++i) + for (i = 0; i < (int)ARRAY_SIZE(flashes); ++i) if (flashes[i].shift == shift && flashes[i].idcode == *idp) { /* we have a match, call probe */ if (flashes[i].probe(spi, idp, flash) == 0) { diff --git a/src/mainboard/google/foster/pmic.c b/src/mainboard/google/foster/pmic.c index e3efd34529..13e2a4743f 100644 --- a/src/mainboard/google/foster/pmic.c +++ b/src/mainboard/google/foster/pmic.c @@ -34,10 +34,6 @@ struct max77620_init_reg { u8 delay; }; -static struct max77620_init_reg init_list[] = { - /* TODO */ -}; - static void pmic_write_reg(unsigned bus, uint8_t reg, uint8_t val, int delay) { if (i2c_writeb(bus, MAX77620_I2C_ADDR, reg, val)) { @@ -51,20 +47,8 @@ static void pmic_write_reg(unsigned bus, uint8_t reg, uint8_t val, int delay) } } -static void pmic_slam_defaults(unsigned bus) -{ - int i; - for (i = 0; i < ARRAY_SIZE(init_list); i++) { - struct max77620_init_reg *reg = &init_list[i]; - pmic_write_reg(bus, reg->reg, reg->val, reg->delay); - } -} - void pmic_init(unsigned bus) { - /* Restore PMIC POR defaults, in case kernel changed 'em */ - pmic_slam_defaults(bus); - /* Setup/Enable GPIO5 - VDD_CPU_REG_EN */ pmic_write_reg(bus, MAX77620_GPIO5_REG, 0x09, 1); diff --git a/src/mainboard/google/octopus/romstage.c b/src/mainboard/google/octopus/romstage.c index 9d8b94d0b9..ff0354dc10 100644 --- a/src/mainboard/google/octopus/romstage.c +++ b/src/mainboard/google/octopus/romstage.c @@ -44,7 +44,7 @@ void mainboard_save_dimm_info(void) if (!CONFIG(DRAM_PART_NUM_ALWAYS_IN_CBI)) { /* Fall back on part numbers encoded in lp4cfg array. */ - if (board_id() < CONFIG_DRAM_PART_IN_CBI_BOARD_ID_MIN) { + if ((int)board_id() < CONFIG_DRAM_PART_IN_CBI_BOARD_ID_MIN) { save_dimm_info_by_sku_config(); return; } diff --git a/src/mainboard/google/octopus/variants/baseboard/memory.c b/src/mainboard/google/octopus/variants/baseboard/memory.c index aec2ba2a4f..fc7c87dcb2 100644 --- a/src/mainboard/google/octopus/variants/baseboard/memory.c +++ b/src/mainboard/google/octopus/variants/baseboard/memory.c @@ -210,7 +210,7 @@ const struct lpddr4_cfg *__weak variant_lpddr4_config(void) if (!CONFIG(DRAM_PART_NUM_ALWAYS_IN_CBI)) { /* Fall back non cbi memory config. */ - if (board_id() < CONFIG_DRAM_PART_IN_CBI_BOARD_ID_MIN) + if ((int)board_id() < CONFIG_DRAM_PART_IN_CBI_BOARD_ID_MIN) return &non_cbi_lp4cfg; } diff --git a/src/mainboard/google/smaug/pmic.c b/src/mainboard/google/smaug/pmic.c index d9dacb7d08..9add211ccd 100644 --- a/src/mainboard/google/smaug/pmic.c +++ b/src/mainboard/google/smaug/pmic.c @@ -36,10 +36,6 @@ struct max77620_init_reg { u8 delay; }; -static struct max77620_init_reg init_list[] = { - /* TODO */ -}; - static void pmic_write_reg(unsigned bus, uint8_t chip, uint8_t reg, uint8_t val, int delay) { @@ -66,20 +62,8 @@ static inline void pmic_write_reg_77621(unsigned bus, uint8_t reg, uint8_t val, pmic_write_reg(bus, MAX77621_CPU_I2C_ADDR, reg, val, delay); } -static void pmic_slam_defaults(unsigned bus) -{ - int i; - for (i = 0; i < ARRAY_SIZE(init_list); i++) { - struct max77620_init_reg *reg = &init_list[i]; - pmic_write_reg_77620(bus, reg->reg, reg->val, reg->delay); - } -} - void pmic_init(unsigned bus) { - /* Restore PMIC POR defaults, in case kernel changed 'em */ - pmic_slam_defaults(bus); - /* MAX77620: Set SD0 to 1.0V - VDD_CORE */ pmic_write_reg_77620(bus, MAX77620_SD0_REG, 0x20, 1); pmic_write_reg_77620(bus, MAX77620_VDVSSD0_REG, 0x20, 1); diff --git a/src/soc/intel/broadwell/lpc.c b/src/soc/intel/broadwell/lpc.c index 8438ab45db..7679724ece 100644 --- a/src/soc/intel/broadwell/lpc.c +++ b/src/soc/intel/broadwell/lpc.c @@ -502,7 +502,7 @@ static void pch_lpc_add_mmio_resources(struct device *dev) #define LPC_DEFAULT_IO_RANGE_LOWER 0 #define LPC_DEFAULT_IO_RANGE_UPPER 0x1000 -static inline int pch_io_range_in_default(u16 base, u16 size) +static inline int pch_io_range_in_default(int base, int size) { /* Does it start above the range? */ if (base >= LPC_DEFAULT_IO_RANGE_UPPER) diff --git a/src/soc/qualcomm/ipq40xx/qup.c b/src/soc/qualcomm/ipq40xx/qup.c index 9d1f92d48a..438bd14757 100644 --- a/src/soc/qualcomm/ipq40xx/qup.c +++ b/src/soc/qualcomm/ipq40xx/qup.c @@ -478,8 +478,7 @@ qup_return_t qup_set_state(blsp_qup_id_t id, uint32_t state) qup_return_t ret = QUP_ERR_UNDEFINED; unsigned curr_state = read32(QUP_ADDR(id, QUP_STATE)); - if ((state >= QUP_STATE_RESET && state <= QUP_STATE_PAUSE) - && (curr_state & QUP_STATE_VALID_MASK)) { + if (state <= QUP_STATE_PAUSE && (curr_state & QUP_STATE_VALID_MASK)) { /* * For PAUSE_STATE to RESET_STATE transition, * two writes of 10[binary]) are required for the diff --git a/src/soc/qualcomm/ipq40xx/spi.c b/src/soc/qualcomm/ipq40xx/spi.c index 109eda9fc0..b68e1cb864 100644 --- a/src/soc/qualcomm/ipq40xx/spi.c +++ b/src/soc/qualcomm/ipq40xx/spi.c @@ -648,8 +648,8 @@ static int spi_ctrlr_setup(const struct spi_slave *slave) { struct ipq_spi_slave *ds = NULL; int i; - unsigned int bus = slave->bus; - unsigned int cs = slave->cs; + int bus = slave->bus; + int cs = slave->cs; if ((bus < BLSP0_SPI) || (bus > BLSP1_SPI) || ((bus == BLSP0_SPI) && (cs > 2)) diff --git a/src/soc/qualcomm/ipq806x/qup.c b/src/soc/qualcomm/ipq806x/qup.c index 872b264cfa..3ceb84d881 100644 --- a/src/soc/qualcomm/ipq806x/qup.c +++ b/src/soc/qualcomm/ipq806x/qup.c @@ -379,8 +379,7 @@ qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state) qup_return_t ret = QUP_ERR_UNDEFINED; unsigned curr_state = read32(QUP_ADDR(gsbi_id, QUP_STATE)); - if ((state >= QUP_STATE_RESET && state <= QUP_STATE_PAUSE) - && (curr_state & QUP_STATE_VALID_MASK)) { + if (state <= QUP_STATE_PAUSE && (curr_state & QUP_STATE_VALID_MASK)) { /* * For PAUSE_STATE to RESET_STATE transition, * two writes of 10[binary]) are required for the diff --git a/src/soc/qualcomm/ipq806x/spi.c b/src/soc/qualcomm/ipq806x/spi.c index 657734524c..2657b9c574 100644 --- a/src/soc/qualcomm/ipq806x/spi.c +++ b/src/soc/qualcomm/ipq806x/spi.c @@ -760,8 +760,8 @@ static int spi_ctrlr_setup(const struct spi_slave *slave) { struct ipq_spi_slave *ds = NULL; int i; - unsigned int bus = slave->bus; - unsigned int cs = slave->cs; + int bus = slave->bus; + int cs = slave->cs; /* * IPQ GSBI (Generic Serial Bus Interface) supports SPI Flash diff --git a/src/soc/rockchip/common/spi.c b/src/soc/rockchip/common/spi.c index 98016c0fc9..e929419a14 100644 --- a/src/soc/rockchip/common/spi.c +++ b/src/soc/rockchip/common/spi.c @@ -96,7 +96,7 @@ static void rockchip_spi_set_clk(struct rockchip_spi *regs, unsigned int hz) void rockchip_spi_init(unsigned int bus, unsigned int speed_hz) { - assert(bus >= 0 && bus < ARRAY_SIZE(rockchip_spi_slaves)); + assert(bus < ARRAY_SIZE(rockchip_spi_slaves)); struct rockchip_spi *regs = rockchip_spi_slaves[bus].regs; unsigned int ctrlr0 = 0; @@ -134,13 +134,13 @@ void rockchip_spi_init(unsigned int bus, unsigned int speed_hz) void rockchip_spi_set_sample_delay(unsigned int bus, unsigned int delay_ns) { - assert(bus >= 0 && bus < ARRAY_SIZE(rockchip_spi_slaves)); + assert(bus < ARRAY_SIZE(rockchip_spi_slaves)); struct rockchip_spi *regs = rockchip_spi_slaves[bus].regs; unsigned int rsd; /* Rxd Sample Delay */ rsd = DIV_ROUND_CLOSEST(delay_ns * (SPI_SRCCLK_HZ >> 8), 1*GHz >> 8); - assert(rsd >= 0 && rsd <= 3); + assert(rsd <= 3); clrsetbits_le32(®s->ctrlr0, SPI_RXDSD_MASK << SPI_RXDSD_OFFSET, rsd << SPI_RXDSD_OFFSET); } diff --git a/src/soc/samsung/exynos5420/spi.c b/src/soc/samsung/exynos5420/spi.c index 753a24be19..1903f6b3b9 100644 --- a/src/soc/samsung/exynos5420/spi.c +++ b/src/soc/samsung/exynos5420/spi.c @@ -206,7 +206,7 @@ static void spi_ctrlr_release_bus(const struct spi_slave *slave) static int spi_ctrlr_setup(const struct spi_slave *slave) { - ASSERT(slave->bus >= 0 && slave->bus < 3); + ASSERT(slave->bus < 3); struct exynos_spi_slave *eslave; eslave = to_exynos_spi(slave); diff --git a/src/southbridge/intel/lynxpoint/lpc.c b/src/southbridge/intel/lynxpoint/lpc.c index e8cad388d5..951c69c11c 100644 --- a/src/southbridge/intel/lynxpoint/lpc.c +++ b/src/southbridge/intel/lynxpoint/lpc.c @@ -623,7 +623,7 @@ static void pch_lpc_add_mmio_resources(struct device *dev) #define LPC_DEFAULT_IO_RANGE_LOWER 0 #define LPC_DEFAULT_IO_RANGE_UPPER 0x1000 -static inline int pch_io_range_in_default(u16 base, u16 size) +static inline int pch_io_range_in_default(int base, int size) { /* Does it start above the range? */ if (base >= LPC_DEFAULT_IO_RANGE_UPPER) diff --git a/src/vendorcode/amd/agesa/f12/Proc/GNB/Nb/NbSmuLib.c b/src/vendorcode/amd/agesa/f12/Proc/GNB/Nb/NbSmuLib.c index 37c9ff19bd..3bf8de5d71 100644 --- a/src/vendorcode/amd/agesa/f12/Proc/GNB/Nb/NbSmuLib.c +++ b/src/vendorcode/amd/agesa/f12/Proc/GNB/Nb/NbSmuLib.c @@ -527,7 +527,6 @@ NbSmuReadEfuseField ( UINT32 Address; UINT16 Shift; ASSERT (Length <= 32); - ASSERT (Chain <= 0xff); Shift = (Offset - (Offset & ~0x7)); Address = 0xFE000000 | (Chain << 12) | (Offset >> 3); Value = NbSmuReadEfuse (Address, StdHeader); diff --git a/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/NbSmuLib.c b/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/NbSmuLib.c index 76401d435c..bf1396de55 100644 --- a/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/NbSmuLib.c +++ b/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/NbSmuLib.c @@ -506,7 +506,6 @@ NbSmuReadEfuseField ( UINT32 Address; UINT16 Shift; ASSERT (Length <= 32); - ASSERT (Chain <= 0xff); Shift = (Offset - (Offset & ~0x7)); Address = 0xFE000000 | (Chain << 12) | (Offset >> 3); Value = NbSmuReadEfuse (Address, StdHeader); diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/CPU/Family/0x15/TN/cpuF15TnDmi.c b/src/vendorcode/amd/agesa/f15tn/Proc/CPU/Family/0x15/TN/cpuF15TnDmi.c index 7b7fa0dd91..b0f98cf01c 100644 --- a/src/vendorcode/amd/agesa/f15tn/Proc/CPU/Family/0x15/TN/cpuF15TnDmi.c +++ b/src/vendorcode/amd/agesa/f15tn/Proc/CPU/Family/0x15/TN/cpuF15TnDmi.c @@ -331,7 +331,7 @@ DmiF15TnGetVoltage ( LibAmdMsrRead ((MSR_PSTATE_0 + NumberBoostStates), &MsrData, StdHeader); MaxVid = (UINT8) (((PSTATE_MSR *)&MsrData)->CpuVid); - if ((MaxVid >= 0xF8) && (MaxVid <= 0xFF)) { + if ((MaxVid >= 0xF8)) { Voltage = 0; } else { Voltage = (UINT8) ((155000L - (625 * MaxVid) + 5000) / 10000); diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/IDS/Family/0x15/TN/IdsF15TnAllService.c b/src/vendorcode/amd/agesa/f15tn/Proc/IDS/Family/0x15/TN/IdsF15TnAllService.c index 5e76e9a88a..a7cb9547dc 100644 --- a/src/vendorcode/amd/agesa/f15tn/Proc/IDS/Family/0x15/TN/IdsF15TnAllService.c +++ b/src/vendorcode/amd/agesa/f15tn/Proc/IDS/Family/0x15/TN/IdsF15TnAllService.c @@ -62,6 +62,9 @@ CODE_GROUP (G3_DXE) RDATA_GROUP (G3_DXE) +/* Don't warn when checking header-defined ranges that may start at 0. */ +#pragma GCC diagnostic ignored "-Wtype-limits" + #define FILECODE PROC_IDS_FAMILY_0X15_TN_IDSF15TNALLSERVICE_FILECODE /** diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Family/0x16/KB/F16KbDmi.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Family/0x16/KB/F16KbDmi.c index 45b1b8f418..6e8e6f06ab 100644 --- a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Family/0x16/KB/F16KbDmi.c +++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Family/0x16/KB/F16KbDmi.c @@ -287,7 +287,7 @@ DmiF16KbGetVoltage ( LibAmdMsrRead ((MSR_PSTATE_0 + NumberBoostStates), &MsrData, StdHeader); MaxVid = (UINT8) (((PSTATE_MSR *)&MsrData)->CpuVid); - if ((MaxVid >= 0xF8) && (MaxVid <= 0xFF)) { + if ((MaxVid >= 0xF8)) { Voltage = 0; } else { Voltage = (UINT8) ((155000L - (625 * MaxVid) + 5000) / 10000); diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/IDS/Family/0x16/KB/IdsF16KbAllService.c b/src/vendorcode/amd/agesa/f16kb/Proc/IDS/Family/0x16/KB/IdsF16KbAllService.c index fddf8eb403..94e32a3743 100644 --- a/src/vendorcode/amd/agesa/f16kb/Proc/IDS/Family/0x16/KB/IdsF16KbAllService.c +++ b/src/vendorcode/amd/agesa/f16kb/Proc/IDS/Family/0x16/KB/IdsF16KbAllService.c @@ -63,6 +63,9 @@ CODE_GROUP (G3_DXE) RDATA_GROUP (G3_DXE) +/* Don't warn when checking header-defined ranges that may start at 0. */ +#pragma GCC diagnostic ignored "-Wtype-limits" + #define FILECODE PROC_IDS_FAMILY_0X16_KB_IDSF16KBALLSERVICE_FILECODE /** diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Ps/mpmaxfreq.c b/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Ps/mpmaxfreq.c index 1302396909..eba8263e34 100644 --- a/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Ps/mpmaxfreq.c +++ b/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Ps/mpmaxfreq.c @@ -136,7 +136,7 @@ MemPGetMaxFreqSupported ( UINT16 MaxFreqSupported; UINT16 *SpeedArray; UINT8 DDR3Voltage; - UINT8 CurrentVoltage; + INT8 CurrentVoltage; DIMM_TYPE DimmType; CPU_LOGICAL_ID LogicalCpuid; UINT8 PackageType; From c4ab50cdde4bfd01ec7509012b105c88bcf4c953 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Wed, 1 May 2019 16:48:44 -0700 Subject: [PATCH 033/107] Makefile.inc: Enable -Wtype-limits This patch enables -Wtype-limits for the whole repository, which disallows checking for a condition that must be always true or always false based on type width (e.g. checking whether an unsigned variable is negative or whether a 32-bit integer is larger than 4G). This helps avoid easy to make and hard to find (because they often only affect error paths) mistakes like size_t size = fmap_read_area(...); if (size < 0) die("If only the compiler could've told me to use ssize_t instead"); Change-Id: I19edabfd092d09dad720e3fc47b44838163bfe25 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32536 Reviewed-by: Paul Menzel Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc index a9aaaed783..9860da1b68 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -401,7 +401,7 @@ endif CFLAGS_common += -pipe -g -nostdinc -std=gnu11 CFLAGS_common += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs -CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time +CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time -Wtype-limits CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie ifeq ($(CONFIG_COMPILER_GCC),y) From e09caf6428bbda556df7089a46abcf7dd26bb3a3 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Thu, 2 May 2019 17:58:12 -0600 Subject: [PATCH 034/107] soc/amd/stoneyridge: Move acpi_fill_mcfg to northbridge Relocate the function to the more appropriate file. Change-Id: I92a3e8d0461ae228f6c01567db159e2458de5f6b Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/32550 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/soc/amd/stoneyridge/lpc.c | 13 ------------- src/soc/amd/stoneyridge/northbridge.c | 12 ++++++++++++ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/soc/amd/stoneyridge/lpc.c b/src/soc/amd/stoneyridge/lpc.c index 87da9f1271..9a8c8efdee 100644 --- a/src/soc/amd/stoneyridge/lpc.c +++ b/src/soc/amd/stoneyridge/lpc.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -326,18 +325,6 @@ static void lpc_enable_resources(struct device *dev) lpc_enable_childrens_resources(dev); } -unsigned long acpi_fill_mcfg(unsigned long current) -{ - - current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current, - CONFIG_MMCONF_BASE_ADDRESS, - 0, - 0, - CONFIG_MMCONF_BUS_NUMBER); - - return current; -} - static struct pci_operations lops_pci = { .set_subsystem = pci_dev_set_subsystem, }; diff --git a/src/soc/amd/stoneyridge/northbridge.c b/src/soc/amd/stoneyridge/northbridge.c index 42963c0941..5985832c81 100644 --- a/src/soc/amd/stoneyridge/northbridge.c +++ b/src/soc/amd/stoneyridge/northbridge.c @@ -176,6 +176,18 @@ static void northbridge_init(struct device *dev) setup_ioapic((u8 *)IO_APIC2_ADDR, CONFIG_MAX_CPUS+1); } +unsigned long acpi_fill_mcfg(unsigned long current) +{ + + current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current, + CONFIG_MMCONF_BASE_ADDRESS, + 0, + 0, + CONFIG_MMCONF_BUS_NUMBER); + + return current; +} + static unsigned long acpi_fill_hest(acpi_hest_t *hest) { void *addr, *current; From 1bc04e3c3edf5b1537b4846dea41a530a1b83016 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Thu, 2 May 2019 18:56:54 -0600 Subject: [PATCH 035/107] soc/amd/stoneyridge: Correct bugs in lpc.c Remove the bridge enable step of accessing D14F0x64. This method for enabling the bridge appears to be last present in the SB700 device. Beginning in the SB800 (and all FCH, SoC devices), the enable is in PMxEC[0]. Since the bridge is enabled in bootblock to allow port 80h, there is no need to maintain it in ramstage. Correct the device used for misc. configuration of the LPC bridge. The #defined value removed is 14.0 but the settings are in 14.3. TEST=Boot Grunt, check console and dmesg for errors and warnings BUG=b:131862871 Change-Id: I078be974dc3c78c94cb7c0832518f21bac029ff2 Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/32551 Tested-by: build bot (Jenkins) Reviewed-by: Richard Spiegel --- src/soc/amd/stoneyridge/lpc.c | 39 ++++++++++++----------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/src/soc/amd/stoneyridge/lpc.c b/src/soc/amd/stoneyridge/lpc.c index 9a8c8efdee..a838146c84 100644 --- a/src/soc/amd/stoneyridge/lpc.c +++ b/src/soc/amd/stoneyridge/lpc.c @@ -35,31 +35,22 @@ static void lpc_init(struct device *dev) { u8 byte; - u32 dword; - - /* - * Enable the LPC Controller - * SMBus register 0x64 is not defined in public datasheet. - */ - dword = pci_read_config32(SOC_SMBUS_DEV, 0x64); - dword |= 1 << 20; - pci_write_config32(SOC_SMBUS_DEV, 0x64, dword); /* Initialize isa dma */ isa_dma_init(); /* Enable DMA transaction on the LPC bus */ - byte = pci_read_config8(SOC_SMBUS_DEV, LPC_PCI_CONTROL); + byte = pci_read_config8(dev, LPC_PCI_CONTROL); byte |= LEGACY_DMA_EN; - pci_write_config8(SOC_SMBUS_DEV, LPC_PCI_CONTROL, byte); + pci_write_config8(dev, LPC_PCI_CONTROL, byte); /* Disable the timeout mechanism on LPC */ - byte = pci_read_config8(SOC_SMBUS_DEV, LPC_IO_OR_MEM_DECODE_ENABLE); + byte = pci_read_config8(dev, LPC_IO_OR_MEM_DECODE_ENABLE); byte &= ~LPC_SYNC_TIMEOUT_COUNT_ENABLE; - pci_write_config8(SOC_SMBUS_DEV, LPC_IO_OR_MEM_DECODE_ENABLE, byte); + pci_write_config8(dev, LPC_IO_OR_MEM_DECODE_ENABLE, byte); /* Disable LPC MSI Capability */ - byte = pci_read_config8(SOC_SMBUS_DEV, LPC_MISC_CONTROL_BITS); + byte = pci_read_config8(dev, LPC_MISC_CONTROL_BITS); /* BIT 1 is not defined in public datasheet. */ byte &= ~(1 << 1); @@ -69,15 +60,15 @@ static void lpc_init(struct device *dev) * interrupt and visit LPC. */ byte &= ~LPC_NOHOG; - pci_write_config8(SOC_SMBUS_DEV, LPC_MISC_CONTROL_BITS, byte); + pci_write_config8(dev, LPC_MISC_CONTROL_BITS, byte); /* * Enable hand-instance of the pulse generator and SPI * controller prefetch of flash. */ - byte = pci_read_config8(SOC_SMBUS_DEV, LPC_HOST_CONTROL); + byte = pci_read_config8(dev, LPC_HOST_CONTROL); byte |= PREFETCH_EN_SPI_FROM_HOST | T_START_ENH; - pci_write_config8(SOC_SMBUS_DEV, LPC_HOST_CONTROL, byte); + pci_write_config8(dev, LPC_HOST_CONTROL, byte); cmos_check_update_date(); @@ -161,9 +152,8 @@ static void lpc_set_resources(struct device *dev) pci_dev_set_resources(dev); } -static void set_child_resource(struct device *child, - u32 *reg, - u32 *reg_x) +static void set_child_resource(struct device *dev, struct device *child, + u32 *reg, u32 *reg_x) { struct resource *res; u32 base, end; @@ -272,7 +262,7 @@ static void set_child_resource(struct device *child, wideio_index = sb_set_wideio_range(base, res->size); if (wideio_index != WIDEIO_RANGE_ERROR) { /* preserve wide IO related bits. */ - *reg_x = pci_read_config32(SOC_LPC_DEV, + *reg_x = pci_read_config32(dev, LPC_IO_OR_MEM_DECODE_ENABLE); printk(BIOS_DEBUG, @@ -308,11 +298,8 @@ static void lpc_enable_childrens_resources(struct device *dev) for (child = link->children; child; child = child->sibling) { if (child->enabled - && (child->path.type == DEVICE_PATH_PNP)) { - set_child_resource(child, - ®, - ®_x); - } + && (child->path.type == DEVICE_PATH_PNP)) + set_child_resource(dev, child, ®, ®_x); } } pci_write_config32(dev, LPC_IO_PORT_DECODE_ENABLE, reg); From e59ae107c2156bcea84a1e5af7ac18a49dabca1b Mon Sep 17 00:00:00 2001 From: Felix Singer Date: Thu, 2 May 2019 13:57:57 +0200 Subject: [PATCH 036/107] soc/apollolake: Add ramstage hook A hook for romstage is already existing but not for ramstage. It's very useful for debugging as it allows to run code for testing purposes by the mainboard. Also, it allows to run configuration code or configure FSP options, which don't have a devicetree option. Change-Id: I9edc543943c5cbc696fc6c615cb77ef68294c980 Signed-off-by: Felix Singer Reviewed-on: https://review.coreboot.org/c/coreboot/+/32543 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- src/soc/intel/apollolake/chip.c | 9 +++++++ .../intel/apollolake/include/soc/ramstage.h | 26 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/soc/intel/apollolake/include/soc/ramstage.h diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c index c3de4ee802..279551f9e0 100644 --- a/src/soc/intel/apollolake/chip.c +++ b/src/soc/intel/apollolake/chip.c @@ -50,6 +50,7 @@ #include #include #include +#include #include "chip.h" @@ -762,6 +763,8 @@ void platform_fsp_silicon_init_params_cb(FSPS_UPD *silupd) /* Set VTD feature according to devicetree */ silconfig->VtdEnable = cfg->enable_vtd; + + mainboard_silicon_init_params(silconfig); } struct chip_operations soc_intel_apollolake_ops = { @@ -879,4 +882,10 @@ static void spi_flash_init_cb(void *unused) fast_spi_init(); } +__weak +void mainboard_silicon_init_params(FSP_S_CONFIG *silconfig) +{ + printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__); +} + BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, spi_flash_init_cb, NULL); diff --git a/src/soc/intel/apollolake/include/soc/ramstage.h b/src/soc/intel/apollolake/include/soc/ramstage.h new file mode 100644 index 0000000000..287f2ff945 --- /dev/null +++ b/src/soc/intel/apollolake/include/soc/ramstage.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Intel Corp. + * (Written by Andrey Petrov for Intel Corp.) + * Copyright (C) 2019 9elements Agency GmbH + * + * 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. + */ + +#ifndef _SOC_APOLLOLAKE_RAMSTAGE_H_ +#define _SOC_APOLLOLAKE_RAMSTAGE_H_ + +#include + +void mainboard_silicon_init_params(FSP_S_CONFIG *silconfig); + +#endif /* _SOC_APOLLOLAKE_RAMSTAGE_H_ */ From 7f1e9dbf3a951599cfa0b2decf0bb6540a666cbd Mon Sep 17 00:00:00 2001 From: Eric Lai Date: Thu, 2 May 2019 15:13:31 +0800 Subject: [PATCH 037/107] soc/intel/cannonlake/acpi: Add board level s0ix call back Add board level s0ix call back. Since some driver doesn't care _ON/_OFF method. Add a control method for s0ix usage. BUG=b:129177593 TEST=NA Signed-off-by: Eric Lai Change-Id: I404f388b19355ae89b36d1fb07f9fb4f97eb3b2d Reviewed-on: https://review.coreboot.org/c/coreboot/+/32539 Tested-by: build bot (Jenkins) Reviewed-by: Duncan Laurie Reviewed-by: Furquan Shaikh --- src/soc/intel/cannonlake/acpi/lpit.asl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/soc/intel/cannonlake/acpi/lpit.asl b/src/soc/intel/cannonlake/acpi/lpit.asl index 85158069b6..93bce2644e 100644 --- a/src/soc/intel/cannonlake/acpi/lpit.asl +++ b/src/soc/intel/cannonlake/acpi/lpit.asl @@ -14,6 +14,8 @@ * GNU General Public License for more details. */ +External(\_SB.MS0X, MethodObj) + scope(\_SB) { Device(LPID) { @@ -62,12 +64,20 @@ scope(\_SB) */ If(Arg2 == 5) { \_SB.PCI0.LPCB.EC0.S0IX(1) + /* provide board level s0ix hook */ + If (CondRefOf (\_SB.MS0X)) { + \_SB.MS0X(1) + } } /* * Function 6. */ If(Arg2 == 6) { \_SB.PCI0.LPCB.EC0.S0IX(0) + /* provide board level s0ix hook */ + If (CondRefOf (\_SB.MS0X)) { + \_SB.MS0X(0) + } } } Return(Buffer(One) {0x00}) From 6629b4bbf810e5d2e9323651acf8afb2936cf10b Mon Sep 17 00:00:00 2001 From: Karthikeyan Ramasubramanian Date: Wed, 1 May 2019 10:22:22 -0600 Subject: [PATCH 038/107] soc/intel/apollolake: Reset GPI IS & IE registers at ramstage Reset GPI Interrupt status and enable registers from ramstage instead of bootblock so that it applies to devices in field. BUG=b:130593883 BRANCH=octopus TEST=Ensure that the Interrupt status & enable registers are reset during the boot up when the system is brought out of G3, S5 & S3. Ensure that the system boots fine to ChromeOS. Change-Id: Ib11b580ceb23bd1fe789f549b667a8ced2d859a1 Signed-off-by: Karthikeyan Ramasubramanian Reviewed-on: https://review.coreboot.org/c/coreboot/+/32534 Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/soc/intel/apollolake/bootblock/bootblock.c | 9 --------- src/soc/intel/apollolake/chip.c | 6 ++++++ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/soc/intel/apollolake/bootblock/bootblock.c b/src/soc/intel/apollolake/bootblock/bootblock.c index c791378f13..ac6903a9d2 100644 --- a/src/soc/intel/apollolake/bootblock/bootblock.c +++ b/src/soc/intel/apollolake/bootblock/bootblock.c @@ -122,12 +122,3 @@ void bootblock_soc_early_init(void) paging_enable_for_car("pdpt", "pt"); } } - -void bootblock_soc_init(void) -{ - /* - * Clear the GPI interrupt enable & status registers to avoid any - * interrupt storm during the kernel bootup. - */ - gpi_clear_int_cfg(); -} diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c index 279551f9e0..f6880a7f3f 100644 --- a/src/soc/intel/apollolake/chip.c +++ b/src/soc/intel/apollolake/chip.c @@ -395,6 +395,12 @@ static void soc_init(void *data) * default policy that doesn't honor boards' requirements. */ itss_snapshot_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END); + /* + * Clear the GPI interrupt status and enable registers. These + * registers do not get reset to default state when booting from S5. + */ + gpi_clear_int_cfg(); + fsp_silicon_init(romstage_handoff_is_resume()); /* Restore GPIO IRQ polarities back to previous settings. */ From 78b58a4996d42191f5dc941f9c14fa07228acca1 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Sat, 28 Jul 2018 16:53:16 -0700 Subject: [PATCH 039/107] drivers/intel/fsp2_0: Fix fsp post-init validation Part of this checks whether tolum_base and cbmem_top are the same - however, cbmem_top hasn't been initialised at the point where this call occurs. Change the ordering to fix that. Signed-off-by: Matthew Garrett Change-Id: Ib89e0513bdc35c3751a9d4c2a2789a2836046789 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32530 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh Reviewed-by: Subrata Banik --- src/drivers/intel/fsp2_0/memory_init.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/drivers/intel/fsp2_0/memory_init.c b/src/drivers/intel/fsp2_0/memory_init.c index 985ee3a07f..b3afb98c4d 100644 --- a/src/drivers/intel/fsp2_0/memory_init.c +++ b/src/drivers/intel/fsp2_0/memory_init.c @@ -310,8 +310,6 @@ static void do_fsp_memory_init(struct fsp_header *hdr, bool s3wake, post_code(POST_FSP_MEMORY_EXIT); timestamp_add_now(TS_FSP_MEMORY_INIT_END); - fsp_debug_after_memory_init(status); - /* Handle any errors returned by FspMemoryInit */ fsp_handle_reset(status); if (status != FSP_SUCCESS) { @@ -320,6 +318,13 @@ static void do_fsp_memory_init(struct fsp_header *hdr, bool s3wake, } do_fsp_post_memory_init(s3wake, fsp_version); + + /* + * fsp_debug_after_memory_init() checks whether the end of the tolum + * region is the same as the top of cbmem, so must be called here + * after cbmem has been initialised in do_fsp_post_memory_init(). + */ + fsp_debug_after_memory_init(status); } /* Load the binary into the memory specified by the info header. */ From a06fa32daf216c6fcd35a1412b2c476031191aec Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Sat, 4 May 2019 13:05:58 +0200 Subject: [PATCH 040/107] arch/x86: Remove unused file The file is no longer used by any code. Remove it. Change-Id: I73f06cac11201dc37218d352ab995cf4f012c36a Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/32584 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes --- src/arch/x86/stages.c | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 src/arch/x86/stages.c diff --git a/src/arch/x86/stages.c b/src/arch/x86/stages.c deleted file mode 100644 index b4d0723e16..0000000000 --- a/src/arch/x86/stages.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 coresystems GmbH - * - * 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; version 2 of the License. - * - * 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. - */ - -static void skip_romstage(void) -{ - asm volatile ( - "jmp __main\n" - ); -} From b4951c92a1070123e3c56571481dc1a20f09657a Mon Sep 17 00:00:00 2001 From: Bluemax <1403092+BlueMax@users.noreply.github.com> Date: Sun, 7 Apr 2019 00:18:42 +0200 Subject: [PATCH 041/107] Documentation: Add MSI MS-7707 Change-Id: Iba38bda9becba9fcffb51afc4756023659f092ef Signed-off-by: Max Blau Reviewed-on: https://review.coreboot.org/c/coreboot/+/32236 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- Documentation/mainboard/index.md | 4 + .../mainboard/msi/ms7707/J1-flash-protect.jpg | Bin 0 -> 240521 bytes .../msi/ms7707/JSPI1-Winbond-W25Q32BVSIG.jpg | Bin 0 -> 150406 bytes .../mainboard/msi/ms7707/JSPI1-connected.jpg | Bin 0 -> 83025 bytes Documentation/mainboard/msi/ms7707/JSPI1.png | Bin 0 -> 38818 bytes .../mainboard/msi/ms7707/flashlayout.svg | 34 ++++++ Documentation/mainboard/msi/ms7707/ms7707.md | 112 ++++++++++++++++++ 7 files changed, 150 insertions(+) create mode 100644 Documentation/mainboard/msi/ms7707/J1-flash-protect.jpg create mode 100644 Documentation/mainboard/msi/ms7707/JSPI1-Winbond-W25Q32BVSIG.jpg create mode 100644 Documentation/mainboard/msi/ms7707/JSPI1-connected.jpg create mode 100644 Documentation/mainboard/msi/ms7707/JSPI1.png create mode 100644 Documentation/mainboard/msi/ms7707/flashlayout.svg create mode 100644 Documentation/mainboard/msi/ms7707/ms7707.md diff --git a/Documentation/mainboard/index.md b/Documentation/mainboard/index.md index 7eaf425e20..9af5c80883 100644 --- a/Documentation/mainboard/index.md +++ b/Documentation/mainboard/index.md @@ -70,6 +70,10 @@ The boards in this section are not real mainboards, but emulators. - [T430 / T530 / X230 / W530 common](lenovo/xx30_series.md) - [T431s](lenovo/t431s.md) +## MSI + +- [MS-7707](msi/ms7707/ms7707.md) + ## SiFive - [SiFive HiFive Unleashed](sifive/hifive-unleashed.md) diff --git a/Documentation/mainboard/msi/ms7707/J1-flash-protect.jpg b/Documentation/mainboard/msi/ms7707/J1-flash-protect.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b649d059a81ee610e56b2dd623a10958bb20c81d GIT binary patch literal 240521 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 literal 0 HcmV?d00001 diff --git a/Documentation/mainboard/msi/ms7707/JSPI1-Winbond-W25Q32BVSIG.jpg b/Documentation/mainboard/msi/ms7707/JSPI1-Winbond-W25Q32BVSIG.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7a0df71dd777b06e4b5025cbbc234ab3c573693f GIT binary patch literal 150406 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

-BCZ%&`klyX<*6t}d!tuv# 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 literal 0 HcmV?d00001 diff --git a/Documentation/mainboard/msi/ms7707/JSPI1-connected.jpg b/Documentation/mainboard/msi/ms7707/JSPI1-connected.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d1eed2760ed53549c0dcc8e7a0e60f216993bdcd GIT binary patch literal 83025 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

ZxRd6}^%=7XaE>Q<5NZy%Sx{$**%VwCPiFvf?TZ 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 E02W%n3IG5A literal 0 HcmV?d00001 diff --git a/Documentation/mainboard/msi/ms7707/JSPI1.png b/Documentation/mainboard/msi/ms7707/JSPI1.png new file mode 100644 index 0000000000000000000000000000000000000000..b1eadc28e6866d23a39a05afd1aa4ab862b7fbdc GIT binary patch literal 38818 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 + + + + + image/svg+xml + + + + + + + + IFD + + BIOS + + + + ME + + + GBE + + 0x000000 + 0x001000 + 0x003000 + 0x200000 + 0x400000 + + + + Flash + diff --git a/Documentation/mainboard/msi/ms7707/ms7707.md b/Documentation/mainboard/msi/ms7707/ms7707.md new file mode 100644 index 0000000000..789431872c --- /dev/null +++ b/Documentation/mainboard/msi/ms7707/ms7707.md @@ -0,0 +1,112 @@ +# MSI MS-7707 V1.1 + +* MSI MS-7707 V1.1 (Medion OEM Akoya P4385D MSN10014555) +* SandyBridge Intel P67 (BD82x6x) +* Winbond 25Q32BV (4MB) +* Fintek F71808A SuperIO +* Intel 82579V Gigabit +* NEC uPD720200 USB 3.0 Host Controller +* IME 7.0.4.1197 + +## Flash chip (Winbond 25Q32BV) +```eval_rst ++---------------------+--------------------+ +| Type | Value | ++=====================+====================+ +| Size | 4 MiB | ++---------------------+--------------------+ +| BIOS range | 2 MiB | ++---------------------+--------------------+ +| Write protection | Yes (via jumper) | ++---------------------+--------------------+ +| Header | Yes (JSPI1) | ++---------------------+--------------------+ +| Package | SOIC-8 | ++---------------------+--------------------+ +| In circuit flashing | Yes | ++---------------------+--------------------+ +| Internal flashing | Yes | ++---------------------+--------------------+ +| Socketed flash | No | ++---------------------+--------------------+ +| Dual BIOS feature | No | ++---------------------+--------------------+ +| ME removable | Yes | ++---------------------+--------------------+ +``` + +## Installation instructions +* The standard method is to only flash the 2MiB BIOS region. In that case it's +not needed to extract blobs from vendor firmware and internal flashing is +sufficient. +* To flash the whole chip (e.g. to disable ME) blobs are needed to build +coreboot. Blobs can be extracted with util/ifdtool from 4MiB full dump image +(see below). Its recommended to include the VGA BIOS as well (4MiB write only). +Kconfig is prepared already if it gets enabled (path and 8086,0102). +``` +coreboot/3rdparty/blobs/mainboard/msi/ms7707 +├── descriptor.bin +├── gbe.bin +├── me.bin +└── vgabios.bin +``` +* Never write a full 4MiB image if blobs are not included. The generated +coreboot.rom file is always 4MiB but the 2MiB flash command below will only +flash the last 2MiB (BIOS) block. +* The J1-Jumper sets the 'Flash Descriptor Override Strap-Pin' and enables +full 4MiB access for internal flasher (read and write). +* **Write BIOS-range** (2MiB) with J1-Jumper=off (as on picture/default + position): +``` +flashrom -p internal:ich_spi_force=yes --noverify-all --ifd -i bios -w coreboot.rom +``` +* **Read full dump** (4MiB) with J1-jumper=on: +``` +flashrom -p internal -r original.rom +``` +* **Write full dump** (4MiB) with J1-Jumper=on: +``` +flashrom -p internal -w coreboot.rom +``` +* After successful flashing turn main power off, wait some seconds to drain +the capacitors, pull the battery and set the JBAT (clrcmos) jumper for some +seconds. Setting the jumper alone is not enough (the Fintek is VBAT backed). +Put all back in place and restart the board. It might need 1-2 AC power cycles +to reinitialize (running at full fan speed - don't panic). +* External flashing has been tested with RPi2 without main power connected. +3.3V provided by RPi2. Read more about flashing methods [here](https://doc.coreboot.org/flash_tutorial/index.html). +* In case of going back to proprietary BIOS create/save cmos settings as early +as possible (do not leave BIOS on first start without saving settings). +The BIOS might corrupt nvram (not cmos!) and leave the system in a dead state +that needs an external flasher to revive. If stuck, reset the Fintek (see +above) and restart the system several times and/or try setting J1 to +temporarily disable ME. + +![](J1-flash-protect.jpg) + +* The JSPI1 header (5×2 2.0mm pitch pin header) for external flashing is +directly connected to the flash chip. Additional 3.3V to /HOLD and /WP is not +needed (internally re-routed already). + +![](JSPI1-Winbond-W25Q32BVSIG.jpg) + +![](JSPI1-connected.jpg) + +![](JSPI1.png) + +## Flash layout + +* The 4MiB flashrom is divided into 4 sections: + +![][flashlayout] + +## Links + +- [BIOS ROM] +- [Fintek F71808A datasheet] +- [Winbond 25Q32BV datasheet] + +[BIOS ROM]: https://www.medion.com/de/servicebackend/_lightbox/treiber_details.php?did=9744 +[Winbond 25Q32BV datasheet]: https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf +[Fintek F71808A datasheet]: https://www.alldatasheet.com/datasheet-pdf/pdf/459069/FINTEK/F71808A.html +[flashlayout]: flashlayout.svg From 0a7543db2d9938fe449d800f0b2e61ffefd7b822 Mon Sep 17 00:00:00 2001 From: Felix Singer Date: Tue, 19 Feb 2019 23:49:11 +0100 Subject: [PATCH 042/107] inteltool: Add Sunrise Point-LP Skylake PCH IDs Sunrise Point-LP is used on Skylake and KabyLake platforms, but the PCH IDs differ. This commit adds the PCH IDs for Skylake mobile platforms and renames the Kabylake macros to distinguish them. Used Intel documents: - 332995-001EN (I/O datasheet vol. 1) - 332996-002EN (I/O datasheet vol. 2) Change-Id: Id46224fcc44b06c91cbcd6c74a55c95e1de65ec6 Signed-off-by: Felix Singer Reviewed-on: https://review.coreboot.org/c/coreboot/+/31506 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- util/inteltool/gpio.c | 10 +++++++--- util/inteltool/gpio_groups.c | 10 +++++++--- util/inteltool/inteltool.c | 26 +++++++++++++++++--------- util/inteltool/inteltool.h | 10 +++++++--- util/inteltool/pcr.c | 10 +++++++--- util/inteltool/powermgt.c | 10 +++++++--- util/inteltool/rootcmplx.c | 10 +++++++--- util/inteltool/spi.c | 20 ++++++++++++++------ 8 files changed, 73 insertions(+), 33 deletions(-) diff --git a/util/inteltool/gpio.c b/util/inteltool/gpio.c index 41f4df90c8..c946d5c65f 100644 --- a/util/inteltool/gpio.c +++ b/util/inteltool/gpio.c @@ -1028,9 +1028,13 @@ int print_gpios(struct pci_dev *sb, int show_all, int show_diffs) case PCI_DEVICE_ID_INTEL_CM236: case PCI_DEVICE_ID_INTEL_APL_LPC: case PCI_DEVICE_ID_INTEL_DNV_LPC: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM: diff --git a/util/inteltool/gpio_groups.c b/util/inteltool/gpio_groups.c index 8b328a7383..21e2de93d5 100644 --- a/util/inteltool/gpio_groups.c +++ b/util/inteltool/gpio_groups.c @@ -1778,9 +1778,13 @@ void print_gpio_groups(struct pci_dev *const sb) communities = sunrise_communities; pcr_init(sb); break; - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM: diff --git a/util/inteltool/inteltool.c b/util/inteltool/inteltool.c index e89fd3cf22..40e7646450 100644 --- a/util/inteltool/inteltool.c +++ b/util/inteltool/inteltool.c @@ -224,18 +224,26 @@ static const struct { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BAYTRAIL_LPC, "Bay Trail" }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_PRE, "Sunrise Point Desktop Engineering Sample" }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE, - "Sunrise Point-LP U Base" }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM, - "Sunrise Point-LP U Premium" }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM, - "Sunrise Point-LP Y Premium" }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE, + "Sunrise Point-LP Engineering Sample" }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL, + "Sunrise Point-LP U Base/Skylake" }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL, + "Sunrise Point-LP Y Premium/Skylake" }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL, + "Sunrise Point-LP U Premium/Skylake" }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL, + "Sunrise Point-LP U Base/Kabylake" }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL, + "Sunrise Point-LP Y Premium/Kabylake" }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL, + "Sunrise Point-LP U Premium/Kabylake" }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE, - "Sunrise Point-LP U iHDCP 2.2 Base" }, + "Sunrise Point-LP U iHDCP 2.2 Base/Kabylake" }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM, - "Sunrise Point-LP U iHDCP 2.2 Premium" }, + "Sunrise Point-LP U iHDCP 2.2 Premium/Kabylake" }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM, - "Sunrise Point-LP Y iHDCP 2.2 Premium" }, + "Sunrise Point-LP Y iHDCP 2.2 Premium/Kabylake" }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_H110, "H110" }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_H170, "H170" }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Z170, "Z170" }, diff --git a/util/inteltool/inteltool.h b/util/inteltool/inteltool.h index 25b3a1504a..6aec3879c2 100644 --- a/util/inteltool/inteltool.h +++ b/util/inteltool/inteltool.h @@ -145,9 +145,13 @@ static inline uint32_t inl(unsigned port) #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_P2SB 0xa120 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_PRE 0xa141 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SATA 0x9d03 -#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE 0x9d53 -#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM 0x9d58 -#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM 0x9d56 +#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE 0x9d41 +#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL 0x9d43 +#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL 0x9d46 +#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL 0x9d48 +#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL 0x9d53 +#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL 0x9d56 +#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL 0x9d58 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE 0x9d50 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM 0x9d4e #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM 0x9d4b diff --git a/util/inteltool/pcr.c b/util/inteltool/pcr.c index a296b19be4..c969620fa0 100644 --- a/util/inteltool/pcr.c +++ b/util/inteltool/pcr.c @@ -79,9 +79,13 @@ void pcr_init(struct pci_dev *const sb) switch (sb->device_id) { case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_PRE: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM: diff --git a/util/inteltool/powermgt.c b/util/inteltool/powermgt.c index 359180093d..675e31a1da 100644 --- a/util/inteltool/powermgt.c +++ b/util/inteltool/powermgt.c @@ -745,9 +745,13 @@ int print_pmbase(struct pci_dev *sb, struct pci_access *pacc) case PCI_DEVICE_ID_INTEL_C224: case PCI_DEVICE_ID_INTEL_C226: case PCI_DEVICE_ID_INTEL_H81: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM: diff --git a/util/inteltool/rootcmplx.c b/util/inteltool/rootcmplx.c index ddcd8e3ed3..70d7cbe3ed 100644 --- a/util/inteltool/rootcmplx.c +++ b/util/inteltool/rootcmplx.c @@ -112,9 +112,13 @@ int print_rcba(struct pci_dev *sb) case PCI_DEVICE_ID_INTEL_C224: case PCI_DEVICE_ID_INTEL_C226: case PCI_DEVICE_ID_INTEL_H81: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM: diff --git a/util/inteltool/spi.c b/util/inteltool/spi.c index cb38c55587..da5533deaa 100644 --- a/util/inteltool/spi.c +++ b/util/inteltool/spi.c @@ -175,9 +175,13 @@ int print_bioscntl(struct pci_dev *sb) case PCI_DEVICE_ID_INTEL_C224: case PCI_DEVICE_ID_INTEL_C226: case PCI_DEVICE_ID_INTEL_H81: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM: @@ -309,9 +313,13 @@ int print_spibar(struct pci_dev *sb) { case PCI_DEVICE_ID_INTEL_C224: case PCI_DEVICE_ID_INTEL_C226: case PCI_DEVICE_ID_INTEL_H81: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM: - case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL: + case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM: From 45b824d69433a630147dd690f6b5993bc2d4bb76 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 5 May 2019 17:37:49 +0200 Subject: [PATCH 043/107] src: Remove unused include Change-Id: I2f142cc80692e60eb0f81f57339a247f6ef4a524 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32611 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/mainboard/apple/macbook21/romstage.c | 1 - src/mainboard/asus/p5gc-mx/romstage.c | 1 - src/mainboard/asus/p5qpl-am/romstage.c | 1 - src/mainboard/getac/p470/romstage.c | 1 - src/mainboard/ibase/mb899/romstage.c | 1 - src/mainboard/intel/dcp847ske/early_southbridge.c | 1 - src/mainboard/kontron/986lcd-m/romstage.c | 1 - src/mainboard/lenovo/t60/romstage.c | 1 - src/mainboard/lenovo/z61t/romstage.c | 1 - src/mainboard/roda/rk886ex/romstage.c | 1 - src/northbridge/intel/haswell/raminit.c | 1 - src/northbridge/intel/i945/early_init.c | 1 - src/northbridge/intel/i945/raminit.c | 1 - src/northbridge/intel/pineview/romstage.c | 1 - src/northbridge/intel/sandybridge/raminit.c | 1 - src/northbridge/intel/sandybridge/raminit_mrc.c | 1 - 16 files changed, 16 deletions(-) diff --git a/src/mainboard/apple/macbook21/romstage.c b/src/mainboard/apple/macbook21/romstage.c index c056ac8fcb..468cffb7d9 100644 --- a/src/mainboard/apple/macbook21/romstage.c +++ b/src/mainboard/apple/macbook21/romstage.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/src/mainboard/asus/p5gc-mx/romstage.c b/src/mainboard/asus/p5gc-mx/romstage.c index beb276c7da..08379f78a1 100644 --- a/src/mainboard/asus/p5gc-mx/romstage.c +++ b/src/mainboard/asus/p5gc-mx/romstage.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/src/mainboard/asus/p5qpl-am/romstage.c b/src/mainboard/asus/p5qpl-am/romstage.c index 4174981ac2..bd6bfc6ee7 100644 --- a/src/mainboard/asus/p5qpl-am/romstage.c +++ b/src/mainboard/asus/p5qpl-am/romstage.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/src/mainboard/getac/p470/romstage.c b/src/mainboard/getac/p470/romstage.c index d643b12f8a..aaa3422c02 100644 --- a/src/mainboard/getac/p470/romstage.c +++ b/src/mainboard/getac/p470/romstage.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/src/mainboard/ibase/mb899/romstage.c b/src/mainboard/ibase/mb899/romstage.c index 7e3b7dba68..9cb1144b80 100644 --- a/src/mainboard/ibase/mb899/romstage.c +++ b/src/mainboard/ibase/mb899/romstage.c @@ -16,7 +16,6 @@ // __PRE_RAM__ means: use "unsigned" for device, not a struct. #include -#include #include #include #include diff --git a/src/mainboard/intel/dcp847ske/early_southbridge.c b/src/mainboard/intel/dcp847ske/early_southbridge.c index 46f9a94e9e..778525f320 100644 --- a/src/mainboard/intel/dcp847ske/early_southbridge.c +++ b/src/mainboard/intel/dcp847ske/early_southbridge.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/kontron/986lcd-m/romstage.c b/src/mainboard/kontron/986lcd-m/romstage.c index 3d01eb1e0f..b85bd6883d 100644 --- a/src/mainboard/kontron/986lcd-m/romstage.c +++ b/src/mainboard/kontron/986lcd-m/romstage.c @@ -16,7 +16,6 @@ /* __PRE_RAM__ means: use "unsigned" for device, not a struct. */ #include -#include #include #include #include diff --git a/src/mainboard/lenovo/t60/romstage.c b/src/mainboard/lenovo/t60/romstage.c index ea207e80a9..0c7c0cfb2d 100644 --- a/src/mainboard/lenovo/t60/romstage.c +++ b/src/mainboard/lenovo/t60/romstage.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/src/mainboard/lenovo/z61t/romstage.c b/src/mainboard/lenovo/z61t/romstage.c index 0d68faca2c..47a52db39b 100644 --- a/src/mainboard/lenovo/z61t/romstage.c +++ b/src/mainboard/lenovo/z61t/romstage.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/src/mainboard/roda/rk886ex/romstage.c b/src/mainboard/roda/rk886ex/romstage.c index e85da1f480..2bdad276c1 100644 --- a/src/mainboard/roda/rk886ex/romstage.c +++ b/src/mainboard/roda/rk886ex/romstage.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/src/northbridge/intel/haswell/raminit.c b/src/northbridge/intel/haswell/raminit.c index fddada4ba0..96dc94e7d2 100644 --- a/src/northbridge/intel/haswell/raminit.c +++ b/src/northbridge/intel/haswell/raminit.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/src/northbridge/intel/i945/early_init.c b/src/northbridge/intel/i945/early_init.c index a9de844f15..274296d482 100644 --- a/src/northbridge/intel/i945/early_init.c +++ b/src/northbridge/intel/i945/early_init.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include "i945.h" #include diff --git a/src/northbridge/intel/i945/raminit.c b/src/northbridge/intel/i945/raminit.c index 1e8cf65581..0cf03ae605 100644 --- a/src/northbridge/intel/i945/raminit.c +++ b/src/northbridge/intel/i945/raminit.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "raminit.h" #include "i945.h" #include "chip.h" diff --git a/src/northbridge/intel/pineview/romstage.c b/src/northbridge/intel/pineview/romstage.c index bdb685b252..a3e6c39172 100644 --- a/src/northbridge/intel/pineview/romstage.c +++ b/src/northbridge/intel/pineview/romstage.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c index cea3f2cd70..e60c37875b 100644 --- a/src/northbridge/intel/sandybridge/raminit.c +++ b/src/northbridge/intel/sandybridge/raminit.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/src/northbridge/intel/sandybridge/raminit_mrc.c b/src/northbridge/intel/sandybridge/raminit_mrc.c index a68ae49c7c..ea3590f78d 100644 --- a/src/northbridge/intel/sandybridge/raminit_mrc.c +++ b/src/northbridge/intel/sandybridge/raminit_mrc.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include "raminit.h" #include "pei_data.h" From 1a6b5c23a1f5892c7a461d6a6ef547e2abe524f4 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Thu, 25 Apr 2019 19:11:13 +0800 Subject: [PATCH 044/107] vboot: remove use of GoogleBinaryBlockHeader Remove use of deprecated GoogleBinaryBlockHeader struct, and replace with vb2_gbb_header. BUG=b:124141368, chromium:954774 TEST=make clean && make test-abuild BRANCH=none Change-Id: Iee3bd877cb1791a689efdeabda324f43f7d0c6f2 Signed-off-by: Joel Kitching Reviewed-on: https://review.coreboot.org/c/coreboot/+/32455 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/security/vboot/gbb.c | 13 ++++++++----- src/security/vboot/gbb.h | 2 +- src/security/vboot/vboot_common.c | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/security/vboot/gbb.c b/src/security/vboot/gbb.c index 8f57c798b2..5293033666 100644 --- a/src/security/vboot/gbb.c +++ b/src/security/vboot/gbb.c @@ -13,17 +13,19 @@ * GNU General Public License for more details. */ +#define NEED_VB20_INTERNALS /* Peeking into vb2_gbb_header */ + #include #include #include -#include #include #include +#include #define GBB_FMAP_REGION_NAME "GBB" /* Copy of GBB header read from boot media. */ -static GoogleBinaryBlockHeader gbb_header; +static struct vb2_gbb_header gbb_header; /* * Read "GBB" region from SPI flash to obtain GBB header and validate @@ -45,13 +47,14 @@ static int gbb_init(void) return 1; if (rdev_readat(&gbb_rdev, &gbb_header, 0, - sizeof(GoogleBinaryBlockHeader)) != - sizeof(GoogleBinaryBlockHeader)) { + sizeof(struct vb2_gbb_header)) != + sizeof(struct vb2_gbb_header)) { printk(BIOS_ERR, "%s: Failure to read GBB header!\n", __func__); return 1; } - if (memcmp(gbb_header.signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE)) { + if (memcmp(gbb_header.signature, VB2_GBB_SIGNATURE, + VB2_GBB_SIGNATURE_SIZE)) { printk(BIOS_ERR, "%s: Signature check failed!\n", __func__); return 1; } diff --git a/src/security/vboot/gbb.h b/src/security/vboot/gbb.h index 550548d613..389242a3a2 100644 --- a/src/security/vboot/gbb.h +++ b/src/security/vboot/gbb.h @@ -18,7 +18,7 @@ #include -/* In order to use GBB_FLAG_* macros from vboot, include gbb_header.h. */ +/* In order to use VB2_GBB_FLAG_* macros from vboot, include vb2_api.h. */ /* * Read flags field from GBB header. diff --git a/src/security/vboot/vboot_common.c b/src/security/vboot/vboot_common.c index 3dddc76556..493cb88898 100644 --- a/src/security/vboot/vboot_common.c +++ b/src/security/vboot/vboot_common.c @@ -18,12 +18,12 @@ #include #include #include -#include #include #include #include #include #include +#include int vboot_named_region_device(const char *name, struct region_device *rdev) { @@ -42,7 +42,7 @@ int vboot_can_enable_udc(void) if (!vboot_developer_mode_enabled()) return 0; /* Enable if GBB flag is set */ - if (gbb_is_flag_set(GBB_FLAG_ENABLE_UDC)) + if (gbb_is_flag_set(VB2_GBB_FLAG_ENABLE_UDC)) return 1; /* Enable if VBNV flag is set */ if (vbnv_udc_enable_flag()) From 8c0acc5515f8a381cf2d33c61951d229d4ef358a Mon Sep 17 00:00:00 2001 From: Eric Lai Date: Fri, 3 May 2019 16:08:07 +0800 Subject: [PATCH 045/107] mb/google/sarien: Fine tune SD card D3 cold timing A13 and A15 need to set low before H12 reset. Change the program sequence for fit HW requirement. BUG=b:131876963 TEST=boot up and check SD card functional Signed-off-by: Eric Lai Change-Id: I2f1752070f24833aaaab75dea8493caf2ed7f157 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32552 Tested-by: build bot (Jenkins) Reviewed-by: Lijian Zhao Reviewed-by: Duncan Laurie --- src/mainboard/google/sarien/variants/sarien/gpio.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mainboard/google/sarien/variants/sarien/gpio.c b/src/mainboard/google/sarien/variants/sarien/gpio.c index 53a937ff39..ec3b44d4a3 100644 --- a/src/mainboard/google/sarien/variants/sarien/gpio.c +++ b/src/mainboard/google/sarien/variants/sarien/gpio.c @@ -31,9 +31,9 @@ static const struct pad_config gpio_table[] = { /* CLKOUT_LPC1 */ PAD_NC(GPP_A10, NONE), /* PME# */ PAD_NC(GPP_A11, NONE), /* BM_BUSY# */ PAD_NC(GPP_A12, NONE), -/* SUSWARN# */ PAD_CFG_GPO(GPP_A13, 0, DEEP), /* Card reader D3 cold */ + /* ESPI_RESET# */ -/* SUSACK# */ PAD_CFG_GPO(GPP_A15, 0, DEEP), /* Card reader D3 cold */ + /* SD_1P8_SEL */ PAD_NC(GPP_A16, NONE), /* SD_PWR_EN# */ PAD_NC(GPP_A17, NONE), /* ISH_GP0 */ PAD_NC(GPP_A18, NONE), @@ -224,9 +224,12 @@ static const struct pad_config gpio_table[] = { /* Early pad configuration in bootblock */ static const struct pad_config early_gpio_table[] = { -/* M2_SKT2_CFG0 */ PAD_CFG_GPO(GPP_H12, 0, DEEP), /* D3 cold RST */ +/* SUSWARN# */ PAD_CFG_GPO(GPP_A13, 0, DEEP), /* Card reader D3 cold */ +/* SUSACK# */ PAD_CFG_GPO(GPP_A15, 0, DEEP), /* Card reader D3 cold */ /* UART2_RXD */ PAD_CFG_NF(GPP_C20, NONE, DEEP, NF1), /* SERVOTX_UART */ /* UART2_TXD */ PAD_CFG_NF(GPP_C21, NONE, DEEP, NF1), /* SERVORX_UART */ +/* SSD RESET pin will stay low first */ +/* M2_SKT2_CFG0 */ PAD_CFG_GPO(GPP_H12, 0, DEEP), /* D3 cold RST */ /* I2C4_SDA */ PAD_CFG_NF(GPP_H8, NONE, DEEP, NF1), /* I2C_SDA_H1 */ /* I2C4_SCL */ PAD_CFG_NF(GPP_H9, NONE, DEEP, NF1), /* I2C_SCL_H1 */ /* DMIC_DATA1 */ PAD_CFG_GPI_APIC(GPP_D18, NONE, PLTRST, @@ -236,9 +239,8 @@ static const struct pad_config early_gpio_table[] = { /* CPU_GP0 */ PAD_CFG_GPI(GPP_E3, NONE, DEEP), /* MEM_INTERLEAVED */ /* SATALED# */ PAD_CFG_GPI(GPP_E8, NONE, DEEP), /* RECOVERY# */ /* DDPD_HPD2 */ PAD_CFG_GPI(GPP_E15, NONE, DEEP), /* H1_FLASH_WP */ -/* SSD RESET need to stay low first */ -/* M2_SKT2_CFG0 */ PAD_CFG_GPO(GPP_H12, 1, DEEP), /* D3 cold RST */ /* PWRBTN# */ PAD_CFG_NF(GPD3, UP_20K, DEEP, NF1), /* SIO_PWRBTN# */ +/* M2_SKT2_CFG0 */ PAD_CFG_GPO(GPP_H12, 1, DEEP), /* D3 cold RST */ }; const struct pad_config *variant_gpio_table(size_t *num) From 0c0a9810c7d00524a8bcebacc36496b590de3a79 Mon Sep 17 00:00:00 2001 From: Eric Lai Date: Mon, 29 Apr 2019 15:17:06 +0800 Subject: [PATCH 046/107] mb/google/sarien: Turn off camera power when s0ix Turn off camera power when s0ix for power saving. BUG=b:129177593 TEST= measure camera power comsumption is 0mV under s0ix Change-Id: I5a9b7ec1e95cc9931d8d5f2dc1254805c9d0ffed Signed-off-by: Eric Lai Reviewed-on: https://review.coreboot.org/c/coreboot/+/32519 Tested-by: build bot (Jenkins) Reviewed-by: Lijian Zhao Reviewed-by: Duncan Laurie --- src/mainboard/google/sarien/dsdt.asl | 2 ++ .../arcada/include/variant/acpi/mainboard.asl | 28 +++++++++++++++++++ .../sarien/include/variant/acpi/mainboard.asl | 28 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl create mode 100644 src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl diff --git a/src/mainboard/google/sarien/dsdt.asl b/src/mainboard/google/sarien/dsdt.asl index e5b0ccad2e..58e0704deb 100644 --- a/src/mainboard/google/sarien/dsdt.asl +++ b/src/mainboard/google/sarien/dsdt.asl @@ -40,6 +40,8 @@ DefinitionBlock( #include #include } + /* Per board variant mainboard hooks. */ + #include } #if CONFIG(CHROMEOS) diff --git a/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl b/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl new file mode 100644 index 0000000000..7b252c7f1c --- /dev/null +++ b/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2019 Intel Corp. + * + * 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; version 2 of the License. + * + * 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. + */ + +#define CAM_EN GPP_B11 /* Active low */ + +/* Method called from LPIT prior to enter s0ix state */ +Method (MS0X, 1) +{ + If (Arg0) { + /* Turn off camera power */ + \_SB.PCI0.STXS (CAM_EN) + } Else { + /* Turn on camera power */ + \_SB.PCI0.CTXS (CAM_EN) + } +} diff --git a/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl b/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl new file mode 100644 index 0000000000..7b252c7f1c --- /dev/null +++ b/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2019 Intel Corp. + * + * 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; version 2 of the License. + * + * 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. + */ + +#define CAM_EN GPP_B11 /* Active low */ + +/* Method called from LPIT prior to enter s0ix state */ +Method (MS0X, 1) +{ + If (Arg0) { + /* Turn off camera power */ + \_SB.PCI0.STXS (CAM_EN) + } Else { + /* Turn on camera power */ + \_SB.PCI0.CTXS (CAM_EN) + } +} From 0de835d52ee8f44a32f2b483d1e4a1c9a172e4c6 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Mon, 6 May 2019 06:12:33 +0000 Subject: [PATCH 047/107] Update vboot submodule to upstream master Updating from commit id 304aa429: 2019-03-12 10:38:56 -0700 - (futility: updater: Unit test for preserving sections using FMAP flags) to commit id e7edff66: 2019-05-03 07:02:32 -0700 - (vboot: implement DISPLAY_INIT context and SD flag) This brings in 45 new commits. Change-Id: I7493e43bddc553f9724de46130ccb4cb44e18573 Signed-off-by: Joel Kitching Reviewed-on: https://review.coreboot.org/c/coreboot/+/32612 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- 3rdparty/vboot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty/vboot b/3rdparty/vboot index 304aa429c1..e7edff6653 160000 --- a/3rdparty/vboot +++ b/3rdparty/vboot @@ -1 +1 @@ -Subproject commit 304aa429c1a04cda3ab2ce37b9e31af84405bfca +Subproject commit e7edff6653e16ed915c3ad12234d133d1ef4dcc9 From ba092a9ab6e87fec458d6557d0114147e2713686 Mon Sep 17 00:00:00 2001 From: Evgeny Zinoviev Date: Sun, 5 May 2019 13:23:25 +0300 Subject: [PATCH 048/107] mb/apple/macbookair4_2: Correct internal video port selection The MacBook Air 4,2 uses eDP, according to the schematics. Change-Id: Ifc98eab343fd89b8512e92e01fddf34ef8447d5f Signed-off-by: Evgeny Zinoviev Reviewed-on: https://review.coreboot.org/c/coreboot/+/32606 Reviewed-by: Angel Pons Reviewed-by: Nico Huber Reviewed-by: Felix Held Tested-by: build bot (Jenkins) --- src/mainboard/apple/macbookair4_2/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/apple/macbookair4_2/Kconfig b/src/mainboard/apple/macbookair4_2/Kconfig index 82f120ab08..4b2ee8fdc8 100644 --- a/src/mainboard/apple/macbookair4_2/Kconfig +++ b/src/mainboard/apple/macbookair4_2/Kconfig @@ -12,7 +12,7 @@ config BOARD_SPECIFIC_OPTIONS select SERIRQ_CONTINUOUS_MODE select SOUTHBRIDGE_INTEL_BD82X6X select SYSTEM_TYPE_LAPTOP - select GFX_GMA_INTERNAL_IS_LVDS + select GFX_GMA_INTERNAL_IS_EDP select MAINBOARD_HAS_LIBGFXINIT config MAINBOARD_DIR From 1bc7b6e1350c4ba8eee10a859d10150b15b7b7e9 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 5 May 2019 16:29:41 +0200 Subject: [PATCH 049/107] {gm45,pineview,sandybridge,x4x}: Use {full,system}_reset() function Use already defined system_reset() and full_reset() functions. Change-Id: Ic29fab70cf7f23d49c3eeeb97c984c523f973972 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32608 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/northbridge/intel/gm45/early_reset.c | 8 +++----- src/northbridge/intel/pineview/raminit.c | 7 +++---- src/northbridge/intel/sandybridge/romstage.c | 7 +++---- src/northbridge/intel/x4x/raminit.c | 5 +---- 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/northbridge/intel/gm45/early_reset.c b/src/northbridge/intel/gm45/early_reset.c index 9f919cfbcd..3f095a256f 100644 --- a/src/northbridge/intel/gm45/early_reset.c +++ b/src/northbridge/intel/gm45/early_reset.c @@ -16,8 +16,9 @@ #include #include +#include #include -#include + #include "gm45.h" void gm45_early_reset(void/*const timings_t *const timings*/) @@ -63,8 +64,5 @@ void gm45_early_reset(void/*const timings_t *const timings*/) /* Normally, we would set this after successful raminit. */ MCHBAR32(DCC_MCHBAR) |= (1 << 19); - /* Perform system reset through CF9 interface. */ - outb(0x02, 0xcf9); /* Set system reset bit. */ - outb(0x06, 0xcf9); /* Set CPU reset bit, too. */ - halt(); + system_reset(); } diff --git a/src/northbridge/intel/pineview/raminit.c b/src/northbridge/intel/pineview/raminit.c index 48bca36faa..144905fb92 100644 --- a/src/northbridge/intel/pineview/raminit.c +++ b/src/northbridge/intel/pineview/raminit.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -1744,10 +1745,8 @@ static void sdram_checkreset(void) } pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2); pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3); - if (reset) { - printk(BIOS_DEBUG, "Power cycle reset...\n"); - outb(0xe, 0xcf9); - } + if (reset) + full_reset(); } static void sdram_dradrb(struct sysinfo *s) diff --git a/src/northbridge/intel/sandybridge/romstage.c b/src/northbridge/intel/sandybridge/romstage.c index 3fab3be85d..43316a2f22 100644 --- a/src/northbridge/intel/sandybridge/romstage.c +++ b/src/northbridge/intel/sandybridge/romstage.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -47,10 +48,8 @@ void mainboard_romstage_entry(unsigned long bist) { int s3resume = 0; - if (MCHBAR16(SSKPD) == 0xCAFE) { - outb(0x6, 0xcf9); - halt (); - } + if (MCHBAR16(SSKPD) == 0xCAFE) + system_reset(); if (bist == 0) enable_lapic(); diff --git a/src/northbridge/intel/x4x/raminit.c b/src/northbridge/intel/x4x/raminit.c index 4d5bdce9ac..60d3b55531 100644 --- a/src/northbridge/intel/x4x/raminit.c +++ b/src/northbridge/intel/x4x/raminit.c @@ -22,7 +22,6 @@ #include #include #include -#include #if CONFIG(SOUTHBRIDGE_INTEL_I82801GX) #include /* smbus_read_byte */ #else @@ -624,9 +623,7 @@ static void checkreset_ddr2(int boot_path) reg8 = pci_read_config8(PCI_DEV(0, 0, 0), 0xf0); pci_write_config8(PCI_DEV(0, 0, 0), 0xf0, reg8 | (1 << 2)); - printk(BIOS_DEBUG, "Reset...\n"); - outb(0xe, 0xcf9); - asm ("hlt"); + full_reset(); } pmcon2 |= 0x80; pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2); From 66b35bad88807fa18a5ade87283fdb5ffef538f0 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 5 May 2019 16:35:55 +0200 Subject: [PATCH 050/107] mb/lenovo/x60: Use system_reset() Change-Id: I4515d8d14629741f3bf49e9459d7d57c18d321ce Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32609 Tested-by: build bot (Jenkins) Reviewed-by: Alexander Couzens Reviewed-by: Nico Huber --- src/mainboard/lenovo/x60/romstage.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mainboard/lenovo/x60/romstage.c b/src/mainboard/lenovo/x60/romstage.c index 95192f733b..ea93707ce9 100644 --- a/src/mainboard/lenovo/x60/romstage.c +++ b/src/mainboard/lenovo/x60/romstage.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -198,8 +198,7 @@ void mainboard_romstage_entry(unsigned long bist) if (MCHBAR16(SSKPD) == 0xCAFE) { printk(BIOS_DEBUG, "Soft reset detected, rebooting properly.\n"); - outb(0x6, 0xcf9); - halt(); + system_reset(); } /* Perform some early chipset initialization required From a842d3ee6a191322f47be49f17338073120778b8 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Sat, 4 May 2019 16:26:25 +0200 Subject: [PATCH 051/107] intel/fsp1_1: Drop unused, weak raminit() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I5d155df1d589fc8d7462f46e87275bd6efae0a7f Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/32587 Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier Reviewed-by: Patrick Rudolph Reviewed-by: Frans Hendriks Reviewed-by: Michał Żygowski --- src/drivers/intel/fsp1_1/romstage.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/drivers/intel/fsp1_1/romstage.c b/src/drivers/intel/fsp1_1/romstage.c index ebb6a6678b..bfed1213cd 100644 --- a/src/drivers/intel/fsp1_1/romstage.c +++ b/src/drivers/intel/fsp1_1/romstage.c @@ -343,13 +343,6 @@ __weak int mrc_cache_stash_data(int type, uint32_t version, return -1; } -/* Transition RAM from off or self-refresh to active */ -__weak void raminit(struct romstage_params *params) -{ - post_code(POST_MEM_PREINIT_PREP_START); - die("ERROR - No RAM initialization specified!\n"); -} - /* Display the memory configuration */ __weak void report_memory_config(void) { From 16895c529c5e44b3c7725ef92f9119ba03397576 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Sat, 4 May 2019 16:29:17 +0200 Subject: [PATCH 052/107] intel/fsp1_1: Drop `boot_mode` from `pei_data` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was only used locally. Change-Id: Iaaad760e8ceca62655f5448c30846cf11959e8e1 Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/32588 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph Reviewed-by: Michał Żygowski --- src/drivers/intel/fsp1_1/raminit.c | 5 +++-- src/drivers/intel/fsp1_1/romstage.c | 5 ++--- src/soc/intel/braswell/include/soc/pei_data.h | 3 --- src/soc/intel/skylake/include/soc/pei_data.h | 1 - 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/drivers/intel/fsp1_1/raminit.c b/src/drivers/intel/fsp1_1/raminit.c index 8405c943aa..4ea1f00897 100644 --- a/src/drivers/intel/fsp1_1/raminit.c +++ b/src/drivers/intel/fsp1_1/raminit.c @@ -28,6 +28,7 @@ void raminit(struct romstage_params *params) { + const bool s3wake = params->power_state->prev_sleep_state == ACPI_S3; const EFI_GUID bootldr_tolum_guid = FSP_BOOTLOADER_TOLUM_HOB_GUID; EFI_HOB_RESOURCE_DESCRIPTOR *cbmem_root; FSP_INFO_HEADER *fsp_header; @@ -81,7 +82,7 @@ void raminit(struct romstage_params *params) /* Zero fill RT Buffer data and start populating fields. */ memset(&fsp_rt_common_buffer, 0, sizeof(fsp_rt_common_buffer)); pei_ptr = params->pei_data; - if (pei_ptr->boot_mode == ACPI_S3) { + if (s3wake) { fsp_rt_common_buffer.BootMode = BOOT_ON_S3_RESUME; } else if (pei_ptr->saved_data != NULL) { fsp_rt_common_buffer.BootMode = @@ -158,7 +159,7 @@ void raminit(struct romstage_params *params) /* Migrate CAR data */ printk(BIOS_DEBUG, "0x%p: cbmem_top\n", cbmem_top()); - if (pei_ptr->boot_mode != ACPI_S3) { + if (!s3wake) { cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY, fsp_reserved_bytes); } else if (cbmem_initialize_id_size(CBMEM_ID_FSP_RESERVED_MEMORY, diff --git a/src/drivers/intel/fsp1_1/romstage.c b/src/drivers/intel/fsp1_1/romstage.c index bfed1213cd..17bd638290 100644 --- a/src/drivers/intel/fsp1_1/romstage.c +++ b/src/drivers/intel/fsp1_1/romstage.c @@ -101,7 +101,6 @@ void romstage_common(struct romstage_params *params) timestamp_add_now(TS_BEFORE_INITRAM); pei_data = params->pei_data; - pei_data->boot_mode = params->power_state->prev_sleep_state; s3wake = params->power_state->prev_sleep_state == ACPI_S3; if (CONFIG(ELOG_BOOT_COUNT) && !s3wake) @@ -129,7 +128,7 @@ void romstage_common(struct romstage_params *params) params->pei_data->saved_data = rdev_mmap_full(&rdev); /* Assume boot device is memory mapped. */ assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED)); - } else if (params->pei_data->boot_mode == ACPI_S3) { + } else if (s3wake) { /* Waking from S3 and no cache. */ printk(BIOS_DEBUG, "No MRC cache found in S3 resume path.\n"); @@ -149,7 +148,7 @@ void romstage_common(struct romstage_params *params) if (CONFIG(CACHE_MRC_SETTINGS)) { printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", pei_data->data_to_save, pei_data->data_to_save_size); - if ((params->pei_data->boot_mode != ACPI_S3) + if (!s3wake && (params->pei_data->data_to_save_size != 0) && (params->pei_data->data_to_save != NULL)) mrc_cache_stash_data(MRC_TRAINING_DATA, diff --git a/src/soc/intel/braswell/include/soc/pei_data.h b/src/soc/intel/braswell/include/soc/pei_data.h index 50aabed66e..7ea83ba8db 100644 --- a/src/soc/intel/braswell/include/soc/pei_data.h +++ b/src/soc/intel/braswell/include/soc/pei_data.h @@ -44,9 +44,6 @@ struct pei_data { uint8_t spd_ch0_config; uint8_t spd_ch1_config; - /* System state information */ - int boot_mode; - /* Fast boot and S3 resume MRC data */ int saved_data_size; const void *saved_data; diff --git a/src/soc/intel/skylake/include/soc/pei_data.h b/src/soc/intel/skylake/include/soc/pei_data.h index 02e04c6c02..7406a3322e 100644 --- a/src/soc/intel/skylake/include/soc/pei_data.h +++ b/src/soc/intel/skylake/include/soc/pei_data.h @@ -41,7 +41,6 @@ typedef void ABI_X86(*tx_byte_func)(unsigned char byte); struct pei_data { uint32_t pei_version; - int boot_mode; int ec_present; /* Console output function */ From 99e836c843e6a8536348d5cc9581b5a17512a263 Mon Sep 17 00:00:00 2001 From: Patrick Georgi Date: Tue, 7 May 2019 15:35:40 +0000 Subject: [PATCH 053/107] Revert "Makefile.inc: Enable -Wtype-limits" This reverts commit c4ab50cdde4bfd01ec7509012b105c88bcf4c953. Reason for revert: vboot recently was changed so that -Wtype-limits fails, and that was just brought upstream. Since vboot internals are more likely to be used elsewhere while -Wtype-limits is less critical, revert this until vboot is resolved, then bring -Wtype-limits back again. Change-Id: I9cce10462b9e57189513fa49e11fd27ebe35ba51 Signed-off-by: Patrick Georgi Reviewed-on: https://review.coreboot.org/c/coreboot/+/32670 Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc index 9860da1b68..a9aaaed783 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -401,7 +401,7 @@ endif CFLAGS_common += -pipe -g -nostdinc -std=gnu11 CFLAGS_common += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs -CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time -Wtype-limits +CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie ifeq ($(CONFIG_COMPILER_GCC),y) From 66318aad07e6810065bc0668f4a1f34b7cb77687 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Sat, 4 May 2019 16:59:20 +0200 Subject: [PATCH 054/107] intel/fsp1_1: Move MRC cache pointers into `romstage_params` These are part of a common concept and not SoC specific. Change-Id: I9cb218d7825bd06a138f7f5d9e2b68e86077a3ec Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/32589 Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier Reviewed-by: Patrick Rudolph Reviewed-by: Frans Hendriks --- .../intel/fsp1_1/include/fsp/romstage.h | 10 ++++++++ src/drivers/intel/fsp1_1/raminit.c | 12 ++++----- src/drivers/intel/fsp1_1/romstage.c | 25 ++++++++----------- src/soc/intel/braswell/include/soc/pei_data.h | 9 ------- src/soc/intel/skylake/include/soc/pei_data.h | 9 ------- src/soc/intel/skylake/pei_data.c | 9 ------- src/soc/intel/skylake/romstage/romstage.c | 6 +++++ 7 files changed, 32 insertions(+), 48 deletions(-) diff --git a/src/drivers/intel/fsp1_1/include/fsp/romstage.h b/src/drivers/intel/fsp1_1/include/fsp/romstage.h index d608484999..4e95dadadf 100644 --- a/src/drivers/intel/fsp1_1/include/fsp/romstage.h +++ b/src/drivers/intel/fsp1_1/include/fsp/romstage.h @@ -18,6 +18,7 @@ #ifndef _COMMON_ROMSTAGE_H_ #define _COMMON_ROMSTAGE_H_ +#include #include #include #include @@ -32,6 +33,15 @@ struct romstage_params { struct chipset_power_state *power_state; struct pei_data *pei_data; void *chipset_context; + + /* Fast boot and S3 resume MRC data */ + size_t saved_data_size; + const void *saved_data; + bool disable_saved_data; + + /* New save data from MRC */ + size_t data_to_save_size; + const void *data_to_save; }; /* diff --git a/src/drivers/intel/fsp1_1/raminit.c b/src/drivers/intel/fsp1_1/raminit.c index 4ea1f00897..726cc26a0c 100644 --- a/src/drivers/intel/fsp1_1/raminit.c +++ b/src/drivers/intel/fsp1_1/raminit.c @@ -47,7 +47,6 @@ void raminit(struct romstage_params *params) u32 *mrc_hob; u32 fsp_reserved_bytes; MEMORY_INIT_UPD *original_params; - struct pei_data *pei_ptr; EFI_STATUS status; VPD_DATA_REGION *vpd_ptr; UPD_DATA_REGION *upd_ptr; @@ -81,10 +80,9 @@ void raminit(struct romstage_params *params) /* Zero fill RT Buffer data and start populating fields. */ memset(&fsp_rt_common_buffer, 0, sizeof(fsp_rt_common_buffer)); - pei_ptr = params->pei_data; if (s3wake) { fsp_rt_common_buffer.BootMode = BOOT_ON_S3_RESUME; - } else if (pei_ptr->saved_data != NULL) { + } else if (params->saved_data != NULL) { fsp_rt_common_buffer.BootMode = BOOT_ASSUMING_NO_CONFIGURATION_CHANGES; } else { @@ -94,7 +92,7 @@ void raminit(struct romstage_params *params) fsp_rt_common_buffer.BootLoaderTolumSize = cbmem_overhead_size(); /* Get any board specific changes */ - fsp_memory_init_params.NvsBufferPtr = (void *)pei_ptr->saved_data; + fsp_memory_init_params.NvsBufferPtr = (void *)params->saved_data; fsp_memory_init_params.RtBufferPtr = &fsp_rt_common_buffer; fsp_memory_init_params.HobListPtr = &hob_list_ptr; @@ -221,7 +219,7 @@ void raminit(struct romstage_params *params) } hob_ptr.Raw = get_next_guid_hob(&mrc_guid, hob_list_ptr); if (hob_ptr.Raw == NULL) { - if (params->pei_data->saved_data == NULL) { + if (params->saved_data == NULL) { printk(BIOS_ERR, "7.3: FSP_NON_VOLATILE_STORAGE_HOB missing!\n"); fsp_verification_failure = 1; } @@ -295,8 +293,8 @@ void raminit(struct romstage_params *params) "Memory Configuration Data Hob not present\n"); else if (!vboot_recovery_mode_enabled()) { /* Do not save MRC data in recovery path */ - pei_ptr->data_to_save = GET_GUID_HOB_DATA(mrc_hob); - pei_ptr->data_to_save_size = ALIGN( + params->data_to_save = GET_GUID_HOB_DATA(mrc_hob); + params->data_to_save_size = ALIGN( ((u32)GET_HOB_LENGTH(mrc_hob)), 16); } } diff --git a/src/drivers/intel/fsp1_1/romstage.c b/src/drivers/intel/fsp1_1/romstage.c index 17bd638290..87fd1a4c01 100644 --- a/src/drivers/intel/fsp1_1/romstage.c +++ b/src/drivers/intel/fsp1_1/romstage.c @@ -94,13 +94,11 @@ void romstage_common(struct romstage_params *params) { bool s3wake; struct region_device rdev; - struct pei_data *pei_data; post_code(0x32); timestamp_add_now(TS_BEFORE_INITRAM); - pei_data = params->pei_data; s3wake = params->power_state->prev_sleep_state == ACPI_S3; if (CONFIG(ELOG_BOOT_COUNT) && !s3wake) @@ -111,9 +109,9 @@ void romstage_common(struct romstage_params *params) post_code(0x33); /* Check recovery and MRC cache */ - params->pei_data->saved_data_size = 0; - params->pei_data->saved_data = NULL; - if (!params->pei_data->disable_saved_data) { + params->saved_data_size = 0; + params->saved_data = NULL; + if (!params->disable_saved_data) { if (vboot_recovery_mode_enabled()) { /* Recovery mode does not use MRC cache */ printk(BIOS_DEBUG, @@ -123,9 +121,8 @@ void romstage_common(struct romstage_params *params) params->fsp_version, &rdev))) { /* MRC cache found */ - params->pei_data->saved_data_size = - region_device_sz(&rdev); - params->pei_data->saved_data = rdev_mmap_full(&rdev); + params->saved_data_size = region_device_sz(&rdev); + params->saved_data = rdev_mmap_full(&rdev); /* Assume boot device is memory mapped. */ assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED)); } else if (s3wake) { @@ -146,15 +143,15 @@ void romstage_common(struct romstage_params *params) /* Save MRC output */ if (CONFIG(CACHE_MRC_SETTINGS)) { - printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", - pei_data->data_to_save, pei_data->data_to_save_size); + printk(BIOS_DEBUG, "MRC data at %p %zu bytes\n", + params->data_to_save, params->data_to_save_size); if (!s3wake - && (params->pei_data->data_to_save_size != 0) - && (params->pei_data->data_to_save != NULL)) + && (params->data_to_save_size != 0) + && (params->data_to_save != NULL)) mrc_cache_stash_data(MRC_TRAINING_DATA, params->fsp_version, - params->pei_data->data_to_save, - params->pei_data->data_to_save_size); + params->data_to_save, + params->data_to_save_size); } /* Save DIMM information */ diff --git a/src/soc/intel/braswell/include/soc/pei_data.h b/src/soc/intel/braswell/include/soc/pei_data.h index 7ea83ba8db..df18dc087a 100644 --- a/src/soc/intel/braswell/include/soc/pei_data.h +++ b/src/soc/intel/braswell/include/soc/pei_data.h @@ -43,15 +43,6 @@ struct pei_data { void *spd_data_ch1; uint8_t spd_ch0_config; uint8_t spd_ch1_config; - - /* Fast boot and S3 resume MRC data */ - int saved_data_size; - const void *saved_data; - int disable_saved_data; - - /* New save data from MRC */ - int data_to_save_size; - void *data_to_save; }; typedef struct pei_data PEI_DATA; diff --git a/src/soc/intel/skylake/include/soc/pei_data.h b/src/soc/intel/skylake/include/soc/pei_data.h index 7406a3322e..5ea2190b8e 100644 --- a/src/soc/intel/skylake/include/soc/pei_data.h +++ b/src/soc/intel/skylake/include/soc/pei_data.h @@ -80,16 +80,7 @@ struct pei_data { uint8_t dqs_map[2][8]; uint16_t RcompResistor[3]; uint16_t RcompTarget[5]; - /* 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; int mem_cfg_id; } __packed; diff --git a/src/soc/intel/skylake/pei_data.c b/src/soc/intel/skylake/pei_data.c index 203a1d8e36..7d314a106f 100644 --- a/src/soc/intel/skylake/pei_data.c +++ b/src/soc/intel/skylake/pei_data.c @@ -33,16 +33,7 @@ static void ABI_X86 send_to_console(unsigned char b) void soc_fill_pei_data(struct pei_data *pei_data) { - const struct device *dev; - const struct soc_intel_skylake_config *config; - /* Set the parameters for MemoryInit */ - dev = dev_find_slot(0, PCH_DEVFN_LPC); - config = dev->chip_info; - pei_data->pei_version = PEI_VERSION; pei_data->tx_byte = &send_to_console; - - /* Force a full memory train if RMT is enabled */ - pei_data->disable_saved_data = config->Rmt; } diff --git a/src/soc/intel/skylake/romstage/romstage.c b/src/soc/intel/skylake/romstage/romstage.c index 0501b04493..8ec08c2d0f 100644 --- a/src/soc/intel/skylake/romstage/romstage.c +++ b/src/soc/intel/skylake/romstage/romstage.c @@ -46,6 +46,12 @@ void soc_pre_ram_init(struct romstage_params *params) /* Prepare to initialize memory */ soc_fill_pei_data(params->pei_data); + + const struct device *const dev = pcidev_path_on_root(PCH_DEVFN_LPC); + const struct soc_intel_skylake_config *const config = + dev ? dev->chip_info : NULL; + /* Force a full memory train if RMT is enabled */ + params->disable_saved_data = config && config->Rmt; } /* UPD parameters to be initialized before MemoryInit */ From 9b5b9e46b9342500a411514e62032fa3edb565a2 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Sat, 4 May 2019 17:06:06 +0200 Subject: [PATCH 055/107] mb/intel/kunimitsu: Refactor to get rid of `pei_data` The SoC specific `struct pei_data` was filled with values that were later only consumed by the mainboard code again. Avoid jumping through this hoop and fill FSP UPDs directly. Change-Id: Ibc013ccea9f83ef29f22fe2da4c0d12096308636 Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/32590 Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier Reviewed-by: Patrick Rudolph --- src/mainboard/intel/kunimitsu/Makefile.inc | 3 -- src/mainboard/intel/kunimitsu/pei_data.c | 29 ------------------- src/mainboard/intel/kunimitsu/romstage.c | 30 ++++---------------- src/mainboard/intel/kunimitsu/spd/spd.c | 20 ++++++------- src/mainboard/intel/kunimitsu/spd/spd.h | 2 ++ src/mainboard/intel/kunimitsu/spd/spd_util.c | 2 -- 6 files changed, 17 insertions(+), 69 deletions(-) delete mode 100644 src/mainboard/intel/kunimitsu/pei_data.c diff --git a/src/mainboard/intel/kunimitsu/Makefile.inc b/src/mainboard/intel/kunimitsu/Makefile.inc index dc4b83c0bb..3330a0aab8 100644 --- a/src/mainboard/intel/kunimitsu/Makefile.inc +++ b/src/mainboard/intel/kunimitsu/Makefile.inc @@ -18,8 +18,6 @@ subdirs-y += spd bootblock-y += bootblock_mainboard.c -romstage-y += pei_data.c - bootblock-$(CONFIG_CHROMEOS) += chromeos.c verstage-$(CONFIG_CHROMEOS) += chromeos.c romstage-$(CONFIG_CHROMEOS) += chromeos.c @@ -28,7 +26,6 @@ ramstage-$(CONFIG_CHROMEOS) += chromeos.c ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC) += ec.c ramstage-y += mainboard.c -ramstage-y += pei_data.c ramstage-y += ramstage.c smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c diff --git a/src/mainboard/intel/kunimitsu/pei_data.c b/src/mainboard/intel/kunimitsu/pei_data.c deleted file mode 100644 index bfc40c2748..0000000000 --- a/src/mainboard/intel/kunimitsu/pei_data.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2014 Google Inc. - * Copyright (C) 2015 Intel Corporation. - * - * 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; version 2 of the License. - * - * 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 -#include -#include -#include "boardid.h" -#include "spd/spd.h" - -void mainboard_fill_pei_data(struct pei_data *pei_data) -{ - mainboard_fill_dq_map_data(&pei_data->dq_map); - mainboard_fill_dqs_map_data(&pei_data->dqs_map); - mainboard_fill_rcomp_res_data(&pei_data->RcompResistor); - mainboard_fill_rcomp_strength_data(&pei_data->RcompTarget); -} diff --git a/src/mainboard/intel/kunimitsu/romstage.c b/src/mainboard/intel/kunimitsu/romstage.c index 1c6f5a2cd3..f25f88b4dd 100644 --- a/src/mainboard/intel/kunimitsu/romstage.c +++ b/src/mainboard/intel/kunimitsu/romstage.c @@ -15,20 +15,13 @@ * GNU General Public License for more details. */ -#include #include -#include -#include #include #include "gpio.h" #include "spd/spd.h" void mainboard_romstage_entry(struct romstage_params *params) { - params->pei_data->mem_cfg_id = get_spd_index(); - /* Fill out PEI DATA */ - mainboard_fill_pei_data(params->pei_data); - mainboard_fill_spd_data(params->pei_data); /* Initialize memory */ romstage_common(params); } @@ -36,24 +29,11 @@ void mainboard_romstage_entry(struct romstage_params *params) void mainboard_memory_init_params(struct romstage_params *params, MEMORY_INIT_UPD *memory_params) { - if (params->pei_data->spd_data[0][0][0] != 0) { - memory_params->MemorySpdPtr00 = - (UINT32)(params->pei_data->spd_data[0][0]); - memory_params->MemorySpdPtr10 = - (UINT32)(params->pei_data->spd_data[1][0]); - } - memcpy(memory_params->DqByteMapCh0, params->pei_data->dq_map[0], - sizeof(params->pei_data->dq_map[0])); - memcpy(memory_params->DqByteMapCh1, params->pei_data->dq_map[1], - sizeof(params->pei_data->dq_map[1])); - memcpy(memory_params->DqsMapCpu2DramCh0, params->pei_data->dqs_map[0], - sizeof(params->pei_data->dqs_map[0])); - memcpy(memory_params->DqsMapCpu2DramCh1, params->pei_data->dqs_map[1], - sizeof(params->pei_data->dqs_map[1])); - memcpy(memory_params->RcompResistor, params->pei_data->RcompResistor, - sizeof(params->pei_data->RcompResistor)); - memcpy(memory_params->RcompTarget, params->pei_data->RcompTarget, - sizeof(params->pei_data->RcompTarget)); + spd_memory_init_params(memory_params); + mainboard_fill_dq_map_data(&memory_params->DqByteMapCh0); + mainboard_fill_dqs_map_data(&memory_params->DqsMapCpu2DramCh0); + mainboard_fill_rcomp_res_data(&memory_params->RcompResistor); + mainboard_fill_rcomp_strength_data(&memory_params->RcompTarget); memory_params->MemorySpdDataLen = SPD_LEN; memory_params->DqPinsInterleaved = FALSE; } diff --git a/src/mainboard/intel/kunimitsu/spd/spd.c b/src/mainboard/intel/kunimitsu/spd/spd.c index 8656d4bc17..bebb544a4d 100644 --- a/src/mainboard/intel/kunimitsu/spd/spd.c +++ b/src/mainboard/intel/kunimitsu/spd/spd.c @@ -16,8 +16,9 @@ #include #include -#include +#include #include +#include #include #include "spd.h" @@ -73,20 +74,19 @@ static void mainboard_print_spd_info(uint8_t spd[]) } } -/* Copy SPD data for on-board memory */ -void mainboard_fill_spd_data(struct pei_data *pei_data) +/* Fill SPD pointers for on-board memory */ +void spd_memory_init_params(MEMORY_INIT_UPD *memory_params) { uintptr_t spd_data; spd_data = mainboard_get_spd_data(); - memcpy(pei_data->spd_data[0][0], (void *)spd_data, SPD_LEN); - - if (mainboard_has_dual_channel_mem()) - memcpy(pei_data->spd_data[1][0], (void *)spd_data, SPD_LEN); - /* Make sure a valid SPD was found */ - if (pei_data->spd_data[0][0][0] == 0) + if (*(uint8_t *)spd_data == 0) die("Invalid SPD data."); - mainboard_print_spd_info(pei_data->spd_data[0][0]); + memory_params->MemorySpdPtr00 = spd_data; + if (mainboard_has_dual_channel_mem()) + memory_params->MemorySpdPtr10 = spd_data; + + mainboard_print_spd_info((uint8_t *)spd_data); } diff --git a/src/mainboard/intel/kunimitsu/spd/spd.h b/src/mainboard/intel/kunimitsu/spd/spd.h index f53c9ec9fa..22d371f4bc 100644 --- a/src/mainboard/intel/kunimitsu/spd/spd.h +++ b/src/mainboard/intel/kunimitsu/spd/spd.h @@ -16,6 +16,7 @@ #ifndef MAINBOARD_SPD_H +#include #include #include "../gpio.h" @@ -53,6 +54,7 @@ static inline int get_spd_index(void) { }; return (gpio_base2_value(spd_gpios, ARRAY_SIZE(spd_gpios))); } +void spd_memory_init_params(MEMORY_INIT_UPD *memory_params); void mainboard_fill_dq_map_data(void *dq_map_ptr); void mainboard_fill_dqs_map_data(void *dqs_map_ptr); void mainboard_fill_rcomp_res_data(void *rcomp_ptr); diff --git a/src/mainboard/intel/kunimitsu/spd/spd_util.c b/src/mainboard/intel/kunimitsu/spd/spd_util.c index fc0581cb24..b173628e29 100644 --- a/src/mainboard/intel/kunimitsu/spd/spd_util.c +++ b/src/mainboard/intel/kunimitsu/spd/spd_util.c @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include "boardid.h" #include "spd.h" From f98f8ebb8cb43f17c8d244f2c4cce2e257355e37 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Sat, 4 May 2019 17:06:06 +0200 Subject: [PATCH 056/107] mb/intel/saddlebrook: Refactor to get rid of `pei_data` The SoC specific `struct pei_data` was filled with values that were later only consumed by the mainboard code again. Avoid jumping through this hoop and fill FSP UPDs directly. Change-Id: I399dd89f85ccea43fdf90bd895e71324f4b409cc Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/32591 Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier Reviewed-by: Patrick Rudolph --- src/mainboard/intel/saddlebrook/Makefile.inc | 1 - src/mainboard/intel/saddlebrook/pei_data.c | 27 ------------------- src/mainboard/intel/saddlebrook/romstage.c | 20 +++----------- .../intel/saddlebrook/spd/spd_util.c | 2 -- 4 files changed, 4 insertions(+), 46 deletions(-) delete mode 100644 src/mainboard/intel/saddlebrook/pei_data.c diff --git a/src/mainboard/intel/saddlebrook/Makefile.inc b/src/mainboard/intel/saddlebrook/Makefile.inc index 63889af078..683462b9de 100644 --- a/src/mainboard/intel/saddlebrook/Makefile.inc +++ b/src/mainboard/intel/saddlebrook/Makefile.inc @@ -17,6 +17,5 @@ subdirs-y += spd bootblock-y += bootblock.c -romstage-y += pei_data.c ramstage-y += ramstage.c diff --git a/src/mainboard/intel/saddlebrook/pei_data.c b/src/mainboard/intel/saddlebrook/pei_data.c deleted file mode 100644 index ac4ce95723..0000000000 --- a/src/mainboard/intel/saddlebrook/pei_data.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2014 Google Inc. - * Copyright (C) 2015 Intel Corporation. - * - * 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; version 2 of the License. - * - * 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 -#include -#include "spd/spd.h" - -void mainboard_fill_pei_data(struct pei_data *pei_data) -{ - mainboard_fill_dq_map_data(&pei_data->dq_map); - mainboard_fill_dqs_map_data(&pei_data->dqs_map); - mainboard_fill_rcomp_res_data(&pei_data->RcompResistor); - mainboard_fill_rcomp_strength_data(&pei_data->RcompTarget); -} diff --git a/src/mainboard/intel/saddlebrook/romstage.c b/src/mainboard/intel/saddlebrook/romstage.c index d19629cf9e..48d39db309 100644 --- a/src/mainboard/intel/saddlebrook/romstage.c +++ b/src/mainboard/intel/saddlebrook/romstage.c @@ -19,8 +19,6 @@ #include #include #include -#include -#include #include #include #include "spd/spd.h" @@ -38,8 +36,6 @@ void car_mainboard_pre_console_init(void) void mainboard_romstage_entry(struct romstage_params *params) { post_code(0x31); - /* Fill out PEI DATA */ - mainboard_fill_pei_data(params->pei_data); romstage_common(params); } @@ -67,18 +63,10 @@ void mainboard_memory_init_params( * should be set in the FSP flash image and should not need to be * changed. */ - memcpy(memory_params->DqByteMapCh0, params->pei_data->dq_map[0], - sizeof(params->pei_data->dq_map[0])); - memcpy(memory_params->DqByteMapCh1, params->pei_data->dq_map[1], - sizeof(params->pei_data->dq_map[1])); - memcpy(memory_params->DqsMapCpu2DramCh0, params->pei_data->dqs_map[0], - sizeof(params->pei_data->dqs_map[0])); - memcpy(memory_params->DqsMapCpu2DramCh1, params->pei_data->dqs_map[1], - sizeof(params->pei_data->dqs_map[1])); - memcpy(memory_params->RcompResistor, params->pei_data->RcompResistor, - sizeof(params->pei_data->RcompResistor)); - memcpy(memory_params->RcompTarget, params->pei_data->RcompTarget, - sizeof(params->pei_data->RcompTarget)); + mainboard_fill_dq_map_data(&memory_params->DqByteMapCh0); + mainboard_fill_dqs_map_data(&memory_params->DqsMapCpu2DramCh0); + mainboard_fill_rcomp_res_data(&memory_params->RcompResistor); + mainboard_fill_rcomp_strength_data(&memory_params->RcompTarget); /* update spd length*/ memory_params->MemorySpdDataLen = blk.len; diff --git a/src/mainboard/intel/saddlebrook/spd/spd_util.c b/src/mainboard/intel/saddlebrook/spd/spd_util.c index 2c26d787d7..5055d9a3af 100644 --- a/src/mainboard/intel/saddlebrook/spd/spd_util.c +++ b/src/mainboard/intel/saddlebrook/spd/spd_util.c @@ -15,8 +15,6 @@ #include #include -#include -#include #include "spd.h" void mainboard_fill_dq_map_data(void *dq_map_ptr) From ec562161cd2265c924482835fd2ab32c13ba587e Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Sat, 4 May 2019 17:17:40 +0200 Subject: [PATCH 057/107] soc/intel/bsw: Move memory init values into `romstage.h` `chip.h` is usually used as devicetree interface. Change-Id: Ied30927d68927b86758a84ccf3f5fbd8cce632f1 Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/32592 Reviewed-by: Patrick Georgi Reviewed-by: Matt DeVillier Reviewed-by: Frans Hendriks Tested-by: build bot (Jenkins) --- src/mainboard/google/cyan/romstage.c | 1 - src/mainboard/intel/strago/romstage.c | 1 - src/soc/intel/braswell/chip.h | 3 --- src/soc/intel/braswell/include/soc/romstage.h | 4 ++++ 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/mainboard/google/cyan/romstage.c b/src/mainboard/google/cyan/romstage.c index aa20593d5f..5470b9c465 100644 --- a/src/mainboard/google/cyan/romstage.c +++ b/src/mainboard/google/cyan/romstage.c @@ -16,7 +16,6 @@ #include #include -#include /* All FSP specific code goes in this block */ void mainboard_romstage_entry(struct romstage_params *rp) diff --git a/src/mainboard/intel/strago/romstage.c b/src/mainboard/intel/strago/romstage.c index 0f3067ea81..ba0ff7b85e 100644 --- a/src/mainboard/intel/strago/romstage.c +++ b/src/mainboard/intel/strago/romstage.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "onboard.h" #include diff --git a/src/soc/intel/braswell/chip.h b/src/soc/intel/braswell/chip.h index bb06dd595a..5a00328f4d 100644 --- a/src/soc/intel/braswell/chip.h +++ b/src/soc/intel/braswell/chip.h @@ -32,9 +32,6 @@ #define SVID_CONFIG3 3 #define SVID_PMIC_CONFIG 8 -#define MEM_DDR3 0 -#define MEM_LPDDR3 1 - enum lpe_clk_src { LPE_CLK_SRC_XTAL, LPE_CLK_SRC_PLL, diff --git a/src/soc/intel/braswell/include/soc/romstage.h b/src/soc/intel/braswell/include/soc/romstage.h index 8fa9c8a713..2512430f75 100644 --- a/src/soc/intel/braswell/include/soc/romstage.h +++ b/src/soc/intel/braswell/include/soc/romstage.h @@ -34,4 +34,8 @@ void set_max_freq(void); void program_base_addresses(void); int chipset_prev_sleep_state(struct chipset_power_state *ps); +/* Values for FSP's PcdMemoryTypeEnable */ +#define MEM_DDR3 0 +#define MEM_LPDDR3 1 + #endif /* _SOC_ROMSTAGE_H_ */ From 85f0b051ba441dead63a4a14f4f20d49581fea0e Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Sat, 4 May 2019 17:06:06 +0200 Subject: [PATCH 058/107] mb/google/cyan: Refactor to get rid of `pei_data` The SoC specific `struct pei_data` was filled with values that were later only consumed by the mainboard code again. Avoid jumping through this hoop and fill FSP UPDs directly. The provided solution locates the SPD data in CBFS again to fill SMBIOS tables. This is not perfect. OTOH, this code isn't mainboard specific and doesn't belong here anyway. Change-Id: Ib6103d5b9550846fe17c926631a013ff80b9598f Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/32593 Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier Reviewed-by: Patrick Rudolph --- src/mainboard/google/cyan/romstage.c | 17 ++----- src/mainboard/google/cyan/spd/spd.c | 64 ++++++++++++++---------- src/mainboard/google/cyan/spd/spd_util.h | 3 ++ 3 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/mainboard/google/cyan/romstage.c b/src/mainboard/google/cyan/romstage.c index 5470b9c465..c877e42055 100644 --- a/src/mainboard/google/cyan/romstage.c +++ b/src/mainboard/google/cyan/romstage.c @@ -17,13 +17,11 @@ #include #include +#include "spd/spd_util.h" + /* All FSP specific code goes in this block */ void mainboard_romstage_entry(struct romstage_params *rp) { - struct pei_data *ps = rp->pei_data; - - mainboard_fill_spd_data(ps); - /* Call back into chipset code with platform values updated. */ romstage_common(rp); } @@ -31,16 +29,7 @@ void mainboard_romstage_entry(struct romstage_params *rp) void mainboard_memory_init_params(struct romstage_params *params, MEMORY_INIT_UPD *memory_params) { - /* Update SPD data */ - if (CONFIG(BOARD_GOOGLE_CYAN)) { - memory_params->PcdMemoryTypeEnable = MEM_DDR3; - memory_params->PcdMemorySpdPtr = - (u32)params->pei_data->spd_data_ch0; - } else - memory_params->PcdMemoryTypeEnable = MEM_LPDDR3; - - memory_params->PcdMemChannel0Config = params->pei_data->spd_ch0_config; - memory_params->PcdMemChannel1Config = params->pei_data->spd_ch1_config; + spd_memory_init_params(memory_params); /* Variant-specific memory params */ variant_memory_init_params(memory_params); diff --git a/src/mainboard/google/cyan/spd/spd.c b/src/mainboard/google/cyan/spd/spd.c index af694a4339..7c66e947fc 100644 --- a/src/mainboard/google/cyan/spd/spd.c +++ b/src/mainboard/google/cyan/spd/spd.c @@ -40,11 +40,24 @@ __weak uint8_t get_ramid(void) return gpio_base2_value(spd_gpios, ARRAY_SIZE(spd_gpios)); } -static void *get_spd_pointer(char *spd_file_content, int total_spds, int *dual) +static void *get_spd_pointer(int *dual) { + char *spd_file; + size_t spd_file_len; + int total_spds; int ram_id = 0; int spd_index = 0; + /* Find the SPD data in CBFS. */ + spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD, + &spd_file_len); + if (!spd_file) + die("SPD data not found."); + + if (spd_file_len < SPD_PAGE_LEN) + die("Missing SPD data."); + total_spds = spd_file_len / SPD_PAGE_LEN; + ram_id = get_ramid(); printk(BIOS_DEBUG, "ram_id=%d, total_spds: %d\n", ram_id, total_spds); @@ -54,33 +67,20 @@ static void *get_spd_pointer(char *spd_file_content, int total_spds, int *dual) return NULL; } /* Return the serial product data for the RAM */ - return &spd_file_content[SPD_PAGE_LEN * spd_index]; + return &spd_file[SPD_PAGE_LEN * spd_index]; } /* Copy SPD data for on-board memory */ -void mainboard_fill_spd_data(struct pei_data *ps) +void spd_memory_init_params(MEMORY_INIT_UPD *memory_params) { - char *spd_file; - size_t spd_file_len; void *spd_content; int dual_channel = 0; - /* Find the SPD data in CBFS. */ - spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD, - &spd_file_len); - if (!spd_file) - die("SPD data not found."); - - if (spd_file_len < SPD_PAGE_LEN) - die("Missing SPD data."); - /* * Both channels are always present in SPD data. Always use matched * DIMMs so use the same SPD data for each DIMM. */ - spd_content = get_spd_pointer(spd_file, - spd_file_len / SPD_PAGE_LEN, - &dual_channel); + spd_content = get_spd_pointer(&dual_channel); if (CONFIG(DISPLAY_SPD_DATA) && spd_content != NULL) { printk(BIOS_DEBUG, "SPD Data:\n"); hexdump(spd_content, SPD_PAGE_LEN); @@ -94,21 +94,27 @@ void mainboard_fill_spd_data(struct pei_data *ps) * 2=DimmDisabled */ if (spd_content != NULL) { - ps->spd_data_ch0 = spd_content; - ps->spd_ch0_config = 1; + memory_params->PcdMemChannel0Config = 1; printk(BIOS_DEBUG, "Channel 0 DIMM soldered down\n"); if (dual_channel) { printk(BIOS_DEBUG, "Channel 1 DIMM soldered down\n"); - ps->spd_data_ch1 = spd_content; - ps->spd_ch1_config = 1; + memory_params->PcdMemChannel1Config = 1; } else { printk(BIOS_DEBUG, "Channel 1 DIMM not installed\n"); - ps->spd_ch1_config = 2; + memory_params->PcdMemChannel1Config = 2; } } + + /* Update SPD data */ + if (CONFIG(BOARD_GOOGLE_CYAN)) { + memory_params->PcdMemoryTypeEnable = MEM_DDR3; + memory_params->PcdMemorySpdPtr = (uintptr_t)spd_content; + } else { + memory_params->PcdMemoryTypeEnable = MEM_LPDDR3; + } } -static void set_dimm_info(uint8_t *spd, struct dimm_info *dimm) +static void set_dimm_info(const uint8_t *spd, struct dimm_info *dimm) { const int spd_capmb[8] = { 1, 2, 4, 8, 16, 32, 64, 0 }; const int spd_ranks[8] = { 1, 2, 3, 4, -1, -1, -1, -1 }; @@ -171,9 +177,15 @@ static void set_dimm_info(uint8_t *spd, struct dimm_info *dimm) void mainboard_save_dimm_info(struct romstage_params *params) { + const void *spd_content; + int dual_channel; struct dimm_info *dimm; struct memory_info *mem_info; + spd_content = get_spd_pointer(&dual_channel); + if (spd_content == NULL) + return; + /* * Allocate CBMEM area for DIMM information used to populate SMBIOS * table 17 @@ -186,13 +198,13 @@ void mainboard_save_dimm_info(struct romstage_params *params) /* Describe the first channel memory */ dimm = &mem_info->dimm[0]; - set_dimm_info(params->pei_data->spd_data_ch0, dimm); + set_dimm_info(spd_content, dimm); mem_info->dimm_cnt = 1; /* Describe the second channel memory */ - if (params->pei_data->spd_ch1_config == 1) { + if (dual_channel) { dimm = &mem_info->dimm[1]; - set_dimm_info(params->pei_data->spd_data_ch1, dimm); + set_dimm_info(spd_content, dimm); dimm->channel_num = 1; mem_info->dimm_cnt = 2; } diff --git a/src/mainboard/google/cyan/spd/spd_util.h b/src/mainboard/google/cyan/spd/spd_util.h index 11d6eaa16d..0c5b3265ef 100644 --- a/src/mainboard/google/cyan/spd/spd_util.h +++ b/src/mainboard/google/cyan/spd/spd_util.h @@ -16,7 +16,10 @@ #ifndef SPD_UTIL_H #define SPD_UTIL_H +#include + uint8_t get_ramid(void); int get_variant_spd_index(int ram_id, int *dual); +void spd_memory_init_params(MEMORY_INIT_UPD *memory_params); #endif /* SPD_UTIL_H */ From feb50f15cc888150c90a5a12e749773cfe401dd5 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Sat, 4 May 2019 17:06:06 +0200 Subject: [PATCH 059/107] mb/google/glados: Refactor to get rid of `pei_data` The SoC specific `struct pei_data` was filled with values that were later only consumed by the mainboard code again. Avoid jumping through this hoop and fill FSP UPDs directly. Change-Id: I040f4a55b4f4bad3f6072920e5e2eceded4cb9bb Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/32594 Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier Reviewed-by: Patrick Rudolph --- src/mainboard/google/glados/romstage.c | 52 ++++++------------- src/mainboard/google/glados/spd/spd.c | 25 +++++---- src/mainboard/google/glados/spd/spd_util.h | 21 ++++++++ .../google/glados/variants/asuka/variant.c | 20 +++---- .../baseboard/include/baseboard/variant.h | 3 ++ .../google/glados/variants/caroline/variant.c | 21 ++++---- .../google/glados/variants/cave/variant.c | 20 +++---- .../google/glados/variants/chell/variant.c | 20 +++---- .../google/glados/variants/glados/variant.c | 20 +++---- .../google/glados/variants/lars/variant.c | 23 ++++---- .../google/glados/variants/sentry/variant.c | 23 ++++---- 11 files changed, 132 insertions(+), 116 deletions(-) create mode 100644 src/mainboard/google/glados/spd/spd_util.h diff --git a/src/mainboard/google/glados/romstage.c b/src/mainboard/google/glados/romstage.c index 81f0866dd6..47524c28ba 100644 --- a/src/mainboard/google/glados/romstage.c +++ b/src/mainboard/google/glados/romstage.c @@ -15,16 +15,16 @@ * GNU General Public License for more details. */ -#include +#include #include #include -#include -#include #include -#include "spd/spd.h" #include #include +#include "spd/spd_util.h" +#include "spd/spd.h" + void mainboard_romstage_entry(struct romstage_params *params) { #ifdef EC_ENABLE_KEYBOARD_BACKLIGHT @@ -32,18 +32,6 @@ void mainboard_romstage_entry(struct romstage_params *params) if (params->power_state->prev_sleep_state != ACPI_S3) google_chromeec_kbbacklight(25); #endif - /* Get SPD index */ - gpio_t spd_gpios[] = { - GPIO_MEM_CONFIG_0, - GPIO_MEM_CONFIG_1, - GPIO_MEM_CONFIG_2, - GPIO_MEM_CONFIG_3, - }; - params->pei_data->mem_cfg_id = - gpio_base2_value(spd_gpios, ARRAY_SIZE(spd_gpios)); - /* Fill out PEI DATA */ - mainboard_fill_pei_data(params->pei_data); - mainboard_fill_spd_data(params->pei_data); /* Initialize memory */ romstage_common(params); } @@ -51,26 +39,18 @@ void mainboard_romstage_entry(struct romstage_params *params) void mainboard_memory_init_params(struct romstage_params *params, MEMORY_INIT_UPD *memory_params) { - if (params->pei_data->spd_data[0][0][0] != 0) { - memory_params->MemorySpdPtr00 = - (UINT32)(params->pei_data->spd_data[0][0]); - memory_params->MemorySpdPtr10 = - (UINT32)(params->pei_data->spd_data[1][0]); - } - memcpy(memory_params->DqByteMapCh0, params->pei_data->dq_map[0], - sizeof(params->pei_data->dq_map[0])); - memcpy(memory_params->DqByteMapCh1, params->pei_data->dq_map[1], - sizeof(params->pei_data->dq_map[1])); - memcpy(memory_params->DqsMapCpu2DramCh0, params->pei_data->dqs_map[0], - sizeof(params->pei_data->dqs_map[0])); - memcpy(memory_params->DqsMapCpu2DramCh1, params->pei_data->dqs_map[1], - sizeof(params->pei_data->dqs_map[1])); - memcpy(memory_params->RcompResistor, params->pei_data->RcompResistor, - sizeof(params->pei_data->RcompResistor)); - memcpy(memory_params->RcompTarget, params->pei_data->RcompTarget, - sizeof(params->pei_data->RcompTarget)); + /* Get SPD index */ + const gpio_t spd_gpios[] = { + GPIO_MEM_CONFIG_0, + GPIO_MEM_CONFIG_1, + GPIO_MEM_CONFIG_2, + GPIO_MEM_CONFIG_3, + }; + const int spd_idx = gpio_base2_value(spd_gpios, ARRAY_SIZE(spd_gpios)); + memory_params->MemorySpdDataLen = SPD_LEN; memory_params->DqPinsInterleaved = FALSE; - if (CONFIG(BOARD_GOOGLE_CAROLINE)) - memory_params->DdrFreqLimit = 1600; + + spd_memory_init_params(memory_params, spd_idx); + variant_memory_init_params(memory_params, spd_idx); } diff --git a/src/mainboard/google/glados/spd/spd.c b/src/mainboard/google/glados/spd/spd.c index 391b702172..b3cf3f9416 100644 --- a/src/mainboard/google/glados/spd/spd.c +++ b/src/mainboard/google/glados/spd/spd.c @@ -19,10 +19,11 @@ #include #include #include -#include #include #include #include + +#include "spd_util.h" #include "spd.h" static void mainboard_print_spd_info(uint8_t spd[]) @@ -83,13 +84,11 @@ __weak int is_dual_channel(const int spd_index) } /* Copy SPD data for on-board memory */ -void mainboard_fill_spd_data(struct pei_data *pei_data) +void spd_memory_init_params(MEMORY_INIT_UPD *const memory_params, int spd_index) { - char *spd_file; + uint8_t *spd_file; size_t spd_file_len; - int spd_index; - spd_index = pei_data->mem_cfg_id; printk(BIOS_INFO, "SPD index %d\n", spd_index); /* Load SPD data from CBFS */ @@ -108,15 +107,15 @@ void mainboard_fill_spd_data(struct pei_data *pei_data) spd_index = 1; } - /* Assume same memory in both channels */ - spd_index *= SPD_LEN; - memcpy(pei_data->spd_data[0][0], spd_file + spd_index, SPD_LEN); - if (is_dual_channel(spd_index)) - memcpy(pei_data->spd_data[1][0], spd_file + spd_index, SPD_LEN); - + const size_t spd_offset = spd_index * SPD_LEN; /* Make sure a valid SPD was found */ - if (pei_data->spd_data[0][0][0] == 0) + if (spd_file[spd_offset] == 0) die("Invalid SPD data."); - mainboard_print_spd_info(pei_data->spd_data[0][0]); + /* Assume same memory in both channels */ + memory_params->MemorySpdPtr00 = (uintptr_t)spd_file + spd_offset; + if (is_dual_channel(spd_index)) + memory_params->MemorySpdPtr10 = memory_params->MemorySpdPtr00; + + mainboard_print_spd_info(spd_file + spd_offset); } diff --git a/src/mainboard/google/glados/spd/spd_util.h b/src/mainboard/google/glados/spd/spd_util.h new file mode 100644 index 0000000000..90dbd5ff98 --- /dev/null +++ b/src/mainboard/google/glados/spd/spd_util.h @@ -0,0 +1,21 @@ +/* + * This file is part of the coreboot project. + * + * 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; version 2 of the License. + * + * 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. + */ + +#ifndef SPD_UTIL_H +#define SPD_UTIL_H + +#include + +void spd_memory_init_params(MEMORY_INIT_UPD *, int spd_index); + +#endif /* SPD_UTIL_H */ diff --git a/src/mainboard/google/glados/variants/asuka/variant.c b/src/mainboard/google/glados/variants/asuka/variant.c index 13cfe4fecd..4c778970fe 100644 --- a/src/mainboard/google/glados/variants/asuka/variant.c +++ b/src/mainboard/google/glados/variants/asuka/variant.c @@ -17,10 +17,10 @@ #include #include #include -#include -#include +#include -void mainboard_fill_pei_data(struct pei_data *pei_data) +void variant_memory_init_params( + MEMORY_INIT_UPD *const memory_params, const int spd_index) { /* DQ byte map */ const u8 dq_map[2][12] = { @@ -39,12 +39,14 @@ void mainboard_fill_pei_data(struct pei_data *pei_data) /* Rcomp target */ const u16 RcompTarget[5] = { 100, 40, 40, 23, 40 }; - memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); - memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); - memcpy(pei_data->RcompResistor, RcompResistor, - sizeof(RcompResistor)); - memcpy(pei_data->RcompTarget, RcompTarget, - sizeof(RcompTarget)); + memcpy(memory_params->DqByteMapCh0, dq_map, + sizeof(memory_params->DqByteMapCh0) * 2); + memcpy(memory_params->DqsMapCpu2DramCh0, dqs_map, + sizeof(memory_params->DqsMapCpu2DramCh0) * 2); + memcpy(memory_params->RcompResistor, RcompResistor, + sizeof(memory_params->RcompResistor)); + memcpy(memory_params->RcompTarget, RcompTarget, + sizeof(memory_params->RcompTarget)); } int is_dual_channel(const int spd_index) diff --git a/src/mainboard/google/glados/variants/baseboard/include/baseboard/variant.h b/src/mainboard/google/glados/variants/baseboard/include/baseboard/variant.h index bbab7fc1f5..72eef684b8 100644 --- a/src/mainboard/google/glados/variants/baseboard/include/baseboard/variant.h +++ b/src/mainboard/google/glados/variants/baseboard/include/baseboard/variant.h @@ -15,7 +15,10 @@ #ifndef GLADOS_VARIANT_H #define GLADOS_VARIANT_H +#include + int is_dual_channel(const int spd_index); void mainboard_gpio_smi_sleep(void); +void variant_memory_init_params(MEMORY_INIT_UPD *memory_params, int spd_index); #endif /* GLADOS_VARIANT_H */ diff --git a/src/mainboard/google/glados/variants/caroline/variant.c b/src/mainboard/google/glados/variants/caroline/variant.c index a00eacf0ed..d61a538d56 100644 --- a/src/mainboard/google/glados/variants/caroline/variant.c +++ b/src/mainboard/google/glados/variants/caroline/variant.c @@ -15,14 +15,14 @@ */ #include +#include #include #include #include -#include -#include #include -void mainboard_fill_pei_data(struct pei_data *pei_data) +void variant_memory_init_params( + MEMORY_INIT_UPD *const memory_params, const int spd_index) { /* DQ byte map */ const u8 dq_map[2][12] = { @@ -41,12 +41,15 @@ void mainboard_fill_pei_data(struct pei_data *pei_data) /* Rcomp target */ const u16 RcompTarget[5] = { 100, 40, 40, 23, 40 }; - memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); - memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); - memcpy(pei_data->RcompResistor, RcompResistor, - sizeof(RcompResistor)); - memcpy(pei_data->RcompTarget, RcompTarget, - sizeof(RcompTarget)); + memcpy(memory_params->DqByteMapCh0, dq_map, + sizeof(memory_params->DqByteMapCh0) * 2); + memcpy(memory_params->DqsMapCpu2DramCh0, dqs_map, + sizeof(memory_params->DqsMapCpu2DramCh0) * 2); + memcpy(memory_params->RcompResistor, RcompResistor, + sizeof(memory_params->RcompResistor)); + memcpy(memory_params->RcompTarget, RcompTarget, + sizeof(memory_params->RcompTarget)); + memory_params->DdrFreqLimit = 1600; } void mainboard_gpio_smi_sleep(void) diff --git a/src/mainboard/google/glados/variants/cave/variant.c b/src/mainboard/google/glados/variants/cave/variant.c index 2ce0a9001c..fc27fb4b61 100644 --- a/src/mainboard/google/glados/variants/cave/variant.c +++ b/src/mainboard/google/glados/variants/cave/variant.c @@ -15,14 +15,14 @@ */ #include +#include #include #include #include -#include -#include #include -void mainboard_fill_pei_data(struct pei_data *pei_data) +void variant_memory_init_params( + MEMORY_INIT_UPD *const memory_params, const int spd_index) { /* DQ byte map */ const u8 dq_map[2][12] = { @@ -41,12 +41,14 @@ void mainboard_fill_pei_data(struct pei_data *pei_data) /* Rcomp target */ const u16 RcompTarget[5] = { 100, 40, 40, 23, 40 }; - memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); - memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); - memcpy(pei_data->RcompResistor, RcompResistor, - sizeof(RcompResistor)); - memcpy(pei_data->RcompTarget, RcompTarget, - sizeof(RcompTarget)); + memcpy(memory_params->DqByteMapCh0, dq_map, + sizeof(memory_params->DqByteMapCh0) * 2); + memcpy(memory_params->DqsMapCpu2DramCh0, dqs_map, + sizeof(memory_params->DqsMapCpu2DramCh0) * 2); + memcpy(memory_params->RcompResistor, RcompResistor, + sizeof(memory_params->RcompResistor)); + memcpy(memory_params->RcompTarget, RcompTarget, + sizeof(memory_params->RcompTarget)); } void mainboard_gpio_smi_sleep(void) diff --git a/src/mainboard/google/glados/variants/chell/variant.c b/src/mainboard/google/glados/variants/chell/variant.c index da83ed0f7d..2d1b363cab 100644 --- a/src/mainboard/google/glados/variants/chell/variant.c +++ b/src/mainboard/google/glados/variants/chell/variant.c @@ -15,14 +15,14 @@ */ #include +#include #include #include #include -#include -#include #include -void mainboard_fill_pei_data(struct pei_data *pei_data) +void variant_memory_init_params( + MEMORY_INIT_UPD *const memory_params, const int spd_index) { /* DQ byte map */ const u8 dq_map[2][12] = { @@ -41,12 +41,14 @@ void mainboard_fill_pei_data(struct pei_data *pei_data) /* Rcomp target */ const u16 RcompTarget[5] = { 100, 40, 40, 23, 40 }; - memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); - memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); - memcpy(pei_data->RcompResistor, RcompResistor, - sizeof(RcompResistor)); - memcpy(pei_data->RcompTarget, RcompTarget, - sizeof(RcompTarget)); + memcpy(memory_params->DqByteMapCh0, dq_map, + sizeof(memory_params->DqByteMapCh0) * 2); + memcpy(memory_params->DqsMapCpu2DramCh0, dqs_map, + sizeof(memory_params->DqsMapCpu2DramCh0) * 2); + memcpy(memory_params->RcompResistor, RcompResistor, + sizeof(memory_params->RcompResistor)); + memcpy(memory_params->RcompTarget, RcompTarget, + sizeof(memory_params->RcompTarget)); } void mainboard_gpio_smi_sleep(void) diff --git a/src/mainboard/google/glados/variants/glados/variant.c b/src/mainboard/google/glados/variants/glados/variant.c index 2ce0a9001c..fc27fb4b61 100644 --- a/src/mainboard/google/glados/variants/glados/variant.c +++ b/src/mainboard/google/glados/variants/glados/variant.c @@ -15,14 +15,14 @@ */ #include +#include #include #include #include -#include -#include #include -void mainboard_fill_pei_data(struct pei_data *pei_data) +void variant_memory_init_params( + MEMORY_INIT_UPD *const memory_params, const int spd_index) { /* DQ byte map */ const u8 dq_map[2][12] = { @@ -41,12 +41,14 @@ void mainboard_fill_pei_data(struct pei_data *pei_data) /* Rcomp target */ const u16 RcompTarget[5] = { 100, 40, 40, 23, 40 }; - memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); - memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); - memcpy(pei_data->RcompResistor, RcompResistor, - sizeof(RcompResistor)); - memcpy(pei_data->RcompTarget, RcompTarget, - sizeof(RcompTarget)); + memcpy(memory_params->DqByteMapCh0, dq_map, + sizeof(memory_params->DqByteMapCh0) * 2); + memcpy(memory_params->DqsMapCpu2DramCh0, dqs_map, + sizeof(memory_params->DqsMapCpu2DramCh0) * 2); + memcpy(memory_params->RcompResistor, RcompResistor, + sizeof(memory_params->RcompResistor)); + memcpy(memory_params->RcompTarget, RcompTarget, + sizeof(memory_params->RcompTarget)); } void mainboard_gpio_smi_sleep(void) diff --git a/src/mainboard/google/glados/variants/lars/variant.c b/src/mainboard/google/glados/variants/lars/variant.c index 4fe88ef7c8..cff0096291 100644 --- a/src/mainboard/google/glados/variants/lars/variant.c +++ b/src/mainboard/google/glados/variants/lars/variant.c @@ -17,8 +17,7 @@ #include #include #include -#include -#include +#include #define K4E6E304EB_MEM_ID 0x5 @@ -29,7 +28,8 @@ #define MEM_SINGLE_CHANB 0xb #define MEM_SINGLE_CHANC 0xc -void mainboard_fill_pei_data(struct pei_data *pei_data) +void variant_memory_init_params( + MEMORY_INIT_UPD *const params, const int spd_index) { /* DQ byte map */ const u8 dq_map[2][12] = { @@ -54,17 +54,18 @@ void mainboard_fill_pei_data(struct pei_data *pei_data) /* Default Rcomp Target assignment */ const u16 *targeted_rcomp = RcompTarget; - memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); - memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); - memcpy(pei_data->RcompResistor, RcompResistor, - sizeof(RcompResistor)); - /* Override Rcomp Target assignment for specific SKU(s) */ - if (pei_data->mem_cfg_id == K4E6E304EB_MEM_ID) + if (spd_index == K4E6E304EB_MEM_ID) targeted_rcomp = StrengthendRcompTarget; - memcpy(pei_data->RcompTarget, targeted_rcomp, - sizeof(pei_data->RcompTarget)); + memcpy(params->DqByteMapCh0, dq_map, + sizeof(params->DqByteMapCh0) * 2); + memcpy(params->DqsMapCpu2DramCh0, dqs_map, + sizeof(params->DqsMapCpu2DramCh0) * 2); + memcpy(params->RcompResistor, RcompResistor, + sizeof(params->RcompResistor)); + memcpy(params->RcompTarget, targeted_rcomp, + sizeof(params->RcompTarget)); } int is_dual_channel(const int spd_index) diff --git a/src/mainboard/google/glados/variants/sentry/variant.c b/src/mainboard/google/glados/variants/sentry/variant.c index 00f49fecf7..4c7fa23f08 100644 --- a/src/mainboard/google/glados/variants/sentry/variant.c +++ b/src/mainboard/google/glados/variants/sentry/variant.c @@ -17,12 +17,12 @@ #include #include #include -#include -#include +#include #define K4E6E304EE_MEM_ID 0x3 -void mainboard_fill_pei_data(struct pei_data *pei_data) +void variant_memory_init_params( + MEMORY_INIT_UPD *const memory_params, const int spd_index) { /* DQ byte map */ const u8 dq_map[2][12] = { @@ -47,15 +47,16 @@ void mainboard_fill_pei_data(struct pei_data *pei_data) /* Default Rcomp Target assignment */ const u16 *targeted_rcomp = RcompTarget; - memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); - memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); - memcpy(pei_data->RcompResistor, RcompResistor, - sizeof(RcompResistor)); - /* Override Rcomp Target assignment for specific SKU(s) */ - if (pei_data->mem_cfg_id == K4E6E304EE_MEM_ID) + if (spd_index == K4E6E304EE_MEM_ID) targeted_rcomp = StrengthendRcompTarget; - memcpy(pei_data->RcompTarget, targeted_rcomp, - sizeof(pei_data->RcompTarget)); + memcpy(memory_params->DqByteMapCh0, dq_map, + sizeof(memory_params->DqByteMapCh0) * 2); + memcpy(memory_params->DqsMapCpu2DramCh0, dqs_map, + sizeof(memory_params->DqsMapCpu2DramCh0) * 2); + memcpy(memory_params->RcompResistor, RcompResistor, + sizeof(memory_params->RcompResistor)); + memcpy(memory_params->RcompTarget, targeted_rcomp, + sizeof(memory_params->RcompTarget)); } From 0ebdf2ac75a6459534d0543d3bc963a96316f920 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Sat, 4 May 2019 17:06:06 +0200 Subject: [PATCH 060/107] mb/purism/librem_skl: Refactor to get rid of `pei_data` The SoC specific `struct pei_data` was filled with values that were never consumed anywhere again. So just merge the used code into `romstage.c` where it's effectively used. Change-Id: I499b3cfcdd5400ea132749555d433a2d8a9471a3 Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/32595 Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier Reviewed-by: Patrick Rudolph --- src/mainboard/purism/librem_skl/Makefile.inc | 3 - src/mainboard/purism/librem_skl/pei_data.c | 65 -------------------- src/mainboard/purism/librem_skl/pei_data.h | 24 -------- src/mainboard/purism/librem_skl/romstage.c | 36 ++++++++++- 4 files changed, 35 insertions(+), 93 deletions(-) delete mode 100644 src/mainboard/purism/librem_skl/pei_data.c delete mode 100644 src/mainboard/purism/librem_skl/pei_data.h diff --git a/src/mainboard/purism/librem_skl/Makefile.inc b/src/mainboard/purism/librem_skl/Makefile.inc index 5a7131f1ba..35f0f6cbde 100644 --- a/src/mainboard/purism/librem_skl/Makefile.inc +++ b/src/mainboard/purism/librem_skl/Makefile.inc @@ -13,8 +13,5 @@ ## GNU General Public License for more details. ## -romstage-y += pei_data.c - -ramstage-y += pei_data.c ramstage-y += ramstage.c ramstage-y += hda_verb.c diff --git a/src/mainboard/purism/librem_skl/pei_data.c b/src/mainboard/purism/librem_skl/pei_data.c deleted file mode 100644 index 0be917d3c7..0000000000 --- a/src/mainboard/purism/librem_skl/pei_data.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2015 Google Inc. - * Copyright (C) 2015 Intel Corporation - * Copyright (C) 2017 Purism SPC. - * - * 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; version 2 of the License. - * - * 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 -#include -#include -#include -#include "pei_data.h" - -void mainboard_fill_dq_map_data(void *dq_map_ptr) -{ - /* DQ byte map */ - const u8 dq_map[2][12] = { - { 0x0F, 0xF0, 0x00, 0xF0, 0x0F, 0xF0, - 0x0F, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, - { 0x33, 0xCC, 0x00, 0xCC, 0x33, 0xCC, - 0x33, 0x00, 0xFF, 0x00, 0xFF, 0x00 } }; - memcpy(dq_map_ptr, dq_map, sizeof(dq_map)); -} - -void mainboard_fill_dqs_map_data(void *dqs_map_ptr) -{ - /* DQS CPU<>DRAM map */ - const u8 dqs_map[2][8] = { - { 0, 1, 3, 2, 4, 5, 6, 7 }, - { 1, 0, 4, 5, 2, 3, 6, 7 } }; - memcpy(dqs_map_ptr, dqs_map, sizeof(dqs_map)); -} - -void mainboard_fill_rcomp_res_data(void *rcomp_ptr) -{ - /* Rcomp resistor */ - const u16 RcompResistor[3] = { 121, 81, 100 }; - memcpy(rcomp_ptr, RcompResistor, - sizeof(RcompResistor)); -} - -void mainboard_fill_rcomp_strength_data(void *rcomp_strength_ptr) -{ - /* Rcomp target */ - const u16 RcompTarget[5] = { 100, 40, 20, 20, 26 }; - memcpy(rcomp_strength_ptr, RcompTarget, sizeof(RcompTarget)); -} - -void mainboard_fill_pei_data(struct pei_data *pei_data) -{ - mainboard_fill_dq_map_data(&pei_data->dq_map); - mainboard_fill_dqs_map_data(&pei_data->dqs_map); - mainboard_fill_rcomp_res_data(&pei_data->RcompResistor); - mainboard_fill_rcomp_strength_data(&pei_data->RcompTarget); -} diff --git a/src/mainboard/purism/librem_skl/pei_data.h b/src/mainboard/purism/librem_skl/pei_data.h deleted file mode 100644 index 320d9803d1..0000000000 --- a/src/mainboard/purism/librem_skl/pei_data.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2017 Purism SPC. - * - * 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; version 2 of the License. - * - * 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. - */ - -#ifndef _MAINBOARD_PEI_DATA_H_ -#define _MAINBOARD_PEI_DATA_H_ - -void mainboard_fill_dq_map_data(void *dq_map_ptr); -void mainboard_fill_dqs_map_data(void *dqs_map_ptr); -void mainboard_fill_rcomp_res_data(void *rcomp_ptr); -void mainboard_fill_rcomp_strength_data(void *rcomp_strength_ptr); - -#endif diff --git a/src/mainboard/purism/librem_skl/romstage.c b/src/mainboard/purism/librem_skl/romstage.c index 63d148a98e..faf4090ae1 100644 --- a/src/mainboard/purism/librem_skl/romstage.c +++ b/src/mainboard/purism/librem_skl/romstage.c @@ -19,7 +19,41 @@ #include #include #include -#include "pei_data.h" +#include + +static void mainboard_fill_dq_map_data(void *dq_map_ptr) +{ + /* DQ byte map */ + const u8 dq_map[2][12] = { + { 0x0F, 0xF0, 0x00, 0xF0, 0x0F, 0xF0, + 0x0F, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, + { 0x33, 0xCC, 0x00, 0xCC, 0x33, 0xCC, + 0x33, 0x00, 0xFF, 0x00, 0xFF, 0x00 } }; + memcpy(dq_map_ptr, dq_map, sizeof(dq_map)); +} + +static void mainboard_fill_dqs_map_data(void *dqs_map_ptr) +{ + /* DQS CPU<>DRAM map */ + const u8 dqs_map[2][8] = { + { 0, 1, 3, 2, 4, 5, 6, 7 }, + { 1, 0, 4, 5, 2, 3, 6, 7 } }; + memcpy(dqs_map_ptr, dqs_map, sizeof(dqs_map)); +} + +static void mainboard_fill_rcomp_res_data(void *rcomp_ptr) +{ + /* Rcomp resistor */ + const u16 RcompResistor[3] = { 121, 81, 100 }; + memcpy(rcomp_ptr, RcompResistor, sizeof(RcompResistor)); +} + +static void mainboard_fill_rcomp_strength_data(void *rcomp_strength_ptr) +{ + /* Rcomp target */ + const u16 RcompTarget[5] = { 100, 40, 20, 20, 26 }; + memcpy(rcomp_strength_ptr, RcompTarget, sizeof(RcompTarget)); +} void mainboard_memory_init_params(FSPM_UPD *mupd) { From 3c0d23b6ab1ca23c9e54f3554386e7aa2cfec94d Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Sat, 4 May 2019 19:19:10 +0200 Subject: [PATCH 061/107] intel/fsp1_1: Drop remnants of `pei_data` `pei_data` was a struct with blob parameters from pre-FSP times. Somehow, it sneaked into upstream FSP1.1 support (probably because early board ports were written for a different blob). When added upstream, its usage was already perverted. It was declared at SoC level but mostly used to pass mainboard data from mainboard code to itself and FSP data from FSP code to itself. Now that no board/ SoC code uses it anymore, we can finally drop it. Change-Id: Ib0bc402703188539cf2254bdc395cca9dd32d863 Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/32596 Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier Reviewed-by: Patrick Rudolph --- .../intel/fsp1_1/include/fsp/romstage.h | 2 - src/drivers/intel/fsp1_1/romstage.c | 4 - src/mainboard/google/eve/spd/spd.c | 1 - src/mainboard/intel/kblrvp/spd/spd_util.c | 2 - src/soc/intel/braswell/include/soc/pei_data.h | 50 ----------- .../intel/braswell/include/soc/pei_wrapper.h | 26 ------ src/soc/intel/braswell/include/soc/romstage.h | 2 - src/soc/intel/skylake/Makefile.inc | 2 - .../skylake/include/fsp11/soc/romstage.h | 2 - src/soc/intel/skylake/include/soc/pei_data.h | 89 ------------------- .../intel/skylake/include/soc/pei_wrapper.h | 27 ------ src/soc/intel/skylake/pei_data.c | 39 -------- src/soc/intel/skylake/romstage/romstage.c | 4 - 13 files changed, 250 deletions(-) delete mode 100644 src/soc/intel/braswell/include/soc/pei_data.h delete mode 100644 src/soc/intel/braswell/include/soc/pei_wrapper.h delete mode 100644 src/soc/intel/skylake/include/soc/pei_data.h delete mode 100644 src/soc/intel/skylake/include/soc/pei_wrapper.h delete mode 100644 src/soc/intel/skylake/pei_data.c diff --git a/src/drivers/intel/fsp1_1/include/fsp/romstage.h b/src/drivers/intel/fsp1_1/include/fsp/romstage.h index 4e95dadadf..b01f11059c 100644 --- a/src/drivers/intel/fsp1_1/include/fsp/romstage.h +++ b/src/drivers/intel/fsp1_1/include/fsp/romstage.h @@ -25,13 +25,11 @@ #include #include #include -#include #include /* chip_power_state */ struct romstage_params { uint32_t fsp_version; struct chipset_power_state *power_state; - struct pei_data *pei_data; void *chipset_context; /* Fast boot and S3 resume MRC data */ diff --git a/src/drivers/intel/fsp1_1/romstage.c b/src/drivers/intel/fsp1_1/romstage.c index 87fd1a4c01..433e16cf13 100644 --- a/src/drivers/intel/fsp1_1/romstage.c +++ b/src/drivers/intel/fsp1_1/romstage.c @@ -41,9 +41,7 @@ asmlinkage void *romstage_main(FSP_INFO_HEADER *fih) { void *top_of_stack; - struct pei_data pei_data; struct romstage_params params = { - .pei_data = &pei_data, .chipset_context = fih, }; @@ -55,8 +53,6 @@ asmlinkage void *romstage_main(FSP_INFO_HEADER *fih) if (CONFIG(SUPPORT_CPU_UCODE_IN_CBFS)) intel_update_microcode_from_cbfs(); - memset(&pei_data, 0, sizeof(pei_data)); - /* Display parameters */ if (!CONFIG(NO_MMCONF_SUPPORT)) printk(BIOS_SPEW, "CONFIG_MMCONF_BASE_ADDRESS: 0x%08x\n", diff --git a/src/mainboard/google/eve/spd/spd.c b/src/mainboard/google/eve/spd/spd.c index 2f365a7b5c..077bed4bf1 100644 --- a/src/mainboard/google/eve/spd/spd.c +++ b/src/mainboard/google/eve/spd/spd.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/src/mainboard/intel/kblrvp/spd/spd_util.c b/src/mainboard/intel/kblrvp/spd/spd_util.c index 10043843a2..f22dcaa3b7 100644 --- a/src/mainboard/intel/kblrvp/spd/spd_util.c +++ b/src/mainboard/intel/kblrvp/spd/spd_util.c @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include "../board_id.h" #include "spd.h" diff --git a/src/soc/intel/braswell/include/soc/pei_data.h b/src/soc/intel/braswell/include/soc/pei_data.h deleted file mode 100644 index df18dc087a..0000000000 --- a/src/soc/intel/braswell/include/soc/pei_data.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * UEFI PEI wrapper - * - * Copyright (C) 2014 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Google Inc. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _PEI_DATA_H_ -#define _PEI_DATA_H_ - -#include - -#define PEI_VERSION 22 - -#define ABI_X86 __attribute__((regparm(0))) - -typedef void ABI_X86(*tx_byte_func)(unsigned char byte); - -struct pei_data { - /* Chip settings */ - void *spd_data_ch0; - void *spd_data_ch1; - uint8_t spd_ch0_config; - uint8_t spd_ch1_config; -}; - -typedef struct pei_data PEI_DATA; - -#endif /* _PEI_DATA_H_ */ diff --git a/src/soc/intel/braswell/include/soc/pei_wrapper.h b/src/soc/intel/braswell/include/soc/pei_wrapper.h deleted file mode 100644 index 3222328bef..0000000000 --- a/src/soc/intel/braswell/include/soc/pei_wrapper.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2014 Google Inc. - * - * 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; version 2 of the License. - * - * 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. - */ - -#ifndef _SOC_PEI_WRAPPER_H_ -#define _SOC_PEI_WRAPPER_H_ - -#include - -typedef int ABI_X86(*pei_wrapper_entry_t)(struct pei_data *pei_data); - -void broadwell_fill_pei_data(struct pei_data *pei_data); -void mainboard_fill_pei_data(struct pei_data *pei_data); - -#endif diff --git a/src/soc/intel/braswell/include/soc/romstage.h b/src/soc/intel/braswell/include/soc/romstage.h index 2512430f75..633233e6c6 100644 --- a/src/soc/intel/braswell/include/soc/romstage.h +++ b/src/soc/intel/braswell/include/soc/romstage.h @@ -20,14 +20,12 @@ #include #include #include -#include #include void gfx_init(void); void tco_disable(void); void punit_init(void); int early_spi_read_wpsr(u8 *sr); -void mainboard_fill_spd_data(struct pei_data *pei_data); void set_max_freq(void); /* romstage_common.c functions */ diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc index ee2c928464..e9f555f13c 100644 --- a/src/soc/intel/skylake/Makefile.inc +++ b/src/soc/intel/skylake/Makefile.inc @@ -35,7 +35,6 @@ romstage-y += gspi.c romstage-y += i2c.c romstage-y += memmap.c romstage-y += me.c -romstage-y += pei_data.c romstage-y += pmc.c romstage-y += pmutil.c romstage-$(CONFIG_PLATFORM_USES_FSP2_0) += reset.c @@ -58,7 +57,6 @@ ramstage-y += lpc.c ramstage-y += me.c ramstage-y += memmap.c ramstage-y += p2sb.c -ramstage-y += pei_data.c ramstage-y += pmc.c ramstage-y += pmutil.c ramstage-$(CONFIG_PLATFORM_USES_FSP2_0) += reset.c diff --git a/src/soc/intel/skylake/include/fsp11/soc/romstage.h b/src/soc/intel/skylake/include/fsp11/soc/romstage.h index 36825f7aea..386931043d 100644 --- a/src/soc/intel/skylake/include/fsp11/soc/romstage.h +++ b/src/soc/intel/skylake/include/fsp11/soc/romstage.h @@ -24,6 +24,4 @@ void intel_early_me_status(void); void enable_smbus(void); int smbus_read_byte(unsigned int device, unsigned int address); -void mainboard_fill_spd_data(struct pei_data *pei_data); - #endif /* _SOC_ROMSTAGE_H_ */ diff --git a/src/soc/intel/skylake/include/soc/pei_data.h b/src/soc/intel/skylake/include/soc/pei_data.h deleted file mode 100644 index 5ea2190b8e..0000000000 --- a/src/soc/intel/skylake/include/soc/pei_data.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * UEFI PEI wrapper - * - * Copyright (C) 2014 Google Inc. - * Copyright (C) 2015 Intel Corporation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Google Inc. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _PEI_DATA_H_ -#define _PEI_DATA_H_ - -#include - -#define PEI_VERSION 22 - -#define ABI_X86 __attribute__((regparm(0))) - -typedef void ABI_X86(*tx_byte_func)(unsigned char byte); - -struct pei_data { - uint32_t pei_version; - - int ec_present; - - /* Console output function */ - 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][12]; - - /* - * LPDDR3 Map from CPU DQS pins to SDRAM DQS pins - * [CHANNEL][MAX_BYTES] - */ - uint8_t dqs_map[2][8]; - uint16_t RcompResistor[3]; - uint16_t RcompTarget[5]; - - int mem_cfg_id; -} __packed; - -typedef struct pei_data PEI_DATA; - -#endif /* _PEI_DATA_H_ */ diff --git a/src/soc/intel/skylake/include/soc/pei_wrapper.h b/src/soc/intel/skylake/include/soc/pei_wrapper.h deleted file mode 100644 index d53fe8b769..0000000000 --- a/src/soc/intel/skylake/include/soc/pei_wrapper.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2014 Google Inc. - * Copyright (C) 2015 Intel Corporation. - * - * 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; version 2 of the License. - * - * 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. - */ - -#ifndef _SOC_PEI_WRAPPER_H_ -#define _SOC_PEI_WRAPPER_H_ - -#include - -typedef int ABI_X86(*pei_wrapper_entry_t)(struct pei_data *pei_data); - -void soc_fill_pei_data(struct pei_data *pei_data); -void mainboard_fill_pei_data(struct pei_data *pei_data); - -#endif diff --git a/src/soc/intel/skylake/pei_data.c b/src/soc/intel/skylake/pei_data.c deleted file mode 100644 index 7d314a106f..0000000000 --- a/src/soc/intel/skylake/pei_data.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2014 Google Inc. - * Copyright (C) 2015 Intel Corporation. - * - * 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; version 2 of the License. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include "chip.h" - -static void ABI_X86 send_to_console(unsigned char b) -{ - console_tx_byte(b); -} - -void soc_fill_pei_data(struct pei_data *pei_data) -{ - /* Set the parameters for MemoryInit */ - pei_data->pei_version = PEI_VERSION; - pei_data->tx_byte = &send_to_console; -} diff --git a/src/soc/intel/skylake/romstage/romstage.c b/src/soc/intel/skylake/romstage/romstage.c index 8ec08c2d0f..12239ae13e 100644 --- a/src/soc/intel/skylake/romstage/romstage.c +++ b/src/soc/intel/skylake/romstage/romstage.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -44,9 +43,6 @@ void soc_pre_ram_init(struct romstage_params *params) /* Program MCHBAR and DMIBAR */ systemagent_early_init(); - /* Prepare to initialize memory */ - soc_fill_pei_data(params->pei_data); - const struct device *const dev = pcidev_path_on_root(PCH_DEVFN_LPC); const struct soc_intel_skylake_config *const config = dev ? dev->chip_info : NULL; From 30bc9f415d9564de90fc0c6c6a92462ce3ce7c06 Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Tue, 23 Apr 2019 20:45:50 +0800 Subject: [PATCH 062/107] google/kukui: Support sound in boot process Configure and enable GPIO for speaker amp max98357a. BUG=b:117254418 TEST=Build pass and verified on kukui p1 board BRANCH=None Change-Id: I97655702dff402245326d2eff71fae0e336df9f5 Signed-off-by: Jiaxin Yu Reviewed-on: https://review.coreboot.org/c/coreboot/+/32459 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/mainboard/google/kukui/chromeos.c | 2 ++ src/mainboard/google/kukui/gpio.h | 1 + src/mainboard/google/kukui/mainboard.c | 13 +++++++++++++ 3 files changed, 16 insertions(+) diff --git a/src/mainboard/google/kukui/chromeos.c b/src/mainboard/google/kukui/chromeos.c index 44e75e29f0..35395014d6 100644 --- a/src/mainboard/google/kukui/chromeos.c +++ b/src/mainboard/google/kukui/chromeos.c @@ -27,6 +27,7 @@ void setup_chromeos_gpios(void) gpio_input_pullup(EC_IRQ); gpio_input_pullup(CR50_IRQ); gpio_output(GPIO_RESET, 0); + gpio_output(GPIO_EN_SPK_AMP, 0); } void fill_lb_gpios(struct lb_gpios *gpios) @@ -38,6 +39,7 @@ void fill_lb_gpios(struct lb_gpios *gpios) {EC_IN_RW.id, ACTIVE_HIGH, -1, "EC in RW"}, {EC_IRQ.id, ACTIVE_LOW, -1, "EC interrupt"}, {CR50_IRQ.id, ACTIVE_HIGH, -1, "TPM interrupt"}, + {GPIO_EN_SPK_AMP.id, ACTIVE_HIGH, -1, "speaker enable"}, }; lb_add_gpios(gpios, chromeos_gpios, ARRAY_SIZE(chromeos_gpios)); } diff --git a/src/mainboard/google/kukui/gpio.h b/src/mainboard/google/kukui/gpio.h index 92d238ece2..977acc3739 100644 --- a/src/mainboard/google/kukui/gpio.h +++ b/src/mainboard/google/kukui/gpio.h @@ -23,6 +23,7 @@ #define EC_IN_RW GPIO(PERIPHERAL_EN14) #define CR50_IRQ GPIO(PERIPHERAL_EN3) #define GPIO_RESET GPIO(PERIPHERAL_EN8) +#define GPIO_EN_SPK_AMP GPIO(PERIPHERAL_EN12) void setup_chromeos_gpios(void); diff --git a/src/mainboard/google/kukui/mainboard.c b/src/mainboard/google/kukui/mainboard.c index e1d8f5fb8d..40b8a49c61 100644 --- a/src/mainboard/google/kukui/mainboard.c +++ b/src/mainboard/google/kukui/mainboard.c @@ -16,6 +16,7 @@ #include #include #include +#include #include static void configure_emmc(void) @@ -37,10 +38,22 @@ static void configure_usb(void) setup_usb_host(); } +static void configure_audio(void) +{ + /* Audio PWR*/ + mtcmos_audio_power_on(); + + /* SoC I2S */ + gpio_set_mode(GPIO(CAM_RST0), PAD_CAM_RST0_FUNC_I2S2_LRCK); + gpio_set_mode(GPIO(CAM_PDN1), PAD_CAM_PDN1_FUNC_I2S2_BCK); + gpio_set_mode(GPIO(CAM_PDN0), PAD_CAM_PDN0_FUNC_I2S2_MCK); + gpio_set_mode(GPIO(EINT3), PAD_EINT3_FUNC_I2S3_DO); +} static void mainboard_init(struct device *dev) { configure_emmc(); configure_usb(); + configure_audio(); } static void mainboard_enable(struct device *dev) From 551a75923ec7e7bacaf6da79b38eda5c3b3821ad Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Wed, 1 May 2019 16:56:36 +0200 Subject: [PATCH 063/107] sb/{ICH7,NM10,PCH}: Use common watchdog_off function Change-Id: I704780b6ae7238560dcb72fc027addc1089e0674 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32533 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber Reviewed-by: David Guckian --- src/southbridge/intel/bd82x6x/Kconfig | 1 + src/southbridge/intel/bd82x6x/Makefile.inc | 1 - src/southbridge/intel/common/Kconfig | 4 ++ src/southbridge/intel/common/Makefile.inc | 2 + src/southbridge/intel/common/tco.h | 27 +++++++++ .../intel/{bd82x6x => common}/watchdog.c | 29 +++++----- src/southbridge/intel/fsp_rangeley/Kconfig | 1 + .../intel/fsp_rangeley/Makefile.inc | 1 - src/southbridge/intel/fsp_rangeley/watchdog.c | 53 ------------------ src/southbridge/intel/i82801gx/Kconfig | 1 + src/southbridge/intel/i82801gx/Makefile.inc | 2 - src/southbridge/intel/i82801gx/watchdog.c | 50 ----------------- src/southbridge/intel/i82801ix/Kconfig | 1 + src/southbridge/intel/i82801ix/Makefile.inc | 2 - src/southbridge/intel/i82801jx/Kconfig | 1 + src/southbridge/intel/i82801jx/Makefile.inc | 2 - src/southbridge/intel/ibexpeak/Kconfig | 1 + src/southbridge/intel/ibexpeak/Makefile.inc | 1 - src/southbridge/intel/lynxpoint/Kconfig | 1 + src/southbridge/intel/lynxpoint/Makefile.inc | 1 - src/southbridge/intel/lynxpoint/watchdog.c | 56 ------------------- 21 files changed, 56 insertions(+), 182 deletions(-) create mode 100644 src/southbridge/intel/common/tco.h rename src/southbridge/intel/{bd82x6x => common}/watchdog.c (67%) delete mode 100644 src/southbridge/intel/fsp_rangeley/watchdog.c delete mode 100644 src/southbridge/intel/i82801gx/watchdog.c delete mode 100644 src/southbridge/intel/lynxpoint/watchdog.c diff --git a/src/southbridge/intel/bd82x6x/Kconfig b/src/southbridge/intel/bd82x6x/Kconfig index dae3c32c86..fc3e9fcadb 100644 --- a/src/southbridge/intel/bd82x6x/Kconfig +++ b/src/southbridge/intel/bd82x6x/Kconfig @@ -44,6 +44,7 @@ config SOUTH_BRIDGE_OPTIONS # dummy select HAVE_INTEL_CHIPSET_LOCKDOWN select SOUTHBRIDGE_INTEL_COMMON_SMM select SOUTHBRIDGE_INTEL_COMMON_ACPI_MADT + select SOUTHBRIDGE_INTEL_COMMON_WATCHDOG config EHCI_BAR hex diff --git a/src/southbridge/intel/bd82x6x/Makefile.inc b/src/southbridge/intel/bd82x6x/Makefile.inc index a950e5ce5d..023f5d32c2 100644 --- a/src/southbridge/intel/bd82x6x/Makefile.inc +++ b/src/southbridge/intel/bd82x6x/Makefile.inc @@ -31,7 +31,6 @@ ramstage-y += ../common/pciehp.c ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/hda_verb.c ramstage-y += me_status.c -ramstage-y += watchdog.c ramstage-$(CONFIG_ELOG) += elog.c diff --git a/src/southbridge/intel/common/Kconfig b/src/southbridge/intel/common/Kconfig index 0bda06e10a..c3bd90dca8 100644 --- a/src/southbridge/intel/common/Kconfig +++ b/src/southbridge/intel/common/Kconfig @@ -65,6 +65,10 @@ config INTEL_CHIPSET_LOCKDOWN and S3 resume (always done by coreboot). Select this to let coreboot to do this on normal boot path. +config SOUTHBRIDGE_INTEL_COMMON_WATCHDOG + bool + depends on SOUTHBRIDGE_INTEL_COMMON + if SOUTHBRIDGE_INTEL_COMMON_FINALIZE choice diff --git a/src/southbridge/intel/common/Makefile.inc b/src/southbridge/intel/common/Makefile.inc index 1085f6c66a..4cf6e6f57e 100644 --- a/src/southbridge/intel/common/Makefile.inc +++ b/src/southbridge/intel/common/Makefile.inc @@ -27,6 +27,8 @@ ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_PMCLIB) += pmclib.c +ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_WATCHDOG) += watchdog.c + ifeq ($(CONFIG_SOUTHBRIDGE_INTEL_COMMON),y) verstage-y += pmbase.c diff --git a/src/southbridge/intel/common/tco.h b/src/southbridge/intel/common/tco.h new file mode 100644 index 0000000000..9d6f15326e --- /dev/null +++ b/src/southbridge/intel/common/tco.h @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2019 Elyes Haouas + * + * 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; version 2 of the License. + * + * 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. + */ + +#ifndef SOUTHBRIDGE_INTEL_COMMON_TCO_H +#define SOUTHBRIDGE_INTEL_COMMON_TCO_H + +#define PMBASE_TCO_OFFSET 0x60 +#define TCO1_STS 0x04 +#define TCO1_TIMEOUT (1 << 3) +#define TCO2_STS 0x06 +#define SECOND_TO_STS (1 << 1) +#define TCO1_CNT 0x08 +#define TCO_TMR_HLT (1 << 11) + +#endif /* SOUTHBRIDGE_INTEL_COMMON_TCO_H */ diff --git a/src/southbridge/intel/bd82x6x/watchdog.c b/src/southbridge/intel/common/watchdog.c similarity index 67% rename from src/southbridge/intel/bd82x6x/watchdog.c rename to src/southbridge/intel/common/watchdog.c index 6373a39e47..778a7a9f7f 100644 --- a/src/southbridge/intel/bd82x6x/watchdog.c +++ b/src/southbridge/intel/common/watchdog.c @@ -16,17 +16,16 @@ */ #include -#include #include #include #include +#include #include -#include - +#include #include /* - * Disable PCH watchdog timer + * Disable ICH-NM10-PCH watchdog timer */ void watchdog_off(void) { @@ -36,21 +35,25 @@ void watchdog_off(void) /* Get LPC device. */ dev = pcidev_on_root(0x1f, 0); - /* Disable interrupt. */ value = pci_read_config16(dev, PCI_COMMAND); - value |= PCI_COMMAND_INT_DISABLE; + + if (CONFIG(SOUTHBRIDGE_INTEL_FSP_RANGELEY)) { + /* Enable I/O space. */ + value |= PCI_COMMAND_IO; + } else { + /* Disable interrupt. */ + value |= PCI_COMMAND_INT_DISABLE; + } pci_write_config16(dev, PCI_COMMAND, value); /* Disable the watchdog timer. */ - value = read_pmbase16(TCO1_CNT); + value = read_pmbase16(PMBASE_TCO_OFFSET + TCO1_CNT); value |= TCO_TMR_HLT; - write_pmbase16(TCO1_CNT, value); + write_pmbase16(PMBASE_TCO_OFFSET + TCO1_CNT, value); /* Clear TCO timeout status. */ - write_pmbase16(TCO1_STS, TCO1_TIMEOUT); - write_pmbase16(TCO2_STS, SECOND_TO_STS); + write_pmbase16(PMBASE_TCO_OFFSET + TCO1_STS, TCO1_TIMEOUT); + write_pmbase16(PMBASE_TCO_OFFSET + TCO2_STS, SECOND_TO_STS); - /* FIXME: Set RCBA GCS Bit5 "No Reboot" ? */ - - printk(BIOS_DEBUG, "PCH: watchdog disabled\n"); + printk(BIOS_DEBUG, "ICH-NM10-PCH: watchdog disabled\n"); } diff --git a/src/southbridge/intel/fsp_rangeley/Kconfig b/src/southbridge/intel/fsp_rangeley/Kconfig index c15c48d445..4526cb3cf5 100644 --- a/src/southbridge/intel/fsp_rangeley/Kconfig +++ b/src/southbridge/intel/fsp_rangeley/Kconfig @@ -31,6 +31,7 @@ config SOUTH_BRIDGE_OPTIONS # dummy select INTEL_DESCRIPTOR_MODE_CAPABLE select SOUTHBRIDGE_INTEL_COMMON select SOUTHBRIDGE_INTEL_COMMON_SMBUS + select SOUTHBRIDGE_INTEL_COMMON_WATCHDOG config EHCI_BAR hex diff --git a/src/southbridge/intel/fsp_rangeley/Makefile.inc b/src/southbridge/intel/fsp_rangeley/Makefile.inc index ac5888ca38..7fc86012de 100644 --- a/src/southbridge/intel/fsp_rangeley/Makefile.inc +++ b/src/southbridge/intel/fsp_rangeley/Makefile.inc @@ -19,7 +19,6 @@ ifeq ($(CONFIG_SOUTHBRIDGE_INTEL_FSP_RANGELEY),y) ramstage-y += soc.c ramstage-y += lpc.c ramstage-y += sata.c -ramstage-y += watchdog.c ramstage-y += spi.c ramstage-y += smbus.c ramstage-y += acpi.c diff --git a/src/southbridge/intel/fsp_rangeley/watchdog.c b/src/southbridge/intel/fsp_rangeley/watchdog.c deleted file mode 100644 index f18af8927c..0000000000 --- a/src/southbridge/intel/fsp_rangeley/watchdog.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008-2009 coresystems GmbH - * Copyright (C) 2011 Google Inc. - * Copyright (C) 2013 Sage Electronic Engineering, LLC. - * - * 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; version 2 of - * the License. - * - * 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 -#include -#include -#include -#include -#include -#include "soc.h" - -void watchdog_off(void) -{ - struct device *dev; - u32 value, abase; - - /* Turn off the watchdog. */ - dev = pcidev_on_root(0x1f, 0); - - /* Enable I/O space. */ - value = pci_read_config16(dev, 0x04); - value |= 1; - pci_write_config16(dev, 0x04, value); - - /* Get TCO base. */ - abase = (pci_read_config32(dev, ABASE) & ~0xf); - - /* Disable the watchdog timer. */ - value = inw(abase + 0x68); - value |= 1 << 11; - outw(value, abase + 0x68); - - /* Clear TCO timeout status. */ - outw(0x0008, abase + 0x64); - outw(0x0002, abase + 0x66); - - printk(BIOS_DEBUG, "TCO Watchdog disabled\n"); -} diff --git a/src/southbridge/intel/i82801gx/Kconfig b/src/southbridge/intel/i82801gx/Kconfig index a7d65c52bb..2d6e938eba 100644 --- a/src/southbridge/intel/i82801gx/Kconfig +++ b/src/southbridge/intel/i82801gx/Kconfig @@ -30,6 +30,7 @@ config SOUTHBRIDGE_INTEL_I82801GX select SOUTHBRIDGE_INTEL_COMMON_RCBA_PIRQ select INTEL_HAS_TOP_SWAP select SOUTHBRIDGE_INTEL_COMMON_SMM + select SOUTHBRIDGE_INTEL_COMMON_WATCHDOG if SOUTHBRIDGE_INTEL_I82801GX diff --git a/src/southbridge/intel/i82801gx/Makefile.inc b/src/southbridge/intel/i82801gx/Makefile.inc index b72ca235f5..32a4bf5333 100644 --- a/src/southbridge/intel/i82801gx/Makefile.inc +++ b/src/southbridge/intel/i82801gx/Makefile.inc @@ -30,8 +30,6 @@ ramstage-y += usb_ehci.c ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/hda_verb.c -ramstage-y += watchdog.c - smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c romstage-y += early_smbus.c diff --git a/src/southbridge/intel/i82801gx/watchdog.c b/src/southbridge/intel/i82801gx/watchdog.c deleted file mode 100644 index 12284b46c1..0000000000 --- a/src/southbridge/intel/i82801gx/watchdog.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008-2009 coresystems GmbH - * - * 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; version 2 of - * the License. - * - * 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 -#include -#include -#include -#include -#include - -void watchdog_off(void) -{ - struct device *dev; - unsigned long value, base; - - /* Turn off the ICH7 watchdog. */ - dev = pcidev_on_root(0x1f, 0); - - /* Enable I/O space. */ - value = pci_read_config16(dev, 0x04); - value |= (1 << 10); - pci_write_config16(dev, 0x04, value); - - /* Get TCO base. */ - base = (pci_read_config32(dev, 0x40) & 0x0fffe) + 0x60; - - /* Disable the watchdog timer. */ - value = inw(base + 0x08); - value |= 1 << 11; - outw(value, base + 0x08); - - /* Clear TCO timeout status. */ - outw(0x0008, base + 0x04); - outw(0x0002, base + 0x06); - - printk(BIOS_DEBUG, "ICH7 watchdog disabled\n"); -} diff --git a/src/southbridge/intel/i82801ix/Kconfig b/src/southbridge/intel/i82801ix/Kconfig index 44b2cbc0e6..a2697739a8 100644 --- a/src/southbridge/intel/i82801ix/Kconfig +++ b/src/southbridge/intel/i82801ix/Kconfig @@ -29,6 +29,7 @@ config SOUTHBRIDGE_INTEL_I82801IX select SOUTHBRIDGE_INTEL_COMMON_PMCLIB select INTEL_DESCRIPTOR_MODE_CAPABLE select ACPI_INTEL_HARDWARE_SLEEP_VALUES + select SOUTHBRIDGE_INTEL_COMMON_WATCHDOG if SOUTHBRIDGE_INTEL_I82801IX diff --git a/src/southbridge/intel/i82801ix/Makefile.inc b/src/southbridge/intel/i82801ix/Makefile.inc index 3cc7da5ead..caa493211c 100644 --- a/src/southbridge/intel/i82801ix/Makefile.inc +++ b/src/southbridge/intel/i82801ix/Makefile.inc @@ -29,8 +29,6 @@ ramstage-y += ../common/pciehp.c ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/hda_verb.c -ramstage-y += ../i82801gx/watchdog.c - ifneq ($(CONFIG_SMM_TSEG),y) ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c ramstage-$(CONFIG_HAVE_SMI_HANDLER) += ../../../cpu/x86/smm/smmrelocate.S diff --git a/src/southbridge/intel/i82801jx/Kconfig b/src/southbridge/intel/i82801jx/Kconfig index be2d2897ba..b423ecae40 100644 --- a/src/southbridge/intel/i82801jx/Kconfig +++ b/src/southbridge/intel/i82801jx/Kconfig @@ -33,6 +33,7 @@ config SOUTHBRIDGE_INTEL_I82801JX select ACPI_INTEL_HARDWARE_SLEEP_VALUES select HAVE_POWER_STATE_AFTER_FAILURE select HAVE_POWER_STATE_PREVIOUS_AFTER_FAILURE + select SOUTHBRIDGE_INTEL_COMMON_WATCHDOG if SOUTHBRIDGE_INTEL_I82801JX diff --git a/src/southbridge/intel/i82801jx/Makefile.inc b/src/southbridge/intel/i82801jx/Makefile.inc index c333566e0f..6626bb5d33 100644 --- a/src/southbridge/intel/i82801jx/Makefile.inc +++ b/src/southbridge/intel/i82801jx/Makefile.inc @@ -29,8 +29,6 @@ ramstage-y += ../common/pciehp.c ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/hda_verb.c -ramstage-y += ../i82801gx/watchdog.c - smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c romstage-y += early_smbus.c diff --git a/src/southbridge/intel/ibexpeak/Kconfig b/src/southbridge/intel/ibexpeak/Kconfig index bb6e22cb73..4763133b80 100644 --- a/src/southbridge/intel/ibexpeak/Kconfig +++ b/src/southbridge/intel/ibexpeak/Kconfig @@ -40,6 +40,7 @@ config SOUTH_BRIDGE_OPTIONS # dummy select HAVE_INTEL_CHIPSET_LOCKDOWN select HAVE_POWER_STATE_AFTER_FAILURE select HAVE_POWER_STATE_PREVIOUS_AFTER_FAILURE + select SOUTHBRIDGE_INTEL_COMMON_WATCHDOG config EHCI_BAR hex diff --git a/src/southbridge/intel/ibexpeak/Makefile.inc b/src/southbridge/intel/ibexpeak/Makefile.inc index 5c890300a4..2fb371841a 100644 --- a/src/southbridge/intel/ibexpeak/Makefile.inc +++ b/src/southbridge/intel/ibexpeak/Makefile.inc @@ -31,7 +31,6 @@ ramstage-y += ../common/pciehp.c ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/hda_verb.c ramstage-y += ../bd82x6x/me_status.c -ramstage-y += ../bd82x6x/watchdog.c ramstage-$(CONFIG_ELOG) += ../bd82x6x/elog.c ramstage-y += madt.c diff --git a/src/southbridge/intel/lynxpoint/Kconfig b/src/southbridge/intel/lynxpoint/Kconfig index 5573ec96ad..67e20be11f 100644 --- a/src/southbridge/intel/lynxpoint/Kconfig +++ b/src/southbridge/intel/lynxpoint/Kconfig @@ -42,6 +42,7 @@ config SOUTH_BRIDGE_OPTIONS # dummy select COMMON_FADT select HAVE_POWER_STATE_AFTER_FAILURE select HAVE_POWER_STATE_PREVIOUS_AFTER_FAILURE + select SOUTHBRIDGE_INTEL_COMMON_WATCHDOG config INTEL_LYNXPOINT_LP bool diff --git a/src/southbridge/intel/lynxpoint/Makefile.inc b/src/southbridge/intel/lynxpoint/Makefile.inc index 04e0bc9909..f0bfa5bcc3 100644 --- a/src/southbridge/intel/lynxpoint/Makefile.inc +++ b/src/southbridge/intel/lynxpoint/Makefile.inc @@ -37,7 +37,6 @@ endif ramstage-y += rcba.c ramstage-y += me_status.c -ramstage-y += watchdog.c ramstage-y += acpi.c ramstage-$(CONFIG_ELOG) += elog.c diff --git a/src/southbridge/intel/lynxpoint/watchdog.c b/src/southbridge/intel/lynxpoint/watchdog.c deleted file mode 100644 index 545d3d50d5..0000000000 --- a/src/southbridge/intel/lynxpoint/watchdog.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008-2009 coresystems GmbH - * Copyright (C) 2011 Google Inc. - * - * 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; version 2 of - * the License. - * - * 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 -#include -#include -#include -#include -#include - - // - // Disable PCH Watchdog timer at SB_RCBA+0x3410 - // - // Mmio32((MmPci32(0, 0, 0x1F, 0, 0xF0) & ~BIT0), 0x3410) |= 0x20; - // -void watchdog_off(void) -{ - struct device *dev; - unsigned long value, base; - - /* Turn off the ICH7 watchdog. */ - dev = pcidev_on_root(0x1f, 0); - - /* Enable I/O space. */ - value = pci_read_config16(dev, 0x04); - value |= (1 << 10); - pci_write_config16(dev, 0x04, value); - - /* Get TCO base. */ - base = (pci_read_config32(dev, 0x40) & 0x0fffe) + 0x60; - - /* Disable the watchdog timer. */ - value = inw(base + 0x08); - value |= 1 << 11; - outw(value, base + 0x08); - - /* Clear TCO timeout status. */ - outw(0x0008, base + 0x04); - outw(0x0002, base + 0x06); - - printk(BIOS_DEBUG, "PCH watchdog disabled\n"); -} From d7d0b04d3a0201bc7b2fed913bb623efe0158f81 Mon Sep 17 00:00:00 2001 From: Maxim Polyakov Date: Mon, 6 May 2019 11:54:21 +0300 Subject: [PATCH 064/107] soc/skl/memmap: calculate mem size even if IGD undefined in devtree The DRAM base memory should be calculated even if IGD isn`t defined in the board device tree Tested on Asrock H110M-DVS Change-Id: I3da51473e6c06da803bd969a4a6dff792c18f962 Signed-off-by: Maxim Polyakov Reviewed-on: https://review.coreboot.org/c/coreboot/+/32614 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/soc/intel/skylake/memmap.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/soc/intel/skylake/memmap.c b/src/soc/intel/skylake/memmap.c index fde916a922..ff7edbc95a 100644 --- a/src/soc/intel/skylake/memmap.c +++ b/src/soc/intel/skylake/memmap.c @@ -170,13 +170,13 @@ static size_t get_prmrr_size(uintptr_t dram_base, } /* Calculate Intel Traditional Memory size based on GSM, DSM, TSEG and DPR. */ -static size_t calculate_traditional_mem_size(uintptr_t dram_base, - const struct device *dev) +static size_t calculate_traditional_mem_size(uintptr_t dram_base) { + const struct device *igd_dev = pcidev_path_on_root(SA_DEVFN_IGD); uintptr_t traditional_mem_base = dram_base; size_t traditional_mem_size; - if (dev->enabled) { + if (igd_dev && igd_dev->enabled) { /* Read BDSM from Host Bridge */ traditional_mem_base -= sa_get_dsm_size(); @@ -200,9 +200,9 @@ static size_t calculate_traditional_mem_size(uintptr_t dram_base, * Calculate Intel Reserved Memory size based on * PRMRR size, Trace Hub config and PTT selection. */ -static size_t calculate_reserved_mem_size(uintptr_t dram_base, - const struct device *dev) +static size_t calculate_reserved_mem_size(uintptr_t dram_base) { + const struct device *dev = pcidev_path_on_root(SA_DEVFN_ROOT); uintptr_t reserve_mem_base = dram_base; size_t reserve_mem_size; const struct soc_intel_skylake_config *config; @@ -259,20 +259,15 @@ static size_t calculate_reserved_mem_size(uintptr_t dram_base, static uintptr_t calculate_dram_base(size_t *reserved_mem_size) { uintptr_t dram_base; - const struct device *dev; - - dev = dev_find_slot(0, PCI_DEVFN(SA_DEV_SLOT_IGD, 0)); - if (!dev) - die("ERROR - IGD device not found!"); /* Read TOLUD from Host Bridge offset */ dram_base = sa_get_tolud_base(); /* Get Intel Traditional Memory Range Size */ - dram_base -= calculate_traditional_mem_size(dram_base, dev); + dram_base -= calculate_traditional_mem_size(dram_base); /* Get Intel Reserved Memory Range Size */ - *reserved_mem_size = calculate_reserved_mem_size(dram_base, dev); + *reserved_mem_size = calculate_reserved_mem_size(dram_base); dram_base -= *reserved_mem_size; From 3ba380797b562bbeb7051abd4641bffcf1cf040c Mon Sep 17 00:00:00 2001 From: Maxim Polyakov Date: Mon, 6 May 2019 12:07:24 +0300 Subject: [PATCH 065/107] soc/intel/skylake: remove PrimaryDisplay check Checking the PrimaryDisplay parameter (added by patch with Change Id Ie3f9362676105e41c69139a094dbb9e8b865689f) isn`t required. The display connected to PEG works even if IGD is primary for output image and at the same time this device is disabled Tested on Asrock H110M-DVS with NVIDIA GTX 1060 GPU Payload: tianocore edk2-stable201811-216-g51be9d0 Change-Id: I5615597881a151bb004676d914fbf40874ac1f68 Signed-off-by: Maxim Polyakov Reviewed-on: https://review.coreboot.org/c/coreboot/+/32615 Reviewed-by: Furquan Shaikh Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- src/soc/intel/skylake/romstage/romstage_fsp20.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/soc/intel/skylake/romstage/romstage_fsp20.c b/src/soc/intel/skylake/romstage/romstage_fsp20.c index c166e3a7c1..2f75479339 100644 --- a/src/soc/intel/skylake/romstage/romstage_fsp20.c +++ b/src/soc/intel/skylake/romstage/romstage_fsp20.c @@ -304,10 +304,6 @@ static void soc_primary_gfx_config_params(FSP_M_CONFIG *m_cfg, */ m_cfg->InternalGfx = 0; m_cfg->IgdDvmt50PreAlloc = 0; - if (config->PrimaryDisplay == Display_iGFX) - m_cfg->PrimaryDisplay = Display_Auto; - else - m_cfg->PrimaryDisplay = config->PrimaryDisplay; } else { m_cfg->InternalGfx = 1; /* @@ -319,8 +315,8 @@ static void soc_primary_gfx_config_params(FSP_M_CONFIG *m_cfg, * a high resolution panel */ m_cfg->IgdDvmt50PreAlloc = 2; - m_cfg->PrimaryDisplay = config->PrimaryDisplay; } + m_cfg->PrimaryDisplay = config->PrimaryDisplay; } void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) From 1a930584482c1cafb7ed02a9c37fcfe7cb61fb3f Mon Sep 17 00:00:00 2001 From: Dan Elkouby Date: Sun, 1 Apr 2018 19:54:57 +0300 Subject: [PATCH 066/107] sb/intel/bd82x6x: Fix flashconsole after lockdown SMM final locks the SPI BAR, which causes flashconsole to hang. Re-init it like SMM does with CONFIG_SPI_FLASH_SMM. Change-Id: Ib802d7ee32f1fb0a68a84b0280480dcaefa9831f Signed-off-by: Dan Elkouby Signed-off-by: Evgeny Zinoviev Reviewed-on: https://review.coreboot.org/c/coreboot/+/25660 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- src/southbridge/intel/bd82x6x/lpc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/southbridge/intel/bd82x6x/lpc.c b/src/southbridge/intel/bd82x6x/lpc.c index e9e49649f2..f7bb7e4303 100644 --- a/src/southbridge/intel/bd82x6x/lpc.c +++ b/src/southbridge/intel/bd82x6x/lpc.c @@ -908,6 +908,12 @@ static void lpc_final(struct device *dev) if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3()) { outb(APM_CNT_FINALIZE, APM_CNT); + if (CONFIG(CONSOLE_SPI_FLASH)) + /* Re-init SPI driver to handle locked BAR. + This prevents flashconsole from hanging. + If other code needs to use SPI during + ramstage, whitelist it here. */ + spi_init(); } } } From ac24d3c3118f0ffbf7f26e0ef867c58dbdcc98e3 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Fri, 12 Apr 2019 14:42:17 +0200 Subject: [PATCH 067/107] sconfig: Add SMBIOS type 9 entries Add the new field 'smbios_slot_desc', which takes 2 to 4 arguments. The field is valid for PCI devices and only compiled if SMBIOS table generation is enabled. smbios_slot_desc arguments: 1. slot type 2. slot lenth 3. slot designation (optional) 4. slot data width (optional) Example: device pci 1c.1 on smbios_slot_desc "21" "3" "MINI-PCI-FULL" "8" end # PCIe Port #2 Integrated Wireless LAN Tested on Lenovo T520. Change-Id: If95aae3c322d3da47637613b9a872ba1f7af9080 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/32307 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: Philipp Deppenwiese --- src/include/device/device.h | 6 + util/sconfig/lex.yy.c_shipped | 247 +++++++++++++++-------------- util/sconfig/main.c | 41 ++++- util/sconfig/sconfig.h | 15 ++ util/sconfig/sconfig.l | 73 ++++----- util/sconfig/sconfig.tab.c_shipped | 163 ++++++++++--------- util/sconfig/sconfig.tab.h_shipped | 27 ++-- util/sconfig/sconfig.y | 14 +- 8 files changed, 344 insertions(+), 242 deletions(-) diff --git a/src/include/device/device.h b/src/include/device/device.h index 39a4d567a2..32cf07282b 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -141,6 +141,12 @@ struct device { #if !DEVTREE_EARLY struct chip_operations *chip_ops; const char *name; +#if CONFIG(GENERATE_SMBIOS_TABLES) + u8 smbios_slot_type; + u8 smbios_slot_data_width; + u8 smbios_slot_length; + const char *smbios_slot_designation; +#endif #endif DEVTREE_CONST void *chip_info; }; diff --git a/util/sconfig/lex.yy.c_shipped b/util/sconfig/lex.yy.c_shipped index b3dff41e58..14ffeff9a2 100644 --- a/util/sconfig/lex.yy.c_shipped +++ b/util/sconfig/lex.yy.c_shipped @@ -168,7 +168,7 @@ extern FILE *yyin, *yyout; do \ { \ /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ + yy_size_t yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ @@ -358,8 +358,8 @@ static void yynoreturn yy_fatal_error (yyconst char* msg ); *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 37 -#define YY_END_OF_BUFFER 38 +#define YY_NUM_RULES 38 +#define YY_END_OF_BUFFER 39 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -367,24 +367,25 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[145] = +static yyconst flex_int16_t yy_accept[160] = { 0, - 0, 0, 38, 36, 1, 3, 36, 36, 36, 31, - 31, 29, 32, 36, 32, 32, 32, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 1, 3, - 36, 0, 36, 36, 0, 2, 31, 32, 36, 36, - 36, 36, 32, 36, 36, 36, 36, 36, 36, 36, - 24, 36, 36, 36, 36, 7, 36, 36, 36, 36, - 36, 36, 35, 35, 36, 0, 30, 36, 36, 16, - 36, 36, 23, 28, 36, 36, 13, 36, 36, 22, - 36, 36, 8, 10, 12, 36, 20, 36, 21, 36, - 0, 33, 4, 36, 36, 36, 36, 36, 36, 36, + 0, 0, 39, 37, 1, 3, 37, 37, 37, 32, + 32, 30, 33, 37, 33, 33, 33, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 1, 3, + 37, 0, 37, 37, 0, 2, 32, 33, 37, 37, + 37, 37, 33, 37, 37, 37, 37, 37, 37, 37, + 24, 37, 37, 37, 37, 7, 37, 37, 37, 37, + 37, 37, 37, 36, 36, 37, 0, 31, 37, 37, + 16, 37, 37, 23, 28, 37, 37, 13, 37, 37, + 22, 37, 37, 8, 10, 12, 37, 37, 20, 37, + 21, 37, 0, 34, 4, 37, 37, 37, 37, 37, - 36, 19, 36, 36, 34, 34, 36, 36, 36, 36, - 36, 36, 36, 14, 36, 36, 36, 5, 17, 36, - 9, 36, 11, 36, 36, 36, 18, 26, 36, 36, - 36, 36, 36, 6, 36, 36, 36, 36, 36, 25, - 36, 15, 27, 0 + 37, 37, 37, 19, 37, 37, 37, 35, 35, 37, + 37, 37, 37, 37, 37, 37, 14, 37, 37, 37, + 37, 5, 17, 37, 9, 37, 11, 37, 37, 37, + 37, 18, 26, 37, 37, 37, 37, 37, 37, 6, + 37, 37, 37, 37, 37, 37, 37, 25, 37, 37, + 15, 37, 27, 37, 37, 37, 37, 29, 0 } ; static yyconst YY_CHAR yy_ec[256] = @@ -427,110 +428,114 @@ static yyconst YY_CHAR yy_meta[39] = 1, 1, 1, 1, 1, 1, 1, 1 } ; -static yyconst flex_uint16_t yy_base[152] = +static yyconst flex_uint16_t yy_base[167] = { 0, - 0, 0, 212, 0, 209, 213, 207, 37, 41, 38, - 172, 0, 44, 194, 54, 78, 60, 186, 181, 45, - 188, 177, 42, 47, 182, 41, 169, 0, 199, 213, - 77, 195, 87, 91, 196, 213, 0, 88, 104, 183, - 172, 161, 93, 168, 163, 173, 164, 171, 171, 165, - 171, 156, 156, 160, 162, 0, 158, 152, 158, 155, - 161, 160, 0, 213, 101, 172, 0, 165, 145, 158, - 148, 155, 0, 0, 150, 150, 0, 148, 138, 0, - 142, 137, 0, 0, 0, 140, 0, 131, 0, 158, - 157, 0, 0, 142, 141, 134, 126, 136, 124, 130, + 0, 0, 227, 0, 224, 228, 222, 37, 41, 38, + 187, 0, 44, 209, 54, 78, 60, 201, 196, 45, + 203, 192, 42, 47, 197, 62, 184, 0, 214, 228, + 77, 210, 88, 69, 211, 228, 0, 87, 104, 198, + 187, 176, 93, 183, 178, 188, 179, 186, 186, 180, + 186, 171, 171, 175, 177, 0, 173, 167, 173, 177, + 169, 175, 174, 0, 228, 101, 186, 0, 179, 159, + 172, 162, 169, 0, 0, 164, 164, 0, 162, 152, + 0, 156, 151, 0, 0, 0, 154, 153, 0, 144, + 0, 171, 170, 0, 0, 155, 154, 147, 139, 149, - 135, 0, 120, 114, 0, 213, 125, 129, 121, 123, - 119, 121, 126, 0, 110, 110, 107, 0, 0, 109, - 0, 93, 104, 98, 84, 84, 0, 0, 89, 77, - 87, 71, 66, 0, 64, 62, 50, 47, 33, 0, - 28, 0, 0, 213, 40, 129, 131, 133, 135, 137, - 139 + 137, 143, 148, 0, 133, 136, 126, 0, 228, 137, + 141, 133, 135, 131, 133, 138, 0, 122, 122, 121, + 118, 0, 0, 133, 0, 117, 134, 128, 132, 113, + 113, 0, 0, 120, 112, 110, 121, 94, 95, 0, + 94, 92, 97, 86, 85, 84, 76, 0, 71, 78, + 0, 67, 0, 61, 55, 32, 29, 0, 228, 40, + 129, 131, 133, 135, 137, 139 } ; -static yyconst flex_int16_t yy_def[152] = +static yyconst flex_int16_t yy_def[167] = { 0, - 144, 1, 144, 145, 144, 144, 145, 146, 147, 145, - 10, 145, 10, 145, 10, 10, 10, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, - 146, 148, 149, 147, 150, 144, 10, 10, 10, 145, - 145, 145, 10, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 144, 149, 151, 39, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 144, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 159, 1, 159, 160, 159, 159, 160, 161, 162, 160, + 10, 160, 10, 160, 10, 10, 10, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 159, 159, + 161, 163, 164, 162, 165, 159, 10, 10, 10, 160, + 160, 160, 10, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 159, 164, 166, 39, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 159, 160, 160, 160, 160, 160, 160, 160, - 145, 145, 145, 145, 145, 144, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 0, 144, 144, 144, 144, 144, 144, - 144 + 160, 160, 160, 160, 160, 160, 160, 160, 159, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 0, 159, + 159, 159, 159, 159, 159, 159 } ; -static yyconst flex_uint16_t yy_nxt[252] = +static yyconst flex_uint16_t yy_nxt[267] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 10, 12, 13, 13, 14, 4, 4, 4, 13, 13, 15, 16, 17, 13, 18, 19, 20, 21, 22, 4, 23, 24, 4, 25, 26, 4, 27, 4, 4, 4, 32, 32, - 28, 33, 35, 36, 37, 37, 37, 143, 38, 38, + 28, 33, 35, 36, 37, 37, 37, 158, 38, 38, 38, 38, 38, 49, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 55, 142, 57, 38, 38, 38, 56, - 60, 141, 50, 51, 58, 61, 52, 41, 32, 32, - 140, 63, 139, 42, 38, 38, 38, 46, 66, 66, - 138, 28, 35, 36, 38, 38, 38, 137, 43, 38, + 38, 38, 38, 55, 157, 57, 38, 38, 38, 56, + 35, 36, 50, 51, 58, 156, 52, 41, 32, 32, + 155, 64, 154, 42, 38, 38, 38, 46, 60, 67, + 67, 61, 28, 38, 38, 38, 62, 153, 43, 38, - 38, 38, 66, 66, 136, 90, 44, 135, 134, 45, - 67, 67, 67, 133, 67, 67, 132, 131, 130, 129, - 67, 67, 67, 67, 67, 67, 128, 127, 71, 31, - 31, 34, 34, 32, 32, 65, 65, 35, 35, 66, - 66, 126, 125, 124, 123, 122, 121, 120, 119, 118, - 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, - 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, - 97, 96, 95, 94, 93, 92, 91, 89, 88, 87, - 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, - 76, 75, 74, 73, 72, 70, 69, 68, 36, 64, + 38, 38, 67, 67, 152, 92, 44, 151, 150, 45, + 68, 68, 68, 149, 68, 68, 148, 147, 146, 145, + 68, 68, 68, 68, 68, 68, 144, 143, 72, 31, + 31, 34, 34, 32, 32, 66, 66, 35, 35, 67, + 67, 142, 141, 140, 139, 138, 137, 136, 135, 134, + 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, + 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, + 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, + 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, + 93, 91, 90, 89, 88, 87, 86, 85, 84, 83, - 29, 62, 59, 54, 53, 48, 47, 40, 39, 30, - 29, 144, 3, 144, 144, 144, 144, 144, 144, 144, - 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, - 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, - 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, - 144 + 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, + 71, 70, 69, 36, 65, 29, 63, 59, 54, 53, + 48, 47, 40, 39, 30, 29, 159, 3, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159 } ; -static yyconst flex_int16_t yy_chk[252] = +static yyconst flex_int16_t yy_chk[267] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, - 145, 8, 9, 9, 10, 10, 10, 141, 10, 10, + 160, 8, 9, 9, 10, 10, 10, 157, 10, 10, 13, 13, 13, 20, 10, 10, 10, 10, 10, 10, - 15, 15, 15, 23, 139, 24, 17, 17, 17, 23, - 26, 138, 20, 20, 24, 26, 20, 15, 31, 31, - 137, 31, 136, 15, 16, 16, 16, 17, 33, 33, - 135, 33, 34, 34, 38, 38, 38, 133, 16, 43, + 15, 15, 15, 23, 156, 24, 17, 17, 17, 23, + 34, 34, 20, 20, 24, 155, 20, 15, 31, 31, + 154, 31, 152, 15, 16, 16, 16, 17, 26, 33, + 33, 26, 33, 38, 38, 38, 26, 150, 16, 43, - 43, 43, 65, 65, 132, 65, 16, 131, 130, 16, - 39, 39, 39, 129, 39, 39, 126, 125, 124, 123, - 39, 39, 39, 39, 39, 39, 122, 120, 43, 146, - 146, 147, 147, 148, 148, 149, 149, 150, 150, 151, - 151, 117, 116, 115, 113, 112, 111, 110, 109, 108, - 107, 104, 103, 101, 100, 99, 98, 97, 96, 95, - 94, 91, 90, 88, 86, 82, 81, 79, 78, 76, - 75, 72, 71, 70, 69, 68, 66, 62, 61, 60, - 59, 58, 57, 55, 54, 53, 52, 51, 50, 49, - 48, 47, 46, 45, 44, 42, 41, 40, 35, 32, + 43, 43, 66, 66, 149, 66, 16, 147, 146, 16, + 39, 39, 39, 145, 39, 39, 144, 143, 142, 141, + 39, 39, 39, 39, 39, 39, 139, 138, 43, 161, + 161, 162, 162, 163, 163, 164, 164, 165, 165, 166, + 166, 137, 136, 135, 134, 131, 130, 129, 128, 127, + 126, 124, 121, 120, 119, 118, 116, 115, 114, 113, + 112, 111, 110, 107, 106, 105, 103, 102, 101, 100, + 99, 98, 97, 96, 93, 92, 90, 88, 87, 83, + 82, 80, 79, 77, 76, 73, 72, 71, 70, 69, + 67, 63, 62, 61, 60, 59, 58, 57, 55, 54, - 29, 27, 25, 22, 21, 19, 18, 14, 11, 7, - 5, 3, 144, 144, 144, 144, 144, 144, 144, 144, - 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, - 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, - 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, - 144 + 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, + 42, 41, 40, 35, 32, 29, 27, 25, 22, 21, + 19, 18, 14, 11, 7, 5, 3, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159 } ; static yy_state_type yy_last_accepting_state; @@ -674,7 +679,7 @@ static int input (void ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - size_t n; \ + int n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -687,7 +692,7 @@ static int input (void ); else \ { \ errno=0; \ - while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ @@ -809,13 +814,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 145 ) + if ( yy_current_state >= 160 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 213 ); + while ( yy_base[yy_current_state] != 228 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -955,11 +960,11 @@ YY_RULE_SETUP YY_BREAK case 29: YY_RULE_SETUP -{return(EQUALS);} +{return(SLOT_DESC);} YY_BREAK case 30: YY_RULE_SETUP -{yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(NUMBER);} +{return(EQUALS);} YY_BREAK case 31: YY_RULE_SETUP @@ -971,12 +976,11 @@ YY_RULE_SETUP YY_BREAK case 33: YY_RULE_SETUP -{yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(PCIINT);} +{yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(NUMBER);} YY_BREAK case 34: -/* rule 34 can match eol */ YY_RULE_SETUP -{yylval.string = malloc(yyleng-1); strncpy(yylval.string, yytext+1, yyleng-2); yylval.string[yyleng-2]='\0'; return(STRING);} +{yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(PCIINT);} YY_BREAK case 35: /* rule 35 can match eol */ @@ -984,10 +988,15 @@ YY_RULE_SETUP {yylval.string = malloc(yyleng-1); strncpy(yylval.string, yytext+1, yyleng-2); yylval.string[yyleng-2]='\0'; return(STRING);} YY_BREAK case 36: +/* rule 36 can match eol */ +YY_RULE_SETUP +{yylval.string = malloc(yyleng-1); strncpy(yylval.string, yytext+1, yyleng-2); yylval.string[yyleng-2]='\0'; return(STRING);} + YY_BREAK +case 37: YY_RULE_SETUP {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(STRING);} YY_BREAK -case 37: +case 38: YY_RULE_SETUP ECHO; YY_BREAK @@ -1135,7 +1144,7 @@ static int yy_get_next_buffer (void) { char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = (yytext_ptr); - int number_to_move, i; + yy_size_t number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) @@ -1164,7 +1173,7 @@ static int yy_get_next_buffer (void) /* Try to read more data. */ /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); + number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); @@ -1200,7 +1209,7 @@ static int yy_get_next_buffer (void) b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + yyrealloc((void *) b->yy_ch_buf,(yy_size_t) (b->yy_buf_size + 2) ); } else /* Can't grow it, we don't own it. */ @@ -1246,10 +1255,10 @@ static int yy_get_next_buffer (void) else ret_val = EOB_ACT_CONTINUE_SCAN; - if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + if ((int) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,(yy_size_t) new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } @@ -1283,7 +1292,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 145 ) + if ( yy_current_state >= 160 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; @@ -1311,11 +1320,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 145 ) + if ( yy_current_state >= 160 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; - yy_is_jam = (yy_current_state == 144); + yy_is_jam = (yy_current_state == 159); return yy_is_jam ? 0 : yy_current_state; } @@ -1510,12 +1519,12 @@ static void yy_load_buffer_state (void) if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - b->yy_buf_size = (yy_size_t)size; + b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + b->yy_ch_buf = (char *) yyalloc((yy_size_t) (b->yy_buf_size + 2) ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); @@ -1718,7 +1727,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = NULL; @@ -1801,7 +1810,7 @@ static void yynoreturn yy_fatal_error (yyconst char* msg ) do \ { \ /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ + yy_size_t yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ diff --git a/util/sconfig/main.c b/util/sconfig/main.c index 5382f470fd..c3aa17f1a0 100644 --- a/util/sconfig/main.c +++ b/util/sconfig/main.c @@ -622,6 +622,22 @@ void add_register(struct chip_instance *chip_instance, char *name, char *val) } } +void add_slot_desc(struct bus *bus, char *type, char *length, char *designation, + char *data_width) +{ + struct device *dev = bus->dev; + + if (dev->bustype != PCI && dev->bustype != DOMAIN) { + printf("ERROR: 'slot_type' only allowed for PCI devices\n"); + exit(1); + } + + dev->smbios_slot_type = type; + dev->smbios_slot_length = length; + dev->smbios_slot_data_width = data_width; + dev->smbios_slot_designation = designation; +} + void add_pci_subsystem_ids(struct bus *bus, int vendor, int device, int inherit) { @@ -831,7 +847,30 @@ static void pass1(FILE *fil, struct device *ptr, struct device *next) fprintf(fil, "\t.chip_info = &%s_info_%d,\n", chip_ins->chip->name_underscore, chip_ins->id); if (next) - fprintf(fil, "\t.next=&%s\n", next->name); + fprintf(fil, "\t.next=&%s,\n", next->name); + if (ptr->smbios_slot_type || ptr->smbios_slot_data_width || + ptr->smbios_slot_designation || ptr->smbios_slot_length) { + fprintf(fil, "#if !DEVTREE_EARLY\n"); + fprintf(fil, "#if CONFIG(GENERATE_SMBIOS_TABLES)\n"); + } + /* SMBIOS types start at 1, if zero it hasn't been set */ + if (ptr->smbios_slot_type) + fprintf(fil, "\t.smbios_slot_type = %s,\n", + ptr->smbios_slot_type); + if (ptr->smbios_slot_data_width) + fprintf(fil, "\t.smbios_slot_data_width = %s,\n", + ptr->smbios_slot_data_width); + if (ptr->smbios_slot_designation) + fprintf(fil, "\t.smbios_slot_designation = \"%s\",\n", + ptr->smbios_slot_designation); + if (ptr->smbios_slot_length) + fprintf(fil, "\t.smbios_slot_length = %s,\n", + ptr->smbios_slot_length); + if (ptr->smbios_slot_type || ptr->smbios_slot_data_width || + ptr->smbios_slot_designation || ptr->smbios_slot_length) { + fprintf(fil, "#endif\n"); + fprintf(fil, "#endif\n"); + } fprintf(fil, "};\n"); emit_resources(fil, ptr); diff --git a/util/sconfig/sconfig.h b/util/sconfig/sconfig.h index 389d697a33..e6363dea83 100644 --- a/util/sconfig/sconfig.h +++ b/util/sconfig/sconfig.h @@ -141,6 +141,18 @@ struct device { struct bus *bus; /* Pointer to last bus under this device. */ struct bus *last_bus; + + /* SMBIOS slot type */ + char *smbios_slot_type; + + /* SMBIOS slot data width */ + char *smbios_slot_data_width; + + /* SMBIOS slot description for reference designation */ + char *smbios_slot_designation; + + /* SMBIOS slot length */ + char *smbios_slot_length; }; extern struct bus *root_parent; @@ -158,6 +170,9 @@ void add_pci_subsystem_ids(struct bus *bus, int vendor, int device, void add_ioapic_info(struct bus *bus, int apicid, const char *_srcpin, int irqpin); +void add_slot_desc(struct bus *bus, char *type, char *length, char *designation, + char *data_width); + void yyrestart(FILE *input_file); /* Add chip data to tail of queue. */ diff --git a/util/sconfig/sconfig.l b/util/sconfig/sconfig.l index b21cca54b1..87de6e2763 100755 --- a/util/sconfig/sconfig.l +++ b/util/sconfig/sconfig.l @@ -21,40 +21,41 @@ int linenum = 0; %} %option nodebug %% -[ \t]+ {} -#.*\n {linenum++;} -\r?\n {linenum++;} -chip {return(CHIP);} -device {return(DEVICE);} -register {return(REGISTER);} -on {yylval.number=1; return(BOOL);} -off {yylval.number=0; return(BOOL);} -hidden {yylval.number=3; return(HIDDEN);} -pci {yylval.number=PCI; return(BUS);} -ioapic {yylval.number=IOAPIC; return(BUS);} -pnp {yylval.number=PNP; return(BUS);} -i2c {yylval.number=I2C; return(BUS);} -lapic {yylval.number=APIC; return(BUS);} -cpu_cluster {yylval.number=CPU_CLUSTER; return(BUS);} -cpu {yylval.number=CPU; return(BUS);} -domain {yylval.number=DOMAIN; return(BUS);} -generic {yylval.number=GENERIC; return(BUS);} -mmio {yylval.number=MMIO; return(BUS);} -spi {yylval.number=SPI; return(BUS);} -usb {yylval.number=USB; return(BUS);} -irq {yylval.number=IRQ; return(RESOURCE);} -drq {yylval.number=DRQ; return(RESOURCE);} -io {yylval.number=IO; return(RESOURCE);} -ioapic_irq {return(IOAPIC_IRQ);} -inherit {return(INHERIT);} -subsystemid {return(SUBSYSTEMID);} -end {return(END);} -= {return(EQUALS);} -0x[0-9a-fA-F.]+ {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(NUMBER);} -[0-9.]+ {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(NUMBER);} -[0-9a-fA-F.]+ {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(NUMBER);} -INT[A-D] {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(PCIINT);} -\"\"[^\"]+\"\" {yylval.string = malloc(yyleng-1); strncpy(yylval.string, yytext+1, yyleng-2); yylval.string[yyleng-2]='\0'; return(STRING);} -\"[^\"]+\" {yylval.string = malloc(yyleng-1); strncpy(yylval.string, yytext+1, yyleng-2); yylval.string[yyleng-2]='\0'; return(STRING);} -[^ \n\t]+ {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(STRING);} +[ \t]+ {} +#.*\n {linenum++;} +\r?\n {linenum++;} +chip {return(CHIP);} +device {return(DEVICE);} +register {return(REGISTER);} +on {yylval.number=1; return(BOOL);} +off {yylval.number=0; return(BOOL);} +hidden {yylval.number=3; return(HIDDEN);} +pci {yylval.number=PCI; return(BUS);} +ioapic {yylval.number=IOAPIC; return(BUS);} +pnp {yylval.number=PNP; return(BUS);} +i2c {yylval.number=I2C; return(BUS);} +lapic {yylval.number=APIC; return(BUS);} +cpu_cluster {yylval.number=CPU_CLUSTER; return(BUS);} +cpu {yylval.number=CPU; return(BUS);} +domain {yylval.number=DOMAIN; return(BUS);} +generic {yylval.number=GENERIC; return(BUS);} +mmio {yylval.number=MMIO; return(BUS);} +spi {yylval.number=SPI; return(BUS);} +usb {yylval.number=USB; return(BUS);} +irq {yylval.number=IRQ; return(RESOURCE);} +drq {yylval.number=DRQ; return(RESOURCE);} +io {yylval.number=IO; return(RESOURCE);} +ioapic_irq {return(IOAPIC_IRQ);} +inherit {return(INHERIT);} +subsystemid {return(SUBSYSTEMID);} +end {return(END);} +smbios_slot_desc {return(SLOT_DESC);} += {return(EQUALS);} +0x[0-9a-fA-F.]+ {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(NUMBER);} +[0-9.]+ {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(NUMBER);} +[0-9a-fA-F.]+ {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(NUMBER);} +INT[A-D] {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(PCIINT);} +\"\"[^\"]+\"\" {yylval.string = malloc(yyleng-1); strncpy(yylval.string, yytext+1, yyleng-2); yylval.string[yyleng-2]='\0'; return(STRING);} +\"[^\"]+\" {yylval.string = malloc(yyleng-1); strncpy(yylval.string, yytext+1, yyleng-2); yylval.string[yyleng-2]='\0'; return(STRING);} +[^ \n\t]+ {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(STRING);} %% diff --git a/util/sconfig/sconfig.tab.c_shipped b/util/sconfig/sconfig.tab.c_shipped index d59a1b6883..8e1e57de54 100644 --- a/util/sconfig/sconfig.tab.c_shipped +++ b/util/sconfig/sconfig.tab.c_shipped @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.0.5. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc. 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 @@ -44,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.4" +#define YYBISON_VERSION "3.0.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -144,17 +144,18 @@ extern int yydebug; DOMAIN = 275, IRQ = 276, DRQ = 277, - IO = 278, - NUMBER = 279, - SUBSYSTEMID = 280, - INHERIT = 281, - IOAPIC_IRQ = 282, - IOAPIC = 283, - PCIINT = 284, - GENERIC = 285, - SPI = 286, - USB = 287, - MMIO = 288 + SLOT_DESC = 278, + IO = 279, + NUMBER = 280, + SUBSYSTEMID = 281, + INHERIT = 282, + IOAPIC_IRQ = 283, + IOAPIC = 284, + PCIINT = 285, + GENERIC = 286, + SPI = 287, + USB = 288, + MMIO = 289 }; #endif @@ -429,21 +430,21 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 40 +#define YYLAST 43 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 34 +#define YYNTOKENS 35 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 14 +#define YYNNTS 15 /* YYNRULES -- Number of rules. */ -#define YYNRULES 24 +#define YYNRULES 28 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 43 +#define YYNSTATES 49 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 288 +#define YYMAXUTOK 289 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -480,7 +481,7 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33 + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 }; #if YYDEBUG @@ -488,8 +489,8 @@ static const yytype_uint8 yytranslate[] = static const yytype_uint8 yyrline[] = { 0, 36, 36, 36, 38, 38, 38, 38, 40, 40, - 40, 40, 40, 40, 42, 42, 51, 51, 59, 59, - 61, 64, 67, 70, 73 + 40, 40, 40, 40, 40, 42, 42, 51, 51, 59, + 59, 61, 64, 67, 70, 73, 76, 79, 82 }; #endif @@ -500,11 +501,12 @@ static const char *const yytname[] = { "$end", "error", "$undefined", "CHIP", "DEVICE", "REGISTER", "BOOL", "HIDDEN", "BUS", "RESOURCE", "END", "EQUALS", "HEX", "STRING", "PCI", - "PNP", "I2C", "APIC", "CPU_CLUSTER", "CPU", "DOMAIN", "IRQ", "DRQ", "IO", - "NUMBER", "SUBSYSTEMID", "INHERIT", "IOAPIC_IRQ", "IOAPIC", "PCIINT", - "GENERIC", "SPI", "USB", "MMIO", "$accept", "devtree", "$@1", - "chipchildren", "devicechildren", "chip", "@2", "device", "@3", "status", - "resource", "registers", "subsystemid", "ioapic_irq", YY_NULLPTR + "PNP", "I2C", "APIC", "CPU_CLUSTER", "CPU", "DOMAIN", "IRQ", "DRQ", + "SLOT_DESC", "IO", "NUMBER", "SUBSYSTEMID", "INHERIT", "IOAPIC_IRQ", + "IOAPIC", "PCIINT", "GENERIC", "SPI", "USB", "MMIO", "$accept", + "devtree", "$@1", "chipchildren", "devicechildren", "chip", "@2", + "device", "@3", "status", "resource", "registers", "subsystemid", + "ioapic_irq", "smbios_slot_desc", YY_NULLPTR }; #endif @@ -516,14 +518,14 @@ static const yytype_uint16 yytoknum[] = 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288 + 285, 286, 287, 288, 289 }; # endif -#define YYPACT_NINF -10 +#define YYPACT_NINF -12 #define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-10))) + (!!((Yystate) == (-12))) #define YYTABLE_NINF -1 @@ -534,11 +536,11 @@ static const yytype_uint16 yytoknum[] = STATE-NUM. */ static const yytype_int8 yypact[] = { - -10, 11, 9, -10, 1, -10, -10, -10, 0, 5, - 3, -10, -10, -10, -10, -9, 6, 2, 7, -10, - -10, -10, -10, -10, -3, -5, -10, -1, 4, -10, - -10, -10, -10, -10, 10, 8, -4, 12, 13, 14, - -10, -10, -10 + -12, 11, 9, -12, 1, -12, -12, -12, 0, 5, + 3, -12, -12, -12, -12, -10, 6, 2, 8, -12, + -12, -12, -12, -12, -3, -1, -12, 13, 4, 7, + -12, -12, -12, -12, -12, -12, 16, 15, 10, -11, + 12, 17, -5, 14, -12, 18, -12, -12, -12 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -546,25 +548,25 @@ static const yytype_int8 yypact[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 2, 0, 0, 1, 0, 3, 14, 7, 0, 0, - 0, 15, 5, 4, 6, 0, 0, 0, 0, 18, - 19, 16, 21, 13, 0, 0, 17, 0, 0, 9, - 8, 10, 11, 12, 0, 0, 0, 0, 22, 0, - 20, 23, 24 + 2, 0, 0, 1, 0, 3, 15, 7, 0, 0, + 0, 16, 5, 4, 6, 0, 0, 0, 0, 19, + 20, 17, 22, 14, 0, 0, 18, 0, 0, 0, + 9, 8, 10, 11, 12, 13, 0, 0, 0, 0, + 0, 28, 23, 0, 21, 27, 24, 25, 26 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -10, -10, -10, -10, -10, -6, -10, 16, -10, -10, - -10, -10, -10, -10 + -12, -12, -12, -12, -12, -6, -12, 19, -12, -12, + -12, -12, -12, -12, -12 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 1, 2, 8, 24, 5, 7, 13, 23, 21, - 31, 14, 32, 33 + 32, 14, 33, 34, 35 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -573,46 +575,46 @@ static const yytype_int8 yydefgoto[] = static const yytype_uint8 yytable[] = { 4, 9, 12, 4, 9, 10, 25, 26, 19, 20, - 11, 3, 4, 15, 6, 17, 16, 18, 29, 34, - 22, 37, 27, 35, 28, 39, 0, 0, 36, 0, - 0, 0, 38, 0, 0, 0, 40, 0, 42, 41, - 30 + 11, 3, 4, 15, 6, 17, 16, 18, 30, 43, + 27, 22, 46, 28, 36, 29, 37, 40, 41, 38, + 45, 48, 39, 0, 0, 42, 0, 44, 0, 47, + 0, 0, 0, 31 }; static const yytype_int8 yycheck[] = { 3, 4, 8, 3, 4, 5, 9, 10, 6, 7, - 10, 0, 3, 8, 13, 24, 13, 11, 24, 24, - 13, 11, 25, 24, 27, 29, -1, -1, 24, -1, - -1, -1, 24, -1, -1, -1, 24, -1, 24, 26, - 24 + 10, 0, 3, 8, 13, 25, 13, 11, 24, 30, + 23, 13, 27, 26, 25, 28, 13, 11, 13, 25, + 13, 13, 25, -1, -1, 25, -1, 25, -1, 25, + -1, -1, -1, 24 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 35, 36, 0, 3, 39, 13, 40, 37, 4, - 5, 10, 39, 41, 45, 8, 13, 24, 11, 6, - 7, 43, 13, 42, 38, 9, 10, 25, 27, 39, - 41, 44, 46, 47, 24, 24, 24, 11, 24, 29, - 24, 26, 24 + 0, 36, 37, 0, 3, 40, 13, 41, 38, 4, + 5, 10, 40, 42, 46, 8, 13, 25, 11, 6, + 7, 44, 13, 43, 39, 9, 10, 23, 26, 28, + 40, 42, 45, 47, 48, 49, 25, 13, 25, 25, + 11, 13, 25, 30, 25, 13, 27, 25, 13 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 34, 36, 35, 37, 37, 37, 37, 38, 38, - 38, 38, 38, 38, 40, 39, 42, 41, 43, 43, - 44, 45, 46, 46, 47 + 0, 35, 37, 36, 38, 38, 38, 38, 39, 39, + 39, 39, 39, 39, 39, 41, 40, 43, 42, 44, + 44, 45, 46, 47, 47, 48, 49, 49, 49 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 2, 2, 2, 2, 0, 2, 2, - 2, 2, 2, 0, 0, 5, 0, 7, 1, 1, - 4, 4, 3, 4, 4 + 2, 2, 2, 2, 0, 0, 5, 0, 7, 1, + 1, 4, 4, 3, 4, 4, 5, 4, 3 }; @@ -973,6 +975,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, case N: \ yyformat = S; \ break + default: /* Avoid compiler warnings. */ YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); @@ -1294,7 +1297,7 @@ yyreduce: break; - case 14: + case 15: { (yyval.chip_instance) = new_chip_instance((yyvsp[0].string)); @@ -1304,7 +1307,7 @@ yyreduce: break; - case 15: + case 16: { cur_chip_instance = chip_dequeue_tail(); @@ -1312,7 +1315,7 @@ yyreduce: break; - case 16: + case 17: { (yyval.dev) = new_device(cur_parent, cur_chip_instance, (yyvsp[-2].number), (yyvsp[-1].string), (yyvsp[0].number)); @@ -1321,7 +1324,7 @@ yyreduce: break; - case 17: + case 18: { cur_parent = (yyvsp[-2].dev)->parent; @@ -1329,36 +1332,54 @@ yyreduce: break; - case 20: + case 21: { add_resource(cur_parent, (yyvsp[-3].number), strtol((yyvsp[-2].string), NULL, 0), strtol((yyvsp[0].string), NULL, 0)); } break; - case 21: + case 22: { add_register(cur_chip_instance, (yyvsp[-2].string), (yyvsp[0].string)); } break; - case 22: + case 23: { add_pci_subsystem_ids(cur_parent, strtol((yyvsp[-1].string), NULL, 16), strtol((yyvsp[0].string), NULL, 16), 0); } break; - case 23: + case 24: { add_pci_subsystem_ids(cur_parent, strtol((yyvsp[-2].string), NULL, 16), strtol((yyvsp[-1].string), NULL, 16), 1); } break; - case 24: + case 25: { add_ioapic_info(cur_parent, strtol((yyvsp[-2].string), NULL, 16), (yyvsp[-1].string), strtol((yyvsp[0].string), NULL, 16)); } break; + case 26: + + { add_slot_desc(cur_parent, (yyvsp[-3].string), (yyvsp[-2].string), (yyvsp[-1].string), (yyvsp[0].string)); } + + break; + + case 27: + + { add_slot_desc(cur_parent, (yyvsp[-2].string), (yyvsp[-1].string), (yyvsp[0].string), NULL); } + + break; + + case 28: + + { add_slot_desc(cur_parent, (yyvsp[-1].string), (yyvsp[0].string), NULL, NULL); } + + break; + default: break; diff --git a/util/sconfig/sconfig.tab.h_shipped b/util/sconfig/sconfig.tab.h_shipped index cabc4743b8..bcbd644b01 100644 --- a/util/sconfig/sconfig.tab.h_shipped +++ b/util/sconfig/sconfig.tab.h_shipped @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.0.5. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc. 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 @@ -65,17 +65,18 @@ extern int yydebug; DOMAIN = 275, IRQ = 276, DRQ = 277, - IO = 278, - NUMBER = 279, - SUBSYSTEMID = 280, - INHERIT = 281, - IOAPIC_IRQ = 282, - IOAPIC = 283, - PCIINT = 284, - GENERIC = 285, - SPI = 286, - USB = 287, - MMIO = 288 + SLOT_DESC = 278, + IO = 279, + NUMBER = 280, + SUBSYSTEMID = 281, + INHERIT = 282, + IOAPIC_IRQ = 283, + IOAPIC = 284, + PCIINT = 285, + GENERIC = 286, + SPI = 287, + USB = 288, + MMIO = 289 }; #endif diff --git a/util/sconfig/sconfig.y b/util/sconfig/sconfig.y index 3a6e9ab8a3..0d894a9e35 100755 --- a/util/sconfig/sconfig.y +++ b/util/sconfig/sconfig.y @@ -31,13 +31,13 @@ static struct chip_instance *cur_chip_instance; int number; } -%token CHIP DEVICE REGISTER BOOL HIDDEN BUS RESOURCE END EQUALS HEX STRING PCI PNP I2C APIC CPU_CLUSTER CPU DOMAIN IRQ DRQ IO NUMBER SUBSYSTEMID INHERIT IOAPIC_IRQ IOAPIC PCIINT GENERIC SPI USB MMIO +%token CHIP DEVICE REGISTER BOOL HIDDEN BUS RESOURCE END EQUALS HEX STRING PCI PNP I2C APIC CPU_CLUSTER CPU DOMAIN IRQ DRQ SLOT_DESC IO NUMBER SUBSYSTEMID INHERIT IOAPIC_IRQ IOAPIC PCIINT GENERIC SPI USB MMIO %% devtree: { cur_parent = root_parent; } chip; chipchildren: chipchildren device | chipchildren chip | chipchildren registers | /* empty */ ; -devicechildren: devicechildren device | devicechildren chip | devicechildren resource | devicechildren subsystemid | devicechildren ioapic_irq | /* empty */ ; +devicechildren: devicechildren device | devicechildren chip | devicechildren resource | devicechildren subsystemid | devicechildren ioapic_irq | devicechildren smbios_slot_desc | /* empty */ ; chip: CHIP STRING /* == path */ { $$ = new_chip_instance($2); @@ -72,4 +72,14 @@ subsystemid: SUBSYSTEMID NUMBER NUMBER INHERIT ioapic_irq: IOAPIC_IRQ NUMBER PCIINT NUMBER { add_ioapic_info(cur_parent, strtol($2, NULL, 16), $3, strtol($4, NULL, 16)); }; + +smbios_slot_desc: SLOT_DESC STRING STRING STRING STRING + { add_slot_desc(cur_parent, $2, $3, $4, $5); }; + +smbios_slot_desc: SLOT_DESC STRING STRING STRING + { add_slot_desc(cur_parent, $2, $3, $4, NULL); }; + +smbios_slot_desc: SLOT_DESC STRING STRING + { add_slot_desc(cur_parent, $2, $3, NULL, NULL); }; + %% From bd7739f3aa64aa5409265397722728ba1ffa78ac Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Wed, 24 Apr 2019 09:35:51 +0200 Subject: [PATCH 068/107] device: ignore NONE devices behind bridge Ignore NONE devices in dev_is_active_bridge that are commonly used to indicate hotplug capable ports. Tested on Lenovo T520: The empty ExpressCard Slot is no longer marked as active bridge. Change-Id: I23347270aaab17647023969091ce4bcdd41dd57a Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/32441 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: Philipp Deppenwiese --- src/device/device_util.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/device/device_util.c b/src/device/device_util.c index 5c4f911b8b..47df3052e2 100644 --- a/src/device/device_util.c +++ b/src/device/device_util.c @@ -628,7 +628,7 @@ void disable_children(struct bus *bus) /* * Returns true if the device is an enabled bridge that has at least - * one enabled device on its secondary bus. + * one enabled device on its secondary bus that is not of type NONE. */ bool dev_is_active_bridge(struct device *dev) { @@ -643,6 +643,9 @@ bool dev_is_active_bridge(struct device *dev) for (link = dev->link_list; link; link = link->next) { for (child = link->children; child; child = child->sibling) { + if (child->path.type == DEVICE_PATH_NONE) + continue; + if (child->enabled) return 1; } From f5b9369720ac0458be13e723468e27ab987b439e Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Fri, 12 Apr 2019 15:59:40 +0200 Subject: [PATCH 069/107] smbios: Walk over PCI devicetree to fill type 9 Use the devicetree values for type 9 slots. Tested on Lenovo T520. Change-Id: I1961d8af2d21f755ff52ad58804ea9b31d2a5b9b Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/32308 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes Reviewed-by: Philipp Deppenwiese --- src/arch/x86/smbios.c | 51 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c index 7c87c693e1..589f4f0e30 100644 --- a/src/arch/x86/smbios.c +++ b/src/arch/x86/smbios.c @@ -999,6 +999,56 @@ static int smbios_write_type127(unsigned long *current, int handle) return len; } +/* Generate Type9 entries from devicetree */ +static int smbios_walk_device_tree_type9(struct device *dev, int *handle, + unsigned long *current) +{ + enum misc_slot_usage usage; + enum slot_data_bus_bandwidth bandwidth; + enum misc_slot_type type; + enum misc_slot_length length; + + if (dev->path.type != DEVICE_PATH_PCI) + return 0; + + if (!dev->smbios_slot_type && !dev->smbios_slot_data_width && + !dev->smbios_slot_designation && !dev->smbios_slot_length) + return 0; + + if (dev_is_active_bridge(dev)) + usage = SlotUsageInUse; + else if (dev->enabled) + usage = SlotUsageAvailable; + else + usage = SlotUsageUnknown; + + if (dev->smbios_slot_data_width) + bandwidth = dev->smbios_slot_data_width; + else + bandwidth = SlotDataBusWidthUnknown; + + if (dev->smbios_slot_type) + type = dev->smbios_slot_type; + else + type = SlotTypeUnknown; + + if (dev->smbios_slot_length) + length = dev->smbios_slot_length; + else + length = SlotLengthUnknown; + + return smbios_write_type9(current, handle, + dev->smbios_slot_designation, + type, + bandwidth, + usage, + length, + 1, + 0, + dev->bus->secondary, + dev->path.pci.devfn); +} + static int smbios_walk_device_tree(struct device *tree, int *handle, unsigned long *current) { @@ -1011,6 +1061,7 @@ static int smbios_walk_device_tree(struct device *tree, int *handle, dev_name(dev)); len += dev->ops->get_smbios_data(dev, handle, current); } + len += smbios_walk_device_tree_type9(dev, handle, current); } return len; } From d694f6e21b4a24c70adb55b65f095bc87a9878cd Mon Sep 17 00:00:00 2001 From: Lijian Zhao Date: Mon, 22 Apr 2019 09:41:14 -0700 Subject: [PATCH 070/107] mb/google/sarien: Add SMBIOS type 9 fields Fill SMBIOS type 9 fields for both sarien and arcada platform. BUG=b:129485789 TEST=Boot up into OS and check with dmidecode -t 9 to we do have entry. Signed-off-by: Lijian Zhao Change-Id: I47a697131b7aeeb64e0c4b4c0556842f1cb1b02e Reviewed-on: https://review.coreboot.org/c/coreboot/+/32389 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes Reviewed-by: Patrick Georgi --- src/mainboard/google/sarien/variants/arcada/devicetree.cb | 8 ++++++-- src/mainboard/google/sarien/variants/sarien/devicetree.cb | 8 ++++++-- src/soc/intel/cannonlake/chip.h | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/mainboard/google/sarien/variants/arcada/devicetree.cb b/src/mainboard/google/sarien/variants/arcada/devicetree.cb index 77bd82a64b..0cc9970488 100644 --- a/src/mainboard/google/sarien/variants/arcada/devicetree.cb +++ b/src/mainboard/google/sarien/variants/arcada/devicetree.cb @@ -349,11 +349,15 @@ chip soc/intel/cannonlake device pci 1c.5 off end # PCI Express Port 6 device pci 1c.6 off end # PCI Express Port 7 device pci 1c.7 off end # PCI Express Port 8 - device pci 1d.0 on end # PCI Express Port 9 + device pci 1d.0 on + smbios_slot_desc "SlotTypeM2Socket1_SD" "SlotLengthOther" "2230" "SlotDataBusWidth1X" + end # PCI Express Port 9 device pci 1d.1 on end # PCI Express Port 10 device pci 1d.2 on end # PCI Express Port 11 device pci 1d.3 off end # PCI Express Port 12 - device pci 1d.4 on end # PCI Express Port 13 (x4) + device pci 1d.4 on + smbios_slot_desc "SlotTypeM2Socket3" "SlotLengthOther" "2280" "SlotDataBusWidth4X" + end # PCI Express Port 13 (x4) device pci 1e.0 off end # UART #0 device pci 1e.1 off end # UART #1 device pci 1e.2 off end # GSPI #0 diff --git a/src/mainboard/google/sarien/variants/sarien/devicetree.cb b/src/mainboard/google/sarien/variants/sarien/devicetree.cb index e9786f14eb..3807047e0f 100644 --- a/src/mainboard/google/sarien/variants/sarien/devicetree.cb +++ b/src/mainboard/google/sarien/variants/sarien/devicetree.cb @@ -378,11 +378,15 @@ chip soc/intel/cannonlake device pci 1c.5 off end # PCI Express Port 6 device pci 1c.6 off end # PCI Express Port 7 device pci 1c.7 on end # PCI Express Port 8 - device pci 1d.0 on end # PCI Express Port 9 + device pci 1d.0 on + smbios_slot_desc "SlotTypeM2Socket1_SD" "SlotLengthOther" "2230" "SlotDataBusWidth1X" + end # PCI Express Port 9 device pci 1d.1 on end # PCI Express Port 10 device pci 1d.2 off end # PCI Express Port 11 device pci 1d.3 off end # PCI Express Port 12 - device pci 1d.4 on end # PCI Express Port 13 (x4) + device pci 1d.4 on + smbios_slot_desc "SlotTypeM2Socket3" "SlotLengthOther" "2280" "SlotDataBusWidth4X" + end # PCI Express Port 13 (x4) device pci 1e.0 off end # UART #0 device pci 1e.1 off end # UART #1 device pci 1e.2 off end # GSPI #0 diff --git a/src/soc/intel/cannonlake/chip.h b/src/soc/intel/cannonlake/chip.h index 40d9f71eed..b17df4b21b 100644 --- a/src/soc/intel/cannonlake/chip.h +++ b/src/soc/intel/cannonlake/chip.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include From 052163236c928de11fa9bf8efbd33c1565fb735d Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Fri, 12 Apr 2019 16:14:27 +0200 Subject: [PATCH 071/107] mb/lenovo: Add SMBIOS type 9 for ExpressCard Mark all known PCIe root ports as ExpressCard slot. Tested on Lenovo T520. Change-Id: I43fb481512a54ee054c6fd0189053028fb3c3ec2 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/32309 Reviewed-by: Philipp Deppenwiese Reviewed-by: Paul Menzel Tested-by: build bot (Jenkins) --- src/mainboard/lenovo/t400/devicetree.cb | 1 + src/mainboard/lenovo/t420/devicetree.cb | 1 + src/mainboard/lenovo/t420s/devicetree.cb | 1 + src/mainboard/lenovo/t430/devicetree.cb | 1 + src/mainboard/lenovo/t430s/devicetree.cb | 1 + src/mainboard/lenovo/t520/variants/t520/devicetree.cb | 4 +++- src/mainboard/lenovo/t520/variants/w520/devicetree.cb | 4 +++- src/mainboard/lenovo/t530/variants/t530/devicetree.cb | 4 +++- src/mainboard/lenovo/t530/variants/w530/devicetree.cb | 1 + src/mainboard/lenovo/x200/devicetree.cb | 1 + src/mainboard/lenovo/x201/devicetree.cb | 4 +++- src/mainboard/lenovo/x220/devicetree.cb | 1 + src/mainboard/lenovo/x230/devicetree.cb | 1 + 13 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/mainboard/lenovo/t400/devicetree.cb b/src/mainboard/lenovo/t400/devicetree.cb index 8e90431d5f..475c45ebbd 100644 --- a/src/mainboard/lenovo/t400/devicetree.cb +++ b/src/mainboard/lenovo/t400/devicetree.cb @@ -109,6 +109,7 @@ chip northbridge/intel/gm45 end # PCIe Port #3 device pci 1c.3 on subsystemid 0x17aa 0x20f3 # Expresscard + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" end # PCIe Port #4 device pci 1c.4 off end # PCIe Port #5 device pci 1c.5 off end # PCIe Port #6 diff --git a/src/mainboard/lenovo/t420/devicetree.cb b/src/mainboard/lenovo/t420/devicetree.cb index 47c14ef909..c4092fe901 100644 --- a/src/mainboard/lenovo/t420/devicetree.cb +++ b/src/mainboard/lenovo/t420/devicetree.cb @@ -94,6 +94,7 @@ chip northbridge/intel/sandybridge device pci 1c.2 off end # PCIe Port #3 device pci 1c.3 on subsystemid 0x17aa 0x21ce + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" end # PCIe Port #4 ExpressCard device pci 1c.4 on subsystemid 0x17aa 0x21ce diff --git a/src/mainboard/lenovo/t420s/devicetree.cb b/src/mainboard/lenovo/t420s/devicetree.cb index 0f09db8fa9..d1e3f75499 100644 --- a/src/mainboard/lenovo/t420s/devicetree.cb +++ b/src/mainboard/lenovo/t420s/devicetree.cb @@ -93,6 +93,7 @@ chip northbridge/intel/sandybridge device pci 1c.2 off end # PCIe Port #3 device pci 1c.3 on subsystemid 0x17aa 0x21d2 + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" end # PCIe Port #4 ExpressCard device pci 1c.4 off end # PCIe Port #5 device pci 1c.5 off end # PCIe Port #6 Intel Gigabit Ethernet PHY (not PCIe) diff --git a/src/mainboard/lenovo/t430/devicetree.cb b/src/mainboard/lenovo/t430/devicetree.cb index 9e731f9fbd..2731b69ec0 100644 --- a/src/mainboard/lenovo/t430/devicetree.cb +++ b/src/mainboard/lenovo/t430/devicetree.cb @@ -88,6 +88,7 @@ chip northbridge/intel/sandybridge end device pci 1c.2 on # PCIe Port #3 subsystemid 0x17aa 0x21f3 + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" end device pci 1c.3 off # PCIe Port #4 end diff --git a/src/mainboard/lenovo/t430s/devicetree.cb b/src/mainboard/lenovo/t430s/devicetree.cb index 2ecf05ee43..21d54acf11 100644 --- a/src/mainboard/lenovo/t430s/devicetree.cb +++ b/src/mainboard/lenovo/t430s/devicetree.cb @@ -99,6 +99,7 @@ chip northbridge/intel/sandybridge end # PCIe Port #2 Integrated Wireless LAN device pci 1c.2 on subsystemid 0x17aa 0x21fb + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" end # PCIe Port #3 ExpressCard device pci 1c.3 off end # PCIe Port #4 device pci 1c.4 off end # PCIe Port #5 diff --git a/src/mainboard/lenovo/t520/variants/t520/devicetree.cb b/src/mainboard/lenovo/t520/variants/t520/devicetree.cb index cf8e7ce1d2..5f1bc60863 100644 --- a/src/mainboard/lenovo/t520/variants/t520/devicetree.cb +++ b/src/mainboard/lenovo/t520/variants/t520/devicetree.cb @@ -80,7 +80,9 @@ chip northbridge/intel/sandybridge device pci 1c.0 off end # PCIe Port #1 device pci 1c.1 on end # PCIe Port #2 Integrated Wireless LAN device pci 1c.2 off end # PCIe Port #3 - device pci 1c.3 on end # PCIe Port #4 Express Card + device pci 1c.3 on + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" + end # PCIe Port #4 Express Card device pci 1c.4 on end # PCIe Port #5 MMC/SDXC + IEEE1394 device pci 1c.5 off end # PCIe Port #6 Intel Ethernet PHY device pci 1c.6 off end # PCIe Port #7 USB 3.0 only W520 diff --git a/src/mainboard/lenovo/t520/variants/w520/devicetree.cb b/src/mainboard/lenovo/t520/variants/w520/devicetree.cb index 1770ad9722..ceca46ea84 100644 --- a/src/mainboard/lenovo/t520/variants/w520/devicetree.cb +++ b/src/mainboard/lenovo/t520/variants/w520/devicetree.cb @@ -80,7 +80,9 @@ chip northbridge/intel/sandybridge device pci 1c.0 off end # PCIe Port #1 device pci 1c.1 on end # PCIe Port #2 Integrated Wireless LAN device pci 1c.2 off end # PCIe Port #3 - device pci 1c.3 on end # PCIe Port #4 Express Card + device pci 1c.3 on + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" + end # PCIe Port #4 Express Card device pci 1c.4 on end # PCIe Port #5 MMC/SDXC + IEEE1394 device pci 1c.5 off end # PCIe Port #6 Intel Ethernet PHY device pci 1c.6 on end # PCIe Port #7 USB 3.0 only W520 diff --git a/src/mainboard/lenovo/t530/variants/t530/devicetree.cb b/src/mainboard/lenovo/t530/variants/t530/devicetree.cb index 1a1e7075f2..335543a8f7 100644 --- a/src/mainboard/lenovo/t530/variants/t530/devicetree.cb +++ b/src/mainboard/lenovo/t530/variants/t530/devicetree.cb @@ -83,7 +83,9 @@ chip northbridge/intel/sandybridge device pci 1b.0 on end # High Definition Audio device pci 1c.0 on end # PCIe Port #1 device pci 1c.1 on end # PCIe Port #2 - device pci 1c.2 on end # PCIe Port #3 (expresscard) + device pci 1c.2 on + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" + end # PCIe Port #3 (expresscard) device pci 1c.3 off end # PCIe Port #4 device pci 1c.4 off end # PCIe Port #5 device pci 1c.5 off end # PCIe Port #6 diff --git a/src/mainboard/lenovo/t530/variants/w530/devicetree.cb b/src/mainboard/lenovo/t530/variants/w530/devicetree.cb index 253096c316..0a80fa1d8c 100644 --- a/src/mainboard/lenovo/t530/variants/w530/devicetree.cb +++ b/src/mainboard/lenovo/t530/variants/w530/devicetree.cb @@ -98,6 +98,7 @@ chip northbridge/intel/sandybridge end device pci 1c.2 on # PCIe Port #3 subsystemid 0x17aa 0x21f6 + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" end device pci 1c.3 off # PCIe Port #4 end diff --git a/src/mainboard/lenovo/x200/devicetree.cb b/src/mainboard/lenovo/x200/devicetree.cb index d800e4fdfe..2ed4308cfa 100644 --- a/src/mainboard/lenovo/x200/devicetree.cb +++ b/src/mainboard/lenovo/x200/devicetree.cb @@ -113,6 +113,7 @@ chip northbridge/intel/gm45 end # PCIe Port #3 device pci 1c.3 on subsystemid 0x17aa 0x20f3 # Expresscard + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" end # PCIe Port #4 device pci 1c.4 off end # PCIe Port #5 device pci 1c.5 off end # PCIe Port #6 diff --git a/src/mainboard/lenovo/x201/devicetree.cb b/src/mainboard/lenovo/x201/devicetree.cb index fa33aeb431..6ece08bee6 100644 --- a/src/mainboard/lenovo/x201/devicetree.cb +++ b/src/mainboard/lenovo/x201/devicetree.cb @@ -92,7 +92,9 @@ chip northbridge/intel/nehalem device pci 1c.0 on end # PCIe Port #1 device pci 1c.1 on end # PCIe Port #2 (wwan) - device pci 1c.3 on end # PCIe Port #4 (Expresscard) + device pci 1c.3 on + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" + end # PCIe Port #4 (Expresscard) device pci 1c.4 on end # PCIe Port #5 (wlan) device pci 1d.0 on # USB2 EHCI diff --git a/src/mainboard/lenovo/x220/devicetree.cb b/src/mainboard/lenovo/x220/devicetree.cb index 0ec66f59b8..360de04943 100644 --- a/src/mainboard/lenovo/x220/devicetree.cb +++ b/src/mainboard/lenovo/x220/devicetree.cb @@ -98,6 +98,7 @@ chip northbridge/intel/sandybridge end # PCIe Port #3 device pci 1c.3 on subsystemid 0x17aa 0x21db + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" end # PCIe Port #4 device pci 1c.4 on subsystemid 0x17aa 0x21db diff --git a/src/mainboard/lenovo/x230/devicetree.cb b/src/mainboard/lenovo/x230/devicetree.cb index 68e2f8ea2c..4687e9ccc3 100644 --- a/src/mainboard/lenovo/x230/devicetree.cb +++ b/src/mainboard/lenovo/x230/devicetree.cb @@ -110,6 +110,7 @@ chip northbridge/intel/sandybridge end # PCIe Port #2 device pci 1c.2 on subsystemid 0x17aa 0x21fa + smbios_slot_desc "7" "3" "ExpressCard Slot" "8" end # PCIe Port #3 (expresscard) device pci 1c.3 off end # PCIe Port #4 device pci 1c.4 off end # PCIe Port #5 From 1d3b3c3c0955a652a1b602c5fd86dc6c5890e967 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sat, 4 May 2019 08:12:42 +0200 Subject: [PATCH 072/107] {src,util}: Remove duplicated includes Change-Id: Id09cec6b2aae58b131b208e96fec539d068ff68a Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32566 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- src/northbridge/intel/sandybridge/raminit_common.c | 2 +- util/cbmem/cbmem.c | 1 - util/ectool/ectool.c | 1 - util/romcc/romcc.c | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/northbridge/intel/sandybridge/raminit_common.c b/src/northbridge/intel/sandybridge/raminit_common.c index cbbd2317ed..5347c5c493 100644 --- a/src/northbridge/intel/sandybridge/raminit_common.c +++ b/src/northbridge/intel/sandybridge/raminit_common.c @@ -23,7 +23,7 @@ #include #include #include -#include + #include "raminit_native.h" #include "raminit_common.h" #include "sandybridge.h" diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index ae1d2127fb..52fdc9b81f 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/util/ectool/ectool.c b/util/ectool/ectool.c index bc3d46cd52..2af45c30f2 100644 --- a/util/ectool/ectool.c +++ b/util/ectool/ectool.c @@ -22,7 +22,6 @@ #include #endif #include -#include #if defined __NetBSD__ || defined __OpenBSD__ diff --git a/util/romcc/romcc.c b/util/romcc/romcc.c index 4cb2aadcc9..43be171213 100644 --- a/util/romcc/romcc.c +++ b/util/romcc/romcc.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include From 2dc00fab7c46369bffdedf3afea2af720e4add80 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Sat, 20 Oct 2018 17:10:04 +0200 Subject: [PATCH 073/107] ec/lenovo/h8: Add function to query sense state * Add function to wait for sense registers to become valid. * Add function to retrieve Fn-Key state. Tested on Lenovo T500: * It takes about 700msec for the registers to become valid. Tested on Lenovo T520: * It takes less than 150msec for the registers to become valid. Change-Id: Ie27e2881a256c4efb3def11f05070c446db6e5fc Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/29204 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Deppenwiese Reviewed-by: Nico Huber --- src/ec/lenovo/h8/Makefile.inc | 7 +++++ src/ec/lenovo/h8/h8.h | 5 ++++ src/ec/lenovo/h8/sense.c | 54 +++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 src/ec/lenovo/h8/sense.c diff --git a/src/ec/lenovo/h8/Makefile.inc b/src/ec/lenovo/h8/Makefile.inc index ebf6d7d7a4..bccdd91b7d 100644 --- a/src/ec/lenovo/h8/Makefile.inc +++ b/src/ec/lenovo/h8/Makefile.inc @@ -1,5 +1,12 @@ ifeq ($(CONFIG_EC_LENOVO_H8),y) +ramstage-y += sense.c +verstage-y += sense.c +romstage-y += sense.c +bootblock-y += sense.c +postcar-y += sense.c +smm-y += sense.c + ifneq ($(filter y,$(CONFIG_H8_BEEP_ON_DEATH) $(CONFIG_H8_FLASH_LEDS_ON_DEATH)),) romstage-y += panic.c ramstage-y += panic.c diff --git a/src/ec/lenovo/h8/h8.h b/src/ec/lenovo/h8/h8.h index a46ba1f5e0..14948c55ce 100644 --- a/src/ec/lenovo/h8/h8.h +++ b/src/ec/lenovo/h8/h8.h @@ -38,6 +38,9 @@ void h8_usb_always_on(void); void h8_mainboard_init_dock (void); +int h8_get_fn_key(void); +int h8_get_sense_ready(void); + void h8_bluetooth_enable(int on); bool h8_bluetooth_nv_enable(void); bool h8_has_bdc(struct device *dev); @@ -135,8 +138,10 @@ void h8_ssdt_generator(struct device *dev); #define H8_EVENT_FN_PRESS 0x39 #define H8_STATUS0 0x46 +#define H8_STATUS0_FN_KEY_DOWN 0x01 #define H8_STATUS1 0x47 #define H8_STATUS2 0x48 +#define H8_STATUS3 0x49 #define H8_EVENT_BAT0 0x4a #define H8_EVENT_BAT0_STATE 0x4b diff --git a/src/ec/lenovo/h8/sense.c b/src/ec/lenovo/h8/sense.c new file mode 100644 index 0000000000..b929d7ede3 --- /dev/null +++ b/src/ec/lenovo/h8/sense.c @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018 Patrick Rudolph + * + * 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; version 2 of the License. + * + * 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 + +#include "h8.h" + +/** + * Return the EC sense status register state. + * + * Observations showed the sense registers are all zero until the EC populates + * them after some time. Likely the EC sets all bits to it's valid state at + * once, but there's no prove as the firmware isn't available. + * + * Wait for any register having at least one bit set. + * Unlikely that all register will be zero after booting has finished. + * + * @return 1 if the EC provides valid data in sense status registers + */ +int h8_get_sense_ready(void) +{ + static const u8 regs[] = { H8_STATUS0, H8_STATUS1, H8_STATUS2, + H8_STATUS3}; + + for (size_t i = 0; i < ARRAY_SIZE(regs); i++) { + if (ec_read(regs[i])) + return 1; + } + + return 0; +} + +/** + * Return the state of Fn key. + * Only valid if h8_get_sense_ready (see above) returns true. + * + * @return 1 if the key is pressed. + */ +int h8_get_fn_key(void) +{ + return ec_read(H8_STATUS0) & H8_STATUS0_FN_KEY_DOWN; +} From 25212117534f0cb29939a7fc6c1271ca0fa083cd Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Sun, 5 May 2019 11:15:25 +0200 Subject: [PATCH 074/107] ec/lenovo/h8: Add VBOOT board support Use Fn-Key as recovery mode switch. Tested using Icb7b263ed86551cc53e1db7babccaca6b3ae2fe6. Change-Id: I2c682431b3f09839db265259205104bd9ef4abfc Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/32607 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Deppenwiese --- src/ec/lenovo/h8/Kconfig | 8 +++++ src/ec/lenovo/h8/Makefile.inc | 6 ++++ src/ec/lenovo/h8/vboot.c | 55 +++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 src/ec/lenovo/h8/vboot.c diff --git a/src/ec/lenovo/h8/Kconfig b/src/ec/lenovo/h8/Kconfig index b109831105..d874975428 100644 --- a/src/ec/lenovo/h8/Kconfig +++ b/src/ec/lenovo/h8/Kconfig @@ -32,6 +32,14 @@ config H8_HAS_BAT_TRESHOLDS_IMPL bool default n +config H8_FN_KEY_AS_VBOOT_RECOVERY_SW + bool "Enable Fn-Key as VBOOT recovery switch" + depends on VBOOT + default n + help + If VBOOT is enabled, press Fn-Key at power on to force a recovery mode + boot instead of regular FW_MAIN_x boot. + endif config H8_DOCK_EARLY_INIT diff --git a/src/ec/lenovo/h8/Makefile.inc b/src/ec/lenovo/h8/Makefile.inc index bccdd91b7d..51c11be625 100644 --- a/src/ec/lenovo/h8/Makefile.inc +++ b/src/ec/lenovo/h8/Makefile.inc @@ -7,6 +7,12 @@ bootblock-y += sense.c postcar-y += sense.c smm-y += sense.c +ramstage-$(CONFIG_VBOOT) += vboot.c +verstage-$(CONFIG_VBOOT) += vboot.c +romstage-$(CONFIG_VBOOT) += vboot.c +bootblock-$(CONFIG_VBOOT) += vboot.c +postcar-$(CONFIG_VBOOT) += vboot.c + ifneq ($(filter y,$(CONFIG_H8_BEEP_ON_DEATH) $(CONFIG_H8_FLASH_LEDS_ON_DEATH)),) romstage-y += panic.c ramstage-y += panic.c diff --git a/src/ec/lenovo/h8/vboot.c b/src/ec/lenovo/h8/vboot.c new file mode 100644 index 0000000000..3b9f74a117 --- /dev/null +++ b/src/ec/lenovo/h8/vboot.c @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 Patrick Rudolph + * + * 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; version 2 of the License. + * + * 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 +#include +#include +#include + +#include "h8.h" + +/** + * HACK: Use Fn-Key as recovery mode switch. + * Wait for sense register ready and read Fn-Key state. + */ +int get_recovery_mode_switch(void) +{ + struct stopwatch sw; + + if (!CONFIG(H8_FN_KEY_AS_VBOOT_RECOVERY_SW)) + return 0; + + /* Tests showed that it takes: + * - 700msec on Lenovo T500 from AC power on + * - less than 150msec on Lenovo T520 from AC power on + */ + stopwatch_init_msecs_expire(&sw, 1000); + while (!stopwatch_expired(&sw) && !h8_get_sense_ready()) + mdelay(1); + + if (!h8_get_sense_ready()) + return 0; + + return h8_get_fn_key(); +} + +/** + * Only used if CONFIG_CHROMEOS is set. + * Always zero as the #WP pin of the flash is tied high. + */ +int get_write_protect_state(void) +{ + return 0; +} From 62bc1cb88ba0103189f6c1c957207c9520986043 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Sat, 4 May 2019 14:19:32 +0200 Subject: [PATCH 075/107] mb/lenovo/*: Add support for VBOOT on 8MiB devices Enable VBOOT support on all devices that have a 8 MiB flash, using a single RW_MAIN_A partition, allowing the use of tianocore payload in both RW_MAIN_A and WP_RO. * Add VBNV section to cmos.layout * Add FMAP for VBOOT and regular boot * Select Kconfigs for VBOOT * Enable VBOOT_SLOTS_RW_A by default Also build test VBOOT on Lenovo T420. Tested on Lenovo T520 using Icb7b263ed86551cc53e1db7babccaca6b3ae2fe6. Change-Id: Icb7b263ed86551cc53e1db7babccaca6b3ae2fe6 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/32585 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Deppenwiese Reviewed-by: Patrick Georgi --- ...novo_t420_static_option_table_no_mem_fuses | 2 ++ src/mainboard/lenovo/t420/Kconfig | 20 +++++++++++++ src/mainboard/lenovo/t420/board.fmd | 16 ++++++++++ src/mainboard/lenovo/t420/cmos.layout | 3 ++ src/mainboard/lenovo/t420/vboot-rwa.fmd | 29 +++++++++++++++++++ src/mainboard/lenovo/t420s/Kconfig | 20 +++++++++++++ src/mainboard/lenovo/t420s/board.fmd | 16 ++++++++++ src/mainboard/lenovo/t420s/cmos.layout | 3 ++ src/mainboard/lenovo/t420s/vboot-rwa.fmd | 29 +++++++++++++++++++ src/mainboard/lenovo/t520/Kconfig | 20 +++++++++++++ src/mainboard/lenovo/t520/board.fmd | 16 ++++++++++ src/mainboard/lenovo/t520/cmos.layout | 3 ++ src/mainboard/lenovo/t520/vboot-rwa.fmd | 29 +++++++++++++++++++ src/mainboard/lenovo/x220/Kconfig | 19 ++++++++++++ src/mainboard/lenovo/x220/board.fmd | 16 ++++++++++ src/mainboard/lenovo/x220/cmos.layout | 3 ++ src/mainboard/lenovo/x220/vboot-rwa.fmd | 29 +++++++++++++++++++ 17 files changed, 273 insertions(+) create mode 100644 src/mainboard/lenovo/t420/board.fmd create mode 100644 src/mainboard/lenovo/t420/vboot-rwa.fmd create mode 100644 src/mainboard/lenovo/t420s/board.fmd create mode 100644 src/mainboard/lenovo/t420s/vboot-rwa.fmd create mode 100644 src/mainboard/lenovo/t520/board.fmd create mode 100644 src/mainboard/lenovo/t520/vboot-rwa.fmd create mode 100644 src/mainboard/lenovo/x220/board.fmd create mode 100644 src/mainboard/lenovo/x220/vboot-rwa.fmd diff --git a/configs/config.lenovo_t420_static_option_table_no_mem_fuses b/configs/config.lenovo_t420_static_option_table_no_mem_fuses index a268d88b78..0a3513cfac 100644 --- a/configs/config.lenovo_t420_static_option_table_no_mem_fuses +++ b/configs/config.lenovo_t420_static_option_table_no_mem_fuses @@ -4,4 +4,6 @@ CONFIG_VENDOR_LENOVO=y CONFIG_BOARD_LENOVO_T420=y CONFIG_NATIVE_RAMINIT_IGNORE_MAX_MEM_FUSES=y CONFIG_NATIVE_RAMINIT_IGNORE_XMP_MAX_DIMMS=y +CONFIG_VBOOT=y +CONFIG_H8_FN_KEY_AS_VBOOT_RECOVERY_SW=y # CONFIG_INTEL_CHIPSET_LOCKDOWN is not set diff --git a/src/mainboard/lenovo/t420/Kconfig b/src/mainboard/lenovo/t420/Kconfig index ce81907ccb..3d3b56ae22 100644 --- a/src/mainboard/lenovo/t420/Kconfig +++ b/src/mainboard/lenovo/t420/Kconfig @@ -28,6 +28,26 @@ config BOARD_SPECIFIC_OPTIONS # Workaround for EC/KBC IRQ1. select SERIRQ_CONTINUOUS_MODE +config VBOOT + select VBOOT_VBNV_CMOS + select GBB_FLAG_DISABLE_LID_SHUTDOWN + select GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC + select GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC + select GBB_FLAG_DISABLE_FWMP + select HAS_RECOVERY_MRC_CACHE + +config VBOOT_SLOTS_RW_A + default y + +config VBOOT_VBNV_OFFSET + hex + default 0x2a + +config FMDFILE + string + default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/vboot-rwa.fmd" if VBOOT + default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/board.fmd" + config MAINBOARD_DIR string default lenovo/t420 diff --git a/src/mainboard/lenovo/t420/board.fmd b/src/mainboard/lenovo/t420/board.fmd new file mode 100644 index 0000000000..04cf827a87 --- /dev/null +++ b/src/mainboard/lenovo/t420/board.fmd @@ -0,0 +1,16 @@ +FLASH@0xff800000 0x800000 { + SI_ALL@0x0 0x500000 { + SI_DESC@0x0 0x1000 + SI_GBE@0x1000 0x2000 + SI_ME@0x3000 0x4ed000 + } + SI_BIOS@0x500000 0x300000 { + RW_MRC_CACHE@0 0x10000 + SMMSTORE(PRESERVE)@0x10000 0x40000 + + WP_RO@0x50000 0x2a0000 { + FMAP@0x0 0x800 + COREBOOT(CBFS)@0x1000 0x29f000 + } + } +} diff --git a/src/mainboard/lenovo/t420/cmos.layout b/src/mainboard/lenovo/t420/cmos.layout index f55c2037d5..a9f5f5ff47 100644 --- a/src/mainboard/lenovo/t420/cmos.layout +++ b/src/mainboard/lenovo/t420/cmos.layout @@ -81,6 +81,9 @@ entries 440 8 h 0 volume +# VBOOT +448 128 r 0 vbnv + # SandyBridge MRC Scrambler Seed values 896 32 r 0 mrc_scrambler_seed 928 32 r 0 mrc_scrambler_seed_s3 diff --git a/src/mainboard/lenovo/t420/vboot-rwa.fmd b/src/mainboard/lenovo/t420/vboot-rwa.fmd new file mode 100644 index 0000000000..8a4cd3b477 --- /dev/null +++ b/src/mainboard/lenovo/t420/vboot-rwa.fmd @@ -0,0 +1,29 @@ +FLASH@0xff800000 0x800000 { + SI_ALL@0x0 0x500000 { + SI_DESC@0x0 0x1000 + SI_GBE@0x1000 0x2000 + SI_ME@0x3000 0x4ed000 + } + SI_BIOS@0x500000 0x300000 { + RW_SECTION_A@0x00000 0x180000 { + VBLOCK_A@0x0 0x10000 + FW_MAIN_A(CBFS)@0x10000 0x16ffc0 + RW_FWID_A@0x17ffc0 0x40 + } + UNIFIED_MRC_CACHE@0x180000 0x20000 { + RECOVERY_MRC_CACHE@0x0 0x10000 + RW_MRC_CACHE@0x10000 0x10000 + } + RW_VPD(PRESERVE)@0x1a0000 0x1000 + SMMSTORE(PRESERVE)@0x1a1000 0x40000 + + WP_RO@0x1e1000 0x11f000 { + FMAP@0x0 0x800 + RO_FRID@0x800 0x40 + RO_PADDING@0x840 0x7c0 + RO_VPD(PRESERVE)@0x1000 0x1000 + GBB@0x2000 0x1e000 + COREBOOT(CBFS)@0x20000 0xff000 + } + } +} diff --git a/src/mainboard/lenovo/t420s/Kconfig b/src/mainboard/lenovo/t420s/Kconfig index c5efb55653..1383d4166c 100644 --- a/src/mainboard/lenovo/t420s/Kconfig +++ b/src/mainboard/lenovo/t420s/Kconfig @@ -27,6 +27,26 @@ config BOARD_SPECIFIC_OPTIONS # Workaround for EC/KBC IRQ1. select SERIRQ_CONTINUOUS_MODE +config VBOOT + select VBOOT_VBNV_CMOS + select GBB_FLAG_DISABLE_LID_SHUTDOWN + select GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC + select GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC + select GBB_FLAG_DISABLE_FWMP + select HAS_RECOVERY_MRC_CACHE + +config VBOOT_SLOTS_RW_A + default y + +config VBOOT_VBNV_OFFSET + hex + default 0x2a + +config FMDFILE + string + default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/vboot-rwa.fmd" if VBOOT + default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/board.fmd" + config MAINBOARD_DIR string default lenovo/t420s diff --git a/src/mainboard/lenovo/t420s/board.fmd b/src/mainboard/lenovo/t420s/board.fmd new file mode 100644 index 0000000000..04cf827a87 --- /dev/null +++ b/src/mainboard/lenovo/t420s/board.fmd @@ -0,0 +1,16 @@ +FLASH@0xff800000 0x800000 { + SI_ALL@0x0 0x500000 { + SI_DESC@0x0 0x1000 + SI_GBE@0x1000 0x2000 + SI_ME@0x3000 0x4ed000 + } + SI_BIOS@0x500000 0x300000 { + RW_MRC_CACHE@0 0x10000 + SMMSTORE(PRESERVE)@0x10000 0x40000 + + WP_RO@0x50000 0x2a0000 { + FMAP@0x0 0x800 + COREBOOT(CBFS)@0x1000 0x29f000 + } + } +} diff --git a/src/mainboard/lenovo/t420s/cmos.layout b/src/mainboard/lenovo/t420s/cmos.layout index 2be55f67c7..172191a59a 100644 --- a/src/mainboard/lenovo/t420s/cmos.layout +++ b/src/mainboard/lenovo/t420s/cmos.layout @@ -81,6 +81,9 @@ entries 440 8 h 0 volume +# VBOOT +448 128 r 0 vbnv + # SandyBridge MRC Scrambler Seed values 896 32 r 0 mrc_scrambler_seed 928 32 r 0 mrc_scrambler_seed_s3 diff --git a/src/mainboard/lenovo/t420s/vboot-rwa.fmd b/src/mainboard/lenovo/t420s/vboot-rwa.fmd new file mode 100644 index 0000000000..8a4cd3b477 --- /dev/null +++ b/src/mainboard/lenovo/t420s/vboot-rwa.fmd @@ -0,0 +1,29 @@ +FLASH@0xff800000 0x800000 { + SI_ALL@0x0 0x500000 { + SI_DESC@0x0 0x1000 + SI_GBE@0x1000 0x2000 + SI_ME@0x3000 0x4ed000 + } + SI_BIOS@0x500000 0x300000 { + RW_SECTION_A@0x00000 0x180000 { + VBLOCK_A@0x0 0x10000 + FW_MAIN_A(CBFS)@0x10000 0x16ffc0 + RW_FWID_A@0x17ffc0 0x40 + } + UNIFIED_MRC_CACHE@0x180000 0x20000 { + RECOVERY_MRC_CACHE@0x0 0x10000 + RW_MRC_CACHE@0x10000 0x10000 + } + RW_VPD(PRESERVE)@0x1a0000 0x1000 + SMMSTORE(PRESERVE)@0x1a1000 0x40000 + + WP_RO@0x1e1000 0x11f000 { + FMAP@0x0 0x800 + RO_FRID@0x800 0x40 + RO_PADDING@0x840 0x7c0 + RO_VPD(PRESERVE)@0x1000 0x1000 + GBB@0x2000 0x1e000 + COREBOOT(CBFS)@0x20000 0xff000 + } + } +} diff --git a/src/mainboard/lenovo/t520/Kconfig b/src/mainboard/lenovo/t520/Kconfig index 06f296bc6d..ba17e8092b 100644 --- a/src/mainboard/lenovo/t520/Kconfig +++ b/src/mainboard/lenovo/t520/Kconfig @@ -27,6 +27,21 @@ config BOARD_LENOVO_BASEBOARD_T520 if BOARD_LENOVO_BASEBOARD_T520 +config VBOOT + select VBOOT_VBNV_CMOS + select GBB_FLAG_DISABLE_LID_SHUTDOWN + select GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC + select GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC + select GBB_FLAG_DISABLE_FWMP + select HAS_RECOVERY_MRC_CACHE + +config VBOOT_SLOTS_RW_A + default y + +config VBOOT_VBNV_OFFSET + hex + default 0x2a + config VARIANT_DIR string default "t520" if BOARD_LENOVO_T520 @@ -40,6 +55,11 @@ config DEVICETREE string default "variants/$(CONFIG_VARIANT_DIR)/devicetree.cb" +config FMDFILE + string + default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/vboot-rwa.fmd" if VBOOT + default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/board.fmd" + config MAINBOARD_PART_NUMBER string default "ThinkPad T520" if BOARD_LENOVO_T520 diff --git a/src/mainboard/lenovo/t520/board.fmd b/src/mainboard/lenovo/t520/board.fmd new file mode 100644 index 0000000000..04cf827a87 --- /dev/null +++ b/src/mainboard/lenovo/t520/board.fmd @@ -0,0 +1,16 @@ +FLASH@0xff800000 0x800000 { + SI_ALL@0x0 0x500000 { + SI_DESC@0x0 0x1000 + SI_GBE@0x1000 0x2000 + SI_ME@0x3000 0x4ed000 + } + SI_BIOS@0x500000 0x300000 { + RW_MRC_CACHE@0 0x10000 + SMMSTORE(PRESERVE)@0x10000 0x40000 + + WP_RO@0x50000 0x2a0000 { + FMAP@0x0 0x800 + COREBOOT(CBFS)@0x1000 0x29f000 + } + } +} diff --git a/src/mainboard/lenovo/t520/cmos.layout b/src/mainboard/lenovo/t520/cmos.layout index 1a7943e5a4..ec6ce858eb 100644 --- a/src/mainboard/lenovo/t520/cmos.layout +++ b/src/mainboard/lenovo/t520/cmos.layout @@ -81,6 +81,9 @@ entries #437 3 r 0 unused 440 8 h 0 volume +# VBOOT +448 128 r 0 vbnv + # SandyBridge MRC Scrambler Seed values 896 32 r 0 mrc_scrambler_seed 928 32 r 0 mrc_scrambler_seed_s3 diff --git a/src/mainboard/lenovo/t520/vboot-rwa.fmd b/src/mainboard/lenovo/t520/vboot-rwa.fmd new file mode 100644 index 0000000000..8a4cd3b477 --- /dev/null +++ b/src/mainboard/lenovo/t520/vboot-rwa.fmd @@ -0,0 +1,29 @@ +FLASH@0xff800000 0x800000 { + SI_ALL@0x0 0x500000 { + SI_DESC@0x0 0x1000 + SI_GBE@0x1000 0x2000 + SI_ME@0x3000 0x4ed000 + } + SI_BIOS@0x500000 0x300000 { + RW_SECTION_A@0x00000 0x180000 { + VBLOCK_A@0x0 0x10000 + FW_MAIN_A(CBFS)@0x10000 0x16ffc0 + RW_FWID_A@0x17ffc0 0x40 + } + UNIFIED_MRC_CACHE@0x180000 0x20000 { + RECOVERY_MRC_CACHE@0x0 0x10000 + RW_MRC_CACHE@0x10000 0x10000 + } + RW_VPD(PRESERVE)@0x1a0000 0x1000 + SMMSTORE(PRESERVE)@0x1a1000 0x40000 + + WP_RO@0x1e1000 0x11f000 { + FMAP@0x0 0x800 + RO_FRID@0x800 0x40 + RO_PADDING@0x840 0x7c0 + RO_VPD(PRESERVE)@0x1000 0x1000 + GBB@0x2000 0x1e000 + COREBOOT(CBFS)@0x20000 0xff000 + } + } +} diff --git a/src/mainboard/lenovo/x220/Kconfig b/src/mainboard/lenovo/x220/Kconfig index 16f42e850e..358cf8ec39 100644 --- a/src/mainboard/lenovo/x220/Kconfig +++ b/src/mainboard/lenovo/x220/Kconfig @@ -26,6 +26,21 @@ config BOARD_SPECIFIC_OPTIONS # Workaround for EC/KBC IRQ1. select SERIRQ_CONTINUOUS_MODE +config VBOOT + select VBOOT_VBNV_CMOS + select GBB_FLAG_DISABLE_LID_SHUTDOWN + select GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC + select GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC + select GBB_FLAG_DISABLE_FWMP + select HAS_RECOVERY_MRC_CACHE + +config VBOOT_SLOTS_RW_A + default y + +config VBOOT_VBNV_OFFSET + hex + default 0x2a + config MAINBOARD_DIR string default lenovo/x220 @@ -35,6 +50,10 @@ config VARIANT_DIR default "x220" if BOARD_LENOVO_X220 || BOARD_LENOVO_X220I default "x1" if BOARD_LENOVO_X1 +config FMDFILE + string + default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/vboot-rwa.fmd" if VBOOT + default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/board.fmd" config MAINBOARD_PART_NUMBER string diff --git a/src/mainboard/lenovo/x220/board.fmd b/src/mainboard/lenovo/x220/board.fmd new file mode 100644 index 0000000000..04cf827a87 --- /dev/null +++ b/src/mainboard/lenovo/x220/board.fmd @@ -0,0 +1,16 @@ +FLASH@0xff800000 0x800000 { + SI_ALL@0x0 0x500000 { + SI_DESC@0x0 0x1000 + SI_GBE@0x1000 0x2000 + SI_ME@0x3000 0x4ed000 + } + SI_BIOS@0x500000 0x300000 { + RW_MRC_CACHE@0 0x10000 + SMMSTORE(PRESERVE)@0x10000 0x40000 + + WP_RO@0x50000 0x2a0000 { + FMAP@0x0 0x800 + COREBOOT(CBFS)@0x1000 0x29f000 + } + } +} diff --git a/src/mainboard/lenovo/x220/cmos.layout b/src/mainboard/lenovo/x220/cmos.layout index d4a4ed3371..dc98010ea2 100644 --- a/src/mainboard/lenovo/x220/cmos.layout +++ b/src/mainboard/lenovo/x220/cmos.layout @@ -80,6 +80,9 @@ entries #435 549 r 0 unused 440 8 h 0 volume +# VBOOT +448 128 r 0 vbnv + # SandyBridge MRC Scrambler Seed values 896 32 r 0 mrc_scrambler_seed 928 32 r 0 mrc_scrambler_seed_s3 diff --git a/src/mainboard/lenovo/x220/vboot-rwa.fmd b/src/mainboard/lenovo/x220/vboot-rwa.fmd new file mode 100644 index 0000000000..8a4cd3b477 --- /dev/null +++ b/src/mainboard/lenovo/x220/vboot-rwa.fmd @@ -0,0 +1,29 @@ +FLASH@0xff800000 0x800000 { + SI_ALL@0x0 0x500000 { + SI_DESC@0x0 0x1000 + SI_GBE@0x1000 0x2000 + SI_ME@0x3000 0x4ed000 + } + SI_BIOS@0x500000 0x300000 { + RW_SECTION_A@0x00000 0x180000 { + VBLOCK_A@0x0 0x10000 + FW_MAIN_A(CBFS)@0x10000 0x16ffc0 + RW_FWID_A@0x17ffc0 0x40 + } + UNIFIED_MRC_CACHE@0x180000 0x20000 { + RECOVERY_MRC_CACHE@0x0 0x10000 + RW_MRC_CACHE@0x10000 0x10000 + } + RW_VPD(PRESERVE)@0x1a0000 0x1000 + SMMSTORE(PRESERVE)@0x1a1000 0x40000 + + WP_RO@0x1e1000 0x11f000 { + FMAP@0x0 0x800 + RO_FRID@0x800 0x40 + RO_PADDING@0x840 0x7c0 + RO_VPD(PRESERVE)@0x1000 0x1000 + GBB@0x2000 0x1e000 + COREBOOT(CBFS)@0x20000 0xff000 + } + } +} From fe80bf2fd1e4f027d68af1c5bc58a8b1344a806d Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Sun, 5 May 2019 16:38:04 +0200 Subject: [PATCH 076/107] Documentation: Convert vboot to markdown Convert the HTML document to markdown and place it under security section. Change-Id: I212c6d0c977fd6772371ff6676478d48cc215d6e Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/32610 Reviewed-by: Patrick Georgi Tested-by: build bot (Jenkins) --- Documentation/Intel/index.html | 1 - Documentation/Intel/vboot.html | 402 -------------------------- Documentation/security/index.md | 1 + Documentation/security/vboot/index.md | 324 +++++++++++++++++++++ 4 files changed, 325 insertions(+), 403 deletions(-) delete mode 100644 Documentation/Intel/vboot.html create mode 100644 Documentation/security/vboot/index.md diff --git a/Documentation/Intel/index.html b/Documentation/Intel/index.html index b4daa960a9..9d8aad05e9 100644 --- a/Documentation/Intel/index.html +++ b/Documentation/Intel/index.html @@ -29,7 +29,6 @@

  • SoC support
  • Board support
  • -
  • Verified Boot (vboot) support
  • diff --git a/Documentation/Intel/vboot.html b/Documentation/Intel/vboot.html deleted file mode 100644 index ca49ac2e2d..0000000000 --- a/Documentation/Intel/vboot.html +++ /dev/null @@ -1,402 +0,0 @@ - - - - vboot - Verified Boot Support - - - -

    vboot - Verified Boot Support

    - -

    -Google's verified boot support consists of: -

    -
      -
    • A root of trust
    • -
    • Special firmware layout
    • -
    • Firmware verification
    • -
    • Firmware measurements
    • -
    • A firmware update mechanism
    • -
    • Specific build flags
    • -
    • Signing the coreboot image
    • -
    - -Google's vboot verifies the firmware and places measurements -within the TPM. - -
    -

    Root of Trust

    -

    -When using vboot, the root-of-trust is basically the read-only portion of the -SPI flash. The following items factor into the trust equation: -

    -
      -
    • The GCC compiler must reliably translate the code into machine code - without inserting any additional code (virus, backdoor, etc.) -
    • -
    • The CPU must reliably execute the reset sequence and instructions as - documented by the CPU manufacturer. -
    • -
    • The SPI flash must provide only the code programmed into it to the CPU - without providing any alternative reset vector or code sequence. -
    • -
    • The SPI flash must honor the write-protect input and protect the - specified portion of the SPI flash from all erase and write accesses. -
    • -
    - -

    -The firmware is typically protected using the write-protect pin on the SPI -flash part and setting some of the write-protect bits in the status register -during manufacturing. The protected area is platform specific and for x86 -platforms is typically 1/4th of the SPI flash -part size. Because this portion of the SPI flash is hardware write protected, -it is not possible to update this portion of the SPI flash in the field, -without altering the system to eliminate the ground connection to the SPI flash -write-protect pin. Without hardware modifications, this portion of the SPI -flash maintains the manufactured state during the system's lifetime. -

    - -
    -

    Firmware Layout

    -

    -Several sections are added to the firmware layout to support vboot: -

    -
      -
    • Read-only section
    • -
    • Google Binary Blob (GBB) area
    • -
    • Read/write section A
    • -
    • Read/write section B
    • -
    -

    -The following sections describe the various portions of the flash layout. -

    - -

    Read-Only Section

    -

    -The read-only section contains a coreboot file system (CBFS) that contains all -of the boot firmware necessary to perform recovery for the system. This -firmware is typically protected using the write-protect pin on the SPI flash -part and setting some of the write-protect bits in the status register during -manufacturing. The protected area is typically 1/4th of the SPI flash part -size and must cover the entire read-only section which consists of: -

    -
      -
    • Vital Product Data (VPD) area
    • -
    • Firmware ID area
    • -
    • Google Binary Blob (GBB) area
    • -
    • coreboot file system containing read-only recovery firmware
    • -
    - -

    Google Binary Blob (GBB) Area

    -

    -The GBB area is part of the read-only section. This area contains a 4096 or -8192 bit public root RSA key that is used to verify the VBLOCK area to obtain -the firmware signing key. -

    - -

    Recovery Firmware

    -

    -The recovery firmware is contained within a coreboot file system and consists -of: -

    -
      -
    • reset vector
    • -
    • bootblock
    • -
    • verstage
    • -
    • romstage
    • -
    • postcar
    • -
    • ramstage
    • -
    • payload
    • -
    • flash map file
    • -
    • config file
    • -
    • processor specific files: -
        -
      • Microcode
      • -
      • fspm.bin
      • -
      • fsps.bin
      • -
      -
    • -
    - -

    -The recovery firmware is written during manufacturing and typically contains -code to write the storage device (eMMC device or hard disk). The recovery -image is usually contained on a socketed device such as a USB flash drive or -an SD card. Depending upon the payload firmware doing the recovery, it may -be possible for the user to interact with the system to specify the recovery -image path. Part of the recovery is also to write the A and B areas of the -SPI flash device to boot the system. -

    - - -

    Read/Write Section

    - -

    -The read/write sections contain an area which contains the firmware signing -key and signature and an area containing a coreboot file system with a subset -of the firmware. The firmware files in FW_MAIN_A and FW_MAIN_B are: -

    -
      -
    • romstage
    • -
    • postcar
    • -
    • ramstage
    • -
    • payload
    • -
    • config file
    • -
    • processor specific files: -
        -
      • Microcode
      • -
      • fspm.bin
      • -
      • fsps.bin
      • -
      -
    • -
    - -

    -The firmware subset enables most issues to be fixed in the field with firmware -updates. The firmware files handle memory and most of silicon initialization. -These files also produce the tables which get passed to the operating system. -

    - -
    -

    Firmware Updates

    -

    -The read/write sections exist in one of three states: -

    -
      -
    • Invalid
    • -
    • Ready to boot
    • -
    • Successfully booted
    • -
    - - - - - -
    -Where is this state information written? -
    CMOS? -
    RW_NVRAM? -
    RW_FWID_* -
    - -

    -Firmware updates are handled by the operating system by writing any read/write -section that is not in the "successfully booted" state. Upon the next reboot, -vboot determines the section to boot. If it finds one in the "ready to boot" -state then it attempts to boot using that section. If the boot fails then -vboot marks the section as invalid and attempts to fall back to a read/write -section in the "successfully booted" state. If vboot is not able to find a -section in the "successfully booted" state then vboot enters recovery mode. -

    - -

    -Only the operating system is able to transition a section from the "ready to -boot" state to the "successfully booted" state. The transition is typically -done after the operating system has been running for a while indicating -that successful boot was possible and the operating system is stable. -

    - -

    -Note that as long as the SPI write protection is in place then the system is -always recoverable. If the flash update fails then the system will continue -to boot using the previous read/write area. The same is true if coreboot -passes control to the payload or the operating system and then the boot fails. -In the worst case, the SPI flash gets totally corrupted in which case vboot -fails the signature checks and enters recovery mode. There are no times where -the SPI flash is exposed and the reset vector or part of the recovery firmware -gets corrupted. -

    - -
    -

    Build Flags

    -

    -The following Kconfig values need to be selected to enable vboot: -

    -
      -
    • COLLECT_TIMESTAMPS
    • -
    • VBOOT
    • -
    - -

    -The starting stage needs to be specified by selecting either -VBOOT_STARTS_IN_BOOTBLOCK or VBOOT_STARTS_IN_ROMSTAGE. -

    - -

    -If vboot starts in bootblock then vboot may be built as a separate stage by -selecting VBOOT_SEPARATE_VERSTAGE. Additionally, if static RAM is too small -to fit both verstage and romstage then selecting VBOOT_RETURN_FROM_VERSTAGE -enables bootblock to reuse the RAM occupied by verstage for romstage. -

    - -

    -Non-volatile flash is needed for vboot operation. This flash area may be in -CMOS, the EC, or in a read/write area of the SPI flash device. Select one of -the following: -

    -
      -
    • VBOOT_VBNV_CMOS
    • -
    • VBOOT_VBNV_EC
    • -
    • VBOOT_VBNV_FLASH
    • -
    -

    -More non-volatile storage features may be found in src/vboot/Kconfig. -

    - -

    -A TPM is also required for vboot operation. TPMs are available in -drivers/i2c/tpm and drivers/pc80/tpm. -

    - -

    -In addition to adding the coreboot files into the read-only region, enabling -vboot causes the build script to add the read/write files into coreboot file -systems in FW_MAIN_A and FW_MAIN_B. -

    - -
    -

    Signing the coreboot Image

    -

    -The following command script is an example of how to sign the coreboot image file. -This script is used on the Intel Galileo board and creates the GBB area and -inserts it into the coreboot image. It also updates the VBLOCK areas with the -firmware signing key and the signature for the FW_MAIN firmware. More details -are available in 3rdparty/vboot/README. -

    - -
    #!/bin/sh
    -#
    -#  The necessary tools were built and installed using the following commands:
    -#
    -#        pushd 3rdparty/vboot
    -#        make
    -#        sudo make install
    -#        popd
    -#
    -#  The keys were made using the following command
    -#
    -#        3rdparty/vboot/scripts/keygeneration/create_new_keys.sh  \
    -#                --4k --4k-root --output $PWD/keys
    -#
    -#
    -#  The "magic" numbers below are derived from the GBB section in
    -#  src/mainboard/intel/galileo/vboot.fmd.
    -#
    -#  GBB Header Size:     0x80
    -#  GBB Offset:      0x611000, 4KiB block number: 1553 (0x611)
    -#  GBB Length:       0x7f000, 4KiB blocks:        127  (0x7f)
    -#  COREBOOT Offset: 0x690000, 4KiB block number: 1680 (0x690)
    -#  COREBOOT Length: 0x170000, 4KiB blocks:        368 (0x170)
    -#
    -#  0x7f000 (GBB Length) = 0x80 + 0x100 + 0x1000 + 0x7ce80 + 0x1000
    -#
    -#  Create the GBB area blob
    -#  Parameters: hwid_size,rootkey_size,bmpfv_size,recoverykey_size
    -#
    -gbb_utility -c 0x100,0x1000,0x7ce80,0x1000 gbb.blob
    -
    -#
    -#  Copy from the start of the flash to the GBB region into the signed flash
    -#  image.
    -#
    -#  1553 * 4096 = 0x611 * 0x1000 = 0x611000, size of area before GBB
    -#
    -dd  conv=fdatasync  ibs=4096  obs=4096  count=1553  \
    -    if=build/coreboot.rom  of=build/coreboot.signed.rom
    -
    -#
    -#  Append the empty GBB area to the coreboot.rom image.
    -#
    -#  1553 * 4096 = 0x611 * 0x1000 = 0x611000, offset to GBB
    -#
    -dd  conv=fdatasync  obs=4096  obs=4096  seek=1553  if=gbb.blob  \
    -    of=build/coreboot.signed.rom
    -
    -#
    -#  Append the rest of the read-only region into the signed flash image.
    -#
    -#  1680 * 4096 = 0x690 * 0x1000 = 0x690000, offset to COREBOOT area
    -#   368 * 4096 = 0x170 * 0x1000 = 0x170000, length of COREBOOT area
    -#
    -dd  conv=fdatasync  ibs=4096  obs=4096  skip=1680  seek=1680  count=368  \
    -    if=build/coreboot.rom  of=build/coreboot.signed.rom
    -
    -#
    -#  Insert the HWID and public root and recovery RSA keys into the GBB area.
    -#
    -gbb_utility                          \
    -   --set --hwid='Galileo'            \
    -   -r $PWD/keys/recovery_key.vbpubk  \
    -   -k $PWD/keys/root_key.vbpubk      \
    -   build/coreboot.signed.rom
    -
    -#
    -#  Sign the read/write firmware areas with the private signing key and update
    -#  the VBLOCK_A and VBLOCK_B regions.
    -#
    -3rdparty/vboot/scripts/image_signing/sign_firmware.sh  \
    -   build/coreboot.signed.rom                           \
    -   $PWD/keys                                           \
    -   build/coreboot.signed.rom
    -
    - -
    -

    Boot Flow

    -

    -The reset vector exist in the read-only area and points to the bootblock entry -point. The only copy of the bootblock exists in the read-only area of the SPI -flash. Verstage may be part of the bootblock or a separate stage. If separate -then the bootblock loads verstage from the read-only area and transfers control -to it. -

    - -

    -Upon first boot, verstage attempts to verify the read/write section A. It gets -the public root key from the GBB area and uses that to verify the VBLOCK area -in read-write section A. If the VBLOCK area is valid then it extracts the -firmware signing key (1024-8192 bits) and uses that to verify the FW_MAIN_A -area of read/write section A. If the verification is successful then verstage -instructs coreboot to use the coreboot file system in read/write section A for -the contents of the remaining boot firmware (romstage, postcar, ramstage and -the payload). -

    - -

    -If verification fails for the read/write area and the other read/write area is -not valid vboot falls back to the read-only area to boot into system recovery. -

    - -
    -

    Chromebook Special Features

    -

    -Google's Chromebooks have some special features: -

    -
      -
    • Developer mode
    • -
    • Write-protect screw
    • -
    - -

    Developer Mode

    -

    -Developer mode allows the user to use coreboot to boot another operating system. -This may be a another (beta) version of Chrome OS, or another flavor of -GNU/Linux. Use of developer mode does not void the system warranty. Upon -entry into developer mode, all locally saved data on the system is lost. -This prevents someone from entering developer mode to subvert the system -security to access files on the local system or cloud. -

    - -

    Write Protect Screw

    -

    -Chromebooks have a write-protect screw which provides the ground to the -write-protect pin of the SPI flash. Google specifically did this to allow -the manufacturing line and advanced developers to re-write the entire SPI flash -part. Once the screw is removed, any firmware may be placed on the device. -However, accessing this screw requires opening the case and voids the system -warranty! -

    - -
    -

    Modified: 2 May 2017

    - - diff --git a/Documentation/security/index.md b/Documentation/security/index.md index 89db42ecee..9ad54866c2 100644 --- a/Documentation/security/index.md +++ b/Documentation/security/index.md @@ -4,4 +4,5 @@ This section describes documentation about the security architecture of coreboot ## Vendor +- [Verified Boot](vboot/index.md) - [Measured Boot](vboot/measured_boot.md) diff --git a/Documentation/security/vboot/index.md b/Documentation/security/vboot/index.md new file mode 100644 index 0000000000..97420893e5 --- /dev/null +++ b/Documentation/security/vboot/index.md @@ -0,0 +1,324 @@ +# vboot - Verified Boot Support + +Google's verified boot support consists of: + +* A root of trust +* Special firmware layout +* Firmware verification +* Firmware measurements +* A firmware update mechanism +* Specific build flags +* Signing the coreboot image + +Google's vboot verifies the firmware and places measurements within the TPM. + +*** + +## Root of Trust + +When using vboot, the root-of-trust is basically the read-only portion of the +SPI flash. The following items factor into the trust equation: + +* The GCC compiler must reliably translate the code into machine code + without inserting any additional code (virus, backdoor, etc.) +* The CPU must reliably execute the reset sequence and instructions as + documented by the CPU manufacturer. +* The SPI flash must provide only the code programmed into it to the CPU + without providing any alternative reset vector or code sequence. +* The SPI flash must honor the write-protect input and protect the specified + portion of the SPI flash from all erase and write accesses. + +The firmware is typically protected using the write-protect pin on the SPI +flash part and setting some of the write-protect bits in the status register +during manufacturing. The protected area is platform specific and for x86 +platforms is typically 1/4th of the SPI flash part size. +Because this portion of the SPI flash is hardware write protected, it is not +possible to update this portion of the SPI flash in the field, without altering +the system to eliminate the ground connection to the SPI flash write-protect pin. +Without hardware modifications, this portion of the SPI flash maintains the +manufactured state during the system's lifetime. + +*** + +## Firmware Layout + +Several sections are added to the firmware layout to support vboot: + +* Read-only section +* Google Binary Blob (GBB) area +* Read/write section A +* Read/write section B + +The following sections describe the various portions of the flash layout. + +### Read-Only Section + +The read-only section contains a coreboot file system (CBFS) that contains all +of the boot firmware necessary to perform recovery for the system. This firmware +is typically protected using the write-protect pin on the SPI flash part and +setting some of the write-protect bits in the status register during +manufacturing. +The protected area is typically 1/4th of the SPI flash part size and must cover +the entire read-only section which consists of: + +* Vital Product Data (VPD) area +* Firmware ID area +* Google Binary Blob (GBB) area +* coreboot file system containing read-only recovery firmware + +### Google Binary Blob (GBB) Area + +The GBB area is part of the read-only section. This area contains a 4096 or 8192 +bit public root RSA key that is used to verify the *VBLOCK* area to obtain the +firmware signing key. + +### Recovery Firmware + +The recovery firmware is contained within a coreboot file system and consists of: + +* reset vector +* bootblock +* verstage +* romstage +* postcar +* ramstage +* payload +* flash map file +* config file +* processor specific files: + * Microcode + * fspm.bin + * fsps.bin + +The recovery firmware is written during manufacturing and typically contains +code to write the storage device (eMMC device or hard disk). The recovery image +is usually contained on a socketed device such as a USB flash drive or an +SD card. Depending upon the payload firmware doing the recovery, it may be +possible for the user to interact with the system to specify the recovery +image path. Part of the recovery is also to write the A and B areas of the SPI +flash device to boot the system. + +### Read/Write Section + +The read/write sections contain an area which contains the firmware signing +key and signature and an area containing a coreboot file system with a subset +of the firmware. The firmware files in *FW_MAIN_A* and *FW_MAIN_B* are: + +* romstage +* postcar +* ramstage +* payload +* config file +* processor specific files: + * Microcode + * fspm.bin + * fsps.bin + +The firmware subset enables most issues to be fixed in the field with firmware +updates. The firmware files handle memory and most of silicon initialization. +These files also produce the tables which get passed to the operating system. + +*** + +## Firmware Updates + +The read/write sections exist in one of three states: + +* Invalid +* Ready to boot +* Successfully booted + + +Firmware updates are handled by the operating system by writing any read/write +section that is not in the "successfully booted" state. Upon the next reboot, +vboot determines the section to boot. If it finds one in the "ready to boot" +state then it attempts to boot using that section. If the boot fails then +vboot marks the section as invalid and attempts to fall back to a read/write +section in the "successfully booted" state. If vboot is not able to find a +section in the "successfully booted" state then vboot enters recovery mode. + +Only the operating system is able to transition a section from the +"ready to boot" state to the "successfully booted" state. +The transition is typically done after the operating system has been running +for a while indicating that successful boot was possible and the operating +system is stable. + +Note that as long as the SPI write protection is in place then the system +is always recoverable. If the flash update fails then the system will continue +to boot using the previous read/write area. The same is true if coreboot passes +control to the payload or the operating system and then the boot fails. In the +worst case, the SPI flash gets totally corrupted in which case vboot fails the +signature checks and enters recovery mode. There are no times where the SPI +flash is exposed and the reset vector or part of the recovery firmware gets +corrupted. + +*** + +## Build Flags + +The following *Kconfig* values need to be selected to enable vboot: + +* COLLECT_TIMESTAMPS +* VBOOT + +The starting stage needs to be specified by selecting either +VBOOT_STARTS_IN_BOOTBLOCK or VBOOT_STARTS_IN_ROMSTAGE. + +If vboot starts in bootblock then vboot may be built as a separate stage by +selecting `VBOOT_SEPARATE_VERSTAGE`. Additionally, if static RAM is too small +to fit both verstage and romstage then selecting `VBOOT_RETURN_FROM_VERSTAGE` +enables bootblock to reuse the RAM occupied by verstage for romstage. + +Non-volatile flash is needed for vboot operation. This flash area may be in +CMOS, the EC, or in a read/write area of the SPI flash device. +Select one of the following: + +* `VBOOT_VBNV_CMOS` +* `VBOOT_VBNV_EC` +* `VBOOT_VBNV_FLASH` + +More non-volatile storage features may be found in `security/vboot/Kconfig`. + +A TPM is also required for vboot operation. +TPMs are available in `drivers/i2c/tpm` and `drivers/pc80/tpm`. + +In addition to adding the coreboot files into the read-only region, +enabling vboot causes the build script to add the read/write files into +coreboot file systems in *FW_MAIN_A* and *FW_MAIN_B*. + +*** + +## Signing the coreboot Image + +The following command script is an example of how to sign the coreboot image +file. This script is used on the Intel Galileo board and creates the *GBB* area +and inserts it into the coreboot image. It also updates the *VBLOCK* areas with +the firmware signing key and the signature for the *FW_MAIN* firmware. +More details are available in `3rdparty/vboot/README`. + +```bash +#!/bin/sh +# +# The necessary tools were built and installed using the following commands: +# +# pushd 3rdparty/vboot +# make +# sudo make install +# popd +# +# The keys were made using the following command +# +# 3rdparty/vboot/scripts/keygeneration/create_new_keys.sh \ +# --4k --4k-root --output $PWD/keys +# +# +# The "magic" numbers below are derived from the GBB section in +# src/mainboard/intel/galileo/vboot.fmd. +# +# GBB Header Size: 0x80 +# GBB Offset: 0x611000, 4KiB block number: 1553 (0x611) +# GBB Length: 0x7f000, 4KiB blocks: 127 (0x7f) +# COREBOOT Offset: 0x690000, 4KiB block number: 1680 (0x690) +# COREBOOT Length: 0x170000, 4KiB blocks: 368 (0x170) +# +# 0x7f000 (GBB Length) = 0x80 + 0x100 + 0x1000 + 0x7ce80 + 0x1000 +# +# Create the GBB area blob +# Parameters: hwid_size,rootkey_size,bmpfv_size,recoverykey_size +# +gbb_utility -c 0x100,0x1000,0x7ce80,0x1000 gbb.blob + +# +# Copy from the start of the flash to the GBB region into the signed flash +# image. +# +# 1553 * 4096 = 0x611 * 0x1000 = 0x611000, size of area before GBB +# +dd conv=fdatasync ibs=4096 obs=4096 count=1553 \ +if=build/coreboot.rom of=build/coreboot.signed.rom + +# +# Append the empty GBB area to the coreboot.rom image. +# +# 1553 * 4096 = 0x611 * 0x1000 = 0x611000, offset to GBB +# +dd conv=fdatasync obs=4096 obs=4096 seek=1553 if=gbb.blob \ +of=build/coreboot.signed.rom + +# +# Append the rest of the read-only region into the signed flash image. +# +# 1680 * 4096 = 0x690 * 0x1000 = 0x690000, offset to COREBOOT area +# 368 * 4096 = 0x170 * 0x1000 = 0x170000, length of COREBOOT area +# +dd conv=fdatasync ibs=4096 obs=4096 skip=1680 seek=1680 count=368 \ +if=build/coreboot.rom of=build/coreboot.signed.rom + +# +# Insert the HWID and public root and recovery RSA keys into the GBB area. +# +gbb_utility \ +--set --hwid='Galileo' \ +-r $PWD/keys/recovery_key.vbpubk \ +-k $PWD/keys/root_key.vbpubk \ +build/coreboot.signed.rom + +# +# Sign the read/write firmware areas with the private signing key and update +# the VBLOCK_A and VBLOCK_B regions. +# +3rdparty/vboot/scripts/image_signing/sign_firmware.sh \ +build/coreboot.signed.rom \ +$PWD/keys \ + build/coreboot.signed.rom +``` + +*** + +## Boot Flow + +The reset vector exist in the read-only area and points to the bootblock +entry point. The only copy of the bootblock exists in the read-only area +of the SPI flash. Verstage may be part of the bootblock or a separate stage. +If separate then the bootblock loads verstage from the read-only area and +transfers control to it. + +Upon first boot, verstage attempts to verify the read/write section A. +It gets the public root key from the GBB area and uses that to verify the +*VBLOCK* area in read-write section A. If the *VBLOCK* area is valid then it +extracts the firmware signing key (1024-8192 bits) and uses that to verify +the *FW_MAIN_A* area of read/write section A. If the verification is successful +then verstage instructs coreboot to use the coreboot file system in read/write +section A for the contents of the remaining boot firmware (romstage, postcar, +ramstage and the payload). + +If verification fails for the read/write area and the other read/write area is +not valid vboot falls back to the read-only area to boot into system recovery. + +*** + +## Chromebook Special Features + +Google's Chromebooks have some special features: + +* Developer mode +* Write-protect screw + +### Developer Mode + +Developer mode allows the user to use coreboot to boot another operating system. +This may be a another (beta) version of Chrome OS, or another flavor of +GNU/Linux. Use of developer mode does not void the system warranty. Upon entry +into developer mode, all locally saved data on the system is lost. +This prevents someone from entering developer mode to subvert the system +security to access files on the local system or cloud. + +### Write Protect Screw + +Chromebooks have a write-protect screw which provides the ground to the +write-protect pin of the SPI flash. +Google specifically did this to allow the manufacturing line and advanced +developers to re-write the entire SPI flash part. Once the screw is removed, +any firmware may be placed on the device. +However, accessing this screw requires opening the case and voids the +system warranty! From 5de4771360c0e57bd76bc81850298091e0b9bde7 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Wed, 1 May 2019 16:14:42 -0600 Subject: [PATCH 077/107] soc/amd/stoneyridge: Rename AcpiMmio blocks A subsequent patch will move the AcpiMmio support into amd/common. Take this opportunity to rename the blocks in the 0xfed8xxxx region with more consistency. Change-Id: I9a69a6ecfc10f78b4860df05a77a061d2fc8be7d Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/32642 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/mainboard/google/kahlee/mainboard.c | 4 +- .../include/baseboard/acpi/audio.asl | 2 +- src/soc/amd/stoneyridge/acpi/gpio_lib.asl | 2 +- src/soc/amd/stoneyridge/acpi/sb_fch.asl | 2 +- src/soc/amd/stoneyridge/gpio.c | 14 +++-- src/soc/amd/stoneyridge/include/soc/iomap.h | 34 +++++++---- src/soc/amd/stoneyridge/sb_util.c | 56 +++++++++---------- src/soc/amd/stoneyridge/sm.c | 4 +- src/soc/amd/stoneyridge/smbus_spd.c | 4 +- src/soc/amd/stoneyridge/southbridge.c | 16 +++--- 10 files changed, 75 insertions(+), 63 deletions(-) diff --git a/src/mainboard/google/kahlee/mainboard.c b/src/mainboard/google/kahlee/mainboard.c index 1bf6c07045..ad979a567f 100644 --- a/src/mainboard/google/kahlee/mainboard.c +++ b/src/mainboard/google/kahlee/mainboard.c @@ -145,13 +145,13 @@ static void mainboard_init(void *chip_info) pm_write8(PM_PCIB_CFG, pm_read8(PM_PCIB_CFG) | PM_GENINT_DISABLE); /* Set low-power mode for BayHub eMMC bridge's PCIe clock. */ - clrsetbits_le32((uint32_t *)(MISC_MMIO_BASE + GPP_CLK_CNTRL), + clrsetbits_le32((uint32_t *)(ACPIMMIO_MISC_BASE + GPP_CLK_CNTRL), GPP_CLK2_REQ_MAP_MASK, GPP_CLK2_REQ_MAP_CLK_REQ2 << GPP_CLK2_REQ_MAP_SHIFT); /* Same for the WiFi */ - clrsetbits_le32((uint32_t *)(MISC_MMIO_BASE + GPP_CLK_CNTRL), + clrsetbits_le32((uint32_t *)(ACPIMMIO_MISC_BASE + GPP_CLK_CNTRL), GPP_CLK0_REQ_MAP_MASK, GPP_CLK0_REQ_MAP_CLK_REQ0 << GPP_CLK0_REQ_MAP_SHIFT); diff --git a/src/mainboard/google/kahlee/variants/baseboard/include/baseboard/acpi/audio.asl b/src/mainboard/google/kahlee/variants/baseboard/include/baseboard/acpi/audio.asl index 6bb41ae6b3..87890daf36 100644 --- a/src/mainboard/google/kahlee/variants/baseboard/include/baseboard/acpi/audio.asl +++ b/src/mainboard/google/kahlee/variants/baseboard/include/baseboard/acpi/audio.asl @@ -35,7 +35,7 @@ Device (I2S) Name (RBUF, ResourceTemplate () { // Memory resource is for MISC FCH register set. // It is needed for enabling the clock. - Memory32Fixed(ReadWrite, MISC_MMIO_BASE, 0x100) + Memory32Fixed(ReadWrite, ACPIMMIO_MISC_BASE, 0x100) }) Return (RBUF) diff --git a/src/soc/amd/stoneyridge/acpi/gpio_lib.asl b/src/soc/amd/stoneyridge/acpi/gpio_lib.asl index d18b147d71..8185c35ac5 100644 --- a/src/soc/amd/stoneyridge/acpi/gpio_lib.asl +++ b/src/soc/amd/stoneyridge/acpi/gpio_lib.asl @@ -19,7 +19,7 @@ Method (GPAD, 0x1) { /* Arg0 - GPIO pin number */ - Return (Add(Multiply(Arg0, 4), GPIO_CONTROL_MMIO_BASE)) + Return (Add(Multiply(Arg0, 4), ACPIMMIO_GPIO0_BASE)) } /* Read pin control dword */ diff --git a/src/soc/amd/stoneyridge/acpi/sb_fch.asl b/src/soc/amd/stoneyridge/acpi/sb_fch.asl index 114401e24b..4c1196dad6 100644 --- a/src/soc/amd/stoneyridge/acpi/sb_fch.asl +++ b/src/soc/amd/stoneyridge/acpi/sb_fch.asl @@ -144,7 +144,7 @@ Device (MISC) Name (_HID, "AMD0040") Name (_UID, 0x3) Name (_CRS, ResourceTemplate() { - Memory32Fixed(ReadWrite, MISC_MMIO_BASE, 0x100) + Memory32Fixed(ReadWrite, ACPIMMIO_MISC_BASE, 0x100) }) Method (_STA, 0x0, NotSerialized) { diff --git a/src/soc/amd/stoneyridge/gpio.c b/src/soc/amd/stoneyridge/gpio.c index da1ba0bb74..b747538eaa 100644 --- a/src/soc/amd/stoneyridge/gpio.c +++ b/src/soc/amd/stoneyridge/gpio.c @@ -228,7 +228,7 @@ void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size) uint8_t mux, index, gpio; int gevent_num; - inter_master = (uint32_t *)(uintptr_t)(GPIO_CONTROL_MMIO_BASE + inter_master = (uint32_t *)(uintptr_t)(ACPIMMIO_GPIO0_BASE + GPIO_MASTER_SWITCH); direction = 0; edge_level = 0; @@ -252,7 +252,7 @@ void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size) control = gpio_list_ptr[index].control; control_flags = gpio_list_ptr[index].flags; - mux_ptr = (uint8_t *)(uintptr_t)(gpio + GPIO_IOMUX_MMIO_BASE); + mux_ptr = (uint8_t *)(uintptr_t)(gpio + ACPIMMIO_IOMUX_BASE); write8(mux_ptr, mux & AMD_GPIO_MUX_MASK); read8(mux_ptr); /* Flush posted write */ /* special case if pin 2 is assigned to wake */ @@ -316,11 +316,13 @@ void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size) mem_read_write32(inter_master, GPIO_INTERRUPT_EN, GPIO_INTERRUPT_EN); /* Set all SCI trigger direction (high/low) */ - mem_read_write32((uint32_t *)(uintptr_t)(APU_SMI_BASE + SMI_SCI_TRIG), + mem_read_write32((uint32_t *) + (uintptr_t)(ACPIMMIO_SMI_BASE + SMI_SCI_TRIG), direction, mask); /* Set all SCI trigger level (edge/level) */ - mem_read_write32((uint32_t *)(uintptr_t)(APU_SMI_BASE + SMI_SCI_LEVEL), + mem_read_write32((uint32_t *) + (uintptr_t)(ACPIMMIO_SMI_BASE + SMI_SCI_LEVEL), edge_level, mask); } @@ -348,7 +350,7 @@ static void save_i2c_pin_registers(uint8_t gpio, uint32_t *gpio_ptr; uint8_t *mux_ptr; - mux_ptr = (uint8_t *)(uintptr_t)(gpio + GPIO_IOMUX_MMIO_BASE); + mux_ptr = (uint8_t *)(uintptr_t)(gpio + ACPIMMIO_IOMUX_BASE); gpio_ptr = (uint32_t *)gpio_get_address(gpio); save_table->mux_value = read8(mux_ptr); save_table->control_value = read32(gpio_ptr); @@ -360,7 +362,7 @@ static void restore_i2c_pin_registers(uint8_t gpio, uint32_t *gpio_ptr; uint8_t *mux_ptr; - mux_ptr = (uint8_t *)(uintptr_t)(gpio + GPIO_IOMUX_MMIO_BASE); + mux_ptr = (uint8_t *)(uintptr_t)(gpio + ACPIMMIO_IOMUX_BASE); gpio_ptr = (uint32_t *)gpio_get_address(gpio); write8(mux_ptr, save_table->mux_value); read8(mux_ptr); diff --git a/src/soc/amd/stoneyridge/include/soc/iomap.h b/src/soc/amd/stoneyridge/include/soc/iomap.h index 613dd044f6..e6327dc6db 100644 --- a/src/soc/amd/stoneyridge/include/soc/iomap.h +++ b/src/soc/amd/stoneyridge/include/soc/iomap.h @@ -32,19 +32,29 @@ #endif #define HPET_BASE_ADDRESS 0xfed00000 -/* Register blocks at fixed offsets from FED8_0000h and enabled in PMx04[1] */ +/* AcpiMmio blocks are at fixed offsets from FED8_0000h, enabled in PMx04[1] */ #define AMD_SB_ACPI_MMIO_ADDR 0xfed80000 -#define APU_SMI_BASE 0xfed80200 -#define PM_MMIO_BASE 0xfed80300 -#define BIOSRAM_MMIO_BASE 0xfed80500 -#define ACPI_REG_MMIO_BASE 0xfed80800 -#define ASF_MMIO_BASE 0xfed80900 -#define SMBUS_MMIO_BASE 0xfed80a00 -#define GPIO_IOMUX_MMIO_BASE 0xfed80d00 -#define MISC_MMIO_BASE 0xfed80e00 -#define XHCI_ACPI_PM_MMIO_BASE 0xfed81c00 -#define GPIO_CONTROL_MMIO_BASE 0xfed81500 -#define AOAC_MMIO_BASE 0xfed81e00 +#define ACPIMMIO_SM_PCI_BASE 0xfed80000 +#define ACPIMMIO_SMI_BASE 0xfed80200 +#define ACPIMMIO_PMIO_BASE 0xfed80300 +#define ACPIMMIO_PMIO2_BASE 0xfed80400 +#define ACPIMMIO_BIOSRAM_BASE 0xfed80500 +#define ACPIMMIO_CMOSRAM_BASE 0xfed80600 +#define ACPIMMIO_CMOS_BASE 0xfed80700 +#define ACPIMMIO_ACPI_BASE 0xfed80800 +#define ACPIMMIO_ASF_BASE 0xfed80900 +#define ACPIMMIO_SMBUS_BASE 0xfed80a00 +#define ACPIMMIO_WDT_BASE 0xfed80b00 +#define ACPIMMIO_HPET_BASE 0xfed80c00 +#define ACPIMMIO_IOMUX_BASE 0xfed80d00 +#define ACPIMMIO_MISC_BASE 0xfed80e00 +#define ACPIMMIO_DPVGA_BASE 0xfed81400 +#define ACPIMMIO_GPIO0_BASE 0xfed81500 +#define ACPIMMIO_GPIO1_BASE 0xfed81600 +#define ACPIMMIO_GPIO2_BASE 0xfed81700 +#define ACPIMMIO_XHCIPM_BASE 0xfed81c00 +#define ACPIMMIO_ACDCTMR_BASE 0xfed81d00 +#define ACPIMMIO_AOAC_BASE 0xfed81e00 #define APU_UART0_BASE 0xfedc6000 #define APU_UART1_BASE 0xfedc8000 diff --git a/src/soc/amd/stoneyridge/sb_util.c b/src/soc/amd/stoneyridge/sb_util.c index b60f186ac8..3005f4101f 100644 --- a/src/soc/amd/stoneyridge/sb_util.c +++ b/src/soc/amd/stoneyridge/sb_util.c @@ -20,112 +20,112 @@ void pm_write8(u8 reg, u8 value) { - write8((void *)(PM_MMIO_BASE + reg), value); + write8((void *)(ACPIMMIO_PMIO_BASE + reg), value); } u8 pm_read8(u8 reg) { - return read8((void *)(PM_MMIO_BASE + reg)); + return read8((void *)(ACPIMMIO_PMIO_BASE + reg)); } void pm_write16(u8 reg, u16 value) { - write16((void *)(PM_MMIO_BASE + reg), value); + write16((void *)(ACPIMMIO_PMIO_BASE + reg), value); } u16 pm_read16(u8 reg) { - return read16((void *)(PM_MMIO_BASE + reg)); + return read16((void *)(ACPIMMIO_PMIO_BASE + reg)); } void misc_write32(u8 reg, u32 value) { - write32((void *)(MISC_MMIO_BASE + reg), value); + write32((void *)(ACPIMMIO_MISC_BASE + reg), value); } u32 misc_read32(u8 reg) { - return read32((void *)(MISC_MMIO_BASE + reg)); + return read32((void *)(ACPIMMIO_MISC_BASE + reg)); } void pm_write32(u8 reg, u32 value) { - write32((void *)(PM_MMIO_BASE + reg), value); + write32((void *)(ACPIMMIO_PMIO_BASE + reg), value); } u32 pm_read32(u8 reg) { - return read32((void *)(PM_MMIO_BASE + reg)); + return read32((void *)(ACPIMMIO_PMIO_BASE + reg)); } u8 acpi_read8(u8 reg) { - return read8((void *)(ACPI_REG_MMIO_BASE + reg)); + return read8((void *)(ACPIMMIO_ACPI_BASE + reg)); } u16 acpi_read16(u8 reg) { - return read16((void *)(ACPI_REG_MMIO_BASE + reg)); + return read16((void *)(ACPIMMIO_ACPI_BASE + reg)); } u32 acpi_read32(u8 reg) { - return read32((void *)(ACPI_REG_MMIO_BASE + reg)); + return read32((void *)(ACPIMMIO_ACPI_BASE + reg)); } void acpi_write8(u8 reg, u8 value) { - write8((void *)(ACPI_REG_MMIO_BASE + reg), value); + write8((void *)(ACPIMMIO_ACPI_BASE + reg), value); } void acpi_write16(u8 reg, u16 value) { - write16((void *)(ACPI_REG_MMIO_BASE + reg), value); + write16((void *)(ACPIMMIO_ACPI_BASE + reg), value); } void acpi_write32(u8 reg, u32 value) { - write32((void *)(ACPI_REG_MMIO_BASE + reg), value); + write32((void *)(ACPIMMIO_ACPI_BASE + reg), value); } void smi_write32(uint8_t offset, uint32_t value) { - write32((void *)(APU_SMI_BASE + offset), value); + write32((void *)(ACPIMMIO_SMI_BASE + offset), value); } uint32_t smi_read32(uint8_t offset) { - return read32((void *)(APU_SMI_BASE + offset)); + return read32((void *)(ACPIMMIO_SMI_BASE + offset)); } uint16_t smi_read16(uint8_t offset) { - return read16((void *)(APU_SMI_BASE + offset)); + return read16((void *)(ACPIMMIO_SMI_BASE + offset)); } void smi_write16(uint8_t offset, uint16_t value) { - write16((void *)(APU_SMI_BASE + offset), value); + write16((void *)(ACPIMMIO_SMI_BASE + offset), value); } uint8_t smi_read8(uint8_t offset) { - return read8((void *)(APU_SMI_BASE + offset)); + return read8((void *)(ACPIMMIO_SMI_BASE + offset)); } void smi_write8(uint8_t offset, uint8_t value) { - write8((void *)(APU_SMI_BASE + offset), value); + write8((void *)(ACPIMMIO_SMI_BASE + offset), value); } uint8_t biosram_read8(uint8_t offset) { - return read8((void *)(BIOSRAM_MMIO_BASE + offset)); + return read8((void *)(ACPIMMIO_BIOSRAM_BASE + offset)); } void biosram_write8(uint8_t offset, uint8_t value) { - write8((void *)(BIOSRAM_MMIO_BASE + offset), value); + write8((void *)(ACPIMMIO_BIOSRAM_BASE + offset), value); } /* BiosRam may only be accessed a byte at a time */ @@ -174,32 +174,32 @@ uint16_t pm_acpi_pm_evt_blk(void) void xhci_pm_write8(uint8_t reg, uint8_t value) { - write8((void *)(XHCI_ACPI_PM_MMIO_BASE + reg), value); + write8((void *)(ACPIMMIO_XHCIPM_BASE + reg), value); } uint8_t xhci_pm_read8(uint8_t reg) { - return read8((void *)(XHCI_ACPI_PM_MMIO_BASE + reg)); + return read8((void *)(ACPIMMIO_XHCIPM_BASE + reg)); } void xhci_pm_write16(uint8_t reg, uint16_t value) { - write16((void *)(XHCI_ACPI_PM_MMIO_BASE + reg), value); + write16((void *)(ACPIMMIO_XHCIPM_BASE + reg), value); } uint16_t xhci_pm_read16(uint8_t reg) { - return read16((void *)(XHCI_ACPI_PM_MMIO_BASE + reg)); + return read16((void *)(ACPIMMIO_XHCIPM_BASE + reg)); } void xhci_pm_write32(uint8_t reg, uint32_t value) { - write32((void *)(XHCI_ACPI_PM_MMIO_BASE + reg), value); + write32((void *)(ACPIMMIO_XHCIPM_BASE + reg), value); } uint32_t xhci_pm_read32(uint8_t reg) { - return read32((void *)(XHCI_ACPI_PM_MMIO_BASE + reg)); + return read32((void *)(ACPIMMIO_XHCIPM_BASE + reg)); } void smbus_write8(uint32_t mmio, uint8_t reg, uint8_t value) diff --git a/src/soc/amd/stoneyridge/sm.c b/src/soc/amd/stoneyridge/sm.c index 9344b2f180..803e628320 100644 --- a/src/soc/amd/stoneyridge/sm.c +++ b/src/soc/amd/stoneyridge/sm.c @@ -42,9 +42,9 @@ static u32 get_sm_mmio(struct device *dev) pbus = get_pbus_smbus(dev); res = find_resource(pbus->dev, 0x90); if (res->base == SMB_BASE_ADDR) - return SMBUS_MMIO_BASE; + return ACPIMMIO_SMBUS_BASE; - return ASF_MMIO_BASE; + return ACPIMMIO_ASF_BASE; } static int lsmbus_recv_byte(struct device *dev) diff --git a/src/soc/amd/stoneyridge/smbus_spd.c b/src/soc/amd/stoneyridge/smbus_spd.c index ed73a6e51b..e57ecde578 100644 --- a/src/soc/amd/stoneyridge/smbus_spd.c +++ b/src/soc/amd/stoneyridge/smbus_spd.c @@ -46,7 +46,7 @@ static int readspd(uint8_t SmbusSlaveAddress, char *buffer, size_t count) dev_addr = (SmbusSlaveAddress >> 1); /* Read the first SPD byte */ - error = do_smbus_read_byte(SMBUS_MMIO_BASE, dev_addr, 0); + error = do_smbus_read_byte(ACPIMMIO_SMBUS_BASE, dev_addr, 0); if (error < 0) { printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n"); return error; @@ -56,7 +56,7 @@ static int readspd(uint8_t SmbusSlaveAddress, char *buffer, size_t count) /* Read the remaining SPD bytes using do_smbus_recv_byte for speed */ for (index = 1 ; index < count ; index++) { - error = do_smbus_recv_byte(SMBUS_MMIO_BASE, dev_addr); + error = do_smbus_recv_byte(ACPIMMIO_SMBUS_BASE, dev_addr); if (error < 0) { printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n"); return error; diff --git a/src/soc/amd/stoneyridge/southbridge.c b/src/soc/amd/stoneyridge/southbridge.c index 9c546947e3..4f9e8efe71 100644 --- a/src/soc/amd/stoneyridge/southbridge.c +++ b/src/soc/amd/stoneyridge/southbridge.c @@ -279,7 +279,7 @@ int sb_set_wideio_range(uint16_t start, uint16_t size) static void power_on_aoac_device(int aoac_device_control_register) { uint8_t byte; - uint8_t *register_pointer = (uint8_t *)(uintptr_t)AOAC_MMIO_BASE + uint8_t *register_pointer = (uint8_t *)(uintptr_t)ACPIMMIO_AOAC_BASE + aoac_device_control_register; /* Power on the UART and AMBA devices */ @@ -291,7 +291,7 @@ static void power_on_aoac_device(int aoac_device_control_register) static bool is_aoac_device_enabled(int aoac_device_status_register) { uint8_t byte; - byte = read8((uint8_t *)(uintptr_t)AOAC_MMIO_BASE + byte = read8((uint8_t *)(uintptr_t)ACPIMMIO_AOAC_BASE + aoac_device_status_register); byte &= (FCH_AOAC_PWR_RST_STATE | FCH_AOAC_RST_CLK_OK_STATE); if (byte == (FCH_AOAC_PWR_RST_STATE | FCH_AOAC_RST_CLK_OK_STATE)) @@ -393,7 +393,7 @@ static void sb_enable_legacy_io(void) void sb_clk_output_48Mhz(u32 osc) { u32 ctrl; - u32 *misc_clk_cntl_1_ptr = (u32 *)(uintptr_t)(MISC_MMIO_BASE + u32 *misc_clk_cntl_1_ptr = (u32 *)(uintptr_t)(ACPIMMIO_MISC_BASE + MISC_CLK_CNTL1); /* @@ -632,12 +632,12 @@ static void setup_misc(int *reboot) static void fch_smbus_init(void) { pm_write8(SMB_ASF_IO_BASE, SMB_BASE_ADDR >> 8); - smbus_write8(SMBUS_MMIO_BASE, SMBTIMING, SMB_SPEED_400KHZ); + smbus_write8(ACPIMMIO_SMBUS_BASE, SMBTIMING, SMB_SPEED_400KHZ); /* Clear all SMBUS status bits */ - smbus_write8(SMBUS_MMIO_BASE, SMBHSTSTAT, SMBHST_STAT_CLEAR); - smbus_write8(SMBUS_MMIO_BASE, SMBSLVSTAT, SMBSLV_STAT_CLEAR); - smbus_write8(ASF_MMIO_BASE, SMBHSTSTAT, SMBHST_STAT_CLEAR); - smbus_write8(ASF_MMIO_BASE, SMBSLVSTAT, SMBSLV_STAT_CLEAR); + smbus_write8(ACPIMMIO_SMBUS_BASE, SMBHSTSTAT, SMBHST_STAT_CLEAR); + smbus_write8(ACPIMMIO_SMBUS_BASE, SMBSLVSTAT, SMBSLV_STAT_CLEAR); + smbus_write8(ACPIMMIO_ASF_BASE, SMBHSTSTAT, SMBHST_STAT_CLEAR); + smbus_write8(ACPIMMIO_ASF_BASE, SMBSLVSTAT, SMBSLV_STAT_CLEAR); } /* Before console init */ From 6ac87c4986e8af2fbbe8b3ddc6da868422a28101 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Sun, 5 May 2019 12:17:53 -0600 Subject: [PATCH 078/107] soc/amd/stoneyridge: Rearrange sb_util.c In preparation to move code to a common directory, rearrange some of the functions in sb_util.c. Add various comments. This change should have no functional differences. Change-Id: I1ad55a4a14a27e45459dcaf2fcc7449e29da6d4b Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/32643 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth Reviewed-by: Richard Spiegel --- src/soc/amd/stoneyridge/sb_util.c | 289 +++++++++++++++++------------- 1 file changed, 163 insertions(+), 126 deletions(-) diff --git a/src/soc/amd/stoneyridge/sb_util.c b/src/soc/amd/stoneyridge/sb_util.c index 3005f4101f..b777b1a5c9 100644 --- a/src/soc/amd/stoneyridge/sb_util.c +++ b/src/soc/amd/stoneyridge/sb_util.c @@ -18,34 +18,65 @@ #include #include -void pm_write8(u8 reg, u8 value) +/* smbus pci read/write - access registers at 0xfed80000 - currently unused */ + +/* smi read/write - access registers at 0xfed80200 */ + +uint8_t smi_read8(uint8_t offset) { - write8((void *)(ACPIMMIO_PMIO_BASE + reg), value); + return read8((void *)(ACPIMMIO_SMI_BASE + offset)); } +uint16_t smi_read16(uint8_t offset) +{ + return read16((void *)(ACPIMMIO_SMI_BASE + offset)); +} + +uint32_t smi_read32(uint8_t offset) +{ + return read32((void *)(ACPIMMIO_SMI_BASE + offset)); +} + +void smi_write8(uint8_t offset, uint8_t value) +{ + write8((void *)(ACPIMMIO_SMI_BASE + offset), value); +} + +void smi_write16(uint8_t offset, uint16_t value) +{ + write16((void *)(ACPIMMIO_SMI_BASE + offset), value); +} + +void smi_write32(uint8_t offset, uint32_t value) +{ + write32((void *)(ACPIMMIO_SMI_BASE + offset), value); +} + +/* pm read/write - access registers at 0xfed80300 */ + u8 pm_read8(u8 reg) { return read8((void *)(ACPIMMIO_PMIO_BASE + reg)); } -void pm_write16(u8 reg, u16 value) -{ - write16((void *)(ACPIMMIO_PMIO_BASE + reg), value); -} - u16 pm_read16(u8 reg) { return read16((void *)(ACPIMMIO_PMIO_BASE + reg)); } -void misc_write32(u8 reg, u32 value) +u32 pm_read32(u8 reg) { - write32((void *)(ACPIMMIO_MISC_BASE + reg), value); + return read32((void *)(ACPIMMIO_PMIO_BASE + reg)); } -u32 misc_read32(u8 reg) +void pm_write8(u8 reg, u8 value) { - return read32((void *)(ACPIMMIO_MISC_BASE + reg)); + write8((void *)(ACPIMMIO_PMIO_BASE + reg), value); +} + +void pm_write16(u8 reg, u16 value) +{ + write16((void *)(ACPIMMIO_PMIO_BASE + reg), value); } void pm_write32(u8 reg, u32 value) @@ -53,11 +84,59 @@ void pm_write32(u8 reg, u32 value) write32((void *)(ACPIMMIO_PMIO_BASE + reg), value); } -u32 pm_read32(u8 reg) +/* pm2 read/write - access registers at 0xfed80400 - currently unused */ + +/* biosram read/write - access registers at 0xfed80500 */ + +uint8_t biosram_read8(uint8_t offset) { - return read32((void *)(ACPIMMIO_PMIO_BASE + reg)); + return read8((void *)(ACPIMMIO_BIOSRAM_BASE + offset)); } +uint16_t biosram_read16(uint8_t offset) /* Must be 1 byte at a time */ +{ + int i; + uint16_t value = 0; + for (i = sizeof(value) - 1 ; i >= 0 ; i--) + value = (value << 8) | biosram_read8(offset + i); + return value; +} + +uint32_t biosram_read32(uint8_t offset) +{ + uint32_t value = biosram_read16(offset + sizeof(uint16_t)) << 16; + return value | biosram_read16(offset); +} + +void biosram_write8(uint8_t offset, uint8_t value) +{ + write8((void *)(ACPIMMIO_BIOSRAM_BASE + offset), value); +} + +void biosram_write16(uint8_t offset, uint16_t value) +{ + int i; + for (i = 0 ; i < sizeof(value) ; i++) { + biosram_write8(offset + i, value & 0xff); + value >>= 8; + } +} + +void biosram_write32(uint8_t offset, uint32_t value) +{ + int i; + for (i = 0 ; i < sizeof(value) ; i++) { + biosram_write8(offset + i, value & 0xff); + value >>= 8; + } +} + +/* cmosram read/write - access registers at 0xfed80600 - currently unused */ + +/* cmos read/write - access registers at 0xfed80700 - currently unused */ + +/* acpi read/write - access registers at 0xfed80800 */ + u8 acpi_read8(u8 reg) { return read8((void *)(ACPIMMIO_ACPI_BASE + reg)); @@ -88,119 +167,7 @@ void acpi_write32(u8 reg, u32 value) write32((void *)(ACPIMMIO_ACPI_BASE + reg), value); } -void smi_write32(uint8_t offset, uint32_t value) -{ - write32((void *)(ACPIMMIO_SMI_BASE + offset), value); -} - -uint32_t smi_read32(uint8_t offset) -{ - return read32((void *)(ACPIMMIO_SMI_BASE + offset)); -} - -uint16_t smi_read16(uint8_t offset) -{ - return read16((void *)(ACPIMMIO_SMI_BASE + offset)); -} - -void smi_write16(uint8_t offset, uint16_t value) -{ - write16((void *)(ACPIMMIO_SMI_BASE + offset), value); -} - -uint8_t smi_read8(uint8_t offset) -{ - return read8((void *)(ACPIMMIO_SMI_BASE + offset)); -} - -void smi_write8(uint8_t offset, uint8_t value) -{ - write8((void *)(ACPIMMIO_SMI_BASE + offset), value); -} - -uint8_t biosram_read8(uint8_t offset) -{ - return read8((void *)(ACPIMMIO_BIOSRAM_BASE + offset)); -} - -void biosram_write8(uint8_t offset, uint8_t value) -{ - write8((void *)(ACPIMMIO_BIOSRAM_BASE + offset), value); -} - -/* BiosRam may only be accessed a byte at a time */ -uint16_t biosram_read16(uint8_t offset) -{ - int i; - uint16_t value = 0; - for (i = sizeof(value) - 1 ; i >= 0 ; i--) - value = (value << 8) | biosram_read8(offset + i); - return value; -} - -uint32_t biosram_read32(uint8_t offset) -{ - uint32_t value = biosram_read16(offset + sizeof(uint16_t)) << 16; - return value | biosram_read16(offset); -} - -void biosram_write16(uint8_t offset, uint16_t value) -{ - int i; - for (i = 0 ; i < sizeof(value) ; i++) { - biosram_write8(offset + i, value & 0xff); - value >>= 8; - } -} - -void biosram_write32(uint8_t offset, uint32_t value) -{ - int i; - for (i = 0 ; i < sizeof(value) ; i++) { - biosram_write8(offset + i, value & 0xff); - value >>= 8; - } -} - -uint16_t pm_acpi_pm_cnt_blk(void) -{ - return pm_read16(PM1_CNT_BLK); -} - -uint16_t pm_acpi_pm_evt_blk(void) -{ - return pm_read16(PM_EVT_BLK); -} - -void xhci_pm_write8(uint8_t reg, uint8_t value) -{ - write8((void *)(ACPIMMIO_XHCIPM_BASE + reg), value); -} - -uint8_t xhci_pm_read8(uint8_t reg) -{ - return read8((void *)(ACPIMMIO_XHCIPM_BASE + reg)); -} - -void xhci_pm_write16(uint8_t reg, uint16_t value) -{ - write16((void *)(ACPIMMIO_XHCIPM_BASE + reg), value); -} - -uint16_t xhci_pm_read16(uint8_t reg) -{ - return read16((void *)(ACPIMMIO_XHCIPM_BASE + reg)); -} - -void xhci_pm_write32(uint8_t reg, uint32_t value) -{ - write32((void *)(ACPIMMIO_XHCIPM_BASE + reg), value); -} - -uint32_t xhci_pm_read32(uint8_t reg) -{ - return read32((void *)(ACPIMMIO_XHCIPM_BASE + reg)); -} +/* smbus read/write - access registers at 0xfed80a00 and ASF at 0xfed80900 */ void smbus_write8(uint32_t mmio, uint8_t reg, uint8_t value) { @@ -212,6 +179,76 @@ uint8_t smbus_read8(uint32_t mmio, uint8_t reg) return read8((void *)(mmio + reg)); } +/* wdt read/write - access registers at 0xfed80b00 - not currently used */ + +/* hpet read/write - access registers at 0xfed80c00 - not currently used */ + +/* iomux read/write - access registers at 0xfed80d00 - not currently used */ + +/* misc read/write - access registers at 0xfed80e00 */ + +u32 misc_read32(u8 reg) +{ + return read32((void *)(ACPIMMIO_MISC_BASE + reg)); +} + +void misc_write32(u8 reg, u32 value) +{ + write32((void *)(ACPIMMIO_MISC_BASE + reg), value); +} + +/* dpvga read/write - access registers at 0xfed81400 - not currently used */ + +/* gpio bk 0 read/write - access registers at 0xfed81500 - not currently used */ +/* gpio bk 1 read/write - access registers at 0xfed81600 - not currently used */ +/* gpio bk 2 read/write - access registers at 0xfed81700 - not currently used */ + +/* xhci_pm read/write - access registers at 0xfed81c00 */ + +uint8_t xhci_pm_read8(uint8_t reg) +{ + return read8((void *)(ACPIMMIO_XHCIPM_BASE + reg)); +} + +uint16_t xhci_pm_read16(uint8_t reg) +{ + return read16((void *)(ACPIMMIO_XHCIPM_BASE + reg)); +} + +uint32_t xhci_pm_read32(uint8_t reg) +{ + return read32((void *)(ACPIMMIO_XHCIPM_BASE + reg)); +} + +void xhci_pm_write8(uint8_t reg, uint8_t value) +{ + write8((void *)(ACPIMMIO_XHCIPM_BASE + reg), value); +} + +void xhci_pm_write16(uint8_t reg, uint16_t value) +{ + write16((void *)(ACPIMMIO_XHCIPM_BASE + reg), value); +} + +void xhci_pm_write32(uint8_t reg, uint32_t value) +{ + write32((void *)(ACPIMMIO_XHCIPM_BASE + reg), value); +} + +/* acdc_tmr read/write - access registers at 0xfed81d00 */ + +/* aoac read/write - access registers at 0xfed81e00 - not currently used */ + +uint16_t pm_acpi_pm_cnt_blk(void) +{ + return pm_read16(PM1_CNT_BLK); +} + +uint16_t pm_acpi_pm_evt_blk(void) +{ + return pm_read16(PM_EVT_BLK); +} + int acpi_get_sleep_type(void) { return acpi_sleep_from_pm1(inw(pm_acpi_pm_cnt_blk())); From 753c225c2c22df0260a97d3eabaaf15aeb0c4bd6 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Sun, 5 May 2019 14:08:59 -0600 Subject: [PATCH 079/107] soc/amd/stoneyridge: Rewrite smbus_read/write, add asf Convert smbus_read8() and smbus_write8() functions to use the same arguments as the other AcpiMmio blocks, and add 16 and 32 bit versions. Add matching functions for the ASF controller. Change-Id: I3b0ecf21f20472245da98ab5e711a54e99dca93a Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/32644 Tested-by: build bot (Jenkins) Reviewed-by: Richard Spiegel Reviewed-by: Martin Roth --- .../amd/stoneyridge/include/soc/southbridge.h | 10 ++- src/soc/amd/stoneyridge/sb_util.c | 42 +++++++++-- src/soc/amd/stoneyridge/smbus.c | 74 +++++++++++++------ src/soc/amd/stoneyridge/southbridge.c | 10 +-- 4 files changed, 102 insertions(+), 34 deletions(-) diff --git a/src/soc/amd/stoneyridge/include/soc/southbridge.h b/src/soc/amd/stoneyridge/include/soc/southbridge.h index 9fa93c8245..aed3288ae8 100644 --- a/src/soc/amd/stoneyridge/include/soc/southbridge.h +++ b/src/soc/amd/stoneyridge/include/soc/southbridge.h @@ -525,8 +525,14 @@ void xhci_pm_write16(uint8_t reg, uint16_t value); uint16_t xhci_pm_read16(uint8_t reg); void xhci_pm_write32(uint8_t reg, uint32_t value); uint32_t xhci_pm_read32(uint8_t reg); -void smbus_write8(uint32_t mmio, uint8_t reg, uint8_t value); -uint8_t smbus_read8(uint32_t mmio, uint8_t reg); +uint8_t asf_read8(uint8_t offset); +uint16_t asf_read16(uint8_t offset); +void asf_write8(uint8_t offset, uint8_t value); +void asf_write16(uint8_t offset, uint16_t value); +uint8_t smbus_read8(uint8_t offset); +uint16_t smbus_read16(uint8_t offset); +void smbus_write8(uint8_t offset, uint8_t value); +void smbus_write16(uint8_t offset, uint16_t value); void bootblock_fch_early_init(void); void bootblock_fch_init(void); /** diff --git a/src/soc/amd/stoneyridge/sb_util.c b/src/soc/amd/stoneyridge/sb_util.c index b777b1a5c9..4bffdbc5cf 100644 --- a/src/soc/amd/stoneyridge/sb_util.c +++ b/src/soc/amd/stoneyridge/sb_util.c @@ -167,16 +167,48 @@ void acpi_write32(u8 reg, u32 value) write32((void *)(ACPIMMIO_ACPI_BASE + reg), value); } -/* smbus read/write - access registers at 0xfed80a00 and ASF at 0xfed80900 */ +/* asf read/write - access registers at 0xfed80900 - not currently used */ -void smbus_write8(uint32_t mmio, uint8_t reg, uint8_t value) +u8 asf_read8(u8 reg) { - write8((void *)(mmio + reg), value); + return read8((void *)(ACPIMMIO_ASF_BASE + reg)); } -uint8_t smbus_read8(uint32_t mmio, uint8_t reg) +u16 asf_read16(u8 reg) { - return read8((void *)(mmio + reg)); + return read16((void *)(ACPIMMIO_ASF_BASE + reg)); +} + +void asf_write8(u8 reg, u8 value) +{ + write8((void *)(ACPIMMIO_ASF_BASE + reg), value); +} + +void asf_write16(u8 reg, u16 value) +{ + write16((void *)(ACPIMMIO_ASF_BASE + reg), value); +} + +/* smbus read/write - access registers at 0xfed80a00 and ASF at 0xfed80900 */ + +u8 smbus_read8(u8 reg) +{ + return read8((void *)(ACPIMMIO_SMBUS_BASE + reg)); +} + +u16 smbus_read16(u8 reg) +{ + return read16((void *)(ACPIMMIO_SMBUS_BASE + reg)); +} + +void smbus_write8(u8 reg, u8 value) +{ + write8((void *)(ACPIMMIO_SMBUS_BASE + reg), value); +} + +void smbus_write16(u8 reg, u16 value) +{ + write16((void *)(ACPIMMIO_SMBUS_BASE + reg), value); } /* wdt read/write - access registers at 0xfed80b00 - not currently used */ diff --git a/src/soc/amd/stoneyridge/smbus.c b/src/soc/amd/stoneyridge/smbus.c index c4a022a9a9..6285d793b7 100644 --- a/src/soc/amd/stoneyridge/smbus.c +++ b/src/soc/amd/stoneyridge/smbus.c @@ -15,21 +15,51 @@ #include #include +#include #include #include +static u8 controller_read8(u32 base, u8 reg) +{ + switch (base) { + case ACPIMMIO_SMBUS_BASE: + return smbus_read8(reg); + case ACPIMMIO_ASF_BASE: + return asf_read8(reg); + default: + printk(BIOS_ERR, "Error attempting to read SMBus at address 0x%x\n", + base); + } + return 0xff; +} + +static void controller_write8(u32 base, u8 reg, u8 val) +{ + switch (base) { + case ACPIMMIO_SMBUS_BASE: + smbus_write8(reg, val); + break; + case ACPIMMIO_ASF_BASE: + asf_write8(reg, val); + break; + default: + printk(BIOS_ERR, "Error attempting to write SMBus at address 0x%x\n", + base); + } +} + static int smbus_wait_until_ready(u32 mmio) { u32 loops; loops = SMBUS_TIMEOUT; do { u8 val; - val = smbus_read8(mmio, SMBHSTSTAT); + val = controller_read8(mmio, SMBHSTSTAT); val &= SMBHST_STAT_VAL_BITS; if (val == 0) { /* ready now */ return 0; } - smbus_write8(mmio, SMBHSTSTAT, val); + controller_write8(mmio, SMBHSTSTAT, val); } while (--loops); return -2; /* time out */ } @@ -41,12 +71,12 @@ static int smbus_wait_until_done(u32 mmio) do { u8 val; - val = smbus_read8(mmio, SMBHSTSTAT); + val = controller_read8(mmio, SMBHSTSTAT); val &= SMBHST_STAT_VAL_BITS; /* mask off reserved bits */ if (val & SMBHST_STAT_ERROR_BITS) return -5; /* error */ if (val == SMBHST_STAT_NOERROR) { - smbus_write8(mmio, SMBHSTSTAT, val); /* clear sts */ + controller_write8(mmio, SMBHSTSTAT, val); /* clr sts */ return 0; } } while (--loops); @@ -61,19 +91,19 @@ int do_smbus_recv_byte(u32 mmio, u8 device) return -2; /* not ready */ /* set the device I'm talking to */ - smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1); + controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1); - byte = smbus_read8(mmio, SMBHSTCTRL); + byte = controller_read8(mmio, SMBHSTCTRL); byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */ - smbus_write8(mmio, SMBHSTCTRL, byte); + controller_write8(mmio, SMBHSTCTRL, byte); /* poll for transaction completion */ if (smbus_wait_until_done(mmio) < 0) return -3; /* timeout or error */ /* read results of transaction */ - byte = smbus_read8(mmio, SMBHSTDAT0); + byte = controller_read8(mmio, SMBHSTDAT0); return byte; } @@ -86,15 +116,15 @@ int do_smbus_send_byte(u32 mmio, u8 device, u8 val) return -2; /* not ready */ /* set the command... */ - smbus_write8(mmio, SMBHSTDAT0, val); + controller_write8(mmio, SMBHSTDAT0, val); /* set the device I'm talking to */ - smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0); + controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0); - byte = smbus_read8(mmio, SMBHSTCTRL); + byte = controller_read8(mmio, SMBHSTCTRL); byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */ - smbus_write8(mmio, SMBHSTCTRL, byte); + controller_write8(mmio, SMBHSTCTRL, byte); /* poll for transaction completion */ if (smbus_wait_until_done(mmio) < 0) @@ -111,22 +141,22 @@ int do_smbus_read_byte(u32 mmio, u8 device, u8 address) return -2; /* not ready */ /* set the command/address... */ - smbus_write8(mmio, SMBHSTCMD, address & 0xff); + controller_write8(mmio, SMBHSTCMD, address & 0xff); /* set the device I'm talking to */ - smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1); + controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1); - byte = smbus_read8(mmio, SMBHSTCTRL); + byte = controller_read8(mmio, SMBHSTCTRL); byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */ - smbus_write8(mmio, SMBHSTCTRL, byte); + controller_write8(mmio, SMBHSTCTRL, byte); /* poll for transaction completion */ if (smbus_wait_until_done(mmio) < 0) return -3; /* timeout or error */ /* read results of transaction */ - byte = smbus_read8(mmio, SMBHSTDAT0); + byte = controller_read8(mmio, SMBHSTDAT0); return byte; } @@ -139,18 +169,18 @@ int do_smbus_write_byte(u32 mmio, u8 device, u8 address, u8 val) return -2; /* not ready */ /* set the command/address... */ - smbus_write8(mmio, SMBHSTCMD, address & 0xff); + controller_write8(mmio, SMBHSTCMD, address & 0xff); /* set the device I'm talking to */ - smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0); + controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0); /* output value */ - smbus_write8(mmio, SMBHSTDAT0, val); + controller_write8(mmio, SMBHSTDAT0, val); - byte = smbus_read8(mmio, SMBHSTCTRL); + byte = controller_read8(mmio, SMBHSTCTRL); byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */ - smbus_write8(mmio, SMBHSTCTRL, byte); + controller_write8(mmio, SMBHSTCTRL, byte); /* poll for transaction completion */ if (smbus_wait_until_done(mmio) < 0) diff --git a/src/soc/amd/stoneyridge/southbridge.c b/src/soc/amd/stoneyridge/southbridge.c index 4f9e8efe71..66894a24b4 100644 --- a/src/soc/amd/stoneyridge/southbridge.c +++ b/src/soc/amd/stoneyridge/southbridge.c @@ -632,12 +632,12 @@ static void setup_misc(int *reboot) static void fch_smbus_init(void) { pm_write8(SMB_ASF_IO_BASE, SMB_BASE_ADDR >> 8); - smbus_write8(ACPIMMIO_SMBUS_BASE, SMBTIMING, SMB_SPEED_400KHZ); + smbus_write8(SMBTIMING, SMB_SPEED_400KHZ); /* Clear all SMBUS status bits */ - smbus_write8(ACPIMMIO_SMBUS_BASE, SMBHSTSTAT, SMBHST_STAT_CLEAR); - smbus_write8(ACPIMMIO_SMBUS_BASE, SMBSLVSTAT, SMBSLV_STAT_CLEAR); - smbus_write8(ACPIMMIO_ASF_BASE, SMBHSTSTAT, SMBHST_STAT_CLEAR); - smbus_write8(ACPIMMIO_ASF_BASE, SMBSLVSTAT, SMBSLV_STAT_CLEAR); + smbus_write8(SMBHSTSTAT, SMBHST_STAT_CLEAR); + smbus_write8(SMBSLVSTAT, SMBSLV_STAT_CLEAR); + asf_write8(SMBHSTSTAT, SMBHST_STAT_CLEAR); + asf_write8(SMBSLVSTAT, SMBSLV_STAT_CLEAR); } /* Before console init */ From b435d4405dacdc218777aaba349151ae28997741 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Wed, 1 May 2019 21:17:20 -0600 Subject: [PATCH 080/107] soc/amd/stoneyridge: Add aoac_ read/write functions Add 8-bit functions to access the AOAC registers and use them in southbridge.c. At this time, there is no reason to pursue WORD or DWORD access and it's not known if those transaction sizes are supported. Change-Id: I3a8f493625f941fb855c0b8a0eff511a9a5ddfe8 Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/32645 Tested-by: build bot (Jenkins) Reviewed-by: Richard Spiegel Reviewed-by: Martin Roth --- src/soc/amd/stoneyridge/include/soc/southbridge.h | 2 ++ src/soc/amd/stoneyridge/sb_util.c | 10 ++++++++++ src/soc/amd/stoneyridge/southbridge.c | 10 ++++------ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/soc/amd/stoneyridge/include/soc/southbridge.h b/src/soc/amd/stoneyridge/include/soc/southbridge.h index aed3288ae8..098d24edbb 100644 --- a/src/soc/amd/stoneyridge/include/soc/southbridge.h +++ b/src/soc/amd/stoneyridge/include/soc/southbridge.h @@ -533,6 +533,8 @@ uint8_t smbus_read8(uint8_t offset); uint16_t smbus_read16(uint8_t offset); void smbus_write8(uint8_t offset, uint8_t value); void smbus_write16(uint8_t offset, uint16_t value); +uint8_t aoac_read8(uint8_t reg); +void aoac_write8(uint8_t reg, uint8_t value); void bootblock_fch_early_init(void); void bootblock_fch_init(void); /** diff --git a/src/soc/amd/stoneyridge/sb_util.c b/src/soc/amd/stoneyridge/sb_util.c index 4bffdbc5cf..530e9cd946 100644 --- a/src/soc/amd/stoneyridge/sb_util.c +++ b/src/soc/amd/stoneyridge/sb_util.c @@ -271,6 +271,16 @@ void xhci_pm_write32(uint8_t reg, uint32_t value) /* aoac read/write - access registers at 0xfed81e00 - not currently used */ +u8 aoac_read8(u8 reg) +{ + return read8((void *)(ACPIMMIO_AOAC_BASE + reg)); +} + +void aoac_write8(u8 reg, u8 value) +{ + write8((void *)(ACPIMMIO_AOAC_BASE + reg), value); +} + uint16_t pm_acpi_pm_cnt_blk(void) { return pm_read16(PM1_CNT_BLK); diff --git a/src/soc/amd/stoneyridge/southbridge.c b/src/soc/amd/stoneyridge/southbridge.c index 66894a24b4..7dc27c86da 100644 --- a/src/soc/amd/stoneyridge/southbridge.c +++ b/src/soc/amd/stoneyridge/southbridge.c @@ -279,20 +279,18 @@ int sb_set_wideio_range(uint16_t start, uint16_t size) static void power_on_aoac_device(int aoac_device_control_register) { uint8_t byte; - uint8_t *register_pointer = (uint8_t *)(uintptr_t)ACPIMMIO_AOAC_BASE - + aoac_device_control_register; /* Power on the UART and AMBA devices */ - byte = read8(register_pointer); + byte = aoac_read8(aoac_device_control_register); byte |= FCH_AOAC_PWR_ON_DEV; - write8(register_pointer, byte); + aoac_write8(aoac_device_control_register, byte); } static bool is_aoac_device_enabled(int aoac_device_status_register) { uint8_t byte; - byte = read8((uint8_t *)(uintptr_t)ACPIMMIO_AOAC_BASE - + aoac_device_status_register); + + byte = aoac_read8(aoac_device_status_register); byte &= (FCH_AOAC_PWR_RST_STATE | FCH_AOAC_RST_CLK_OK_STATE); if (byte == (FCH_AOAC_PWR_RST_STATE | FCH_AOAC_RST_CLK_OK_STATE)) return true; From b4b9efcfdd47efe67b13e1cf8cfea2ffe08fb012 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Wed, 1 May 2019 17:33:42 -0600 Subject: [PATCH 081/107] soc/amd/stoneyridge: Finish read/write misc registers Add 16 and 32-bit versions of read / write_misc functions. Find one access of the MISC block still using read8() and write8(), and convert it. Change-Id: I296c521ea7f43210db406013bbe79362545ce6f3 Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/32646 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- .../amd/stoneyridge/include/soc/southbridge.h | 4 ++++ src/soc/amd/stoneyridge/sb_util.c | 20 +++++++++++++++++++ src/soc/amd/stoneyridge/southbridge.c | 6 ++---- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/soc/amd/stoneyridge/include/soc/southbridge.h b/src/soc/amd/stoneyridge/include/soc/southbridge.h index 098d24edbb..e5ba2af5eb 100644 --- a/src/soc/amd/stoneyridge/include/soc/southbridge.h +++ b/src/soc/amd/stoneyridge/include/soc/southbridge.h @@ -503,7 +503,11 @@ u32 acpi_read32(u8 reg); void acpi_write8(u8 reg, u8 value); void acpi_write16(u8 reg, u16 value); void acpi_write32(u8 reg, u32 value); +u8 misc_read8(u8 reg); +u16 misc_read16(u8 reg); u32 misc_read32(u8 reg); +void misc_write8(u8 reg, u8 value); +void misc_write16(u8 reg, u16 value); void misc_write32(u8 reg, u32 value); uint8_t smi_read8(uint8_t offset); uint16_t smi_read16(uint8_t offset); diff --git a/src/soc/amd/stoneyridge/sb_util.c b/src/soc/amd/stoneyridge/sb_util.c index 530e9cd946..5aec431593 100644 --- a/src/soc/amd/stoneyridge/sb_util.c +++ b/src/soc/amd/stoneyridge/sb_util.c @@ -219,11 +219,31 @@ void smbus_write16(u8 reg, u16 value) /* misc read/write - access registers at 0xfed80e00 */ +u8 misc_read8(u8 reg) +{ + return read8((void *)(ACPIMMIO_MISC_BASE + reg)); +} + +u16 misc_read16(u8 reg) +{ + return read16((void *)(ACPIMMIO_MISC_BASE + reg)); +} + u32 misc_read32(u8 reg) { return read32((void *)(ACPIMMIO_MISC_BASE + reg)); } +void misc_write8(u8 reg, u8 value) +{ + write8((void *)(ACPIMMIO_MISC_BASE + reg), value); +} + +void misc_write16(u8 reg, u16 value) +{ + write16((void *)(ACPIMMIO_MISC_BASE + reg), value); +} + void misc_write32(u8 reg, u32 value) { write32((void *)(ACPIMMIO_MISC_BASE + reg), value); diff --git a/src/soc/amd/stoneyridge/southbridge.c b/src/soc/amd/stoneyridge/southbridge.c index 7dc27c86da..b5901782f6 100644 --- a/src/soc/amd/stoneyridge/southbridge.c +++ b/src/soc/amd/stoneyridge/southbridge.c @@ -391,14 +391,12 @@ static void sb_enable_legacy_io(void) void sb_clk_output_48Mhz(u32 osc) { u32 ctrl; - u32 *misc_clk_cntl_1_ptr = (u32 *)(uintptr_t)(ACPIMMIO_MISC_BASE - + MISC_CLK_CNTL1); /* * Clear the disable for OSCOUT1 (signal typically named XnnM_25M_48M) * or OSCOUT2 (USBCLK/25M_48M_OSC). The frequency defaults to 48MHz. */ - ctrl = read32(misc_clk_cntl_1_ptr); + ctrl = misc_read32(MISC_CLK_CNTL1); switch (osc) { case 1: @@ -410,7 +408,7 @@ void sb_clk_output_48Mhz(u32 osc) default: return; /* do nothing if invalid */ } - write32(misc_clk_cntl_1_ptr, ctrl); + misc_write32(MISC_CLK_CNTL1, ctrl); } static uintptr_t sb_spibase(void) From 976e3e9ae68d64c374e7e2ace2df86173bd5bec8 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Wed, 1 May 2019 17:48:44 -0600 Subject: [PATCH 082/107] soc/amd/stoneyridge: Add iomux read/write functions Add functions to read and write the region in the AcpiMmio block. Convert gpio.c to use them instead of creating pointers. Change-Id: I2a0f44b6ec7261648cf0357b44a6c18dd40d1504 Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/32647 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/soc/amd/stoneyridge/gpio.c | 16 +++------- .../amd/stoneyridge/include/soc/southbridge.h | 6 ++++ src/soc/amd/stoneyridge/sb_util.c | 32 ++++++++++++++++++- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/soc/amd/stoneyridge/gpio.c b/src/soc/amd/stoneyridge/gpio.c index b747538eaa..285fedd238 100644 --- a/src/soc/amd/stoneyridge/gpio.c +++ b/src/soc/amd/stoneyridge/gpio.c @@ -221,7 +221,6 @@ uint16_t gpio_acpi_pin(gpio_t gpio) void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size) { - uint8_t *mux_ptr; uint32_t *gpio_ptr, *inter_master; uint32_t control, control_flags, edge_level, direction; uint32_t mask, bit_edge, bit_level; @@ -252,9 +251,8 @@ void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size) control = gpio_list_ptr[index].control; control_flags = gpio_list_ptr[index].flags; - mux_ptr = (uint8_t *)(uintptr_t)(gpio + ACPIMMIO_IOMUX_BASE); - write8(mux_ptr, mux & AMD_GPIO_MUX_MASK); - read8(mux_ptr); /* Flush posted write */ + iomux_write8(gpio, mux & AMD_GPIO_MUX_MASK); + iomux_read8(gpio); /* Flush posted write */ /* special case if pin 2 is assigned to wake */ if ((gpio == 2) && !(mux & AMD_GPIO_MUX_MASK)) route_sci(GPIO_2_EVENT); @@ -348,11 +346,9 @@ static void save_i2c_pin_registers(uint8_t gpio, struct soc_amd_i2c_save *save_table) { uint32_t *gpio_ptr; - uint8_t *mux_ptr; - mux_ptr = (uint8_t *)(uintptr_t)(gpio + ACPIMMIO_IOMUX_BASE); gpio_ptr = (uint32_t *)gpio_get_address(gpio); - save_table->mux_value = read8(mux_ptr); + save_table->mux_value = iomux_read8(gpio); save_table->control_value = read32(gpio_ptr); } @@ -360,12 +356,10 @@ static void restore_i2c_pin_registers(uint8_t gpio, struct soc_amd_i2c_save *save_table) { uint32_t *gpio_ptr; - uint8_t *mux_ptr; - mux_ptr = (uint8_t *)(uintptr_t)(gpio + ACPIMMIO_IOMUX_BASE); gpio_ptr = (uint32_t *)gpio_get_address(gpio); - write8(mux_ptr, save_table->mux_value); - read8(mux_ptr); + iomux_write8(gpio, save_table->mux_value); + iomux_read8(gpio); write32(gpio_ptr, save_table->control_value); read32(gpio_ptr); } diff --git a/src/soc/amd/stoneyridge/include/soc/southbridge.h b/src/soc/amd/stoneyridge/include/soc/southbridge.h index e5ba2af5eb..f755c0a0d4 100644 --- a/src/soc/amd/stoneyridge/include/soc/southbridge.h +++ b/src/soc/amd/stoneyridge/include/soc/southbridge.h @@ -529,6 +529,12 @@ void xhci_pm_write16(uint8_t reg, uint16_t value); uint16_t xhci_pm_read16(uint8_t reg); void xhci_pm_write32(uint8_t reg, uint32_t value); uint32_t xhci_pm_read32(uint8_t reg); +u8 iomux_read8(u8 reg); +u16 iomux_read16(u8 reg); +u32 iomux_read32(u8 reg); +void iomux_write8(u8 reg, u8 value); +void iomux_write16(u8 reg, u16 value); +void iomux_write32(u8 reg, u32 value); uint8_t asf_read8(uint8_t offset); uint16_t asf_read16(uint8_t offset); void asf_write8(uint8_t offset, uint8_t value); diff --git a/src/soc/amd/stoneyridge/sb_util.c b/src/soc/amd/stoneyridge/sb_util.c index 5aec431593..41ebb37be2 100644 --- a/src/soc/amd/stoneyridge/sb_util.c +++ b/src/soc/amd/stoneyridge/sb_util.c @@ -215,7 +215,37 @@ void smbus_write16(u8 reg, u16 value) /* hpet read/write - access registers at 0xfed80c00 - not currently used */ -/* iomux read/write - access registers at 0xfed80d00 - not currently used */ +/* iomux read/write - access registers at 0xfed80d00 */ + +u8 iomux_read8(u8 reg) +{ + return read8((void *)(ACPIMMIO_IOMUX_BASE + reg)); +} + +u16 iomux_read16(u8 reg) +{ + return read16((void *)(ACPIMMIO_IOMUX_BASE + reg)); +} + +u32 iomux_read32(u8 reg) +{ + return read32((void *)(ACPIMMIO_IOMUX_BASE + reg)); +} + +void iomux_write8(u8 reg, u8 value) +{ + write8((void *)(ACPIMMIO_IOMUX_BASE + reg), value); +} + +void iomux_write16(u8 reg, u16 value) +{ + write16((void *)(ACPIMMIO_IOMUX_BASE + reg), value); +} + +void iomux_write32(u8 reg, u32 value) +{ + write32((void *)(ACPIMMIO_IOMUX_BASE + reg), value); +} /* misc read/write - access registers at 0xfed80e00 */ From 49df54a1dc0596e23e7865e65a45544c947efc9e Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Sun, 14 Apr 2019 14:39:34 +0200 Subject: [PATCH 083/107] mb/lenovo/t520: Fix devicetree Disable unused PCI devices. Reduces idle power by around 0.5Watt. Tested on Lenovo T520. Change-Id: I6990dc5810084261b75d2a327b6a103be44fd4cc Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/32317 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans --- src/mainboard/lenovo/t520/variants/t520/devicetree.cb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mainboard/lenovo/t520/variants/t520/devicetree.cb b/src/mainboard/lenovo/t520/variants/t520/devicetree.cb index 5f1bc60863..eff2d69304 100644 --- a/src/mainboard/lenovo/t520/variants/t520/devicetree.cb +++ b/src/mainboard/lenovo/t520/variants/t520/devicetree.cb @@ -88,6 +88,8 @@ chip northbridge/intel/sandybridge device pci 1c.6 off end # PCIe Port #7 USB 3.0 only W520 device pci 1c.7 off end # PCIe Port #8 device pci 1d.0 on end # USB2 EHCI #1 + device pci 1e.0 off end # PCI-2-PCI bridge + device pci 1f.0 on #LPC bridge chip ec/lenovo/pmh7 device pnp ff.1 on # dummy @@ -167,6 +169,8 @@ chip northbridge/intel/sandybridge device i2c 5f on end end end # SMBus + device pci 1f.5 off end # IDE controller + device pci 1f.6 off end # Thermal controller end end end From b3ddb29c366d043e9988f1865e9f414e716f02f3 Mon Sep 17 00:00:00 2001 From: Mike Hsieh Date: Thu, 2 May 2019 14:43:26 +0800 Subject: [PATCH 084/107] mb/google/sarien/variants/arcada: Update thermal configuration for DPTF Update dptf for arcada DVT1. BUG=b:123924662 TEST=Built and tested on arcada system Signed-off-by: Mike Hsieh Change-Id: Ia8024a69547a569d288e02931190a98676eeaab4 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32538 Tested-by: build bot (Jenkins) Reviewed-by: Lijian Zhao --- .../arcada/include/variant/acpi/dptf.asl | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/dptf.asl b/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/dptf.asl index 6fa06c7d73..4d380713e2 100644 --- a/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/dptf.asl +++ b/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/dptf.asl @@ -13,14 +13,14 @@ * GNU General Public License for more details. */ -#define DPTF_CPU_PASSIVE 96 -#define DPTF_CPU_CRITICAL 103 +#define DPTF_CPU_PASSIVE 90 +#define DPTF_CPU_CRITICAL 105 /* Skin Sensor for CPU VR temperature monitor */ #define DPTF_TSR0_SENSOR_ID 1 #define DPTF_TSR0_SENSOR_NAME "Skin" -#define DPTF_TSR0_PASSIVE 56 -#define DPTF_TSR0_CRITICAL 108 +#define DPTF_TSR0_PASSIVE 60 +#define DPTF_TSR0_CRITICAL 105 /* Memory Sensor for DDR temperature monitor */ #define DPTF_TSR1_SENSOR_ID 2 @@ -31,24 +31,24 @@ /* M.2 Sensor for Ambient temperature monitor */ #define DPTF_TSR2_SENSOR_ID 3 #define DPTF_TSR2_SENSOR_NAME "Ambient" -#define DPTF_TSR2_PASSIVE 50 -#define DPTF_TSR2_CRITICAL 95 +#define DPTF_TSR2_PASSIVE 37 +#define DPTF_TSR2_CRITICAL 80 #undef DPTF_ENABLE_FAN_CONTROL #undef DPTF_ENABLE_CHARGER Name (DTRT, Package () { /* CPU Throttle Effect on CPU */ - Package () { \_SB.PCI0.TCPU, \_SB.PCI0.TCPU, 100, 10, 0, 0, 0, 0 }, + Package () { \_SB.PCI0.TCPU, \_SB.PCI0.TCPU, 500, 100, 0, 0, 0, 0 }, /* CPU Throttle Effect on Skin (TSR0) */ - Package () { \_SB.PCI0.TCPU, \_SB.DPTF.TSR0, 100, 600, 0, 0, 0, 0 }, + Package () { \_SB.PCI0.TCPU, \_SB.DPTF.TSR0, 500, 30, 0, 0, 0, 0 }, /* CPU Throttle Effect on DDR (TSR1) */ - Package () { \_SB.PCI0.TCPU, \_SB.DPTF.TSR1, 100, 90, 0, 0, 0, 0 }, + Package () { \_SB.PCI0.TCPU, \_SB.DPTF.TSR1, 100, 50, 2, 0, 0, 0 }, /* CPU Throttle Effect on Ambient (TSR2) */ - Package () { \_SB.PCI0.TCPU, \_SB.DPTF.TSR2, 100, 600, 0, 0, 0, 0 }, + Package () { \_SB.PCI0.TCPU, \_SB.DPTF.TSR2, 1000, 100, 1, 0, 0, 0 }, }) Name (MPPC, Package () From c7817bc1280fe2e017c2f99dbb3d19c414ee8c63 Mon Sep 17 00:00:00 2001 From: Lijian Zhao Date: Fri, 19 Apr 2019 20:21:43 -0700 Subject: [PATCH 085/107] soc/intel/common/acpi: Remove EC PTS/WAK dynamic loading Use CondRefOf to replace config optios for PTS/WAK acpi method dynamic loading. Then we can move EC PTS and WAK method to be under mainboard. BUG=N/A TEST=Build sarien source code, check build/dsdt.dsl have EC.PTS method included, build whlrvp soure, check build/dsdt.dsl don't have EC.PTS method. Both able to build pass. Signed-off-by: Lijian Zhao Change-Id: I9f4bd7240832caf070e65039e4ba2d8656371da8 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32371 Reviewed-by: Duncan Laurie Tested-by: build bot (Jenkins) --- src/mainboard/google/sarien/Kconfig | 1 - src/soc/intel/common/Kconfig | 7 ------- src/soc/intel/common/acpi/platform.asl | 9 --------- 3 files changed, 17 deletions(-) diff --git a/src/mainboard/google/sarien/Kconfig b/src/mainboard/google/sarien/Kconfig index c48a908dc1..e6d1f1f60f 100644 --- a/src/mainboard/google/sarien/Kconfig +++ b/src/mainboard/google/sarien/Kconfig @@ -16,7 +16,6 @@ config BOARD_GOOGLE_BASEBOARD_SARIEN select MAINBOARD_HAS_CHROMEOS select MAINBOARD_HAS_I2C_TPM_CR50 select MAINBOARD_HAS_TPM2 - select SOC_INTEL_COMMON_ACPI_EC_PTS_WAK select SOC_INTEL_WHISKEYLAKE select SOC_INTEL_COMMON_BLOCK_HDA_VERB select SOC_INTEL_COMMON_BLOCK_SMM_ESPI_DISABLE diff --git a/src/soc/intel/common/Kconfig b/src/soc/intel/common/Kconfig index 318cc25c87..ac2268661f 100644 --- a/src/soc/intel/common/Kconfig +++ b/src/soc/intel/common/Kconfig @@ -51,13 +51,6 @@ config SOC_INTEL_COMMON_ACPI bool default n -config SOC_INTEL_COMMON_ACPI_EC_PTS_WAK - bool - default n - help - Set this option to have the platform level _PTS/_WAK methods call - methods provided by the Embedded Controller. - config SOC_INTEL_COMMON_NHLT bool default n diff --git a/src/soc/intel/common/acpi/platform.asl b/src/soc/intel/common/acpi/platform.asl index 8b85d44057..9aa2edc6df 100644 --- a/src/soc/intel/common/acpi/platform.asl +++ b/src/soc/intel/common/acpi/platform.asl @@ -37,10 +37,6 @@ Method (_PTS, 1) { Store (POST_OS_ENTER_PTS, DBG0) -#if CONFIG(SOC_INTEL_COMMON_ACPI_EC_PTS_WAK) - /* Call EC _PTS handler */ - \_SB.PCI0.LPCB.EC0.PTS (Arg0) -#endif If (CondRefOf (\_SB.MPTS)) { \_SB.MPTS (Arg0) @@ -58,10 +54,5 @@ Method (_WAK, 1) \_SB.MWAK (Arg0) } -#if CONFIG(SOC_INTEL_COMMON_ACPI_EC_PTS_WAK) - /* Call EC _WAK handler */ - \_SB.PCI0.LPCB.EC0.WAK (Arg0) -#endif - Return (Package(){0,0}) } From 0a433db22cd4eca1d26cd20ed4e662ad7c928934 Mon Sep 17 00:00:00 2001 From: Lijian Zhao Date: Tue, 7 May 2019 13:42:57 -0700 Subject: [PATCH 086/107] mb/google/sarien: Move EC PTS/WAK function to mainboard Move optional EC PTS and WAK function into mainboard level. Signed-off-by: Lijian Zhao Change-Id: Ie91a8168ae234f4fb4843c8587c77ae2f74aeb81 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32671 Tested-by: build bot (Jenkins) Reviewed-by: Duncan Laurie --- .../arcada/include/variant/acpi/mainboard.asl | 12 ++++++++++++ .../sarien/include/variant/acpi/mainboard.asl | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl b/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl index 7b252c7f1c..bc03696048 100644 --- a/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl +++ b/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl @@ -26,3 +26,15 @@ Method (MS0X, 1) \_SB.PCI0.CTXS (CAM_EN) } } + +/* Method called from _PTS prior to enter sleep state */ +Method (MPTS, 1) +{ + \_SB.PCI0.LPCB.EC0.PTS (Arg0) +} + +/* Method called from _WAK prior to wakeup */ +Method (MWAK, 1) +{ + \_SB.PCI0.LPCB.EC0.WAK (Arg0) +} diff --git a/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl b/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl index 7b252c7f1c..bc03696048 100644 --- a/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl +++ b/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl @@ -26,3 +26,15 @@ Method (MS0X, 1) \_SB.PCI0.CTXS (CAM_EN) } } + +/* Method called from _PTS prior to enter sleep state */ +Method (MPTS, 1) +{ + \_SB.PCI0.LPCB.EC0.PTS (Arg0) +} + +/* Method called from _WAK prior to wakeup */ +Method (MWAK, 1) +{ + \_SB.PCI0.LPCB.EC0.WAK (Arg0) +} From 9e8cf3cc869ca70267b43ba4898a9dfa06b5a643 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Tue, 7 May 2019 13:01:53 +0800 Subject: [PATCH 087/107] vboot: remove use of VbInitParams The VbInitParams struct will be deprecated. Remove its use in preparation. Additionally, remove use of the flag VB_INIT_OUT_ENABLE_USB_STORAGE, which is no longer used downstream since vboot_reference CL:347257. BUG=b:124141368, chromium:960226 TEST=make clean && make test-abuild BRANCH=none Change-Id: Ibe02cb6ba639de0d7cbdf79fc4dbf49044c92278 Signed-off-by: Joel Kitching Cq-Depend: chromium:1583943 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32664 Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/security/vboot/vboot_common.c | 2 +- src/security/vboot/vboot_common.h | 3 ++- src/security/vboot/vboot_handoff.c | 4 +--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/security/vboot/vboot_common.c b/src/security/vboot/vboot_common.c index 493cb88898..14f154c438 100644 --- a/src/security/vboot/vboot_common.c +++ b/src/security/vboot/vboot_common.c @@ -85,7 +85,7 @@ static int vboot_get_handoff_flag(uint32_t flag) if (vboot_get_handoff_info((void **)&vbho, NULL)) return 0; - return !!(vbho->init_params.out_flags & flag); + return !!(vbho->out_flags & flag); } int vboot_handoff_check_developer_flag(void) diff --git a/src/security/vboot/vboot_common.h b/src/security/vboot/vboot_common.h index 768b29d4fc..9a02303d12 100644 --- a/src/security/vboot/vboot_common.h +++ b/src/security/vboot/vboot_common.h @@ -39,7 +39,8 @@ int vboot_check_recovery_request(void); * vboot shared data as well as the flags from VbInit. */ struct vboot_handoff { - VbInitParams init_params; + uint32_t reserved0; /* originally from VbInitParams */ + uint32_t out_flags; uint32_t selected_firmware; char shared_data[VB_SHARED_DATA_MIN_SIZE]; } __packed; diff --git a/src/security/vboot/vboot_handoff.c b/src/security/vboot/vboot_handoff.c index 178877d847..208663e029 100644 --- a/src/security/vboot/vboot_handoff.c +++ b/src/security/vboot/vboot_handoff.c @@ -40,7 +40,7 @@ static void fill_vboot_handoff(struct vboot_handoff *vboot_handoff, { VbSharedDataHeader *vb_sd = (VbSharedDataHeader *)vboot_handoff->shared_data; - uint32_t *oflags = &vboot_handoff->init_params.out_flags; + uint32_t *oflags = &vboot_handoff->out_flags; vb_sd->flags |= VBSD_BOOT_FIRMWARE_VBOOT2; @@ -61,12 +61,10 @@ static void fill_vboot_handoff(struct vboot_handoff *vboot_handoff, vb_sd->flags |= VBSD_BOOT_REC_SWITCH_ON; *oflags |= VB_INIT_OUT_ENABLE_RECOVERY; *oflags |= VB_INIT_OUT_CLEAR_RAM; - *oflags |= VB_INIT_OUT_ENABLE_USB_STORAGE; } if (vb2_sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) { *oflags |= VB_INIT_OUT_ENABLE_DEVELOPER; *oflags |= VB_INIT_OUT_CLEAR_RAM; - *oflags |= VB_INIT_OUT_ENABLE_USB_STORAGE; vb_sd->flags |= VBSD_BOOT_DEV_SWITCH_ON; vb_sd->flags |= VBSD_LF_DEV_SWITCH_ON; } From 5923d67cfd07a950ffd435aa078167144366f7dc Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Fri, 12 Apr 2019 15:57:43 +0800 Subject: [PATCH 088/107] vboot: communicate display requirements with vb2api_fw_phase1 Input: tell vb2api_fw_phase1 if display unconditionally available Output: vb2api_fw_phase1 may request coreboot to initialize display, if needed based on some internal request Move setting the VBOOT_FLAG_DISPLAY_REQUESTED flag into verstage_main. BUG=b:124141368, b:124192753, chromium:948529 TEST=make clean && make test-abuild BRANCH=none Change-Id: I81c82c46303564b63b8a32e7f80beb9d891a4628 Cq-Depend: chromium:1564232 Signed-off-by: Joel Kitching Reviewed-on: https://review.coreboot.org/c/coreboot/+/32324 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/security/vboot/vboot_handoff.c | 9 +++------ src/security/vboot/vboot_logic.c | 9 +++++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/security/vboot/vboot_handoff.c b/src/security/vboot/vboot_handoff.c index 208663e029..fccbdfc0b7 100644 --- a/src/security/vboot/vboot_handoff.c +++ b/src/security/vboot/vboot_handoff.c @@ -68,14 +68,11 @@ static void fill_vboot_handoff(struct vboot_handoff *vboot_handoff, vb_sd->flags |= VBSD_BOOT_DEV_SWITCH_ON; vb_sd->flags |= VBSD_LF_DEV_SWITCH_ON; } - /* Inform vboot if the display was requested by vboot kernel phase - or enabled by dev/rec mode. */ + /* TODO(chromium:948529): Remove these two flags after downstream + vboot code longer reads them. */ if (vboot_wants_oprom() || vb2_sd->recovery_reason || - vb2_sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) { - vboot_get_working_data()->flags |= VBOOT_WD_FLAG_DISPLAY_INIT; + vb2_sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) vb_sd->flags |= VBSD_OPROM_LOADED; - } - /* TODO: Remove when depthcharge no longer reads this flag. */ if (CONFIG(VBOOT_MUST_REQUEST_DISPLAY)) vb_sd->flags |= VBSD_OPROM_MATTERS; diff --git a/src/security/vboot/vboot_logic.c b/src/security/vboot/vboot_logic.c index 2a8e619289..df34490f98 100644 --- a/src/security/vboot/vboot_logic.c +++ b/src/security/vboot/vboot_logic.c @@ -336,6 +336,10 @@ void verstage_main(void) if (CONFIG(VBOOT_LID_SWITCH) && !get_lid_switch()) ctx.flags |= VB2_CONTEXT_NOFAIL_BOOT; + /* Mainboard/SoC always initializes display. */ + if (!CONFIG(VBOOT_MUST_REQUEST_DISPLAY)) + ctx.flags |= VB2_CONTEXT_DISPLAY_INIT; + /* Do early init (set up secdata and NVRAM, load GBB) */ printk(BIOS_INFO, "Phase 1\n"); rv = vb2api_fw_phase1(&ctx); @@ -360,6 +364,11 @@ void verstage_main(void) vboot_reboot(); } + /* Is vboot declaring that display is available? If so, we should mark + it down, so that the mainboard/SoC knows to initialize display. */ + if (ctx.flags & VB2_CONTEXT_DISPLAY_INIT) + vboot_get_working_data()->flags |= VBOOT_WD_FLAG_DISPLAY_INIT; + /* Determine which firmware slot to boot (based on NVRAM) */ printk(BIOS_INFO, "Phase 2\n"); rv = vb2api_fw_phase2(&ctx); From 2eb89c8b1479876d37eef37eb4485e23956116e3 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Thu, 25 Apr 2019 17:45:12 +0800 Subject: [PATCH 089/107] vboot: include vb2_sha.h when required Should include vb2_sha.h header when SHA library functions or constants are required. This replaces NEED_VB2_SHA_LIBRARY. BUG=b:124141368, chromium:956474 TEST=make clean && make test-abuild BRANCH=none Change-Id: I9f32174dbf3de05fbe5279cb8017888757abf368 Signed-off-by: Joel Kitching Cq-Depend: chromium:1583820 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32454 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/commonlib/cbfs.c | 1 + src/security/tpm/tspi/tspi.c | 1 + src/security/vboot/antirollback.h | 1 + util/cbfstool/Makefile.inc | 1 - util/cbfstool/cbfs_image.c | 1 + 5 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/commonlib/cbfs.c b/src/commonlib/cbfs.c index 4379099ffe..a509bc9f61 100644 --- a/src/commonlib/cbfs.c +++ b/src/commonlib/cbfs.c @@ -18,6 +18,7 @@ #include #include #include +#include #if !defined(ERROR) #define ERROR(x...) printk(BIOS_ERR, "CBFS: " x) diff --git a/src/security/tpm/tspi/tspi.c b/src/security/tpm/tspi/tspi.c index e466eb87aa..4698a4dc8c 100644 --- a/src/security/tpm/tspi/tspi.c +++ b/src/security/tpm/tspi/tspi.c @@ -22,6 +22,7 @@ #include #if CONFIG(VBOOT) #include +#include #include #endif diff --git a/src/security/vboot/antirollback.h b/src/security/vboot/antirollback.h index 6ea2c13a97..62d2e20f03 100644 --- a/src/security/vboot/antirollback.h +++ b/src/security/vboot/antirollback.h @@ -37,6 +37,7 @@ #include #include +#include struct vb2_context; enum vb2_pcr_digest; diff --git a/util/cbfstool/Makefile.inc b/util/cbfstool/Makefile.inc index 1787eb14c0..79285207b0 100644 --- a/util/cbfstool/Makefile.inc +++ b/util/cbfstool/Makefile.inc @@ -81,7 +81,6 @@ TOOLCPPFLAGS += -I$(top)/util/cbfstool TOOLCPPFLAGS += -I$(objutil)/cbfstool TOOLCPPFLAGS += -I$(top)/src/commonlib/include TOOLCPPFLAGS += -include $(top)/src/commonlib/include/commonlib/compiler.h -TOOLCPPFLAGS += -DNEED_VB2_SHA_LIBRARY TOOLCPPFLAGS += -I$(VBOOT_SOURCE)/firmware/include TOOLCPPFLAGS += -I$(VBOOT_SOURCE)/firmware/2lib/include # UEFI header file support. It's not pretty, but that's what we currently diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c index 5ff81309f4..5cbe1f185a 100644 --- a/util/cbfstool/cbfs_image.c +++ b/util/cbfstool/cbfs_image.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "common.h" #include "cbfs_image.h" From 24047fefdac1d5abc1298a0da20340dc3d7eda48 Mon Sep 17 00:00:00 2001 From: "Ronald G. Minnich" Date: Thu, 9 May 2019 00:01:45 +0000 Subject: [PATCH 090/107] Change the guard for bootblock_systemagent_early_init to ENV_BOOTBLOCK The definition of bootblock_systemagent_early_init was guarded by !ENV_RAMSTAGE. But it's only called in the bootblock. So guard it with ENV_BOOTBLOCK instead. Change-Id: I143cf72e4a63b176e4772575e7a60a2a611e4ad9 Signed-off-by: Ronald G. Minnich Reviewed-on: https://review.coreboot.org/c/coreboot/+/32697 Tested-by: build bot (Jenkins) Reviewed-by: Lijian Zhao Reviewed-by: Subrata Banik --- src/soc/intel/common/block/systemagent/systemagent_early.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/soc/intel/common/block/systemagent/systemagent_early.c b/src/soc/intel/common/block/systemagent/systemagent_early.c index 61f14a935c..c12c64ab53 100644 --- a/src/soc/intel/common/block/systemagent/systemagent_early.c +++ b/src/soc/intel/common/block/systemagent/systemagent_early.c @@ -24,7 +24,7 @@ #include "systemagent_def.h" -#if !ENV_RAMSTAGE +#if ENV_BOOTBLOCK void bootblock_systemagent_early_init(void) { uint32_t reg; From 643daed6b54970da4d83055649b6abc2a198a840 Mon Sep 17 00:00:00 2001 From: Duncan Laurie Date: Wed, 8 May 2019 15:09:29 -0600 Subject: [PATCH 091/107] vendorcode/google/chromeos: Use explicit zero check in ACPI code The ASL 2.0 syntax for "!X" resolves to "LNot(X)" which will evaluate the object as an integer and turn into a boolean. This may not do the right thing if the object is actually a string and it can lead to unexpected behavior. Instead be specific about the object type and check for zero or an empty string depending on what is being returned. This fixes an issue where some VPD keys were causing the search to stop and miss subsequent entries. Change-Id: I1688842964f9c2f81ca31073da9c2d71a8c81767 Signed-off-by: Duncan Laurie Reviewed-on: https://review.coreboot.org/c/coreboot/+/32694 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/vendorcode/google/chromeos/acpi/amac.asl | 3 ++- src/vendorcode/google/chromeos/acpi/vpd.asl | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/vendorcode/google/chromeos/acpi/amac.asl b/src/vendorcode/google/chromeos/acpi/amac.asl index 51159f5124..c87862f6ff 100644 --- a/src/vendorcode/google/chromeos/acpi/amac.asl +++ b/src/vendorcode/google/chromeos/acpi/amac.asl @@ -42,6 +42,7 @@ Scope (\_SB) /* Get "dock_passthru" value from RW_VPD */ Local0 = \VPD.VPDF ("RW", "dock_passthru") + Local1 = Zero Switch (ToString (Local0)) { Case ("ethernet_mac0") { @@ -55,7 +56,7 @@ Scope (\_SB) Local1 = \VPD.VPDF ("RO", "dock_mac") } } - If (!Local1) { + If (Local1 == Zero) { Return (Zero) } Printf ("MAC address returned from VPD: %o", Local1) diff --git a/src/vendorcode/google/chromeos/acpi/vpd.asl b/src/vendorcode/google/chromeos/acpi/vpd.asl index 3b262f75a8..8f8b0e571d 100644 --- a/src/vendorcode/google/chromeos/acpi/vpd.asl +++ b/src/vendorcode/google/chromeos/acpi/vpd.asl @@ -139,7 +139,7 @@ Device (VPD) Local1 <<= 7 Local1 |= Local2 & 0x7f } - If (!Local1) { + If (Local1 == Zero) { Return (Zero) } @@ -162,7 +162,7 @@ Device (VPD) */ Method (VPDS, 0, Serialized) { - Name (VPKV, Package () { Zero, Zero }) + Name (VPKV, Package () { "", "" }) /* Read the VPD type and ensure it is a string */ If (^VPRB () != ^VPES) { @@ -193,14 +193,14 @@ Device (VPD) /* End address of VPD region */ ^VEND = ^VPTR + DerefOf (Local0[1]) - If (!^VPTR || !^VEND) { + If (^VPTR == Zero || ^VEND == Zero) { Printf ("Unable to find VPD region") Return (Zero) } /* Verify VPD info header and save size */ Local0 = VVPD (^VPTR) - If (!Local0) { + If (Local0 == Zero) { Printf ("VPD region %o did not verify", Arg0) Return (Zero) } @@ -213,7 +213,7 @@ Device (VPD) While (Local1 != ToString (Arg1)) { Local2 = VPDS () Local1 = DerefOf (Local2[0]) - If (!Local1) { + If (Local1 == "") { Printf ("VPD KEY %o not found", Arg1) Return (Zero) } From d5d89c8a55ee3a57fb30a7bca346076269266cab Mon Sep 17 00:00:00 2001 From: Lijian Zhao Date: Tue, 7 May 2019 14:05:33 -0700 Subject: [PATCH 092/107] soc/intel/cannonlake: Fix pcie clock number Cannonlake PCH LP have total 6 pcie clocks and Cannonlake PCH H have total 16 pcie clocks. It is different with pcie root port numbers. BUG=CID 1381814 TEST=Build and boot up fine on sarien platform. Signed-off-by: Lijian Zhao Change-Id: I909b5b584c596e6fe878ffe24d9cabc53c4576ed Reviewed-on: https://review.coreboot.org/c/coreboot/+/32672 Tested-by: build bot (Jenkins) Reviewed-by: John Zhao Reviewed-by: Nico Huber Reviewed-by: Furquan Shaikh Reviewed-by: Subrata Banik --- src/soc/intel/cannonlake/Kconfig | 5 +++++ src/soc/intel/cannonlake/chip.h | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig index c06b91eb48..e524275b8f 100644 --- a/src/soc/intel/cannonlake/Kconfig +++ b/src/soc/intel/cannonlake/Kconfig @@ -183,6 +183,11 @@ config MAX_ROOT_PORTS default 24 if SOC_INTEL_CANNONLAKE_PCH_H default 16 +config MAX_PCIE_CLOCKS + int + default 16 if SOC_INTEL_CANNONLAKE_PCH_H + default 6 + config SMM_TSEG_SIZE hex default 0x800000 diff --git a/src/soc/intel/cannonlake/chip.h b/src/soc/intel/cannonlake/chip.h index b17df4b21b..f34528a017 100644 --- a/src/soc/intel/cannonlake/chip.h +++ b/src/soc/intel/cannonlake/chip.h @@ -168,10 +168,10 @@ struct soc_intel_cannonlake_config { /* PCIe output clocks type to Pcie devices. * 0-23: PCH rootport, 0x70: LAN, 0x80: unspecified but in use, * 0xFF: not used */ - uint8_t PcieClkSrcUsage[CONFIG_MAX_ROOT_PORTS]; + uint8_t PcieClkSrcUsage[CONFIG_MAX_PCIE_CLOCKS]; /* PCIe ClkReq-to-ClkSrc mapping, number of clkreq signal assigned to * clksrc. */ - uint8_t PcieClkSrcClkReq[CONFIG_MAX_ROOT_PORTS]; + uint8_t PcieClkSrcClkReq[CONFIG_MAX_PCIE_CLOCKS]; /* PCIe LTR(Latency Tolerance Reporting) mechanism */ uint8_t PcieRpLtrEnable[CONFIG_MAX_ROOT_PORTS]; /* Enable/Disable HotPlug support for Root Port */ From 4feaf6b7b8745ba5a98b9b9372bb0a53b36b38e8 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Wed, 8 May 2019 09:13:34 +0200 Subject: [PATCH 093/107] sb/i82801gx: Remove duplicated 'define PMBASE' Change-Id: If08bea821043bc8e661bf5327f4fe2cef3a65be8 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32677 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- src/southbridge/intel/i82801gx/i82801gx.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/southbridge/intel/i82801gx/i82801gx.h b/src/southbridge/intel/i82801gx/i82801gx.h index 3db5d49f3f..b693b75ccf 100644 --- a/src/southbridge/intel/i82801gx/i82801gx.h +++ b/src/southbridge/intel/i82801gx/i82801gx.h @@ -89,7 +89,6 @@ int smbus_block_write(unsigned int device, unsigned int cmd, u8 bytes, #define RTC_POWER_FAILED (1 << 1) #define SLEEP_AFTER_POWER_FAIL (1 << 0) -#define PMBASE 0x40 #define ACPI_CNTL 0x44 #define ACPI_EN (1 << 7) #define BIOS_CNTL 0xDC From 1119428693e9a8b071115187e601f94d1d706c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Wed, 27 Mar 2019 10:39:55 +0100 Subject: [PATCH 094/107] soc/intel/braswell/smbus: Enable early SMBus in romstage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable early SMBus support compatible with SPD library using Intel SB common SMBus API. TEST=boot Protectli FW2B with new FSP, MemoryInit should pass without errors Signed-off-by: Michał Żygowski Change-Id: I92a2c5a6d0b38e5658cfdc017041f12717dabdd5 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32062 Tested-by: build bot (Jenkins) Reviewed-by: Frans Hendriks Reviewed-by: Patrick Georgi Reviewed-by: Nico Huber --- src/soc/intel/braswell/Makefile.inc | 1 + src/soc/intel/braswell/smbus.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/soc/intel/braswell/smbus.c diff --git a/src/soc/intel/braswell/Makefile.inc b/src/soc/intel/braswell/Makefile.inc index a2b7ee5e67..4e90edf15c 100644 --- a/src/soc/intel/braswell/Makefile.inc +++ b/src/soc/intel/braswell/Makefile.inc @@ -14,6 +14,7 @@ romstage-y += iosf.c romstage-y += lpc_init.c romstage-y += memmap.c romstage-y += pmutil.c +romstage-y += smbus.c romstage-y += tsc_freq.c postcar-y += tsc_freq.c diff --git a/src/soc/intel/braswell/smbus.c b/src/soc/intel/braswell/smbus.c new file mode 100644 index 0000000000..7e1b0dfbb0 --- /dev/null +++ b/src/soc/intel/braswell/smbus.c @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 Intel Corporation. + * Copyright (C) 2019 3mdeb + * + * 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; version 2 of the License. + * + * 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 +#include +#include + +u8 smbus_read_byte(u32 smbus_dev, u8 addr, u8 offset) +{ + return do_smbus_read_byte(SMBUS_BASE_ADDRESS, addr, offset); +} + +u8 smbus_write_byte(u32 smbus_dev, u8 addr, u8 offset, u8 value) +{ + return do_smbus_write_byte(SMBUS_BASE_ADDRESS, addr, offset, value); +} From 8ed01a0e314990539c956b880560526f7c68177d Mon Sep 17 00:00:00 2001 From: Kevin Chiu Date: Wed, 8 May 2019 16:14:47 +0800 Subject: [PATCH 095/107] mainboard/google/kahlee: Fix Micron MT40A512M16TB-062E:J SPD CRC error Correct Micron MT40A512M16TB-062E:J SPD CRC to 0x5330 to fix post hang in AGESA TestPoint:05 TpProcMemSPDChecking. BUG=b:127394249 BRANCH=master TEST=emerge-grunt coreboot chromeos-bootimage Signed-off-by: Kevin Chiu Change-Id: I8fa49e6e938b3195945b3199438cc53f3e9c92e7 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32678 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- .../variants/baseboard/spd/micron-MT40A512M16TB-062E-J.spd.hex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/google/kahlee/variants/baseboard/spd/micron-MT40A512M16TB-062E-J.spd.hex b/src/mainboard/google/kahlee/variants/baseboard/spd/micron-MT40A512M16TB-062E-J.spd.hex index d4afea7263..67640fe849 100644 --- a/src/mainboard/google/kahlee/variants/baseboard/spd/micron-MT40A512M16TB-062E-J.spd.hex +++ b/src/mainboard/google/kahlee/variants/baseboard/spd/micron-MT40A512M16TB-062E-J.spd.hex @@ -6,7 +6,7 @@ 16 36 0B 35 00 00 16 36 0B 35 16 36 0B 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 9C B5 00 00 00 00 E7 00 60 5B +00 00 00 00 00 00 9C B5 00 00 00 00 E7 00 30 53 0F 01 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 From 32b9a99e1670c638cf6e2db2a6274c3f0ab27c85 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Mon, 21 Jan 2019 14:54:31 +0100 Subject: [PATCH 096/107] nb/intel/i945: Use macro instead of magic number Change-Id: I028013bd7511b5b9fc80e5f744fcad584cb25fd3 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/31027 Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- src/northbridge/intel/i945/early_init.c | 4 ++-- src/northbridge/intel/i945/raminit.c | 22 +++++++++++----------- src/southbridge/intel/i82801gx/i82801gx.h | 1 + 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/northbridge/intel/i945/early_init.c b/src/northbridge/intel/i945/early_init.c index 274296d482..84d9c105d6 100644 --- a/src/northbridge/intel/i945/early_init.c +++ b/src/northbridge/intel/i945/early_init.c @@ -158,10 +158,10 @@ static void i945_setup_bars(void) printk(BIOS_DEBUG, "Setting up static southbridge registers..."); pci_write_config32(PCI_DEV(0, 0x1f, 0), PMBASE, DEFAULT_PMBASE | 1); - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0x44, 0x80); /* ACPI_CNTL: Enable ACPI BAR */ + pci_write_config8(PCI_DEV(0, 0x1f, 0), ACPI_CNTL, ACPI_EN); pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIOBASE, DEFAULT_GPIOBASE | 1); - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0x4c, 0x10); /* GC: Enable GPIOs */ + pci_write_config8(PCI_DEV(0, 0x1f, 0), GPIO_CNTL, GPIO_EN); setup_pch_gpios(&mainboard_gpio_map); printk(BIOS_DEBUG, " done.\n"); diff --git a/src/northbridge/intel/i945/raminit.c b/src/northbridge/intel/i945/raminit.c index 0cf03ae605..74407c14ff 100644 --- a/src/northbridge/intel/i945/raminit.c +++ b/src/northbridge/intel/i945/raminit.c @@ -247,13 +247,13 @@ static void sdram_detect_errors(struct sys_info *sysinfo) u8 reg8; u8 do_reset = 0; - reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2); + reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_2); if (reg8 & ((1<<7)|(1<<2))) { if (reg8 & (1<<2)) { printk(BIOS_DEBUG, "SLP S4# Assertion Width Violation.\n"); /* Write back clears bit 2 */ - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8); + pci_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_2, reg8); do_reset = 1; } @@ -261,14 +261,14 @@ static void sdram_detect_errors(struct sys_info *sysinfo) if (reg8 & (1<<7)) { printk(BIOS_DEBUG, "DRAM initialization was interrupted.\n"); reg8 &= ~(1<<7); - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8); + pci_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_2, reg8); do_reset = 1; } /* Set SLP_S3# Assertion Stretch Enable */ - reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); /* GEN_PMCON_3 */ + reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3); reg8 |= (1 << 3); - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8); + pci_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3, reg8); if (do_reset) { printk(BIOS_DEBUG, "Reset required.\n"); @@ -277,9 +277,9 @@ static void sdram_detect_errors(struct sys_info *sysinfo) } /* Set DRAM initialization bit in ICH7 */ - reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2); + reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_2); reg8 |= (1<<7); - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8); + pci_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_2, reg8); /* clear self refresh status if check is disabled or not a resume */ if (!CONFIG(CHECK_SLFRCS_ON_RESUME) @@ -1807,9 +1807,9 @@ static void sdram_program_memory_frequency(struct sys_info *sysinfo) */ goto cache_code; vco_update: - reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2); + reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_2); reg8 &= ~(1 << 7); - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8); + pci_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_2, reg8); clkcfg &= ~(1 << 10); MCHBAR32(CLKCFG) = clkcfg; @@ -2813,9 +2813,9 @@ void sdram_initialize(int boot_path, const u8 *spd_addresses) sdram_enable_rcomp(); /* Tell ICH7 that we're done */ - reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2); + reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_2); reg8 &= ~(1 << 7); - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8); + pci_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_2, reg8); printk(BIOS_DEBUG, "RAM initialization finished.\n"); diff --git a/src/southbridge/intel/i82801gx/i82801gx.h b/src/southbridge/intel/i82801gx/i82801gx.h index b693b75ccf..a91ffc500b 100644 --- a/src/southbridge/intel/i82801gx/i82801gx.h +++ b/src/southbridge/intel/i82801gx/i82801gx.h @@ -94,6 +94,7 @@ int smbus_block_write(unsigned int device, unsigned int cmd, u8 bytes, #define BIOS_CNTL 0xDC #define GPIO_BASE 0x48 /* LPC GPIO Base Address Register */ #define GPIO_CNTL 0x4C /* LPC GPIO Control Register */ +#define GPIO_EN (1 << 4) #define PIRQA_ROUT 0x60 #define PIRQB_ROUT 0x61 From 2de7af0c39c3d65b592c1e83d5511e2ef09a203c Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Wed, 8 May 2019 12:40:19 -0700 Subject: [PATCH 097/107] mb/google/hatch: Fix GBB_HWID for kohaku This change fixes the typo in CB:32161 (mb/google/hatch: Add Kohaku board) that defaults GBB_HWID incorrectly for kohaku using BOARD_GOOGLE_HATCH_WHL. Change-Id: I387879619ac4f79fad422e5f1f047dfe3c7b5b22 Signed-off-by: Furquan Shaikh Reviewed-on: https://review.coreboot.org/c/coreboot/+/32690 Reviewed-by: Tim Wawrzynczak Reviewed-by: Paul Fagerburg Reviewed-by: Shelley Chen Tested-by: build bot (Jenkins) --- src/mainboard/google/hatch/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/google/hatch/Kconfig b/src/mainboard/google/hatch/Kconfig index 07ae7d214e..09f792128c 100644 --- a/src/mainboard/google/hatch/Kconfig +++ b/src/mainboard/google/hatch/Kconfig @@ -64,7 +64,7 @@ config GBB_HWID depends on CHROMEOS default "HATCH TEST 1823" if BOARD_GOOGLE_HATCH default "HATCH_WHL TEST 2374" if BOARD_GOOGLE_HATCH_WHL - default "KOHAKU TEST 1953" if BOARD_GOOGLE_HATCH_WHL + default "KOHAKU TEST 1953" if BOARD_GOOGLE_KOHAKU config MAINBOARD_DIR string From bddfa59f1da418b7c144a4b0eee5e0303aa1183c Mon Sep 17 00:00:00 2001 From: Dtrain Hsu Date: Tue, 7 May 2019 14:35:56 +0800 Subject: [PATCH 098/107] mb/google/hatch: Fine tune Goodix touch screen timing According to Goodix GT7375P datasheet, reduce Goodix touch screen timing. BUG=b:129727745 BRANCH=None TEST=local build and tested with Goodix touch screen worked under coldboot (10 times), warmboot (10 times), S3 (10 times). Change-Id: I4bf081bab5e89d3ce336c6432da5ba71279fa98d Signed-off-by: Dtrain Hsu Reviewed-on: https://review.coreboot.org/c/coreboot/+/32665 Tested-by: build bot (Jenkins) Reviewed-by: Paul Fagerburg Reviewed-by: Shelley Chen --- src/mainboard/google/hatch/variants/hatch/overridetree.cb | 4 ++-- src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mainboard/google/hatch/variants/hatch/overridetree.cb b/src/mainboard/google/hatch/variants/hatch/overridetree.cb index 42752e68f1..562bb8b229 100644 --- a/src/mainboard/google/hatch/variants/hatch/overridetree.cb +++ b/src/mainboard/google/hatch/variants/hatch/overridetree.cb @@ -78,8 +78,8 @@ chip soc/intel/cannonlake register "generic.probed" = "1" register "generic.reset_gpio" = "ACPI_GPIO_OUTPUT_ACTIVE_LOW(GPP_D15)" - register "generic.reset_delay_ms" = "30" - register "generic.reset_off_delay_ms" = "3" + register "generic.reset_delay_ms" = "10" + register "generic.reset_off_delay_ms" = "1" register "generic.has_power_resource" = "1" register "hid_desc_reg_offset" = "0x01" device i2c 5d on end diff --git a/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb b/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb index 115a513038..eec7880752 100644 --- a/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb +++ b/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb @@ -63,8 +63,8 @@ chip soc/intel/cannonlake register "generic.probed" = "1" register "generic.reset_gpio" = "ACPI_GPIO_OUTPUT_ACTIVE_LOW(GPP_D15)" - register "generic.reset_delay_ms" = "30" - register "generic.reset_off_delay_ms" = "3" + register "generic.reset_delay_ms" = "10" + register "generic.reset_off_delay_ms" = "1" register "generic.has_power_resource" = "1" register "hid_desc_reg_offset" = "0x01" device i2c 5d on end From 1360b9a73f5389efd94f0de36588d71f6f8cd1d1 Mon Sep 17 00:00:00 2001 From: Bonnie Lin Date: Wed, 8 May 2019 18:08:08 +0800 Subject: [PATCH 099/107] mb/google/sarien/variants/arcada: Set tcc offset value Set tcc offset value to 1 degree celsius for Arcada system. BRANCH=None BUG=b:122636962 TEST=Built and tested on Arcada system Signed-off-by: Bonnie Lin Change-Id: I3ca4be2f7b92e29fb133ecc32023526b177d2ac2 Reviewed-on: https://review.coreboot.org/c/coreboot/+/32680 Tested-by: build bot (Jenkins) Reviewed-by: Casper Chang Reviewed-by: Lijian Zhao Reviewed-by: Sumeet R Pawnikar --- src/mainboard/google/sarien/variants/arcada/devicetree.cb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/google/sarien/variants/arcada/devicetree.cb b/src/mainboard/google/sarien/variants/arcada/devicetree.cb index 0cc9970488..27c61f3563 100644 --- a/src/mainboard/google/sarien/variants/arcada/devicetree.cb +++ b/src/mainboard/google/sarien/variants/arcada/devicetree.cb @@ -161,7 +161,7 @@ chip soc/intel/cannonlake #| I2C4 | H1 TPM | #+-------------------+---------------------------+ - register "tcc_offset" = "10" + register "tcc_offset" = "1" register "common_soc_config" = "{ .chipset_lockdown = CHIPSET_LOCKDOWN_COREBOOT, From 9d9ce62ae9bd122e43ab87468de541a822a0ff1f Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 25 Dec 2018 18:12:41 +0100 Subject: [PATCH 100/107] mb/google/nami: Add VBT blobs and include them in cbfs Add vbt files for nami variants and select Kconfig option to utilize them. The default vbt is automatically added by the Kconfig selection and so does not need to be specified in the makefile with the others. Test: boot vayne and akali nami variants, verify display functional and correct vbt loaded. Change-Id: Iaf49bdee7ae82a0a61192327351267f098eb5ab1 Signed-off-by: Arthur Heymans Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/30427 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/mainboard/google/poppy/Kconfig | 1 + .../google/poppy/variants/nami/Makefile.inc | 3 +++ .../nami/{vbt-akali.bin => akali-data.vbt} | Bin .../google/poppy/variants/nami/data.vbt | Bin 0 -> 4608 bytes .../google/poppy/variants/nami/pantheon-data.vbt | Bin 0 -> 4608 bytes .../google/poppy/variants/nami/vayne-data.vbt | Bin 0 -> 4608 bytes 6 files changed, 4 insertions(+) rename src/mainboard/google/poppy/variants/nami/{vbt-akali.bin => akali-data.vbt} (100%) create mode 100644 src/mainboard/google/poppy/variants/nami/data.vbt create mode 100644 src/mainboard/google/poppy/variants/nami/pantheon-data.vbt create mode 100644 src/mainboard/google/poppy/variants/nami/vayne-data.vbt diff --git a/src/mainboard/google/poppy/Kconfig b/src/mainboard/google/poppy/Kconfig index b7f479f888..6bc8269aa7 100644 --- a/src/mainboard/google/poppy/Kconfig +++ b/src/mainboard/google/poppy/Kconfig @@ -10,6 +10,7 @@ config BOARD_GOOGLE_BASEBOARD_POPPY select EC_GOOGLE_CHROMEEC_LPC select HAVE_ACPI_RESUME select HAVE_ACPI_TABLES + select INTEL_GMA_HAVE_VBT if BOARD_GOOGLE_NAMI select INTEL_LPSS_UART_FOR_CONSOLE select MAINBOARD_HAS_CHROMEOS select MAINBOARD_USES_FSP2_0 diff --git a/src/mainboard/google/poppy/variants/nami/Makefile.inc b/src/mainboard/google/poppy/variants/nami/Makefile.inc index dc80357835..0033c60ee7 100644 --- a/src/mainboard/google/poppy/variants/nami/Makefile.inc +++ b/src/mainboard/google/poppy/variants/nami/Makefile.inc @@ -43,3 +43,6 @@ oem.bin-file := $(call strip_quotes,$(CONFIG_OEM_BIN_FILE)) oem.bin-type := raw $(call add_vbt_to_cbfs, vbt-bard.bin, bard-data.vbt) +$(call add_vbt_to_cbfs, vbt-akali.bin, akali-data.vbt) +$(call add_vbt_to_cbfs, vbt-pantheon.bin, pantheon-data.vbt) +$(call add_vbt_to_cbfs, vbt-vayne.bin, vayne-data.vbt) diff --git a/src/mainboard/google/poppy/variants/nami/vbt-akali.bin b/src/mainboard/google/poppy/variants/nami/akali-data.vbt similarity index 100% rename from src/mainboard/google/poppy/variants/nami/vbt-akali.bin rename to src/mainboard/google/poppy/variants/nami/akali-data.vbt diff --git a/src/mainboard/google/poppy/variants/nami/data.vbt b/src/mainboard/google/poppy/variants/nami/data.vbt new file mode 100644 index 0000000000000000000000000000000000000000..84063621d0a655cdc7024cf8c0e25004d09183b4 GIT binary patch literal 4608 zcmeHKUu;ul6hF7Of4_TgcY8;m6r4vy=mu=J118KVw`&J0>sY&vIid+2wCG}CV;g4p zj~ZvP1T}q7gNEo5UktvG7@v%h7b6K#c~E?m7ZW6!n27NOxSspn%L**81|tT;Y0r1g zckb!$p7Z@ZT{+k}fVrMs>3B~UI#d81c7?W6JD)mJeYxGq_&|JjXSy%ZgWtnqh=#6S z1Skl?QaPsUvDAUdVkz3+NU&+_9o;ihDz+qx6VFYKj$tN|!ua03#Zqy6c(Pc)+~Br2 zT9^v!JTy`&;EqH4_Y}w5k$`ma#@L4D^&1dlEv@v`V;f1;+hc9*8#gN~*_G()&7{)t zfmGiP?CZy5Di_b?x_Ud)yD-z=*PZH24Rj?HHkU?XbnNi>$TQDQVl>f+t@Ms{9F&KQ ziP7<~W{j6g*l+nvV1IFQS*{Vmi(EG>XNS-Y=klPc{)>cUkq^Mb6;(ir zgkm8^!|}T8c-gPzkI^;fg^pJ+V3`0&c)6krXuq0z6f}`a(K}ueccJ&-^T2G}M>VN!I#E8-?t;XV!i0K%Gp3QrJciO+Z#{6PE@@h`-G z5MLqoc^QO=mk~cg+(NvWI6>S?{3P)(vG)*MHeF?F3W&;rBSW?X)eUboLixC3KknEA zztdzBF-J;{bmIj@3rg<%xyN)q!)3zS2ejFw$la{{TkN~iFpnuhyWVj2Jtb5!%UlC>}7@@G3_(PzGV0_)Ba*ikZ`r6 zZI)O zL_5l}V<#Ubgr@3TRCt{t&w8e7SP$b{O~&c`bU_bi z?RpR>3z3$iwI1$pO>zXqM(|(_SzL_3YzCL;vYx1BQK9`vF_e9q_OV literal 0 HcmV?d00001 diff --git a/src/mainboard/google/poppy/variants/nami/pantheon-data.vbt b/src/mainboard/google/poppy/variants/nami/pantheon-data.vbt new file mode 100644 index 0000000000000000000000000000000000000000..7e4fb0afe5ae87582126da375c018c4b5e1b389f GIT binary patch literal 4608 zcmeGfU2GI(aQ60ozump=Z3!F)))5h|1=_s=6>62e-W7WEO7D85mT1Bi?$E}AmbQ@M zA7`uy32N>^4H}|Nd@=Y!Vtg`2UW_C}pV14D&USo`}Y*b+mQ_Eq>Zr+&FeQH##&nGtH(AHtGCD6+Ba@iSh6e8*PBVD z;{&O_9oW~8$y6?$%XRg3rgveczpp#hnHuOyDr`24#OT$p+w zGA2gH$C@!-Dq+8+GlBiZiQ@R-Vxd`KmXR~ycMAZ52kHzE;94ty-~J-_Rd5^NMsTZO zAQ&p3YCUxW7yt;MT283o+9tQ=>VA0<(y_^TK6To~=5n&2g$k}To*W?>T$(0tp z3*HFlz}I2Z`QtzNBw|&-vY%Y%eGJa~t_a8KtK22=0LcWHE2}=eyPTCZb%BqaSt>B+ zSg_~zSeQHcpZ`y1V0kxO2$U;$@jlg`Uty=B;m#!YKS?#|^3%a!01_)hH$))}NmvPs zAP*VdH~INF`=^}OCPIWdYlGefq7gDaF;C$X0YKv$AU?uym}wJ?y}K(;KPcRQdmyGBZ_uhVQ(t`xJmZv zHyLO1(*-@8wfjM!C`2kps~+yKCbjQLASsR>o(LDlx0P26s9{>OV literal 0 HcmV?d00001 diff --git a/src/mainboard/google/poppy/variants/nami/vayne-data.vbt b/src/mainboard/google/poppy/variants/nami/vayne-data.vbt new file mode 100644 index 0000000000000000000000000000000000000000..7e4fb0afe5ae87582126da375c018c4b5e1b389f GIT binary patch literal 4608 zcmeGfU2GI(aQ60ozump=Z3!F)))5h|1=_s=6>62e-W7WEO7D85mT1Bi?$E}AmbQ@M zA7`uy32N>^4H}|Nd@=Y!Vtg`2UW_C}pV14D&USo`}Y*b+mQ_Eq>Zr+&FeQH##&nGtH(AHtGCD6+Ba@iSh6e8*PBVD z;{&O_9oW~8$y6?$%XRg3rgveczpp#hnHuOyDr`24#OT$p+w zGA2gH$C@!-Dq+8+GlBiZiQ@R-Vxd`KmXR~ycMAZ52kHzE;94ty-~J-_Rd5^NMsTZO zAQ&p3YCUxW7yt;MT283o+9tQ=>VA0<(y_^TK6To~=5n&2g$k}To*W?>T$(0tp z3*HFlz}I2Z`QtzNBw|&-vY%Y%eGJa~t_a8KtK22=0LcWHE2}=eyPTCZb%BqaSt>B+ zSg_~zSeQHcpZ`y1V0kxO2$U;$@jlg`Uty=B;m#!YKS?#|^3%a!01_)hH$))}NmvPs zAP*VdH~INF`=^}OCPIWdYlGefq7gDaF;C$X0YKv$AU?uym}wJ?y}K(;KPcRQdmyGBZ_uhVQ(t`xJmZv zHyLO1(*-@8wfjM!C`2kps~+yKCbjQLASsR>o(LDlx0P26s9{>OV literal 0 HcmV?d00001 From c9f6bd90857d3a7efe08c60f7f5fc19995fb1756 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Thu, 9 May 2019 12:40:53 +0200 Subject: [PATCH 101/107] sb/i82801gx: Don't rewrite over BCTRL PCI_MIN_GNT is defined at offset 0x3e in which does not apply to this PCI bridge because it is only defined for "Header type 0 (normal devices)" (line 82). BCTRL registry for D30:F0 is defined at offset 0x3e for i82801gx (see ICH7 Family Datasheet page 355). The write on that register is already done some lines above. So remove wrong register name and the wrong code line. Change-Id: Ib8a0514200f424049503bb8e4bc076ee6ae86ce3 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32699 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/southbridge/intel/i82801gx/pci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/southbridge/intel/i82801gx/pci.c b/src/southbridge/intel/i82801gx/pci.c index c54769fff3..22c516581f 100644 --- a/src/southbridge/intel/i82801gx/pci.c +++ b/src/southbridge/intel/i82801gx/pci.c @@ -46,9 +46,6 @@ static void pci_init(struct device *dev) reg8 |= (0x04 << 3); pci_write_config8(dev, SMLT, reg8); - /* Will this improve throughput of bus masters? */ - pci_write_config8(dev, PCI_MIN_GNT, 0x06); - /* Clear errors in status registers */ reg16 = pci_read_config16(dev, PSTS); //reg16 |= 0xf900; From 9646cfe989a096372a717d8ef16ce5096d1b2708 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Thu, 9 May 2019 13:24:14 +0200 Subject: [PATCH 102/107] sb/bd82x6x: Don't rewrite over BCTRL PCI_MIN_GNT is defined at offset 0x3e in which does not apply to this PCI bridge because it is only defined for "Header type 0 (normal devices)" (line 82). Some lines obove that code line, the "write" on BCTRL is already done. Change-Id: I8f1b98ba627947ab6652a4ba31d2acb159dd3e32 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32700 Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- src/southbridge/intel/bd82x6x/pci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/southbridge/intel/bd82x6x/pci.c b/src/southbridge/intel/bd82x6x/pci.c index c3b82577e1..2186287df2 100644 --- a/src/southbridge/intel/bd82x6x/pci.c +++ b/src/southbridge/intel/bd82x6x/pci.c @@ -47,9 +47,6 @@ static void pci_init(struct device *dev) reg8 |= (0x04 << 3); pci_write_config8(dev, SMLT, reg8); - /* Will this improve throughput of bus masters? */ - pci_write_config8(dev, PCI_MIN_GNT, 0x06); - /* Clear errors in status registers */ reg16 = pci_read_config16(dev, PSTS); //reg16 |= 0xf900; From f36fcdf2ab6a9956ac60012404e0edf1d6653fac Mon Sep 17 00:00:00 2001 From: Lijian Zhao Date: Fri, 19 Apr 2019 17:36:46 -0700 Subject: [PATCH 103/107] mb/google/sarien: Fix s5 touchscreen power leakage Leakage power is observed from TOUCH_SCREEN_PD# (GPP_E7 which is connected to RESET pin of Wacom controller) during S5. To avoid leakage power, GPP_E7 needs to be turned off before S5 entry. BUG=b:129899315 TEST=Measure leakage power in S5 from both Arcada and Sarien Signed-off-by: Lijian Zhao Change-Id: Ie4229477b7149c0a75f4a8c6c7c453a37cc1c78c Reviewed-on: https://review.coreboot.org/c/coreboot/+/32367 Tested-by: build bot (Jenkins) Reviewed-by: Roy Mingi Park Reviewed-by: Duncan Laurie --- .../sarien/variants/arcada/include/variant/acpi/mainboard.asl | 4 ++++ .../sarien/variants/sarien/include/variant/acpi/mainboard.asl | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl b/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl index bc03696048..41121d28fe 100644 --- a/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl +++ b/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl @@ -14,6 +14,7 @@ */ #define CAM_EN GPP_B11 /* Active low */ +#define TS_PD GPP_E7 /* Method called from LPIT prior to enter s0ix state */ Method (MS0X, 1) @@ -31,6 +32,9 @@ Method (MS0X, 1) Method (MPTS, 1) { \_SB.PCI0.LPCB.EC0.PTS (Arg0) + + /* Clear touch screen pd pin to avoid leakage */ + \_SB.PCI0.CTXS (TS_PD) } /* Method called from _WAK prior to wakeup */ diff --git a/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl b/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl index bc03696048..41121d28fe 100644 --- a/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl +++ b/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl @@ -14,6 +14,7 @@ */ #define CAM_EN GPP_B11 /* Active low */ +#define TS_PD GPP_E7 /* Method called from LPIT prior to enter s0ix state */ Method (MS0X, 1) @@ -31,6 +32,9 @@ Method (MS0X, 1) Method (MPTS, 1) { \_SB.PCI0.LPCB.EC0.PTS (Arg0) + + /* Clear touch screen pd pin to avoid leakage */ + \_SB.PCI0.CTXS (TS_PD) } /* Method called from _WAK prior to wakeup */ From 939bfccb3dbf04a0a2f7e15b82db1fdb469b7a73 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Sun, 5 May 2019 15:39:40 -0600 Subject: [PATCH 104/107] soc/amd/stoneyridge: Add IO access functions for PMx Replace locations in the source that explicitely use the CD6/CD7 index/data pair with utility function calls. Change-Id: I6e7ba472ef2551e363987d18a79408fcd2074de4 Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/32648 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/soc/amd/stoneyridge/enable_usbdebug.c | 5 +-- .../amd/stoneyridge/include/soc/southbridge.h | 6 +++ src/soc/amd/stoneyridge/sb_util.c | 37 +++++++++++++++++++ src/soc/amd/stoneyridge/southbridge.c | 12 ++---- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/soc/amd/stoneyridge/enable_usbdebug.c b/src/soc/amd/stoneyridge/enable_usbdebug.c index ce84a47929..90bd6e8f33 100644 --- a/src/soc/amd/stoneyridge/enable_usbdebug.c +++ b/src/soc/amd/stoneyridge/enable_usbdebug.c @@ -26,10 +26,7 @@ pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx) { - /* Enable all of the USB controllers */ - outb(PM_USB_ENABLE, PM_INDEX); - outb(PM_USB_ALL_CONTROLLERS, PM_DATA); - + pm_io_write8(PM_USB_ENABLE, PM_USB_ALL_CONTROLLERS); return SOC_EHCI1_DEV; } diff --git a/src/soc/amd/stoneyridge/include/soc/southbridge.h b/src/soc/amd/stoneyridge/include/soc/southbridge.h index f755c0a0d4..618a5deff7 100644 --- a/src/soc/amd/stoneyridge/include/soc/southbridge.h +++ b/src/soc/amd/stoneyridge/include/soc/southbridge.h @@ -491,6 +491,12 @@ void sb_tpm_decode(void); void sb_tpm_decode_spi(void); void lpc_wideio_512_window(uint16_t base); void lpc_wideio_16_window(uint16_t base); +uint8_t pm_io_read8(uint8_t reg); +uint16_t pm_io_read16(uint8_t reg); +uint32_t pm_io_read32(uint8_t reg); +void pm_io_write8(uint8_t reg, uint8_t value); +void pm_io_write16(uint8_t reg, uint16_t value); +void pm_io_write32(uint8_t reg, uint32_t value); u8 pm_read8(u8 reg); u16 pm_read16(u8 reg); u32 pm_read32(u8 reg); diff --git a/src/soc/amd/stoneyridge/sb_util.c b/src/soc/amd/stoneyridge/sb_util.c index 41ebb37be2..524efc45ad 100644 --- a/src/soc/amd/stoneyridge/sb_util.c +++ b/src/soc/amd/stoneyridge/sb_util.c @@ -18,6 +18,43 @@ #include #include +/* PM registers are accessed a byte at a time via CD6/CD7 */ +uint8_t pm_io_read8(uint8_t reg) +{ + outb(reg, PM_INDEX); + return inb(PM_DATA); +} + +uint16_t pm_io_read16(uint8_t reg) +{ + return (pm_io_read8(reg + sizeof(uint8_t)) << 8) | pm_io_read8(reg); +} + +uint32_t pm_io_read32(uint8_t reg) +{ + return (pm_io_read16(reg + sizeof(uint16_t)) << 16) | pm_io_read16(reg); +} + +void pm_io_write8(uint8_t reg, uint8_t value) +{ + outb(reg, PM_INDEX); + outb(value, PM_DATA); +} + +void pm_io_write16(uint8_t reg, uint16_t value) +{ + pm_io_write8(reg, value & 0xff); + value >>= 8; + pm_io_write8(reg + sizeof(uint8_t), value & 0xff); +} + +void pm_io_write32(uint8_t reg, uint32_t value) +{ + pm_io_write16(reg, value & 0xffff); + value >>= 16; + pm_io_write16(reg + sizeof(uint16_t), value & 0xffff); +} + /* smbus pci read/write - access registers at 0xfed80000 - currently unused */ /* smi read/write - access registers at 0xfed80200 */ diff --git a/src/soc/amd/stoneyridge/southbridge.c b/src/soc/amd/stoneyridge/southbridge.c index b5901782f6..8dfef8b369 100644 --- a/src/soc/amd/stoneyridge/southbridge.c +++ b/src/soc/amd/stoneyridge/southbridge.c @@ -329,11 +329,9 @@ void sb_lpc_port80(void) u8 byte; /* Enable LPC controller */ - outb(PM_LPC_GATING, PM_INDEX); - byte = inb(PM_DATA); + byte = pm_io_read8(PM_LPC_GATING); byte |= PM_LPC_ENABLE; - outb(PM_LPC_GATING, PM_INDEX); - outb(byte, PM_DATA); + pm_io_write8(PM_LPC_GATING, byte); /* Enable port 80 LPC decode in pci function 3 configuration space. */ byte = pci_read_config8(SOC_LPC_DEV, LPC_IO_OR_MEM_DEC_EN_HIGH); @@ -367,11 +365,9 @@ void sb_acpi_mmio_decode(void) uint8_t byte; /* Enable ACPI MMIO range 0xfed80000 - 0xfed81fff */ - outb(PM_ISA_CONTROL, PM_INDEX); - byte = inb(PM_DATA); + byte = pm_io_read8(PM_ISA_CONTROL); byte |= MMIO_EN; - outb(PM_ISA_CONTROL, PM_INDEX); - outb(byte, PM_DATA); + pm_io_write8(PM_ISA_CONTROL, byte); } static void sb_enable_cf9_io(void) From ef7d89cabe658e7f2951112c50853328988cea98 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Thu, 9 May 2019 13:40:23 -0700 Subject: [PATCH 105/107] vboot: Make vboot_logic_executed() a bit more precise This patch adds another check to vboot_logic_executed() to make sure we only do a runtime check for verstage_should_load() if CONFIG_VBOOT_RETURN_FROM_VERSTAGE is enabled. That's the only case where the stage that's loading the verstage can execute after verification has run (because the verstage will return to it when it's done). In the other case, the stage that loads verstage really just loads it and will never do anything again after hand-off, so it's guaranteed to always execute before verification. This change may allow extra dead-code elimination in some cases. Change-Id: I7019b6f7b0acfbf0a8173914b53364751b08f2cf Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32714 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/security/vboot/vboot_loader.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/security/vboot/vboot_loader.c b/src/security/vboot/vboot_loader.c index 0640ebd173..3bbb3da99c 100644 --- a/src/security/vboot/vboot_loader.c +++ b/src/security/vboot/vboot_loader.c @@ -64,9 +64,11 @@ static int vboot_executed CAR_GLOBAL; int vboot_logic_executed(void) { - /* If we are in a stage that would load the verstage or execute the - vboot logic directly, we store the answer in a global. */ - if (verstage_should_load() || verification_should_run()) + /* If we are in the stage that runs verification, or in the stage that + both loads the verstage and is returned to from it afterwards, we + need to check a global to see if verfication has run. */ + if (verification_should_run() || + (verstage_should_load() && CONFIG(VBOOT_RETURN_FROM_VERSTAGE))) return car_get_var(vboot_executed); if (CONFIG(VBOOT_STARTS_IN_BOOTBLOCK)) { From a73e5a75b1b1ba03e7712d981456974e89a21264 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Thu, 9 May 2019 14:12:17 -0700 Subject: [PATCH 106/107] assert.h: Undefine ASSERT macro in case vendorcode headers set it Some edk2 vendorcode headers define an ASSERT macro. They're guarded with an #ifndef ASSERT, but if coreboot's assert.h gets included after that header, we still have a problem. Add code to assert.h to undefine any rogue definitions that may have already been set by vendorcode headers. This is ugly and should only be a stopgap... it would be nice if someone maintaining those vendorcode parts could eventually replace it with a better solution. One option would be to use a "guard header" for every vendorcode header we want to pull into normal coreboot code which would chain-include the vendorcode header and then undefine anything that clashes with coreboot again. Change-Id: Ibf8dc8b2365821e401ce69705df20aa7540aefb2 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32715 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin Reviewed-by: Furquan Shaikh --- src/include/assert.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/assert.h b/src/include/assert.h index 6036635273..4575a29e44 100644 --- a/src/include/assert.h +++ b/src/include/assert.h @@ -19,6 +19,12 @@ #include #include +/* TODO: Fix vendorcode headers to not define macros coreboot uses or to be more + properly isolated. */ +#ifdef ASSERT +#undef ASSERT +#endif + /* GCC and CAR versions */ #define ASSERT(x) { \ if (!(x)) { \ From 998dc17f522af6ef8fc7c85fa1e90fa7873fe7d1 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Thu, 9 May 2019 14:16:13 -0700 Subject: [PATCH 107/107] vboot: Turn vboot_logic_executed() into a static inline This patch moves vboot_logic_executed() (and its dependencies) into a header and turns it into a static inline function. The function is used to guard larger amounts of code in several places, so this should allow us to save some more space through compile-time elimination (and also makes it easier to avoid undefined reference issues in some cases). Change-Id: I193f608882cbfe07dc91ee90d02fafbd67a3c324 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32716 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin Reviewed-by: Frans Hendriks --- src/security/vboot/misc.h | 61 ++++++++++++++++++++++++++++--- src/security/vboot/vboot_loader.c | 50 +------------------------ 2 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/security/vboot/misc.h b/src/security/vboot/misc.h index b4fae19d74..23159c8a0d 100644 --- a/src/security/vboot/misc.h +++ b/src/security/vboot/misc.h @@ -16,6 +16,8 @@ #ifndef __VBOOT_MISC_H__ #define __VBOOT_MISC_H__ +#include +#include #include struct vb2_context; @@ -65,14 +67,63 @@ int vboot_is_slot_selected(void); */ void vboot_fill_handoff(void); -/* - * Source: security/vboot/vboot_loader.c - */ -int vboot_logic_executed(void); - /* * Source: security/vboot/bootmode.c */ void vboot_save_recovery_reason_vbnv(void); +/* + * The stage loading code is compiled and entered from multiple stages. The + * helper functions below attempt to provide more clarity on when certain + * code should be called. They are implemented inline for better compile-time + * code elimination. + */ + +static inline int verification_should_run(void) +{ + if (CONFIG(VBOOT_SEPARATE_VERSTAGE)) + return ENV_VERSTAGE; + else if (CONFIG(VBOOT_STARTS_IN_ROMSTAGE)) + return ENV_ROMSTAGE; + else if (CONFIG(VBOOT_STARTS_IN_BOOTBLOCK)) + return ENV_BOOTBLOCK; + else + dead_code(); +} + +static inline int verstage_should_load(void) +{ + if (CONFIG(VBOOT_SEPARATE_VERSTAGE)) + return ENV_BOOTBLOCK; + else + return 0; +} + +static inline int vboot_logic_executed(void) +{ + extern int vboot_executed; /* should not be globally accessible */ + + /* If we are in the stage that runs verification, or in the stage that + both loads the verstage and is returned to from it afterwards, we + need to check a global to see if verfication has run. */ + if (verification_should_run() || + (verstage_should_load() && CONFIG(VBOOT_RETURN_FROM_VERSTAGE))) + return car_get_var(vboot_executed); + + if (CONFIG(VBOOT_STARTS_IN_BOOTBLOCK)) { + /* All other stages are "after the bootblock" */ + return !ENV_BOOTBLOCK; + } else if (CONFIG(VBOOT_STARTS_IN_ROMSTAGE)) { + /* Post-RAM stages are "after the romstage" */ +#ifdef __PRE_RAM__ + return 0; +#else + return 1; +#endif + } else { + dead_code(); + } +} + + #endif /* __VBOOT_MISC_H__ */ diff --git a/src/security/vboot/vboot_loader.c b/src/security/vboot/vboot_loader.c index 3bbb3da99c..1350307425 100644 --- a/src/security/vboot/vboot_loader.c +++ b/src/security/vboot/vboot_loader.c @@ -36,55 +36,7 @@ _Static_assert(!CONFIG(VBOOT_RETURN_FROM_VERSTAGE) || CONFIG(VBOOT_SEPARATE_VERSTAGE), "return from verstage only makes sense for separate verstages"); -/* The stage loading code is compiled and entered from multiple stages. The - * helper functions below attempt to provide more clarity on when certain - * code should be called. */ - -static int verification_should_run(void) -{ - if (CONFIG(VBOOT_SEPARATE_VERSTAGE)) - return ENV_VERSTAGE; - else if (CONFIG(VBOOT_STARTS_IN_ROMSTAGE)) - return ENV_ROMSTAGE; - else if (CONFIG(VBOOT_STARTS_IN_BOOTBLOCK)) - return ENV_BOOTBLOCK; - else - die("impossible!"); -} - -static int verstage_should_load(void) -{ - if (CONFIG(VBOOT_SEPARATE_VERSTAGE)) - return ENV_BOOTBLOCK; - else - return 0; -} - -static int vboot_executed CAR_GLOBAL; - -int vboot_logic_executed(void) -{ - /* If we are in the stage that runs verification, or in the stage that - both loads the verstage and is returned to from it afterwards, we - need to check a global to see if verfication has run. */ - if (verification_should_run() || - (verstage_should_load() && CONFIG(VBOOT_RETURN_FROM_VERSTAGE))) - return car_get_var(vboot_executed); - - if (CONFIG(VBOOT_STARTS_IN_BOOTBLOCK)) { - /* All other stages are "after the bootblock" */ - return !ENV_BOOTBLOCK; - } else if (CONFIG(VBOOT_STARTS_IN_ROMSTAGE)) { - /* Post-RAM stages are "after the romstage" */ -#ifdef __PRE_RAM__ - return 0; -#else - return 1; -#endif - } else { - die("impossible!"); - } -} +int vboot_executed CAR_GLOBAL; static void vboot_prepare(void) {