// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2020 Unisoc Communications Inc. */ /*\ * [Description] * * RTC device set time function test. * * [Algorithm] * * - Save RTC time * - Set RTC time * - Read the RTC time back * - Check if the set time and the read time are identical * - Restore RTC time */ #include #include "tst_rtctime.h" #include "tst_wallclock.h" #include "tst_test.h" static char *rtc_dev = "/dev/rtc"; static char *rtctime_to_str(struct rtc_time *tm) { static char rtctime_buf[128]; sprintf(rtctime_buf, "%04d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return rtctime_buf; } static int rtc_tm_cmp(struct rtc_time *set_tm, struct rtc_time *read_tm) { long delta, seconds1, seconds2; if (set_tm->tm_year != read_tm->tm_year) return 1; if (set_tm->tm_mon != read_tm->tm_mon) return 1; if (set_tm->tm_mday != read_tm->tm_mday) return 1; /* * Convert hour/min/sec into seconds to handle the normal * and special situations: * 1# * set_tm: 2022-04-28 13:00:50 * read_tm: 2022-04-28 13:00:50 * 2# * set_tm: 2022-04-28 13:00:50 * read_tm: 2022-04-28 13:00:51 * 3# * set_tm: 2022-04-28 13:00:59 * read_tm: 2022-04-28 13:01:00 * 4# * set_tm: 2022-04-28 13:59:59 * read_tm: 2022-04-28 14:00:00 * * Note: as we have avoided testing around the zero * clock, so it's impossible to hit situation 5# * set_tm: 2022-04-28 23:59:59 * read_tm: 2022-04-29 00:00:00 */ if ((set_tm->tm_hour != read_tm->tm_hour) || (set_tm->tm_min != read_tm->tm_min) || (set_tm->tm_sec != read_tm->tm_sec)) { seconds1 = (set_tm->tm_hour * 3600) + (set_tm->tm_min * 60) + set_tm->tm_sec; seconds2 = (read_tm->tm_hour * 3600) + (read_tm->tm_min * 60) + read_tm->tm_sec; delta = seconds2 - seconds1; if (delta < 0 || delta > 3) { tst_res(TFAIL, "seconds1 is %ld, seconds2 is %ld", seconds1, seconds2); return 1; } } return 0; } static void set_rtc_test(void) { struct rtc_time read_tm, set_tm; int ret; /* Read current RTC Time */ ret = tst_rtc_gettime(rtc_dev, &read_tm); if (ret != 0) { tst_res(TFAIL | TERRNO, "ioctl() RTC_RD_TIME"); return; } /* set rtc to +/-1 hour */ set_tm = read_tm; if (set_tm.tm_hour == 0) set_tm.tm_hour += 1; else set_tm.tm_hour -= 1; tst_res(TINFO, "To set RTC date/time is: %s", rtctime_to_str(&set_tm)); ret = tst_rtc_settime(rtc_dev, &set_tm); if (ret != 0) { tst_res(TFAIL | TERRNO, "ioctl() RTC_SET_TIME"); return; } /* Read new RTC Time */ ret = tst_rtc_gettime(rtc_dev, &read_tm); if (ret != 0) { tst_res(TFAIL | TERRNO, "ioctl() RTC_RD_TIME"); return; } tst_res(TINFO, "read RTC date/time is: %s", rtctime_to_str(&read_tm)); if (rtc_tm_cmp(&set_tm, &read_tm)) { tst_res(TFAIL, "RTC SET TEST"); return; } tst_res(TPASS, "The read RTC time is consistent with set time"); } static void rtc_setup(void) { int exists = access(rtc_dev, F_OK); if (exists < 0) tst_brk(TCONF, "RTC device %s not available", rtc_dev); tst_rtc_clock_save(rtc_dev); } static void rtc_cleanup(void) { tst_rtc_clock_restore(rtc_dev); } static struct tst_test test = { .setup = rtc_setup, .test_all = set_rtc_test, .cleanup = rtc_cleanup, .needs_root = 1, };