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