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