From: Sergei Shtylyov Subject: spi: renesas-rpc: allow reading from large flashes Signed-off-by: Sergei Shtylyov --- drivers/spi/spi-renesas-rpc.c | 26 ++++++++++++++++++++------ include/linux/mfd/renesas-rpc.h | 2 ++ 2 files changed, 22 insertions(+), 6 deletions(-) Index: renesas/drivers/spi/spi-renesas-rpc.c =================================================================== --- renesas.orig/drivers/spi/spi-renesas-rpc.c +++ renesas/drivers/spi/spi-renesas-rpc.c @@ -264,14 +264,12 @@ static ssize_t rpc_spi_mem_dirmap_read(s { struct rpc_spi *rpc = spi_controller_get_devdata(desc->mem->spi->controller); + size_t _len = len; int ret; if (offs + desc->info.offset + len > U32_MAX) return -EINVAL; - if (len > 0x4000000) - len = 0x4000000; - ret = rpc_spi_set_freq(rpc, desc->mem->spi->max_speed_hz); if (ret) return ret; @@ -284,15 +282,31 @@ static ssize_t rpc_spi_mem_dirmap_read(s RPC_DRCR_RBE); regmap_write(rpc->regmap, RPC_DRCMR, rpc->cmd); - regmap_write(rpc->regmap, RPC_DREAR, RPC_DREAR_EAC(1)); regmap_write(rpc->regmap, RPC_DROPR, 0); regmap_write(rpc->regmap, RPC_DRENR, rpc->smenr); regmap_write(rpc->regmap, RPC_DRDMCR, rpc->dummy); regmap_write(rpc->regmap, RPC_DRDRENR, 0); - memcpy_fromio(buf, rpc->dirmap + desc->info.offset + offs, len); + while (len) { + loff_t from = offs & (RPC_DIRMAP_SIZE - 1); + size_t size = RPC_DIRMAP_SIZE - from; + u32 val = RPC_DREAR_EAC(1); + + if (rpc->smenr & RPC_DRENR_ADE(8)) + val |= RPC_DREAR_EAV(offs >> 25); + regmap_write(rpc->regmap, RPC_DREAR, val); + + if (size > len) + size = len; + + memcpy_fromio(buf, rpc->dirmap + desc->info.offset + from, + size); + buf += size; + offs += size; + len -= size; + } - return len; + return _len; } static ssize_t rpc_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc, Index: renesas/include/linux/mfd/renesas-rpc.h =================================================================== --- renesas.orig/include/linux/mfd/renesas-rpc.h +++ renesas/include/linux/mfd/renesas-rpc.h @@ -57,6 +57,7 @@ #define RPC_DRCMR_OCMD(c) (((c) & 0xFF) << 0) #define RPC_DREAR 0x0014 // R/W +#define RPC_DREAR_EAV(v) (((v) & 0xff) << 16) #define RPC_DREAR_EAC(c) (((c) & 0x7) << 0) #define RPC_DROPR 0x0018 // R/W @@ -140,6 +141,7 @@ #define RPC_PHYOFFSET2 0x0084 // R/W #define RPC_PHYOFFSET2_OCTTMG(v) (((v) & 0x7) << 8) +#define RPC_DIRMAP_SIZE 0x4000000 #define RPC_WBUF_SIZE 256 // Write Buffer size struct rpc_mfd {