Loading Documentation/spi/spi-summary +4 −4 Original line number Diff line number Diff line Loading @@ -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), 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. - Words are usually sent with their most significant bit (MSB) first, Loading Loading @@ -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 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, 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? Loading Loading @@ -548,7 +548,7 @@ SPI MASTER METHODS DEPRECATED METHODS 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 will normally happen later, after other transfers complete, and if the controller is idle it will need to be kickstarted. This Loading drivers/spi/spi.c +26 −20 Original line number Diff line number Diff line Loading @@ -695,7 +695,7 @@ static void spi_pump_messages(struct kthread_work *work) } /* Extract head of queue */ 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); if (master->busy) Loading Loading @@ -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 */ spin_lock_irqsave(&master->queue_lock, flags); if (list_empty(&master->queue)) next = NULL; else next = list_entry(master->queue.next, struct spi_message, queue); next = list_first_entry_or_null(&master->queue, struct spi_message, queue); spin_unlock_irqrestore(&master->queue_lock, flags); return next; Loading Loading @@ -1608,15 +1605,11 @@ int spi_setup(struct spi_device *spi) } 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_transfer *xfer; message->spi = spi; trace_spi_message_submit(message); if (list_empty(&message->transfers)) return -EINVAL; if (!message->complete) Loading Loading @@ -1679,9 +1672,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) if (xfer->rx_buf && !xfer->rx_nbits) xfer->rx_nbits = SPI_NBITS_SINGLE; /* check transfer tx/rx_nbits: * 1. keep the value is not out of single, dual and quad * 2. keep tx/rx_nbits is contained by mode in spi_device * 3. if SPI_3WIRE, tx/rx_nbits should be in single * 1. check the value matches one of single, dual and quad * 2. check tx/rx_nbits match the mode in spi_device */ if (xfer->tx_buf) { if (xfer->tx_nbits != SPI_NBITS_SINGLE && Loading @@ -1694,9 +1686,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) if ((xfer->tx_nbits == SPI_NBITS_QUAD) && !(spi->mode & SPI_TX_QUAD)) return -EINVAL; if ((spi->mode & SPI_3WIRE) && (xfer->tx_nbits != SPI_NBITS_SINGLE)) return -EINVAL; } /* check transfer rx_nbits */ if (xfer->rx_buf) { Loading @@ -1710,13 +1699,22 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) if ((xfer->rx_nbits == SPI_NBITS_QUAD) && !(spi->mode & SPI_RX_QUAD)) return -EINVAL; if ((spi->mode & SPI_3WIRE) && (xfer->rx_nbits != SPI_NBITS_SINGLE)) return -EINVAL; } } 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); } Loading Loading @@ -1755,6 +1753,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message) int ret; unsigned long flags; ret = __spi_validate(spi, message); if (ret != 0) return ret; spin_lock_irqsave(&master->bus_lock_spinlock, flags); if (master->bus_lock_flag) Loading Loading @@ -1803,6 +1805,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) int ret; unsigned long flags; ret = __spi_validate(spi, message); if (ret != 0) return ret; spin_lock_irqsave(&master->bus_lock_spinlock, flags); ret = __spi_async(spi, message); Loading include/linux/spi/spi.h +4 −4 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ struct spi_device { struct spi_master *master; u32 max_speed_hz; u8 chip_select; u8 bits_per_word; u16 mode; #define SPI_CPHA 0x01 /* clock phase */ #define SPI_CPOL 0x02 /* clock polarity */ Loading @@ -92,7 +93,6 @@ struct spi_device { #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */ #define SPI_RX_DUAL 0x400 /* receive with 2 wires */ #define SPI_RX_QUAD 0x800 /* receive with 4 wires */ u8 bits_per_word; int irq; void *controller_state; void *controller_data; Loading Loading @@ -578,8 +578,8 @@ struct spi_transfer { dma_addr_t rx_dma; unsigned cs_change:1; u8 tx_nbits; u8 rx_nbits; unsigned tx_nbits:3; unsigned rx_nbits:3; #define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */ #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */ #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */ Loading Loading @@ -849,7 +849,7 @@ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd) ssize_t status; 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 (status < 0) ? status : result; Loading Loading
Documentation/spi/spi-summary +4 −4 Original line number Diff line number Diff line Loading @@ -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), 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. - Words are usually sent with their most significant bit (MSB) first, Loading Loading @@ -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 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, 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? Loading Loading @@ -548,7 +548,7 @@ SPI MASTER METHODS DEPRECATED METHODS 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 will normally happen later, after other transfers complete, and if the controller is idle it will need to be kickstarted. This Loading
drivers/spi/spi.c +26 −20 Original line number Diff line number Diff line Loading @@ -695,7 +695,7 @@ static void spi_pump_messages(struct kthread_work *work) } /* Extract head of queue */ 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); if (master->busy) Loading Loading @@ -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 */ spin_lock_irqsave(&master->queue_lock, flags); if (list_empty(&master->queue)) next = NULL; else next = list_entry(master->queue.next, struct spi_message, queue); next = list_first_entry_or_null(&master->queue, struct spi_message, queue); spin_unlock_irqrestore(&master->queue_lock, flags); return next; Loading Loading @@ -1608,15 +1605,11 @@ int spi_setup(struct spi_device *spi) } 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_transfer *xfer; message->spi = spi; trace_spi_message_submit(message); if (list_empty(&message->transfers)) return -EINVAL; if (!message->complete) Loading Loading @@ -1679,9 +1672,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) if (xfer->rx_buf && !xfer->rx_nbits) xfer->rx_nbits = SPI_NBITS_SINGLE; /* check transfer tx/rx_nbits: * 1. keep the value is not out of single, dual and quad * 2. keep tx/rx_nbits is contained by mode in spi_device * 3. if SPI_3WIRE, tx/rx_nbits should be in single * 1. check the value matches one of single, dual and quad * 2. check tx/rx_nbits match the mode in spi_device */ if (xfer->tx_buf) { if (xfer->tx_nbits != SPI_NBITS_SINGLE && Loading @@ -1694,9 +1686,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) if ((xfer->tx_nbits == SPI_NBITS_QUAD) && !(spi->mode & SPI_TX_QUAD)) return -EINVAL; if ((spi->mode & SPI_3WIRE) && (xfer->tx_nbits != SPI_NBITS_SINGLE)) return -EINVAL; } /* check transfer rx_nbits */ if (xfer->rx_buf) { Loading @@ -1710,13 +1699,22 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) if ((xfer->rx_nbits == SPI_NBITS_QUAD) && !(spi->mode & SPI_RX_QUAD)) return -EINVAL; if ((spi->mode & SPI_3WIRE) && (xfer->rx_nbits != SPI_NBITS_SINGLE)) return -EINVAL; } } 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); } Loading Loading @@ -1755,6 +1753,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message) int ret; unsigned long flags; ret = __spi_validate(spi, message); if (ret != 0) return ret; spin_lock_irqsave(&master->bus_lock_spinlock, flags); if (master->bus_lock_flag) Loading Loading @@ -1803,6 +1805,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) int ret; unsigned long flags; ret = __spi_validate(spi, message); if (ret != 0) return ret; spin_lock_irqsave(&master->bus_lock_spinlock, flags); ret = __spi_async(spi, message); Loading
include/linux/spi/spi.h +4 −4 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ struct spi_device { struct spi_master *master; u32 max_speed_hz; u8 chip_select; u8 bits_per_word; u16 mode; #define SPI_CPHA 0x01 /* clock phase */ #define SPI_CPOL 0x02 /* clock polarity */ Loading @@ -92,7 +93,6 @@ struct spi_device { #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */ #define SPI_RX_DUAL 0x400 /* receive with 2 wires */ #define SPI_RX_QUAD 0x800 /* receive with 4 wires */ u8 bits_per_word; int irq; void *controller_state; void *controller_data; Loading Loading @@ -578,8 +578,8 @@ struct spi_transfer { dma_addr_t rx_dma; unsigned cs_change:1; u8 tx_nbits; u8 rx_nbits; unsigned tx_nbits:3; unsigned rx_nbits:3; #define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */ #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */ #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */ Loading Loading @@ -849,7 +849,7 @@ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd) ssize_t status; 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 (status < 0) ? status : result; Loading