msm: watchdog: make watchdog a platform device

There are now several conditionals that control how the watchdog
behaves. We have described these in terms cpu_is and machine_is macros.
Instead, convert tunables to platform data so we can keep the driver
clean.

Additionally, since it is a platform device, we can now move the
suspending code to the suspend_noirq function, which leaves the watchdog
on for more of the suspend process.

Change-Id: If47b3abbeeaa40f4e6f0f5d301d0a28efa8d3535
Signed-off-by: Jeff Ohlstein <johlstei@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 312ea46..755132b 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -664,6 +664,7 @@
 		defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
 	&msm9615_qcedev_device,
 #endif
+	&msm9615_device_watchdog,
 };
 
 static void __init msm9615_i2c_init(void)
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-apq8064.c
index 4aa6abe..88ce818 100644
--- a/arch/arm/mach-msm/board-apq8064.c
+++ b/arch/arm/mach-msm/board-apq8064.c
@@ -38,6 +38,7 @@
 #include <linux/bootmem.h>
 #include <asm/setup.h>
 
+#include "msm_watchdog.h"
 #include "board-apq8064.h"
 
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0x600000
@@ -493,6 +494,7 @@
 	&android_pmem_device,
 	&android_pmem_adsp_device,
 	&android_pmem_audio_device,
+	&msm8064_device_watchdog,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -733,6 +735,10 @@
 
 static void __init apq8064_sim_init(void)
 {
+	struct msm_watchdog_pdata *wdog_pdata = (struct msm_watchdog_pdata *)
+		&msm8064_device_watchdog.dev.platform_data;
+
+	wdog_pdata->bark_time = 15000;
 	apq8064_common_init();
 	platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
 }
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 3412539..c264011 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -89,6 +89,7 @@
 #include "rpm_log.h"
 #include "smd_private.h"
 #include "pm-boot.h"
+#include "msm_watchdog.h"
 
 static struct platform_device msm_fm_platform_init = {
 	.name = "iris_fm",
@@ -3757,6 +3758,7 @@
 	&msm_ptm_device,
 #endif
 	&msm_device_dspcrashd_8960,
+	&msm8960_device_watchdog,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -4532,6 +4534,10 @@
 
 static void __init msm8960_sim_init(void)
 {
+	struct msm_watchdog_pdata *wdog_pdata = (struct msm_watchdog_pdata *)
+		&msm8960_device_watchdog.dev.platform_data;
+
+	wdog_pdata->bark_time = 15000;
 	BUG_ON(msm_rpm_init(&msm_rpm_data));
 	BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
 				ARRAY_SIZE(msm_rpmrs_levels)));
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index d3d5ffa..455644f 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -5131,6 +5131,7 @@
 #ifdef CONFIG_ION_MSM
 	&ion_dev,
 #endif
+	&msm8660_device_watchdog,
 };
 
 #ifdef CONFIG_ION_MSM
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index fd2be92..35a69df 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -24,6 +24,7 @@
 #include <mach/dma.h>
 #include "clock.h"
 #include "devices.h"
+#include "msm_watchdog.h"
 
 /* Address of GSBI blocks */
 #define MSM_GSBI1_PHYS		0x12440000
@@ -54,6 +55,20 @@
 #define MSM_HSUSB_PHYS		0x12500000
 #define MSM_HSUSB_SIZE		SZ_4K
 
