Merge "mtd: msm_qpic_nand: Add support to read one codeword"

This commit is contained in:
qctecmdr 2021-04-19 01:52:40 -07:00 • committed by Gerrit - the friendly Code Review server
commit cc2c00539e

View file

@ -17,6 +17,7 @@
#define MAX_DESC 16
#define SMEM_AARM_PARTITION_TABLE 9
#define SMEM_APPS 0
#define ONE_CODEWORD_SIZE 516
/*
* Get the DMA memory for requested amount of size. It returns the pointer
@ -1076,10 +1077,16 @@ static int msm_nand_validate_mtd_params(struct mtd_info *mtd, bool read,
err = -EINVAL;
goto out;
}
args->page_count = ops->len / (mtd->writesize + mtd->oobsize);
if (ops->len <= ONE_CODEWORD_SIZE)
args->page_count = 1;
else
args->page_count = ops->len /
(mtd->writesize + mtd->oobsize);
} else if (ops->mode == MTD_OPS_AUTO_OOB) {
if (ops->datbuf && (ops->len % mtd->writesize) != 0) {
if (ops->datbuf && (ops->len %
((ops->len <= ONE_CODEWORD_SIZE) ?
ONE_CODEWORD_SIZE : mtd->writesize)) != 0) {
/* when ops->datbuf is NULL, ops->len can be ooblen */
pr_err("unsupported data len %d for AUTO mode\n",
ops->len);
@ -1092,7 +1099,10 @@ static int msm_nand_validate_mtd_params(struct mtd_info *mtd, bool read,
if ((args->page_count == 0) && (ops->ooblen))
args->page_count = 1;
} else if (ops->datbuf) {
args->page_count = ops->len / mtd->writesize;
if (ops->len <= ONE_CODEWORD_SIZE)
args->page_count = 1;
else
args->page_count = ops->len / mtd->writesize;
}
}
@ -1138,12 +1148,20 @@ static void msm_nand_update_rw_reg_data(struct msm_nand_chip *chip,
struct msm_nand_rw_params *args,
struct msm_nand_rw_reg_data *data)
{
/*
* While reading one codeword, CW_PER_PAGE bits of QPIC_NAND_DEV0_CFG0
* should be set to 0, which implies 1 codeword per page. 'n' below,
* is used to configure cfg0 for reading one full page or one single
* codeword.
*/
int n = (ops->len <= ONE_CODEWORD_SIZE) ? args->cwperpage : 1;
if (args->read) {
if (ops->mode != MTD_OPS_RAW) {
data->cmd = MSM_NAND_CMD_PAGE_READ_ECC;
data->cfg0 =
(chip->cfg0 & ~(7U << CW_PER_PAGE)) |
(((args->cwperpage-1) - args->start_sector)
(((args->cwperpage-n) - args->start_sector)
<< CW_PER_PAGE);
data->cfg1 = chip->cfg1;
data->ecc_bch_cfg = chip->ecc_bch_cfg;
@ -1151,7 +1169,7 @@ static void msm_nand_update_rw_reg_data(struct msm_nand_chip *chip,
data->cmd = MSM_NAND_CMD_PAGE_READ_ALL;
data->cfg0 =
(chip->cfg0_raw & ~(7U << CW_PER_PAGE)) |
(((args->cwperpage-1) - args->start_sector)
(((args->cwperpage-n) - args->start_sector)
<< CW_PER_PAGE);
data->cfg1 = chip->cfg1_raw;
data->ecc_bch_cfg = chip->ecc_cfg_raw;
@ -1195,6 +1213,11 @@ static void msm_nand_prep_rw_cmd_desc(struct mtd_oob_ops *ops,
uint32_t offset, size, last_read;
struct sps_command_element *curr_ce, *start_ce;
uint32_t *flags_ptr, *num_ce_ptr;
/*
* Variable to configure read_location register parameters
* while reading one codeword or one full page
*/
int n = (ops->len <= ONE_CODEWORD_SIZE) ? args->cwperpage : 1;
if (curr_cw == args->start_sector) {
curr_ce = start_ce = &cmd_list->setup_desc.ce[0];
@ -1287,10 +1310,15 @@ static void msm_nand_prep_rw_cmd_desc(struct mtd_oob_ops *ops,
if (ops->mode == MTD_OPS_AUTO_OOB) {
if (ops->datbuf) {
offset = 0;
size = (curr_cw < (args->cwperpage - 1)) ? 516 :
(512 - ((args->cwperpage - 1) << 2));
last_read = (curr_cw < (args->cwperpage - 1)) ? 1 :
(ops->oobbuf ? 0 : 1);
if (ops->len <= ONE_CODEWORD_SIZE) {
size = ONE_CODEWORD_SIZE;
last_read = 1;
} else {
size = (curr_cw < (args->cwperpage - 1)) ? 516 :
(512 - ((args->cwperpage - 1) << 2));
last_read = (curr_cw < (args->cwperpage - 1)) ?
1 : (ops->oobbuf ? 0 : 1);
}
rdata = (offset << 0) | (size << 16) |
(last_read << 31);
@ -1306,7 +1334,7 @@ static void msm_nand_prep_rw_cmd_desc(struct mtd_oob_ops *ops,
curr_ce++;
}
}
if (curr_cw == (args->cwperpage - 1) && ops->oobbuf) {
if (curr_cw == (args->cwperpage - n) && ops->oobbuf) {
offset = 512 - ((args->cwperpage - 1) << 2);
size = (args->cwperpage) << 2;
if (size > args->oob_len_cmd)
@ -1364,6 +1392,11 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops,
uint32_t sectordatasize, sectoroobsize;
uint32_t sps_flags = 0;
int err = 0;
/*
* Variable to configure sectordatasize and sectoroobsize
* while reading one codeword or one full page.
*/
int n = (ops->len <= ONE_CODEWORD_SIZE) ? args->cwperpage : 1;
if (args->read)
data_pipe_handle = info->sps.data_prod.handle;
@ -1372,7 +1405,7 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops,
if (ops->mode == MTD_OPS_RAW) {
if (ecc_parity_bytes && args->read) {
if (curr_cw == (args->cwperpage - 1))
if (curr_cw == (args->cwperpage - n))
sps_flags |= SPS_IOVEC_FLAG_INT;
/* read only ecc bytes */
@ -1387,7 +1420,7 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops,
sectordatasize = chip->cw_size;
if (!args->read)
sps_flags = SPS_IOVEC_FLAG_EOT;
if (curr_cw == (args->cwperpage - 1))
if (curr_cw == (args->cwperpage - n))
sps_flags |= SPS_IOVEC_FLAG_INT;
err = sps_transfer_one(data_pipe_handle,
@ -1400,8 +1433,13 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops,
}
} else if (ops->mode == MTD_OPS_AUTO_OOB) {
if (ops->datbuf) {
sectordatasize = (curr_cw < (args->cwperpage - 1))
? 516 : (512 - ((args->cwperpage - 1) << 2));
if (ops->len <= ONE_CODEWORD_SIZE)
sectordatasize = ONE_CODEWORD_SIZE;
else
sectordatasize =
(curr_cw < (args->cwperpage - 1))
? 516 :
(512 - ((args->cwperpage - 1) << 2));
if (!args->read) {
sps_flags = SPS_IOVEC_FLAG_EOT;
@ -1409,7 +1447,7 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops,
ops->oobbuf)
sps_flags = 0;
}
if ((curr_cw == (args->cwperpage - 1)) && !ops->oobbuf)
if ((curr_cw == (args->cwperpage - n)) && !ops->oobbuf)
sps_flags |= SPS_IOVEC_FLAG_INT;
err = sps_transfer_one(data_pipe_handle,
@ -1421,7 +1459,7 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops,
args->data_dma_addr_curr += sectordatasize;
}
if (ops->oobbuf && (curr_cw == (args->cwperpage - 1))) {
if (ops->oobbuf && (curr_cw == (args->cwperpage - n))) {
sectoroobsize = args->cwperpage << 2;
if (sectoroobsize > args->oob_len_data)
sectoroobsize = args->oob_len_data;
@ -2590,6 +2628,9 @@ static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from,
data.addr0 = (rw_params.page << 16) | rw_params.oob_col;
data.addr1 = (rw_params.page >> 16) & 0xff;
if (ops->len <= ONE_CODEWORD_SIZE)
cwperpage = 1;
for (n = rw_params.start_sector; n < cwperpage; n++) {
struct sps_command_element *curr_ce, *start_ce;
@ -2667,7 +2708,7 @@ static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from,
} else if (ops->mode == MTD_OPS_AUTO_OOB) {
if (ops->datbuf)
submitted_num_desc = cwperpage -
rw_params.start_sector;
rw_params.start_sector;
if (ops->oobbuf)
submitted_num_desc++;
}
@ -2846,7 +2887,10 @@ free_dma:
}
validate_mtd_params_failed:
if (ops->mode != MTD_OPS_RAW)
ops->retlen = mtd->writesize * pages_read;
if (ops->len <= ONE_CODEWORD_SIZE)
ops->retlen = ONE_CODEWORD_SIZE;
else
ops->retlen = mtd->writesize * pages_read;
else
ops->retlen = (mtd->writesize + mtd->oobsize) * pages_read;
ops->oobretlen = ops->ooblen - rw_params.oob_len_data;
@ -2917,8 +2961,11 @@ static int msm_nand_read_partial_page(struct mtd_info *mtd,
ops->datbuf = no_copy ? actual_buf : bounce_buf;
if (info->nand_chip.caps & MSM_NAND_CAP_PAGE_SCOPE_READ)
err = msm_nand_read_pagescope(mtd, aligned_from, ops);
else
else {
if ((len <= ONE_CODEWORD_SIZE) && (offset == 0))
ops->len = ONE_CODEWORD_SIZE;
err = msm_nand_read_oob(mtd, aligned_from, ops);
}
if (err == -EUCLEAN) {
is_euclean = 1;
err = 0;