diff options
Diffstat (limited to 'target/linux/generic/patches-4.4/081-spi-bcm53xx-add-spi_flash_read-callback-for-MMIO-bas.patch')
-rw-r--r-- | target/linux/generic/patches-4.4/081-spi-bcm53xx-add-spi_flash_read-callback-for-MMIO-bas.patch | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/target/linux/generic/patches-4.4/081-spi-bcm53xx-add-spi_flash_read-callback-for-MMIO-bas.patch b/target/linux/generic/patches-4.4/081-spi-bcm53xx-add-spi_flash_read-callback-for-MMIO-bas.patch new file mode 100644 index 0000000..5f131e7 --- /dev/null +++ b/target/linux/generic/patches-4.4/081-spi-bcm53xx-add-spi_flash_read-callback-for-MMIO-bas.patch @@ -0,0 +1,157 @@ +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(struct bcm53xxspi *b53spi, u16 offset, + 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(struct spi_master *master, + 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(struct spi_master *master, + 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_bcma_tbl); + + 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 bcma_device *core) + 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 bcma_device *core) + 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); |