diff --git a/drivers/rkflash/sfc_nand.c b/drivers/rkflash/sfc_nand.c index b551ade0a583..b03f8015ac61 100644 --- a/drivers/rkflash/sfc_nand.c +++ b/drivers/rkflash/sfc_nand.c @@ -34,23 +34,27 @@ static struct nand_info spi_nand_tbl[] = { /* IS37SML01G1 */ {0xC821, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x00, 18, 1, 0xB0, 0XFF, 8, 12, &sfc_nand_ecc_status_sp1}, /* W25N01GV */ - {0xEFAA, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 1, 0xFF, 0XFF, 4, 20, &sfc_nand_ecc_status_sp1}, + {0xEFAA, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xFF, 0XFF, 4, 20, &sfc_nand_ecc_status_sp1}, /* HYF2GQ4UAACAE */ - {0xC952, 4, 64, 2, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 14, 0xB0, 0, 4, 36, NULL}, + {0xC952, 4, 64, 2, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 14, 0xB0, 0, 4, 36, NULL}, /* HYF2GQ4UAACAE */ - {0xC952, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 14, 0xB0, 0, 4, 36, NULL}, + {0xC952, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 14, 0xB0, 0, 4, 36, NULL}, /* HYF2GQ4UDACAE */ - {0xC922, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 4, 0xB0, 0, 4, 20, NULL}, + {0xC922, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 4, 0xB0, 0, 4, 20, NULL}, /* HYF2GQ4UHCCAE */ - {0xC95A, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 14, 0xB0, 0, 4, 36, NULL}, + {0xC95A, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 14, 0xB0, 0, 4, 36, NULL}, /* HYF1GQ4UDACAE */ - {0xC921, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 4, 0xB0, 0, 4, 20, NULL}, + {0xC921, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 4, 0xB0, 0, 4, 20, NULL}, /* F50L1G41LB */ - {0xC801, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 1, 0xB0, 0xFF, 20, 36, NULL}, + {0xC801, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xFF, 0xFF, 20, 36, NULL}, /* XT26G02A */ - {0x0be2, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 19, 1, 0xB0, 0x0, 8, 12, &sfc_nand_ecc_status_sp3}, + {0x0be2, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 19, 1, 0xB0, 0x0, 8, 12, &sfc_nand_ecc_status_sp4}, /* XT26G01A */ - {0x0be1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 1, 0xB0, 0x0, 8, 12, &sfc_nand_ecc_status_sp3}, + {0x0be1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x4C, 18, 1, 0xB0, 0x0, 8, 12, &sfc_nand_ecc_status_sp4}, + /* FS35ND01G-S1 */ + {0xCDB1, 4, 64, 1, 1024, 0x13, 0x10, 0x03, 0x02, 0x6B, 0x32, 0xD8, 0x0C, 18, 4, 0xB0, 0x0, 16, 20, &sfc_nand_ecc_status_sp5}, + /* FS35ND02G-S2 */ + {0xCDA2, 4, 64, 1, 2048, 0x13, 0x10, 0x03, 0x02, 0x03, 0x02, 0xD8, 0x00, 19, 4, 0xFF, 0xFF, 16, 20, &sfc_nand_ecc_status_sp5}, }; static u8 id_byte[8]; @@ -269,6 +273,84 @@ u32 sfc_nand_ecc_status_sp3(void) return ret; } +/* + * ecc spectial type4: + * [0x0000], No bit errors were detected; + * [0x0001, 0x0111], Bit errors were detected and corrected. Not + * reach Flipping Bits; + * [0x1000], Multiple bit errors were detected and + * not corrected. + * [0x1100], Bit error count equals the bit flip + * detectionthreshold + * else, reserved + */ +u32 sfc_nand_ecc_status_sp4(void) +{ + int ret; + u32 i; + u8 ecc; + u8 status; + u32 timeout = 1000 * 1000; + + for (i = 0; i < timeout; i++) { + ret = sfc_nand_read_feature(0xC0, &status); + if (ret != SFC_OK) + return SFC_NAND_ECC_ERROR; + if (!(status & (1 << 0))) + break; + sfc_delay(1); + } + + ecc = (status >> 2) & 0x0f; + if (ecc < 7) + ret = SFC_NAND_ECC_OK; + else if (ecc == 7 || ecc == 12) + ret = SFC_NAND_ECC_REFRESH; + else + ret = SFC_NAND_ECC_ERROR; + + return ret; +} + +/* + * ecc spectial type5: + * [0x0], No bit errors were detected; + * [0x001, 0x011], Bit errors were detected and corrected. Not + * reach Flipping Bits; + * [0x100], Bit error count equals the bit flip + * detectionthreshold + * [0x101, 0x110], Reserved; + * [0x111], Multiple bit errors were detected and + * not corrected. + */ +u32 sfc_nand_ecc_status_sp5(void) +{ + int ret; + u32 i; + u8 ecc; + u8 status; + u32 timeout = 1000 * 1000; + + for (i = 0; i < timeout; i++) { + ret = sfc_nand_read_feature(0xC0, &status); + if (ret != SFC_OK) + return SFC_NAND_ECC_ERROR; + if (!(status & (1 << 0))) + break; + sfc_delay(1); + } + + ecc = (status >> 4) & 0x07; + if (ecc < 4) + ret = SFC_NAND_ECC_OK; + else if (ecc == 4) + ret = SFC_NAND_ECC_REFRESH; + else + ret = SFC_NAND_ECC_ERROR; + + return ret; +} + static u32 sfc_nand_erase_block(u8 cs, u32 addr) { int ret; @@ -304,8 +386,8 @@ static u32 sfc_nand_prog_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare) sfc_nand_write_en(); if (sfc_nand_dev.prog_lines == DATA_LINES_X4 && - p_nand_info->QE_address == 0xFF && - sfc_get_version() != SFC_VER_3) + p_nand_info->feature & FEA_SOFT_QOP_BIT && + sfc_get_version() < SFC_VER_3) sfc_nand_rw_preset(); sfcmd.d32 = 0; @@ -355,8 +437,8 @@ static u32 sfc_nand_read_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare) ecc_result = sfc_nand_ecc_status(); if (sfc_nand_dev.read_lines == DATA_LINES_X4 && - p_nand_info->QE_address == 0xFF && - sfc_get_version() != SFC_VER_3) + p_nand_info->feature & FEA_SOFT_QOP_BIT && + sfc_get_version() < SFC_VER_3) sfc_nand_rw_preset(); sfcmd.d32 = 0; diff --git a/drivers/rkflash/sfc_nand.h b/drivers/rkflash/sfc_nand.h index c4d92a02bd1d..a9119b26c6a2 100644 --- a/drivers/rkflash/sfc_nand.h +++ b/drivers/rkflash/sfc_nand.h @@ -22,6 +22,7 @@ #define FEA_4BIT_PROG BIT(3) #define FEA_4BYTE_ADDR BIT(4) #define FEA_4BYTE_ADDR_MODE BIT(5) +#define FEA_SOFT_QOP_BIT BIT(6) #define MID_WINBOND 0xEF #define MID_GIGADEV 0xC8 @@ -123,5 +124,7 @@ void sfc_nand_deinit(void); int sfc_nand_read_id(u8 *buf); u32 sfc_nand_ecc_status_sp1(void); u32 sfc_nand_ecc_status_sp3(void); +u32 sfc_nand_ecc_status_sp4(void); +u32 sfc_nand_ecc_status_sp5(void); #endif