Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F95956561
D29534.id98067.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D29534.id98067.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D29534: spibus: extend API: add cs_delay ivar, KEEP_CS and NO_SLEEP flags
Attached
Detach File
Event Timeline
Log In to Comment