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