core: add ofnode_get_by_phandle() api
[people/ms/u-boot.git] / post / drivers / rtc.c
1 /*
2 * (C) Copyright 2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
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:
15 * o) RTC Power Fault
16 * This is verified by analyzing the rtc_get() return status.
17 * 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
27 #include <post.h>
28 #include <rtc.h>
29
30 #if CONFIG_POST & CONFIG_SYS_POST_RTC
31
32 static 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
60 static void rtc_post_restore (struct rtc_time *tm, unsigned int sec)
61 {
62 time_t t = rtc_mktime(tm) + sec;
63 struct rtc_time ntm;
64
65 rtc_to_tm(t, &ntm);
66
67 rtc_set (&ntm);
68 }
69
70 int 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;
82 int reliable;
83
84 /* Time reliability */
85 reliable = rtc_get (&svtm);
86
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++) {
118 time_t t;
119 struct rtc_time tm;
120
121 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);
128 rtc_to_tm(t, &tm);
129 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++) {
149 time_t t;
150 struct rtc_time tm;
151
152 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
160 rtc_to_tm(t, &tm);
161 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
181 /* 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
190 return 0;
191 }
192
193 #endif /* CONFIG_POST & CONFIG_SYS_POST_RTC */