rtc.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Read/write DS3231M RTC
  3. */
  4. #include <string.h>
  5. #include "fw.h"
  6. #include "console.h"
  7. #include "io.h"
  8. #include "systime.h"
  9. static inline uint32_t i2c_wait(void)
  10. {
  11. uint32_t rdata;
  12. while ((rdata = I2C_RDATA) & I2C_BUSY)
  13. pause();
  14. return rdata;
  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. return !(i2c_wait() & I2C_NAK);
  24. }
  25. static int i2c_recv(uint8_t ctl)
  26. {
  27. uint32_t rdata;
  28. i2c_wait();
  29. I2C_WDATA = (~0xff) | ctl;
  30. rdata = i2c_wait();
  31. return rdata >> 8;
  32. }
  33. #define RTC_REGS 19
  34. #define RTC_ADDR 0x68
  35. #define RTC_WCMD ((RTC_ADDR << 1)+0)
  36. #define RTC_RCMD ((RTC_ADDR << 1)+1)
  37. static unsigned int unbcd(uint8_t v)
  38. {
  39. return (v & 0x0f) + (v >> 4) * 10;
  40. }
  41. void read_rtc(void)
  42. {
  43. uint8_t rtc_regs[RTC_REGS];
  44. int i;
  45. struct tms tms;
  46. i2c_set_speed(100);
  47. i2c_send(RTC_WCMD, 0);
  48. if (!i2c_acked()) {
  49. con_printf("No RTC detected at I2C address 0x%02x\n", RTC_ADDR);
  50. i2c_send(0xff, I2C_P);
  51. return;
  52. }
  53. i2c_send(0, I2C_SR);
  54. i2c_send(RTC_RCMD, 0);
  55. for (i = 0; i < RTC_REGS-1; i++)
  56. rtc_regs[i] = i2c_recv(0);
  57. rtc_regs[i] = i2c_recv(I2C_NAK | I2C_P);
  58. /* Convert to struct tms and set systime */
  59. memset(&tms, 0, sizeof tms);
  60. unsigned int sec = unbcd(rtc_regs[0]);
  61. tms.tm_2sec = sec >> 1;
  62. tms.hold.tm_1sec = sec & 1;
  63. tms.hold.tm_tick = 0x4000; /* Without more info, assume mid-second */
  64. tms.tm_min = unbcd(rtc_regs[1]);
  65. unsigned int hour;
  66. if (rtc_regs[2] & 0x40) {
  67. /* AM/PM mode - this shouldn't happen */
  68. hour = unbcd(rtc_regs[2] & 0x1f);
  69. if (hour > 11)
  70. hour -= 12;
  71. if (rtc_regs[2] & 0x20)
  72. hour += 12;
  73. } else {
  74. /* 24-hour mode */
  75. hour = unbcd(rtc_regs[2]);
  76. }
  77. tms.tm_hour = hour;
  78. tms.tm_mday = unbcd(rtc_regs[4]);
  79. tms.tm_mon = unbcd(rtc_regs[5] & 0x1f);
  80. tms.tm_year = unbcd(rtc_regs[6]) + (rtc_regs[5] & 0x80 ? 100 : 0) + 20;
  81. set_systime(tms);
  82. con_printf("RTC register content:\n");
  83. for (i = 0; i < RTC_REGS; i++)
  84. con_printf(" %02x", rtc_regs[i]);
  85. con_printf("\nRTC time: %04u-%02u-%02u %02u:%02u:%02u\n",
  86. tms.tm_year + 1980, tms.tm_mon, tms.tm_mday,
  87. tms.tm_hour, tms.tm_min, tms_sec(tms));
  88. }