@@ -56,10 +56,13 @@ MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
static unsigned int wdt_trgr_pattern = 0x1234;
static spinlock_t wdt_lock;
+#define OMAP_WDT_STATE_OPENED_BIT 1
+#define OMAP_WDT_STATE_ACTIVATED_BIT 8
+
struct omap_wdt_dev {
void __iomem *base; /* physical */
struct device *dev;
- int omap_wdt_users;
+ int omap_wdt_state;
struct clk *mpu_wdt_ick;
struct clk *mpu_wdt_fck;
struct resource *mem;
@@ -152,19 +155,25 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev);
void __iomem *base = wdev->base;
- if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users)))
+ if (test_and_set_bit(OMAP_WDT_STATE_OPENED_BIT,
+ (unsigned long *)&(wdev->omap_wdt_state)))
return -EBUSY;
omap_wdt_ick_enable(wdev->mpu_wdt_ick, 1);
- clk_enable(wdev->mpu_wdt_fck);
+ if (wdev->omap_wdt_state & (1 << OMAP_WDT_STATE_ACTIVATED_BIT))
+ omap_wdt_ping(wdev);
+ else {
+ clk_enable(wdev->mpu_wdt_fck);
- /* initialize prescaler */
- while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
- cpu_relax();
+ /* initialize prescaler */
+ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
+ cpu_relax();
- __raw_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL);
- while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
- cpu_relax();
+ __raw_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL);
+ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
+ cpu_relax();
+ wdev->omap_wdt_state |= (1 << OMAP_WDT_STATE_ACTIVATED_BIT);
+ }
file->private_data = (void *) wdev;
@@ -189,10 +198,13 @@ static int omap_wdt_release(struct inode *inode, struct file *file)
omap_wdt_ick_enable(wdev->mpu_wdt_ick, 0);
clk_disable(wdev->mpu_wdt_fck);
+ wdev->omap_wdt_state &= ~(1 << OMAP_WDT_STATE_ACTIVATED_BIT);
#else
+ /* Give the user application some time to recover in case of crash. */
+ omap_wdt_ping(wdev);
printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
#endif
- wdev->omap_wdt_users = 0;
+ wdev->omap_wdt_state &= ~(1 << OMAP_WDT_STATE_OPENED_BIT);
return 0;
}
@@ -307,7 +319,7 @@ static int __init omap_wdt_probe(struct platform_device *pdev)
goto err_kzalloc;
}
- wdev->omap_wdt_users = 0;
+ wdev->omap_wdt_state = 0;
wdev->mem = mem;
if (cpu_is_omap16xx()) {
@@ -417,7 +429,7 @@ static void omap_wdt_shutdown(struct platform_device *pdev)
{
struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
- if (wdev->omap_wdt_users) {
+ if (wdev->omap_wdt_state & (1<<OMAP_WDT_STATE_ACTIVATED_BIT)) {
omap_wdt_ick_enable(wdev->mpu_wdt_ick, 1);
omap_wdt_disable(wdev);
omap_wdt_ick_enable(wdev->mpu_wdt_ick, 0);
@@ -465,7 +477,7 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
{
struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
- if (wdev->omap_wdt_users) {
+ if (wdev->omap_wdt_state & (1<<OMAP_WDT_STATE_ACTIVATED_BIT)) {
omap_wdt_ick_enable(wdev->mpu_wdt_ick, 1);
omap_wdt_disable(wdev);
omap_wdt_ick_enable(wdev->mpu_wdt_ick, 0);
@@ -478,7 +490,7 @@ static int omap_wdt_resume(struct platform_device *pdev)
{
struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
- if (wdev->omap_wdt_users) {
+ if (wdev->omap_wdt_state & (1<<OMAP_WDT_STATE_ACTIVATED_BIT)) {
omap_wdt_ick_enable(wdev->mpu_wdt_ick, 1);
omap_wdt_enable(wdev);
omap_wdt_ping(wdev);
Needed to support CONFIG_WATCHDOG_NOWAYOUT option. Signed-off-by: Atal Shargorodsky <ext-atal.shargorodsky@nokia.com> --- drivers/watchdog/omap_wdt.c | 40 ++++++++++++++++++++++++++-------------- 1 files changed, 26 insertions(+), 14 deletions(-)