Commit 3c103974 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'spi/topic/core' into spi-linus

parents 7e2c225d 1afd9989
...@@ -34,7 +34,7 @@ SPI slave functions are usually not interoperable between vendors ...@@ -34,7 +34,7 @@ SPI slave functions are usually not interoperable between vendors
- It may also be used to stream data in either direction (half duplex), - It may also be used to stream data in either direction (half duplex),
or both of them at the same time (full duplex). or both of them at the same time (full duplex).
- Some devices may use eight bit words. Others may different word - Some devices may use eight bit words. Others may use different word
lengths, such as streams of 12-bit or 20-bit digital samples. lengths, such as streams of 12-bit or 20-bit digital samples.
- Words are usually sent with their most significant bit (MSB) first, - Words are usually sent with their most significant bit (MSB) first,
...@@ -121,7 +121,7 @@ active. So the master must set the clock to inactive before selecting ...@@ -121,7 +121,7 @@ active. So the master must set the clock to inactive before selecting
a slave, and the slave can tell the chosen polarity by sampling the a slave, and the slave can tell the chosen polarity by sampling the
clock level when its select line goes active. That's why many devices clock level when its select line goes active. That's why many devices
support for example both modes 0 and 3: they don't care about polarity, support for example both modes 0 and 3: they don't care about polarity,
and alway clock data in/out on rising clock edges. and always clock data in/out on rising clock edges.
How do these driver programming interfaces work? How do these driver programming interfaces work?
...@@ -139,7 +139,7 @@ a command and then reading its response. ...@@ -139,7 +139,7 @@ a command and then reading its response.
There are two types of SPI driver, here called: There are two types of SPI driver, here called:
Controller drivers ... controllers may be built in to System-On-Chip Controller drivers ... controllers may be built into System-On-Chip
processors, and often support both Master and Slave roles. processors, and often support both Master and Slave roles.
These drivers touch hardware registers and may use DMA. These drivers touch hardware registers and may use DMA.
Or they can be PIO bitbangers, needing just GPIO pins. Or they can be PIO bitbangers, needing just GPIO pins.
...@@ -548,7 +548,7 @@ SPI MASTER METHODS ...@@ -548,7 +548,7 @@ SPI MASTER METHODS
DEPRECATED METHODS DEPRECATED METHODS
master->transfer(struct spi_device *spi, struct spi_message *message) master->transfer(struct spi_device *spi, struct spi_message *message)
This must not sleep. Its responsibility is arrange that the This must not sleep. Its responsibility is to arrange that the
transfer happens and its complete() callback is issued. The two transfer happens and its complete() callback is issued. The two
will normally happen later, after other transfers complete, and will normally happen later, after other transfers complete, and
if the controller is idle it will need to be kickstarted. This if the controller is idle it will need to be kickstarted. This
......
...@@ -695,7 +695,7 @@ static void spi_pump_messages(struct kthread_work *work) ...@@ -695,7 +695,7 @@ static void spi_pump_messages(struct kthread_work *work)
} }
/* Extract head of queue */ /* Extract head of queue */
master->cur_msg = master->cur_msg =
list_entry(master->queue.next, struct spi_message, queue); list_first_entry(&master->queue, struct spi_message, queue);
list_del_init(&master->cur_msg->queue); list_del_init(&master->cur_msg->queue);
if (master->busy) if (master->busy)
...@@ -803,11 +803,8 @@ struct spi_message *spi_get_next_queued_message(struct spi_master *master) ...@@ -803,11 +803,8 @@ struct spi_message *spi_get_next_queued_message(struct spi_master *master)
/* get a pointer to the next message, if any */ /* get a pointer to the next message, if any */
spin_lock_irqsave(&master->queue_lock, flags); spin_lock_irqsave(&master->queue_lock, flags);
if (list_empty(&master->queue)) next = list_first_entry_or_null(&master->queue, struct spi_message,
next = NULL; queue);
else
next = list_entry(master->queue.next,
struct spi_message, queue);
spin_unlock_irqrestore(&master->queue_lock, flags); spin_unlock_irqrestore(&master->queue_lock, flags);
return next; return next;
...@@ -1608,15 +1605,11 @@ int spi_setup(struct spi_device *spi) ...@@ -1608,15 +1605,11 @@ int spi_setup(struct spi_device *spi)
} }
EXPORT_SYMBOL_GPL(spi_setup); EXPORT_SYMBOL_GPL(spi_setup);
static int __spi_async(struct spi_device *spi, struct spi_message *message) static int __spi_validate(struct spi_device *spi, struct spi_message *message)
{ {
struct spi_master *master = spi->master; struct spi_master *master = spi->master;
struct spi_transfer *xfer; struct spi_transfer *xfer;
message->spi = spi;
trace_spi_message_submit(message);
if (list_empty(&message->transfers)) if (list_empty(&message->transfers))
return -EINVAL; return -EINVAL;
if (!message->complete) if (!message->complete)
...@@ -1679,9 +1672,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) ...@@ -1679,9 +1672,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
if (xfer->rx_buf && !xfer->rx_nbits) if (xfer->rx_buf && !xfer->rx_nbits)
xfer->rx_nbits = SPI_NBITS_SINGLE; xfer->rx_nbits = SPI_NBITS_SINGLE;
/* check transfer tx/rx_nbits: /* check transfer tx/rx_nbits:
* 1. keep the value is not out of single, dual and quad * 1. check the value matches one of single, dual and quad
* 2. keep tx/rx_nbits is contained by mode in spi_device * 2. check tx/rx_nbits match the mode in spi_device
* 3. if SPI_3WIRE, tx/rx_nbits should be in single
*/ */
if (xfer->tx_buf) { if (xfer->tx_buf) {
if (xfer->tx_nbits != SPI_NBITS_SINGLE && if (xfer->tx_nbits != SPI_NBITS_SINGLE &&
...@@ -1694,9 +1686,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) ...@@ -1694,9 +1686,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
if ((xfer->tx_nbits == SPI_NBITS_QUAD) && if ((xfer->tx_nbits == SPI_NBITS_QUAD) &&
!(spi->mode & SPI_TX_QUAD)) !(spi->mode & SPI_TX_QUAD))
return -EINVAL; return -EINVAL;
if ((spi->mode & SPI_3WIRE) &&
(xfer->tx_nbits != SPI_NBITS_SINGLE))
return -EINVAL;
} }
/* check transfer rx_nbits */ /* check transfer rx_nbits */
if (xfer->rx_buf) { if (xfer->rx_buf) {
...@@ -1710,13 +1699,22 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) ...@@ -1710,13 +1699,22 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
if ((xfer->rx_nbits == SPI_NBITS_QUAD) && if ((xfer->rx_nbits == SPI_NBITS_QUAD) &&
!(spi->mode & SPI_RX_QUAD)) !(spi->mode & SPI_RX_QUAD))
return -EINVAL; return -EINVAL;
if ((spi->mode & SPI_3WIRE) &&
(xfer->rx_nbits != SPI_NBITS_SINGLE))
return -EINVAL;
} }
} }
message->status = -EINPROGRESS; message->status = -EINPROGRESS;
return 0;
}
static int __spi_async(struct spi_device *spi, struct spi_message *message)
{
struct spi_master *master = spi->master;
message->spi = spi;
trace_spi_message_submit(message);
return master->transfer(spi, message); return master->transfer(spi, message);
} }
...@@ -1755,6 +1753,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message) ...@@ -1755,6 +1753,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
int ret; int ret;
unsigned long flags; unsigned long flags;
ret = __spi_validate(spi, message);
if (ret != 0)
return ret;
spin_lock_irqsave(&master->bus_lock_spinlock, flags); spin_lock_irqsave(&master->bus_lock_spinlock, flags);
if (master->bus_lock_flag) if (master->bus_lock_flag)
...@@ -1803,6 +1805,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) ...@@ -1803,6 +1805,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message)
int ret; int ret;
unsigned long flags; unsigned long flags;
ret = __spi_validate(spi, message);
if (ret != 0)
return ret;
spin_lock_irqsave(&master->bus_lock_spinlock, flags); spin_lock_irqsave(&master->bus_lock_spinlock, flags);
ret = __spi_async(spi, message); ret = __spi_async(spi, message);
......
...@@ -75,6 +75,7 @@ struct spi_device { ...@@ -75,6 +75,7 @@ struct spi_device {
struct spi_master *master; struct spi_master *master;
u32 max_speed_hz; u32 max_speed_hz;
u8 chip_select; u8 chip_select;
u8 bits_per_word;
u16 mode; u16 mode;
#define SPI_CPHA 0x01 /* clock phase */ #define SPI_CPHA 0x01 /* clock phase */
#define SPI_CPOL 0x02 /* clock polarity */ #define SPI_CPOL 0x02 /* clock polarity */
...@@ -92,7 +93,6 @@ struct spi_device { ...@@ -92,7 +93,6 @@ struct spi_device {
#define SPI_TX_QUAD 0x200 /* transmit with 4 wires */ #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */
#define SPI_RX_DUAL 0x400 /* receive with 2 wires */ #define SPI_RX_DUAL 0x400 /* receive with 2 wires */
#define SPI_RX_QUAD 0x800 /* receive with 4 wires */ #define SPI_RX_QUAD 0x800 /* receive with 4 wires */
u8 bits_per_word;
int irq; int irq;
void *controller_state; void *controller_state;
void *controller_data; void *controller_data;
...@@ -578,8 +578,8 @@ struct spi_transfer { ...@@ -578,8 +578,8 @@ struct spi_transfer {
dma_addr_t rx_dma; dma_addr_t rx_dma;
unsigned cs_change:1; unsigned cs_change:1;
u8 tx_nbits; unsigned tx_nbits:3;
u8 rx_nbits; unsigned rx_nbits:3;
#define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */ #define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */
#define SPI_NBITS_DUAL 0x02 /* 2bits transfer */ #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */
#define SPI_NBITS_QUAD 0x04 /* 4bits transfer */ #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */
...@@ -849,7 +849,7 @@ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd) ...@@ -849,7 +849,7 @@ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
ssize_t status; ssize_t status;
u16 result; u16 result;
status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2); status = spi_write_then_read(spi, &cmd, 1, &result, 2);
/* return negative errno or unsigned value */ /* return negative errno or unsigned value */
return (status < 0) ? status : result; return (status < 0) ? status : result;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment