MICRON_ON_DIE_MANDATORY,
};
+#define MICRON_ID_INTERNAL_ECC_MASK GENMASK(1, 0)
+#define MICRON_ID_ECC_ENABLED BIT(7)
+
/*
* Try to detect if the NAND support on-die ECC. To do this, we enable
* the feature, and read back if it has been enabled as expected. We
*/
static int micron_supports_on_die_ecc(struct nand_chip *chip)
{
- u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = { 0, };
+ u8 id[5];
int ret;
if (!chip->parameters.onfi.version)
if (chip->bits_per_cell != 1)
return MICRON_ON_DIE_UNSUPPORTED;
+ /*
+ * We only support on-die ECC of 4/512 or 8/512
+ */
+ if (chip->ecc_strength_ds != 4 && chip->ecc_strength_ds != 8)
+ return MICRON_ON_DIE_UNSUPPORTED;
+
+ /* 0x2 means on-die ECC is available. */
+ if (chip->id.len != 5 ||
+ (chip->id.data[4] & MICRON_ID_INTERNAL_ECC_MASK) != 0x2)
+ return MICRON_ON_DIE_UNSUPPORTED;
+
ret = micron_nand_on_die_ecc_setup(chip, true);
if (ret)
return MICRON_ON_DIE_UNSUPPORTED;
- ret = nand_get_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature);
- if (ret < 0)
- return ret;
+ ret = nand_readid_op(chip, 0, id, sizeof(id));
+ if (ret)
+ return MICRON_ON_DIE_UNSUPPORTED;
- if ((feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN) == 0)
+ if (!(id[4] & MICRON_ID_ECC_ENABLED))
return MICRON_ON_DIE_UNSUPPORTED;
ret = micron_nand_on_die_ecc_setup(chip, false);
if (ret)
return MICRON_ON_DIE_UNSUPPORTED;
- ret = nand_get_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature);
- if (ret < 0)
- return ret;
+ ret = nand_readid_op(chip, 0, id, sizeof(id));
+ if (ret)
+ return MICRON_ON_DIE_UNSUPPORTED;
- if (feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN)
+ if (id[4] & MICRON_ID_ECC_ENABLED)
return MICRON_ON_DIE_MANDATORY;
/*