soc/intel/common/block/lpc: Fix AMASK decoding in window detection

Commit 339ef9b5c9 ("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 <jeremy.compostella@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/91418
Reviewed-by: Subrata Banik <subratabanik@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Pranava Y N <pranavayn@google.com>
This commit is contained in:
Patrick Rudolph 2026-02-12 07:11:47 +01:00 committed by Matt DeVillier
commit 34c156427d

View file

@ -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;