1 // SPDX-License-Identifier: GPL-2.0
3 * Real Time Clock Driver Test Program
10 #include <linux/rtc.h>
13 #include <sys/ioctl.h>
15 #include <sys/types.h>
19 #include "../kselftest_harness.h"
23 #define READ_LOOP_DURATION_SEC 30
24 #define READ_LOOP_SLEEP_MS 11
26 static char *rtc_file = "/dev/rtc0";
28 enum rtc_alarm_state {
39 self->fd = open(rtc_file, O_RDONLY);
42 FIXTURE_TEARDOWN(rtc) {
46 TEST_F(rtc, date_read) {
48 struct rtc_time rtc_tm;
50 if (self->fd == -1 && errno == ENOENT)
51 SKIP(return, "Skipping test since %s does not exist", rtc_file);
52 ASSERT_NE(-1, self->fd);
54 /* Read the RTC time/date */
55 rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
58 TH_LOG("Current RTC date/time is %02d/%02d/%02d %02d:%02d:%02d.",
59 rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
60 rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
63 static time_t rtc_time_to_timestamp(struct rtc_time *rtc_time)
66 .tm_sec = rtc_time->tm_sec,
67 .tm_min = rtc_time->tm_min,
68 .tm_hour = rtc_time->tm_hour,
69 .tm_mday = rtc_time->tm_mday,
70 .tm_mon = rtc_time->tm_mon,
71 .tm_year = rtc_time->tm_year,
74 return mktime(&tm_time);
77 static void nanosleep_with_retries(long ns)
79 struct timespec req = {
85 while (nanosleep(&req, &rem) != 0) {
86 req.tv_sec = rem.tv_sec;
87 req.tv_nsec = rem.tv_nsec;
91 static enum rtc_alarm_state get_rtc_alarm_state(int fd)
93 struct rtc_param param = { 0 };
96 /* Validate kernel reflects unsupported RTC alarm state */
97 param.param = RTC_PARAM_FEATURES;
99 rc = ioctl(fd, RTC_PARAM_GET, ¶m);
101 return RTC_ALARM_UNKNOWN;
103 if ((param.uvalue & _BITUL(RTC_FEATURE_ALARM)) == 0)
104 return RTC_ALARM_DISABLED;
106 return RTC_ALARM_ENABLED;
109 TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) {
112 struct rtc_time rtc_tm;
113 time_t start_rtc_read, prev_rtc_read;
115 if (self->fd == -1 && errno == ENOENT)
116 SKIP(return, "Skipping test since %s does not exist", rtc_file);
117 ASSERT_NE(-1, self->fd);
119 TH_LOG("Continuously reading RTC time for %ds (with %dms breaks after every read).",
120 READ_LOOP_DURATION_SEC, READ_LOOP_SLEEP_MS);
122 rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
124 start_rtc_read = rtc_time_to_timestamp(&rtc_tm);
125 prev_rtc_read = start_rtc_read;
130 rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
133 rtc_read = rtc_time_to_timestamp(&rtc_tm);
134 /* Time should not go backwards */
135 ASSERT_LE(prev_rtc_read, rtc_read);
136 /* Time should not increase more then 1s at a time */
137 ASSERT_GE(prev_rtc_read + 1, rtc_read);
139 /* Sleep 11ms to avoid killing / overheating the RTC */
140 nanosleep_with_retries(READ_LOOP_SLEEP_MS * 1000000);
142 prev_rtc_read = rtc_read;
144 } while (prev_rtc_read <= start_rtc_read + READ_LOOP_DURATION_SEC);
146 TH_LOG("Performed %ld RTC time reads.", iter_count);
149 TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) {
153 if (self->fd == -1 && errno == ENOENT)
154 SKIP(return, "Skipping test since %s does not exist", rtc_file);
155 ASSERT_NE(-1, self->fd);
157 /* Turn on update interrupts */
158 rc = ioctl(self->fd, RTC_UIE_ON, 0);
160 ASSERT_EQ(EINVAL, errno);
161 TH_LOG("skip update IRQs not supported.");
165 for (i = 0; i < NUM_UIE; i++) {
166 /* This read will block */
167 rc = read(self->fd, &data, sizeof(data));
172 EXPECT_EQ(NUM_UIE, irq);
174 rc = ioctl(self->fd, RTC_UIE_OFF, 0);
178 TEST_F(rtc, uie_select) {
182 if (self->fd == -1 && errno == ENOENT)
183 SKIP(return, "Skipping test since %s does not exist", rtc_file);
184 ASSERT_NE(-1, self->fd);
186 /* Turn on update interrupts */
187 rc = ioctl(self->fd, RTC_UIE_ON, 0);
189 ASSERT_EQ(EINVAL, errno);
190 TH_LOG("skip update IRQs not supported.");
194 for (i = 0; i < NUM_UIE; i++) {
195 struct timeval tv = { .tv_sec = 2 };
199 FD_SET(self->fd, &readfds);
200 /* The select will wait until an RTC interrupt happens. */
201 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
205 /* This read won't block */
206 rc = read(self->fd, &data, sizeof(unsigned long));
211 EXPECT_EQ(NUM_UIE, irq);
213 rc = ioctl(self->fd, RTC_UIE_OFF, 0);
217 TEST_F(rtc, alarm_alm_set) {
218 struct timeval tv = { .tv_sec = ALARM_DELTA + 2 };
224 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN;
226 if (self->fd == -1 && errno == ENOENT)
227 SKIP(return, "Skipping test since %s does not exist", rtc_file);
228 ASSERT_NE(-1, self->fd);
230 alarm_state = get_rtc_alarm_state(self->fd);
231 if (alarm_state == RTC_ALARM_DISABLED)
232 SKIP(return, "Skipping test since alarms are not supported.");
234 rc = ioctl(self->fd, RTC_RD_TIME, &tm);
237 secs = timegm((struct tm *)&tm) + ALARM_DELTA;
238 gmtime_r(&secs, (struct tm *)&tm);
240 rc = ioctl(self->fd, RTC_ALM_SET, &tm);
243 * Report error if rtc alarm was enabled. Fallback to check ioctl
244 * error number if rtc alarm state is unknown.
246 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state);
247 ASSERT_EQ(EINVAL, errno);
248 TH_LOG("skip alarms are not supported.");
252 rc = ioctl(self->fd, RTC_ALM_READ, &tm);
255 TH_LOG("Alarm time now set to %02d:%02d:%02d.",
256 tm.tm_hour, tm.tm_min, tm.tm_sec);
258 /* Enable alarm interrupts */
259 rc = ioctl(self->fd, RTC_AIE_ON, 0);
263 FD_SET(self->fd, &readfds);
265 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
269 /* Disable alarm interrupts */
270 rc = ioctl(self->fd, RTC_AIE_OFF, 0);
273 rc = read(self->fd, &data, sizeof(unsigned long));
275 TH_LOG("data: %lx", data);
277 rc = ioctl(self->fd, RTC_RD_TIME, &tm);
280 new = timegm((struct tm *)&tm);
281 ASSERT_EQ(new, secs);
284 TEST_F(rtc, alarm_wkalm_set) {
285 struct timeval tv = { .tv_sec = ALARM_DELTA + 2 };
286 struct rtc_wkalrm alarm = { 0 };
292 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN;
294 if (self->fd == -1 && errno == ENOENT)
295 SKIP(return, "Skipping test since %s does not exist", rtc_file);
296 ASSERT_NE(-1, self->fd);
298 alarm_state = get_rtc_alarm_state(self->fd);
299 if (alarm_state == RTC_ALARM_DISABLED)
300 SKIP(return, "Skipping test since alarms are not supported.");
302 rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
305 secs = timegm((struct tm *)&alarm.time) + ALARM_DELTA;
306 gmtime_r(&secs, (struct tm *)&alarm.time);
310 rc = ioctl(self->fd, RTC_WKALM_SET, &alarm);
313 * Report error if rtc alarm was enabled. Fallback to check ioctl
314 * error number if rtc alarm state is unknown.
316 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state);
317 ASSERT_EQ(EINVAL, errno);
318 TH_LOG("skip alarms are not supported.");
322 rc = ioctl(self->fd, RTC_WKALM_RD, &alarm);
325 TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.",
326 alarm.time.tm_mday, alarm.time.tm_mon + 1,
327 alarm.time.tm_year + 1900, alarm.time.tm_hour,
328 alarm.time.tm_min, alarm.time.tm_sec);
331 FD_SET(self->fd, &readfds);
333 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
337 rc = read(self->fd, &data, sizeof(unsigned long));
340 rc = ioctl(self->fd, RTC_RD_TIME, &tm);
343 new = timegm((struct tm *)&tm);
344 ASSERT_EQ(new, secs);
347 TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) {
348 struct timeval tv = { .tv_sec = 62 };
354 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN;
356 if (self->fd == -1 && errno == ENOENT)
357 SKIP(return, "Skipping test since %s does not exist", rtc_file);
358 ASSERT_NE(-1, self->fd);
360 alarm_state = get_rtc_alarm_state(self->fd);
361 if (alarm_state == RTC_ALARM_DISABLED)
362 SKIP(return, "Skipping test since alarms are not supported.");
364 rc = ioctl(self->fd, RTC_RD_TIME, &tm);
367 secs = timegm((struct tm *)&tm) + 60 - tm.tm_sec;
368 gmtime_r(&secs, (struct tm *)&tm);
370 rc = ioctl(self->fd, RTC_ALM_SET, &tm);
373 * Report error if rtc alarm was enabled. Fallback to check ioctl
374 * error number if rtc alarm state is unknown.
376 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state);
377 ASSERT_EQ(EINVAL, errno);
378 TH_LOG("skip alarms are not supported.");
382 rc = ioctl(self->fd, RTC_ALM_READ, &tm);
385 TH_LOG("Alarm time now set to %02d:%02d:%02d.",
386 tm.tm_hour, tm.tm_min, tm.tm_sec);
388 /* Enable alarm interrupts */
389 rc = ioctl(self->fd, RTC_AIE_ON, 0);
393 FD_SET(self->fd, &readfds);
395 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
399 /* Disable alarm interrupts */
400 rc = ioctl(self->fd, RTC_AIE_OFF, 0);
403 rc = read(self->fd, &data, sizeof(unsigned long));
405 TH_LOG("data: %lx", data);
407 rc = ioctl(self->fd, RTC_RD_TIME, &tm);
410 new = timegm((struct tm *)&tm);
411 ASSERT_EQ(new, secs);
414 TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) {
415 struct timeval tv = { .tv_sec = 62 };
416 struct rtc_wkalrm alarm = { 0 };
422 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN;
424 if (self->fd == -1 && errno == ENOENT)
425 SKIP(return, "Skipping test since %s does not exist", rtc_file);
426 ASSERT_NE(-1, self->fd);
428 alarm_state = get_rtc_alarm_state(self->fd);
429 if (alarm_state == RTC_ALARM_DISABLED)
430 SKIP(return, "Skipping test since alarms are not supported.");
432 rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
435 secs = timegm((struct tm *)&alarm.time) + 60 - alarm.time.tm_sec;
436 gmtime_r(&secs, (struct tm *)&alarm.time);
440 rc = ioctl(self->fd, RTC_WKALM_SET, &alarm);
443 * Report error if rtc alarm was enabled. Fallback to check ioctl
444 * error number if rtc alarm state is unknown.
446 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state);
447 ASSERT_EQ(EINVAL, errno);
448 TH_LOG("skip alarms are not supported.");
452 rc = ioctl(self->fd, RTC_WKALM_RD, &alarm);
455 TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.",
456 alarm.time.tm_mday, alarm.time.tm_mon + 1,
457 alarm.time.tm_year + 1900, alarm.time.tm_hour,
458 alarm.time.tm_min, alarm.time.tm_sec);
461 FD_SET(self->fd, &readfds);
463 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
467 rc = read(self->fd, &data, sizeof(unsigned long));
470 rc = ioctl(self->fd, RTC_RD_TIME, &tm);
473 new = timegm((struct tm *)&tm);
474 ASSERT_EQ(new, secs);
477 int main(int argc, char **argv)
488 fprintf(stderr, "usage: %s [rtcdev]\n", argv[0]);
492 /* Run the test if rtc_file is accessible */
493 if (access(rtc_file, R_OK) == 0)
494 ret = test_harness_run(argc, argv);
496 ksft_exit_skip("[SKIP]: Cannot access rtc file %s - Exiting\n",