diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2022-11-08 11:51:35 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2022-11-08 11:51:35 +0000 |
commit | 811ba8051fc4cc221f86014a929f4c56a7ac6120 (patch) | |
tree | fa7aabdb9aa078909d69bd943cc9379f1d1851c2 /sys | |
parent | 5abad3f68def18f86eb643ccc9bda4c35fdd3838 (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')
-rw-r--r-- | sys/dev/fdt/qcgpio_fdt.c | 54 |
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); |