m41t62.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2018
  4. * Lukasz Majewski, DENX Software Engineering, lukma@denx.de.
  5. *
  6. * (C) Copyright 2008
  7. * Stefan Roese, DENX Software Engineering, sr@denx.de.
  8. *
  9. * based on a the Linux rtc-m41t80.c driver which is:
  10. * Alexander Bigga <ab@mycable.de>, 2006 (c) mycable GmbH
  11. */
  12. /*
  13. * Date & Time support for STMicroelectronics M41T62
  14. */
  15. /* #define DEBUG */
  16. #include <common.h>
  17. #include <command.h>
  18. #include <dm.h>
  19. #include <log.h>
  20. #include <rtc.h>
  21. #include <i2c.h>
  22. #include <linux/log2.h>
  23. #include <linux/delay.h>
  24. #define M41T62_REG_SSEC 0
  25. #define M41T62_REG_SEC 1
  26. #define M41T62_REG_MIN 2
  27. #define M41T62_REG_HOUR 3
  28. #define M41T62_REG_WDAY 4
  29. #define M41T62_REG_DAY 5
  30. #define M41T62_REG_MON 6
  31. #define M41T62_REG_YEAR 7
  32. #define M41T62_REG_ALARM_MON 0xa
  33. #define M41T62_REG_ALARM_DAY 0xb
  34. #define M41T62_REG_ALARM_HOUR 0xc
  35. #define M41T62_REG_ALARM_MIN 0xd
  36. #define M41T62_REG_ALARM_SEC 0xe
  37. #define M41T62_REG_FLAGS 0xf
  38. #define M41T62_DATETIME_REG_SIZE (M41T62_REG_YEAR + 1)
  39. #define M41T62_ALARM_REG_SIZE \
  40. (M41T62_REG_ALARM_SEC + 1 - M41T62_REG_ALARM_MON)
  41. #define M41T62_SEC_ST (1 << 7) /* ST: Stop Bit */
  42. #define M41T62_ALMON_AFE (1 << 7) /* AFE: AF Enable Bit */
  43. #define M41T62_ALMON_SQWE (1 << 6) /* SQWE: SQW Enable Bit */
  44. #define M41T62_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */
  45. #define M41T62_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */
  46. #define M41T62_FLAGS_OF (1 << 2) /* OF: Oscillator Flag Bit */
  47. #define M41T62_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */
  48. #define M41T62_WDAY_SQW_FREQ_MASK 0xf0
  49. #define M41T62_WDAY_SQW_FREQ_SHIFT 4
  50. #define M41T62_SQW_MAX_FREQ 32768
  51. #define M41T62_FEATURE_HT (1 << 0)
  52. #define M41T62_FEATURE_BL (1 << 1)
  53. #define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */
  54. static void m41t62_update_rtc_time(struct rtc_time *tm, u8 *buf)
  55. {
  56. debug("%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
  57. "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
  58. __FUNCTION__,
  59. buf[0], buf[1], buf[2], buf[3],
  60. buf[4], buf[5], buf[6], buf[7]);
  61. tm->tm_sec = bcd2bin(buf[M41T62_REG_SEC] & 0x7f);
  62. tm->tm_min = bcd2bin(buf[M41T62_REG_MIN] & 0x7f);
  63. tm->tm_hour = bcd2bin(buf[M41T62_REG_HOUR] & 0x3f);
  64. tm->tm_mday = bcd2bin(buf[M41T62_REG_DAY] & 0x3f);
  65. tm->tm_wday = buf[M41T62_REG_WDAY] & 0x07;
  66. tm->tm_mon = bcd2bin(buf[M41T62_REG_MON] & 0x1f);
  67. /* assume 20YY not 19YY, and ignore the Century Bit */
  68. /* U-Boot needs to add 1900 here */
  69. tm->tm_year = bcd2bin(buf[M41T62_REG_YEAR]) + 100 + 1900;
  70. debug("%s: tm is secs=%d, mins=%d, hours=%d, "
  71. "mday=%d, mon=%d, year=%d, wday=%d\n",
  72. __FUNCTION__,
  73. tm->tm_sec, tm->tm_min, tm->tm_hour,
  74. tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
  75. }
  76. static void m41t62_set_rtc_buf(const struct rtc_time *tm, u8 *buf)
  77. {
  78. debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
  79. tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
  80. tm->tm_hour, tm->tm_min, tm->tm_sec);
  81. /* Merge time-data and register flags into buf[0..7] */
  82. buf[M41T62_REG_SSEC] = 0;
  83. buf[M41T62_REG_SEC] =
  84. bin2bcd(tm->tm_sec) | (buf[M41T62_REG_SEC] & ~0x7f);
  85. buf[M41T62_REG_MIN] =
  86. bin2bcd(tm->tm_min) | (buf[M41T62_REG_MIN] & ~0x7f);
  87. buf[M41T62_REG_HOUR] =
  88. bin2bcd(tm->tm_hour) | (buf[M41T62_REG_HOUR] & ~0x3f) ;
  89. buf[M41T62_REG_WDAY] =
  90. (tm->tm_wday & 0x07) | (buf[M41T62_REG_WDAY] & ~0x07);
  91. buf[M41T62_REG_DAY] =
  92. bin2bcd(tm->tm_mday) | (buf[M41T62_REG_DAY] & ~0x3f);
  93. buf[M41T62_REG_MON] =
  94. bin2bcd(tm->tm_mon) | (buf[M41T62_REG_MON] & ~0x1f);
  95. /* assume 20YY not 19YY */
  96. buf[M41T62_REG_YEAR] = bin2bcd(tm->tm_year % 100);
  97. }
  98. #ifdef CONFIG_DM_RTC
  99. static int m41t62_rtc_get(struct udevice *dev, struct rtc_time *tm)
  100. {
  101. u8 buf[M41T62_DATETIME_REG_SIZE];
  102. int ret;
  103. ret = dm_i2c_read(dev, 0, buf, sizeof(buf));
  104. if (ret)
  105. return ret;
  106. m41t62_update_rtc_time(tm, buf);
  107. return 0;
  108. }
  109. static int m41t62_rtc_set(struct udevice *dev, const struct rtc_time *tm)
  110. {
  111. u8 buf[M41T62_DATETIME_REG_SIZE];
  112. int ret;
  113. ret = dm_i2c_read(dev, 0, buf, sizeof(buf));
  114. if (ret)
  115. return ret;
  116. m41t62_set_rtc_buf(tm, buf);
  117. ret = dm_i2c_write(dev, 0, buf, sizeof(buf));
  118. if (ret) {
  119. printf("I2C write failed in %s()\n", __func__);
  120. return ret;
  121. }
  122. return 0;
  123. }
  124. static int m41t62_sqw_enable(struct udevice *dev, bool enable)
  125. {
  126. u8 val;
  127. int ret;
  128. ret = dm_i2c_read(dev, M41T62_REG_ALARM_MON, &val, sizeof(val));
  129. if (ret)
  130. return ret;
  131. if (enable)
  132. val |= M41T62_ALMON_SQWE;
  133. else
  134. val &= ~M41T62_ALMON_SQWE;
  135. return dm_i2c_write(dev, M41T62_REG_ALARM_MON, &val, sizeof(val));
  136. }
  137. static int m41t62_sqw_set_rate(struct udevice *dev, unsigned int rate)
  138. {
  139. u8 val, newval, sqwrateval;
  140. int ret;
  141. if (rate >= M41T62_SQW_MAX_FREQ)
  142. sqwrateval = 1;
  143. else if (rate >= M41T62_SQW_MAX_FREQ / 4)
  144. sqwrateval = 2;
  145. else if (rate)
  146. sqwrateval = 15 - ilog2(rate);
  147. ret = dm_i2c_read(dev, M41T62_REG_WDAY, &val, sizeof(val));
  148. if (ret)
  149. return ret;
  150. newval = val;
  151. newval &= ~M41T62_WDAY_SQW_FREQ_MASK;
  152. newval |= (sqwrateval << M41T62_WDAY_SQW_FREQ_SHIFT);
  153. /*
  154. * Try to avoid writing unchanged values. Writing to this register
  155. * will reset the internal counter pipeline and thus affect system
  156. * time.
  157. */
  158. if (newval == val)
  159. return 0;
  160. return dm_i2c_write(dev, M41T62_REG_WDAY, &newval, sizeof(newval));
  161. }
  162. static int m41t62_rtc_restart_osc(struct udevice *dev)
  163. {
  164. u8 val;
  165. int ret;
  166. /* 0. check if oscillator failure happened */
  167. ret = dm_i2c_read(dev, M41T62_REG_FLAGS, &val, sizeof(val));
  168. if (ret)
  169. return ret;
  170. if (!(val & M41T62_FLAGS_OF))
  171. return 0;
  172. ret = dm_i2c_read(dev, M41T62_REG_SEC, &val, sizeof(val));
  173. if (ret)
  174. return ret;
  175. /* 1. Set stop bit */
  176. val |= M41T62_SEC_ST;
  177. ret = dm_i2c_write(dev, M41T62_REG_SEC, &val, sizeof(val));
  178. if (ret)
  179. return ret;
  180. /* 2. Clear stop bit */
  181. val &= ~M41T62_SEC_ST;
  182. ret = dm_i2c_write(dev, M41T62_REG_SEC, &val, sizeof(val));
  183. if (ret)
  184. return ret;
  185. /* 3. wait 4 seconds */
  186. mdelay(4000);
  187. ret = dm_i2c_read(dev, M41T62_REG_FLAGS, &val, sizeof(val));
  188. if (ret)
  189. return ret;
  190. /* 4. clear M41T62_FLAGS_OF bit */
  191. val &= ~M41T62_FLAGS_OF;
  192. ret = dm_i2c_write(dev, M41T62_REG_FLAGS, &val, sizeof(val));
  193. if (ret)
  194. return ret;
  195. return 0;
  196. }
  197. static int m41t62_rtc_clear_ht(struct udevice *dev)
  198. {
  199. u8 val;
  200. int ret;
  201. /*
  202. * M41T82: Make sure HT (Halt Update) bit is cleared.
  203. * This bit is 0 in M41T62 so its save to clear it always.
  204. */
  205. ret = dm_i2c_read(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val));
  206. if (ret)
  207. return ret;
  208. val &= ~M41T80_ALHOUR_HT;
  209. ret = dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val));
  210. if (ret)
  211. return ret;
  212. return 0;
  213. }
  214. static int m41t62_rtc_reset(struct udevice *dev)
  215. {
  216. int ret;
  217. ret = m41t62_rtc_restart_osc(dev);
  218. if (ret)
  219. return ret;
  220. ret = m41t62_rtc_clear_ht(dev);
  221. if (ret)
  222. return ret;
  223. /*
  224. * Some boards feed the square wave as clock input into
  225. * the SoC. This enables a 32.768kHz square wave, which is
  226. * also the hardware default after power-loss.
  227. */
  228. ret = m41t62_sqw_set_rate(dev, 32768);
  229. if (ret)
  230. return ret;
  231. return m41t62_sqw_enable(dev, true);
  232. }
  233. static int m41t62_rtc_read8(struct udevice *dev, unsigned int reg)
  234. {
  235. return dm_i2c_reg_read(dev, reg);
  236. }
  237. static int m41t62_rtc_write8(struct udevice *dev, unsigned int reg, int val)
  238. {
  239. return dm_i2c_reg_write(dev, reg, val);
  240. }
  241. /*
  242. * Make sure HT bit is cleared. This bit is set on entering battery backup
  243. * mode, so do this before the first read access.
  244. */
  245. static int m41t62_rtc_probe(struct udevice *dev)
  246. {
  247. return m41t62_rtc_clear_ht(dev);
  248. }
  249. static const struct rtc_ops m41t62_rtc_ops = {
  250. .get = m41t62_rtc_get,
  251. .set = m41t62_rtc_set,
  252. .reset = m41t62_rtc_reset,
  253. .read8 = m41t62_rtc_read8,
  254. .write8 = m41t62_rtc_write8,
  255. };
  256. static const struct udevice_id m41t62_rtc_ids[] = {
  257. { .compatible = "st,m41t62" },
  258. { .compatible = "st,m41t82" },
  259. { .compatible = "st,m41st87" },
  260. { .compatible = "microcrystal,rv4162" },
  261. { }
  262. };
  263. U_BOOT_DRIVER(rtc_m41t62) = {
  264. .name = "rtc-m41t62",
  265. .id = UCLASS_RTC,
  266. .of_match = m41t62_rtc_ids,
  267. .ops = &m41t62_rtc_ops,
  268. .probe = &m41t62_rtc_probe,
  269. };
  270. #else /* NON DM RTC code - will be removed */
  271. int rtc_get(struct rtc_time *tm)
  272. {
  273. u8 buf[M41T62_DATETIME_REG_SIZE];
  274. i2c_read(CFG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE);
  275. m41t62_update_rtc_time(tm, buf);
  276. return 0;
  277. }
  278. int rtc_set(struct rtc_time *tm)
  279. {
  280. u8 buf[M41T62_DATETIME_REG_SIZE];
  281. i2c_read(CFG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE);
  282. m41t62_set_rtc_buf(tm, buf);
  283. if (i2c_write(CFG_SYS_I2C_RTC_ADDR, 0, 1, buf,
  284. M41T62_DATETIME_REG_SIZE)) {
  285. printf("I2C write failed in %s()\n", __func__);
  286. return -1;
  287. }
  288. return 0;
  289. }
  290. void rtc_reset(void)
  291. {
  292. u8 val;
  293. /*
  294. * M41T82: Make sure HT (Halt Update) bit is cleared.
  295. * This bit is 0 in M41T62 so its save to clear it always.
  296. */
  297. i2c_read(CFG_SYS_I2C_RTC_ADDR, M41T62_REG_ALARM_HOUR, 1, &val, 1);
  298. val &= ~M41T80_ALHOUR_HT;
  299. i2c_write(CFG_SYS_I2C_RTC_ADDR, M41T62_REG_ALARM_HOUR, 1, &val, 1);
  300. }
  301. #endif /* CONFIG_DM_RTC */