blob: c2e73917ec51141b20290fb3aa7249fccfc0d809 [file] [log] [blame]
Wolfgang Denkb38e0df2007-03-06 18:08:43 +01001/*
2 * (C) Copyright 2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Wolfgang Denkb38e0df2007-03-06 18:08:43 +01006 */
7
8#include <common.h>
9
10/*
11 * RTC test
12 *
13 * The Real Time Clock (RTC) operation is verified by this test.
14 * The following features are verified:
Yuri Tikhonov9bacd942008-03-20 17:56:04 +030015 * o) RTC Power Fault
16 * This is verified by analyzing the rtc_get() return status.
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010017 * o) Time uniformity
18 * This is verified by reading RTC in polling within
19 * a short period of time.
20 * o) Passing month boundaries
21 * This is checked by setting RTC to a second before
22 * a month boundary and reading it after its passing the
23 * boundary. The test is performed for both leap- and
24 * nonleap-years.
25 */
26
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010027#include <post.h>
28#include <rtc.h>
29
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020030#if CONFIG_POST & CONFIG_SYS_POST_RTC
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010031
32static int rtc_post_skip (ulong * diff)
33{
34 struct rtc_time tm1;
35 struct rtc_time tm2;
36 ulong start1;
37 ulong start2;
38
39 rtc_get (&tm1);
40 start1 = get_timer (0);
41
42 while (1) {
43 rtc_get (&tm2);
44 start2 = get_timer (0);
45 if (tm1.tm_sec != tm2.tm_sec)
46 break;
47 if (start2 - start1 > 1500)
48 break;
49 }
50
51 if (tm1.tm_sec != tm2.tm_sec) {
52 *diff = start2 - start1;
53
54 return 0;
55 } else {
56 return -1;
57 }
58}
59
60static void rtc_post_restore (struct rtc_time *tm, unsigned int sec)
61{
Simon Glass4283e842015-04-20 12:37:19 -060062 time_t t = rtc_mktime(tm) + sec;
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010063 struct rtc_time ntm;
64
Simon Glass12994662015-04-20 12:37:18 -060065 rtc_to_tm(t, &ntm);
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010066
67 rtc_set (&ntm);
68}
69
70int rtc_post_test (int flags)
71{
72 ulong diff;
73 unsigned int i;
74 struct rtc_time svtm;
75 static unsigned int daysnl[] =
76 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
77 static unsigned int daysl[] =
78 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
79 unsigned int ynl = 1999;
80 unsigned int yl = 2000;
81 unsigned int skipped = 0;
Yuri Tikhonov9bacd942008-03-20 17:56:04 +030082 int reliable;
83
84 /* Time reliability */
85 reliable = rtc_get (&svtm);
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010086
87 /* Time uniformity */
88 if (rtc_post_skip (&diff) != 0) {
89 post_log ("Timeout while waiting for a new second !\n");
90
91 return -1;
92 }
93
94 for (i = 0; i < 5; i++) {
95 if (rtc_post_skip (&diff) != 0) {
96 post_log ("Timeout while waiting for a new second !\n");
97
98 return -1;
99 }
100
101 if (diff < 950 || diff > 1050) {
102 post_log ("Invalid second duration !\n");
103
104 return -1;
105 }
106 }
107
108 /* Passing month boundaries */
109
110 if (rtc_post_skip (&diff) != 0) {
111 post_log ("Timeout while waiting for a new second !\n");
112
113 return -1;
114 }
115 rtc_get (&svtm);
116
117 for (i = 0; i < 12; i++) {
Simon Glass4283e842015-04-20 12:37:19 -0600118 time_t t;
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100119 struct rtc_time tm;
120
Simon Glass4283e842015-04-20 12:37:19 -0600121 tm.tm_year = ynl;
122 tm.tm_mon = i + 1;
123 tm.tm_mday = daysnl[i];
124 tm.tm_hour = 23;
125 tm.tm_min = 59;
126 tm.tm_sec = 59;
127 t = rtc_mktime(&tm);
Simon Glass12994662015-04-20 12:37:18 -0600128 rtc_to_tm(t, &tm);
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100129 rtc_set (&tm);
130
131 skipped++;
132 if (rtc_post_skip (&diff) != 0) {
133 rtc_post_restore (&svtm, skipped);
134 post_log ("Timeout while waiting for a new second !\n");
135
136 return -1;
137 }
138
139 rtc_get (&tm);
140 if (tm.tm_mon == i + 1) {
141 rtc_post_restore (&svtm, skipped);
142 post_log ("Month %d boundary is not passed !\n", i + 1);
143
144 return -1;
145 }
146 }
147
148 for (i = 0; i < 12; i++) {
Simon Glass4283e842015-04-20 12:37:19 -0600149 time_t t;
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100150 struct rtc_time tm;
151
Simon Glass4283e842015-04-20 12:37:19 -0600152 tm.tm_year = yl;
153 tm.tm_mon = i + 1;
154 tm.tm_mday = daysl[i];
155 tm.tm_hour = 23;
156 tm.tm_min = 59;
157 tm.tm_sec = 59;
158 t = rtc_mktime(&tm);
159
Simon Glass12994662015-04-20 12:37:18 -0600160 rtc_to_tm(t, &tm);
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100161 rtc_set (&tm);
162
163 skipped++;
164 if (rtc_post_skip (&diff) != 0) {
165 rtc_post_restore (&svtm, skipped);
166 post_log ("Timeout while waiting for a new second !\n");
167
168 return -1;
169 }
170
171 rtc_get (&tm);
172 if (tm.tm_mon == i + 1) {
173 rtc_post_restore (&svtm, skipped);
174 post_log ("Month %d boundary is not passed !\n", i + 1);
175
176 return -1;
177 }
178 }
179 rtc_post_restore (&svtm, skipped);
180
Yuri Tikhonov9bacd942008-03-20 17:56:04 +0300181 /* If come here, then RTC operates correcty, check the correctness
182 * of the time it reports.
183 */
184 if (reliable < 0) {
185 post_log ("RTC Time is not reliable! Power fault? \n");
186
187 return -1;
188 }
189
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100190 return 0;
191}
192
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200193#endif /* CONFIG_POST & CONFIG_SYS_POST_RTC */