Blame view
drivers/edac/highbank_l2_edac.c
3.97 KB
69154d069 edac: add support... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
/* * Copyright 2011-2012 Calxeda, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/types.h> #include <linux/kernel.h> #include <linux/ctype.h> #include <linux/edac.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/of_platform.h> #include "edac_core.h" #include "edac_module.h" #define SR_CLR_SB_ECC_INTR 0x0 #define SR_CLR_DB_ECC_INTR 0x4 struct hb_l2_drvdata { void __iomem *base; int sb_irq; int db_irq; }; static irqreturn_t highbank_l2_err_handler(int irq, void *dev_id) { struct edac_device_ctl_info *dci = dev_id; struct hb_l2_drvdata *drvdata = dci->pvt_info; if (irq == drvdata->sb_irq) { writel(1, drvdata->base + SR_CLR_SB_ECC_INTR); edac_device_handle_ce(dci, 0, 0, dci->ctl_name); } if (irq == drvdata->db_irq) { writel(1, drvdata->base + SR_CLR_DB_ECC_INTR); edac_device_handle_ue(dci, 0, 0, dci->ctl_name); } return IRQ_HANDLED; } |
41ec0e8da edac, highbank: I... |
52 53 54 55 56 |
static const struct of_device_id hb_l2_err_of_match[] = { { .compatible = "calxeda,hb-sregs-l2-ecc", }, {}, }; MODULE_DEVICE_TABLE(of, hb_l2_err_of_match); |
9b3c6e85c Drivers: edac: re... |
57 |
static int highbank_l2_err_probe(struct platform_device *pdev) |
69154d069 edac: add support... |
58 |
{ |
41ec0e8da edac, highbank: I... |
59 |
const struct of_device_id *id; |
69154d069 edac: add support... |
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
struct edac_device_ctl_info *dci; struct hb_l2_drvdata *drvdata; struct resource *r; int res = 0; dci = edac_device_alloc_ctl_info(sizeof(*drvdata), "cpu", 1, "L", 1, 2, NULL, 0, 0); if (!dci) return -ENOMEM; drvdata = dci->pvt_info; dci->dev = &pdev->dev; platform_set_drvdata(pdev, dci); if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) return -ENOMEM; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { dev_err(&pdev->dev, "Unable to get mem resource "); res = -ENODEV; goto err; } if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r), dev_name(&pdev->dev))) { dev_err(&pdev->dev, "Error while requesting mem region "); res = -EBUSY; goto err; } drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (!drvdata->base) { dev_err(&pdev->dev, "Unable to map regs "); res = -ENOMEM; goto err; } |
41ec0e8da edac, highbank: I... |
100 101 102 |
id = of_match_device(hb_l2_err_of_match, &pdev->dev); dci->mod_name = pdev->dev.driver->name; dci->ctl_name = id ? id->compatible : "unknown"; |
a72b8859f edac, highbank: F... |
103 104 105 106 |
dci->dev_name = dev_name(&pdev->dev); if (edac_device_add_device(dci)) goto err; |
69154d069 edac: add support... |
107 108 109 110 111 |
drvdata->db_irq = platform_get_irq(pdev, 0); res = devm_request_irq(&pdev->dev, drvdata->db_irq, highbank_l2_err_handler, 0, dev_name(&pdev->dev), dci); if (res < 0) |
a72b8859f edac, highbank: F... |
112 |
goto err2; |
69154d069 edac: add support... |
113 114 115 116 117 118 |
drvdata->sb_irq = platform_get_irq(pdev, 1); res = devm_request_irq(&pdev->dev, drvdata->sb_irq, highbank_l2_err_handler, 0, dev_name(&pdev->dev), dci); if (res < 0) |
a72b8859f edac, highbank: F... |
119 |
goto err2; |
69154d069 edac: add support... |
120 121 122 |
devres_close_group(&pdev->dev, NULL); return 0; |
a72b8859f edac, highbank: F... |
123 124 |
err2: edac_device_del_device(&pdev->dev); |
69154d069 edac: add support... |
125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
err: devres_release_group(&pdev->dev, NULL); edac_device_free_ctl_info(dci); return res; } static int highbank_l2_err_remove(struct platform_device *pdev) { struct edac_device_ctl_info *dci = platform_get_drvdata(pdev); edac_device_del_device(&pdev->dev); edac_device_free_ctl_info(dci); return 0; } |
69154d069 edac: add support... |
139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
static struct platform_driver highbank_l2_edac_driver = { .probe = highbank_l2_err_probe, .remove = highbank_l2_err_remove, .driver = { .name = "hb_l2_edac", .of_match_table = hb_l2_err_of_match, }, }; module_platform_driver(highbank_l2_edac_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Calxeda, Inc."); MODULE_DESCRIPTION("EDAC Driver for Calxeda Highbank L2 Cache"); |