1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author            Notes
8  * 2015-06-19     ItsEddy           add gpio driver support
9  * 2022-09-14     YangZhongQing     full gpio driver support
10  *                                  I referred AM335X_StarterWare_02_00_01_01
11  */
12 
13 #include <ctype.h>
14 #include <rthw.h>
15 #include <rtthread.h>
16 #include <rtdevice.h>
17 
18 #include <am33xx.h>
19 #include <interrupt.h>
20 #include "gpio.h"
21 
22 #ifdef RT_USING_PIN
23 
24 #define reg(base)         *(int*)(base)
25 
26 #define GPIO_PIN_LOW              (0x0)
27 #define GPIO_PIN_HIGH             (0x1)
28 
29 /* Values denoting the Interrupt Line number to be used. */
30 #define GPIO_INT_LINE_1                  (0x0)
31 #define GPIO_INT_LINE_2                  (0x1)
32 
33 #define GPIO_REVISION   (0x0)
34 #define GPIO_SYSCONFIG   (0x10)
35 #define GPIO_IRQSTATUS_RAW(n)   (0x24 + (n * 4))
36 #define GPIO_IRQSTATUS(n)   (0x2C + (n * 4))
37 #define GPIO_IRQSTATUS_SET(n)   (0x34 + (n * 4))
38 #define GPIO_IRQSTATUS_CLR(n)   (0x3C + (n * 4))
39 #define GPIO_IRQWAKEN(n)   (0x44 + (n * 4))
40 #define GPIO_SYSSTATUS   (0x114)
41 #define GPIO_CTRL   (0x130)
42 #define GPIO_OE   (0x134)
43 #define GPIO_DATAIN   (0x138)
44 #define GPIO_DATAOUT   (0x13C)
45 #define GPIO_LEVELDETECT(n)   (0x140 + (n * 4))
46 #define GPIO_RISINGDETECT   (0x148)
47 #define GPIO_FALLINGDETECT   (0x14C)
48 #define GPIO_DEBOUNCENABLE   (0x150)
49 #define GPIO_DEBOUNCINGTIME   (0x154)
50 #define GPIO_CLEARDATAOUT   (0x190)
51 #define GPIO_SETDATAOUT   (0x194)
52 
53 static const rt_base_t GPIO_BASE[] =
54 {
55     AM33XX_GPIO_0_REGS,
56     AM33XX_GPIO_1_REGS,
57     AM33XX_GPIO_2_REGS,
58     AM33XX_GPIO_3_REGS
59 };
60 
61 #define GPIO_INT0x GPIO_INT0A
62 #define GPIO_INT1x GPIO_INT1A
63 #define GPIO_INT2x GPIO_INT2A
64 #define GPIO_INT3x GPIO_INT3A
65 static const rt_uint8_t GPIO_INTx[] = {GPIO_INT0x, GPIO_INT1x, GPIO_INT2x, GPIO_INT3x};
66 
67 // auto determine which int line
68 #define GPIO_INT0_LINE ((GPIO_INT0x == GPIO_INT0A) ? GPIO_INT_LINE_1 : GPIO_INT_LINE_2)
69 #define GPIO_INT1_LINE ((GPIO_INT1x == GPIO_INT1A) ? GPIO_INT_LINE_1 : GPIO_INT_LINE_2)
70 #define GPIO_INT2_LINE ((GPIO_INT2x == GPIO_INT2A) ? GPIO_INT_LINE_1 : GPIO_INT_LINE_2)
71 #define GPIO_INT3_LINE ((GPIO_INT3x == GPIO_INT3A) ? GPIO_INT_LINE_1 : GPIO_INT_LINE_2)
72 static const rt_uint8_t GPIO_INT_LINEx[] = {GPIO_INT0_LINE, GPIO_INT1_LINE, GPIO_INT2_LINE, GPIO_INT3_LINE};
73 
74 struct am33xx_pin_irq_hdr
75 {
76     void (*hdr)(void *args);
77     void             *args;
78 };
79 
80 struct am33xx_gpio_irq_param
81 {
82     struct am33xx_pin_irq_hdr hdr_tab[32];
83 };
84 
85 static struct am33xx_gpio_irq_param GPIO_PARAMx[sizeof(GPIO_BASE) / sizeof(GPIO_BASE[0])];
86 
am33xx_gpio_hdr(rt_base_t base,rt_base_t int_line,void * param)87 rt_inline void am33xx_gpio_hdr(rt_base_t base, rt_base_t int_line, void *param)
88 {
89     struct am33xx_gpio_irq_param *irq_param = param;
90     struct am33xx_pin_irq_hdr *irq_hdr;
91     int pinNumber;
92     rt_ubase_t irqstatus;
93 
94     irqstatus = REG32(base + GPIO_IRQSTATUS(int_line));
95     REG32(base + GPIO_IRQSTATUS(int_line)) = irqstatus;
96 
97     for (pinNumber = 0; pinNumber < sizeof(irq_param->hdr_tab); pinNumber++)
98     {
99         if (irqstatus & 0x1)
100         {
101             irq_hdr = &irq_param->hdr_tab[pinNumber];
102             if (irq_hdr->hdr)
103                 irq_hdr->hdr(irq_hdr->args);
104             // if the last one, exit immediately
105             if (irqstatus == 0x1)
106                 break;
107         }
108         irqstatus >>= 1;
109     }
110 }
111 
am33xx_gpio0_isr(int vector,void * param)112 static void am33xx_gpio0_isr(int vector, void *param)
113 {
114     am33xx_gpio_hdr(AM33XX_GPIO_0_REGS, GPIO_INT0_LINE, param);
115 }
116 
am33xx_gpio1_isr(int vector,void * param)117 static void am33xx_gpio1_isr(int vector, void *param)
118 {
119     am33xx_gpio_hdr(AM33XX_GPIO_1_REGS, GPIO_INT1_LINE, param);
120 }
121 
am33xx_gpio2_isr(int vector,void * param)122 static void am33xx_gpio2_isr(int vector, void *param)
123 {
124     am33xx_gpio_hdr(AM33XX_GPIO_2_REGS, GPIO_INT2_LINE, param);
125 }
126 
am33xx_gpio3_isr(int vector,void * param)127 static void am33xx_gpio3_isr(int vector, void *param)
128 {
129     am33xx_gpio_hdr(AM33XX_GPIO_3_REGS, GPIO_INT3_LINE, param);
130 }
131 
132 static const rt_isr_handler_t GPIO_ISRx[] =
133 {
134     am33xx_gpio0_isr,
135     am33xx_gpio1_isr,
136     am33xx_gpio2_isr,
137     am33xx_gpio3_isr,
138 };
139 
am33xx_pin_mode(struct rt_device * device,rt_base_t pin,rt_uint8_t mode)140 static void am33xx_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
141 {
142     RT_ASSERT(pin >= 0 && pin < 128);
143     RT_ASSERT(mode != PIN_MODE_INPUT_PULLUP); /* Mode not supported */
144     rt_base_t gpiox     = pin >> 5;
145     rt_base_t pinNumber = pin & 0x1F;
146 
147     if (PIN_MODE_OUTPUT == mode)
148     {
149         reg(GPIO_BASE[gpiox] + GPIO_OE) &= ~(1 << pinNumber);
150     }
151     else if (PIN_MODE_INPUT == mode)
152     {
153         reg(GPIO_BASE[gpiox] + GPIO_OE) |= (1 << pinNumber);
154     }
155 }
156 
am33xx_pin_write(struct rt_device * device,rt_base_t pin,rt_uint8_t value)157 static void am33xx_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
158 {
159     RT_ASSERT(pin >= 0 && pin < 128);
160     rt_base_t gpiox     = pin >> 5;
161     rt_base_t pinNumber = pin & 0x1F;
162 
163     if (GPIO_PIN_HIGH == value)
164     {
165         reg(GPIO_BASE[gpiox] + GPIO_SETDATAOUT) = (1 << pinNumber);
166     }
167     else /* GPIO_PIN_LOW */
168     {
169         reg(GPIO_BASE[gpiox] + GPIO_CLEARDATAOUT) = (1 << pinNumber);
170     }
171 }
172 
am33xx_pin_read(struct rt_device * device,rt_base_t pin)173 static rt_ssize_t am33xx_pin_read(struct rt_device *device, rt_base_t pin)
174 {
175     RT_ASSERT(pin >= 0 && pin < 128);
176     rt_base_t gpiox     = pin >> 5;
177     rt_base_t pinNumber = pin & 0x1F;
178 
179     return reg(GPIO_BASE[gpiox] + GPIO_DATAIN) & (1 << pinNumber) ? 1 : 0;
180 }
181 
am33xx_pin_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t mode,void (* hdr)(void * args),void * args)182 static rt_err_t am33xx_pin_attach_irq(struct rt_device *device, rt_base_t pin,
183                                       rt_uint8_t mode, void (*hdr)(void *args), void *args)
184 {
185     RT_ASSERT(pin >= 0 && pin < 128);
186     rt_base_t gpiox     = pin >> 5;
187     rt_base_t pinNumber = pin & 0x1F;
188     rt_base_t baseAdd = GPIO_BASE[gpiox];
189     struct am33xx_pin_irq_hdr *irq_hdr = &GPIO_PARAMx[gpiox].hdr_tab[pinNumber];
190     rt_base_t level;
191 
192     level = rt_hw_interrupt_disable();
193 
194     if (irq_hdr->hdr != RT_NULL)
195     {
196         rt_hw_interrupt_enable(level);
197         return -RT_EBUSY;
198     }
199 
200     irq_hdr->hdr = hdr;
201     irq_hdr->args = args;
202 
203     switch (mode)
204     {
205     case PIN_IRQ_MODE_RISING:
206         /* Enabling rising edge detect interrupt generation. */
207         REG32(baseAdd + GPIO_RISINGDETECT) |= (1 << pinNumber);
208 
209         /* Disabling falling edge detect interrupt generation. */
210         REG32(baseAdd + GPIO_FALLINGDETECT) &= ~(1 << pinNumber);
211 
212         /* Disabling logic LOW level detect interrupt generation. */
213         REG32(baseAdd + GPIO_LEVELDETECT(0)) &= ~(1 << pinNumber);
214 
215         /* Disabling logic HIGH level detect interrupt generation. */
216         REG32(baseAdd + GPIO_LEVELDETECT(1)) &= ~(1 << pinNumber);
217         break;
218     case PIN_IRQ_MODE_FALLING:
219         /* Disabling rising edge detect interrupt generation. */
220         REG32(baseAdd + GPIO_RISINGDETECT) &= ~(1 << pinNumber);
221 
222         /* Enabling falling edge detect interrupt generation. */
223         REG32(baseAdd + GPIO_FALLINGDETECT) |= (1 << pinNumber);
224 
225         /* Disabling logic LOW level detect interrupt generation. */
226         REG32(baseAdd + GPIO_LEVELDETECT(0)) &= ~(1 << pinNumber);
227 
228         /* Disabling logic HIGH level detect interrupt generation. */
229         REG32(baseAdd + GPIO_LEVELDETECT(1)) &= ~(1 << pinNumber);
230         break;
231     case PIN_IRQ_MODE_RISING_FALLING:
232         /* Enabling rising edge detect interrupt generation. */
233         REG32(baseAdd + GPIO_RISINGDETECT) |= (1 << pinNumber);
234 
235         /* Enabling falling edge detect interrupt generation. */
236         REG32(baseAdd + GPIO_FALLINGDETECT) |= (1 << pinNumber);
237 
238         /* Disabling logic LOW level detect interrupt generation. */
239         REG32(baseAdd + GPIO_LEVELDETECT(0)) &= ~(1 << pinNumber);
240 
241         /* Disabling logic HIGH level detect interrupt generation. */
242         REG32(baseAdd + GPIO_LEVELDETECT(1)) &= ~(1 << pinNumber);
243         break;
244     case PIN_IRQ_MODE_HIGH_LEVEL:
245         /* Disabling logic LOW level detect interrupt generation. */
246         REG32(baseAdd + GPIO_LEVELDETECT(0)) &= ~(1 << pinNumber);
247 
248         /* Enabling logic HIGH level detect interrupt generation. */
249         REG32(baseAdd + GPIO_LEVELDETECT(1)) |= (1 << pinNumber);
250 
251         /* Disabling rising edge detect interrupt generation. */
252         REG32(baseAdd + GPIO_RISINGDETECT) &= ~(1 << pinNumber);
253 
254         /* Disabling falling edge detect interrupt generation. */
255         REG32(baseAdd + GPIO_FALLINGDETECT) &= ~(1 << pinNumber);
256         break;
257     case PIN_IRQ_MODE_LOW_LEVEL:
258         /* Enabling logic LOW level detect interrupt geenration. */
259         REG32(baseAdd + GPIO_LEVELDETECT(0)) |= (1 << pinNumber);
260 
261         /* Disabling logic HIGH level detect interrupt generation. */
262         REG32(baseAdd + GPIO_LEVELDETECT(1)) &= ~(1 << pinNumber);
263 
264         /* Disabling rising edge detect interrupt generation. */
265         REG32(baseAdd + GPIO_RISINGDETECT) &= ~(1 << pinNumber);
266 
267         /* Disabling falling edge detect interrupt generation. */
268         REG32(baseAdd + GPIO_FALLINGDETECT) &= ~(1 << pinNumber);
269         break;
270     }
271 
272     rt_hw_interrupt_enable(level);
273     return 0;
274 }
275 
am33xx_pin_detach_irq(struct rt_device * device,rt_base_t pin)276 static rt_err_t am33xx_pin_detach_irq(struct rt_device *device, rt_base_t pin)
277 {
278     RT_ASSERT(pin >= 0 && pin < 128);
279     rt_base_t gpiox     = pin >> 5;
280     rt_base_t pinNumber = pin & 0x1F;
281     struct am33xx_pin_irq_hdr *irq_hdr = &GPIO_PARAMx[gpiox].hdr_tab[pinNumber];
282     rt_base_t level;
283 
284     level = rt_hw_interrupt_disable();
285 
286     irq_hdr->hdr = RT_NULL;
287     irq_hdr->args = RT_NULL;
288 
289     rt_hw_interrupt_enable(level);
290     return 0;
291 }
292 
am33xx_pin_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)293 static rt_err_t am33xx_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
294 {
295     RT_ASSERT(pin >= 0 && pin < 128);
296     rt_base_t gpiox     = pin >> 5;
297     rt_base_t pinNumber = pin & 0x1F;
298     rt_base_t baseAdd = GPIO_BASE[gpiox];
299     rt_base_t intLine = GPIO_INT_LINEx[gpiox];
300 
301     if (enabled == PIN_IRQ_ENABLE)
302         REG32(baseAdd + GPIO_IRQSTATUS_SET(intLine)) = (1 << pinNumber);
303     else
304         REG32(baseAdd + GPIO_IRQSTATUS_CLR(intLine)) = (1 << pinNumber);
305 
306     return 0;
307 }
308 
309 // name format: P0.0, range: GPIO0_[31:0] ... GPIO5_[31:0]
am33xx_pin_get(const char * name)310 static rt_base_t am33xx_pin_get(const char *name)
311 {
312     rt_base_t gpiox;
313     rt_base_t pinNumber;
314 
315     if (!isdigit((int)name[1]))
316         return -RT_EINVAL;
317     gpiox = name[1] - '0';
318 
319     if (name[2] != '.')
320         return -RT_EINVAL;
321 
322     if (!isdigit((int)name[3]))
323         return -RT_EINVAL;
324     pinNumber = name[3] - '0';
325 
326     if (name[4] == '\0')
327         goto done;
328     else if (!isdigit((int)name[4]))
329         return -RT_EINVAL;
330 
331     pinNumber *= 10;
332     pinNumber += name[4] - '0';
333 
334     if (name[5] != '\0')
335         return -RT_EINVAL;
336 
337 done:
338     if (pinNumber > 0x1F)
339         return -RT_EINVAL;
340 
341     return GET_PIN(gpiox, pinNumber);
342 }
343 
344 static const struct rt_pin_ops am33xx_pin_ops =
345 {
346     am33xx_pin_mode,
347     am33xx_pin_write,
348     am33xx_pin_read,
349     am33xx_pin_attach_irq,
350     am33xx_pin_detach_irq,
351     am33xx_pin_irq_enable,
352     am33xx_pin_get,
353 };
354 
rt_hw_gpio_init(void)355 int rt_hw_gpio_init(void)
356 {
357     int vector;
358     rt_base_t gpiox;
359     char name[RT_NAME_MAX];
360 
361     for (gpiox = 0; gpiox < 4; gpiox++)
362     {
363         rt_snprintf(name, sizeof(name), "%s%d", "gpio", gpiox);
364         vector = GPIO_INTx[gpiox];
365 
366         rt_hw_interrupt_install(vector, GPIO_ISRx[gpiox], &GPIO_PARAMx[gpiox], name);
367         rt_hw_interrupt_control(vector, 0, 0);
368         rt_hw_interrupt_umask(vector);
369     }
370 
371     rt_device_pin_register("gpio", &am33xx_pin_ops, RT_NULL);
372     return 0;
373 }
374 INIT_BOARD_EXPORT(rt_hw_gpio_init);
375 #endif
376