From: visa Date: Fri, 18 Feb 2022 10:51:43 +0000 (+0000) Subject: Add mpfgpio(4), a driver for the PolarFire SoC MSS GPIO controller. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=3b631e80721f28fd06f68adc3d62cdb9c478ebef;p=openbsd Add mpfgpio(4), a driver for the PolarFire SoC MSS GPIO controller. Feedback and OK kettenis@ --- diff --git a/share/man/man4/gpio.4 b/share/man/man4/gpio.4 index 4379457357e..8dfbdbeff6d 100644 --- a/share/man/man4/gpio.4 +++ b/share/man/man4/gpio.4 @@ -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 .\" @@ -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?" diff --git a/share/man/man4/man4.riscv64/Makefile b/share/man/man4/man4.riscv64/Makefile index 4b5e28d66d0..c6d30a2f9a7 100644 --- a/share/man/man4/man4.riscv64/Makefile +++ b/share/man/man4/man4.riscv64/Makefile @@ -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 index 00000000000..b367357457d --- /dev/null +++ b/share/man/man4/man4.riscv64/mpfgpio.4 @@ -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 . diff --git a/sys/arch/riscv64/conf/GENERIC b/sys/arch/riscv64/conf/GENERIC index 3baca054367..2435be44119 100644 --- a/sys/arch/riscv64/conf/GENERIC +++ b/sys/arch/riscv64/conf/GENERIC @@ -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? diff --git a/sys/arch/riscv64/conf/RAMDISK b/sys/arch/riscv64/conf/RAMDISK index 3cb408b3ff9..5db2eca12d1 100644 --- a/sys/arch/riscv64/conf/RAMDISK +++ b/sys/arch/riscv64/conf/RAMDISK @@ -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? diff --git a/sys/arch/riscv64/conf/files.riscv64 b/sys/arch/riscv64/conf/files.riscv64 index 973ec9f876b..3f4bd1464b6 100644 --- a/sys/arch/riscv64/conf/files.riscv64 +++ b/sys/arch/riscv64/conf/files.riscv64 @@ -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 index 00000000000..7d8b049dfa1 --- /dev/null +++ b/sys/arch/riscv64/dev/mpfgpio.c @@ -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 +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#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 diff --git a/sys/arch/riscv64/riscv64/conf.c b/sys/arch/riscv64/riscv64/conf.c index f89dccd2540..b21652f1fa9 100644 --- a/sys/arch/riscv64/riscv64/conf.c +++ b/sys/arch/riscv64/riscv64/conf.c @@ -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 */