1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Real Time Clock Driver Test Program 4 * 5 * Copyright (c) 2018 Alexandre Belloni <alexandre.belloni@bootlin.com> 6 */ 7 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <linux/rtc.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <sys/ioctl.h> 14 #include <sys/time.h> 15 #include <sys/types.h> 16 #include <time.h> 17 #include <unistd.h> 18 19 #include "../kselftest_harness.h" 20 21 #define NUM_UIE 3 22 #define ALARM_DELTA 3 23 #define READ_LOOP_DURATION_SEC 30 24 #define READ_LOOP_SLEEP_MS 11 25 26 static char *rtc_file = "/dev/rtc0"; 27 28 enum rtc_alarm_state { 29 RTC_ALARM_UNKNOWN, 30 RTC_ALARM_ENABLED, 31 RTC_ALARM_DISABLED, 32 }; 33 34 FIXTURE(rtc) { 35 int fd; 36 }; 37 38 FIXTURE_SETUP(rtc) { 39 self->fd = open(rtc_file, O_RDONLY); 40 } 41 42 FIXTURE_TEARDOWN(rtc) { 43 close(self->fd); 44 } 45 46 TEST_F(rtc, date_read) { 47 int rc; 48 struct rtc_time rtc_tm; 49 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); 53 54 /* Read the RTC time/date */ 55 rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); 56 ASSERT_NE(-1, rc); 57 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); 61 } 62 63 static time_t rtc_time_to_timestamp(struct rtc_time *rtc_time) 64 { 65 struct tm tm_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, 72 }; 73 74 return mktime(&tm_time); 75 } 76 77 static void nanosleep_with_retries(long ns) 78 { 79 struct timespec req = { 80 .tv_sec = 0, 81 .tv_nsec = ns, 82 }; 83 struct timespec rem; 84 85 while (nanosleep(&req, &rem) != 0) { 86 req.tv_sec = rem.tv_sec; 87 req.tv_nsec = rem.tv_nsec; 88 } 89 } 90 91 static enum rtc_alarm_state get_rtc_alarm_state(int fd) 92 { 93 struct rtc_param param = { 0 }; 94 int rc; 95 96 /* Validate kernel reflects unsupported RTC alarm state */ 97 param.param = RTC_PARAM_FEATURES; 98 param.index = 0; 99 rc = ioctl(fd, RTC_PARAM_GET, ¶m); 100 if (rc < 0) 101 return RTC_ALARM_UNKNOWN; 102 103 if ((param.uvalue & _BITUL(RTC_FEATURE_ALARM)) == 0) 104 return RTC_ALARM_DISABLED; 105 106 return RTC_ALARM_ENABLED; 107 } 108 109 TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) { 110 int rc; 111 long iter_count = 0; 112 struct rtc_time rtc_tm; 113 time_t start_rtc_read, prev_rtc_read; 114 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); 118 119 TH_LOG("Continuously reading RTC time for %ds (with %dms breaks after every read).", 120 READ_LOOP_DURATION_SEC, READ_LOOP_SLEEP_MS); 121 122 rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); 123 ASSERT_NE(-1, rc); 124 start_rtc_read = rtc_time_to_timestamp(&rtc_tm); 125 prev_rtc_read = start_rtc_read; 126 127 do { 128 time_t rtc_read; 129 130 rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); 131 ASSERT_NE(-1, rc); 132 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); 138 139 /* Sleep 11ms to avoid killing / overheating the RTC */ 140 nanosleep_with_retries(READ_LOOP_SLEEP_MS * 1000000); 141 142 prev_rtc_read = rtc_read; 143 iter_count++; 144 } while (prev_rtc_read <= start_rtc_read + READ_LOOP_DURATION_SEC); 145 146 TH_LOG("Performed %ld RTC time reads.", iter_count); 147 } 148 149 TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) { 150 int i, rc, irq = 0; 151 unsigned long data; 152 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); 156 157 /* Turn on update interrupts */ 158 rc = ioctl(self->fd, RTC_UIE_ON, 0); 159 if (rc == -1) { 160 ASSERT_EQ(EINVAL, errno); 161 TH_LOG("skip update IRQs not supported."); 162 return; 163 } 164 165 for (i = 0; i < NUM_UIE; i++) { 166 /* This read will block */ 167 rc = read(self->fd, &data, sizeof(data)); 168 ASSERT_NE(-1, rc); 169 irq++; 170 } 171 172 EXPECT_EQ(NUM_UIE, irq); 173 174 rc = ioctl(self->fd, RTC_UIE_OFF, 0); 175 ASSERT_NE(-1, rc); 176 } 177 178 TEST_F(rtc, uie_select) { 179 int i, rc, irq = 0; 180 unsigned long data; 181 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); 185 186 /* Turn on update interrupts */ 187 rc = ioctl(self->fd, RTC_UIE_ON, 0); 188 if (rc == -1) { 189 ASSERT_EQ(EINVAL, errno); 190 TH_LOG("skip update IRQs not supported."); 191 return; 192 } 193 194 for (i = 0; i < NUM_UIE; i++) { 195 struct timeval tv = { .tv_sec = 2 }; 196 fd_set readfds; 197 198 FD_ZERO(&readfds); 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); 202 ASSERT_NE(-1, rc); 203 ASSERT_NE(0, rc); 204 205 /* This read won't block */ 206 rc = read(self->fd, &data, sizeof(unsigned long)); 207 ASSERT_NE(-1, rc); 208 irq++; 209 } 210 211 EXPECT_EQ(NUM_UIE, irq); 212 213 rc = ioctl(self->fd, RTC_UIE_OFF, 0); 214 ASSERT_NE(-1, rc); 215 } 216 217 TEST_F(rtc, alarm_alm_set) { 218 struct timeval tv = { .tv_sec = ALARM_DELTA + 2 }; 219 unsigned long data; 220 struct rtc_time tm; 221 fd_set readfds; 222 time_t secs, new; 223 int rc; 224 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; 225 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); 229 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."); 233 234 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 235 ASSERT_NE(-1, rc); 236 237 secs = timegm((struct tm *)&tm) + ALARM_DELTA; 238 gmtime_r(&secs, (struct tm *)&tm); 239 240 rc = ioctl(self->fd, RTC_ALM_SET, &tm); 241 if (rc == -1) { 242 /* 243 * Report error if rtc alarm was enabled. Fallback to check ioctl 244 * error number if rtc alarm state is unknown. 245 */ 246 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); 247 ASSERT_EQ(EINVAL, errno); 248 TH_LOG("skip alarms are not supported."); 249 return; 250 } 251 252 rc = ioctl(self->fd, RTC_ALM_READ, &tm); 253 ASSERT_NE(-1, rc); 254 255 TH_LOG("Alarm time now set to %02d:%02d:%02d.", 256 tm.tm_hour, tm.tm_min, tm.tm_sec); 257 258 /* Enable alarm interrupts */ 259 rc = ioctl(self->fd, RTC_AIE_ON, 0); 260 ASSERT_NE(-1, rc); 261 262 FD_ZERO(&readfds); 263 FD_SET(self->fd, &readfds); 264 265 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 266 ASSERT_NE(-1, rc); 267 ASSERT_NE(0, rc); 268 269 /* Disable alarm interrupts */ 270 rc = ioctl(self->fd, RTC_AIE_OFF, 0); 271 ASSERT_NE(-1, rc); 272 273 rc = read(self->fd, &data, sizeof(unsigned long)); 274 ASSERT_NE(-1, rc); 275 TH_LOG("data: %lx", data); 276 277 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 278 ASSERT_NE(-1, rc); 279 280 new = timegm((struct tm *)&tm); 281 ASSERT_EQ(new, secs); 282 } 283 284 TEST_F(rtc, alarm_wkalm_set) { 285 struct timeval tv = { .tv_sec = ALARM_DELTA + 2 }; 286 struct rtc_wkalrm alarm = { 0 }; 287 struct rtc_time tm; 288 unsigned long data; 289 fd_set readfds; 290 time_t secs, new; 291 int rc; 292 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; 293 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); 297 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."); 301 302 rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); 303 ASSERT_NE(-1, rc); 304 305 secs = timegm((struct tm *)&alarm.time) + ALARM_DELTA; 306 gmtime_r(&secs, (struct tm *)&alarm.time); 307 308 alarm.enabled = 1; 309 310 rc = ioctl(self->fd, RTC_WKALM_SET, &alarm); 311 if (rc == -1) { 312 /* 313 * Report error if rtc alarm was enabled. Fallback to check ioctl 314 * error number if rtc alarm state is unknown. 315 */ 316 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); 317 ASSERT_EQ(EINVAL, errno); 318 TH_LOG("skip alarms are not supported."); 319 return; 320 } 321 322 rc = ioctl(self->fd, RTC_WKALM_RD, &alarm); 323 ASSERT_NE(-1, rc); 324 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); 329 330 FD_ZERO(&readfds); 331 FD_SET(self->fd, &readfds); 332 333 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 334 ASSERT_NE(-1, rc); 335 ASSERT_NE(0, rc); 336 337 rc = read(self->fd, &data, sizeof(unsigned long)); 338 ASSERT_NE(-1, rc); 339 340 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 341 ASSERT_NE(-1, rc); 342 343 new = timegm((struct tm *)&tm); 344 ASSERT_EQ(new, secs); 345 } 346 347 TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) { 348 struct timeval tv = { .tv_sec = 62 }; 349 unsigned long data; 350 struct rtc_time tm; 351 fd_set readfds; 352 time_t secs, new; 353 int rc; 354 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; 355 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); 359 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."); 363 364 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 365 ASSERT_NE(-1, rc); 366 367 secs = timegm((struct tm *)&tm) + 60 - tm.tm_sec; 368 gmtime_r(&secs, (struct tm *)&tm); 369 370 rc = ioctl(self->fd, RTC_ALM_SET, &tm); 371 if (rc == -1) { 372 /* 373 * Report error if rtc alarm was enabled. Fallback to check ioctl 374 * error number if rtc alarm state is unknown. 375 */ 376 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); 377 ASSERT_EQ(EINVAL, errno); 378 TH_LOG("skip alarms are not supported."); 379 return; 380 } 381 382 rc = ioctl(self->fd, RTC_ALM_READ, &tm); 383 ASSERT_NE(-1, rc); 384 385 TH_LOG("Alarm time now set to %02d:%02d:%02d.", 386 tm.tm_hour, tm.tm_min, tm.tm_sec); 387 388 /* Enable alarm interrupts */ 389 rc = ioctl(self->fd, RTC_AIE_ON, 0); 390 ASSERT_NE(-1, rc); 391 392 FD_ZERO(&readfds); 393 FD_SET(self->fd, &readfds); 394 395 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 396 ASSERT_NE(-1, rc); 397 ASSERT_NE(0, rc); 398 399 /* Disable alarm interrupts */ 400 rc = ioctl(self->fd, RTC_AIE_OFF, 0); 401 ASSERT_NE(-1, rc); 402 403 rc = read(self->fd, &data, sizeof(unsigned long)); 404 ASSERT_NE(-1, rc); 405 TH_LOG("data: %lx", data); 406 407 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 408 ASSERT_NE(-1, rc); 409 410 new = timegm((struct tm *)&tm); 411 ASSERT_EQ(new, secs); 412 } 413 414 TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) { 415 struct timeval tv = { .tv_sec = 62 }; 416 struct rtc_wkalrm alarm = { 0 }; 417 struct rtc_time tm; 418 unsigned long data; 419 fd_set readfds; 420 time_t secs, new; 421 int rc; 422 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; 423 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); 427 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."); 431 432 rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); 433 ASSERT_NE(-1, rc); 434 435 secs = timegm((struct tm *)&alarm.time) + 60 - alarm.time.tm_sec; 436 gmtime_r(&secs, (struct tm *)&alarm.time); 437 438 alarm.enabled = 1; 439 440 rc = ioctl(self->fd, RTC_WKALM_SET, &alarm); 441 if (rc == -1) { 442 /* 443 * Report error if rtc alarm was enabled. Fallback to check ioctl 444 * error number if rtc alarm state is unknown. 445 */ 446 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); 447 ASSERT_EQ(EINVAL, errno); 448 TH_LOG("skip alarms are not supported."); 449 return; 450 } 451 452 rc = ioctl(self->fd, RTC_WKALM_RD, &alarm); 453 ASSERT_NE(-1, rc); 454 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); 459 460 FD_ZERO(&readfds); 461 FD_SET(self->fd, &readfds); 462 463 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 464 ASSERT_NE(-1, rc); 465 ASSERT_NE(0, rc); 466 467 rc = read(self->fd, &data, sizeof(unsigned long)); 468 ASSERT_NE(-1, rc); 469 470 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 471 ASSERT_NE(-1, rc); 472 473 new = timegm((struct tm *)&tm); 474 ASSERT_EQ(new, secs); 475 } 476 477 int main(int argc, char **argv) 478 { 479 int ret = -1; 480 481 switch (argc) { 482 case 2: 483 rtc_file = argv[1]; 484 /* FALLTHROUGH */ 485 case 1: 486 break; 487 default: 488 fprintf(stderr, "usage: %s [rtcdev]\n", argv[0]); 489 return 1; 490 } 491 492 /* Run the test if rtc_file is accessible */ 493 if (access(rtc_file, R_OK) == 0) 494 ret = test_harness_run(argc, argv); 495 else 496 ksft_exit_skip("[SKIP]: Cannot access rtc file %s - Exiting\n", 497 rtc_file); 498 499 return ret; 500 } 501