From: Siva Durga Prasad Paladugu Date: Sat, 11 Aug 2018 08:52:37 +0000 (+0530) Subject: spi: cadence_qspi: Add support for DMA reads X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=075605d57e2814be35cbdb3d617cb53971a0f5d5;p=thirdparty%2Fu-boot.git spi: cadence_qspi: Add support for DMA reads This patch adds support for DMA read operation if controller supports it which is determined by reading DT property "cdns,is-dma". This patch provides hooks for vendor specific DMA routines as the cadence qspi controller supports external DMA which is vendor specific. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 11fce9c4fe5..17b1932445e 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -291,6 +291,7 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus) plat->fifo_width = fdtdec_get_uint(blob, node, "cdns,fifo-width", 4); plat->trigger_address = fdtdec_get_uint(blob, node, "cdns,trigger-address", 0); + plat->is_dma = fdtdec_get_bool(blob, node, "cdns,is-dma"); /* All other paramters are embedded in the child node */ subnode = fdt_first_subnode(blob, node); diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index 055900def00..233793d4dce 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -29,6 +29,7 @@ struct cadence_spi_platdata { u32 tsd2d_ns; u32 tchsh_ns; u32 tslch_ns; + bool is_dma; }; struct cadence_spi_priv { @@ -76,5 +77,8 @@ void cadence_qspi_apb_delay(void *reg_base, void cadence_qspi_apb_enter_xip(void *reg_base, char xip_dummy); void cadence_qspi_apb_readdata_capture(void *reg_base, unsigned int bypass, unsigned int delay); +void cadence_qspi_apb_dma_read(struct cadence_spi_platdata *plat, + unsigned int n_rx, u8 *rxbuf); +int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_platdata *plat); #endif /* __CADENCE_QSPI_H__ */ diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index a8af3520303..e7b67c91bd3 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -56,6 +56,7 @@ #define CQSPI_REG_CONFIG_CLK_PHA BIT(2) #define CQSPI_REG_CONFIG_DIRECT BIT(7) #define CQSPI_REG_CONFIG_DECODE BIT(9) +#define CQSPI_REG_CONFIG_ENBL_DMA BIT(15) #define CQSPI_REG_CONFIG_XIP_IMM BIT(18) #define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10 #define CQSPI_REG_CONFIG_BAUD_LSB 19 @@ -171,6 +172,17 @@ (((readl(reg_base + CQSPI_REG_SDRAMLEVEL)) >> \ CQSPI_REG_SDRAMLEVEL_WR_LSB) & CQSPI_REG_SDRAMLEVEL_WR_MASK) +__weak void cadence_qspi_apb_dma_read(struct cadence_spi_platdata *plat, + unsigned int n_rx, u8 *rxbuf) +{ +} + +__weak +int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_platdata *plat) +{ + return 0; +} + static unsigned int cadence_qspi_apb_cmd2addr(const unsigned char *addr_buf, unsigned int addr_width) { @@ -398,6 +410,13 @@ void cadence_qspi_apb_controller_init(struct cadence_spi_platdata *plat) /* Disable all interrupts */ writel(0, plat->regbase + CQSPI_REG_IRQMASK); + reg = readl(plat->regbase + CQSPI_REG_CONFIG); + reg &= ~CQSPI_REG_CONFIG_DIRECT; + if (plat->is_dma) + reg |= CQSPI_REG_CONFIG_ENBL_DMA; + + writel(reg, plat->regbase + CQSPI_REG_CONFIG); + cadence_qspi_apb_controller_enable(plat->regbase); } @@ -631,10 +650,20 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, writel(n_rx, plat->regbase + CQSPI_REG_INDIRECTRDBYTES); + if (plat->is_dma) + cadence_qspi_apb_dma_read(plat, n_rx, rxbuf); + /* Start the indirect read transfer */ writel(CQSPI_REG_INDIRECTRD_START, plat->regbase + CQSPI_REG_INDIRECTRD); + if (plat->is_dma) { + ret = cadence_qspi_apb_wait_for_dma_cmplt(plat); + if (ret) + return ret; + goto rd_done; + } + while (remaining > 0) { ret = cadence_qspi_wait_for_data(plat); if (ret < 0) { @@ -663,6 +692,7 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, } } +rd_done: /* Check indirect done status */ ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTRD, CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);