mtd: rawnand: qcom: code reorganization for raw read

Make separate function to perform raw read for one codeword and
call this function multiple times for each codeword in case of
raw page read. This separate function will help in subsequent
patches related with erased codeword bitflip detection.

It will decrease throughput for raw page read. Raw page read
is used for debug purpose so it won't affect normal flash
operations.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
This commit is contained in:
Abhishek Sahu 2018-06-20 12:57:40 +05:30 committed by Miquel Raynal
parent 5bc36b2bf6
commit 85632c1719

View File

@ -1587,6 +1587,74 @@ static int check_flash_errors(struct qcom_nand_host *host, int cw_cnt)
return 0;
}
/* performs raw read for one codeword */
static int
qcom_nandc_read_cw_raw(struct mtd_info *mtd, struct nand_chip *chip,
u8 *data_buf, u8 *oob_buf, int page, int cw)
{
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
int data_size1, data_size2, oob_size1, oob_size2;
int ret, reg_off = FLASH_BUF_ACC, read_loc = 0;
nand_read_page_op(chip, page, 0, NULL, 0);
host->use_ecc = false;
clear_bam_transaction(nandc);
set_address(host, host->cw_size * cw, page);
update_rw_regs(host, 1, true);
config_nand_page_read(nandc);
data_size1 = mtd->writesize - host->cw_size * (ecc->steps - 1);
oob_size1 = host->bbm_size;
if (cw == (ecc->steps - 1)) {
data_size2 = ecc->size - data_size1 -
((ecc->steps - 1) * 4);
oob_size2 = (ecc->steps * 4) + host->ecc_bytes_hw +
host->spare_bytes;
} else {
data_size2 = host->cw_data - data_size1;
oob_size2 = host->ecc_bytes_hw + host->spare_bytes;
}
if (nandc->props->is_bam) {
nandc_set_read_loc(nandc, 0, read_loc, data_size1, 0);
read_loc += data_size1;
nandc_set_read_loc(nandc, 1, read_loc, oob_size1, 0);
read_loc += oob_size1;
nandc_set_read_loc(nandc, 2, read_loc, data_size2, 0);
read_loc += data_size2;
nandc_set_read_loc(nandc, 3, read_loc, oob_size2, 1);
}
config_nand_cw_read(nandc, false);
read_data_dma(nandc, reg_off, data_buf, data_size1, 0);
reg_off += data_size1;
read_data_dma(nandc, reg_off, oob_buf, oob_size1, 0);
reg_off += oob_size1;
read_data_dma(nandc, reg_off, data_buf + data_size1, data_size2, 0);
reg_off += data_size2;
read_data_dma(nandc, reg_off, oob_buf + oob_size1, oob_size2, 0);
ret = submit_descs(nandc);
free_descs(nandc);
if (ret) {
dev_err(nandc->dev, "failure to read raw cw %d\n", cw);
return ret;
}
return check_flash_errors(host, 1);
}
/*
* reads back status registers set by the controller to notify page read
* errors. this is equivalent to what 'ecc->correct()' would do.
@ -1851,79 +1919,21 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd,
int oob_required, int page)
{
struct qcom_nand_host *host = to_qcom_nand_host(chip);
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
u8 *data_buf, *oob_buf;
struct nand_ecc_ctrl *ecc = &chip->ecc;
int i, ret;
int read_loc;
int cw, ret;
u8 *data_buf = buf, *oob_buf = chip->oob_poi;
nand_read_page_op(chip, page, 0, NULL, 0);
data_buf = buf;
oob_buf = chip->oob_poi;
for (cw = 0; cw < ecc->steps; cw++) {
ret = qcom_nandc_read_cw_raw(mtd, chip, data_buf, oob_buf,
page, cw);
if (ret)
return ret;
host->use_ecc = false;
clear_bam_transaction(nandc);
update_rw_regs(host, ecc->steps, true);
config_nand_page_read(nandc);
for (i = 0; i < ecc->steps; i++) {
int data_size1, data_size2, oob_size1, oob_size2;
int reg_off = FLASH_BUF_ACC;
data_size1 = mtd->writesize - host->cw_size * (ecc->steps - 1);
oob_size1 = host->bbm_size;
if (i == (ecc->steps - 1)) {
data_size2 = ecc->size - data_size1 -
((ecc->steps - 1) << 2);
oob_size2 = (ecc->steps << 2) + host->ecc_bytes_hw +
host->spare_bytes;
} else {
data_size2 = host->cw_data - data_size1;
oob_size2 = host->ecc_bytes_hw + host->spare_bytes;
}
if (nandc->props->is_bam) {
read_loc = 0;
nandc_set_read_loc(nandc, 0, read_loc, data_size1, 0);
read_loc += data_size1;
nandc_set_read_loc(nandc, 1, read_loc, oob_size1, 0);
read_loc += oob_size1;
nandc_set_read_loc(nandc, 2, read_loc, data_size2, 0);
read_loc += data_size2;
nandc_set_read_loc(nandc, 3, read_loc, oob_size2, 1);
}
config_nand_cw_read(nandc, false);
read_data_dma(nandc, reg_off, data_buf, data_size1, 0);
reg_off += data_size1;
data_buf += data_size1;
read_data_dma(nandc, reg_off, oob_buf, oob_size1, 0);
reg_off += oob_size1;
oob_buf += oob_size1;
read_data_dma(nandc, reg_off, data_buf, data_size2, 0);
reg_off += data_size2;
data_buf += data_size2;
read_data_dma(nandc, reg_off, oob_buf, oob_size2, 0);
oob_buf += oob_size2;
data_buf += host->cw_data;
oob_buf += ecc->bytes;
}
ret = submit_descs(nandc);
free_descs(nandc);
if (ret) {
dev_err(nandc->dev, "failure to read raw page\n");
return ret;
}
return check_flash_errors(host, ecc->steps);
return 0;
}
/* implements ecc->read_oob() */