1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2002 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 5 */ 6 7 #include <common.h> 8 9 /* 10 * RTC test 11 * 12 * The Real Time Clock (RTC) operation is verified by this test. 13 * The following features are verified: 14 * o) RTC Power Fault 15 * This is verified by analyzing the rtc_get() return status. 16 * o) Time uniformity 17 * This is verified by reading RTC in polling within 18 * a short period of time. 19 * o) Passing month boundaries 20 * This is checked by setting RTC to a second before 21 * a month boundary and reading it after its passing the 22 * boundary. The test is performed for both leap- and 23 * nonleap-years. 24 */ 25 26 #include <post.h> 27 #include <rtc.h> 28 29 #if CONFIG_POST & CONFIG_SYS_POST_RTC 30 31 static int rtc_post_skip (ulong * diff) 32 { 33 struct rtc_time tm1; 34 struct rtc_time tm2; 35 ulong start1; 36 ulong start2; 37 38 rtc_get (&tm1); 39 start1 = get_timer (0); 40 41 while (1) { 42 rtc_get (&tm2); 43 start2 = get_timer (0); 44 if (tm1.tm_sec != tm2.tm_sec) 45 break; 46 if (start2 - start1 > 1500) 47 break; 48 } 49 50 if (tm1.tm_sec != tm2.tm_sec) { 51 *diff = start2 - start1; 52 53 return 0; 54 } else { 55 return -1; 56 } 57 } 58 59 static void rtc_post_restore (struct rtc_time *tm, unsigned int sec) 60 { 61 time_t t = rtc_mktime(tm) + sec; 62 struct rtc_time ntm; 63 64 rtc_to_tm(t, &ntm); 65 66 rtc_set (&ntm); 67 } 68 69 int rtc_post_test (int flags) 70 { 71 ulong diff; 72 unsigned int i; 73 struct rtc_time svtm; 74 static unsigned int daysnl[] = 75 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 76 static unsigned int daysl[] = 77 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 78 unsigned int ynl = 1999; 79 unsigned int yl = 2000; 80 unsigned int skipped = 0; 81 int reliable; 82 83 /* Time reliability */ 84 reliable = rtc_get (&svtm); 85 86 /* Time uniformity */ 87 if (rtc_post_skip (&diff) != 0) { 88 post_log ("Timeout while waiting for a new second !\n"); 89 90 return -1; 91 } 92 93 for (i = 0; i < 5; i++) { 94 if (rtc_post_skip (&diff) != 0) { 95 post_log ("Timeout while waiting for a new second !\n"); 96 97 return -1; 98 } 99 100 if (diff < 950 || diff > 1050) { 101 post_log ("Invalid second duration !\n"); 102 103 return -1; 104 } 105 } 106 107 /* Passing month boundaries */ 108 109 if (rtc_post_skip (&diff) != 0) { 110 post_log ("Timeout while waiting for a new second !\n"); 111 112 return -1; 113 } 114 rtc_get (&svtm); 115 116 for (i = 0; i < 12; i++) { 117 time_t t; 118 struct rtc_time tm; 119 120 tm.tm_year = ynl; 121 tm.tm_mon = i + 1; 122 tm.tm_mday = daysnl[i]; 123 tm.tm_hour = 23; 124 tm.tm_min = 59; 125 tm.tm_sec = 59; 126 t = rtc_mktime(&tm); 127 rtc_to_tm(t, &tm); 128 rtc_set (&tm); 129 130 skipped++; 131 if (rtc_post_skip (&diff) != 0) { 132 rtc_post_restore (&svtm, skipped); 133 post_log ("Timeout while waiting for a new second !\n"); 134 135 return -1; 136 } 137 138 rtc_get (&tm); 139 if (tm.tm_mon == i + 1) { 140 rtc_post_restore (&svtm, skipped); 141 post_log ("Month %d boundary is not passed !\n", i + 1); 142 143 return -1; 144 } 145 } 146 147 for (i = 0; i < 12; i++) { 148 time_t t; 149 struct rtc_time tm; 150 151 tm.tm_year = yl; 152 tm.tm_mon = i + 1; 153 tm.tm_mday = daysl[i]; 154 tm.tm_hour = 23; 155 tm.tm_min = 59; 156 tm.tm_sec = 59; 157 t = rtc_mktime(&tm); 158 159 rtc_to_tm(t, &tm); 160 rtc_set (&tm); 161 162 skipped++; 163 if (rtc_post_skip (&diff) != 0) { 164 rtc_post_restore (&svtm, skipped); 165 post_log ("Timeout while waiting for a new second !\n"); 166 167 return -1; 168 } 169 170 rtc_get (&tm); 171 if (tm.tm_mon == i + 1) { 172 rtc_post_restore (&svtm, skipped); 173 post_log ("Month %d boundary is not passed !\n", i + 1); 174 175 return -1; 176 } 177 } 178 rtc_post_restore (&svtm, skipped); 179 180 /* If come here, then RTC operates correcty, check the correctness 181 * of the time it reports. 182 */ 183 if (reliable < 0) { 184 post_log ("RTC Time is not reliable! Power fault? \n"); 185 186 return -1; 187 } 188 189 return 0; 190 } 191 192 #endif /* CONFIG_POST & CONFIG_SYS_POST_RTC */ 193