1 /*
2  * Copyright (c) 2006-2020, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2020-06-08     hqfang       first implementation.
9  */
10 
11 #include "drv_rtc.h"
12 
13 #ifdef BSP_USING_RTC
14 
get_timestamp(void)15 static time_t get_timestamp(void)
16 {
17     return (time_t)rtc_counter_get();
18 }
19 
set_timestamp(time_t timestamp)20 static int set_timestamp(time_t timestamp)
21 {
22     /* wait until last write operation on RTC registers has finished */
23     rtc_lwoff_wait();
24     /* change the current time */
25     rtc_counter_set((uint32_t)timestamp);
26     /* wait until last write operation on RTC registers has finished */
27     rtc_lwoff_wait();
28     return RT_EOK;
29 }
30 
rtc_configuration(void)31 static void rtc_configuration(void)
32 {
33     /* enable PMU and BKPI clocks */
34     rcu_periph_clock_enable(RCU_BKPI);
35     rcu_periph_clock_enable(RCU_PMU);
36     /* allow access to BKP domain */
37     pmu_backup_write_enable();
38 
39     /* reset backup domain */
40     bkp_deinit();
41 
42     /* enable LXTAL */
43     rcu_osci_on(RCU_LXTAL);
44     /* wait till LXTAL is ready */
45     rcu_osci_stab_wait(RCU_LXTAL);
46 
47     /* select RCU_LXTAL as RTC clock source */
48     rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);
49 
50     /* enable RTC Clock */
51     rcu_periph_clock_enable(RCU_RTC);
52 
53     /* wait for RTC registers synchronization */
54     rtc_register_sync_wait();
55 
56     /* wait until last write operation on RTC registers has finished */
57     rtc_lwoff_wait();
58 
59     /* wait until last write operation on RTC registers has finished */
60     rtc_lwoff_wait();
61 
62     /* set RTC prescaler: set RTC period to 1s */
63     rtc_prescaler_set(32767);
64 
65     /* wait until last write operation on RTC registers has finished */
66     rtc_lwoff_wait();
67 }
68 
gd32_rtc_init(rt_device_t dev)69 static rt_err_t gd32_rtc_init(rt_device_t dev)
70 {
71     if (bkp_data_read(BKP_DATA_0) != 0xA5A5)
72     {
73         rtc_configuration();
74         bkp_data_write(BKP_DATA_0, 0xA5A5);
75     }
76     else
77     {
78         /* allow access to BKP domain */
79         rcu_periph_clock_enable(RCU_PMU);
80         pmu_backup_write_enable();
81 
82         /* wait for RTC registers synchronization */
83         rtc_register_sync_wait();
84         /* wait until last write operation on RTC registers has finished */
85         rtc_lwoff_wait();
86     }
87 
88     return RT_EOK;
89 }
90 
gd32_rtc_open(rt_device_t dev,rt_uint16_t oflag)91 static rt_err_t gd32_rtc_open(rt_device_t dev, rt_uint16_t oflag)
92 {
93     return RT_EOK;
94 }
95 
gd32_rtc_close(rt_device_t dev)96 static rt_err_t gd32_rtc_close(rt_device_t dev)
97 {
98     return RT_EOK;
99 }
100 
gd32_rtc_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)101 static rt_ssize_t gd32_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
102 {
103     return RT_EOK;
104 }
105 
gd32_rtc_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)106 static rt_ssize_t gd32_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
107 {
108     return RT_EOK;
109 }
110 
gd32_rtc_control(rt_device_t dev,int cmd,void * args)111 static rt_err_t gd32_rtc_control(rt_device_t dev, int cmd, void *args)
112 {
113     RT_ASSERT(dev != RT_NULL);
114 
115     switch (cmd)
116     {
117     case RT_DEVICE_CTRL_RTC_GET_TIME:
118     {
119         *(uint32_t *)args = get_timestamp();
120     }
121     break;
122 
123     case RT_DEVICE_CTRL_RTC_SET_TIME:
124     {
125         set_timestamp(*(time_t *)args);
126     }
127     break;
128 
129     default:
130         return -RT_EINVAL;
131     }
132 
133     return RT_EOK;
134 }
135 
136 static struct rt_device rtc_device =
137 {
138     .type    = RT_Device_Class_RTC,
139     .init    = gd32_rtc_init,
140     .open    = gd32_rtc_open,
141     .close   = gd32_rtc_close,
142     .read    = gd32_rtc_read,
143     .write   = gd32_rtc_write,
144     .control = gd32_rtc_control,
145 };
146 
rt_hw_rtc_init(void)147 int rt_hw_rtc_init(void)
148 {
149     rt_err_t ret = RT_EOK;
150 
151     ret = rt_device_register(&rtc_device, "rtc", RT_DEVICE_FLAG_RDWR);
152 
153     rt_device_open(&rtc_device, RT_DEVICE_OFLAG_RDWR);
154 
155     return RT_EOK;
156 }
157 
158 INIT_DEVICE_EXPORT(rt_hw_rtc_init);
159 
160 #endif /* BSP_USING_RTC */
161