]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - post/drivers/rtc.c
POST: preparations for moving CONFIG_POST to Makefiles
[karo-tx-uboot.git] / post / drivers / rtc.c
1 /*
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:
31  *   o) Time uniformity
32  *      This is verified by reading RTC in polling within
33  *      a short period of time.
34  *   o) Passing month boundaries
35  *      This is checked by setting RTC to a second before
36  *      a month boundary and reading it after its passing the
37  *      boundary. The test is performed for both leap- and
38  *      nonleap-years.
39  */
40
41 #include <post.h>
42 #include <rtc.h>
43
44 #if CONFIG_POST & CFG_POST_RTC
45
46 static int rtc_post_skip (ulong * diff)
47 {
48         struct rtc_time tm1;
49         struct rtc_time tm2;
50         ulong start1;
51         ulong start2;
52
53         rtc_get (&tm1);
54         start1 = get_timer (0);
55
56         while (1) {
57                 rtc_get (&tm2);
58                 start2 = get_timer (0);
59                 if (tm1.tm_sec != tm2.tm_sec)
60                         break;
61                 if (start2 - start1 > 1500)
62                         break;
63         }
64
65         if (tm1.tm_sec != tm2.tm_sec) {
66                 *diff = start2 - start1;
67
68                 return 0;
69         } else {
70                 return -1;
71         }
72 }
73
74 static void rtc_post_restore (struct rtc_time *tm, unsigned int sec)
75 {
76         time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
77                                            tm->tm_min, tm->tm_sec) + sec;
78         struct rtc_time ntm;
79
80         to_tm (t, &ntm);
81
82         rtc_set (&ntm);
83 }
84
85 int rtc_post_test (int flags)
86 {
87         ulong diff;
88         unsigned int i;
89         struct rtc_time svtm;
90         static unsigned int daysnl[] =
91                         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
92         static unsigned int daysl[] =
93                         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
94         unsigned int ynl = 1999;
95         unsigned int yl = 2000;
96         unsigned int skipped = 0;
97
98         /* Time uniformity */
99         if (rtc_post_skip (&diff) != 0) {
100                 post_log ("Timeout while waiting for a new second !\n");
101
102                 return -1;
103         }
104
105         for (i = 0; i < 5; i++) {
106                 if (rtc_post_skip (&diff) != 0) {
107                         post_log ("Timeout while waiting for a new second !\n");
108
109                         return -1;
110                 }
111
112                 if (diff < 950 || diff > 1050) {
113                         post_log ("Invalid second duration !\n");
114
115                         return -1;
116                 }
117         }
118
119         /* Passing month boundaries */
120
121         if (rtc_post_skip (&diff) != 0) {
122                 post_log ("Timeout while waiting for a new second !\n");
123
124                 return -1;
125         }
126         rtc_get (&svtm);
127
128         for (i = 0; i < 12; i++) {
129                 time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59);
130                 struct rtc_time tm;
131
132                 to_tm (t, &tm);
133                 rtc_set (&tm);
134
135                 skipped++;
136                 if (rtc_post_skip (&diff) != 0) {
137                         rtc_post_restore (&svtm, skipped);
138                         post_log ("Timeout while waiting for a new second !\n");
139
140                         return -1;
141                 }
142
143                 rtc_get (&tm);
144                 if (tm.tm_mon == i + 1) {
145                         rtc_post_restore (&svtm, skipped);
146                         post_log ("Month %d boundary is not passed !\n", i + 1);
147
148                         return -1;
149                 }
150         }
151
152         for (i = 0; i < 12; i++) {
153                 time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59);
154                 struct rtc_time tm;
155
156                 to_tm (t, &tm);
157                 rtc_set (&tm);
158
159                 skipped++;
160                 if (rtc_post_skip (&diff) != 0) {
161                         rtc_post_restore (&svtm, skipped);
162                         post_log ("Timeout while waiting for a new second !\n");
163
164                         return -1;
165                 }
166
167                 rtc_get (&tm);
168                 if (tm.tm_mon == i + 1) {
169                         rtc_post_restore (&svtm, skipped);
170                         post_log ("Month %d boundary is not passed !\n", i + 1);
171
172                         return -1;
173                 }
174         }
175         rtc_post_restore (&svtm, skipped);
176
177         return 0;
178 }
179
180 #endif /* CONFIG_POST & CFG_POST_RTC */