/* * (C) Copyright 2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include <common.h> /* * RTC test * * The Real Time Clock (RTC) operation is verified by this test. * The following features are verified: * o) RTC Power Fault * This is verified by analyzing the rtc_get() return status. * o) Time uniformity * This is verified by reading RTC in polling within * a short period of time. * o) Passing month boundaries * This is checked by setting RTC to a second before * a month boundary and reading it after its passing the * boundary. The test is performed for both leap- and * nonleap-years. */ #include <post.h> #include <rtc.h> #if CONFIG_POST & CONFIG_SYS_POST_RTC static int rtc_post_skip (ulong * diff) { struct rtc_time tm1; struct rtc_time tm2; ulong start1; ulong start2; rtc_get (&tm1); start1 = get_timer (0); while (1) { rtc_get (&tm2); start2 = get_timer (0); if (tm1.tm_sec != tm2.tm_sec) break; if (start2 - start1 > 1500) break; } if (tm1.tm_sec != tm2.tm_sec) { *diff = start2 - start1; return 0; } else { return -1; } } static void rtc_post_restore (struct rtc_time *tm, unsigned int sec) { time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec) + sec; struct rtc_time ntm; to_tm (t, &ntm); rtc_set (&ntm); } int rtc_post_test (int flags) { ulong diff; unsigned int i; struct rtc_time svtm; static unsigned int daysnl[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static unsigned int daysl[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned int ynl = 1999; unsigned int yl = 2000; unsigned int skipped = 0; int reliable; /* Time reliability */ reliable = rtc_get (&svtm); /* Time uniformity */ if (rtc_post_skip (&diff) != 0) { post_log ("Timeout while waiting for a new second !\n"); return -1; } for (i = 0; i < 5; i++) { if (rtc_post_skip (&diff) != 0) { post_log ("Timeout while waiting for a new second !\n"); return -1; } if (diff < 950 || diff > 1050) { post_log ("Invalid second duration !\n"); return -1; } } /* Passing month boundaries */ if (rtc_post_skip (&diff) != 0) { post_log ("Timeout while waiting for a new second !\n"); return -1; } rtc_get (&svtm); for (i = 0; i < 12; i++) { time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59); struct rtc_time tm; to_tm (t, &tm); rtc_set (&tm); skipped++; if (rtc_post_skip (&diff) != 0) { rtc_post_restore (&svtm, skipped); post_log ("Timeout while waiting for a new second !\n"); return -1; } rtc_get (&tm); if (tm.tm_mon == i + 1) { rtc_post_restore (&svtm, skipped); post_log ("Month %d boundary is not passed !\n", i + 1); return -1; } } for (i = 0; i < 12; i++) { time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59); struct rtc_time tm; to_tm (t, &tm); rtc_set (&tm); skipped++; if (rtc_post_skip (&diff) != 0) { rtc_post_restore (&svtm, skipped); post_log ("Timeout while waiting for a new second !\n"); return -1; } rtc_get (&tm); if (tm.tm_mon == i + 1) { rtc_post_restore (&svtm, skipped); post_log ("Month %d boundary is not passed !\n", i + 1); return -1; } } rtc_post_restore (&svtm, skipped); /* If come here, then RTC operates correcty, check the correctness * of the time it reports. */ if (reliable < 0) { post_log ("RTC Time is not reliable! Power fault? \n"); return -1; } return 0; } #endif /* CONFIG_POST & CONFIG_SYS_POST_RTC */