/* * Copyright (c) 2006-2018, RT-Thread Development Team * Copyright (c) 2020, Du Huanpeng <548708880@qq.com> * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-01-30 armink the first version * 2020-06-23 Du Huanpeng based on components/drivers/rtc/soft_rtc.c */ #include #include #include #include #include "ls2k1000.h" #ifdef RT_USING_RTC struct loongson_rtc { rt_uint32_t sys_toytrim; rt_uint32_t sys_toywrite0; rt_uint32_t sys_toywrite1; rt_uint32_t sys_toyread0; rt_uint32_t sys_toyread1; rt_uint32_t sys_toymatch0; rt_uint32_t sys_toymatch1; rt_uint32_t sys_toymatch2; rt_uint32_t sys_rtcctrl; rt_uint32_t __pad4[3]; rt_uint32_t __pad5[4]; rt_uint32_t sys_rtctrim; rt_uint32_t sys_rtcwrite0; rt_uint32_t sys_rtcread0; rt_uint32_t sys_rtcmatch0; rt_uint32_t sys_rtcmatch1; rt_uint32_t sys_rtcmatch2; }; /* bit field helpers. */ #define __M(n) (~(~0<<(n))) #define __RBF(number, n) ((number)&__M(n)) #define __BF(number, n, m) __RBF((number>>m), (n-m+1)) #define BF(number, n, m) (msys_toyread0, 3, 0); msec *= 100; time.tm_sec = BF(rtctp->sys_toyread0, 9, 4); time.tm_min = BF(rtctp->sys_toyread0, 15, 10); time.tm_hour = BF(rtctp->sys_toyread0, 20, 16); time.tm_mday = BF(rtctp->sys_toyread0, 21, 25); time.tm_mon = BF(rtctp->sys_toyread0, 26, 31); /* struct tm has three more members: time.tm_isdst time.tm_wday time.tm_yday */ time.tm_mon -= 1; time.tm_year = rtctp->sys_toyread1; return &time; } rtctime_t mkrtctime(struct tm *tm) { rtctime_t rtctm; struct tm tmptime; rtctm.sys_toyread0 <<= 31 - 26 + 1; rtctm.sys_toyread0 |= tm->tm_mon + 1; rtctm.sys_toyread0 <<= 25 - 21 + 1; rtctm.sys_toyread0 |= tm->tm_mday; rtctm.sys_toyread0 <<= 20 - 16 + 1; rtctm.sys_toyread0 |= tm->tm_hour; rtctm.sys_toyread0 <<= 15 - 10 + 1; rtctm.sys_toyread0 |= tm->tm_min; rtctm.sys_toyread0 <<= 9 - 4 + 1; rtctm.sys_toyread0 |= tm->tm_sec; /* Fixme: 0.1 second */ rtctm.sys_toyread0 <<= 3 - 0 + 1; rtctm.sys_toyread0 |= 0; rtctm.sys_toyread1 = tm->tm_year; tmptime = *localrtctime(&rtctm); return rtctm; } static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag) { return RT_EOK; } static rt_ssize_t rt_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) { return 0; } static rt_err_t rt_rtc_ioctl(rt_device_t dev, int cmd, void *args) { rt_err_t err = -RT_ENOSYS; static int count = 0; struct loongson_rtc *hw_rtc; rtctime_t rtctm; struct tm time; struct tm tmptime; time_t *t; hw_rtc = dev->user_data; t = (time_t *)args; rtctm.sys_toyread0 = hw_rtc->sys_toyread0; rtctm.sys_toyread1 = hw_rtc->sys_toyread1; rtctm.sys_rtcread0 = hw_rtc->sys_rtcread0; tmptime = *localrtctime(&rtctm); switch (cmd) { case RT_DEVICE_CTRL_RTC_GET_TIME: *t = timegm(&tmptime); break; case RT_DEVICE_CTRL_RTC_SET_TIME: gmtime_r(t, &time); tmptime.tm_hour = time.tm_hour; tmptime.tm_min = time.tm_min; tmptime.tm_sec = time.tm_sec; tmptime.tm_year = time.tm_year; tmptime.tm_mon = time.tm_mon; tmptime.tm_mday = time.tm_mday; rtctm = mkrtctime(&tmptime); /* write to hw RTC */ hw_rtc->sys_toywrite0 = rtctm.sys_toyread0; hw_rtc->sys_toywrite1 = rtctm.sys_toyread1; break; case RT_DEVICE_CTRL_RTC_GET_ALARM: break; case RT_DEVICE_CTRL_RTC_SET_ALARM: break; default: break; } return RT_EOK; } int rt_hw_rtc_init(void) { static struct rt_device rtc = { .type = RT_Device_Class_RTC, .init = RT_NULL, .open = rt_rtc_open, .close = RT_NULL, .read = rt_rtc_read, .write = RT_NULL, .control = rt_rtc_ioctl, .user_data = (void *)RTC_BASE, }; rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR); } INIT_DEVICE_EXPORT(rt_hw_rtc_init); #endif /*RT_USING_RTC*/