xref: /openbmc/linux/tools/testing/selftests/rtc/rtctest.c (revision eff82a263b5cfa3427fd9dbfedd96da94fdc9f19)
1d8da8665SAlexandre Belloni // SPDX-License-Identifier: GPL-2.0
2a12ab9e1SAlexandre Belloni /*
3d8da8665SAlexandre Belloni  * Real Time Clock Driver Test Program
4a12ab9e1SAlexandre Belloni  *
5d8da8665SAlexandre Belloni  * Copyright (c) 2018 Alexandre Belloni <alexandre.belloni@bootlin.com>
6a12ab9e1SAlexandre Belloni  */
7a12ab9e1SAlexandre Belloni 
8d8da8665SAlexandre Belloni #include <errno.h>
9d8da8665SAlexandre Belloni #include <fcntl.h>
10a12ab9e1SAlexandre Belloni #include <linux/rtc.h>
11d8da8665SAlexandre Belloni #include <stdio.h>
12d8da8665SAlexandre Belloni #include <stdlib.h>
13a12ab9e1SAlexandre Belloni #include <sys/ioctl.h>
14a12ab9e1SAlexandre Belloni #include <sys/time.h>
15a12ab9e1SAlexandre Belloni #include <sys/types.h>
16d8da8665SAlexandre Belloni #include <time.h>
17a12ab9e1SAlexandre Belloni #include <unistd.h>
18a12ab9e1SAlexandre Belloni 
19d8da8665SAlexandre Belloni #include "../kselftest_harness.h"
20a12ab9e1SAlexandre Belloni 
21d8da8665SAlexandre Belloni #define NUM_UIE 3
22d8da8665SAlexandre Belloni #define ALARM_DELTA 3
23a12ab9e1SAlexandre Belloni 
24d8da8665SAlexandre Belloni static char *rtc_file = "/dev/rtc0";
25d8da8665SAlexandre Belloni 
26d8da8665SAlexandre Belloni FIXTURE(rtc) {
27d8da8665SAlexandre Belloni 	int fd;
28a12ab9e1SAlexandre Belloni };
29a12ab9e1SAlexandre Belloni 
30d8da8665SAlexandre Belloni FIXTURE_SETUP(rtc) {
31d8da8665SAlexandre Belloni 	self->fd = open(rtc_file, O_RDONLY);
32d8da8665SAlexandre Belloni 	ASSERT_NE(-1, self->fd);
33d8da8665SAlexandre Belloni }
34a12ab9e1SAlexandre Belloni 
35d8da8665SAlexandre Belloni FIXTURE_TEARDOWN(rtc) {
36d8da8665SAlexandre Belloni 	close(self->fd);
37d8da8665SAlexandre Belloni }
38d8da8665SAlexandre Belloni 
39d8da8665SAlexandre Belloni TEST_F(rtc, date_read) {
40d8da8665SAlexandre Belloni 	int rc;
41d8da8665SAlexandre Belloni 	struct rtc_time rtc_tm;
42d8da8665SAlexandre Belloni 
43d8da8665SAlexandre Belloni 	/* Read the RTC time/date */
44d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
45d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
46d8da8665SAlexandre Belloni 
47d8da8665SAlexandre Belloni 	TH_LOG("Current RTC date/time is %02d/%02d/%02d %02d:%02d:%02d.",
48d8da8665SAlexandre Belloni 	       rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
49d8da8665SAlexandre Belloni 	       rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
50d8da8665SAlexandre Belloni }
51d8da8665SAlexandre Belloni 
52*eff82a26SAlexandre Belloni TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) {
53d8da8665SAlexandre Belloni 	int i, rc, irq = 0;
54d8da8665SAlexandre Belloni 	unsigned long data;
55d8da8665SAlexandre Belloni 
56d8da8665SAlexandre Belloni 	/* Turn on update interrupts */
57d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_UIE_ON, 0);
58d8da8665SAlexandre Belloni 	if (rc == -1) {
59d8da8665SAlexandre Belloni 		ASSERT_EQ(EINVAL, errno);
60d8da8665SAlexandre Belloni 		TH_LOG("skip update IRQs not supported.");
61d8da8665SAlexandre Belloni 		return;
62d8da8665SAlexandre Belloni 	}
63d8da8665SAlexandre Belloni 
64d8da8665SAlexandre Belloni 	for (i = 0; i < NUM_UIE; i++) {
65d8da8665SAlexandre Belloni 		/* This read will block */
66d8da8665SAlexandre Belloni 		rc = read(self->fd, &data, sizeof(data));
67d8da8665SAlexandre Belloni 		ASSERT_NE(-1, rc);
68d8da8665SAlexandre Belloni 		irq++;
69d8da8665SAlexandre Belloni 	}
70d8da8665SAlexandre Belloni 
71d8da8665SAlexandre Belloni 	EXPECT_EQ(NUM_UIE, irq);
72d8da8665SAlexandre Belloni 
73d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_UIE_OFF, 0);
74d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
75d8da8665SAlexandre Belloni }
76d8da8665SAlexandre Belloni 
77d8da8665SAlexandre Belloni TEST_F(rtc, uie_select) {
78d8da8665SAlexandre Belloni 	int i, rc, irq = 0;
79d8da8665SAlexandre Belloni 	unsigned long data;
80d8da8665SAlexandre Belloni 
81d8da8665SAlexandre Belloni 	/* Turn on update interrupts */
82d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_UIE_ON, 0);
83d8da8665SAlexandre Belloni 	if (rc == -1) {
84d8da8665SAlexandre Belloni 		ASSERT_EQ(EINVAL, errno);
85d8da8665SAlexandre Belloni 		TH_LOG("skip update IRQs not supported.");
86d8da8665SAlexandre Belloni 		return;
87d8da8665SAlexandre Belloni 	}
88d8da8665SAlexandre Belloni 
89d8da8665SAlexandre Belloni 	for (i = 0; i < NUM_UIE; i++) {
90d8da8665SAlexandre Belloni 		struct timeval tv = { .tv_sec = 2 };
91d8da8665SAlexandre Belloni 		fd_set readfds;
92d8da8665SAlexandre Belloni 
93d8da8665SAlexandre Belloni 		FD_ZERO(&readfds);
94d8da8665SAlexandre Belloni 		FD_SET(self->fd, &readfds);
95d8da8665SAlexandre Belloni 		/* The select will wait until an RTC interrupt happens. */
96d8da8665SAlexandre Belloni 		rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
97d8da8665SAlexandre Belloni 		ASSERT_NE(-1, rc);
98d8da8665SAlexandre Belloni 		ASSERT_NE(0, rc);
99d8da8665SAlexandre Belloni 
100d8da8665SAlexandre Belloni 		/* This read won't block */
101d8da8665SAlexandre Belloni 		rc = read(self->fd, &data, sizeof(unsigned long));
102d8da8665SAlexandre Belloni 		ASSERT_NE(-1, rc);
103d8da8665SAlexandre Belloni 		irq++;
104d8da8665SAlexandre Belloni 	}
105d8da8665SAlexandre Belloni 
106d8da8665SAlexandre Belloni 	EXPECT_EQ(NUM_UIE, irq);
107d8da8665SAlexandre Belloni 
108d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_UIE_OFF, 0);
109d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
110d8da8665SAlexandre Belloni }
111d8da8665SAlexandre Belloni 
112d8da8665SAlexandre Belloni TEST_F(rtc, alarm_alm_set) {
113d8da8665SAlexandre Belloni 	struct timeval tv = { .tv_sec = ALARM_DELTA + 2 };
114d8da8665SAlexandre Belloni 	unsigned long data;
115d8da8665SAlexandre Belloni 	struct rtc_time tm;
116d8da8665SAlexandre Belloni 	fd_set readfds;
117d8da8665SAlexandre Belloni 	time_t secs, new;
118d8da8665SAlexandre Belloni 	int rc;
119d8da8665SAlexandre Belloni 
120d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_RD_TIME, &tm);
121d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
122d8da8665SAlexandre Belloni 
123d8da8665SAlexandre Belloni 	secs = timegm((struct tm *)&tm) + ALARM_DELTA;
124d8da8665SAlexandre Belloni 	gmtime_r(&secs, (struct tm *)&tm);
125d8da8665SAlexandre Belloni 
126d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_ALM_SET, &tm);
127d8da8665SAlexandre Belloni 	if (rc == -1) {
128d8da8665SAlexandre Belloni 		ASSERT_EQ(EINVAL, errno);
129d8da8665SAlexandre Belloni 		TH_LOG("skip alarms are not supported.");
130d8da8665SAlexandre Belloni 		return;
131d8da8665SAlexandre Belloni 	}
132d8da8665SAlexandre Belloni 
133d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_ALM_READ, &tm);
134d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
135d8da8665SAlexandre Belloni 
136d8da8665SAlexandre Belloni 	TH_LOG("Alarm time now set to %02d:%02d:%02d.",
137d8da8665SAlexandre Belloni 	       tm.tm_hour, tm.tm_min, tm.tm_sec);
138d8da8665SAlexandre Belloni 
139d8da8665SAlexandre Belloni 	/* Enable alarm interrupts */
140d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_AIE_ON, 0);
141d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
142d8da8665SAlexandre Belloni 
143d8da8665SAlexandre Belloni 	FD_ZERO(&readfds);
144d8da8665SAlexandre Belloni 	FD_SET(self->fd, &readfds);
145d8da8665SAlexandre Belloni 
146d8da8665SAlexandre Belloni 	rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
147d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
148fdac9448SAlexandre Belloni 	ASSERT_NE(0, rc);
149d8da8665SAlexandre Belloni 
150d8da8665SAlexandre Belloni 	/* Disable alarm interrupts */
151d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_AIE_OFF, 0);
152d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
153d8da8665SAlexandre Belloni 
154d8da8665SAlexandre Belloni 	rc = read(self->fd, &data, sizeof(unsigned long));
155d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
156d8da8665SAlexandre Belloni 	TH_LOG("data: %lx", data);
157d8da8665SAlexandre Belloni 
158d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_RD_TIME, &tm);
159d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
160d8da8665SAlexandre Belloni 
161d8da8665SAlexandre Belloni 	new = timegm((struct tm *)&tm);
162d8da8665SAlexandre Belloni 	ASSERT_EQ(new, secs);
163d8da8665SAlexandre Belloni }
164d8da8665SAlexandre Belloni 
165d8da8665SAlexandre Belloni TEST_F(rtc, alarm_wkalm_set) {
166d8da8665SAlexandre Belloni 	struct timeval tv = { .tv_sec = ALARM_DELTA + 2 };
167d8da8665SAlexandre Belloni 	struct rtc_wkalrm alarm = { 0 };
168d8da8665SAlexandre Belloni 	struct rtc_time tm;
169d8da8665SAlexandre Belloni 	unsigned long data;
170d8da8665SAlexandre Belloni 	fd_set readfds;
171d8da8665SAlexandre Belloni 	time_t secs, new;
172d8da8665SAlexandre Belloni 	int rc;
173d8da8665SAlexandre Belloni 
174d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
175d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
176d8da8665SAlexandre Belloni 
177d8da8665SAlexandre Belloni 	secs = timegm((struct tm *)&alarm.time) + ALARM_DELTA;
178d8da8665SAlexandre Belloni 	gmtime_r(&secs, (struct tm *)&alarm.time);
179d8da8665SAlexandre Belloni 
180d8da8665SAlexandre Belloni 	alarm.enabled = 1;
181d8da8665SAlexandre Belloni 
182d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_WKALM_SET, &alarm);
183d8da8665SAlexandre Belloni 	if (rc == -1) {
184d8da8665SAlexandre Belloni 		ASSERT_EQ(EINVAL, errno);
185d8da8665SAlexandre Belloni 		TH_LOG("skip alarms are not supported.");
186d8da8665SAlexandre Belloni 		return;
187d8da8665SAlexandre Belloni 	}
188d8da8665SAlexandre Belloni 
189d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_WKALM_RD, &alarm);
190d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
191d8da8665SAlexandre Belloni 
192d8da8665SAlexandre Belloni 	TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.",
193d8da8665SAlexandre Belloni 	       alarm.time.tm_mday, alarm.time.tm_mon + 1,
194d8da8665SAlexandre Belloni 	       alarm.time.tm_year + 1900, alarm.time.tm_hour,
195d8da8665SAlexandre Belloni 	       alarm.time.tm_min, alarm.time.tm_sec);
196d8da8665SAlexandre Belloni 
197d8da8665SAlexandre Belloni 	FD_ZERO(&readfds);
198d8da8665SAlexandre Belloni 	FD_SET(self->fd, &readfds);
199d8da8665SAlexandre Belloni 
200d8da8665SAlexandre Belloni 	rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
201d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
202fdac9448SAlexandre Belloni 	ASSERT_NE(0, rc);
203d8da8665SAlexandre Belloni 
204d8da8665SAlexandre Belloni 	rc = read(self->fd, &data, sizeof(unsigned long));
205d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
206d8da8665SAlexandre Belloni 
207d8da8665SAlexandre Belloni 	rc = ioctl(self->fd, RTC_RD_TIME, &tm);
208d8da8665SAlexandre Belloni 	ASSERT_NE(-1, rc);
209d8da8665SAlexandre Belloni 
210d8da8665SAlexandre Belloni 	new = timegm((struct tm *)&tm);
211d8da8665SAlexandre Belloni 	ASSERT_EQ(new, secs);
212d8da8665SAlexandre Belloni }
213d8da8665SAlexandre Belloni 
214*eff82a26SAlexandre Belloni TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) {
2157b302772SAlexandre Belloni 	struct timeval tv = { .tv_sec = 62 };
2167b302772SAlexandre Belloni 	unsigned long data;
2177b302772SAlexandre Belloni 	struct rtc_time tm;
2187b302772SAlexandre Belloni 	fd_set readfds;
2197b302772SAlexandre Belloni 	time_t secs, new;
2207b302772SAlexandre Belloni 	int rc;
2217b302772SAlexandre Belloni 
2227b302772SAlexandre Belloni 	rc = ioctl(self->fd, RTC_RD_TIME, &tm);
2237b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
2247b302772SAlexandre Belloni 
2257b302772SAlexandre Belloni 	secs = timegm((struct tm *)&tm) + 60 - tm.tm_sec;
2267b302772SAlexandre Belloni 	gmtime_r(&secs, (struct tm *)&tm);
2277b302772SAlexandre Belloni 
2287b302772SAlexandre Belloni 	rc = ioctl(self->fd, RTC_ALM_SET, &tm);
2297b302772SAlexandre Belloni 	if (rc == -1) {
2307b302772SAlexandre Belloni 		ASSERT_EQ(EINVAL, errno);
2317b302772SAlexandre Belloni 		TH_LOG("skip alarms are not supported.");
2327b302772SAlexandre Belloni 		return;
2337b302772SAlexandre Belloni 	}
2347b302772SAlexandre Belloni 
2357b302772SAlexandre Belloni 	rc = ioctl(self->fd, RTC_ALM_READ, &tm);
2367b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
2377b302772SAlexandre Belloni 
2387b302772SAlexandre Belloni 	TH_LOG("Alarm time now set to %02d:%02d:%02d.",
2397b302772SAlexandre Belloni 	       tm.tm_hour, tm.tm_min, tm.tm_sec);
2407b302772SAlexandre Belloni 
2417b302772SAlexandre Belloni 	/* Enable alarm interrupts */
2427b302772SAlexandre Belloni 	rc = ioctl(self->fd, RTC_AIE_ON, 0);
2437b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
2447b302772SAlexandre Belloni 
2457b302772SAlexandre Belloni 	FD_ZERO(&readfds);
2467b302772SAlexandre Belloni 	FD_SET(self->fd, &readfds);
2477b302772SAlexandre Belloni 
2487b302772SAlexandre Belloni 	rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
2497b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
2507b302772SAlexandre Belloni 	ASSERT_NE(0, rc);
2517b302772SAlexandre Belloni 
2527b302772SAlexandre Belloni 	/* Disable alarm interrupts */
2537b302772SAlexandre Belloni 	rc = ioctl(self->fd, RTC_AIE_OFF, 0);
2547b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
2557b302772SAlexandre Belloni 
2567b302772SAlexandre Belloni 	rc = read(self->fd, &data, sizeof(unsigned long));
2577b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
2587b302772SAlexandre Belloni 	TH_LOG("data: %lx", data);
2597b302772SAlexandre Belloni 
2607b302772SAlexandre Belloni 	rc = ioctl(self->fd, RTC_RD_TIME, &tm);
2617b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
2627b302772SAlexandre Belloni 
2637b302772SAlexandre Belloni 	new = timegm((struct tm *)&tm);
2647b302772SAlexandre Belloni 	ASSERT_EQ(new, secs);
2657b302772SAlexandre Belloni }
2667b302772SAlexandre Belloni 
267*eff82a26SAlexandre Belloni TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) {
2687b302772SAlexandre Belloni 	struct timeval tv = { .tv_sec = 62 };
2697b302772SAlexandre Belloni 	struct rtc_wkalrm alarm = { 0 };
2707b302772SAlexandre Belloni 	struct rtc_time tm;
2717b302772SAlexandre Belloni 	unsigned long data;
2727b302772SAlexandre Belloni 	fd_set readfds;
2737b302772SAlexandre Belloni 	time_t secs, new;
2747b302772SAlexandre Belloni 	int rc;
2757b302772SAlexandre Belloni 
2767b302772SAlexandre Belloni 	rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
2777b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
2787b302772SAlexandre Belloni 
2797b302772SAlexandre Belloni 	secs = timegm((struct tm *)&alarm.time) + 60 - alarm.time.tm_sec;
2807b302772SAlexandre Belloni 	gmtime_r(&secs, (struct tm *)&alarm.time);
2817b302772SAlexandre Belloni 
2827b302772SAlexandre Belloni 	alarm.enabled = 1;
2837b302772SAlexandre Belloni 
2847b302772SAlexandre Belloni 	rc = ioctl(self->fd, RTC_WKALM_SET, &alarm);
2857b302772SAlexandre Belloni 	if (rc == -1) {
2867b302772SAlexandre Belloni 		ASSERT_EQ(EINVAL, errno);
2877b302772SAlexandre Belloni 		TH_LOG("skip alarms are not supported.");
2887b302772SAlexandre Belloni 		return;
2897b302772SAlexandre Belloni 	}
2907b302772SAlexandre Belloni 
2917b302772SAlexandre Belloni 	rc = ioctl(self->fd, RTC_WKALM_RD, &alarm);
2927b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
2937b302772SAlexandre Belloni 
2947b302772SAlexandre Belloni 	TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.",
2957b302772SAlexandre Belloni 	       alarm.time.tm_mday, alarm.time.tm_mon + 1,
2967b302772SAlexandre Belloni 	       alarm.time.tm_year + 1900, alarm.time.tm_hour,
2977b302772SAlexandre Belloni 	       alarm.time.tm_min, alarm.time.tm_sec);
2987b302772SAlexandre Belloni 
2997b302772SAlexandre Belloni 	FD_ZERO(&readfds);
3007b302772SAlexandre Belloni 	FD_SET(self->fd, &readfds);
3017b302772SAlexandre Belloni 
3027b302772SAlexandre Belloni 	rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
3037b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
3047b302772SAlexandre Belloni 	ASSERT_NE(0, rc);
3057b302772SAlexandre Belloni 
3067b302772SAlexandre Belloni 	rc = read(self->fd, &data, sizeof(unsigned long));
3077b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
3087b302772SAlexandre Belloni 
3097b302772SAlexandre Belloni 	rc = ioctl(self->fd, RTC_RD_TIME, &tm);
3107b302772SAlexandre Belloni 	ASSERT_NE(-1, rc);
3117b302772SAlexandre Belloni 
3127b302772SAlexandre Belloni 	new = timegm((struct tm *)&tm);
3137b302772SAlexandre Belloni 	ASSERT_EQ(new, secs);
3147b302772SAlexandre Belloni }
3157b302772SAlexandre Belloni 
316d8da8665SAlexandre Belloni static void __attribute__((constructor))
317d8da8665SAlexandre Belloni __constructor_order_last(void)
318d8da8665SAlexandre Belloni {
319d8da8665SAlexandre Belloni 	if (!__constructor_order)
320d8da8665SAlexandre Belloni 		__constructor_order = _CONSTRUCTOR_ORDER_BACKWARD;
321a12ab9e1SAlexandre Belloni }
322a12ab9e1SAlexandre Belloni 
323a12ab9e1SAlexandre Belloni int main(int argc, char **argv)
324a12ab9e1SAlexandre Belloni {
325a12ab9e1SAlexandre Belloni 	switch (argc) {
326a12ab9e1SAlexandre Belloni 	case 2:
327d8da8665SAlexandre Belloni 		rtc_file = argv[1];
328a12ab9e1SAlexandre Belloni 		/* FALLTHROUGH */
329a12ab9e1SAlexandre Belloni 	case 1:
330a12ab9e1SAlexandre Belloni 		break;
331a12ab9e1SAlexandre Belloni 	default:
332d8da8665SAlexandre Belloni 		fprintf(stderr, "usage: %s [rtcdev]\n", argv[0]);
333a12ab9e1SAlexandre Belloni 		return 1;
334a12ab9e1SAlexandre Belloni 	}
335a12ab9e1SAlexandre Belloni 
336d8da8665SAlexandre Belloni 	return test_harness_run(argc, argv);
337a12ab9e1SAlexandre Belloni }
338