RE: [PATCH 2/3] soc: sifive: beu: Add support for SiFive Bus Error Unit

2020-12-09 Thread Yash Shah
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

2020-11-12 Thread Yash Shah
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,
+