1 // SPDX-License-Identifier: GPL-2.0
3 * Real Time Clock Periodic Interrupt test program
5 * Since commit 6610e0893b8bc ("RTC: Rework RTC code to use timerqueue for
6 * events"), PIE are completely handled using hrtimers, without actually using
7 * any underlying hardware RTC.
12 #include <linux/rtc.h>
13 #include <sys/ioctl.h>
15 #include <sys/types.h>
22 * This expects the new RTC class driver framework, working with
23 * clocks that will often not be clones of what the PC-AT had.
24 * Use the command line to specify another RTC if you need one.
26 static const char default_rtc
[] = "/dev/rtc0";
28 int main(int argc
, char **argv
)
30 int i
, fd
, retval
, irqcount
= 0;
31 unsigned long tmp
, data
, old_pie_rate
;
32 const char *rtc
= default_rtc
;
33 struct timeval start
, end
, diff
;
42 fprintf(stderr
, "usage: rtctest [rtcdev] [d]\n");
46 fd
= open(rtc
, O_RDONLY
);
53 /* Read periodic IRQ rate */
54 retval
= ioctl(fd
, RTC_IRQP_READ
, &old_pie_rate
);
56 /* not all RTCs support periodic IRQs */
57 if (errno
== EINVAL
) {
58 fprintf(stderr
, "\nNo periodic IRQ support\n");
61 perror("RTC_IRQP_READ ioctl");
64 fprintf(stderr
, "\nPeriodic IRQ rate is %ldHz.\n", old_pie_rate
);
66 fprintf(stderr
, "Counting 20 interrupts at:");
69 /* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
70 for (tmp
=2; tmp
<=64; tmp
*=2) {
72 retval
= ioctl(fd
, RTC_IRQP_SET
, tmp
);
74 /* not all RTCs can change their periodic IRQ rate */
75 if (errno
== EINVAL
) {
77 "\n...Periodic IRQ rate is fixed\n");
80 perror("RTC_IRQP_SET ioctl");
84 fprintf(stderr
, "\n%ldHz:\t", tmp
);
87 /* Enable periodic interrupts */
88 retval
= ioctl(fd
, RTC_PIE_ON
, 0);
90 perror("RTC_PIE_ON ioctl");
94 for (i
=1; i
<21; i
++) {
95 gettimeofday(&start
, NULL
);
97 retval
= read(fd
, &data
, sizeof(unsigned long));
102 gettimeofday(&end
, NULL
);
103 timersub(&end
, &start
, &diff
);
104 if (diff
.tv_sec
> 0 ||
105 diff
.tv_usec
> ((1000000L / tmp
) * 1.10)) {
106 fprintf(stderr
, "\nPIE delta error: %ld.%06ld should be close to 0.%06ld\n",
107 diff
.tv_sec
, diff
.tv_usec
,
113 fprintf(stderr
, " %d",i
);
118 /* Disable periodic interrupts */
119 retval
= ioctl(fd
, RTC_PIE_OFF
, 0);
121 perror("RTC_PIE_OFF ioctl");
127 ioctl(fd
, RTC_IRQP_SET
, old_pie_rate
);
129 fprintf(stderr
, "\n\n\t\t\t *** Test complete ***\n");