rtc: alarm: Add power-on alarm feature
Android does not support powering up of phone through alarm.
Adding shutdown hook in alarm driver which will set alarm while phone
is going down so as to power-up the phone after alarm expiration.
CRs-Fixed: 432312
Change-Id: I21786d264b93f7c0c660823a0a1a221c1b4df7b2
Signed-off-by: Ashay Jaiswal <ashayj@codeaurora.org>
diff --git a/drivers/rtc/alarm-dev.c b/drivers/rtc/alarm-dev.c
index bfcaebc..1d60e97 100644
--- a/drivers/rtc/alarm-dev.c
+++ b/drivers/rtc/alarm-dev.c
@@ -98,6 +98,8 @@
wake_unlock(&alarm_wake_lock);
}
alarm_enabled &= ~alarm_type_mask;
+ if (alarm_type == ANDROID_ALARM_RTC_WAKEUP)
+ set_power_on_alarm(0);
spin_unlock_irqrestore(&alarm_slock, flags);
break;
@@ -125,6 +127,10 @@
alarm_start_range(&alarms[alarm_type],
timespec_to_ktime(new_alarm_time),
timespec_to_ktime(new_alarm_time));
+ if ((alarm_type == ANDROID_ALARM_RTC_WAKEUP) &&
+ (ANDROID_ALARM_BASE_CMD(cmd) ==
+ ANDROID_ALARM_SET(0)))
+ set_power_on_alarm(new_alarm_time.tv_sec);
spin_unlock_irqrestore(&alarm_slock, flags);
if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
&& cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
diff --git a/drivers/rtc/alarm.c b/drivers/rtc/alarm.c
index 9340af7..e318ecf 100644
--- a/drivers/rtc/alarm.c
+++ b/drivers/rtc/alarm.c
@@ -68,6 +68,13 @@
static struct platform_device *alarm_platform_dev;
struct alarm_queue alarms[ANDROID_ALARM_TYPE_COUNT];
static bool suspended;
+static long power_on_alarm;
+
+void set_power_on_alarm(long secs)
+{
+ power_on_alarm = secs;
+}
+
static void update_timer_locked(struct alarm_queue *base, bool head_removed)
{
@@ -486,6 +493,45 @@
return 0;
}
+static void alarm_shutdown(struct platform_device *dev)
+{
+ struct timespec wall_time;
+ struct rtc_time rtc_time;
+ struct rtc_wkalrm alarm;
+ unsigned long flags;
+ long rtc_secs, alarm_delta, alarm_time;
+ int rc;
+
+ spin_lock_irqsave(&alarm_slock, flags);
+
+ if (!power_on_alarm)
+ goto disable_alarm;
+
+ rtc_read_time(alarm_rtc_dev, &rtc_time);
+ getnstimeofday(&wall_time);
+ rtc_tm_to_time(&rtc_time, &rtc_secs);
+ alarm_delta = wall_time.tv_sec - rtc_secs;
+ alarm_time = power_on_alarm - alarm_delta;
+ if (alarm_time <= rtc_secs)
+ goto disable_alarm;
+
+ rtc_time_to_tm(alarm_time, &alarm.time);
+ alarm.enabled = 1;
+ rc = rtc_set_alarm(alarm_rtc_dev, &alarm);
+ if (rc)
+ pr_alarm(ERROR, "Unable to set power-on alarm\n");
+ else
+ pr_alarm(FLOW, "Power-on alarm set to %lu\n",
+ alarm_time);
+
+ spin_unlock_irqrestore(&alarm_slock, flags);
+ return;
+
+disable_alarm:
+ rtc_alarm_irq_enable(alarm_rtc_dev, 0);
+ spin_unlock_irqrestore(&alarm_slock, flags);
+}
+
static struct rtc_task alarm_rtc_task = {
.func = alarm_triggered_func
};
@@ -545,6 +591,7 @@
static struct platform_driver alarm_driver = {
.suspend = alarm_suspend,
.resume = alarm_resume,
+ .shutdown = alarm_shutdown,
.driver = {
.name = "alarm"
}
diff --git a/include/linux/android_alarm.h b/include/linux/android_alarm.h
index cbfeafc..096f777 100644
--- a/include/linux/android_alarm.h
+++ b/include/linux/android_alarm.h
@@ -70,6 +70,7 @@
void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end);
int alarm_try_to_cancel(struct alarm *alarm);
int alarm_cancel(struct alarm *alarm);
+void set_power_on_alarm(long secs);
ktime_t alarm_get_elapsed_realtime(void);
/* set rtc while preserving elapsed realtime */