1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * amd8111_edac.c, AMD8111 Hyper Transport 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/bitops.h>
16#include <linux/edac.h>
17#include <linux/pci_ids.h>
18#include <asm/io.h>
19
20#include "edac_module.h"
21#include "amd8111_edac.h"
22
23#define AMD8111_EDAC_REVISION	" Ver: 1.0.0"
24#define AMD8111_EDAC_MOD_STR	"amd8111_edac"
25
26#define PCI_DEVICE_ID_AMD_8111_PCI	0x7460
27
28enum amd8111_edac_devs {
29	LPC_BRIDGE = 0,
30};
31
32enum amd8111_edac_pcis {
33	PCI_BRIDGE = 0,
34};
35
36/* Wrapper functions for accessing PCI configuration space */
37static int edac_pci_read_dword(struct pci_dev *dev, int reg, u32 *val32)
38{
39	int ret;
40
41	ret = pci_read_config_dword(dev, reg, val32);
42	if (ret != 0)
43		printk(KERN_ERR AMD8111_EDAC_MOD_STR
44			" PCI Access Read Error at 0x%x\n", reg);
45
46	return ret;
47}
48
49static void edac_pci_read_byte(struct pci_dev *dev, int reg, u8 *val8)
50{
51	int ret;
52
53	ret = pci_read_config_byte(dev, reg, val8);
54	if (ret != 0)
55		printk(KERN_ERR AMD8111_EDAC_MOD_STR
56			" PCI Access Read Error at 0x%x\n", reg);
57}
58
59static void edac_pci_write_dword(struct pci_dev *dev, int reg, u32 val32)
60{
61	int ret;
62
63	ret = pci_write_config_dword(dev, reg, val32);
64	if (ret != 0)
65		printk(KERN_ERR AMD8111_EDAC_MOD_STR
66			" PCI Access Write Error at 0x%x\n", reg);
67}
68
69static void edac_pci_write_byte(struct pci_dev *dev, int reg, u8 val8)
70{
71	int ret;
72
73	ret = pci_write_config_byte(dev, reg, val8);
74	if (ret != 0)
75		printk(KERN_ERR AMD8111_EDAC_MOD_STR
76			" PCI Access Write Error at 0x%x\n", reg);
77}
78
79/*
80 * device-specific methods for amd8111 PCI Bridge Controller
81 *
82 * Error Reporting and Handling for amd8111 chipset could be found
83 * in its datasheet 3.1.2 section, P37
84 */
85static void amd8111_pci_bridge_init(struct amd8111_pci_info *pci_info)
86{
87	u32 val32;
88	struct pci_dev *dev = pci_info->dev;
89
90	/* First clear error detection flags on the host interface */
91
92	/* Clear SSE/SMA/STA flags in the global status register*/
93	edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
94	if (val32 & PCI_STSCMD_CLEAR_MASK)
95		edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
96
97	/* Clear CRC and Link Fail flags in HT Link Control reg */
98	edac_pci_read_dword(dev, REG_HT_LINK, &val32);
99	if (val32 & HT_LINK_CLEAR_MASK)
100		edac_pci_write_dword(dev, REG_HT_LINK, val32);
101
102	/* Second clear all fault on the secondary interface */
103
104	/* Clear error flags in the memory-base limit reg. */
105	edac_pci_read_dword(dev, REG_MEM_LIM, &val32);
106	if (val32 & MEM_LIMIT_CLEAR_MASK)
107		edac_pci_write_dword(dev, REG_MEM_LIM, val32);
108
109	/* Clear Discard Timer Expired flag in Interrupt/Bridge Control reg */
110	edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
111	if (val32 & PCI_INTBRG_CTRL_CLEAR_MASK)
112		edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
113
114	/* Last enable error detections */
115	if (edac_op_state == EDAC_OPSTATE_POLL) {
116		/* Enable System Error reporting in global status register */
117		edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
118		val32 |= PCI_STSCMD_SERREN;
119		edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
120
121		/* Enable CRC Sync flood packets to HyperTransport Link */
122		edac_pci_read_dword(dev, REG_HT_LINK, &val32);
123		val32 |= HT_LINK_CRCFEN;
124		edac_pci_write_dword(dev, REG_HT_LINK, val32);
125
126		/* Enable SSE reporting etc in Interrupt control reg */
127		edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
128		val32 |= PCI_INTBRG_CTRL_POLL_MASK;
129		edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
130	}
131}
132
133static void amd8111_pci_bridge_exit(struct amd8111_pci_info *pci_info)
134{
135	u32 val32;
136	struct pci_dev *dev = pci_info->dev;
137
138	if (edac_op_state == EDAC_OPSTATE_POLL) {
139		/* Disable System Error reporting */
140		edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
141		val32 &= ~PCI_STSCMD_SERREN;
142		edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
143
144		/* Disable CRC flood packets */
145		edac_pci_read_dword(dev, REG_HT_LINK, &val32);
146		val32 &= ~HT_LINK_CRCFEN;
147		edac_pci_write_dword(dev, REG_HT_LINK, val32);
148
149		/* Disable DTSERREN/MARSP/SERREN in Interrupt Control reg */
150		edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
151		val32 &= ~PCI_INTBRG_CTRL_POLL_MASK;
152		edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
153	}
154}
155
156static void amd8111_pci_bridge_check(struct edac_pci_ctl_info *edac_dev)
157{
158	struct amd8111_pci_info *pci_info = edac_dev->pvt_info;
159	struct pci_dev *dev = pci_info->dev;
160	u32 val32;
161
162	/* Check out PCI Bridge Status and Command Register */
163	edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
164	if (val32 & PCI_STSCMD_CLEAR_MASK) {
165		printk(KERN_INFO "Error(s) in PCI bridge status and command"
166			"register on device %s\n", pci_info->ctl_name);
167		printk(KERN_INFO "SSE: %d, RMA: %d, RTA: %d\n",
168			(val32 & PCI_STSCMD_SSE) != 0,
169			(val32 & PCI_STSCMD_RMA) != 0,
170			(val32 & PCI_STSCMD_RTA) != 0);
171
172		val32 |= PCI_STSCMD_CLEAR_MASK;
173		edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
174
175		edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
176	}
177
178	/* Check out HyperTransport Link Control Register */
179	edac_pci_read_dword(dev, REG_HT_LINK, &val32);
180	if (val32 & HT_LINK_LKFAIL) {
181		printk(KERN_INFO "Error(s) in hypertransport link control"
182			"register on device %s\n", pci_info->ctl_name);
183		printk(KERN_INFO "LKFAIL: %d\n",
184			(val32 & HT_LINK_LKFAIL) != 0);
185
186		val32 |= HT_LINK_LKFAIL;
187		edac_pci_write_dword(dev, REG_HT_LINK, val32);
188
189		edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
190	}
191
192	/* Check out PCI Interrupt and Bridge Control Register */
193	edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
194	if (val32 & PCI_INTBRG_CTRL_DTSTAT) {
195		printk(KERN_INFO "Error(s) in PCI interrupt and bridge control"
196			"register on device %s\n", pci_info->ctl_name);
197		printk(KERN_INFO "DTSTAT: %d\n",
198			(val32 & PCI_INTBRG_CTRL_DTSTAT) != 0);
199
200		val32 |= PCI_INTBRG_CTRL_DTSTAT;
201		edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
202
203		edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
204	}
205
206	/* Check out PCI Bridge Memory Base-Limit Register */
207	edac_pci_read_dword(dev, REG_MEM_LIM, &val32);
208	if (val32 & MEM_LIMIT_CLEAR_MASK) {
209		printk(KERN_INFO
210			"Error(s) in mem limit register on %s device\n",
211			pci_info->ctl_name);
212		printk(KERN_INFO "DPE: %d, RSE: %d, RMA: %d\n"
213			"RTA: %d, STA: %d, MDPE: %d\n",
214			(val32 & MEM_LIMIT_DPE)  != 0,
215			(val32 & MEM_LIMIT_RSE)  != 0,
216			(val32 & MEM_LIMIT_RMA)  != 0,
217			(val32 & MEM_LIMIT_RTA)  != 0,
218			(val32 & MEM_LIMIT_STA)  != 0,
219			(val32 & MEM_LIMIT_MDPE) != 0);
220
221		val32 |= MEM_LIMIT_CLEAR_MASK;
222		edac_pci_write_dword(dev, REG_MEM_LIM, val32);
223
224		edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
225	}
226}
227
228static struct resource *legacy_io_res;
229static int at_compat_reg_broken;
230#define LEGACY_NR_PORTS	1
231
232/* device-specific methods for amd8111 LPC Bridge device */
233static void amd8111_lpc_bridge_init(struct amd8111_dev_info *dev_info)
234{
235	u8 val8;
236	struct pci_dev *dev = dev_info->dev;
237
238	/* First clear REG_AT_COMPAT[SERR, IOCHK] if necessary */
239	legacy_io_res = request_region(REG_AT_COMPAT, LEGACY_NR_PORTS,
240					AMD8111_EDAC_MOD_STR);
241	if (!legacy_io_res)
242		printk(KERN_INFO "%s: failed to request legacy I/O region "
243			"start %d, len %d\n", __func__,
244			REG_AT_COMPAT, LEGACY_NR_PORTS);
245	else {
246		val8 = __do_inb(REG_AT_COMPAT);
247		if (val8 == 0xff) { /* buggy port */
248			printk(KERN_INFO "%s: port %d is buggy, not supported"
249				" by hardware?\n", __func__, REG_AT_COMPAT);
250			at_compat_reg_broken = 1;
251			release_region(REG_AT_COMPAT, LEGACY_NR_PORTS);
252			legacy_io_res = NULL;
253		} else {
254			u8 out8 = 0;
255			if (val8 & AT_COMPAT_SERR)
256				out8 = AT_COMPAT_CLRSERR;
257			if (val8 & AT_COMPAT_IOCHK)
258				out8 |= AT_COMPAT_CLRIOCHK;
259			if (out8 > 0)
260				__do_outb(out8, REG_AT_COMPAT);
261		}
262	}
263
264	/* Second clear error flags on LPC bridge */
265	edac_pci_read_byte(dev, REG_IO_CTRL_1, &val8);
266	if (val8 & IO_CTRL_1_CLEAR_MASK)
267		edac_pci_write_byte(dev, REG_IO_CTRL_1, val8);
268}
269
270static void amd8111_lpc_bridge_exit(struct amd8111_dev_info *dev_info)
271{
272	if (legacy_io_res)
273		release_region(REG_AT_COMPAT, LEGACY_NR_PORTS);
274}
275
276static void amd8111_lpc_bridge_check(struct edac_device_ctl_info *edac_dev)
277{
278	struct amd8111_dev_info *dev_info = edac_dev->pvt_info;
279	struct pci_dev *dev = dev_info->dev;
280	u8 val8;
281
282	edac_pci_read_byte(dev, REG_IO_CTRL_1, &val8);
283	if (val8 & IO_CTRL_1_CLEAR_MASK) {
284		printk(KERN_INFO
285			"Error(s) in IO control register on %s device\n",
286			dev_info->ctl_name);
287		printk(KERN_INFO "LPC ERR: %d, PW2LPC: %d\n",
288			(val8 & IO_CTRL_1_LPC_ERR) != 0,
289			(val8 & IO_CTRL_1_PW2LPC) != 0);
290
291		val8 |= IO_CTRL_1_CLEAR_MASK;
292		edac_pci_write_byte(dev, REG_IO_CTRL_1, val8);
293
294		edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
295	}
296
297	if (at_compat_reg_broken == 0) {
298		u8 out8 = 0;
299		val8 = __do_inb(REG_AT_COMPAT);
300		if (val8 & AT_COMPAT_SERR)
301			out8 = AT_COMPAT_CLRSERR;
302		if (val8 & AT_COMPAT_IOCHK)
303			out8 |= AT_COMPAT_CLRIOCHK;
304		if (out8 > 0) {
305			__do_outb(out8, REG_AT_COMPAT);
306			edac_device_handle_ue(edac_dev, 0, 0,
307						edac_dev->ctl_name);
308		}
309	}
310}
311
312/* General devices represented by edac_device_ctl_info */
313static struct amd8111_dev_info amd8111_devices[] = {
314	[LPC_BRIDGE] = {
315		.err_dev = PCI_DEVICE_ID_AMD_8111_LPC,
316		.ctl_name = "lpc",
317		.init = amd8111_lpc_bridge_init,
318		.exit = amd8111_lpc_bridge_exit,
319		.check = amd8111_lpc_bridge_check,
320	},
321	{0},
322};
323
324/* PCI controllers represented by edac_pci_ctl_info */
325static struct amd8111_pci_info amd8111_pcis[] = {
326	[PCI_BRIDGE] = {
327		.err_dev = PCI_DEVICE_ID_AMD_8111_PCI,
328		.ctl_name = "AMD8111_PCI_Controller",
329		.init = amd8111_pci_bridge_init,
330		.exit = amd8111_pci_bridge_exit,
331		.check = amd8111_pci_bridge_check,
332	},
333	{0},
334};
335
336static int amd8111_dev_probe(struct pci_dev *dev,
337				const struct pci_device_id *id)
338{
339	struct amd8111_dev_info *dev_info = &amd8111_devices[id->driver_data];
340	int ret = -ENODEV;
341
342	dev_info->dev = pci_get_device(PCI_VENDOR_ID_AMD,
343					dev_info->err_dev, NULL);
344
345	if (!dev_info->dev) {
346		printk(KERN_ERR "EDAC device not found:"
347			"vendor %x, device %x, name %s\n",
348			PCI_VENDOR_ID_AMD, dev_info->err_dev,
349			dev_info->ctl_name);
350		goto err;
351	}
352
353	if (pci_enable_device(dev_info->dev)) {
354		printk(KERN_ERR "failed to enable:"
355			"vendor %x, device %x, name %s\n",
356			PCI_VENDOR_ID_AMD, dev_info->err_dev,
357			dev_info->ctl_name);
358		goto err_dev_put;
359	}
360
361	/*
362	 * we do not allocate extra private structure for
363	 * edac_device_ctl_info, but make use of existing
364	 * one instead.
365	*/
366	dev_info->edac_idx = edac_device_alloc_index();
367	dev_info->edac_dev =
368		edac_device_alloc_ctl_info(0, dev_info->ctl_name, 1,
369					   NULL, 0, 0, dev_info->edac_idx);
370	if (!dev_info->edac_dev) {
371		ret = -ENOMEM;
372		goto err_dev_put;
373	}
374
375	dev_info->edac_dev->pvt_info = dev_info;
376	dev_info->edac_dev->dev = &dev_info->dev->dev;
377	dev_info->edac_dev->mod_name = AMD8111_EDAC_MOD_STR;
378	dev_info->edac_dev->ctl_name = dev_info->ctl_name;
379	dev_info->edac_dev->dev_name = dev_name(&dev_info->dev->dev);
380
381	if (edac_op_state == EDAC_OPSTATE_POLL)
382		dev_info->edac_dev->edac_check = dev_info->check;
383
384	if (dev_info->init)
385		dev_info->init(dev_info);
386
387	if (edac_device_add_device(dev_info->edac_dev) > 0) {
388		printk(KERN_ERR "failed to add edac_dev for %s\n",
389			dev_info->ctl_name);
390		goto err_edac_free_ctl;
391	}
392
393	printk(KERN_INFO "added one edac_dev on AMD8111 "
394		"vendor %x, device %x, name %s\n",
395		PCI_VENDOR_ID_AMD, dev_info->err_dev,
396		dev_info->ctl_name);
397
398	return 0;
399
400err_edac_free_ctl:
401	edac_device_free_ctl_info(dev_info->edac_dev);
402err_dev_put:
403	pci_dev_put(dev_info->dev);
404err:
405	return ret;
406}
407
408static void amd8111_dev_remove(struct pci_dev *dev)
409{
410	struct amd8111_dev_info *dev_info;
411
412	for (dev_info = amd8111_devices; dev_info->err_dev; dev_info++)
413		if (dev_info->dev->device == dev->device)
414			break;
415
416	if (!dev_info->err_dev)	/* should never happen */
417		return;
418
419	if (dev_info->edac_dev) {
420		edac_device_del_device(dev_info->edac_dev->dev);
421		edac_device_free_ctl_info(dev_info->edac_dev);
422	}
423
424	if (dev_info->exit)
425		dev_info->exit(dev_info);
426
427	pci_dev_put(dev_info->dev);
428}
429
430static int amd8111_pci_probe(struct pci_dev *dev,
431				const struct pci_device_id *id)
432{
433	struct amd8111_pci_info *pci_info = &amd8111_pcis[id->driver_data];
434	int ret = -ENODEV;
435
436	pci_info->dev = pci_get_device(PCI_VENDOR_ID_AMD,
437					pci_info->err_dev, NULL);
438
439	if (!pci_info->dev) {
440		printk(KERN_ERR "EDAC device not found:"
441			"vendor %x, device %x, name %s\n",
442			PCI_VENDOR_ID_AMD, pci_info->err_dev,
443			pci_info->ctl_name);
444		goto err;
445	}
446
447	if (pci_enable_device(pci_info->dev)) {
448		printk(KERN_ERR "failed to enable:"
449			"vendor %x, device %x, name %s\n",
450			PCI_VENDOR_ID_AMD, pci_info->err_dev,
451			pci_info->ctl_name);
452		goto err_dev_put;
453	}
454
455	/*
456	 * we do not allocate extra private structure for
457	 * edac_pci_ctl_info, but make use of existing
458	 * one instead.
459	*/
460	pci_info->edac_idx = edac_pci_alloc_index();
461	pci_info->edac_dev = edac_pci_alloc_ctl_info(0, pci_info->ctl_name);
462	if (!pci_info->edac_dev) {
463		ret = -ENOMEM;
464		goto err_dev_put;
465	}
466
467	pci_info->edac_dev->pvt_info = pci_info;
468	pci_info->edac_dev->dev = &pci_info->dev->dev;
469	pci_info->edac_dev->mod_name = AMD8111_EDAC_MOD_STR;
470	pci_info->edac_dev->ctl_name = pci_info->ctl_name;
471	pci_info->edac_dev->dev_name = dev_name(&pci_info->dev->dev);
472
473	if (edac_op_state == EDAC_OPSTATE_POLL)
474		pci_info->edac_dev->edac_check = pci_info->check;
475
476	if (pci_info->init)
477		pci_info->init(pci_info);
478
479	if (edac_pci_add_device(pci_info->edac_dev, pci_info->edac_idx) > 0) {
480		printk(KERN_ERR "failed to add edac_pci for %s\n",
481			pci_info->ctl_name);
482		goto err_edac_free_ctl;
483	}
484
485	printk(KERN_INFO "added one edac_pci on AMD8111 "
486		"vendor %x, device %x, name %s\n",
487		PCI_VENDOR_ID_AMD, pci_info->err_dev,
488		pci_info->ctl_name);
489
490	return 0;
491
492err_edac_free_ctl:
493	edac_pci_free_ctl_info(pci_info->edac_dev);
494err_dev_put:
495	pci_dev_put(pci_info->dev);
496err:
497	return ret;
498}
499
500static void amd8111_pci_remove(struct pci_dev *dev)
501{
502	struct amd8111_pci_info *pci_info;
503
504	for (pci_info = amd8111_pcis; pci_info->err_dev; pci_info++)
505		if (pci_info->dev->device == dev->device)
506			break;
507
508	if (!pci_info->err_dev)	/* should never happen */
509		return;
510
511	if (pci_info->edac_dev) {
512		edac_pci_del_device(pci_info->edac_dev->dev);
513		edac_pci_free_ctl_info(pci_info->edac_dev);
514	}
515
516	if (pci_info->exit)
517		pci_info->exit(pci_info);
518
519	pci_dev_put(pci_info->dev);
520}
521
522/* PCI Device ID talbe for general EDAC device */
523static const struct pci_device_id amd8111_edac_dev_tbl[] = {
524	{
525	PCI_VEND_DEV(AMD, 8111_LPC),
526	.subvendor = PCI_ANY_ID,
527	.subdevice = PCI_ANY_ID,
528	.class = 0,
529	.class_mask = 0,
530	.driver_data = LPC_BRIDGE,
531	},
532	{
533	0,
534	}			/* table is NULL-terminated */
535};
536MODULE_DEVICE_TABLE(pci, amd8111_edac_dev_tbl);
537
538static struct pci_driver amd8111_edac_dev_driver = {
539	.name = "AMD8111_EDAC_DEV",
540	.probe = amd8111_dev_probe,
541	.remove = amd8111_dev_remove,
542	.id_table = amd8111_edac_dev_tbl,
543};
544
545/* PCI Device ID table for EDAC PCI controller */
546static const struct pci_device_id amd8111_edac_pci_tbl[] = {
547	{
548	PCI_VEND_DEV(AMD, 8111_PCI),
549	.subvendor = PCI_ANY_ID,
550	.subdevice = PCI_ANY_ID,
551	.class = 0,
552	.class_mask = 0,
553	.driver_data = PCI_BRIDGE,
554	},
555	{
556	0,
557	}			/* table is NULL-terminated */
558};
559MODULE_DEVICE_TABLE(pci, amd8111_edac_pci_tbl);
560
561static struct pci_driver amd8111_edac_pci_driver = {
562	.name = "AMD8111_EDAC_PCI",
563	.probe = amd8111_pci_probe,
564	.remove = amd8111_pci_remove,
565	.id_table = amd8111_edac_pci_tbl,
566};
567
568static int __init amd8111_edac_init(void)
569{
570	int val;
571
572	printk(KERN_INFO "AMD8111 EDAC driver "	AMD8111_EDAC_REVISION "\n");
573	printk(KERN_INFO "\t(c) 2008 Wind River Systems, Inc.\n");
574
575	/* Only POLL mode supported so far */
576	edac_op_state = EDAC_OPSTATE_POLL;
577
578	val = pci_register_driver(&amd8111_edac_dev_driver);
579	val |= pci_register_driver(&amd8111_edac_pci_driver);
580
581	return val;
582}
583
584static void __exit amd8111_edac_exit(void)
585{
586	pci_unregister_driver(&amd8111_edac_pci_driver);
587	pci_unregister_driver(&amd8111_edac_dev_driver);
588}
589
590
591module_init(amd8111_edac_init);
592module_exit(amd8111_edac_exit);
593
594MODULE_LICENSE("GPL");
595MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>");
596MODULE_DESCRIPTION("AMD8111 HyperTransport I/O Hub EDAC kernel module");
597