RE: [PATCH 2/3] soc: sifive: beu: Add support for SiFive Bus Error Unit
Any updates on this patch? - Yash > -Original Message- > From: Yash Shah > Sent: 12 November 2020 17:31 > To: robh...@kernel.org; Paul Walmsley ( Sifive) > ; pal...@dabbelt.com; b...@alien8.de; > mche...@kernel.org; tony.l...@intel.com; james.mo...@arm.com; > r...@kernel.org > Cc: a...@eecs.berkeley.edu; devicet...@vger.kernel.org; linux- > ri...@lists.infradead.org; linux-kernel@vger.kernel.org; linux- > e...@vger.kernel.org; Sachin Ghadi ; Yash > Shah > 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 > --- > 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 000..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 > + * > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define SIFIVE_BEU_CAUSE 0x00 > +#define SIFIVE_BEU_VALUE 0x08 > +#define SIFIVE_BEU_ENABLE0x10 > +#define SIFIVE_BEU_PLIC_INTR 0x18 > +#define SIFIVE_BEU_ACCRUED 0x20 > +#define SIFIVE_BEU_LOCAL_INTR0x28 > + > +#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(_chain, nb); } > + > +int unregister_sifive_beu_error_notifier(struct notifier_block *nb) { > + return atomic_notifier_chain_unregister(_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); >
[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 --- 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 000..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 + * + */ + +#include +#include +#include +#include +#include +#include + +#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_INTERRUPT0 +#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(_chain, nb); +} + +int unregister_sifive_beu_error_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(_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(_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(_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(_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(_chain, SIFIVE_BEU_ERR_TYPE_UE, +