From a61956a6d7e63a2870151dd434b1236a189ad31a Mon Sep 17 00:00:00 2001
From: Ashokkumar G <0xfee1dead.sa@gmail.com>
Date: Mon, 26 Jan 2015 12:08:26 -0700
Subject: [PATCH 8/8] arch:arm:mmp:gplugd: Fix gPlugD reboot issue

Board hangs in u-boot after issuing reboot related
commands from Linux console due to not resetting
Timer registers in the platform reset function which uses
generic softreset. Fixing the issue by adding board reset
code for gPlugD.

Signed-off-by: Ashokkumar G <0xfee1dead.sa@gmail.com>
---
 arch/arm/mach-mmp/gplugd.c                 | 35 ++++++++++++++++-
 arch/arm/mach-mmp/include/mach/regs-mpmu.h | 62 ++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-mmp/include/mach/regs-mpmu.h

diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index b9c3c9257eec..ec4257ee1d60 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -22,6 +22,8 @@
 #include <mach/irqs.h>
 #include <mach/pxa168.h>
 #include <mach/mfp-pxa168.h>
+#include <mach/regs-mpmu.h>
+#include <mach/regs-timers.h>
 
 #include <uapi/linux/ethtool.h>
 #include <linux/etherdevice.h>
@@ -365,6 +367,37 @@ static struct pxa168_eth_platform_data gplugd_eth_platform_data = {
 	.device_mac  = device_mac_address,
 };
 
+static void gplugd_restart(char mode, const char *cmd)
+{
+#define MPMU_APRR_WDTR	(1<<4)
+	volatile u32 watchdog_virt_base;
+
+	watchdog_virt_base = (u32)TIMERS1_VIRT_BASE;
+	/* negate hardware reset to the WDT after system reset */
+	writel((readl(MPMU_APRR) | MPMU_APRR_WDTR), MPMU_APRR);
+
+	/*disable functional WDT clock */
+	writel(0x1, MPMU_WDTPCR);
+
+	/* clear previous WDT status */
+	writel(0xbaba, (volatile void*)(watchdog_virt_base + TMR_WFAR));
+	writel(0xeb10, (volatile void*)(watchdog_virt_base + TMR_WSAR));
+	writel(0, (volatile void*)(watchdog_virt_base + TMR_WSR));
+
+	/* set match counter */
+	writel(0xbaba, (volatile void*)(watchdog_virt_base + TMR_WFAR));
+	writel(0xeb10, (volatile void*)(watchdog_virt_base + TMR_WSAR));
+	writel(0xf, (volatile void*)(watchdog_virt_base + TMR_WMR));
+
+	/* enable WDT reset */
+	writel(0xbaba, (volatile void*)(watchdog_virt_base + TMR_WFAR));
+	writel(0xeb10, (volatile void*)(watchdog_virt_base + TMR_WSAR));
+	writel(0x3, (volatile void*)(watchdog_virt_base + TMR_WMER));
+
+	/*enable functional WDT clock */
+	writel(0x3, MPMU_WDTPCR);
+}
+
 static void __init gplugd_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(gplugd_pin_config));
@@ -413,5 +446,5 @@ MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform")
 	.init_irq       = pxa168_init_irq,
 	.init_time	= pxa168_timer_init,
 	.init_machine   = gplugd_init,
-	.restart	= pxa168_restart,
+	.restart	= gplugd_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/include/mach/regs-mpmu.h b/arch/arm/mach-mmp/include/mach/regs-mpmu.h
new file mode 100644
index 000000000000..91ecb7899ff0
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/regs-mpmu.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2009, 2010 Marvell International Ltd.
+ *
+ * This file is part of GNU program.
+ *
+ * GNU 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, either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNU 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 http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ *************************************************************************/
+
+/*
+ * linux/arch/arm/mach-mmp/include/mach/regs-mpmu.h
+ *
+ *   Main Power Management Unit
+ */
+
+#ifndef __ASM_MACH_REGS_MPMU_H
+#define __ASM_MACH_REGS_MPMU_H
+
+#include <mach/addr-map.h>
+
+#define MPMU_CPCR	MPMU_REG(0x0000)
+#define MPMU_FCCR	MPMU_REG(0x0008)
+#define MPMU_POCR	MPMU_REG(0x000c)
+#define MPMU_POSR	MPMU_REG(0x0010)
+#define MPMU_SUCCR	MPMU_REG(0x0014)
+#define MPMU_VRCR	MPMU_REG(0x0018)
+#define MPMU_OHCR	MPMU_REG(0x001c)
+#define MPMU_GPCR	MPMU_REG(0x0030)
+#define MPMU_PLL2CR	MPMU_REG(0x0034)
+#define MPMU_SCCR	MPMU_REG(0x0038)
+#define MPMU_CWUCRM	MPMU_REG(0x004c)
+#define MPMU_PLL1_REG1	MPMU_REG(0x0050)
+#define MPMU_PLL1_REG2	MPMU_REG(0x0054)
+#define MPMU_PLL1_SSC	MPMU_REG(0x0058)
+#define MPMU_PLL2_REG1	MPMU_REG(0x0060)
+#define MPMU_PLL2_REG2	MPMU_REG(0x0064)
+#define MPMU_PLL2_SSC	MPMU_REG(0x0068)
+#define MPMU_TS		MPMU_REG(0x0080)
+#define MPMU_WDTPCR	MPMU_REG(0x0200)
+#define MPMU_APCR	MPMU_REG(0x1000)
+#define MPMU_APSR	MPMU_REG(0x1004)
+#define MPMU_APRR	MPMU_REG(0x1020)
+#define MPMU_ACGR	MPMU_REG(0x1024)
+#define MPMU_ARSR	MPMU_REG(0x1028)
+#define MPMU_AWUCRS	MPMU_REG(0x1048)
+#define MPMU_AWUCRM	MPMU_REG(0x104c)
+
+#endif /* __ASM_MACH_REGS_APMU_H */
-- 
2.11.1