Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/sunxi sun6i_spi: bring over non-intrusive impro...



details:   https://anonhg.NetBSD.org/src/rev/99655c59f359
branches:  trunk
changeset: 458624:99655c59f359
user:      tnn <tnn%NetBSD.org@localhost>
date:      Sat Aug 03 14:42:24 2019 +0000

description:
sun6i_spi: bring over non-intrusive improvements from sun4i_spi

- simplify attach error handling
- calculate minfreq & maxfreq instead of hardcoding
- print configured value of SPI_SCLK
- add convenience macro for reading/writing SPI register
- clean up commented out debug printfs

diffstat:

 sys/arch/arm/sunxi/sun6i_spi.c |  175 ++++++++++++++++------------------------
 1 files changed, 70 insertions(+), 105 deletions(-)

diffs (truncated from 360 to 300 lines):

diff -r d63e8fba6ab8 -r 99655c59f359 sys/arch/arm/sunxi/sun6i_spi.c
--- a/sys/arch/arm/sunxi/sun6i_spi.c    Sat Aug 03 14:00:42 2019 +0000
+++ b/sys/arch/arm/sunxi/sun6i_spi.c    Sat Aug 03 14:42:24 2019 +0000
@@ -1,6 +1,7 @@
-/*     $NetBSD: sun6i_spi.c,v 1.2 2018/02/01 14:50:36 jakllsch Exp $   */
+/*     $NetBSD: sun6i_spi.c,v 1.3 2019/08/03 14:42:24 tnn Exp $        */
 
 /*
+ * Copyright (c) 2019 Tobias Nygren
  * Copyright (c) 2018 Jonathan A. Kollasch
  * All rights reserved.
  *
@@ -27,12 +28,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sun6i_spi.c,v 1.2 2018/02/01 14:50:36 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sun6i_spi.c,v 1.3 2019/08/03 14:42:24 tnn Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
 #include <sys/systm.h>
-#include <sys/mutex.h>
 #include <sys/bus.h>
 #include <sys/intr.h>
 #include <sys/kernel.h>
@@ -64,6 +64,11 @@
        volatile bool           sc_running;
 };
 
+#define SPIREG_READ(sc, reg) \
+    bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
+#define SPIREG_WRITE(sc, reg, val) \
+    bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+
 static int sun6ispi_match(device_t, cfdata_t, void *);
 static void sun6ispi_attach(device_t, device_t, void *);
 
@@ -97,52 +102,37 @@
        struct sun6ispi_softc * const sc = device_private(self);
        struct fdt_attach_args * const faa = aux;
        struct spibus_attach_args sba;
+       const int phandle = faa->faa_phandle;
+       bus_addr_t addr;
+       bus_size_t size;
        struct fdtbus_reset *rst;
        struct clk *clk, *modclk;
        uint32_t gcr, isr;
        char intrstr[128];
 
-       aprint_naive("\n");
-       aprint_normal(": SPI\n");
-
        sc->sc_dev = self;
        sc->sc_iot = faa->faa_bst;
        SIMPLEQ_INIT(&sc->sc_q);
 
-       const int phandle = faa->faa_phandle;
-       bus_addr_t addr;
-       bus_size_t size;
-
-       if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
-               aprint_error_dev(sc->sc_dev, "missing 'reg' property\n");
-               return;
-       }
-
-       if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh) != 0) {
-               aprint_error_dev(sc->sc_dev, "unable to map device\n");
+       if ((clk = fdtbus_clock_get_index(phandle, 0)) == NULL
+           || clk_enable(clk) != 0) {
+               aprint_error(": couldn't enable clock\n");
                return;
        }
 
-       if ((clk = fdtbus_clock_get_index(phandle, 0)) != NULL) {
-               if (clk_enable(clk) != 0) {
-                       aprint_error_dev(sc->sc_dev, "couldn't enable clock\n");
-                       return;
-               }
-               device_printf(self, "%s ahb @ %uHz\n", __func__, clk_get_rate(clk));
+       /* 200MHz max on H3,H5 */
+       if ((modclk = fdtbus_clock_get(phandle, "mod")) == NULL
+           || clk_set_rate(modclk, 200000000) != 0
+           || clk_enable(modclk) != 0) {
+               aprint_error(": couldn't enable module clock\n");
+               return;
        }
+       sc->sc_modclkrate = clk_get_rate(modclk);
 
