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 = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, 63 tm->tm_min, tm->tm_sec) + sec; 64 struct rtc_time ntm; 65 66 to_tm (t, &ntm); 67 68 rtc_set (&ntm); 69 } 70 71 int rtc_post_test (int flags) 72 { 73 ulong diff; 74 unsigned int i; 75 struct rtc_time svtm; 76 static unsigned int daysnl[] = 77 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 78 static unsigned int daysl[] = 79 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 80 unsigned int ynl = 1999; 81 unsigned int yl = 2000; 82 unsigned int skipped = 0; 83 int reliable; 84 85 /* Time reliability */ 86 reliable = rtc_get (&svtm); 87 88 /* Time uniformity */ 89 if (rtc_post_skip (&diff) != 0) { 90 post_log ("Timeout while waiting for a new second !\n"); 91 92 return -1; 93 } 94 95 for (i = 0; i < 5; i++) { 96 if (rtc_post_skip (&diff) != 0) { 97 post_log ("Timeout while waiting for a new second !\n"); 98 99 return -1; 100 } 101 102 if (diff < 950 || diff > 1050) { 103 post_log ("Invalid second duration !\n"); 104 105 return -1; 106 } 107 } 108 109 /* Passing month boundaries */ 110 111 if (rtc_post_skip (&diff) != 0) { 112 post_log ("Timeout while waiting for a new second !\n"); 113 114 return -1; 115 } 116 rtc_get (&svtm); 117 118 for (i = 0; i < 12; i++) { 119 time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59); 120 struct rtc_time tm; 121 122 to_tm (t, &tm); 123 rtc_set (&tm); 124 125 skipped++; 126 if (rtc_post_skip (&diff) != 0) { 127 rtc_post_restore (&svtm, skipped); 128 post_log ("Timeout while waiting for a new second !\n"); 129 130 return -1; 131 } 132 133 rtc_get (&tm); 134 if (tm.tm_mon == i + 1) { 135 rtc_post_restore (&svtm, skipped); 136 post_log ("Month %d boundary is not passed !\n", i + 1); 137 138 return -1; 139 } 140 } 141 142 for (i = 0; i < 12; i++) { 143 time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59); 144 struct rtc_time tm; 145 146 to_tm (t, &tm); 147 rtc_set (&tm); 148 149 skipped++; 150 if (rtc_post_skip (&diff) != 0) { 151 rtc_post_restore (&svtm, skipped); 152 post_log ("Timeout while waiting for a new second !\n"); 153 154 return -1; 155 } 156 157 rtc_get (&tm); 158 if (tm.tm_mon == i + 1) { 159 rtc_post_restore (&svtm, skipped); 160 post_log ("Month %d boundary is not passed !\n", i + 1); 161 162 return -1; 163 } 164 } 165 rtc_post_restore (&svtm, skipped); 166 167 /* If come here, then RTC operates correcty, check the correctness 168 * of the time it reports. 169 */ 170 if (reliable < 0) { 171 post_log ("RTC Time is not reliable! Power fault? \n"); 172 173 return -1; 174 } 175 176 return 0; 177 } 178 179 #endif /* CONFIG_POST & CONFIG_SYS_POST_RTC */ 180