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

From: Md Sadre Alam
Date: Fri Aug 18 2023 - 10:52:35 EST


From: Sricharan Ramabadhran <quic_srichara@xxxxxxxxxxx>

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@xxxxxxxxxxx>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@xxxxxxxxxxx>
---
drivers/mtd/nand/raw/qcom_nandc.c | 93 ++++++++++++-------------------
1 file changed, 35 insertions(+), 58 deletions(-)

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:
--
2.17.1