0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <stdio.h>
0012 #include <linux/rtc.h>
0013 #include <sys/ioctl.h>
0014 #include <sys/time.h>
0015 #include <sys/types.h>
0016 #include <fcntl.h>
0017 #include <unistd.h>
0018 #include <stdlib.h>
0019 #include <errno.h>
0020
0021 #include "../kselftest.h"
0022
0023
0024
0025
0026
0027
0028 static const char default_rtc[] = "/dev/rtc0";
0029
0030 int main(int argc, char **argv)
0031 {
0032 int i, fd, retval, irqcount = 0;
0033 unsigned long tmp, data, old_pie_rate;
0034 const char *rtc = default_rtc;
0035 struct timeval start, end, diff;
0036
0037 switch (argc) {
0038 case 2:
0039 rtc = argv[1];
0040 break;
0041 case 1:
0042 fd = open(default_rtc, O_RDONLY);
0043 if (fd == -1) {
0044 printf("Default RTC %s does not exist. Test Skipped!\n", default_rtc);
0045 exit(KSFT_SKIP);
0046 }
0047 close(fd);
0048 break;
0049 default:
0050 fprintf(stderr, "usage: rtctest [rtcdev] [d]\n");
0051 return 1;
0052 }
0053
0054 fd = open(rtc, O_RDONLY);
0055
0056 if (fd == -1) {
0057 perror(rtc);
0058 exit(errno);
0059 }
0060
0061
0062 retval = ioctl(fd, RTC_IRQP_READ, &old_pie_rate);
0063 if (retval == -1) {
0064
0065 if (errno == EINVAL) {
0066 fprintf(stderr, "\nNo periodic IRQ support\n");
0067 goto done;
0068 }
0069 perror("RTC_IRQP_READ ioctl");
0070 exit(errno);
0071 }
0072 fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", old_pie_rate);
0073
0074 fprintf(stderr, "Counting 20 interrupts at:");
0075 fflush(stderr);
0076
0077
0078 for (tmp=2; tmp<=64; tmp*=2) {
0079
0080 retval = ioctl(fd, RTC_IRQP_SET, tmp);
0081 if (retval == -1) {
0082
0083 if (errno == EINVAL) {
0084 fprintf(stderr,
0085 "\n...Periodic IRQ rate is fixed\n");
0086 goto done;
0087 }
0088 perror("RTC_IRQP_SET ioctl");
0089 exit(errno);
0090 }
0091
0092 fprintf(stderr, "\n%ldHz:\t", tmp);
0093 fflush(stderr);
0094
0095
0096 retval = ioctl(fd, RTC_PIE_ON, 0);
0097 if (retval == -1) {
0098 perror("RTC_PIE_ON ioctl");
0099 exit(errno);
0100 }
0101
0102 for (i=1; i<21; i++) {
0103 gettimeofday(&start, NULL);
0104
0105 retval = read(fd, &data, sizeof(unsigned long));
0106 if (retval == -1) {
0107 perror("read");
0108 exit(errno);
0109 }
0110 gettimeofday(&end, NULL);
0111 timersub(&end, &start, &diff);
0112 if (diff.tv_sec > 0 ||
0113 diff.tv_usec > ((1000000L / tmp) * 1.10)) {
0114 fprintf(stderr, "\nPIE delta error: %ld.%06ld should be close to 0.%06ld\n",
0115 diff.tv_sec, diff.tv_usec,
0116 (1000000L / tmp));
0117 fflush(stdout);
0118 exit(-1);
0119 }
0120
0121 fprintf(stderr, " %d",i);
0122 fflush(stderr);
0123 irqcount++;
0124 }
0125
0126
0127 retval = ioctl(fd, RTC_PIE_OFF, 0);
0128 if (retval == -1) {
0129 perror("RTC_PIE_OFF ioctl");
0130 exit(errno);
0131 }
0132 }
0133
0134 done:
0135 ioctl(fd, RTC_IRQP_SET, old_pie_rate);
0136
0137 fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
0138
0139 close(fd);
0140
0141 return 0;
0142 }