diff --git a/3rdparty/intel-microcode b/3rdparty/intel-microcode index 439ddde999b..4b73c1f1ec8 160000 --- a/3rdparty/intel-microcode +++ b/3rdparty/intel-microcode @@ -1 +1 @@ -Subproject commit 439ddde999b07b28877a60e874f753e72ec2cd59 +Subproject commit 4b73c1f1ec867af894826718ce90d641924a4267 diff --git a/configs/config.msi_ms7d25_ddr4 b/configs/config.msi_ms7d25_ddr4 index 05c89eaa8e9..5a954386faa 100644 --- a/configs/config.msi_ms7d25_ddr4 +++ b/configs/config.msi_ms7d25_ddr4 @@ -1,5 +1,4 @@ -CONFIG_LOCALVERSION="v1.1.7-rc3" -CONFIG_OPTION_BACKEND_NONE=y +CONFIG_LOCALVERSION="v1.1.7" CONFIG_SBOM=y CONFIG_SBOM_PAYLOAD=y CONFIG_SBOM_ME=y @@ -33,12 +32,12 @@ CONFIG_HAVE_ME_BIN=y CONFIG_DASHARO_PREFER_S3_SLEEP=y CONFIG_PCIEXP_SUPPORT_RESIZABLE_BARS=y CONFIG_PCIEXP_LANE_ERR_STAT_CLEAR=y -CONFIG_DRIVERS_EFI_VARIABLE_STORE=y CONFIG_DRIVERS_EFI_FW_INFO=y CONFIG_DRIVERS_EFI_MAIN_FW_GUID="0f3e8ba6-19d3-461b-bbbc-8b5689fe8097" -CONFIG_DRIVERS_EFI_MAIN_FW_VERSION=0x01010703 -CONFIG_DRIVERS_EFI_MAIN_FW_LSV=0x01010701 +CONFIG_DRIVERS_EFI_MAIN_FW_VERSION=0x01010780 +CONFIG_DRIVERS_EFI_MAIN_FW_LSV=0x01010780 CONFIG_DRIVERS_EFI_UPDATE_CAPSULES=y +CONFIG_DRIVERS_OPTION_CFR=y CONFIG_TPM2=y CONFIG_STM=y CONFIG_STM_STMPE_ENABLED=y @@ -76,8 +75,7 @@ CONFIG_EDK2_DASHARO_NETWORK_CONFIG=y CONFIG_EDK2_DASHARO_CHIPSET_CONFIG=y CONFIG_EDK2_DASHARO_POWER_CONFIG=y CONFIG_EDK2_DASHARO_PCI_CONFIG=y -CONFIG_EDK2_DASHARO_MEMORY_CONFIG=y -CONFIG_EDK2_DASHARO_SPD_PROFILE_OPTION=y +CONFIG_EDK2_DASHARO_SERIAL_REDIRECTION_DEFAULT_ENABLE=y CONFIG_EDK2_DASHARO_CPU_CONFIG=y CONFIG_EDK2_CORE_DISABLE_OPTION=y CONFIG_EDK2_HYPERTHREADING_OPTION=y @@ -85,5 +83,5 @@ CONFIG_EDK2_BOOT_MENU_KEY=0x0015 CONFIG_EDK2_SETUP_MENU_KEY=0x0008 CONFIG_EDK2_RAM_DISK_ENABLE=y CONFIG_EDK2_CREATE_PREINSTALLED_BOOT_OPTIONS=y -CONFIG_EDK2_CAPSULES_V2=y -CONFIG_EDK2_CAPSULES_V2_TRANSITION=y +CONFIG_EDK2_ENABLE_FAST_BOOT_FEATURE=y +CONFIG_EDK2_ENABLE_QUIET_BOOT_FEATURE=y diff --git a/configs/config.msi_ms7d25_ddr5 b/configs/config.msi_ms7d25_ddr5 index 7e8e6de625e..38af6330cf5 100644 --- a/configs/config.msi_ms7d25_ddr5 +++ b/configs/config.msi_ms7d25_ddr5 @@ -1,5 +1,4 @@ -CONFIG_LOCALVERSION="v1.1.7-rc3" -CONFIG_OPTION_BACKEND_NONE=y +CONFIG_LOCALVERSION="v1.1.7" CONFIG_SBOM=y CONFIG_SBOM_PAYLOAD=y CONFIG_SBOM_ME=y @@ -33,12 +32,12 @@ CONFIG_HAVE_ME_BIN=y CONFIG_DASHARO_PREFER_S3_SLEEP=y CONFIG_PCIEXP_SUPPORT_RESIZABLE_BARS=y CONFIG_PCIEXP_LANE_ERR_STAT_CLEAR=y -CONFIG_DRIVERS_EFI_VARIABLE_STORE=y CONFIG_DRIVERS_EFI_FW_INFO=y CONFIG_DRIVERS_EFI_MAIN_FW_GUID="119059ec-1a5e-4844-b2e6-6f573b257570" -CONFIG_DRIVERS_EFI_MAIN_FW_VERSION=0x01010703 -CONFIG_DRIVERS_EFI_MAIN_FW_LSV=0x01010701 +CONFIG_DRIVERS_EFI_MAIN_FW_VERSION=0x01010780 +CONFIG_DRIVERS_EFI_MAIN_FW_LSV=0x01010780 CONFIG_DRIVERS_EFI_UPDATE_CAPSULES=y +CONFIG_DRIVERS_OPTION_CFR=y CONFIG_TPM2=y CONFIG_STM=y CONFIG_STM_STMPE_ENABLED=y @@ -75,8 +74,7 @@ CONFIG_EDK2_DASHARO_NETWORK_CONFIG=y CONFIG_EDK2_DASHARO_CHIPSET_CONFIG=y CONFIG_EDK2_DASHARO_POWER_CONFIG=y CONFIG_EDK2_DASHARO_PCI_CONFIG=y -CONFIG_EDK2_DASHARO_MEMORY_CONFIG=y -CONFIG_EDK2_DASHARO_SPD_PROFILE_OPTION=y +CONFIG_EDK2_DASHARO_SERIAL_REDIRECTION_DEFAULT_ENABLE=y CONFIG_EDK2_DASHARO_CPU_CONFIG=y CONFIG_EDK2_CORE_DISABLE_OPTION=y CONFIG_EDK2_HYPERTHREADING_OPTION=y @@ -84,5 +82,5 @@ CONFIG_EDK2_BOOT_MENU_KEY=0x0015 CONFIG_EDK2_SETUP_MENU_KEY=0x0008 CONFIG_EDK2_RAM_DISK_ENABLE=y CONFIG_EDK2_CREATE_PREINSTALLED_BOOT_OPTIONS=y -CONFIG_EDK2_CAPSULES_V2=y -CONFIG_EDK2_CAPSULES_V2_TRANSITION=y +CONFIG_EDK2_ENABLE_FAST_BOOT_FEATURE=y +CONFIG_EDK2_ENABLE_QUIET_BOOT_FEATURE=y diff --git a/configs/config.msi_ms7e06_ddr4 b/configs/config.msi_ms7e06_ddr4 index a759be88c2a..d29f87be8ac 100644 --- a/configs/config.msi_ms7e06_ddr4 +++ b/configs/config.msi_ms7e06_ddr4 @@ -1,5 +1,4 @@ -CONFIG_LOCALVERSION="v0.9.5-rc3" -CONFIG_OPTION_BACKEND_NONE=y +CONFIG_LOCALVERSION="v0.9.5" CONFIG_SBOM=y CONFIG_SBOM_PAYLOAD=y CONFIG_SBOM_ME=y @@ -33,12 +32,12 @@ CONFIG_HAVE_ME_BIN=y CONFIG_DASHARO_PREFER_S3_SLEEP=y CONFIG_PCIEXP_SUPPORT_RESIZABLE_BARS=y CONFIG_PCIEXP_LANE_ERR_STAT_CLEAR=y -CONFIG_DRIVERS_EFI_VARIABLE_STORE=y CONFIG_DRIVERS_EFI_FW_INFO=y CONFIG_DRIVERS_EFI_MAIN_FW_GUID="91e6522e-25e1-4543-9b38-02e2aeafc9ed" -CONFIG_DRIVERS_EFI_MAIN_FW_VERSION=0x00090503 -CONFIG_DRIVERS_EFI_MAIN_FW_LSV=0x00090501 +CONFIG_DRIVERS_EFI_MAIN_FW_VERSION=0x00090580 +CONFIG_DRIVERS_EFI_MAIN_FW_LSV=0x00090580 CONFIG_DRIVERS_EFI_UPDATE_CAPSULES=y +CONFIG_DRIVERS_OPTION_CFR=y CONFIG_TPM2=y CONFIG_STM=y CONFIG_STM_STMPE_ENABLED=y @@ -75,8 +74,7 @@ CONFIG_EDK2_DASHARO_NETWORK_CONFIG=y CONFIG_EDK2_DASHARO_CHIPSET_CONFIG=y CONFIG_EDK2_DASHARO_POWER_CONFIG=y CONFIG_EDK2_DASHARO_PCI_CONFIG=y -CONFIG_EDK2_DASHARO_MEMORY_CONFIG=y -CONFIG_EDK2_DASHARO_SPD_PROFILE_OPTION=y +CONFIG_EDK2_DASHARO_SERIAL_REDIRECTION_DEFAULT_ENABLE=y CONFIG_EDK2_DASHARO_CPU_CONFIG=y CONFIG_EDK2_CORE_DISABLE_OPTION=y CONFIG_EDK2_HYPERTHREADING_OPTION=y @@ -84,5 +82,5 @@ CONFIG_EDK2_BOOT_MENU_KEY=0x0015 CONFIG_EDK2_SETUP_MENU_KEY=0x0008 CONFIG_EDK2_RAM_DISK_ENABLE=y CONFIG_EDK2_CREATE_PREINSTALLED_BOOT_OPTIONS=y -CONFIG_EDK2_CAPSULES_V2=y -CONFIG_EDK2_CAPSULES_V2_TRANSITION=y +CONFIG_EDK2_ENABLE_FAST_BOOT_FEATURE=y +CONFIG_EDK2_ENABLE_QUIET_BOOT_FEATURE=y diff --git a/configs/config.msi_ms7e06_ddr5 b/configs/config.msi_ms7e06_ddr5 index 764d0454cd0..58c333201a3 100644 --- a/configs/config.msi_ms7e06_ddr5 +++ b/configs/config.msi_ms7e06_ddr5 @@ -1,5 +1,4 @@ -CONFIG_LOCALVERSION="v0.9.5-rc3" -CONFIG_OPTION_BACKEND_NONE=y +CONFIG_LOCALVERSION="v0.9.5" CONFIG_SBOM=y CONFIG_SBOM_PAYLOAD=y CONFIG_SBOM_ME=y @@ -33,12 +32,12 @@ CONFIG_HAVE_ME_BIN=y CONFIG_DASHARO_PREFER_S3_SLEEP=y CONFIG_PCIEXP_SUPPORT_RESIZABLE_BARS=y CONFIG_PCIEXP_LANE_ERR_STAT_CLEAR=y -CONFIG_DRIVERS_EFI_VARIABLE_STORE=y CONFIG_DRIVERS_EFI_FW_INFO=y CONFIG_DRIVERS_EFI_MAIN_FW_GUID="58301b3d-5b6d-4562-9ec1-fbce40f15253" -CONFIG_DRIVERS_EFI_MAIN_FW_VERSION=0x00090503 -CONFIG_DRIVERS_EFI_MAIN_FW_LSV=0x00090501 +CONFIG_DRIVERS_EFI_MAIN_FW_VERSION=0x00090580 +CONFIG_DRIVERS_EFI_MAIN_FW_LSV=0x00090580 CONFIG_DRIVERS_EFI_UPDATE_CAPSULES=y +CONFIG_DRIVERS_OPTION_CFR=y CONFIG_TPM2=y CONFIG_STM=y CONFIG_STM_STMPE_ENABLED=y @@ -75,8 +74,7 @@ CONFIG_EDK2_DASHARO_NETWORK_CONFIG=y CONFIG_EDK2_DASHARO_CHIPSET_CONFIG=y CONFIG_EDK2_DASHARO_POWER_CONFIG=y CONFIG_EDK2_DASHARO_PCI_CONFIG=y -CONFIG_EDK2_DASHARO_MEMORY_CONFIG=y -CONFIG_EDK2_DASHARO_SPD_PROFILE_OPTION=y +CONFIG_EDK2_DASHARO_SERIAL_REDIRECTION_DEFAULT_ENABLE=y CONFIG_EDK2_DASHARO_CPU_CONFIG=y CONFIG_EDK2_CORE_DISABLE_OPTION=y CONFIG_EDK2_HYPERTHREADING_OPTION=y @@ -84,5 +82,5 @@ CONFIG_EDK2_BOOT_MENU_KEY=0x0015 CONFIG_EDK2_SETUP_MENU_KEY=0x0008 CONFIG_EDK2_RAM_DISK_ENABLE=y CONFIG_EDK2_CREATE_PREINSTALLED_BOOT_OPTIONS=y -CONFIG_EDK2_CAPSULES_V2=y -CONFIG_EDK2_CAPSULES_V2_TRANSITION=y +CONFIG_EDK2_ENABLE_FAST_BOOT_FEATURE=y +CONFIG_EDK2_ENABLE_QUIET_BOOT_FEATURE=y diff --git a/payloads/external/edk2/Kconfig.dasharo b/payloads/external/edk2/Kconfig.dasharo index 2252e0a26f1..93ce1f1f70d 100644 --- a/payloads/external/edk2/Kconfig.dasharo +++ b/payloads/external/edk2/Kconfig.dasharo @@ -4,7 +4,7 @@ config EDK2_REPOSITORY default "https://github.com/Dasharo/edk2" config EDK2_TAG_OR_REV - default "6d5a8a9a6363e2b30657c4ee4d2088ec11356f0b" + default "5dc2238ef9d7a60e260a7cf4ccd93c0f2c8a04dd" config EDK2_SYSTEM76_EC_LOGGING bool "Enable edk2 logging to System76 EC" diff --git a/src/device/dram/ddr4.c b/src/device/dram/ddr4.c index 6ccef7274f8..41dfa2ab366 100644 --- a/src/device/dram/ddr4.c +++ b/src/device/dram/ddr4.c @@ -226,6 +226,8 @@ int spd_decode_ddr4(struct dimm_attr_ddr4_st *dimm, spd_ddr4_raw_data spd) dimm->ecc_extension = spd[SPD_PRIMARY_SDRAM_WIDTH] & SPD_ECC_8BIT; + dimm->dimms_per_channel = 4; + /* make sure we have the manufacturing information block */ if (spd_bytes_used > 320) { dimm->manufacturer_id = (spd[351] << 8) | spd[350]; @@ -236,6 +238,78 @@ int spd_decode_ddr4(struct dimm_attr_ddr4_st *dimm, spd_ddr4_raw_data spd) return SPD_STATUS_OK; } +/** + * \brief Decode the raw SPD XMP data + * + * Decodes a raw SPD XMP data from a DDR4 DIMM, and organizes it into a + * @ref dimm_attr structure. The SPD data must first be read in a contiguous + * array, and passed to this function. + * + * @param dimm pointer to @ref dimm_attr structure where the decoded data is to + * be stored + * @param spd array of raw data previously read from the SPD. + * + * @param profile select one of the profiles to load + * + * @return @ref spd_status enumerator + * SPD_STATUS_OK -- decoding was successful + * SPD_STATUS_INVALID -- invalid SPD or not a DDR4 SPD + * SPD_STATUS_CRC_ERROR -- CRC did not verify + * SPD_STATUS_INVALID_FIELD -- A field with an invalid value was + * detected. + */ +int spd_xmp_decode_ddr4(struct dimm_attr_ddr4_st *dimm, spd_ddr4_raw_data spd, + enum ddr4_xmp_profile profile) +{ + int ret; + u8 *xmp; /* pointer to XMP profile data */ + + /* need a valid SPD */ + ret = spd_decode_ddr4(dimm, spd); + if (ret != SPD_STATUS_OK) + return ret; + + /* search for magic header */ + if (spd[384] != 0x0C || spd[385] != 0x4A) { + printk(BIOS_ERR, "Not a DDR4 XMP profile!\n"); + dimm->dram_type = SPD_MEMORY_TYPE_UNDEFINED; + return SPD_STATUS_INVALID; + } + + if (profile == DDR4_XMP_PROFILE_1) { + if (!(spd[386] & 1)) { + printk(BIOS_ERR, "XMP profile 1 disabled!\n"); + dimm->dram_type = SPD_MEMORY_TYPE_UNDEFINED; + return SPD_STATUS_INVALID; + } + + xmp = &spd[393]; + dimm->dimms_per_channel = ((spd[386] >> 2) & 0x3) + 1; + printk(BIOS_DEBUG, "XMP profile 1 present\n"); + } else { + if (!(spd[386] & 2)) { + printk(BIOS_ERR, "XMP 2 profile disabled!\n"); + dimm->dram_type = SPD_MEMORY_TYPE_UNDEFINED; + return SPD_STATUS_INVALID; + } + xmp = &spd[440]; + dimm->dimms_per_channel = ((spd[386] >> 4) & 0x3) + 1; + printk(BIOS_DEBUG, "XMP profile 2 present\n"); + } + + printk(BIOS_DEBUG, " Max DIMMs/channel : %u\n", dimm->dimms_per_channel); + + printk(BIOS_DEBUG, " XMP Revision : %u.%u\n", spd[387] >> 4, spd[387] & 0xf); + + /* calculate voltage in mV */ + dimm->vdd_voltage = (xmp[0] & 0x7f) * 10; + dimm->vdd_voltage += (xmp[0] >> 7) * 1000; + + printk(BIOS_DEBUG, " Requested voltage : %u mV\n", dimm->vdd_voltage); + + return ret; +} + enum cb_err spd_add_smbios17_ddr4(const u8 channel, const u8 slot, const u16 selected_freq, const struct dimm_attr_ddr4_st *info) { diff --git a/src/drivers/efi/option.c b/src/drivers/efi/option.c index cc147d26697..b026b3c52f2 100644 --- a/src/drivers/efi/option.c +++ b/src/drivers/efi/option.c @@ -2,6 +2,7 @@ #include #include +#include #include #include "efivars.h" @@ -16,6 +17,9 @@ unsigned int get_uint_option(const char *name, const unsigned int fallback) uint32_t var; uint32_t size; + if (cmos_is_invalid()) + return fallback; + if (smmstore_lookup_region(&rdev)) return fallback; diff --git a/src/drivers/nuvoton/nct3933/Kconfig b/src/drivers/nuvoton/nct3933/Kconfig new file mode 100644 index 00000000000..abf75d90380 --- /dev/null +++ b/src/drivers/nuvoton/nct3933/Kconfig @@ -0,0 +1,6 @@ +config DRIVERS_NUVOTON_NCT3933 + bool + default n + help + Driver for Nuvoton NCT3933 SMBus Sink/Source Current DAC + diff --git a/src/drivers/nuvoton/nct3933/Makefile.mk b/src/drivers/nuvoton/nct3933/Makefile.mk new file mode 100644 index 00000000000..9bccaf8ec2a --- /dev/null +++ b/src/drivers/nuvoton/nct3933/Makefile.mk @@ -0,0 +1,5 @@ +## SPDX-License-Identifier: GPL-2.0-only + +ifeq ($(CONFIG_DRIVERS_NUVOTON_NCT3933),y) +all-y += nct3933.c +endif diff --git a/src/drivers/nuvoton/nct3933/nct3933.c b/src/drivers/nuvoton/nct3933/nct3933.c new file mode 100644 index 00000000000..97c708dd47c --- /dev/null +++ b/src/drivers/nuvoton/nct3933/nct3933.c @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include + +#include "nct3933.h" + +/* + * Based on NCT3933U datasheet: + * https://datasheet.octopart.com/NCT3933U-TR-Nuvoton-datasheet-11773509.pdf + */ + +#define NCT3933_OUT1_DAC_REG 0x01 +#define NCT3933_OUT2_DAC_REG 0x02 +#define NCT3933_OUT3_DAC_REG 0x03 + +#define NCT3933_WDT_REG 0x04 +#define NCT3933_VER_ID_MASK (3 << 0) +#define NCT3933_STEP_SPEED_DELAY_MASK (3 << 2) +#define NCT3933_STEP_SPEED_DELAY_10US (0 << 2) +#define NCT3933_STEP_SPEED_DELAY_20US (1 << 2) +#define NCT3933_STEP_SPEED_DELAY_30US (2 << 2) +#define NCT3933_STEP_SPEED_DELAY_40US (3 << 2) +#define NCT3933_WDT_DELAY_MASK (3 << 4) +#define NCT3933_WDT_DELAY_1400MS (0 << 4) +#define NCT3933_WDT_DELAY_2800MS (1 << 4) +#define NCT3933_WDT_DELAY_5500MS (2 << 4) +#define NCT3933_WDT_DELAY_11000MS (3 << 4) +#define NCT3933_WDT_TIMEOUT_STS (1 << 6) +#define NCT3933_WDT_EN (1 << 7) + +#define NCT3933_TWOFOLD_OUT_CURRENT_REG 0x05 +#define NCT3933_OUT_CURRENT_X2_EN(x) (1 << (((x) - 1) * 2)) +#define NCT3933_POWER_SAVING_FN_EN (1 << 6) + +#define NCT3933_VENDOR_ID1_REG 0x5d +#define NCT3933_VENDOR_ID2_REG 0x5e + +int nct3933_probe(const struct nct3933_smbus_ops *ops, uint8_t addr) +{ + uint8_t ven_id[2] = { 0 }; + uint8_t version = 0; + + if (!addr || !ops || !ops->read_byte) + return -1; + + ops->read_byte(addr, NCT3933_VENDOR_ID1_REG, &ven_id[0]); + ops->read_byte(addr, NCT3933_VENDOR_ID2_REG, &ven_id[1]); + + if (ven_id[0] != 0x39 && ven_id[1] != 0x33) + return -1; + + + ops->read_byte(addr, NCT3933_VENDOR_ID1_REG, &version); + + printk(BIOS_DEBUG, "Found Nuvoton NCT3933 ver %d @ 0x%02x\n", + version & NCT3933_VER_ID_MASK, addr); + + return 0; +} + +int nct3933_set_current_dac(const struct nct3933_smbus_ops *ops, uint8_t addr, uint8_t out_no, + uint8_t value) +{ + if (out_no < NCT3933_OUT1_DAC_REG || out_no > NCT3933_OUT3_DAC_REG) + return -1; + + if (!addr || !ops || !ops->write_byte) + return -1; + + return ops->write_byte(addr, NCT3933_OUT_DAC_REG(out_no), value); +} + +int nct3933_get_current_dac(const struct nct3933_smbus_ops *ops, uint8_t addr, uint8_t out_no, + uint8_t *value) +{ + if (out_no < NCT3933_OUT1_DAC_REG || out_no > NCT3933_OUT3_DAC_REG) + return -1; + + if (!addr || !ops || !ops->read_byte) + return -1; + + return ops->read_byte(addr, NCT3933_OUT_DAC_REG(out_no), value); +} + +int nct3933_set_current_x2(const struct nct3933_smbus_ops *ops, uint8_t addr, uint8_t out_no, + bool enable) +{ + int ret; + uint8_t val; + + if (out_no < NCT3933_OUT1_DAC_REG || out_no > NCT3933_OUT3_DAC_REG) + return -1; + + if (!addr || !ops || !ops->read_byte || !ops->write_byte) + return -1; + + ret = ops->read_byte(addr, NCT3933_TWOFOLD_OUT_CURRENT_REG, &val); + if (ret) + return ret; + + if (enable) + val |= NCT3933_OUT_CURRENT_X2_EN(out_no); + else + val &= ~NCT3933_OUT_CURRENT_X2_EN(out_no); + + return ops->write_byte(addr, NCT3933_TWOFOLD_OUT_CURRENT_REG, val); +} + +int nct3933_set_power_saving(const struct nct3933_smbus_ops *ops, uint8_t addr, uint8_t out_no, + bool enable) +{ + int ret; + uint8_t val; + + if (out_no < NCT3933_OUT1_DAC_REG || out_no > NCT3933_OUT3_DAC_REG) + return -1; + + if (!addr || !ops || !ops->read_byte || !ops->write_byte) + return -1; + + ret = ops->read_byte(addr, NCT3933_TWOFOLD_OUT_CURRENT_REG, &val); + if (ret) + return ret; + + if (enable) + val |= NCT3933_POWER_SAVING_FN_EN; + else + val &= ~NCT3933_POWER_SAVING_FN_EN; + + return ops->write_byte(addr, NCT3933_TWOFOLD_OUT_CURRENT_REG, val); +} \ No newline at end of file diff --git a/src/drivers/nuvoton/nct3933/nct3933.h b/src/drivers/nuvoton/nct3933/nct3933.h new file mode 100644 index 00000000000..c7e198d2380 --- /dev/null +++ b/src/drivers/nuvoton/nct3933/nct3933.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef NCT3933_H +#define NCT3933_H + +#include + +#define NCT3933_OUT_DAC_REG(x) (x) +#define NCT3933_CURRENT_VAL_MASK 0x7f +#define NCT3933_CURRENT_SOURCE (1 << 7) + +/* SMBus operationss struct */ +struct nct3933_smbus_ops { + int (*read_byte)(uint8_t address, uint8_t command, uint8_t *data); + int (*write_byte)(uint8_t address, uint8_t command, uint8_t data); +}; + +int nct3933_probe(const struct nct3933_smbus_ops *ops, uint8_t addr); +int nct3933_set_current_dac(const struct nct3933_smbus_ops *ops, uint8_t addr, uint8_t out_no, + uint8_t value); +int nct3933_get_current_dac(const struct nct3933_smbus_ops *ops, uint8_t addr, uint8_t out_no, + uint8_t *value); +int nct3933_set_current_x2(const struct nct3933_smbus_ops *ops, uint8_t addr, uint8_t out_no, + bool enable); +int nct3933_set_power_saving(const struct nct3933_smbus_ops *ops, uint8_t addr, uint8_t out_no, + bool enable); + +#endif /* NCT3933_H */ diff --git a/src/drivers/pc80/rtc/mc146818rtc.c b/src/drivers/pc80/rtc/mc146818rtc.c index 1c4428a4471..964ce38514e 100644 --- a/src/drivers/pc80/rtc/mc146818rtc.c +++ b/src/drivers/pc80/rtc/mc146818rtc.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,11 @@ int cmos_error(void) return (cmos_read(RTC_VALID) & RTC_VRT) == 0; } +__weak bool cmos_is_invalid(void) +{ + return cmos_read(RTC_CLK_ALTCENTURY) == 0xff; +} + #define RTC_CONTROL_DEFAULT (RTC_24H) #define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ) @@ -165,6 +171,9 @@ void cmos_init(bool invalid) cmos_init_vbnv(invalid); else __cmos_init(invalid); + + if (invalid) + dasharo_reset_options(); } /* diff --git a/src/include/device/dram/ddr4.h b/src/include/device/dram/ddr4.h index da7359a253a..b749438cc04 100644 --- a/src/include/device/dram/ddr4.h +++ b/src/include/device/dram/ddr4.h @@ -62,12 +62,22 @@ struct dimm_attr_ddr4_st { u16 manufacturer_id; u16 vdd_voltage; bool ecc_extension; + u8 dimms_per_channel; +}; + + +enum ddr4_xmp_profile { + DDR4_XMP_PROFILE_1 = 0, + DDR4_XMP_PROFILE_2 = 1, }; typedef u8 spd_ddr4_raw_data[SPD_SIZE_MAX_DDR4]; int spd_decode_ddr4(struct dimm_attr_ddr4_st *dimm, spd_ddr4_raw_data spd); +int spd_xmp_decode_ddr4(struct dimm_attr_ddr4_st *dimm, spd_ddr4_raw_data spd, + enum ddr4_xmp_profile profile); + enum cb_err spd_add_smbios17_ddr4(const u8 channel, const u8 slot, const u16 selected_freq, const struct dimm_attr_ddr4_st *info); diff --git a/src/include/pc80/mc146818rtc.h b/src/include/pc80/mc146818rtc.h index 701cc73af8a..babe2314b2a 100644 --- a/src/include/pc80/mc146818rtc.h +++ b/src/include/pc80/mc146818rtc.h @@ -179,6 +179,7 @@ static inline void cmos_write32(u32 value, u8 offset) void cmos_init(bool invalid); void cmos_check_update_date(void); int cmos_error(void); +bool cmos_is_invalid(void); int cmos_lb_cks_valid(void); int cmos_checksum_valid(int range_start, int range_end, int cks_loc); diff --git a/src/mainboard/msi/ms7d25/Kconfig b/src/mainboard/msi/ms7d25/Kconfig index 05cb0e030c5..e3f6e7c22a4 100644 --- a/src/mainboard/msi/ms7d25/Kconfig +++ b/src/mainboard/msi/ms7d25/Kconfig @@ -2,9 +2,11 @@ config BOARD_MSI_Z690_A_PRO_WIFI_DDR4 select BOARD_MSI_MS7D25 + select DRAM_SUPPORT_DDR4 config BOARD_MSI_Z690_A_PRO_WIFI_DDR5 select BOARD_MSI_MS7D25 + select DRAM_SUPPORT_DDR5 config BOARD_MSI_MS7D25 def_bool n @@ -14,6 +16,7 @@ config BOARD_MSI_MS7D25 select BOARD_ROMSIZE_KB_32768 select SOC_INTEL_COMMON_BLOCK_HDA_VERB select SUPERIO_NUVOTON_NCT6687D + select DRIVERS_NUVOTON_NCT3933 select DRIVERS_UART_8250IO select HAVE_ACPI_RESUME select HAVE_ACPI_TABLES diff --git a/src/mainboard/msi/ms7d25/Makefile.mk b/src/mainboard/msi/ms7d25/Makefile.mk index 8f444768b00..4dbe7c3069c 100644 --- a/src/mainboard/msi/ms7d25/Makefile.mk +++ b/src/mainboard/msi/ms7d25/Makefile.mk @@ -6,6 +6,7 @@ bootblock-y += msi_id.S romstage-y += romstage_fsp_params.c +ramstage-$(CONFIG_DRIVERS_OPTION_CFR) += cfr.c ramstage-y += mainboard.c ramstage-y += smbios.c ramstage-$(CONFIG_STM) += stm.c diff --git a/src/mainboard/msi/ms7d25/cfr.c b/src/mainboard/msi/ms7d25/cfr.c new file mode 100644 index 00000000000..b5914a033b9 --- /dev/null +++ b/src/mainboard/msi/ms7d25/cfr.c @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include + +static struct sm_obj_form cpu_features = { + .ui_name = "CPU Features", + .obj_list = (const struct sm_object *[]) { + &igd_enabled, + &vtd, + &vmx, + NULL + }, +}; + +static struct sm_obj_form pcie_features = { + .ui_name = "PCI Express", + .obj_list = (const struct sm_object *[]) { + &pciexp_speed, + &pciexp_aspm, + &pciexp_aspm_cpu, + &pciexp_clk_pm, + &pciexp_l1ss, + NULL + }, +}; + +static struct sm_obj_form cpu_power = { + .ui_name = "CPU Power and Performance", + .obj_list = (const struct sm_object *[]) { +#if !CONFIG(SOC_INTEL_DISABLE_POWER_LIMITS) + &pl1_override, + &pl1_time, + &pl2_override, + &pl4_override, +#endif + &pcore_turbo_ratio_group0, + &pcore_turbo_ratio_limit0, + &pcore_turbo_ratio_group1, + &pcore_turbo_ratio_limit1, + &pcore_turbo_ratio_group2, + &pcore_turbo_ratio_limit2, + &pcore_turbo_ratio_group3, + &pcore_turbo_ratio_limit3, + &pcore_turbo_ratio_group4, + &pcore_turbo_ratio_limit4, + &pcore_turbo_ratio_group5, + &pcore_turbo_ratio_limit5, + &pcore_turbo_ratio_group6, + &pcore_turbo_ratio_limit6, + &pcore_turbo_ratio_group7, + &pcore_turbo_ratio_limit7, + &ecore_turbo_ratio_group0, + &ecore_turbo_ratio_limit0, + &ecore_turbo_ratio_group1, + &ecore_turbo_ratio_limit1, + &ecore_turbo_ratio_group2, + &ecore_turbo_ratio_limit2, + &ecore_turbo_ratio_group3, + &ecore_turbo_ratio_limit3, + &ecore_turbo_ratio_group4, + &ecore_turbo_ratio_limit4, + &ecore_turbo_ratio_group5, + &ecore_turbo_ratio_limit5, + &ecore_turbo_ratio_group6, + &ecore_turbo_ratio_limit6, + &ecore_turbo_ratio_group7, + &ecore_turbo_ratio_limit7, + NULL + }, +}; + +static const struct sm_object spd_mem_profile = SM_DECLARE_ENUM({ + .opt_name = "spd_mem_profile", + .ui_name = "Memory SPD Profile", + .ui_helptext = "This option selects memory profile applied to RAM modules.\n", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + {"JEDEC (safe non-overclocked default)", 0 }, + {"XMP#1 (predefined extreme memory profile)", 2 }, + {"XMP#2 (predefined extreme memory profile)", 3 }, +#if CONFIG(BOARD_MSI_Z690_A_PRO_WIFI_DDR5) + {"XMP#3 (predefined extreme memory profile)", 4 }, +#endif + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static struct sm_obj_form cpu_oc = { + .ui_name = "CPU Overclocking (EXPERIMENTAL)\n" + "Changing options below may lead to system instability or CPU damage!\n" + "Use at your own responsibility", + .obj_list = (const struct sm_object *[]) { + &oc_support, + &oc_lock, + &spd_mem_profile, + &core_volt_mode, + &core_volt_ovr, + &core_volt_adapt, + &core_volt_off, + &core_volt_off_sign, + &atom_core_volt_mode, + &atom_core_volt_ovr, + &atom_core_volt_adapt, + &atom_core_volt_off, + &atom_core_volt_off_sign, + >_volt_mode, + >_volt_ovr, + >_volt_adapt, + >_volt_off, + >_volt_off_sign, + &ring_downbin, + &undervolt_protection, + &ia_cep, + >_cep, + &ia_vr_config, + &ia_ac_ll, + &ia_dc_ll, + &ia_vr_vlimit, + >_vr_config, + >_ac_ll, + >_dc_ll, + >_vr_vlimit, + NULL + }, +}; + +#if CONFIG(BOARD_MSI_Z690_A_PRO_WIFI_DDR4) +static const struct sm_object ram_ov_config = SM_DECLARE_ENUM({ + .opt_name = "ram_ov_config", + .ui_name = "RAM Overvolting", + .ui_helptext = "Enable or disable the RAM Overvolting.\n\n" + "By default RAM voltage will be set according to selected Memory SPD Profile", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + { "Use voltage from Memory SPD profile", 0 }, + { "Manual ", 1 }, + SM_ENUM_VALUE_END }, +}); + +static const struct sm_object dram_volt = SM_DECLARE_NUMBER({ + .opt_name = "dram_voltage", + .ui_name = "DRAM Voltage", + .ui_helptext = "Configure DRAM Voltage. Unit is 1mV, 10mV step.", + .default_value = 1200, + .min = 850, + .max = 2200, + .step = 10, +}, WITH_DEP_VALUES(&ram_ov_config, 1)); + +static const struct sm_object dram_vtt = SM_DECLARE_NUMBER({ + .opt_name = "dram_vtt", + .ui_name = "DRAM VTT Voltage", + .ui_helptext = "Configure DRAM VTT Voltage. Unit is 1mV, 10mV step.", + .default_value = 600, + .min = 120, + .max = 1100, + .step = 10, +}, WITH_DEP_VALUES(&ram_ov_config, 1)); + +static const struct sm_object dram_vpp = SM_DECLARE_NUMBER({ + .opt_name = "dram_vpp", + .ui_name = "DRAM VPP Voltage", + .ui_helptext = "Configure DRAM VPP Voltage. Unit is 1mV, 10mV step.", + .default_value = 2500, + .min = 1240, + .max = 3300, + .step = 10, +}, WITH_DEP_VALUES(&ram_ov_config, 1)); + +static struct sm_obj_form ram_ov = { + .ui_name = "RAM Overvolting (EXPERIMENTAL)\n" + "Changing options below may lead to system instability or CPU/RAM damage!\n" + "Use at your own responsibility", + .obj_list = (const struct sm_object *[]) { + &ram_ov_config, + &dram_volt, + &dram_vtt, + &dram_vpp, + NULL + }, +}; +#endif + +static struct sm_obj_form *sm_root[] = { + &cpu_features, + &pcie_features, + &cpu_power, + &cpu_oc, +#if CONFIG(BOARD_MSI_Z690_A_PRO_WIFI_DDR4) + &ram_ov, +#endif + NULL +}; + +void mb_cfr_setup_menu(struct lb_cfr *cfr_root) +{ + cfr_write_setup_menu(cfr_root, sm_root); +} diff --git a/src/mainboard/msi/ms7d25/gpio.h b/src/mainboard/msi/ms7d25/gpio.h index 2d7e4fbbada..e0eb432c54c 100644 --- a/src/mainboard/msi/ms7d25/gpio.h +++ b/src/mainboard/msi/ms7d25/gpio.h @@ -288,13 +288,13 @@ static const struct pad_config gpio_table[] = { PAD_CFG_GPI_TRIG_OWN(GPP_H18, NONE, PLTRST, OFF, ACPI), /* GPP_H19 - GPIO */ PAD_CFG_GPI_TRIG_OWN(GPP_H19, NONE, PLTRST, OFF, ACPI), - /* GPP_H20 - GPIO */ + /* GPP_H20 - GPIO - DEVICE EZ LED */ PAD_CFG_GPO(GPP_H20, 1, PLTRST), - /* GPP_H21 - GPIO */ + /* GPP_H21 - GPIO - CPU EZ LED */ PAD_CFG_GPO(GPP_H21, 0, PLTRST), - /* GPP_H22 - GPIO */ - PAD_CFG_GPO(GPP_H22, 1, PLTRST), - /* GPP_H23 - GPIO */ + /* GPP_H22 - GPIO - DRAM EZ LED */ + PAD_CFG_GPO(GPP_H22, 0, PLTRST), + /* GPP_H23 - GPIO - VGA EZ LED */ PAD_CFG_GPO(GPP_H23, 1, PLTRST), /* ------- GPIO Community 2 ------- */ diff --git a/src/mainboard/msi/ms7d25/mainboard.c b/src/mainboard/msi/ms7d25/mainboard.c index 527e0865bce..20daba2306c 100644 --- a/src/mainboard/msi/ms7d25/mainboard.c +++ b/src/mainboard/msi/ms7d25/mainboard.c @@ -1,20 +1,40 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include -#include +#include +#include #include #include +#include +#include #include #include #include #include #include -#define MSR_ATOM_TURBO_RATIO_LIMIT 0x650 -#define MSR_ATOM_TURBO_RATIO_LIMIT_CORES 0x651 -#define MSR_BIGCORE_TURBO_RATIO_LIMIT 0x1ad -#define MSR_BIGCORE_TURBO_RATIO_LIMIT_CORES 0x1ae +void fill_lb_gpios(struct lb_gpios *gpios) +{ + /* Pass the EZ LEDs to payload. We may need to turn off VGA LED there. */ + struct lb_gpio ez_debug_leds[] = { + { (uint32_t)gpio_dwx_address(GPP_H20), ACTIVE_LOW, 1, "EZ LED DEVICE" }, + { (uint32_t)gpio_dwx_address(GPP_H21), ACTIVE_HIGH, 0, "EZ LED CPU" }, + { (uint32_t)gpio_dwx_address(GPP_H22), ACTIVE_LOW, 1, "EZ LED DRAM" }, + { (uint32_t)gpio_dwx_address(GPP_H23), ACTIVE_LOW, 1, "EZ LED VGA" } + }; + lb_add_gpios(gpios, ez_debug_leds, ARRAY_SIZE(ez_debug_leds)); +} + +static void unset_device_ez_led(void *unused) +{ + /* + * Turn off the EZ LED DEVICE, at this point, coreboot/FSP have + * initialized the PCI devices. + */ + gpio_set(GPP_H20, 1); +} +BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, unset_device_ez_led, NULL); void mainboard_fill_fadt(acpi_fadt_t *fadt) { @@ -22,7 +42,6 @@ void mainboard_fill_fadt(acpi_fadt_t *fadt) fadt->iapc_boot_arch |= ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; } - static void mainboard_init(void *chip_info) { struct device *ps2_dev = dev_find_slot_pnp(0x4e, NCT6687D_KBC); @@ -32,48 +51,19 @@ static void mainboard_init(void *chip_info) printk(BIOS_DEBUG, "PS2 Controller state: %d\n", ps2_en); } -static void fill_turbo_ratio_limits(FSP_S_CONFIG *params) -{ - msr_t msr; - - msr = rdmsr(MSR_BIGCORE_TURBO_RATIO_LIMIT); - memcpy(¶ms->TurboRatioLimitRatio[0], &msr.lo, 4); - memcpy(¶ms->TurboRatioLimitRatio[4], &msr.hi, 4); - - msr = rdmsr(MSR_BIGCORE_TURBO_RATIO_LIMIT_CORES); - memcpy(¶ms->TurboRatioLimitNumCore[0], &msr.lo, 4); - memcpy(¶ms->TurboRatioLimitNumCore[4], &msr.hi, 4); - - msr = rdmsr(MSR_ATOM_TURBO_RATIO_LIMIT); - memcpy(¶ms->AtomTurboRatioLimitRatio[0], &msr.lo, 4); - memcpy(¶ms->AtomTurboRatioLimitRatio[4], &msr.hi, 4); - - msr = rdmsr(MSR_ATOM_TURBO_RATIO_LIMIT_CORES); - memcpy(¶ms->AtomTurboRatioLimitNumCore[0], &msr.lo, 4); - memcpy(¶ms->AtomTurboRatioLimitNumCore[4], &msr.hi, 4); -} - void mainboard_silicon_init_params(FSP_S_CONFIG *params) { - uint8_t aspm, aspm_l1; - - /* ASPM L1 sub-states require CLKREQ, so CLK_PM should be enabled as well */ - if (CONFIG(PCIEXP_L1_SUB_STATE) && CONFIG(PCIEXP_CLK_PM)) - aspm_l1 = 2; // 2 - L1.1 and L1.2 - else - aspm_l1 = 0; - - if (CONFIG(PCIEXP_ASPM)) { - aspm = CONFIG(PCIEXP_L1_SUB_STATE) ? 3 : 1; // 3 - L0sL1, 1 - L0s - } else { - aspm = 0; - aspm_l1 = 0; - } + /* + * Turn off the EZ LED DRAM, at this point, coreboot/FSP have + * initialized the memory and it should be working properly. + */ + gpio_set(GPP_H22, 1); - memset(params->PcieRpEnableCpm, 0, sizeof(params->PcieRpEnableCpm)); - memset(params->CpuPcieRpEnableCpm, 0, sizeof(params->CpuPcieRpEnableCpm)); - memset(params->CpuPcieClockGating, 0, sizeof(params->CpuPcieClockGating)); - memset(params->CpuPciePowerGating, 0, sizeof(params->CpuPciePowerGating)); + /* + * Turn on the EZ LED DEVICE, to indicate coreboot/FSP have + * started initializing devices. + */ + gpio_set(GPP_H20, 0); params->UsbPdoProgramming = 1; params->CpuPcieFiaProgramming = 1; @@ -110,33 +100,6 @@ void mainboard_silicon_init_params(FSP_S_CONFIG *params) params->PcieRpTransmitterHalfSwing[20] = 1; // M2_4 params->PcieRpTransmitterHalfSwing[24] = 1; // M2_2 - params->CpuPcieRpEnableCpm[0] = CONFIG(PCIEXP_CLK_PM); // M2_1 - params->CpuPcieRpEnableCpm[1] = CONFIG(PCIEXP_CLK_PM); // PCI_E1 - params->PcieRpEnableCpm[0] = CONFIG(PCIEXP_CLK_PM); // PCI_E2 - params->PcieRpEnableCpm[1] = CONFIG(PCIEXP_CLK_PM); // PCI_E4 - params->PcieRpEnableCpm[4] = CONFIG(PCIEXP_CLK_PM); // PCI_E3 - params->PcieRpEnableCpm[8] = CONFIG(PCIEXP_CLK_PM); // M2_3 - params->PcieRpEnableCpm[20] = CONFIG(PCIEXP_CLK_PM); // M2_4 - params->PcieRpEnableCpm[24] = CONFIG(PCIEXP_CLK_PM); // M2_2 - - params->CpuPcieRpL1Substates[0] = aspm_l1; // M2_1 - params->CpuPcieRpL1Substates[1] = aspm_l1; // PCI_E1 - params->PcieRpL1Substates[0] = aspm_l1; // PCI_E2 - params->PcieRpL1Substates[1] = aspm_l1; // PCI_E4 - params->PcieRpL1Substates[4] = aspm_l1; // PCI_E3 - params->PcieRpL1Substates[8] = aspm_l1; // M2_3 - params->PcieRpL1Substates[20] = aspm_l1; // M2_4 - params->PcieRpL1Substates[24] = aspm_l1; // M2_2 - - params->CpuPcieRpAspm[0] = aspm; // M2_1 - params->CpuPcieRpAspm[1] = aspm; // PCI_E1 - params->PcieRpAspm[0] = aspm; // PCI_E2 - params->PcieRpAspm[1] = aspm; // PCI_E4 - params->PcieRpAspm[4] = aspm; // PCI_E3 - params->PcieRpAspm[8] = aspm; // M2_3 - params->PcieRpAspm[20] = aspm; // M2_4 - params->PcieRpAspm[24] = aspm; // M2_2 - params->PcieRpAcsEnabled[0] = 1; // PCI_E2 params->PcieRpAcsEnabled[1] = 1; // PCI_E4 params->PcieRpAcsEnabled[2] = 1; // Ethernet @@ -145,15 +108,11 @@ void mainboard_silicon_init_params(FSP_S_CONFIG *params) params->PcieRpAcsEnabled[20] = 1; // M2_4 params->PcieRpAcsEnabled[24] = 1; // M2_2 - params->CpuPcieClockGating[0] = CONFIG(PCIEXP_CLK_PM); - params->CpuPciePowerGating[0] = CONFIG(PCIEXP_CLK_PM); params->CpuPcieRpMultiVcEnabled[0] = 1; params->CpuPcieRpPeerToPeerMode[0] = 1; params->CpuPcieRpMaxPayload[0] = 2; // 512B params->CpuPcieRpAcsEnabled[0] = 1; - params->CpuPcieClockGating[1] = CONFIG(PCIEXP_CLK_PM); - params->CpuPciePowerGating[1] = CONFIG(PCIEXP_CLK_PM); params->CpuPcieRpPeerToPeerMode[1] = 1; params->CpuPcieRpMaxPayload[1] = 2; // 512B params->CpuPcieRpAcsEnabled[1] = 1; @@ -161,12 +120,6 @@ void mainboard_silicon_init_params(FSP_S_CONFIG *params) params->SataPortsSolidStateDrive[6] = 1; // M2_3 params->SataPortsSolidStateDrive[7] = 1; // M2_4 params->SataLedEnable = 1; - - /* - * If OcLock is not set in FSP-M UPD, FSP-S UPD will take and program - * zeroed turbo ratio limits. Avoid this by populating defautl values here. - */ - fill_turbo_ratio_limits(params); } #if CONFIG(GENERATE_SMBIOS_TABLES) diff --git a/src/mainboard/msi/ms7d25/romstage_fsp_params.c b/src/mainboard/msi/ms7d25/romstage_fsp_params.c index f152de76b5f..7150626cf2f 100644 --- a/src/mainboard/msi/ms7d25/romstage_fsp_params.c +++ b/src/mainboard/msi/ms7d25/romstage_fsp_params.c @@ -1,13 +1,23 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include +#include +#include +#include #include +#include #include #include +#include +#include #include #include "gpio.h" +#define EC_IO_BASE 0xa20 + +#define NCT3933_DRAM_OV_ADDR 0x20 + #define FSP_CLK_NOTUSED 0xFF #define FSP_CLK_FREE_RUNNING 0x80 @@ -71,11 +81,188 @@ static void disable_pcie_clock_requests(FSP_M_CONFIG *m_cfg) gpio_configure_pads(clkreq_disabled_table, ARRAY_SIZE(clkreq_disabled_table)); } +static void set_dram_voltage(const struct nct3933_smbus_ops *ops, uint8_t addr, uint8_t reg, + uint16_t requested_mv, uint16_t default_mv) +{ + uint16_t current_mv; + uint8_t dac_val, direction; + int steps; + static const char * const voltages[] = { "", "VDD", "VTT", "VPP" }; + + if (nct3933_get_current_dac(ops, addr, reg, &dac_val)) { + printk(BIOS_ERR, "Failed to read current DRAM %s from NCT3933\n", voltages[reg]); + return; + } + + if ((dac_val == 0) && (requested_mv == default_mv)) { + printk(BIOS_ERR, "DRAM %s at standard default value\n", voltages[reg]); + return; + } + + if (dac_val & NCT3933_CURRENT_SOURCE) + current_mv = default_mv + (dac_val & NCT3933_CURRENT_VAL_MASK) * 10; + else + current_mv = default_mv - (dac_val & NCT3933_CURRENT_VAL_MASK) * 10; + + printk(BIOS_DEBUG, "Current DRAM %s: %u mV\n", voltages[reg], current_mv); + + /* Round up to 10mV */ + if (requested_mv % 10 >= 5) + requested_mv += 10 - (requested_mv % 10); + else + requested_mv -= (requested_mv % 10); + + if (requested_mv == current_mv) + return; + + if (current_mv > requested_mv) { + steps = (current_mv - requested_mv) / 10; + direction = 0; // decrementing + } else { + steps = (requested_mv - current_mv) / 10; + direction = 1; // incrementing + } + + for (int i = 0; i < steps; i++) { + if (direction) { + if ((dac_val & NCT3933_CURRENT_VAL_MASK) == NCT3933_CURRENT_VAL_MASK) + break; + + dac_val = (dac_val & NCT3933_CURRENT_VAL_MASK) + 1; + } else { + if ((dac_val & NCT3933_CURRENT_VAL_MASK) == 0) + break; + + dac_val = (dac_val & NCT3933_CURRENT_VAL_MASK) - 1; + } + + /* We are always ramping the voltage above default 1.2V or down to 1.2V */ + dac_val |= NCT3933_CURRENT_SOURCE; + + if (nct3933_set_current_dac(ops, addr, reg, dac_val)) + printk(BIOS_ERR, "Failed to set DRAM %s to %02x via NCT3933\n", + voltages[reg], dac_val); + + mdelay(1); + } + + if (!nct3933_get_current_dac(ops, addr, reg, &dac_val)) { + if (dac_val & NCT3933_CURRENT_SOURCE) + current_mv = default_mv + (dac_val & NCT3933_CURRENT_VAL_MASK) * 10; + else + current_mv = default_mv - (dac_val & NCT3933_CURRENT_VAL_MASK) * 10; + + printk(BIOS_DEBUG, "DRAM %s set to %u mV\n", voltages[reg], current_mv); + } +} + +static void boost_ddr4_dram_voltage(uint16_t requested_voltage) +{ + static const struct nct3933_smbus_ops ops = { + .read_byte = nct6687d_smbus_read_byte, + .write_byte = nct6687d_smbus_write_byte + }; + + bool ram_ov_manual = get_uint_option("ram_ov_config", 0); + + nct6687d_smbus_init(EC_IO_BASE); + + if (nct3933_probe(&ops, NCT3933_DRAM_OV_ADDR)) { + printk(BIOS_ERR, "NCT3933 for DRAM OV not found\n" + "Will not overvolt the memory\n"); + return; + } + + if (!ram_ov_manual) { + /* OUT1 is used for DRAM VDD OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(1), + requested_voltage, 1200); + + /* OUT2 is used for DRAM VTT OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(2), + requested_voltage / 2, 600); + + /* OUT3 is used for DRAM VPP OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(3), + MIN(requested_voltage, 3300), 2500); + } else { + requested_voltage = get_uint_option("dram_voltage", 1200); + /* OUT1 is used for DRAM VDD OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(1), + requested_voltage, 1200); + + requested_voltage = get_uint_option("dram_vtt", 600); + /* OUT2 is used for DRAM VTT OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(2), + requested_voltage / 2, 600); + + requested_voltage = get_uint_option("dram_vpp", 2500); + /* OUT3 is used for DRAM VPP OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(3), + MIN(requested_voltage, 3300), 2500); + } +} + +static void check_ddr4_xmp_valid(FSPM_UPD *memupd) +{ + int ret = 0; + uint16_t requested_voltage = 1200; // DDR4 default 1.2V + enum ddr4_xmp_profile profile; + struct dimm_attr_ddr4_st dimm[4]; + struct spd_block blk = { + .addr_map = { 0x50, 0x51, 0x52, 0x53, }, + }; + + if (memupd->FspmConfig.SpdProfileSelected == 2) { // XMP1 + profile = DDR4_XMP_PROFILE_1; + } else if (memupd->FspmConfig.SpdProfileSelected == 3) { // XMP2 + profile = DDR4_XMP_PROFILE_2; + } else { + /* XMP3 and user profiles not available on DDR4 */ + if (memupd->FspmConfig.SpdProfileSelected > 3) + memupd->FspmConfig.SpdProfileSelected = 0; + + boost_ddr4_dram_voltage(requested_voltage); + return; + } + + get_spd_smbus(&blk); + + if (blk.spd_array[0] == NULL && blk.spd_array[1] == NULL && + blk.spd_array[2] == NULL && blk.spd_array[3] == NULL) + die("DRAM SPD not found!\n"); + + for (int i = 0; i < 4; i++) { + if (blk.spd_array[i] == NULL) + continue; + + ret = spd_xmp_decode_ddr4(&dimm[i], blk.spd_array[i], profile); + if (ret) + break; + + /* Take the maximum of all DIMM voltages */ + requested_voltage = MAX(requested_voltage, dimm[i].vdd_voltage); + } + + /* If any error occurred when parsing, revert to JEDEC standard profile */ + if (ret != 0) { + printk(BIOS_ERR, "An error occurred when parsing XMP profile," + " reverting to standard JEDEC profile\n"); + memupd->FspmConfig.SpdProfileSelected = 0; + requested_voltage = 1200; + } else { + /* Do not exceed 1.5V */ + requested_voltage = MIN(requested_voltage, 1500); + memupd->FspmConfig.VddVoltage = requested_voltage; + } + + boost_ddr4_dram_voltage(requested_voltage); +} + void mainboard_memory_init_params(FSPM_UPD *memupd) { - memupd->FspmConfig.CpuPcieRpClockReqMsgEnable[0] = CONFIG(PCIEXP_CLK_PM); - memupd->FspmConfig.CpuPcieRpClockReqMsgEnable[1] = CONFIG(PCIEXP_CLK_PM); - memupd->FspmConfig.CpuPcieRpClockReqMsgEnable[2] = CONFIG(PCIEXP_CLK_PM); + bool pciexp_clk_pm = get_uint_option("pciexp_clk_pm", CONFIG(PCIEXP_CLK_PM)); + memupd->FspmConfig.DmiMaxLinkSpeed = 4; // Gen4 speed, undocumented memupd->FspmConfig.DmiAspm = 0; memupd->FspmConfig.DmiAspmCtrl = 0; @@ -85,18 +272,17 @@ void mainboard_memory_init_params(FSPM_UPD *memupd) memupd->FspmConfig.PchHdaSdiEnable[0] = 1; memupd->FspmConfig.MmioSize = 0xb00; /* 2.75GB in MB */ + memupd->FspmConfig.SpdProfileSelected = get_uint_option("spd_mem_profile", 0); - memupd->FspmConfig.OcLock = 0; - - memupd->FspmConfig.SpdProfileSelected = dasharo_get_memory_profile(); - - if (CONFIG(BOARD_MSI_Z690_A_PRO_WIFI_DDR4)) + if (CONFIG(BOARD_MSI_Z690_A_PRO_WIFI_DDR4)) { + check_ddr4_xmp_valid(memupd); memcfg_init(memupd, &ddr4_mem_config, &dimm_module_spd_info, false); + } if (CONFIG(BOARD_MSI_Z690_A_PRO_WIFI_DDR5)) memcfg_init(memupd, &ddr5_mem_config, &dimm_module_spd_info, false); gpio_configure_pads(gpio_table, ARRAY_SIZE(gpio_table)); - if (!CONFIG(PCIEXP_CLK_PM)) + if (!pciexp_clk_pm) disable_pcie_clock_requests(&memupd->FspmConfig); } diff --git a/src/mainboard/msi/ms7d25/smihandler.c b/src/mainboard/msi/ms7d25/smihandler.c index 3978d4fcef1..91b8908c322 100644 --- a/src/mainboard/msi/ms7d25/smihandler.c +++ b/src/mainboard/msi/ms7d25/smihandler.c @@ -3,6 +3,7 @@ #include #include #include +#include #define POWER_DEV PNP_DEV(0x4e, NCT6687D_SLEEP_PWR) #define ACPI_DEV PNP_DEV(0x4e, NCT6687D_ACPI) @@ -10,6 +11,8 @@ #define NUVOTON_ENTRY_KEY 0x87 #define NUVOTON_EXIT_KEY 0xAA +#define EC_IO_BASE 0xa20 + static void nuvoton_pnp_enter_conf_state(pnp_devfn_t dev) { u16 port = dev >> 8; @@ -52,6 +55,8 @@ void mainboard_smi_sleep(u8 slp_typ) pnp_write_config(POWER_DEV, 0xe7, 0x88); /* Set AUTO_EN */ pnp_write_config(POWER_DEV, 0xe8, 0x07); /* LED to low */ disable_ps2_wake(); + /* Disable USB port power */ + nct6687d_ec_and_or_page(EC_IO_BASE, 0, 0x3d, 0xbf, 0x00); break; } diff --git a/src/mainboard/msi/ms7e06/Kconfig b/src/mainboard/msi/ms7e06/Kconfig index 6fc99feec76..14ad0ef4381 100644 --- a/src/mainboard/msi/ms7e06/Kconfig +++ b/src/mainboard/msi/ms7e06/Kconfig @@ -2,9 +2,11 @@ config BOARD_MSI_Z790_P_PRO_WIFI_DDR4 select BOARD_MSI_MS7E06 + select DRAM_SUPPORT_DDR4 config BOARD_MSI_Z790_P_PRO_WIFI_DDR5 select BOARD_MSI_MS7E06 + select DRAM_SUPPORT_DDR5 config BOARD_MSI_MS7E06 def_bool n @@ -13,6 +15,7 @@ config BOARD_MSI_MS7E06 select BOARD_ROMSIZE_KB_32768 select SOC_INTEL_COMMON_BLOCK_HDA_VERB select SUPERIO_NUVOTON_NCT6687D + select DRIVERS_NUVOTON_NCT3933 select DRIVERS_UART_8250IO select HAVE_ACPI_RESUME select HAVE_ACPI_TABLES diff --git a/src/mainboard/msi/ms7e06/Makefile.mk b/src/mainboard/msi/ms7e06/Makefile.mk index 364196ef067..e4e1bf6c91d 100644 --- a/src/mainboard/msi/ms7e06/Makefile.mk +++ b/src/mainboard/msi/ms7e06/Makefile.mk @@ -7,6 +7,7 @@ bootblock-y += msi_id.S romstage-y += romstage_fsp_params.c +ramstage-$(CONFIG_DRIVERS_OPTION_CFR) += cfr.c ramstage-y += mainboard.c ramstage-y += smbios.c ramstage-$(CONFIG_STM) += stm.c diff --git a/src/mainboard/msi/ms7e06/cfr.c b/src/mainboard/msi/ms7e06/cfr.c new file mode 100644 index 00000000000..6acaff3391f --- /dev/null +++ b/src/mainboard/msi/ms7e06/cfr.c @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include + +static struct sm_obj_form cpu_features = { + .ui_name = "CPU Features", + .obj_list = (const struct sm_object *[]) { + &igd_enabled, + &vtd, + &vmx, + NULL + }, +}; + +static struct sm_obj_form pcie_features = { + .ui_name = "PCI Express", + .obj_list = (const struct sm_object *[]) { + &pciexp_speed, + &pciexp_aspm, + &pciexp_aspm_cpu, + &pciexp_clk_pm, + &pciexp_l1ss, + NULL + }, +}; + +static struct sm_obj_form cpu_power = { + .ui_name = "CPU Power and Performance", + .obj_list = (const struct sm_object *[]) { +#if !CONFIG(SOC_INTEL_DISABLE_POWER_LIMITS) + &pl1_override, + &pl1_time, + &pl2_override, + &pl4_override, +#endif + &pcore_turbo_ratio_group0, + &pcore_turbo_ratio_limit0, + &pcore_turbo_ratio_group1, + &pcore_turbo_ratio_limit1, + &pcore_turbo_ratio_group2, + &pcore_turbo_ratio_limit2, + &pcore_turbo_ratio_group3, + &pcore_turbo_ratio_limit3, + &pcore_turbo_ratio_group4, + &pcore_turbo_ratio_limit4, + &pcore_turbo_ratio_group5, + &pcore_turbo_ratio_limit5, + &pcore_turbo_ratio_group6, + &pcore_turbo_ratio_limit6, + &pcore_turbo_ratio_group7, + &pcore_turbo_ratio_limit7, + &ecore_turbo_ratio_group0, + &ecore_turbo_ratio_limit0, + &ecore_turbo_ratio_group1, + &ecore_turbo_ratio_limit1, + &ecore_turbo_ratio_group2, + &ecore_turbo_ratio_limit2, + &ecore_turbo_ratio_group3, + &ecore_turbo_ratio_limit3, + &ecore_turbo_ratio_group4, + &ecore_turbo_ratio_limit4, + &ecore_turbo_ratio_group5, + &ecore_turbo_ratio_limit5, + &ecore_turbo_ratio_group6, + &ecore_turbo_ratio_limit6, + &ecore_turbo_ratio_group7, + &ecore_turbo_ratio_limit7, + NULL + }, +}; + +static const struct sm_object spd_mem_profile = SM_DECLARE_ENUM({ + .opt_name = "spd_mem_profile", + .ui_name = "Memory SPD Profile", + .ui_helptext = "This option selects memory profile applied to RAM modules.\n", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + {"JEDEC (safe non-overclocked default)", 0 }, + {"XMP#1 (predefined extreme memory profile)", 2 }, + {"XMP#2 (predefined extreme memory profile)", 3 }, +#if CONFIG(BOARD_MSI_Z790_P_PRO_WIFI_DDR5) + {"XMP#3 (predefined extreme memory profile)", 4 }, +#endif + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static struct sm_obj_form cpu_oc = { + .ui_name = "CPU Overclocking (EXPERIMENTAL)\n" + "Changing options below may lead to system instability or CPU damage!\n" + "Use at your own responsibility", + .obj_list = (const struct sm_object *[]) { + &oc_support, + &oc_lock, + &spd_mem_profile, + &core_volt_mode, + &core_volt_ovr, + &core_volt_adapt, + &core_volt_off, + &core_volt_off_sign, + &atom_core_volt_mode, + &atom_core_volt_ovr, + &atom_core_volt_adapt, + &atom_core_volt_off, + &atom_core_volt_off_sign, + >_volt_mode, + >_volt_ovr, + >_volt_adapt, + >_volt_off, + >_volt_off_sign, + &ring_downbin, + &undervolt_protection, + &ia_cep, + >_cep, + &ia_vr_config, + &ia_ac_ll, + &ia_dc_ll, + &ia_vr_vlimit, + >_vr_config, + >_ac_ll, + >_dc_ll, + >_vr_vlimit, + NULL + }, +}; + +#if CONFIG(BOARD_MSI_Z790_P_PRO_WIFI_DDR4) +static const struct sm_object ram_ov_config = SM_DECLARE_ENUM({ + .opt_name = "ram_ov_config", + .ui_name = "RAM Overvolting", + .ui_helptext = "Enable or disable the RAM Overvolting.\n\n" + "By default RAM voltage will be set according to selected Memory SPD Profile", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + { "Use voltage from Memory SPD profile", 0 }, + { "Manual ", 1 }, + SM_ENUM_VALUE_END }, +}); + +static const struct sm_object dram_volt = SM_DECLARE_NUMBER({ + .opt_name = "dram_voltage", + .ui_name = "DRAM Voltage", + .ui_helptext = "Configure DRAM Voltage. Unit is 1mV, 10mV step.", + .default_value = 1200, + .min = 850, + .max = 2200, + .step = 10, +}, WITH_DEP_VALUES(&ram_ov_config, 1)); + +static const struct sm_object dram_vtt = SM_DECLARE_NUMBER({ + .opt_name = "dram_vtt", + .ui_name = "DRAM VTT Voltage", + .ui_helptext = "Configure DRAM VTT Voltage. Unit is 1mV, 10mV step.", + .default_value = 600, + .min = 120, + .max = 1100, + .step = 10, +}, WITH_DEP_VALUES(&ram_ov_config, 1)); + +static const struct sm_object dram_vpp = SM_DECLARE_NUMBER({ + .opt_name = "dram_vpp", + .ui_name = "DRAM VPP Voltage", + .ui_helptext = "Configure DRAM VPP Voltage. Unit is 1mV, 10mV step.", + .default_value = 2500, + .min = 1240, + .max = 3300, + .step = 10, +}, WITH_DEP_VALUES(&ram_ov_config, 1)); + +static struct sm_obj_form ram_ov = { + .ui_name = "RAM Overvolting (EXPERIMENTAL)\n" + "Changing options below may lead to system instability or CPU/RAM damage!\n" + "Use at your own responsibility", + .obj_list = (const struct sm_object *[]) { + &ram_ov_config, + &dram_volt, + &dram_vtt, + &dram_vpp, + NULL + }, +}; +#endif + +static struct sm_obj_form *sm_root[] = { + &cpu_features, + &pcie_features, + &cpu_power, + &cpu_oc, +#if CONFIG(BOARD_MSI_Z790_P_PRO_WIFI_DDR4) + &ram_ov, +#endif + NULL +}; + +void mb_cfr_setup_menu(struct lb_cfr *cfr_root) +{ + cfr_write_setup_menu(cfr_root, sm_root); +} diff --git a/src/mainboard/msi/ms7e06/gpio.h b/src/mainboard/msi/ms7e06/gpio.h index 2014fa8ef80..15893b0ac91 100644 --- a/src/mainboard/msi/ms7e06/gpio.h +++ b/src/mainboard/msi/ms7e06/gpio.h @@ -288,13 +288,13 @@ static const struct pad_config gpio_table[] = { PAD_CFG_GPI_TRIG_OWN(GPP_H18, NONE, PLTRST, OFF, ACPI), /* GPP_H19 - GPIO */ PAD_CFG_GPI_TRIG_OWN(GPP_H19, NONE, PLTRST, OFF, ACPI), - /* GPP_H20 - GPIO */ + /* GPP_H20 - GPIO - DEVICE EZ LED */ PAD_CFG_GPO(GPP_H20, 1, PLTRST), - /* GPP_H21 - GPIO */ + /* GPP_H21 - GPIO - CPU EZ LED */ PAD_CFG_GPO(GPP_H21, 0, PLTRST), - /* GPP_H22 - GPIO */ - PAD_CFG_GPO(GPP_H22, 1, PLTRST), - /* GPP_H23 - GPIO */ + /* GPP_H22 - GPIO - DRAM EZ LED */ + PAD_CFG_GPO(GPP_H22, 0, PLTRST), + /* GPP_H23 - GPIO - VGA EZ LED */ PAD_CFG_GPO(GPP_H23, 1, PLTRST), /* ------- GPIO Community 2 ------- */ diff --git a/src/mainboard/msi/ms7e06/mainboard.c b/src/mainboard/msi/ms7e06/mainboard.c index be30b6fbabf..20daba2306c 100644 --- a/src/mainboard/msi/ms7e06/mainboard.c +++ b/src/mainboard/msi/ms7e06/mainboard.c @@ -1,21 +1,40 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include -#include +#include +#include #include #include +#include +#include #include #include #include #include #include +void fill_lb_gpios(struct lb_gpios *gpios) +{ + /* Pass the EZ LEDs to payload. We may need to turn off VGA LED there. */ + struct lb_gpio ez_debug_leds[] = { + { (uint32_t)gpio_dwx_address(GPP_H20), ACTIVE_LOW, 1, "EZ LED DEVICE" }, + { (uint32_t)gpio_dwx_address(GPP_H21), ACTIVE_HIGH, 0, "EZ LED CPU" }, + { (uint32_t)gpio_dwx_address(GPP_H22), ACTIVE_LOW, 1, "EZ LED DRAM" }, + { (uint32_t)gpio_dwx_address(GPP_H23), ACTIVE_LOW, 1, "EZ LED VGA" } + }; + lb_add_gpios(gpios, ez_debug_leds, ARRAY_SIZE(ez_debug_leds)); +} -#define MSR_ATOM_TURBO_RATIO_LIMIT 0x650 -#define MSR_ATOM_TURBO_RATIO_LIMIT_CORES 0x651 -#define MSR_BIGCORE_TURBO_RATIO_LIMIT 0x1ad -#define MSR_BIGCORE_TURBO_RATIO_LIMIT_CORES 0x1ae +static void unset_device_ez_led(void *unused) +{ + /* + * Turn off the EZ LED DEVICE, at this point, coreboot/FSP have + * initialized the PCI devices. + */ + gpio_set(GPP_H20, 1); +} +BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, unset_device_ez_led, NULL); void mainboard_fill_fadt(acpi_fadt_t *fadt) { @@ -32,47 +51,19 @@ static void mainboard_init(void *chip_info) printk(BIOS_DEBUG, "PS2 Controller state: %d\n", ps2_en); } -static void fill_turbo_ratio_limits(FSP_S_CONFIG *params) -{ - msr_t msr; - - msr = rdmsr(MSR_BIGCORE_TURBO_RATIO_LIMIT); - memcpy(¶ms->TurboRatioLimitRatio[0], &msr.lo, 4); - memcpy(¶ms->TurboRatioLimitRatio[4], &msr.hi, 4); - - msr = rdmsr(MSR_BIGCORE_TURBO_RATIO_LIMIT_CORES); - memcpy(¶ms->TurboRatioLimitNumCore[0], &msr.lo, 4); - memcpy(¶ms->TurboRatioLimitNumCore[4], &msr.hi, 4); - - msr = rdmsr(MSR_ATOM_TURBO_RATIO_LIMIT); - memcpy(¶ms->AtomTurboRatioLimitRatio[0], &msr.lo, 4); - memcpy(¶ms->AtomTurboRatioLimitRatio[4], &msr.hi, 4); - - msr = rdmsr(MSR_ATOM_TURBO_RATIO_LIMIT_CORES); - memcpy(¶ms->AtomTurboRatioLimitNumCore[0], &msr.lo, 4); - memcpy(¶ms->AtomTurboRatioLimitNumCore[4], &msr.hi, 4); -} - void mainboard_silicon_init_params(FSP_S_CONFIG *params) { - uint8_t aspm, aspm_l1; - - if (CONFIG(PCIEXP_L1_SUB_STATE) && CONFIG(PCIEXP_CLK_PM)) - aspm_l1 = 2; // 2 - L1.1 and L1.2 - else - aspm_l1 = 0; - - if (CONFIG(PCIEXP_ASPM)) { - aspm = CONFIG(PCIEXP_L1_SUB_STATE) ? 3 : 1; // 3 - L0sL1, 1 - L0s - } else { - aspm = 0; - aspm_l1 = 0; - } + /* + * Turn off the EZ LED DRAM, at this point, coreboot/FSP have + * initialized the memory and it should be working properly. + */ + gpio_set(GPP_H22, 1); - memset(params->PcieRpEnableCpm, 0, sizeof(params->PcieRpEnableCpm)); - memset(params->CpuPcieRpEnableCpm, 0, sizeof(params->CpuPcieRpEnableCpm)); - memset(params->CpuPcieClockGating, 0, sizeof(params->CpuPcieClockGating)); - memset(params->CpuPciePowerGating, 0, sizeof(params->CpuPciePowerGating)); + /* + * Turn on the EZ LED DEVICE, to indicate coreboot/FSP have + * started initializing devices. + */ + gpio_set(GPP_H20, 0); params->UsbPdoProgramming = 1; params->CpuPcieFiaProgramming = 1; @@ -109,33 +100,6 @@ void mainboard_silicon_init_params(FSP_S_CONFIG *params) params->PcieRpTransmitterHalfSwing[20] = 1; // M2_4 params->PcieRpTransmitterHalfSwing[24] = 1; // M2_2 - params->CpuPcieRpEnableCpm[0] = CONFIG(PCIEXP_CLK_PM); // M2_1 - params->CpuPcieRpEnableCpm[1] = CONFIG(PCIEXP_CLK_PM); // PCI_E1 - params->PcieRpEnableCpm[0] = CONFIG(PCIEXP_CLK_PM); // PCI_E2 - params->PcieRpEnableCpm[1] = CONFIG(PCIEXP_CLK_PM); // PCI_E4 - params->PcieRpEnableCpm[4] = CONFIG(PCIEXP_CLK_PM); // PCI_E3 - params->PcieRpEnableCpm[8] = CONFIG(PCIEXP_CLK_PM); // M2_3 - params->PcieRpEnableCpm[20] = CONFIG(PCIEXP_CLK_PM); // M2_4 - params->PcieRpEnableCpm[24] = CONFIG(PCIEXP_CLK_PM); // M2_2 - - params->CpuPcieRpL1Substates[0] = aspm_l1; // M2_1 - params->CpuPcieRpL1Substates[1] = aspm_l1; // PCI_E1 - params->PcieRpL1Substates[0] = aspm_l1; // PCI_E2 - params->PcieRpL1Substates[1] = aspm_l1; // PCI_E4 - params->PcieRpL1Substates[4] = aspm_l1; // PCI_E3 - params->PcieRpL1Substates[8] = aspm_l1; // M2_3 - params->PcieRpL1Substates[20] = aspm_l1; // M2_4 - params->PcieRpL1Substates[24] = aspm_l1; // M2_2 - - params->CpuPcieRpAspm[0] = aspm; // M2_1 - params->CpuPcieRpAspm[1] = aspm; // PCI_E1 - params->PcieRpAspm[0] = aspm; // PCI_E2 - params->PcieRpAspm[1] = aspm; // PCI_E4 - params->PcieRpAspm[4] = aspm; // PCI_E3 - params->PcieRpAspm[8] = aspm; // M2_3 - params->PcieRpAspm[20] = aspm; // M2_4 - params->PcieRpAspm[24] = aspm; // M2_2 - params->PcieRpAcsEnabled[0] = 1; // PCI_E2 params->PcieRpAcsEnabled[1] = 1; // PCI_E4 params->PcieRpAcsEnabled[2] = 1; // Ethernet @@ -144,15 +108,11 @@ void mainboard_silicon_init_params(FSP_S_CONFIG *params) params->PcieRpAcsEnabled[20] = 1; // M2_4 params->PcieRpAcsEnabled[24] = 1; // M2_2 - params->CpuPcieClockGating[0] = CONFIG(PCIEXP_CLK_PM); - params->CpuPciePowerGating[0] = CONFIG(PCIEXP_CLK_PM); params->CpuPcieRpMultiVcEnabled[0] = 1; params->CpuPcieRpPeerToPeerMode[0] = 1; params->CpuPcieRpMaxPayload[0] = 2; // 512B params->CpuPcieRpAcsEnabled[0] = 1; - params->CpuPcieClockGating[1] = CONFIG(PCIEXP_CLK_PM); - params->CpuPciePowerGating[1] = CONFIG(PCIEXP_CLK_PM); params->CpuPcieRpPeerToPeerMode[1] = 1; params->CpuPcieRpMaxPayload[1] = 2; // 512B params->CpuPcieRpAcsEnabled[1] = 1; @@ -160,12 +120,6 @@ void mainboard_silicon_init_params(FSP_S_CONFIG *params) params->SataPortsSolidStateDrive[6] = 1; // M2_3 params->SataPortsSolidStateDrive[7] = 1; // M2_4 params->SataLedEnable = 1; - - /* - * If OcLock is not set in FSP-M UPD, FSP-S UPD will take and program - * zeroed turbo ratio limits. Avoid this by populating defautl values here. - */ - fill_turbo_ratio_limits(params); } #if CONFIG(GENERATE_SMBIOS_TABLES) diff --git a/src/mainboard/msi/ms7e06/romstage_fsp_params.c b/src/mainboard/msi/ms7e06/romstage_fsp_params.c index ff4e04abe3d..ec35a93d434 100644 --- a/src/mainboard/msi/ms7e06/romstage_fsp_params.c +++ b/src/mainboard/msi/ms7e06/romstage_fsp_params.c @@ -1,13 +1,23 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include +#include +#include +#include #include +#include #include #include +#include +#include #include #include "gpio.h" +#define EC_IO_BASE 0xa20 + +#define NCT3933_DRAM_OV_ADDR 0x20 + #define FSP_CLK_NOTUSED 0xFF #define FSP_CLK_FREE_RUNNING 0x80 @@ -57,6 +67,7 @@ static void disable_pcie_clock_requests(FSP_M_CONFIG *m_cfg) memset(m_cfg->PcieClkSrcUsage, FSP_CLK_NOTUSED, sizeof(m_cfg->PcieClkSrcUsage)); memset(m_cfg->PcieClkSrcClkReq, FSP_CLK_NOTUSED, sizeof(m_cfg->PcieClkSrcClkReq)); + /* PCIe CLK SRCes as per devicetree.cb */ m_cfg->PcieClkSrcUsage[0] = FSP_CLK_FREE_RUNNING; m_cfg->PcieClkSrcUsage[8] = FSP_CLK_FREE_RUNNING; m_cfg->PcieClkSrcUsage[9] = FSP_CLK_FREE_RUNNING; @@ -70,11 +81,188 @@ static void disable_pcie_clock_requests(FSP_M_CONFIG *m_cfg) gpio_configure_pads(clkreq_disabled_table, ARRAY_SIZE(clkreq_disabled_table)); } +static void set_dram_voltage(const struct nct3933_smbus_ops *ops, uint8_t addr, uint8_t reg, + uint16_t requested_mv, uint16_t default_mv) +{ + uint16_t current_mv; + uint8_t dac_val, direction; + int steps; + static const char * const voltages[] = { "", "VDD", "VTT", "VPP" }; + + if (nct3933_get_current_dac(ops, addr, reg, &dac_val)) { + printk(BIOS_ERR, "Failed to read current DRAM %s from NCT3933\n", voltages[reg]); + return; + } + + if ((dac_val == 0) && (requested_mv == default_mv)) { + printk(BIOS_ERR, "DRAM %s at standard default value\n", voltages[reg]); + return; + } + + if (dac_val & NCT3933_CURRENT_SOURCE) + current_mv = default_mv + (dac_val & NCT3933_CURRENT_VAL_MASK) * 10; + else + current_mv = default_mv - (dac_val & NCT3933_CURRENT_VAL_MASK) * 10; + + printk(BIOS_DEBUG, "Current DRAM %s: %u mV\n", voltages[reg], current_mv); + + /* Round up to 10mV */ + if (requested_mv % 10 >= 5) + requested_mv += 10 - (requested_mv % 10); + else + requested_mv -= (requested_mv % 10); + + if (requested_mv == current_mv) + return; + + if (current_mv > requested_mv) { + steps = (current_mv - requested_mv) / 10; + direction = 0; // decrementing + } else { + steps = (requested_mv - current_mv) / 10; + direction = 1; // incrementing + } + + for (int i = 0; i < steps; i++) { + if (direction) { + if ((dac_val & NCT3933_CURRENT_VAL_MASK) == NCT3933_CURRENT_VAL_MASK) + break; + + dac_val = (dac_val & NCT3933_CURRENT_VAL_MASK) + 1; + } else { + if ((dac_val & NCT3933_CURRENT_VAL_MASK) == 0) + break; + + dac_val = (dac_val & NCT3933_CURRENT_VAL_MASK) - 1; + } + + /* We are always ramping the voltage above default 1.2V or down to 1.2V */ + dac_val |= NCT3933_CURRENT_SOURCE; + + if (nct3933_set_current_dac(ops, addr, reg, dac_val)) + printk(BIOS_ERR, "Failed to set DRAM %s to %02x via NCT3933\n", + voltages[reg], dac_val); + + mdelay(1); + } + + if (!nct3933_get_current_dac(ops, addr, reg, &dac_val)) { + if (dac_val & NCT3933_CURRENT_SOURCE) + current_mv = default_mv + (dac_val & NCT3933_CURRENT_VAL_MASK) * 10; + else + current_mv = default_mv - (dac_val & NCT3933_CURRENT_VAL_MASK) * 10; + + printk(BIOS_DEBUG, "DRAM %s set to %u mV\n", voltages[reg], current_mv); + } +} + +static void boost_ddr4_dram_voltage(uint16_t requested_voltage) +{ + static const struct nct3933_smbus_ops ops = { + .read_byte = nct6687d_smbus_read_byte, + .write_byte = nct6687d_smbus_write_byte + }; + + bool ram_ov_manual = get_uint_option("ram_ov_config", 0); + + nct6687d_smbus_init(EC_IO_BASE); + + if (nct3933_probe(&ops, NCT3933_DRAM_OV_ADDR)) { + printk(BIOS_ERR, "NCT3933 for DRAM OV not found\n" + "Will not overvolt the memory\n"); + return; + } + + if (!ram_ov_manual) { + /* OUT1 is used for DRAM VDD OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(1), + requested_voltage, 1200); + + /* OUT2 is used for DRAM VTT OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(2), + requested_voltage / 2, 600); + + /* OUT3 is used for DRAM VPP OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(3), + MIN(requested_voltage, 3300), 2500); + } else { + requested_voltage = get_uint_option("dram_voltage", 1200); + /* OUT1 is used for DRAM VDD OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(1), + requested_voltage, 1200); + + requested_voltage = get_uint_option("dram_vtt", 600); + /* OUT2 is used for DRAM VTT OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(2), + requested_voltage / 2, 600); + + requested_voltage = get_uint_option("dram_vpp", 2500); + /* OUT3 is used for DRAM VPP OV */ + set_dram_voltage(&ops, NCT3933_DRAM_OV_ADDR, NCT3933_OUT_DAC_REG(3), + MIN(requested_voltage, 3300), 2500); + } +} + +static void check_ddr4_xmp_valid(FSPM_UPD *memupd) +{ + int ret = 0; + uint16_t requested_voltage = 1200; // DDR4 default 1.2V + enum ddr4_xmp_profile profile; + struct dimm_attr_ddr4_st dimm[4]; + struct spd_block blk = { + .addr_map = { 0x50, 0x51, 0x52, 0x53, }, + }; + + if (memupd->FspmConfig.SpdProfileSelected == 2) { // XMP1 + profile = DDR4_XMP_PROFILE_1; + } else if (memupd->FspmConfig.SpdProfileSelected == 3) { // XMP2 + profile = DDR4_XMP_PROFILE_2; + } else { + /* XMP3 and user profiles not available on DDR4 */ + if (memupd->FspmConfig.SpdProfileSelected > 3) + memupd->FspmConfig.SpdProfileSelected = 0; + + boost_ddr4_dram_voltage(requested_voltage); + return; + } + + get_spd_smbus(&blk); + + if (blk.spd_array[0] == NULL && blk.spd_array[1] == NULL && + blk.spd_array[2] == NULL && blk.spd_array[3] == NULL) + die("DRAM SPD not found!\n"); + + for (int i = 0; i < 4; i++) { + if (blk.spd_array[i] == NULL) + continue; + + ret = spd_xmp_decode_ddr4(&dimm[i], blk.spd_array[i], profile); + if (ret) + break; + + /* Take the maximum of all DIMM voltages */ + requested_voltage = MAX(requested_voltage, dimm[i].vdd_voltage); + } + + /* If any error occurred when parsing, revert to JEDEC standard profile */ + if (ret != 0) { + printk(BIOS_ERR, "An error occurred when parsing XMP profile," + " reverting to standard JEDEC profile\n"); + memupd->FspmConfig.SpdProfileSelected = 0; + requested_voltage = 1200; + } else { + /* Do not exceed 1.5V */ + requested_voltage = MIN(requested_voltage, 1500); + memupd->FspmConfig.VddVoltage = requested_voltage; + } + + boost_ddr4_dram_voltage(requested_voltage); +} + void mainboard_memory_init_params(FSPM_UPD *memupd) { - memupd->FspmConfig.CpuPcieRpClockReqMsgEnable[0] = CONFIG(PCIEXP_CLK_PM); - memupd->FspmConfig.CpuPcieRpClockReqMsgEnable[1] = CONFIG(PCIEXP_CLK_PM); - memupd->FspmConfig.CpuPcieRpClockReqMsgEnable[2] = CONFIG(PCIEXP_CLK_PM); + bool pciexp_clk_pm = get_uint_option("pciexp_clk_pm", CONFIG(PCIEXP_CLK_PM)); + memupd->FspmConfig.DmiMaxLinkSpeed = 4; // Gen4 speed, undocumented memupd->FspmConfig.DmiAspm = 0; memupd->FspmConfig.DmiAspmCtrl = 0; @@ -84,18 +272,17 @@ void mainboard_memory_init_params(FSPM_UPD *memupd) memupd->FspmConfig.PchHdaSdiEnable[0] = 1; memupd->FspmConfig.MmioSize = 0xb00; /* 2.75GB in MB */ + memupd->FspmConfig.SpdProfileSelected = get_uint_option("spd_mem_profile", 0); - memupd->FspmConfig.OcLock = 0; - - memupd->FspmConfig.SpdProfileSelected = dasharo_get_memory_profile(); - - if (CONFIG(BOARD_MSI_Z790_P_PRO_WIFI_DDR4)) + if (CONFIG(BOARD_MSI_Z790_P_PRO_WIFI_DDR4)) { + check_ddr4_xmp_valid(memupd); memcfg_init(memupd, &ddr4_mem_config, &dimm_module_spd_info, false); + } if (CONFIG(BOARD_MSI_Z790_P_PRO_WIFI_DDR5)) memcfg_init(memupd, &ddr5_mem_config, &dimm_module_spd_info, false); gpio_configure_pads(gpio_table, ARRAY_SIZE(gpio_table)); - if (!CONFIG(PCIEXP_CLK_PM)) + if (!pciexp_clk_pm) disable_pcie_clock_requests(&memupd->FspmConfig); } diff --git a/src/mainboard/msi/ms7e06/smihandler.c b/src/mainboard/msi/ms7e06/smihandler.c index 3978d4fcef1..91b8908c322 100644 --- a/src/mainboard/msi/ms7e06/smihandler.c +++ b/src/mainboard/msi/ms7e06/smihandler.c @@ -3,6 +3,7 @@ #include #include #include +#include #define POWER_DEV PNP_DEV(0x4e, NCT6687D_SLEEP_PWR) #define ACPI_DEV PNP_DEV(0x4e, NCT6687D_ACPI) @@ -10,6 +11,8 @@ #define NUVOTON_ENTRY_KEY 0x87 #define NUVOTON_EXIT_KEY 0xAA +#define EC_IO_BASE 0xa20 + static void nuvoton_pnp_enter_conf_state(pnp_devfn_t dev) { u16 port = dev >> 8; @@ -52,6 +55,8 @@ void mainboard_smi_sleep(u8 slp_typ) pnp_write_config(POWER_DEV, 0xe7, 0x88); /* Set AUTO_EN */ pnp_write_config(POWER_DEV, 0xe8, 0x07); /* LED to low */ disable_ps2_wake(); + /* Disable USB port power */ + nct6687d_ec_and_or_page(EC_IO_BASE, 0, 0x3d, 0xbf, 0x00); break; } diff --git a/src/soc/intel/alderlake/fsp_params.c b/src/soc/intel/alderlake/fsp_params.c index 5225c9f29a6..1a8c2159b51 100644 --- a/src/soc/intel/alderlake/fsp_params.c +++ b/src/soc/intel/alderlake/fsp_params.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1042,6 +1044,7 @@ static void fill_fsps_misc_power_params(FSP_S_CONFIG *s_cfg, const struct soc_intel_alderlake_config *config) { u32 cpu_id = cpu_get_cpuid(); + /* Skip setting D0I3 bit for all HECI devices */ s_cfg->DisableD0I3SettingForHeci = 1; /* @@ -1068,6 +1071,21 @@ static void fill_fsps_misc_power_params(FSP_S_CONFIG *s_cfg, for (size_t i = 0; i < ARRAY_SIZE(config->domain_vr_config); i++) fill_vr_domain_config(s_cfg, i, &config->domain_vr_config[i]); + s_cfg->VrConfigEnable[VR_DOMAIN_IA] = get_uint_option("ia_vr_config_enable", s_cfg->VrConfigEnable[VR_DOMAIN_IA]); + s_cfg->VrConfigEnable[VR_DOMAIN_GT] = get_uint_option("gt_vr_config_enable", s_cfg->VrConfigEnable[VR_DOMAIN_GT]); + + if (s_cfg->VrConfigEnable[VR_DOMAIN_IA]) { + s_cfg->AcLoadline[VR_DOMAIN_IA] = get_uint_option("ia_ac_ll", s_cfg->AcLoadline[VR_DOMAIN_IA]); + s_cfg->DcLoadline[VR_DOMAIN_IA] = get_uint_option("ia_dc_ll", s_cfg->DcLoadline[VR_DOMAIN_IA]); + s_cfg->VrVoltageLimit[VR_DOMAIN_IA] = get_uint_option("ia_vr_vlimit", s_cfg->VrVoltageLimit[VR_DOMAIN_IA]); + } + + if (s_cfg->VrConfigEnable[VR_DOMAIN_GT]) { + s_cfg->AcLoadline[VR_DOMAIN_GT] = get_uint_option("gt_ac_ll", s_cfg->AcLoadline[VR_DOMAIN_GT]); + s_cfg->DcLoadline[VR_DOMAIN_GT] = get_uint_option("gt_dc_ll", s_cfg->DcLoadline[VR_DOMAIN_GT]); + s_cfg->VrVoltageLimit[VR_DOMAIN_GT] = get_uint_option("gt_vr_vlimit", s_cfg->VrVoltageLimit[VR_DOMAIN_GT]); + } + s_cfg->PmcLpmS0ixSubStateEnableMask = get_supported_lpm_mask(); /* Apply minimum assertion width settings */ @@ -1127,6 +1145,67 @@ static void fill_fsps_misc_power_params(FSP_S_CONFIG *s_cfg, #endif } +static void fill_fsps_turbo_ratio_params(FSP_S_CONFIG *s_cfg, + const struct soc_intel_alderlake_config *config) +{ + uint8_t val; + char p_ratio_group_name[25] = "pcore_turbo_ratio_group0"; + char p_ratio_limit_name[25] = "pcore_turbo_ratio_limit0"; + char e_ratio_group_name[25] = "ecore_turbo_ratio_group0"; + char e_ratio_limit_name[25] = "ecore_turbo_ratio_limit0"; + size_t group_name_len = strlen(p_ratio_group_name); + size_t limit_name_len = strlen(p_ratio_limit_name); + uint8_t i; + msr_t msr; + + /* + * If OcLock is not set in FSP-M UPD, FSP-S UPD will take and program + * zeroed turbo ratio limits. Avoid this by populating default values here. + */ + msr = rdmsr(MSR_TURBO_RATIO_LIMIT); + memcpy(&s_cfg->TurboRatioLimitRatio[0], &msr.lo, 4); + memcpy(&s_cfg->TurboRatioLimitRatio[4], &msr.hi, 4); + + msr = rdmsr(MSR_TURBO_RATIO_LIMIT_CORES); + memcpy(&s_cfg->TurboRatioLimitNumCore[0], &msr.lo, 4); + memcpy(&s_cfg->TurboRatioLimitNumCore[4], &msr.hi, 4); + + msr = rdmsr(MSR_ATOM_TURBO_RATIO_LIMIT); + memcpy(&s_cfg->AtomTurboRatioLimitRatio[0], &msr.lo, 4); + memcpy(&s_cfg->AtomTurboRatioLimitRatio[4], &msr.hi, 4); + + msr = rdmsr(MSR_ATOM_TURBO_RATIO_LIMIT_CORES); + memcpy(&s_cfg->AtomTurboRatioLimitNumCore[0], &msr.lo, 4); + memcpy(&s_cfg->AtomTurboRatioLimitNumCore[4], &msr.hi, 4); + + for (i = 0; i < 8; i++) { + p_ratio_group_name[group_name_len - 1] = '0' + i; + p_ratio_limit_name[limit_name_len - 1] = '0' + i; + val = get_uint_option(p_ratio_limit_name, 0); + if (val != 0) + s_cfg->TurboRatioLimitRatio[i] = val; + + val = get_uint_option(p_ratio_group_name, 0); + if (val != 0) + s_cfg->TurboRatioLimitNumCore[i] = val; + } + + group_name_len = strlen(e_ratio_group_name); + limit_name_len = strlen(e_ratio_limit_name); + + for (i = 0; i < 8; i++) { + e_ratio_group_name[group_name_len - 1] = '0' + i; + e_ratio_limit_name[limit_name_len - 1] = '0' + i; + val = get_uint_option(e_ratio_limit_name, 0); + if (val != 0) + s_cfg->AtomTurboRatioLimitRatio[i] = val; + + val = get_uint_option(e_ratio_group_name, 0); + if (val != 0) + s_cfg->AtomTurboRatioLimitNumCore[i] = val; + } +} + static void fill_fsps_irq_params(FSP_S_CONFIG *s_cfg, const struct soc_intel_alderlake_config *config) { @@ -1324,6 +1403,7 @@ static void soc_silicon_init_params(FSP_S_CONFIG *s_cfg, fill_fsps_fivr_rfi_params, fill_fsps_acoustic_params, fill_fsps_pci_ssid_params, + fill_fsps_turbo_ratio_params, }; for (size_t i = 0; i < ARRAY_SIZE(fill_fsps_params); i++) diff --git a/src/soc/intel/alderlake/include/soc/cfr.h b/src/soc/intel/alderlake/include/soc/cfr.h index 1cacac618cc..5a4ffa86fc8 100644 --- a/src/soc/intel/alderlake/include/soc/cfr.h +++ b/src/soc/intel/alderlake/include/soc/cfr.h @@ -93,16 +93,669 @@ static const struct sm_object s0ix_enable = SM_DECLARE_ENUM({ SM_ENUM_VALUE_END }, }); +/* VMX */ +static const struct sm_object vmx = SM_DECLARE_ENUM({ + .opt_name = "vmx", + .ui_name = "Intel (VMX) Virtualization Technology", + .ui_helptext = "Enable or disable Intel VMX (VT-x virtualization extension)", + .default_value = CONFIG(ENABLE_VMX), + .values = (const struct sm_enum_value[]) { + { "Disabled", 0 }, + { "Enabled", 1 }, + SM_ENUM_VALUE_END }, +}); + /* VT-d */ static const struct sm_object vtd = SM_DECLARE_ENUM({ .opt_name = "vtd", .ui_name = "VT-d", - .ui_helptext = "Enable or disable Intel VT-d (virtualization)", + .ui_helptext = "Enable or disable Intel VT-d (IOMMU)", + .default_value = 1, + .values = (const struct sm_enum_value[]) { + { "Disabled", 0 }, + { "Enabled", 1 }, + SM_ENUM_VALUE_END }, +}); + +static const struct sm_object oc_lock = SM_DECLARE_ENUM({ + .opt_name = "oc_lock", + .ui_name = "OC Lock", + .ui_helptext = "Lock OC settings", + .default_value = 1, + .values = (const struct sm_enum_value[]) { + { "Disabled", 0 }, + { "Enabled", 1 }, + SM_ENUM_VALUE_END }, +}); + +static const struct sm_object oc_support = SM_DECLARE_ENUM({ + .opt_name = "oc_support", + .ui_name = "OC Support", + .ui_helptext = "Enable Overclocking support", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + { "Disabled", 0 }, + { "Enabled", 1 }, + SM_ENUM_VALUE_END }, +}); + +static const struct sm_object ia_vr_config = SM_DECLARE_ENUM({ + .opt_name = "ia_vr_config_enable", + .ui_name = "IA VR Configuration", + .ui_helptext = "Configure Core/IA VR settings. Disabled means use HW default", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + { "Disabled", 0 }, + { "Enabled", 1 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object ia_ac_ll = SM_DECLARE_NUMBER({ + .opt_name = "ia_ac_ll", + .ui_name = "IA AC LoadLine", + .ui_helptext = "Configure Core/IA AC Loadline. 0 means use HW default. Unit is 1/100 mOhms, e.g 1250 means 12.50 mOhms", + .default_value = 0, + .min = 0, + .max = 6249, + .step = 0, +}, WITH_DEP_VALUES(&ia_vr_config, 1)); + +static const struct sm_object ia_dc_ll = SM_DECLARE_NUMBER({ + .opt_name = "ia_dc_ll", + .ui_name = "IA DC LoadLine", + .ui_helptext = "Configure Core/IA DC Loadline. 0 means use HW default. Unit is 1/100 mOhms, e.g 1250 means 12.50 mOhms", + .default_value = 0, + .min = 0, + .max = 6249, + .step = 0, +}, WITH_DEP_VALUES(&ia_vr_config, 1)); + +static const struct sm_object ia_vr_vlimit = SM_DECLARE_NUMBER({ + .opt_name = "ia_vr_vlimit", + .ui_name = "IA VR Voltage Limit", + .ui_helptext = "Configure Core/IA VR Voltage Limit. 0 means use HW default. Unit is 1mV", + .default_value = 0, + .min = 0, + .max = 7999, + .step = 0, +}, WITH_DEP_VALUES(&ia_vr_config, 1)); + +static const struct sm_object gt_vr_config = SM_DECLARE_ENUM({ + .opt_name = "gt_vr_config_enable", + .ui_name = "GT VR Configuration", + .ui_helptext = "Configure GT VR settings. Disabled means use HW default", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + { "Disabled", 0 }, + { "Enabled", 1 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object gt_ac_ll = SM_DECLARE_NUMBER({ + .opt_name = "gt_ac_ll", + .ui_name = "GT AC LoadLine", + .ui_helptext = "Configure GT AC Loadline. 0 means use HW default. Unit is 1/100 mOhms, e.g 1250 means 12.50 mOhms", + .default_value = 0, + .min = 0, + .max = 6249, + .step = 0, +}, WITH_DEP_VALUES(>_vr_config, 1)); + +static const struct sm_object gt_dc_ll = SM_DECLARE_NUMBER({ + .opt_name = "gt_dc_ll", + .ui_name = "GT DC LoadLine", + .ui_helptext = "Configure GT DC Loadline. 0 means use HW default. Unit is 1/100 mOhms, e.g 1250 means 12.50 mOhms", + .default_value = 0, + .min = 0, + .max = 6249, + .step = 0, +}, WITH_DEP_VALUES(>_vr_config, 1)); + +static const struct sm_object gt_vr_vlimit = SM_DECLARE_NUMBER({ + .opt_name = "gt_vr_vlimit", + .ui_name = "GT VR Voltage Limit", + .ui_helptext = "Configure GT VR Voltage Limit. 0 means use HW default. Unit is 1mV", + .default_value = 0, + .min = 0, + .max = 7999, + .step = 0, +}, WITH_DEP_VALUES(>_vr_config, 1)); + +static const struct sm_object undervolt_protection = SM_DECLARE_ENUM({ + .opt_name = "undervolt_prot", + .ui_name = "Undervolt Protection", + .ui_helptext = "Enable Undervolt Protection", .default_value = 1, .values = (const struct sm_enum_value[]) { { "Disabled", 0 }, { "Enabled", 1 }, SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object ia_cep = SM_DECLARE_ENUM({ + .opt_name = "ia_cep", + .ui_name = "IA Current Excursion Protection (CEP)", + .ui_helptext = "Enable/disable IA Current Excursion Protection (CEP)", + .default_value = 1, + .values = (const struct sm_enum_value[]) { + { "Disabled", 0 }, + { "Enabled", 1 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object gt_cep = SM_DECLARE_ENUM({ + .opt_name = "gt_cep", + .ui_name = "GT Current Excursion Protection (CEP)", + .ui_helptext = "Enable/disable GT Current Excursion Protection (CEP)", + .default_value = 1, + .values = (const struct sm_enum_value[]) { + { "Disabled", 0 }, + { "Enabled", 1 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object ring_downbin = SM_DECLARE_ENUM({ + .opt_name = "ring_downbin", + .ui_name = "Rign Downbin", + .ui_helptext = "When enabled, the CPU will force the ring ratio to be lower than the core ratio.", + .default_value = 1, + .values = (const struct sm_enum_value[]) { + { "Disabled", 0 }, + { "Enabled", 1 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object pcore_turbo_ratio_group0 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_group0", + .ui_name = "P-core Turbo Ratio Limit Group 0", + .ui_helptext = "Performance-core Turbo Ratio Limit Group 0 defines the core range.\n\n" + "The turbo ratio is defined in P-core Turbo Ratio Limit Ratio 0.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_group1 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_group1", + .ui_name = "P-core Turbo Ratio Limit Group 1", + .ui_helptext = "Performance-core Turbo Ratio Limit Group 1 defines the core range.\n\n" + "The turbo ratio is defined in P-core Turbo Ratio Limit Ratio 1.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_group2 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_group2", + .ui_name = "P-core Turbo Ratio Limit Group 2", + .ui_helptext = "Performance-core Turbo Ratio Limit Group 2 defines the core range.\n\n" + "The turbo ratio is defined in P-core Turbo Ratio Limit Ratio 2.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_group3 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_group3", + .ui_name = "P-core Turbo Ratio Limit Group 3", + .ui_helptext = "Performance-core Turbo Ratio Limit Group 3 defines the core range.\n\n" + "The turbo ratio is defined in P-core Turbo Ratio Limit Ratio 3.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_group4 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_group4", + .ui_name = "P-core Turbo Ratio Limit Group 4", + .ui_helptext = "Performance-core Turbo Ratio Limit Group 4 defines the core range.\n\n" + "The turbo ratio is defined in P-core Turbo Ratio Limit Ratio 4.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_group5 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_group5", + .ui_name = "P-core Turbo Ratio Limit Group 5", + .ui_helptext = "Performance-core Turbo Ratio Limit Group 5 defines the core range.\n\n" + "The turbo ratio is defined in P-core Turbo Ratio Limit Ratio 5.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_group6 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_group6", + .ui_name = "P-core Turbo Ratio Limit Group 6", + .ui_helptext = "Performance-core Turbo Ratio Limit Group 6 defines the core range.\n\n" + "The turbo ratio is defined in P-core Turbo Ratio Limit Ratio 6.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_group7 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_group7", + .ui_name = "P-core Turbo Ratio Limit Group 7", + .ui_helptext = "Performance-core Turbo Ratio Limit Group 7 defines the core range.\n\n" + "The turbo ratio is defined in P-core Turbo Ratio Limit Ratio 7.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_limit0 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_limit0", + .ui_name = "P-core Turbo Ratio Limit Ratio 0", + .ui_helptext = "Performance-core Turbo Ratio Limit Ratio0 defines the turbo ratio.\n\n" + "The core range is defined in P-core Turbo Ratio Limit Group 0.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_limit1 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_limit1", + .ui_name = "P-core Turbo Ratio Limit Ratio 1", + .ui_helptext = "Performance-core Turbo Ratio Limit Ratio 1 defines the turbo ratio.\n\n" + "The core range is defined in P-core Turbo Ratio Limit Group 1.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_limit2 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_limit2", + .ui_name = "P-core Turbo Ratio Limit Ratio 2", + .ui_helptext = "Performance-core Turbo Ratio Limit Ratio 2 defines the turbo ratio.\n\n" + "The core range is defined in P-core Turbo Ratio Limit Group 2.", + .default_value = 0, + .min = 0, + .max = 255, }); +static const struct sm_object pcore_turbo_ratio_limit3 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_limit3", + .ui_name = "P-core Turbo Ratio Limit Ratio 3", + .ui_helptext = "Performance-core Turbo Ratio Limit Ratio 3 defines the turbo ratio.\n\n" + "The core range is defined in P-core Turbo Ratio Limit Group 3.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_limit4 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_limit4", + .ui_name = "P-core Turbo Ratio Limit Ratio 4", + .ui_helptext = "Performance-core Turbo Ratio Limit Ratio 4 defines the turbo ratio.\n\n" + "The core range is defined in P-core Turbo Ratio Limit Group 4.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_limit5 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_limit5", + .ui_name = "P-core Turbo Ratio Limit Ratio 5", + .ui_helptext = "Performance-core Turbo Ratio Limit Ratio 5 defines the turbo ratio.\n\n" + "The core range is defined in P-core Turbo Ratio Limit Group 5.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_limit6 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_limit6", + .ui_name = "P-core Turbo Ratio Limit Ratio 6", + .ui_helptext = "Performance-core Turbo Ratio Limit Ratio 6 defines the turbo ratio.\n\n" + "The core range is defined in P-core Turbo Ratio Limit Group 6.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object pcore_turbo_ratio_limit7 = SM_DECLARE_NUMBER({ + .opt_name = "pcore_turbo_ratio_limit7", + .ui_name = "P-core Turbo Ratio Limit Ratio 7", + .ui_helptext = "Performance-core Turbo Ratio Limit Ratio 7 defines the turbo ratio.\n\n" + "The core range is defined in P-core Turbo Ratio Limit Group 7.", + .default_value = 0, + .min = 0, + .max = 255, +}); + + +static const struct sm_object ecore_turbo_ratio_group0 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_group0", + .ui_name = "E-core Turbo Ratio Limit Group 0", + .ui_helptext = "Efficient-core Turbo Ratio Limit Group 0 defines the core range.\n\n" + "The turbo ratio is defined in E-coreTurbo Ratio Limit Ratio 0.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_group1 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_group1", + .ui_name = "E-core Turbo Ratio Limit Group 1", + .ui_helptext = "Efficient-core Turbo Ratio Limit Group 1 defines the core range.\n\n" + "The turbo ratio is defined in E-coreTurbo Ratio Limit Ratio 1.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_group2 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_group2", + .ui_name = "E-core Turbo Ratio Limit Group 2", + .ui_helptext = "Efficient-core Turbo Ratio Limit Group 2 defines the core range.\n\n" + "The turbo ratio is defined in E-coreTurbo Ratio Limit Ratio 2.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_group3 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_group3", + .ui_name = "E-core Turbo Ratio Limit Group 3", + .ui_helptext = "Efficient-core Turbo Ratio Limit Group 3 defines the core range.\n\n" + "The turbo ratio is defined in E-coreTurbo Ratio Limit Ratio 3.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_group4 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_group4", + .ui_name = "E-core Turbo Ratio Limit Group 4", + .ui_helptext = "Efficient-core Turbo Ratio Limit Group 4 defines the core range.\n\n" + "The turbo ratio is defined in E-coreTurbo Ratio Limit Ratio 4.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_group5 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_group5", + .ui_name = "E-core Turbo Ratio Limit Group 5", + .ui_helptext = "Efficient-core Turbo Ratio Limit Group 5 defines the core range.\n\n" + "The turbo ratio is defined in E-coreTurbo Ratio Limit Ratio 5.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_group6 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_group6", + .ui_name = "E-core Turbo Ratio Limit Group 6", + .ui_helptext = "Efficient-core Turbo Ratio Limit Group 6 defines the core range.\n\n" + "The turbo ratio is defined in E-coreTurbo Ratio Limit Ratio 6.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_group7 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_group7", + .ui_name = "E-core Turbo Ratio Limit Group 7", + .ui_helptext = "Efficient-core Turbo Ratio Limit Group 7 defines the core range.\n\n" + "The turbo ratio is defined in E-coreTurbo Ratio Limit Ratio 7.\n\n" + "If value is zero, this entry is ignored.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_limit0 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_limit0", + .ui_name = "E-core Turbo Ratio Limit Ratio 0", + .ui_helptext = "Efficient-core Turbo Ratio Limit Ratio0 defines the turbo ratio.\n\n" + "The core range is defined in E-core Turbo Ratio Limit Group 0.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_limit1 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_limit1", + .ui_name = "E-core Turbo Ratio Limit Ratio 1", + .ui_helptext = "Efficient-core Turbo Ratio Limit Ratio 1 defines the turbo ratio.\n\n" + "The core range is defined in E-core Turbo Ratio Limit Group 1.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_limit2 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_limit2", + .ui_name = "E-core Turbo Ratio Limit Ratio 2", + .ui_helptext = "Efficient-core Turbo Ratio Limit Ratio 2 defines the turbo ratio.\n\n" + "The core range is defined in E-core Turbo Ratio Limit Group 2.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_limit3 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_limit3", + .ui_name = "E-core Turbo Ratio Limit Ratio 3", + .ui_helptext = "Efficient-core Turbo Ratio Limit Ratio 3 defines the turbo ratio.\n\n" + "The core range is defined in E-core Turbo Ratio Limit Group 3.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_limit4 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_limit4", + .ui_name = "E-core Turbo Ratio Limit Ratio 4", + .ui_helptext = "Efficient-core Turbo Ratio Limit Ratio 4 defines the turbo ratio.\n\n" + "The core range is defined in E-core Turbo Ratio Limit Group 4.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_limit5 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_limit5", + .ui_name = "E-core Turbo Ratio Limit Ratio 5", + .ui_helptext = "Efficient-core Turbo Ratio Limit Ratio 5 defines the turbo ratio.\n\n" + "The core range is defined in E-core Turbo Ratio Limit Group 5.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_limit6 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_limit6", + .ui_name = "E-core Turbo Ratio Limit Ratio 6", + .ui_helptext = "Efficient-core Turbo Ratio Limit Ratio 6 defines the turbo ratio.\n\n" + "The core range is defined in E-core Turbo Ratio Limit Group 6.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object ecore_turbo_ratio_limit7 = SM_DECLARE_NUMBER({ + .opt_name = "ecore_turbo_ratio_limit7", + .ui_name = "E-core Turbo Ratio Limit Ratio 7", + .ui_helptext = "Efficient-core Turbo Ratio Limit Ratio 7 defines the turbo ratio.\n\n" + "The core range is defined in E-core Turbo Ratio Limit Group 7.", + .default_value = 0, + .min = 0, + .max = 255, +}); + +static const struct sm_object core_volt_mode = SM_DECLARE_ENUM({ + .opt_name = "core_volt_mode", + .ui_name = "Core Voltage Mode", + .ui_helptext = "Core Voltage mode", + .default_value = 2, + .values = (const struct sm_enum_value[]) { + { "Adaptive", 0 }, + { "Override", 1 }, + { "Auto", 2 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object core_volt_ovr = SM_DECLARE_NUMBER({ + .opt_name = "core_volt_ovr", + .ui_name = "Core Voltage Override", + .ui_helptext = "The core voltage override which is applied to the entire range of cpu core frequencies. Unit is mV", + .default_value = 0, + .min = 0, + .max = 2000, +}, WITH_DEP_VALUES(&core_volt_mode, 1)); + +static const struct sm_object core_volt_adapt = SM_DECLARE_NUMBER({ + .opt_name = "core_volt_adapt", + .ui_name = "Core Adaptive Voltage", + .ui_helptext = "Extra Turbo voltage applied to the cpu core when the cpu is operating in turbo mode. Unit is mV", + .default_value = 0, + .min = 0, + .max = 2000, +}, WITH_DEP_VALUES(&core_volt_mode, 0)); + +static const struct sm_object core_volt_off = SM_DECLARE_NUMBER({ + .opt_name = "core_volt_off", + .ui_name = "Core Voltage Offset", + .ui_helptext = "Core Voltage Offset applied on top of all other voltage modes.\n\n" + "This offset is applied over the entire frequency range. Unit is mV", + .default_value = 0, + .min = 0, + .max = 1000, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object core_volt_off_sign = SM_DECLARE_ENUM({ + .opt_name = "core_volt_off_sign", + .ui_name = "Core Voltage Offset Sign", + .ui_helptext = "Core Voltage Offset sign.\n\n" + "Negative means the offset will be subtracted from voltage, otherwise added.", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + { "Positive", 0 }, + { "Negative", 1 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object gt_volt_mode = SM_DECLARE_ENUM({ + .opt_name = "gt_volt_mode", + .ui_name = "GT Voltage Mode", + .ui_helptext = "GT Voltage mode", + .default_value = 2, + .values = (const struct sm_enum_value[]) { + { "Adaptive", 0 }, + { "Override", 1 }, + { "Auto", 2 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object gt_volt_ovr = SM_DECLARE_NUMBER({ + .opt_name = "gt_volt_ovr", + .ui_name = "GT Voltage Override", + .ui_helptext = "The gt voltage override which is applied to the entire range of GT frequencies. Unit is mV", + .default_value = 0, + .min = 0, + .max = 2000, +}, WITH_DEP_VALUES(>_volt_mode, 1)); + +static const struct sm_object gt_volt_adapt = SM_DECLARE_NUMBER({ + .opt_name = "gt_volt_adapt", + .ui_name = "GT Adaptive Voltage", + .ui_helptext = "Extra Turbo voltage applied to the GT when operating in turbo mode. Unit is mV", + .default_value = 0, + .min = 0, + .max = 2000, +}, WITH_DEP_VALUES(>_volt_mode, 0)); + +static const struct sm_object gt_volt_off = SM_DECLARE_NUMBER({ + .opt_name = "gt_volt_off", + .ui_name = "GT Voltage Offset", + .ui_helptext = "GT Voltage Offset applied on top of all other voltage modes.\n\n" + "This offset is applied over the entire frequency range. Unit is mV", + .default_value = 0, + .min = 0, + .max = 1000, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object gt_volt_off_sign = SM_DECLARE_ENUM({ + .opt_name = "gt_volt_off_sign", + .ui_name = "GT Voltage Offset Sign", + .ui_helptext = "GT Voltage Offset sign.\n\n" + "Negative means the offset will be subtracted from voltage, otherwise added.", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + { "Positive", 0 }, + { "Negative", 1 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object atom_core_volt_mode = SM_DECLARE_ENUM({ + .opt_name = "atom_core_volt_mode", + .ui_name = "Atom Core Voltage Mode", + .ui_helptext = "Atom Core Voltage mode", + .default_value = 2, + .values = (const struct sm_enum_value[]) { + { "Adaptive", 0 }, + { "Override", 1 }, + { "Auto", 2 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object atom_core_volt_ovr = SM_DECLARE_NUMBER({ + .opt_name = "atom_core_volt_ovr", + .ui_name = "Atom Core Voltage Override", + .ui_helptext = "The atom core voltage override which is applied to the entire range of cpu atom core frequencies. Unit is mV", + .default_value = 0, + .min = 0, + .max = 2000, +}, WITH_DEP_VALUES(&atom_core_volt_mode, 1)); + +static const struct sm_object atom_core_volt_adapt = SM_DECLARE_NUMBER({ + .opt_name = "atom_core_volt_adapt", + .ui_name = "Atom Core Adaptive Voltage", + .ui_helptext = "Extra Turbo voltage applied to the cpu atom core when the cpu is operating in turbo mode. Unit is mV", + .default_value = 0, + .min = 0, + .max = 2000, +}, WITH_DEP_VALUES(&atom_core_volt_mode, 0)); + +static const struct sm_object atom_core_volt_off = SM_DECLARE_NUMBER({ + .opt_name = "atom_core_volt_off", + .ui_name = "Atom Core Voltage Offset", + .ui_helptext = "Atom Core Voltage Offset applied on top of all other voltage modes.\n\n" + "This offset is applied over the entire frequency range. Unit is mV", + .default_value = 0, + .min = 0, + .max = 1000, +}, WITH_DEP_VALUES(&oc_support, 1)); + +static const struct sm_object atom_core_volt_off_sign = SM_DECLARE_ENUM({ + .opt_name = "atom_core_volt_off_sign", + .ui_name = "Atom Core Voltage Offset Sign", + .ui_helptext = "Atom Core Voltage Offset sign.\n\n" + "Negative means the offset will be subtracted from voltage, otherwise added.", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + { "Positive", 0 }, + { "Negative", 1 }, + SM_ENUM_VALUE_END }, +}, WITH_DEP_VALUES(&oc_support, 1)); + #endif /* _ALDERLAKE_CFR_H_ */ diff --git a/src/soc/intel/alderlake/romstage/fsp_params.c b/src/soc/intel/alderlake/romstage/fsp_params.c index 14d3ab9f025..d004f85f3c0 100644 --- a/src/soc/intel/alderlake/romstage/fsp_params.c +++ b/src/soc/intel/alderlake/romstage/fsp_params.c @@ -70,6 +70,13 @@ static void configure_cpu_rp_speed(FSP_M_CONFIG *m_cfg, index + 1, speeds[m_cfg->CpuPcieRpPcieSpeed[index]]); } +static void configure_cpu_rp_clkreq_msg(FSP_M_CONFIG *m_cfg, + const struct pcie_rp_config *cfg, + size_t index, bool enable) +{ + m_cfg->CpuPcieRpClockReqMsgEnable[index] = enable; +} + static void configure_rp_clocks(FSP_M_CONFIG *m_cfg, enum pcie_rp_type type, const struct pcie_rp_config *rp_cfg, size_t index) { @@ -105,12 +112,16 @@ static void configure_rp_clocks(FSP_M_CONFIG *m_cfg, enum pcie_rp_type type, static void pcie_rp_init(FSP_M_CONFIG *m_cfg, uint32_t en_mask, enum pcie_rp_type type, const struct pcie_rp_config *cfg, size_t cfg_count) { + bool pciexp_clk_pm = get_uint_option("pciexp_clk_pm", CONFIG(PCIEXP_CLK_PM)); + for (size_t i = 0; i < cfg_count; i++) { if (!(en_mask & BIT(i))) continue; configure_rp_clocks(m_cfg, type, &cfg[i], i); - if (type == PCIE_RP_CPU) + if (type == PCIE_RP_CPU) { configure_cpu_rp_speed(m_cfg, &cfg[i], i); + configure_cpu_rp_clkreq_msg(m_cfg, &cfg[i], i, pciexp_clk_pm); + } } } @@ -237,6 +248,55 @@ static void fill_fspm_cpu_params(FSP_M_CONFIG *m_cfg, /* Invalid setting, enable all E-cores */ m_cfg->ActiveSmallCoreCount = ALL_CORES_ACTIVE; } + + m_cfg->IaCepEnable = get_uint_option("ia_cep", m_cfg->IaCepEnable); + m_cfg->GtCepEnable = get_uint_option("gt_cep", m_cfg->GtCepEnable); + + m_cfg->OcLock = get_uint_option("oc_lock", m_cfg->OcLock); + m_cfg->OcSupport = get_uint_option("oc_support", m_cfg->OcSupport); + + if (m_cfg->OcSupport) { + m_cfg->CoreVoltageMode = get_uint_option("core_volt_mode", m_cfg->CoreVoltageMode); + m_cfg->AtomL2VoltageMode = get_uint_option("atom_core_volt_mode", m_cfg->AtomL2VoltageMode); + m_cfg->GtVoltageMode = get_uint_option("gt_volt_mode", m_cfg->GtVoltageMode); + + if (m_cfg->CoreVoltageMode == 0) /* Adaptive */ + m_cfg->CoreVoltageAdaptive = get_uint_option("core_volt_adapt", m_cfg->CoreVoltageAdaptive); + else if (m_cfg->CoreVoltageMode == 1) /* Override */ + m_cfg->CoreVoltageOverride = get_uint_option("core_volt_ovr", m_cfg->CoreVoltageOverride); + else if (m_cfg->CoreVoltageMode >= 2) /* Default: Adaptive, do not change any value */ + m_cfg->CoreVoltageMode = 0; + + m_cfg->CoreVoltageOffset = get_uint_option("core_volt_off", m_cfg->CoreVoltageOffset); + if (get_uint_option("core_volt_off_sign", 0) == 1) /* If negative, convert the value */ + m_cfg->CoreVoltageOffset = (int16_t)(~m_cfg->CoreVoltageOffset + 1); + + if (m_cfg->AtomL2VoltageMode == 0) /* Adaptive */ + m_cfg->AtomL2VoltageAdaptive = get_uint_option("atom_core_volt_adapt", m_cfg->AtomL2VoltageAdaptive); + else if (m_cfg->AtomL2VoltageMode == 1) /* Override */ + m_cfg->AtomL2VoltageOverride = get_uint_option("atom_core_volt_ovr", m_cfg->AtomL2VoltageOverride); + else if (m_cfg->AtomL2VoltageOverride >= 2) /* Default: Adaptive, do not change any value */ + m_cfg->AtomL2VoltageOverride = 0; + + m_cfg->AtomL2VoltageOffset = get_uint_option("atom_core_volt_off", m_cfg->AtomL2VoltageOffset); + if (get_uint_option("atom_core_volt_off_sign", 0) == 1) /* If negative, convert the value */ + m_cfg->AtomL2VoltageOffset = (int16_t)(~m_cfg->AtomL2VoltageOffset + 1); + + if (m_cfg->GtVoltageMode == 0) /* Adaptive */ + m_cfg->GtExtraTurboVoltage = get_uint_option("gt_volt_adapt", m_cfg->GtExtraTurboVoltage); + else if (m_cfg->GtVoltageMode == 1) /* Override */ + m_cfg->GtVoltageOverride = get_uint_option("gt_volt_ovr", m_cfg->GtVoltageOverride); + else if (m_cfg->GtVoltageOverride >= 2) /* Default: Adaptive, do not change any value */ + m_cfg->GtVoltageOverride = 0; + + m_cfg->GtVoltageOffset = get_uint_option("gt_volt_off", m_cfg->GtVoltageOffset); + if (get_uint_option("gt_volt_off_sign", 0) == 1) /* If negative, convert the value */ + m_cfg->GtVoltageOffset = (int16_t)(~m_cfg->GtVoltageOffset + 1); + + m_cfg->RingDownBin = get_uint_option("ring_downbin", m_cfg->RingDownBin); + m_cfg->UnderVoltProtection = get_uint_option("undervolt_prot", m_cfg->UnderVoltProtection); + } + } static void fill_fspm_security_params(FSP_M_CONFIG *m_cfg, @@ -405,7 +465,7 @@ static void fill_fspm_vtd_params(FSP_M_CONFIG *m_cfg, m_cfg->VtdBaseAddress[VTD_TBT3] = TBT3_BASE_ADDRESS; /* Change VmxEnable UPD value according to ENABLE_VMX Kconfig */ - m_cfg->VmxEnable = CONFIG(ENABLE_VMX); + m_cfg->VmxEnable = get_uint_option("vmx", CONFIG(ENABLE_VMX)); } static void fill_fspm_trace_params(FSP_M_CONFIG *m_cfg, diff --git a/src/soc/intel/common/block/include/intelblocks/cfr.h b/src/soc/intel/common/block/include/intelblocks/cfr.h index 7828e1f3597..585d5dcef18 100644 --- a/src/soc/intel/common/block/include/intelblocks/cfr.h +++ b/src/soc/intel/common/block/include/intelblocks/cfr.h @@ -133,4 +133,73 @@ static const struct sm_object pciexp_speed = SM_DECLARE_ENUM({ SM_ENUM_VALUE_END }, }); +#if !CONFIG(SOC_INTEL_DISABLE_POWER_LIMITS) + +static const struct sm_object pl1_override = SM_DECLARE_NUMBER({ + .opt_name = "pl1_override", + .ui_name = "Power Limit PL1", + .ui_helptext = "Power Limit 1 value in Watts. 0 means use the default HW value.", + .default_value = 0, + .min = 0, + .max = 32767, + .step = 1, +}); + +static const struct sm_object pl2_override = SM_DECLARE_NUMBER({ + .opt_name = "pl2_override", + .ui_name = "Power Limit PL2", + .ui_helptext = "Power Limit 2 value in Watts. 0 means use the default HW value.", + .default_value = 0, + .min = 0, + .max = 32767, + .step = 1, +}); + +static const struct sm_object pl4_override = SM_DECLARE_NUMBER({ + .opt_name = "tdp_pl4", + .ui_name = "Power Limit PL4", + .ui_helptext = "Power Limit 4 value in Watts. 0 means use the default HW value.", + .default_value = 0, + .min = 0, + .max = 32767, + .step = 1, +}); + +static const struct sm_object pl1_time = SM_DECLARE_ENUM({ + .opt_name = "pl1_time", + .ui_name = "Power Limit PL1 Time Window", + .ui_helptext = "Power Limit 1 Time Window value in seconds.\n\n" + "Auto means use the default HW value (28s Mobile and 56s Desktop).", + .default_value = 0, + .values = (const struct sm_enum_value[]) { + { "Auto", 0x00, }, + { "1s", 0x0a, }, + { "2s", 0x0b, }, + { "3s", 0x4b, }, + { "4s", 0x0c, }, + { "5s", 0x2c, }, + { "6s", 0x4c, }, + { "7s", 0x6c, }, + { "8s", 0x0d, }, + { "10s", 0x2d, }, + { "12s", 0x4d, }, + { "14s", 0x6d, }, + { "16s", 0x0e, }, + { "20s", 0x2e, }, + { "24s", 0x4e, }, + { "28s", 0x6e, }, + { "32s", 0x0f, }, + { "40s", 0x2f, }, + { "48s", 0x4f, }, + { "56s", 0x6f, }, + { "64s", 0x10, }, + { "80s", 0x30, }, + { "96s", 0x50, }, + { "112s", 0x70, }, + { "128s", 0x11, }, + SM_ENUM_VALUE_END }, +}); + +#endif + #endif /* SOC_INTEL_CMN_CFR_H */ diff --git a/src/soc/intel/common/block/include/intelblocks/msr.h b/src/soc/intel/common/block/include/intelblocks/msr.h index 4bdd90c5366..5aba9d00451 100644 --- a/src/soc/intel/common/block/include/intelblocks/msr.h +++ b/src/soc/intel/common/block/include/intelblocks/msr.h @@ -44,6 +44,7 @@ #define MSR_DISABLE_SIGNALING_THREE_STRIKE_EVENT 0x1ab #define THREE_STRIKE_COUNT (1 << 0) #define MSR_TURBO_RATIO_LIMIT 0x1ad +#define MSR_TURBO_RATIO_LIMIT_CORES 0x1ae #define MSR_PRMRR_PHYS_BASE 0x1f4 #define MSR_PRMRR_PHYS_MASK 0x1f5 #define PRMRR_PHYS_MASK_LOCK (1 << 10) @@ -68,6 +69,7 @@ #define MSR_C_STATE_LATENCY_CONTROL_1 0x60b #define MSR_C_STATE_LATENCY_CONTROL_2 0x60c #define MSR_PKG_POWER_LIMIT 0x610 + /* * For Mobile, RAPL default PL1 time window value set to 28 seconds. * RAPL time window calculation defined as follows: @@ -102,6 +104,9 @@ #define PKG_POWER_LIMIT_DUTYCYCLE_SHIFT 24 #define PKG_POWER_LIMIT_DUTYCYCLE_MASK (0x7f) +#define MSR_ATOM_TURBO_RATIO_LIMIT 0x650 +#define MSR_ATOM_TURBO_RATIO_LIMIT_CORES 0x651 + #define MSR_CORE_MKTME_ACTIVATION 0x9ff /* SMM save state MSRs */ #define SMBASE_MSR 0xc20 diff --git a/src/soc/intel/common/block/power_limit/power_limit.c b/src/soc/intel/common/block/power_limit/power_limit.c index 4758f09f825..ec5f202f797 100644 --- a/src/soc/intel/common/block/power_limit/power_limit.c +++ b/src/soc/intel/common/block/power_limit/power_limit.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -80,8 +81,8 @@ void set_power_limits(u8 power_limit_1_time, msr_t msr; msr_t limit; unsigned int power_unit; - unsigned int tdp, min_power, max_power, max_time, tdp_pl2, tdp_pl1; - u8 power_limit_1_val; + unsigned int tdp, min_power, max_power, max_time, tdp_pl4, tdp_pl2, tdp_pl1; + u8 power_limit_1_val, pl1_time; uint32_t value; if (CONFIG(SOC_INTEL_DISABLE_POWER_LIMITS)) { @@ -108,8 +109,12 @@ void set_power_limits(u8 power_limit_1_time, return; } - if (power_limit_1_time >= ARRAY_SIZE(power_limit_time_sec_to_msr)) - power_limit_1_time = ARRAY_SIZE(power_limit_time_sec_to_msr) - 1; + pl1_time = get_uint_option("pl1_time", power_limit_1_time); + if (pl1_time == 0) + pl1_time = power_limit_1_time; + + if (pl1_time >= ARRAY_SIZE(power_limit_time_sec_to_msr)) + pl1_time = ARRAY_SIZE(power_limit_time_sec_to_msr) - 1; msr = rdmsr(MSR_PLATFORM_INFO); if (!(msr.lo & PLATFORM_INFO_SET_TDP)) @@ -128,8 +133,8 @@ void set_power_limits(u8 power_limit_1_time, printk(BIOS_INFO, "CPU TDP = %u Watts\n", tdp / power_unit); - if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time) - power_limit_1_time = power_limit_time_msr_to_sec[max_time]; + if (power_limit_time_msr_to_sec[max_time] > pl1_time) + pl1_time = power_limit_time_msr_to_sec[max_time]; if (min_power > 0 && tdp < min_power) tdp = min_power; @@ -137,12 +142,17 @@ void set_power_limits(u8 power_limit_1_time, if (max_power > 0 && tdp > max_power) tdp = max_power; - power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time]; + power_limit_1_val = power_limit_time_sec_to_msr[pl1_time]; /* Set long term power limit to TDP */ limit.lo = 0; - tdp_pl1 = ((conf->tdp_pl1_override == 0) ? - tdp : (conf->tdp_pl1_override * power_unit)); + tdp_pl1 = get_uint_option("pl1_override", conf->tdp_pl1_override); + if (tdp_pl1 == 0) + tdp_pl1 = ((conf->tdp_pl1_override == 0) ? + tdp : (conf->tdp_pl1_override * power_unit)); + else + tdp_pl1 *= power_unit; + printk(BIOS_INFO, "CPU PL1 = %u Watts\n", tdp_pl1 / power_unit); limit.lo |= (tdp_pl1 & PKG_POWER_LIMIT_MASK); @@ -155,8 +165,13 @@ void set_power_limits(u8 power_limit_1_time, /* Set short term power limit to 1.25 * TDP if no config given */ limit.hi = 0; - tdp_pl2 = (conf->tdp_pl2_override == 0) ? - (tdp * 125) / 100 : (conf->tdp_pl2_override * power_unit); + tdp_pl2 = get_uint_option("pl2_override", conf->tdp_pl2_override); + if (tdp_pl2 == 0) + tdp_pl2 = (conf->tdp_pl2_override == 0) ? + (tdp * 125) / 100 : (conf->tdp_pl2_override * power_unit); + else + tdp_pl2 *= power_unit; + printk(BIOS_INFO, "CPU PL2 = %u Watts\n", tdp_pl2 / power_unit); limit.hi |= (tdp_pl2) & PKG_POWER_LIMIT_MASK; limit.hi |= PKG_POWER_LIMIT_CLAMP; @@ -204,12 +219,13 @@ void set_power_limits(u8 power_limit_1_time, } /* Set Pl4 */ - if (conf->tdp_pl4) { + tdp_pl4 = get_uint_option("tdp_pl4", conf->tdp_pl4); + if (tdp_pl4) { + tdp_pl4 *= power_unit; limit = rdmsr(MSR_VR_CURRENT_CONFIG); limit.lo = 0; - printk(BIOS_INFO, "CPU PL4 = %u Watts\n", conf->tdp_pl4); - limit.lo |= (conf->tdp_pl4 * power_unit) & - PKG_POWER_LIMIT_MASK; + printk(BIOS_INFO, "CPU PL4 = %u Watts\n", tdp_pl4 / power_unit); + limit.lo |= tdp_pl4 & PKG_POWER_LIMIT_MASK; wrmsr(MSR_VR_CURRENT_CONFIG, limit); } diff --git a/src/soc/intel/common/block/rtc/rtc.c b/src/soc/intel/common/block/rtc/rtc.c index cf219e80613..3c7f31837e3 100644 --- a/src/soc/intel/common/block/rtc/rtc.c +++ b/src/soc/intel/common/block/rtc/rtc.c @@ -8,6 +8,7 @@ #include #include #include +#include #include /* RTC PCR configuration */ @@ -31,6 +32,11 @@ __weak int soc_get_rtc_failed(void) return 0; } +bool cmos_is_invalid(void) +{ + return (bool)vbnv_cmos_failed(); +} + void rtc_init(void) { /* Ensure the date is set including century byte. */ diff --git a/src/southbridge/intel/common/rtc.c b/src/southbridge/intel/common/rtc.c index 933ac6349ff..d2a9e812988 100644 --- a/src/southbridge/intel/common/rtc.c +++ b/src/southbridge/intel/common/rtc.c @@ -39,3 +39,8 @@ int vbnv_cmos_failed(void) { return rtc_failure(); } + +bool cmos_is_invalid(void) +{ + return (bool)rtc_failure(); +} diff --git a/src/superio/nuvoton/nct6687d/Makefile.mk b/src/superio/nuvoton/nct6687d/Makefile.mk index 899cf5daec1..18784b9dfd2 100644 --- a/src/superio/nuvoton/nct6687d/Makefile.mk +++ b/src/superio/nuvoton/nct6687d/Makefile.mk @@ -3,6 +3,11 @@ bootblock-$(CONFIG_SUPERIO_NUVOTON_NCT6687D) += nct6687d_ec.c romstage-$(CONFIG_SUPERIO_NUVOTON_NCT6687D) += nct6687d_ec.c ramstage-$(CONFIG_SUPERIO_NUVOTON_NCT6687D) += nct6687d_ec.c +smm-$(CONFIG_SUPERIO_NUVOTON_NCT6687D) += nct6687d_ec.c + +bootblock-$(CONFIG_SUPERIO_NUVOTON_NCT6687D) += nct6687d_smbus.c +romstage-$(CONFIG_SUPERIO_NUVOTON_NCT6687D) += nct6687d_smbus.c +ramstage-$(CONFIG_SUPERIO_NUVOTON_NCT6687D) += nct6687d_smbus.c ramstage-$(CONFIG_SUPERIO_NUVOTON_NCT6687D) += nct6687d_hwm.c ramstage-$(CONFIG_SUPERIO_NUVOTON_NCT6687D) += superio.c diff --git a/src/superio/nuvoton/nct6687d/nct6687d_smbus.c b/src/superio/nuvoton/nct6687d/nct6687d_smbus.c new file mode 100644 index 00000000000..76bc889b5fb --- /dev/null +++ b/src/superio/nuvoton/nct6687d/nct6687d_smbus.c @@ -0,0 +1,218 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include + +#include "nct6687d_hwm.h" +#include "nct6687d_smbus.h" + +#if !ENV_RAMSTAGE +uint16_t nct6687d_hwm_base = 0; +#endif + +static void prepare_smbus_transaction(uint8_t operation, uint8_t address, uint8_t command, uint8_t length) +{ + hwm_reg_write(SMBUS_MASTER_PROTOCOL_SEL_REG, operation); + + if (operation == SMBUS_MASTER_BLOCK_WRITE) + hwm_reg_write(SMBUS_MASTER_BLOCK_WR_LEN_REG, length); + + hwm_reg_write(SMBUS_MASTER_DEV_ADDR_REG, address); + hwm_reg_write(SMBUS_MASTER_CMD_REG, command); +} + +static bool wait_smbus_status_bit_clear(uint8_t bit) +{ + struct stopwatch timer; + + stopwatch_init_msecs_expire(&timer, 500); + + while (true) { + if ((hwm_reg_read(SMBUS_MASTER_CFG1_REG) & bit) == 0) + return true; + + /* On timeout, assume that the TPM is not working */ + if (stopwatch_expired(&timer)) + return false; + + mdelay(1); + } +} + +static void start_smbus_transaction(void) +{ + hwm_reg_write(SMBUS_MASTER_CFG1_REG, SMB_MASTER_EN | SMB_MASTER_START); +} + + +void nct6687d_smbus_init(uint16_t hwmbase) +{ + if (hwmbase) + nct6687d_hwm_base = hwmbase; + + hwm_reg_write(SMBUS_MASTER_CFG2_REG, SMB_MASTER_PORT(4)); + hwm_reg_write(SMBUS_MASTER_BAUD_RATE_SEL_REG, SMB_MASTER_BAUD_100K); +} + +int nct6687d_smbus_read_byte(uint8_t address, uint8_t command, uint8_t *data) +{ + uint8_t error; + + if (!data) + return -1; + + prepare_smbus_transaction(SMBUS_MASTER_READ_BYTE, address, command, 0); + + hwm_reg_write(SMBUS_MASTER_CFG1_REG, SMB_MASTER_EN | SMB_MASTER_CLEAR_BUF); + if (!wait_smbus_status_bit_clear(SMB_MASTER_CLEAR_BUF)) + return -2; + + start_smbus_transaction(); + + if (!wait_smbus_status_bit_clear(SMB_MASTER_START)) + return -3; + + error = hwm_reg_read(SMBUS_MASTER_ERR_STS_REG); + + if (error != 0) + return (int)error; + + *data = hwm_reg_read(SMBUS_MASTER_READ_BUFFER(0)); + + return 0; +} + +int nct6687d_smbus_read_word(uint8_t address, uint8_t command, uint16_t *data) +{ + uint8_t error; + + if (!data) + return -1; + + prepare_smbus_transaction(SMBUS_MASTER_READ_WORD, address, command, 0); + + hwm_reg_write(SMBUS_MASTER_CFG1_REG, SMB_MASTER_EN | SMB_MASTER_CLEAR_BUF); + if (!wait_smbus_status_bit_clear(SMB_MASTER_CLEAR_BUF)) + return -2; + + start_smbus_transaction(); + + if (!wait_smbus_status_bit_clear(SMB_MASTER_START)) + return -3; + + error = hwm_reg_read(SMBUS_MASTER_ERR_STS_REG); + + if (error != 0) + return (int)error; + + *data = hwm_reg_read(SMBUS_MASTER_READ_BUFFER(0)); + *data |= hwm_reg_read(SMBUS_MASTER_READ_BUFFER(1)) << 8; + + return 0; +} + +int nct6687d_smbus_write_byte(uint8_t address, uint8_t command, uint8_t data) +{ + uint8_t error; + + prepare_smbus_transaction(SMBUS_MASTER_WRITE_BYTE, address, command, 0); + + hwm_reg_write(SMBUS_MASTER_WRITE_BUFFER(0), data); + + start_smbus_transaction(); + + if (!wait_smbus_status_bit_clear(SMB_MASTER_START)) + return -3; + + error = hwm_reg_read(SMBUS_MASTER_ERR_STS_REG); + + if (error != 0) + return (int)error; + + return 0; +} + +int nct6687d_smbus_write_word(uint8_t address, uint8_t command, uint16_t data) +{ + uint8_t error; + + prepare_smbus_transaction(SMBUS_MASTER_WRITE_WORD, address, command, 0); + + hwm_reg_write(SMBUS_MASTER_WRITE_BUFFER(0), data & 0xff); + hwm_reg_write(SMBUS_MASTER_WRITE_BUFFER(1), data >> 8); + + start_smbus_transaction(); + + if (!wait_smbus_status_bit_clear(SMB_MASTER_START)) + return -3; + + error = hwm_reg_read(SMBUS_MASTER_ERR_STS_REG); + + if (error != 0) + return (int)error; + + return 0; +} + +int nct6687d_smbus_block_read(uint8_t address, uint8_t command, uint8_t *data, uint8_t *length) +{ + uint8_t error; + uint8_t read_len; + + if (!data || !length || *length >= SMBUS_MASTER_READ_BUFFER_LEN || *length == 0) + return -1; + + prepare_smbus_transaction(SMBUS_MASTER_BLOCK_READ, address, command, 0); + + if (!wait_smbus_status_bit_clear(SMB_MASTER_CLEAR_BUF)) + return -2; + + start_smbus_transaction(); + + if (!wait_smbus_status_bit_clear(SMB_MASTER_START)) + return -3; + + error = hwm_reg_read(SMBUS_MASTER_ERR_STS_REG); + + if (error != 0) + return (int)error; + + read_len = hwm_reg_read(SMBUS_MASTER_READ_BUFFER(0)); + + if (read_len > *length || read_len >= SMBUS_MASTER_READ_BUFFER_LEN) + return -4; + + for (int i = 0; i <= read_len; i++) + data[i] = hwm_reg_read(SMBUS_MASTER_READ_BUFFER(i + 1)); + + return 0; +} + +int nct6687d_smbus_block_write(uint8_t address, uint8_t command, uint8_t *data, uint8_t length) +{ + uint8_t error; + + if (!data || length > SMBUS_MASTER_WRITE_BUFFER_LEN || length == 0) + return -1; + + prepare_smbus_transaction(SMBUS_MASTER_BLOCK_WRITE, address, command, length); + + hwm_reg_write(SMBUS_MASTER_CFG1_REG, SMB_MASTER_EN | SMB_MASTER_CLEAR_BUF); + if (!wait_smbus_status_bit_clear(SMB_MASTER_CLEAR_BUF)) + return -2; + + for (int i = 0; i < length; i++) + hwm_reg_write(SMBUS_MASTER_WRITE_BUFFER(i), data[i]); + + start_smbus_transaction(); + + if (!wait_smbus_status_bit_clear(SMB_MASTER_START)) + return -3; + + error = hwm_reg_read(SMBUS_MASTER_ERR_STS_REG); + + if (error != 0) + return (int)error; + + return 0; +} diff --git a/src/superio/nuvoton/nct6687d/nct6687d_smbus.h b/src/superio/nuvoton/nct6687d/nct6687d_smbus.h new file mode 100644 index 00000000000..195a24af1a6 --- /dev/null +++ b/src/superio/nuvoton/nct6687d/nct6687d_smbus.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef SUPERIO_NUVOTON_NCT6687D_SMBUS_H +#define SUPERIO_NUVOTON_NCT6687D_SMBUS_H + +#include + +void nct6687d_smbus_init(uint16_t hwmbase); +int nct6687d_smbus_read_byte(uint8_t address, uint8_t command, uint8_t *data); +int nct6687d_smbus_read_word(uint8_t address, uint8_t command, uint16_t *data); +int nct6687d_smbus_write_byte(uint8_t address, uint8_t command, uint8_t data); +int nct6687d_smbus_write_word(uint8_t address, uint8_t command, uint16_t data); +int nct6687d_smbus_block_read(uint8_t address, uint8_t command, uint8_t *data, uint8_t *length); +int nct6687d_smbus_block_write(uint8_t address, uint8_t command, uint8_t *data, uint8_t length); + +#endif /* SUPERIO_NUVOTON_NCT6687D_SMBUS_H */ diff --git a/src/vendorcode/dasharo/options.c b/src/vendorcode/dasharo/options.c index 77888edc837..5fb12ed2cc2 100644 --- a/src/vendorcode/dasharo/options.c +++ b/src/vendorcode/dasharo/options.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,9 @@ static enum cb_err read_u8_var(const char *var_name, uint8_t *var) { struct region_device rdev; + if (cmos_is_invalid()) + return CB_SUCCESS; + if (CONFIG(SMMSTORE_V2) && !smmstore_lookup_region(&rdev)) { uint8_t tmp; uint32_t size = sizeof(tmp); @@ -94,6 +98,11 @@ static struct apu_config_t get_apu_config(void) cfg = val; + if (cmos_is_invalid()) { + init_done = true; + return cfg; + } + struct region_device rdev; if (CONFIG(SMMSTORE_V2) && !smmstore_lookup_region(&rdev)) { uint32_t size = sizeof(val); @@ -227,9 +236,13 @@ bool dma_protection_enabled(void) return false; size = sizeof(iommu_var); - if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) + if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) { + if (cmos_is_invalid()) + return false; + ret = efi_fv_get_option(&rdev, &dasharo_system_features_guid, "IommuConfig", &iommu_var, &size); + } if (ret != CB_SUCCESS) return false; @@ -354,9 +367,13 @@ void get_watchdog_config(struct watchdog_config *wdt_cfg) return; size = sizeof(*wdt_cfg); - if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) + if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) { + if (cmos_is_invalid()) + return; + ret = efi_fv_get_option(&rdev, &dasharo_system_features_guid, "WatchdogConfig", wdt_cfg, &size); + } if (ret != CB_SUCCESS || size != sizeof(*wdt_cfg)) { wdt_cfg->wdt_enable = CONFIG(SOC_INTEL_COMMON_OC_WDT_ENABLE); @@ -428,9 +445,13 @@ void get_battery_config(struct battery_config *bat_cfg) return; size = sizeof(*bat_cfg); - if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) + if (CONFIG(DRIVERS_EFI_VARIABLE_STORE)) { + if (cmos_is_invalid()) + return; + ret = efi_fv_get_option(&rdev, &dasharo_system_features_guid, "BatteryConfig", bat_cfg, &size); + } if (ret != CB_SUCCESS || size != sizeof(*bat_cfg)) { bat_cfg->start_threshold = BATTERY_START_THRESHOLD_DEFAULT;