mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 14:04:26 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			158 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From a7b221d8f0d75511c5f959584712a5dd35f88a86 Mon Sep 17 00:00:00 2001
 | |
| From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
 | |
| Date: Mon, 18 Apr 2016 14:39:30 +0200
 | |
| Subject: [PATCH] spi: bcm53xx: add spi_flash_read callback for MMIO-based
 | |
|  reads
 | |
| MIME-Version: 1.0
 | |
| Content-Type: text/plain; charset=UTF-8
 | |
| Content-Transfer-Encoding: 8bit
 | |
| 
 | |
| This implements more efficient reads of SPI-attached flash content.
 | |
| 
 | |
| Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
 | |
| Signed-off-by: Mark Brown <broonie@kernel.org>
 | |
| ---
 | |
| 
 | |
| --- a/drivers/spi/spi-bcm53xx.c
 | |
| +++ b/drivers/spi/spi-bcm53xx.c
 | |
| @@ -10,6 +10,7 @@
 | |
|  #include "spi-bcm53xx.h"
 | |
|  
 | |
|  #define BCM53XXSPI_MAX_SPI_BAUD	13500000	/* 216 MHz? */
 | |
| +#define BCM53XXSPI_FLASH_WINDOW	SZ_32M
 | |
|  
 | |
|  /* The longest observed required wait was 19 ms */
 | |
|  #define BCM53XXSPI_SPE_TIMEOUT_MS	80
 | |
| @@ -17,8 +18,10 @@
 | |
|  struct bcm53xxspi {
 | |
|  	struct bcma_device *core;
 | |
|  	struct spi_master *master;
 | |
| +	void __iomem *mmio_base;
 | |
|  
 | |
|  	size_t read_offset;
 | |
| +	bool bspi;				/* Boot SPI mode with memory mapping */
 | |
|  };
 | |
|  
 | |
|  static inline u32 bcm53xxspi_read(struct bcm53xxspi *b53spi, u16 offset)
 | |
| @@ -32,6 +35,50 @@ static inline void bcm53xxspi_write(stru
 | |
|  	bcma_write32(b53spi->core, offset, value);
 | |
|  }
 | |
|  
 | |
| +static void bcm53xxspi_disable_bspi(struct bcm53xxspi *b53spi)
 | |
| +{
 | |
| +	struct device *dev = &b53spi->core->dev;
 | |
| +	unsigned long deadline;
 | |
| +	u32 tmp;
 | |
| +
 | |
| +	if (!b53spi->bspi)
 | |
| +		return;
 | |
| +
 | |
| +	tmp = bcm53xxspi_read(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL);
 | |
| +	if (tmp & 0x1)
 | |
| +		return;
 | |
| +
 | |
| +	deadline = jiffies + usecs_to_jiffies(200);
 | |
| +	do {
 | |
| +		tmp = bcm53xxspi_read(b53spi, B53SPI_BSPI_BUSY_STATUS);
 | |
| +		if (!(tmp & 0x1)) {
 | |
| +			bcm53xxspi_write(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL,
 | |
| +					 0x1);
 | |
| +			ndelay(200);
 | |
| +			b53spi->bspi = false;
 | |
| +			return;
 | |
| +		}
 | |
| +		udelay(1);
 | |
| +	} while (!time_after_eq(jiffies, deadline));
 | |
| +
 | |
| +	dev_warn(dev, "Timeout disabling BSPI\n");
 | |
| +}
 | |
| +
 | |
| +static void bcm53xxspi_enable_bspi(struct bcm53xxspi *b53spi)
 | |
| +{
 | |
| +	u32 tmp;
 | |
| +
 | |
| +	if (b53spi->bspi)
 | |
| +		return;
 | |
| +
 | |
| +	tmp = bcm53xxspi_read(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL);
 | |
| +	if (!(tmp & 0x1))
 | |
| +		return;
 | |
| +
 | |
| +	bcm53xxspi_write(b53spi, B53SPI_BSPI_MAST_N_BOOT_CTRL, 0x0);
 | |
| +	b53spi->bspi = true;
 | |
| +}
 | |
