diff mbox series

[3/3] mtd: rawnand: qcom: Add read/read_start ops in exec_op path

Message ID 20230818145101.23825-4-quic_mdalam@quicinc.com
State New
Headers show
Series mtd: rawnand: qcom: Fixes for exec_op | expand

Commit Message

Md Sadre Alam Aug. 18, 2023, 2:51 p.m. UTC
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>

READ/READ_START opcodes are not set in exec_op path.
Fixing that here.

While there, Steps to program the controller is common for
erase/reset/read/program page. So use a common pattern and
pull them under one function.

Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
---
 drivers/mtd/nand/raw/qcom_nandc.c | 93 ++++++++++++-------------------
 1 file changed, 35 insertions(+), 58 deletions(-)

Comments

Miquel Raynal Aug. 18, 2023, 8:02 p.m. UTC | #1
On Fri, 2023-08-18 at 14:51:01 UTC, Md Sadre Alam wrote:
> From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
> 
> READ/READ_START opcodes are not set in exec_op path.
> Fixing that here.
> 
> While there, Steps to program the controller is common for
> erase/reset/read/program page. So use a common pattern and
> pull them under one function.
> 
> Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
> Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.

Miquel
diff mbox series

Patch

diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
index 73dd1b4e4e31..370a779610e2 100644
--- a/drivers/mtd/nand/raw/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
@@ -2541,9 +2541,11 @@  static int qcom_nand_attach_chip(struct nand_chip *chip)
 	return 0;
 }
 
