168 lines
4.8 KiB
Diff
168 lines
4.8 KiB
Diff
From f8a629d4c8eb27b9712ac581cedef05375bc27b4 Mon Sep 17 00:00:00 2001
|
|
From: Yu Ning <ningyu@eswincomputing.com>
|
|
Date: Tue, 30 Jul 2024 11:21:30 +0000
|
|
Subject: [PATCH 020/128] drivers: bus-error: Added SiFive Bus Error driver
|
|
|
|
Signed-off-by: Yu Ning <ningyu@eswincomputing.com>
|
|
Signed-off-by: Darshan Prajapati <darshan.prajapati@einfochips.com>
|
|
Signed-off-by: Pinkesh Vaghela <pinkesh.vaghela@einfochips.com>
|
|
---
|
|
arch/riscv/kernel/Makefile | 1 +
|
|
arch/riscv/kernel/bus_error.c | 132 ++++++++++++++++++++++++++++++++++
|
|
2 files changed, 133 insertions(+)
|
|
create mode 100644 arch/riscv/kernel/bus_error.c
|
|
|
|
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
|
|
index 03968c06258c..7a1afa40c69e 100644
|
|
--- a/arch/riscv/kernel/Makefile
|
|
+++ b/arch/riscv/kernel/Makefile
|
|
@@ -59,6 +59,7 @@ obj-y += stacktrace.o
|
|
obj-y += cacheinfo.o
|
|
obj-y += patch.o
|
|
obj-y += probes/
|
|
+obj-y += bus_error.o
|
|
obj-$(CONFIG_MMU) += vdso.o vdso/
|
|
|
|
obj-$(CONFIG_RISCV_M_MODE) += traps_misaligned.o
|
|
diff --git a/arch/riscv/kernel/bus_error.c b/arch/riscv/kernel/bus_error.c
|
|
new file mode 100644
|
|
index 000000000000..67ea83094fed
|
|
--- /dev/null
|
|
+++ b/arch/riscv/kernel/bus_error.c
|
|
@@ -0,0 +1,132 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+/*
|
|
+ * BUS error monitor of core driver
|
|
+ *
|
|
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
|
|
+ * SPDX-License-Identifier: GPL-2.0
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, version 2.
|
|
+ *
|
|
+ * This program is distributed in the hope that 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 <https://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ * Authors: Yu Ning <ningyu@eswincomputing.com>
|
|
+ */
|
|
+
|
|
+#include <linux/init.h>
|
|
+#include <linux/io.h>
|
|
+#include <linux/of.h>
|
|
+#include <linux/interrupt.h>
|
|
+#include <linux/of_address.h>
|
|
+#include <linux/of_irq.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/slab.h>
|
|
+
|
|
+/**
|
|
+ * @brief Bus error unit register map
|
|
+ * 0x00 : cause of error event
|
|
+ * 0x08 : physical address of error event
|
|
+ * 0x10 : event enable mask
|
|
+ * 0x18 : platform-level interrupt enable mask
|
|
+ * 0x20 : accrued event mask
|
|
+ * 0x28 : hart-local interrupt enable mask
|
|
+ */
|
|
+
|
|
+struct bus_error_device {
|
|
+ struct device *dev;
|
|
+ void __iomem *control;
|
|
+ int plic_irq;
|
|
+};
|
|
+
|
|
+static irqreturn_t bus_error_handle(int irq, void *dev_id)
|
|
+{
|
|
+ struct bus_error_device *bus_err = dev_id;
|
|
+ void __iomem *base = bus_err->control;
|
|
+
|
|
+ printk(KERN_ERR "bus error of cause event: %d, accrued: 0x%x, physical address: 0x%llx\n",
|
|
+ readl(base),readl(base+0x20),readq(base+0x8));
|
|
+
|
|
+ /* clean interrupt */
|
|
+ writel(0,base);
|
|
+ writel(0,base+0x20);
|
|
+
|
|
+ return IRQ_HANDLED;
|
|
+}
|
|
+
|
|
+static const struct of_device_id eswin_bus_error_of_match[] = {
|
|
+ {.compatible = "sifive,buserror", },
|
|
+ { /* sentinel */ }
|
|
+};
|
|
+
|
|
+static int bus_error_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct device *dev = &pdev->dev;
|
|
+ struct device_node *node = pdev->dev.of_node;
|
|
+ struct bus_error_device *bus_err_dev;
|
|
+ int ret;
|
|
+ struct resource *res;
|
|
+
|
|
+ bus_err_dev = devm_kcalloc(dev, 1,
|
|
+ sizeof(struct bus_error_device), GFP_KERNEL);
|
|
+ if (!bus_err_dev)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ bus_err_dev->dev = dev;
|
|
+ dev_set_drvdata(dev, bus_err_dev);
|
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
+ if (!res) {
|
|
+ dev_err(dev, "Error while get mem resource\n");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+ bus_err_dev->control = devm_ioremap_resource(&pdev->dev, res);
|
|
+ if (IS_ERR_OR_NULL(bus_err_dev->control)) {
|
|
+ dev_err(dev, "Fail to get resource %s from 0x%llx!\n",
|
|
+ node->name, res->start);
|
|
+ ret = -EINVAL;
|
|
+ goto free_bus_err_dev;
|
|
+ }
|
|
+ bus_err_dev->plic_irq = platform_get_irq(pdev, 0);
|
|
+ ret = devm_request_irq(dev, bus_err_dev->plic_irq, bus_error_handle,
|
|
+ IRQF_SHARED, dev_name(dev), bus_err_dev);
|
|
+ if (ret) {
|
|
+ dev_err(dev, "Fail to request irq %d \n",
|
|
+ (int)bus_err_dev->plic_irq);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* clean any interrupt before */
|
|
+ writel(0,bus_err_dev->control);
|
|
+ writel(0,bus_err_dev->control+0x20);
|
|
+
|
|
+ /* enable interrupt */
|
|
+ writel(0xee2,bus_err_dev->control+0x18);
|
|
+ writel(0xee2,bus_err_dev->control+0x10);
|
|
+ dev_dbg(dev, "Bus-err unit init OK\n");
|
|
+ return 0;
|
|
+
|
|
+free_bus_err_dev:
|
|
+ return ret;
|
|
+
|
|
+}
|
|
+
|
|
+static struct platform_driver bus_error_driver = {
|
|
+ .probe = bus_error_probe,
|
|
+ .driver = {
|
|
+ .name = "buserror",
|
|
+ .owner = THIS_MODULE,
|
|
+ .of_match_table = of_match_ptr(eswin_bus_error_of_match),},
|
|
+};
|
|
+
|
|
+static int __init init_bus_error_unit(void)
|
|
+{
|
|
+ return platform_driver_register(&bus_error_driver);
|
|
+}
|
|
+
|
|
+subsys_initcall(init_bus_error_unit);
|
|
--
|
|
2.47.0
|
|
|