1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2009-04-26 yi.qiu first version
9 * 2010-03-18 Gary Lee add functions such as GregorianDay
10 * and rtc_time_to_tm
11 * 2009-03-20 yi.qiu clean up
12 */
13
14 #include <rtthread.h>
15 #include <rtdevice.h>
16 #include <sys/time.h>
17 #include <s3c24x0.h>
18
19 // #define RTC_DEBUG
20 #ifdef RT_USING_RTC
21 #define RTC_ENABLE RTCCON |= 0x01; /*RTC read and write enable */
22 #define RTC_DISABLE RTCCON &= ~0x01; /* RTC read and write disable */
23 #define BCD2BIN(n) (((((n) >> 4) & 0x0F) * 10) + ((n) & 0x0F))
24 #define BIN2BCD(n) ((((n) / 10) << 4) | ((n) % 10))
25
26 /**
27 * This function get rtc time
28 */
rt_hw_rtc_get(struct tm * ti)29 void rt_hw_rtc_get(struct tm *ti)
30 {
31 rt_uint8_t sec, min, hour, mday, wday, mon, year;
32
33 /* enable access to RTC registers */
34 RTCCON |= RTC_ENABLE;
35
36 /* read RTC registers */
37 do
38 {
39 sec = BCDSEC;
40 min = BCDMIN;
41 hour = BCDHOUR;
42 mday = BCDDATE;
43 wday = BCDDAY;
44 mon = BCDMON;
45 year = BCDYEAR;
46 } while (sec != BCDSEC);
47
48 #ifdef RTC_DEBUG
49 rt_kprintf("sec:%x min:%x hour:%x mday:%x wday:%x mon:%x year:%x\n",
50 sec, min, hour, mday, wday, mon, year);
51 #endif
52
53 /* disable access to RTC registers */
54 RTC_DISABLE
55
56 ti->tm_sec = BCD2BIN(sec & 0x7F);
57 ti->tm_min = BCD2BIN(min & 0x7F);
58 ti->tm_hour = BCD2BIN(hour & 0x3F);
59 ti->tm_mday = BCD2BIN(mday & 0x3F);
60 ti->tm_mon = BCD2BIN(mon & 0x1F);
61 ti->tm_year = BCD2BIN(year);
62 ti->tm_wday = BCD2BIN(wday & 0x07);
63 ti->tm_yday = 0;
64 ti->tm_isdst = 0;
65 }
66
67 /**
68 * This function set rtc time
69 */
rt_hw_rtc_set(struct tm * ti)70 void rt_hw_rtc_set(struct tm *ti)
71 {
72 rt_uint8_t sec, min, hour, mday, wday, mon, year;
73
74 year = BIN2BCD(ti->tm_year);
75 mon = BIN2BCD(ti->tm_mon);
76 wday = BIN2BCD(ti->tm_wday);
77 mday = BIN2BCD(ti->tm_mday);
78 hour = BIN2BCD(ti->tm_hour);
79 min = BIN2BCD(ti->tm_min);
80 sec = BIN2BCD(ti->tm_sec);
81
82 /* enable access to RTC registers */
83 RTC_ENABLE
84
85 do{
86 /* write RTC registers */
87 BCDSEC = sec;
88 BCDMIN = min;
89 BCDHOUR = hour;
90 BCDDATE = mday;
91 BCDDAY = wday;
92 BCDMON = mon;
93 BCDYEAR = year;
94 }while (sec != BCDSEC);
95
96 /* disable access to RTC registers */
97 RTC_DISABLE
98 }
99
100 /**
101 * This function reset rtc
102 */
rt_hw_rtc_reset(void)103 void rt_hw_rtc_reset (void)
104 {
105 RTCCON = (RTCCON & ~0x06) | 0x08;
106 RTCCON &= ~(0x08|0x01);
107 }
108
109 static struct rt_device rtc;
rtc_open(rt_device_t dev,rt_uint16_t oflag)110 static rt_err_t rtc_open(rt_device_t dev, rt_uint16_t oflag)
111 {
112 RTC_ENABLE
113 return RT_EOK;
114 }
115
rtc_close(rt_device_t dev)116 static rt_err_t rtc_close(rt_device_t dev)
117 {
118 RTC_DISABLE
119 return RT_EOK;
120 }
121
rtc_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)122 static rt_ssize_t rtc_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
123 {
124 return RT_EOK;
125 }
126
rtc_control(rt_device_t dev,int cmd,void * args)127 static rt_err_t rtc_control(rt_device_t dev, int cmd, void *args)
128 {
129 struct tm tmp;
130 time_t *time;
131 RT_ASSERT(dev != RT_NULL);
132
133 time = (time_t *)args;
134 switch (cmd)
135 {
136 case RT_DEVICE_CTRL_RTC_GET_TIME:
137 /* read device */
138 rt_hw_rtc_get(&tmp);
139 *((rt_time_t *)args) = timegm(&tmp);
140 break;
141
142 case RT_DEVICE_CTRL_RTC_SET_TIME:
143 /* write device */
144 gmtime_r(time, &tmp);
145 rt_hw_rtc_set(&tmp);
146 break;
147 }
148
149 return RT_EOK;
150 }
151
rt_hw_rtc_init(void)152 void rt_hw_rtc_init(void)
153 {
154 rtc.type = RT_Device_Class_RTC;
155
156 /* register rtc device */
157 rtc.init = RT_NULL;
158 rtc.open = rtc_open;
159 rtc.close = rtc_close;
160 rtc.read = rtc_read;
161 rtc.write = RT_NULL;
162 rtc.control = rtc_control;
163
164 /* no private */
165 rtc.user_data = RT_NULL;
166
167 rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR);
168 }
169
170 #ifdef RT_USING_FINSH
171 #include <finsh.h>
list_date()172 void list_date()
173 {
174 time_t time;
175 rt_device_t device;
176
177 device = rt_device_find("rtc");
178 if (device != RT_NULL)
179 {
180 rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time);
181
182 rt_kprintf("%d, %s\n", time, ctime(&time));
183 }
184 }
185 FINSH_FUNCTION_EXPORT(list_date, list date);
186 #endif
187 #endif
188