From 34c156427dcac5311eb2e96dd847e624cf200809 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: Fix AMASK decoding in window detection Commit 339ef9b5c929 ("soc/intel/common/block/lpc: Improve automatic window opening") introduced a bug in the decoding of existing LPC I/O window sizes from the LGIR (LPC Generic I/O Range) registers. The AMASK field in the LGIR register stores bits [7:2] of the address mask, with bits [1:0] implicitly always set to 1 (representing 4-byte granularity). The original implementation incorrectly calculated the window size as: exist_size = 1 + ((reg32 & LPC_LGIR_AMASK_MASK) >> 16) This fails to restore the implicit lower bits [1:0] of the mask. For example, a window programmed with size 8 bytes: - Stored mask: (8-1) & 0xfc = 0x4 (bits [7:2] only) - Incorrectly decoded: 0x4 + 1 = 5 bytes (WRONG) - Correctly decoded: (0x4 | 0x3) + 1 = 8 bytes (CORRECT) This bug caused failures on Panther Lake boards where existing windows were not recognized as covering requested ranges, leading to: [ERROR] LPC: Cannot open IO window: 800 size 8 [ERROR] No more IO windows The fix properly reconstructs the full mask by OR-ing in the implicit bits [1:0] before calculating the size: exist_size = ((amask_raw & 0xfc) | 0x3) + 1 BUG=b:486133237 TEST=Boot Panther Lake Fatcat board, verify no LPC window errors Change-Id: I0b5f95c01da6ce84924a038106edec600e3b97f8 Signed-off-by: Jeremy Compostella Reviewed-on: https://review.coreboot.org/c/coreboot/+/91418 Reviewed-by: Subrata Banik Tested-by: build bot (Jenkins) Reviewed-by: Pranava Y N --- src/soc/intel/common/block/lpc/lpc_lib.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/soc/intel/common/block/lpc/lpc_lib.c b/src/soc/intel/common/block/lpc/lpc_lib.c index 337a098848..18cf1670af 100644 --- a/src/soc/intel/common/block/lpc/lpc_lib.c +++ b/src/soc/intel/common/block/lpc/lpc_lib.c @@ -176,8 +176,16 @@ void lpc_open_pmio_window(uint16_t base, uint16_t size) 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)); + + /* The AMASK field stores bits [7:2] of the address mask. + * Bits [1:0] are always set (4-byte granularity). + * To decode: mask = (amask_raw & 0xfc) | 0x3 + * size = mask + 1 + */ + const u32 exist_base = reg32 & LPC_LGIR_ADDR_MASK; + const u32 amask_raw = (reg32 & LPC_LGIR_AMASK_MASK) >> 16; + const u32 exist_size = ((amask_raw & 0xfc) | 0x3) + 1; + const struct region exist = region_create(exist_base, exist_size); if (region_is_subregion(&exist, &win)) return;