mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
Documentation, split up rtc.txt into documentation and test file
This patch splits rtc.txt into two separate files, one for the documentation itself, and the other for the rtctest.c file. The rtctest file is moved into the kernel tools/testing/selftests/timers directory. This will make automated testing easier. Note that the only difference in the rtc.txt file is that the location of the rtctest.c file has changed. Signed-off-by: Prarit Bhargava <prarit@redhat.com> Acked-by: Jonathan Corbet <corbet@lwn.net> Acked-by: John Stultz <john.stultz@linaro.org> Cc: corbet@lwn.net Cc: rtc-linux@googlegroups.com Cc: linux-doc@vger.kernel.org Cc: a.zummo@towertech.it Cc: prarit@redhat.com Cc: john.stultz@linaro.org Cc: shuahkh@osg.samsung.com Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
This commit is contained in:
parent
f901caaf8e
commit
4a5fd81507
@ -204,266 +204,4 @@ Some common examples:
|
||||
|
||||
* RTC_PIE_ON, RTC_PIE_OFF: These are also emulated by the generic code.
|
||||
|
||||
If all else fails, check out the rtc-test.c driver!
|
||||
|
||||
|
||||
-------------------- 8< ---------------- 8< -----------------------------
|
||||
|
||||
/*
|
||||
* Real Time Clock Driver Test/Example Program
|
||||
*
|
||||
* Compile with:
|
||||
* gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest
|
||||
*
|
||||
* Copyright (C) 1996, Paul Gortmaker.
|
||||
*
|
||||
* Released under the GNU General Public License, version 2,
|
||||
* included herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
|
||||
/*
|
||||
* This expects the new RTC class driver framework, working with
|
||||
* clocks that will often not be clones of what the PC-AT had.
|
||||
* Use the command line to specify another RTC if you need one.
|
||||
*/
|
||||
static const char default_rtc[] = "/dev/rtc0";
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, fd, retval, irqcount = 0;
|
||||
unsigned long tmp, data;
|
||||
struct rtc_time rtc_tm;
|
||||
const char *rtc = default_rtc;
|
||||
|
||||
switch (argc) {
|
||||
case 2:
|
||||
rtc = argv[1];
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "usage: rtctest [rtcdev]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd = open(rtc, O_RDONLY);
|
||||
|
||||
if (fd == -1) {
|
||||
perror(rtc);
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n");
|
||||
|
||||
/* Turn on update interrupts (one per second) */
|
||||
retval = ioctl(fd, RTC_UIE_ON, 0);
|
||||
if (retval == -1) {
|
||||
if (errno == ENOTTY) {
|
||||
fprintf(stderr,
|
||||
"\n...Update IRQs not supported.\n");
|
||||
goto test_READ;
|
||||
}
|
||||
perror("RTC_UIE_ON ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading %s:",
|
||||
rtc);
|
||||
fflush(stderr);
|
||||
for (i=1; i<6; i++) {
|
||||
/* This read will block */
|
||||
retval = read(fd, &data, sizeof(unsigned long));
|
||||
if (retval == -1) {
|
||||
perror("read");
|
||||
exit(errno);
|
||||
}
|
||||
fprintf(stderr, " %d",i);
|
||||
fflush(stderr);
|
||||
irqcount++;
|
||||
}
|
||||
|
||||
fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:");
|
||||
fflush(stderr);
|
||||
for (i=1; i<6; i++) {
|
||||
struct timeval tv = {5, 0}; /* 5 second timeout on select */
|
||||
fd_set readfds;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd, &readfds);
|
||||
/* The select will wait until an RTC interrupt happens. */
|
||||
retval = select(fd+1, &readfds, NULL, NULL, &tv);
|
||||
if (retval == -1) {
|
||||
perror("select");
|
||||
exit(errno);
|
||||
}
|
||||
/* This read won't block unlike the select-less case above. */
|
||||
retval = read(fd, &data, sizeof(unsigned long));
|
||||
if (retval == -1) {
|
||||
perror("read");
|
||||
exit(errno);
|
||||
}
|
||||
fprintf(stderr, " %d",i);
|
||||
fflush(stderr);
|
||||
irqcount++;
|
||||
}
|
||||
|
||||
/* Turn off update interrupts */
|
||||
retval = ioctl(fd, RTC_UIE_OFF, 0);
|
||||
if (retval == -1) {
|
||||
perror("RTC_UIE_OFF ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
test_READ:
|
||||
/* Read the RTC time/date */
|
||||
retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
|
||||
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",
|
||||
rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
|
||||
rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
|
||||
|
||||
/* Set the alarm to 5 sec in the future, and check for rollover */
|
||||
rtc_tm.tm_sec += 5;
|
||||
if (rtc_tm.tm_sec >= 60) {
|
||||
rtc_tm.tm_sec %= 60;
|
||||
rtc_tm.tm_min++;
|
||||
}
|
||||
if (rtc_tm.tm_min == 60) {
|
||||
rtc_tm.tm_min = 0;
|
||||
rtc_tm.tm_hour++;
|
||||
}
|
||||
if (rtc_tm.tm_hour == 24)
|
||||
rtc_tm.tm_hour = 0;
|
||||
|
||||
retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
|
||||
if (retval == -1) {
|
||||
if (errno == ENOTTY) {
|
||||
fprintf(stderr,
|
||||
"\n...Alarm IRQs not supported.\n");
|
||||
goto test_PIE;
|
||||
}
|
||||
perror("RTC_ALM_SET ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
/* Read the current alarm settings */
|
||||
retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
|
||||
if (retval == -1) {
|
||||
perror("RTC_ALM_READ ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n",
|
||||
rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
|
||||
|
||||
/* Enable alarm interrupts */
|
||||
retval = ioctl(fd, RTC_AIE_ON, 0);
|
||||
if (retval == -1) {
|
||||
perror("RTC_AIE_ON ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Waiting 5 seconds for alarm...");
|
||||
fflush(stderr);
|
||||
/* This blocks until the alarm ring causes an interrupt */
|
||||
retval = read(fd, &data, sizeof(unsigned long));
|
||||
if (retval == -1) {
|
||||
perror("read");
|
||||
exit(errno);
|
||||
}
|
||||
irqcount++;
|
||||
fprintf(stderr, " okay. Alarm rang.\n");
|
||||
|
||||
/* Disable alarm interrupts */
|
||||
retval = ioctl(fd, RTC_AIE_OFF, 0);
|
||||
if (retval == -1) {
|
||||
perror("RTC_AIE_OFF ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
test_PIE:
|
||||
/* Read periodic IRQ rate */
|
||||
retval = ioctl(fd, RTC_IRQP_READ, &tmp);
|
||||
if (retval == -1) {
|
||||
/* not all RTCs support periodic IRQs */
|
||||
if (errno == ENOTTY) {
|
||||
fprintf(stderr, "\nNo periodic IRQ support\n");
|
||||
goto done;
|
||||
}
|
||||
perror("RTC_IRQP_READ ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp);
|
||||
|
||||
fprintf(stderr, "Counting 20 interrupts at:");
|
||||
fflush(stderr);
|
||||
|
||||
/* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
|
||||
for (tmp=2; tmp<=64; tmp*=2) {
|
||||
|
||||
retval = ioctl(fd, RTC_IRQP_SET, tmp);
|
||||
if (retval == -1) {
|
||||
/* not all RTCs can change their periodic IRQ rate */
|
||||
if (errno == ENOTTY) {
|
||||
fprintf(stderr,
|
||||
"\n...Periodic IRQ rate is fixed\n");
|
||||
goto done;
|
||||
}
|
||||
perror("RTC_IRQP_SET ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n%ldHz:\t", tmp);
|
||||
fflush(stderr);
|
||||
|
||||
/* Enable periodic interrupts */
|
||||
retval = ioctl(fd, RTC_PIE_ON, 0);
|
||||
if (retval == -1) {
|
||||
perror("RTC_PIE_ON ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
for (i=1; i<21; i++) {
|
||||
/* This blocks */
|
||||
retval = read(fd, &data, sizeof(unsigned long));
|
||||
if (retval == -1) {
|
||||
perror("read");
|
||||
exit(errno);
|
||||
}
|
||||
fprintf(stderr, " %d",i);
|
||||
fflush(stderr);
|
||||
irqcount++;
|
||||
}
|
||||
|
||||
/* Disable periodic interrupts */
|
||||
retval = ioctl(fd, RTC_PIE_OFF, 0);
|
||||
if (retval == -1) {
|
||||
perror("RTC_PIE_OFF ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
If all else fails, check out the tools/testing/selftests/timers/rtctest.c test!
|
||||
|
@ -6,7 +6,7 @@ LDFLAGS += -lrt -lpthread
|
||||
# these are all "safe" tests that don't modify
|
||||
# system time or require escalated privledges
|
||||
TEST_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
|
||||
inconsistency-check raw_skew threadtest
|
||||
inconsistency-check raw_skew threadtest rtctest
|
||||
|
||||
TEST_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex change_skew \
|
||||
skew_consistency clocksource-switch leap-a-day \
|
||||
|
258
tools/testing/selftests/timers/rtctest.c
Normal file
258
tools/testing/selftests/timers/rtctest.c
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Real Time Clock Driver Test/Example Program
|
||||
*
|
||||
* Compile with:
|
||||
* gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest
|
||||
*
|
||||
* Copyright (C) 1996, Paul Gortmaker.
|
||||
*
|
||||
* Released under the GNU General Public License, version 2,
|
||||
* included herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
|
||||
/*
|
||||
* This expects the new RTC class driver framework, working with
|
||||
* clocks that will often not be clones of what the PC-AT had.
|
||||
* Use the command line to specify another RTC if you need one.
|
||||
*/
|
||||
static const char default_rtc[] = "/dev/rtc0";
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, fd, retval, irqcount = 0;
|
||||
unsigned long tmp, data;
|
||||
struct rtc_time rtc_tm;
|
||||
const char *rtc = default_rtc;
|
||||
|
||||
switch (argc) {
|
||||
case 2:
|
||||
rtc = argv[1];
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "usage: rtctest [rtcdev]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd = open(rtc, O_RDONLY);
|
||||
|
||||
if (fd == -1) {
|
||||
perror(rtc);
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n");
|
||||
|
||||
/* Turn on update interrupts (one per second) */
|
||||
retval = ioctl(fd, RTC_UIE_ON, 0);
|
||||
if (retval == -1) {
|
||||
if (errno == ENOTTY) {
|
||||
fprintf(stderr,
|
||||
"\n...Update IRQs not supported.\n");
|
||||
goto test_READ;
|
||||
}
|
||||
perror("RTC_UIE_ON ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading %s:",
|
||||
rtc);
|
||||
fflush(stderr);
|
||||
for (i=1; i<6; i++) {
|
||||
/* This read will block */
|
||||
retval = read(fd, &data, sizeof(unsigned long));
|
||||
if (retval == -1) {
|
||||
perror("read");
|
||||
exit(errno);
|
||||
}
|
||||
fprintf(stderr, " %d",i);
|
||||
fflush(stderr);
|
||||
irqcount++;
|
||||
}
|
||||
|
||||
fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:");
|
||||
fflush(stderr);
|
||||
for (i=1; i<6; i++) {
|
||||
struct timeval tv = {5, 0}; /* 5 second timeout on select */
|
||||
fd_set readfds;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd, &readfds);
|
||||
/* The select will wait until an RTC interrupt happens. */
|
||||
retval = select(fd+1, &readfds, NULL, NULL, &tv);
|
||||
if (retval == -1) {
|
||||
perror("select");
|
||||
exit(errno);
|
||||
}
|
||||
/* This read won't block unlike the select-less case above. */
|
||||
retval = read(fd, &data, sizeof(unsigned long));
|
||||
if (retval == -1) {
|
||||
perror("read");
|
||||
exit(errno);
|
||||
}
|
||||
fprintf(stderr, " %d",i);
|
||||
fflush(stderr);
|
||||
irqcount++;
|
||||
}
|
||||
|
||||
/* Turn off update interrupts */
|
||||
retval = ioctl(fd, RTC_UIE_OFF, 0);
|
||||
if (retval == -1) {
|
||||
perror("RTC_UIE_OFF ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
test_READ:
|
||||
/* Read the RTC time/date */
|
||||
retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
|
||||
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",
|
||||
rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
|
||||
rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
|
||||
|
||||
/* Set the alarm to 5 sec in the future, and check for rollover */
|
||||
rtc_tm.tm_sec += 5;
|
||||
if (rtc_tm.tm_sec >= 60) {
|
||||
rtc_tm.tm_sec %= 60;
|
||||
rtc_tm.tm_min++;
|
||||
}
|
||||
if (rtc_tm.tm_min == 60) {
|
||||
rtc_tm.tm_min = 0;
|
||||
rtc_tm.tm_hour++;
|
||||
}
|
||||
if (rtc_tm.tm_hour == 24)
|
||||
rtc_tm.tm_hour = 0;
|
||||
|
||||
retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
|
||||
if (retval == -1) {
|
||||
if (errno == ENOTTY) {
|
||||
fprintf(stderr,
|
||||
"\n...Alarm IRQs not supported.\n");
|
||||
goto test_PIE;
|
||||
}
|
||||
perror("RTC_ALM_SET ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
/* Read the current alarm settings */
|
||||
retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
|
||||
if (retval == -1) {
|
||||
perror("RTC_ALM_READ ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n",
|
||||
rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
|
||||
|
||||
/* Enable alarm interrupts */
|
||||
retval = ioctl(fd, RTC_AIE_ON, 0);
|
||||
if (retval == -1) {
|
||||
perror("RTC_AIE_ON ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Waiting 5 seconds for alarm...");
|
||||
fflush(stderr);
|
||||
/* This blocks until the alarm ring causes an interrupt */
|
||||
retval = read(fd, &data, sizeof(unsigned long));
|
||||
if (retval == -1) {
|
||||
perror("read");
|
||||
exit(errno);
|
||||
}
|
||||
irqcount++;
|
||||
fprintf(stderr, " okay. Alarm rang.\n");
|
||||
|
||||
/* Disable alarm interrupts */
|
||||
retval = ioctl(fd, RTC_AIE_OFF, 0);
|
||||
if (retval == -1) {
|
||||
perror("RTC_AIE_OFF ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
test_PIE:
|
||||
/* Read periodic IRQ rate */
|
||||
retval = ioctl(fd, RTC_IRQP_READ, &tmp);
|
||||
if (retval == -1) {
|
||||
/* not all RTCs support periodic IRQs */
|
||||
if (errno == ENOTTY) {
|
||||
fprintf(stderr, "\nNo periodic IRQ support\n");
|
||||
goto done;
|
||||
}
|
||||
perror("RTC_IRQP_READ ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp);
|
||||
|
||||
fprintf(stderr, "Counting 20 interrupts at:");
|
||||
fflush(stderr);
|
||||
|
||||
/* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
|
||||
for (tmp=2; tmp<=64; tmp*=2) {
|
||||
|
||||
retval = ioctl(fd, RTC_IRQP_SET, tmp);
|
||||
if (retval == -1) {
|
||||
/* not all RTCs can change their periodic IRQ rate */
|
||||
if (errno == ENOTTY) {
|
||||
fprintf(stderr,
|
||||
"\n...Periodic IRQ rate is fixed\n");
|
||||
goto done;
|
||||
}
|
||||
perror("RTC_IRQP_SET ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n%ldHz:\t", tmp);
|
||||
fflush(stderr);
|
||||
|
||||
/* Enable periodic interrupts */
|
||||
retval = ioctl(fd, RTC_PIE_ON, 0);
|
||||
if (retval == -1) {
|
||||
perror("RTC_PIE_ON ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
for (i=1; i<21; i++) {
|
||||
/* This blocks */
|
||||
retval = read(fd, &data, sizeof(unsigned long));
|
||||
if (retval == -1) {
|
||||
perror("read");
|
||||
exit(errno);
|
||||
}
|
||||
fprintf(stderr, " %d",i);
|
||||
fflush(stderr);
|
||||
irqcount++;
|
||||
}
|
||||
|
||||
/* Disable periodic interrupts */
|
||||
retval = ioctl(fd, RTC_PIE_OFF, 0);
|
||||
if (retval == -1) {
|
||||
perror("RTC_PIE_OFF ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user