Add mpfgpio(4), a driver for the PolarFire SoC MSS GPIO controller.
authorvisa <visa@openbsd.org>
Fri, 18 Feb 2022 10:51:43 +0000 (10:51 +0000)
committervisa <visa@openbsd.org>
Fri, 18 Feb 2022 10:51:43 +0000 (10:51 +0000)
Feedback and OK kettenis@

share/man/man4/gpio.4
share/man/man4/man4.riscv64/Makefile
share/man/man4/man4.riscv64/mpfgpio.4 [new file with mode: 0644]
sys/arch/riscv64/conf/GENERIC
sys/arch/riscv64/conf/RAMDISK
sys/arch/riscv64/conf/files.riscv64
sys/arch/riscv64/dev/mpfgpio.c [new file with mode: 0644]
sys/arch/riscv64/riscv64/conf.c

index 4379457..8dfbdbe 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: gpio.4,v 1.27 2020/05/16 16:37:49 martin Exp $
+.\"    $OpenBSD: gpio.4,v 1.28 2022/02/18 10:51:43 visa Exp $
 .\"
 .\" Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: May 16 2020 $
+.Dd $Mdocdate: February 18 2022 $
 .Dt GPIO 4
 .Os
 .Sh NAME
@@ -27,6 +27,7 @@
 .Cd "gpio* at glxpcib?" Pq i386
 .Cd "gpio* at gscpcib?" Pq i386
 .Cd "gpio* at isagpio?"
+.Cd "gpio* at mpfgpio?" Pq riscv64
 .Cd "gpio* at nsclpcsio?"
 .Cd "gpio* at omgpio?" Pq armv7
 .Cd "gpio* at pcagpio?"
index 4b5e28d..c6d30a2 100644 (file)
@@ -1,6 +1,6 @@
-#      $OpenBSD: Makefile,v 1.5 2022/02/16 13:07:36 visa Exp $
+#      $OpenBSD: Makefile,v 1.6 2022/02/18 10:51:43 visa Exp $
 
-MAN=   intro.4 mpfclock.4 mpfiic.4 plic.4 sfcc.4 sfclock.4 sfuart.4
+MAN=   intro.4 mpfclock.4 mpfgpio.4 mpfiic.4 plic.4 sfcc.4 sfclock.4 sfuart.4
 
 MANSUBDIR=riscv64
 
diff --git a/share/man/man4/man4.riscv64/mpfgpio.4 b/share/man/man4/man4.riscv64/mpfgpio.4
new file mode 100644 (file)
index 0000000..b367357
--- /dev/null
@@ -0,0 +1,55 @@
+.\"    $OpenBSD: mpfgpio.4,v 1.1 2022/02/18 10:51:43 visa Exp $
+.\"
+.\" Copyright (c) 2022 Visa Hankala
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: February 18 2022 $
+.Dt MPFGPIO 4 riscv64
+.Os
+.Sh NAME
+.Nm mpfgpio
+.Nd Microchip PolarFire SoC MSS GPIO controller
+.Sh SYNOPSIS
+.Cd "mpfgpio* at fdt?"
+.Cd "gpio* at mpfgpio?"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the Microchip PolarFire SoC MSS GPIO controller.
+.Pp
+The PolarFire SoC MSS has three GPIO units:
+.Dv GPIO_0 ,
+.Dv GPIO_1
+and
+.Dv GPIO_2 .
+.Dv GPIO_0
+and
+.Dv GPIO_1
+control up to 14 and 24 IOs, respectively.
+These IOs are routed through IOMUXes.
+.Dv GPIO_2
+controls up to 32 IOs through the FPGA fabric.
+.Pp
+The IOs can be configured as either inputs or outputs,
+and accessed using
+.Xr gpioctl 8 .
+.Sh SEE ALSO
+.Xr gpio 4 ,
+.Xr intro 4 ,
+.Xr gpioctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 7.1 .
index 3baca05..2435be4 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: GENERIC,v 1.34 2022/02/16 13:07:36 visa Exp $
+#      $OpenBSD: GENERIC,v 1.35 2022/02/18 10:51:43 visa Exp $
 #
 # For further information on compiling OpenBSD kernels, see the config(8)
 # man page.
@@ -48,6 +48,8 @@ com*          at fdt?
 cdsdhc*                at fdt?
 sdmmc*         at cdsdhc?
 mpfclock*      at fdt? early 1
+mpfgpio*       at fdt?
+gpio*          at mpfgpio?
 mpfiic*                at fdt?
 iic*           at mpfiic?
 
index 3cb408b..5db2eca 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: RAMDISK,v 1.30 2022/02/16 13:07:36 visa Exp $
+#      $OpenBSD: RAMDISK,v 1.31 2022/02/18 10:51:43 visa Exp $
 
 machine                riscv64
 maxusers       4
@@ -39,6 +39,8 @@ com*          at fdt?
 cdsdhc*                at fdt?
 sdmmc*         at cdsdhc?
 mpfclock*      at fdt? early 1
+mpfgpio*       at fdt?
+gpio*          at mpfgpio?
 mpfiic*                at fdt?
 iic*           at mpfiic?
 
index 973ec9f..3f4bd14 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.riscv64,v 1.19 2022/02/16 13:07:36 visa Exp $
+#      $OpenBSD: files.riscv64,v 1.20 2022/02/18 10:51:43 visa Exp $
 
 # Standard stanzas config(8) can't run without
 maxpartitions 16
@@ -89,6 +89,11 @@ device       mpfclock
 attach mpfclock at fdt
 file   arch/riscv64/dev/mpfclock.c             mpfclock
 
+# PolarFire SoC MSS GPIO controller
+device mpfgpio: gpiobus
+attach mpfgpio at fdt
+file   arch/riscv64/dev/mpfgpio.c              mpfgpio
+
 # PolarFire SoC MSS I2C controller
 device mpfiic: i2cbus
 attach mpfiic at fdt
@@ -134,6 +139,9 @@ include "dev/ofw/files.ofw"
 # Machine-independent FDT drivers
 include "dev/fdt/files.fdt"
 
+# Machine-independent GPIO drivers
+include "dev/gpio/files.gpio"
+
 # Machine-independent SCSI drivers
 include "scsi/files.scsi"
 
