Skip to content

Commit

Permalink
rtc: test: emulate alarms using timers
Browse files Browse the repository at this point in the history
Use timers to emulate alarms. Note that multiple alarms may happen if they
are set more than 15 days after the current RTC time.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
  • Loading branch information
Alexandre Belloni committed May 31, 2018
1 parent 4dc2403 commit 8be0902
Showing 1 changed file with 52 additions and 4 deletions.
56 changes: 52 additions & 4 deletions drivers/rtc/rtc-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,49 @@
struct rtc_test_data {
struct rtc_device *rtc;
time64_t offset;
struct timer_list alarm;
bool alarm_en;
};

struct platform_device *pdev[MAX_RTC_TEST];

static int test_rtc_read_alarm(struct device *dev,
struct rtc_wkalrm *alrm)
static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rtc_test_data *rtd = dev_get_drvdata(dev);
time64_t alarm;

alarm = (rtd->alarm.expires - jiffies) / HZ;
alarm += ktime_get_real_seconds() + rtd->offset;

rtc_time64_to_tm(alarm, &alrm->time);
alrm->enabled = rtd->alarm_en;

return 0;
}

static int test_rtc_set_alarm(struct device *dev,
struct rtc_wkalrm *alrm)
static int test_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rtc_test_data *rtd = dev_get_drvdata(dev);
ktime_t timeout;
u64 expires;

timeout = rtc_tm_to_time64(&alrm->time) - ktime_get_real_seconds();
timeout -= rtd->offset;

del_timer(&rtd->alarm);

expires = jiffies + timeout * HZ;
if (expires > U32_MAX)
expires = U32_MAX;

pr_err("ABE: %s +%d %s\n", __FILE__, __LINE__, __func__);
rtd->alarm.expires = expires;

if (alrm->enabled)
add_timer(&rtd->alarm);

rtd->alarm_en = alrm->enabled;

return 0;
}

Expand All @@ -54,6 +84,14 @@ static int test_rtc_set_mmss64(struct device *dev, time64_t secs)

static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
{
struct rtc_test_data *rtd = dev_get_drvdata(dev);

rtd->alarm_en = enable;
if (enable)
add_timer(&rtd->alarm);
else
del_timer(&rtd->alarm);

return 0;
}

Expand All @@ -65,6 +103,13 @@ static const struct rtc_class_ops test_rtc_ops = {
.alarm_irq_enable = test_rtc_alarm_irq_enable,
};

static void test_rtc_alarm_handler(struct timer_list *t)
{
struct rtc_test_data *rtd = from_timer(rtd, t, alarm);

rtc_update_irq(rtd->rtc, 1, RTC_AF | RTC_IRQF);
}

static ssize_t test_irq_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
Expand Down Expand Up @@ -111,6 +156,9 @@ static int test_probe(struct platform_device *plat_dev)
if (IS_ERR(rtd->rtc))
return PTR_ERR(rtd->rtc);

timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0);
rtd->alarm.expires = 0;

return 0;
}

Expand Down

0 comments on commit 8be0902

Please sign in to comment.