struct spi_bitbang_cs *cs = spi->controller_state;
struct spi_bitbang *bitbang;
int retval;
+ unsigned long flags;
bitbang = spi_master_get_devdata(spi->master);
- /* REVISIT: some systems will want to support devices using lsb-first
- * bit encodings on the wire. In pure software that would be trivial,
- * just bitbang_txrx_le_cphaX() routines shifting the other way, and
- * some hardware controllers also have this support.
+ /* Bitbangers can support SPI_CS_HIGH, SPI_3WIRE, and so on;
+ * add those to master->flags, and provide the other support.
*/
- if ((spi->mode & SPI_LSB_FIRST) != 0)
+ if ((spi->mode & ~(SPI_CPOL|SPI_CPHA|bitbang->flags)) != 0)
return -EINVAL;
if (!cs) {
return retval;
dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
- __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
+ __func__, spi->mode & (SPI_CPOL | SPI_CPHA),
spi->bits_per_word, 2 * cs->nsecs);
/* NOTE we _need_ to call chipselect() early, ideally with adapter
*/
/* deselect chip (low or high) */
- spin_lock(&bitbang->lock);
+ spin_lock_irqsave(&bitbang->lock, flags);
if (!bitbang->busy) {
bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
ndelay(cs->nsecs);
}
- spin_unlock(&bitbang->lock);
+ spin_unlock_irqrestore(&bitbang->lock, flags);
return 0;
}
setup_transfer = NULL;
list_for_each_entry (t, &m->transfers, transfer_list) {
- if (bitbang->shutdown) {
- status = -ESHUTDOWN;
- break;
- }
/* override or restore speed and wordsize */
if (t->speed_hz || t->bits_per_word) {
t->rx_dma = t->tx_dma = 0;
status = bitbang->txrx_bufs(spi, t);
}
+ if (status > 0)
+ m->actual_length += status;
if (status != t->len) {
- if (status > 0)
- status = -EMSGSIZE;
+ /* always report some kind of error */
+ if (status >= 0)
+ status = -EREMOTEIO;
break;
}
- m->actual_length += status;
status = 0;
/* protocol tweaks before next transfer */
m->status = -EINPROGRESS;
bitbang = spi_master_get_devdata(spi->master);
- if (bitbang->shutdown)
- return -ESHUTDOWN;
spin_lock_irqsave(&bitbang->lock, flags);
if (!spi->max_speed_hz)
/* this task is the only thing to touch the SPI bits */
bitbang->busy = 0;
bitbang->workqueue = create_singlethread_workqueue(
- bitbang->master->cdev.dev->bus_id);
+ bitbang->master->dev.parent->bus_id);
if (bitbang->workqueue == NULL) {
status = -EBUSY;
goto err1;
*/
int spi_bitbang_stop(struct spi_bitbang *bitbang)
{
- unsigned limit = 500;
-
- spin_lock_irq(&bitbang->lock);
- bitbang->shutdown = 0;
- while (!list_empty(&bitbang->queue) && limit--) {
- spin_unlock_irq(&bitbang->lock);
-
- dev_dbg(bitbang->master->cdev.dev, "wait for queue\n");
- msleep(10);
+ spi_unregister_master(bitbang->master);
- spin_lock_irq(&bitbang->lock);
- }
- spin_unlock_irq(&bitbang->lock);
- if (!list_empty(&bitbang->queue)) {
- dev_err(bitbang->master->cdev.dev, "queue didn't empty\n");
- return -EBUSY;
- }
+ WARN_ON(!list_empty(&bitbang->queue));
destroy_workqueue(bitbang->workqueue);
- spi_unregister_master(bitbang->master);
-
return 0;
}
EXPORT_SYMBOL_GPL(spi_bitbang_stop);