1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-08-28     qiyu     first version
9  */
10 #include <rthw.h>
11 #include "drv_gpio.h"
12 #include "F2837xD_device.h"
13 #include "F28x_Project.h"     // Device Headerfile and Examples Include File
14 #ifdef RT_USING_PIN
15 
16 // the gpio pin number for each port is 32, while it is 16 for ARM
17 #define PIN_NUM(port, no) (((((port) & 0xFu) << 5) | ((no) & 0x1F)))
18 #define PIN_PORT(pin) ((rt_uint16_t)(((pin) >> 5) & 0xFu))
19 #define PIN_NO(pin) ((rt_uint16_t)((pin) & 0x1Fu))
20 
21 #define PIN_c28x_PORT(pin) (volatile Uint32 *)&GpioDataRegs + (PIN_PORT(pin))*GPY_DATA_OFFSET
22 #define PIN_c28x_PIN(pin) ((rt_uint32_t)(1u << PIN_NO(pin)))
23 
24 #define PIN_c28x_PORT_MAX 6 /* gpioA to GPIOF in total*/
25 #define PIN_IRQ_MAX 5   /* XINT1 to XINT5 in total */
26 
27 static rt_err_t c28x_pin_attach_irq(struct rt_device *device, rt_base_t pin,
28                                      rt_uint8_t mode, void (*hdr)(void *args), void *args);
29 static rt_err_t c28x_pin_dettach_irq(struct rt_device *device, rt_base_t pin);
30 static rt_err_t c28x_pin_irq_enable(struct rt_device *device, rt_base_t pin,
31                                      rt_uint8_t enabled);
32 
c28x_pin_get(const char * name)33 static rt_base_t c28x_pin_get(const char *name)
34 {
35     int hw_pin_num = 0;
36     int i, name_len;
37 
38     name_len = rt_strlen(name);
39 
40     if ((name_len < 3) || (name_len >= 7))
41     {
42         return -RT_EINVAL;
43     }
44     /*
45      * PX.y
46      */
47     if ((name[0] != 'P') || (name[2] != '.'))
48     {
49         return -RT_EINVAL;
50     }
51 
52     for (i = 3; i < name_len; i++)
53     {
54         hw_pin_num *= 10;
55         hw_pin_num += name[i] - '0';
56     }
57     return hw_pin_num;
58 }
59 
c28x_pin_write(rt_device_t dev,rt_base_t pin,rt_uint8_t value)60 static void c28x_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
61 {
62     volatile Uint32 *gpioDataReg;
63     Uint32 pinMask;
64     if (PIN_PORT(pin) < PIN_c28x_PORT_MAX)
65     {
66         gpioDataReg = PIN_c28x_PORT(pin);
67         pinMask = 1UL << (PIN_NO(pin));
68         if (value == 0)
69         {
70             gpioDataReg[GPYCLEAR] = pinMask;
71         }
72         else
73         {
74             gpioDataReg[GPYSET] = pinMask;
75         }
76     }
77 }
78 
c28x_pin_read(rt_device_t dev,rt_base_t pin)79 static rt_ssize_t c28x_pin_read(rt_device_t dev, rt_base_t pin)
80 {
81     volatile Uint32 *gpioDataReg;
82     rt_ssize_t value = PIN_LOW;
83 
84     if (PIN_PORT(pin) < PIN_c28x_PORT_MAX)
85     {
86         gpioDataReg = PIN_c28x_PORT(pin);
87         value = (gpioDataReg[GPYDAT] >> PIN_NO(pin)) & 0x1;
88     }
89 
90     return value;
91 }
92 
c28x_pin_mode(rt_device_t dev,rt_base_t pin,rt_uint8_t mode)93 static void c28x_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
94 {
95     volatile Uint32 *gpioBaseAddr;
96     volatile Uint32 *dir, *pud, *odr;
97     if (PIN_PORT(pin) >= PIN_c28x_PORT_MAX)
98     {
99         return;
100     }
101     rt_uint32_t pinMask;
102     pinMask = 1UL << PIN_NO(pin);
103     gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (PIN_PORT(pin))*GPY_CTRL_OFFSET;
104 
105     dir = gpioBaseAddr + GPYDIR;
106     pud = gpioBaseAddr + GPYPUD;
107     odr = gpioBaseAddr + GPYODR;
108 
109     EALLOW;
110     if (mode == PIN_MODE_OUTPUT)
111     {
112         *dir |= pinMask;
113     }
114     else if (mode == PIN_MODE_INPUT)
115     {
116         *dir &= ~pinMask;
117     }
118     else if (mode == PIN_MODE_INPUT_PULLUP)
119     {
120         *dir &= ~pinMask;
121         *pud &= ~pinMask;
122     }
123     else if (mode == PIN_MODE_INPUT_PULLDOWN)
124     {
125         /* input setting: pull down. */
126         *dir &= ~pinMask;
127         *pud |= pinMask;
128     }
129     else if (mode == PIN_MODE_OUTPUT_OD)
130     {
131         /* output setting: od. */
132         *dir |= pinMask;
133         *odr |= pinMask;
134     }
135     EDIS;
136 }
137 
138 const static struct rt_pin_ops _c28x_pin_ops =
139 {
140     c28x_pin_mode,
141     c28x_pin_write,
142     c28x_pin_read,
143     c28x_pin_attach_irq,
144     c28x_pin_dettach_irq,
145     c28x_pin_irq_enable,
146     c28x_pin_get,
147 };
148 
rt_hw_pin_init(void)149 int rt_hw_pin_init(void)
150 {
151     return rt_device_pin_register("pin", &_c28x_pin_ops, RT_NULL);
152 }
153 
154 static struct rt_pin_irq_hdr pin_irq_hdr_tab[] =
155 {
156     {-1, 0, RT_NULL, RT_NULL},
157     {-1, 0, RT_NULL, RT_NULL},
158     {-1, 0, RT_NULL, RT_NULL},
159     {-1, 0, RT_NULL, RT_NULL},
160     {-1, 0, RT_NULL, RT_NULL},
161 };
162 
163 static rt_int16_t pin_irq_xint_tab[] =
164 {
165     BSP_XINT1_PIN,
166     BSP_XINT2_PIN,
167     BSP_XINT3_PIN,
168     BSP_XINT4_PIN,
169     BSP_XINT5_PIN
170 };
get_irq_index(rt_uint32_t pin)171 rt_inline rt_int32_t get_irq_index(rt_uint32_t pin)
172 {
173     int i;
174     for(i = 0 ; i < PIN_IRQ_MAX ; i++)
175     {
176         if(pin_irq_xint_tab[i] == pin)
177         {
178             return i;
179         }
180     }
181     return -1;
182 }
183 
184 #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
185 
c28x_pin_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t mode,void (* hdr)(void * args),void * args)186 static rt_err_t c28x_pin_attach_irq(struct rt_device *device, rt_base_t pin,
187                                      rt_uint8_t mode, void (*hdr)(void *args), void *args)
188 {
189     rt_base_t level;
190     rt_int32_t irqindex = -1;
191 
192     if (PIN_PORT(pin) >= PIN_c28x_PORT_MAX)
193     {
194         return -RT_ENOSYS;
195     }
196     irqindex = get_irq_index(pin);
197     level = rt_hw_interrupt_disable();
198     if (pin_irq_hdr_tab[irqindex].pin == pin &&
199         pin_irq_hdr_tab[irqindex].hdr == hdr &&
200         pin_irq_hdr_tab[irqindex].mode == mode &&
201         pin_irq_hdr_tab[irqindex].args == args)
202     {
203         rt_hw_interrupt_enable(level);
204         return RT_EOK;
205     }
206     if (pin_irq_hdr_tab[irqindex].pin != -1)
207     {
208         rt_hw_interrupt_enable(level);
209         return -RT_EBUSY;
210     }
211     pin_irq_hdr_tab[irqindex].pin = pin;
212     pin_irq_hdr_tab[irqindex].hdr = hdr;
213     pin_irq_hdr_tab[irqindex].mode = mode;
214     pin_irq_hdr_tab[irqindex].args = args;
215     rt_hw_interrupt_enable(level);
216 
217     return RT_EOK;
218 }
219 
c28x_pin_dettach_irq(struct rt_device * device,rt_base_t pin)220 static rt_err_t c28x_pin_dettach_irq(struct rt_device *device, rt_base_t pin)
221 {
222     rt_base_t level;
223     rt_int32_t irqindex = -1;
224     rt_uint16_t i;
225     if (PIN_PORT(pin) >= PIN_c28x_PORT_MAX)
226     {
227         return -RT_ENOSYS;
228     }
229 
230     for(i = 0 ; i < PIN_IRQ_MAX ; i++)
231     {
232         if(pin_irq_hdr_tab[i].pin == pin)
233         {
234             irqindex = i;
235             break;
236         }
237     }
238     if (irqindex == -1)
239     {
240         return -RT_ENOSYS;
241     }
242     level = rt_hw_interrupt_disable();
243     pin_irq_hdr_tab[irqindex].pin = -1;
244     pin_irq_hdr_tab[irqindex].hdr = RT_NULL;
245     pin_irq_hdr_tab[irqindex].mode = 0;
246     pin_irq_hdr_tab[irqindex].args = RT_NULL;
247     rt_hw_interrupt_enable(level);
248 
249     return RT_EOK;
250 }
251 
c28x_pin_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)252 static rt_err_t c28x_pin_irq_enable(struct rt_device *device, rt_base_t pin,
253                                      rt_uint8_t enabled)
254 {
255     rt_base_t level;
256     rt_int32_t irqindex = -1;
257     rt_uint16_t channel;
258     rt_uint16_t edge_mode,pin_mode;
259 
260     if (PIN_PORT(pin) >= PIN_c28x_PORT_MAX)
261     {
262         return -RT_ENOSYS;
263     }
264 
265     irqindex = get_irq_index(pin);
266 
267     /* irqindex+1 = channel*/
268     if (irqindex < 0 || irqindex >= PIN_IRQ_MAX)
269     {
270         return -RT_ENOSYS;
271     }
272 
273     if (enabled == PIN_IRQ_ENABLE)
274     {
275         level = rt_hw_interrupt_disable();
276 
277         if (pin_irq_hdr_tab[irqindex].pin == -1)
278         {
279             rt_hw_interrupt_enable(level);
280             return -RT_ENOSYS;
281         }
282 
283         /*
284          * 1. set the edge mode of interrupt triggering
285          * 2. set the GPIO mode
286          * 3. enable XINT channel and set the input source
287         */
288         channel = irqindex+1;
289         switch (pin_irq_hdr_tab[irqindex].mode)
290         {
291         case PIN_IRQ_MODE_RISING:
292             edge_mode = 1;
293             pin_mode = PIN_MODE_INPUT_PULLDOWN;
294             break;
295         case PIN_IRQ_MODE_FALLING:
296             edge_mode = 0;
297             pin_mode = PIN_MODE_INPUT_PULLUP;
298             break;
299         case PIN_IRQ_MODE_RISING_FALLING:
300             edge_mode = 3;
301             pin_mode = PIN_MODE_INPUT;
302             break;
303         }
304         if(channel == 1)
305         {
306             XintRegs.XINT1CR.bit.ENABLE = 1;        // Enable XINT1
307             EALLOW;
308             InputXbarRegs.INPUT4SELECT = pin;       //Set XINT1 source to GPIO-pin
309             EDIS;
310             XintRegs.XINT1CR.bit.POLARITY = edge_mode;      // Falling edge interrupt
311         }
312         else if(channel == 2)
313         {
314             XintRegs.XINT2CR.bit.ENABLE = 1;        // Enable XINT2
315             EALLOW;
316             InputXbarRegs.INPUT5SELECT = pin;       //Set XINT1 source to GPIO-pin
317             EDIS;
318             XintRegs.XINT2CR.bit.POLARITY = edge_mode;      // Falling edge interrupt
319         }
320         else if(channel == 3)
321         {
322             XintRegs.XINT3CR.bit.ENABLE = 1;        // Enable XINT2
323             EALLOW;
324             InputXbarRegs.INPUT6SELECT = pin;       //Set XINT1 source to GPIO-pin
325             EDIS;
326             XintRegs.XINT3CR.bit.POLARITY = edge_mode;      // Falling edge interrupt
327         }
328         else if(channel == 4)
329         {
330             XintRegs.XINT4CR.bit.ENABLE = 1;        // Enable XINT2
331             EALLOW;
332             InputXbarRegs.INPUT13SELECT = pin;       //Set XINT1 source to GPIO-pin
333             EDIS;
334             XintRegs.XINT4CR.bit.POLARITY = edge_mode;      // Falling edge interrupt
335         }
336         else if(channel == 5)
337         {
338             XintRegs.XINT5CR.bit.ENABLE = 1;        // Enable XINT2
339             EALLOW;
340             InputXbarRegs.INPUT14SELECT = pin;       //Set XINT1 source to GPIO-pin
341             EDIS;
342             XintRegs.XINT5CR.bit.POLARITY = edge_mode;      // Falling edge interrupt
343         }
344 
345         c28x_pin_mode(device, pin, pin_mode);
346         rt_hw_interrupt_enable(level);
347     }
348     else if (enabled == PIN_IRQ_DISABLE)
349     {
350         level = rt_hw_interrupt_disable();
351         channel = irqindex+1;
352         /*
353          * TODO modify this simpler
354          */
355         if(channel == 1)
356         {
357             XintRegs.XINT1CR.bit.ENABLE = 0;        // Disable XINT1
358         }
359         else if(channel == 2)
360         {
361             XintRegs.XINT2CR.bit.ENABLE = 0;        // Disable XINT2
362         }
363         else if(channel == 3)
364         {
365             XintRegs.XINT3CR.bit.ENABLE = 0;        // Disable XINT2
366         }
367         else if(channel == 4)
368         {
369             XintRegs.XINT4CR.bit.ENABLE = 0;        // Disable XINT2
370         }
371         else if(channel == 5)
372         {
373             XintRegs.XINT5CR.bit.ENABLE = 0;        // Disable XINT2
374         }
375         rt_hw_interrupt_enable(level);
376     }
377     else
378     {
379         return -RT_ENOSYS;
380     }
381 
382     return RT_EOK;
383 }
384 
385 void GPIO_XINT_Callback(rt_int16_t XINT_number);
386 
XINT1_Handler(void)387 interrupt void XINT1_Handler(void)
388 {
389     rt_interrupt_enter();
390     PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
391     GPIO_XINT_Callback(1);
392     rt_interrupt_leave();
393 }
394 
XINT2_Handler(void)395 interrupt void XINT2_Handler(void)
396 {
397     rt_interrupt_enter();
398     GPIO_XINT_Callback(2);
399     PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
400     rt_interrupt_leave();
401 }
402 
XINT3_Handler(void)403 interrupt void XINT3_Handler(void)
404 {
405     rt_interrupt_enter();
406     GPIO_XINT_Callback(3);
407     PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
408     rt_interrupt_leave();
409 }
410 
XINT4_Handler(void)411 interrupt void XINT4_Handler(void)
412 {
413     rt_interrupt_enter();
414     GPIO_XINT_Callback(4);
415     PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
416     rt_interrupt_leave();
417 }
418 
XINT5_Handler(void)419 interrupt void XINT5_Handler(void)
420 {
421     rt_interrupt_enter();
422     GPIO_XINT_Callback(5);
423     PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
424     rt_interrupt_leave();
425 }
426 
GPIO_XINT_Callback(rt_int16_t XINT_number)427 void GPIO_XINT_Callback(rt_int16_t XINT_number)
428 {
429     rt_int32_t irqindex = XINT_number - 1;
430     if(pin_irq_hdr_tab[irqindex].hdr)
431     {
432         pin_irq_hdr_tab[irqindex].hdr(pin_irq_hdr_tab[irqindex].args);
433     }
434 }
435 
436 #endif /* RT_USING_PIN */
437 
438 
439 
440