1ad5bb451SWolfgang Denk /* 2ad5bb451SWolfgang Denk * (C) Copyright 2002 3ad5bb451SWolfgang Denk * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4ad5bb451SWolfgang Denk * 5ad5bb451SWolfgang Denk * See file CREDITS for list of people who contributed to this 6ad5bb451SWolfgang Denk * project. 7ad5bb451SWolfgang Denk * 8ad5bb451SWolfgang Denk * This program is free software; you can redistribute it and/or 9ad5bb451SWolfgang Denk * modify it under the terms of the GNU General Public License as 10ad5bb451SWolfgang Denk * published by the Free Software Foundation; either version 2 of 11ad5bb451SWolfgang Denk * the License, or (at your option) any later version. 12ad5bb451SWolfgang Denk * 13ad5bb451SWolfgang Denk * This program is distributed in the hope that it will be useful, 14ad5bb451SWolfgang Denk * but WITHOUT ANY WARRANTY; without even the implied warranty of 15ad5bb451SWolfgang Denk * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16ad5bb451SWolfgang Denk * GNU General Public License for more details. 17ad5bb451SWolfgang Denk * 18ad5bb451SWolfgang Denk * You should have received a copy of the GNU General Public License 19ad5bb451SWolfgang Denk * along with this program; if not, write to the Free Software 20ad5bb451SWolfgang Denk * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21ad5bb451SWolfgang Denk * MA 02111-1307 USA 22ad5bb451SWolfgang Denk */ 23ad5bb451SWolfgang Denk 24ad5bb451SWolfgang Denk #include <common.h> 25ad5bb451SWolfgang Denk 26ad5bb451SWolfgang Denk /* 27ad5bb451SWolfgang Denk * RTC test 28ad5bb451SWolfgang Denk * 29ad5bb451SWolfgang Denk * The Real Time Clock (RTC) operation is verified by this test. 30ad5bb451SWolfgang Denk * The following features are verified: 31*b73a19e1SYuri Tikhonov * o) RTC Power Fault 32*b73a19e1SYuri Tikhonov * This is verified by analyzing the rtc_get() return status. 33ad5bb451SWolfgang Denk * o) Time uniformity 34ad5bb451SWolfgang Denk * This is verified by reading RTC in polling within 35ad5bb451SWolfgang Denk * a short period of time. 36ad5bb451SWolfgang Denk * o) Passing month boundaries 37ad5bb451SWolfgang Denk * This is checked by setting RTC to a second before 38ad5bb451SWolfgang Denk * a month boundary and reading it after its passing the 39ad5bb451SWolfgang Denk * boundary. The test is performed for both leap- and 40ad5bb451SWolfgang Denk * nonleap-years. 41ad5bb451SWolfgang Denk */ 42ad5bb451SWolfgang Denk 43ad5bb451SWolfgang Denk #ifdef CONFIG_POST 44ad5bb451SWolfgang Denk 45ad5bb451SWolfgang Denk #include <post.h> 46ad5bb451SWolfgang Denk #include <rtc.h> 47ad5bb451SWolfgang Denk 48ad5bb451SWolfgang Denk #if CONFIG_POST & CFG_POST_RTC 49ad5bb451SWolfgang Denk 50ad5bb451SWolfgang Denk static int rtc_post_skip (ulong * diff) 51ad5bb451SWolfgang Denk { 52ad5bb451SWolfgang Denk struct rtc_time tm1; 53ad5bb451SWolfgang Denk struct rtc_time tm2; 54ad5bb451SWolfgang Denk ulong start1; 55ad5bb451SWolfgang Denk ulong start2; 56ad5bb451SWolfgang Denk 57ad5bb451SWolfgang Denk rtc_get (&tm1); 58ad5bb451SWolfgang Denk start1 = get_timer (0); 59ad5bb451SWolfgang Denk 60ad5bb451SWolfgang Denk while (1) { 61ad5bb451SWolfgang Denk rtc_get (&tm2); 62ad5bb451SWolfgang Denk start2 = get_timer (0); 63ad5bb451SWolfgang Denk if (tm1.tm_sec != tm2.tm_sec) 64ad5bb451SWolfgang Denk break; 65ad5bb451SWolfgang Denk if (start2 - start1 > 1500) 66ad5bb451SWolfgang Denk break; 67ad5bb451SWolfgang Denk } 68ad5bb451SWolfgang Denk 69ad5bb451SWolfgang Denk if (tm1.tm_sec != tm2.tm_sec) { 70ad5bb451SWolfgang Denk *diff = start2 - start1; 71ad5bb451SWolfgang Denk 72ad5bb451SWolfgang Denk return 0; 73ad5bb451SWolfgang Denk } else { 74ad5bb451SWolfgang Denk return -1; 75ad5bb451SWolfgang Denk } 76ad5bb451SWolfgang Denk } 77ad5bb451SWolfgang Denk 78ad5bb451SWolfgang Denk static void rtc_post_restore (struct rtc_time *tm, unsigned int sec) 79ad5bb451SWolfgang Denk { 80ad5bb451SWolfgang Denk time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, 81ad5bb451SWolfgang Denk tm->tm_min, tm->tm_sec) + sec; 82ad5bb451SWolfgang Denk struct rtc_time ntm; 83ad5bb451SWolfgang Denk 84ad5bb451SWolfgang Denk to_tm (t, &ntm); 85ad5bb451SWolfgang Denk 86ad5bb451SWolfgang Denk rtc_set (&ntm); 87ad5bb451SWolfgang Denk } 88ad5bb451SWolfgang Denk 89ad5bb451SWolfgang Denk int rtc_post_test (int flags) 90ad5bb451SWolfgang Denk { 91ad5bb451SWolfgang Denk ulong diff; 92ad5bb451SWolfgang Denk unsigned int i; 93ad5bb451SWolfgang Denk struct rtc_time svtm; 94ad5bb451SWolfgang Denk static unsigned int daysnl[] = 95ad5bb451SWolfgang Denk { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 96ad5bb451SWolfgang Denk static unsigned int daysl[] = 97ad5bb451SWolfgang Denk { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 98ad5bb451SWolfgang Denk unsigned int ynl = 1999; 99ad5bb451SWolfgang Denk unsigned int yl = 2000; 100ad5bb451SWolfgang Denk unsigned int skipped = 0; 101*b73a19e1SYuri Tikhonov int reliable; 102*b73a19e1SYuri Tikhonov 103*b73a19e1SYuri Tikhonov /* Time reliability */ 104*b73a19e1SYuri Tikhonov reliable = rtc_get (&svtm); 105ad5bb451SWolfgang Denk 106ad5bb451SWolfgang Denk /* Time uniformity */ 107ad5bb451SWolfgang Denk if (rtc_post_skip (&diff) != 0) { 108ad5bb451SWolfgang Denk post_log ("Timeout while waiting for a new second !\n"); 109ad5bb451SWolfgang Denk 110ad5bb451SWolfgang Denk return -1; 111ad5bb451SWolfgang Denk } 112ad5bb451SWolfgang Denk 113ad5bb451SWolfgang Denk for (i = 0; i < 5; i++) { 114ad5bb451SWolfgang Denk if (rtc_post_skip (&diff) != 0) { 115ad5bb451SWolfgang Denk post_log ("Timeout while waiting for a new second !\n"); 116ad5bb451SWolfgang Denk 117ad5bb451SWolfgang Denk return -1; 118ad5bb451SWolfgang Denk } 119ad5bb451SWolfgang Denk 120ad5bb451SWolfgang Denk if (diff < 950 || diff > 1050) { 121ad5bb451SWolfgang Denk post_log ("Invalid second duration !\n"); 122ad5bb451SWolfgang Denk 123ad5bb451SWolfgang Denk return -1; 124ad5bb451SWolfgang Denk } 125ad5bb451SWolfgang Denk } 126ad5bb451SWolfgang Denk 127ad5bb451SWolfgang Denk /* Passing month boundaries */ 128ad5bb451SWolfgang Denk 129ad5bb451SWolfgang Denk if (rtc_post_skip (&diff) != 0) { 130ad5bb451SWolfgang Denk post_log ("Timeout while waiting for a new second !\n"); 131ad5bb451SWolfgang Denk 132ad5bb451SWolfgang Denk return -1; 133ad5bb451SWolfgang Denk } 134ad5bb451SWolfgang Denk rtc_get (&svtm); 135ad5bb451SWolfgang Denk 136ad5bb451SWolfgang Denk for (i = 0; i < 12; i++) { 137ad5bb451SWolfgang Denk time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59); 138ad5bb451SWolfgang Denk struct rtc_time tm; 139ad5bb451SWolfgang Denk 140ad5bb451SWolfgang Denk to_tm (t, &tm); 141ad5bb451SWolfgang Denk rtc_set (&tm); 142ad5bb451SWolfgang Denk 143ad5bb451SWolfgang Denk skipped++; 144ad5bb451SWolfgang Denk if (rtc_post_skip (&diff) != 0) { 145ad5bb451SWolfgang Denk rtc_post_restore (&svtm, skipped); 146ad5bb451SWolfgang Denk post_log ("Timeout while waiting for a new second !\n"); 147ad5bb451SWolfgang Denk 148ad5bb451SWolfgang Denk return -1; 149ad5bb451SWolfgang Denk } 150ad5bb451SWolfgang Denk 151ad5bb451SWolfgang Denk rtc_get (&tm); 152ad5bb451SWolfgang Denk if (tm.tm_mon == i + 1) { 153ad5bb451SWolfgang Denk rtc_post_restore (&svtm, skipped); 154ad5bb451SWolfgang Denk post_log ("Month %d boundary is not passed !\n", i + 1); 155ad5bb451SWolfgang Denk 156ad5bb451SWolfgang Denk return -1; 157ad5bb451SWolfgang Denk } 158ad5bb451SWolfgang Denk } 159ad5bb451SWolfgang Denk 160ad5bb451SWolfgang Denk for (i = 0; i < 12; i++) { 161ad5bb451SWolfgang Denk time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59); 162ad5bb451SWolfgang Denk struct rtc_time tm; 163ad5bb451SWolfgang Denk 164ad5bb451SWolfgang Denk to_tm (t, &tm); 165ad5bb451SWolfgang Denk rtc_set (&tm); 166ad5bb451SWolfgang Denk 167ad5bb451SWolfgang Denk skipped++; 168ad5bb451SWolfgang Denk if (rtc_post_skip (&diff) != 0) { 169ad5bb451SWolfgang Denk rtc_post_restore (&svtm, skipped); 170ad5bb451SWolfgang Denk post_log ("Timeout while waiting for a new second !\n"); 171ad5bb451SWolfgang Denk 172ad5bb451SWolfgang Denk return -1; 173ad5bb451SWolfgang Denk } 174ad5bb451SWolfgang Denk 175ad5bb451SWolfgang Denk rtc_get (&tm); 176ad5bb451SWolfgang Denk if (tm.tm_mon == i + 1) { 177ad5bb451SWolfgang Denk rtc_post_restore (&svtm, skipped); 178ad5bb451SWolfgang Denk post_log ("Month %d boundary is not passed !\n", i + 1); 179ad5bb451SWolfgang Denk 180ad5bb451SWolfgang Denk return -1; 181ad5bb451SWolfgang Denk } 182ad5bb451SWolfgang Denk } 183ad5bb451SWolfgang Denk rtc_post_restore (&svtm, skipped); 184ad5bb451SWolfgang Denk 185*b73a19e1SYuri Tikhonov /* If come here, then RTC operates correcty, check the correctness 186*b73a19e1SYuri Tikhonov * of the time it reports. 187*b73a19e1SYuri Tikhonov */ 188*b73a19e1SYuri Tikhonov if (reliable < 0) { 189*b73a19e1SYuri Tikhonov post_log ("RTC Time is not reliable! Power fault? \n"); 190*b73a19e1SYuri Tikhonov 191*b73a19e1SYuri Tikhonov return -1; 192*b73a19e1SYuri Tikhonov } 193*b73a19e1SYuri Tikhonov 194ad5bb451SWolfgang Denk return 0; 195ad5bb451SWolfgang Denk } 196ad5bb451SWolfgang Denk 197ad5bb451SWolfgang Denk #endif /* CONFIG_POST & CFG_POST_RTC */ 198ad5bb451SWolfgang Denk #endif /* CONFIG_POST */ 199