Merge remote-tracking branch 'spi/topic/core' into spi-linus
This commit is contained in:
@@ -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
|
|||||||
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.
|
|||||||
|
|
||||||
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
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
/* 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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
#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 {
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user