From 2fc26b1b6377156e07c6c9ce934c58f634fcd21b Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Wed, 1 Apr 2020 14:51:37 +0800 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 [rebase] Signed-off-by: Yangbo Lu --- drivers/spi/spi-fsl-qspi.c | 71 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 16 deletions(-) --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -197,6 +197,12 @@ */ #define QUADSPI_QUIRK_USE_TDH_SETTING BIT(5) +/* + * 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 struct fsl_qspi_devtype_data { @@ -213,7 +219,7 @@ static const struct fsl_qspi_devtype_dat .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, }; @@ -222,7 +228,8 @@ static const struct fsl_qspi_devtype_dat .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, }; @@ -232,7 +239,7 @@ static const struct fsl_qspi_devtype_dat .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, }; @@ -242,7 +249,7 @@ static const struct fsl_qspi_devtype_dat .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, }; @@ -310,6 +317,11 @@ static inline int needs_tdh_setting(stru 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. @@ -556,6 +568,14 @@ static void fsl_qspi_select_mem(struct f 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; @@ -674,6 +694,7 @@ static int fsl_qspi_exec_op(struct spi_m 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); @@ -686,8 +707,11 @@ static int fsl_qspi_exec_op(struct spi_m 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) | @@ -751,6 +775,7 @@ static int fsl_qspi_default_setup(struct 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); @@ -805,19 +830,22 @@ static int fsl_qspi_default_setup(struct 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; @@ -904,6 +932,15 @@ static int fsl_qspi_probe(struct platfor 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); @@ -979,8 +1016,10 @@ static int fsl_qspi_remove(struct platfo 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; }