1e3892e10SLaurent Vivier /*
2e3892e10SLaurent Vivier * Test the RTAS interface
3e3892e10SLaurent Vivier */
4e3892e10SLaurent Vivier
5e3892e10SLaurent Vivier #include <libcflat.h>
6e3892e10SLaurent Vivier #include <util.h>
7e3892e10SLaurent Vivier #include <asm/rtas.h>
8e3892e10SLaurent Vivier
9e3892e10SLaurent Vivier #define DAYS(y,m,d) (365UL * (y) + ((y) / 4) - ((y) / 100) + ((y) / 400) + \
10e3892e10SLaurent Vivier 367UL * (m) / 12 + \
11e3892e10SLaurent Vivier (d))
12e3892e10SLaurent Vivier
mktime(int year,int month,int day,int hour,int minute,int second)13e3892e10SLaurent Vivier static unsigned long mktime(int year, int month, int day,
14e3892e10SLaurent Vivier int hour, int minute, int second)
15e3892e10SLaurent Vivier {
16e3892e10SLaurent Vivier unsigned long epoch;
17e3892e10SLaurent Vivier
18e3892e10SLaurent Vivier /* Put February at end of the year to avoid leap day this year */
19e3892e10SLaurent Vivier
20e3892e10SLaurent Vivier month -= 2;
21e3892e10SLaurent Vivier if (month <= 0) {
22e3892e10SLaurent Vivier month += 12;
23e3892e10SLaurent Vivier year -= 1;
24e3892e10SLaurent Vivier }
25e3892e10SLaurent Vivier
26e3892e10SLaurent Vivier /* compute epoch: substract DAYS(since_March(1-1-1970)) */
27e3892e10SLaurent Vivier
28e3892e10SLaurent Vivier epoch = DAYS(year, month, day) - DAYS(1969, 11, 1);
29e3892e10SLaurent Vivier
30e3892e10SLaurent Vivier epoch = epoch * 24 + hour;
31e3892e10SLaurent Vivier epoch = epoch * 60 + minute;
32e3892e10SLaurent Vivier epoch = epoch * 60 + second;
33e3892e10SLaurent Vivier
34e3892e10SLaurent Vivier return epoch;
35e3892e10SLaurent Vivier }
36e3892e10SLaurent Vivier
37e3892e10SLaurent Vivier #define DELAY 1
38e3892e10SLaurent Vivier #define MAX_LOOP 10000000
39e3892e10SLaurent Vivier
check_get_time_of_day(unsigned long start)40e3892e10SLaurent Vivier static void check_get_time_of_day(unsigned long start)
41e3892e10SLaurent Vivier {
422565dce1SThomas Huth uint32_t token;
43e3892e10SLaurent Vivier int ret;
44e3892e10SLaurent Vivier int now[8];
45e3892e10SLaurent Vivier unsigned long t1, t2, count;
46e3892e10SLaurent Vivier
472565dce1SThomas Huth ret = rtas_token("get-time-of-day", &token);
48*a299895bSThomas Huth report(ret == 0, "token available");
492565dce1SThomas Huth if (ret)
50e3892e10SLaurent Vivier return;
51e3892e10SLaurent Vivier
52e3892e10SLaurent Vivier ret = rtas_call(token, 0, 8, now);
53*a299895bSThomas Huth report(ret == 0, "execution");
54e3892e10SLaurent Vivier
55*a299895bSThomas Huth report(now[5] >= 0 && now[5] <= 59, "second");
56*a299895bSThomas Huth report(now[4] >= 0 && now[4] <= 59, "minute");
57*a299895bSThomas Huth report(now[3] >= 0 && now[3] <= 23, "hour");
58*a299895bSThomas Huth report(now[2] >= 1 && now[2] <= 31, "day");
59*a299895bSThomas Huth report(now[1] >= 1 && now[1] <= 12, "month");
60*a299895bSThomas Huth report(now[0] >= 1970, "year");
61*a299895bSThomas Huth report(mktime(now[0], now[1], now[2], now[3], now[4], now[5]) - start < 3,
62*a299895bSThomas Huth "accuracy (< 3s)");
63e3892e10SLaurent Vivier
64e3892e10SLaurent Vivier ret = rtas_call(token, 0, 8, now);
65e3892e10SLaurent Vivier t1 = mktime(now[0], now[1], now[2], now[3], now[4], now[5]);
66e3892e10SLaurent Vivier count = 0;
67e3892e10SLaurent Vivier do {
68e3892e10SLaurent Vivier ret = rtas_call(token, 0, 8, now);
69e3892e10SLaurent Vivier t2 = mktime(now[0], now[1], now[2], now[3], now[4], now[5]);
70e3892e10SLaurent Vivier count++;
71e3892e10SLaurent Vivier } while (t1 + DELAY > t2 && count < MAX_LOOP);
72*a299895bSThomas Huth report(t1 + DELAY <= t2, "running");
73e3892e10SLaurent Vivier }
74e3892e10SLaurent Vivier
check_set_time_of_day(void)75e3892e10SLaurent Vivier static void check_set_time_of_day(void)
76e3892e10SLaurent Vivier {
772565dce1SThomas Huth uint32_t stod_token, gtod_token;
78e3892e10SLaurent Vivier int ret;
79e3892e10SLaurent Vivier int date[8];
80e3892e10SLaurent Vivier unsigned long t1, t2, count;
81e3892e10SLaurent Vivier
822565dce1SThomas Huth ret = rtas_token("set-time-of-day", &stod_token);
83*a299895bSThomas Huth report(ret == 0, "token available");
842565dce1SThomas Huth if (ret)
85e3892e10SLaurent Vivier return;
86e3892e10SLaurent Vivier
87e3892e10SLaurent Vivier /* 23:59:59 28/2/2000 */
88e3892e10SLaurent Vivier
892565dce1SThomas Huth ret = rtas_call(stod_token, 7, 1, NULL, 2000, 2, 28, 23, 59, 59);
90*a299895bSThomas Huth report(ret == 0, "execution");
91e3892e10SLaurent Vivier
92e3892e10SLaurent Vivier /* check it has worked */
932565dce1SThomas Huth ret = rtas_token("get-time-of-day", >od_token);
942565dce1SThomas Huth assert(ret == 0);
952565dce1SThomas Huth ret = rtas_call(gtod_token, 0, 8, date);
96*a299895bSThomas Huth report(ret == 0, "re-read");
97e3892e10SLaurent Vivier t1 = mktime(2000, 2, 28, 23, 59, 59);
98e3892e10SLaurent Vivier t2 = mktime(date[0], date[1], date[2],
99e3892e10SLaurent Vivier date[3], date[4], date[5]);
100*a299895bSThomas Huth report(t2 - t1 < 2, "result");
101e3892e10SLaurent Vivier
102e3892e10SLaurent Vivier /* check it is running */
103e3892e10SLaurent Vivier count = 0;
104e3892e10SLaurent Vivier do {
1052565dce1SThomas Huth ret = rtas_call(gtod_token, 0, 8, date);
106e3892e10SLaurent Vivier t2 = mktime(date[0], date[1], date[2],
107e3892e10SLaurent Vivier date[3], date[4], date[5]);
108e3892e10SLaurent Vivier count++;
109e3892e10SLaurent Vivier } while (t1 + DELAY > t2 && count < MAX_LOOP);
110*a299895bSThomas Huth report(t1 + DELAY <= t2, "running");
111e3892e10SLaurent Vivier }
112e3892e10SLaurent Vivier
main(int argc,char ** argv)113e3892e10SLaurent Vivier int main(int argc, char **argv)
114e3892e10SLaurent Vivier {
115e3892e10SLaurent Vivier int len;
116e3892e10SLaurent Vivier long val;
117e3892e10SLaurent Vivier
118e3892e10SLaurent Vivier report_prefix_push("rtas");
119e3892e10SLaurent Vivier
120a9abb1b8SAndrew Jones if (argc < 2)
121e3892e10SLaurent Vivier report_abort("no test specified");
122e3892e10SLaurent Vivier
123a9abb1b8SAndrew Jones report_prefix_push(argv[1]);
124e3892e10SLaurent Vivier
125a9abb1b8SAndrew Jones if (strcmp(argv[1], "get-time-of-day") == 0) {
126e3892e10SLaurent Vivier
127a9abb1b8SAndrew Jones len = parse_keyval(argv[2], &val);
128e3892e10SLaurent Vivier if (len == -1) {
129e3892e10SLaurent Vivier printf("Missing parameter \"date\"\n");
130e3892e10SLaurent Vivier abort();
131e3892e10SLaurent Vivier }
132a9abb1b8SAndrew Jones argv[2][len] = '\0';
133e3892e10SLaurent Vivier
134e3892e10SLaurent Vivier check_get_time_of_day(val);
135e3892e10SLaurent Vivier
136a9abb1b8SAndrew Jones } else if (strcmp(argv[1], "set-time-of-day") == 0) {
137e3892e10SLaurent Vivier
138e3892e10SLaurent Vivier check_set_time_of_day();
139e3892e10SLaurent Vivier
140e3892e10SLaurent Vivier } else {
141e3892e10SLaurent Vivier printf("Unknown subtest\n");
142e3892e10SLaurent Vivier abort();
143e3892e10SLaurent Vivier }
144e3892e10SLaurent Vivier
145e3892e10SLaurent Vivier report_prefix_pop();
146e3892e10SLaurent Vivier
147e3892e10SLaurent Vivier report_prefix_pop();
148e3892e10SLaurent Vivier
149e3892e10SLaurent Vivier return report_summary();
150e3892e10SLaurent Vivier }
151