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/2a6ca03142f9
branches: trunk
changeset: 453240:2a6ca03142f9
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 9e552f8268ee -r 2a6ca03142f9 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