Any updates on this patch? - Yash > -----Original Message----- > From: Yash Shah <yash.shah@xxxxxxxxxxxx> > Sent: 12 November 2020 17:31 > To: robh+dt@xxxxxxxxxx; Paul Walmsley ( Sifive) > <paul.walmsley@xxxxxxxxxx>; palmer@xxxxxxxxxxx; bp@xxxxxxxxx; > mchehab@xxxxxxxxxx; tony.luck@xxxxxxxxx; james.morse@xxxxxxx; > rric@xxxxxxxxxx > Cc: aou@xxxxxxxxxxxxxxxxx; devicetree@xxxxxxxxxxxxxxx; linux- > riscv@xxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; linux- > edac@xxxxxxxxxxxxxxx; Sachin Ghadi <sachin.ghadi@xxxxxxxxxxxx>; Yash > Shah <yash.shah@xxxxxxxxxxxx> > Subject: [PATCH 2/3] soc: sifive: beu: Add support for SiFive Bus Error Unit > > Add driver support for Bus Error Unit present in SiFive's FU740 chip. > Currently the driver reports erroneous events only using Platform-level > interrupts. The support for reporting events using hart-local interrupts can > be added in future. > > Signed-off-by: Yash Shah <yash.shah@xxxxxxxxxx> > --- > drivers/soc/sifive/Kconfig | 5 + > drivers/soc/sifive/Makefile | 1 + > drivers/soc/sifive/sifive_beu.c | 197 > ++++++++++++++++++++++++++++++++++++++++ > include/soc/sifive/sifive_beu.h | 16 ++++ > 4 files changed, 219 insertions(+) > create mode 100644 drivers/soc/sifive/sifive_beu.c create mode 100644 > include/soc/sifive/sifive_beu.h > > diff --git a/drivers/soc/sifive/Kconfig b/drivers/soc/sifive/Kconfig index > 58cf8c4..d575fc1 100644 > --- a/drivers/soc/sifive/Kconfig > +++ b/drivers/soc/sifive/Kconfig > @@ -7,4 +7,9 @@ config SIFIVE_L2 > help > Support for the L2 cache controller on SiFive platforms. > > +config SIFIVE_BEU > + bool "Sifive Bus Error Unit" > + help > + Support for the Bus Error Unit on SiFive platforms. > + > endif > diff --git a/drivers/soc/sifive/Makefile b/drivers/soc/sifive/Makefile index > b5caff7..1b43ecd 100644 > --- a/drivers/soc/sifive/Makefile > +++ b/drivers/soc/sifive/Makefile > @@ -1,3 +1,4 @@ > # SPDX-License-Identifier: GPL-2.0 > > obj-$(CONFIG_SIFIVE_L2) += sifive_l2_cache.o > +obj-$(CONFIG_SIFIVE_BEU) += sifive_beu.o > diff --git a/drivers/soc/sifive/sifive_beu.c b/drivers/soc/sifive/sifive_beu.c > new file mode 100644 index 0000000..87b69ba > --- /dev/null > +++ b/drivers/soc/sifive/sifive_beu.c > @@ -0,0 +1,197 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * SiFive Bus Error Unit driver > + * Copyright (C) 2020 SiFive > + * Author: Yash Shah <yash.shah@xxxxxxxxxx> > + * > + */ > + > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/of_platform.h> > +#include <linux/interrupt.h> > +#include <linux/io.h> > +#include <soc/sifive/sifive_beu.h> > + > +#define SIFIVE_BEU_CAUSE 0x00 > +#define SIFIVE_BEU_VALUE 0x08 > +#define SIFIVE_BEU_ENABLE 0x10 > +#define SIFIVE_BEU_PLIC_INTR 0x18 > +#define SIFIVE_BEU_ACCRUED 0x20 > +#define SIFIVE_BEU_LOCAL_INTR 0x28 > + > +#define LOCAL_INTERRUPT 0 > +#define PLIC_INTERRUPT 1 > +#define MAX_ERR_EVENTS 5 > + > +enum beu_err_events { > + RESERVED = -1, > + NO_ERR, > + ITIM_CORR_ECC = 2, > + ITIM_UNCORR_ECC, > + TILINKBUS_ERR = 5, > + DCACHE_CORR_ECC, > + DCACHE_UNCORR_ECC > +}; > + > +static > +int err_events[MAX_ERR_EVENTS] = {ITIM_CORR_ECC, ITIM_UNCORR_ECC, > TILINKBUS_ERR, > + DCACHE_CORR_ECC, > DCACHE_UNCORR_ECC}; > + > +struct beu_sifive_ddata { > + void __iomem *regs; > + int irq; > +}; > + > +static int beu_enable_event(struct beu_sifive_ddata *ddata, > + int event, int intr_type) > +{ > + unsigned char event_mask = BIT(event), val; > + > + val = readb(ddata->regs + SIFIVE_BEU_ENABLE); > + val |= event_mask; > + writeb(val, ddata->regs + SIFIVE_BEU_ENABLE); > + > + if (intr_type == PLIC_INTERRUPT) { > + val = readb(ddata->regs + SIFIVE_BEU_PLIC_INTR); > + val |= event_mask; > + writeb(val, ddata->regs + SIFIVE_BEU_PLIC_INTR); > + } else if (intr_type == LOCAL_INTERRUPT) { > + val = readb(ddata->regs + SIFIVE_BEU_LOCAL_INTR); > + val |= event_mask; > + writeb(event_mask, ddata->regs + SIFIVE_BEU_LOCAL_INTR); > + } > + > + return 0; > +} > + > +static ATOMIC_NOTIFIER_HEAD(beu_chain); > + > +int register_sifive_beu_error_notifier(struct notifier_block *nb) { > + return atomic_notifier_chain_register(&beu_chain, nb); } > + > +int unregister_sifive_beu_error_notifier(struct notifier_block *nb) { > + return atomic_notifier_chain_unregister(&beu_chain, nb); } > + > +static irqreturn_t beu_sifive_irq(int irq, void *data) { > + struct beu_sifive_ddata *ddata = data; > + unsigned char cause, addr; > + > + addr = readb(ddata->regs + SIFIVE_BEU_VALUE); > + cause = readb(ddata->regs + SIFIVE_BEU_CAUSE); > + switch (cause) { > + case NO_ERR: > + break; > + case ITIM_CORR_ECC: > + pr_err("BEU: ITIM ECCFIX @ %d\n", addr); > + atomic_notifier_call_chain(&beu_chain, > SIFIVE_BEU_ERR_TYPE_CE, > + "ITIM ECCFIX"); > + break; > + case ITIM_UNCORR_ECC: > + pr_err("BEU: ITIM ECCFAIL @ %d\n", addr); > + atomic_notifier_call_chain(&beu_chain, > SIFIVE_BEU_ERR_TYPE_UE, > + "ITIM ECCFAIL"); > + break; > + case TILINKBUS_ERR: > + pr_err("BEU: Load or Store TILINK BUS ERR occurred\n"); > + break; > + case DCACHE_CORR_ECC: > + pr_err("BEU: DATACACHE ECCFIX @ %d\n", addr); > + atomic_notifier_call_chain(&beu_chain, > SIFIVE_BEU_ERR_TYPE_CE, > + "DCACHE ECCFIX"); > + break; > + case DCACHE_UNCORR_ECC: > + pr_err("BEU: DATACACHE ECCFAIL @ %d\n", addr); > + atomic_notifier_call_chain(&beu_chain, > SIFIVE_BEU_ERR_TYPE_UE, > + "DCACHE ECCFAIL"); > + break; > + default: > + pr_err("BEU: Unidentified cause\n"); > + break; > + } > + writeb(0, ddata->regs + SIFIVE_BEU_CAUSE); > + writeb(0, ddata->regs + SIFIVE_BEU_ACCRUED); > + > + return IRQ_HANDLED; > +} > + > +static int beu_sifive_probe(struct platform_device *pdev) { > + struct device *dev = &pdev->dev; > + struct beu_sifive_ddata *ddata; > + struct resource *res; > + int ret, i; > + > + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); > + if (!ddata) > + return -ENOMEM; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + ddata->regs = devm_ioremap_resource(dev, res); > + if (IS_ERR(ddata->regs)) { > + dev_err(dev, "Unable to map IO resources\n"); > + return PTR_ERR(ddata->regs); > + } > + > + ddata->irq = platform_get_irq(pdev, 0); > + if (ddata->irq < 0) { > + dev_err(dev, "Unable to find interrupt\n"); > + ret = ddata->irq; > + return ret; > + } > + > + ret = devm_request_irq(dev, ddata->irq, beu_sifive_irq, 0, > + dev_name(dev), ddata); > + if (ret) { > + dev_err(dev, "Unable to request IRQ\n"); > + return ret; > + } > + > + for (i = 0; i < MAX_ERR_EVENTS; i++) { > + ret = beu_enable_event(ddata, err_events[i], > PLIC_INTERRUPT); > + if (ret) { > + dev_err(dev, "Unable to register PLIC interrupt\n"); > + return ret; > + } > + } > + > + platform_set_drvdata(pdev, ddata); > + > + return 0; > +} > + > +static int beu_sifive_remove(struct platform_device *pdev) { > + struct beu_sifive_ddata *ddata = platform_get_drvdata(pdev); > + > + /* Mask all error events */ > + writeb(0, ddata->regs + SIFIVE_BEU_ENABLE); > + writeb(0, ddata->regs + SIFIVE_BEU_PLIC_INTR); > + writeb(0, ddata->regs + SIFIVE_BEU_LOCAL_INTR); > + > + return 0; > +} > + > +static const struct of_device_id beu_sifive_of_match[] = { > + { .compatible = "sifive,beu0" }, > + {}, > +}; > +MODULE_DEVICE_TABLE(of, beu_sifive_of_match); > + > +static struct platform_driver beu_sifive_driver = { > + .probe = beu_sifive_probe, > + .remove = beu_sifive_remove, > + .driver = { > + .name = "beu-sifive", > + .of_match_table = beu_sifive_of_match, > + }, > +}; > +module_platform_driver(beu_sifive_driver); > + > +MODULE_DESCRIPTION("SiFive BEU driver"); MODULE_LICENSE("GPL v2"); > diff --git a/include/soc/sifive/sifive_beu.h b/include/soc/sifive/sifive_beu.h > new file mode 100644 index 0000000..c2ab688 > --- /dev/null > +++ b/include/soc/sifive/sifive_beu.h > @@ -0,0 +1,16 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * SiFive Bus Error unit header file > + * > + */ > + > +#ifndef __SOC_SIFIVE_BEU_H > +#define __SOC_SIFIVE_BEU_H > + > +extern int register_sifive_beu_error_notifier(struct notifier_block > +*nb); extern int unregister_sifive_beu_error_notifier(struct > +notifier_block *nb); > + > +#define SIFIVE_BEU_ERR_TYPE_CE 0 > +#define SIFIVE_BEU_ERR_TYPE_UE 1 > + > +#endif /* __SOC_SIFIVE_BEU_H */ > -- > 2.7.4