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) RTC Power Fault 32 * This is verified by analyzing the rtc_get() return status. 33 * 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 43 #ifdef CONFIG_POST 44 45 #include <post.h> 46 #include <rtc.h> 47 48 #if CONFIG_POST & CFG_POST_RTC 49 50 static int rtc_post_skip (ulong * diff) 51 { 52 struct rtc_time tm1; 53 struct rtc_time tm2; 54 ulong start1; 55 ulong start2; 56 57 rtc_get (&tm1); 58 start1 = get_timer (0); 59 60 while (1) { 61 rtc_get (&tm2); 62 start2 = get_timer (0); 63 if (tm1.tm_sec != tm2.tm_sec) 64 break; 65 if (start2 - start1 > 1500) 66 break; 67 } 68 69 if (tm1.tm_sec != tm2.tm_sec) { 70 *diff = start2 - start1; 71 72 return 0; 73 } else { 74 return -1; 75 } 76 } 77 78 static void rtc_post_restore (struct rtc_time *tm, unsigned int sec) 79 { 80 time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, 81 tm->tm_min, tm->tm_sec) + sec; 82 struct rtc_time ntm; 83 84 to_tm (t, &ntm); 85 86 rtc_set (&ntm); 87 } 88 89 int rtc_post_test (int flags) 90 { 91 ulong diff; 92 unsigned int i; 93 struct rtc_time svtm; 94 static unsigned int daysnl[] = 95 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 96 static unsigned int daysl[] = 97 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 98 unsigned int ynl = 1999; 99 unsigned int yl = 2000; 100 unsigned int skipped = 0; 101 int reliable; 102 103 /* Time reliability */ 104 reliable = rtc_get (&svtm); 105 106 /* Time uniformity */ 107 if (rtc_post_skip (&diff) != 0) { 108 post_log ("Timeout while waiting for a new second !\n"); 109 110 return -1; 111 } 112 113 for (i = 0; i < 5; i++) { 114 if (rtc_post_skip (&diff) != 0) { 115 post_log ("Timeout while waiting for a new second !\n"); 116 117 return -1; 118 } 119 120 if (diff < 950 || diff > 1050) { 121 post_log ("Invalid second duration !\n"); 122 123 return -1; 124 } 125 } 126 127 /* Passing month boundaries */ 128 129 if (rtc_post_skip (&diff) != 0) { 130 post_log ("Timeout while waiting for a new second !\n"); 131 132 return -1; 133 } 134 rtc_get (&svtm); 135 136 for (i = 0; i < 12; i++) { 137 time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59); 138 struct rtc_time tm; 139 140 to_tm (t, &tm); 141 rtc_set (&tm); 142 143 skipped++; 144 if (rtc_post_skip (&diff) != 0) { 145 rtc_post_restore (&svtm, skipped); 146 post_log ("Timeout while waiting for a new second !\n"); 147 148 return -1; 149 } 150 151 rtc_get (&tm); 152 if (tm.tm_mon == i + 1) { 153 rtc_post_restore (&svtm, skipped); 154 post_log ("Month %d boundary is not passed !\n", i + 1); 155 156 return -1; 157 } 158 } 159 160 for (i = 0; i < 12; i++) { 161 time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59); 162 struct rtc_time tm; 163 164 to_tm (t, &tm); 165 rtc_set (&tm); 166 167 skipped++; 168 if (rtc_post_skip (&diff) != 0) { 169 rtc_post_restore (&svtm, skipped); 170 post_log ("Timeout while waiting for a new second !\n"); 171 172 return -1; 173 } 174 175 rtc_get (&tm); 176 if (tm.tm_mon == i + 1) { 177 rtc_post_restore (&svtm, skipped); 178 post_log ("Month %d boundary is not passed !\n", i + 1); 179 180 return -1; 181 } 182 } 183 rtc_post_restore (&svtm, skipped); 184 185 /* If come here, then RTC operates correcty, check the correctness 186 * of the time it reports. 187 */ 188 if (reliable < 0) { 189 post_log ("RTC Time is not reliable! Power fault? \n"); 190 191 return -1; 192 } 193 194 return 0; 195 } 196 197 #endif /* CONFIG_POST & CFG_POST_RTC */ 198 #endif /* CONFIG_POST */ 199