mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			113 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| --- a/drivers/mtd/devices/m25p80.c
 | |
| +++ b/drivers/mtd/devices/m25p80.c
 | |
| @@ -100,6 +100,7 @@ struct m25p {
 | |
|  	u16			addr_width;
 | |
|  	u8			erase_opcode;
 | |
|  	u8			*command;
 | |
| +	size_t			max_read_len;
 | |
|  };
 | |
|  
 | |
|  static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
 | |
| @@ -352,6 +353,7 @@ static int m25p80_read(struct mtd_info *
 | |
|  	struct m25p *flash = mtd_to_m25p(mtd);
 | |
|  	struct spi_transfer t[2];
 | |
|  	struct spi_message m;
 | |
| +	loff_t ofs;
 | |
|  
 | |
|  	pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
 | |
|  			__func__, (u32)from, len);
 | |
| @@ -374,8 +376,6 @@ static int m25p80_read(struct mtd_info *
 | |
|  	t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
 | |
|  	spi_message_add_tail(&t[0], &m);
 | |
|  
 | |
| -	t[1].rx_buf = buf;
 | |
| -	t[1].len = len;
 | |
|  	spi_message_add_tail(&t[1], &m);
 | |
|  
 | |
|  	/* Byte count starts at zero. */
 | |
| @@ -383,13 +383,6 @@ static int m25p80_read(struct mtd_info *
 | |
|  
 | |
|  	mutex_lock(&flash->lock);
 | |
|  
 | |
| -	/* Wait till previous write/erase is done. */
 | |
| -	if (wait_till_ready(flash)) {
 | |
| -		/* REVISIT status return?? */
 | |
| -		mutex_unlock(&flash->lock);
 | |
| -		return 1;
 | |
| -	}
 | |
| -
 | |
|  	/* FIXME switch to OPCODE_FAST_READ.  It's required for higher
 | |
|  	 * clocks; and at this writing, every chip this driver handles
 | |
|  	 * supports that opcode.
 | |
| @@ -397,11 +390,44 @@ static int m25p80_read(struct mtd_info *
 | |
|  
 | |
|  	/* Set up the write data buffer. */
 | |
|  	flash->command[0] = OPCODE_READ;
 | |
| -	m25p_addr2cmd(flash, from, flash->command);
 | |
|  
 | |
| -	spi_sync(flash->spi, &m);
 | |
| +	ofs = 0;
 | |
| +	while (len) {
 | |
| +		size_t readlen;
 | |
| +		size_t done;
 | |
| +		int ret;
 | |
| +
 | |
| +		ret = wait_till_ready(flash);
 | |
| +		if (ret) {
 | |
| +			mutex_unlock(&flash->lock);
 | |
| +			return 1;
 | |
| +		}
 | |
| +
 | |
| +		if (flash->max_read_len > 0 &&
 | |
| +		    flash->max_read_len < len)
 | |
| +			readlen = flash->max_read_len;
 | |
| +		else
 | |
| +			readlen = len;
 | |
| +
 | |
| +		t[1].rx_buf = buf + ofs;
 | |
| +		t[1].len = readlen;
 | |
| +
 | |
| +		m25p_addr2cmd(flash, from + ofs, flash->command);
 | |
| +
 | |
| +		spi_sync(flash->spi, &m);
 | |
|  
 | |
| -	*retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE;
 | |
| +		done = m.actual_length - m25p_cmdsz(flash) -
 | |
| +		       FAST_READ_DUMMY_BYTE;
 | |
| +		if (done != readlen) {
 | |
| +			mutex_unlock(&flash->lock);
 | |
| +			return 1;
 | |
| +		}
 | |
| +
 | |
| +		ofs += done;
 | |
| +		len -= done;
 | |
| +	}
 | |
| +
 | |
| +	*retlen = ofs;
 | |
|  
 | |
|  	mutex_unlock(&flash->lock);
 | |
|  
 | |
| @@ -924,6 +950,12 @@ static int __devinit m25p_probe(struct s
 | |
|  	flash->mtd.erase = m25p80_erase;
 | |
|  	flash->mtd.read = m25p80_read;
 | |
|  
 | |
| +	if (data && data->max_read_len) {
 | |
| +		flash->max_read_len = data->max_read_len;
 | |
| +		dev_warn(&spi->dev, "max_read_len set to %d bytes\n",
 | |
| +			flash->max_read_len);
 | |
| +	}
 | |
| +
 | |
|  	/* sst flash chips use AAI word program */
 | |
|  	if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST)
 | |
|  		flash->mtd.write = sst_write;
 | |
| --- a/include/linux/spi/flash.h
 | |
| +++ b/include/linux/spi/flash.h
 | |
| @@ -25,6 +25,7 @@ struct flash_platform_data {
 | |
|  
 | |
|  	char		*type;
 | |
|  
 | |
| +	size_t		max_read_len;
 | |
|  	/* we'll likely add more ... use JEDEC IDs, etc */
 | |
|  };
 | |
|  
 |