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 RTC_ALARM_RES_MINUTE, 33 }; 34 35 FIXTURE(rtc) { 36 int fd; 37 }; 38 39 FIXTURE_SETUP(rtc) { 40 self->fd = open(rtc_file, O_RDONLY); 41 } 42 43 FIXTURE_TEARDOWN(rtc) { 44 close(self->fd); 45 } 46 47 TEST_F(rtc, date_read) { 48 int rc; 49 struct rtc_time rtc_tm; 50 51 if (self->fd == -1 && errno == ENOENT) 52 SKIP(return, "Skipping test since %s does not exist", rtc_file); 53 ASSERT_NE(-1, self->fd); 54 55 /* Read the RTC time/date */ 56 rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); 57 ASSERT_NE(-1, rc); 58 59 TH_LOG("Current RTC date/time is %02d/%02d/%02d %02d:%02d:%02d.", 60 rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900, 61 rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); 62 } 63 64 static time_t rtc_time_to_timestamp(struct rtc_time *rtc_time) 65 { 66 struct tm tm_time = { 67 .tm_sec = rtc_time->tm_sec, 68 .tm_min = rtc_time->tm_min, 69 .tm_hour = rtc_time->tm_hour, 70 .tm_mday = rtc_time->tm_mday, 71 .tm_mon = rtc_time->tm_mon, 72 .tm_year = rtc_time->tm_year, 73 }; 74 75 return mktime(&tm_time); 76 } 77 78 static void nanosleep_with_retries(long ns) 79 { 80 struct timespec req = { 81 .tv_sec = 0, 82 .tv_nsec = ns, 83 }; 84 struct timespec rem; 85 86 while (nanosleep(&req, &rem) != 0) { 87 req.tv_sec = rem.tv_sec; 88 req.tv_nsec = rem.tv_nsec; 89 } 90 } 91 92 static enum rtc_alarm_state get_rtc_alarm_state(int fd, int need_seconds) 93 { 94 struct rtc_param param = { 0 }; 95 int rc; 96 97 /* Validate kernel reflects unsupported RTC alarm state */ 98 param.param = RTC_PARAM_FEATURES; 99 param.index = 0; 100 rc = ioctl(fd, RTC_PARAM_GET, ¶m); 101 if (rc < 0) 102 return RTC_ALARM_UNKNOWN; 103 104 if ((param.uvalue & _BITUL(RTC_FEATURE_ALARM)) == 0) 105 return RTC_ALARM_DISABLED; 106 107 /* Check if alarm has desired granularity */ 108 if (need_seconds && (param.uvalue & _BITUL(RTC_FEATURE_ALARM_RES_MINUTE))) 109 return RTC_ALARM_RES_MINUTE; 110 111 return RTC_ALARM_ENABLED; 112 } 113 114 TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) { 115 int rc; 116 long iter_count = 0; 117 struct rtc_time rtc_tm; 118 time_t start_rtc_read, prev_rtc_read; 119 120 if (self->fd == -1 && errno == ENOENT) 121 SKIP(return, "Skipping test since %s does not exist", rtc_file); 122 ASSERT_NE(-1, self->fd); 123 124 TH_LOG("Continuously reading RTC time for %ds (with %dms breaks after every read).", 125 READ_LOOP_DURATION_SEC, READ_LOOP_SLEEP_MS); 126 127 rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); 128 ASSERT_NE(-1, rc); 129 start_rtc_read = rtc_time_to_timestamp(&rtc_tm); 130 prev_rtc_read = start_rtc_read; 131 132 do { 133 time_t rtc_read; 134 135 rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); 136 ASSERT_NE(-1, rc); 137 138 rtc_read = rtc_time_to_timestamp(&rtc_tm); 139 /* Time should not go backwards */ 140 ASSERT_LE(prev_rtc_read, rtc_read); 141 /* Time should not increase more then 1s at a time */ 142 ASSERT_GE(prev_rtc_read + 1, rtc_read); 143 144 /* Sleep 11ms to avoid killing / overheating the RTC */ 145 nanosleep_with_retries(READ_LOOP_SLEEP_MS * 1000000); 146 147 prev_rtc_read = rtc_read; 148 iter_count++; 149 } while (prev_rtc_read <= start_rtc_read + READ_LOOP_DURATION_SEC); 150 151 TH_LOG("Performed %ld RTC time reads.", iter_count); 152 } 153 154 TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) { 155 int i, rc, irq = 0; 156 unsigned long data; 157 158 if (self->fd == -1 && errno == ENOENT) 159 SKIP(return, "Skipping test since %s does not exist", rtc_file); 160 ASSERT_NE(-1, self->fd); 161 162 /* Turn on update interrupts */ 163 rc = ioctl(self->fd, RTC_UIE_ON, 0); 164 if (rc == -1) { 165 ASSERT_EQ(EINVAL, errno); 166 TH_LOG("skip update IRQs not supported."); 167 return; 168 } 169 170 for (i = 0; i < NUM_UIE; i++) { 171 /* This read will block */ 172 rc = read(self->fd, &data, sizeof(data)); 173 ASSERT_NE(-1, rc); 174 irq++; 175 } 176 177 EXPECT_EQ(NUM_UIE, irq); 178 179 rc = ioctl(self->fd, RTC_UIE_OFF, 0); 180 ASSERT_NE(-1, rc); 181 } 182 183 TEST_F(rtc, uie_select) { 184 int i, rc, irq = 0; 185 unsigned long data; 186 187 if (self->fd == -1 && errno == ENOENT) 188 SKIP(return, "Skipping test since %s does not exist", rtc_file); 189 ASSERT_NE(-1, self->fd); 190 191 /* Turn on update interrupts */ 192 rc = ioctl(self->fd, RTC_UIE_ON, 0); 193 if (rc == -1) { 194 ASSERT_EQ(EINVAL, errno); 195 TH_LOG("skip update IRQs not supported."); 196 return; 197 } 198 199 for (i = 0; i < NUM_UIE; i++) { 200 struct timeval tv = { .tv_sec = 2 }; 201 fd_set readfds; 202 203 FD_ZERO(&readfds); 204 FD_SET(self->fd, &readfds); 205 /* The select will wait until an RTC interrupt happens. */ 206 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 207 ASSERT_NE(-1, rc); 208 ASSERT_NE(0, rc); 209 210 /* This read won't block */ 211 rc = read(self->fd, &data, sizeof(unsigned long)); 212 ASSERT_NE(-1, rc); 213 irq++; 214 } 215 216 EXPECT_EQ(NUM_UIE, irq); 217 218 rc = ioctl(self->fd, RTC_UIE_OFF, 0); 219 ASSERT_NE(-1, rc); 220 } 221 222 TEST_F(rtc, alarm_alm_set) { 223 struct timeval tv = { .tv_sec = ALARM_DELTA + 2 }; 224 unsigned long data; 225 struct rtc_time tm; 226 fd_set readfds; 227 time_t secs, new; 228 int rc; 229 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; 230 231 if (self->fd == -1 && errno == ENOENT) 232 SKIP(return, "Skipping test since %s does not exist", rtc_file); 233 ASSERT_NE(-1, self->fd); 234 235 alarm_state = get_rtc_alarm_state(self->fd, 1); 236 if (alarm_state == RTC_ALARM_DISABLED) 237 SKIP(return, "Skipping test since alarms are not supported."); 238 if (alarm_state == RTC_ALARM_RES_MINUTE) 239 SKIP(return, "Skipping test since alarms has only minute granularity."); 240 241 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 242 ASSERT_NE(-1, rc); 243 244 secs = timegm((struct tm *)&tm) + ALARM_DELTA; 245 gmtime_r(&secs, (struct tm *)&tm); 246 247 rc = ioctl(self->fd, RTC_ALM_SET, &tm); 248 if (rc == -1) { 249 /* 250 * Report error if rtc alarm was enabled. Fallback to check ioctl 251 * error number if rtc alarm state is unknown. 252 */ 253 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); 254 ASSERT_EQ(EINVAL, errno); 255 TH_LOG("skip alarms are not supported."); 256 return; 257 } 258 259 rc = ioctl(self->fd, RTC_ALM_READ, &tm); 260 ASSERT_NE(-1, rc); 261 262 TH_LOG("Alarm time now set to %02d:%02d:%02d.", 263 tm.tm_hour, tm.tm_min, tm.tm_sec); 264 265 /* Enable alarm interrupts */ 266 rc = ioctl(self->fd, RTC_AIE_ON, 0); 267 ASSERT_NE(-1, rc); 268 269 FD_ZERO(&readfds); 270 FD_SET(self->fd, &readfds); 271 272 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 273 ASSERT_NE(-1, rc); 274 ASSERT_NE(0, rc); 275 276 /* Disable alarm interrupts */ 277 rc = ioctl(self->fd, RTC_AIE_OFF, 0); 278 ASSERT_NE(-1, rc); 279 280 rc = read(self->fd, &data, sizeof(unsigned long)); 281 ASSERT_NE(-1, rc); 282 TH_LOG("data: %lx", data); 283 284 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 285 ASSERT_NE(-1, rc); 286 287 new = timegm((struct tm *)&tm); 288 ASSERT_EQ(new, secs); 289 } 290 291 TEST_F(rtc, alarm_wkalm_set) { 292 struct timeval tv = { .tv_sec = ALARM_DELTA + 2 }; 293 struct rtc_wkalrm alarm = { 0 }; 294 struct rtc_time tm; 295 unsigned long data; 296 fd_set readfds; 297 time_t secs, new; 298 int rc; 299 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; 300 301 if (self->fd == -1 && errno == ENOENT) 302 SKIP(return, "Skipping test since %s does not exist", rtc_file); 303 ASSERT_NE(-1, self->fd); 304 305 alarm_state = get_rtc_alarm_state(self->fd, 1); 306 if (alarm_state == RTC_ALARM_DISABLED) 307 SKIP(return, "Skipping test since alarms are not supported."); 308 if (alarm_state == RTC_ALARM_RES_MINUTE) 309 SKIP(return, "Skipping test since alarms has only minute granularity."); 310 311 rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); 312 ASSERT_NE(-1, rc); 313 314 secs = timegm((struct tm *)&alarm.time) + ALARM_DELTA; 315 gmtime_r(&secs, (struct tm *)&alarm.time); 316 317 alarm.enabled = 1; 318 319 rc = ioctl(self->fd, RTC_WKALM_SET, &alarm); 320 if (rc == -1) { 321 /* 322 * Report error if rtc alarm was enabled. Fallback to check ioctl 323 * error number if rtc alarm state is unknown. 324 */ 325 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); 326 ASSERT_EQ(EINVAL, errno); 327 TH_LOG("skip alarms are not supported."); 328 return; 329 } 330 331 rc = ioctl(self->fd, RTC_WKALM_RD, &alarm); 332 ASSERT_NE(-1, rc); 333 334 TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.", 335 alarm.time.tm_mday, alarm.time.tm_mon + 1, 336 alarm.time.tm_year + 1900, alarm.time.tm_hour, 337 alarm.time.tm_min, alarm.time.tm_sec); 338 339 FD_ZERO(&readfds); 340 FD_SET(self->fd, &readfds); 341 342 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 343 ASSERT_NE(-1, rc); 344 ASSERT_NE(0, rc); 345 346 rc = read(self->fd, &data, sizeof(unsigned long)); 347 ASSERT_NE(-1, rc); 348 349 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 350 ASSERT_NE(-1, rc); 351 352 new = timegm((struct tm *)&tm); 353 ASSERT_EQ(new, secs); 354 } 355 356 TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) { 357 struct timeval tv = { .tv_sec = 62 }; 358 unsigned long data; 359 struct rtc_time tm; 360 fd_set readfds; 361 time_t secs, new; 362 int rc; 363 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; 364 365 if (self->fd == -1 && errno == ENOENT) 366 SKIP(return, "Skipping test since %s does not exist", rtc_file); 367 ASSERT_NE(-1, self->fd); 368 369 alarm_state = get_rtc_alarm_state(self->fd, 0); 370 if (alarm_state == RTC_ALARM_DISABLED) 371 SKIP(return, "Skipping test since alarms are not supported."); 372 373 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 374 ASSERT_NE(-1, rc); 375 376 secs = timegm((struct tm *)&tm) + 60 - tm.tm_sec; 377 gmtime_r(&secs, (struct tm *)&tm); 378 379 rc = ioctl(self->fd, RTC_ALM_SET, &tm); 380 if (rc == -1) { 381 /* 382 * Report error if rtc alarm was enabled. Fallback to check ioctl 383 * error number if rtc alarm state is unknown. 384 */ 385 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); 386 ASSERT_EQ(EINVAL, errno); 387 TH_LOG("skip alarms are not supported."); 388 return; 389 } 390 391 rc = ioctl(self->fd, RTC_ALM_READ, &tm); 392 ASSERT_NE(-1, rc); 393 394 TH_LOG("Alarm time now set to %02d:%02d:%02d.", 395 tm.tm_hour, tm.tm_min, tm.tm_sec); 396 397 /* Enable alarm interrupts */ 398 rc = ioctl(self->fd, RTC_AIE_ON, 0); 399 ASSERT_NE(-1, rc); 400 401 FD_ZERO(&readfds); 402 FD_SET(self->fd, &readfds); 403 404 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 405 ASSERT_NE(-1, rc); 406 ASSERT_NE(0, rc); 407 408 /* Disable alarm interrupts */ 409 rc = ioctl(self->fd, RTC_AIE_OFF, 0); 410 ASSERT_NE(-1, rc); 411 412 rc = read(self->fd, &data, sizeof(unsigned long)); 413 ASSERT_NE(-1, rc); 414 TH_LOG("data: %lx", data); 415 416 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 417 ASSERT_NE(-1, rc); 418 419 new = timegm((struct tm *)&tm); 420 ASSERT_EQ(new, secs); 421 } 422 423 TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) { 424 struct timeval tv = { .tv_sec = 62 }; 425 struct rtc_wkalrm alarm = { 0 }; 426 struct rtc_time tm; 427 unsigned long data; 428 fd_set readfds; 429 time_t secs, new; 430 int rc; 431 enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; 432 433 if (self->fd == -1 && errno == ENOENT) 434 SKIP(return, "Skipping test since %s does not exist", rtc_file); 435 ASSERT_NE(-1, self->fd); 436 437 alarm_state = get_rtc_alarm_state(self->fd, 0); 438 if (alarm_state == RTC_ALARM_DISABLED) 439 SKIP(return, "Skipping test since alarms are not supported."); 440 441 rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); 442 ASSERT_NE(-1, rc); 443 444 secs = timegm((struct tm *)&alarm.time) + 60 - alarm.time.tm_sec; 445 gmtime_r(&secs, (struct tm *)&alarm.time); 446 447 alarm.enabled = 1; 448 449 rc = ioctl(self->fd, RTC_WKALM_SET, &alarm); 450 if (rc == -1) { 451 /* 452 * Report error if rtc alarm was enabled. Fallback to check ioctl 453 * error number if rtc alarm state is unknown. 454 */ 455 ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); 456 ASSERT_EQ(EINVAL, errno); 457 TH_LOG("skip alarms are not supported."); 458 return; 459 } 460 461 rc = ioctl(self->fd, RTC_WKALM_RD, &alarm); 462 ASSERT_NE(-1, rc); 463 464 TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.", 465 alarm.time.tm_mday, alarm.time.tm_mon + 1, 466 alarm.time.tm_year + 1900, alarm.time.tm_hour, 467 alarm.time.tm_min, alarm.time.tm_sec); 468 469 FD_ZERO(&readfds); 470 FD_SET(self->fd, &readfds); 471 472 rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 473 ASSERT_NE(-1, rc); 474 ASSERT_NE(0, rc); 475 476 rc = read(self->fd, &data, sizeof(unsigned long)); 477 ASSERT_NE(-1, rc); 478 479 rc = ioctl(self->fd, RTC_RD_TIME, &tm); 480 ASSERT_NE(-1, rc); 481 482 new = timegm((struct tm *)&tm); 483 ASSERT_EQ(new, secs); 484 } 485 486 int main(int argc, char **argv) 487 { 488 int ret = -1; 489 490 switch (argc) { 491 case 2: 492 rtc_file = argv[1]; 493 /* FALLTHROUGH */ 494 case 1: 495 break; 496 default: 497 fprintf(stderr, "usage: %s [rtcdev]\n", argv[0]); 498 return 1; 499 } 500 501 /* Run the test if rtc_file is accessible */ 502 if (access(rtc_file, R_OK) == 0) 503 ret = test_harness_run(argc, argv); 504 else 505 ksft_exit_skip("[SKIP]: Cannot access rtc file %s - Exiting\n", 506 rtc_file); 507 508 return ret; 509 } 510