ds3232.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2019, Vaisala Oyj
  4. */
  5. #include <common.h>
  6. #include <command.h>
  7. #include <dm.h>
  8. #include <i2c.h>
  9. #include <rtc.h>
  10. #include <dm/device_compat.h>
  11. #include <linux/bitops.h>
  12. /*
  13. * RTC register addresses
  14. */
  15. #define RTC_SEC_REG_ADDR 0x00
  16. #define RTC_MIN_REG_ADDR 0x01
  17. #define RTC_HR_REG_ADDR 0x02
  18. #define RTC_DAY_REG_ADDR 0x03
  19. #define RTC_DATE_REG_ADDR 0x04
  20. #define RTC_MON_REG_ADDR 0x05
  21. #define RTC_YR_REG_ADDR 0x06
  22. #define RTC_CTL_REG_ADDR 0x0e
  23. #define RTC_STAT_REG_ADDR 0x0f
  24. #define RTC_TEST_REG_ADDR 0x13
  25. /*
  26. * RTC control register bits
  27. */
  28. #define RTC_CTL_BIT_A1IE BIT(0) /* Alarm 1 interrupt enable */
  29. #define RTC_CTL_BIT_A2IE BIT(1) /* Alarm 2 interrupt enable */
  30. #define RTC_CTL_BIT_INTCN BIT(2) /* Interrupt control */
  31. #define RTC_CTL_BIT_DOSC BIT(7) /* Disable Oscillator */
  32. /*
  33. * RTC status register bits
  34. */
  35. #define RTC_STAT_BIT_A1F BIT(0) /* Alarm 1 flag */
  36. #define RTC_STAT_BIT_A2F BIT(1) /* Alarm 2 flag */
  37. #define RTC_STAT_BIT_EN32KHZ BIT(3) /* Enable 32KHz Output */
  38. #define RTC_STAT_BIT_BB32KHZ BIT(6) /* Battery backed 32KHz Output */
  39. #define RTC_STAT_BIT_OSF BIT(7) /* Oscillator stop flag */
  40. /*
  41. * RTC test register bits
  42. */
  43. #define RTC_TEST_BIT_SWRST BIT(7) /* Software reset */
  44. #define RTC_DATE_TIME_REG_SIZE 7
  45. #define RTC_SRAM_START 0x14
  46. #define RTC_SRAM_END 0xFF
  47. #define RTC_SRAM_SIZE 236
  48. struct ds3232_priv_data {
  49. u8 max_register;
  50. u8 sram_start;
  51. int sram_size;
  52. };
  53. static int ds3232_rtc_read8(struct udevice *dev, unsigned int reg)
  54. {
  55. int ret;
  56. u8 buf;
  57. struct ds3232_priv_data *priv_data;
  58. priv_data = dev_get_priv(dev);
  59. if (!priv_data)
  60. return -EINVAL;
  61. if (reg > priv_data->max_register)
  62. return -EINVAL;
  63. ret = dm_i2c_read(dev, reg, &buf, sizeof(buf));
  64. if (ret < 0)
  65. return ret;
  66. return buf;
  67. }
  68. static int ds3232_rtc_write8(struct udevice *dev, unsigned int reg, int val)
  69. {
  70. u8 buf = (u8)val;
  71. struct ds3232_priv_data *priv_data;
  72. priv_data = dev_get_priv(dev);
  73. if (!priv_data)
  74. return -EINVAL;
  75. if (reg > priv_data->max_register)
  76. return -EINVAL;
  77. return dm_i2c_write(dev, reg, &buf, sizeof(buf));
  78. }
  79. static int reset_sram(struct udevice *dev)
  80. {
  81. int ret, sram_end, reg;
  82. struct ds3232_priv_data *priv_data;
  83. priv_data = dev_get_priv(dev);
  84. if (!priv_data)
  85. return -EINVAL;
  86. sram_end = priv_data->sram_start + priv_data->sram_size;
  87. for (reg = priv_data->sram_start; reg < sram_end; reg++) {
  88. ret = ds3232_rtc_write8(dev, reg, 0x00);
  89. if (ret < 0)
  90. return ret;
  91. }
  92. return 0;
  93. }
  94. static int verify_osc(struct udevice *dev)
  95. {
  96. int ret, rtc_status;
  97. ret = ds3232_rtc_read8(dev, RTC_STAT_REG_ADDR);
  98. if (ret < 0)
  99. return ret;
  100. rtc_status = ret;
  101. if (rtc_status & RTC_STAT_BIT_OSF) {
  102. dev_warn(dev,
  103. "oscillator discontinuity flagged, time unreliable\n");
  104. /*
  105. * In case OSC was off we cannot trust the SRAM data anymore.
  106. * Reset it to 0x00.
  107. */
  108. ret = reset_sram(dev);
  109. if (ret < 0)
  110. return ret;
  111. }
  112. return 0;
  113. }
  114. static int ds3232_rtc_set(struct udevice *dev, const struct rtc_time *tm)
  115. {
  116. u8 buf[RTC_DATE_TIME_REG_SIZE];
  117. u8 is_century;
  118. if (tm->tm_year < 1900 || tm->tm_year > 2099)
  119. dev_warn(dev, "WARNING: year should be between 1900 and 2099!\n");
  120. is_century = (tm->tm_year >= 2000) ? 0x80 : 0;
  121. buf[RTC_SEC_REG_ADDR] = bin2bcd(tm->tm_sec);
  122. buf[RTC_MIN_REG_ADDR] = bin2bcd(tm->tm_min);
  123. buf[RTC_HR_REG_ADDR] = bin2bcd(tm->tm_hour);
  124. buf[RTC_DAY_REG_ADDR] = bin2bcd(tm->tm_wday + 1);
  125. buf[RTC_DATE_REG_ADDR] = bin2bcd(tm->tm_mday);
  126. buf[RTC_MON_REG_ADDR] = bin2bcd(tm->tm_mon) | is_century;
  127. buf[RTC_YR_REG_ADDR] = bin2bcd(tm->tm_year % 100);
  128. return dm_i2c_write(dev, 0, buf, sizeof(buf));
  129. }
  130. static int ds3232_rtc_get(struct udevice *dev, struct rtc_time *tm)
  131. {
  132. int ret;
  133. u8 buf[RTC_DATE_TIME_REG_SIZE];
  134. u8 is_twelve_hr;
  135. u8 is_pm;
  136. u8 is_century;
  137. ret = verify_osc(dev);
  138. if (ret < 0)
  139. return ret;
  140. ret = dm_i2c_read(dev, 0, buf, sizeof(buf));
  141. if (ret < 0)
  142. return ret;
  143. /* Extract additional information for AM/PM and century */
  144. is_twelve_hr = buf[RTC_HR_REG_ADDR] & 0x40;
  145. is_pm = buf[RTC_HR_REG_ADDR] & 0x20;
  146. is_century = buf[RTC_MON_REG_ADDR] & 0x80;
  147. tm->tm_sec = bcd2bin(buf[RTC_SEC_REG_ADDR] & 0x7F);
  148. tm->tm_min = bcd2bin(buf[RTC_MIN_REG_ADDR] & 0x7F);
  149. if (is_twelve_hr)
  150. tm->tm_hour = bcd2bin(buf[RTC_HR_REG_ADDR] & 0x1F)
  151. + (is_pm ? 12 : 0);
  152. else
  153. tm->tm_hour = bcd2bin(buf[RTC_HR_REG_ADDR]);
  154. tm->tm_wday = bcd2bin((buf[RTC_DAY_REG_ADDR] & 0x07) - 1);
  155. tm->tm_mday = bcd2bin(buf[RTC_DATE_REG_ADDR] & 0x3F);
  156. tm->tm_mon = bcd2bin((buf[RTC_MON_REG_ADDR] & 0x7F));
  157. tm->tm_year = bcd2bin(buf[RTC_YR_REG_ADDR])
  158. + (is_century ? 2000 : 1900);
  159. tm->tm_yday = 0;
  160. tm->tm_isdst = 0;
  161. return 0;
  162. }
  163. static int ds3232_rtc_reset(struct udevice *dev)
  164. {
  165. int ret;
  166. ret = reset_sram(dev);
  167. if (ret < 0)
  168. return ret;
  169. /*
  170. * From datasheet
  171. * (https://datasheets.maximintegrated.com/en/ds/DS3232M.pdf):
  172. *
  173. * The device reset occurs during the normal acknowledge time slot
  174. * following the receipt of the data byte carrying that
  175. * SWRST instruction a NACK occurs due to the resetting action.
  176. *
  177. * Therefore we don't verify the result of I2C write operation since it
  178. * will fail due the NACK.
  179. */
  180. ds3232_rtc_write8(dev, RTC_TEST_REG_ADDR, RTC_TEST_BIT_SWRST);
  181. return 0;
  182. }
  183. static int ds3232_probe(struct udevice *dev)
  184. {
  185. int rtc_status;
  186. int ret;
  187. struct ds3232_priv_data *priv_data;
  188. priv_data = dev_get_priv(dev);
  189. if (!priv_data)
  190. return -EINVAL;
  191. priv_data->sram_start = RTC_SRAM_START;
  192. priv_data->max_register = RTC_SRAM_END;
  193. priv_data->sram_size = RTC_SRAM_SIZE;
  194. ret = ds3232_rtc_read8(dev, RTC_STAT_REG_ADDR);
  195. if (ret < 0)
  196. return ret;
  197. rtc_status = ret;
  198. ret = verify_osc(dev);
  199. if (ret < 0)
  200. return ret;
  201. rtc_status &= ~(RTC_STAT_BIT_OSF | RTC_STAT_BIT_A1F | RTC_STAT_BIT_A2F);
  202. return ds3232_rtc_write8(dev, RTC_STAT_REG_ADDR, rtc_status);
  203. }
  204. static const struct rtc_ops ds3232_rtc_ops = {
  205. .get = ds3232_rtc_get,
  206. .set = ds3232_rtc_set,
  207. .reset = ds3232_rtc_reset,
  208. .read8 = ds3232_rtc_read8,
  209. .write8 = ds3232_rtc_write8
  210. };
  211. static const struct udevice_id ds3232_rtc_ids[] = {
  212. { .compatible = "dallas,ds3232" },
  213. { }
  214. };
  215. U_BOOT_DRIVER(rtc_ds3232) = {
  216. .name = "rtc-ds3232",
  217. .id = UCLASS_RTC,
  218. .probe = ds3232_probe,
  219. .of_match = ds3232_rtc_ids,
  220. .ops = &ds3232_rtc_ops,
  221. .priv_auto_alloc_size = sizeof(struct ds3232_priv_data),
  222. };