xref: /netbsd-src/sys/dev/ic/pl061.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /* $NetBSD: pl061.c,v 1.4 2021/08/07 16:19:12 thorpej Exp $ */
25e1be26aSjmcneill 
35e1be26aSjmcneill /*
45e1be26aSjmcneill  * Copyright (c) 2018 Jonathan A. Kollasch
55e1be26aSjmcneill  * All rights reserved.
65e1be26aSjmcneill  *
75e1be26aSjmcneill  * Redistribution and use in source and binary forms, with or without
85e1be26aSjmcneill  * modification, are permitted provided that the following conditions
95e1be26aSjmcneill  * are met:
105e1be26aSjmcneill  * 1. Redistributions of source code must retain the above copyright
115e1be26aSjmcneill  *    notice, this list of conditions and the following disclaimer.
125e1be26aSjmcneill  * 2. Redistributions in binary form must reproduce the above copyright
135e1be26aSjmcneill  *    notice, this list of conditions and the following disclaimer in the
145e1be26aSjmcneill  *    documentation and/or other materials provided with the distribution.
155e1be26aSjmcneill  *
165e1be26aSjmcneill  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175e1be26aSjmcneill  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
185e1be26aSjmcneill  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
195e1be26aSjmcneill  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
205e1be26aSjmcneill  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
215e1be26aSjmcneill  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
225e1be26aSjmcneill  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
235e1be26aSjmcneill  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
245e1be26aSjmcneill  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
255e1be26aSjmcneill  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
265e1be26aSjmcneill  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275e1be26aSjmcneill  */
285e1be26aSjmcneill 
295e1be26aSjmcneill #include <sys/cdefs.h>
30*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: pl061.c,v 1.4 2021/08/07 16:19:12 thorpej Exp $");
315e1be26aSjmcneill 
325e1be26aSjmcneill #include <sys/param.h>
335e1be26aSjmcneill #include <sys/bus.h>
345e1be26aSjmcneill #include <sys/device.h>
355e1be26aSjmcneill #include <sys/intr.h>
365e1be26aSjmcneill #include <sys/systm.h>
375e1be26aSjmcneill #include <sys/kernel.h>
385e1be26aSjmcneill #include <sys/kmem.h>
395e1be26aSjmcneill #include <sys/gpio.h>
405e1be26aSjmcneill 
415e1be26aSjmcneill #include <dev/gpio/gpiovar.h>
425e1be26aSjmcneill #include "gpio.h"
435e1be26aSjmcneill 
445e1be26aSjmcneill #include <dev/ic/pl061reg.h>
455e1be26aSjmcneill #include <dev/ic/pl061var.h>
465e1be26aSjmcneill 
475e1be26aSjmcneill void
plgpio_attach(struct plgpio_softc * sc)485e1be26aSjmcneill plgpio_attach(struct plgpio_softc *sc)
495e1be26aSjmcneill {
505e1be26aSjmcneill 	struct gpiobus_attach_args gba;
515e1be26aSjmcneill 	u_int pin;
525e1be26aSjmcneill 
535e1be26aSjmcneill 	sc->sc_gc.gp_cookie = sc;
545e1be26aSjmcneill 	sc->sc_gc.gp_pin_read = plgpio_pin_read;
555e1be26aSjmcneill 	sc->sc_gc.gp_pin_write = plgpio_pin_write;
565e1be26aSjmcneill 	sc->sc_gc.gp_pin_ctl = plgpio_pin_ctl;
575e1be26aSjmcneill 
5884f5ea61Sjmcneill 	const uint32_t cnf = PLGPIO_READ(sc, PL061_GPIOAFSEL_REG) |
5984f5ea61Sjmcneill 	    sc->sc_reserved_mask;
605e1be26aSjmcneill 
615e1be26aSjmcneill 	for (pin = 0; pin < 8; pin++) {
625e1be26aSjmcneill 		sc->sc_pins[pin].pin_num = pin;
635e1be26aSjmcneill 		/* skip pins in hardware control mode */
645e1be26aSjmcneill 		if ((cnf & __BIT(pin)) != 0)
655e1be26aSjmcneill 			continue;
665e1be26aSjmcneill 		sc->sc_pins[pin].pin_caps =
675e1be26aSjmcneill 		    GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
685e1be26aSjmcneill 		    GPIO_PIN_TRISTATE;
695e1be26aSjmcneill 		sc->sc_pins[pin].pin_state =
705e1be26aSjmcneill 		    plgpio_pin_read(sc, pin);
715e1be26aSjmcneill 	}
725e1be26aSjmcneill 
735e1be26aSjmcneill 	memset(&gba, 0, sizeof(gba));
745e1be26aSjmcneill 	gba.gba_gc = &sc->sc_gc;
755e1be26aSjmcneill 	gba.gba_pins = sc->sc_pins;
765e1be26aSjmcneill 	gba.gba_npins = 8;
775e1be26aSjmcneill 
785e1be26aSjmcneill #if NGPIO > 0
79*c7fb772bSthorpej 	config_found(sc->sc_dev, &gba, gpiobus_print, CFARGS_NONE);
805e1be26aSjmcneill #endif
815e1be26aSjmcneill }
825e1be26aSjmcneill 
835e1be26aSjmcneill int
plgpio_pin_read(void * priv,int pin)845e1be26aSjmcneill plgpio_pin_read(void *priv, int pin)
855e1be26aSjmcneill {
865e1be26aSjmcneill 	struct plgpio_softc * const sc = priv;
875e1be26aSjmcneill 
885e1be26aSjmcneill 	const uint32_t v = PLGPIO_READ(sc, PL061_GPIODATA_REG(1<<pin));
895e1be26aSjmcneill 
905e1be26aSjmcneill 	return (v >> pin) & 1;
915e1be26aSjmcneill }
925e1be26aSjmcneill 
935e1be26aSjmcneill void
plgpio_pin_write(void * priv,int pin,int val)945e1be26aSjmcneill plgpio_pin_write(void *priv, int pin, int val)
955e1be26aSjmcneill {
965e1be26aSjmcneill 	struct plgpio_softc * const sc = priv;
975e1be26aSjmcneill 
985e1be26aSjmcneill 	PLGPIO_WRITE(sc, PL061_GPIODATA_REG(1 << pin), val << pin);
995e1be26aSjmcneill }
1005e1be26aSjmcneill 
1015e1be26aSjmcneill void
plgpio_pin_ctl(void * priv,int pin,int flags)1025e1be26aSjmcneill plgpio_pin_ctl(void *priv, int pin, int flags)
1035e1be26aSjmcneill {
1045e1be26aSjmcneill 	struct plgpio_softc * const sc = priv;
1055e1be26aSjmcneill 	uint32_t v;
1065e1be26aSjmcneill 
1075e1be26aSjmcneill 	if (flags & GPIO_PIN_INPUT) {
1085e1be26aSjmcneill 		v = PLGPIO_READ(sc, PL061_GPIODIR_REG);
1095e1be26aSjmcneill 		v &= ~(1 << pin);
1105e1be26aSjmcneill 		PLGPIO_WRITE(sc, PL061_GPIODIR_REG, v);
1115e1be26aSjmcneill 	} else if (flags & GPIO_PIN_OUTPUT) {
1125e1be26aSjmcneill 		v = PLGPIO_READ(sc, PL061_GPIODIR_REG);
1135e1be26aSjmcneill 		v |= (1 << pin);
1145e1be26aSjmcneill 		PLGPIO_WRITE(sc, PL061_GPIODIR_REG, v);
1155e1be26aSjmcneill 	}
1165e1be26aSjmcneill }
117