121c9fbd8SShawn Lin /*
221c9fbd8SShawn Lin * PCI AER infomation display library
321c9fbd8SShawn Lin *
421c9fbd8SShawn Lin * Author: Shawn Lin <shawn.lin@rock-chips.com>
521c9fbd8SShawn Lin *
621c9fbd8SShawn Lin * Copyright 2025 Rockchip Co., Ltd.
721c9fbd8SShawn Lin *
821c9fbd8SShawn Lin * SPDX-License-Identifier: GPL-2.0+
921c9fbd8SShawn Lin */
1021c9fbd8SShawn Lin
1121c9fbd8SShawn Lin #include <common.h>
1221c9fbd8SShawn Lin #include <pci.h>
1321c9fbd8SShawn Lin #include <errno.h>
14*1053d9feSShawn Lin #include <dm/device.h>
1521c9fbd8SShawn Lin
1621c9fbd8SShawn Lin /**
1721c9fbd8SShawn Lin * pci_aer_dump - Parse and print AER information in a human-readable format
1821c9fbd8SShawn Lin * @dev: PCI device
1921c9fbd8SShawn Lin *
2021c9fbd8SShawn Lin * Return: 0 on success, negative error code on failure.
2121c9fbd8SShawn Lin */
pci_aer_dump(struct udevice * udev,pci_dev_t dev)2221c9fbd8SShawn Lin int pci_aer_dump(struct udevice *udev, pci_dev_t dev)
2321c9fbd8SShawn Lin {
2421c9fbd8SShawn Lin int aer_cap_ptr;
2521c9fbd8SShawn Lin u32 aer_status, aer_mask, aer_severity;
2621c9fbd8SShawn Lin u32 aer_capabilities;
27*1053d9feSShawn Lin struct dm_pci_ops *ops;
28*1053d9feSShawn Lin struct udevice *bus;
2921c9fbd8SShawn Lin
3021c9fbd8SShawn Lin /* Find the AER Capability */
3121c9fbd8SShawn Lin aer_cap_ptr = dm_pci_find_ext_capability(udev, PCI_EXT_CAP_ID_ERR);
3221c9fbd8SShawn Lin if (!aer_cap_ptr) {
3321c9fbd8SShawn Lin printf("AER Capability not found for device %04x:%04x\n",
3421c9fbd8SShawn Lin PCI_BUS(dev), PCI_DEV(dev));
3521c9fbd8SShawn Lin return -ENODEV;
3621c9fbd8SShawn Lin }
3721c9fbd8SShawn Lin
3821c9fbd8SShawn Lin /* Read AER-related registers */
3921c9fbd8SShawn Lin dm_pci_read_config32(udev, aer_cap_ptr + PCI_AER_STATUS, &aer_status);
4021c9fbd8SShawn Lin dm_pci_read_config32(udev, aer_cap_ptr + PCI_AER_MASK, &aer_mask);
4121c9fbd8SShawn Lin dm_pci_read_config32(udev, aer_cap_ptr + PCI_AER_SEVERITY, &aer_severity);
4221c9fbd8SShawn Lin dm_pci_read_config32(udev, aer_cap_ptr + 0x18, &aer_capabilities); /* AER Capabilities Register */
4321c9fbd8SShawn Lin
4421c9fbd8SShawn Lin /* Print AER Capability information */
4521c9fbd8SShawn Lin printf("AER Capability found at offset 0x%x\n", aer_cap_ptr);
4621c9fbd8SShawn Lin
4721c9fbd8SShawn Lin /* Print Uncorrectable Error Status (UES) */
4821c9fbd8SShawn Lin printf(" UESta: ");
4921c9fbd8SShawn Lin printf("DLP-%c ", (aer_status & (1 << 0)) ? '+' : '-');
5021c9fbd8SShawn Lin printf("SDES-%c ", (aer_status & (1 << 1)) ? '+' : '-');
5121c9fbd8SShawn Lin printf("TLP-%c ", (aer_status & (1 << 2)) ? '+' : '-');
5221c9fbd8SShawn Lin printf("FCP-%c ", (aer_status & (1 << 3)) ? '+' : '-');
5321c9fbd8SShawn Lin printf("CmpltTO-%c ", (aer_status & (1 << 4)) ? '+' : '-');
5421c9fbd8SShawn Lin printf("CmpltAbrt-%c ", (aer_status & (1 << 5)) ? '+' : '-');
5521c9fbd8SShawn Lin printf("UnxCmplt-%c ", (aer_status & (1 << 6)) ? '+' : '-');
5621c9fbd8SShawn Lin printf("RxOF-%c ", (aer_status & (1 << 7)) ? '+' : '-');
5721c9fbd8SShawn Lin printf("MalfTLP-%c ", (aer_status & (1 << 8)) ? '+' : '-');
5821c9fbd8SShawn Lin printf("ECRC-%c ", (aer_status & (1 << 9)) ? '+' : '-');
5921c9fbd8SShawn Lin printf("UnsupReq-%c ", (aer_status & (1 << 10)) ? '+' : '-');
6021c9fbd8SShawn Lin printf("ACSViol-%c\n", (aer_status & (1 << 11)) ? '+' : '-');
6121c9fbd8SShawn Lin
6221c9fbd8SShawn Lin /* Print Uncorrectable Error Mask (UEMsk) */
6321c9fbd8SShawn Lin printf(" UEMsk: ");
6421c9fbd8SShawn Lin printf("DLP-%c ", (aer_mask & (1 << 0)) ? '+' : '-');
6521c9fbd8SShawn Lin printf("SDES-%c ", (aer_mask & (1 << 1)) ? '+' : '-');
6621c9fbd8SShawn Lin printf("TLP-%c ", (aer_mask & (1 << 2)) ? '+' : '-');
6721c9fbd8SShawn Lin printf("FCP-%c ", (aer_mask & (1 << 3)) ? '+' : '-');
6821c9fbd8SShawn Lin printf("CmpltTO-%c ", (aer_mask & (1 << 4)) ? '+' : '-');
6921c9fbd8SShawn Lin printf("CmpltAbrt-%c ", (aer_mask & (1 << 5)) ? '+' : '-');
7021c9fbd8SShawn Lin printf("UnxCmplt-%c ", (aer_mask & (1 << 6)) ? '+' : '-');
7121c9fbd8SShawn Lin printf("RxOF-%c ", (aer_mask & (1 << 7)) ? '+' : '-');
7221c9fbd8SShawn Lin printf("MalfTLP-%c ", (aer_mask & (1 << 8)) ? '+' : '-');
7321c9fbd8SShawn Lin printf("ECRC-%c ", (aer_mask & (1 << 9)) ? '+' : '-');
7421c9fbd8SShawn Lin printf("UnsupReq-%c ", (aer_mask & (1 << 10)) ? '+' : '-');
7521c9fbd8SShawn Lin printf("ACSViol-%c\n", (aer_mask & (1 << 11)) ? '+' : '-');
7621c9fbd8SShawn Lin
7721c9fbd8SShawn Lin /* Print Uncorrectable Error Severity (UESvrt) */
7821c9fbd8SShawn Lin printf(" UESvrt: ");
7921c9fbd8SShawn Lin printf("DLP%c ", (aer_severity & (1 << 0)) ? '+' : '-');
8021c9fbd8SShawn Lin printf("SDES%c ", (aer_severity & (1 << 1)) ? '+' : '-');
8121c9fbd8SShawn Lin printf("TLP%c ", (aer_severity & (1 << 2)) ? '+' : '-');
8221c9fbd8SShawn Lin printf("FCP%c ", (aer_severity & (1 << 3)) ? '+' : '-');
8321c9fbd8SShawn Lin printf("CmpltTO%c ", (aer_severity & (1 << 4)) ? '+' : '-');
8421c9fbd8SShawn Lin printf("CmpltAbrt%c ", (aer_severity & (1 << 5)) ? '+' : '-');
8521c9fbd8SShawn Lin printf("UnxCmplt%c ", (aer_severity & (1 << 6)) ? '+' : '-');
8621c9fbd8SShawn Lin printf("RxOF%c ", (aer_severity & (1 << 7)) ? '+' : '-');
8721c9fbd8SShawn Lin printf("MalfTLP%c ", (aer_severity & (1 << 8)) ? '+' : '-');
8821c9fbd8SShawn Lin printf("ECRC%c ", (aer_severity & (1 << 9)) ? '+' : '-');
8921c9fbd8SShawn Lin printf("UnsupReq%c ", (aer_severity & (1 << 10)) ? '+' : '-');
9021c9fbd8SShawn Lin printf("ACSViol%c\n", (aer_severity & (1 << 11)) ? '+' : '-');
9121c9fbd8SShawn Lin
9221c9fbd8SShawn Lin /* Print Correctable Error Status (CESta) */
9321c9fbd8SShawn Lin printf(" CESta: ");
9421c9fbd8SShawn Lin printf("RxErr-%c ", (aer_status & (1 << 12)) ? '+' : '-');
9521c9fbd8SShawn Lin printf("BadTLP-%c ", (aer_status & (1 << 13)) ? '+' : '-');
9621c9fbd8SShawn Lin printf("BadDLLP-%c ", (aer_status & (1 << 14)) ? '+' : '-');
9721c9fbd8SShawn Lin printf("Rollover-%c ", (aer_status & (1 << 15)) ? '+' : '-');
9821c9fbd8SShawn Lin printf("Timeout-%c ", (aer_status & (1 << 16)) ? '+' : '-');
9921c9fbd8SShawn Lin printf("NonFatalErr-%c\n", (aer_status & (1 << 17)) ? '+' : '-');
10021c9fbd8SShawn Lin
10121c9fbd8SShawn Lin /* Print Correctable Error Mask (CEMsk) */
10221c9fbd8SShawn Lin printf(" CEMsk: ");
10321c9fbd8SShawn Lin printf("RxErr-%c ", (aer_mask & (1 << 12)) ? '+' : '-');
10421c9fbd8SShawn Lin printf("BadTLP-%c ", (aer_mask & (1 << 13)) ? '+' : '-');
10521c9fbd8SShawn Lin printf("BadDLLP-%c ", (aer_mask & (1 << 14)) ? '+' : '-');
10621c9fbd8SShawn Lin printf("Rollover-%c ", (aer_mask & (1 << 15)) ? '+' : '-');
10721c9fbd8SShawn Lin printf("Timeout-%c ", (aer_mask & (1 << 16)) ? '+' : '-');
10821c9fbd8SShawn Lin printf("NonFatalErr-%c\n", (aer_mask & (1 << 17)) ? '+' : '-');
10921c9fbd8SShawn Lin
11021c9fbd8SShawn Lin /* Print AER Capabilities (AERCap) */
11121c9fbd8SShawn Lin printf(" AERCap: ");
11221c9fbd8SShawn Lin printf("First Error Pointer: %02x, ", (aer_capabilities >> 0) & 0x1F);
11321c9fbd8SShawn Lin printf("GenCap%c ", (aer_capabilities & (1 << 5)) ? '+' : '-');
11421c9fbd8SShawn Lin printf("CGenEn%c ", (aer_capabilities & (1 << 6)) ? '+' : '-');
11521c9fbd8SShawn Lin printf("ChkCap%c ", (aer_capabilities & (1 << 7)) ? '+' : '-');
11621c9fbd8SShawn Lin printf("ChkEn%c\n", (aer_capabilities & (1 << 8)) ? '+' : '-');
11721c9fbd8SShawn Lin
118*1053d9feSShawn Lin for (bus = udev; device_is_on_pci_bus(bus);)
119*1053d9feSShawn Lin bus = bus->parent;
120*1053d9feSShawn Lin
121*1053d9feSShawn Lin ops = pci_get_ops(bus);
122*1053d9feSShawn Lin if (ops->vendor_aer_dump)
123*1053d9feSShawn Lin return ops->vendor_aer_dump(bus);
124*1053d9feSShawn Lin
12521c9fbd8SShawn Lin return 0;
12621c9fbd8SShawn Lin }
127