| +
 | |
|  static inline unsigned int bcm53xxspi_calc_timeout(size_t len)
 | |
|  {
 | |
|  	/* Do some magic calculation based on length and buad. Add 10% and 1. */
 | |
| @@ -176,6 +223,8 @@ static int bcm53xxspi_transfer_one(struc
 | |
|  	u8 *buf;
 | |
|  	size_t left;
 | |
|  
 | |
| +	bcm53xxspi_disable_bspi(b53spi);
 | |
| +
 | |
|  	if (t->tx_buf) {
 | |
|  		buf = (u8 *)t->tx_buf;
 | |
|  		left = t->len;
 | |
| @@ -206,6 +255,22 @@ static int bcm53xxspi_transfer_one(struc
 | |
|  	return 0;
 | |
|  }
 | |
|  
 | |
| +static int bcm53xxspi_flash_read(struct spi_device *spi,
 | |
| +				 struct spi_flash_read_message *msg)
 | |
| +{
 | |
| +	struct bcm53xxspi *b53spi = spi_master_get_devdata(spi->master);
 | |
| +	int ret = 0;
 | |
| +
 | |
| +	if (msg->from + msg->len > BCM53XXSPI_FLASH_WINDOW)
 | |
| +		return -EINVAL;
 | |
| +
 | |
| +	bcm53xxspi_enable_bspi(b53spi);
 | |
| +	memcpy_fromio(msg->buf, b53spi->mmio_base + msg->from, msg->len);
 | |
| +	msg->retlen = msg->len;
 | |
| +
 | |
| +	return ret;
 | |
| +}
 | |
| +
 | |
|  /**************************************************
 | |
|   * BCMA
 | |
|   **************************************************/
 | |
| @@ -222,6 +287,7 @@ MODULE_DEVICE_TABLE(bcma, bcm53xxspi_bcm
 | |
|  
 | |
|  static int bcm53xxspi_bcma_probe(struct bcma_device *core)
 | |
|  {
 | |
| +	struct device *dev = &core->dev;
 | |
|  	struct bcm53xxspi *b53spi;
 | |
|  	struct spi_master *master;
 | |
|  	int err;
 | |
| @@ -231,7 +297,7 @@ static int bcm53xxspi_bcma_probe(struct
 | |
|  		return -ENOTSUPP;
 | |
|  	}
 | |
|  
 | |
| -	master = spi_alloc_master(&core->dev, sizeof(*b53spi));
 | |
| +	master = spi_alloc_master(dev, sizeof(*b53spi));
 | |
|  	if (!master)
 | |
|  		return -ENOMEM;
 | |
|  
 | |
| @@ -239,11 +305,19 @@ static int bcm53xxspi_bcma_probe(struct
 | |
|  	b53spi->master = master;
 | |
|  	b53spi->core = core;
 | |
|  
 | |
| +	if (core->addr_s[0])
 | |
| +		b53spi->mmio_base = devm_ioremap(dev, core->addr_s[0],
 | |
| +						 BCM53XXSPI_FLASH_WINDOW);
 | |
| +	b53spi->bspi = true;
 | |
| +	bcm53xxspi_disable_bspi(b53spi);
 | |
| +
 | |
|  	master->transfer_one = bcm53xxspi_transfer_one;
 | |
| +	if (b53spi->mmio_base)
 | |
| +		master->spi_flash_read = bcm53xxspi_flash_read;
 | |
|  
 | |
|  	bcma_set_drvdata(core, b53spi);
 | |
|  
 | |
| -	err = devm_spi_register_master(&core->dev, master);
 | |
| +	err = devm_spi_register_master(dev, master);
 | |
|  	if (err) {
 | |
|  		spi_master_put(master);
 | |
|  		bcma_set_drvdata(core, NULL);
 |