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

Commit e1a9092b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "rtc: alarm: Add power-on alarm feature"

parents 3981c4a7 833eed93
Loading
Loading
Loading
Loading
+12 −2
Original line number Original line Diff line number Diff line
@@ -40,7 +40,8 @@ do { \


#define ANDROID_ALARM_WAKEUP_MASK ( \
#define ANDROID_ALARM_WAKEUP_MASK ( \
	ANDROID_ALARM_RTC_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 int alarm_opened;
static DEFINE_SPINLOCK(alarm_slock);
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)
static int is_wakeup(enum android_alarm_type type)
{
{
	return (type == ANDROID_ALARM_RTC_WAKEUP ||
	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;
	alarm_enabled &= ~alarm_type_mask;
	spin_unlock_irqrestore(&alarm_slock, flags);
	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,
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;
	alarm_enabled |= alarm_type_mask;
	devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts));
	devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts));
	spin_unlock_irqrestore(&alarm_slock, flags);
	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)
static int alarm_wait(void)
@@ -181,6 +188,7 @@ static int alarm_get_time(enum android_alarm_type alarm_type,
	switch (alarm_type) {
	switch (alarm_type) {
	case ANDROID_ALARM_RTC_WAKEUP:
	case ANDROID_ALARM_RTC_WAKEUP:
	case ANDROID_ALARM_RTC:
	case ANDROID_ALARM_RTC:
	case ANDROID_ALARM_RTC_POWEROFF_WAKEUP:
		getnstimeofday(ts);
		getnstimeofday(ts);
		break;
		break;
	case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
	case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
@@ -421,6 +429,8 @@ static int __init alarm_dev_init(void)
			CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
			CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
	hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt,
	hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt,
			CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
			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++) {
	for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) {
		alarms[i].type = i;
		alarms[i].type = i;
+3 −0
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ enum android_alarm_type {
	ANDROID_ALARM_RTC,
	ANDROID_ALARM_RTC,
	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
	ANDROID_ALARM_ELAPSED_REALTIME,
	ANDROID_ALARM_ELAPSED_REALTIME,
	ANDROID_ALARM_RTC_POWEROFF_WAKEUP,
	ANDROID_ALARM_SYSTEMTIME,
	ANDROID_ALARM_SYSTEMTIME,


	ANDROID_ALARM_TYPE_COUNT,
	ANDROID_ALARM_TYPE_COUNT,
@@ -41,6 +42,8 @@ enum android_alarm_return_flags {
				1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
				1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
	ANDROID_ALARM_ELAPSED_REALTIME_MASK =
	ANDROID_ALARM_ELAPSED_REALTIME_MASK =
				1U << ANDROID_ALARM_ELAPSED_REALTIME,
				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_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME,
	ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16
	ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16
};
};
+1 −0
Original line number Original line 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);
void alarm_restart(struct alarm *alarm);
int alarm_try_to_cancel(struct alarm *alarm);
int alarm_try_to_cancel(struct alarm *alarm);
int alarm_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(struct alarm *alarm, ktime_t now, ktime_t interval);
u64 alarm_forward_now(struct alarm *alarm, ktime_t interval);
u64 alarm_forward_now(struct alarm *alarm, ktime_t interval);
+51 −0
Original line number Original line Diff line number Diff line
@@ -26,6 +26,8 @@
#include <linux/workqueue.h>
#include <linux/workqueue.h>
#include <linux/freezer.h>
#include <linux/freezer.h>


#define ALARM_DELTA 120

/**
/**
 * struct alarm_base - Alarm timer bases
 * struct alarm_base - Alarm timer bases
 * @lock:		Lock for syncrhonized access to the base
 * @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_timer		rtctimer;
static struct rtc_device	*rtcdev;
static struct rtc_device	*rtcdev;
static DEFINE_SPINLOCK(rtcdev_lock);
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)
static void alarmtimer_triggered_func(void *p)
{
{
@@ -837,6 +887,7 @@ static int __init alarmtimer_init(void)
		.nsleep		= alarm_timer_nsleep,
		.nsleep		= alarm_timer_nsleep,
	};
	};


	mutex_init(&power_on_alarm_lock);
	alarmtimer_rtc_timer_init();
	alarmtimer_rtc_timer_init();


	posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
	posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);