rtc.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * (C) Copyright 2002
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. /*
  9. * RTC test
  10. *
  11. * The Real Time Clock (RTC) operation is verified by this test.
  12. * The following features are verified:
  13. * o) RTC Power Fault
  14. * This is verified by analyzing the rtc_get() return status.
  15. * o) Time uniformity
  16. * This is verified by reading RTC in polling within
  17. * a short period of time.
  18. * o) Passing month boundaries
  19. * This is checked by setting RTC to a second before
  20. * a month boundary and reading it after its passing the
  21. * boundary. The test is performed for both leap- and
  22. * nonleap-years.
  23. */
  24. #include <post.h>
  25. #include <rtc.h>
  26. #if CONFIG_POST & CONFIG_SYS_POST_RTC
  27. static int rtc_post_skip (ulong * diff)
  28. {
  29. struct rtc_time tm1;
  30. struct rtc_time tm2;
  31. ulong start1;
  32. ulong start2;
  33. rtc_get (&tm1);
  34. start1 = get_timer (0);
  35. while (1) {
  36. rtc_get (&tm2);
  37. start2 = get_timer (0);
  38. if (tm1.tm_sec != tm2.tm_sec)
  39. break;
  40. if (start2 - start1 > 1500)
  41. break;
  42. }
  43. if (tm1.tm_sec != tm2.tm_sec) {
  44. *diff = start2 - start1;
  45. return 0;
  46. } else {
  47. return -1;
  48. }
  49. }
  50. static void rtc_post_restore (struct rtc_time *tm, unsigned int sec)
  51. {
  52. time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
  53. tm->tm_min, tm->tm_sec) + sec;
  54. struct rtc_time ntm;
  55. to_tm (t, &ntm);
  56. rtc_set (&ntm);
  57. }
  58. int rtc_post_test (int flags)
  59. {
  60. ulong diff;
  61. unsigned int i;
  62. struct rtc_time svtm;
  63. static unsigned int daysnl[] =
  64. { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  65. static unsigned int daysl[] =
  66. { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  67. unsigned int ynl = 1999;
  68. unsigned int yl = 2000;
  69. unsigned int skipped = 0;
  70. int reliable;
  71. /* Time reliability */
  72. reliable = rtc_get (&svtm);
  73. /* Time uniformity */
  74. if (rtc_post_skip (&diff) != 0) {
  75. post_log ("Timeout while waiting for a new second !\n");
  76. return -1;
  77. }
  78. for (i = 0; i < 5; i++) {
  79. if (rtc_post_skip (&diff) != 0) {
  80. post_log ("Timeout while waiting for a new second !\n");
  81. return -1;
  82. }
  83. if (diff < 950 || diff > 1050) {
  84. post_log ("Invalid second duration !\n");
  85. return -1;
  86. }
  87. }
  88. /* Passing month boundaries */
  89. if (rtc_post_skip (&diff) != 0) {
  90. post_log ("Timeout while waiting for a new second !\n");
  91. return -1;
  92. }
  93. rtc_get (&svtm);
  94. for (i = 0; i < 12; i++) {
  95. time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59);
  96. struct rtc_time tm;
  97. to_tm (t, &tm);
  98. rtc_set (&tm);
  99. skipped++;
  100. if (rtc_post_skip (&diff) != 0) {
  101. rtc_post_restore (&svtm, skipped);
  102. post_log ("Timeout while waiting for a new second !\n");
  103. return -1;
  104. }
  105. rtc_get (&tm);
  106. if (tm.tm_mon == i + 1) {
  107. rtc_post_restore (&svtm, skipped);
  108. post_log ("Month %d boundary is not passed !\n", i + 1);
  109. return -1;
  110. }
  111. }
  112. for (i = 0; i < 12; i++) {
  113. time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59);
  114. struct rtc_time tm;
  115. to_tm (t, &tm);
  116. rtc_set (&tm);
  117. skipped++;
  118. if (rtc_post_skip (&diff) != 0) {
  119. rtc_post_restore (&svtm, skipped);
  120. post_log ("Timeout while waiting for a new second !\n");
  121. return -1;
  122. }
  123. rtc_get (&tm);
  124. if (tm.tm_mon == i + 1) {
  125. rtc_post_restore (&svtm, skipped);
  126. post_log ("Month %d boundary is not passed !\n", i + 1);
  127. return -1;
  128. }
  129. }
  130. rtc_post_restore (&svtm, skipped);
  131. /* If come here, then RTC operates correcty, check the correctness
  132. * of the time it reports.
  133. */
  134. if (reliable < 0) {
  135. post_log ("RTC Time is not reliable! Power fault? \n");
  136. return -1;
  137. }
  138. return 0;
  139. }
  140. #endif /* CONFIG_POST & CONFIG_SYS_POST_RTC */