From 339ef9b5c9297019330259828b278dab2f524cdc Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Thu, 12 Feb 2026 07:11:47 +0100 Subject: [PATCH] soc/intel/common/block/lpc: Improve automatic window opening MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an existing LPC window covers an IO range, but is bigger or starts earlier the current code doesn't recognize it. It will open another window overlapping an existing one. Check if an existing LPC IO window covers the current one and allow it to be bigger than the entry. TEST=Thinkpad X280 still boots and error messages are gone. Should fix the following line seen in the coreboot log of the Lenovo T480 and compatible: [ERROR] LPC: Cannot open IO window: 1604 size 1 [ERROR] No more IO windows [ERROR] LPC: Cannot open IO window: 1606 size 1 [ERROR] No more IO windows [ERROR] LPC: Cannot open IO window: 1610 size 10 [ERROR] No more IO windows Change-Id: I586066238b801d2abb1122698fb4092ee0b2f6b9 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/91171 Reviewed-by: Ladislav Ezr Reviewed-by: Johann C Rode Reviewed-by: Paul Menzel Reviewed-by: Jérémy Compostella Tested-by: build bot (Jenkins) --- src/soc/intel/common/block/lpc/lpc_lib.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/soc/intel/common/block/lpc/lpc_lib.c b/src/soc/intel/common/block/lpc/lpc_lib.c index 9a7165baaf..337a098848 100644 --- a/src/soc/intel/common/block/lpc/lpc_lib.c +++ b/src/soc/intel/common/block/lpc/lpc_lib.c @@ -169,14 +169,17 @@ void lpc_open_pmio_window(uint16_t base, uint16_t size) alignment = 1UL << (log2_ceil(window_size)); window_size = ALIGN_UP(window_size, alignment); - /* Address[15:2] in LGIR[15:12] and Mask[7:2] in LGIR[23:18]. */ - lgir = (bridge_base & LPC_LGIR_ADDR_MASK) | LPC_LGIR_EN; - lgir |= ((window_size - 1) << 16) & LPC_LGIR_AMASK_MASK; + const struct region win = region_create(bridge_base, window_size); - /* Skip programming if same range already programmed. */ + /* Skip programming if covered by existing window. */ for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) { - if (lgir == pci_read_config32(PCH_DEV_LPC, - LPC_GENERIC_IO_RANGE(i))) + const u32 reg32 = pci_read_config32(PCH_DEV_LPC, LPC_GENERIC_IO_RANGE(i)); + if (!(reg32 & LPC_LGIR_EN)) + continue; + const struct region exist = region_create(reg32 & LPC_LGIR_ADDR_MASK, + 1 + ((reg32 & LPC_LGIR_AMASK_MASK) >> 16)); + + if (region_is_subregion(&exist, &win)) return; } @@ -190,6 +193,10 @@ void lpc_open_pmio_window(uint16_t base, uint16_t size) } lgir_reg_offset = LPC_GENERIC_IO_RANGE(lgir_reg_num); + /* Address[15:2] in LGIR[15:12] and Mask[7:2] in LGIR[23:18]. */ + lgir = (bridge_base & LPC_LGIR_ADDR_MASK) | LPC_LGIR_EN; + lgir |= ((window_size - 1) << 16) & LPC_LGIR_AMASK_MASK; + pci_write_config32(PCH_DEV_LPC, lgir_reg_offset, lgir); if (CONFIG(SOC_INTEL_COMMON_BLOCK_LPC_MIRROR_TO_GPMR)) gpmr_write32(GPMR_LPCLGIR1 + lgir_reg_num * 4, lgir);