mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 05:54:26 -04:00 
			
		
		
		
	This flag was added to 4.9 with upstream commit 76a4707de5e18dc32d9cb4e990686140c5664a15. Signed-off-by: Victor Shyba <victor1984@riseup.net> [refresh and adjust platform patches, fix commit message] Signed-off-by: Mathias Kresin <dev@kresin.me>
		
			
				
	
	
		
			106 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 56bd0e13d8bc3b4486251b10ac9d2ba7434c21ee Mon Sep 17 00:00:00 2001
 | |
| From: Brian Norris <computersforpeace@gmail.com>
 | |
| Date: Tue, 10 Nov 2015 12:15:27 -0800
 | |
| Subject: [PATCH 081/113] mtd: spi-nor: provide default erase_sector
 | |
|  implementation
 | |
| 
 | |
| Some spi-nor drivers perform sector erase by duplicating their
 | |
| write_reg() command. Let's not require that the driver fill this out,
 | |
| and provide a default instead.
 | |
| 
 | |
| Tested on m25p80.c and Medatek's MT8173 SPI NOR flash driver.
 | |
| 
 | |
| Signed-off-by: Brian Norris <computersforpeace@gmail.com>
 | |
| ---
 | |
|  drivers/mtd/spi-nor/spi-nor.c |   37 +++++++++++++++++++++++++++++++++----
 | |
|  include/linux/mtd/spi-nor.h   |    3 ++-
 | |
|  2 files changed, 35 insertions(+), 5 deletions(-)
 | |
| 
 | |
| --- a/drivers/mtd/spi-nor/spi-nor.c
 | |
| +++ b/drivers/mtd/spi-nor/spi-nor.c
 | |
| @@ -38,6 +38,7 @@
 | |
|  #define CHIP_ERASE_2MB_READY_WAIT_JIFFIES	(40UL * HZ)
 | |
|  
 | |
|  #define SPI_NOR_MAX_ID_LEN	6
 | |
| +#define SPI_NOR_MAX_ADDR_WIDTH	4
 | |
|  
 | |
|  struct flash_info {
 | |
|  	char		*name;
 | |
| @@ -314,6 +315,29 @@ static void spi_nor_unlock_and_unprep(st
 | |
|  }
 | |
|  
 | |
|  /*
 | |
| + * Initiate the erasure of a single sector
 | |
| + */
 | |
| +static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
 | |
| +{
 | |
| +	u8 buf[SPI_NOR_MAX_ADDR_WIDTH];
 | |
| +	int i;
 | |
| +
 | |
| +	if (nor->erase)
 | |
| +		return nor->erase(nor, addr);
 | |
| +
 | |
| +	/*
 | |
| +	 * Default implementation, if driver doesn't have a specialized HW
 | |
| +	 * control
 | |
| +	 */
 | |
| +	for (i = nor->addr_width - 1; i >= 0; i--) {
 | |
| +		buf[i] = addr & 0xff;
 | |
| +		addr >>= 8;
 | |
| +	}
 | |
| +
 | |
| +	return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width);
 | |
| +}
 | |
| +
 | |
| +/*
 | |
|   * Erase an address range on the nor chip.  The address range may extend
 | |
|   * one or more erase sectors.  Return an error is there is a problem erasing.
 | |
|   */
 | |
| @@ -372,10 +396,9 @@ static int spi_nor_erase(struct mtd_info
 | |
|  		while (len) {
 | |
|  			write_enable(nor);
 | |
|  
 | |
| -			if (nor->erase(nor, addr)) {
 | |
| -				ret = -EIO;
 | |
| +			ret = spi_nor_erase_sector(nor, addr);
 | |
| +			if (ret)
 | |
|  				goto erase_err;
 | |
| -			}
 | |
|  
 | |
|  			addr += mtd->erasesize;
 | |
|  			len -= mtd->erasesize;
 | |
| @@ -1100,7 +1123,7 @@ static int set_quad_mode(struct spi_nor
 | |
|  static int spi_nor_check(struct spi_nor *nor)
 | |
|  {
 | |
|  	if (!nor->dev || !nor->read || !nor->write ||
 | |
| -		!nor->read_reg || !nor->write_reg || !nor->erase) {
 | |
| +		!nor->read_reg || !nor->write_reg) {
 | |
|  		pr_err("spi-nor: please fill all the necessary fields!\n");
 | |
|  		return -EINVAL;
 | |
|  	}
 | |
| @@ -1303,6 +1326,12 @@ int spi_nor_scan(struct spi_nor *nor, co
 | |
|  		nor->addr_width = 3;
 | |
|  	}
 | |
|  
 | |
| +	if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) {
 | |
| +		dev_err(dev, "address width is too large: %u\n",
 | |
| +			nor->addr_width);
 | |
| +		return -EINVAL;
 | |
| +	}
 | |
| +
 | |
|  	nor->read_dummy = spi_nor_read_dummy_cycles(nor);
 | |
|  
 | |
|  	dev_info(dev, "%s (%lld Kbytes)\n", info->name,
 | |
| --- a/include/linux/mtd/spi-nor.h
 | |
| +++ b/include/linux/mtd/spi-nor.h
 | |
| @@ -142,7 +142,8 @@ enum spi_nor_option_flags {
 | |
|   * @read:		[DRIVER-SPECIFIC] read data from the SPI NOR
 | |
|   * @write:		[DRIVER-SPECIFIC] write data to the SPI NOR
 | |
|   * @erase:		[DRIVER-SPECIFIC] erase a sector of the SPI NOR
 | |
| - *			at the offset @offs
 | |
| + *			at the offset @offs; if not provided by the driver,
 | |
| + *			spi-nor will send the erase opcode via write_reg()
 | |
|   * @flash_lock:		[FLASH-SPECIFIC] lock a region of the SPI NOR
 | |
|   * @flash_unlock:	[FLASH-SPECIFIC] unlock a region of the SPI NOR
 | |
|   * @flash_is_locked:	[FLASH-SPECIFIC] check if a region of the SPI NOR is
 |