1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * amd8131_edac.c, AMD8131 hypertransport chip EDAC kernel module |
4 | * |
5 | * Copyright (c) 2008 Wind River Systems, Inc. |
6 | * |
7 | * Authors: Cao Qingtao <qingtao.cao@windriver.com> |
8 | * Benjamin Walsh <benjamin.walsh@windriver.com> |
9 | * Hu Yongqi <yongqi.hu@windriver.com> |
10 | */ |
11 | |
12 | #include <linux/module.h> |
13 | #include <linux/init.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/io.h> |
16 | #include <linux/bitops.h> |
17 | #include <linux/edac.h> |
18 | #include <linux/pci_ids.h> |
19 | |
20 | #include "edac_module.h" |
21 | #include "amd8131_edac.h" |
22 | |
23 | #define AMD8131_EDAC_REVISION " Ver: 1.0.0" |
24 | #define AMD8131_EDAC_MOD_STR "amd8131_edac" |
25 | |
26 | /* Wrapper functions for accessing PCI configuration space */ |
27 | static void edac_pci_read_dword(struct pci_dev *dev, int reg, u32 *val32) |
28 | { |
29 | int ret; |
30 | |
31 | ret = pci_read_config_dword(dev, where: reg, val: val32); |
32 | if (ret != 0) |
33 | printk(KERN_ERR AMD8131_EDAC_MOD_STR |
34 | " PCI Access Read Error at 0x%x\n" , reg); |
35 | } |
36 | |
37 | static void edac_pci_write_dword(struct pci_dev *dev, int reg, u32 val32) |
38 | { |
39 | int ret; |
40 | |
41 | ret = pci_write_config_dword(dev, where: reg, val: val32); |
42 | if (ret != 0) |
43 | printk(KERN_ERR AMD8131_EDAC_MOD_STR |
44 | " PCI Access Write Error at 0x%x\n" , reg); |
45 | } |
46 | |
47 | /* Support up to two AMD8131 chipsets on a platform */ |
48 | static struct amd8131_dev_info amd8131_devices[] = { |
49 | { |
50 | .inst = NORTH_A, |
51 | .devfn = DEVFN_PCIX_BRIDGE_NORTH_A, |
52 | .ctl_name = "AMD8131_PCIX_NORTH_A" , |
53 | }, |
54 | { |
55 | .inst = NORTH_B, |
56 | .devfn = DEVFN_PCIX_BRIDGE_NORTH_B, |
57 | .ctl_name = "AMD8131_PCIX_NORTH_B" , |
58 | }, |
59 | { |
60 | .inst = SOUTH_A, |
61 | .devfn = DEVFN_PCIX_BRIDGE_SOUTH_A, |
62 | .ctl_name = "AMD8131_PCIX_SOUTH_A" , |
63 | }, |
64 | { |
65 | .inst = SOUTH_B, |
66 | .devfn = DEVFN_PCIX_BRIDGE_SOUTH_B, |
67 | .ctl_name = "AMD8131_PCIX_SOUTH_B" , |
68 | }, |
69 | {.inst = NO_BRIDGE,}, |
70 | }; |
71 | |
72 | static void amd8131_pcix_init(struct amd8131_dev_info *dev_info) |
73 | { |
74 | u32 val32; |
75 | struct pci_dev *dev = dev_info->dev; |
76 | |
77 | /* First clear error detection flags */ |
78 | edac_pci_read_dword(dev, REG_MEM_LIM, val32: &val32); |
79 | if (val32 & MEM_LIMIT_MASK) |
80 | edac_pci_write_dword(dev, REG_MEM_LIM, val32); |
81 | |
82 | /* Clear Discard Timer Timedout flag */ |
83 | edac_pci_read_dword(dev, REG_INT_CTLR, val32: &val32); |
84 | if (val32 & INT_CTLR_DTS) |
85 | edac_pci_write_dword(dev, REG_INT_CTLR, val32); |
86 | |
87 | /* Clear CRC Error flag on link side A */ |
88 | edac_pci_read_dword(dev, REG_LNK_CTRL_A, val32: &val32); |
89 | if (val32 & LNK_CTRL_CRCERR_A) |
90 | edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32); |
91 | |
92 | /* Clear CRC Error flag on link side B */ |
93 | edac_pci_read_dword(dev, REG_LNK_CTRL_B, val32: &val32); |
94 | if (val32 & LNK_CTRL_CRCERR_B) |
95 | edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32); |
96 | |
97 | /* |
98 | * Then enable all error detections. |
99 | * |
100 | * Setup Discard Timer Sync Flood Enable, |
101 | * System Error Enable and Parity Error Enable. |
102 | */ |
103 | edac_pci_read_dword(dev, REG_INT_CTLR, val32: &val32); |
104 | val32 |= INT_CTLR_PERR | INT_CTLR_SERR | INT_CTLR_DTSE; |
105 | edac_pci_write_dword(dev, REG_INT_CTLR, val32); |
106 | |
107 | /* Enable overall SERR Error detection */ |
108 | edac_pci_read_dword(dev, REG_STS_CMD, val32: &val32); |
109 | val32 |= STS_CMD_SERREN; |
110 | edac_pci_write_dword(dev, REG_STS_CMD, val32); |
111 | |
112 | /* Setup CRC Flood Enable for link side A */ |
113 | edac_pci_read_dword(dev, REG_LNK_CTRL_A, val32: &val32); |
114 | val32 |= LNK_CTRL_CRCFEN; |
115 | edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32); |
116 | |
117 | /* Setup CRC Flood Enable for link side B */ |
118 | edac_pci_read_dword(dev, REG_LNK_CTRL_B, val32: &val32); |
119 | val32 |= LNK_CTRL_CRCFEN; |
120 | edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32); |
121 | } |
122 | |
123 | static void amd8131_pcix_exit(struct amd8131_dev_info *dev_info) |
124 | { |
125 | u32 val32; |
126 | struct pci_dev *dev = dev_info->dev; |
127 | |
128 | /* Disable SERR, PERR and DTSE Error detection */ |
129 | edac_pci_read_dword(dev, REG_INT_CTLR, val32: &val32); |
130 | val32 &= ~(INT_CTLR_PERR | INT_CTLR_SERR | INT_CTLR_DTSE); |
131 | edac_pci_write_dword(dev, REG_INT_CTLR, val32); |
132 | |
133 | /* Disable overall System Error detection */ |
134 | edac_pci_read_dword(dev, REG_STS_CMD, val32: &val32); |
135 | val32 &= ~STS_CMD_SERREN; |
136 | edac_pci_write_dword(dev, REG_STS_CMD, val32); |
137 | |
138 | /* Disable CRC Sync Flood on link side A */ |
139 | edac_pci_read_dword(dev, REG_LNK_CTRL_A, val32: &val32); |
140 | val32 &= ~LNK_CTRL_CRCFEN; |
141 | edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32); |
142 | |
143 | /* Disable CRC Sync Flood on link side B */ |
144 | edac_pci_read_dword(dev, REG_LNK_CTRL_B, val32: &val32); |
145 | val32 &= ~LNK_CTRL_CRCFEN; |
146 | edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32); |
147 | } |
148 | |
149 | static void amd8131_pcix_check(struct edac_pci_ctl_info *edac_dev) |
150 | { |
151 | struct amd8131_dev_info *dev_info = edac_dev->pvt_info; |
152 | struct pci_dev *dev = dev_info->dev; |
153 | u32 val32; |
154 | |
155 | /* Check PCI-X Bridge Memory Base-Limit Register for errors */ |
156 | edac_pci_read_dword(dev, REG_MEM_LIM, val32: &val32); |
157 | if (val32 & MEM_LIMIT_MASK) { |
158 | printk(KERN_INFO "Error(s) in mem limit register " |
159 | "on %s bridge\n" , dev_info->ctl_name); |
160 | printk(KERN_INFO "DPE: %d, RSE: %d, RMA: %d\n" |
161 | "RTA: %d, STA: %d, MDPE: %d\n" , |
162 | val32 & MEM_LIMIT_DPE, |
163 | val32 & MEM_LIMIT_RSE, |
164 | val32 & MEM_LIMIT_RMA, |
165 | val32 & MEM_LIMIT_RTA, |
166 | val32 & MEM_LIMIT_STA, |
167 | val32 & MEM_LIMIT_MDPE); |
168 | |
169 | val32 |= MEM_LIMIT_MASK; |
170 | edac_pci_write_dword(dev, REG_MEM_LIM, val32); |
171 | |
172 | edac_pci_handle_npe(pci: edac_dev, msg: edac_dev->ctl_name); |
173 | } |
174 | |
175 | /* Check if Discard Timer timed out */ |
176 | edac_pci_read_dword(dev, REG_INT_CTLR, val32: &val32); |
177 | if (val32 & INT_CTLR_DTS) { |
178 | printk(KERN_INFO "Error(s) in interrupt and control register " |
179 | "on %s bridge\n" , dev_info->ctl_name); |
180 | printk(KERN_INFO "DTS: %d\n" , val32 & INT_CTLR_DTS); |
181 | |
182 | val32 |= INT_CTLR_DTS; |
183 | edac_pci_write_dword(dev, REG_INT_CTLR, val32); |
184 | |
185 | edac_pci_handle_npe(pci: edac_dev, msg: edac_dev->ctl_name); |
186 | } |
187 | |
188 | /* Check if CRC error happens on link side A */ |
189 | edac_pci_read_dword(dev, REG_LNK_CTRL_A, val32: &val32); |
190 | if (val32 & LNK_CTRL_CRCERR_A) { |
191 | printk(KERN_INFO "Error(s) in link conf and control register " |
192 | "on %s bridge\n" , dev_info->ctl_name); |
193 | printk(KERN_INFO "CRCERR: %d\n" , val32 & LNK_CTRL_CRCERR_A); |
194 | |
195 | val32 |= LNK_CTRL_CRCERR_A; |
196 | edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32); |
197 | |
198 | edac_pci_handle_npe(pci: edac_dev, msg: edac_dev->ctl_name); |
199 | } |
200 | |
201 | /* Check if CRC error happens on link side B */ |
202 | edac_pci_read_dword(dev, REG_LNK_CTRL_B, val32: &val32); |
203 | if (val32 & LNK_CTRL_CRCERR_B) { |
204 | printk(KERN_INFO "Error(s) in link conf and control register " |
205 | "on %s bridge\n" , dev_info->ctl_name); |
206 | printk(KERN_INFO "CRCERR: %d\n" , val32 & LNK_CTRL_CRCERR_B); |
207 | |
208 | val32 |= LNK_CTRL_CRCERR_B; |
209 | edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32); |
210 | |
211 | edac_pci_handle_npe(pci: edac_dev, msg: edac_dev->ctl_name); |
212 | } |
213 | } |
214 | |
215 | static struct amd8131_info amd8131_chipset = { |
216 | .err_dev = PCI_DEVICE_ID_AMD_8131_APIC, |
217 | .devices = amd8131_devices, |
218 | .init = amd8131_pcix_init, |
219 | .exit = amd8131_pcix_exit, |
220 | .check = amd8131_pcix_check, |
221 | }; |
222 | |
223 | /* |
224 | * There are 4 PCIX Bridges on ATCA-6101 that share the same PCI Device ID, |
225 | * so amd8131_probe() would be called by kernel 4 times, with different |
226 | * address of pci_dev for each of them each time. |
227 | */ |
228 | static int amd8131_probe(struct pci_dev *dev, const struct pci_device_id *id) |
229 | { |
230 | struct amd8131_dev_info *dev_info; |
231 | |
232 | for (dev_info = amd8131_chipset.devices; dev_info->inst != NO_BRIDGE; |
233 | dev_info++) |
234 | if (dev_info->devfn == dev->devfn) |
235 | break; |
236 | |
237 | if (dev_info->inst == NO_BRIDGE) /* should never happen */ |
238 | return -ENODEV; |
239 | |
240 | /* |
241 | * We can't call pci_get_device() as we are used to do because |
242 | * there are 4 of them but pci_dev_get() instead. |
243 | */ |
244 | dev_info->dev = pci_dev_get(dev); |
245 | |
246 | if (pci_enable_device(dev: dev_info->dev)) { |
247 | pci_dev_put(dev: dev_info->dev); |
248 | printk(KERN_ERR "failed to enable:" |
249 | "vendor %x, device %x, devfn %x, name %s\n" , |
250 | PCI_VENDOR_ID_AMD, amd8131_chipset.err_dev, |
251 | dev_info->devfn, dev_info->ctl_name); |
252 | return -ENODEV; |
253 | } |
254 | |
255 | /* |
256 | * we do not allocate extra private structure for |
257 | * edac_pci_ctl_info, but make use of existing |
258 | * one instead. |
259 | */ |
260 | dev_info->edac_idx = edac_pci_alloc_index(); |
261 | dev_info->edac_dev = edac_pci_alloc_ctl_info(sz_pvt: 0, edac_pci_name: dev_info->ctl_name); |
262 | if (!dev_info->edac_dev) |
263 | return -ENOMEM; |
264 | |
265 | dev_info->edac_dev->pvt_info = dev_info; |
266 | dev_info->edac_dev->dev = &dev_info->dev->dev; |
267 | dev_info->edac_dev->mod_name = AMD8131_EDAC_MOD_STR; |
268 | dev_info->edac_dev->ctl_name = dev_info->ctl_name; |
269 | dev_info->edac_dev->dev_name = dev_name(dev: &dev_info->dev->dev); |
270 | |
271 | if (edac_op_state == EDAC_OPSTATE_POLL) |
272 | dev_info->edac_dev->edac_check = amd8131_chipset.check; |
273 | |
274 | if (amd8131_chipset.init) |
275 | amd8131_chipset.init(dev_info); |
276 | |
277 | if (edac_pci_add_device(pci: dev_info->edac_dev, edac_idx: dev_info->edac_idx) > 0) { |
278 | printk(KERN_ERR "failed edac_pci_add_device() for %s\n" , |
279 | dev_info->ctl_name); |
280 | edac_pci_free_ctl_info(pci: dev_info->edac_dev); |
281 | return -ENODEV; |
282 | } |
283 | |
284 | printk(KERN_INFO "added one device on AMD8131 " |
285 | "vendor %x, device %x, devfn %x, name %s\n" , |
286 | PCI_VENDOR_ID_AMD, amd8131_chipset.err_dev, |
287 | dev_info->devfn, dev_info->ctl_name); |
288 | |
289 | return 0; |
290 | } |
291 | |
292 | static void amd8131_remove(struct pci_dev *dev) |
293 | { |
294 | struct amd8131_dev_info *dev_info; |
295 | |
296 | for (dev_info = amd8131_chipset.devices; dev_info->inst != NO_BRIDGE; |
297 | dev_info++) |
298 | if (dev_info->devfn == dev->devfn) |
299 | break; |
300 | |
301 | if (dev_info->inst == NO_BRIDGE) /* should never happen */ |
302 | return; |
303 | |
304 | if (dev_info->edac_dev) { |
305 | edac_pci_del_device(dev: dev_info->edac_dev->dev); |
306 | edac_pci_free_ctl_info(pci: dev_info->edac_dev); |
307 | } |
308 | |
309 | if (amd8131_chipset.exit) |
310 | amd8131_chipset.exit(dev_info); |
311 | |
312 | pci_dev_put(dev: dev_info->dev); |
313 | } |
314 | |
315 | static const struct pci_device_id amd8131_edac_pci_tbl[] = { |
316 | { |
317 | PCI_VEND_DEV(AMD, 8131_BRIDGE), |
318 | .subvendor = PCI_ANY_ID, |
319 | .subdevice = PCI_ANY_ID, |
320 | .class = 0, |
321 | .class_mask = 0, |
322 | .driver_data = 0, |
323 | }, |
324 | { |
325 | 0, |
326 | } /* table is NULL-terminated */ |
327 | }; |
328 | MODULE_DEVICE_TABLE(pci, amd8131_edac_pci_tbl); |
329 | |
330 | static struct pci_driver amd8131_edac_driver = { |
331 | .name = AMD8131_EDAC_MOD_STR, |
332 | .probe = amd8131_probe, |
333 | .remove = amd8131_remove, |
334 | .id_table = amd8131_edac_pci_tbl, |
335 | }; |
336 | |
337 | static int __init amd8131_edac_init(void) |
338 | { |
339 | printk(KERN_INFO "AMD8131 EDAC driver " AMD8131_EDAC_REVISION "\n" ); |
340 | printk(KERN_INFO "\t(c) 2008 Wind River Systems, Inc.\n" ); |
341 | |
342 | /* Only POLL mode supported so far */ |
343 | edac_op_state = EDAC_OPSTATE_POLL; |
344 | |
345 | return pci_register_driver(&amd8131_edac_driver); |
346 | } |
347 | |
348 | static void __exit amd8131_edac_exit(void) |
349 | { |
350 | pci_unregister_driver(dev: &amd8131_edac_driver); |
351 | } |
352 | |
353 | module_init(amd8131_edac_init); |
354 | module_exit(amd8131_edac_exit); |
355 | |
356 | MODULE_LICENSE("GPL" ); |
357 | MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>" ); |
358 | MODULE_DESCRIPTION("AMD8131 HyperTransport PCI-X Tunnel EDAC kernel module" ); |
359 | |