Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 833eed93 authored by Matthew Qin's avatar Matthew Qin
Browse files

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.

Change-Id: Ic2611e33ae9c1f8e83f21efdb93e26ac9f9499de
Signed-off-by: default avatarMatthew Qin <yqin@codeaurora.org>
parent fe59e87b
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -40,7 +40,8 @@ do { \

#define ANDROID_ALARM_WAKEUP_MASK ( \
	ANDROID_ALARM_RTC_WAKEUP_MASK | \
	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK | \
	ANDROID_ALARM_RTC_POWEROFF_WAKEUP_MASK)

static int alarm_opened;
static DEFINE_SPINLOCK(alarm_slock);
@@ -64,7 +65,8 @@ static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT];
static int is_wakeup(enum android_alarm_type type)
{
	return (type == ANDROID_ALARM_RTC_WAKEUP ||
		type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP);
		type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP ||
		type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP);
}


@@ -108,6 +110,8 @@ static void alarm_clear(enum android_alarm_type alarm_type)
	alarm_enabled &= ~alarm_type_mask;
	spin_unlock_irqrestore(&alarm_slock, flags);

	if (alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP)
		set_power_on_alarm(0);
}

static void alarm_set(enum android_alarm_type alarm_type,
@@ -122,6 +126,9 @@ static void alarm_set(enum android_alarm_type alarm_type,
	alarm_enabled |= alarm_type_mask;
	devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts));
	spin_unlock_irqrestore(&alarm_slock, flags);

	if (alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP)
		set_power_on_alarm(ts->tv_sec);
}

static int alarm_wait(void)
@@ -181,6 +188,7 @@ static int alarm_get_time(enum android_alarm_type alarm_type,
	switch (alarm_type) {
	case ANDROID_ALARM_RTC_WAKEUP:
	case ANDROID_ALARM_RTC:
	case ANDROID_ALARM_RTC_POWEROFF_WAKEUP:
		getnstimeofday(ts);
		break;
	case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
@@ -421,6 +429,8 @@ static int __init alarm_dev_init(void)
			CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
	hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt,
			CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
	alarm_init(&alarms[ANDROID_ALARM_RTC_POWEROFF_WAKEUP].u.alrm,
			ALARM_REALTIME, devalarm_alarmhandler);

	for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) {
		alarms[i].type = i;
+3 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ enum android_alarm_type {
	ANDROID_ALARM_RTC,
	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
	ANDROID_ALARM_ELAPSED_REALTIME,
	ANDROID_ALARM_RTC_POWEROFF_WAKEUP,
	ANDROID_ALARM_SYSTEMTIME,

	ANDROID_ALARM_TYPE_COUNT,
@@ -41,6 +42,8 @@ enum android_alarm_return_flags {
				1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
	ANDROID_ALARM_ELAPSED_REALTIME_MASK =
				1U << ANDROID_ALARM_ELAPSED_REALTIME,
	ANDROID_ALARM_RTC_POWEROFF_WAKEUP_MASK =
				1U << ANDROID_ALARM_RTC_POWEROFF_WAKEUP,
	ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME,
	ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16
};
+1 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ int alarm_start_relative(struct alarm *alarm, ktime_t start);
void alarm_restart(struct alarm *alarm);
int alarm_try_to_cancel(struct alarm *alarm);
int alarm_cancel(struct alarm *alarm);
void set_power_on_alarm(long secs);

u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval);
u64 alarm_forward_now(struct alarm *alarm, ktime_t interval);
+51 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@
#include <linux/workqueue.h>
#include <linux/freezer.h>

#define ALARM_DELTA 120

/**
 * struct alarm_base - Alarm timer bases
 * @lock:		Lock for syncrhonized access to the base
@@ -52,6 +54,54 @@ static struct wakeup_source *ws;
static struct rtc_timer		rtctimer;
static struct rtc_device	*rtcdev;
static DEFINE_SPINLOCK(rtcdev_lock);
static unsigned long power_on_alarm;
static struct mutex power_on_alarm_lock;

void set_power_on_alarm(long secs)
{
	int rc;
	long rtc_secs, alarm_time;
	struct rtc_time rtc_time;
	struct rtc_wkalrm alarm;

	rc = mutex_lock_interruptible(&power_on_alarm_lock);
	if (rc != 0)
		return;

	rtc_read_time(rtcdev, &rtc_time);
	rtc_tm_to_time(&rtc_time, &rtc_secs);

	if (!secs)
		goto disable_alarm;
	else
		power_on_alarm = secs + rtc_secs;

	alarm_time = power_on_alarm;

	/*
	 *Substract ALARM_DELTA from actual alarm time
	 *to power up the device before actual alarm
	 *expiration
	 */
	if ((alarm_time - ALARM_DELTA) > rtc_secs)
		alarm_time -= 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(rtcdev, &alarm);
	if (rc)
		goto disable_alarm;

	mutex_unlock(&power_on_alarm_lock);
	return;

disable_alarm:
	rtc_alarm_irq_enable(rtcdev, 0);
	mutex_unlock(&power_on_alarm_lock);
}

static void alarmtimer_triggered_func(void *p)
{
@@ -837,6 +887,7 @@ static int __init alarmtimer_init(void)
		.nsleep		= alarm_timer_nsleep,
	};

	mutex_init(&power_on_alarm_lock);
	alarmtimer_rtc_timer_init();

	posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);