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:
parent
b50c219557
commit
34c156427d
1 changed files with 10 additions and 2 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue