> Date: Thu, 17 Feb 2022 16:16:30 +0000
> From: Visa Hankala <[email protected]>
> 
> On Thu, Feb 17, 2022 at 03:38:05PM +0100, Mark Kettenis wrote:
> > > Date: Thu, 17 Feb 2022 13:52:39 +0000
> > > From: Visa Hankala <[email protected]>
> > > 
> > > This patch adds a driver for the PolarFire SoC MSS GPIO controller.
> > > 
> > > The driver provides a gpio(4) interface, so the patch also enables
> > > gpioctl(8) on riscv64. The MAKEDEV script already creates gpio nodes.
> > > 
> > > OK?
> > 
> > So on arm64 I've been trying to build in protection against userland
> > access to GPIOs used by kernel drivers.  See for example bcmgpio(4) or
> > sxipio(4).  I think it would be good if we did the same thing on
> > riscv64.
> 
> Sure, here is a revised diff. Now the driver tracks which pins get
> configured. The pins that were claimed during autoconfiguration are
> skipped when setting up gpio(4).

Yes I think that's better.

ok kettenis@

> Index: share/man/man4/gpio.4
> ===================================================================
> RCS file: src/share/man/man4/gpio.4,v
> retrieving revision 1.27
> diff -u -p -r1.27 gpio.4
> --- share/man/man4/gpio.4     16 May 2020 16:37:49 -0000      1.27
> +++ share/man/man4/gpio.4     17 Feb 2022 15:45:40 -0000
> @@ -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: share/man/man4/man4.riscv64/Makefile
> ===================================================================
> RCS file: src/share/man/man4/man4.riscv64/Makefile,v
> retrieving revision 1.5
> diff -u -p -r1.5 Makefile
> --- share/man/man4/man4.riscv64/Makefile      16 Feb 2022 13:07:36 -0000      
> 1.5
> +++ share/man/man4/man4.riscv64/Makefile      17 Feb 2022 15:45:40 -0000
> @@ -1,6 +1,6 @@
>  #    $OpenBSD: Makefile,v 1.5 2022/02/16 13:07:36 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
>  
> Index: share/man/man4/man4.riscv64/mpfgpio.4
> ===================================================================
> RCS file: share/man/man4/man4.riscv64/mpfgpio.4
> diff -N share/man/man4/man4.riscv64/mpfgpio.4
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ share/man/man4/man4.riscv64/mpfgpio.4     17 Feb 2022 15:45:40 -0000
> @@ -0,0 +1,55 @@
> +.\"  $OpenBSD$
> +.\"
> +.\" 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$
> +.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: sys/arch/riscv64/conf/GENERIC
> ===================================================================
> RCS file: src/sys/arch/riscv64/conf/GENERIC,v
> retrieving revision 1.34
> diff -u -p -r1.34 GENERIC
> --- sys/arch/riscv64/conf/GENERIC     16 Feb 2022 13:07:36 -0000      1.34
> +++ sys/arch/riscv64/conf/GENERIC     17 Feb 2022 15:45:40 -0000
> @@ -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: sys/arch/riscv64/conf/RAMDISK
> ===================================================================
> RCS file: src/sys/arch/riscv64/conf/RAMDISK,v
> retrieving revision 1.30
> diff -u -p -r1.30 RAMDISK
> --- sys/arch/riscv64/conf/RAMDISK     16 Feb 2022 13:07:36 -0000      1.30
> +++ sys/arch/riscv64/conf/RAMDISK     17 Feb 2022 15:45:40 -0000
> @@ -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: sys/arch/riscv64/conf/files.riscv64
> ===================================================================
> RCS file: src/sys/arch/riscv64/conf/files.riscv64,v
> retrieving revision 1.19
> diff -u -p -r1.19 files.riscv64
> --- sys/arch/riscv64/conf/files.riscv64       16 Feb 2022 13:07:36 -0000      
> 1.19
> +++ sys/arch/riscv64/conf/files.riscv64       17 Feb 2022 15:45:40 -0000
> @@ -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"
>  
> Index: sys/arch/riscv64/dev/mpfgpio.c
> ===================================================================
> RCS file: sys/arch/riscv64/dev/mpfgpio.c
> diff -N sys/arch/riscv64/dev/mpfgpio.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ sys/arch/riscv64/dev/mpfgpio.c    17 Feb 2022 15:45:40 -0000
> @@ -0,0 +1,294 @@
> +/*   $OpenBSD$       */
> +
> +/*
> + * 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: sys/arch/riscv64/riscv64/conf.c
> ===================================================================
> RCS file: src/sys/arch/riscv64/riscv64/conf.c,v
> retrieving revision 1.13
> diff -u -p -r1.13 conf.c
> --- sys/arch/riscv64/riscv64/conf.c   30 Nov 2021 02:13:57 -0000      1.13
> +++ sys/arch/riscv64/riscv64/conf.c   17 Feb 2022 15:45:41 -0000
> @@ -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 */
> Index: usr.sbin/gpioctl/Makefile
> ===================================================================
> RCS file: src/usr.sbin/gpioctl/Makefile,v
> retrieving revision 1.9
> diff -u -p -r1.9 Makefile
> --- usr.sbin/gpioctl/Makefile 16 May 2020 16:37:50 -0000      1.9
> +++ usr.sbin/gpioctl/Makefile 17 Feb 2022 15:45:41 -0000
> @@ -2,7 +2,7 @@
>  
>  .if ${MACHINE} == "amd64" || ${MACHINE} == "arm64" || \
>      ${MACHINE} == "armv7" || ${MACHINE} == "i386" || \
> -    ${MACHINE} == "macppc"
> +    ${MACHINE} == "macppc" || ${MACHINE} == "riscv64"
>  
>  PROG=        gpioctl
>  SRCS=        gpioctl.c
> @@ -19,6 +19,6 @@ NOPROG=     yes
>  .endif
>  
>  MAN= gpioctl.8
> -MANSUBDIR=i386 macppc amd64 armv7 arm64
> +MANSUBDIR=amd64 arm64 armv7 i386 macppc riscv64
>  
>  .include <bsd.prog.mk>
> 

Reply via email to