[linux-yocto] [PATCH 31/35] drivers/misc/lsi-smmon.c: Updated smmon driver

Daniel Dragomir daniel.dragomir at windriver.com
Thu Nov 13 09:19:58 PST 2014


From: SangeethaRao <sangeetha.rao at lsi.com>

Updated smmon driver such that uncorrectable errors causes
machine_restart instead of kernel panic. Also, setting
persistent register (0xdc) bit 3 to indicate
uncorrectable errors. Updated kconfig such that if EDAC
driver is enabled in Kernel config then smmon driver will
be disabled by default.

Signed-off-by: SangeethaRao <sangeetha.rao at lsi.com>
---
 arch/arm/boot/dts/axm55xx.dtsi |  6 ++++--
 drivers/misc/Kconfig           |  1 +
 drivers/misc/lsi-smmon.c       | 34 ++++++++++++++++++++++++++--------
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/axm55xx.dtsi b/arch/arm/boot/dts/axm55xx.dtsi
index a272110..ace763fc 100644
--- a/arch/arm/boot/dts/axm55xx.dtsi
+++ b/arch/arm/boot/dts/axm55xx.dtsi
@@ -87,14 +87,16 @@
         };
 	sm0: sm0 at 00220000 {
 		compatible = "lsi,smmon";
-		reg = <0 0x00220000 0 0x1000>;
+		reg = <0 0x00220000 0 0x1000>,
+			<0x20 0x10030000 0 0001000>;
 		interrupts = <0 161 4>;
 		status = "disabled";
 	};
 
 	sm1: sm1 at 00220000 {
 		compatible = "lsi,smmon";
-		reg = <0 0x000f0000 0 0x1000>;
+		reg = <0 0x000f0000 0 0x1000>,
+			<0x20 0x10030000 0 0001000>;
 		interrupts = <0 160 4>;
 		status = "disabled";
 	};
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index d7f1432..c6fa981 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -554,6 +554,7 @@ config LSI_NCR
 config LSI_SMMON
 	tristate "LSI System Memory Monitor"
 	depends on ARCH_AXXIA || ACP
+	depends on !EDAC_AXXIA
 	help
 	  Monitor the system memory controllers for errors.
 
diff --git a/drivers/misc/lsi-smmon.c b/drivers/misc/lsi-smmon.c
index d2ceb31..789901c 100644
--- a/drivers/misc/lsi-smmon.c
+++ b/drivers/misc/lsi-smmon.c
@@ -17,17 +17,22 @@
 #include <linux/platform_device.h>
 #include <linux/ratelimit.h>
 #include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/reboot.h>
 
 #include <mach/ncr.h>
 
+#define APB2_SER3_PHY_ADDR        0x002010030000ULL
+#define APB2_SER3_PHY_SIZE   0x1000
+
 static int log = 1;
 module_param(log, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(log, "Log each error to kernel log.");
 
-static int panic_on_fatal = 1;
-module_param(panic_on_fatal, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(panic_on_fatal, "Panic on fatal error.");
-
+static int machineRestart = 1;
+module_param(machineRestart, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(machineRestart, "Machine restart on fatal error.");
 /*
   AXM55xx memory controller interrupt status bits:
 
@@ -129,6 +134,7 @@ struct smmon_attr {
 struct sm_dev {
 	struct platform_device *pdev;
 	u32 region; /* NCR region address */
+	void __iomem *apb2ser3_region;
 	u32 counter[NR_EVENTS];
 };
 
@@ -176,6 +182,7 @@ smmon_isr(int interrupt, void *device)
 {
 	struct sm_dev *sm = device;
 	u32 status;
+	unsigned long setVal;
 	int i;
 
 	if (ncr_read(sm->region, 0x410, 4, &status)) {
@@ -187,10 +194,14 @@ smmon_isr(int interrupt, void *device)
 	for (i = 0; i < NR_EVENTS; ++i) {
 		if ((status & event_mask[i]) != 0) {
 			++sm->counter[i];
-			if (panic_on_fatal && event_logging[i].fatal)
-				panic("%s (%s)\n",
-				      event_logging[i].name,
-				      dev_name(&sm->pdev->dev));
+			if (machineRestart && event_logging[i].fatal) {
+				setVal = readl(sm->apb2ser3_region + 0xdc);
+				/* set bit 3 in pscratch reg */
+				setVal = (setVal) | (0x1 << 3);
+				writel(setVal, sm->apb2ser3_region + 0xdc);
+				pr_info("CPU uncorrectable error\n");
+				machine_restart(NULL);
+			}
 			if (log)
 				printk_ratelimited("%s%s: %s\n",
 						   event_logging[i].level,
@@ -213,6 +224,8 @@ smmon_probe(struct platform_device *pdev)
 	int irq;
 	u32 mask;
 	int rc = 0;
+	struct device_node *np = pdev->dev.of_node;
+
 
 	sm = devm_kzalloc(&pdev->dev, sizeof(*sm), GFP_KERNEL);
 	if (!sm) {
@@ -228,6 +241,11 @@ smmon_probe(struct platform_device *pdev)
 	}
 	sm->region = io->start;
 
+	sm->apb2ser3_region = of_iomap(np, 1);
+	if (!sm->apb2ser3_region)
+		sm->apb2ser3_region = ioremap(APB2_SER3_PHY_ADDR,
+				APB2_SER3_PHY_SIZE);
+
 	/* Disable all memory controller interrupts */
 	mask = 0xffffffff;
 	ncr_write(sm->region, 0x414, 4, &mask);
-- 
1.8.1.4



More information about the linux-yocto mailing list