+static struct msm_watchdog_pdata msm_watchdog_pdata = {
+	.pet_time = 10000,
+	.bark_time = 11000,
+	.has_secure = true,
+};
+
+struct platform_device msm8064_device_watchdog = {
+	.name = "msm_watchdog",
+	.id = -1,
+	.dev = {
+		.platform_data = &msm_watchdog_pdata,
+	},
+};
+
 static struct resource msm_dmov_resource[] = {
 	{
 		.start = ADM_0_SCSS_0_IRQ,
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 899f2e1..ba36f69 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -35,6 +35,7 @@
 #include "devices.h"
 #include "devices-msm8x60.h"
 #include "footswitch.h"
+#include "msm_watchdog.h"
 
 #ifdef CONFIG_MSM_MPM
 #include "mpm.h"
@@ -800,6 +801,20 @@
 	.id		= -1,
 };
 
+static struct msm_watchdog_pdata msm_watchdog_pdata = {
+	.pet_time = 10000,
+	.bark_time = 11000,
+	.has_secure = true,
+};
+
+struct platform_device msm8960_device_watchdog = {
+	.name = "msm_watchdog",
+	.id = -1,
+	.dev = {
+		.platform_data = &msm_watchdog_pdata,
+	},
+};
+
 static struct resource msm_dmov_resource[] = {
 	{
 		.start = ADM_0_SCSS_1_IRQ,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 13772ce..3cf7d48 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -34,6 +34,7 @@
 #include "spm.h"
 #include "pm.h"
 #include "rpm_resources.h"
+#include "msm_watchdog.h"
 
 /* Address of GSBI blocks */
 #define MSM_GSBI1_PHYS          0x16000000
@@ -56,6 +57,20 @@
 #define MSM_PMIC1_SSBI_CMD_PHYS	0x00500000
 #define MSM_PMIC_SSBI_SIZE	SZ_4K
 
+static struct msm_watchdog_pdata msm_watchdog_pdata = {
+	.pet_time = 10000,
+	.bark_time = 11000,
+	.has_secure = true,
+};
+
+struct platform_device msm9615_device_watchdog = {
+	.name = "msm_watchdog",
+	.id = -1,
+	.dev = {
+		.platform_data = &msm_watchdog_pdata,
+	},
+};
+
 static struct resource msm_dmov_resource[] = {
 	{
 		.start = ADM_0_SCSS_1_IRQ,
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 49f3d3b..def2558 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -53,6 +53,7 @@
 #include <sound/apr_audio.h>
 #include "rpm_stats.h"
 #include "mpm.h"
+#include "msm_watchdog.h"
 
 /* Address of GSBI blocks */
 #define MSM_GSBI1_PHYS	0x16000000
@@ -1833,6 +1834,20 @@
 	.id             = -1,
 };
 
+static struct msm_watchdog_pdata msm_watchdog_pdata = {
+	.pet_time = 10000,
+	.bark_time = 11000,
+	.has_secure = true,
+};
+
+struct platform_device msm8660_device_watchdog = {
+	.name = "msm_watchdog",
+	.id = -1,
+	.dev = {
+		.platform_data = &msm_watchdog_pdata,
+	},
+};
+
 static struct resource msm_dmov_resource_adm0[] = {
 	{
 		.start = INT_ADM0_AARM,
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 1748838..c490574 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -202,4 +202,8 @@
 		defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
 extern struct platform_device msm9615_qcedev_device;
 #endif
+extern struct platform_device msm8960_device_watchdog;
+extern struct platform_device msm8660_device_watchdog;
+extern struct platform_device msm8064_device_watchdog;
+extern struct platform_device msm9615_device_watchdog;
 #endif
diff --git a/arch/arm/mach-msm/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index 8a9ac36..a1316b7 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -29,6 +29,8 @@
 #include "msm_watchdog.h"
 #include "timer.h"
 
+#define MODULE_NAME "msm_watchdog"
+
 #define TCSR_WDT_CFG	0x30
 
 #define WDT0_RST	0x38
@@ -36,11 +38,12 @@
 #define WDT0_BARK_TIME	0x4C
 #define WDT0_BITE_TIME	0x5C
 
+#define WDT_HZ		32768
+
 static void __iomem *msm_tmr0_base;
 
-/* Watchdog pet interval in ms */
-#define PET_DELAY 10000
 static unsigned long delay_time;
+static unsigned long bark_time;
 static unsigned long long last_pet;
 
 /*
@@ -88,33 +91,26 @@
 static DECLARE_DELAYED_WORK(dogwork_struct, pet_watchdog_work);
 static DECLARE_WORK(init_dogwork_struct, init_watchdog_work);
 
-static int msm_watchdog_suspend(void)
+static int msm_watchdog_suspend(struct device *dev)
 {
+	if (!enable)
+		return 0;
+
 	__raw_writel(1, msm_tmr0_base + WDT0_RST);
 	__raw_writel(0, msm_tmr0_base + WDT0_EN);
 	mb();
-	return NOTIFY_DONE;
-}
-static int msm_watchdog_resume(void)
-{
-	__raw_writel(1, msm_tmr0_base + WDT0_EN);
-	__raw_writel(1, msm_tmr0_base + WDT0_RST);
-	return NOTIFY_DONE;
+	return 0;
 }
 
-static int msm_watchdog_power_event(struct notifier_block *this,
-				unsigned long event, void *ptr)
+static int msm_watchdog_resume(struct device *dev)
 {
-	switch (event) {
-	case PM_POST_HIBERNATION:
-	case PM_POST_SUSPEND:
-		return msm_watchdog_resume();
-	case PM_HIBERNATION_PREPARE:
-	case PM_SUSPEND_PREPARE:
-		return msm_watchdog_suspend();
-	default:
-		return NOTIFY_DONE;
-	}
+	if (!enable)
+		return 0;
+
+	__raw_writel(1, msm_tmr0_base + WDT0_EN);
+	__raw_writel(1, msm_tmr0_base + WDT0_RST);
+	mb();
+	return 0;
 }
 
 static int panic_wdog_handler(struct notifier_block *this,
@@ -124,9 +120,9 @@
 		__raw_writel(0, msm_tmr0_base + WDT0_EN);
 		mb();
 	} else {
-		__raw_writel(32768 * (panic_timeout + 4),
+		__raw_writel(WDT_HZ * (panic_timeout + 4),
 				msm_tmr0_base + WDT0_BARK_TIME);
-		__raw_writel(32768 * (panic_timeout + 4),
+		__raw_writel(WDT_HZ * (panic_timeout + 4),
 				msm_tmr0_base + WDT0_BITE_TIME);
 		__raw_writel(1, msm_tmr0_base + WDT0_RST);
 	}
@@ -137,10 +133,6 @@
 	.notifier_call	= panic_wdog_handler,
 };
 
-static struct notifier_block msm_watchdog_power_notifier = {
-	.notifier_call = msm_watchdog_power_event,
-};
-
 static int wdog_enable_set(const char *val, struct kernel_param *kp)
 {
 	int ret = 0;
@@ -164,16 +156,14 @@
 	case 1:
 		if (!old_val) {
 			__raw_writel(0, msm_tmr0_base + WDT0_EN);
-			unregister_pm_notifier(&msm_watchdog_power_notifier);
-
-			/* may be suspended after the first write above */
-			__raw_writel(0, msm_tmr0_base + WDT0_EN);
 			mb();
 			free_irq(WDT0_ACCSCSSNBARK_INT, 0);
 			enable = 0;
 			atomic_notifier_chain_unregister(&panic_notifier_list,
 			       &panic_blk);
 			cancel_delayed_work(&dogwork_struct);
+			/* may be suspended after the first write above */
+			__raw_writel(0, msm_tmr0_base + WDT0_EN);
 			printk(KERN_INFO "MSM Watchdog deactivated.\n");
 		}
 	break;
@@ -204,18 +194,18 @@
 		schedule_delayed_work_on(0, &dogwork_struct, delay_time);
 }
 
-static void __exit exit_watchdog(void)
+static int msm_watchdog_remove(struct platform_device *pdev)
 {
 	if (enable) {
 		__raw_writel(0, msm_tmr0_base + WDT0_EN);
-		unregister_pm_notifier(&msm_watchdog_power_notifier);
-		/* In case we got suspended mid-exit */
-		__raw_writel(0, msm_tmr0_base + WDT0_EN);
 		mb();
 		free_irq(WDT0_ACCSCSSNBARK_INT, 0);
 		enable = 0;
+		/* In case we got suspended mid-exit */
+		__raw_writel(0, msm_tmr0_base + WDT0_EN);
 	}
 	printk(KERN_INFO "MSM Watchdog Exit - Deactivated\n");
+	return 0;
 }
 
 static irqreturn_t wdog_bark_handler(int irq, void *dev_id)
@@ -235,7 +225,7 @@
 	if (print_all_stacks) {
 
 		/* Suspend wdog until all stacks are printed */
-		msm_watchdog_suspend();
+		msm_watchdog_suspend(NULL);
 
 		printk(KERN_INFO "Stack trace dump:\n");
 
@@ -245,7 +235,7 @@
 			show_stack(tsk, NULL);
 		}
 
-		msm_watchdog_resume();
+		msm_watchdog_resume(NULL);
 	}
 
 	panic("Apps watchdog bark received!");
@@ -262,7 +252,7 @@
 		int len;
 	} cmd_buf;
 
-	if (!appsbark && !cpu_is_msm9615()) {
+	if (!appsbark) {
 		scm_regsave = (void *)__get_free_page(GFP_KERNEL);
 
 		if (scm_regsave) {
@@ -289,46 +279,9 @@
 
 static void init_watchdog_work(struct work_struct *work)
 {
-	int ret;
-
-	if (!enable) {
-		printk(KERN_INFO "MSM Watchdog Not Initialized\n");
-		return;
-	}
-
-	msm_tmr0_base = msm_timer_get_timer0_base();
-
-	/* Must request irq before sending scm command */
-	ret = request_irq(WDT0_ACCSCSSNBARK_INT, wdog_bark_handler, 0,
-			  "apps_wdog_bark", NULL);
-	if (ret)
-		return;
-
-	/*
-	 * This is only temporary till SBLs turn on the XPUs
-	 * This initialization will be done in SBLs on a later releases
-	 */
-	if (cpu_is_msm9615())
-		__raw_writel(0xF, MSM_TCSR_BASE + TCSR_WDT_CFG);
-
-	configure_bark_dump();
-
-	delay_time = msecs_to_jiffies(PET_DELAY);
-
-	/* 32768 ticks = 1 second */
-	if (machine_is_msm8960_sim()) {
-		__raw_writel(32768*15, msm_tmr0_base + WDT0_BARK_TIME);
-		__raw_writel(32768*17, msm_tmr0_base + WDT0_BITE_TIME);
-	} else {
-		__raw_writel(32768*11, msm_tmr0_base + WDT0_BARK_TIME);
-		__raw_writel(32768*12, msm_tmr0_base + WDT0_BITE_TIME);
-	}
-
-	ret = register_pm_notifier(&msm_watchdog_power_notifier);
-	if (ret) {
-		free_irq(WDT0_ACCSCSSNBARK_INT, NULL);
-		return;
-	}
+	u64 timeout = (bark_time * WDT_HZ)/1000;
+	__raw_writel(timeout, msm_tmr0_base + WDT0_BARK_TIME);
+	__raw_writel(timeout + 3*WDT_HZ, msm_tmr0_base + WDT0_BITE_TIME);
 
 	schedule_delayed_work_on(0, &dogwork_struct, delay_time);
 
@@ -344,14 +297,64 @@
 	return;
 }
 
-static int __init init_watchdog(void)
+static int msm_watchdog_probe(struct platform_device *pdev)
 {
+	struct msm_watchdog_pdata *pdata = pdev->dev.platform_data;
+	int ret;
+
+	if (!enable || !pdata || !pdata->pet_time || !pdata->bark_time) {
+		printk(KERN_INFO "MSM Watchdog Not Initialized\n");
+		return -ENODEV;
+	}
+
+	if (!pdata->has_secure)
+		appsbark = 1;
+
+	bark_time = pdata->bark_time;
+
+	msm_tmr0_base = msm_timer_get_timer0_base();
+
+	/* Must request irq before sending scm command */
+	ret = request_irq(WDT0_ACCSCSSNBARK_INT, wdog_bark_handler, 0,
+			  "apps_wdog_bark", NULL);
+	if (ret)
+		return -EINVAL;
+
+	/*
+	 * This is only temporary till SBLs turn on the XPUs
+	 * This initialization will be done in SBLs on a later releases
+	 */
+	if (cpu_is_msm9615())
+		__raw_writel(0xF, MSM_TCSR_BASE + TCSR_WDT_CFG);
+
+	configure_bark_dump();
+
+	delay_time = msecs_to_jiffies(pdata->pet_time);
 	schedule_work_on(0, &init_dogwork_struct);
 	return 0;
 }
 
+static const struct dev_pm_ops msm_watchdog_dev_pm_ops = {
+	.suspend_noirq = msm_watchdog_suspend,
+	.resume_noirq = msm_watchdog_resume,
+};
+
+static struct platform_driver msm_watchdog_driver = {
+	.probe = msm_watchdog_probe,
+	.remove = msm_watchdog_remove,
+	.driver = {
+		.name = MODULE_NAME,
+		.owner = THIS_MODULE,
+		.pm = &msm_watchdog_dev_pm_ops,
+	},
+};
+
+static int init_watchdog(void)
+{
+	return platform_driver_register(&msm_watchdog_driver);
+}
+
 late_initcall(init_watchdog);
-module_exit(exit_watchdog);
 MODULE_DESCRIPTION("MSM Watchdog Driver");
 MODULE_VERSION("1.0");
 MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/msm_watchdog.h b/arch/arm/mach-msm/msm_watchdog.h
index 23ff60e..201c2b1 100644
--- a/arch/arm/mach-msm/msm_watchdog.h
+++ b/arch/arm/mach-msm/msm_watchdog.h
@@ -13,6 +13,14 @@
 #ifndef __ARCH_ARM_MACH_MSM_MSM_WATCHDOG_H
 #define __ARCH_ARM_MACH_MSM_MSM_WATCHDOG_H
 
+struct msm_watchdog_pdata {
+	/* pet interval period in ms */
+	unsigned int pet_time;
+	/* bark timeout in ms */
+	unsigned int bark_time;
+	bool has_secure;
+};
+
 #ifdef CONFIG_MSM_WATCHDOG
 void pet_watchdog(void);
 #else