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/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");