Merge remote-tracking branch 'spi/topic/core' into spi-next
This commit is contained in:
commit
df9633a780
|
@ -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);
|
trace_spi_message_start(master->cur_msg);
|
||||||
|
|
||||||
if (master->prepare_message) {
|
if (master->prepare_message) {
|
||||||
|
@ -1161,6 +1162,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
|
||||||
"failed to prepare message: %d\n", ret);
|
"failed to prepare message: %d\n", ret);
|
||||||
master->cur_msg->status = ret;
|
master->cur_msg->status = ret;
|
||||||
spi_finalize_current_message(master);
|
spi_finalize_current_message(master);
|
||||||
|
mutex_unlock(&master->bus_lock_mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
master->cur_msg_prepared = true;
|
master->cur_msg_prepared = true;
|
||||||
|
@ -1170,6 +1172,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
master->cur_msg->status = ret;
|
master->cur_msg->status = ret;
|
||||||
spi_finalize_current_message(master);
|
spi_finalize_current_message(master);
|
||||||
|
mutex_unlock(&master->bus_lock_mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1177,8 +1180,13 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&master->dev,
|
dev_err(&master->dev,
|
||||||
"failed to transfer one message from queue\n");
|
"failed to transfer one message from queue\n");
|
||||||
|
mutex_unlock(&master->bus_lock_mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&master->bus_lock_mutex);
|
||||||
|
|
||||||
|
/* Prod the scheduler in case transfer_one() was busy waiting */
|
||||||
|
cond_resched();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2351,6 +2359,46 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message)
|
||||||
EXPORT_SYMBOL_GPL(spi_async_locked);
|
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
|
/* Utility methods for SPI master protocol drivers, layered on
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
struct dma_chan;
|
struct dma_chan;
|
||||||
struct spi_master;
|
struct spi_master;
|
||||||
struct spi_transfer;
|
struct spi_transfer;
|
||||||
|
struct spi_flash_read_message;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* INTERFACES between SPI master-side drivers and SPI infrastructure.
|
* INTERFACES between SPI master-side drivers and SPI infrastructure.
|
||||||
|
@ -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
|
* @handle_err: the subsystem calls the driver to handle an error that occurs
|
||||||
* in the generic implementation of transfer_one_message().
|
* in the generic implementation of transfer_one_message().
|
||||||
* @unprepare_message: undo any work done by prepare_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
|
* @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
|
* number. Any individual value may be -ENOENT for CS lines that
|
||||||
* are not GPIOs (driven by the SPI controller itself).
|
* are not GPIOs (driven by the SPI controller itself).
|
||||||
|
@ -513,6 +516,8 @@ struct spi_master {
|
||||||
struct spi_message *message);
|
struct spi_message *message);
|
||||||
int (*unprepare_message)(struct spi_master *master,
|
int (*unprepare_message)(struct spi_master *master,
|
||||||
struct spi_message *message);
|
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
|
* These hooks are for drivers that use a generic implementation
|
||||||
|
@ -1019,6 +1024,42 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd)
|
||||||
return be16_to_cpu(result);
|
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…
Reference in New Issue