diff options
Diffstat (limited to 'drivers/spi/cadence_qspi_apb.c')
-rw-r--r-- | drivers/spi/cadence_qspi_apb.c | 76 |
1 files changed, 44 insertions, 32 deletions
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 86cd67ae9c..0f6941ec3f 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -327,7 +327,14 @@ static int cadence_qspi_set_protocol(struct cadence_spi_platdata *plat, { int ret; - plat->dtr = op->data.dtr && op->cmd.dtr && op->addr.dtr; + /* + * For an op to be DTR, cmd phase along with every other non-empty + * phase should have dtr field set to 1. If an op phase has zero + * nbytes, ignore its dtr field; otherwise, check its dtr field. + */ + plat->dtr = op->cmd.dtr && + (!op->addr.nbytes || op->addr.dtr) && + (!op->data.nbytes || op->data.dtr); ret = cadence_qspi_buswidth_to_inst_type(op->cmd.buswidth); if (ret < 0) @@ -632,6 +639,8 @@ static int cadence_qspi_apb_exec_flash_cmd(void *reg_base, if (!cadence_qspi_wait_idle(reg_base)) return -EIO; + /* Flush the CMDCTRL reg after the execution */ + writel(0, reg_base + CQSPI_REG_CMDCTRL); return 0; } @@ -718,11 +727,6 @@ int cadence_qspi_apb_command_read(struct cadence_spi_platdata *plat, unsigned int dummy_clk; u8 opcode; - if (rxlen > CQSPI_STIG_DATA_LEN_MAX || !rxbuf) { - printf("QSPI: Invalid input arguments rxlen %u\n", rxlen); - return -EINVAL; - } - if (plat->dtr) opcode = op->cmd.opcode >> 8; else @@ -730,6 +734,18 @@ int cadence_qspi_apb_command_read(struct cadence_spi_platdata *plat, reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB; + /* setup ADDR BIT field */ + if (op->addr.nbytes) { + writel(op->addr.val, plat->regbase + CQSPI_REG_CMDADDRESS); + /* + * address bytes are zero indexed + */ + reg |= (((op->addr.nbytes - 1) & + CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) << + CQSPI_REG_CMDCTRL_ADD_BYTES_LSB); + reg |= CQSPI_REG_CMDCTRL_ADDR_EN; + } + /* Set up dummy cycles. */ dummy_clk = cadence_qspi_calc_dummy(op, plat->dtr); if (dummy_clk > CQSPI_DUMMY_CLKS_MAX) @@ -745,18 +761,6 @@ int cadence_qspi_apb_command_read(struct cadence_spi_platdata *plat, reg |= (((rxlen - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK) << CQSPI_REG_CMDCTRL_RD_BYTES_LSB); - /* setup ADDR BIT field */ - if (op->addr.nbytes) { - writel(op->addr.val, plat->regbase + CQSPI_REG_CMDADDRESS); - /* - * address bytes are zero indexed - */ - reg |= (((op->addr.nbytes - 1) & - CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) << - CQSPI_REG_CMDCTRL_ADD_BYTES_LSB); - reg |= CQSPI_REG_CMDCTRL_ADDR_EN; - } - status = cadence_qspi_apb_exec_flash_cmd(reg_base, reg); if (status != 0) return status; @@ -805,25 +809,12 @@ int cadence_qspi_apb_command_write(struct cadence_spi_platdata *plat, unsigned int reg = 0; unsigned int wr_data; unsigned int wr_len; + unsigned int dummy_clk; unsigned int txlen = op->data.nbytes; const void *txbuf = op->data.buf.out; void *reg_base = plat->regbase; - u32 addr; u8 opcode; - /* Reorder address to SPI bus order if only transferring address */ - if (!txlen) { - addr = cpu_to_be32(op->addr.val); - if (op->addr.nbytes == 3) - addr >>= 8; - txbuf = &addr; - txlen = op->addr.nbytes; - } - - if (txlen > CQSPI_STIG_DATA_LEN_MAX) { - printf("QSPI: Invalid input arguments txlen %u\n", txlen); - return -EINVAL; - } if (plat->dtr) opcode = op->cmd.opcode >> 8; @@ -832,6 +823,27 @@ int cadence_qspi_apb_command_write(struct cadence_spi_platdata *plat, reg |= opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB; + /* setup ADDR BIT field */ + if (op->addr.nbytes) { + writel(op->addr.val, plat->regbase + CQSPI_REG_CMDADDRESS); + /* + * address bytes are zero indexed + */ + reg |= (((op->addr.nbytes - 1) & + CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) << + CQSPI_REG_CMDCTRL_ADD_BYTES_LSB); + reg |= CQSPI_REG_CMDCTRL_ADDR_EN; + } + + /* Set up dummy cycles. */ + dummy_clk = cadence_qspi_calc_dummy(op, plat->dtr); + if (dummy_clk > CQSPI_DUMMY_CLKS_MAX) + return -ENOTSUPP; + + if (dummy_clk) + reg |= (dummy_clk & CQSPI_REG_CMDCTRL_DUMMY_MASK) + << CQSPI_REG_CMDCTRL_DUMMY_LSB; + if (txlen) { /* writing data = yes */ reg |= (0x1 << CQSPI_REG_CMDCTRL_WR_EN_LSB); |