aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorYash Shah <yash.shah@sifive.com>2019-05-06 07:27:06 -0400
committerTony Luck <tony.luck@intel.com>2019-06-20 14:44:36 -0400
commit91abaeaaff35d97e88d2249f69f19db749a19a68 (patch)
tree9173bac76607319c7fdb1587609750b9d7fb04a0 /drivers/edac
parent0042e9e7a5f662d7b8226316369d02c3553d6400 (diff)
EDAC/sifive: Add EDAC platform driver for SiFive SoCs
Add an EDAC driver for SiFive SoCs. The initial version supports ECC event monitoring and reporting through the EDAC framework for the SiFive L2 cache controller. It registers for notifier events from the L2 cache controller driver (arch/riscv/mm/sifive_l2_cache.c) for L2 ECC events. [ bp: Massage commit message. ] Signed-off-by: Yash Shah <yash.shah@sifive.com> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: James Morse <james.morse@arm.com> Cc: Albert Ou <aou@eecs.berkeley.edu> Cc: "David S. Miller" <davem@davemloft.net> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: linux-edac <linux-edac@vger.kernel.org> Cc: linux-riscv@lists.infradead.org Cc: Mauro Carvalho Chehab <mchehab@kernel.org> Cc: Nicolas Ferre <nicolas.ferre@microchip.com> Cc: Palmer Dabbelt <palmer@sifive.com> Cc: "Paul E. McKenney" <paulmck@linux.ibm.com> Cc: Paul Walmsley <paul.walmsley@sifive.com> Cc: sachin.ghadi@sifive.com Link: https://lkml.kernel.org/r/1557142026-15949-2-git-send-email-yash.shah@sifive.com
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/Kconfig6
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/sifive_edac.c119
3 files changed, 126 insertions, 0 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 5e2e0348d460..200c04ce5b0e 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -460,6 +460,12 @@ config EDAC_ALTERA_SDMMC
460 Support for error detection and correction on the 460 Support for error detection and correction on the
461 Altera SDMMC FIFO Memory for Altera SoCs. 461 Altera SDMMC FIFO Memory for Altera SoCs.
462 462
463config EDAC_SIFIVE
464 bool "Sifive platform EDAC driver"
465 depends on EDAC=y && RISCV
466 help
467 Support for error detection and correction on the SiFive SoCs.
468
463config EDAC_SYNOPSYS 469config EDAC_SYNOPSYS
464 tristate "Synopsys DDR Memory Controller" 470 tristate "Synopsys DDR Memory Controller"
465 depends on ARCH_ZYNQ || ARCH_ZYNQMP 471 depends on ARCH_ZYNQ || ARCH_ZYNQMP
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 89ad4a84a0f6..165ca65e1a3a 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_EDAC_OCTEON_PCI) += octeon_edac-pci.o
79obj-$(CONFIG_EDAC_THUNDERX) += thunderx_edac.o 79obj-$(CONFIG_EDAC_THUNDERX) += thunderx_edac.o
80 80
81obj-$(CONFIG_EDAC_ALTERA) += altera_edac.o 81obj-$(CONFIG_EDAC_ALTERA) += altera_edac.o
82obj-$(CONFIG_EDAC_SIFIVE) += sifive_edac.o
82obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o 83obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o
83obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o 84obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o
84obj-$(CONFIG_EDAC_TI) += ti_edac.o 85obj-$(CONFIG_EDAC_TI) += ti_edac.o
diff --git a/drivers/edac/sifive_edac.c b/drivers/edac/sifive_edac.c
new file mode 100644
index 000000000000..413cdb4a591d
--- /dev/null
+++ b/drivers/edac/sifive_edac.c
@@ -0,0 +1,119 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * SiFive Platform EDAC Driver
4 *
5 * Copyright (C) 2018-2019 SiFive, Inc.
6 *
7 * This driver is partially based on octeon_edac-pc.c
8 *
9 */
10#include <linux/edac.h>
11#include <linux/platform_device.h>
12#include "edac_module.h"
13#include <asm/sifive_l2_cache.h>
14
15#define DRVNAME "sifive_edac"
16
17struct sifive_edac_priv {
18 struct notifier_block notifier;
19 struct edac_device_ctl_info *dci;
20};
21
22/**
23 * EDAC error callback
24 *
25 * @event: non-zero if unrecoverable.
26 */
27static
28int ecc_err_event(struct notifier_block *this, unsigned long event, void *ptr)
29{
30 const char *msg = (char *)ptr;
31 struct sifive_edac_priv *p;
32
33 p = container_of(this, struct sifive_edac_priv, notifier);
34
35 if (event == SIFIVE_L2_ERR_TYPE_UE)
36 edac_device_handle_ue(p->dci, 0, 0, msg);
37 else if (event == SIFIVE_L2_ERR_TYPE_CE)
38 edac_device_handle_ce(p->dci, 0, 0, msg);
39
40 return NOTIFY_OK;
41}
42
43static int ecc_register(struct platform_device *pdev)
44{
45 struct sifive_edac_priv *p;
46
47 p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
48 if (!p)
49 return -ENOMEM;
50
51 p->notifier.notifier_call = ecc_err_event;
52 platform_set_drvdata(pdev, p);
53
54 p->dci = edac_device_alloc_ctl_info(0, "sifive_ecc", 1, "sifive_ecc",
55 1, 1, NULL, 0,
56 edac_device_alloc_index());
57 if (IS_ERR(p->dci))
58 return PTR_ERR(p->dci);
59
60 p->dci->dev = &pdev->dev;
61 p->dci->mod_name = "Sifive ECC Manager";
62 p->dci->ctl_name = dev_name(&pdev->dev);
63 p->dci->dev_name = dev_name(&pdev->dev);
64
65 if (edac_device_add_device(p->dci)) {
66 dev_err(p->dci->dev, "failed to register with EDAC core\n");
67 goto err;
68 }
69
70 register_sifive_l2_error_notifier(&p->notifier);
71
72 return 0;
73
74err:
75 edac_device_free_ctl_info(p->dci);
76
77 return -ENXIO;
78}
79
80static int ecc_unregister(struct platform_device *pdev)
81{
82 struct sifive_edac_priv *p = platform_get_drvdata(pdev);
83
84 unregister_sifive_l2_error_notifier(&p->notifier);
85 edac_device_del_device(&pdev->dev);
86 edac_device_free_ctl_info(p->dci);
87
88 return 0;
89}
90
91static struct platform_device *sifive_pdev;
92
93static int __init sifive_edac_init(void)
94{
95 int ret;
96
97 sifive_pdev = platform_device_register_simple(DRVNAME, 0, NULL, 0);
98 if (IS_ERR(sifive_pdev))
99 return PTR_ERR(sifive_pdev);
100
101 ret = ecc_register(sifive_pdev);
102 if (ret)
103 platform_device_unregister(sifive_pdev);
104
105 return ret;
106}
107
108static void __exit sifive_edac_exit(void)
109{
110 ecc_unregister(sifive_pdev);
111 platform_device_unregister(sifive_pdev);
112}
113
114module_init(sifive_edac_init);
115module_exit(sifive_edac_exit);
116
117MODULE_AUTHOR("SiFive Inc.");
118MODULE_DESCRIPTION("SiFive platform EDAC driver");
119MODULE_LICENSE("GPL v2");