From fe678cbd195d354e11b702e649ad6aba384f92ba Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Wed, 5 Jan 2022 18:46:02 +0000 Subject: soc/intel/common/gpio: Perform GPIO PAD lock outside SMM This patch performs GPIO PAD lock configuration in non-smm mode. Typically, coreboot enables SMI at latest boot phase post FSP-S, hence, FSP-S might get chance to perform GPP lock configuration. With this code changes, coreboot is able to perform GPIO PAD lock configuration early in the boot flow, prior to calling FSP-S. Also, this patch ensures to have two possible options as per GPIO BWG to lock the GPIO PAD configuration. 1. Using SBI message with opcode 0x13 2. Using Private Configuration Register (PCR) BUG=b:211573253, b:211950520 TEST=Able to build and boot brya variant with this code change. Signed-off-by: Subrata Banik Change-Id: I71b4e2f24303b6acb56debd581bd6bc818b6f926 Reviewed-on: https://review.coreboot.org/c/coreboot/+/60801 Reviewed-by: Nick Vaccaro Reviewed-by: EricR Lai Tested-by: build bot (Jenkins) --- src/soc/intel/common/block/gpio/gpio.c | 170 ++++++++++++++++++++++----------- 1 file changed, 114 insertions(+), 56 deletions(-) (limited to 'src/soc/intel') diff --git a/src/soc/intel/common/block/gpio/gpio.c b/src/soc/intel/common/block/gpio/gpio.c index 1d28905a5e..8d262fad18 100644 --- a/src/soc/intel/common/block/gpio/gpio.c +++ b/src/soc/intel/common/block/gpio/gpio.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -450,26 +451,58 @@ int gpio_get(gpio_t gpio_num) return !!(reg & PAD_CFG0_RX_STATE); } -static int sideband_msg_err(int status, int response) +static void +gpio_pad_config_lock_using_sbi(const struct gpio_lock_config *pad_info, + uint8_t pid, uint16_t offset, const uint32_t bit_mask) { - if (status || response) { - printk(BIOS_ERR, "%s: error status=%x response=%x\n", - __func__, status, response); - return (status == -1) ? -1 : response; + int status; + uint8_t response; + uint32_t data; + struct pcr_sbi_msg msg = { + .pid = pid, + .offset = offset, + .opcode = GPIO_LOCK_UNLOCK, + .is_posted = false, + .fast_byte_enable = 0xf, + .bar = 0, + .fid = 0, + }; + + if (!(pad_info->action & GPIO_LOCK_FULL)) { + printk(BIOS_ERR, "%s: Error: no action specified for pad %d!\n", + __func__, pad_info->pad); + return; } - return 0; + if ((pad_info->action & GPIO_LOCK_CONFIG) == GPIO_LOCK_CONFIG) { + if (CONFIG(DEBUG_GPIO)) + printk(BIOS_INFO, "%s: Locking pad %d configuration\n", + __func__, pad_info->pad); + data = pcr_read32(pid, offset) | bit_mask; + status = pcr_execute_sideband_msg(PCH_DEV_P2SB, &msg, &data, &response); + if (status || response) + printk(BIOS_ERR, "Failed to lock GPIO PAD, response = %d\n", response); + } + + if ((pad_info->action & GPIO_LOCK_TX) == GPIO_LOCK_TX) { + if (CONFIG(DEBUG_GPIO)) + printk(BIOS_INFO, "%s: Locking pad %d Tx state\n", + __func__, pad_info->pad); + offset += sizeof(uint32_t); + data = pcr_read32(pid, offset) | bit_mask; + msg.offset = offset; + status = pcr_execute_sideband_msg(PCH_DEV_P2SB, &msg, &data, &response); + if (status || response) + printk(BIOS_ERR, "Failed to lock GPIO PAD Tx state, response = %d\n", + response); + } } int gpio_lock_pads(const struct gpio_lock_config *pad_list, const size_t count) { const struct pad_community *comm; - enum gpio_lock_action action; - int status, err_response = 0; - uint8_t response; uint16_t offset; size_t rel_pad; - uint32_t data; gpio_t pad; if (!CONFIG(SOC_INTEL_COMMON_BLOCK_SMM_LOCK_GPIO_PADS)) @@ -492,29 +525,10 @@ int gpio_lock_pads(const struct gpio_lock_config *pad_list, const size_t count) return -1; } - /* We must use the sideband interface in order to lock the pad. */ - struct pcr_sbi_msg msg = { - .opcode = GPIO_LOCK_UNLOCK, - .is_posted = false, - .fast_byte_enable = 0xF, - .bar = 0, - .fid = 0, - }; - p2sb_unhide(); for (int x = 0; x < count; x++) { - int err; - pad = pad_list[x].pad; - action = pad_list[x].action; - - if (!(action & GPIO_LOCK_FULL)) { - printk(BIOS_ERR, "%s: Error: no action specified for pad %d!\n", - __func__, pad); - continue; - } - comm = gpio_get_community(pad); rel_pad = relative_pad_in_comm(comm, pad); offset = comm->pad_cfg_lock_offset; @@ -527,47 +541,91 @@ int gpio_lock_pads(const struct gpio_lock_config *pad_list, const size_t count) offset += gpio_group_index_scaled(comm, rel_pad, 2 * sizeof(uint32_t)); const uint32_t bit_mask = gpio_bitmask_within_group(comm, rel_pad); - msg.pid = comm->port; - msg.offset = offset; - if ((action & GPIO_LOCK_CONFIG) == GPIO_LOCK_CONFIG) { - if (CONFIG(DEBUG_GPIO)) - printk(BIOS_INFO, "%s: Locking pad %d configuration\n", - __func__, pad); - data = pcr_read32(msg.pid, msg.offset) | bit_mask; - status = pcr_execute_sideband_msg(PCH_DEV_P2SB, &msg, &data, &response); - if ((err = sideband_msg_err(status, response)) != 0) { - err_response = err; - continue; - } - } - - if ((action & GPIO_LOCK_TX) == GPIO_LOCK_TX) { - if (CONFIG(DEBUG_GPIO)) - printk(BIOS_INFO, "%s: Locking pad %d TX state\n", - __func__, pad); - msg.offset += sizeof(uint32_t); - data = pcr_read32(msg.pid, msg.offset) | bit_mask; - status = pcr_execute_sideband_msg(PCH_DEV_P2SB, &msg, &data, &response); - if ((err = sideband_msg_err(status, response)) != 0) { - err_response = err; - continue; - } - } + gpio_pad_config_lock_using_sbi(&pad_list[x], comm->port, offset, bit_mask); } p2sb_hide(); +} + +static void +gpio_pad_config_lock_using_pcr(const struct gpio_lock_config *pad_info, + uint8_t pid, uint16_t offset, const uint32_t bit_mask) +{ + if ((pad_info->action & GPIO_LOCK_CONFIG) == GPIO_LOCK_CONFIG) { + if (CONFIG(DEBUG_GPIO)) + printk(BIOS_INFO, "%s: Locking pad %d configuration\n", + __func__, pad_info->pad); + pcr_or32(pid, offset, bit_mask); + } + + if ((pad_info->action & GPIO_LOCK_TX) == GPIO_LOCK_TX) { + if (CONFIG(DEBUG_GPIO)) + printk(BIOS_INFO, "%s: Locking pad %d TX state\n", + __func__, pad_info->pad); + pcr_or32(pid, offset + sizeof(uint32_t), bit_mask); + } +} + +static int gpio_non_smm_lock_pad(const struct gpio_lock_config *pad_info) +{ + const struct pad_community *comm = gpio_get_community(pad_info->pad); + uint16_t offset; + size_t rel_pad; + + if (!pad_info) { + printk(BIOS_ERR, "%s: Error: pad_info is null!\n", __func__); + return -1; + } + + if (cpu_soc_is_in_untrusted_mode()) { + printk(BIOS_ERR, "%s: Error: IA Untrusted Mode enabled, can't lock pad!\n", + __func__); + return -1; + } + + rel_pad = relative_pad_in_comm(comm, pad_info->pad); + offset = comm->pad_cfg_lock_offset; + if (!offset) { + printk(BIOS_ERR, "%s: Error: offset not defined for pad %d!\n", + __func__, pad_info->pad); + return -1; + } + + /* PADCFGLOCK and PADCFGLOCKTX registers for each community are contiguous */ + offset += gpio_group_index_scaled(comm, rel_pad, 2 * sizeof(uint32_t)); + const uint32_t bit_mask = gpio_bitmask_within_group(comm, rel_pad); - return err_response; + if (CONFIG(SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_USING_PCR)) { + if (CONFIG(DEBUG_GPIO)) + printk(BIOS_INFO, "Locking pad configuration using PCR\n"); + gpio_pad_config_lock_using_pcr(pad_info, comm->port, offset, bit_mask); + } else if (CONFIG(SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_USING_SBI)) { + if (CONFIG(DEBUG_GPIO)) + printk(BIOS_INFO, "Locking pad configuration using SBI\n"); + gpio_pad_config_lock_using_sbi(pad_info, comm->port, offset, bit_mask); + } else { + printk(BIOS_ERR, "%s: Error: No pad configuration lock method is selected!\n", + __func__); + } + + return 0; } int gpio_lock_pad(const gpio_t pad, enum gpio_lock_action action) { + /* Skip locking GPIO PAD in early stages */ + if (ENV_ROMSTAGE_OR_BEFORE) + return -1; + const struct gpio_lock_config pads = { .pad = pad, .action = action }; + if (!ENV_SMM && !CONFIG(SOC_INTEL_COMMON_BLOCK_SMM_LOCK_GPIO_PADS)) + return gpio_non_smm_lock_pad(&pads); + return gpio_lock_pads(&pads, 1); } -- cgit v1.2.3