mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
rtc: alarm: Change wake-up source
Currently, RTC_ALARM is used to wake-up target from suspend state and is also used for power-off alarm feature. This patch uses qtimer to wake-up from suspend state. Change-Id: Ia42cfecd573309be2f03c18b4f1c321be8202d7d Signed-off-by: Mohit Aggarwal <maggarwa@codeaurora.org>
This commit is contained in:
parent
fef205de12
commit
4ea7106deb
3 changed files with 71 additions and 2 deletions
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -46,9 +46,10 @@
|
|||
(arr[3] << 24))
|
||||
|
||||
/* Module parameter to control power-on-alarm */
|
||||
static bool poweron_alarm;
|
||||
bool poweron_alarm;
|
||||
module_param(poweron_alarm, bool, 0644);
|
||||
MODULE_PARM_DESC(poweron_alarm, "Enable/Disable power-on alarm");
|
||||
EXPORT_SYMBOL(poweron_alarm);
|
||||
|
||||
/* rtc driver internal structure */
|
||||
struct qpnp_rtc {
|
||||
|
|
|
@ -85,5 +85,8 @@ static inline int alarmtimer_callback_running(struct alarm *timer)
|
|||
|
||||
/* Provide way to access the rtc device being used by alarmtimers */
|
||||
struct rtc_device *alarmtimer_get_rtcdev(void);
|
||||
#ifdef CONFIG_RTC_DRV_QPNP
|
||||
extern bool poweron_alarm;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -327,6 +327,70 @@ ktime_t alarm_expires_remaining(const struct alarm *alarm)
|
|||
* set an rtc timer to fire that far into the future, which
|
||||
* will wake us from suspend.
|
||||
*/
|
||||
#if defined(CONFIG_RTC_DRV_QPNP) && defined(CONFIG_MSM_PM)
|
||||
extern void lpm_suspend_wake_time(uint64_t wakeup_time);
|
||||
static int alarmtimer_suspend(struct device *dev)
|
||||
{
|
||||
struct rtc_time tm;
|
||||
ktime_t min, now;
|
||||
unsigned long flags;
|
||||
struct rtc_device *rtc;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&freezer_delta_lock, flags);
|
||||
min = freezer_delta;
|
||||
freezer_delta = ktime_set(0, 0);
|
||||
spin_unlock_irqrestore(&freezer_delta_lock, flags);
|
||||
|
||||
rtc = alarmtimer_get_rtcdev();
|
||||
/* If we have no rtcdev, just return */
|
||||
if (!rtc)
|
||||
return 0;
|
||||
|
||||
/* Find the soonest timer to expire*/
|
||||
for (i = 0; i < ALARM_NUMTYPE; i++) {
|
||||
struct alarm_base *base = &alarm_bases[i];
|
||||
struct timerqueue_node *next;
|
||||
ktime_t delta;
|
||||
|
||||
spin_lock_irqsave(&base->lock, flags);
|
||||
next = timerqueue_getnext(&base->timerqueue);
|
||||
spin_unlock_irqrestore(&base->lock, flags);
|
||||
if (!next)
|
||||
continue;
|
||||
delta = ktime_sub(next->expires, base->gettime());
|
||||
if (!min.tv64 || (delta.tv64 < min.tv64))
|
||||
min = delta;
|
||||
}
|
||||
if (min.tv64 == 0)
|
||||
return 0;
|
||||
|
||||
if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) {
|
||||
__pm_wakeup_event(ws, 2 * MSEC_PER_SEC);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Setup a timer to fire that far in the future */
|
||||
rtc_timer_cancel(rtc, &rtctimer);
|
||||
rtc_read_time(rtc, &tm);
|
||||
now = rtc_tm_to_ktime(tm);
|
||||
now = ktime_add(now, min);
|
||||
if (poweron_alarm) {
|
||||
struct rtc_time tm_val;
|
||||
unsigned long secs;
|
||||
tm_val = rtc_ktime_to_tm(min);
|
||||
rtc_tm_to_time(&tm_val, &secs);
|
||||
lpm_suspend_wake_time(secs);
|
||||
} else {
|
||||
/* Set alarm, if in the past reject suspend briefly to handle */
|
||||
ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
|
||||
if (ret < 0)
|
||||
__pm_wakeup_event(ws, MSEC_PER_SEC);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static int alarmtimer_suspend(struct device *dev)
|
||||
{
|
||||
struct rtc_time tm;
|
||||
|
@ -381,6 +445,7 @@ static int alarmtimer_suspend(struct device *dev)
|
|||
__pm_wakeup_event(ws, 1 * MSEC_PER_SEC);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
static int alarmtimer_resume(struct device *dev)
|
||||
{
|
||||
struct rtc_device *rtc;
|
||||
|
|
Loading…
Reference in a new issue