1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023/01/5 chushicheng first version
9 *
10 */
11
12 #include "drv_gpio.h"
13 #include <stdbool.h>
14
15 #ifdef BSP_USING_GPIO
16
17 #define DBG_TAG "drv.gpio"
18 #define DBG_LVL DBG_INFO
19 #include <rtdbg.h>
20
21 static struct bflb_device_s *gpio;
22
23 static struct rt_pin_irq_hdr pin_irq_hdr_tab[GPIO_MAX];
24
gpio_isr(int irq,void * arg)25 static void gpio_isr(int irq, void *arg)
26 {
27 rt_base_t i;
28 for(i = 0; i < GPIO_MAX; i ++)
29 {
30 if(pin_irq_hdr_tab[i].pin != -1)
31 {
32 bool intstatus = bflb_gpio_get_intstatus(gpio, i);
33 if (intstatus) {
34 bflb_gpio_int_clear(gpio, i);
35 if(pin_irq_hdr_tab[i].hdr)
36 pin_irq_hdr_tab[i].hdr(pin_irq_hdr_tab[i].args);
37 }
38 }
39 }
40
41 }
42
_pin_write(rt_device_t dev,rt_base_t pin,rt_uint8_t value)43 static void _pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
44 {
45 if(value)
46 bflb_gpio_set(gpio, pin);
47 else
48 bflb_gpio_reset(gpio, pin);
49 }
50
_pin_read(rt_device_t dev,rt_base_t pin)51 static rt_ssize_t _pin_read(rt_device_t dev, rt_base_t pin)
52 {
53 return bflb_gpio_read(gpio, pin);
54 }
55
_pin_mode(rt_device_t dev,rt_base_t pin,rt_uint8_t mode)56 static void _pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
57 {
58 rt_uint32_t cfgset = 0;
59
60 switch(mode)
61 {
62 case PIN_MODE_OUTPUT:
63 cfgset = GPIO_OUTPUT;
64 break;
65
66 case PIN_MODE_INPUT:
67 cfgset = GPIO_INPUT;
68 break;
69
70 case PIN_MODE_INPUT_PULLUP:
71 cfgset = GPIO_INPUT | GPIO_PULLUP;
72 break;
73
74 case PIN_MODE_INPUT_PULLDOWN:
75 cfgset = GPIO_INPUT | GPIO_PULLDOWN;
76 break;
77
78 case PIN_MODE_OUTPUT_OD:
79 cfgset = GPIO_OUTPUT | GPIO_FLOAT;
80 break;
81
82 default:
83 cfgset = GPIO_OUTPUT | GPIO_FLOAT;
84 break;
85 }
86
87 cfgset |= GPIO_SMT_EN | GPIO_DRV_0;
88 bflb_gpio_init(gpio, pin, cfgset);
89 }
90
_pin_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t irq_mode,void (* hdr)(void * args),void * args)91 static rt_err_t _pin_attach_irq(struct rt_device *device, rt_base_t pin,
92 rt_uint8_t irq_mode, void (*hdr)(void *args), void *args)
93 {
94 rt_base_t level;
95
96 level = rt_hw_interrupt_disable();
97 if(pin_irq_hdr_tab[pin].pin == pin &&
98 pin_irq_hdr_tab[pin].hdr == hdr &&
99 pin_irq_hdr_tab[pin].mode == irq_mode &&
100 pin_irq_hdr_tab[pin].args == args)
101 {
102 rt_hw_interrupt_enable(level);
103 return RT_EOK;
104 }
105
106 if(pin_irq_hdr_tab[pin].pin != -1)
107 {
108 rt_hw_interrupt_enable(level);
109 return -RT_EBUSY;
110 }
111
112 pin_irq_hdr_tab[pin].pin = pin;
113 pin_irq_hdr_tab[pin].mode = irq_mode;
114 pin_irq_hdr_tab[pin].hdr = hdr;
115 pin_irq_hdr_tab[pin].args = args;
116
117 rt_hw_interrupt_enable(level);
118
119 return RT_EOK;
120 }
121
_pin_detach_irq(struct rt_device * device,rt_base_t pin)122 static rt_err_t _pin_detach_irq(struct rt_device *device, rt_base_t pin)
123 {
124 rt_base_t level;
125
126 level = rt_hw_interrupt_disable();
127
128 if(pin_irq_hdr_tab[pin].pin == -1)
129 {
130 rt_hw_interrupt_enable(level);
131
132 return RT_EOK;
133 }
134
135 pin_irq_hdr_tab[pin].pin = -1;
136 pin_irq_hdr_tab[pin].mode = 0;
137 pin_irq_hdr_tab[pin].hdr = RT_NULL;
138 pin_irq_hdr_tab[pin].args = RT_NULL;
139
140 rt_hw_interrupt_enable(level);
141
142 return RT_EOK;
143 }
144
_pin_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)145 static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin,
146 rt_uint8_t enabled)
147 {
148 rt_base_t level;
149 rt_uint8_t trig_mode = 0;
150
151 if (enabled == PIN_IRQ_ENABLE)
152 {
153 level = rt_hw_interrupt_disable();
154
155 if(pin_irq_hdr_tab[pin].pin == -1)
156 {
157 rt_hw_interrupt_enable(level);
158 return -RT_ENOSYS;
159 }
160
161 switch (pin_irq_hdr_tab[pin].mode)
162 {
163 case PIN_IRQ_MODE_RISING:
164 trig_mode = GPIO_INT_TRIG_MODE_SYNC_RISING_EDGE;
165 break;
166
167 case PIN_IRQ_MODE_FALLING:
168 trig_mode = GPIO_INT_TRIG_MODE_SYNC_FALLING_EDGE;
169 break;
170
171 case PIN_IRQ_MODE_RISING_FALLING:
172 trig_mode = GPIO_INT_TRIG_MODE_ASYNC_FALLING_EDGE;
173 break;
174
175 case PIN_IRQ_MODE_HIGH_LEVEL:
176 trig_mode = GPIO_INT_TRIG_MODE_SYNC_HIGH_LEVEL;
177 break;
178
179 case PIN_IRQ_MODE_LOW_LEVEL:
180 trig_mode = GPIO_INT_TRIG_MODE_SYNC_LOW_LEVEL;
181 break;
182 }
183
184 bflb_gpio_int_init(gpio, pin, trig_mode);
185 bflb_gpio_int_mask(gpio, pin, false);
186
187 rt_hw_interrupt_enable(level);
188 }
189 else if(enabled == PIN_IRQ_DISABLE)
190 {
191 level = rt_hw_interrupt_disable();
192 bflb_gpio_int_mask(gpio, pin, true);
193
194 rt_hw_interrupt_enable(level);
195 }
196 else
197 {
198 return -RT_ENOSYS;
199 }
200 return RT_EOK;
201 }
202
203 const static struct rt_pin_ops bl_drv_pin_ops =
204 {
205 _pin_mode,
206 _pin_write,
207 _pin_read,
208 _pin_attach_irq,
209 _pin_detach_irq,
210 _pin_irq_enable,
211 NULL,
212 };
213
rt_hw_pin_init(void)214 int rt_hw_pin_init(void)
215 {
216 rt_uint8_t i;
217
218 for(i = 0; i < GPIO_MAX; i ++)
219 {
220 pin_irq_hdr_tab[i].pin = -1;
221 }
222 gpio = bflb_device_get_by_name("gpio");
223 bflb_irq_attach(gpio->irq_num, gpio_isr, gpio);
224 bflb_irq_enable(gpio->irq_num);
225
226 return rt_device_pin_register("pin", &bl_drv_pin_ops, RT_NULL);
227 }
228 INIT_BOARD_EXPORT(rt_hw_pin_init);
229
230 #endif /*BSP_USING_GPIO */
231