• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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