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-11-26     GuEe-GUI     first version
9  */
10 
11 #include "dev_pin_dm.h"
12 
13 static rt_size_t pin_total_nr = 0;
14 static RT_DEFINE_SPINLOCK(pin_lock);
15 static rt_list_t pin_nodes = RT_LIST_OBJECT_INIT(pin_nodes);
16 
pin_device_find(rt_ubase_t pin)17 static struct rt_device_pin *pin_device_find(rt_ubase_t pin)
18 {
19     struct rt_device_pin *gpio = RT_NULL, *gpio_tmp;
20 
21     rt_spin_lock(&pin_lock);
22 
23     rt_list_for_each_entry(gpio_tmp, &pin_nodes, list)
24     {
25         if (pin >= gpio_tmp->pin_start &&
26             pin - gpio_tmp->pin_start < gpio_tmp->pin_nr)
27         {
28             gpio = gpio_tmp;
29             break;
30         }
31     }
32 
33     rt_spin_unlock(&pin_lock);
34 
35     return gpio;
36 }
37 
pin_api_mode(struct rt_device * device,rt_base_t pin,rt_uint8_t mode)38 static void pin_api_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
39 {
40     struct rt_device_pin *gpio = pin_device_find(pin);
41 
42     if (gpio && gpio->ops->pin_mode)
43     {
44         gpio->ops->pin_mode(&gpio->parent, pin - gpio->pin_start, mode);
45     }
46 }
47 
pin_api_write(struct rt_device * device,rt_base_t pin,rt_uint8_t value)48 static void pin_api_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
49 {
50     struct rt_device_pin *gpio = pin_device_find(pin);
51 
52     if (gpio && gpio->ops->pin_write)
53     {
54         gpio->ops->pin_write(&gpio->parent, pin - gpio->pin_start, value);
55     }
56 }
57 
pin_api_read(struct rt_device * device,rt_base_t pin)58 static rt_ssize_t pin_api_read(struct rt_device *device, rt_base_t pin)
59 {
60     struct rt_device_pin *gpio = pin_device_find(pin);
61 
62     if (gpio && gpio->ops->pin_read)
63     {
64         return gpio->ops->pin_read(&gpio->parent, pin - gpio->pin_start);
65     }
66 
67     return -RT_EINVAL;
68 }
69 
pin_api_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t mode,void (* hdr)(void * args),void * args)70 static rt_err_t pin_api_attach_irq(struct rt_device *device, rt_base_t pin,
71         rt_uint8_t mode, void (*hdr)(void *args), void *args)
72 {
73     struct rt_device_pin *gpio = pin_device_find(pin);
74 
75     if (gpio)
76     {
77         rt_base_t pin_index = pin - gpio->pin_start;
78 
79         if (!gpio->ops->pin_attach_irq)
80         {
81             rt_err_t err;
82             struct rt_pin_irq_hdr *legacy_isr;
83 
84             if ((err = gpio->ops->pin_irq_mode(&gpio->parent, pin_index, mode)))
85             {
86                 return err;
87             }
88 
89             legacy_isr = &gpio->legacy_isr[pin_index];
90             legacy_isr->pin = pin_index;
91             legacy_isr->mode = mode;
92             legacy_isr->hdr = hdr;
93             legacy_isr->args = args;
94 
95             return RT_EOK;
96         }
97         else
98         {
99             return gpio->ops->pin_attach_irq(&gpio->parent, pin_index, mode, hdr, args);
100         }
101     }
102 
103     return -RT_EINVAL;
104 }
105 
pin_api_detach_irq(struct rt_device * device,rt_base_t pin)106 static rt_err_t pin_api_detach_irq(struct rt_device *device, rt_base_t pin)
107 {
108     struct rt_device_pin *gpio = pin_device_find(pin);
109 
110     if (gpio)
111     {
112         rt_base_t pin_index = pin - gpio->pin_start;
113 
114         if (!gpio->ops->pin_detach_irq)
115         {
116             struct rt_pin_irq_hdr *legacy_isr;
117 
118             legacy_isr = &gpio->legacy_isr[pin_index];
119             rt_memset(legacy_isr, 0, sizeof(*legacy_isr));
120 
121             return RT_EOK;
122         }
123         else
124         {
125             return gpio->ops->pin_detach_irq(&gpio->parent, pin);
126         }
127     }
128 
129     return -RT_EINVAL;
130 }
131 
pin_api_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)132 static rt_err_t pin_api_irq_enable(struct rt_device *device, rt_base_t pin,
133         rt_uint8_t enabled)
134 {
135     struct rt_device_pin *gpio = pin_device_find(pin);
136 
137     if (gpio && gpio->ops->pin_irq_enable)
138     {
139         return gpio->ops->pin_irq_enable(&gpio->parent, pin - gpio->pin_start, enabled);
140     }
141 
142     return -RT_EINVAL;
143 }
144 
pin_api_get(const char * name)145 static rt_base_t pin_api_get(const char *name)
146 {
147     rt_base_t res = -RT_EINVAL;
148     struct rt_device_pin *gpio;
149 
150     rt_spin_lock(&pin_lock);
151 
152     rt_list_for_each_entry(gpio, &pin_nodes, list)
153     {
154         if (gpio->ops->pin_get && !(res = gpio->ops->pin_get(name)))
155         {
156             break;
157         }
158     }
159 
160     rt_spin_unlock(&pin_lock);
161 
162     return res;
163 }
164 
pin_api_debounce(struct rt_device * device,rt_base_t pin,rt_uint32_t debounce)165 static rt_err_t pin_api_debounce(struct rt_device *device, rt_base_t pin,
166         rt_uint32_t debounce)
167 {
168     struct rt_device_pin *gpio = pin_device_find(pin);
169 
170     if (gpio && gpio->ops->pin_debounce)
171     {
172         return gpio->ops->pin_debounce(&gpio->parent, pin - gpio->pin_start, debounce);
173     }
174 
175     return -RT_EINVAL;
176 }
177 
pin_api_irq_mode(struct rt_device * device,rt_base_t pin,rt_uint8_t mode)178 static rt_err_t pin_api_irq_mode(struct rt_device *device, rt_base_t pin,
179         rt_uint8_t mode)
180 {
181     struct rt_device_pin *gpio = pin_device_find(pin);
182 
183     if (gpio && gpio->ops->pin_irq_mode)
184     {
185         return gpio->ops->pin_irq_mode(&gpio->parent, pin - gpio->pin_start, mode);
186     }
187 
188     return -RT_EINVAL;
189 }
190 
191 static const struct rt_pin_ops pin_api_dm_ops =
192 {
193     .pin_mode = pin_api_mode,
194     .pin_write = pin_api_write,
195     .pin_read = pin_api_read,
196     .pin_attach_irq = pin_api_attach_irq,
197     .pin_detach_irq = pin_api_detach_irq,
198     .pin_irq_enable = pin_api_irq_enable,
199     .pin_get = pin_api_get,
200     .pin_debounce = pin_api_debounce,
201     .pin_irq_mode = pin_api_irq_mode,
202 };
203 
pin_api_init(struct rt_device_pin * gpio,rt_size_t pin_nr)204 rt_err_t pin_api_init(struct rt_device_pin *gpio, rt_size_t pin_nr)
205 {
206     rt_err_t err = RT_EOK;
207 
208     if (!gpio || !gpio->ops)
209     {
210         return -RT_EINVAL;
211     }
212 
213     rt_spin_lock(&pin_lock);
214 
215     if (rt_list_isempty(&pin_nodes))
216     {
217         rt_spin_unlock(&pin_lock);
218         rt_device_pin_register("gpio", &pin_api_dm_ops, RT_NULL);
219         rt_spin_lock(&pin_lock);
220     }
221 
222     gpio->pin_start = pin_total_nr;
223     gpio->pin_nr = pin_nr;
224     pin_total_nr += pin_nr;
225 
226     rt_list_init(&gpio->list);
227     rt_list_insert_before(&pin_nodes, &gpio->list);
228 
229     rt_spin_unlock(&pin_lock);
230 
231     return err;
232 }
233 
pin_dm_irq_mask(struct rt_pic_irq * pirq)234 static void pin_dm_irq_mask(struct rt_pic_irq *pirq)
235 {
236     struct rt_device_pin *gpio = pirq->pic->priv_data;
237 
238     gpio->ops->pin_irq_enable(&gpio->parent, pirq->hwirq, 0);
239 }
240 
pin_dm_irq_unmask(struct rt_pic_irq * pirq)241 static void pin_dm_irq_unmask(struct rt_pic_irq *pirq)
242 {
243     struct rt_device_pin *gpio = pirq->pic->priv_data;
244 
245     gpio->ops->pin_irq_enable(&gpio->parent, pirq->hwirq, 1);
246 }
247 
pin_dm_irq_set_triger_mode(struct rt_pic_irq * pirq,rt_uint32_t mode)248 static rt_err_t pin_dm_irq_set_triger_mode(struct rt_pic_irq *pirq, rt_uint32_t mode)
249 {
250     rt_uint8_t pin_mode;
251     struct rt_device_pin *gpio = pirq->pic->priv_data;
252 
253     switch (mode)
254     {
255     case RT_IRQ_MODE_EDGE_RISING:
256         pin_mode = PIN_IRQ_MODE_RISING;
257         break;
258 
259     case RT_IRQ_MODE_EDGE_FALLING:
260         pin_mode = PIN_IRQ_MODE_FALLING;
261         break;
262 
263     case RT_IRQ_MODE_EDGE_BOTH:
264         pin_mode = PIN_IRQ_MODE_RISING_FALLING;
265         break;
266 
267     case RT_IRQ_MODE_LEVEL_HIGH:
268         pin_mode = PIN_IRQ_MODE_HIGH_LEVEL;
269         break;
270 
271     case RT_IRQ_MODE_LEVEL_LOW:
272         pin_mode = PIN_IRQ_MODE_LOW_LEVEL;
273         break;
274 
275     default:
276         return -RT_ENOSYS;
277     }
278 
279     return gpio->ops->pin_irq_mode(&gpio->parent, pirq->hwirq, pin_mode);
280 }
281 
pin_dm_irq_map(struct rt_pic * pic,int hwirq,rt_uint32_t mode)282 static int pin_dm_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
283 {
284     int irq = -1;
285     struct rt_device_pin *gpio = pic->priv_data;
286     struct rt_pic_irq *pirq = rt_pic_find_irq(pic, hwirq);
287 
288     if (pirq)
289     {
290         irq = rt_pic_config_irq(pic, hwirq, hwirq);
291 
292         if (irq >= 0)
293         {
294             rt_pic_cascade(pirq, gpio->irqchip.irq);
295             rt_pic_irq_set_triger_mode(irq, mode);
296         }
297     }
298 
299     return irq;
300 }
301 
pin_dm_irq_parse(struct rt_pic * pic,struct rt_ofw_cell_args * args,struct rt_pic_irq * out_pirq)302 static rt_err_t pin_dm_irq_parse(struct rt_pic *pic,
303         struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq)
304 {
305     rt_err_t err = RT_EOK;
306 
307     if (args->args_count == 2)
308     {
309         out_pirq->hwirq = args->args[0];
310         out_pirq->mode = args->args[1] & RT_IRQ_MODE_MASK;
311     }
312     else
313     {
314         err = -RT_EINVAL;
315     }
316 
317     return err;
318 }
319 
320 const static struct rt_pic_ops pin_dm_ops =
321 {
322     .name = "GPIO",
323     .irq_enable = pin_dm_irq_mask,
324     .irq_disable = pin_dm_irq_unmask,
325     .irq_mask = pin_dm_irq_mask,
326     .irq_unmask = pin_dm_irq_unmask,
327     .irq_set_triger_mode = pin_dm_irq_set_triger_mode,
328     .irq_map = pin_dm_irq_map,
329     .irq_parse = pin_dm_irq_parse,
330 };
331 
pin_pic_handle_isr(struct rt_device_pin * gpio,rt_base_t pin)332 rt_err_t pin_pic_handle_isr(struct rt_device_pin *gpio, rt_base_t pin)
333 {
334     rt_err_t err;
335 
336     if (gpio)
337     {
338         rt_ubase_t pin_index = pin;
339         struct rt_pin_irqchip *irqchip = &gpio->irqchip;
340 
341         if (pin_index < gpio->pin_nr)
342         {
343             struct rt_pic_irq *pirq;
344             struct rt_pin_irq_hdr *legacy_isr;
345 
346             pirq = rt_pic_find_irq(&irqchip->parent, pin_index);
347 
348             if (pirq->irq >= 0)
349             {
350                 err = rt_pic_handle_isr(pirq);
351             }
352             else
353             {
354                 err = -RT_EINVAL;
355             }
356 
357             legacy_isr = &gpio->legacy_isr[pin_index];
358 
359             if (legacy_isr->hdr)
360             {
361                 legacy_isr->hdr(legacy_isr->args);
362             }
363         }
364         else
365         {
366             err = -RT_EINVAL;
367         }
368     }
369     else
370     {
371         err = -RT_EINVAL;
372     }
373 
374     return err;
375 }
376 
pin_pic_init(struct rt_device_pin * gpio,int pin_irq)377 rt_err_t pin_pic_init(struct rt_device_pin *gpio, int pin_irq)
378 {
379     rt_err_t err;
380 
381     if (gpio)
382     {
383         struct rt_pin_irqchip *irqchip = &gpio->irqchip;
384         struct rt_pic *pic = &irqchip->parent;
385 
386         irqchip->irq = pin_irq;
387 
388         if (!gpio->pin_nr)
389         {
390             return -RT_EINVAL;
391         }
392 
393         gpio->legacy_isr = rt_calloc(gpio->pin_nr, sizeof(*gpio->legacy_isr));
394 
395         if (!gpio->legacy_isr)
396         {
397             return -RT_ENOMEM;
398         }
399 
400         pic->priv_data = gpio;
401         pic->ops = &pin_dm_ops;
402         /* Make sure the type of gpio for pic */
403         gpio->parent.parent.type = RT_Object_Class_Device;
404         rt_pic_default_name(&irqchip->parent);
405 
406         err = rt_pic_linear_irq(pic, gpio->pin_nr);
407         rt_pic_user_extends(pic);
408 
409         err = RT_EOK;
410     }
411     else
412     {
413         err = -RT_EINVAL;
414     }
415 
416     return err;
417 }
418 
rt_pin_get_named_pin(struct rt_device * dev,const char * propname,int index,rt_uint8_t * out_mode,rt_uint8_t * out_value)419 rt_ssize_t rt_pin_get_named_pin(struct rt_device *dev, const char *propname, int index,
420         rt_uint8_t *out_mode, rt_uint8_t *out_value)
421 {
422     rt_ssize_t res = -RT_ENOSYS;
423 
424     RT_ASSERT(dev != RT_NULL);
425 
426 #ifdef RT_USING_OFW
427     if (dev->ofw_node)
428     {
429         res = rt_ofw_get_named_pin(dev->ofw_node, propname, index, out_mode, out_value);
430     }
431     else
432     {
433         res = -RT_EINVAL;
434     }
435 #endif /* RT_USING_OFW */
436 
437     return res;
438 }
439 
rt_pin_get_named_pin_count(struct rt_device * dev,const char * propname)440 rt_ssize_t rt_pin_get_named_pin_count(struct rt_device *dev, const char *propname)
441 {
442     rt_ssize_t count = -RT_ENOSYS;
443 
444     RT_ASSERT(dev != RT_NULL);
445 
446 #ifdef RT_USING_OFW
447     if (dev->ofw_node)
448     {
449         count = rt_ofw_get_named_pin_count(dev->ofw_node, propname);
450     }
451     else
452     {
453         count = -RT_EINVAL;
454     }
455 #endif /* RT_USING_OFW */
456 
457     return count;
458 }
459