nand: fix nand bugs [1/1]

PD#SWPL-120491
PD#SWPL-129754
PD#SWPL-155674
PD#SWPL-183416

Problem:
1.wrong select onfi mode
2.erase flash error during OTA upgrade
3.strncmp can't match full id 01h,DCh,00h,05h,04h(S34ML04G300BHI00)
and 01h,DCh,00h,1Ah,00h(S34ML04G300TFI000)
4.mtd_device_parse_register panic when parse_mtd_partitions return -EPROBE_DEFER

Solution:
1.get onfi mode from id table
2.change the check way of badblock
3.use memcmp to compare ID memory instead strncmp
4.nvmem_unregister otp_user_nvmem/otp_factory_nvmem if them existing

Verify:
1-2:s4
3:AT301_T962D4-K35E(1.5G) #256
4:BR309-T950D5_SOCKET #48

Change-Id: Ie747ceb95f1045c2acaaf2afb6862c9b05d36d8b
Signed-off-by: Bichao Zheng <bichao.zheng@amlogic.com>
Signed-off-by: zhikui.cui <zhikui.cui@amlogic.com>
This commit is contained in:
Bichao Zheng
2023-04-20 16:23:24 +08:00
committed by Dongjin Kim
parent 146c08e2ed
commit e4fe4d2af5
5 changed files with 51 additions and 2 deletions

View File

@@ -1008,8 +1008,15 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
out:
if (ret) {
#if (IS_ENABLED(CONFIG_AMLOGIC_MTD_NAND) || IS_ENABLED(CONFIG_AMLOGIC_MTD_SPI_NAND))
if (mtd->otp_user_nvmem)
nvmem_unregister(mtd->otp_user_nvmem);
if (mtd->otp_factory_nvmem)
nvmem_unregister(mtd->otp_factory_nvmem);
#else
nvmem_unregister(mtd->otp_user_nvmem);
nvmem_unregister(mtd->otp_factory_nvmem);
#endif
}
if (ret && device_is_registered(&mtd->dev))

View File

@@ -963,6 +963,10 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip,
return ret;
}
#if IS_ENABLED(CONFIG_AMLOGIC_MTD_NAND)
EXPORT_SYMBOL_GPL(nand_choose_best_sdr_timings);
#endif
/**
* nand_choose_best_nvddr_timings - Pick up the best NVDDR timings that both the
* NAND controller and the NAND chip support
@@ -4891,7 +4895,12 @@ static bool find_full_id_nand(struct nand_chip *chip,
memorg = nanddev_get_memorg(&chip->base);
#if IS_ENABLED(CONFIG_AMLOGIC_MTD_NAND)
if (!memcmp(type->id, id_data, type->id_len)) {
#else
if (!strncmp(type->id, id_data, type->id_len)) {
#endif
memorg->pagesize = type->pagesize;
mtd->writesize = memorg->pagesize;
memorg->pages_per_eraseblock = type->erasesize /
@@ -5151,7 +5160,9 @@ ident_done:
chip->options |= NAND_ROW_ADDR_3;
chip->badblockbits = 8;
#if IS_ENABLED(CONFIG_AMLOGIC_MTD_NAND)
chip->type = type;
#endif
nand_legacy_adjust_cmdfunc(chip);
pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",

View File

@@ -75,9 +75,16 @@
static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block)
{
#if !IS_ENABLED(CONFIG_AMLOGIC_MTD_NAND)
uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT];
entry >>= (block & BBT_ENTRY_MASK) * 2;
return entry & BBT_ENTRY_MASK;
#else
if (chip->bbt)
return chip->bbt[block];
return 1;
#endif
}
static inline void bbt_mark_entry(struct nand_chip *chip, int block,
@@ -1454,7 +1461,7 @@ int nand_isbad_bbt(struct nand_chip *this, loff_t offs, int allowbbt)
pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
(unsigned int)offs, block, res);
#if !IS_ENABLED(CONFIG_AMLOGIC_MTD_NAND)
switch (res) {
case BBT_BLOCK_GOOD:
return 0;
@@ -1464,6 +1471,9 @@ int nand_isbad_bbt(struct nand_chip *this, loff_t offs, int allowbbt)
return allowbbt ? 0 : 1;
}
return 1;
#else
return res ? 1 : 0;
#endif
}
/**

View File

@@ -735,3 +735,7 @@ void onfi_fill_interface_config(struct nand_chip *chip,
else
return onfi_fill_nvddr_interface_config(chip, iface, timing_mode);
}
#if IS_ENABLED(CONFIG_AMLOGIC_MTD_NAND)
EXPORT_SYMBOL_GPL(onfi_fill_interface_config);
#endif

View File

@@ -1304,6 +1304,9 @@ struct nand_chip {
/* Externals */
struct nand_controller *controller;
struct nand_ecc_ctrl ecc;
#if IS_ENABLED(CONFIG_AMLOGIC_MTD_NAND)
struct nand_flash_dev *type;
#endif
void *priv;
};
@@ -1432,6 +1435,9 @@ struct nand_flash_dev {
uint16_t strength_ds;
uint16_t step_ds;
} ecc;
#if IS_ENABLED(CONFIG_AMLOGIC_MTD_NAND)
int onfi_timing_mode_default;
#endif
};
int nand_create_bbt(struct nand_chip *chip);
@@ -1548,6 +1554,17 @@ int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf,
int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips,
struct nand_flash_dev *ids);
#if IS_ENABLED(CONFIG_AMLOGIC_MTD_NAND)
void onfi_fill_interface_config(struct nand_chip *chip,
struct nand_interface_config *iface,
enum nand_interface_type type,
unsigned int timing_mode);
int nand_choose_best_sdr_timings(struct nand_chip *chip,
struct nand_interface_config *iface,
struct nand_sdr_timings *spec_timings);
#endif
static inline int nand_scan(struct nand_chip *chip, unsigned int max_chips)
{
return nand_scan_with_ids(chip, max_chips, NULL);