drv_rtc.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * Copyright (c) 2019 Winner Microelectronics Co., Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-09-15 flyingcys 1st version
  9. * 2019-03-01 fanwenl add alarm
  10. */
  11. #include <rtdevice.h>
  12. #include <rtthread.h>
  13. #include <time.h>
  14. #include "wm_regs.h"
  15. #include "wm_irq.h"
  16. #include "tls_common.h"
  17. #include "wm_rtc.h"
  18. #include "drv_rtc.h"
  19. #ifdef BSP_USING_RTC
  20. #if defined(RT_USING_SOFT_RTC)
  21. #error "Please CANCEL the RT_USING_SOFT_RTC option. Make sure there is only one RTC device on the system."
  22. #endif
  23. static struct rt_rtc_device rtc_device;
  24. static time_t wm_get_timestamp(void)
  25. {
  26. struct tm tm_new = {0};
  27. int ctrl1 = 0;
  28. int ctrl2 = 0;
  29. ctrl1 = tls_reg_read32(HR_PMU_RTC_CTRL1);
  30. ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2);
  31. tm_new.tm_year = ((int)((int)ctrl2 & 0x00007f00) >> 8);
  32. tm_new.tm_mon = (ctrl2 & 0x0000000f);
  33. tm_new.tm_mday = (ctrl1 & 0x1f000000) >> 24;
  34. tm_new.tm_hour = (ctrl1 & 0x001f0000) >> 16;
  35. tm_new.tm_min = (ctrl1 & 0x00003f00) >> 8;
  36. tm_new.tm_sec = ctrl1 & 0x0000003f;
  37. return mktime(&tm_new);
  38. }
  39. static int wm_set_timestamp(time_t timestamp)
  40. {
  41. int ctrl1 = 0;
  42. int ctrl2 = 0;
  43. struct tm *tblock;
  44. tblock = localtime(&timestamp);
  45. ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2); /* disable */
  46. ctrl2 &= ~(1 << 16);
  47. tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2);
  48. ctrl1 |= tblock->tm_sec;
  49. ctrl1 |= tblock->tm_min << 8;
  50. ctrl1 |= tblock->tm_hour << 16;
  51. ctrl1 |= tblock->tm_mday << 24;
  52. tls_reg_write32(HR_PMU_RTC_CTRL1, ctrl1);
  53. ctrl2 = 0;
  54. ctrl2 |= tblock->tm_mon;
  55. ctrl2 |= tblock->tm_year << 8;
  56. tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2);
  57. ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2);/* enable */
  58. ctrl2 |= (1 << 16);
  59. tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2);
  60. return RT_EOK;
  61. }
  62. #ifdef BSP_USING_ALARM
  63. static int wm_alarm_set_timestamp(struct rt_rtc_wkalarm *wkalarm)
  64. {
  65. int ctrl1 = 0;
  66. int ctrl2 = 0;
  67. struct tm *tblock;
  68. time_t timestamp = 0;
  69. timestamp = wm_get_timestamp();
  70. tblock = localtime(&timestamp);
  71. tls_irq_enable(PMU_RTC_INT);
  72. ctrl1 |= wkalarm->tm_sec;
  73. ctrl1 |= wkalarm->tm_min << 8;
  74. ctrl1 |= wkalarm->tm_hour << 16;
  75. ctrl1 |= tblock->tm_mday << 24;
  76. ctrl2 |= tblock->tm_mon;
  77. ctrl2 |= tblock->tm_year << 8;
  78. tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2 | BIT(16));
  79. tls_reg_write32(HR_PMU_RTC_CTRL1, ctrl1 | BIT(31));/* must set the enable */
  80. return RT_EOK;
  81. }
  82. static void wm_rtc_alarm_callback(void *arg)
  83. {
  84. rt_alarm_update(0, 0);
  85. }
  86. #endif
  87. static rt_err_t wm_rtc_init(rt_device_t dev)
  88. {
  89. wm_set_timestamp((time_t)0);
  90. #ifdef BSP_USING_ALARM
  91. tls_rtc_isr_register(wm_rtc_alarm_callback, (void *)0);
  92. #endif
  93. return RT_EOK;
  94. }
  95. static rt_err_t wm_rtc_open(rt_device_t dev, rt_uint16_t oflag)
  96. {
  97. return RT_EOK;
  98. }
  99. static rt_err_t wm_rtc_close(rt_device_t dev)
  100. {
  101. return RT_EOK;
  102. }
  103. static rt_err_t wm_rtc_control(rt_device_t dev, int cmd, void *args)
  104. {
  105. #ifdef BSP_USING_ALARM
  106. struct rt_rtc_device* rtc_device;
  107. rtc_device = (struct rt_rtc_device* )dev;
  108. #endif
  109. RT_ASSERT(dev != RT_NULL);
  110. switch (cmd)
  111. {
  112. case RT_DEVICE_CTRL_RTC_GET_TIME:
  113. *(rt_uint32_t *)args = wm_get_timestamp();
  114. break;
  115. case RT_DEVICE_CTRL_RTC_SET_TIME:
  116. wm_set_timestamp(*(time_t *)args);
  117. break;
  118. #ifdef BSP_USING_ALARM
  119. case RT_DEVICE_CTRL_RTC_GET_ALARM:
  120. *(struct rt_rtc_wkalarm *)args = rtc_device->wkalarm;
  121. return RT_EOK;
  122. case RT_DEVICE_CTRL_RTC_SET_ALARM:
  123. rtc_device->wkalarm = *(struct rt_rtc_wkalarm *)args;
  124. wm_alarm_set_timestamp(&rtc_device->wkalarm);
  125. break;
  126. #endif
  127. default:
  128. return RT_EINVAL;
  129. }
  130. return RT_EOK;
  131. }
  132. static rt_size_t wm_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  133. {
  134. wm_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer);
  135. return size;
  136. }
  137. static rt_size_t wm_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  138. {
  139. wm_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer);
  140. return size;
  141. }
  142. #ifdef RT_USING_DEVICE_OPS
  143. const static struct rt_device_ops _ops =
  144. {
  145. .init = wm_rtc_init,
  146. .open = wm_rtc_open,
  147. .close = wm_rtc_close,
  148. .read = wm_rtc_read,
  149. .write = wm_rtc_write,
  150. .control = wm_rtc_control
  151. };
  152. #endif
  153. int wm_hw_rtc_init(void)
  154. {
  155. rt_memset(&rtc_device, 0, sizeof(rtc_device));
  156. rtc_device.device.type = RT_Device_Class_RTC;
  157. rtc_device.device.rx_indicate = RT_NULL;
  158. rtc_device.device.tx_complete = RT_NULL;
  159. #ifdef RT_USING_DEVICE_OPS
  160. rtc_device.ops = &_ops;
  161. #else
  162. rtc_device.device.init = wm_rtc_init;
  163. rtc_device.device.open = wm_rtc_open;
  164. rtc_device.device.close = wm_rtc_close;
  165. rtc_device.device.read = wm_rtc_read;
  166. rtc_device.device.write = wm_rtc_write;
  167. rtc_device.device.control = wm_rtc_control;
  168. #endif
  169. rtc_device.device.user_data = RT_NULL;
  170. /* register a rtc device */
  171. rt_device_register(&rtc_device.device, "rtc", RT_DEVICE_FLAG_RDWR);
  172. return 0;
  173. }
  174. INIT_DEVICE_EXPORT(wm_hw_rtc_init);
  175. #endif /* BSP_USING_RTC */