xref: /rk3399_rockchip-uboot/post/drivers/rtc.c (revision a6e6fc610e39dec41b79680413d4ed38145bd3c8)
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 */
181