From: kettenis Date: Sun, 31 Oct 2021 15:12:00 +0000 (+0000) Subject: Extend the SPI bus API a bit. The config structure gets an sc_cs_delay X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=fe92277574533ee44bdcd49cfe822a8841b6a825;p=openbsd Extend the SPI bus API a bit. The config structure gets an sc_cs_delay member to allow us to specify a delay between assert the CS# signal and starting the clock. And the transfer function gains a flags argument, which can be used to specify a new SPI_KEEP_CS flag to keep CS# asserted after the transfer. This allows us to do another transfer immediately afterwards without de-asserting CS# which is necessary for sending commands to the upcoming Apple M1 keyboard/touchpad driver. ok patrick@ --- diff --git a/sys/dev/fdt/imxspi.c b/sys/dev/fdt/imxspi.c index 425c3cba968..3c07fe68b17 100644 --- a/sys/dev/fdt/imxspi.c +++ b/sys/dev/fdt/imxspi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imxspi.c,v 1.2 2021/10/24 17:52:26 mpi Exp $ */ +/* $OpenBSD: imxspi.c,v 1.3 2021/10/31 15:12:00 kettenis Exp $ */ /* * Copyright (c) 2018 Patrick Wildt * @@ -99,6 +99,7 @@ struct imxspi_softc { int sc_ridx; int sc_widx; int sc_cs; + u_int sc_cs_delay; }; int imxspi_match(struct device *, void *, void *); @@ -109,7 +110,7 @@ int imxspi_intr(void *); void imxspi_config(void *, struct spi_config *); uint32_t imxspi_clkdiv(struct imxspi_softc *, uint32_t); -int imxspi_transfer(void *, char *, char *, int); +int imxspi_transfer(void *, char *, char *, int, int); int imxspi_acquire_bus(void *, int); void imxspi_release_bus(void *, int); @@ -235,6 +236,7 @@ imxspi_config(void *cookie, struct spi_config *conf) return; } sc->sc_cs = cs; + sc->sc_cs_delay = conf->sc_cs_delay; conreg = SPI_CONREG_EN; conreg |= SPI_CONREG_CHANNEL_MASTER; @@ -322,7 +324,7 @@ imxspi_find_cs_gpio(struct imxspi_softc *sc, int cs) } int -imxspi_transfer(void *cookie, char *out, char *in, int len) +imxspi_transfer(void *cookie, char *out, char *in, int len, int flags) { struct imxspi_softc *sc = cookie; uint32_t *gpio; @@ -335,6 +337,7 @@ imxspi_transfer(void *cookie, char *out, char *in, int len) gpio_controller_set_pin(gpio, 0); delay(1); } + delay(sc->sc_cs_delay); /* drain input buffer */ while (HREAD4(sc, SPI_STATREG) & SPI_STATREG_RR) @@ -370,10 +373,12 @@ imxspi_transfer(void *cookie, char *out, char *in, int len) HWRITE4(sc, SPI_STATREG, SPI_STATREG_TC); } - gpio = imxspi_find_cs_gpio(sc, sc->sc_cs); - if (gpio) { - gpio_controller_set_pin(gpio, 1); - delay(1); + if (!ISSET(flags, SPI_KEEP_CS)) { + gpio = imxspi_find_cs_gpio(sc, sc->sc_cs); + if (gpio) { + gpio_controller_set_pin(gpio, 1); + delay(1); + } } return 0; diff --git a/sys/dev/fdt/mvspi.c b/sys/dev/fdt/mvspi.c index 4731e349f3e..30b8831dbb5 100644 --- a/sys/dev/fdt/mvspi.c +++ b/sys/dev/fdt/mvspi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mvspi.c,v 1.2 2021/10/24 17:52:26 mpi Exp $ */ +/* $OpenBSD: mvspi.c,v 1.3 2021/10/31 15:12:00 kettenis Exp $ */ /* * Copyright (c) 2019 Patrick Wildt * @@ -60,6 +60,7 @@ struct mvspi_softc { struct spi_controller sc_tag; int sc_cs; + u_int sc_cs_delay; }; int mvspi_match(struct device *, void *, void *); @@ -68,7 +69,7 @@ int mvspi_detach(struct device *, int); void mvspi_config(void *, struct spi_config *); uint32_t mvspi_clkdiv(struct mvspi_softc *, uint32_t); -int mvspi_transfer(void *, char *, char *, int); +int mvspi_transfer(void *, char *, char *, int, int); int mvspi_acquire_bus(void *, int); void mvspi_release_bus(void *, int); @@ -177,6 +178,7 @@ mvspi_config(void *cookie, struct spi_config *conf) return; } sc->sc_cs = cs; + sc->sc_cs_delay = conf->sc_cs_delay; HCLR4(sc, SPI_CFG, SPI_CFG_PRESCALE_MASK); HSET4(sc, SPI_CFG, mvspi_clkdiv(sc, conf->sc_freq)); @@ -229,12 +231,13 @@ mvspi_set_cs(struct mvspi_softc *sc, int cs, int on) } int -mvspi_transfer(void *cookie, char *out, char *in, int len) +mvspi_transfer(void *cookie, char *out, char *in, int len, int flags) { struct mvspi_softc *sc = cookie; int i = 0; mvspi_set_cs(sc, sc->sc_cs, 1); + delay(sc->sc_cs_delay); while (i < len) { if (mvspi_wait_state(sc, SPI_CTRL_XFER_READY, @@ -255,7 +258,8 @@ mvspi_transfer(void *cookie, char *out, char *in, int len) i++; } - mvspi_set_cs(sc, sc->sc_cs, 0); + if (!ISSET(flags, SPI_KEEP_CS)) + mvspi_set_cs(sc, sc->sc_cs, 0); return 0; err: diff --git a/sys/dev/spi/spivar.h b/sys/dev/spi/spivar.h index 986bc7f602d..c56b840a3b6 100644 --- a/sys/dev/spi/spivar.h +++ b/sys/dev/spi/spivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: spivar.h,v 1.1 2018/07/26 10:59:07 patrick Exp $ */ +/* $OpenBSD: spivar.h,v 1.2 2021/10/31 15:12:00 kettenis Exp $ */ /* * Copyright (c) 2018 Patrick Wildt * @@ -23,14 +23,17 @@ struct spi_config { #define SPI_CONFIG_CS_HIGH (1 << 2) int sc_bpw; uint32_t sc_freq; + u_int sc_cs_delay; }; +#define SPI_KEEP_CS (1 << 0) + typedef struct spi_controller { - void *sc_cookie; - void (*sc_config)(void *, struct spi_config *); - int (*sc_transfer)(void *, char *, char *, int); - int (*sc_acquire_bus)(void *, int); - void (*sc_release_bus)(void *, int); + void *sc_cookie; + void (*sc_config)(void *, struct spi_config *); + int (*sc_transfer)(void *, char *, char *, int, int); + int (*sc_acquire_bus)(void *, int); + void (*sc_release_bus)(void *, int); } *spi_tag_t; struct spi_attach_args { @@ -42,11 +45,11 @@ struct spi_attach_args { #define spi_config(sc, config) \ (*(sc)->sc_config)((sc)->sc_cookie, (config)) #define spi_read(sc, data, len) \ - (*(sc)->sc_transfer)((sc)->sc_cookie, NULL, (data), (len)) + (*(sc)->sc_transfer)((sc)->sc_cookie, NULL, (data), (len), 0) #define spi_write(sc, data, len) \ - (*(sc)->sc_transfer)((sc)->sc_cookie, (data), NULL, (len)) -#define spi_transfer(sc, out, in, len) \ - (*(sc)->sc_transfer)((sc)->sc_cookie, (out), (in), (len)) + (*(sc)->sc_transfer)((sc)->sc_cookie, (data), NULL, (len), 0) +#define spi_transfer(sc, out, in, len, flags) \ + (*(sc)->sc_transfer)((sc)->sc_cookie, (out), (in), (len), (flags)) #define spi_acquire_bus(sc, flags) \ (*(sc)->sc_acquire_bus)((sc)->sc_cookie, (flags)) #define spi_release_bus(sc, flags) \