Loading drivers/spi/spi.c +48 −0 Original line number Diff line number Diff line Loading @@ -1152,6 +1152,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) } } mutex_lock(&master->bus_lock_mutex); trace_spi_message_start(master->cur_msg); if (master->prepare_message) { Loading @@ -1161,6 +1162,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) "failed to prepare message: %d\n", ret); master->cur_msg->status = ret; spi_finalize_current_message(master); mutex_unlock(&master->bus_lock_mutex); return; } master->cur_msg_prepared = true; Loading @@ -1170,6 +1172,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { master->cur_msg->status = ret; spi_finalize_current_message(master); mutex_unlock(&master->bus_lock_mutex); return; } Loading @@ -1177,8 +1180,13 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { dev_err(&master->dev, "failed to transfer one message from queue\n"); mutex_unlock(&master->bus_lock_mutex); return; } mutex_unlock(&master->bus_lock_mutex); /* Prod the scheduler in case transfer_one() was busy waiting */ cond_resched(); } /** Loading Loading @@ -2351,6 +2359,46 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) EXPORT_SYMBOL_GPL(spi_async_locked); int spi_flash_read(struct spi_device *spi, struct spi_flash_read_message *msg) { struct spi_master *master = spi->master; int ret; if ((msg->opcode_nbits == SPI_NBITS_DUAL || msg->addr_nbits == SPI_NBITS_DUAL) && !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD))) return -EINVAL; if ((msg->opcode_nbits == SPI_NBITS_QUAD || msg->addr_nbits == SPI_NBITS_QUAD) && !(spi->mode & SPI_TX_QUAD)) return -EINVAL; if (msg->data_nbits == SPI_NBITS_DUAL && !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD))) return -EINVAL; if (msg->data_nbits == SPI_NBITS_QUAD && !(spi->mode & SPI_RX_QUAD)) return -EINVAL; if (master->auto_runtime_pm) { ret = pm_runtime_get_sync(master->dev.parent); if (ret < 0) { dev_err(&master->dev, "Failed to power device: %d\n", ret); return ret; } } mutex_lock(&master->bus_lock_mutex); ret = master->spi_flash_read(spi, msg); mutex_unlock(&master->bus_lock_mutex); if (master->auto_runtime_pm) pm_runtime_put(master->dev.parent); return ret; } EXPORT_SYMBOL_GPL(spi_flash_read); /*-------------------------------------------------------------------------*/ /* Utility methods for SPI master protocol drivers, layered on Loading include/linux/spi/spi.h +41 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ struct dma_chan; struct spi_master; struct spi_transfer; struct spi_flash_read_message; /* * INTERFACES between SPI master-side drivers and SPI infrastructure. Loading Loading @@ -361,6 +362,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @handle_err: the subsystem calls the driver to handle an error that occurs * in the generic implementation of transfer_one_message(). * @unprepare_message: undo any work done by prepare_message(). * @spi_flash_read: to support spi-controller hardwares that provide * accelerated interface to read from flash devices. * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * number. Any individual value may be -ENOENT for CS lines that * are not GPIOs (driven by the SPI controller itself). Loading Loading @@ -513,6 +516,8 @@ struct spi_master { struct spi_message *message); int (*unprepare_message)(struct spi_master *master, struct spi_message *message); int (*spi_flash_read)(struct spi_device *spi, struct spi_flash_read_message *msg); /* * These hooks are for drivers that use a generic implementation Loading Loading @@ -1019,6 +1024,42 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd) return be16_to_cpu(result); } /** * struct spi_flash_read_message - flash specific information for * spi-masters that provide accelerated flash read interfaces * @buf: buffer to read data * @from: offset within the flash from where data is to be read * @len: length of data to be read * @retlen: actual length of data read * @read_opcode: read_opcode to be used to communicate with flash * @addr_width: number of address bytes * @dummy_bytes: number of dummy bytes * @opcode_nbits: number of lines to send opcode * @addr_nbits: number of lines to send address * @data_nbits: number of lines for data */ struct spi_flash_read_message { void *buf; loff_t from; size_t len; size_t retlen; u8 read_opcode; u8 addr_width; u8 dummy_bytes; u8 opcode_nbits; u8 addr_nbits; u8 data_nbits; }; /* SPI core interface for flash read support */ static inline bool spi_flash_read_supported(struct spi_device *spi) { return spi->master->spi_flash_read ? true : false; } int spi_flash_read(struct spi_device *spi, struct spi_flash_read_message *msg); /*---------------------------------------------------------------------------*/ /* Loading Loading
drivers/spi/spi.c +48 −0 Original line number Diff line number Diff line Loading @@ -1152,6 +1152,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) } } mutex_lock(&master->bus_lock_mutex); trace_spi_message_start(master->cur_msg); if (master->prepare_message) { Loading @@ -1161,6 +1162,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) "failed to prepare message: %d\n", ret); master->cur_msg->status = ret; spi_finalize_current_message(master); mutex_unlock(&master->bus_lock_mutex); return; } master->cur_msg_prepared = true; Loading @@ -1170,6 +1172,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { master->cur_msg->status = ret; spi_finalize_current_message(master); mutex_unlock(&master->bus_lock_mutex); return; } Loading @@ -1177,8 +1180,13 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { dev_err(&master->dev, "failed to transfer one message from queue\n"); mutex_unlock(&master->bus_lock_mutex); return; } mutex_unlock(&master->bus_lock_mutex); /* Prod the scheduler in case transfer_one() was busy waiting */ cond_resched(); } /** Loading Loading @@ -2351,6 +2359,46 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) EXPORT_SYMBOL_GPL(spi_async_locked); int spi_flash_read(struct spi_device *spi, struct spi_flash_read_message *msg) { struct spi_master *master = spi->master; int ret; if ((msg->opcode_nbits == SPI_NBITS_DUAL || msg->addr_nbits == SPI_NBITS_DUAL) && !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD))) return -EINVAL; if ((msg->opcode_nbits == SPI_NBITS_QUAD || msg->addr_nbits == SPI_NBITS_QUAD) && !(spi->mode & SPI_TX_QUAD)) return -EINVAL; if (msg->data_nbits == SPI_NBITS_DUAL && !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD))) return -EINVAL; if (msg->data_nbits == SPI_NBITS_QUAD && !(spi->mode & SPI_RX_QUAD)) return -EINVAL; if (master->auto_runtime_pm) { ret = pm_runtime_get_sync(master->dev.parent); if (ret < 0) { dev_err(&master->dev, "Failed to power device: %d\n", ret); return ret; } } mutex_lock(&master->bus_lock_mutex); ret = master->spi_flash_read(spi, msg); mutex_unlock(&master->bus_lock_mutex); if (master->auto_runtime_pm) pm_runtime_put(master->dev.parent); return ret; } EXPORT_SYMBOL_GPL(spi_flash_read); /*-------------------------------------------------------------------------*/ /* Utility methods for SPI master protocol drivers, layered on Loading
include/linux/spi/spi.h +41 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ struct dma_chan; struct spi_master; struct spi_transfer; struct spi_flash_read_message; /* * INTERFACES between SPI master-side drivers and SPI infrastructure. Loading Loading @@ -361,6 +362,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @handle_err: the subsystem calls the driver to handle an error that occurs * in the generic implementation of transfer_one_message(). * @unprepare_message: undo any work done by prepare_message(). * @spi_flash_read: to support spi-controller hardwares that provide * accelerated interface to read from flash devices. * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * number. Any individual value may be -ENOENT for CS lines that * are not GPIOs (driven by the SPI controller itself). Loading Loading @@ -513,6 +516,8 @@ struct spi_master { struct spi_message *message); int (*unprepare_message)(struct spi_master *master, struct spi_message *message); int (*spi_flash_read)(struct spi_device *spi, struct spi_flash_read_message *msg); /* * These hooks are for drivers that use a generic implementation Loading Loading @@ -1019,6 +1024,42 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd) return be16_to_cpu(result); } /** * struct spi_flash_read_message - flash specific information for * spi-masters that provide accelerated flash read interfaces * @buf: buffer to read data * @from: offset within the flash from where data is to be read * @len: length of data to be read * @retlen: actual length of data read * @read_opcode: read_opcode to be used to communicate with flash * @addr_width: number of address bytes * @dummy_bytes: number of dummy bytes * @opcode_nbits: number of lines to send opcode * @addr_nbits: number of lines to send address * @data_nbits: number of lines for data */ struct spi_flash_read_message { void *buf; loff_t from; size_t len; size_t retlen; u8 read_opcode; u8 addr_width; u8 dummy_bytes; u8 opcode_nbits; u8 addr_nbits; u8 data_nbits; }; /* SPI core interface for flash read support */ static inline bool spi_flash_read_supported(struct spi_device *spi) { return spi->master->spi_flash_read ? true : false; } int spi_flash_read(struct spi_device *spi, struct spi_flash_read_message *msg); /*---------------------------------------------------------------------------*/ /* Loading