rtc.c 3.7 KB

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