spi: bcm53xx: add spi_flash_read callback for MMIO-based reads
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>
This commit is contained in:
parent
f55532a0c0
commit
a7b221d8f0
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user