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_module.h"
23 static void octeon_pci_poll(struct edac_pci_ctl_info
*pci
)
25 union cvmx_pci_cfg01 cfg01
;
27 cfg01
.u32
= octeon_npi_read32(CVMX_NPI_PCI_CFG01
);
28 if (cfg01
.s
.dpe
) { /* Detected parity error */
29 edac_pci_handle_pe(pci
, pci
->ctl_name
);
30 cfg01
.s
.dpe
= 1; /* Reset */
31 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
34 edac_pci_handle_npe(pci
, "Signaled System Error");
35 cfg01
.s
.sse
= 1; /* Reset */
36 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
39 edac_pci_handle_npe(pci
, "Received Master Abort");
40 cfg01
.s
.rma
= 1; /* Reset */
41 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
44 edac_pci_handle_npe(pci
, "Received Target Abort");
45 cfg01
.s
.rta
= 1; /* Reset */
46 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
49 edac_pci_handle_npe(pci
, "Signaled Target Abort");
50 cfg01
.s
.sta
= 1; /* Reset */
51 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
54 edac_pci_handle_npe(pci
, "Master Data Parity Error");
55 cfg01
.s
.mdpe
= 1; /* Reset */
56 octeon_npi_write32(CVMX_NPI_PCI_CFG01
, cfg01
.u32
);
60 static int octeon_pci_probe(struct platform_device
*pdev
)
62 struct edac_pci_ctl_info
*pci
;
65 pci
= edac_pci_alloc_ctl_info(0, "octeon_pci_err");
69 pci
->dev
= &pdev
->dev
;
70 platform_set_drvdata(pdev
, pci
);
71 pci
->dev_name
= dev_name(&pdev
->dev
);
73 pci
->mod_name
= "octeon-pci";
74 pci
->ctl_name
= "octeon_pci_err";
75 pci
->edac_check
= octeon_pci_poll
;
77 if (edac_pci_add_device(pci
, 0) > 0) {
78 pr_err("%s: edac_pci_add_device() failed\n", __func__
);
85 edac_pci_free_ctl_info(pci
);
90 static int octeon_pci_remove(struct platform_device
*pdev
)
92 struct edac_pci_ctl_info
*pci
= platform_get_drvdata(pdev
);
94 edac_pci_del_device(&pdev
->dev
);
95 edac_pci_free_ctl_info(pci
);
100 static struct platform_driver octeon_pci_driver
= {
101 .probe
= octeon_pci_probe
,
102 .remove
= octeon_pci_remove
,
104 .name
= "octeon_pci_edac",
107 module_platform_driver(octeon_pci_driver
);
109 MODULE_LICENSE("GPL");
110 MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");