summaryrefslogtreecommitdiffstats
path: root/src/device/pciexp_device.c
diff options
context:
space:
mode:
authorWilson Chou <Wilson.Chou@quantatw.com>2022-08-29 02:08:24 +0000
committerFelix Held <felix-coreboot@felixheld.de>2022-09-12 12:41:13 +0000
commitc8a86954f3336da19c96320b6c695ea4a25a8990 (patch)
tree845c42ab3dea7f675524c51d7d461bc17721d7b1 /src/device/pciexp_device.c
parent46ffccd753f5a350265b8650a83ba51972a5a0cf (diff)
downloadcoreboot-c8a86954f3336da19c96320b6c695ea4a25a8990.tar.gz
coreboot-c8a86954f3336da19c96320b6c695ea4a25a8990.tar.bz2
coreboot-c8a86954f3336da19c96320b6c695ea4a25a8990.zip
device: Clear lane error status
Refer to PCI Express Base rev6.0 v1.0, 4.2.7 Link Training and Status State Rules, Lane Error Status is normal to record the error when link training. To make sure Lane Error Status is correct in OS runtime, add a Kconfig PCIEXP_LANE_ERR_STAT_CLEAR that clears the PCIe lane error status register at the end of PCIe link training. Test=On Crater Lake, lspci -vvv shows bb:01.0 PCI bridge: Intel Corporation Device 352a (rev 03) (prog-if 00 [Normal decode]) Capabilities: [a30 v1] Secondary PCI Express LnkCtl3: LnkEquIntrruptEn- PerformEqu- LaneErrStat: LaneErr at lane: 0 Signed-off-by: Wilson Chou <Wilson.Chou@quantatw.com> Change-Id: I6344223636409d8fc25e365a6375fc81e69f41a5 Reviewed-on: https://review.coreboot.org/c/coreboot/+/67264 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Jonathan Zhang <jonzhang@fb.com>
Diffstat (limited to 'src/device/pciexp_device.c')
-rw-r--r--src/device/pciexp_device.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/src/device/pciexp_device.c b/src/device/pciexp_device.c
index 6023497241b2..b03089b8f692 100644
--- a/src/device/pciexp_device.c
+++ b/src/device/pciexp_device.c
@@ -532,6 +532,30 @@ static void pciexp_set_max_payload_size(struct device *root, unsigned int root_c
printk(BIOS_INFO, "PCIe: Max_Payload_Size adjusted to %d\n", (1 << (max_payload + 7)));
}
+/*
+ * Clear Lane Error State at the end of PCIe link training.
+ * Lane error status is cleared if PCIEXP_LANE_ERR_STAT_CLEAR is set.
+ * Lane error is normal during link training, so we need to clear it.
+ * At this moment, link has been used, but for a very short duration.
+ */
+static void clear_lane_error_status(struct device *dev)
+{
+ u32 reg32;
+ u16 pos;
+
+ pos = pciexp_find_extended_cap(dev, PCI_EXP_SEC_CAP_ID, 0);
+ if (pos == 0)
+ return;
+
+ reg32 = pci_read_config32(dev, pos + PCI_EXP_SEC_LANE_ERR_STATUS);
+ if (reg32 == 0)
+ return;
+
+ printk(BIOS_DEBUG, "%s: Clear Lane Error Status.\n", dev_path(dev));
+ printk(BIOS_DEBUG, "LaneErrStat:0x%x\n", reg32);
+ pci_write_config32(dev, pos + PCI_EXP_SEC_LANE_ERR_STATUS, reg32);
+}
+
static void pciexp_tune_dev(struct device *dev)
{
struct device *root = dev->bus->dev;
@@ -561,6 +585,10 @@ static void pciexp_tune_dev(struct device *dev)
if (CONFIG(PCIEXP_ASPM))
pciexp_enable_aspm(root, root_cap, dev, cap);
+ /* Clear PCIe Lane Error Status */
+ if (CONFIG(PCIEXP_LANE_ERR_STAT_CLEAR))
+ clear_lane_error_status(root);
+
/* Adjust Max_Payload_Size of link ends. */
pciexp_set_max_payload_size(root, root_cap, dev, cap);