Page MenuHomeFreeBSD

D29534.id98067.diff
No OneTemporary

D29534.id98067.diff

diff --git a/sys/dev/intel/spi.c b/sys/dev/intel/spi.c
--- a/sys/dev/intel/spi.c
+++ b/sys/dev/intel/spi.c
@@ -304,8 +304,8 @@
intelspi_transfer(device_t dev, device_t child, struct spi_command *cmd)
{
struct intelspi_softc *sc;
- int err;
- uint32_t sscr0, sscr1, mode, clock;
+ int err, poll_limit;
+ uint32_t sscr0, sscr1, mode, clock, cs_delay;
bool restart = false;
sc = device_get_softc(dev);
@@ -320,6 +320,8 @@
/* If the controller is in use wait until it is available. */
while (sc->sc_flags & INTELSPI_BUSY) {
+ if ((cmd->flags & SPI_FLAG_NO_SLEEP) == SPI_FLAG_NO_SLEEP)
+ return (EBUSY);
err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", 0);
if (err == EINTR) {
INTELSPI_UNLOCK(sc);
@@ -377,19 +379,34 @@
/* Enable CS */
intelspi_set_cs(sc, CS_LOW);
- /* Transfer as much as possible to FIFOs */
- if (!intelspi_transact(sc)) {
- /* If FIFO is not large enough - enable interrupts */
- sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1);
- sscr1 |= (SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE);
- INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1);
- /* and wait for transaction to complete */
- err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", hz * 2);
+ /* Wait the CS delay */
+ spibus_get_cs_delay(child, &cs_delay);
+ DELAY(cs_delay);
+
+ /* Transfer as much as possible to FIFOs */
+ if ((cmd->flags & SPI_FLAG_NO_SLEEP) == SPI_FLAG_NO_SLEEP) {
+ /* We cannot wait with mtx_sleep if we're called from e.g. an ithread */
+ poll_limit = 100;
+ while (!intelspi_transact(sc) && poll_limit-- > 0)
+ DELAY(1000);
+ if (poll_limit == 0)
+ device_printf(dev, "polling was stuck, transaction not finished\n");
+ } else {
+ if (!intelspi_transact(sc)) {
+ /* If FIFO is not large enough - enable interrupts */
+ sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1);
+ sscr1 |= (SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE);
+ INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1);
+
+ /* and wait for transaction to complete */
+ err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", hz * 2);
+ }
}
- /* de-asser CS */
- intelspi_set_cs(sc, CS_HIGH);
+ /* De-assert CS */
+ if ((cmd->flags & SPI_FLAG_KEEP_CS) == 0)
+ intelspi_set_cs(sc, CS_HIGH);
/* Clear transaction details */
sc->sc_cmd = NULL;
diff --git a/sys/dev/spibus/spi.h b/sys/dev/spibus/spi.h
--- a/sys/dev/spibus/spi.h
+++ b/sys/dev/spibus/spi.h
@@ -34,9 +34,13 @@
uint32_t tx_data_sz;
void *rx_data;
uint32_t rx_data_sz;
+ uint32_t flags;
};
#define SPI_COMMAND_INITIALIZER { 0 }
+#define SPI_FLAG_KEEP_CS 0x1 /* Keep chip select asserted */
+#define SPI_FLAG_NO_SLEEP 0x2 /* Prevent driver from sleeping (use polling) */
+
#define SPI_CHIP_SELECT_HIGH 0x1 /* Chip select high (else low) */
#ifdef FDT
diff --git a/sys/dev/spibus/spibus.c b/sys/dev/spibus/spibus.c
--- a/sys/dev/spibus/spibus.c
+++ b/sys/dev/spibus/spibus.c
@@ -146,6 +146,9 @@
case SPIBUS_IVAR_CLOCK:
*(uint32_t *)result = devi->clock;
break;
+ case SPIBUS_IVAR_CS_DELAY:
+ *(uint32_t *)result = devi->cs_delay;
+ break;
}
return (0);
}
@@ -174,6 +177,9 @@
return (EINVAL);
devi->mode = (uint32_t)value;
break;
+ case SPIBUS_IVAR_CS_DELAY:
+ devi->cs_delay = (uint32_t)value;
+ break;
default:
return (EINVAL);
}
diff --git a/sys/dev/spibus/spibusvar.h b/sys/dev/spibus/spibusvar.h
--- a/sys/dev/spibus/spibusvar.h
+++ b/sys/dev/spibus/spibusvar.h
@@ -43,6 +43,7 @@
uint32_t cs;
uint32_t mode;
uint32_t clock;
+ uint32_t cs_delay;
struct resource_list rl;
};
@@ -52,6 +53,7 @@
SPIBUS_IVAR_CS, /* chip select that we're on */
SPIBUS_IVAR_MODE, /* SPI mode (0-3) */
SPIBUS_IVAR_CLOCK, /* maximum clock freq for device */
+ SPIBUS_IVAR_CS_DELAY, /* delay in microseconds after toggling chip select */
};
#define SPIBUS_ACCESSOR(A, B, T) \
@@ -71,6 +73,7 @@
SPIBUS_ACCESSOR(cs, CS, uint32_t)
SPIBUS_ACCESSOR(mode, MODE, uint32_t)
SPIBUS_ACCESSOR(clock, CLOCK, uint32_t)
+SPIBUS_ACCESSOR(cs_delay, CS_DELAY, uint32_t)
extern driver_t spibus_driver;
extern devclass_t spibus_devclass;

File Metadata

Mime Type
text/plain
Expires
Tue, Sep 24, 3:57 AM (5 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
12625723
Default Alt Text
D29534.id98067.diff (3 KB)

Event Timeline