1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3  * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
4  */
5 
6 #include "hal_base.h"
7 
8 #ifdef HAL_TIMER_MODULE_ENABLED
9 
10 /** @addtogroup RK_HAL_Driver
11  *  @{
12  */
13 
14 /** @addtogroup TIMER
15  *  @{
16  */
17 
18 /** @defgroup TIMER_How_To_Use How To Use
19  *  @{
20 
21  The TIMER driver can be used as follows:
22 
23  - IT mode: Resgister TIMER handler.
24  - Initialize the TIMER by calling HAL_TIMER_Init():
25  - Set TIMER count by calling HAL_TIMER_SetCount().
26  - Start the TIMER by calling HAL_TIMER_Start() or HAL_TIMER_Start_IT().
27  - Stop the TIMER by calling HAL_TIMER_Stop() or HAL_TIMER_Stop_IT().
28 
29  SYS_TIMER
30 
31  - SYS_TIMER is a rk timer fixed to serve the delay system. Invoke HAL_TIMER_SysTimerInit() to init.
32 
33  @} */
34 
35 /** @defgroup TIMER_Private_Definition Private Definition
36  *  @{
37  */
38 /********************* Private MACRO Definition ******************************/
39 #define TIMER_CONTROLREG_TIMER_MODE_FREE_RUNNING (0x0U << TIMER_CONTROLREG_TIMER_MODE_SHIFT)
40 
41 #define TIMER_CONTROLREG_TIMER_ENABLE_ENABLED  (0x1U << TIMER_CONTROLREG_TIMER_ENABLE_SHIFT)
42 #define TIMER_CONTROLREG_TIMER_ENABLE_DISABLED (0x0U << TIMER_CONTROLREG_TIMER_ENABLE_SHIFT)
43 
44 #define TIMER_CONTROLREG_TIMER_INT_MASK_UNMASK (0x1U << TIMER_CONTROLREG_TIMER_INT_MASK_SHIFT)
45 
46 /********************* Private Structure Definition **************************/
47 
48 /********************* Private Variable Definition ***************************/
49 
50 /********************* Private Function Definition ***************************/
51 
52 /** @} */
53 /********************* Public Function Definition ****************************/
54 
55 /** @defgroup TIMER_Exported_Functions_Group4 Init and DeInit Functions
56 
57  This section provides functions allowing to init and deinit module as follows:
58 
59  *  @{
60  */
61 
62 /**
63  * @brief  Timer init.
64  * @param  pReg: Choose TIMER.
65  * @param  mode: Choose TIMER mode.
66  * @return HAL_Status.
67  */
HAL_TIMER_Init(struct TIMER_REG * pReg,eTIMER_MODE mode)68 HAL_Status HAL_TIMER_Init(struct TIMER_REG *pReg, eTIMER_MODE mode)
69 {
70     HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
71 #ifdef SYS_TIMER
72     if (pReg == SYS_TIMER) {
73         return HAL_BUSY;
74     }
75 #endif
76 
77     WRITE_REG(pReg->CONTROLREG, mode << TIMER_CONTROLREG_TIMER_MODE_SHIFT);
78 
79     return HAL_OK;
80 }
81 
82 /**
83  * @brief  System Timer init.
84  * @return HAL_Status.
85  * @attention this API allow direct use in the HAL layer. SYS_TTIMER is used for delay system.
86  */
HAL_TIMER_SysTimerInit(struct TIMER_REG * pReg)87 HAL_Status HAL_TIMER_SysTimerInit(struct TIMER_REG *pReg)
88 {
89     HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
90 
91     if (READ_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_MASK)) {
92         return HAL_OK;
93     }
94 
95     WRITE_REG(pReg->CONTROLREG, TIMER_FREE_RUNNING);
96     pReg->LOAD_COUNT[0] = 0xFFFFFFFFU;
97     pReg->LOAD_COUNT[1] = 0xFFFFFFFFU;
98     CLEAR_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_INT_MASK_MASK);
99     SET_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_MASK);
100 
101     return HAL_OK;
102 }
103 
104 /**
105  * @brief  Timer deinit.
106  * @param  pReg: Choose TIMER.
107  * @return HAL_Status.
108  */
HAL_TIMER_DeInit(struct TIMER_REG * pReg)109 HAL_Status HAL_TIMER_DeInit(struct TIMER_REG *pReg)
110 {
111     HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
112 #ifdef SYS_TIMER
113     if (pReg == SYS_TIMER) {
114         return HAL_BUSY;
115     }
116 #endif
117 
118     WRITE_REG(pReg->CONTROLREG, 0);
119 
120     return HAL_OK;
121 }
122 
123 /** @} */
124 
125 /** @defgroup TIMER_Exported_Functions_Group5 Other Functions
126  *  @{
127  */
128 
129 /**
130  * @brief  Start TIMER counter.
131  * @param  pReg: Choose TIMER.
132  * @return HAL_Status.
133  */
HAL_TIMER_Start(struct TIMER_REG * pReg)134 HAL_Status HAL_TIMER_Start(struct TIMER_REG *pReg)
135 {
136     HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
137 #ifdef SYS_TIMER
138     if (pReg == SYS_TIMER) {
139         return HAL_BUSY;
140     }
141 #endif
142 
143     CLEAR_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_INT_MASK_MASK);
144     SET_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_MASK);
145 
146     return HAL_OK;
147 }
148 
149 /**
150  * @brief  Stop TIMER counter.
151  * @param  pReg: Choose TIMER.
152  * @return HAL_Status.
153  * Just disable TIMER, and keep TIMER configuration.
154  */
HAL_TIMER_Stop(struct TIMER_REG * pReg)155 HAL_Status HAL_TIMER_Stop(struct TIMER_REG *pReg)
156 {
157     HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
158 #ifdef SYS_TIMER
159     if (pReg == SYS_TIMER) {
160         return HAL_BUSY;
161     }
162 #endif
163 
164     CLEAR_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_MASK);
165 
166     return HAL_OK;
167 }
168 
169 /**
170  * @brief  Start TIMER counter in interrupt mode.
171  * @param  pReg: Choose TIMER.
172  * @return HAL_Status.
173  */
HAL_TIMER_Start_IT(struct TIMER_REG * pReg)174 HAL_Status HAL_TIMER_Start_IT(struct TIMER_REG *pReg)
175 {
176     HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
177 #ifdef SYS_TIMER
178     if (pReg == SYS_TIMER) {
179         return HAL_BUSY;
180     }
181 #endif
182 
183     SET_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_ENABLED | TIMER_CONTROLREG_TIMER_INT_MASK_UNMASK);
184 
185     return HAL_OK;
186 }
187 
188 /**
189  * @brief  Stop TIMER counter in interrupt mode.
190  * @param  pReg: Choose TIMER.
191  * @return HAL_Status.
192  * Just disable TIMER, and keep TIMER configuration.
193  */
HAL_TIMER_Stop_IT(struct TIMER_REG * pReg)194 HAL_Status HAL_TIMER_Stop_IT(struct TIMER_REG *pReg)
195 {
196     HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
197 #ifdef SYS_TIMER
198     if (pReg == SYS_TIMER) {
199         return HAL_BUSY;
200     }
201 #endif
202 
203     CLEAR_BIT(pReg->CONTROLREG, TIMER_CONTROLREG_TIMER_ENABLE_MASK);
204 
205     return HAL_OK;
206 }
207 
208 /**
209  * @brief  Set TIMER count number.
210  * @param  pReg: Choose TIMER.
211  * @param  timerCount: TIMER counter loading number.
212  * @return HAL_Status.
213  * Set timer count number.
214  */
HAL_TIMER_SetCount(struct TIMER_REG * pReg,uint64_t timerCount)215 HAL_Status HAL_TIMER_SetCount(struct TIMER_REG *pReg, uint64_t timerCount)
216 {
217     uint64_t loadCount = 0;
218 
219     HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
220 #ifdef SYS_TIMER
221     if (pReg == SYS_TIMER) {
222         return HAL_BUSY;
223     }
224 #endif
225 
226     loadCount = timerCount;
227     pReg->LOAD_COUNT[0] = (loadCount & 0xffffffff);
228     pReg->LOAD_COUNT[1] = ((loadCount >> 32) & 0xffffffff);
229 
230     return HAL_OK;
231 }
232 
233 /**
234  * @brief  Get TIMER count number.
235  * @param  pReg: Choose TIMER.
236  * @return uint64_t: Current conut number.
237  */
238 HAL_SECTION_SRAM_CODE
HAL_TIMER_GetCount(struct TIMER_REG * pReg)239 uint64_t HAL_TIMER_GetCount(struct TIMER_REG *pReg)
240 {
241     uint32_t high, low, temp;
242 
243     HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
244 
245     do {
246         high = pReg->CURRENT_VALUE[1];
247         low = pReg->CURRENT_VALUE[0];
248         temp = pReg->CURRENT_VALUE[1];
249     } while (high != temp);
250 
251     return ((uint64_t)high << 32) | low;
252 }
253 
254 /**
255  * @brief  Clear TIMER interrupt status.
256  * @param  pReg: Choose TIMER.
257  * @return HAL_Status: HAL_OK.
258  */
HAL_TIMER_ClrInt(struct TIMER_REG * pReg)259 HAL_Status HAL_TIMER_ClrInt(struct TIMER_REG *pReg)
260 {
261     uint32_t timeOut = 1000;
262 
263     HAL_ASSERT(IS_TIMER_INSTANCE(pReg));
264 
265     pReg->INTSTATUS = 0x1;
266     while (pReg->INTSTATUS && timeOut) {
267         timeOut--;
268     }
269 
270     if (timeOut == 0) {
271         return HAL_TIMEOUT;
272     } else {
273         return HAL_OK;
274     }
275 }
276 
277 /**
278  * @brief  TIMER0 interrupt handler.
279  * @return HAL_Status: HAL_OK.
280  * Clear interrupt status.
281  */
HAL_TIMER0_Handler(void)282 __WEAK HAL_Status HAL_TIMER0_Handler(void)
283 {
284     HAL_TIMER_ClrInt(TIMER0);
285 
286     return HAL_OK;
287 }
288 
289 /**
290  * @brief  TIMER1 interrupt handler.
291  * @return HAL_Status: HAL_OK.
292  * Clear interrupt status.
293  */
HAL_TIMER1_Handler(void)294 __WEAK HAL_Status HAL_TIMER1_Handler(void)
295 {
296     HAL_TIMER_ClrInt(TIMER1);
297 
298     return HAL_OK;
299 }
300 
301 /** @} */
302 
303 /** @} */
304 
305 /** @} */
306 
307 #endif /* HAL_TIMER_MODULE_ENABLED */
308