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