Skip to content

Commit dbc44ed

Browse files
Boris Brezillonmiquelraynal
authored andcommitted
mtd: rawnand: micron: Fix on-die ECC detection logic
Basing the "mandatory on-die" detection on ID byte 2 does not work, because Micron has plenty of NANDs using the same device ID code, and not all of them have forcibly enabled on-die ECC. Since the "Array Operation" feature does not provide the "ECC enabled/disabled" bit when the ECC can't be disabled, let's try to use the "ECC enabled/disabled" bit in the READ_ID bytes. It seems that this bit is dynamically updated on NANDs where on-die ECC can freely be enabled/disabled, so let's hope it stays at one when we have a NAND with on-die ECC forcibly enabled. Fixes: 51f3b3970a8c ("mtd: rawnand: micron: detect forced on-die ECC") Signed-off-by: Boris Brezillon <[email protected]> Tested-by: Chris Packham <[email protected]> Signed-off-by: Miquel Raynal <[email protected]>
1 parent 79e1ca3 commit dbc44ed

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

drivers/mtd/nand/raw/nand_micron.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ enum {
196196
MICRON_ON_DIE_MANDATORY,
197197
};
198198

199+
#define MICRON_ID_INTERNAL_ECC_MASK GENMASK(1, 0)
200+
#define MICRON_ID_ECC_ENABLED BIT(7)
201+
199202
/*
200203
* Try to detect if the NAND support on-die ECC. To do this, we enable
201204
* the feature, and read back if it has been enabled as expected. We
@@ -208,7 +211,7 @@ enum {
208211
*/
209212
static int micron_supports_on_die_ecc(struct nand_chip *chip)
210213
{
211-
u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = { 0, };
214+
u8 id[5];
212215
int ret;
213216

214217
if (!chip->parameters.onfi.version)
@@ -217,26 +220,37 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
217220
if (chip->bits_per_cell != 1)
218221
return MICRON_ON_DIE_UNSUPPORTED;
219222

223+
/*
224+
* We only support on-die ECC of 4/512 or 8/512
225+
*/
226+
if (chip->ecc_strength_ds != 4 && chip->ecc_strength_ds != 8)
227+
return MICRON_ON_DIE_UNSUPPORTED;
228+
229+
/* 0x2 means on-die ECC is available. */
230+
if (chip->id.len != 5 ||
231+
(chip->id.data[4] & MICRON_ID_INTERNAL_ECC_MASK) != 0x2)
232+
return MICRON_ON_DIE_UNSUPPORTED;
233+
220234
ret = micron_nand_on_die_ecc_setup(chip, true);
221235
if (ret)
222236
return MICRON_ON_DIE_UNSUPPORTED;
223237

224-
ret = nand_get_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature);
225-
if (ret < 0)
226-
return ret;
238+
ret = nand_readid_op(chip, 0, id, sizeof(id));
239+
if (ret)
240+
return MICRON_ON_DIE_UNSUPPORTED;
227241

228-
if ((feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN) == 0)
242+
if (!(id[4] & MICRON_ID_ECC_ENABLED))
229243
return MICRON_ON_DIE_UNSUPPORTED;
230244

231245
ret = micron_nand_on_die_ecc_setup(chip, false);
232246
if (ret)
233247
return MICRON_ON_DIE_UNSUPPORTED;
234248

235-
ret = nand_get_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature);
236-
if (ret < 0)
237-
return ret;
249+
ret = nand_readid_op(chip, 0, id, sizeof(id));
250+
if (ret)
251+
return MICRON_ON_DIE_UNSUPPORTED;
238252

239-
if (feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN)
253+
if (id[4] & MICRON_ID_ECC_ENABLED)
240254
return MICRON_ON_DIE_MANDATORY;
241255

242256
/*

0 commit comments

Comments
 (0)