1 /* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * 1. Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * 2. Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 *
11 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
12 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
13 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
16 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
17 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 /*
27 * Copyright (c) 2006-2025, RT-Thread Development Team
28 *
29 * SPDX-License-Identifier: Apache-2.0
30 */
31
32 /*
33 * K230 Hardware Timer Driver
34 *
35 * K230 provides 9 timers, 6 general-purpose timers (TIMER0-TIMER5) and
36 * 3 STC timers.
37 * This driver only implements the general-purpose timers (TIMER0-TIMER5).
38 * This driver only supports the ONESHOT mode.
39 * Support frequency options: 12.5M(min), 25M, 50M, 100M(max)
40 */
41
42 #include <rtthread.h>
43 #include <rtdevice.h>
44 #include "riscv_io.h"
45 #include "board.h"
46 #include "ioremap.h"
47 #include <rtdbg.h>
48 #include <stdbool.h>
49 #include <stdio.h>
50 #include <rthw.h>
51 #include "sysctl_rst.h"
52 #include "drv_timer.h"
53 #include <dfs_posix.h>
54
55 static void k230_timer_stop(rt_hwtimer_t *timer);
k230_timer_init(rt_hwtimer_t * timer,rt_uint32_t state)56 static void k230_timer_init(rt_hwtimer_t *timer, rt_uint32_t state)
57 {
58 struct k230_timer *kd_timer = rt_container_of(timer, struct k230_timer, device);
59
60 uint8_t id = kd_timer->id;
61 if (state == 0)
62 {
63 k230_timer_stop(timer);
64 }
65 else
66 {
67 sysctl_clk_set_leaf_parent(kd_timer->clk, kd_timer->clk_src);
68 if (timer->freq == timer->info->minfreq)
69 sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 8);
70 if (timer->freq == timer->info->maxfreq)
71 sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 1);
72 if (timer->freq == 50*MHz)
73 sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 2);
74 if (timer->freq == 25*MHz)
75 sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 4);
76 }
77 }
78
k230_timer_start(rt_hwtimer_t * timer,rt_uint32_t cnt,rt_hwtimer_mode_t mode)79 static rt_err_t k230_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
80 {
81 struct k230_timer *kd_timer = rt_container_of(timer, struct k230_timer, device);
82 uint8_t id = kd_timer->id;
83 k230_timer_regs_t* reg = (k230_timer_regs_t *)kd_timer->base;
84 reg->channel[id].load_count = cnt;
85 reg->channel[id].control &= ~(TIMER_CR_INTERRUPT_MASK);
86 reg->channel[id].control |= (TIMER_CR_USER_MODE | TIMER_CR_ENABLE);
87 return RT_EOK;
88 }
89
k230_timer_stop(rt_hwtimer_t * timer)90 static void k230_timer_stop(rt_hwtimer_t *timer)
91 {
92 struct k230_timer *kd_timer = rt_container_of(timer, struct k230_timer, device);
93 uint8_t id = kd_timer->id;
94 k230_timer_regs_t* reg = (k230_timer_regs_t *)kd_timer->base;
95 reg->channel[id].control &= ~TIMER_CR_ENABLE;
96 reg->channel[id].control |= TIMER_CR_INTERRUPT_MASK;
97 }
98
k230_timer_get(rt_hwtimer_t * timer)99 static rt_uint32_t k230_timer_get(rt_hwtimer_t *timer)
100 {
101 struct k230_timer *kd_timer = rt_container_of(timer, struct k230_timer, device);
102 uint8_t id = kd_timer->id;
103 k230_timer_regs_t* reg = (k230_timer_regs_t *)kd_timer->base;
104 return reg->channel[id].current_value;
105 }
106
k230_timer_ctrl(rt_hwtimer_t * timer,rt_uint32_t cmd,void * arg)107 static rt_err_t k230_timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
108 {
109 struct k230_timer *kd_timer = rt_container_of(timer, struct k230_timer, device);
110
111 switch (cmd)
112 {
113 case HWTIMER_CTRL_FREQ_SET:
114 timer->freq = *((rt_uint32_t*)arg);
115 sysctl_clk_set_leaf_parent(kd_timer->clk, kd_timer->clk_src);
116 if (timer->freq == timer->info->minfreq)
117 sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 8);
118 if (timer->freq == timer->info->maxfreq)
119 sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 1);
120 if (timer->freq == 50*MHz)
121 sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 2);
122 if (timer->freq == 25*MHz)
123 sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 4);
124 break;
125 case HWTIMER_CTRL_STOP:
126 k230_timer_stop(timer);
127 break;
128 case HWTIMER_CTRL_INFO_GET:
129 if (arg == RT_NULL)
130 {
131 LOG_E("HWTIMER_CTRL_INFO_GET arg is NULL");
132 return -RT_ERROR;
133 }
134 *(struct rt_hwtimer_info *)arg = *(kd_timer->device.info);
135 break;
136 case HWTIMER_CTRL_MODE_SET:
137 if (arg == RT_NULL)
138 {
139 LOG_E("HWTIMER_CTRL_MODE_SET arg is NULL");
140 return -RT_ERROR;
141 }
142 timer->mode = *(rt_hwtimer_mode_t *)arg;
143 if (timer->mode != HWTIMER_MODE_ONESHOT)
144 {
145 LOG_E("mode is invalid/unsupported, only ONESHOT is supported");
146 return -RT_ERROR;
147 }
148 break;
149 default:
150 LOG_E("HWTIMER_CTRL cmd is invalid");
151 return -RT_ERROR;
152 }
153 return RT_EOK;
154 }
155
k230_timer_fops_open(struct dfs_file * fd)156 static int k230_timer_fops_open(struct dfs_file* fd)
157 {
158 rt_device_t device = (rt_device_t)fd->vnode->data;
159 return rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
160 }
161
k230_timer_fops_close(struct dfs_file * fd)162 static int k230_timer_fops_close(struct dfs_file* fd)
163 {
164 rt_device_t device = (rt_device_t)fd->vnode->data;
165 return rt_device_close(device);
166 }
167
168 static const struct rt_hwtimer_info k230_timer_info =
169 {
170 100000000, /* the maximum count frequency can be set */
171 12500000, /* the minimum count frequency can be set */
172 0xFFFFFFFF, /* the maximum counter value */
173 HWTIMER_CNTMODE_DW, /* Increment or Decreasing count mode */
174 };
175
176 static const struct rt_hwtimer_ops k230_timer_ops =
177 {
178 .init = k230_timer_init,
179 .start = k230_timer_start,
180 .stop = k230_timer_stop,
181 .count_get = k230_timer_get,
182 .control = k230_timer_ctrl,
183 };
184
185 static const struct dfs_file_ops k230_timer_fops = {
186 k230_timer_fops_open,
187 k230_timer_fops_close,
188 };
189
k230_hwtimer_isr(int vector,void * param)190 void k230_hwtimer_isr(int vector, void *param)
191 {
192 uint32_t ret;
193 struct k230_timer *kd_timer = (struct k230_timer *)param;
194 rt_hwtimer_t *hwtimer = (rt_hwtimer_t *)&(kd_timer->device);
195
196 RT_ASSERT(kd_timer != RT_NULL && hwtimer != RT_NULL);
197
198 int id = kd_timer->id;
199 k230_timer_regs_t* reg = (k230_timer_regs_t *)kd_timer->base;
200
201 ret = (reg->channel[id].eoi);
202
203 rt_device_hwtimer_isr(hwtimer);
204 }
205
206 static struct k230_timer timer_devices[] =
207 {
208 #ifdef BSP_USING_TIMER0
209 {
210 .device.info = &k230_timer_info,
211 .device.ops = &k230_timer_ops,
212 .device.parent.fops = &k230_timer_fops,
213
214 .name = "hwtimer0",
215 .id = 0,
216 .clk = SYSCTL_CLK_TIMER0,
217 .clk_src = SYSCTL_CLK_TIMER0_SRC,
218 .irq_num = IRQN_TIMER_0_INTERRUPT
219 },
220 #endif /* BSP_USING_TIMER0 */
221
222 #ifdef BSP_USING_TIMER1
223 {
224 .device.info = &k230_timer_info,
225 .device.ops = &k230_timer_ops,
226 .device.parent.fops = &k230_timer_fops,
227
228 .name = "hwtimer1",
229 .id = 1,
230 .clk = SYSCTL_CLK_TIMER1,
231 .clk_src = SYSCTL_CLK_TIMER1_SRC,
232 .irq_num = IRQN_TIMER_1_INTERRUPT
233 },
234 #endif /* BSP_USING_TIMER1 */
235
236 #ifdef BSP_USING_TIMER2
237 {
238 .device.info = &k230_timer_info,
239 .device.ops = &k230_timer_ops,
240 .device.parent.fops = &k230_timer_fops,
241
242 .name = "hwtimer2",
243 .id = 2,
244 .clk = SYSCTL_CLK_TIMER2,
245 .clk_src = SYSCTL_CLK_TIMER2_SRC,
246 .irq_num = IRQN_TIMER_2_INTERRUPT
247 },
248 #endif /* BSP_USING_TIMER0 */
249
250 #ifdef BSP_USING_TIMER3
251 {
252 .device.info = &k230_timer_info,
253 .device.ops = &k230_timer_ops,
254 .device.parent.fops = &k230_timer_fops,
255
256 .name = "hwtimer3",
257 .id = 3,
258 .clk = SYSCTL_CLK_TIMER3,
259 .clk_src = SYSCTL_CLK_TIMER3_SRC,
260 .irq_num = IRQN_TIMER_3_INTERRUPT
261 },
262 #endif /* BSP_USING_TIMER3 */
263
264 #ifdef BSP_USING_TIMER4
265 {
266 .device.info = &k230_timer_info,
267 .device.ops = &k230_timer_ops,
268 .device.parent.fops = &k230_timer_fops,
269
270 .name = "hwtimer4",
271 .id = 4,
272 .clk = SYSCTL_CLK_TIMER4,
273 .clk_src = SYSCTL_CLK_TIMER4_SRC,
274 .irq_num = IRQN_TIMER_4_INTERRUPT
275 },
276 #endif /* BSP_USING_TIMER4 */
277
278 #ifdef BSP_USING_TIMER5
279 {
280 .device.info = &k230_timer_info,
281 .device.ops = &k230_timer_ops,
282 .device.parent.fops = &k230_timer_fops,
283
284 .name = "hwtimer5",
285 .id = 5,
286 .clk = SYSCTL_CLK_TIMER5,
287 .clk_src = SYSCTL_CLK_TIMER5_SRC,
288 .irq_num = IRQN_TIMER_5_INTERRUPT
289 },
290 #endif /* BSP_USING_TIMER5 */
291
292 #if !defined(BSP_USING_TIMER0) && \
293 !defined(BSP_USING_TIMER1) && \
294 !defined(BSP_USING_TIMER2) && \
295 !defined(BSP_USING_TIMER3) && \
296 !defined(BSP_USING_TIMER4) && \
297 !defined(BSP_USING_TIMER5)
298 #error "No hardware timer device enabled!"
299 #endif
300 };
301
rt_hw_timer_init(void)302 int rt_hw_timer_init(void)
303 {
304 rt_uint8_t i, array_size;
305
306 array_size = sizeof(timer_devices) / sizeof(struct k230_timer);
307 if (array_size == 0)
308 {
309 LOG_E("No timer device defined!");
310 return -RT_ERROR;
311 }
312
313 volatile void* base = (void *)rt_ioremap((void *)HW_TIMER_BASE_ADDR, HW_TIMER_IO_SIZE);
314 for (i = 0; i < array_size; i++)
315 {
316 timer_devices[i].base = (rt_ubase_t)base;
317
318 if (rt_device_hwtimer_register(&timer_devices[i].device, timer_devices[i].name, RT_NULL) != RT_EOK)
319 {
320 LOG_E("%s register failed!", timer_devices[i].name);
321 return -RT_ERROR;
322 }
323 LOG_D("%s register OK!", timer_devices[i].name);
324
325 rt_hw_interrupt_install(timer_devices[i].irq_num,
326 k230_hwtimer_isr,
327 &timer_devices[i],
328 timer_devices[i].name);
329 rt_hw_interrupt_umask(timer_devices[i].irq_num);
330 }
331 return RT_EOK;
332 }
333 INIT_BOARD_EXPORT(rt_hw_timer_init);