 74d00a8c38
			
		
	
	74d00a8c38
	
	
	
		
			
			* properly format/comment all patches * merge debloat patches * merge Kconfig patches * merge swconfig patches * merge hotplug patches * drop 200-fix_localversion.patch - upstream * drop 222-arm_zimage_none.patch - unused * drop 252-mv_cesa_depends.patch - no longer required * drop 410-mtd-move-forward-declaration-of-struct-mtd_info.patch - unused * drop 661-fq_codel_keep_dropped_stats.patch - outdated * drop 702-phy_add_aneg_done_function.patch - upstream * drop 840-rtc7301.patch - unused * drop 841-rtc_pt7c4338.patch - upstream * drop 921-use_preinit_as_init.patch - unused * drop spio-gpio-old and gpio-mmc - unused Signed-off-by: John Crispin <john@phrozen.org>
		
			
				
	
	
		
			180 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 556351f14e74db4cd3ddde386457edce7bf0b27f Mon Sep 17 00:00:00 2001
 | |
| From: Vignesh R <vigneshr@ti.com>
 | |
| Date: Fri, 11 Dec 2015 09:39:56 +0530
 | |
| Subject: [PATCH] spi: introduce accelerated read support for spi flash devices
 | |
| 
 | |
| In addition to providing direct access to SPI bus, some spi controller
 | |
| hardwares (like ti-qspi) provide special port (like memory mapped port)
 | |
| that are optimized to improve SPI flash read performance.
 | |
| This means the controller can automatically send the SPI signals
 | |
| required to read data from the SPI flash device.
 | |
| For this, SPI controller needs to know flash specific information like
 | |
| read command to use, dummy bytes and address width.
 | |
| 
 | |
| Introduce spi_flash_read() interface to support accelerated read
 | |
| over SPI flash devices. SPI master drivers can implement this callback to
 | |
| support interfaces such as memory mapped read etc. m25p80 flash driver
 | |
| and other flash drivers can call this make use of such interfaces. The
 | |
| interface should only be used with SPI flashes and cannot be used with
 | |
| other SPI devices.
 | |
| 
 | |
| Signed-off-by: Vignesh R <vigneshr@ti.com>
 | |
| Signed-off-by: Mark Brown <broonie@kernel.org>
 | |
| ---
 | |
| 
 | |
| --- a/drivers/spi/spi.c
 | |
| +++ b/drivers/spi/spi.c
 | |
| @@ -1135,6 +1135,7 @@ static void __spi_pump_messages(struct s
 | |
|  		}
 | |
|  	}
 | |
|  
 | |
| +	mutex_lock(&master->bus_lock_mutex);
 | |
|  	trace_spi_message_start(master->cur_msg);
 | |
|  
 | |
|  	if (master->prepare_message) {
 | |
| @@ -1144,6 +1145,7 @@ static void __spi_pump_messages(struct s
 | |
|  				"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;
 | |
| @@ -1153,6 +1155,7 @@ static void __spi_pump_messages(struct s
 | |
|  	if (ret) {
 | |
|  		master->cur_msg->status = ret;
 | |
|  		spi_finalize_current_message(master);
 | |
| +		mutex_unlock(&master->bus_lock_mutex);
 | |
|  		return;
 | |
|  	}
 | |
|  
 | |
| @@ -1160,8 +1163,10 @@ static void __spi_pump_messages(struct s
 | |
|  	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);
 | |
|  }
 | |
|  
 | |
|  /**
 | |
| @@ -2329,6 +2334,46 @@ int spi_async_locked(struct spi_device *
 | |
|  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
 | |
| --- a/include/linux/spi/spi.h
 | |
| +++ b/include/linux/spi/spi.h
 | |
| @@ -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.
 | |
| @@ -361,6 +362,8 @@ static inline void spi_unregister_driver
 | |
|   * @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).
 | |
| @@ -507,6 +510,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
 | |
| @@ -999,6 +1004,42 @@ static inline ssize_t spi_w8r16be(struct
 | |
|  	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);
 | |
| +
 | |
|  /*---------------------------------------------------------------------------*/
 | |
|  
 | |
|  /*
 |