summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2021-12-11 20:04:38 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2021-12-11 20:04:38 +0000
commit713402bf2ebb21053a3b53666bb50dc88a200556 (patch)
tree3e68ce8293f7615ff28e20149e3bd330701910be
parentda3293404937e8ea764cba062b1b270efb980544 (diff)
Thanks to the reverse engineering efforts by Hector Martin, we now know
that we can controll the CS# pin directly from the SPI controller itself. Add support for this as future device trees will probably use this mode instead of explicitly specifying a "cs-gpios" property. ok patrick@
-rw-r--r--sys/arch/arm64/dev/aplspi.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/sys/arch/arm64/dev/aplspi.c b/sys/arch/arm64/dev/aplspi.c
index 4bd1483adce..224a50276c8 100644
--- a/sys/arch/arm64/dev/aplspi.c
+++ b/sys/arch/arm64/dev/aplspi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aplspi.c,v 1.2 2021/11/12 17:04:32 kettenis Exp $ */
+/* $OpenBSD: aplspi.c,v 1.3 2021/12/11 20:04:37 kettenis Exp $ */
/*
* Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
*
@@ -38,6 +38,8 @@
#define SPI_CONFIG_EN (1 << 18)
#define SPI_CONFIG_PIOEN (1 << 5)
#define SPI_STATUS 0x08
+#define SPI_PIN 0x0c
+#define SPI_PIN_CS (1 << 1)
#define SPI_TXDATA 0x10
#define SPI_RXDATA 0x20
#define SPI_CLKDIV 0x30
@@ -49,6 +51,11 @@
#define SPI_AVAIL 0x10c
#define SPI_AVAIL_TX(avail) ((avail >> 8) & 0xff)
#define SPI_AVAIL_RX(avail) ((avail >> 24) & 0xff)
+#define SPI_SHIFTCFG 0x150
+#define SPI_SHIFTCFG_OVERRIDE_CS (1 << 24)
+#define SPI_PINCFG 0x154
+#define SPI_PINCFG_KEEP_CS (1 << 1)
+#define SPI_PINCFG_CS_IDLE_VAL (1 << 9)
#define SPI_FIFO_SIZE 16
@@ -67,7 +74,7 @@ struct aplspi_softc {
int sc_cs;
uint32_t *sc_csgpio;
- size_t sc_csgpiolen;
+ int sc_csgpiolen;
u_int sc_cs_delay;
};
@@ -140,6 +147,14 @@ aplspi_attach(struct device *parent, struct device *self, void *aux)
sc->sc_pfreq = clock_get_frequency(sc->sc_node, NULL);
+ pinctrl_byname(sc->sc_node, "default");
+
+ /* Configure CS# pin for manual control. */
+ HWRITE4(sc, SPI_PIN, SPI_PIN_CS);
+ HCLR4(sc, SPI_SHIFTCFG, SPI_SHIFTCFG_OVERRIDE_CS);
+ HCLR4(sc, SPI_PINCFG, SPI_PINCFG_CS_IDLE_VAL);
+ HSET4(sc, SPI_PINCFG, SPI_PINCFG_KEEP_CS);
+
sc->sc_tag.sc_cookie = sc;
sc->sc_tag.sc_config = aplspi_config;
sc->sc_tag.sc_transfer = aplspi_transfer;
@@ -193,8 +208,12 @@ aplspi_clkdiv(struct aplspi_softc *sc, uint32_t freq)
void
aplspi_set_cs(struct aplspi_softc *sc, int cs, int on)
{
- if (sc->sc_csgpio && cs == 0)
- gpio_controller_set_pin(sc->sc_csgpio, on);
+ if (cs == 0) {
+ if (sc->sc_csgpio)
+ gpio_controller_set_pin(sc->sc_csgpio, on);
+ else
+ HWRITE4(sc, SPI_PIN, on ? 0 : SPI_PIN_CS);
+ }
}
int