diff options
Diffstat (limited to 'drivers/spi/spi-cadence-quadspi.c')
-rw-r--r-- | drivers/spi/spi-cadence-quadspi.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 676313e1bdad..64b6a460d739 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -84,6 +84,7 @@ struct cqspi_st { u32 trigger_address; u32 wr_delay; bool use_direct_mode; + bool use_direct_mode_wr; struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT]; bool use_dma_read; u32 pd_dev_id; @@ -531,6 +532,17 @@ static int cqspi_command_read(struct cqspi_flash_pdata *f_pdata, /* 0 means 1 byte. */ reg |= (((n_rx - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK) << CQSPI_REG_CMDCTRL_RD_BYTES_LSB); + + /* setup ADDR BIT field */ + if (op->addr.nbytes) { + reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB); + reg |= ((op->addr.nbytes - 1) & + CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) + << CQSPI_REG_CMDCTRL_ADD_BYTES_LSB; + + writel(op->addr.val, reg_base + CQSPI_REG_CMDADDRESS); + } + status = cqspi_exec_flash_cmd(cqspi, reg); if (status) return status; @@ -549,6 +561,9 @@ static int cqspi_command_read(struct cqspi_flash_pdata *f_pdata, memcpy(rxbuf, ®, read_len); } + /* Reset CMD_CTRL Reg once command read completes */ + writel(0, reg_base + CQSPI_REG_CMDCTRL); + return 0; } @@ -613,7 +628,12 @@ static int cqspi_command_write(struct cqspi_flash_pdata *f_pdata, } } - return cqspi_exec_flash_cmd(cqspi, reg); + ret = cqspi_exec_flash_cmd(cqspi, reg); + + /* Reset CMD_CTRL Reg once command write completes */ + writel(0, reg_base + CQSPI_REG_CMDCTRL); + + return ret; } static int cqspi_read_setup(struct cqspi_flash_pdata *f_pdata, @@ -766,7 +786,7 @@ failrd: writel(0, reg_base + CQSPI_REG_IRQMASK); /* Cancel the indirect read */ - writel(CQSPI_REG_INDIRECTWR_CANCEL_MASK, + writel(CQSPI_REG_INDIRECTRD_CANCEL_MASK, reg_base + CQSPI_REG_INDIRECTRD); return ret; } @@ -937,6 +957,12 @@ static int cqspi_write_setup(struct cqspi_flash_pdata *f_pdata, reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL); reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL; writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL); + /* + * DAC mode require auto polling as flash needs to be polled + * for write completion in case of bubble in SPI transaction + * due to slow CPU/DMA master. + */ + cqspi->use_direct_mode_wr = false; } reg = readl(reg_base + CQSPI_REG_SIZE); @@ -1222,7 +1248,7 @@ static ssize_t cqspi_write(struct cqspi_flash_pdata *f_pdata, * data. */ if (!op->cmd.dtr && cqspi->use_direct_mode && - ((to + len) <= cqspi->ahb_size)) { + cqspi->use_direct_mode_wr && ((to + len) <= cqspi->ahb_size)) { memcpy_toio(cqspi->ahb_base + to, buf, len); return cqspi_wait_idle(cqspi); } @@ -1333,7 +1359,13 @@ static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op) cqspi_configure(f_pdata, mem->spi->max_speed_hz); if (op->data.dir == SPI_MEM_DATA_IN && op->data.buf.in) { - if (!op->addr.nbytes) + /* + * Performing reads in DAC mode forces to read minimum 4 bytes + * which is unsupported on some flash devices during register + * reads, prefer STIG mode for such small reads. + */ + if (!op->addr.nbytes || + op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX) return cqspi_command_read(f_pdata, op); return cqspi_read(f_pdata, op); @@ -1692,8 +1724,10 @@ static int cqspi_probe(struct platform_device *pdev) cqspi->master_ref_clk_hz); if (ddata->hwcaps_mask & CQSPI_SUPPORTS_OCTAL) master->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL; - if (!(ddata->quirks & CQSPI_DISABLE_DAC_MODE)) + if (!(ddata->quirks & CQSPI_DISABLE_DAC_MODE)) { cqspi->use_direct_mode = true; + cqspi->use_direct_mode_wr = true; + } if (ddata->quirks & CQSPI_SUPPORT_EXTERNAL_DMA) cqspi->use_dma_read = true; if (ddata->quirks & CQSPI_NO_SUPPORT_WR_COMPLETION) |