mtd: rawnand: qcom: Add read/read_start ops in exec_op path
authorSricharan Ramabadhran <quic_srichara@quicinc.com>
Fri, 18 Aug 2023 14:51:01 +0000 (20:21 +0530)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Mon, 21 Aug 2023 07:35:30 +0000 (09:35 +0200)
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>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20230818145101.23825-4-quic_mdalam@quicinc.com
drivers/mtd/nand/raw/qcom_nandc.c

index 985c4f4e618049a24e9c515d30cbe0f8577bdc57..0ee1caf021f701b06f0c0efa2e7d10fa82ee145c 100644 (file)
@@ -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;
@@ -2584,7 +2593,6 @@ static int qcom_parse_instructions(struct nand_chip *chip,
                                    const struct nand_subop *subop,
                                    struct qcom_op *q_op)
 {
-       struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
        const struct nand_op_instr *instr = NULL;
        unsigned int op_id;
        int i, ret;
@@ -2597,7 +2605,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 +2799,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 +2829,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);
@@ -2925,56 +2948,7 @@ err_out:
        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),
@@ -2991,10 +2965,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)),
                );
 
@@ -3015,7 +2989,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: