rtc-rx8010.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  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. * 2022-11-26 GuEe-GUI first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #define DBG_TAG "rtc.rx8010"
  13. #define DBG_LVL DBG_INFO
  14. #include <rtdbg.h>
  15. #include "rtc_dm.h"
  16. #define RX8010_SEC 0x10
  17. #define RX8010_MIN 0x11
  18. #define RX8010_HOUR 0x12
  19. #define RX8010_WDAY 0x13
  20. #define RX8010_MDAY 0x14
  21. #define RX8010_MONTH 0x15
  22. #define RX8010_YEAR 0x16
  23. #define RX8010_RESV17 0x17
  24. #define RX8010_ALMIN 0x18
  25. #define RX8010_ALHOUR 0x19
  26. #define RX8010_ALWDAY 0x1a
  27. #define RX8010_TCOUNT0 0x1b
  28. #define RX8010_TCOUNT1 0x1c
  29. #define RX8010_EXT 0x1d
  30. #define RX8010_FLAG 0x1e
  31. #define RX8010_CTRL 0x1f
  32. /* 0x20 to 0x2F are user registers */
  33. #define RX8010_RESV30 0x30
  34. #define RX8010_RESV31 0x31
  35. #define RX8010_IRQ 0x32
  36. #define RX8010_EXT_WADA RT_BIT(3)
  37. #define RX8010_FLAG_VLF RT_BIT(1)
  38. #define RX8010_FLAG_AF RT_BIT(3)
  39. #define RX8010_FLAG_TF RT_BIT(4)
  40. #define RX8010_FLAG_UF RT_BIT(5)
  41. #define RX8010_CTRL_AIE RT_BIT(3)
  42. #define RX8010_CTRL_UIE RT_BIT(5)
  43. #define RX8010_CTRL_STOP RT_BIT(6)
  44. #define RX8010_CTRL_TEST RT_BIT(7)
  45. #define RX8010_ALARM_AE RT_BIT(7)
  46. struct rx8010_rtc
  47. {
  48. struct rt_device parent;
  49. int irq;
  50. rt_uint8_t ctrlreg;
  51. struct rt_i2c_client *client;
  52. struct rt_thread *irq_thread;
  53. struct rt_rtc_wkalarm wkalarm;
  54. };
  55. #define raw_to_rx8010_rtc(raw) rt_container_of(raw, struct rx8010_rtc, parent)
  56. static rt_err_t rx8010_rtc_write(struct rx8010_rtc *rx8010,
  57. rt_uint8_t reg, rt_uint8_t value)
  58. {
  59. rt_int32_t res;
  60. struct rt_i2c_msg msg[1];
  61. rt_uint8_t data[sizeof(reg) + sizeof(value)] = { reg };
  62. struct rt_i2c_client *client = rx8010->client;
  63. rt_memcpy(&data[sizeof(reg)], &value, sizeof(value));
  64. msg[0].buf = data;
  65. msg[0].addr = client->client_addr;
  66. msg[0].len = sizeof(data);
  67. msg[0].flags = RT_I2C_WR;
  68. res = rt_i2c_transfer(client->bus, msg, 1);
  69. return res > 0 ? RT_EOK : res;
  70. }
  71. static rt_err_t rx8010_rtc_read(struct rx8010_rtc *rx8010,
  72. rt_uint8_t reg, rt_uint8_t *values)
  73. {
  74. rt_int32_t res;
  75. struct rt_i2c_msg msg[2];
  76. struct rt_i2c_client *client = rx8010->client;
  77. msg[0].buf = &reg;
  78. msg[0].addr = client->client_addr;
  79. msg[0].len = sizeof(reg);
  80. msg[0].flags = RT_I2C_WR;
  81. msg[1].buf = (rt_uint8_t *)values;
  82. msg[1].addr = client->client_addr;
  83. msg[1].len = sizeof(*values);
  84. msg[1].flags = RT_I2C_RD;
  85. res = rt_i2c_transfer(client->bus, msg, 2);
  86. return res > 0 ? RT_EOK : res;
  87. }
  88. static rt_err_t rx8010_rtc_set_bit(struct rx8010_rtc *rx8010,
  89. rt_uint8_t reg, rt_uint8_t bit)
  90. {
  91. rt_err_t err;
  92. rt_uint8_t value;
  93. if ((err = rx8010_rtc_read(rx8010, reg, &value)))
  94. {
  95. return err;
  96. }
  97. return rx8010_rtc_write(rx8010, reg, value | bit);
  98. }
  99. static rt_err_t rx8010_rtc_clear_bit(struct rx8010_rtc *rx8010,
  100. rt_uint8_t reg, rt_uint8_t bit)
  101. {
  102. rt_err_t err;
  103. rt_uint8_t value;
  104. if ((err = rx8010_rtc_read(rx8010, reg, &value)))
  105. {
  106. return err;
  107. }
  108. return rx8010_rtc_write(rx8010, reg, value & ~bit);
  109. }
  110. static rt_err_t rx8010_rtc_read_time(struct rx8010_rtc *rx8010, time_t *sec)
  111. {
  112. struct tm tm;
  113. rt_err_t err;
  114. rt_uint8_t flagreg, date[RX8010_YEAR - RX8010_SEC + 1];
  115. if ((err = rx8010_rtc_read(rx8010, RX8010_FLAG, &flagreg)))
  116. {
  117. return err;
  118. }
  119. if (flagreg & RX8010_FLAG_VLF)
  120. {
  121. LOG_W("Frequency stop detected");
  122. return -RT_EINVAL;
  123. }
  124. for (int i = 0; i < sizeof(date); ++i)
  125. {
  126. if ((err = rx8010_rtc_read(rx8010, RX8010_SEC + i, &date[i])))
  127. {
  128. return err;
  129. }
  130. }
  131. tm.tm_sec = rt_bcd2bin(date[RX8010_SEC - RX8010_SEC] & 0x7f);
  132. tm.tm_min = rt_bcd2bin(date[RX8010_MIN - RX8010_SEC] & 0x7f);
  133. tm.tm_hour = rt_bcd2bin(date[RX8010_HOUR - RX8010_SEC] & 0x3f);
  134. tm.tm_mday = rt_bcd2bin(date[RX8010_MDAY - RX8010_SEC] & 0x3f);
  135. tm.tm_mon = rt_bcd2bin(date[RX8010_MONTH - RX8010_SEC] & 0x1f) - 1;
  136. tm.tm_year = rt_bcd2bin(date[RX8010_YEAR - RX8010_SEC]) + 100;
  137. tm.tm_wday = __rt_ffs(date[RX8010_WDAY - RX8010_SEC] & 0x7f);
  138. *sec = timegm(&tm);
  139. return RT_EOK;
  140. }
  141. static rt_err_t rx8010_rtc_set_time(struct rx8010_rtc *rx8010, time_t *sec)
  142. {
  143. rt_err_t err;
  144. struct tm *tm;
  145. rt_uint8_t date[RX8010_YEAR - RX8010_SEC + 1];
  146. /* Set STOP bit before changing clock/calendar */
  147. if ((err = rx8010_rtc_set_bit(rx8010, RX8010_CTRL, RX8010_CTRL_STOP)))
  148. {
  149. return err;
  150. }
  151. tm = localtime(sec);
  152. date[RX8010_SEC - RX8010_SEC] = rt_bin2bcd(tm->tm_sec);
  153. date[RX8010_MIN - RX8010_SEC] = rt_bin2bcd(tm->tm_min);
  154. date[RX8010_HOUR - RX8010_SEC] = rt_bin2bcd(tm->tm_hour);
  155. date[RX8010_MDAY - RX8010_SEC] = rt_bin2bcd(tm->tm_mday);
  156. date[RX8010_MONTH - RX8010_SEC] = rt_bin2bcd(tm->tm_mon + 1);
  157. date[RX8010_YEAR - RX8010_SEC] = rt_bin2bcd(tm->tm_year - 100);
  158. date[RX8010_WDAY - RX8010_SEC] = rt_bin2bcd(1 << tm->tm_wday);
  159. for (int i = 0; i < sizeof(date); ++i)
  160. {
  161. if ((err = rx8010_rtc_write(rx8010, RX8010_SEC + i, date[i])))
  162. {
  163. return err;
  164. }
  165. }
  166. /* Clear STOP bit after changing clock/calendar */
  167. if ((err = rx8010_rtc_clear_bit(rx8010, RX8010_CTRL, RX8010_CTRL_STOP)))
  168. {
  169. return err;
  170. }
  171. if ((err = rx8010_rtc_clear_bit(rx8010, RX8010_FLAG, RX8010_FLAG_VLF)))
  172. {
  173. return err;
  174. }
  175. return RT_EOK;
  176. }
  177. static rt_err_t rx8010_rtc_read_alarm(struct rx8010_rtc *rx8010,
  178. struct rt_rtc_wkalarm *alarm)
  179. {
  180. rt_err_t err;
  181. rt_uint8_t alarmvals[3], flagreg;
  182. for (int i = 0; i < RT_ARRAY_SIZE(alarmvals); ++i)
  183. {
  184. if ((err = rx8010_rtc_read(rx8010, RX8010_ALMIN + i, &alarmvals[i])))
  185. {
  186. return err;
  187. }
  188. }
  189. if ((err = rx8010_rtc_read(rx8010, RX8010_FLAG, &flagreg)))
  190. {
  191. return err;
  192. }
  193. alarm->tm_sec = 0;
  194. alarm->tm_min = rt_bcd2bin(alarmvals[0] & 0x7f);
  195. alarm->tm_hour = rt_bcd2bin(alarmvals[1] & 0x3f);
  196. if (!(alarmvals[2] & RX8010_ALARM_AE))
  197. {
  198. alarm->tm_mday = rt_bcd2bin(alarmvals[2] & 0x7f);
  199. }
  200. alarm->enable = !!(rx8010->ctrlreg & RX8010_CTRL_AIE);
  201. return RT_EOK;
  202. }
  203. static rt_err_t rx8010_alarm_irq_enable(struct rx8010_rtc *rx8010, rt_bool_t enabled)
  204. {
  205. rt_err_t err;
  206. rt_uint8_t ctrl;
  207. ctrl = rx8010->ctrlreg;
  208. if (enabled)
  209. {
  210. ctrl |= RX8010_CTRL_AIE | RX8010_CTRL_UIE;
  211. }
  212. else
  213. {
  214. ctrl &= ~(RX8010_CTRL_UIE | RX8010_CTRL_AIE);
  215. }
  216. if ((err = rx8010_rtc_clear_bit(rx8010, RX8010_FLAG, RX8010_FLAG_AF)))
  217. {
  218. return err;
  219. }
  220. if (ctrl != rx8010->ctrlreg)
  221. {
  222. rx8010->ctrlreg = ctrl;
  223. if ((err = rx8010_rtc_write(rx8010, RX8010_CTRL, rx8010->ctrlreg)))
  224. {
  225. return err;
  226. }
  227. }
  228. return RT_EOK;
  229. }
  230. static rt_err_t rx8010_rtc_set_alarm(struct rx8010_rtc *rx8010,
  231. struct rt_rtc_wkalarm *alarm)
  232. {
  233. rt_err_t err;
  234. rt_uint8_t alarmvals[3];
  235. struct rt_rtc_wkalarm *wkalarm = &rx8010->wkalarm;
  236. if (rx8010->ctrlreg & (RX8010_CTRL_AIE | RX8010_CTRL_UIE))
  237. {
  238. rx8010->ctrlreg &= ~(RX8010_CTRL_AIE | RX8010_CTRL_UIE);
  239. if ((err = rx8010_rtc_write(rx8010, RX8010_CTRL, rx8010->ctrlreg)))
  240. {
  241. return err;
  242. }
  243. }
  244. if ((err = rx8010_rtc_clear_bit(rx8010, RX8010_FLAG, RX8010_FLAG_AF)))
  245. {
  246. return err;
  247. }
  248. alarmvals[0] = rt_bin2bcd(alarm->tm_min);
  249. alarmvals[1] = rt_bin2bcd(alarm->tm_hour);
  250. alarmvals[2] = rt_bin2bcd(alarm->tm_mday);
  251. for (int i = 0; i < RT_ARRAY_SIZE(alarmvals) - 1; ++i)
  252. {
  253. if ((err = rx8010_rtc_write(rx8010, RX8010_ALMIN + i, alarmvals[i])))
  254. {
  255. return err;
  256. }
  257. }
  258. if ((err = rx8010_rtc_clear_bit(rx8010, RX8010_EXT, RX8010_EXT_WADA)))
  259. {
  260. return err;
  261. }
  262. if (alarmvals[2] == 0)
  263. {
  264. alarmvals[2] |= RX8010_ALARM_AE;
  265. }
  266. if ((err = rx8010_rtc_write(rx8010, RX8010_ALWDAY, alarmvals[2])))
  267. {
  268. return err;
  269. }
  270. if (alarm->enable)
  271. {
  272. rx8010->ctrlreg |= RX8010_CTRL_UIE | RX8010_CTRL_AIE;
  273. if ((err = rx8010_rtc_write(rx8010, RX8010_CTRL, rx8010->ctrlreg)))
  274. {
  275. return err;
  276. }
  277. }
  278. if (!(err = rx8010_alarm_irq_enable(rx8010, alarm->enable)))
  279. {
  280. wkalarm->enable = alarm->enable;
  281. wkalarm->tm_hour = alarm->tm_hour;
  282. wkalarm->tm_min = alarm->tm_min;
  283. wkalarm->tm_sec = alarm->tm_sec;
  284. }
  285. return err;
  286. }
  287. static rt_err_t rx8010_rtc_control(rt_device_t dev, int cmd, void *args)
  288. {
  289. rt_err_t err = RT_EOK;
  290. struct rx8010_rtc *rx8010 = raw_to_rx8010_rtc(dev);
  291. if (!args)
  292. {
  293. return -RT_EINVAL;
  294. }
  295. switch (cmd)
  296. {
  297. case RT_DEVICE_CTRL_RTC_GET_TIME:
  298. err = rx8010_rtc_read_time(rx8010, args);
  299. break;
  300. case RT_DEVICE_CTRL_RTC_SET_TIME:
  301. err = rx8010_rtc_set_time(rx8010, args);
  302. break;
  303. case RT_DEVICE_CTRL_RTC_GET_TIMEVAL:
  304. err = rx8010_rtc_read_time(rx8010, (time_t *)&((struct timeval *)args)->tv_sec);
  305. break;
  306. case RT_DEVICE_CTRL_RTC_SET_TIMEVAL:
  307. err = rx8010_rtc_set_time(rx8010, (time_t *)&((struct timeval *)args)->tv_sec);
  308. break;
  309. case RT_DEVICE_CTRL_RTC_GET_ALARM:
  310. err = rx8010_rtc_read_alarm(rx8010, args);
  311. break;
  312. case RT_DEVICE_CTRL_RTC_SET_ALARM:
  313. err = rx8010_rtc_set_alarm(rx8010, args);
  314. break;
  315. default:
  316. err = -RT_EINVAL;
  317. break;
  318. }
  319. return err;
  320. }
  321. #ifdef RT_USING_DEVICE_OPS
  322. const static struct rt_device_ops rx8010_rtc_ops =
  323. {
  324. .control = rx8010_rtc_control,
  325. };
  326. #endif
  327. static void rx8010_rtc_thread_isr(void *param)
  328. {
  329. rt_err_t err;
  330. rt_uint8_t flagreg;
  331. struct rx8010_rtc *rx8010 = param;
  332. while (RT_TRUE)
  333. {
  334. rt_thread_suspend(rx8010->irq_thread);
  335. rt_schedule();
  336. if ((err = rx8010_rtc_read(rx8010, RX8010_FLAG, &flagreg)))
  337. {
  338. LOG_E("Read flag error = %s", rt_strerror(err));
  339. continue;
  340. }
  341. if (flagreg & RX8010_FLAG_VLF)
  342. {
  343. LOG_W("Frequency stop detected");
  344. }
  345. if (flagreg & RX8010_FLAG_TF)
  346. {
  347. flagreg &= ~RX8010_FLAG_TF;
  348. rt_alarm_update(&rx8010->parent, 1);
  349. }
  350. if (flagreg & RX8010_FLAG_AF)
  351. {
  352. flagreg &= ~RX8010_FLAG_AF;
  353. rt_alarm_update(&rx8010->parent, 1);
  354. }
  355. if (flagreg & RX8010_FLAG_UF)
  356. {
  357. flagreg &= ~RX8010_FLAG_UF;
  358. rt_alarm_update(&rx8010->parent, 1);
  359. }
  360. if ((err = rx8010_rtc_write(rx8010, RX8010_FLAG, flagreg)))
  361. {
  362. LOG_E("Write flag error = %s", rt_strerror(err));
  363. }
  364. }
  365. }
  366. static void rx8010_rtc_isr(int irqno, void *param)
  367. {
  368. struct rx8010_rtc *rx8010 = param;
  369. rt_thread_resume(rx8010->irq_thread);
  370. }
  371. static rt_err_t rx8010_init(struct rx8010_rtc *rx8010)
  372. {
  373. rt_err_t err;
  374. rt_uint8_t ctrl[2];
  375. int need_clear = 0;
  376. /* Initialize reserved registers as specified in datasheet */
  377. if ((err = rx8010_rtc_write(rx8010, RX8010_RESV17, 0xd8)))
  378. {
  379. return err;
  380. }
  381. if ((err = rx8010_rtc_write(rx8010, RX8010_RESV30, 0x00)))
  382. {
  383. return err;
  384. }
  385. if ((err = rx8010_rtc_write(rx8010, RX8010_RESV31, 0x08)))
  386. {
  387. return err;
  388. }
  389. if ((err = rx8010_rtc_write(rx8010, RX8010_IRQ, 0x00)))
  390. {
  391. return err;
  392. }
  393. err |= rx8010_rtc_read(rx8010, RX8010_FLAG, &ctrl[0]);
  394. err |= rx8010_rtc_read(rx8010, RX8010_FLAG + 1, &ctrl[1]);
  395. if (err)
  396. {
  397. return err;
  398. }
  399. if (ctrl[0] & RX8010_FLAG_VLF)
  400. {
  401. LOG_W("Frequency stop was detected");
  402. }
  403. if (ctrl[0] & RX8010_FLAG_AF)
  404. {
  405. LOG_W("Alarm was detected");
  406. need_clear = 1;
  407. }
  408. if (ctrl[0] & (RX8010_FLAG_TF | RX8010_FLAG_UF))
  409. {
  410. need_clear = 1;
  411. }
  412. if (need_clear)
  413. {
  414. ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF);
  415. if ((err = rx8010_rtc_write(rx8010, RX8010_FLAG, ctrl[0])))
  416. {
  417. return err;
  418. }
  419. }
  420. rx8010->ctrlreg = ctrl[1] & ~RX8010_CTRL_TEST;
  421. return RT_EOK;
  422. }
  423. static rt_err_t rx8010_rtc_probe(struct rt_i2c_client *client)
  424. {
  425. rt_err_t err;
  426. const char *dev_name;
  427. struct rt_device *dev = &client->parent;
  428. struct rx8010_rtc *rx8010 = rt_calloc(1, sizeof(*rx8010));
  429. if (!rx8010)
  430. {
  431. return -RT_ENOMEM;
  432. }
  433. rx8010->client = client;
  434. if ((err = rx8010_init(rx8010)))
  435. {
  436. goto _fail;
  437. }
  438. rx8010->irq = rt_dm_dev_get_irq(dev, 0);
  439. if (rx8010->irq >= 0)
  440. {
  441. rx8010->irq_thread = rt_thread_create("rtc-rx8010", &rx8010_rtc_thread_isr,
  442. rx8010, DM_THREAD_STACK_SIZE, RT_THREAD_PRIORITY_MAX / 2, 10);
  443. if (!rx8010->irq_thread)
  444. {
  445. err = -RT_ERROR;
  446. LOG_E("Create RTC IRQ thread fail");
  447. goto _fail;
  448. }
  449. rt_thread_startup(rx8010->irq_thread);
  450. rt_hw_interrupt_install(rx8010->irq, rx8010_rtc_isr, rx8010, "rtc-rx8010");
  451. rt_hw_interrupt_umask(rx8010->irq);
  452. }
  453. dev->user_data = rx8010;
  454. rx8010->parent.type = RT_Device_Class_RTC;
  455. #ifdef RT_USING_DEVICE_OPS
  456. rx8010->parent.ops = &rx8010_rtc_ops;
  457. #else
  458. rx8010->parent.control = rx8010_rtc_control;
  459. #endif
  460. rtc_dev_set_name(&rx8010->parent);
  461. dev_name = rt_dm_dev_get_name(&rx8010->parent);
  462. rt_device_register(&rx8010->parent, dev_name, RT_DEVICE_FLAG_RDWR);
  463. return RT_EOK;
  464. _fail:
  465. if (rx8010->irq_thread)
  466. {
  467. rt_thread_delete(rx8010->irq_thread);
  468. }
  469. rt_free(rx8010);
  470. return err;
  471. }
  472. static rt_err_t rx8010_rtc_remove(struct rt_i2c_client *client)
  473. {
  474. struct rx8010_rtc *rx8010 = client->parent.user_data;
  475. rx8010_rtc_set_bit(rx8010, RX8010_CTRL, RX8010_CTRL_STOP);
  476. if (rx8010->irq >= 0)
  477. {
  478. rt_hw_interrupt_mask(rx8010->irq);
  479. rt_pic_detach_irq(rx8010->irq, rx8010);
  480. rt_thread_delete(rx8010->irq_thread);
  481. }
  482. rt_device_unregister(&rx8010->parent);
  483. rt_free(rx8010);
  484. return RT_EOK;
  485. }
  486. static const struct rt_i2c_device_id rx8010_rtc_ids[] =
  487. {
  488. { .name = "rx8010" },
  489. { /* sentinel */ },
  490. };
  491. static const struct rt_ofw_node_id rx8010_rtc_ofw_ids[] =
  492. {
  493. { .compatible = "epson,rx8010" },
  494. { /* sentinel */ },
  495. };
  496. static struct rt_i2c_driver rx8010_rtc_driver =
  497. {
  498. .ids = rx8010_rtc_ids,
  499. .ofw_ids = rx8010_rtc_ofw_ids,
  500. .probe = rx8010_rtc_probe,
  501. .remove = rx8010_rtc_remove,
  502. };
  503. RT_I2C_DRIVER_EXPORT(rx8010_rtc_driver);