1 /*
2  * Copyright (c) 2022-2023 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <rtthread.h>
9 #include <rtdevice.h>
10 #include <rtdbg.h>
11 #ifdef RT_USING_HWTIMER
12 
13 #include "drv_hwtimer.h"
14 #include "board.h"
15 #include "hpm_gptmr_drv.h"
16 
17 
18 typedef struct _hpm_gptimer
19 {
20     GPTMR_Type *base;
21     const char *name;
22     rt_hwtimer_t timer;
23     uint32_t channel;
24     clock_name_t clock_name;
25     int32_t irq_num;
26 } hpm_gptimer_t;
27 
28 static void hpm_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state);
29 static rt_err_t hpm_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode);
30 static void hpm_hwtimer_stop(rt_hwtimer_t *timer);
31 static rt_uint32_t hpm_hwtimer_count_get(rt_hwtimer_t *timer);
32 static rt_err_t hpm_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
33 
34 static void hpm_hwtmr_isr(hpm_gptimer_t *gptmr);
35 
36 static const struct rt_hwtimer_ops hpm_hwtimer_ops = {
37         .init = hpm_hwtimer_init,
38         .start = hpm_hwtimer_start,
39         .stop = hpm_hwtimer_stop,
40         .count_get = hpm_hwtimer_count_get,
41         .control = hpm_hwtimer_control
42 };
43 
44 static const struct rt_hwtimer_info hpm_hwtimer_info = {
45         .maxfreq = 100000000UL,
46         .minfreq = 93750UL,
47         .maxcnt = 0xFFFFFFFFUL,
48         .cntmode = HWTIMER_CNTMODE_UP
49 };
50 
51 
52 #ifdef BSP_USING_GPTMR0
53 static hpm_gptimer_t timer0 = {.name = "GPT0", .base = HPM_GPTMR0, .clock_name = clock_gptmr0, .irq_num = IRQn_GPTMR0 };
54 #endif
55 #ifdef BSP_USING_GPTMR1
56 static hpm_gptimer_t timer1 = {.name = "GPT1", .base = HPM_GPTMR1, .clock_name = clock_gptmr1, .irq_num = IRQn_GPTMR1 };
57 #endif
58 #ifdef BSP_USING_GPTMR2
59 static hpm_gptimer_t timer2 = {.name = "GPT2", .base = HPM_GPTMR2, .clock_name = clock_gptmr2, .irq_num = IRQn_GPTMR2 };
60 #endif
61 #ifdef BSP_USING_GPTMR3
62 static hpm_gptimer_t timer3 = {.name = "GPT3", .base = HPM_GPTMR3, .clock_name = clock_gptmr3, .irq_num = IRQn_GPTMR3 };
63 #endif
64 #ifdef BSP_USING_GPTMR4
65 static hpm_gptimer_t timer4 = {.name = "GPT4", .base = HPM_GPTMR4, .clock_name = clock_gptmr4, .irq_num = IRQn_GPTMR4 };
66 #endif
67 #ifdef BSP_USING_GPTMR5
68 static hpm_gptimer_t timer5 = {.name = "GPT5", .base = HPM_GPTMR5, .clock_name = clock_gptmr5, .irq_num = IRQn_GPTMR5 };
69 #endif
70 #ifdef BSP_USING_GPTMR6
71 static hpm_gptimer_t timer6 = {.name = "GPT6", .base = HPM_GPTMR6, .clock_name = clock_gptmr6, .irq_num = IRQn_GPTMR6 };
72 #endif
73 #ifdef BSP_USING_GPTMR7
74 static hpm_gptimer_t timer7 = {.name = "GPT7", .base = HPM_GPTMR7, .clock_name = clock_gptmr7, .irq_num = IRQn_GPTMR7 };
75 #endif
76 
77 
78 static hpm_gptimer_t *s_gptimers[] = {
79 #ifdef BSP_USING_GPTMR0
80        &timer0,
81 #endif
82 #ifdef BSP_USING_GPTMR1
83        &timer1,
84 #endif
85 #ifdef BSP_USING_GPTMR2
86        &timer2,
87 #endif
88 #ifdef BSP_USING_GPTMR3
89        &timer3,
90 #endif
91 #ifdef BSP_USING_GPTMR4
92        &timer4,
93 #endif
94 #ifdef BSP_USING_GPTMR5
95        &timer5,
96 #endif
97 #ifdef BSP_USING_GPTMR6
98        &timer6,
99 #endif
100 #ifdef BSP_USING_GPTMR7
101        &timer7,
102 #endif
103     };
104 
105 #ifdef BSP_USING_GPTMR0
gptmr0_isr(void)106 void gptmr0_isr(void)
107 {
108     hpm_hwtmr_isr(&timer0);
109 }
110 SDK_DECLARE_EXT_ISR_M(IRQn_GPTMR0, gptmr0_isr);
111 #endif
112 
113 #ifdef BSP_USING_GPTMR1
gptmr1_isr(void)114 void gptmr1_isr(void)
115 {
116     hpm_hwtmr_isr(&timer1);
117 }
118 SDK_DECLARE_EXT_ISR_M(IRQn_GPTMR1, gptmr1_isr);
119 #endif
120 
121 #ifdef BSP_USING_GPTMR2
gptmr2_isr(void)122 void gptmr2_isr(void)
123 {
124     hpm_hwtmr_isr(&timer2);
125 }
126 SDK_DECLARE_EXT_ISR_M(IRQn_GPTMR2, gptmr2_isr);
127 #endif
128 
129 #ifdef BSP_USING_GPTMR3
gptmr3_isr(void)130 void gptmr3_isr(void)
131 {
132     hpm_hwtmr_isr(&timer3);
133 }
134 SDK_DECLARE_EXT_ISR_M(IRQn_GPTMR3, gptmr3_isr);
135 #endif
136 
137 #ifdef BSP_USING_GPTMR4
gptmr4_isr(void)138 void gptmr4_isr(void)
139 {
140     hpm_hwtmr_isr(&timer4);
141 }
142 SDK_DECLARE_EXT_ISR_M(IRQn_GPTMR4, gptmr4_isr);
143 #endif
144 
145 #ifdef BSP_USING_GPTMR5
gptmr5_isr(void)146 void gptmr5_isr(void)
147 {
148     hpm_hwtmr_isr(&timer5);
149 }
150 SDK_DECLARE_EXT_ISR_M(IRQn_GPTMR5, gptmr5_isr);
151 #endif
152 
153 #ifdef BSP_USING_GPTMR6
gptmr6_isr(void)154 void gptmr6_isr(void)
155 {
156     hpm_hwtmr_isr(&timer6);
157 }
158 SDK_DECLARE_EXT_ISR_M(IRQn_GPTMR6, gptmr6_isr);
159 #endif
160 
161 #ifdef BSP_USING_GPTMR7
gptmr7_isr(void)162 void gptmr7_isr(void)
163 {
164     hpm_hwtmr_isr(&timer7);
165 }
166 SDK_DECLARE_EXT_ISR_M(IRQn_GPTMR7, gptmr7_isr);
167 #endif
168 
hpm_hwtmr_isr(hpm_gptimer_t * timer)169 static void hpm_hwtmr_isr(hpm_gptimer_t *timer)
170 {
171     uint32_t hwtmr_stat = gptmr_get_status(timer->base);
172     if ((hwtmr_stat & GPTMR_CH_RLD_STAT_MASK(timer->channel)) != 0U)
173     {
174         rt_device_hwtimer_isr(&timer->timer);
175         gptmr_clear_status(timer->base, GPTMR_CH_RLD_STAT_MASK(timer->channel));
176     }
177 }
178 
hpm_hwtimer_init(rt_hwtimer_t * timer,rt_uint32_t state)179 static void hpm_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
180 {
181     hpm_gptimer_t *hpm_gptmr = (hpm_gptimer_t*)timer->parent.user_data;
182     GPTMR_Type *base = hpm_gptmr->base;
183     gptmr_channel_config_t config;
184 
185     if (state == 1)
186     {
187         hpm_gptmr->timer.freq = board_init_gptmr_clock(base);
188         gptmr_channel_get_default_config(base, &config);
189         gptmr_channel_config(base, hpm_gptmr->channel, &config, false);
190     }
191 }
192 
hpm_hwtimer_start(rt_hwtimer_t * timer,rt_uint32_t cnt,rt_hwtimer_mode_t mode)193 static rt_err_t hpm_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
194 {
195     hpm_gptimer_t *hpm_gptmr = (hpm_gptimer_t*) timer->parent.user_data;
196     GPTMR_Type *base = hpm_gptmr->base;
197 
198     gptmr_channel_config_t config;
199     gptmr_channel_get_default_config(base, &config);
200     config.cmp[0] = 0;
201     config.reload = cnt;
202 
203     timer->mode = mode;
204 
205     gptmr_channel_config(base, hpm_gptmr->channel, &config, true);
206 
207     gptmr_clear_status(base, 0xFU);
208     gptmr_enable_irq(base, GPTMR_CH_RLD_IRQ_MASK(hpm_gptmr->channel));
209 
210     gptmr_channel_update_count(base, hpm_gptmr->channel, 0);
211     gptmr_start_counter(base, hpm_gptmr->channel);
212 
213     intc_m_enable_irq_with_priority(hpm_gptmr->irq_num, 1);
214 
215     return RT_EOK;
216 }
217 
hpm_hwtimer_stop(rt_hwtimer_t * timer)218 static void hpm_hwtimer_stop(rt_hwtimer_t *timer)
219 {
220     hpm_gptimer_t *hpm_gptmr = (hpm_gptimer_t*)timer->parent.user_data;
221     GPTMR_Type *base = hpm_gptmr->base;
222 
223     gptmr_stop_counter(base, hpm_gptmr->channel);
224 }
225 
hpm_hwtimer_count_get(rt_hwtimer_t * timer)226 static rt_uint32_t hpm_hwtimer_count_get(rt_hwtimer_t *timer)
227 {
228     hpm_gptimer_t *hpm_gptmr = (hpm_gptimer_t*)timer->parent.user_data;
229     GPTMR_Type *base = hpm_gptmr->base;
230 
231     rt_uint32_t current_cnt = gptmr_channel_get_counter(base, hpm_gptmr->channel, gptmr_counter_type_normal);
232 
233     return current_cnt;
234 }
235 
hpm_hwtimer_control(rt_hwtimer_t * timer,rt_uint32_t cmd,void * args)236 static rt_err_t hpm_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
237 {
238     rt_err_t err = RT_EOK;
239     hpm_gptimer_t *hpm_gptmr = (hpm_gptimer_t*) timer->parent.user_data;
240     GPTMR_Type *base = hpm_gptmr->base;
241 
242     switch (cmd)
243     {
244     case HWTIMER_CTRL_FREQ_SET:
245         err = -RT_ERROR;
246         break;
247     case HWTIMER_CTRL_INFO_GET:
248         *(rt_hwtimer_t*)args = hpm_gptmr->timer;
249         break;
250     case HWTIMER_CTRL_MODE_SET:
251         hpm_gptmr->timer.mode = *(rt_uint32_t*)args;
252         break;
253     case HWTIMER_CTRL_STOP:
254         gptmr_stop_counter(base, hpm_gptmr->channel);
255         break;
256     }
257 
258     return err;
259 }
260 
261 
rt_hw_hwtimer_init(void)262 int rt_hw_hwtimer_init(void)
263 {
264     int ret = RT_EOK;
265 
266     for (uint32_t i = 0; i < ARRAY_SIZE(s_gptimers); i++)
267     {
268         s_gptimers[i]->timer.info = &hpm_hwtimer_info;
269         s_gptimers[i]->timer.ops = &hpm_hwtimer_ops;
270         ret = rt_device_hwtimer_register(&s_gptimers[i]->timer, s_gptimers[i]->name, s_gptimers[i]);
271         if (ret != RT_EOK)
272         {
273             LOG_E("%s register failed\n", s_gptimers[i]->name);
274         }
275     }
276 
277     return ret;
278 }
279 
280 INIT_BOARD_EXPORT(rt_hw_hwtimer_init);
281 
282 #endif /* BSP_USING_GPTMR */
283