diff --git a/sys/arch/riscv64/dev/mpfgpio.c b/sys/arch/riscv64/dev/mpfgpio.c
new file mode 100644 (file)
index 0000000..7d8b049
--- /dev/null
@@ -0,0 +1,294 @@
+/*     $OpenBSD: mpfgpio.c,v 1.1 2022/02/18 10:51:43 visa Exp $        */
+
+/*
+ * Copyright (c) 2022 Visa Hankala
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for PolarFire SoC MSS GPIO controller.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/gpio/gpiovar.h>
+
+#include <dev/ofw/fdt.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_clock.h>
+#include <dev/ofw/ofw_gpio.h>
+
+#include "gpio.h"
+
+#define MPFGPIO_CONFIG(i)      (0x0000 + (i) * 4)
+#define  MPFGPIO_CONFIG_EN_INT         (1 << 3)
+#define  MPFGPIO_CONFIG_EN_OE_BUF      (1 << 2)
+#define  MPFGPIO_CONFIG_EN_IN          (1 << 1)
+#define  MPFGPIO_CONFIG_EN_OUT         (1 << 0)
+#define MPFGPIO_GPIN           0x0084
+#define MPFGPIO_GPOUT          0x0088
+#define MPFGPIO_CLEAR_BITS     0x00a0
+#define MPFGPIO_SET_BITS       0x00a4
+
+#define MPFGPIO_MAX_PINS       32
+
+struct mpfgpio_softc {
+       struct device           sc_dev;
+       bus_space_tag_t         sc_iot;
+       bus_space_handle_t      sc_ioh;
+       uint32_t                sc_npins;
+
+       struct gpio_controller  sc_gc;
+
+       struct gpio_chipset_tag sc_gpio_tag;
+       gpio_pin_t              sc_gpio_pins[MPFGPIO_MAX_PINS];
+       uint8_t                 sc_gpio_claimed[MPFGPIO_MAX_PINS];
+};
+
+#define HREAD4(sc, reg) \
+       (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
+#define HWRITE4(sc, reg, val) \
+       bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+
+int    mpfgpio_match(struct device *, void *, void*);
+void   mpfgpio_attach(struct device *, struct device *, void *);
+
+void   mpfgpio_config_pin(void *, uint32_t *, int);
+int    mpfgpio_get_pin(void *, uint32_t *);
+void   mpfgpio_set_pin(void *, uint32_t *, int);
+
+int    mpfgpio_pin_read(void *, int);
+void   mpfgpio_pin_write(void *, int, int);
+void   mpfgpio_pin_ctl(void *, int, int);
+void   mpfgpio_attach_gpio(struct device *);
+
+const struct cfattach mpfgpio_ca = {
+       sizeof(struct mpfgpio_softc), mpfgpio_match, mpfgpio_attach
+};
+
+struct cfdriver mpfgpio_cd = {
+       NULL, "mpfgpio", DV_DULL
+};
+
+int
+mpfgpio_match(struct device *parent, void *match, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+
+       if (faa->fa_nreg < 1)
+               return 0;
+       return OF_is_compatible(faa->fa_node, "microchip,mpfs-gpio");
+}
+
+void
+mpfgpio_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+       struct mpfgpio_softc *sc = (struct mpfgpio_softc *)self;
+       unsigned int unit;
+
+       sc->sc_iot = faa->fa_iot;
+
+       unit = (faa->fa_reg[0].addr >> 12) & 0x3;
+       switch (unit) {
+       case 0:
+               sc->sc_npins = 14;
+               break;
+       case 1:
+               sc->sc_npins = 24;
+               break;
+       case 2:
+               sc->sc_npins = 32;
+               break;
+       default:
+               printf(": unexpected GPIO unit %u\n", unit);
+               return;
+       }
+       KASSERT(sc->sc_npins <= MPFGPIO_MAX_PINS);
+
+       if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size,
+           0, &sc->sc_ioh) != 0) {
+               printf(": can't map registers\n");
+               return;
+       }
+
+       clock_enable_all(faa->fa_node);
+
+       printf(": unit %u\n", unit);
+
+       sc->sc_gc.gc_node = faa->fa_node;
+       sc->sc_gc.gc_cookie = sc;
+       sc->sc_gc.gc_config_pin = mpfgpio_config_pin;
+       sc->sc_gc.gc_get_pin = mpfgpio_get_pin;
+       sc->sc_gc.gc_set_pin = mpfgpio_set_pin;
+       gpio_controller_register(&sc->sc_gc);
+
+#if NGPIO > 0
+       config_mountroot(self, mpfgpio_attach_gpio);
+#endif
+}
+
+void
+mpfgpio_config_pin(void *cookie, uint32_t *cells, int config)
+{
+       struct mpfgpio_softc *sc = cookie;
+       uint32_t pin = cells[0];
+       uint32_t val;
+
+       if (pin >= sc->sc_npins)
+               return;
+
+       val = HREAD4(sc, MPFGPIO_CONFIG(pin));
+       if (config & GPIO_CONFIG_OUTPUT) {
+               val &= ~MPFGPIO_CONFIG_EN_IN;
+               val |= MPFGPIO_CONFIG_EN_OUT;
+       } else {
+               val |= MPFGPIO_CONFIG_EN_IN;
+               val &= ~MPFGPIO_CONFIG_EN_OUT;
+       }
+       val &= ~MPFGPIO_CONFIG_EN_INT;
+       HWRITE4(sc, MPFGPIO_CONFIG(pin), val);
+
+       sc->sc_gpio_claimed[pin] = 1;
+}
+
+int
+mpfgpio_get_pin(void *cookie, uint32_t *cells)
+{
+       struct mpfgpio_softc *sc = cookie;
+       uint32_t pin = cells[0];
+       uint32_t flags = cells[1];
+       int val;
+
+       if (pin >= sc->sc_npins)
+               return 0;
+
+       val = (HREAD4(sc, MPFGPIO_GPIN) >> pin) & 1;
+       if (flags & GPIO_ACTIVE_LOW)
+               val = !val;
+       return val;
+}
+
+void
+mpfgpio_set_pin(void *cookie, uint32_t *cells, int val)
+{
+       struct mpfgpio_softc *sc = cookie;
+       uint32_t pin = cells[0];
+       uint32_t flags = cells[1];
+
+       if (pin >= sc->sc_npins)
+               return;
+
+       if (flags & GPIO_ACTIVE_LOW)
+               val = !val;
+       if (val)
+               HWRITE4(sc, MPFGPIO_SET_BITS, (1U << (pin % 32)));
+       else
+               HWRITE4(sc, MPFGPIO_CLEAR_BITS, (1U << (pin % 32)));
+}
+
+#if NGPIO > 0
+int
+mpfgpio_pin_read(void *cookie, int pin)
+{
+       struct mpfgpio_softc *sc = cookie;
+       uint32_t cells[2];
+
+       cells[0] = pin;
+       cells[1] = 0;
+
+       return mpfgpio_get_pin(sc, cells) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
+}
+
+void
+mpfgpio_pin_write(void *cookie, int pin, int val)
+{
+       struct mpfgpio_softc *sc = cookie;
+       uint32_t cells[2];
+
+       cells[0] = pin;
+       cells[1] = 0;
+
+       mpfgpio_set_pin(sc, cells, val);
+}
+
+void
+mpfgpio_pin_ctl(void *cookie, int pin, int flags)
+{
+       struct mpfgpio_softc *sc = cookie;
+       uint32_t cells[2];
+       uint32_t config = 0;
+
+       cells[0] = pin;
+       cells[1] = 0;
+
+       if (flags & GPIO_PIN_OUTPUT)
+               config |= GPIO_CONFIG_OUTPUT;
+
+       mpfgpio_config_pin(sc, cells, config);
+}
+
+static const struct gpio_chipset_tag mpfgpio_gpio_tag = {
+       .gp_pin_read    = mpfgpio_pin_read,
+       .gp_pin_write   = mpfgpio_pin_write,
+       .gp_pin_ctl     = mpfgpio_pin_ctl,
+};
+
+void
+mpfgpio_attach_gpio(struct device *parent)
+{
+       struct gpiobus_attach_args gba;
+       struct mpfgpio_softc *sc = (struct mpfgpio_softc *)parent;
+       uint32_t cfgreg, pin;
+       int flags, state;
+
+       for (pin = 0; pin < sc->sc_npins; pin++) {
+               /* Skip pins claimed by other devices. */
+               if (sc->sc_gpio_claimed[pin])
+                       continue;
+
+               cfgreg = HREAD4(sc, MPFGPIO_CONFIG(pin));
+               if (cfgreg & MPFGPIO_CONFIG_EN_OUT)
+                       flags = GPIO_PIN_SET | GPIO_PIN_OUTPUT;
+               else if (cfgreg & MPFGPIO_CONFIG_EN_IN)
+                       flags = GPIO_PIN_SET | GPIO_PIN_INPUT;
+               else
+                       flags = GPIO_PIN_SET;
+
+               state = (HREAD4(sc, MPFGPIO_GPIN) >> pin) & 1;
+
+               sc->sc_gpio_pins[pin].pin_caps =
+                   GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+               sc->sc_gpio_pins[pin].pin_flags = flags;
+               sc->sc_gpio_pins[pin].pin_state = state;
+               sc->sc_gpio_pins[pin].pin_num = pin;
+       }
+
+       sc->sc_gpio_tag = mpfgpio_gpio_tag;
+       sc->sc_gpio_tag.gp_cookie = sc;
+
+       gba.gba_name = "gpio";
+       gba.gba_gc = &sc->sc_gpio_tag;
+       gba.gba_pins = sc->sc_gpio_pins;
+       gba.gba_npins = sc->sc_npins;
+
+       config_found(&sc->sc_dev, &gba, gpiobus_print);
+}
+#endif
index f89dccd..b21652f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.13 2021/11/30 02:13:57 deraadt Exp $       */
+/*     $OpenBSD: conf.c,v 1.14 2022/02/18 10:51:43 visa Exp $  */
 
 /*
  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
@@ -111,6 +111,7 @@ cdev_decl(pci);
 #include "pppx.h"
 #include "fuse.h"
 #include "openprom.h"
+#include "gpio.h"
 #include "ipmi.h"
 
 struct cdevsw  cdevsw[] =
@@ -211,7 +212,7 @@ struct cdevsw       cdevsw[] =
        cdev_notdef(),                  /* 85 */
        cdev_notdef(),                  /* 86 */
        cdev_drm_init(NDRM,drm),        /* 87: drm */
-       cdev_notdef(),                  /* 88: GPIO interface */
+       cdev_gpio_init(NGPIO,gpio),     /* 88: GPIO interface */
        cdev_vscsi_init(NVSCSI,vscsi),  /* 89: vscsi */
        cdev_disk_init(1,diskmap),      /* 90: disk mapper */
        cdev_pppx_init(NPPPX,pppx),     /* 91: pppx */