xref: /openbsd-src/sys/dev/gpio/gpio.c (revision 894c7bfe3ebe1305bf9e68d6f2ce049895609e00)
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
gpio_match(struct device * parent,void * match,void * aux)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
gpio_submatch(struct device * parent,void * match,void * aux)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
gpio_attach(struct device * parent,struct device * self,void * aux)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
gpio_detach(struct device * self,int flags)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
gpio_search(struct device * parent,void * arg,void * aux)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
gpio_print(void * aux,const char * pnp)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
gpiobus_print(void * aux,const char * pnp)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
gpio_pin_map(void * gpio,int offset,u_int32_t mask,struct gpio_pinmap * map)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
gpio_pin_unmap(void * gpio,struct gpio_pinmap * map)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
gpio_pin_read(void * gpio,struct gpio_pinmap * map,int pin)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
gpio_pin_write(void * gpio,struct gpio_pinmap * map,int pin,int value)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
gpio_pin_ctl(void * gpio,struct gpio_pinmap * map,int pin,int flags)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
gpio_pin_caps(void * gpio,struct gpio_pinmap * map,int pin)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
gpio_npins(u_int32_t mask)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
gpioopen(dev_t dev,int flag,int mode,struct proc * p)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
gpioclose(dev_t dev,int flag,int mode,struct proc * p)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
gpio_pinbyname(struct gpio_softc * sc,char * gp_name)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
gpio_ioctl(struct gpio_softc * sc,u_long cmd,caddr_t data,int flag)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
gpioioctl(dev_t dev,u_long cmd,caddr_t data,int flag,struct proc * p)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 }
543