1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date         Author      Notes
8  * 2009-01-05   Bernard     the first version
9  * 2010-12-27   onelife     Modify for EFM32
10  * 2011-06-16   onelife     Modify init function for efm32lib v2 upgrading
11  * 2011-12-14   onelife     Move LFXO enabling routine to driver initialization function (board.c)
12  */
13 
14 /***************************************************************************//**
15  * @addtogroup efm32
16  * @{
17  ******************************************************************************/
18 
19 /* Includes ------------------------------------------------------------------*/
20 
21 #include <rtdevice.h>
22 #include "board.h"
23 #include "hdl_interrupt.h"
24 #include "drv_rtc.h"
25 
26 #if defined(RT_USING_RTC)
27 /* Private typedef -----------------------------------------------------------*/
28 /* Private define ------------------------------------------------------------*/
29 /* Private macro -------------------------------------------------------------*/
30 #ifdef RT_RTC_DEBUG
31 #define rtc_debug(format,args...)           rt_kprintf(format, ##args)
32 #else
33 #define rtc_debug(format,args...)
34 #endif
35 
36 /* Private variables ---------------------------------------------------------*/
37 static struct rt_device rtc;
38 static rt_uint32_t rtc_time;
39 
40 /* Private function prototypes -----------------------------------------------*/
41 /* Private functions ---------------------------------------------------------*/
rt_rtc_open(rt_device_t dev,rt_uint16_t oflag)42 static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag)
43 {
44     if (dev->rx_indicate != RT_NULL)
45     {
46         /* Open Interrupt */
47     }
48 
49     return RT_EOK;
50 }
51 
rt_rtc_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)52 static rt_ssize_t rt_rtc_read(
53     rt_device_t     dev,
54     rt_off_t        pos,
55     void*           buffer,
56     rt_size_t       size)
57 {
58     return 0;
59 }
60 
61 /***************************************************************************//**
62  * @brief
63  *  Configure RTC device
64  *
65  * @details
66  *
67  * @note
68  *
69  * @param[in] dev
70  *  Pointer to device descriptor
71  *
72  * @param[in] cmd
73  *  RTC control command
74  *
75  * @param[in] args
76  *  Arguments
77  *
78  * @return
79  *  Error code
80  ******************************************************************************/
rt_rtc_control(rt_device_t dev,int cmd,void * args)81 static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args)
82 {
83     RT_ASSERT(dev != RT_NULL);
84 
85     switch (cmd)
86     {
87     case RT_DEVICE_CTRL_RTC_GET_TIME:
88         *(rt_uint32_t *)args = rtc_time + RTC_CounterGet();
89         rtc_debug("RTC: get rtc_time %x + %x\n", rtc_time, RTC_CounterGet());
90         break;
91 
92     case RT_DEVICE_CTRL_RTC_SET_TIME:
93     {
94         rtc_time = *(rt_uint32_t *)args;
95         rtc_debug("RTC: set rtc_time %x\n", rtc_time);
96 
97         /* Reset counter */
98         RTC_CounterReset();
99     }
100     break;
101     }
102 
103     return RT_EOK;
104 }
105 
106 /***************************************************************************//**
107  * @brief
108  *  RTC counter overflow interrupt handler
109  *
110  * @details
111  *
112  * @note
113  ******************************************************************************/
rt_hw_rtc_isr(rt_device_t device)114 void rt_hw_rtc_isr(rt_device_t device)
115 {
116     if (RTC->IF & RTC_IFC_OF)
117     {
118         rtc_time += _RTC_CNT_MASK;
119     }
120 
121     RTC->IFC = _RTC_IFC_MASK;
122 }
123 
124 /***************************************************************************//**
125  * @brief
126  *  Initialize all RTC module related hardware and register RTC device to kernel
127  *
128  * @details
129  *
130  * @note
131  ******************************************************************************/
rt_hw_rtc_init(void)132 void rt_hw_rtc_init(void)
133 {
134     rt_uint32_t reset;
135 
136     reset = RMU_ResetCauseGet();
137 
138     // TODO: What is the current reset mode?
139     if (reset & RMU_RSTCAUSE_PORST || reset & RMU_RSTCAUSE_EXTRST)
140     {
141         RTC_Init_TypeDef rtcInit;
142         efm32_irq_hook_init_t hook;
143 
144         rtcInit.enable = true;
145         rtcInit.debugRun = false;
146         rtcInit.comp0Top = false;
147 
148         rtc_time = 0UL;
149 
150         rt_kprintf("rtc is not configured\n");
151         rt_kprintf("please configure with set_date and set_time\n");
152 
153         /* Configuring clock */
154         CMU_ClockDivSet(cmuClock_RTC,cmuClkDiv_32768);
155         CMU_ClockEnable(cmuClock_RTC, true);
156 
157         /* Initialize and enable RTC */
158         RTC_Reset();
159         RTC_Init(&rtcInit);
160 
161         hook.type       = efm32_irq_type_rtc;
162         hook.unit       = 0;
163         hook.cbFunc     = rt_hw_rtc_isr;
164         hook.userPtr    = RT_NULL;
165         efm32_irq_hook_register(&hook);
166 
167         /* Enabling Interrupt from RTC */
168         RTC_IntEnable(RTC_IFC_OF);
169         RTC_IntClear(RTC_IFC_OF);
170 
171         NVIC_ClearPendingIRQ(RTC_IRQn);
172         NVIC_SetPriority(RTC_IRQn, EFM32_IRQ_PRI_DEFAULT);
173         NVIC_EnableIRQ(RTC_IRQn);
174     }
175 
176     /* register rtc device */
177     rtc.type        = RT_Device_Class_RTC;
178     rtc.rx_indicate = RT_NULL;
179     rtc.tx_complete = RT_NULL;
180     rtc.init        = RT_NULL;
181     rtc.open        = rt_rtc_open;
182     rtc.close       = RT_NULL;
183     rtc.read        = rt_rtc_read;
184     rtc.write       = RT_NULL;
185     rtc.control     = rt_rtc_control;
186     rtc.user_data   = RT_NULL; /* no private */
187 
188     rt_device_register(&rtc, RT_RTC_NAME, RT_DEVICE_FLAG_RDWR | EFM32_NO_DATA);
189 }
190 
191 #endif
192 
193 /***************************************************************************//**
194  * @}
195  ******************************************************************************/
196