diff options
author | Kuldeep Singh <kuldeep.singh@nxp.com> | 2021-03-02 15:49:33 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2021-03-10 15:46:55 +0300 |
commit | 31e92cbfb9cd9f7dcb2c04858f6cdcb3cbca914f (patch) | |
tree | 7eca3171fe05b7da037b5926f62a91b9ecee37f7 /drivers/spi/spi-nxp-fspi.c | |
parent | 87d62d8fa66622d75a76836ecc0fd2edbbcb38d3 (diff) | |
download | linux-31e92cbfb9cd9f7dcb2c04858f6cdcb3cbca914f.tar.xz |
spi: spi-nxp-fspi: Add support for IP read only
Add support for disabling AHB bus and read entire flash contents via IP
bus only. Please note, this enables IP bus read using a quirk which can
be enabled directly in device-type data or in existence of an errata
where AHB bus may need to be disabled.
Signed-off-by: Kuldeep Singh <kuldeep.singh@nxp.com>
Link: https://lore.kernel.org/r/20210302124936.1972546-2-kuldeep.singh@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-nxp-fspi.c')
-rw-r--r-- | drivers/spi/spi-nxp-fspi.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index ab9035662717..829391e20e92 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -311,6 +311,9 @@ #define NXP_FSPI_MAX_CHIPSELECT 4 #define NXP_FSPI_MIN_IOMAP SZ_4M +/* Access flash memory using IP bus only */ +#define FSPI_QUIRK_USE_IP_ONLY BIT(0) + struct nxp_fspi_devtype_data { unsigned int rxfifo; unsigned int txfifo; @@ -359,6 +362,11 @@ struct nxp_fspi { int selected; }; +static inline int needs_ip_only(struct nxp_fspi *f) +{ + return f->devtype_data->quirks & FSPI_QUIRK_USE_IP_ONLY; +} + /* * R/W functions for big- or little-endian registers: * The FSPI controller's endianness is independent of @@ -553,8 +561,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, for (i = 0; i < ARRAY_SIZE(lutval); i++) fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i)); - dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x]\n", - op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3]); + dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x], size: 0x%08x\n", + op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes); /* lock LUT */ fspi_writel(f, FSPI_LUTKEY_VALUE, f->iobase + FSPI_LUTKEY); @@ -852,12 +860,14 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) nxp_fspi_prepare_lut(f, op); /* - * If we have large chunks of data, we read them through the AHB bus - * by accessing the mapped memory. In all other cases we use - * IP commands to access the flash. + * If we have large chunks of data, we read them through the AHB bus by + * accessing the mapped memory. In all other cases we use IP commands + * to access the flash. Read via AHB bus may be corrupted due to + * existence of an errata and therefore discard AHB read in such cases. */ if (op->data.nbytes > (f->devtype_data->rxfifo - 4) && - op->data.dir == SPI_MEM_DATA_IN) { + op->data.dir == SPI_MEM_DATA_IN && + !needs_ip_only(f)) { err = nxp_fspi_read_ahb(f, op); } else { if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) @@ -888,6 +898,12 @@ static int nxp_fspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8); } + /* Limit data bytes to RX FIFO in case of IP read only */ + if (op->data.dir == SPI_MEM_DATA_IN && + needs_ip_only(f) && + op->data.nbytes > f->devtype_data->rxfifo) + op->data.nbytes = f->devtype_data->rxfifo; + return 0; } |