ht1380.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Holtek HT1380/HT1381 Serial Timekeeper Chip
  4. *
  5. * Communication with the chip is vendor-specific.
  6. * It is done via 3 GPIO pins: reset, clock, and data.
  7. * Describe in .dts this way:
  8. *
  9. * rtc {
  10. * compatible = "holtek,ht1380";
  11. * rst-gpios = <&gpio 19 GPIO_ACTIVE_LOW>;
  12. * clk-gpios = <&gpio 20 GPIO_ACTIVE_HIGH>;
  13. * dat-gpios = <&gpio 21 GPIO_ACTIVE_HIGH>;
  14. * };
  15. *
  16. */
  17. #include <common.h>
  18. #include <dm.h>
  19. #include <rtc.h>
  20. #include <bcd.h>
  21. #include <asm/gpio.h>
  22. #include <linux/delay.h>
  23. struct ht1380_priv {
  24. struct gpio_desc rst_desc;
  25. struct gpio_desc clk_desc;
  26. struct gpio_desc dat_desc;
  27. };
  28. enum registers {
  29. SEC,
  30. MIN,
  31. HOUR,
  32. MDAY,
  33. MONTH,
  34. WDAY,
  35. YEAR,
  36. WP,
  37. N_REGS
  38. };
  39. enum hour_mode {
  40. AMPM_MODE = 0x80, /* RTC is in AM/PM mode */
  41. PM_NOW = 0x20, /* set if PM, clear if AM */
  42. };
  43. static const int BURST = 0xbe;
  44. static const int READ = 1;
  45. static void ht1380_half_period_delay(void)
  46. {
  47. /*
  48. * Delay for half a period. 1 us complies with the 500 KHz maximum
  49. * input serial clock limit given by the datasheet.
  50. */
  51. udelay(1);
  52. }
  53. static int ht1380_send_byte(struct ht1380_priv *priv, int byte)
  54. {
  55. int ret;
  56. for (int bit = 0; bit < 8; bit++) {
  57. ret = dm_gpio_set_value(&priv->dat_desc, byte >> bit & 1);
  58. if (ret)
  59. break;
  60. ht1380_half_period_delay();
  61. ret = dm_gpio_set_value(&priv->clk_desc, 1);
  62. if (ret)
  63. break;
  64. ht1380_half_period_delay();
  65. ret = dm_gpio_set_value(&priv->clk_desc, 0);
  66. if (ret)
  67. break;
  68. }
  69. return ret;
  70. }
  71. /*
  72. * Leave reset state. The transfer operation can then be started.
  73. */
  74. static int ht1380_reset_off(struct ht1380_priv *priv)
  75. {
  76. const unsigned int T_CC = 4; /* us, Reset to Clock Setup */
  77. int ret;
  78. /*
  79. * Leave RESET state.
  80. * Make sure we make the minimal delay required by the datasheet.
  81. */
  82. ret = dm_gpio_set_value(&priv->rst_desc, 0);
  83. udelay(T_CC);
  84. return ret;
  85. }
  86. /*
  87. * Enter reset state. Completes the transfer operation.
  88. */
  89. static int ht1380_reset_on(struct ht1380_priv *priv)
  90. {
  91. const unsigned int T_CWH = 4; /* us, Reset Inactive Time */
  92. int ret;
  93. /*
  94. * Enter RESET state.
  95. * Make sure we make the minimal delay required by the datasheet.
  96. */
  97. ret = dm_gpio_set_value(&priv->rst_desc, 1);
  98. udelay(T_CWH);
  99. return ret;
  100. }
  101. static int ht1380_rtc_get(struct udevice *dev, struct rtc_time *tm)
  102. {
  103. struct ht1380_priv *priv = dev_get_priv(dev);
  104. int ret, i, bit, reg[N_REGS];
  105. ret = dm_gpio_set_value(&priv->clk_desc, 0);
  106. if (ret)
  107. return ret;
  108. ret = dm_gpio_set_dir_flags(&priv->dat_desc, GPIOD_IS_OUT);
  109. if (ret)
  110. return ret;
  111. ret = ht1380_reset_off(priv);
  112. if (ret)
  113. goto exit;
  114. ret = ht1380_send_byte(priv, BURST + READ);
  115. if (ret)
  116. goto exit;
  117. ret = dm_gpio_set_dir_flags(&priv->dat_desc, GPIOD_IS_IN);
  118. if (ret)
  119. goto exit;
  120. for (i = 0; i < N_REGS; i++) {
  121. reg[i] = 0;
  122. for (bit = 0; bit < 8; bit++) {
  123. ht1380_half_period_delay();
  124. ret = dm_gpio_set_value(&priv->clk_desc, 1);
  125. if (ret)
  126. goto exit;
  127. ht1380_half_period_delay();
  128. reg[i] |= dm_gpio_get_value(&priv->dat_desc) << bit;
  129. ret = dm_gpio_set_value(&priv->clk_desc, 0);
  130. if (ret)
  131. goto exit;
  132. }
  133. }
  134. ret = -EINVAL;
  135. /* Correctness check: some bits are always zero */
  136. if (reg[MIN] & 0x80 || reg[HOUR] & 0x40 || reg[MDAY] & 0xc0 ||
  137. reg[MONTH] & 0xe0 || reg[WDAY] & 0xf8 || reg[WP] & 0x7f)
  138. goto exit;
  139. /* Correctness check: some registers are always non-zero */
  140. if (!reg[MDAY] || !reg[MONTH] || !reg[WDAY])
  141. goto exit;
  142. tm->tm_sec = bcd2bin(reg[SEC]);
  143. tm->tm_min = bcd2bin(reg[MIN]);
  144. if (reg[HOUR] & AMPM_MODE) {
  145. /* AM-PM Mode, range is 01-12 */
  146. tm->tm_hour = bcd2bin(reg[HOUR] & 0x1f) % 12;
  147. if (reg[HOUR] & PM_NOW) {
  148. /* it is PM (otherwise AM) */
  149. tm->tm_hour += 12;
  150. }
  151. } else {
  152. /* 24-hour Mode, range is 0-23 */
  153. tm->tm_hour = bcd2bin(reg[HOUR]);
  154. }
  155. tm->tm_mday = bcd2bin(reg[MDAY]);
  156. tm->tm_mon = bcd2bin(reg[MONTH]);
  157. tm->tm_year = 2000 + bcd2bin(reg[YEAR]);
  158. tm->tm_wday = bcd2bin(reg[WDAY]) - 1;
  159. tm->tm_yday = 0;
  160. tm->tm_isdst = 0;
  161. ret = 0;
  162. exit:
  163. ht1380_reset_on(priv);
  164. return ret;
  165. }
  166. static int ht1380_write_protection_off(struct ht1380_priv *priv)
  167. {
  168. int ret;
  169. const int PROTECT = 0x8e;
  170. ret = ht1380_reset_off(priv);
  171. if (ret)
  172. return ret;
  173. ret = ht1380_send_byte(priv, PROTECT);
  174. if (ret)
  175. return ret;
  176. ret = ht1380_send_byte(priv, 0); /* WP bit is 0 */
  177. if (ret)
  178. return ret;
  179. return ht1380_reset_on(priv);
  180. }
  181. static int ht1380_rtc_set(struct udevice *dev, const struct rtc_time *tm)
  182. {
  183. struct ht1380_priv *priv = dev_get_priv(dev);
  184. int ret, i, reg[N_REGS];
  185. ret = dm_gpio_set_value(&priv->clk_desc, 0);
  186. if (ret)
  187. return ret;
  188. ret = dm_gpio_set_dir_flags(&priv->dat_desc, GPIOD_IS_OUT);
  189. if (ret)
  190. goto exit;
  191. ret = ht1380_write_protection_off(priv);
  192. if (ret)
  193. goto exit;
  194. reg[SEC] = bin2bcd(tm->tm_sec);
  195. reg[MIN] = bin2bcd(tm->tm_min);
  196. reg[HOUR] = bin2bcd(tm->tm_hour);
  197. reg[MDAY] = bin2bcd(tm->tm_mday);
  198. reg[MONTH] = bin2bcd(tm->tm_mon);
  199. reg[WDAY] = bin2bcd(tm->tm_wday) + 1;
  200. reg[YEAR] = bin2bcd(tm->tm_year - 2000);
  201. reg[WP] = 0x80; /* WP bit is 1 */
  202. ret = ht1380_reset_off(priv);
  203. if (ret)
  204. goto exit;
  205. ret = ht1380_send_byte(priv, BURST);
  206. for (i = 0; i < N_REGS && ret; i++)
  207. ret = ht1380_send_byte(priv, reg[i]);
  208. exit:
  209. ht1380_reset_on(priv);
  210. return ret;
  211. }
  212. static int ht1380_probe(struct udevice *dev)
  213. {
  214. int ret;
  215. struct ht1380_priv *priv;
  216. priv = dev_get_priv(dev);
  217. if (!priv)
  218. return -EINVAL;
  219. ret = gpio_request_by_name(dev, "rst-gpios", 0,
  220. &priv->rst_desc, GPIOD_IS_OUT);
  221. if (ret)
  222. goto fail_rst;
  223. ret = gpio_request_by_name(dev, "clk-gpios", 0,
  224. &priv->clk_desc, GPIOD_IS_OUT);
  225. if (ret)
  226. goto fail_clk;
  227. ret = gpio_request_by_name(dev, "dat-gpios", 0,
  228. &priv->dat_desc, 0);
  229. if (ret)
  230. goto fail_dat;
  231. ret = ht1380_reset_on(priv);
  232. if (ret)
  233. goto fail;
  234. return 0;
  235. fail:
  236. dm_gpio_free(dev, &priv->dat_desc);
  237. fail_dat:
  238. dm_gpio_free(dev, &priv->clk_desc);
  239. fail_clk:
  240. dm_gpio_free(dev, &priv->rst_desc);
  241. fail_rst:
  242. return ret;
  243. }
  244. static int ht1380_remove(struct udevice *dev)
  245. {
  246. struct ht1380_priv *priv = dev_get_priv(dev);
  247. dm_gpio_free(dev, &priv->rst_desc);
  248. dm_gpio_free(dev, &priv->clk_desc);
  249. dm_gpio_free(dev, &priv->dat_desc);
  250. return 0;
  251. }
  252. static const struct rtc_ops ht1380_rtc_ops = {
  253. .get = ht1380_rtc_get,
  254. .set = ht1380_rtc_set,
  255. };
  256. static const struct udevice_id ht1380_rtc_ids[] = {
  257. { .compatible = "holtek,ht1380" },
  258. { }
  259. };
  260. U_BOOT_DRIVER(rtc_ht1380) = {
  261. .name = "rtc-ht1380",
  262. .id = UCLASS_RTC,
  263. .probe = ht1380_probe,
  264. .remove = ht1380_remove,
  265. .of_match = ht1380_rtc_ids,
  266. .ops = &ht1380_rtc_ops,
  267. .priv_auto = sizeof(struct ht1380_priv),
  268. };