From c99a06d7655d7995d683f2a081442f682c6c8a24 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 13 Feb 2022 11:58:53 +0000 Subject: [PATCH] Add basic GPIO support. ok patrick@ --- sys/arch/arm64/dev/aplsmc.c | 57 +++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/sys/arch/arm64/dev/aplsmc.c b/sys/arch/arm64/dev/aplsmc.c index b7f1aa4d5bf..ba80601ef18 100644 --- a/sys/arch/arm64/dev/aplsmc.c +++ b/sys/arch/arm64/dev/aplsmc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplsmc.c,v 1.6 2022/01/13 08:59:10 kettenis Exp $ */ +/* $OpenBSD: aplsmc.c,v 1.7 2022/02/13 11:58:53 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis * @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -49,6 +50,8 @@ extern void (*cpuresetfn)(void); #define SMC_SRAM_SIZE 0x4000 +#define SMC_GPIO_CMD_OUTPUT (0x01 << 24) + #define SMC_KEY(s) ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]) struct smc_key_info { @@ -83,6 +86,8 @@ struct aplsmc_softc { uint8_t sc_msgid; uint64_t sc_data; + struct gpio_controller sc_gc; + struct aplsmc_sensor *sc_smcsensors[APLSMC_MAX_SENSORS]; struct ksensor sc_sensors[APLSMC_MAX_SENSORS]; int sc_nsensors; @@ -186,6 +191,7 @@ int aplsmc_send_cmd(struct aplsmc_softc *, uint16_t, uint32_t, uint16_t); int aplsmc_wait_cmd(struct aplsmc_softc *sc); int aplsmc_read_key(struct aplsmc_softc *, uint32_t, void *, size_t); void aplsmc_refresh_sensors(void *); +void aplsmc_set_pin(void *, uint32_t *, int); void aplsmc_reset(void); int @@ -201,7 +207,7 @@ aplsmc_attach(struct device *parent, struct device *self, void *aux) { struct aplsmc_softc *sc = (struct aplsmc_softc *)self; struct fdt_attach_args *faa = aux; - int error; + int error, node; int i; if (faa->fa_nreg < 1) { @@ -249,6 +255,14 @@ aplsmc_attach(struct device *parent, struct device *self, void *aux) printf("\n"); + node = OF_getnodebyname(faa->fa_node, "gpio"); + if (node) { + sc->sc_gc.gc_node = node; + sc->sc_gc.gc_cookie = sc; + sc->sc_gc.gc_set_pin = aplsmc_set_pin; + gpio_controller_register(&sc->sc_gc); + } + for (i = 0; i < nitems(aplsmc_sensors); i++) { struct smc_key_info info; @@ -364,6 +378,16 @@ aplsmc_read_key(struct aplsmc_softc *sc, uint32_t key, void *data, size_t len) return 0; } +int +aplsmc_write_key(struct aplsmc_softc *sc, uint32_t key, void *data, size_t len) +{ + bus_space_write_region_1(sc->sc_iot, sc->sc_sram_ioh, 0, data, len); + bus_space_barrier(sc->sc_iot, sc->sc_sram_ioh, 0, len, + BUS_SPACE_BARRIER_WRITE); + aplsmc_send_cmd(sc, SMC_WRITE_KEY, key, len); + return aplsmc_wait_cmd(sc); +} + void aplsmc_refresh_sensors(void *arg) { @@ -430,6 +454,28 @@ aplsmc_refresh_sensors(void *arg) } } +void +aplsmc_set_pin(void *cookie, uint32_t *cells, int val) +{ + struct aplsmc_softc *sc = cookie; + static char *digits = "0123456789abcdef"; + uint32_t pin = cells[0]; + uint32_t flags = cells[1]; + uint32_t key = SMC_KEY("gP\0\0"); + uint32_t data; + + KASSERT(pin < 256); + + key |= (digits[(pin >> 0) & 0xf] << 0); + key |= (digits[(pin >> 8) & 0xf] << 8); + + if (flags & GPIO_ACTIVE_LOW) + val = !val; + data = SMC_GPIO_CMD_OUTPUT | !!val; + + aplsmc_write_key(sc, key, &data, sizeof(data)); +} + void aplsmc_reset(void) { @@ -437,10 +483,5 @@ aplsmc_reset(void) uint32_t key = SMC_KEY("MBSE"); uint32_t data = SMC_KEY("off1"); - bus_space_write_region_1(sc->sc_iot, sc->sc_sram_ioh, 0, - (uint8_t *)&data, sizeof(data)); - bus_space_barrier(sc->sc_iot, sc->sc_sram_ioh, 0, sizeof(data), - BUS_SPACE_BARRIER_WRITE); - aplsmc_send_cmd(sc, SMC_WRITE_KEY, key, sizeof(data)); - aplsmc_wait_cmd(sc); + aplsmc_write_key(sc, key, &data, sizeof(data)); } -- 2.20.1