Skip to content

Commit 8be0902

Browse files
rtc: test: emulate alarms using timers
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>
1 parent 4dc2403 commit 8be0902

File tree

1 file changed

+52
-4
lines changed

1 file changed

+52
-4
lines changed

drivers/rtc/rtc-test.c

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,49 @@
1818
struct rtc_test_data {
1919
struct rtc_device *rtc;
2020
time64_t offset;
21+
struct timer_list alarm;
22+
bool alarm_en;
2123
};
2224

2325
struct platform_device *pdev[MAX_RTC_TEST];
2426

25-
static int test_rtc_read_alarm(struct device *dev,
26-
struct rtc_wkalrm *alrm)
27+
static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
2728
{
29+
struct rtc_test_data *rtd = dev_get_drvdata(dev);
30+
time64_t alarm;
31+
32+
alarm = (rtd->alarm.expires - jiffies) / HZ;
33+
alarm += ktime_get_real_seconds() + rtd->offset;
34+
35+
rtc_time64_to_tm(alarm, &alrm->time);
36+
alrm->enabled = rtd->alarm_en;
37+
2838
return 0;
2939
}
3040

31-
static int test_rtc_set_alarm(struct device *dev,
32-
struct rtc_wkalrm *alrm)
41+
static int test_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
3342
{
43+
struct rtc_test_data *rtd = dev_get_drvdata(dev);
44+
ktime_t timeout;
45+
u64 expires;
46+
47+
timeout = rtc_tm_to_time64(&alrm->time) - ktime_get_real_seconds();
48+
timeout -= rtd->offset;
49+
50+
del_timer(&rtd->alarm);
51+
52+
expires = jiffies + timeout * HZ;
53+
if (expires > U32_MAX)
54+
expires = U32_MAX;
55+
56+
pr_err("ABE: %s +%d %s\n", __FILE__, __LINE__, __func__);
57+
rtd->alarm.expires = expires;
58+
59+
if (alrm->enabled)
60+
add_timer(&rtd->alarm);
61+
62+
rtd->alarm_en = alrm->enabled;
63+
3464
return 0;
3565
}
3666

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

5585
static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
5686
{
87+
struct rtc_test_data *rtd = dev_get_drvdata(dev);
88+
89+
rtd->alarm_en = enable;
90+
if (enable)
91+
add_timer(&rtd->alarm);
92+
else
93+
del_timer(&rtd->alarm);
94+
5795
return 0;
5896
}
5997

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

106+
static void test_rtc_alarm_handler(struct timer_list *t)
107+
{
108+
struct rtc_test_data *rtd = from_timer(rtd, t, alarm);
109+
110+
rtc_update_irq(rtd->rtc, 1, RTC_AF | RTC_IRQF);
111+
}
112+
68113
static ssize_t test_irq_show(struct device *dev,
69114
struct device_attribute *attr, char *buf)
70115
{
@@ -111,6 +156,9 @@ static int test_probe(struct platform_device *plat_dev)
111156
if (IS_ERR(rtd->rtc))
112157
return PTR_ERR(rtd->rtc);
113158

159+
timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0);
160+
rtd->alarm.expires = 0;
161+
114162
return 0;
115163
}
116164

0 commit comments

Comments
 (0)