* [PATCH for-next] spi: bcm53xx: add spi_flash_read callback for MMIO-based reads
@ 2016-04-18 11:10 Rafał Miłecki
2016-04-18 11:24 ` Mark Brown
[not found] ` <1460977843-9426-1-git-send-email-zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
0 siblings, 2 replies; 6+ messages in thread
From: Rafał Miłecki @ 2016-04-18 11:10 UTC (permalink / raw)
To: Mark Brown; +Cc: Rafał Miłecki, open list:SPI SUBSYSTEM, open list
This implements more efficient reads of SPI-attached flash content.
Signed-off-by: Rafał Miłecki <zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
drivers/spi/spi-bcm53xx.c | 73 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/spi-bcm53xx.c b/drivers/spi/spi-bcm53xx.c
index cc3f938..3bc7b77 100644
--- a/drivers/spi/spi-bcm53xx.c
+++ b/drivers/spi/spi-bcm53xx.c
@@ -17,8 +17,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 +34,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 +222,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 +254,19 @@ 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;
+
+ bcm53xxspi_enable_bspi(b53spi);
+ memcpy_fromio(msg->buf, b53spi->mmio_base + msg->from, msg->len);
+ msg->retlen = msg->len;
+
+ return ret;
+}
+
/**************************************************
* BCMA
**************************************************/
@@ -222,6 +283,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 +293,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 +301,18 @@ 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], SZ_32M);
+ 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);
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH for-next] spi: bcm53xx: add spi_flash_read callback for MMIO-based reads
2016-04-18 11:10 [PATCH for-next] spi: bcm53xx: add spi_flash_read callback for MMIO-based reads Rafał Miłecki
@ 2016-04-18 11:24 ` Mark Brown
[not found] ` <20160418112457.GU3217-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
[not found] ` <1460977843-9426-1-git-send-email-zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
1 sibling, 1 reply; 6+ messages in thread
From: Mark Brown @ 2016-04-18 11:24 UTC (permalink / raw)
To: Rafał Miłecki; +Cc: open list:SPI SUBSYSTEM, open list
[-- Attachment #1: Type: text/plain, Size: 727 bytes --]
On Mon, Apr 18, 2016 at 01:10:43PM +0200, Rafał Miłecki wrote:
> +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;
> +
> + bcm53xxspi_enable_bspi(b53spi);
> + memcpy_fromio(msg->buf, b53spi->mmio_base + msg->from, msg->len);
> + msg->retlen = msg->len;
There's no bounds check here but...
> + if (core->addr_s[0])
> + b53spi->mmio_base = devm_ioremap(dev, core->addr_s[0], SZ_32M);
...we only mapped 32M here. What if something tries to do a larger
read? It's also a bit surprising that we're mapping a specific size
here rather than the entire resource.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <1460977843-9426-1-git-send-email-zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>]
* [PATCH V2 for-next] spi: bcm53xx: add spi_flash_read callback for MMIO-based reads
[not found] ` <1460977843-9426-1-git-send-email-zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2016-04-18 12:39 ` Rafał Miłecki
0 siblings, 0 replies; 6+ messages in thread
From: Rafał Miłecki @ 2016-04-18 12:39 UTC (permalink / raw)
To: Mark Brown; +Cc: Rafał Miłecki, open list:SPI SUBSYSTEM, open list
This implements more efficient reads of SPI-attached flash content.
Signed-off-by: Rafał Miłecki <zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
V2: Add BCM53XXSPI_FLASH_WINDOW and check it in bcm53xxspi_flash_read.
---
drivers/spi/spi-bcm53xx.c | 78 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 76 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/spi-bcm53xx.c b/drivers/spi/spi-bcm53xx.c
index cc3f938..afb5169 100644
--- 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);
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2016-04-18 13:48 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-04-18 11:10 [PATCH for-next] spi: bcm53xx: add spi_flash_read callback for MMIO-based reads Rafał Miłecki
2016-04-18 11:24 ` Mark Brown
[not found] ` <20160418112457.GU3217-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2016-04-18 11:38 ` Rafał Miłecki
[not found] ` <CACna6rzQfX7SxDoL-CTQp3_Ms5_K54pEa8uaUAiTPjR-un=VOg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-04-18 11:57 ` Mark Brown
2016-04-18 13:48 ` Vignesh R
[not found] ` <1460977843-9426-1-git-send-email-zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-04-18 12:39 ` [PATCH V2 " Rafał Miłecki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).