soc/intel/common/block/lpc: Improve automatic window opening

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 <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/91171
Reviewed-by: Ladislav Ezr <ladislav@ezr.cz>
Reviewed-by: Johann C Rode <jcrode82@gmail.com>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Reviewed-by: Jérémy Compostella <jeremy.compostella@intel.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Patrick Rudolph 2026-02-12 07:11:47 +01:00 committed by Matt DeVillier
commit 339ef9b5c9

View file

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