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