blob: 66e52651673e2dec2c33463f7dcf52bdec927886 [file] [log] [blame]
Wolfgang Denkad5bb452007-03-06 18:08:43 +01001/*
2 * (C) Copyright 2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25
26/*
27 * RTC test
28 *
29 * The Real Time Clock (RTC) operation is verified by this test.
30 * The following features are verified:
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +030031 * o) RTC Power Fault
32 * This is verified by analyzing the rtc_get() return status.
Wolfgang Denkad5bb452007-03-06 18:08:43 +010033 * o) Time uniformity
34 * This is verified by reading RTC in polling within
35 * a short period of time.
36 * o) Passing month boundaries
37 * This is checked by setting RTC to a second before
38 * a month boundary and reading it after its passing the
39 * boundary. The test is performed for both leap- and
40 * nonleap-years.
41 */
42
Wolfgang Denkad5bb452007-03-06 18:08:43 +010043#include <post.h>
44#include <rtc.h>
45
46#if CONFIG_POST & CFG_POST_RTC
47
48static int rtc_post_skip (ulong * diff)
49{
50 struct rtc_time tm1;
51 struct rtc_time tm2;
52 ulong start1;
53 ulong start2;
54
55 rtc_get (&tm1);
56 start1 = get_timer (0);
57
58 while (1) {
59 rtc_get (&tm2);
60 start2 = get_timer (0);
61 if (tm1.tm_sec != tm2.tm_sec)
62 break;
63 if (start2 - start1 > 1500)
64 break;
65 }
66
67 if (tm1.tm_sec != tm2.tm_sec) {
68 *diff = start2 - start1;
69
70 return 0;
71 } else {
72 return -1;
73 }
74}
75
76static void rtc_post_restore (struct rtc_time *tm, unsigned int sec)
77{
78 time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
79 tm->tm_min, tm->tm_sec) + sec;
80 struct rtc_time ntm;
81
82 to_tm (t, &ntm);
83
84 rtc_set (&ntm);
85}
86
87int rtc_post_test (int flags)
88{
89 ulong diff;
90 unsigned int i;
91 struct rtc_time svtm;
92 static unsigned int daysnl[] =
93 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
94 static unsigned int daysl[] =
95 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
96 unsigned int ynl = 1999;
97 unsigned int yl = 2000;
98 unsigned int skipped = 0;
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +030099 int reliable;
100
101 /* Time reliability */
102 reliable = rtc_get (&svtm);
Wolfgang Denkad5bb452007-03-06 18:08:43 +0100103
104 /* Time uniformity */
105 if (rtc_post_skip (&diff) != 0) {
106 post_log ("Timeout while waiting for a new second !\n");
107
108 return -1;
109 }
110
111 for (i = 0; i < 5; i++) {
112 if (rtc_post_skip (&diff) != 0) {
113 post_log ("Timeout while waiting for a new second !\n");
114
115 return -1;
116 }
117
118 if (diff < 950 || diff > 1050) {
119 post_log ("Invalid second duration !\n");
120
121 return -1;
122 }
123 }
124
125 /* Passing month boundaries */
126
127 if (rtc_post_skip (&diff) != 0) {
128 post_log ("Timeout while waiting for a new second !\n");
129
130 return -1;
131 }
132 rtc_get (&svtm);
133
134 for (i = 0; i < 12; i++) {
135 time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59);
136 struct rtc_time tm;
137
138 to_tm (t, &tm);
139 rtc_set (&tm);
140
141 skipped++;
142 if (rtc_post_skip (&diff) != 0) {
143 rtc_post_restore (&svtm, skipped);
144 post_log ("Timeout while waiting for a new second !\n");
145
146 return -1;
147 }
148
149 rtc_get (&tm);
150 if (tm.tm_mon == i + 1) {
151 rtc_post_restore (&svtm, skipped);
152 post_log ("Month %d boundary is not passed !\n", i + 1);
153
154 return -1;
155 }
156 }
157
158 for (i = 0; i < 12; i++) {
159 time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59);
160 struct rtc_time tm;
161
162 to_tm (t, &tm);
163 rtc_set (&tm);
164
165 skipped++;
166 if (rtc_post_skip (&diff) != 0) {
167 rtc_post_restore (&svtm, skipped);
168 post_log ("Timeout while waiting for a new second !\n");
169
170 return -1;
171 }
172
173 rtc_get (&tm);
174 if (tm.tm_mon == i + 1) {
175 rtc_post_restore (&svtm, skipped);
176 post_log ("Month %d boundary is not passed !\n", i + 1);
177
178 return -1;
179 }
180 }
181 rtc_post_restore (&svtm, skipped);
182
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +0300183 /* If come here, then RTC operates correcty, check the correctness
184 * of the time it reports.
185 */
186 if (reliable < 0) {
187 post_log ("RTC Time is not reliable! Power fault? \n");
188
189 return -1;
190 }
191
Wolfgang Denkad5bb452007-03-06 18:08:43 +0100192 return 0;
193}
194
195#endif /* CONFIG_POST & CFG_POST_RTC */