summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvisa <visa@openbsd.org>2019-01-12 16:59:38 +0000
committervisa <visa@openbsd.org>2019-01-12 16:59:38 +0000
commit4c76d6caa7a3bb2f8b3e92f0155c46acb2ada8db (patch)
treedf6eb609e12ea5faa5fadf460e371151f2a00b26
parentFix potential use-after-free if xfer allocation fails when otus(4) attaches. (diff)
downloadwireguard-openbsd-4c76d6caa7a3bb2f8b3e92f0155c46acb2ada8db.tar.xz
wireguard-openbsd-4c76d6caa7a3bb2f8b3e92f0155c46acb2ada8db.zip
Add a driver for OCTEON GPIO controller.
-rw-r--r--sys/arch/octeon/conf/GENERIC3
-rw-r--r--sys/arch/octeon/conf/RAMDISK3
-rw-r--r--sys/arch/octeon/conf/files.octeon6
-rw-r--r--sys/arch/octeon/dev/octgpio.c192
4 files changed, 201 insertions, 3 deletions
diff --git a/sys/arch/octeon/conf/GENERIC b/sys/arch/octeon/conf/GENERIC
index 6ccb10f2ed7..60739b108df 100644
--- a/sys/arch/octeon/conf/GENERIC
+++ b/sys/arch/octeon/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.44 2018/08/22 15:38:46 mpi Exp $
+# $OpenBSD: GENERIC,v 1.45 2019/01/12 16:59:38 visa Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -53,6 +53,7 @@ com* at fdt_octeon?
octcib* at fdt? # Interrupt controller
octcit* at fdt? # Interrupt controller v3
octciu* at fdt? # Interrupt controller v1
+octgpio* at fdt? # GPIO controller
octmmc* at fdt? # MMC host controller
sdmmc* at octmmc? # SD/MMC bus
diff --git a/sys/arch/octeon/conf/RAMDISK b/sys/arch/octeon/conf/RAMDISK
index c3f8b701457..329bdfcb5fc 100644
--- a/sys/arch/octeon/conf/RAMDISK
+++ b/sys/arch/octeon/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.38 2018/06/01 17:15:27 visa Exp $
+# $OpenBSD: RAMDISK,v 1.39 2019/01/12 16:59:38 visa Exp $
machine octeon mips64
maxusers 4
@@ -53,6 +53,7 @@ com* at fdt_octeon?
octcib* at fdt? # Interrupt controller
octcit* at fdt? # Interrupt controller v3
octciu* at fdt? # Interrupt controller v1
+octgpio* at fdt? # GPIO controller
octmmc* at fdt? # MMC host controller
sdmmc* at octmmc? # SD/MMC bus
diff --git a/sys/arch/octeon/conf/files.octeon b/sys/arch/octeon/conf/files.octeon
index af6f4b96bf4..9c57abd094a 100644
--- a/sys/arch/octeon/conf/files.octeon
+++ b/sys/arch/octeon/conf/files.octeon
@@ -1,4 +1,4 @@
-# $OpenBSD: files.octeon,v 1.48 2018/06/01 17:15:27 visa Exp $
+# $OpenBSD: files.octeon,v 1.49 2019/01/12 16:59:38 visa Exp $
# Standard stanzas config(8) can't run without
maxpartitions 16
@@ -145,6 +145,10 @@ device octciu
attach octciu at fdt
file arch/octeon/dev/octciu.c octciu
+device octgpio
+attach octgpio at fdt
+file arch/octeon/dev/octgpio.c octgpio
+
device octmmc: sdmmcbus
attach octmmc at fdt
file arch/octeon/dev/octmmc.c octmmc
diff --git a/sys/arch/octeon/dev/octgpio.c b/sys/arch/octeon/dev/octgpio.c
new file mode 100644
index 00000000000..83bb314ddc1
--- /dev/null
+++ b/sys/arch/octeon/dev/octgpio.c
@@ -0,0 +1,192 @@
+/* $OpenBSD: octgpio.c,v 1.1 2019/01/12 16:59:38 visa Exp $ */
+
+/*
+ * Copyright (c) 2019 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 OCTEON GPIO controller.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <dev/ofw/fdt.h>
+#include <dev/ofw/ofw_gpio.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/fdt.h>
+#include <machine/octeon_model.h>
+
+#define GPIO_BIT_CFG(x) (0x0000u + (x) * 8)
+#define GPIO_BIT_CFG_INT_EN 0x0000000000000004ull
+#define GPIO_BIT_CFG_RX_XOR 0x0000000000000002ull
+#define GPIO_BIT_CFG_TX_OE 0x0000000000000001ull
+#define GPIO_XBIT_CFG(x) (0x0100u + (x) * 8)
+#define GPIO_RX_DAT 0x0080u
+#define GPIO_TX_SET 0x0088u
+#define GPIO_TX_CLR 0x0090u
+
+#define GPIO_RD_8(sc, reg) \
+ bus_space_read_8((sc)->sc_iot, (sc)->sc_ioh, (reg))
+#define GPIO_WR_8(sc, reg, val) \
+ bus_space_write_8((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+
+struct octgpio_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ struct gpio_controller sc_gc;
+ uint32_t sc_npins;
+ uint32_t sc_xbit;
+};
+
+int octgpio_match(struct device *, void *, void *);
+void octgpio_attach(struct device *, struct device *, void *);
+
+void octgpio_config_pin(void *, uint32_t *, int);
+int octgpio_get_pin(void *, uint32_t *);
+void octgpio_set_pin(void *, uint32_t *, int);
+
+const struct cfattach octgpio_ca = {
+ sizeof(struct octgpio_softc), octgpio_match, octgpio_attach
+};
+
+struct cfdriver octgpio_cd = {
+ NULL, "octgpio", DV_DULL
+};
+
+int
+octgpio_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ return OF_is_compatible(faa->fa_node, "cavium,octeon-3860-gpio") ||
+ OF_is_compatible(faa->fa_node, "cavium,octeon-7890-gpio");
+}
+
+void
+octgpio_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+ struct octgpio_softc *sc = (struct octgpio_softc *)self;
+ uint32_t chipid;
+
+ if (faa->fa_nreg != 1) {
+ printf(": no registers\n");
+ return;
+ }
+
+ sc->sc_iot = faa->fa_iot;
+ if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size,
+ 0, &sc->sc_ioh)) {
+ printf(": can't map registers\n");
+ return;
+ }
+
+ chipid = octeon_get_chipid();
+ switch (octeon_model_family(chipid)) {
+ case OCTEON_MODEL_FAMILY_CN61XX:
+ case OCTEON_MODEL_FAMILY_CN63XX:
+ case OCTEON_MODEL_FAMILY_CN66XX:
+ case OCTEON_MODEL_FAMILY_CN68XX:
+ case OCTEON_MODEL_FAMILY_CN71XX:
+ sc->sc_npins = 20;
+ sc->sc_xbit = 16;
+ break;
+ case OCTEON_MODEL_FAMILY_CN73XX:
+ sc->sc_npins = 32;
+ sc->sc_xbit = 0;
+ break;
+ case OCTEON_MODEL_FAMILY_CN78XX:
+ sc->sc_npins = 20;
+ sc->sc_xbit = 0;
+ break;
+ default:
+ sc->sc_npins = 24;
+ sc->sc_xbit = 16;
+ break;
+ }
+
+ sc->sc_gc.gc_node = faa->fa_node;
+ sc->sc_gc.gc_cookie = sc;
+ sc->sc_gc.gc_config_pin = octgpio_config_pin;
+ sc->sc_gc.gc_get_pin = octgpio_get_pin;
+ sc->sc_gc.gc_set_pin = octgpio_set_pin;
+ gpio_controller_register(&sc->sc_gc);
+
+ printf(": %u pins, xbit %u\n", sc->sc_npins, sc->sc_xbit);
+}
+
+void
+octgpio_config_pin(void *cookie, uint32_t *cells, int config)
+{
+ struct octgpio_softc *sc = cookie;
+ uint64_t reg, value;
+ uint32_t pin = cells[0];
+
+ if (pin >= sc->sc_npins)
+ return;
+ if (pin >= sc->sc_xbit)
+ reg = GPIO_XBIT_CFG(pin - sc->sc_xbit);
+ else
+ reg = GPIO_BIT_CFG(pin);
+
+ value = GPIO_RD_8(sc, reg);
+ if (config & GPIO_CONFIG_OUTPUT)
+ value |= GPIO_BIT_CFG_TX_OE;
+ else
+ value &= ~(GPIO_BIT_CFG_TX_OE | GPIO_BIT_CFG_RX_XOR);
+ /* There is no INT_EN bit on true XBIT pins. */
+ value &= ~GPIO_BIT_CFG_INT_EN;
+ GPIO_WR_8(sc, reg, value);
+}
+
+int
+octgpio_get_pin(void *cookie, uint32_t *cells)
+{
+ struct octgpio_softc *sc = cookie;
+ uint32_t pin = cells[0];
+ uint32_t flags = cells[1];
+ int value;
+
+ if (pin >= sc->sc_npins)
+ return 0;
+
+ value = (GPIO_RD_8(sc, GPIO_RX_DAT) >> pin) & 1;
+ if (flags & GPIO_ACTIVE_LOW)
+ value = !value;
+ return value;
+}
+
+void
+octgpio_set_pin(void *cookie, uint32_t *cells, int value)
+{
+ struct octgpio_softc *sc = cookie;
+ uint32_t pin = cells[0];
+ uint32_t flags = cells[1];
+
+ if (pin >= sc->sc_npins)
+ return;
+
+ if (flags & GPIO_ACTIVE_LOW)
+ value = !value;
+ if (value)
+ GPIO_WR_8(sc, GPIO_TX_SET, 1ul << pin);
+ else
+ GPIO_WR_8(sc, GPIO_TX_CLR, 1ul << pin);
+}