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