xref: /freebsd/sys/dev/bhnd/cores/chipc/chipc_gpio.c (revision c063fb7accae4cbe5e0fb808a1382600dc1b4249)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2017 The FreeBSD Foundation
5  *
6  * This software was developed by Landon Fuller under sponsorship from
7  * the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/param.h>
32 #include <sys/kernel.h>
33 #include <sys/bus.h>
34 #include <sys/gpio.h>
35 #include <sys/limits.h>
36 #include <sys/module.h>
37 
38 #include <machine/_inttypes.h>
39 #include <machine/bus.h>
40 #include <sys/rman.h>
41 #include <machine/resource.h>
42 
43 #include <dev/bhnd/bhnd.h>
44 #include <dev/gpio/gpiobusvar.h>
45 
46 #include "gpio_if.h"
47 
48 #include "bhnd_nvram_map.h"
49 
50 #include "chipcreg.h"
51 #include "chipc_gpiovar.h"
52 
53 /*
54  * ChipCommon GPIO driver
55  */
56 
57 static int			chipc_gpio_check_flags(
58 				    struct chipc_gpio_softc *sc,
59 				    uint32_t pin_num, uint32_t flags,
60 				    chipc_gpio_pin_mode *mode);
61 static int			chipc_gpio_pin_update(
62 				    struct chipc_gpio_softc *sc,
63 				    struct chipc_gpio_update *update,
64 				    uint32_t pin_num, uint32_t flags);
65 static int			chipc_gpio_commit_update(
66 				    struct chipc_gpio_softc *sc,
67 				    struct chipc_gpio_update *update);
68 static chipc_gpio_pin_mode	chipc_gpio_pin_get_mode(
69 				    struct chipc_gpio_softc *sc,
70 				    uint32_t pin_num);
71 
72 /* Debugging flags */
73 static u_long chipc_gpio_debug = 0;
74 TUNABLE_ULONG("hw.bhnd_chipc.gpio_debug", &chipc_gpio_debug);
75 
76 enum {
77 	/** Allow userspace GPIO access on bridged network (e.g. wi-fi)
78 	  * adapters */
79 	CC_GPIO_DEBUG_ADAPTER_GPIOC = 1 << 0,
80 };
81 
82 #define	CC_GPIO_DEBUG(_type)	(CC_GPIO_DEBUG_ ## _type & chipc_gpio_debug)
83 
84 static struct bhnd_device_quirk chipc_gpio_quirks[];
85 
86 /* Supported parent core device identifiers */
87 static const struct bhnd_device chipc_gpio_devices[] = {
88 	BHND_DEVICE(BCM, CC, "Broadcom ChipCommon GPIO", chipc_gpio_quirks),
89 	BHND_DEVICE_END
90 };
91 
92 /* Device quirks table */
93 static struct bhnd_device_quirk chipc_gpio_quirks[] = {
94 	BHND_CORE_QUIRK	(HWREV_LTE(10),	CC_GPIO_QUIRK_NO_EVENTS),
95 	BHND_CORE_QUIRK	(HWREV_LTE(15),	CC_GPIO_QUIRK_NO_DCTIMER),
96 	BHND_CORE_QUIRK	(HWREV_LTE(19),	CC_GPIO_QUIRK_NO_PULLUPDOWN),
97 
98 	BHND_DEVICE_QUIRK_END
99 };
100 
101 static int
chipc_gpio_probe(device_t dev)102 chipc_gpio_probe(device_t dev)
103 {
104 	const struct bhnd_device	*id;
105 	device_t			 chipc;
106 
107 	/* Look for compatible chipc parent */
108 	chipc = device_get_parent(dev);
109 	id = bhnd_device_lookup(chipc, chipc_gpio_devices,
110 	    sizeof(chipc_gpio_devices[0]));
111 	if (id == NULL)
112 		return (ENXIO);
113 
114 	device_set_desc(dev, id->desc);
115 	return (BUS_PROBE_NOWILDCARD);
116 }
117 
118 static int
chipc_gpio_attach(device_t dev)119 chipc_gpio_attach(device_t dev)
120 {
121 	struct chipc_gpio_softc	*sc;
122 	device_t		 chipc;
123 	int			 error;
124 
125 	chipc = device_get_parent(dev);
126 
127 	sc = device_get_softc(dev);
128 	sc->dev = dev;
129 	sc->quirks = bhnd_device_quirks(chipc, chipc_gpio_devices,
130 	    sizeof(chipc_gpio_devices[0]));
131 
132 	/* If this is a bridged wi-fi adapter, we don't want to support
133 	 * userspace requests via gpioc(4) */
134 	if (bhnd_get_attach_type(chipc) == BHND_ATTACH_ADAPTER) {
135 		if (!CC_GPIO_DEBUG(ADAPTER_GPIOC))
136 			sc->quirks |= CC_GPIO_QUIRK_NO_GPIOC;
137 	}
138 
139 	CC_GPIO_LOCK_INIT(sc);
140 
141 	sc->mem_rid = 0;
142 	sc->mem_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
143 	    RF_ACTIVE|RF_SHAREABLE);
144 	if (sc->mem_res == NULL) {
145 		device_printf(dev, "failed to allocate chipcommon registers\n");
146 		error = ENXIO;
147 		goto failed;
148 	}
149 
150 	/*
151 	 * If hardware 'pulsate' support is available, set the timer duty-cycle
152 	 * to either the NVRAM 'leddc' value if available, or the default duty
153 	 * cycle.
154 	 */
155 	if (!CC_GPIO_QUIRK(sc, NO_DCTIMER)) {
156 		uint32_t dctimerval;
157 
158 		error = bhnd_nvram_getvar_uint32(chipc, BHND_NVAR_LEDDC,
159 		    &dctimerval);
160 		if (error == ENOENT) {
161 			/* Fall back on default duty cycle */
162 			dctimerval = CHIPC_GPIOTIMERVAL_DEFAULT;
163 		} else if (error) {
164 			device_printf(dev, "error reading %s from NVRAM: %d\n",
165 			    BHND_NVAR_LEDDC, error);
166 			goto failed;
167 		}
168 
169 		CC_GPIO_WR4(sc, CHIPC_GPIOTIMERVAL, dctimerval);
170 	}
171 
172 	/* Attach gpioc/gpiobus */
173 	if (CC_GPIO_QUIRK(sc, NO_GPIOC)) {
174 		sc->gpiobus = NULL;
175 	} else {
176 		if ((sc->gpiobus = gpiobus_add_bus(dev)) == NULL) {
177 			device_printf(dev, "failed to attach gpiobus\n");
178 			error = ENXIO;
179 			goto failed;
180 		}
181 
182 		bus_attach_children(dev);
183 	}
184 
185 	/* Register as the bus GPIO provider */
186 	if ((error = bhnd_register_provider(dev, BHND_SERVICE_GPIO))) {
187 		device_printf(dev, "failed to register gpio with bus: %d\n",
188 		    error);
189 		goto failed;
190 	}
191 
192 	return (0);
193 
194 failed:
195 	device_delete_children(dev);
196 
197 	if (sc->mem_res != NULL) {
198 		bhnd_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid,
199 		    sc->mem_res);
200 	}
201 
202 	CC_GPIO_LOCK_DESTROY(sc);
203 
204 	return (error);
205 }
206 
207 static int
chipc_gpio_detach(device_t dev)208 chipc_gpio_detach(device_t dev)
209 {
210 	struct chipc_gpio_softc	*sc;
211 	int			 error;
212 
213 	sc = device_get_softc(dev);
214 
215 	if ((error = bus_generic_detach(dev)))
216 		return (error);
217 
218 	if ((error = bhnd_deregister_provider(dev, BHND_SERVICE_ANY)))
219 		return (error);
220 
221 	bhnd_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res);
222 	CC_GPIO_LOCK_DESTROY(sc);
223 
224 	return (0);
225 }
226 
227 static device_t
chipc_gpio_get_bus(device_t dev)228 chipc_gpio_get_bus(device_t dev)
229 {
230 	struct chipc_gpio_softc *sc = device_get_softc(dev);
231 
232 	return (sc->gpiobus);
233 }
234 
235 static int
chipc_gpio_pin_max(device_t dev,int * maxpin)236 chipc_gpio_pin_max(device_t dev, int *maxpin)
237 {
238 	*maxpin = CC_GPIO_NPINS-1;
239 	return (0);
240 }
241 
242 static int
chipc_gpio_pin_set(device_t dev,uint32_t pin_num,uint32_t pin_value)243 chipc_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value)
244 {
245 	struct chipc_gpio_softc	*sc;
246 	bool			 pin_high;
247 	int			 error;
248 
249 	sc = device_get_softc(dev);
250 	error = 0;
251 
252 	if (!CC_GPIO_VALID_PIN(pin_num))
253 		return (EINVAL);
254 
255 	switch (pin_value) {
256 	case GPIO_PIN_HIGH:
257 		pin_high = true;
258 		break;
259 	case GPIO_PIN_LOW:
260 		pin_high = false;
261 		break;
262 	default:
263 		return (EINVAL);
264 	}
265 
266 	CC_GPIO_LOCK(sc);
267 
268 	switch (chipc_gpio_pin_get_mode(sc, pin_num)) {
269 	case CC_GPIO_PIN_INPUT:
270 	case CC_GPIO_PIN_TRISTATE:
271 		error = ENODEV;
272 		break;
273 
274 	case CC_GPIO_PIN_OUTPUT:
275 		CC_GPIO_WRFLAG(sc, pin_num, GPIOOUT, pin_high);
276 		break;
277 	}
278 
279 	CC_GPIO_UNLOCK(sc);
280 
281 	return (error);
282 }
283 
284 static int
chipc_gpio_pin_get(device_t dev,uint32_t pin_num,uint32_t * pin_value)285 chipc_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value)
286 {
287 	struct chipc_gpio_softc	*sc;
288 	bool			 pin_high;
289 
290 	if (!CC_GPIO_VALID_PIN(pin_num))
291 		return (EINVAL);
292 
293 	sc = device_get_softc(dev);
294 	pin_high = false;
295 
296 	CC_GPIO_LOCK(sc);
297 
298 	switch (chipc_gpio_pin_get_mode(sc, pin_num)) {
299 	case CC_GPIO_PIN_INPUT:
300 		pin_high = CC_GPIO_RDFLAG(sc, pin_num, GPIOIN);
301 		break;
302 
303 	case CC_GPIO_PIN_OUTPUT:
304 		pin_high = CC_GPIO_RDFLAG(sc, pin_num, GPIOOUT);
305 		break;
306 
307 	case CC_GPIO_PIN_TRISTATE:
308 		pin_high = false;
309 		break;
310 	}
311 
312 	CC_GPIO_UNLOCK(sc);
313 
314 	*pin_value = pin_high ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
315 
316 	return (0);
317 }
318 
319 static int
chipc_gpio_pin_toggle(device_t dev,uint32_t pin_num)320 chipc_gpio_pin_toggle(device_t dev, uint32_t pin_num)
321 {
322 	struct chipc_gpio_softc	*sc;
323 	bool			 pin_high;
324 	int			 error;
325 
326 	if (!CC_GPIO_VALID_PIN(pin_num))
327 		return (EINVAL);
328 
329 	sc = device_get_softc(dev);
330 	error = 0;
331 
332 	CC_GPIO_LOCK(sc);
333 
334 	switch (chipc_gpio_pin_get_mode(sc, pin_num)) {
335 	case CC_GPIO_PIN_INPUT:
336 	case CC_GPIO_PIN_TRISTATE:
337 		error = ENODEV;
338 		break;
339 
340 	case CC_GPIO_PIN_OUTPUT:
341 		pin_high = CC_GPIO_RDFLAG(sc, pin_num, GPIOOUT);
342 		CC_GPIO_WRFLAG(sc, pin_num, GPIOOUT, !pin_high);
343 		break;
344 	}
345 
346 	CC_GPIO_UNLOCK(sc);
347 
348 	return (error);
349 }
350 
351 static int
chipc_gpio_pin_getcaps(device_t dev,uint32_t pin_num,uint32_t * caps)352 chipc_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps)
353 {
354 	struct chipc_gpio_softc	*sc = device_get_softc(dev);
355 
356 	if (!CC_GPIO_VALID_PIN(pin_num))
357 		return (EINVAL);
358 
359 	*caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
360 
361 	if (!CC_GPIO_QUIRK(sc, NO_PULLUPDOWN))
362 		*caps |= (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
363 
364 	if (!CC_GPIO_QUIRK(sc, NO_DCTIMER))
365 		*caps |= GPIO_PIN_PULSATE;
366 
367 	return (0);
368 }
369 
370 static int
chipc_gpio_pin_getflags(device_t dev,uint32_t pin_num,uint32_t * flags)371 chipc_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags)
372 {
373 	struct chipc_gpio_softc *sc = device_get_softc(dev);
374 
375 	if (!CC_GPIO_VALID_PIN(pin_num))
376 		return (EINVAL);
377 
378 	CC_GPIO_LOCK(sc);
379 
380 	switch (chipc_gpio_pin_get_mode(sc, pin_num)) {
381 	case CC_GPIO_PIN_INPUT:
382 		*flags = GPIO_PIN_INPUT;
383 
384 		if (!CC_GPIO_QUIRK(sc, NO_PULLUPDOWN)) {
385 			if (CC_GPIO_RDFLAG(sc, pin_num, GPIOPU)) {
386 				*flags |= GPIO_PIN_PULLUP;
387 			} else if (CC_GPIO_RDFLAG(sc, pin_num, GPIOPD)) {
388 				*flags |= GPIO_PIN_PULLDOWN;
389 			}
390 		}
391 		break;
392 
393 	case CC_GPIO_PIN_OUTPUT:
394 		*flags = GPIO_PIN_OUTPUT;
395 
396 		if (!CC_GPIO_QUIRK(sc, NO_DCTIMER)) {
397 			if (CC_GPIO_RDFLAG(sc, pin_num, GPIOTIMEROUTMASK))
398 				*flags |= GPIO_PIN_PULSATE;
399 		}
400 
401 		break;
402 
403 	case CC_GPIO_PIN_TRISTATE:
404 		*flags = GPIO_PIN_TRISTATE|GPIO_PIN_OUTPUT;
405 		break;
406 	}
407 
408 	CC_GPIO_UNLOCK(sc);
409 
410 	return (0);
411 }
412 
413 static int
chipc_gpio_pin_getname(device_t dev,uint32_t pin_num,char * name)414 chipc_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name)
415 {
416 	int ret;
417 
418 	if (!CC_GPIO_VALID_PIN(pin_num))
419 		return (EINVAL);
420 
421 	ret = snprintf(name, GPIOMAXNAME, "bhnd_gpio%02" PRIu32, pin_num);
422 
423 	if (ret < 0)
424 		return (ENXIO);
425 
426 	if (ret >= GPIOMAXNAME)
427 		return (ENOMEM);
428 
429 	return (0);
430 }
431 
432 static int
chipc_gpio_pin_setflags(device_t dev,uint32_t pin_num,uint32_t flags)433 chipc_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags)
434 {
435 	struct chipc_gpio_softc		*sc;
436 	struct chipc_gpio_update	 upd;
437 	int				 error;
438 
439 	sc = device_get_softc(dev);
440 
441 	if (!CC_GPIO_VALID_PIN(pin_num))
442 		return (EINVAL);
443 
444 	/* Produce an update descriptor */
445 	memset(&upd, 0, sizeof(upd));
446 	if ((error = chipc_gpio_pin_update(sc, &upd, pin_num, flags)))
447 		return (error);
448 
449 	/* Commit the update */
450 	CC_GPIO_LOCK(sc);
451 	error = chipc_gpio_commit_update(sc, &upd);
452 	CC_GPIO_UNLOCK(sc);
453 
454 	return (error);
455 }
456 
457 static int
chipc_gpio_pin_access_32(device_t dev,uint32_t first_pin,uint32_t clear_pins,uint32_t change_pins,uint32_t * orig_pins)458 chipc_gpio_pin_access_32(device_t dev, uint32_t first_pin, uint32_t clear_pins,
459     uint32_t change_pins, uint32_t *orig_pins)
460 {
461 	struct chipc_gpio_softc		*sc;
462 	struct chipc_gpio_update	 upd;
463 	uint32_t			 out, outen, ctrl;
464 	uint32_t			 num_pins;
465 	int				 error;
466 
467 	sc = device_get_softc(dev);
468 
469 	if (first_pin >= CC_GPIO_NPINS)
470 		return (EINVAL);
471 
472 	/* Determine the actual number of referenced pins */
473 	if (clear_pins == 0 && change_pins == 0) {
474 		num_pins = CC_GPIO_NPINS - first_pin;
475 	} else {
476 		int num_clear_pins, num_change_pins;
477 
478 		num_clear_pins = flsl((u_long)clear_pins);
479 		num_change_pins = flsl((u_long)change_pins);
480 		num_pins = MAX(num_clear_pins, num_change_pins);
481 	}
482 
483 	/* Validate the full pin range */
484 	if (!CC_GPIO_VALID_PINS(first_pin, num_pins))
485 		return (EINVAL);
486 
487 	/* Produce an update descriptor for all pins, relative to the current
488 	 * pin state */
489 	CC_GPIO_LOCK(sc);
490 	memset(&upd, 0, sizeof(upd));
491 
492 	out = CC_GPIO_RD4(sc, CHIPC_GPIOOUT);
493 	outen = CC_GPIO_RD4(sc, CHIPC_GPIOOUTEN);
494 	ctrl = CC_GPIO_RD4(sc, CHIPC_GPIOCTRL);
495 
496 	for (uint32_t i = 0; i < num_pins; i++) {
497 		uint32_t	pin;
498 		bool		pin_high;
499 
500 		pin = first_pin + i;
501 
502 		/* The pin must be configured for output */
503 		if ((outen & (1 << pin)) == 0) {
504 			CC_GPIO_UNLOCK(sc);
505 			return (EINVAL);
506 		}
507 
508 		/* The pin must not tristated */
509 		if ((ctrl & (1 << pin)) != 0) {
510 			CC_GPIO_UNLOCK(sc);
511 			return (EINVAL);
512 		}
513 
514 		/* Fetch current state */
515 		if (out & (1 << pin)) {
516 			pin_high = true;
517 		} else {
518 			pin_high = false;
519 		}
520 
521 		/* Apply clear/toggle request */
522 		if (clear_pins & (1 << pin))
523 			pin_high = false;
524 
525 		if (change_pins & (1 << pin))
526 			pin_high = !pin_high;
527 
528 		/* Add to our update descriptor */
529 		CC_GPIO_UPDATE(&upd, pin, out, pin_high);
530 	}
531 
532 	/* Commit the update */
533 	error = chipc_gpio_commit_update(sc, &upd);
534 	CC_GPIO_UNLOCK(sc);
535 
536 	return (error);
537 }
538 
539 static int
chipc_gpio_pin_config_32(device_t dev,uint32_t first_pin,uint32_t num_pins,uint32_t * pin_flags)540 chipc_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t num_pins,
541     uint32_t *pin_flags)
542 {
543 	struct chipc_gpio_softc		*sc;
544 	struct chipc_gpio_update	 upd;
545 	int				 error;
546 
547 	sc = device_get_softc(dev);
548 
549 	if (!CC_GPIO_VALID_PINS(first_pin, num_pins))
550 		return (EINVAL);
551 
552 	/* Produce an update descriptor */
553 	memset(&upd, 0, sizeof(upd));
554 	for (uint32_t i = 0; i < num_pins; i++) {
555 		uint32_t pin, flags;
556 
557 		pin = first_pin + i;
558 		flags = pin_flags[i];
559 
560 		/* As per the gpio_config_32 API documentation, any pins for
561 		 * which neither GPIO_PIN_OUTPUT or GPIO_PIN_INPUT are set
562 		 * should be ignored and left unmodified */
563 		if ((flags & (GPIO_PIN_OUTPUT|GPIO_PIN_INPUT)) == 0)
564 			continue;
565 
566 		if ((error = chipc_gpio_pin_update(sc, &upd, pin, flags)))
567 			return (error);
568 	}
569 
570 	/* Commit the update */
571 	CC_GPIO_LOCK(sc);
572 	error = chipc_gpio_commit_update(sc, &upd);
573 	CC_GPIO_UNLOCK(sc);
574 
575 	return (error);
576 }
577 
578 /**
579  * Commit a single @p reg register update.
580  */
581 static void
chipc_gpio_commit_reg(struct chipc_gpio_softc * sc,bus_size_t offset,struct chipc_gpio_reg * reg)582 chipc_gpio_commit_reg(struct chipc_gpio_softc *sc, bus_size_t offset,
583     struct chipc_gpio_reg *reg)
584 {
585 	uint32_t value;
586 
587 	CC_GPIO_LOCK_ASSERT(sc, MA_OWNED);
588 
589 	if (reg->mask == 0)
590 		return;
591 
592 	value = bhnd_bus_read_4(sc->mem_res, offset);
593 	value &= ~reg->mask;
594 	value |= reg->value;
595 
596 	bhnd_bus_write_4(sc->mem_res, offset, value);
597 }
598 
599 /**
600  * Commit the set of GPIO register updates described by @p update.
601  */
602 static int
chipc_gpio_commit_update(struct chipc_gpio_softc * sc,struct chipc_gpio_update * update)603 chipc_gpio_commit_update(struct chipc_gpio_softc *sc,
604     struct chipc_gpio_update *update)
605 {
606 	CC_GPIO_LOCK_ASSERT(sc, MA_OWNED);
607 
608 	/* Commit pulldown/pullup before potentially disabling an output pin */
609 	chipc_gpio_commit_reg(sc, CHIPC_GPIOPD, &update->pulldown);
610 	chipc_gpio_commit_reg(sc, CHIPC_GPIOPU, &update->pullup);
611 
612 	/* Commit output settings before potentially enabling an output pin */
613 	chipc_gpio_commit_reg(sc, CHIPC_GPIOTIMEROUTMASK,
614 	    &update->timeroutmask);
615 	chipc_gpio_commit_reg(sc, CHIPC_GPIOOUT, &update->out);
616 
617 	/* Commit input/output/tristate modes */
618 	chipc_gpio_commit_reg(sc, CHIPC_GPIOOUTEN, &update->outen);
619 	chipc_gpio_commit_reg(sc, CHIPC_GPIOCTRL, &update->ctrl);
620 
621 	return (0);
622 }
623 
624 /**
625  * Apply the changes described by @p flags for @p pin_num to the given @p update
626  * descriptor.
627  */
628 static int
chipc_gpio_pin_update(struct chipc_gpio_softc * sc,struct chipc_gpio_update * update,uint32_t pin_num,uint32_t flags)629 chipc_gpio_pin_update(struct chipc_gpio_softc *sc,
630     struct chipc_gpio_update *update, uint32_t pin_num, uint32_t flags)
631 {
632 	chipc_gpio_pin_mode	mode;
633 	int			error;
634 
635 	if (!CC_GPIO_VALID_PIN(pin_num))
636 		return (EINVAL);
637 
638 	/* Verify flag compatibility and determine the pin mode */
639 	if ((error = chipc_gpio_check_flags(sc, pin_num, flags, &mode)))
640 		return (error);
641 
642 	/* Apply the mode-specific changes */
643 	switch (mode) {
644 	case CC_GPIO_PIN_INPUT:
645 		CC_GPIO_UPDATE(update, pin_num, pullup, false);
646 		CC_GPIO_UPDATE(update, pin_num, pulldown, false);
647 		CC_GPIO_UPDATE(update, pin_num, out, false);
648 		CC_GPIO_UPDATE(update, pin_num, outen, false);
649 		CC_GPIO_UPDATE(update, pin_num, timeroutmask, false);
650 		CC_GPIO_UPDATE(update, pin_num, ctrl, false);
651 
652 		if (flags & GPIO_PIN_PULLUP) {
653 			CC_GPIO_UPDATE(update, pin_num, pullup, true);
654 		} else if (flags & GPIO_PIN_PULLDOWN) {
655 			CC_GPIO_UPDATE(update, pin_num, pulldown, true);
656 		}
657 
658 		return (0);
659 
660 	case CC_GPIO_PIN_OUTPUT:
661 		CC_GPIO_UPDATE(update, pin_num, pullup, false);
662 		CC_GPIO_UPDATE(update, pin_num, pulldown, false);
663 		CC_GPIO_UPDATE(update, pin_num, outen, true);
664 		CC_GPIO_UPDATE(update, pin_num, timeroutmask, false);
665 		CC_GPIO_UPDATE(update, pin_num, ctrl, false);
666 
667 		if (flags & GPIO_PIN_PRESET_HIGH) {
668 			CC_GPIO_UPDATE(update, pin_num, out, true);
669 		} else if (flags & GPIO_PIN_PRESET_LOW) {
670 			CC_GPIO_UPDATE(update, pin_num, out, false);
671 		}
672 
673 		if (flags & GPIO_PIN_PULSATE)
674 			CC_GPIO_UPDATE(update, pin_num, timeroutmask, true);
675 
676 		return (0);
677 
678 	case CC_GPIO_PIN_TRISTATE:
679 		CC_GPIO_UPDATE(update, pin_num, pullup, false);
680 		CC_GPIO_UPDATE(update, pin_num, pulldown, false);
681 		CC_GPIO_UPDATE(update, pin_num, out, false);
682 		CC_GPIO_UPDATE(update, pin_num, outen, false);
683 		CC_GPIO_UPDATE(update, pin_num, timeroutmask, false);
684 		CC_GPIO_UPDATE(update, pin_num, ctrl, true);
685 
686 		if (flags & GPIO_PIN_OUTPUT)
687 			CC_GPIO_UPDATE(update, pin_num, outen, true);
688 
689 		return (0);
690 	}
691 
692 	device_printf(sc->dev, "unknown pin mode %d\n", mode);
693 	return (EINVAL);
694 }
695 
696 /**
697  * Verify that @p flags are valid for use with @p pin_num, and on success,
698  * return the pin mode described by @p flags in @p mode.
699  *
700  * @param	sc	GPIO driver instance state.
701  * @param	pin_num	The pin number to configure.
702  * @param	flags	The pin flags to be validated.
703  * @param[out]	mode	On success, will be populated with the GPIO pin mode
704  *			defined by @p flags.
705  *
706  * @retval 0		success
707  * @retval EINVAL	if @p flags are invalid.
708  */
709 static int
chipc_gpio_check_flags(struct chipc_gpio_softc * sc,uint32_t pin_num,uint32_t flags,chipc_gpio_pin_mode * mode)710 chipc_gpio_check_flags(struct chipc_gpio_softc *sc, uint32_t pin_num,
711     uint32_t flags, chipc_gpio_pin_mode *mode)
712 {
713 	uint32_t mode_flag, input_flag, output_flag;
714 
715 	CC_GPIO_ASSERT_VALID_PIN(sc, pin_num);
716 
717 	mode_flag = flags & (GPIO_PIN_OUTPUT | GPIO_PIN_INPUT |
718 	    GPIO_PIN_TRISTATE);
719 	output_flag = flags & (GPIO_PIN_PRESET_HIGH | GPIO_PIN_PRESET_LOW
720 	    | GPIO_PIN_PULSATE);
721 	input_flag = flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
722 
723 	switch (mode_flag) {
724 	case GPIO_PIN_OUTPUT:
725 		/* No input flag(s) should be set */
726 		if (input_flag != 0)
727 			return (EINVAL);
728 
729 		/* Validate our output flag(s) */
730 		switch (output_flag) {
731 		case GPIO_PIN_PRESET_HIGH:
732 		case GPIO_PIN_PRESET_LOW:
733 		case (GPIO_PIN_PRESET_HIGH|GPIO_PIN_PULSATE):
734 		case (GPIO_PIN_PRESET_LOW|GPIO_PIN_PULSATE):
735 		case 0:
736 			/* Check for unhandled flags */
737 			if ((flags & ~(mode_flag | output_flag)) != 0)
738 				return (EINVAL);
739 
740 			*mode = CC_GPIO_PIN_OUTPUT;
741 			return (0);
742 
743 		default:
744 			/* Incompatible output flags */
745 			return (EINVAL);
746 		}
747 
748 	case GPIO_PIN_INPUT:
749 		/* No output flag(s) should be set */
750 		if (output_flag != 0)
751 			return (EINVAL);
752 
753 		/* Validate our input flag(s) */
754 		switch (input_flag) {
755 		case GPIO_PIN_PULLUP:
756 		case GPIO_PIN_PULLDOWN:
757 		case 0:
758 			/* Check for unhandled flags */
759 			if ((flags & ~(mode_flag | input_flag)) != 0)
760 				return (EINVAL);
761 
762 			*mode = CC_GPIO_PIN_INPUT;
763 			return (0);
764 
765 		default:
766 			/* Incompatible input flags */
767 			return (EINVAL);
768 		}
769 
770 		break;
771 
772 	case (GPIO_PIN_TRISTATE|GPIO_PIN_OUTPUT):
773 	case GPIO_PIN_TRISTATE:
774 		/* No input or output flag(s) should be set */
775 		if (input_flag != 0 || output_flag != 0)
776 			return (EINVAL);
777 
778 		/* Check for unhandled flags */
779 		if ((flags & ~mode_flag) != 0)
780 			return (EINVAL);
781 
782 		*mode = CC_GPIO_PIN_TRISTATE;
783 		return (0);
784 
785 	default:
786 		/* Incompatible mode flags */
787 		return (EINVAL);
788 	}
789 }
790 
791 /**
792  * Return the current pin mode for @p pin_num.
793  *
794  * @param sc		GPIO driver instance state.
795  * @param pin_num	The pin number to query.
796  */
797 static chipc_gpio_pin_mode
chipc_gpio_pin_get_mode(struct chipc_gpio_softc * sc,uint32_t pin_num)798 chipc_gpio_pin_get_mode(struct chipc_gpio_softc *sc, uint32_t pin_num)
799 {
800 	CC_GPIO_LOCK_ASSERT(sc, MA_OWNED);
801 	CC_GPIO_ASSERT_VALID_PIN(sc, pin_num);
802 
803 	if (CC_GPIO_RDFLAG(sc, pin_num, GPIOCTRL)) {
804 		return (CC_GPIO_PIN_TRISTATE);
805 	} else if (CC_GPIO_RDFLAG(sc, pin_num, GPIOOUTEN)) {
806 		return (CC_GPIO_PIN_OUTPUT);
807 	} else {
808 		return (CC_GPIO_PIN_INPUT);
809 	}
810 }
811 
812 static device_method_t chipc_gpio_methods[] = {
813 	/* Device interface */
814 	DEVMETHOD(device_probe,		chipc_gpio_probe),
815 	DEVMETHOD(device_attach,	chipc_gpio_attach),
816 	DEVMETHOD(device_detach,	chipc_gpio_detach),
817 
818 	/* GPIO interface */
819 	DEVMETHOD(gpio_get_bus,		chipc_gpio_get_bus),
820 	DEVMETHOD(gpio_pin_max,		chipc_gpio_pin_max),
821 	DEVMETHOD(gpio_pin_getname,	chipc_gpio_pin_getname),
822 	DEVMETHOD(gpio_pin_getflags,	chipc_gpio_pin_getflags),
823 	DEVMETHOD(gpio_pin_getcaps,	chipc_gpio_pin_getcaps),
824 	DEVMETHOD(gpio_pin_setflags,	chipc_gpio_pin_setflags),
825 	DEVMETHOD(gpio_pin_get,		chipc_gpio_pin_get),
826 	DEVMETHOD(gpio_pin_set,		chipc_gpio_pin_set),
827 	DEVMETHOD(gpio_pin_toggle,	chipc_gpio_pin_toggle),
828 	DEVMETHOD(gpio_pin_access_32,	chipc_gpio_pin_access_32),
829 	DEVMETHOD(gpio_pin_config_32,	chipc_gpio_pin_config_32),
830 
831 	DEVMETHOD_END
832 };
833 
834 DEFINE_CLASS_0(gpio, chipc_gpio_driver, chipc_gpio_methods, sizeof(struct chipc_gpio_softc));
835 EARLY_DRIVER_MODULE(chipc_gpio, bhnd_chipc, chipc_gpio_driver, NULL, NULL,
836     BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
837 
838 MODULE_DEPEND(chipc_gpio, bhnd, 1, 1, 1);
839 MODULE_DEPEND(chipc_gpio, gpiobus, 1, 1, 1);
840 MODULE_VERSION(chipc_gpio, 1);
841