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