123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- /*
- * Copyright (c) 2019 Winner Microelectronics Co., Ltd.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2018-09-15 flyingcys 1st version
- * 2019-03-01 fanwenl add alarm
- */
- #include <rtdevice.h>
- #include <rtthread.h>
- #include <time.h>
- #include "wm_regs.h"
- #include "wm_irq.h"
- #include "tls_common.h"
- #include "wm_rtc.h"
- #include "drv_rtc.h"
- #ifdef BSP_USING_RTC
- #if defined(RT_USING_SOFT_RTC)
- #error "Please CANCEL the RT_USING_SOFT_RTC option. Make sure there is only one RTC device on the system."
- #endif
- static struct rt_rtc_device rtc_device;
- static time_t wm_get_timestamp(void)
- {
- struct tm tm_new = {0};
- int ctrl1 = 0;
- int ctrl2 = 0;
- ctrl1 = tls_reg_read32(HR_PMU_RTC_CTRL1);
- ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2);
- tm_new.tm_year = ((int)((int)ctrl2 & 0x00007f00) >> 8);
- tm_new.tm_mon = (ctrl2 & 0x0000000f);
- tm_new.tm_mday = (ctrl1 & 0x1f000000) >> 24;
- tm_new.tm_hour = (ctrl1 & 0x001f0000) >> 16;
- tm_new.tm_min = (ctrl1 & 0x00003f00) >> 8;
- tm_new.tm_sec = ctrl1 & 0x0000003f;
- return mktime(&tm_new);
- }
- static int wm_set_timestamp(time_t timestamp)
- {
- int ctrl1 = 0;
- int ctrl2 = 0;
- struct tm *tblock;
- tblock = localtime(×tamp);
- ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2); /* disable */
- ctrl2 &= ~(1 << 16);
- tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2);
- ctrl1 |= tblock->tm_sec;
- ctrl1 |= tblock->tm_min << 8;
- ctrl1 |= tblock->tm_hour << 16;
- ctrl1 |= tblock->tm_mday << 24;
- tls_reg_write32(HR_PMU_RTC_CTRL1, ctrl1);
- ctrl2 = 0;
- ctrl2 |= tblock->tm_mon;
- ctrl2 |= tblock->tm_year << 8;
- tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2);
- ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2);/* enable */
- ctrl2 |= (1 << 16);
- tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2);
- return RT_EOK;
- }
- #ifdef BSP_USING_ALARM
- static int wm_alarm_set_timestamp(struct rt_rtc_wkalarm *wkalarm)
- {
- int ctrl1 = 0;
- int ctrl2 = 0;
- struct tm *tblock;
- time_t timestamp = 0;
- timestamp = wm_get_timestamp();
- tblock = localtime(×tamp);
- tls_irq_enable(PMU_RTC_INT);
- ctrl1 |= wkalarm->tm_sec;
- ctrl1 |= wkalarm->tm_min << 8;
- ctrl1 |= wkalarm->tm_hour << 16;
- ctrl1 |= tblock->tm_mday << 24;
- ctrl2 |= tblock->tm_mon;
- ctrl2 |= tblock->tm_year << 8;
- tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2 | BIT(16));
- tls_reg_write32(HR_PMU_RTC_CTRL1, ctrl1 | BIT(31));/* must set the enable */
- return RT_EOK;
- }
- static void wm_rtc_alarm_callback(void *arg)
- {
- rt_alarm_update(0, 0);
- }
- #endif
- static rt_err_t wm_rtc_init(rt_device_t dev)
- {
- wm_set_timestamp((time_t)0);
- #ifdef BSP_USING_ALARM
- tls_rtc_isr_register(wm_rtc_alarm_callback, (void *)0);
- #endif
- return RT_EOK;
- }
- static rt_err_t wm_rtc_open(rt_device_t dev, rt_uint16_t oflag)
- {
- return RT_EOK;
- }
- static rt_err_t wm_rtc_close(rt_device_t dev)
- {
- return RT_EOK;
- }
- static rt_err_t wm_rtc_control(rt_device_t dev, int cmd, void *args)
- {
- #ifdef BSP_USING_ALARM
- struct rt_rtc_device* rtc_device;
- rtc_device = (struct rt_rtc_device* )dev;
- #endif
- RT_ASSERT(dev != RT_NULL);
- switch (cmd)
- {
- case RT_DEVICE_CTRL_RTC_GET_TIME:
- *(rt_uint32_t *)args = wm_get_timestamp();
- break;
- case RT_DEVICE_CTRL_RTC_SET_TIME:
- wm_set_timestamp(*(time_t *)args);
- break;
- #ifdef BSP_USING_ALARM
- case RT_DEVICE_CTRL_RTC_GET_ALARM:
- *(struct rt_rtc_wkalarm *)args = rtc_device->wkalarm;
- return RT_EOK;
- case RT_DEVICE_CTRL_RTC_SET_ALARM:
- rtc_device->wkalarm = *(struct rt_rtc_wkalarm *)args;
- wm_alarm_set_timestamp(&rtc_device->wkalarm);
- break;
- #endif
- default:
- return RT_EINVAL;
- }
- return RT_EOK;
- }
- static rt_size_t wm_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
- {
- wm_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer);
- return size;
- }
- static rt_size_t wm_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
- {
- wm_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer);
- return size;
- }
- #ifdef RT_USING_DEVICE_OPS
- const static struct rt_device_ops _ops =
- {
- .init = wm_rtc_init,
- .open = wm_rtc_open,
- .close = wm_rtc_close,
- .read = wm_rtc_read,
- .write = wm_rtc_write,
- .control = wm_rtc_control
- };
- #endif
- int wm_hw_rtc_init(void)
- {
- rt_memset(&rtc_device, 0, sizeof(rtc_device));
- rtc_device.device.type = RT_Device_Class_RTC;
- rtc_device.device.rx_indicate = RT_NULL;
- rtc_device.device.tx_complete = RT_NULL;
- #ifdef RT_USING_DEVICE_OPS
- rtc_device.ops = &_ops;
- #else
- rtc_device.device.init = wm_rtc_init;
- rtc_device.device.open = wm_rtc_open;
- rtc_device.device.close = wm_rtc_close;
- rtc_device.device.read = wm_rtc_read;
- rtc_device.device.write = wm_rtc_write;
- rtc_device.device.control = wm_rtc_control;
- #endif
- rtc_device.device.user_data = RT_NULL;
- /* register a rtc device */
- rt_device_register(&rtc_device.device, "rtc", RT_DEVICE_FLAG_RDWR);
- return 0;
- }
- INIT_DEVICE_EXPORT(wm_hw_rtc_init);
- #endif /* BSP_USING_RTC */
|