2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2012 Cavium, Inc.
7 * Copyright (C) 2009 Wind River Systems,
8 * written by Ralf Baechle <ralf@linux-mips.org>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/slab.h>
14 #include <linux/edac.h>
16 #include <asm/octeon/cvmx.h>
17 #include <asm/octeon/cvmx-npi-defs.h>
18 #include <asm/octeon/cvmx-pci-defs.h>
19 #include <asm/octeon/octeon.h>
21 #include "edac_core.h"
22 #include "edac_module.h"
24 static void octeon_pci_poll(struct edac_pci_ctl_info
*pci
)
26 union cvmx_pci_cfg01 cfg01
;
28 cfg01
.u32
= octeon_npi_read32(CVMX_NPI_PCI_CFG01
);
29 if (cfg01
.s
.dpe
) { /* Detected parity error */
30 edac_pci_handle_pe(pci
, pci
->ctl_name
);
31 cfg01
.s
.dpe
= 1; /* Reset */
32 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
35 edac_pci_handle_npe(pci
, "Signaled System Error");
36 cfg01
.s
.sse
= 1; /* Reset */
37 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
40 edac_pci_handle_npe(pci
, "Received Master Abort");
41 cfg01
.s
.rma
= 1; /* Reset */
42 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
45 edac_pci_handle_npe(pci
, "Received Target Abort");
46 cfg01
.s
.rta
= 1; /* Reset */
47 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
50 edac_pci_handle_npe(pci
, "Signaled Target Abort");
51 cfg01
.s
.sta
= 1; /* Reset */
52 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
55 edac_pci_handle_npe(pci
, "Master Data Parity Error");
56 cfg01
.s
.mdpe
= 1; /* Reset */
57 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
61 static int octeon_pci_probe(struct platform_device
*pdev
)
63 struct edac_pci_ctl_info
*pci
;
66 pci
= edac_pci_alloc_ctl_info(0, "octeon_pci_err");
70 pci
->dev
= &pdev
->dev
;
71 platform_set_drvdata(pdev
, pci
);
72 pci
->dev_name
= dev_name(&pdev
->dev
);
74 pci
->mod_name
= "octeon-pci";
75 pci
->ctl_name
= "octeon_pci_err";
76 pci
->edac_check
= octeon_pci_poll
;
78 if (edac_pci_add_device(pci
, 0) > 0) {
79 pr_err("%s: edac_pci_add_device() failed\n", __func__
);
86 edac_pci_free_ctl_info(pci
);
91 static int octeon_pci_remove(struct platform_device
*pdev
)
93 struct edac_pci_ctl_info
*pci
= platform_get_drvdata(pdev
);
95 edac_pci_del_device(&pdev
->dev
);
96 edac_pci_free_ctl_info(pci
);
101 static struct platform_driver octeon_pci_driver
= {
102 .probe
= octeon_pci_probe
,
103 .remove
= octeon_pci_remove
,
105 .name
= "octeon_pci_edac",
108 module_platform_driver(octeon_pci_driver
);
110 MODULE_LICENSE("GPL");
111 MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");