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 #include <rtthread.h>
33 #include <rthw.h>
34 #include <rtdevice.h>
35 #include <riscv_io.h>
36 #include <rtdef.h>
37 #include "ioremap.h"
38 #include "drv_gpio.h"
39 #include "drv_hardlock.h"
40 #include "board.h"
41 #include <dfs_posix.h>
42 #include <lwp_user_mm.h>
43 #include <sys/ioctl.h>
44 #include <rtdbg.h>
45
46 #define DBG_TAG "GPIO"
47 #ifdef RT_DEBUG
48 #define DBG_LVL DBG_LOG
49 #else
50 #define DBG_LVL DBG_WARNING
51 #endif
52 #define DBG_COLOR
53
54 struct kd_gpio_device {
55 struct rt_device dev;
56 void* base[2];
57 int hardlock;
58 };
59
60 static struct kd_gpio_device gpio_dev;
61
62 static struct
63 {
64 void (*hdr)(void* args);
65 void* args;
66 gpio_pin_edge_t edge;
67 int debounce;
68 struct rt_work debounce_work;
69 struct rt_work send_sig_work;
70 struct rt_lwp* lwp;
71 int lwp_ref_cnt;
72 int signo;
73 void* sigval;
74 } irq_table[GPIO_MAX_NUM];
75
kd_gpio_reg_writel(void * reg,rt_size_t offset,rt_uint32_t value)76 static void kd_gpio_reg_writel(void* reg, rt_size_t offset, rt_uint32_t value)
77 {
78 while (0 != kd_hardlock_lock(gpio_dev.hardlock))
79 ;
80 rt_uint32_t val = readl(reg);
81 val &= ~(1 << offset);
82 val |= (value << offset);
83 writel(val, reg);
84 kd_hardlock_unlock(gpio_dev.hardlock);
85 }
86
kd_gpio_reg_readl(void * reg,rt_size_t offset)87 static rt_uint32_t kd_gpio_reg_readl(void* reg, rt_size_t offset)
88 {
89 rt_uint32_t val = readl(reg);
90 return (val & (1 << offset)) >> offset;
91 }
92
check_pin_valid(rt_base_t pin)93 static int check_pin_valid(rt_base_t pin)
94 {
95 if ((rt_uint16_t)pin < 0 || (rt_uint16_t)pin > GPIO_MAX_NUM)
96 {
97 LOG_E("pin %d is not valid\n", pin);
98 return -RT_EINVAL;
99 }
100 return pin;
101 }
102
kd_pin_mode(rt_base_t pin,rt_base_t mode)103 rt_err_t kd_pin_mode(rt_base_t pin, rt_base_t mode)
104 {
105 void* reg;
106 uint32_t dir;
107
108 if (check_pin_valid(pin) < 0)
109 return -RT_EINVAL;
110
111 switch (mode)
112 {
113 case GPIO_DM_INPUT:
114 dir = 0;
115 break;
116 case GPIO_DM_OUTPUT:
117 dir = 1;
118 break;
119 default:
120 LOG_E("GPIO drive mode is not supported.");
121 return -RT_EINVAL;
122 }
123
124 if (pin < 32)
125 {
126 reg = gpio_dev.base[0] + DIRECTION;
127 } else {
128 pin -= 32;
129 if (pin < 32)
130 {
131 reg = gpio_dev.base[1] + DIRECTION;
132 } else {
133 reg = gpio_dev.base[1] + DIRECTION + DIRECTION_STRIDE;
134 pin -= 32;
135 }
136 }
137
138 kd_gpio_reg_writel(reg, pin, dir);
139
140 return RT_EOK;
141 }
142
kd_pin_mode_get(rt_base_t pin)143 int kd_pin_mode_get(rt_base_t pin)
144 {
145 void* reg;
146
147 if (check_pin_valid(pin) < 0)
148 return -RT_EINVAL;
149
150 if (pin < 32)
151 {
152 reg = gpio_dev.base[0] + DIRECTION;
153 } else {
154 pin -= 32;
155 if (pin < 32)
156 {
157 reg = gpio_dev.base[1] + DIRECTION;
158 } else {
159 reg = gpio_dev.base[1] + DIRECTION + DIRECTION_STRIDE;
160 pin -= 32;
161 }
162 }
163
164 return kd_gpio_reg_readl(reg, pin) ? GPIO_DM_OUTPUT : GPIO_DM_INPUT;
165 }
166
kd_pin_write(rt_base_t pin,rt_base_t value)167 rt_err_t kd_pin_write(rt_base_t pin, rt_base_t value)
168 {
169 void* reg;
170
171 if (check_pin_valid(pin) < 0)
172 return -RT_EINVAL;
173
174 if (pin < 32)
175 {
176 reg = gpio_dev.base[0] + DATA_OUTPUT;
177 } else {
178 pin -= 32;
179 if (pin < 32)
180 {
181 reg = gpio_dev.base[1] + DATA_OUTPUT;
182 } else {
183 reg = gpio_dev.base[1] + DATA_OUTPUT + DATA_INPUT_STRIDE;
184 pin -= 32;
185 }
186 }
187
188 kd_gpio_reg_writel(reg, pin, value ? GPIO_PV_HIGH : GPIO_PV_LOW);
189
190 return RT_EOK;
191 }
192
kd_pin_read(rt_base_t pin)193 int kd_pin_read(rt_base_t pin)
194 {
195 void* reg;
196
197 if (check_pin_valid(pin) < 0)
198 return -RT_EINVAL;
199
200 if (pin < 32)
201 {
202 reg = gpio_dev.base[0] + DATA_INPUT;
203 } else {
204 pin -= 32;
205 if (pin < 32)
206 {
207 reg = gpio_dev.base[1] + DATA_INPUT;
208 } else {
209 reg = gpio_dev.base[1] + DATA_INPUT + DATA_INPUT_STRIDE;
210 pin -= 32;
211 }
212 }
213
214 return kd_gpio_reg_readl(reg, pin) ? GPIO_PV_HIGH : GPIO_PV_LOW;
215 }
216
kd_set_pin_edge(rt_int32_t pin,gpio_pin_edge_t edge)217 static int kd_set_pin_edge(rt_int32_t pin, gpio_pin_edge_t edge)
218 {
219 void* reg;
220
221 reg = gpio_dev.base[pin >> 5];
222 pin = pin & 0x1f;
223
224 switch (edge)
225 {
226 case GPIO_PE_RISING:
227 kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x1);
228 kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x1);
229 kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
230 break;
231 case GPIO_PE_FALLING:
232 kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x1);
233 kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x0);
234 kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
235 break;
236 case GPIO_PE_BOTH:
237 kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x1);
238 break;
239 case GPIO_PE_LOW:
240 kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x0);
241 kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x0);
242 kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
243 break;
244 case GPIO_PE_HIGH:
245 kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x0);
246 kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x1);
247 kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
248 break;
249 default:
250 break;
251 }
252
253 kd_gpio_reg_writel(reg + INT_ENABLE, pin, 0x1);
254
255 return RT_EOK;
256 }
257
debounce_work(struct rt_work * work,void * param)258 static void debounce_work(struct rt_work* work, void* param)
259 {
260 void* reg;
261 rt_size_t pin = (rt_size_t)param;
262
263 reg = gpio_dev.base[pin >> 5];
264 pin = pin & 0x1f;
265
266 rt_base_t level = rt_hw_interrupt_disable();
267 kd_gpio_reg_writel(reg + INT_MASK, pin, 0x0);
268 rt_hw_interrupt_enable(level);
269 }
270
pin_irq(int vector,void * param)271 static void pin_irq(int vector, void* param)
272 {
273 void* reg;
274 long pin = vector - IRQN_GPIO0_INTERRUPT;
275 gpio_pin_edge_t edge = irq_table[pin].edge;
276 long pin_offset;
277
278 reg = gpio_dev.base[pin >> 5];
279 pin_offset = pin & 0x1f;
280
281 switch (edge)
282 {
283 case GPIO_PE_RISING:
284 case GPIO_PE_FALLING:
285 case GPIO_PE_BOTH:
286 kd_gpio_reg_writel(reg + INT_CLEAR, pin_offset, 0x1);
287 break;
288 case GPIO_PE_LOW:
289 case GPIO_PE_HIGH:
290 kd_gpio_reg_writel(reg + INT_MASK, pin_offset, 0x1);
291 rt_work_init(&irq_table[pin].debounce_work, debounce_work, (void *)pin);
292 rt_work_submit(&irq_table[pin].debounce_work, irq_table[pin].debounce);
293 break;
294 default:
295 break;
296 }
297
298 if (irq_table[pin].hdr)
299 irq_table[pin].hdr(irq_table[pin].args);
300 }
301
gpio_irq_to_user(void * args)302 static void gpio_irq_to_user(void* args)
303 {
304 }
305
kd_pin_attach_irq(rt_int32_t pin,rt_uint32_t mode,void (* hdr)(void * args),void * args)306 rt_err_t kd_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void* args), void* args)
307 {
308 char irq_name[10];
309
310 if (check_pin_valid(pin) < 0)
311 return -RT_EINVAL;
312 if (pin >= GPIO_IRQ_MAX_NUM)
313 {
314 LOG_E("pin %d not support interrupt", pin);
315 return -RT_EINVAL;
316 }
317
318 irq_table[pin].hdr = hdr;
319 irq_table[pin].args = args;
320 if (hdr != gpio_irq_to_user)
321 {
322 irq_table[pin].lwp = NULL;
323 irq_table[pin].lwp_ref_cnt = 0;
324 }
325
326 if (mode < 0 || mode > 4)
327 return -RT_EINVAL;
328 irq_table[pin].edge = mode;
329 irq_table[pin].debounce = rt_tick_from_millisecond(10);
330
331 kd_set_pin_edge(pin, irq_table[pin].edge);
332 rt_snprintf(irq_name, sizeof irq_name, "pin%d", pin);
333 rt_hw_interrupt_install(IRQN_GPIO0_INTERRUPT + pin, pin_irq, RT_NULL, irq_name);
334
335 return RT_EOK;
336 }
337
kd_pin_detach_irq(rt_int32_t pin)338 rt_err_t kd_pin_detach_irq(rt_int32_t pin)
339 {
340 void* reg;
341
342 if (check_pin_valid(pin) < 0)
343 return -RT_EINVAL;
344 if (pin >= GPIO_IRQ_MAX_NUM)
345 {
346 LOG_E("pin %d not support interrupt", pin);
347 return -RT_EINVAL;
348 }
349
350 irq_table[pin].hdr = RT_NULL;
351 irq_table[pin].args = RT_NULL;
352 irq_table[pin].lwp = NULL;
353 irq_table[pin].lwp_ref_cnt = 0;
354 irq_table[pin].signo = 0;
355 irq_table[pin].sigval = 0;
356
357 reg = gpio_dev.base[pin >> 5];
358 pin = pin & 0x1f;
359 kd_gpio_reg_writel(reg + INT_ENABLE, pin, 0x0);
360
361 return RT_EOK;
362 }
363
kd_pin_irq_enable(rt_base_t pin,rt_uint32_t enabled)364 rt_err_t kd_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled)
365 {
366 if (check_pin_valid(pin) < 0)
367 return -RT_EINVAL;
368 if (pin >= GPIO_IRQ_MAX_NUM)
369 {
370 LOG_E("pin %d not support interrupt", pin);
371 return -RT_EINVAL;
372 }
373
374 if (enabled)
375 rt_hw_interrupt_umask(IRQN_GPIO0_INTERRUPT + pin);
376 else
377 rt_hw_interrupt_mask(IRQN_GPIO0_INTERRUPT + pin);
378
379 return RT_EOK;
380 }
381
rt_hw_gpio_init(void)382 int rt_hw_gpio_init(void)
383 {
384 rt_err_t ret;
385
386 gpio_dev.base[0] = rt_ioremap((void*)GPIO0_BASE_ADDR, GPIO0_IO_SIZE);
387 gpio_dev.base[1] = rt_ioremap((void*)GPIO1_BASE_ADDR, GPIO1_IO_SIZE);
388
389 if (kd_request_lock(HARDLOCK_GPIO))
390 {
391 rt_kprintf("fail to request hardlock-%d\n", HARDLOCK_GPIO);
392 return -RT_ERROR;
393 }
394 gpio_dev.hardlock = HARDLOCK_GPIO;
395
396 ret = rt_device_register(&gpio_dev.dev, "gpio", RT_DEVICE_FLAG_RDWR);
397
398 return ret;
399 }
400 INIT_BOARD_EXPORT(rt_hw_gpio_init);