1 /*
2 * PCI AER infomation display library
3 *
4 * Author: Shawn Lin <shawn.lin@rock-chips.com>
5 *
6 * Copyright 2025 Rockchip Co., Ltd.
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 */
10
11 #include <common.h>
12 #include <pci.h>
13 #include <errno.h>
14 #include <dm/device.h>
15
16 /**
17 * pci_aer_dump - Parse and print AER information in a human-readable format
18 * @dev: PCI device
19 *
20 * Return: 0 on success, negative error code on failure.
21 */
pci_aer_dump(struct udevice * udev,pci_dev_t dev)22 int pci_aer_dump(struct udevice *udev, pci_dev_t dev)
23 {
24 int aer_cap_ptr;
25 u32 aer_status, aer_mask, aer_severity;
26 u32 aer_capabilities;
27 struct dm_pci_ops *ops;
28 struct udevice *bus;
29
30 /* Find the AER Capability */
31 aer_cap_ptr = dm_pci_find_ext_capability(udev, PCI_EXT_CAP_ID_ERR);
32 if (!aer_cap_ptr) {
33 printf("AER Capability not found for device %04x:%04x\n",
34 PCI_BUS(dev), PCI_DEV(dev));
35 return -ENODEV;
36 }
37
38 /* Read AER-related registers */
39 dm_pci_read_config32(udev, aer_cap_ptr + PCI_AER_STATUS, &aer_status);
40 dm_pci_read_config32(udev, aer_cap_ptr + PCI_AER_MASK, &aer_mask);
41 dm_pci_read_config32(udev, aer_cap_ptr + PCI_AER_SEVERITY, &aer_severity);
42 dm_pci_read_config32(udev, aer_cap_ptr + 0x18, &aer_capabilities); /* AER Capabilities Register */
43
44 /* Print AER Capability information */
45 printf("AER Capability found at offset 0x%x\n", aer_cap_ptr);
46
47 /* Print Uncorrectable Error Status (UES) */
48 printf(" UESta: ");
49 printf("DLP-%c ", (aer_status & (1 << 0)) ? '+' : '-');
50 printf("SDES-%c ", (aer_status & (1 << 1)) ? '+' : '-');
51 printf("TLP-%c ", (aer_status & (1 << 2)) ? '+' : '-');
52 printf("FCP-%c ", (aer_status & (1 << 3)) ? '+' : '-');
53 printf("CmpltTO-%c ", (aer_status & (1 << 4)) ? '+' : '-');
54 printf("CmpltAbrt-%c ", (aer_status & (1 << 5)) ? '+' : '-');
55 printf("UnxCmplt-%c ", (aer_status & (1 << 6)) ? '+' : '-');
56 printf("RxOF-%c ", (aer_status & (1 << 7)) ? '+' : '-');
57 printf("MalfTLP-%c ", (aer_status & (1 << 8)) ? '+' : '-');
58 printf("ECRC-%c ", (aer_status & (1 << 9)) ? '+' : '-');
59 printf("UnsupReq-%c ", (aer_status & (1 << 10)) ? '+' : '-');
60 printf("ACSViol-%c\n", (aer_status & (1 << 11)) ? '+' : '-');
61
62 /* Print Uncorrectable Error Mask (UEMsk) */
63 printf(" UEMsk: ");
64 printf("DLP-%c ", (aer_mask & (1 << 0)) ? '+' : '-');
65 printf("SDES-%c ", (aer_mask & (1 << 1)) ? '+' : '-');
66 printf("TLP-%c ", (aer_mask & (1 << 2)) ? '+' : '-');
67 printf("FCP-%c ", (aer_mask & (1 << 3)) ? '+' : '-');
68 printf("CmpltTO-%c ", (aer_mask & (1 << 4)) ? '+' : '-');
69 printf("CmpltAbrt-%c ", (aer_mask & (1 << 5)) ? '+' : '-');
70 printf("UnxCmplt-%c ", (aer_mask & (1 << 6)) ? '+' : '-');
71 printf("RxOF-%c ", (aer_mask & (1 << 7)) ? '+' : '-');
72 printf("MalfTLP-%c ", (aer_mask & (1 << 8)) ? '+' : '-');
73 printf("ECRC-%c ", (aer_mask & (1 << 9)) ? '+' : '-');
74 printf("UnsupReq-%c ", (aer_mask & (1 << 10)) ? '+' : '-');
75 printf("ACSViol-%c\n", (aer_mask & (1 << 11)) ? '+' : '-');
76
77 /* Print Uncorrectable Error Severity (UESvrt) */
78 printf(" UESvrt: ");
79 printf("DLP%c ", (aer_severity & (1 << 0)) ? '+' : '-');
80 printf("SDES%c ", (aer_severity & (1 << 1)) ? '+' : '-');
81 printf("TLP%c ", (aer_severity & (1 << 2)) ? '+' : '-');
82 printf("FCP%c ", (aer_severity & (1 << 3)) ? '+' : '-');
83 printf("CmpltTO%c ", (aer_severity & (1 << 4)) ? '+' : '-');
84 printf("CmpltAbrt%c ", (aer_severity & (1 << 5)) ? '+' : '-');
85 printf("UnxCmplt%c ", (aer_severity & (1 << 6)) ? '+' : '-');
86 printf("RxOF%c ", (aer_severity & (1 << 7)) ? '+' : '-');
87 printf("MalfTLP%c ", (aer_severity & (1 << 8)) ? '+' : '-');
88 printf("ECRC%c ", (aer_severity & (1 << 9)) ? '+' : '-');
89 printf("UnsupReq%c ", (aer_severity & (1 << 10)) ? '+' : '-');
90 printf("ACSViol%c\n", (aer_severity & (1 << 11)) ? '+' : '-');
91
92 /* Print Correctable Error Status (CESta) */
93 printf(" CESta: ");
94 printf("RxErr-%c ", (aer_status & (1 << 12)) ? '+' : '-');
95 printf("BadTLP-%c ", (aer_status & (1 << 13)) ? '+' : '-');
96 printf("BadDLLP-%c ", (aer_status & (1 << 14)) ? '+' : '-');
97 printf("Rollover-%c ", (aer_status & (1 << 15)) ? '+' : '-');
98 printf("Timeout-%c ", (aer_status & (1 << 16)) ? '+' : '-');
99 printf("NonFatalErr-%c\n", (aer_status & (1 << 17)) ? '+' : '-');
100
101 /* Print Correctable Error Mask (CEMsk) */
102 printf(" CEMsk: ");
103 printf("RxErr-%c ", (aer_mask & (1 << 12)) ? '+' : '-');
104 printf("BadTLP-%c ", (aer_mask & (1 << 13)) ? '+' : '-');
105 printf("BadDLLP-%c ", (aer_mask & (1 << 14)) ? '+' : '-');
106 printf("Rollover-%c ", (aer_mask & (1 << 15)) ? '+' : '-');
107 printf("Timeout-%c ", (aer_mask & (1 << 16)) ? '+' : '-');
108 printf("NonFatalErr-%c\n", (aer_mask & (1 << 17)) ? '+' : '-');
109
110 /* Print AER Capabilities (AERCap) */
111 printf(" AERCap: ");
112 printf("First Error Pointer: %02x, ", (aer_capabilities >> 0) & 0x1F);
113 printf("GenCap%c ", (aer_capabilities & (1 << 5)) ? '+' : '-');
114 printf("CGenEn%c ", (aer_capabilities & (1 << 6)) ? '+' : '-');
115 printf("ChkCap%c ", (aer_capabilities & (1 << 7)) ? '+' : '-');
116 printf("ChkEn%c\n", (aer_capabilities & (1 << 8)) ? '+' : '-');
117
118 for (bus = udev; device_is_on_pci_bus(bus);)
119 bus = bus->parent;
120
121 ops = pci_get_ops(bus);
122 if (ops->vendor_aer_dump)
123 return ops->vendor_aer_dump(bus);
124
125 return 0;
126 }
127