rtc-pcf8523.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-09-23 GuEe-GUI first version
  9. */
  10. #include "rtc_dm.h"
  11. #define DBG_TAG "rtc.pcf8523"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. #define PCF8523_REG_CONTROL1 0x00
  15. #define PCF8523_CONTROL1_CAP_SEL RT_BIT(7)
  16. #define PCF8523_CONTROL1_STOP RT_BIT(5)
  17. #define PCF8523_CONTROL1_AIE RT_BIT(1)
  18. #define PCF8523_REG_CONTROL2 0x01
  19. #define PCF8523_CONTROL2_AF RT_BIT(3)
  20. #define PCF8523_REG_CONTROL3 0x02
  21. #define PCF8523_CONTROL3_PM RT_GENMASK(7, 5)
  22. #define PCF8523_PM_STANDBY 0x7
  23. #define PCF8523_CONTROL3_BLF RT_BIT(2) /* battery low bit, read-only */
  24. #define PCF8523_CONTROL3_BSF RT_BIT(3)
  25. #define PCF8523_REG_SECONDS 0x03
  26. #define PCF8523_SECONDS_OS RT_BIT(7)
  27. #define PCF8523_REG_MINUTES 0x04
  28. #define PCF8523_REG_HOURS 0x05
  29. #define PCF8523_REG_DAYS 0x06
  30. #define PCF8523_REG_WEEKDAYS 0x07
  31. #define PCF8523_REG_MONTHS 0x08
  32. #define PCF8523_REG_YEARS 0x09
  33. #define PCF8523_REG_MINUTE_ALARM 0x0a
  34. #define PCF8523_REG_HOUR_ALARM 0x0b
  35. #define PCF8523_REG_DAY_ALARM 0x0c
  36. #define PCF8523_REG_WEEKDAY_ALARM 0x0d
  37. #define ALARM_DIS RT_BIT(7)
  38. #define PCF8523_REG_OFFSET 0x0e
  39. #define PCF8523_OFFSET_MODE RT_BIT(7)
  40. #define PCF8523_TMR_CLKOUT_CTRL 0x0f
  41. struct pcf8523_rtc
  42. {
  43. struct rt_device parent;
  44. struct rt_clk_node clkout_hw;
  45. int irq;
  46. struct rt_i2c_client *client;
  47. struct rt_thread *irq_thread;
  48. struct rt_rtc_wkalarm wkalarm;
  49. };
  50. #define raw_to_pcf8523_rtc(raw) rt_container_of(raw, struct pcf8523_rtc, parent)
  51. static rt_int32_t i2c_read_byte(struct rt_i2c_client *client,
  52. rt_uint8_t command)
  53. {
  54. rt_int32_t res;
  55. rt_uint8_t ret = 0;
  56. struct rt_i2c_msg msg[2];
  57. msg[0].buf = &command;
  58. msg[0].addr = client->client_addr;
  59. msg[0].len = 1;
  60. msg[0].flags = RT_I2C_WR;
  61. msg[1].buf = &ret;
  62. msg[1].addr = client->client_addr;
  63. msg[1].len = 1;
  64. msg[1].flags = RT_I2C_RD;
  65. res = rt_i2c_transfer(client->bus, msg, 2);
  66. return res == 2 ? ret : res;
  67. }
  68. static rt_int32_t i2c_write_byte(struct rt_i2c_client *client,
  69. rt_uint8_t command, rt_uint8_t value)
  70. {
  71. rt_int32_t res;
  72. struct rt_i2c_msg msg[1];
  73. rt_uint8_t data[2] = { command, value };
  74. msg[0].buf = data;
  75. msg[0].addr = client->client_addr;
  76. msg[0].len = 2;
  77. msg[0].flags = RT_I2C_WR;
  78. res = rt_i2c_transfer(client->bus, msg, 1);
  79. return res == 1 ? 0 : res;
  80. }
  81. static rt_int32_t i2c_update_byte_bits(struct rt_i2c_client *client,
  82. rt_uint8_t command, rt_uint8_t mask, rt_uint8_t value)
  83. {
  84. rt_int32_t res = i2c_read_byte(client, command);
  85. if (res < 0)
  86. {
  87. return res;
  88. }
  89. res &= ~mask;
  90. res |= value;
  91. return i2c_write_byte(client, command, res);
  92. }
  93. /* Returns the number of read bytes */
  94. static rt_int32_t i2c_read_block(struct rt_i2c_client *client,
  95. rt_uint8_t command, rt_uint8_t length, rt_uint8_t *values)
  96. {
  97. struct rt_i2c_msg msg[2];
  98. msg[0].buf = &command;
  99. msg[0].addr = client->client_addr;
  100. msg[0].len = 1;
  101. msg[0].flags = RT_I2C_WR;
  102. msg[1].buf = values;
  103. msg[1].addr = client->client_addr;
  104. msg[1].len = length;
  105. msg[1].flags = RT_I2C_RD;
  106. return rt_i2c_transfer(client->bus, msg, 2);
  107. }
  108. static rt_int32_t i2c_write_block(struct rt_i2c_client *client,
  109. rt_uint8_t command, rt_uint8_t length, const rt_uint8_t *values)
  110. {
  111. rt_uint8_t data[32];
  112. struct rt_i2c_msg msg[1];
  113. length = rt_min_t(rt_uint8_t, length, RT_ARRAY_SIZE(data) - 1);
  114. data[0] = command;
  115. rt_memcpy(&data[1], values, length);
  116. msg[0].buf = data;
  117. msg[0].addr = client->client_addr;
  118. msg[0].len = length + 1;
  119. msg[0].flags = RT_I2C_WR;
  120. return rt_i2c_transfer(client->bus, msg, 1);
  121. }
  122. static void pcf8523_rtc_read_time(struct pcf8523_rtc *pcf8523, time_t *sec)
  123. {
  124. rt_uint8_t regs[10];
  125. struct tm tm;
  126. struct rt_i2c_client *client = pcf8523->client;
  127. if (i2c_read_block(client, PCF8523_REG_CONTROL1, sizeof(regs), regs) < 0)
  128. {
  129. return;
  130. }
  131. if ((regs[0] & PCF8523_CONTROL1_STOP) || (regs[3] & PCF8523_SECONDS_OS))
  132. {
  133. return;
  134. }
  135. tm.tm_sec = rt_bcd2bin(regs[3] & 0x7f);
  136. tm.tm_min = rt_bcd2bin(regs[4] & 0x7f);
  137. tm.tm_hour = rt_bcd2bin(regs[5] & 0x3f);
  138. tm.tm_mday = rt_bcd2bin(regs[6] & 0x3f);
  139. tm.tm_wday = regs[7] & 0x7;
  140. tm.tm_mon = rt_bcd2bin(regs[8] & 0x1f) - 1;
  141. tm.tm_year = rt_bcd2bin(regs[9]) + 100;
  142. *sec = timegm(&tm);
  143. }
  144. static void pcf8523_rtc_set_time(struct pcf8523_rtc *pcf8523, time_t *sec)
  145. {
  146. rt_uint8_t regs[7];
  147. struct tm *tm;
  148. struct rt_i2c_client *client = pcf8523->client;
  149. if (i2c_update_byte_bits(client, PCF8523_REG_CONTROL1,
  150. PCF8523_CONTROL1_STOP, PCF8523_CONTROL1_STOP) < 0)
  151. {
  152. return;
  153. }
  154. tm = localtime(sec);
  155. regs[0] = rt_bin2bcd(tm->tm_sec);
  156. regs[1] = rt_bin2bcd(tm->tm_min);
  157. regs[2] = rt_bin2bcd(tm->tm_hour);
  158. regs[3] = rt_bin2bcd(tm->tm_mday);
  159. regs[4] = 0;
  160. regs[5] = rt_bin2bcd(tm->tm_mon + 1);
  161. regs[6] = rt_bin2bcd(tm->tm_year - 100);
  162. if (i2c_write_block(client, PCF8523_REG_SECONDS, sizeof(regs), regs) < 0)
  163. {
  164. i2c_update_byte_bits(client, PCF8523_REG_CONTROL1, PCF8523_CONTROL1_STOP, 0);
  165. return;
  166. }
  167. i2c_update_byte_bits(client, PCF8523_REG_CONTROL1, PCF8523_CONTROL1_STOP, 0);
  168. }
  169. static int pcf8523_rtc_alarm_irq_enable(struct pcf8523_rtc *pcf8523, rt_bool_t enabled)
  170. {
  171. struct rt_i2c_client *client = pcf8523->client;
  172. return i2c_update_byte_bits(client, PCF8523_REG_CONTROL1,
  173. PCF8523_CONTROL1_AIE, enabled ? PCF8523_CONTROL1_AIE : 0);
  174. }
  175. static int pcf8523_rtc_read_alarm(struct pcf8523_rtc *pcf8523,
  176. struct rt_rtc_wkalarm *alarm)
  177. {
  178. int res;
  179. rt_uint8_t regs[4];
  180. struct rt_i2c_client *client = pcf8523->client;
  181. if ((res = i2c_read_block(client, PCF8523_REG_MINUTE_ALARM, sizeof(regs), regs)))
  182. {
  183. return res;
  184. }
  185. alarm->tm_sec = 0;
  186. alarm->tm_min = rt_bcd2bin(regs[0] & 0x7F);
  187. alarm->tm_hour = rt_bcd2bin(regs[1] & 0x3F);
  188. alarm->tm_mday = rt_bcd2bin(regs[2] & 0x3F);
  189. /* alarm->tm_wday = rt_bcd2bin(regs[3] & 0x7); */
  190. if ((res = i2c_read_byte(client, PCF8523_REG_CONTROL1)) < 0)
  191. {
  192. return res;
  193. }
  194. alarm->enable = !!(res & PCF8523_CONTROL1_AIE);
  195. return RT_EOK;
  196. }
  197. static int pcf8523_rtc_set_alarm(struct pcf8523_rtc *pcf8523,
  198. struct rt_rtc_wkalarm *alarm)
  199. {
  200. int res;
  201. rt_uint8_t regs[5];
  202. struct rt_i2c_client *client = pcf8523->client;
  203. struct rt_rtc_wkalarm *wkalarm = &pcf8523->wkalarm;
  204. if ((res = pcf8523_rtc_alarm_irq_enable(pcf8523, RT_FALSE)) < 0)
  205. {
  206. return res;
  207. }
  208. if ((res = i2c_write_byte(client, PCF8523_REG_CONTROL2, 0)) < 0)
  209. {
  210. return res;
  211. }
  212. regs[0] = rt_bin2bcd(alarm->tm_min);
  213. regs[1] = rt_bin2bcd(alarm->tm_hour);
  214. regs[2] = rt_bin2bcd(alarm->tm_mday);
  215. regs[3] = ALARM_DIS;
  216. if ((res = i2c_write_block(client, PCF8523_REG_MINUTE_ALARM, sizeof(regs), regs)))
  217. {
  218. return res;
  219. }
  220. res = pcf8523_rtc_alarm_irq_enable(pcf8523, alarm->enable);
  221. if (!(res < 0))
  222. {
  223. wkalarm->enable = alarm->enable;
  224. wkalarm->tm_hour = alarm->tm_hour;
  225. wkalarm->tm_min = alarm->tm_min;
  226. wkalarm->tm_sec = alarm->tm_sec;
  227. }
  228. return res;
  229. }
  230. static rt_err_t pcf8523_rtc_control(rt_device_t dev, int cmd, void *args)
  231. {
  232. rt_err_t err = RT_EOK;
  233. struct pcf8523_rtc *pcf8523 = raw_to_pcf8523_rtc(dev);
  234. if (!args)
  235. {
  236. return -RT_EINVAL;
  237. }
  238. switch (cmd)
  239. {
  240. case RT_DEVICE_CTRL_RTC_GET_TIME:
  241. pcf8523_rtc_read_time(pcf8523, args);
  242. break;
  243. case RT_DEVICE_CTRL_RTC_SET_TIME:
  244. pcf8523_rtc_set_time(pcf8523, args);
  245. break;
  246. case RT_DEVICE_CTRL_RTC_GET_TIMEVAL:
  247. pcf8523_rtc_read_time(pcf8523, (time_t *)&((struct timeval *)args)->tv_sec);
  248. break;
  249. case RT_DEVICE_CTRL_RTC_SET_TIMEVAL:
  250. pcf8523_rtc_set_time(pcf8523, (time_t *)&((struct timeval *)args)->tv_sec);
  251. break;
  252. case RT_DEVICE_CTRL_RTC_GET_ALARM:
  253. err = pcf8523_rtc_read_alarm(pcf8523, args);
  254. break;
  255. case RT_DEVICE_CTRL_RTC_SET_ALARM:
  256. err = pcf8523_rtc_set_alarm(pcf8523, args);
  257. break;
  258. default:
  259. err = -RT_EINVAL;
  260. break;
  261. }
  262. return err;
  263. }
  264. #ifdef RT_USING_DEVICE_OPS
  265. const static struct rt_device_ops pcf8523_rtc_ops =
  266. {
  267. .control = pcf8523_rtc_control,
  268. };
  269. #endif
  270. static void pcf8523_rtc_thread_isr(void *param)
  271. {
  272. rt_int32_t res;
  273. struct pcf8523_rtc *pcf8523 = param;
  274. struct rt_i2c_client *client = pcf8523->client;
  275. while (RT_TRUE)
  276. {
  277. rt_thread_suspend(pcf8523->irq_thread);
  278. rt_schedule();
  279. if ((res = i2c_read_byte(client, PCF8523_REG_CONTROL2)) < 0)
  280. {
  281. continue;
  282. }
  283. if (res & PCF8523_CONTROL2_AF)
  284. {
  285. res &= ~PCF8523_CONTROL2_AF;
  286. i2c_write_byte(client, PCF8523_REG_CONTROL2, res);
  287. rt_alarm_update(&pcf8523->parent, 1);
  288. }
  289. }
  290. }
  291. static void pcf8523_rtc_isr(int irqno, void *param)
  292. {
  293. struct pcf8523_rtc *pcf8523 = param;
  294. rt_thread_resume(pcf8523->irq_thread);
  295. }
  296. static rt_err_t pcf8523_rtc_probe(struct rt_i2c_client *client)
  297. {
  298. rt_err_t err;
  299. rt_int32_t res;
  300. const char *dev_name;
  301. struct rt_device *dev = &client->parent;
  302. struct pcf8523_rtc *pcf8523 = rt_calloc(1, sizeof(*pcf8523));
  303. if (!pcf8523)
  304. {
  305. return -RT_ENOMEM;
  306. }
  307. pcf8523->irq = rt_dm_dev_get_irq(dev, 0);
  308. pcf8523->client = client;
  309. #ifdef RT_USING_OFW
  310. if (dev->ofw_node)
  311. {
  312. rt_uint32_t load = 12500, value = 0;
  313. rt_ofw_prop_read_u32(dev->ofw_node, "quartz-load-femtofarads", &load);
  314. if (load != 7000)
  315. {
  316. value = PCF8523_CONTROL1_CAP_SEL;
  317. }
  318. if ((res = i2c_update_byte_bits(client, PCF8523_REG_CONTROL1,
  319. PCF8523_CONTROL1_CAP_SEL, value)) < 0)
  320. {
  321. err = res;
  322. goto _fail;
  323. }
  324. }
  325. #endif /* RT_USING_OFW */
  326. if ((res = i2c_read_byte(client, PCF8523_REG_SECONDS)) < 0)
  327. {
  328. err = res;
  329. goto _fail;
  330. }
  331. if (res & PCF8523_SECONDS_OS)
  332. {
  333. if ((res = i2c_read_byte(client, PCF8523_REG_CONTROL3)) < 0)
  334. {
  335. err = res;
  336. goto _fail;
  337. }
  338. if (RT_FIELD_GET(PCF8523_CONTROL3_PM, res) == PCF8523_PM_STANDBY)
  339. {
  340. res &= ~PCF8523_CONTROL3_PM;
  341. if ((res = i2c_write_byte(client, PCF8523_REG_CONTROL3, res)) < 0)
  342. {
  343. err = res;
  344. goto _fail;
  345. }
  346. }
  347. }
  348. if (pcf8523->irq >= 0)
  349. {
  350. if ((res = i2c_write_byte(client, PCF8523_TMR_CLKOUT_CTRL, 0x38)) < 0)
  351. {
  352. err = res;
  353. goto _fail;
  354. }
  355. pcf8523->irq_thread = rt_thread_create("rtc-pcf8523", &pcf8523_rtc_thread_isr,
  356. pcf8523, DM_THREAD_STACK_SIZE, RT_THREAD_PRIORITY_MAX / 2, 10);
  357. if (!pcf8523->irq_thread)
  358. {
  359. err = -RT_ERROR;
  360. LOG_E("Create RTC IRQ thread fail");
  361. goto _fail;
  362. }
  363. rt_thread_startup(pcf8523->irq_thread);
  364. rt_hw_interrupt_install(pcf8523->irq, pcf8523_rtc_isr, pcf8523, "rtc-pcf8523");
  365. rt_hw_interrupt_umask(pcf8523->irq);
  366. }
  367. dev->user_data = pcf8523;
  368. pcf8523->parent.type = RT_Device_Class_RTC;
  369. #ifdef RT_USING_DEVICE_OPS
  370. pcf8523->parent.ops = &pcf8523_rtc_ops;
  371. #else
  372. pcf8523->parent.control = pcf8523_rtc_control;
  373. #endif
  374. rtc_dev_set_name(&pcf8523->parent);
  375. dev_name = rt_dm_dev_get_name(&pcf8523->parent);
  376. rt_device_register(&pcf8523->parent, dev_name, RT_DEVICE_FLAG_RDWR);
  377. return RT_EOK;
  378. _fail:
  379. if (pcf8523->irq_thread)
  380. {
  381. rt_thread_delete(pcf8523->irq_thread);
  382. }
  383. rt_free(pcf8523);
  384. return err;
  385. }
  386. static rt_err_t pcf8523_rtc_remove(struct rt_i2c_client *client)
  387. {
  388. struct pcf8523_rtc *pcf8523 = client->parent.user_data;
  389. rt_dm_dev_unbind_fwdata(&client->parent, RT_NULL);
  390. if (pcf8523->irq >= 0)
  391. {
  392. if (pcf8523->wkalarm.enable)
  393. {
  394. pcf8523_rtc_alarm_irq_enable(pcf8523, RT_FALSE);
  395. }
  396. rt_hw_interrupt_mask(pcf8523->irq);
  397. rt_pic_detach_irq(pcf8523->irq, pcf8523);
  398. rt_thread_delete(pcf8523->irq_thread);
  399. }
  400. rt_device_unregister(&pcf8523->parent);
  401. rt_free(pcf8523);
  402. return RT_EOK;
  403. }
  404. static const struct rt_i2c_device_id pcf8523_rtc_ids[] =
  405. {
  406. { .name = "pcf8523" },
  407. { /* sentinel */ },
  408. };
  409. static const struct rt_ofw_node_id pcf8523_rtc_ofw_ids[] =
  410. {
  411. { .compatible = "nxp,pcf8523" },
  412. { .compatible = "microcrystal,rv8523" },
  413. { /* sentinel */ },
  414. };
  415. static struct rt_i2c_driver pcf8523_rtc_driver =
  416. {
  417. .ids = pcf8523_rtc_ids,
  418. .ofw_ids = pcf8523_rtc_ofw_ids,
  419. .probe = pcf8523_rtc_probe,
  420. .remove = pcf8523_rtc_remove,
  421. };
  422. RT_I2C_DRIVER_EXPORT(pcf8523_rtc_driver);