2
0

rtc.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * Read/write DS3231M RTC to/from the sysclock.
  3. *
  4. * This currently doesn't try to maintain any kind of subsecond
  5. * accuracy.
  6. */
  7. #include <string.h>
  8. #include "common.h"
  9. #include "console.h"
  10. #include "io.h"
  11. #include "systime.h"
  12. static inline uint32_t i2c_wait(void)
  13. {
  14. waitfor(I2C_IRQ);
  15. }
  16. static void i2c_send(uint8_t byte, uint8_t ctl)
  17. {
  18. i2c_wait();
  19. I2C_WDATA = (byte << 8) | I2C_NAK | ctl;
  20. }
  21. static bool i2c_acked(void)
  22. {
  23. i2c_wait();
  24. return !(I2C_RDATA & I2C_NAK);
  25. }
  26. static uint8_t i2c_recv(uint8_t ctl)
  27. {
  28. uint32_t rdata;
  29. i2c_wait();
  30. I2C_WDATA = (~0xff) | ctl;
  31. i2c_wait();
  32. return I2C_RDATA_DATA;
  33. }
  34. #define RTC_REGS 19 /* Total RTC registers */
  35. #define RTC_TIME_REGS 7 /* RTC registers with time info */
  36. #define RTC_ADDR 0x68
  37. #define RTC_WCMD ((RTC_ADDR << 1)+0)
  38. #define RTC_RCMD ((RTC_ADDR << 1)+1)
  39. static unsigned int unbcd(uint8_t v)
  40. {
  41. return (v & 0x0f) + (v >> 4) * 10;
  42. }
  43. static uint8_t tobcd(unsigned int v)
  44. {
  45. uint8_t q;
  46. v %= 100;
  47. return ((v/10) << 4) + (v%10);
  48. }
  49. static int i2c_start_rtc(void)
  50. {
  51. int sda_retry_count = 16;
  52. i2c_set_speed(400);
  53. /* SDA held low? */
  54. while (!(I2C_RDATA & I2C_SDA)) {
  55. i2c_send(0xff, I2C_DUMMY);
  56. if (!sda_retry_count--) {
  57. con_printf("RTC: I2C SDA stuck low\n");
  58. return -1;
  59. }
  60. }
  61. i2c_send(RTC_WCMD, 0);
  62. if (!i2c_acked()) {
  63. con_printf("No RTC detected at I2C address 0x%02x\n", RTC_ADDR);
  64. i2c_send(0xff, I2C_P);
  65. return -1;
  66. }
  67. return 0;
  68. }
  69. static void con_time(const char *what, struct tms tms)
  70. {
  71. con_printf("RTC time %s: %04u-%02u-%02u %02u:%02u:%02u\n",
  72. what, tms.tm_year + 1980, tms.tm_mon, tms.tm_mday,
  73. tms.tm_hour, tms.tm_min, tms_sec(tms));
  74. }
  75. void read_rtc(void)
  76. {
  77. uint8_t rtc_regs[RTC_TIME_REGS];
  78. int i;
  79. struct tms tms;
  80. con_puts("RTC read: ");
  81. if (i2c_start_rtc())
  82. return;
  83. i2c_send(0, I2C_SR); /* Starting register */
  84. i2c_send(RTC_RCMD, 0);
  85. for (i = 0; i < RTC_TIME_REGS-1; i++) {
  86. rtc_regs[i] = i2c_recv(0);
  87. con_printf("%02x ", rtc_regs[i]);
  88. }
  89. rtc_regs[i] = i2c_recv(I2C_NAK | I2C_P);
  90. con_printf("%02x\n", rtc_regs[i]);
  91. /* Convert to struct tms and set systime */
  92. memset(&tms, 0, sizeof tms);
  93. unsigned int sec = unbcd(rtc_regs[0]);
  94. tms.tm_2sec = sec >> 1;
  95. tms.hold.tm_1sec = sec & 1;
  96. tms.hold.tm_tick = 0x4000; /* Without more info, assume mid-second */
  97. tms.tm_min = unbcd(rtc_regs[1]);
  98. unsigned int hour;
  99. if (rtc_regs[2] & 0x40) {
  100. /* AM/PM mode - this shouldn't happen */
  101. hour = unbcd(rtc_regs[2] & 0x1f);
  102. if (hour > 11)
  103. hour -= 12;
  104. if (rtc_regs[2] & 0x20)
  105. hour += 12;
  106. } else {
  107. /* 24-hour mode */
  108. hour = unbcd(rtc_regs[2]);
  109. }
  110. tms.tm_hour = hour;
  111. tms.tm_mday = unbcd(rtc_regs[4]);
  112. tms.tm_mon = unbcd(rtc_regs[5] & 0x1f);
  113. tms.tm_year = unbcd(rtc_regs[6]) + (rtc_regs[5] & 0x80 ? 100 : 0) + 20;
  114. set_systime(tms);
  115. #ifdef TEST
  116. con_printf("RTC register content:\n");
  117. for (i = 0; i < RTC_REGS; i++)
  118. con_printf(" %02x", rtc_regs[i]);
  119. #endif
  120. con_time("read", tms);
  121. }
  122. volatile bool do_write_rtc;
  123. void write_rtc(void)
  124. {
  125. uint8_t rtc_regs[RTC_TIME_REGS];
  126. int i;
  127. struct tms tms;
  128. int sda_retry_count = 16;
  129. tms = get_systime();
  130. rtc_regs[0] = tobcd(tms_sec(tms));
  131. rtc_regs[1] = tobcd(tms.tm_min);
  132. rtc_regs[2] = tobcd(tms.tm_hour);
  133. rtc_regs[3] = 0; /* Day of week, unused */
  134. rtc_regs[4] = tobcd(tms.tm_mday);
  135. rtc_regs[5] = tobcd(tms.tm_mon);
  136. rtc_regs[6] = tobcd(tms.tm_year - 20);
  137. if (i2c_start_rtc())
  138. return;
  139. i2c_send(0, 0); /* Starting register */
  140. for (i = 0; i < RTC_TIME_REGS-1; i++)
  141. i2c_send(rtc_regs[i], 0);
  142. i2c_send(rtc_regs[i], I2C_P);
  143. con_time("set", tms);
  144. do_write_rtc = false;
  145. }