drivers: qcom: Add support to freeze-restore watchdog
Freeze the watchdog during suspend and enable it after resume. Change-Id: I7e09d2d78f494b8aee9d9c59f681fe6e574a4f9a Signed-off-by: Shreyas K K <quic_shrekk@quicinc.com> Signed-off-by: Auditya Bhattaram <quic_audityab@quicinc.com> Signed-off-by: Kamati Srinivas <quic_kamasrin@quicinc.com>
This commit is contained in:
parent
74b4305257
commit
c558e5abfe
@ -110,6 +110,8 @@ static const struct dev_pm_ops qcom_soc_dev_pm_ops = {
|
||||
.suspend_late = qcom_wdt_pet_suspend,
|
||||
.resume_early = qcom_wdt_pet_resume,
|
||||
#endif
|
||||
.freeze_late = qcom_wdt_pet_suspend,
|
||||
.restore_early = qcom_wdt_pet_resume,
|
||||
};
|
||||
|
||||
static const struct of_device_id qcom_soc_match_table[] = {
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <linux/irq_cpustat.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#define MASK_SIZE 32
|
||||
#define COMPARE_RET -1
|
||||
@ -258,6 +260,20 @@ static void queue_irq_counts_work(struct work_struct *irq_counts_work) { }
|
||||
static void compute_irq_stat(struct work_struct *work) { }
|
||||
#endif
|
||||
|
||||
static int qcom_wdt_hibernation_notifier(struct notifier_block *nb,
|
||||
unsigned long event, void *dummy)
|
||||
{
|
||||
if (event == PM_HIBERNATION_PREPARE)
|
||||
wdog_data->hibernate = true;
|
||||
else if (event == PM_POST_HIBERNATION)
|
||||
wdog_data->hibernate = false;
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block qcom_wdt_notif_block = {
|
||||
.notifier_call = qcom_wdt_hibernation_notifier,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/**
|
||||
* qcom_wdt_pet_suspend() - Suspends qcom watchdog functionality.
|
||||
@ -286,6 +302,10 @@ int qcom_wdt_pet_suspend(struct device *dev)
|
||||
wdog_data->ops->reset_wdt(wdog_data);
|
||||
del_timer_sync(&wdog_data->pet_timer);
|
||||
if (wdog_data->wakeup_irq_enable) {
|
||||
if (wdog_data->hibernate) {
|
||||
wdog_data->ops->disable_wdt(wdog_data);
|
||||
wdog_data->enabled = false;
|
||||
}
|
||||
wdog_data->last_pet = sched_clock();
|
||||
return 0;
|
||||
}
|
||||
@ -308,6 +328,7 @@ EXPORT_SYMBOL(qcom_wdt_pet_suspend);
|
||||
*/
|
||||
int qcom_wdt_pet_resume(struct device *dev)
|
||||
{
|
||||
uint32_t val;
|
||||
struct msm_watchdog_data *wdog_data =
|
||||
(struct msm_watchdog_data *)dev_get_drvdata(dev);
|
||||
unsigned long delay_time = 0;
|
||||
@ -315,6 +336,7 @@ int qcom_wdt_pet_resume(struct device *dev)
|
||||
if (!wdog_data)
|
||||
return 0;
|
||||
|
||||
val = BIT(EN);
|
||||
if (wdog_data->user_pet_enabled) {
|
||||
delay_time = msecs_to_jiffies(wdog_data->bark_time + 3 * 1000);
|
||||
wdog_data->user_pet_timer.expires = jiffies + delay_time;
|
||||
@ -328,12 +350,17 @@ int qcom_wdt_pet_resume(struct device *dev)
|
||||
wdog_data->freeze_in_progress = false;
|
||||
spin_unlock(&wdog_data->freeze_lock);
|
||||
if (wdog_data->wakeup_irq_enable) {
|
||||
if (wdog_data->hibernate) {
|
||||
val |= BIT(UNMASKED_INT_EN);
|
||||
wdog_data->ops->enable_wdt(val, wdog_data);
|
||||
wdog_data->enabled = true;
|
||||
}
|
||||
wdog_data->ops->reset_wdt(wdog_data);
|
||||
wdog_data->last_pet = sched_clock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
wdog_data->ops->enable_wdt(1, wdog_data);
|
||||
wdog_data->ops->enable_wdt(val, wdog_data);
|
||||
wdog_data->ops->reset_wdt(wdog_data);
|
||||
wdog_data->enabled = true;
|
||||
wdog_data->last_pet = sched_clock();
|
||||
@ -862,6 +889,12 @@ static int qcom_wdt_init(struct msm_watchdog_data *wdog_dd,
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
wdog_data->hibernate = false;
|
||||
ret = register_pm_notifier(&qcom_wdt_notif_block);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
INIT_WORK(&wdog_dd->irq_counts_work, compute_irq_stat);
|
||||
atomic_set(&wdog_dd->irq_counts_running, 0);
|
||||
delay_time = msecs_to_jiffies(wdog_dd->pet_time);
|
||||
|
@ -266,6 +266,8 @@ static const struct dev_pm_ops gh_wdt_dev_pm_ops = {
|
||||
.suspend_late = qcom_wdt_pet_suspend,
|
||||
.resume_early = qcom_wdt_pet_resume,
|
||||
#endif
|
||||
.freeze_late = qcom_wdt_pet_suspend,
|
||||
.restore_early = qcom_wdt_pet_resume,
|
||||
};
|
||||
|
||||
static const struct of_device_id gh_wdt_match_table[] = {
|
||||
|
@ -156,6 +156,7 @@ struct msm_watchdog_data {
|
||||
unsigned int tot_irq_count[NR_CPUS];
|
||||
atomic_t irq_counts_running;
|
||||
struct timer_list user_pet_timer;
|
||||
bool hibernate;
|
||||
};
|
||||
|
||||
extern void qcom_wdt_trigger_bite(void);
|
||||
|
Loading…
Reference in New Issue
Block a user