-static int qcom_op_cmd_mapping(struct qcom_nand_controller *nandc, u8 opcode,
+static int qcom_op_cmd_mapping(struct nand_chip *chip, u8 opcode,
 			       struct qcom_op *q_op)
 {
+	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
+	struct qcom_nand_host *host = to_qcom_nand_host(chip);
 	int cmd;
 
 	switch (opcode) {
@@ -2571,6 +2573,13 @@  static int qcom_op_cmd_mapping(struct qcom_nand_controller *nandc, u8 opcode,
 		q_op->flag = OP_PROGRAM_PAGE;
 		nandc->exec_opwrite = true;
 		break;
+	case NAND_CMD_READ0:
+	case NAND_CMD_READSTART:
+		if (host->use_ecc)
+			cmd = OP_PAGE_READ_WITH_ECC;
+		else
+			cmd = OP_PAGE_READ;
+		break;
 	default:
 		dev_err(nandc->dev, "Opcode not supported: %u\n", opcode);
 		return -EOPNOTSUPP;
@@ -2597,7 +2606,7 @@  static int qcom_parse_instructions(struct nand_chip *chip,
 
 		switch (instr->type) {
 		case NAND_OP_CMD_INSTR:
-			ret = qcom_op_cmd_mapping(nandc, instr->ctx.cmd.opcode, q_op);
+			ret = qcom_op_cmd_mapping(chip, instr->ctx.cmd.opcode, q_op);
 			if (ret < 0)
 				return ret;
 
@@ -2791,13 +2800,25 @@  static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_sub
 	struct qcom_nand_host *host = to_qcom_nand_host(chip);
 	struct qcom_op q_op = {};
 	int ret;
+	int instrs = 1;
 
 	ret = qcom_parse_instructions(chip, subop, &q_op);
 	if (ret)
 		return ret;
 
-	if (q_op.flag == OP_PROGRAM_PAGE)
+	if (q_op.flag == OP_PROGRAM_PAGE) {
 		goto wait_rdy;
+	} else if (q_op.cmd_reg == OP_BLOCK_ERASE) {
+		q_op.cmd_reg |= PAGE_ACC | LAST_PAGE;
+		nandc_set_reg(chip, NAND_ADDR0, q_op.addr1_reg);
+		nandc_set_reg(chip, NAND_ADDR1, q_op.addr2_reg);
+		nandc_set_reg(chip, NAND_DEV0_CFG0,
+			      host->cfg0_raw & ~(7 << CW_PER_PAGE));
+		nandc_set_reg(chip, NAND_DEV0_CFG1, host->cfg1_raw);
+		instrs = 3;
+	} else {
+		return 0;
+	}
 
 	nandc->buf_count = 0;
 	nandc->buf_start = 0;
@@ -2809,9 +2830,12 @@  static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_sub
 	nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg);
 	nandc_set_reg(chip, NAND_EXEC_CMD, 1);
 
-	write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
-	write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
+	write_reg_dma(nandc, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL);
+	(q_op.cmd_reg == OP_BLOCK_ERASE) ? write_reg_dma(nandc, NAND_DEV0_CFG0,
+	2, NAND_BAM_NEXT_SGL) : read_reg_dma(nandc,
+	NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
 
+	write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
 	read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
 
 	ret = submit_descs(nandc);
@@ -2928,56 +2952,7 @@  static int qcom_param_page_type_exec(struct nand_chip *chip,  const struct nand_
 	return ret;
 }
 
-static int qcom_erase_cmd_type_exec(struct nand_chip *chip, const struct nand_subop *subop)
-{
-	struct qcom_nand_host *host = to_qcom_nand_host(chip);
-	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
-	struct qcom_op q_op = {};
-	int ret;
-
-	ret = qcom_parse_instructions(chip, subop, &q_op);
-	if (ret)
-		return ret;
-
-	q_op.cmd_reg |= PAGE_ACC | LAST_PAGE;
-
-	nandc->buf_count = 0;
-	nandc->buf_start = 0;
-	host->use_ecc = false;
-	clear_read_regs(nandc);
-	clear_bam_transaction(nandc);
-
-	nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg);
-	nandc_set_reg(chip, NAND_ADDR0, q_op.addr1_reg);
-	nandc_set_reg(chip, NAND_ADDR1, q_op.addr2_reg);
-	nandc_set_reg(chip, NAND_DEV0_CFG0,
-		      host->cfg0_raw & ~(7 << CW_PER_PAGE));
-	nandc_set_reg(chip, NAND_DEV0_CFG1, host->cfg1_raw);
-	nandc_set_reg(chip, NAND_EXEC_CMD, 1);
-
-	write_reg_dma(nandc, NAND_FLASH_CMD, 3, NAND_BAM_NEXT_SGL);
-	write_reg_dma(nandc, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL);
-	write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
-
-	ret = submit_descs(nandc);
-	if (ret) {
-		dev_err(nandc->dev, "failure in submitting erase descriptor\n");
-		goto err_out;
-	}
-
-	ret = qcom_wait_rdy_poll(chip, q_op.rdy_timeout_ms);
-	if (ret)
-		goto err_out;
-
-err_out:
-	return ret;
-}
-
 static const struct nand_op_parser qcom_op_parser = NAND_OP_PARSER(
-		NAND_OP_PARSER_PATTERN(
-			qcom_misc_cmd_type_exec,
-			NAND_OP_PARSER_PAT_CMD_ELEM(false),
-			NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
 		NAND_OP_PARSER_PATTERN(
 			qcom_read_id_type_exec,
 			NAND_OP_PARSER_PAT_CMD_ELEM(false),
@@ -2994,10 +2969,10 @@  static const struct nand_op_parser qcom_op_parser = NAND_OP_PARSER(
 			NAND_OP_PARSER_PAT_WAITRDY_ELEM(true),
 			NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, 512)),
 		NAND_OP_PARSER_PATTERN(
-			qcom_erase_cmd_type_exec,
-			NAND_OP_PARSER_PAT_CMD_ELEM(false),
-			NAND_OP_PARSER_PAT_ADDR_ELEM(false, MAX_ADDRESS_CYCLE),
+			qcom_misc_cmd_type_exec,
 			NAND_OP_PARSER_PAT_CMD_ELEM(false),
+			NAND_OP_PARSER_PAT_ADDR_ELEM(true, MAX_ADDRESS_CYCLE),
+			NAND_OP_PARSER_PAT_CMD_ELEM(true),
 			NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
 		);
 
@@ -3018,7 +2993,9 @@  static int qcom_check_op(struct nand_chip *chip,
 			    instr->ctx.cmd.opcode != NAND_CMD_ERASE1 &&
 			    instr->ctx.cmd.opcode != NAND_CMD_ERASE2 &&
 			    instr->ctx.cmd.opcode != NAND_CMD_STATUS &&
-			    instr->ctx.cmd.opcode != NAND_CMD_PAGEPROG)
+			    instr->ctx.cmd.opcode != NAND_CMD_PAGEPROG &&
+			    instr->ctx.cmd.opcode != NAND_CMD_READ0 &&
+			    instr->ctx.cmd.opcode != NAND_CMD_READSTART)
 				return -EOPNOTSUPP;
 			break;
 		default: