summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2022-11-08 11:51:35 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2022-11-08 11:51:35 +0000
commit811ba8051fc4cc221f86014a929f4c56a7ac6120 (patch)
treefa7aabdb9aa078909d69bd943cc9379f1d1851c2 /sys/dev
parent5abad3f68def18f86eb643ccc9bda4c35fdd3838 (diff)
Implement reading/writing/configuring pins in qcgpio(4). The code has
mostly been there, it only needed to be hooked up to our infrastructure. With this I can e.g. correctly see the lid state on the x13s. ok kettenis@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fdt/qcgpio_fdt.c54
1 files changed, 46 insertions, 8 deletions
diff --git a/sys/dev/fdt/qcgpio_fdt.c b/sys/dev/fdt/qcgpio_fdt.c
index f6813d5cbeb..6af1f684bfd 100644
--- a/sys/dev/fdt/qcgpio_fdt.c
+++ b/sys/dev/fdt/qcgpio_fdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: qcgpio_fdt.c,v 1.1 2022/11/06 15:33:58 patrick Exp $ */
+/* $OpenBSD: qcgpio_fdt.c,v 1.2 2022/11/08 11:51:34 patrick Exp $ */
/*
* Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
*
@@ -26,6 +26,8 @@
#include <dev/ofw/fdt.h>
/* Registers. */
+#define TLMM_GPIO_CFG(pin) (0x0000 + 0x1000 * (pin))
+#define TLMM_GPIO_CFG_OUT_EN (1 << 9)
#define TLMM_GPIO_IN_OUT(pin) (0x0004 + 0x1000 * (pin))
#define TLMM_GPIO_IN_OUT_GPIO_IN (1 << 0)
#define TLMM_GPIO_IN_OUT_GPIO_OUT (1 << 1)
@@ -70,6 +72,7 @@ struct qcgpio_softc {
uint32_t sc_npins;
struct qcgpio_intrhand *sc_pin_ih;
+ struct gpio_controller sc_gc;
struct interrupt_controller sc_ic;
};
@@ -80,8 +83,10 @@ const struct cfattach qcgpio_fdt_ca = {
sizeof(struct qcgpio_softc), qcgpio_fdt_match, qcgpio_fdt_attach
};
-int qcgpio_fdt_read_pin(void *, int);
-void qcgpio_fdt_write_pin(void *, int, int);
+void qcgpio_fdt_config_pin(void *, uint32_t *, int);
+int qcgpio_fdt_get_pin(void *, uint32_t *);
+void qcgpio_fdt_set_pin(void *, uint32_t *, int);
+
void *qcgpio_fdt_intr_establish(void *, int *, int, struct cpu_info *,
int (*)(void *), void *, char *);
void qcgpio_fdt_intr_disestablish(void *);
@@ -123,6 +128,13 @@ qcgpio_fdt_attach(struct device *parent, struct device *self, void *aux)
goto unmap;
}
+ sc->sc_gc.gc_node = faa->fa_node;
+ sc->sc_gc.gc_cookie = sc;
+ sc->sc_gc.gc_config_pin = qcgpio_fdt_config_pin;
+ sc->sc_gc.gc_get_pin = qcgpio_fdt_get_pin;
+ sc->sc_gc.gc_set_pin = qcgpio_fdt_set_pin;
+ gpio_controller_register(&sc->sc_gc);
+
sc->sc_ic.ic_node = faa->fa_node;
sc->sc_ic.ic_cookie = sc;
sc->sc_ic.ic_establish = qcgpio_fdt_intr_establish;
@@ -142,27 +154,53 @@ unmap:
bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
}
+void
+qcgpio_fdt_config_pin(void *cookie, uint32_t *cells, int config)
+{
+ struct qcgpio_softc *sc = cookie;
+ uint32_t pin = cells[0];
+
+ if (pin >= sc->sc_npins)
+ return;
+
+ if (config & GPIO_CONFIG_OUTPUT)
+ HSET4(sc, TLMM_GPIO_CFG(pin), TLMM_GPIO_CFG_OUT_EN);
+ else
+ HCLR4(sc, TLMM_GPIO_CFG(pin), TLMM_GPIO_CFG_OUT_EN);
+}
+
int
-qcgpio_fdt_read_pin(void *cookie, int pin)
+qcgpio_fdt_get_pin(void *cookie, uint32_t *cells)
{
struct qcgpio_softc *sc = cookie;
+ uint32_t pin = cells[0];
+ uint32_t flags = cells[1];
uint32_t reg;
+ int val;
- if (pin < 0 || pin >= sc->sc_npins)
+ if (pin >= sc->sc_npins)
return 0;
reg = HREAD4(sc, TLMM_GPIO_IN_OUT(pin));
- return !!(reg & TLMM_GPIO_IN_OUT_GPIO_IN);
+ val = !!(reg & TLMM_GPIO_IN_OUT_GPIO_IN);
+ if (flags & GPIO_ACTIVE_LOW)
+ val = !val;
+ return val;
}
void
-qcgpio_fdt_write_pin(void *cookie, int pin, int val)
+qcgpio_fdt_set_pin(void *cookie, uint32_t *cells, int val)
{
struct qcgpio_softc *sc = cookie;
+ uint32_t pin = cells[0];
+ uint32_t flags = cells[1];
- if (pin < 0 || pin >= sc->sc_npins)
+ if (pin >= sc->sc_npins)
return;
+ if (flags & GPIO_ACTIVE_LOW)
+ val = !val;
+
if (val) {
HSET4(sc, TLMM_GPIO_IN_OUT(pin),
TLMM_GPIO_IN_OUT_GPIO_OUT);