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 <siva.durga.paladugu@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
This commit is contained in:
committed by
Michal Simek
parent
3629c717e2
commit
075605d57e
@@ -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);
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user