Merge tag 'rtc-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni: "Here is the pull-request for the RTC subsystem for 4.13. Subsystem: - expose non volatile RAM using nvmem instead of open coding in many drivers. Unfortunately, this option has to be enabled by default to not break existing users. - rtctest can now test for cutoff dates, showing when an RTC will start failing to properly save time and date. - new RTC registration functions to remove race conditions in drivers Newly supported RTCs: - Broadcom STB wake-timer - Epson RX8130CE - Maxim IC DS1308 - STMicroelectronics STM32H7 Drivers: - ds1307: use regmap, use nvmem, more cleanups - ds3232: temperature reading support - gemini: renamed to ftrtc010 - m41t80: use CCF to expose the clock - rv8803: use nvmem - s3c: many cleanups - st-lpc: fix y2106 bug" * tag 'rtc-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (51 commits) rtc: Remove wrong deprecation comment nvmem: include linux/err.h from header rtc: st-lpc: make it robust against y2038/2106 bug rtc: rtctest: add check for problematic dates tools: timer: add rtctest_setdate rtc: ds1307: remove ds1307_remove rtc: ds1307: use generic nvmem rtc: ds1307: switch to rtc_register_device rtc: rv8803: remove rv8803_remove rtc: rv8803: use generic nvmem support rtc: rv8803: switch to rtc_register_device rtc: add generic nvmem support rtc: at91rm9200: remove race condition rtc: introduce new registration method rtc: class separate id allocation from registration rtc: class separate device allocation from registration rtc: stm32: add STM32H7 RTC support dt-bindings: rtc: stm32: add support for STM32H7 rtc: ds1307: add ds1308 variant rtc: ds3232: add temperature support ...
This commit is contained in:
@ -9,7 +9,7 @@ TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
|
||||
|
||||
TEST_GEN_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \
|
||||
skew_consistency clocksource-switch freq-step leap-a-day \
|
||||
leapcrash set-tai set-2038 set-tz
|
||||
leapcrash set-tai set-2038 set-tz rtctest_setdate
|
||||
|
||||
|
||||
include ../lib.mk
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This expects the new RTC class driver framework, working with
|
||||
@ -29,23 +32,84 @@
|
||||
*/
|
||||
static const char default_rtc[] = "/dev/rtc0";
|
||||
|
||||
static struct rtc_time cutoff_dates[] = {
|
||||
{
|
||||
.tm_year = 70, /* 1970 -1900 */
|
||||
.tm_mday = 1,
|
||||
},
|
||||
/* signed time_t 19/01/2038 3:14:08 */
|
||||
{
|
||||
.tm_year = 138,
|
||||
.tm_mday = 19,
|
||||
},
|
||||
{
|
||||
.tm_year = 138,
|
||||
.tm_mday = 20,
|
||||
},
|
||||
{
|
||||
.tm_year = 199, /* 2099 -1900 */
|
||||
.tm_mday = 1,
|
||||
},
|
||||
{
|
||||
.tm_year = 200, /* 2100 -1900 */
|
||||
.tm_mday = 1,
|
||||
},
|
||||
/* unsigned time_t 07/02/2106 7:28:15*/
|
||||
{
|
||||
.tm_year = 205,
|
||||
.tm_mon = 1,
|
||||
.tm_mday = 7,
|
||||
},
|
||||
{
|
||||
.tm_year = 206,
|
||||
.tm_mon = 1,
|
||||
.tm_mday = 8,
|
||||
},
|
||||
/* signed time on 64bit in nanoseconds 12/04/2262 01:47:16*/
|
||||
{
|
||||
.tm_year = 362,
|
||||
.tm_mon = 3,
|
||||
.tm_mday = 12,
|
||||
},
|
||||
{
|
||||
.tm_year = 362, /* 2262 -1900 */
|
||||
.tm_mon = 3,
|
||||
.tm_mday = 13,
|
||||
},
|
||||
};
|
||||
|
||||
static int compare_dates(struct rtc_time *a, struct rtc_time *b)
|
||||
{
|
||||
if (a->tm_year != b->tm_year ||
|
||||
a->tm_mon != b->tm_mon ||
|
||||
a->tm_mday != b->tm_mday ||
|
||||
a->tm_hour != b->tm_hour ||
|
||||
a->tm_min != b->tm_min ||
|
||||
((b->tm_sec - a->tm_sec) > 1))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, fd, retval, irqcount = 0;
|
||||
int i, fd, retval, irqcount = 0, dangerous = 0;
|
||||
unsigned long tmp, data;
|
||||
struct rtc_time rtc_tm;
|
||||
const char *rtc = default_rtc;
|
||||
struct timeval start, end, diff;
|
||||
|
||||
switch (argc) {
|
||||
case 3:
|
||||
if (*argv[2] == 'd')
|
||||
dangerous = 1;
|
||||
case 2:
|
||||
rtc = argv[1];
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "usage: rtctest [rtcdev]\n");
|
||||
fprintf(stderr, "usage: rtctest [rtcdev] [d]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -202,7 +266,7 @@ test_PIE:
|
||||
/* not all RTCs support periodic IRQs */
|
||||
if (errno == EINVAL) {
|
||||
fprintf(stderr, "\nNo periodic IRQ support\n");
|
||||
goto done;
|
||||
goto test_DATE;
|
||||
}
|
||||
perror("RTC_IRQP_READ ioctl");
|
||||
exit(errno);
|
||||
@ -221,7 +285,7 @@ test_PIE:
|
||||
if (errno == EINVAL) {
|
||||
fprintf(stderr,
|
||||
"\n...Periodic IRQ rate is fixed\n");
|
||||
goto done;
|
||||
goto test_DATE;
|
||||
}
|
||||
perror("RTC_IRQP_SET ioctl");
|
||||
exit(errno);
|
||||
@ -269,6 +333,62 @@ test_PIE:
|
||||
}
|
||||
}
|
||||
|
||||
test_DATE:
|
||||
if (!dangerous)
|
||||
goto done;
|
||||
|
||||
fprintf(stderr, "\nTesting problematic dates\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cutoff_dates); i++) {
|
||||
struct rtc_time current;
|
||||
|
||||
/* Write the new date in RTC */
|
||||
retval = ioctl(fd, RTC_SET_TIME, &cutoff_dates[i]);
|
||||
if (retval == -1) {
|
||||
perror("RTC_SET_TIME ioctl");
|
||||
close(fd);
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
/* Read back */
|
||||
retval = ioctl(fd, RTC_RD_TIME, ¤t);
|
||||
if (retval == -1) {
|
||||
perror("RTC_RD_TIME ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
if(compare_dates(&cutoff_dates[i], ¤t)) {
|
||||
fprintf(stderr,"Setting date %d failed\n",
|
||||
cutoff_dates[i].tm_year + 1900);
|
||||
goto done;
|
||||
}
|
||||
|
||||
cutoff_dates[i].tm_sec += 5;
|
||||
|
||||
/* Write the new alarm in RTC */
|
||||
retval = ioctl(fd, RTC_ALM_SET, &cutoff_dates[i]);
|
||||
if (retval == -1) {
|
||||
perror("RTC_ALM_SET ioctl");
|
||||
close(fd);
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
/* Read back */
|
||||
retval = ioctl(fd, RTC_ALM_READ, ¤t);
|
||||
if (retval == -1) {
|
||||
perror("RTC_ALM_READ ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
if(compare_dates(&cutoff_dates[i], ¤t)) {
|
||||
fprintf(stderr,"Setting alarm %d failed\n",
|
||||
cutoff_dates[i].tm_year + 1900);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Setting year %d is OK \n",
|
||||
cutoff_dates[i].tm_year + 1900);
|
||||
}
|
||||
done:
|
||||
fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
|
||||
|
||||
|
86
tools/testing/selftests/timers/rtctest_setdate.c
Normal file
86
tools/testing/selftests/timers/rtctest_setdate.c
Normal file
@ -0,0 +1,86 @@
|
||||
/* Real Time Clock Driver Test
|
||||
* by: Benjamin Gaignard (benjamin.gaignard@linaro.org)
|
||||
*
|
||||
* To build
|
||||
* gcc rtctest_setdate.c -o rtctest_setdate
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
static const char default_time[] = "00:00:00";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd, retval;
|
||||
struct rtc_time new, current;
|
||||
const char *rtc, *date;
|
||||
const char *time = default_time;
|
||||
|
||||
switch (argc) {
|
||||
case 4:
|
||||
time = argv[3];
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
date = argv[2];
|
||||
rtc = argv[1];
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "usage: rtctest_setdate <rtcdev> <DD-MM-YYYY> [HH:MM:SS]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd = open(rtc, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
perror(rtc);
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
sscanf(date, "%d-%d-%d", &new.tm_mday, &new.tm_mon, &new.tm_year);
|
||||
new.tm_mon -= 1;
|
||||
new.tm_year -= 1900;
|
||||
sscanf(time, "%d:%d:%d", &new.tm_hour, &new.tm_min, &new.tm_sec);
|
||||
|
||||
fprintf(stderr, "Test will set RTC date/time to %d-%d-%d, %02d:%02d:%02d.\n",
|
||||
new.tm_mday, new.tm_mon + 1, new.tm_year + 1900,
|
||||
new.tm_hour, new.tm_min, new.tm_sec);
|
||||
|
||||
/* Write the new date in RTC */
|
||||
retval = ioctl(fd, RTC_SET_TIME, &new);
|
||||
if (retval == -1) {
|
||||
perror("RTC_SET_TIME ioctl");
|
||||
close(fd);
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
/* Read back */
|
||||
retval = ioctl(fd, RTC_RD_TIME, ¤t);
|
||||
if (retval == -1) {
|
||||
perror("RTC_RD_TIME ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
|
||||
current.tm_mday, current.tm_mon + 1, current.tm_year + 1900,
|
||||
current.tm_hour, current.tm_min, current.tm_sec);
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user