rtc.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2015 Google, Inc
  4. * Written by Simon Glass <sjg@chromium.org>
  5. */
  6. #include <common.h>
  7. #include <console.h>
  8. #include <dm.h>
  9. #include <i2c.h>
  10. #include <log.h>
  11. #include <rtc.h>
  12. #include <asm/io.h>
  13. #include <asm/rtc.h>
  14. #include <asm/test.h>
  15. #include <dm/test.h>
  16. #include <test/test.h>
  17. #include <test/ut.h>
  18. /* Simple RTC sanity check */
  19. static int dm_test_rtc_base(struct unit_test_state *uts)
  20. {
  21. struct udevice *dev;
  22. ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_RTC, 2, &dev));
  23. ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
  24. ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev));
  25. return 0;
  26. }
  27. DM_TEST(dm_test_rtc_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
  28. static void show_time(const char *msg, struct rtc_time *time)
  29. {
  30. printf("%s: %02d/%02d/%04d %02d:%02d:%02d\n", msg,
  31. time->tm_mday, time->tm_mon, time->tm_year,
  32. time->tm_hour, time->tm_min, time->tm_sec);
  33. }
  34. static int cmp_times(struct rtc_time *expect, struct rtc_time *time, bool show)
  35. {
  36. bool same;
  37. same = expect->tm_sec == time->tm_sec;
  38. same &= expect->tm_min == time->tm_min;
  39. same &= expect->tm_hour == time->tm_hour;
  40. same &= expect->tm_mday == time->tm_mday;
  41. same &= expect->tm_mon == time->tm_mon;
  42. same &= expect->tm_year == time->tm_year;
  43. if (!same && show) {
  44. show_time("expected", expect);
  45. show_time("actual", time);
  46. }
  47. return same ? 0 : -EINVAL;
  48. }
  49. /* Set and get the time */
  50. static int dm_test_rtc_set_get(struct unit_test_state *uts)
  51. {
  52. struct rtc_time now, time, cmp;
  53. struct udevice *dev, *emul;
  54. long offset, check_offset, old_offset, old_base_time;
  55. int i;
  56. ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
  57. ut_assertok(i2c_emul_find(dev, &emul));
  58. ut_assertnonnull(emul);
  59. /* Get the offset, putting the RTC into manual mode */
  60. i = 0;
  61. do {
  62. check_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
  63. ut_assertok(dm_rtc_get(dev, &now));
  64. /* Tell the RTC to go into manual mode */
  65. old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
  66. /* If the times changed in that period, read it again */
  67. } while (++i < 2 && check_offset != old_offset);
  68. ut_asserteq(check_offset, old_offset);
  69. old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1);
  70. memset(&time, '\0', sizeof(time));
  71. time.tm_mday = 3;
  72. time.tm_mon = 6;
  73. time.tm_year = 2004;
  74. time.tm_sec = 0;
  75. time.tm_min = 18;
  76. time.tm_hour = 18;
  77. ut_assertok(dm_rtc_set(dev, &time));
  78. memset(&cmp, '\0', sizeof(cmp));
  79. ut_assertok(dm_rtc_get(dev, &cmp));
  80. ut_assertok(cmp_times(&time, &cmp, true));
  81. memset(&time, '\0', sizeof(time));
  82. time.tm_mday = 31;
  83. time.tm_mon = 8;
  84. time.tm_year = 2004;
  85. time.tm_sec = 0;
  86. time.tm_min = 18;
  87. time.tm_hour = 18;
  88. ut_assertok(dm_rtc_set(dev, &time));
  89. memset(&cmp, '\0', sizeof(cmp));
  90. ut_assertok(dm_rtc_get(dev, &cmp));
  91. ut_assertok(cmp_times(&time, &cmp, true));
  92. /* Increment by 1 second */
  93. offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
  94. sandbox_i2c_rtc_set_offset(emul, false, offset + 1);
  95. memset(&cmp, '\0', sizeof(cmp));
  96. ut_assertok(dm_rtc_get(dev, &cmp));
  97. ut_asserteq(1, cmp.tm_sec);
  98. /* Check against original offset */
  99. sandbox_i2c_rtc_set_offset(emul, false, old_offset);
  100. ut_assertok(dm_rtc_get(dev, &cmp));
  101. ut_assertok(cmp_times(&now, &cmp, true));
  102. /* Back to the original offset */
  103. sandbox_i2c_rtc_set_offset(emul, false, 0);
  104. memset(&cmp, '\0', sizeof(cmp));
  105. ut_assertok(dm_rtc_get(dev, &cmp));
  106. ut_assertok(cmp_times(&now, &cmp, true));
  107. /* Increment the base time by 1 emul */
  108. sandbox_i2c_rtc_get_set_base_time(emul, old_base_time + 1);
  109. memset(&cmp, '\0', sizeof(cmp));
  110. ut_assertok(dm_rtc_get(dev, &cmp));
  111. if (now.tm_sec == 59) {
  112. ut_asserteq(0, cmp.tm_sec);
  113. } else {
  114. ut_asserteq(now.tm_sec + 1, cmp.tm_sec);
  115. }
  116. /* return RTC to normal mode */
  117. sandbox_i2c_rtc_set_offset(emul, true, 0);
  118. return 0;
  119. }
  120. DM_TEST(dm_test_rtc_set_get, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
  121. static int dm_test_rtc_read_write(struct unit_test_state *uts)
  122. {
  123. struct rtc_time time;
  124. struct udevice *dev, *emul;
  125. long old_offset;
  126. u8 buf[4], reg;
  127. ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
  128. memcpy(buf, "car", 4);
  129. ut_assertok(dm_rtc_write(dev, REG_AUX0, buf, 4));
  130. memset(buf, '\0', sizeof(buf));
  131. ut_assertok(dm_rtc_read(dev, REG_AUX0, buf, 4));
  132. ut_asserteq(memcmp(buf, "car", 4), 0);
  133. reg = 'b';
  134. ut_assertok(dm_rtc_write(dev, REG_AUX0, &reg, 1));
  135. memset(buf, '\0', sizeof(buf));
  136. ut_assertok(dm_rtc_read(dev, REG_AUX0, buf, 4));
  137. ut_asserteq(memcmp(buf, "bar", 4), 0);
  138. reg = 't';
  139. ut_assertok(dm_rtc_write(dev, REG_AUX2, &reg, 1));
  140. memset(buf, '\0', sizeof(buf));
  141. ut_assertok(dm_rtc_read(dev, REG_AUX1, buf, 3));
  142. ut_asserteq(memcmp(buf, "at", 3), 0);
  143. ut_assertok(i2c_emul_find(dev, &emul));
  144. ut_assertnonnull(emul);
  145. old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
  146. ut_assertok(dm_rtc_get(dev, &time));
  147. ut_assertok(dm_rtc_read(dev, REG_SEC, &reg, 1));
  148. ut_asserteq(time.tm_sec, reg);
  149. ut_assertok(dm_rtc_read(dev, REG_MDAY, &reg, 1));
  150. ut_asserteq(time.tm_mday, reg);
  151. sandbox_i2c_rtc_set_offset(emul, true, old_offset);
  152. return 0;
  153. }
  154. DM_TEST(dm_test_rtc_read_write, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
  155. /* Test 'rtc list' command */
  156. static int dm_test_rtc_cmd_list(struct unit_test_state *uts)
  157. {
  158. console_record_reset();
  159. run_command("rtc list", 0);
  160. ut_assert_nextline("RTC #0 - rtc@43");
  161. ut_assert_nextline("RTC #1 - rtc@61");
  162. ut_assert_console_end();
  163. return 0;
  164. }
  165. DM_TEST(dm_test_rtc_cmd_list, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
  166. /* Test 'rtc read' and 'rtc write' commands */
  167. static int dm_test_rtc_cmd_rw(struct unit_test_state *uts)
  168. {
  169. console_record_reset();
  170. run_command("rtc dev 0", 0);
  171. ut_assert_nextline("RTC #0 - rtc@43");
  172. ut_assert_console_end();
  173. run_command("rtc write 0x30 aabb", 0);
  174. ut_assert_console_end();
  175. run_command("rtc read 0x30 2", 0);
  176. ut_assert_nextline("00000030: aa bb ..");
  177. ut_assert_console_end();
  178. run_command("rtc dev 1", 0);
  179. ut_assert_nextline("RTC #1 - rtc@61");
  180. ut_assert_console_end();
  181. run_command("rtc write 0x30 ccdd", 0);
  182. ut_assert_console_end();
  183. run_command("rtc read 0x30 2", 0);
  184. ut_assert_nextline("00000030: cc dd ..");
  185. ut_assert_console_end();
  186. /*
  187. * Switch back to device #0, check that its aux registers
  188. * still have the same values.
  189. */
  190. run_command("rtc dev 0", 0);
  191. ut_assert_nextline("RTC #0 - rtc@43");
  192. ut_assert_console_end();
  193. run_command("rtc read 0x30 2", 0);
  194. ut_assert_nextline("00000030: aa bb ..");
  195. ut_assert_console_end();
  196. return 0;
  197. }
  198. DM_TEST(dm_test_rtc_cmd_rw, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
  199. /* Reset the time */
  200. static int dm_test_rtc_reset(struct unit_test_state *uts)
  201. {
  202. struct rtc_time now;
  203. struct udevice *dev, *emul;
  204. long old_base_time, base_time;
  205. int i;
  206. ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
  207. ut_assertok(dm_rtc_get(dev, &now));
  208. ut_assertok(i2c_emul_find(dev, &emul));
  209. ut_assertnonnull(emul);
  210. i = 0;
  211. do {
  212. old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, 0);
  213. ut_asserteq(0, sandbox_i2c_rtc_get_set_base_time(emul, -1));
  214. ut_assertok(dm_rtc_reset(dev));
  215. base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1);
  216. /*
  217. * Resetting the RTC should put the base time back to normal.
  218. * Allow for a one-timeadjustment in case the time flips over
  219. * while this test process is pre-empted (either by a second
  220. * or a daylight-saving change), since reset_time() in
  221. * i2c_rtc_emul.c reads the time from the OS.
  222. */
  223. } while (++i < 2 && base_time != old_base_time);
  224. ut_asserteq(old_base_time, base_time);
  225. return 0;
  226. }
  227. DM_TEST(dm_test_rtc_reset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
  228. /* Check that two RTC devices can be used independently */
  229. static int dm_test_rtc_dual(struct unit_test_state *uts)
  230. {
  231. struct rtc_time now1, now2, cmp;
  232. struct udevice *dev1, *dev2;
  233. struct udevice *emul1, *emul2;
  234. long offset;
  235. ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev1));
  236. ut_assertok(dm_rtc_get(dev1, &now1));
  237. ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev2));
  238. ut_assertok(dm_rtc_get(dev2, &now2));
  239. ut_assertok(i2c_emul_find(dev1, &emul1));
  240. ut_assertnonnull(emul1);
  241. ut_assertok(i2c_emul_find(dev2, &emul2));
  242. ut_assertnonnull(emul2);
  243. offset = sandbox_i2c_rtc_set_offset(emul1, false, -1);
  244. sandbox_i2c_rtc_set_offset(emul2, false, offset + 1);
  245. memset(&cmp, '\0', sizeof(cmp));
  246. ut_assertok(dm_rtc_get(dev2, &cmp));
  247. ut_asserteq(-EINVAL, cmp_times(&now1, &cmp, false));
  248. memset(&cmp, '\0', sizeof(cmp));
  249. ut_assertok(dm_rtc_get(dev1, &cmp));
  250. ut_assertok(cmp_times(&now1, &cmp, true));
  251. return 0;
  252. }
  253. DM_TEST(dm_test_rtc_dual, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);