From 41bfdd516e6a74a016b4df3e8c4ccd386b84aa80 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 7 Jan 2020 18:56:49 +0530 Subject: [PATCH] LF-18-3 spi: fsl-qspi: Allocate AHB memory dynamically for imx platforms LS platforms doesn't require dynamic allocaltion of AHB memory. So, let's define a quirk which allocates AHB memory dynamically only for imx platforms. Fixes: c70adc97("spi: spi-fsl-qspi: dynamically alloc AHB memory for QSPI") Signed-off-by: Kuldeep Singh (cherry picked from commit 6ba950732f1398e5644c604a48ee31957cbd996b) --- drivers/spi/spi-fsl-qspi.c | 71 +++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c index b841bcc47be8..9c5e094382c0 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -190,6 +190,12 @@ */ #define QUADSPI_QUIRK_BASE_INTERNAL BIT(4) +/* + * Use flash size for imx platforms and not for LS platforms. Define a + * quirk which enables it only on imx platforms. + */ +#define QUADSPI_QUIRK_USE_FLASH_SIZE BIT(6) + #define QUADSPI_MIN_IOMAP SZ_4M /* * Controller uses TDH bits in register QUADSPI_FLSHCR. @@ -211,7 +217,7 @@ static const struct fsl_qspi_devtype_data vybrid_data = { .txfifo = SZ_64, .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, - .quirks = QUADSPI_QUIRK_SWAP_ENDIAN, + .quirks = QUADSPI_QUIRK_SWAP_ENDIAN | QUADSPI_QUIRK_USE_FLASH_SIZE, .little_endian = true, }; @@ -220,7 +226,8 @@ static const struct fsl_qspi_devtype_data imx6sx_data = { .txfifo = SZ_512, .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, - .quirks = QUADSPI_QUIRK_4X_INT_CLK | QUADSPI_QUIRK_TKT245618, + .quirks = QUADSPI_QUIRK_4X_INT_CLK | QUADSPI_QUIRK_TKT245618 | + QUADSPI_QUIRK_USE_FLASH_SIZE, .little_endian = true, }; @@ -230,7 +237,7 @@ static const struct fsl_qspi_devtype_data imx7d_data = { .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK | - QUADSPI_QUIRK_USE_TDH_SETTING, + QUADSPI_QUIRK_USE_TDH_SETTING | QUADSPI_QUIRK_USE_FLASH_SIZE, .little_endian = true, }; @@ -240,7 +247,7 @@ static const struct fsl_qspi_devtype_data imx6ul_data = { .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK | - QUADSPI_QUIRK_USE_TDH_SETTING, + QUADSPI_QUIRK_USE_TDH_SETTING | QUADSPI_QUIRK_USE_FLASH_SIZE, .little_endian = true, }; @@ -308,6 +315,11 @@ static inline int needs_tdh_setting(struct fsl_qspi *q) return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING; } +static inline int needs_flash_size(struct fsl_qspi *q) +{ + return q->devtype_data->quirks & QUADSPI_QUIRK_USE_FLASH_SIZE; +} + /* * An IC bug makes it necessary to rearrange the 32-bit data. * Later chips, such as IMX6SLX, have fixed this bug. @@ -554,6 +566,14 @@ static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_device *spi) static int fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op) { + if (!needs_flash_size(q)) { + u32 size = q->devtype_data->ahb_buf_size; + memcpy_fromio(op->data.buf.in, + q->ahb_addr + q->selected * size, + op->data.nbytes); + return 0; + } + u32 start = op->addr.val + q->selected * q->memmap_phy_size / 4; u32 len = op->data.nbytes; @@ -672,6 +692,7 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) u32 addr_offset = 0; int err = 0; int invalid_mstrid = q->devtype_data->invalid_mstrid; + u32 size = q->devtype_data->ahb_buf_size; mutex_lock(&q->lock); @@ -684,8 +705,11 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) if (needs_amba_base_offset(q)) addr_offset = q->memmap_phy; + if (needs_flash_size(q)) + size = q->memmap_phy_size / 4; + qspi_writel(q, - q->selected * q->memmap_phy_size / 4 + addr_offset, + q->selected * size + addr_offset, base + QUADSPI_SFAR); qspi_writel(q, qspi_readl(q, base + QUADSPI_MCR) | @@ -749,6 +773,7 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q) void __iomem *base = q->iobase; u32 reg, addr_offset = 0; int ret; + u32 size = q->devtype_data->ahb_buf_size; /* disable and unprepare clock to avoid glitch pass to controller */ fsl_qspi_clk_disable_unprep(q); @@ -803,19 +828,22 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q) addr_offset = q->memmap_phy; /* - * In HW there can be a maximum of four chips on two buses with - * two chip selects on each bus. We use four chip selects in SW - * to differentiate between the four chips. - * We divide the total memory region size equally for each chip - * and set SFA1AD, SFA2AD, SFB1AD, SFB2AD accordingly. + * In HW there can be a maximum of four chips on two buses with two + * chip selects on each bus. We use four chip selects in SW to + * differentiate between the four chips. We divide the total memory + * region/ahb_buf_size size equally for each chip and set SFA1AD, + * SFA2AD, SFB1AD, SFB2AD accordingly. */ - qspi_writel(q, q->memmap_phy_size / 4 + addr_offset, + if (needs_flash_size(q)) + size = q->memmap_phy_size / 4; + + qspi_writel(q, size + addr_offset, base + QUADSPI_SFA1AD); - qspi_writel(q, q->memmap_phy_size / 4 * 2 + addr_offset, + qspi_writel(q, size * 2 + addr_offset, base + QUADSPI_SFA2AD); - qspi_writel(q, q->memmap_phy_size / 4 * 3 + addr_offset, + qspi_writel(q, size * 3 + addr_offset, base + QUADSPI_SFB1AD); - qspi_writel(q, q->memmap_phy_size / 4 * 4 + addr_offset, + qspi_writel(q, size * 4 + addr_offset, base + QUADSPI_SFB2AD); q->selected = -1; @@ -902,6 +930,15 @@ static int fsl_qspi_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI-memory"); + + if (!needs_flash_size(q)) { + q->ahb_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(q->ahb_addr)) { + ret = PTR_ERR(q->ahb_addr); + goto err_put_ctrl; + } + } + q->memmap_phy = res->start; q->memmap_phy_size = resource_size(res); @@ -977,8 +1014,10 @@ static int fsl_qspi_remove(struct platform_device *pdev) mutex_destroy(&q->lock); - if (q->ahb_addr) - iounmap(q->ahb_addr); + if (needs_flash_size(q)) { + if (q->ahb_addr) + iounmap(q->ahb_addr); + } return 0; }