1 /*
2  * Copyright (c) 2006-2021, YICHIP Technology Co.,Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-09-09     WSY          first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <board.h>
14 #include <rthw.h>
15 
16 #define PIN_MAX_NUM     (48)
17 
18 typedef void (*pin_callback_t)(void *args);
19 struct pin
20 {
21     uint32_t package_index;
22     const char *name;
23     IRQn_Type irq;
24     rt_uint32_t irq_mode;
25     pin_callback_t callback;
26     void *callback_args;
27 };
28 typedef struct pin pin_t;
29 
30 
31 struct rt_pin_irq_hdr pin_irq_hdr_tab[] =
32 {
33     {-1, 0, RT_NULL, RT_NULL},
34     {-1, 0, RT_NULL, RT_NULL},
35     {-1, 0, RT_NULL, RT_NULL},
36     {-1, 0, RT_NULL, RT_NULL},
37     {-1, 0, RT_NULL, RT_NULL},
38     {-1, 0, RT_NULL, RT_NULL},
39     {-1, 0, RT_NULL, RT_NULL},
40     {-1, 0, RT_NULL, RT_NULL},
41     {-1, 0, RT_NULL, RT_NULL},
42     {-1, 0, RT_NULL, RT_NULL},
43     {-1, 0, RT_NULL, RT_NULL},
44     {-1, 0, RT_NULL, RT_NULL},
45     {-1, 0, RT_NULL, RT_NULL},
46     {-1, 0, RT_NULL, RT_NULL},
47     {-1, 0, RT_NULL, RT_NULL},
48     {-1, 0, RT_NULL, RT_NULL},
49     {-1, 0, RT_NULL, RT_NULL},
50     {-1, 0, RT_NULL, RT_NULL},
51     {-1, 0, RT_NULL, RT_NULL},
52     {-1, 0, RT_NULL, RT_NULL},
53     {-1, 0, RT_NULL, RT_NULL},
54     {-1, 0, RT_NULL, RT_NULL},
55     {-1, 0, RT_NULL, RT_NULL},
56     {-1, 0, RT_NULL, RT_NULL},
57     {-1, 0, RT_NULL, RT_NULL},
58     {-1, 0, RT_NULL, RT_NULL},
59     {-1, 0, RT_NULL, RT_NULL},
60     {-1, 0, RT_NULL, RT_NULL},
61     {-1, 0, RT_NULL, RT_NULL},
62     {-1, 0, RT_NULL, RT_NULL},
63     {-1, 0, RT_NULL, RT_NULL},
64     {-1, 0, RT_NULL, RT_NULL},
65     {-1, 0, RT_NULL, RT_NULL},
66     {-1, 0, RT_NULL, RT_NULL},
67     {-1, 0, RT_NULL, RT_NULL},
68     {-1, 0, RT_NULL, RT_NULL},
69     {-1, 0, RT_NULL, RT_NULL},
70     {-1, 0, RT_NULL, RT_NULL},
71     {-1, 0, RT_NULL, RT_NULL},
72     {-1, 0, RT_NULL, RT_NULL},
73     {-1, 0, RT_NULL, RT_NULL},
74     {-1, 0, RT_NULL, RT_NULL},
75     {-1, 0, RT_NULL, RT_NULL},
76     {-1, 0, RT_NULL, RT_NULL},
77     {-1, 0, RT_NULL, RT_NULL},
78     {-1, 0, RT_NULL, RT_NULL},
79     {-1, 0, RT_NULL, RT_NULL},
80     {-1, 0, RT_NULL, RT_NULL},
81 };
82 
yc_pin_mode(rt_device_t dev,rt_base_t pin,rt_uint8_t mode)83 static void yc_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
84 {
85     /* Configure GPIO_InitStructure */
86     if (mode == PIN_MODE_OUTPUT)
87     {
88         /* output setting */
89         GPIO_CONFIG(pin) = OUTPUT_LOW;
90     }
91     else if (mode == PIN_MODE_INPUT)
92     {
93         /* input setting: not pull. */
94         GPIO_CONFIG(pin) = INPUT;
95     }
96     else if (mode == PIN_MODE_INPUT_PULLUP)
97     {
98         /* input setting: pull up. */
99         GPIO_CONFIG(pin) = PULL_UP;
100     }
101     else if (mode == PIN_MODE_INPUT_PULLDOWN)
102     {
103         /* input setting: pull down. */
104         GPIO_CONFIG(pin) = PULL_DOWN;
105     }
106     else if (mode == PIN_MODE_OUTPUT_OD)
107     {
108         /* output setting: od. */
109         GPIO_CONFIG(pin) = PULL_UP;
110     }
111 }
112 
yc_pin_write(rt_device_t dev,rt_base_t pin,rt_uint8_t value)113 static void yc_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
114 {
115     if (value)
116     {
117         GPIO_CONFIG(pin) = OUTPUT_HIGH;
118     }
119     else
120     {
121         GPIO_CONFIG(pin) = OUTPUT_LOW;
122     }
123 }
124 
yc_pin_read(rt_device_t dev,rt_base_t pin)125 static rt_ssize_t yc_pin_read(rt_device_t dev, rt_base_t pin)
126 {
127     return GPIO_IN(pin / 16) & (1 << (pin % 16)) ? 1 : 0;
128 }
129 
yc_pin_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t mode,pin_callback_t cb,void * args)130 static rt_err_t yc_pin_attach_irq(struct rt_device *device,
131                                   rt_base_t pin,
132                                   rt_uint8_t mode,
133                                   pin_callback_t cb,
134                                   void *args)
135 {
136     rt_int32_t index = -1;
137     rt_base_t level;
138     if (pin >= PIN_MAX_NUM)
139     {
140         return -RT_EINVAL;
141     }
142 
143     index = pin;
144     level = rt_hw_interrupt_disable();
145 
146     pin_irq_hdr_tab[index].pin = pin;
147     pin_irq_hdr_tab[index].hdr = cb;
148     pin_irq_hdr_tab[index].mode = mode;
149     pin_irq_hdr_tab[index].args = args;
150     rt_hw_interrupt_enable(level);
151 
152     return RT_EOK;
153 }
154 
yc_pin_detach_irq(struct rt_device * device,rt_base_t pin)155 static rt_err_t yc_pin_detach_irq(struct rt_device *device, rt_base_t pin)
156 {
157     rt_int32_t index = -1;
158     rt_base_t level;
159     if (pin >= PIN_MAX_NUM)
160     {
161         return -RT_EINVAL;
162     }
163 
164     index = pin;
165     level = rt_hw_interrupt_disable();
166 
167     pin_irq_hdr_tab[index].pin = -1;
168     pin_irq_hdr_tab[index].hdr = RT_NULL;
169     pin_irq_hdr_tab[index].mode = 0;
170     pin_irq_hdr_tab[index].args = RT_NULL;
171 
172     rt_hw_interrupt_enable(level);
173     return RT_EOK;
174 }
175 
yc_pin_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)176 static rt_err_t yc_pin_irq_enable(struct rt_device *device,
177                                   rt_base_t pin,
178                                   rt_uint8_t enabled)
179 {
180     rt_int32_t index;
181     rt_base_t level = 0;
182     if (pin >= PIN_MAX_NUM)
183     {
184         return -RT_EINVAL;
185     }
186 
187     index = pin;
188 
189     if (enabled == PIN_IRQ_ENABLE)
190     {
191         switch (pin_irq_hdr_tab[index].mode)
192         {
193         case PIN_IRQ_MODE_RISING:
194 
195             break;
196         case PIN_IRQ_MODE_FALLING:
197 
198             break;
199         case PIN_IRQ_MODE_RISING_FALLING:
200 
201             break;
202         case PIN_IRQ_MODE_HIGH_LEVEL:
203             GPIO_CONFIG(pin) = PULL_DOWN;
204             GPIO_TRIG_MODE(pin / 16) &= (1 << (pin % 16));
205             break;
206         case PIN_IRQ_MODE_LOW_LEVEL:
207             GPIO_CONFIG(pin) = PULL_UP;
208             GPIO_TRIG_MODE(pin / 16) |= (1 << (pin % 16));
209             break;
210         default:
211             rt_hw_interrupt_enable(level);
212             return -RT_EINVAL;
213         }
214 
215         level = rt_hw_interrupt_disable();
216         NVIC_EnableIRQ(GPIO_IRQn);
217         GPIO_INTR_EN(pin / 16) |= (1 << (pin % 16));
218         rt_hw_interrupt_enable(level);
219     }
220     else if (enabled == PIN_IRQ_DISABLE)
221     {
222         NVIC_DisableIRQ(GPIO_IRQn);
223         GPIO_INTR_EN(pin / 16) &= ~(1 << (pin % 16));
224     }
225     else
226     {
227         return -RT_ENOSYS;
228     }
229     return RT_EOK;
230 }
231 
232 const static struct rt_pin_ops yc3121_pin_ops =
233 {
234     yc_pin_mode,
235     yc_pin_write,
236     yc_pin_read,
237     yc_pin_attach_irq,
238     yc_pin_detach_irq,
239     yc_pin_irq_enable,
240     RT_NULL,
241 };
242 
rt_hw_pin_init(void)243 int rt_hw_pin_init(void)
244 {
245     int result;
246     result = rt_device_pin_register("pin", &yc3121_pin_ops, RT_NULL);
247     return result;
248 }
249 INIT_BOARD_EXPORT(rt_hw_pin_init);
250 
GPIO_IRQHandler(void)251 void GPIO_IRQHandler(void)
252 {
253     int i;
254 
255     rt_interrupt_enter();
256     for (i = 0; i < PIN_MAX_NUM; i++)
257     {
258         if ((GPIO_TRIG_MODE(i / 16) & (1 << (i % 16))) == (GPIO_IN(i / 16) & (1 << (i % 16))))
259         {
260             if (pin_irq_hdr_tab[i].hdr)
261             {
262                 pin_irq_hdr_tab[i].hdr(pin_irq_hdr_tab[i].args);
263             }
264         }
265     }
266     rt_interrupt_leave();
267 }
268