summaryrefslogtreecommitdiff
path: root/drivers/spi/cadence_qspi_apb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/cadence_qspi_apb.c')
-rw-r--r--drivers/spi/cadence_qspi_apb.c76
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);