1 /*
2 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 /**
17 * @file wm_timer.c
18 *
19 * @brief Timer Driver Module
20 *
21 * @author dave
22 *
23 * Copyright (c) 2014 Winner Microelectronics Co., Ltd.
24 */
25 #include "wm_type_def.h"
26 #include "wm_regs.h"
27 #include "wm_irq.h"
28 #include "wm_cpu.h"
29 #include "wm_pmu.h"
30 #include "wm_timer.h"
31
32 #include "tls_common.h"
33
34 enum tls_timer_id {
35 TLS_TIMER_ID_0 = 0,
36 TLS_TIMER_ID_1,
37 TLS_TIMER_ID_2,
38 TLS_TIMER_ID_3,
39 TLS_TIMER_ID_4,
40 TLS_TIMER_ID_5,
41 TLS_TIMER_ID_MAX
42 };
43
44 struct timer_irq_context {
45 tls_timer_irq_callback callback;
46 void *arg;
47 };
48
49 static struct timer_irq_context timer_context[TLS_TIMER_ID_MAX] = {{0, 0}};
50 static u8 wm_timer_bitmap = 0;
51
timer_clear_irq(int timer_id)52 static void timer_clear_irq(int timer_id)
53 {
54 volatile u8 i;
55 volatile u32 value;
56
57 value = tls_reg_read32(HR_TIMER0_5_CSR);
58 for (i = TLS_TIMER_ID_0; i < TLS_TIMER_ID_MAX; i++) {
59 value &= ~(TLS_TIMER_INT_CLR(i));
60 }
61
62 tls_reg_write32(HR_TIMER0_5_CSR, value | TLS_TIMER_INT_CLR(timer_id));
63 }
64
timer_irq_callback(void * p)65 static void timer_irq_callback(void *p)
66 {
67 u8 timer_id;
68
69 timer_id = (u8)(u32)p;
70
71 if (timer_context[timer_id].callback != NULL)
72 timer_context[timer_id].callback(timer_context[timer_id].arg);
73
74 return;
75 }
76
TIMER0_5_IRQHandler(void)77 void TIMER0_5_IRQHandler(void)
78 {
79 u32 timer_csr = tls_reg_read32(HR_TIMER0_5_CSR);
80
81 tls_reg_write32(HR_TIMER0_5_CSR, timer_csr);
82
83 if (timer_csr & TLS_TIMER_INT_CLR(0)) {
84 timer_irq_callback((void *)TLS_TIMER_ID_0);
85 }
86
87 if (timer_csr & TLS_TIMER_INT_CLR(1)) {
88 timer_irq_callback((void *)TLS_TIMER_ID_1);
89 }
90
91 if (timer_csr & TLS_TIMER_INT_CLR(2)) {
92 timer_irq_callback((void *)TLS_TIMER_ID_2);
93 }
94
95 if (timer_csr & TLS_TIMER_INT_CLR(3)) {
96 timer_irq_callback((void *)TLS_TIMER_ID_3);
97 }
98
99 if (timer_csr & TLS_TIMER_INT_CLR(4)) {
100 timer_irq_callback((void *)TLS_TIMER_ID_4);
101 }
102
103 if (timer_csr & TLS_TIMER_INT_CLR(5)) {
104 timer_irq_callback((void *)TLS_TIMER_ID_5);
105 }
106 }
107
108 /**
109 * @brief This function is used to create the timer
110 *
111 * @param[in] cfg timer configuration
112 *
113 * @retval WM_TIMER_ID_INVALID failed
114 * @retval other timer id[0~5]
115 *
116 * @note
117 * user not need clear interrupt flag.
118 * timer callback function is called in interrupt,
119 * so can not operate the critical data in the callback fuuction,
120 * recommendation to send messages to other tasks to operate it.
121 */
tls_timer_create(struct tls_timer_cfg * cfg)122 u8 tls_timer_create(struct tls_timer_cfg *cfg)
123 {
124 u8 i;
125 int timer_csr;
126
127 for (i = 0; i < TLS_TIMER_ID_MAX; i++) {
128 if (!(wm_timer_bitmap & BIT(i)))
129 break;
130 }
131
132 if (TLS_TIMER_ID_MAX == i) {
133 return WM_TIMER_ID_INVALID;
134 }
135
136 if (wm_timer_bitmap == 0) {
137 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_TIMER);
138 }
139
140 wm_timer_bitmap |= BIT(i);
141 timer_context[i].callback = cfg->callback;
142 timer_context[i].arg = cfg->arg;
143
144 tls_sys_clk sysclk;
145
146 tls_sys_clk_get(&sysclk);
147 tls_reg_write32(HR_TIMER_CFG, sysclk.apbclk-1);
148
149 timer_csr = tls_reg_read32(HR_TIMER0_5_CSR);
150 if (!cfg->is_repeat)
151 timer_csr |= TLS_TIMER_ONE_TIME(i);
152 else
153 timer_csr &= ~(TLS_TIMER_ONE_TIME(i));
154 if (TLS_TIMER_UNIT_MS == cfg->unit)
155 timer_csr |= TLS_TIMER_MS_UNIT(i);
156 else
157 timer_csr &= ~(TLS_TIMER_MS_UNIT(i));
158 tls_reg_write32(HR_TIMER0_5_CSR, timer_csr | TLS_TIMER_INT_CLR(i));
159 if (cfg->timeout) {
160 tls_reg_write32(HR_TIMER0_PRD + 0x04 * i, cfg->timeout);
161 }
162
163 tls_irq_enable(TIMER_IRQn);
164
165 return i;
166 }
167
168 /**
169 * @brief This function is used to start the timer
170 *
171 * @param[in] timer_id timer id[0~5]
172 *
173 * @return None
174 *
175 * @note None
176 */
tls_timer_start(u8 timer_id)177 void tls_timer_start(u8 timer_id)
178 {
179 if (!(wm_timer_bitmap & BIT(timer_id)))
180 return;
181
182 tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR)|TLS_TIMER_INT_EN(timer_id)| \
183 TLS_TIMER_EN(timer_id));
184
185 return;
186 }
187
188 /**
189 * @brief This function is used to stop the timer
190 *
191 * @param[in] timer_id timer id[0~5]
192 *
193 * @return None
194 *
195 * @note None
196 */
tls_timer_stop(u8 timer_id)197 void tls_timer_stop(u8 timer_id)
198 {
199 if (!(wm_timer_bitmap & BIT(timer_id)))
200 return;
201
202 tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR)|TLS_TIMER_INT_CLR(timer_id));
203 tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR) &~ TLS_TIMER_EN(timer_id));
204
205 return;
206 }
207
208 /**
209 * @brief This function is used to change a timer wait time
210 *
211 * @param[in] timer_id timer id[0~5]
212 *
213 * @param[in] newtime new wait time
214 *
215 * @retval None
216 *
217 * @note If the timer does not start, this function will start the timer
218 */
tls_timer_change(u8 timer_id,u32 newtime)219 void tls_timer_change(u8 timer_id, u32 newtime)
220 {
221 if (!(wm_timer_bitmap & BIT(timer_id)))
222 return;
223
224 tls_timer_stop(timer_id);
225 if (newtime)
226 tls_reg_write32(HR_TIMER0_PRD + 0x04 * timer_id, newtime);
227 tls_timer_start(timer_id);
228
229 return;
230 }
231
232 /**
233 * @brief This function is used to read a timer's current value
234 *
235 * @param[in] timer_id timer id[0~5]
236 *
237 * @retval timer's current value
238 *
239 * @note none
240 */
tls_timer_read(u8 timer_id)241 u32 tls_timer_read(u8 timer_id)
242 {
243 u32 value;
244
245 if (!(wm_timer_bitmap & BIT(timer_id))) {
246 return 0;
247 }
248
249 value = tls_reg_read32(HR_TIMER0_CNT + 0x04 * timer_id);
250
251 return value;
252 }
253
254 /**
255 * @brief This function is used to delete the timer
256 *
257 * @param[in] timer_id timer id[0~5]
258 *
259 * @return None
260 *
261 * @note None
262 */
tls_timer_destroy(u8 timer_id)263 void tls_timer_destroy(u8 timer_id)
264 {
265 if (!(wm_timer_bitmap & BIT(timer_id)))
266 return;
267
268 tls_timer_stop(timer_id);
269
270 timer_context[timer_id].callback = NULL;
271 timer_context[timer_id].arg = NULL;
272
273 wm_timer_bitmap &= ~BIT(timer_id);
274 if (wm_timer_bitmap == 0) {
275 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_TIMER);
276 }
277
278 return;
279 }
280
281