From 67dbe9f83b51b916954d2b40df532899aac80f84 Mon Sep 17 00:00:00 2001 From: Sarangdhar Joshi Date: Mon, 15 Jun 2015 13:38:41 -0700 Subject: [PATCH] soc: qcom: watchdog_v2: add support to enable watchdog feature Currently we disable Non secure watchdog during suspend and re-enable it during resume. This leaves suspend / resume path unprotected by Non secure watchdog. There is a feature in hardware where watchdog freezes automatically when all online cores are in suspend and unfreezes watchdog upon wakeup event from low power mode. Set the bit in watchdog control register to enable this feature and protect suspend / resume path by Non secure watchdog. Change-Id: Ibca425a661c74bd1d46513783780ea213a51f87f Signed-off-by: Sarangdhar Joshi --- drivers/soc/qcom/watchdog_v2.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/watchdog_v2.c b/drivers/soc/qcom/watchdog_v2.c index 1cc2a4f40d11..82e8219fb827 100644 --- a/drivers/soc/qcom/watchdog_v2.c +++ b/drivers/soc/qcom/watchdog_v2.c @@ -40,6 +40,9 @@ #define WDOG_ABSENT 0 +#define EN 0 +#define UNMASKED_INT_EN 1 + #define MASK_SIZE 32 #define SCM_SET_REGSAVE_CMD 0x2 #define SCM_SVC_SEC_WDOG_DIS 0x7 @@ -61,6 +64,7 @@ struct msm_watchdog_data { unsigned int bark_irq; unsigned int bite_irq; bool do_ipi_ping; + bool wakeup_irq_enable; unsigned long long last_pet; unsigned min_slack_ticks; unsigned long long min_slack_ns; @@ -117,6 +121,10 @@ static int msm_watchdog_suspend(struct device *dev) if (!enable) return 0; __raw_writel(1, wdog_dd->base + WDT0_RST); + if (wdog_dd->wakeup_irq_enable) { + wdog_dd->last_pet = sched_clock(); + return 0; + } __raw_writel(0, wdog_dd->base + WDT0_EN); mb(); wdog_dd->enabled = false; @@ -128,7 +136,7 @@ static int msm_watchdog_resume(struct device *dev) { struct msm_watchdog_data *wdog_dd = (struct msm_watchdog_data *)dev_get_drvdata(dev); - if (!enable) + if (!enable || wdog_dd->wakeup_irq_enable) return 0; __raw_writel(1, wdog_dd->base + WDT0_EN); __raw_writel(1, wdog_dd->base + WDT0_RST); @@ -513,6 +521,7 @@ static void init_watchdog_work(struct work_struct *work) struct msm_watchdog_data, init_dogwork_struct); unsigned long delay_time; + uint32_t val; int error; u64 timeout; int ret; @@ -562,7 +571,10 @@ static void init_watchdog_work(struct work_struct *work) mutex_init(&wdog_dd->disable_lock); queue_delayed_work(wdog_wq, &wdog_dd->dogwork_struct, delay_time); - __raw_writel(1, wdog_dd->base + WDT0_EN); + val = BIT(EN); + if (wdog_dd->wakeup_irq_enable) + val |= BIT(UNMASKED_INT_EN); + __raw_writel(val, wdog_dd->base + WDT0_EN); __raw_writel(1, wdog_dd->base + WDT0_RST); wdog_dd->last_pet = sched_clock(); wdog_dd->enabled = true; @@ -655,6 +667,9 @@ static int msm_wdog_dt_to_pdata(struct platform_device *pdev, __func__); return -ENXIO; } + pdata->wakeup_irq_enable = of_property_read_bool(node, + "qcom,wakeup-enable"); + pdata->irq_ppi = irq_is_percpu(pdata->bark_irq); dump_pdata(pdata); return 0;