diff options
author | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2018-05-31 17:09:58 -0400 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2018-05-31 17:13:29 -0400 |
commit | 8be09029940227d30ae310bb3fe25bc8abbfe140 (patch) | |
tree | 82ba4eca323f49b6c672754d69a3356cff3c01e4 | |
parent | 4dc2403bed0dbc18d90cc637337eebfc1e939c72 (diff) |
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>
-rw-r--r-- | drivers/rtc/rtc-test.c | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index f50b3321314f..3aee7be3a58a 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c | |||
@@ -18,19 +18,49 @@ | |||
18 | struct rtc_test_data { | 18 | struct rtc_test_data { |
19 | struct rtc_device *rtc; | 19 | struct rtc_device *rtc; |
20 | time64_t offset; | 20 | time64_t offset; |
21 | struct timer_list alarm; | ||
22 | bool alarm_en; | ||
21 | }; | 23 | }; |
22 | 24 | ||
23 | struct platform_device *pdev[MAX_RTC_TEST]; | 25 | struct platform_device *pdev[MAX_RTC_TEST]; |
24 | 26 | ||
25 | static int test_rtc_read_alarm(struct device *dev, | 27 | static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
26 | struct rtc_wkalrm *alrm) | ||
27 | { | 28 | { |
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 | |||
28 | return 0; | 38 | return 0; |
29 | } | 39 | } |
30 | 40 | ||
31 | static int test_rtc_set_alarm(struct device *dev, | 41 | static int test_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
32 | struct rtc_wkalrm *alrm) | ||
33 | { | 42 | { |
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 | |||
34 | return 0; | 64 | return 0; |
35 | } | 65 | } |
36 | 66 | ||
@@ -54,6 +84,14 @@ static int test_rtc_set_mmss64(struct device *dev, time64_t secs) | |||
54 | 84 | ||
55 | static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) | 85 | static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) |
56 | { | 86 | { |
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 | |||
57 | return 0; | 95 | return 0; |
58 | } | 96 | } |
59 | 97 | ||
@@ -65,6 +103,13 @@ static const struct rtc_class_ops test_rtc_ops = { | |||
65 | .alarm_irq_enable = test_rtc_alarm_irq_enable, | 103 | .alarm_irq_enable = test_rtc_alarm_irq_enable, |
66 | }; | 104 | }; |
67 | 105 | ||
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 | |||
68 | static ssize_t test_irq_show(struct device *dev, | 113 | static ssize_t test_irq_show(struct device *dev, |
69 | struct device_attribute *attr, char *buf) | 114 | struct device_attribute *attr, char *buf) |
70 | { | 115 | { |
@@ -111,6 +156,9 @@ static int test_probe(struct platform_device *plat_dev) | |||
111 | if (IS_ERR(rtd->rtc)) | 156 | if (IS_ERR(rtd->rtc)) |
112 | return PTR_ERR(rtd->rtc); | 157 | return PTR_ERR(rtd->rtc); |
113 | 158 | ||
159 | timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0); | ||
160 | rtd->alarm.expires = 0; | ||
161 | |||
114 | return 0; | 162 | return 0; |
115 | } | 163 | } |
116 | 164 | ||