FreeBSD/Linux Kernel Cross Reference
sys/dev/gpio/gpio.c
1 /* $OpenBSD: gpio.c,v 1.17 2022/04/11 14:30:05 visa Exp $ */
2
3 /*
4 * Copyright (c) 2008 Marc Balmer <mbalmer@openbsd.org>
5 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*
21 * General Purpose Input/Output framework.
22 */
23
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/conf.h>
27 #include <sys/device.h>
28 #include <sys/fcntl.h>
29 #include <sys/ioctl.h>
30 #include <sys/gpio.h>
31 #include <sys/vnode.h>
32 #include <sys/malloc.h>
33 #include <sys/queue.h>
34
35 #include <dev/gpio/gpiovar.h>
36
37 struct gpio_softc {
38 struct device sc_dev;
39
40 gpio_chipset_tag_t sc_gc; /* GPIO controller */
41 gpio_pin_t *sc_pins; /* pins array */
42 int sc_npins; /* number of pins */
43
44 int sc_opened;
45 LIST_HEAD(, gpio_dev) sc_devs; /* devices */
46 LIST_HEAD(, gpio_name) sc_names; /* named pins */
47 };
48
49 int gpio_match(struct device *, void *, void *);
50 int gpio_submatch(struct device *, void *, void *);
51 void gpio_attach(struct device *, struct device *, void *);
52 int gpio_detach(struct device *, int);
53 int gpio_search(struct device *, void *, void *);
54 int gpio_print(void *, const char *);
55 int gpio_pinbyname(struct gpio_softc *, char *gp_name);
56 int gpio_ioctl(struct gpio_softc *, u_long, caddr_t, int);
57
58 const struct cfattach gpio_ca = {
59 sizeof (struct gpio_softc),
60 gpio_match,
61 gpio_attach,
62 gpio_detach
63 };
64
65 struct cfdriver gpio_cd = {
66 NULL, "gpio", DV_DULL
67 };
68
69 int
70 gpio_match(struct device *parent, void *match, void *aux)
71 {
72 struct cfdata *cf = match;
73 struct gpiobus_attach_args *gba = aux;
74
75 return (strcmp(gba->gba_name, cf->cf_driver->cd_name) == 0);
76 }
77
78 int
79 gpio_submatch(struct device *parent, void *match, void *aux)
80 {
81 struct cfdata *cf = match;
82 struct gpio_attach_args *ga = aux;
83
84 if (strcmp(ga->ga_dvname, cf->cf_driver->cd_name) != 0)
85 return (0);
86
87 return ((*cf->cf_attach->ca_match)(parent, match, aux));
88 }
89
90 void
91 gpio_attach(struct device *parent, struct device *self, void *aux)
92 {
93 struct gpio_softc *sc = (struct gpio_softc *)self;
94 struct gpiobus_attach_args *gba = aux;
95
96 sc->sc_gc = gba->gba_gc;
97 sc->sc_pins = gba->gba_pins;
98 sc->sc_npins = gba->gba_npins;
99
100 printf(": %d pins\n", sc->sc_npins);
101
102 /*
103 * Attach all devices that can be connected to the GPIO pins
104 * described in the kernel configuration file.
105 */
106 config_search(gpio_search, self, sc);
107 }
108
109 int
110 gpio_detach(struct device *self, int flags)
111 {
112 int maj, mn;
113
114 /* Locate the major number */
115 for (maj = 0; maj < nchrdev; maj++)
116 if (cdevsw[maj].d_open == gpioopen)
117 break;
118
119 /* Nuke the vnodes for any open instances (calls close) */
120 mn = self->dv_unit;
121 vdevgone(maj, mn, mn, VCHR);
122
123 return (0);
124 }
125
126 int
127 gpio_search(struct device *parent, void *arg, void *aux)
128 {
129 struct cfdata *cf = arg;
130 struct gpio_attach_args ga;
131
132 ga.ga_gpio = aux;
133 ga.ga_offset = cf->cf_loc[0];
134 ga.ga_mask = cf->cf_loc[1];
135 ga.ga_flags = cf->cf_loc[2];
136
137 if (cf->cf_attach->ca_match(parent, cf, &ga) > 0)
138 config_attach(parent, cf, &ga, gpio_print);
139
140 return (0);
141 }
142
143 int
144 gpio_print(void *aux, const char *pnp)
145 {
146 struct gpio_attach_args *ga = aux;
147 int i;
148
149 printf(" pins");
150 for (i = 0; i < 32; i++)
151 if (ga->ga_mask & (1 << i))
152 printf(" %d", ga->ga_offset + i);
153
154 return (UNCONF);
155 }
156
157 int
158 gpiobus_print(void *aux, const char *pnp)
159 {
160 struct gpiobus_attach_args *gba = aux;
161
162 if (pnp != NULL)
163 printf("%s at %s", gba->gba_name, pnp);
164
165 return (UNCONF);
166 }
167
168 int
169 gpio_pin_map(void *gpio, int offset, u_int32_t mask, struct gpio_pinmap *map)
170 {
171 struct gpio_softc *sc = gpio;
172 int npins, pin, i;
173
174 npins = gpio_npins(mask);
175 if (npins > sc->sc_npins)
176 return (1);
177
178 for (npins = 0, i = 0; i < 32; i++)
179 if (mask & (1 << i)) {
180 pin = offset + i;
181 if (pin < 0 || pin >= sc->sc_npins)
182 return (1);
183 if (sc->sc_pins[pin].pin_mapped)
184 return (1);
185 sc->sc_pins[pin].pin_mapped = 1;
186 map->pm_map[npins++] = pin;
187 }
188 map->pm_size = npins;
189
190 return (0);
191 }
192
193 void
194 gpio_pin_unmap(void *gpio, struct gpio_pinmap *map)
195 {
196 struct gpio_softc *sc = gpio;
197 int pin, i;
198
199 for (i = 0; i < map->pm_size; i++) {
200 pin = map->pm_map[i];
201 sc->sc_pins[pin].pin_mapped = 0;
202 }
203 }
204
205 int
206 gpio_pin_read(void *gpio, struct gpio_pinmap *map, int pin)
207 {
208 struct gpio_softc *sc = gpio;
209
210 return (gpiobus_pin_read(sc->sc_gc, map->pm_map[pin]));
211 }
212
213 void
214 gpio_pin_write(void *gpio, struct gpio_pinmap *map, int pin, int value)
215 {
216 struct gpio_softc *sc = gpio;
217
218 return (gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value));
219 }
220
221 void
222 gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags)
223 {
224 struct gpio_softc *sc = gpio;
225
226 return (gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags));
227 }
228
229 int
230 gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin)
231 {
232 struct gpio_softc *sc = gpio;
233
234 return (sc->sc_pins[map->pm_map[pin]].pin_caps);
235 }
236
237 int
238 gpio_npins(u_int32_t mask)
239 {
240 int npins, i;
241
242 for (npins = 0, i = 0; i < 32; i++)
243 if (mask & (1 << i))
244 npins++;
245
246 return (npins);
247 }
248
249 int
250 gpioopen(dev_t dev, int flag, int mode, struct proc *p)
251 {
252 struct gpio_softc *sc;
253 int error = 0;
254
255 sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev));
256 if (sc == NULL)
257 return (ENXIO);
258
259 if (sc->sc_opened)
260 error = EBUSY;
261 else
262 sc->sc_opened = 1;
263
264 device_unref(&sc->sc_dev);
265
266 return (error);
267 }
268
269 int
270 gpioclose(dev_t dev, int flag, int mode, struct proc *p)
271 {
272 struct gpio_softc *sc;
273
274 sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev));
275 if (sc == NULL)
276 return (ENXIO);
277
278 sc->sc_opened = 0;
279
280 device_unref(&sc->sc_dev);
281
282 return (0);
283 }
284
285 int
286 gpio_pinbyname(struct gpio_softc *sc, char *gp_name)
287 {
288 struct gpio_name *nm;
289
290 LIST_FOREACH(nm, &sc->sc_names, gp_next)
291 if (!strcmp(nm->gp_name, gp_name))
292 return (nm->gp_pin);
293 return (-1);
294 }
295
296 int
297 gpio_ioctl(struct gpio_softc *sc, u_long cmd, caddr_t data, int flag)
298 {
299 gpio_chipset_tag_t gc;
300 struct gpio_info *info;
301 struct gpio_pin_op *op;
302 struct gpio_attach *attach;
303 struct gpio_attach_args ga;
304 struct gpio_dev *gdev;
305 struct gpio_name *nm;
306 struct gpio_pin_set *set;
307 struct device *dv;
308 int pin, value, flags, npins, found;
309
310 gc = sc->sc_gc;
311
312 switch (cmd) {
313 case GPIOINFO:
314 info = (struct gpio_info *)data;
315 if (securelevel < 1)
316 info->gpio_npins = sc->sc_npins;
317 else {
318 for (pin = npins = 0; pin < sc->sc_npins; pin++)
319 if (sc->sc_pins[pin].pin_flags & GPIO_PIN_SET)
320 ++npins;
321 info->gpio_npins = npins;
322 }
323 break;
324 case GPIOPINREAD:
325 op = (struct gpio_pin_op *)data;
326
327 if (op->gp_name[0] != '\0') {
328 pin = gpio_pinbyname(sc, op->gp_name);
329 if (pin == -1)
330 return (EINVAL);
331 } else
332 pin = op->gp_pin;
333
334 if (pin < 0 || pin >= sc->sc_npins)
335 return (EINVAL);
336
337 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
338 securelevel > 0)
339 return (EPERM);
340
341 /* return read value */
342 op->gp_value = gpiobus_pin_read(gc, pin);
343 break;
344 case GPIOPINWRITE:
345 if ((flag & FWRITE) == 0)
346 return (EBADF);
347
348 op = (struct gpio_pin_op *)data;
349
350 if (op->gp_name[0] != '\0') {
351 pin = gpio_pinbyname(sc, op->gp_name);
352 if (pin == -1)
353 return (EINVAL);
354 } else
355 pin = op->gp_pin;
356
357 if (pin < 0 || pin >= sc->sc_npins)
358 return (EINVAL);
359
360 if (sc->sc_pins[pin].pin_mapped)
361 return (EBUSY);
362
363 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
364 securelevel > 0)
365 return (EPERM);
366
367 value = op->gp_value;
368 if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
369 return (EINVAL);
370
371 gpiobus_pin_write(gc, pin, value);
372 /* return old value */
373 op->gp_value = sc->sc_pins[pin].pin_state;
374 /* update current value */
375 sc->sc_pins[pin].pin_state = value;
376 break;
377 case GPIOPINTOGGLE:
378 if ((flag & FWRITE) == 0)
379 return (EBADF);
380
381 op = (struct gpio_pin_op *)data;
382
383 if (op->gp_name[0] != '\0') {
384 pin = gpio_pinbyname(sc, op->gp_name);
385 if (pin == -1)
386 return (EINVAL);
387 } else
388 pin = op->gp_pin;
389
390 if (pin < 0 || pin >= sc->sc_npins)
391 return (EINVAL);
392
393 if (sc->sc_pins[pin].pin_mapped)
394 return (EBUSY);
395
396 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
397 securelevel > 0)
398 return (EPERM);
399
400 value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
401 GPIO_PIN_HIGH : GPIO_PIN_LOW);
402 gpiobus_pin_write(gc, pin, value);
403 /* return old value */
404 op->gp_value = sc->sc_pins[pin].pin_state;
405 /* update current value */
406 sc->sc_pins[pin].pin_state = value;
407 break;
408 case GPIOATTACH:
409 if (securelevel > 0)
410 return (EPERM);
411
412 attach = (struct gpio_attach *)data;
413 bzero(&ga, sizeof(ga));
414 ga.ga_gpio = sc;
415 ga.ga_dvname = attach->ga_dvname;
416 ga.ga_offset = attach->ga_offset;
417 ga.ga_mask = attach->ga_mask;
418 ga.ga_flags = attach->ga_flags;
419 dv = config_found_sm((struct device *)sc, &ga, gpiobus_print,
420 gpio_submatch);
421 if (dv != NULL) {
422 gdev = malloc(sizeof(*gdev), M_DEVBUF,
423 M_WAITOK);
424 gdev->sc_dev = dv;
425 LIST_INSERT_HEAD(&sc->sc_devs, gdev, sc_next);
426 }
427 break;
428 case GPIODETACH:
429 if (securelevel > 0)
430 return (EPERM);
431
432 attach = (struct gpio_attach *)data;
433 LIST_FOREACH(gdev, &sc->sc_devs, sc_next) {
434 if (strcmp(gdev->sc_dev->dv_xname, attach->ga_dvname)
435 == 0) {
436 if (config_detach(gdev->sc_dev, 0) == 0) {
437 LIST_REMOVE(gdev, sc_next);
438 free(gdev, M_DEVBUF, sizeof(*gdev));
439 }
440 break;
441 }
442 }
443 break;
444 case GPIOPINSET:
445 if (securelevel > 0)
446 return (EPERM);
447
448 set = (struct gpio_pin_set *)data;
449
450 if (set->gp_name[0] != '\0') {
451 pin = gpio_pinbyname(sc, set->gp_name);
452 if (pin == -1)
453 return (EINVAL);
454 } else
455 pin = set->gp_pin;
456 if (pin < 0 || pin >= sc->sc_npins)
457 return (EINVAL);
458 flags = set->gp_flags;
459 /* check that the controller supports all requested flags */
460 if ((flags & sc->sc_pins[pin].pin_caps) != flags)
461 return (ENODEV);
462 flags = set->gp_flags | GPIO_PIN_SET;
463
464 set->gp_caps = sc->sc_pins[pin].pin_caps;
465 /* return old value */
466 set->gp_flags = sc->sc_pins[pin].pin_flags;
467 if (flags > 0) {
468 gpiobus_pin_ctl(gc, pin, flags);
469 /* update current value */
470 sc->sc_pins[pin].pin_flags = flags;
471 }
472
473 /* rename pin or new pin? */
474 if (set->gp_name2[0] != '\0') {
475 found = 0;
476 LIST_FOREACH(nm, &sc->sc_names, gp_next)
477 if (nm->gp_pin == pin) {
478 strlcpy(nm->gp_name, set->gp_name2,
479 sizeof(nm->gp_name));
480 found = 1;
481 break;
482 }
483 if (!found) {
484 nm = malloc(sizeof(*nm), M_DEVBUF, M_WAITOK);
485 strlcpy(nm->gp_name, set->gp_name2,
486 sizeof(nm->gp_name));
487 nm->gp_pin = set->gp_pin;
488 LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next);
489 }
490 }
491 break;
492 case GPIOPINUNSET:
493 if (securelevel > 0)
494 return (EPERM);
495
496 set = (struct gpio_pin_set *)data;
497 if (set->gp_name[0] != '\0') {
498 pin = gpio_pinbyname(sc, set->gp_name);
499 if (pin == -1)
500 return (EINVAL);
501 } else
502 pin = set->gp_pin;
503
504 if (pin < 0 || pin >= sc->sc_npins)
505 return (EINVAL);
506 if (sc->sc_pins[pin].pin_mapped)
507 return (EBUSY);
508 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET))
509 return (EINVAL);
510
511 LIST_FOREACH(nm, &sc->sc_names, gp_next) {
512 if (nm->gp_pin == pin) {
513 LIST_REMOVE(nm, gp_next);
514 free(nm, M_DEVBUF, sizeof(*nm));
515 break;
516 }
517 }
518 sc->sc_pins[pin].pin_flags &= ~GPIO_PIN_SET;
519 break;
520 default:
521 return (ENOTTY);
522 }
523
524 return (0);
525 }
526
527 int
528 gpioioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
529 {
530 struct gpio_softc *sc;
531 int error;
532
533 sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev));
534 if (sc == NULL)
535 return (ENXIO);
536
537 error = gpio_ioctl(sc, cmd, data, flag);
538
539 device_unref(&sc->sc_dev);
540
541 return (error);
542 }
Cache object: 50bccd4ee3e0b66e584863e6052aec9c
|