-       if ((modclk = fdtbus_clock_get(phandle, "mod")) != NULL) {
-               /* 200MHz max on H3,H5 */
-               if (clk_set_rate(modclk, 200000000) != 0) {
-                       aprint_error_dev(sc->sc_dev, "couldn't configure module clock\n");
-                       return;
-               }
-               if (clk_enable(modclk) != 0) {
-                       aprint_error_dev(sc->sc_dev, "couldn't enable module clock\n");
-                       return;
-               }
-               sc->sc_modclkrate = clk_get_rate(modclk);
-               device_printf(self, "%s %uHz\n", __func__, sc->sc_modclkrate);
+       if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0
+           || bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh) != 0) {
+               aprint_error(": couldn't map registers\n");
+               return;
        }
 
        if ((rst = fdtbus_reset_get_index(phandle, 0)) != NULL)
@@ -151,8 +141,8 @@
                        return;
                }
 
-       isr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SPI_INT_STA);
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_INT_STA, isr);
+       isr = SPIREG_READ(sc, SPI_INT_STA);
+       SPIREG_WRITE(sc, SPI_INT_STA, isr);
 
        if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
                aprint_error(": failed to decode interrupt\n");
@@ -162,13 +152,17 @@
        sc->sc_intrh = fdtbus_intr_establish(phandle, 0, IPL_VM, 0,
            sun6ispi_intr, sc);
        if (sc->sc_intrh == NULL) {
-               aprint_error_dev(sc->sc_dev, "unable to establish interrupt\n");
+               aprint_error(": unable to establish interrupt\n");
                return;
        }
+
+       aprint_naive("\n");
+       aprint_normal(": SPI\n");
+       
        aprint_normal_dev(self, "interrupting on %s\n", intrstr);
 
        gcr = SPI_GCR_SRST;
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_GCR, gcr);
+       SPIREG_WRITE(sc, SPI_GCR, gcr);
        for (u_int i = 0; ; i++) {
                if (i >= 1000000) {
                        aprint_error_dev(self, "reset timeout\n");
@@ -181,9 +175,9 @@
                        DELAY(1);
        }
        gcr = SPI_GCR_TP_EN | SPI_GCR_MODE | SPI_GCR_EN;
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_GCR, gcr);
+       SPIREG_WRITE(sc, SPI_GCR, gcr);
 
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_IER, SPI_IER_DEFAULT);
+       SPIREG_WRITE(sc, SPI_IER, SPI_IER_DEFAULT);
 
        sc->sc_spi.sct_cookie = sc;
        sc->sc_spi.sct_configure = sun6ispi_configure;
