diff options
author | Angel Pons <th3fanbus@gmail.com> | 2020-08-04 00:26:45 +0200 |
---|---|---|
committer | Angel Pons <th3fanbus@gmail.com> | 2020-08-07 10:15:15 +0000 |
commit | 12404e04c8d2b3ac925e6967043f3e9fe750fa83 (patch) | |
tree | c2c7c2e9e5917ff9aa2cdcd6f1cb688dc0db19c5 /src/southbridge/intel/lynxpoint | |
parent | 29a4df43cef4dad77d88d4694c1d42ec657c0229 (diff) |
sb/intel/lynxpoint: Consider root ports being disabled by strap
PCIe RPC (Root Port Configuration) straps will force-disable some root
port functions if some root ports have a width greater than x1. In two
cases, this affects the last function. The PCIe init code will never
finish configuring the root ports if that is the case: it assumes that
the last function will eventually run through the code, but it doesn't.
If PCIe initialization does not complete, pressing the power button will
not power off the board, unless it is held for about five seconds. Also,
Windows 10 will show a BSOD about MACHINE CHECK EXCEPTION, and lock up
instead of rebooting. Depending on the microcode version, the BSOD may
not be visible. This happens even when the root port is not populated.
Use the strap fuse configuration value to know which configuration the
PCH is strapped to. If needed, update the number of ports accordingly.
In addition, print the updated value to ease debugging PCIe init code.
Existing code in coreboot disagrees with public documentation about the
root port width straps. Assume existing code is correct and document
these assumptions in a table, as an explanation for the added code.
Tested on Asrock B85M Pro4, PCIe initialization completes successfully.
Change-Id: Id6da3a1f45467f00002a5ed41df8650f4a74eeba
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/44155
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/southbridge/intel/lynxpoint')
-rw-r--r-- | src/southbridge/intel/lynxpoint/pcie.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/southbridge/intel/lynxpoint/pcie.c b/src/southbridge/intel/lynxpoint/pcie.c index d2950e7916..4e94f121c0 100644 --- a/src/southbridge/intel/lynxpoint/pcie.c +++ b/src/southbridge/intel/lynxpoint/pcie.c @@ -100,6 +100,38 @@ static void root_port_config_update_gbe_port(void) } } +static void update_num_ports(void) +{ + /* + * According to existing code in 'root_port_check_disable()', which does + * not agree with the confusing information on the datasheets, the last + * visible function depends on the strapped root port width as follows: + * + * +-----+----+----+----+----+ + * | RPC | #5 | #6 | #7 | #8 | + * +-----+----+----+----+----+ + * | 0 | x1 | x1 | x1 | x1 | + * | 1 | x2 | | x1 | x1 | + * | 2 | x2 | | x2 | | + * | 3 | x4 | | | | + * +-----+----+----+----+----+ + */ + switch ((rpc.strpfusecfg2 >> 14) & 0x3) { + case 0: + case 1: + break; + case 2: + rpc.num_ports = MIN(rpc.num_ports, 7); + break; + case 3: + rpc.num_ports = MIN(rpc.num_ports, 5); + break; + } + + printk(BIOS_DEBUG, "Adjusted number of PCIe root ports to %d as per strpfusecfg2\n", + rpc.num_ports); +} + static void root_port_init_config(struct device *dev) { int rp; @@ -137,6 +169,10 @@ static void root_port_init_config(struct device *dev) case 5: rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc); rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c); + + if (!pch_is_lp()) + update_num_ports(); + break; case 6: rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c); |