|
@@ -5151,6 +5151,8 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
|
|
{
|
|
{
|
|
struct mtd_info *mtd = nand_to_mtd(chip);
|
|
struct mtd_info *mtd = nand_to_mtd(chip);
|
|
struct nand_onfi_params *p;
|
|
struct nand_onfi_params *p;
|
|
|
|
+ struct onfi_params *onfi;
|
|
|
|
+ int onfi_version = 0;
|
|
char id[4];
|
|
char id[4];
|
|
int i, ret, val;
|
|
int i, ret, val;
|
|
|
|
|
|
@@ -5206,21 +5208,19 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
|
|
/* Check version */
|
|
/* Check version */
|
|
val = le16_to_cpu(p->revision);
|
|
val = le16_to_cpu(p->revision);
|
|
if (val & ONFI_VERSION_2_3)
|
|
if (val & ONFI_VERSION_2_3)
|
|
- chip->parameters.onfi.version = 23;
|
|
|
|
|
|
+ onfi_version = 23;
|
|
else if (val & ONFI_VERSION_2_2)
|
|
else if (val & ONFI_VERSION_2_2)
|
|
- chip->parameters.onfi.version = 22;
|
|
|
|
|
|
+ onfi_version = 22;
|
|
else if (val & ONFI_VERSION_2_1)
|
|
else if (val & ONFI_VERSION_2_1)
|
|
- chip->parameters.onfi.version = 21;
|
|
|
|
|
|
+ onfi_version = 21;
|
|
else if (val & ONFI_VERSION_2_0)
|
|
else if (val & ONFI_VERSION_2_0)
|
|
- chip->parameters.onfi.version = 20;
|
|
|
|
|
|
+ onfi_version = 20;
|
|
else if (val & ONFI_VERSION_1_0)
|
|
else if (val & ONFI_VERSION_1_0)
|
|
- chip->parameters.onfi.version = 10;
|
|
|
|
|
|
+ onfi_version = 10;
|
|
|
|
|
|
- if (!chip->parameters.onfi.version) {
|
|
|
|
|
|
+ if (!onfi_version) {
|
|
pr_info("unsupported ONFI version: %d\n", val);
|
|
pr_info("unsupported ONFI version: %d\n", val);
|
|
goto free_onfi_param_page;
|
|
goto free_onfi_param_page;
|
|
- } else {
|
|
|
|
- ret = 1;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
sanitize_string(p->manufacturer, sizeof(p->manufacturer));
|
|
sanitize_string(p->manufacturer, sizeof(p->manufacturer));
|
|
@@ -5257,7 +5257,7 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
|
|
if (p->ecc_bits != 0xff) {
|
|
if (p->ecc_bits != 0xff) {
|
|
chip->ecc_strength_ds = p->ecc_bits;
|
|
chip->ecc_strength_ds = p->ecc_bits;
|
|
chip->ecc_step_ds = 512;
|
|
chip->ecc_step_ds = 512;
|
|
- } else if (chip->parameters.onfi.version >= 21 &&
|
|
|
|
|
|
+ } else if (onfi_version >= 21 &&
|
|
(le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
|
|
(le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -5284,19 +5284,33 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
|
|
bitmap_set(chip->parameters.set_feature_list,
|
|
bitmap_set(chip->parameters.set_feature_list,
|
|
ONFI_FEATURE_ADDR_TIMING_MODE, 1);
|
|
ONFI_FEATURE_ADDR_TIMING_MODE, 1);
|
|
}
|
|
}
|
|
- chip->parameters.onfi.tPROG = le16_to_cpu(p->t_prog);
|
|
|
|
- chip->parameters.onfi.tBERS = le16_to_cpu(p->t_bers);
|
|
|
|
- chip->parameters.onfi.tR = le16_to_cpu(p->t_r);
|
|
|
|
- chip->parameters.onfi.tCCS = le16_to_cpu(p->t_ccs);
|
|
|
|
- chip->parameters.onfi.async_timing_mode =
|
|
|
|
- le16_to_cpu(p->async_timing_mode);
|
|
|
|
- chip->parameters.onfi.vendor_revision =
|
|
|
|
- le16_to_cpu(p->vendor_revision);
|
|
|
|
- memcpy(chip->parameters.onfi.vendor, p->vendor,
|
|
|
|
- sizeof(p->vendor));
|
|
|
|
|
|
|
|
|
|
+ onfi = kzalloc(sizeof(*onfi), GFP_KERNEL);
|
|
|
|
+ if (!onfi) {
|
|
|
|
+ ret = -ENOMEM;
|
|
|
|
+ goto free_model;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ onfi->version = onfi_version;
|
|
|
|
+ onfi->tPROG = le16_to_cpu(p->t_prog);
|
|
|
|
+ onfi->tBERS = le16_to_cpu(p->t_bers);
|
|
|
|
+ onfi->tR = le16_to_cpu(p->t_r);
|
|
|
|
+ onfi->tCCS = le16_to_cpu(p->t_ccs);
|
|
|
|
+ onfi->async_timing_mode = le16_to_cpu(p->async_timing_mode);
|
|
|
|
+ onfi->vendor_revision = le16_to_cpu(p->vendor_revision);
|
|
|
|
+ memcpy(onfi->vendor, p->vendor, sizeof(p->vendor));
|
|
|
|
+ chip->parameters.onfi = onfi;
|
|
|
|
+
|
|
|
|
+ /* Identification done, free the full ONFI parameter page and exit */
|
|
|
|
+ kfree(p);
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+free_model:
|
|
|
|
+ kfree(chip->parameters.model);
|
|
free_onfi_param_page:
|
|
free_onfi_param_page:
|
|
kfree(p);
|
|
kfree(p);
|
|
|
|
+
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -5693,7 +5707,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- chip->parameters.onfi.version = 0;
|
|
|
|
if (!type->name || !type->pagesize) {
|
|
if (!type->name || !type->pagesize) {
|
|
/* Check if the chip is ONFI compliant */
|
|
/* Check if the chip is ONFI compliant */
|
|
ret = nand_flash_detect_onfi(chip);
|
|
ret = nand_flash_detect_onfi(chip);
|
|
@@ -6031,6 +6044,7 @@ static int nand_scan_ident(struct mtd_info *mtd, int maxchips,
|
|
static void nand_scan_ident_cleanup(struct nand_chip *chip)
|
|
static void nand_scan_ident_cleanup(struct nand_chip *chip)
|
|
{
|
|
{
|
|
kfree(chip->parameters.model);
|
|
kfree(chip->parameters.model);
|
|
|
|
+ kfree(chip->parameters.onfi);
|
|
}
|
|
}
|
|
|
|
|
|
static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
|
|
static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
|