Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2012 Cavium, Inc.
0007  * Copyright (C) 2009 Wind River Systems,
0008  *   written by Ralf Baechle <ralf@linux-mips.org>
0009  */
0010 #include <linux/module.h>
0011 #include <linux/init.h>
0012 #include <linux/slab.h>
0013 #include <linux/io.h>
0014 #include <linux/edac.h>
0015 
0016 #include <asm/octeon/cvmx.h>
0017 #include <asm/octeon/cvmx-npi-defs.h>
0018 #include <asm/octeon/cvmx-pci-defs.h>
0019 #include <asm/octeon/octeon.h>
0020 
0021 #include "edac_module.h"
0022 
0023 static void octeon_pci_poll(struct edac_pci_ctl_info *pci)
0024 {
0025     union cvmx_pci_cfg01 cfg01;
0026 
0027     cfg01.u32 = octeon_npi_read32(CVMX_NPI_PCI_CFG01);
0028     if (cfg01.s.dpe) {      /* Detected parity error */
0029         edac_pci_handle_pe(pci, pci->ctl_name);
0030         cfg01.s.dpe = 1;        /* Reset  */
0031         octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
0032     }
0033     if (cfg01.s.sse) {
0034         edac_pci_handle_npe(pci, "Signaled System Error");
0035         cfg01.s.sse = 1;        /* Reset */
0036         octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
0037     }
0038     if (cfg01.s.rma) {
0039         edac_pci_handle_npe(pci, "Received Master Abort");
0040         cfg01.s.rma = 1;        /* Reset */
0041         octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
0042     }
0043     if (cfg01.s.rta) {
0044         edac_pci_handle_npe(pci, "Received Target Abort");
0045         cfg01.s.rta = 1;        /* Reset */
0046         octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
0047     }
0048     if (cfg01.s.sta) {
0049         edac_pci_handle_npe(pci, "Signaled Target Abort");
0050         cfg01.s.sta = 1;        /* Reset */
0051         octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
0052     }
0053     if (cfg01.s.mdpe) {
0054         edac_pci_handle_npe(pci, "Master Data Parity Error");
0055         cfg01.s.mdpe = 1;       /* Reset */
0056         octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
0057     }
0058 }
0059 
0060 static int octeon_pci_probe(struct platform_device *pdev)
0061 {
0062     struct edac_pci_ctl_info *pci;
0063     int res = 0;
0064 
0065     pci = edac_pci_alloc_ctl_info(0, "octeon_pci_err");
0066     if (!pci)
0067         return -ENOMEM;
0068 
0069     pci->dev = &pdev->dev;
0070     platform_set_drvdata(pdev, pci);
0071     pci->dev_name = dev_name(&pdev->dev);
0072 
0073     pci->mod_name = "octeon-pci";
0074     pci->ctl_name = "octeon_pci_err";
0075     pci->edac_check = octeon_pci_poll;
0076 
0077     if (edac_pci_add_device(pci, 0) > 0) {
0078         pr_err("%s: edac_pci_add_device() failed\n", __func__);
0079         goto err;
0080     }
0081 
0082     return 0;
0083 
0084 err:
0085     edac_pci_free_ctl_info(pci);
0086 
0087     return res;
0088 }
0089 
0090 static int octeon_pci_remove(struct platform_device *pdev)
0091 {
0092     struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
0093 
0094     edac_pci_del_device(&pdev->dev);
0095     edac_pci_free_ctl_info(pci);
0096 
0097     return 0;
0098 }
0099 
0100 static struct platform_driver octeon_pci_driver = {
0101     .probe = octeon_pci_probe,
0102     .remove = octeon_pci_remove,
0103     .driver = {
0104            .name = "octeon_pci_edac",
0105     }
0106 };
0107 module_platform_driver(octeon_pci_driver);
0108 
0109 MODULE_LICENSE("GPL");
0110 MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");