@@ -722,23 +722,44 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
{
unsigned int page_size = plat->page_size;
unsigned int remaining = n_tx;
- unsigned int write_bytes;
+ unsigned int write_bytes = 0;
int ret;
+ /* Handle non-4-byte aligned access to avoid data abort. */
+ if ((uintptr_t) txbuf % 4) {
+ write_bytes = n_tx > 3 ? 4 - ((uintptr_t)txbuf % 4) : n_tx;
+ /* Configure the indirect read transfer bytes */
+ writel(write_bytes, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);
+ /* Start the indirect write transfer */
+ writel(CQSPI_REG_INDIRECTWR_START,
+ plat->regbase + CQSPI_REG_INDIRECTWR);
+ writesb(plat->ahbbase, txbuf, write_bytes);
+ txbuf += write_bytes;
+ remaining -= write_bytes;
+ if (remaining > 0) {
+ u32 start_addr = readl(plat->regbase +
+ CQSPI_REG_INDIRECTWRSTARTADDR);
+ start_addr += write_bytes;
+ writel(start_addr, plat->regbase +
+ CQSPI_REG_INDIRECTWRSTARTADDR);
+ }
+ }
+
/* Configure the indirect read transfer bytes */
- writel(n_tx, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);
+ writel(n_tx - write_bytes, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);
- /* Start the indirect write transfer */
- writel(CQSPI_REG_INDIRECTWR_START,
- plat->regbase + CQSPI_REG_INDIRECTWR);
+ if (remaining > 0)
+ writel(CQSPI_REG_INDIRECTWR_START,
+ plat->regbase + CQSPI_REG_INDIRECTWR);
while (remaining > 0) {
write_bytes = remaining > page_size ? page_size : remaining;
- /* Handle non-4-byte aligned access to avoid data abort. */
- if (((uintptr_t)txbuf % 4) || (write_bytes % 4))
- writesb(plat->ahbbase, txbuf, write_bytes);
- else
- writesl(plat->ahbbase, txbuf, write_bytes >> 2);
+
+ writesl(plat->ahbbase, txbuf, write_bytes >> 2);
+ if (write_bytes % 4)
+ writesb(plat->ahbbase,
+ txbuf + rounddown(write_bytes, 4),
+ write_bytes % 4);
ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_SDRAMLEVEL,
CQSPI_REG_SDRAMLEVEL_WR_MASK <<