drivers: rkflash: don't update vpc when record vpc equals 0 in gc progress

1.don't update vpc when record vpc equals 0 in gc progress
2.increase the number of read retry
3.avoid danger of abnormal power lost
4.change flash_read_page_raw return to error_ecc_bits
5.add nand buildin ecc support
6.skip ECC error page instead of marking as bad block
7.adjust the way of building tables to increase ftl init

Change-Id: I9ba24980c06d61a5a1d66019378075e0171a5887
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
Jon Lin 2019-01-24 10:40:10 +08:00 committed by Tao Huang
parent 13940863ec
commit c5243c0140
6 changed files with 16055 additions and 15312 deletions

View File

@ -18,6 +18,7 @@ static u8 g_nand_max_die;
static u16 g_totle_block;
static u8 g_nand_flash_ecc_bits;
static u8 g_nand_idb_res_blk_num;
static u8 g_nand_ecc_en;
static struct NAND_PARA_INFO_T nand_para = {
2,
@ -123,6 +124,7 @@ static void flash_erase_cmd(u8 cs, u32 page_addr)
static void flash_prog_second_cmd(u8 cs, u32 page_addr)
{
usleep_range(100, 120);
nandc_writel(PAGE_PROG_CMD & 0x00ff, NANDC_CHIP_CMD(cs));
}
@ -142,9 +144,28 @@ static void flash_read_random_dataout_cmd(u8 cs, u32 col_addr)
nandc_writel(READ_DP_OUT_CMD & 0x00ff, NANDC_CHIP_CMD(cs));
}
static u32 flash_read_ecc(u8 cs)
{
u32 ecc0, ecc1;
nandc_writel(READ_ECC_STATUS_CMD, NANDC_CHIP_CMD(cs));
nandc_delayns(80);
ecc0 = nandc_readl(NANDC_CHIP_DATA(cs)) & 0xF;
ecc1 = nandc_readl(NANDC_CHIP_DATA(cs)) & 0xF;
if (ecc1 > ecc0)
ecc0 = ecc1;
ecc1 = nandc_readl(NANDC_CHIP_DATA(cs)) & 0xF;
if (ecc1 > ecc0)
ecc0 = ecc1;
ecc1 = nandc_readl(NANDC_CHIP_DATA(cs)) & 0xF;
if (ecc1 > ecc0)
ecc0 = ecc1;
return ecc0;
}
static u32 flash_read_page_raw(u8 cs, u32 page_addr, u32 *p_data, u32 *p_spare)
{
u32 ret = 0;
u32 error_ecc_bits;
u32 sec_per_page = nand_para.sec_per_page;
@ -157,34 +178,44 @@ static u32 flash_read_page_raw(u8 cs, u32 page_addr, u32 *p_data, u32 *p_spare)
error_ecc_bits = nandc_xfer_data(cs, NANDC_READ, sec_per_page,
p_data, p_spare);
if (error_ecc_bits > 2) {
PRINT_NANDC_E("FlashReadRawPage %x %x error_ecc_bits %d\n",
cs, page_addr, error_ecc_bits);
if (p_data)
PRINT_NANDC_HEX("data:", p_data, 4, 8);
if (p_spare)
PRINT_NANDC_HEX("spare:", p_spare, 4, 2);
}
nandc_flash_de_cs(cs);
if (error_ecc_bits != NAND_STS_ECC_ERR) {
if (error_ecc_bits >= (u32)nand_para.ecc_bits - 3)
ret = NAND_STS_REFRESH;
else
ret = NAND_STS_OK;
if (error_ecc_bits >= (u32)nand_para.ecc_bits - 3) {
error_ecc_bits = NAND_STS_REFRESH;
} else {
error_ecc_bits = NAND_STS_OK;
if (g_nand_ecc_en) {
u32 nand_ecc = flash_read_ecc(cs);
if (nand_ecc >= 6) {
PRINT_NANDC_E("%s nand ecc %x ecc %d\n",
__func__, page_addr, nand_ecc);
error_ecc_bits = NAND_STS_REFRESH;
}
}
}
}
return ret;
return error_ecc_bits;
}
static u32 flash_read_page(u8 cs, u32 page_addr, u32 *p_data, u32 *p_spare)
{
u32 ret;
u32 ret, i;
ret = flash_read_page_raw(cs, page_addr, p_data, p_spare);
if (ret == NAND_STS_ECC_ERR)
ret = flash_read_page_raw(cs, page_addr, p_data, p_spare);
if (ret == NAND_STS_ECC_ERR) {
for (i = 0; i < 50; i++) {
ret = flash_read_page_raw(cs, page_addr, p_data, p_spare);
if (ret != NAND_STS_ECC_ERR) {
ret = NAND_STS_REFRESH;
break;
}
}
PRINT_NANDC_E("flash_read_page %x err_ecc %d\n", page_addr, ret);
}
return ret;
}
@ -468,6 +499,7 @@ u32 nandc_flash_init(void __iomem *nandc_addr)
PRINT_NANDC_I("...%s enter...\n", __func__);
g_nand_idb_res_blk_num = MAX_IDB_RESERVED_BLOCK;
g_nand_ecc_en = 0;
nandc_init(nandc_addr);
@ -487,6 +519,8 @@ u32 nandc_flash_init(void __iomem *nandc_addr)
return FTL_UNSUPPORTED_FLASH;
}
}
if (id_byte[0][0] == 0x98 && (id_byte[0][4] & 0x80))
g_nand_ecc_en = 1;
nand_para.nand_id[1] = id_byte[0][1];
if (id_byte[0][1] == 0xDA) {
nand_para.plane_per_die = 2;
@ -497,8 +531,9 @@ u32 nandc_flash_init(void __iomem *nandc_addr)
nand_para.plane_per_die = 2;
nand_para.sec_per_page = 8;
} else if (id_byte[0][0] == 0x98 && id_byte[0][3] == 0x26) {
nand_para.blk_per_plane = 2048;
nand_para.blk_per_plane = 1024;
nand_para.sec_per_page = 8;
nand_para.plane_per_die = 2;
} else {
nand_para.plane_per_die = 2;
nand_para.blk_per_plane = 2048;

View File

@ -40,6 +40,7 @@
#define BLOCK_ERASE_CMD 0x60d0
#define READ_CMD 0x0030
#define READ_DP_OUT_CMD 0x05E0
#define READ_ECC_STATUS_CMD 0x7A
#define SAMSUNG 0x00 /* SAMSUNG */
#define TOSHIBA 0x01 /* TOSHIBA */

View File

@ -15,6 +15,11 @@
#define NAND_STS_EMPTY 512 /* page is not proged */
#define NAND_STS_ECC_ERR NAND_ERROR
#define NAND_IDB_START 64 /* 32 KB*/
#define NAND_IDB_SIZE 512 /* 256 KB*/
#define NAND_IDB_END (NAND_IDB_START + NAND_IDB_SIZE - 1)
#define DEFAULT_IDB_RESERVED_BLOCK 16
#define FULL_SLC 0
#define SLC 1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff