Even with the trickery introduced in the latest version of the RPC-IF SPI driver, RPC-IF corrupts the data byte 4 for the RDID command, so the flash chip is still not detected. It started to work correctly after I tried to implement the workaround to this issue using the U-Boot RPC-IF driver's approach, i.e. using the external address space read mode. While at it, I'm removing the aforementioned trickery... Signed-off-by: Sergei Shtylyov <sergei.shtylyov@xxxxxxxxxxxxxxxxxx> --- The patch is against the 'devel' branch of Simon Horman's 'renesas,git' repo plus the RPC-IF SPI driver patch [1] and its prerequisites... [1] https://patchwork.kernel.org/patch/10742037/ drivers/spi/spi-renesas-rpc.c | 66 ++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 24 deletions(-) Index: renesas/drivers/spi/spi-renesas-rpc.c =================================================================== --- renesas.orig/drivers/spi/spi-renesas-rpc.c +++ renesas/drivers/spi/spi-renesas-rpc.c @@ -270,34 +270,52 @@ static int rpc_spi_io_xfer(struct rpc_sp } else if (rx_buf) { smenr = rpc->smenr; - while (pos < rpc->xferlen) { + /* + * RPC-IF spoils the data for the commands without an address + * phase (like RDID) in the manual mode, so we'll have to work + * around this issue by using the external address space read + * mode instead; we seem to be able to read 8 bytes at most in + * this mode though... + */ + if (!(smenr & RPC_SMENR_ADE(0xf))) { u32 nbytes = rpc->xferlen - pos; + u64 tmp; - if (nbytes > 4) - nbytes = 4; + if (nbytes > 8) + nbytes = 8; - smcr = rpc->smcr | RPC_SMCR_SPIE; + regmap_write(rpc->regmap, RPC_CMNCR, RPC_CMNCR_SFDE | + RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ | + RPC_CMNCR_BSZ(0)); + regmap_write(rpc->regmap, RPC_DRCR, 0); + regmap_write(rpc->regmap, RPC_DREAR, RPC_DREAR_EAC(1)); + regmap_write(rpc->regmap, RPC_DRCMR, rpc->cmd); + regmap_write(rpc->regmap, RPC_DRDMCR, rpc->dummy); + regmap_write(rpc->regmap, RPC_DROPR, 0); + regmap_write(rpc->regmap, RPC_DRENR, rpc->smenr & + ~RPC_SMENR_SPIDE(0xf)); + + tmp = readq(rpc->dirmap); + memcpy(rx_buf, &tmp, nbytes); + } else { + while (pos < rpc->xferlen) { + u32 nbytes = rpc->xferlen - pos; + + if (nbytes > 4) + nbytes = 4; + + smcr = rpc->smcr | RPC_SMCR_SPIE; + + regmap_write(rpc->regmap, RPC_SMENR, smenr); + regmap_write(rpc->regmap, RPC_SMCR, smcr); + ret = wait_msg_xfer_end(rpc); + if (ret) + goto out; + + regmap_read(rpc->regmap, RPC_SMRDR0, &data); + memcpy(rx_buf + pos, &data, nbytes); + pos += nbytes; - if (rpc->xferlen > 4 && rpc->xferlen < 8 && pos == 0) - smcr |= RPC_SMCR_SSLKP; - - regmap_write(rpc->regmap, RPC_SMENR, smenr); - regmap_write(rpc->regmap, RPC_SMCR, smcr); - ret = wait_msg_xfer_end(rpc); - if (ret) - goto out; - - regmap_read(rpc->regmap, RPC_SMRDR0, &data); - memcpy(rx_buf + pos, &data, nbytes); - pos += nbytes; - - if (rpc->xferlen > 4 && rpc->xferlen < 8 && pos == 4) { - smenr = rpc->smenr & ~RPC_SMENR_CDE & - ~RPC_SMENR_ADE(0xf); - } else { - regmap_write(rpc->regmap, RPC_SMCMR, rpc->cmd); - regmap_write(rpc->regmap, RPC_SMDMCR, - rpc->dummy); regmap_write(rpc->regmap, RPC_SMADR, rpc->addr + pos); }