diff mbox series

[04/11] spi: cadence-quadspi: enable opcode extension based on command length

Message ID 20240411223709.573-5-greg.malysa@timesys.com
State New
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series cadence-qspi: Add DTR support including PHY mode calibration | expand

Commit Message

Greg Malysa April 11, 2024, 10:36 p.m. UTC
From: Ian Roberts <ian.roberts@timesys.com>

Some flash chips use dual opcodes in other modes. For example, the
Macronix MX66 requires dual opcodes for STR octal operation. Thus,
enable opcode extension based on the length of the command instead
of the DTR mode of the controller.

Co-developed-by: Nathan Barrett-Morrison <nathan.morrison@timesys.com>
Signed-off-by: Nathan Barrett-Morrison <nathan.morrison@timesys.com>
Signed-off-by: Greg Malysa <greg.malysa@timesys.com>
Signed-off-by: Ian Roberts <ian.roberts@timesys.com>
---

 drivers/spi/cadence_qspi_apb.c | 66 +++++++++++++++++++++++++---------
 1 file changed, 49 insertions(+), 17 deletions(-)
diff mbox series

Patch

diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index 34cacf1880..eb9f4ed63d 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -412,19 +412,27 @@  static int cadence_qspi_enable_dtr(struct cadence_spi_priv *priv,
 
 	reg = readl(priv->regbase + CQSPI_REG_CONFIG);
 
-	if (enable) {
-		reg |= CQSPI_REG_CONFIG_DTR_PROTO;
+	switch (op->cmd.nbytes) {
+	case 1:
+		reg &= ~CQSPI_REG_CONFIG_DUAL_OPCODE;
+		break;
+	case 2:
 		reg |= CQSPI_REG_CONFIG_DUAL_OPCODE;
 
 		/* Set up command opcode extension. */
 		ret = cadence_qspi_setup_opcode_ext(priv, op, shift);
 		if (ret)
 			return ret;
-	} else {
-		reg &= ~CQSPI_REG_CONFIG_DTR_PROTO;
-		reg &= ~CQSPI_REG_CONFIG_DUAL_OPCODE;
+		break;
+	default:
+		return log_msg_ret("QSPI: Invalid command length", -EINVAL);
 	}
 
+	if (enable)
+		reg |= CQSPI_REG_CONFIG_DTR_PROTO;
+	else
+		reg &= ~CQSPI_REG_CONFIG_DTR_PROTO;
+
 	writel(reg, priv->regbase + CQSPI_REG_CONFIG);
 
 	return 0;
@@ -465,10 +473,16 @@  int cadence_qspi_apb_command_read(struct cadence_spi_priv *priv,
 	unsigned int dummy_clk;
 	u8 opcode;
 
-	if (priv->dtr)
-		opcode = op->cmd.opcode >> 8;
-	else
+	switch (op->cmd.nbytes) {
+	case 1:
 		opcode = op->cmd.opcode;
+		break;
+	case 2:
+		opcode = op->cmd.opcode >> 8;
+		break;
+	default:
+		return log_msg_ret("QSPI: Invalid command length", -EINVAL);
+	}
 
 	if (opcode == CMD_4BYTE_OCTAL_READ && !priv->dtr)
 		opcode = CMD_4BYTE_FAST_READ;
@@ -557,10 +571,16 @@  int cadence_qspi_apb_command_write(struct cadence_spi_priv *priv,
 	void *reg_base = priv->regbase;
 	u8 opcode;
 
-	if (priv->dtr)
-		opcode = op->cmd.opcode >> 8;
-	else
+	switch (op->cmd.nbytes) {
+	case 1:
 		opcode = op->cmd.opcode;
+		break;
+	case 2:
+		opcode = op->cmd.opcode >> 8;
+		break;
+	default:
+		return log_msg_ret("QSPI: Invalid command length", -EINVAL);
+	}
 
 	reg |= opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
 
@@ -634,10 +654,16 @@  int cadence_qspi_apb_read_setup(struct cadence_spi_priv *priv,
 	       priv->regbase + CQSPI_REG_INDIRECTTRIGGER);
 
 	/* Configure the opcode */
-	if (priv->dtr)
-		opcode = op->cmd.opcode >> 8;
-	else
+	switch (op->cmd.nbytes) {
+	case 1:
 		opcode = op->cmd.opcode;
+		break;
+	case 2:
+		opcode = op->cmd.opcode >> 8;
+		break;
+	default:
+		return log_msg_ret("QSPI: Invalid command length", -EINVAL);
+	}
 
 	rd_reg = opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB;
 	rd_reg |= op->cmd.dtr ? CQSPI_REG_RD_INSTR_DDR_EN_MASK : 0;
@@ -804,10 +830,16 @@  int cadence_qspi_apb_write_setup(struct cadence_spi_priv *priv,
 	       priv->regbase + CQSPI_REG_INDIRECTTRIGGER);
 
 	/* Configure the opcode */
-	if (priv->dtr)
-		opcode = op->cmd.opcode >> 8;
-	else
+	switch (op->cmd.nbytes) {
+	case 1:
 		opcode = op->cmd.opcode;
+		break;
+	case 2:
+		opcode = op->cmd.opcode >> 8;
+		break;
+	default:
+		return log_msg_ret("QSPI: Invalid command length", -EINVAL);
+	}
 
 	reg = opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB;
 	reg |= priv->data_width << CQSPI_REG_WR_INSTR_TYPE_DATA_LSB;