1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 * Copyright (c) 2020, Du Huanpeng <548708880@qq.com>
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date Author Notes
9 * 2018-01-30 armink the first version
10 * 2020-06-23 Du Huanpeng based on components/drivers/rtc/soft_rtc.c
11 */
12
13
14 #include <rthw.h>
15 #include <rtthread.h>
16 #include <rtdevice.h>
17 #include <sys/time.h>
18 #include "ls2k1000.h"
19
20 #ifdef RT_USING_RTC
21
22 struct loongson_rtc
23 {
24 rt_uint32_t sys_toytrim;
25 rt_uint32_t sys_toywrite0;
26 rt_uint32_t sys_toywrite1;
27 rt_uint32_t sys_toyread0;
28 rt_uint32_t sys_toyread1;
29 rt_uint32_t sys_toymatch0;
30 rt_uint32_t sys_toymatch1;
31 rt_uint32_t sys_toymatch2;
32 rt_uint32_t sys_rtcctrl;
33 rt_uint32_t __pad4[3];
34 rt_uint32_t __pad5[4];
35 rt_uint32_t sys_rtctrim;
36 rt_uint32_t sys_rtcwrite0;
37 rt_uint32_t sys_rtcread0;
38 rt_uint32_t sys_rtcmatch0;
39 rt_uint32_t sys_rtcmatch1;
40 rt_uint32_t sys_rtcmatch2;
41 };
42
43 /* bit field helpers. */
44 #define __M(n) (~(~0<<(n)))
45 #define __RBF(number, n) ((number)&__M(n))
46 #define __BF(number, n, m) __RBF((number>>m), (n-m+1))
47 #define BF(number, n, m) (m<n ? __BF(number, n, m) : __BF(number, m, n))
48
49 struct rtctime
50 {
51 rt_uint32_t sys_toyread0;
52 rt_uint32_t sys_toyread1;
53 rt_uint32_t sys_rtcread0;
54 };
55 typedef struct rtctime rtctime_t;
56
localrtctime(const rtctime_t * rtctp)57 struct tm *localrtctime(const rtctime_t *rtctp)
58 {
59 static struct tm time;
60 int msec;
61
62 msec = BF(rtctp->sys_toyread0, 3, 0);
63 msec *= 100;
64
65 time.tm_sec = BF(rtctp->sys_toyread0, 9, 4);
66 time.tm_min = BF(rtctp->sys_toyread0, 15, 10);
67 time.tm_hour = BF(rtctp->sys_toyread0, 20, 16);
68 time.tm_mday = BF(rtctp->sys_toyread0, 21, 25);
69 time.tm_mon = BF(rtctp->sys_toyread0, 26, 31);
70 /* struct tm has three more members:
71 time.tm_isdst
72 time.tm_wday
73 time.tm_yday
74 */
75 time.tm_mon -= 1;
76 time.tm_year = rtctp->sys_toyread1;
77 return &time;
78 }
79
mkrtctime(struct tm * tm)80 rtctime_t mkrtctime(struct tm *tm)
81 {
82 rtctime_t rtctm;
83 struct tm tmptime;
84
85 rtctm.sys_toyread0 <<= 31 - 26 + 1;
86 rtctm.sys_toyread0 |= tm->tm_mon + 1;
87 rtctm.sys_toyread0 <<= 25 - 21 + 1;
88 rtctm.sys_toyread0 |= tm->tm_mday;
89 rtctm.sys_toyread0 <<= 20 - 16 + 1;
90 rtctm.sys_toyread0 |= tm->tm_hour;
91 rtctm.sys_toyread0 <<= 15 - 10 + 1;
92 rtctm.sys_toyread0 |= tm->tm_min;
93 rtctm.sys_toyread0 <<= 9 - 4 + 1;
94 rtctm.sys_toyread0 |= tm->tm_sec;
95 /* Fixme: 0.1 second */
96 rtctm.sys_toyread0 <<= 3 - 0 + 1;
97 rtctm.sys_toyread0 |= 0;
98
99 rtctm.sys_toyread1 = tm->tm_year;
100
101 tmptime = *localrtctime(&rtctm);
102
103 return rtctm;
104 }
105
rt_rtc_open(rt_device_t dev,rt_uint16_t oflag)106 static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag)
107 {
108 return RT_EOK;
109 }
110
rt_rtc_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)111 static rt_ssize_t rt_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
112 {
113 return 0;
114 }
115
rt_rtc_ioctl(rt_device_t dev,int cmd,void * args)116 static rt_err_t rt_rtc_ioctl(rt_device_t dev, int cmd, void *args)
117 {
118 rt_err_t err = -RT_ENOSYS;
119
120 static int count = 0;
121
122 struct loongson_rtc *hw_rtc;
123 rtctime_t rtctm;
124 struct tm time;
125 struct tm tmptime;
126 time_t *t;
127
128 hw_rtc = dev->user_data;
129
130 t = (time_t *)args;
131
132 rtctm.sys_toyread0 = hw_rtc->sys_toyread0;
133 rtctm.sys_toyread1 = hw_rtc->sys_toyread1;
134 rtctm.sys_rtcread0 = hw_rtc->sys_rtcread0;
135 tmptime = *localrtctime(&rtctm);
136
137 switch (cmd)
138 {
139 case RT_DEVICE_CTRL_RTC_GET_TIME:
140 *t = timegm(&tmptime);
141 break;
142 case RT_DEVICE_CTRL_RTC_SET_TIME:
143 gmtime_r(t, &time);
144 tmptime.tm_hour = time.tm_hour;
145 tmptime.tm_min = time.tm_min;
146 tmptime.tm_sec = time.tm_sec;
147
148 tmptime.tm_year = time.tm_year;
149 tmptime.tm_mon = time.tm_mon;
150 tmptime.tm_mday = time.tm_mday;
151
152 rtctm = mkrtctime(&tmptime);
153 /* write to hw RTC */
154 hw_rtc->sys_toywrite0 = rtctm.sys_toyread0;
155 hw_rtc->sys_toywrite1 = rtctm.sys_toyread1;
156 break;
157 case RT_DEVICE_CTRL_RTC_GET_ALARM:
158 break;
159 case RT_DEVICE_CTRL_RTC_SET_ALARM:
160 break;
161 default:
162 break;
163 }
164
165 return RT_EOK;
166 }
167
rt_hw_rtc_init(void)168 int rt_hw_rtc_init(void)
169 {
170 static struct rt_device rtc =
171 {
172 .type = RT_Device_Class_RTC,
173 .init = RT_NULL,
174 .open = rt_rtc_open,
175 .close = RT_NULL,
176 .read = rt_rtc_read,
177 .write = RT_NULL,
178 .control = rt_rtc_ioctl,
179 .user_data = (void *)RTC_BASE,
180 };
181 rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR);
182 }
183
184 INIT_DEVICE_EXPORT(rt_hw_rtc_init);
185
186 #endif /*RT_USING_RTC*/
187