summaryrefslogtreecommitdiff
path: root/bsp/ls2kdev/drivers
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2020-06-28 19:09:37 +0800
committerGitHub <[email protected]>2020-06-28 19:09:37 +0800
commit7ba7b996dd2a04b1326cea13e46b52a91c0b0111 (patch)
tree07a633566981c9c5cfe7eb4d3752a63fc5a6b3ba /bsp/ls2kdev/drivers
parent08048bbcb7de07bfacbf498ca1feed641c1acae9 (diff)
parente58c7bb2cd31f6f0b097d65fa3ded32837e44ec7 (diff)
Merge pull request #3717 from imgtec/bsp-ls2k/rtc-v2
bsp: ls2k: internal rtc driver
Diffstat (limited to 'bsp/ls2kdev/drivers')
-rw-r--r--bsp/ls2kdev/drivers/drv_rtc.c178
-rw-r--r--bsp/ls2kdev/drivers/ls2k1000.h1
2 files changed, 179 insertions, 0 deletions
diff --git a/bsp/ls2kdev/drivers/drv_rtc.c b/bsp/ls2kdev/drivers/drv_rtc.c
new file mode 100644
index 0000000000..3a873cc6fc
--- /dev/null
+++ b/bsp/ls2kdev/drivers/drv_rtc.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2020, Du Huanpeng <[email protected]>
+ *
+ * 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 <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rtthread.h>
+#include "ls2k1000.h"
+
+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) (m<n ? __BF(number, n, m) : __BF(number, m, n))
+
+struct rtctime {
+ rt_uint32_t sys_toyread0;
+ rt_uint32_t sys_toyread1;
+ rt_uint32_t sys_rtcread0;
+};
+typedef struct rtctime rtctime_t;
+
+struct tm *localrtctime(const rtctime_t *rtctp)
+{
+ static struct tm time;
+ int msec;
+
+ msec = BF(rtctp->sys_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_size_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;
+ time = *localtime(t);
+
+ 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 = mktime(&tmptime);
+ break;
+ case RT_DEVICE_CTRL_RTC_SET_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);
diff --git a/bsp/ls2kdev/drivers/ls2k1000.h b/bsp/ls2kdev/drivers/ls2k1000.h
index cb6586525e..40c0496ba9 100644
--- a/bsp/ls2kdev/drivers/ls2k1000.h
+++ b/bsp/ls2kdev/drivers/ls2k1000.h
@@ -20,6 +20,7 @@
#define GPIO_BASE 0xFFFFFFFFBFE10500
#define PLL_SYS_BASE 0xFFFFFFFFBFE10480
+#define RTC_BASE 0xFFFFFFFFBFE07820
void rt_hw_timer_handler(void);
void rt_hw_uart_init(void);