aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/patches-4.4/081-spi-bcm53xx-add-spi_flash_read-callback-for-MMIO-bas.patch
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2016-04-26 09:23:12 +0000
committerRafał Miłecki <zajec5@gmail.com>2016-04-26 09:23:12 +0000
commit08fe019a4c3dee78a885f0d92287c94e8ec9f6a1 (patch)
treea428bde19f647a9ce72ca00249dbbda1bb1b6103 /target/linux/generic/patches-4.4/081-spi-bcm53xx-add-spi_flash_read-callback-for-MMIO-bas.patch
parent3f91c5fd81050fddcb205762afd9635ae7d09953 (diff)
downloadmaster-187ad058-08fe019a4c3dee78a885f0d92287c94e8ec9f6a1.tar.gz
master-187ad058-08fe019a4c3dee78a885f0d92287c94e8ec9f6a1.tar.bz2
master-187ad058-08fe019a4c3dee78a885f0d92287c94e8ec9f6a1.zip
kernel: backport support for accelerated SPI flash read
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@49233 3c298f89-4303-0410-b956-a3cf2f4a3e73
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.patch157
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 0000000000..5f131e76d3
--- /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);