blob: 2eecc6227c195698f0f037d900ce8aab70504979 [file] [log] [blame]
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +05301/* rtc-test.c
2 *
3 * Tests for the Real Time Clock driver.
4 *
5 * Copyright (c) Larsen & Toubro Infotech Ltd., 2010
Alexey Kodanev473b8cf2013-09-09 16:23:01 +04006 * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +05307 *
8 * Author : Silesh C V <Silesh.Vellattu@lntinfotech.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
18 * the GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080022 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053023 */
24
Alexey Kodanev473b8cf2013-09-09 16:23:01 +040025
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053026#include <sys/ioctl.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <fcntl.h>
30#include <unistd.h>
31#include <linux/rtc.h>
32#include <errno.h>
33#include <time.h>
34
Alexey Kodanev473b8cf2013-09-09 16:23:01 +040035#include "test.h"
Alexey Kodanev473b8cf2013-09-09 16:23:01 +040036
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053037int rtc_fd = -1;
38char *TCID = "rtc01";
39int TST_TOTAL = 3;
40
Alexey Kodanev473b8cf2013-09-09 16:23:01 +040041static char *rtc_dev = "/dev/rtc";
42static int dflag;
43static const option_t options[] = {
44 {"d:", &dflag, &rtc_dev},
45 {NULL, NULL, NULL}
46};
47
48static void help(void)
49{
50 printf(" -d x rtc device node, default is %s\n",
51 rtc_dev);
52}
53
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053054/* Read and Alarm Tests : Read test reads the Date/time from RTC
55 * while Alarm test, sets the alarm to 5 seconds in future and
56 * waits for it to ring.The ioctls tested in these tests are
57 * RTC_RD_TIME, RTC_ALM_SET, RTC_ALM_READ, RTC_AIE_OFF */
58
59void read_alarm_test(void)
60{
Wanlong Gao354ebb42012-12-07 10:10:04 +080061 struct rtc_time rtc_tm;
62 int ret;
63 unsigned long data;
64 fd_set rfds;
65 struct timeval tv;
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053066
Wanlong Gao354ebb42012-12-07 10:10:04 +080067 tst_resm(TINFO, "RTC READ TEST:");
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053068
Wanlong Gao354ebb42012-12-07 10:10:04 +080069 /*Read RTC Time */
70 ret = ioctl(rtc_fd, RTC_RD_TIME, &rtc_tm);
71 if (ret == -1) {
72 tst_resm(TFAIL, "RTC_RD_TIME ioctl failed");
73 return;
74 }
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053075
Wanlong Gao354ebb42012-12-07 10:10:04 +080076 tst_resm(TPASS, "RTC READ TEST Passed");
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053077
Wanlong Gao354ebb42012-12-07 10:10:04 +080078 tst_resm(TINFO, "Current RTC date/time is %d-%d-%d, %02d:%02d:%02d.",
79 rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
80 rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053081
Wanlong Gao354ebb42012-12-07 10:10:04 +080082 tst_resm(TINFO, "RTC ALARM TEST :");
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053083
Wanlong Gao354ebb42012-12-07 10:10:04 +080084 /*set Alarm to 5 Seconds */
85 rtc_tm.tm_sec += 5;
86 if (rtc_tm.tm_sec >= 60) {
87 rtc_tm.tm_sec %= 60;
88 rtc_tm.tm_min++;
89 }
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053090
Wanlong Gao354ebb42012-12-07 10:10:04 +080091 if (rtc_tm.tm_min == 60) {
92 rtc_tm.tm_min = 0;
93 rtc_tm.tm_hour++;
94 }
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053095
Wanlong Gao354ebb42012-12-07 10:10:04 +080096 if (rtc_tm.tm_hour == 24)
97 rtc_tm.tm_hour = 0;
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +053098
Wanlong Gao354ebb42012-12-07 10:10:04 +080099 ret = ioctl(rtc_fd, RTC_ALM_SET, &rtc_tm);
100 if (ret == -1) {
101 tst_resm(TFAIL, "RTC_ALM_SET ioctl failed");
102 return;
103 }
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530104
Wanlong Gao354ebb42012-12-07 10:10:04 +0800105 /*Read current alarm time */
106 ret = ioctl(rtc_fd, RTC_ALM_READ, &rtc_tm);
107 if (ret == -1) {
108 tst_resm(TFAIL, "RTC_ALM_READ ioctl failed");
109 return;
110 }
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530111
Wanlong Gao354ebb42012-12-07 10:10:04 +0800112 tst_resm(TINFO, "Alarm time set to %02d:%02d:%02d.",
113 rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
114 /* Enable alarm interrupts */
115 ret = ioctl(rtc_fd, RTC_AIE_ON, 0);
116 if (ret == -1) {
117 tst_resm(TINFO, "RTC_AIE_ON ioctl failed");
118 return;
119 }
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530120
Wanlong Gao354ebb42012-12-07 10:10:04 +0800121 tst_resm(TINFO, "Waiting 5 seconds for the alarm...");
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530122
Wanlong Gao354ebb42012-12-07 10:10:04 +0800123 tv.tv_sec = 6; /*set 6 seconds as the time out */
124 tv.tv_usec = 0;
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530125
Wanlong Gao354ebb42012-12-07 10:10:04 +0800126 FD_ZERO(&rfds);
127 FD_SET(rtc_fd, &rfds);
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530128
Wanlong Gao354ebb42012-12-07 10:10:04 +0800129 ret = select(rtc_fd + 1, &rfds, NULL, NULL, &tv); /*wait for alarm */
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530130
Wanlong Gao354ebb42012-12-07 10:10:04 +0800131 if (ret == -1) {
132 tst_resm(TFAIL, "select failed");
133 return;
134 } else if (ret) {
135 ret = read(rtc_fd, &data, sizeof(unsigned long));
136 if (ret == -1) {
137 tst_resm(TFAIL, "read failed");
138 return;
139 }
140 tst_resm(TINFO, "Alarm rang.");
141 } else {
142 tst_resm(TFAIL, "Timed out waiting for the alarm");
143 return;
144 }
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530145
Wanlong Gao354ebb42012-12-07 10:10:04 +0800146 /* Disable alarm interrupts */
147 ret = ioctl(rtc_fd, RTC_AIE_OFF, 0);
148 if (ret == -1) {
149 tst_resm(TFAIL, "RTC_AIE_OFF ioctl failed");
150 return;
151 }
152 tst_resm(TPASS, "RTC ALARM TEST Passed");
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530153}
154
155/* Update_interrupts_test :Once the Update interrupts is enabled,
156 * the RTC gives interrupts (1/sec) on the interrupts line(if the rtc
157 * has one). This is tested by enabling the update interrupts
158 * and then waiting for 5 interrupts.*/
159
160void update_interrupts_test(void)
161{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800162 int ret, i;
163 unsigned long data;
164 fd_set rfds;
165 struct timeval tv;
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530166
Wanlong Gao354ebb42012-12-07 10:10:04 +0800167 tst_resm(TINFO, "RTC UPDATE INTERRUPTS TEST :");
168 /*Turn on update interrupts */
169 ret = ioctl(rtc_fd, RTC_UIE_ON, 0);
170 if (ret == -1) {
171 tst_resm(TFAIL, "RTC_UIE_ON ioctl failed");
172 return;
173 }
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530174
Wanlong Gao354ebb42012-12-07 10:10:04 +0800175 tst_resm(TINFO, "Waiting for 5 update interrupts...");
176 for (i = 1; i < 6; i++) {
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530177
Wanlong Gao354ebb42012-12-07 10:10:04 +0800178 tv.tv_sec = 2; /*2 sec time out for each interrupt */
179 tv.tv_usec = 0;
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530180
Wanlong Gao354ebb42012-12-07 10:10:04 +0800181 FD_ZERO(&rfds);
182 FD_SET(rtc_fd, &rfds);
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530183
Wanlong Gao354ebb42012-12-07 10:10:04 +0800184 ret = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
185 if (ret == -1) {
186 tst_resm(TFAIL, "select failed");
187 return;
188 } else if (ret) {
189 ret = read(rtc_fd, &data, sizeof(unsigned long));
190 if (ret == -1) {
191 tst_resm(TFAIL, "read failed");
192 return;
193 }
194 tst_resm(TINFO, "Update interrupt %d", i);
195 } else {
196 tst_resm(TFAIL,
197 "Timed out waiting for the update interrupt");
198 return;
199 }
200 }
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530201
Wanlong Gao354ebb42012-12-07 10:10:04 +0800202 /* Turn off update interrupts */
203 ret = ioctl(rtc_fd, RTC_UIE_OFF, 0);
204 if (ret == -1) {
205 tst_resm(TFAIL, "RTC_UIE_OFF ioctl failed");
206 return;
207 }
208 tst_resm(TPASS, "RTC UPDATE INTERRUPTS TEST Passed");
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530209}
210
Alexey Kodanev473b8cf2013-09-09 16:23:01 +0400211int main(int argc, char *argv[])
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530212{
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200213 const char *msg;
Alexey Kodanev473b8cf2013-09-09 16:23:01 +0400214 msg = parse_opts(argc, argv, options, help);
215 if (msg != NULL)
216 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530217
Alexey Kodanev473b8cf2013-09-09 16:23:01 +0400218 tst_require_root(NULL);
219
220 if (access(rtc_dev, F_OK) == -1)
221 tst_brkm(TCONF, NULL, "couldn't find rtc device '%s'", rtc_dev);
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530222
Wanlong Gao354ebb42012-12-07 10:10:04 +0800223 rtc_fd = open(rtc_dev, O_RDONLY);
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530224
Wanlong Gao354ebb42012-12-07 10:10:04 +0800225 if (rtc_fd < 0)
226 tst_brkm(TBROK | TERRNO, NULL, "couldn't open %s", rtc_dev);
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530227
Wanlong Gao354ebb42012-12-07 10:10:04 +0800228 /*Read and alarm tests */
229 read_alarm_test();
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530230
Wanlong Gao354ebb42012-12-07 10:10:04 +0800231 /*Update interrupts test */
232 update_interrupts_test();
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530233
Wanlong Gao354ebb42012-12-07 10:10:04 +0800234 close(rtc_fd);
Rishikesh K Rajake7ed2872010-03-22 10:42:05 +0530235
Wanlong Gao354ebb42012-12-07 10:10:04 +0800236 tst_resm(TINFO, "RTC Tests Done!");
237 tst_exit();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700238}