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 */ 194