@@ -200,21 +194,18 @@
 {
        struct sun6ispi_softc * const sc = cookie;
        uint32_t tcr, cctl;
-
-#if 0
-       device_printf(sc->sc_dev, "%s slave %d mode %d speed %d\n", __func__, slave, mode, speed);
+       uint32_t minfreq, maxfreq;
 
-       if (speed > 200000)
-               speed = 200000;
-#endif
+       minfreq = sc->sc_modclkrate >> 16;
+       maxfreq = sc->sc_modclkrate >> 1;
 
-       tcr = SPI_TCR_SS_LEVEL | SPI_TCR_SPOL;
-
-       if (slave > 3)
+       if (speed <= 0 || speed < minfreq || speed > maxfreq)
                return EINVAL;
 
-       if (speed <= 0)
+       if (slave >= sc->sc_spi.sct_nslaves)
                return EINVAL;
+       
+       tcr = SPI_TCR_SS_LEVEL | SPI_TCR_SPOL;
 
        switch (mode) {
        case SPI_MODE_0:
@@ -235,10 +226,7 @@
 
        sc->sc_TCR = tcr;
 
-       if (speed < 3000 || speed > 200000000)
-               return EINVAL;
-
-       if (speed > sc->sc_modclkrate / 2 || speed < sc->sc_modclkrate / 512) {
+       if (speed < sc->sc_modclkrate / 512) {
                for (cctl = 0; cctl <= __SHIFTOUT_MASK(SPI_CCTL_CDR1); cctl++) {
                        if ((sc->sc_modclkrate / (1<<cctl)) <= speed)
                                goto cdr1_found;
@@ -251,8 +239,14 @@
                cctl = SPI_CCTL_DRS|__SHIFTIN(cctl, SPI_CCTL_CDR2);
        }
 
-       device_printf(sc->sc_dev, "%s CCTL 0x%08x\n", __func__, cctl);
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_CCTL, cctl);
+       device_printf(sc->sc_dev, "tcr 0x%x, cctl 0x%x, CLK %uHz, SCLK %uHz\n",
+           tcr, cctl, sc->sc_modclkrate,
+           (cctl & SPI_CCTL_DRS)
+           ? (sc->sc_modclkrate / (u_int)(2 * (__SHIFTOUT(cctl, SPI_CCTL_CDR2) + 1)))
+           : (sc->sc_modclkrate >> (__SHIFTOUT(cctl, SPI_CCTL_CDR1) + 1))
+       );
+
+       SPIREG_WRITE(sc, SPI_CCTL, cctl);
 
        return 0;
 }
@@ -272,27 +266,14 @@
        return 0;
 }
 
-static size_t
-chunks_total_count(struct spi_transfer * st)
-{
-       struct spi_chunk *chunk = st->st_chunks;
-       size_t len = 0;
-
-       do {
-               len += chunk->chunk_count;
-       } while ((chunk = chunk->chunk_next) != NULL);
-
-       return len;
-}
-
 static void
 sun6ispi_start(struct sun6ispi_softc * const sc)
 {
        struct spi_transfer *st;
        uint32_t isr, tcr;
-       size_t ctc;
+       struct spi_chunk *chunk;
+       size_t burstcount;
 
-       //device_printf(sc->sc_dev, "%s\n", __func__);
        while ((st = spi_transq_first(&sc->sc_q)) != NULL) {
 
                spi_transq_dequeue(&sc->sc_q);
@@ -302,37 +283,31 @@
                sc->sc_rchunk = sc->sc_wchunk = st->st_chunks;
                sc->sc_running = true;
 
-               isr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SPI_INT_STA);
-               bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_INT_STA, isr);
-
-               //printf("%s fcr 0x%08x\n", __func__, bus_space_read_4(sc->sc_iot, sc->sc_ioh, SPI_FCR));
+               isr = SPIREG_READ(sc, SPI_INT_STA);
+               SPIREG_WRITE(sc, SPI_INT_STA, isr);
 
-               ctc = chunks_total_count(st);
-               //printf("%s total count %zu\n", __func__, ctc);
-
-               bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_BC, __SHIFTIN(ctc, SPI_BC_MBC));
-               bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_TC, __SHIFTIN(ctc, SPI_TC_MWTC));
-               bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_BCC, __SHIFTIN(ctc, SPI_BCC_STC));
+               burstcount = 0;
+               for (chunk = st->st_chunks; chunk; chunk = chunk->chunk_next) {
+                       burstcount += chunk->chunk_count;
+               }
+               KASSERT(burstcount <= SPI_BC_MBC);
+               SPIREG_WRITE(sc, SPI_BC, __SHIFTIN(burstcount, SPI_BC_MBC));
+               SPIREG_WRITE(sc, SPI_TC, __SHIFTIN(burstcount, SPI_TC_MWTC));
+               SPIREG_WRITE(sc, SPI_BCC, __SHIFTIN(burstcount, SPI_BCC_STC));
 
                KASSERT(st->st_slave <= 3);
                tcr = sc->sc_TCR | __SHIFTIN(st->st_slave, SPI_TCR_SS_SEL);
 
-               //device_printf(sc->sc_dev, "%s before TCR write\n", __func__);
-               //bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_TCR, tcr);
-
                sun6ispi_send(sc);
 
                const uint32_t ier = SPI_IER_DEFAULT | SPI_IER_RF_RDY_INT_EN | SPI_IER_TX_ERQ_INT_EN;
-               bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_IER, ier);
+               SPIREG_WRITE(sc, SPI_IER, ier);
 
-               bus_space_write_4(sc->sc_iot, sc->sc_ioh, SPI_TCR, tcr|SPI_TCR_XCH);
-               //device_printf(sc->sc_dev, "%s after TCR write\n", __func__);
+               SPIREG_WRITE(sc, SPI_TCR, tcr|SPI_TCR_XCH);
 
                if (!cold)
                        return;
 
-               //device_printf(sc->sc_dev, "%s cold\n", __func__);
-
                int s = splbio();
                for (;;) {
                        sun6ispi_intr(sc);
@@ -343,7 +318,6 @@
        }
 
        sc->sc_running = false;
-//     device_printf(sc->sc_dev, "%s finishes\n", __func__);
 }
 
 static void
@@ -353,13 +327,10 @@
        uint32_t fsr;
        struct spi_chunk *chunk;



Home | Main Index | Thread Index | Old Index