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