diff options
Diffstat (limited to 'drivers/spi/spi.c')
| -rw-r--r-- | drivers/spi/spi.c | 45 | 
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 47eff8012a77..dcc6f6e92668 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -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) { @@ -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; @@ -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;  	} @@ -1177,8 +1180,10 @@ 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);  }  /** @@ -2351,6 +2356,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  | 
