^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2012 Cavium, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2009 Wind River Systems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * written by Ralf Baechle <ralf@linux-mips.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/edac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/octeon/cvmx.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/octeon/cvmx-npi-defs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/octeon/cvmx-pci-defs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/octeon/octeon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "edac_module.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static void octeon_pci_poll(struct edac_pci_ctl_info *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) union cvmx_pci_cfg01 cfg01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) cfg01.u32 = octeon_npi_read32(CVMX_NPI_PCI_CFG01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (cfg01.s.dpe) { /* Detected parity error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) edac_pci_handle_pe(pci, pci->ctl_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) cfg01.s.dpe = 1; /* Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (cfg01.s.sse) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) edac_pci_handle_npe(pci, "Signaled System Error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) cfg01.s.sse = 1; /* Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (cfg01.s.rma) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) edac_pci_handle_npe(pci, "Received Master Abort");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) cfg01.s.rma = 1; /* Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (cfg01.s.rta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) edac_pci_handle_npe(pci, "Received Target Abort");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) cfg01.s.rta = 1; /* Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (cfg01.s.sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) edac_pci_handle_npe(pci, "Signaled Target Abort");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) cfg01.s.sta = 1; /* Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (cfg01.s.mdpe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) edac_pci_handle_npe(pci, "Master Data Parity Error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) cfg01.s.mdpe = 1; /* Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static int octeon_pci_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct edac_pci_ctl_info *pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) pci = edac_pci_alloc_ctl_info(0, "octeon_pci_err");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (!pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) pci->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) platform_set_drvdata(pdev, pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) pci->dev_name = dev_name(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) pci->mod_name = "octeon-pci";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) pci->ctl_name = "octeon_pci_err";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pci->edac_check = octeon_pci_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (edac_pci_add_device(pci, 0) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) pr_err("%s: edac_pci_add_device() failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) edac_pci_free_ctl_info(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int octeon_pci_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) edac_pci_del_device(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) edac_pci_free_ctl_info(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static struct platform_driver octeon_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .probe = octeon_pci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .remove = octeon_pci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .name = "octeon_pci_edac",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) module_platform_driver(octeon_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");