Skip to content

Commit 5bc36b2

Browse files
Abhishek Sahumiquelraynal
authored andcommitted
mtd: rawnand: qcom: check for operation errors in case of raw read
Currently there is no error checking for raw read. For raw reads, there won’t be any ECC failure but the operational failures are possible, so schedule the NAND_FLASH_STATUS read after each codeword. Signed-off-by: Abhishek Sahu <absahu@codeaurora.org> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
1 parent 783b5bf commit 5bc36b2

File tree

1 file changed

+40
-18
lines changed

1 file changed

+40
-18
lines changed

drivers/mtd/nand/raw/qcom_nandc.c

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,8 @@ static void config_nand_page_read(struct qcom_nand_controller *nandc)
10961096
* Helper to prepare DMA descriptors for configuring registers
10971097
* before reading each codeword in NAND page.
10981098
*/
1099-
static void config_nand_cw_read(struct qcom_nand_controller *nandc)
1099+
static void
1100+
config_nand_cw_read(struct qcom_nand_controller *nandc, bool use_ecc)
11001101
{
11011102
if (nandc->props->is_bam)
11021103
write_reg_dma(nandc, NAND_READ_LOCATION_0, 4,
@@ -1105,19 +1106,25 @@ static void config_nand_cw_read(struct qcom_nand_controller *nandc)
11051106
write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
11061107
write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
11071108

1108-
read_reg_dma(nandc, NAND_FLASH_STATUS, 2, 0);
1109-
read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1,
1110-
NAND_BAM_NEXT_SGL);
1109+
if (use_ecc) {
1110+
read_reg_dma(nandc, NAND_FLASH_STATUS, 2, 0);
1111+
read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1,
1112+
NAND_BAM_NEXT_SGL);
1113+
} else {
1114+
read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
1115+
}
11111116
}
11121117

11131118
/*
11141119
* Helper to prepare dma descriptors to configure registers needed for reading a
11151120
* single codeword in page
11161121
*/
1117-
static void config_nand_single_cw_page_read(struct qcom_nand_controller *nandc)
1122+
static void
1123+
config_nand_single_cw_page_read(struct qcom_nand_controller *nandc,
1124+
bool use_ecc)
11181125
{
11191126
config_nand_page_read(nandc);
1120-
config_nand_cw_read(nandc);
1127+
config_nand_cw_read(nandc, use_ecc);
11211128
}
11221129

11231130
/*
@@ -1198,7 +1205,7 @@ static int nandc_param(struct qcom_nand_host *host)
11981205
nandc->buf_count = 512;
11991206
memset(nandc->data_buffer, 0xff, nandc->buf_count);
12001207

1201-
config_nand_single_cw_page_read(nandc);
1208+
config_nand_single_cw_page_read(nandc, false);
12021209

12031210
read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer,
12041211
nandc->buf_count, 0);
@@ -1563,6 +1570,23 @@ struct read_stats {
15631570
__le32 erased_cw;
15641571
};
15651572

1573+
/* reads back FLASH_STATUS register set by the controller */
1574+
static int check_flash_errors(struct qcom_nand_host *host, int cw_cnt)
1575+
{
1576+
struct nand_chip *chip = &host->chip;
1577+
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
1578+
int i;
1579+
1580+
for (i = 0; i < cw_cnt; i++) {
1581+
u32 flash = le32_to_cpu(nandc->reg_read_buf[i]);
1582+
1583+
if (flash & (FS_OP_ERR | FS_MPU_ERR))
1584+
return -EIO;
1585+
}
1586+
1587+
return 0;
1588+
}
1589+
15661590
/*
15671591
* reads back status registers set by the controller to notify page read
15681592
* errors. this is equivalent to what 'ecc->correct()' would do.
@@ -1729,7 +1753,7 @@ static int read_page_ecc(struct qcom_nand_host *host, u8 *data_buf,
17291753
}
17301754
}
17311755

1732-
config_nand_cw_read(nandc);
1756+
config_nand_cw_read(nandc, true);
17331757

17341758
if (data_buf)
17351759
read_data_dma(nandc, FLASH_BUF_ACC, data_buf,
@@ -1791,7 +1815,7 @@ static int copy_last_cw(struct qcom_nand_host *host, int page)
17911815
set_address(host, host->cw_size * (ecc->steps - 1), page);
17921816
update_rw_regs(host, 1, true);
17931817

1794-
config_nand_single_cw_page_read(nandc);
1818+
config_nand_single_cw_page_read(nandc, host->use_ecc);
17951819

17961820
read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, size, 0);
17971821

@@ -1874,7 +1898,7 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd,
18741898
nandc_set_read_loc(nandc, 3, read_loc, oob_size2, 1);
18751899
}
18761900

1877-
config_nand_cw_read(nandc);
1901+
config_nand_cw_read(nandc, false);
18781902

18791903
read_data_dma(nandc, reg_off, data_buf, data_size1, 0);
18801904
reg_off += data_size1;
@@ -1893,12 +1917,13 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd,
18931917
}
18941918

18951919
ret = submit_descs(nandc);
1896-
if (ret)
1897-
dev_err(nandc->dev, "failure to read raw page\n");
1898-
18991920
free_descs(nandc);
1921+
if (ret) {
1922+
dev_err(nandc->dev, "failure to read raw page\n");
1923+
return ret;
1924+
}
19001925

1901-
return ret;
1926+
return check_flash_errors(host, ecc->steps);
19021927
}
19031928

19041929
/* implements ecc->read_oob() */
@@ -2117,7 +2142,6 @@ static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
21172142
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
21182143
struct nand_ecc_ctrl *ecc = &chip->ecc;
21192144
int page, ret, bbpos, bad = 0;
2120-
u32 flash_status;
21212145

21222146
page = (int)(ofs >> chip->page_shift) & chip->pagemask;
21232147

@@ -2134,9 +2158,7 @@ static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
21342158
if (ret)
21352159
goto err;
21362160

2137-
flash_status = le32_to_cpu(nandc->reg_read_buf[0]);
2138-
2139-
if (flash_status & (FS_OP_ERR | FS_MPU_ERR)) {
2161+
if (check_flash_errors(host, 1)) {
21402162
dev_warn(nandc->dev, "error when trying to read BBM\n");
21412163
goto err;
21422164
}

0 commit comments

Comments
 (0)