/** * struct hynix_read_retry - read-retry data * @nregs: number of register to set when applying a new read-retry mode * @regs: register offsets (NAND chip dependent) * @values: array of values to set in registers. The array size is equal to * (nregs * nmodes)
*/ struct hynix_read_retry { int nregs; const u8 *regs;
u8 values[];
};
/** * struct hynix_read_retry_otp - structure describing how the read-retry OTP * area * @nregs: number of hynix private registers to set before reading the reading * the OTP area * @regs: registers that should be configured * @values: values that should be set in regs * @page: the address to pass to the READ_PAGE command. Depends on the NAND * chip * @size: size of the read-retry OTP section
*/ struct hynix_read_retry_otp { int nregs; const u8 *regs; const u8 *values; int page; int size;
};
/* Enter 'Set Hynix Parameters' mode */
ret = hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_SET_PARAMS); if (ret) return ret;
/* * Configure the NAND in the requested read-retry mode. * This is done by setting pre-defined values in internal NAND * registers. * * The set of registers is NAND specific, and the values are either * predefined or extracted from an OTP area on the NAND (values are * probably tweaked at production in this case).
*/ for (i = 0; i < hynix->read_retry->nregs; i++) {
ret = hynix_nand_reg_write_op(chip, hynix->read_retry->regs[i],
values[i]); if (ret) return ret;
}
/* Apply the new settings. */ return hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_APPLY_PARAMS);
}
/** * hynix_get_majority - get the value that is occurring the most in a given * set of values * @in: the array of values to test * @repeat: the size of the in array * @out: pointer used to store the output value * * This function implements the 'majority check' logic that is supposed to * overcome the unreliability of MLC NANDs when reading the OTP area storing * the read-retry parameters. * * It's based on a pretty simple assumption: if we repeat the same value * several times and then take the one that is occurring the most, we should * find the correct value. * Let's hope this dummy algorithm prevents us from losing the read-retry * parameters.
*/ staticint hynix_get_majority(const u8 *in, int repeat, u8 *out)
{ int i, j, half = repeat / 2;
/* * We only test the first half of the in array because we must ensure * that the value is at least occurring repeat / 2 times. * * This loop is suboptimal since we may count the occurrences of the * same value several time, but we are doing that on small sets, which * makes it acceptable.
*/ for (i = 0; i < half; i++) { int cnt = 0;
u8 val = in[i];
/* Count all values that are matching the one at index i. */ for (j = i + 1; j < repeat; j++) { if (in[j] == val)
cnt++;
}
/* We found a value occurring more than repeat / 2. */ if (cnt > half) {
*out = val; return 0;
}
}
return -EIO;
}
staticint hynix_read_rr_otp(struct nand_chip *chip, conststruct hynix_read_retry_otp *info, void *buf)
{ int i, ret;
ret = nand_reset_op(chip); if (ret) return ret;
ret = hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_SET_PARAMS); if (ret) return ret;
for (i = 0; i < info->nregs; i++) {
ret = hynix_nand_reg_write_op(chip, info->regs[i],
info->values[i]); if (ret) return ret;
}
ret = hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_APPLY_PARAMS); if (ret) return ret;
/* Sequence to enter OTP mode? */
ret = hynix_nand_cmd_op(chip, 0x17); if (ret) return ret;
ret = hynix_nand_cmd_op(chip, 0x4); if (ret) return ret;
ret = hynix_nand_cmd_op(chip, 0x19); if (ret) return ret;
/* Now read the page */
ret = nand_read_page_op(chip, info->page, 0, buf, info->size); if (ret) return ret;
/* Put everything back to normal */
ret = nand_reset_op(chip); if (ret) return ret;
ret = hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_SET_PARAMS); if (ret) return ret;
ret = hynix_nand_reg_write_op(chip, 0x38, 0); if (ret) return ret;
ret = hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_APPLY_PARAMS); if (ret) return ret;
staticint hynix_mlc_1xnm_rr_value(const u8 *buf, int nmodes, int nregs, int mode, int reg, bool inv, u8 *val)
{
u8 tmp[NAND_HYNIX_1XNM_RR_REPEAT]; int val_offs = (mode * nregs) + reg; int set_size = nmodes * nregs; int i, ret;
for (i = 0; i < NAND_HYNIX_1XNM_RR_REPEAT; i++) { int set_offs = NAND_HYNIX_1XNM_RR_SET_OFFS(i, set_size, inv);
tmp[i] = buf[val_offs + set_offs];
}
ret = hynix_get_majority(tmp, NAND_HYNIX_1XNM_RR_REPEAT, val); if (ret) return ret;
/* * We only support read-retry for 1xnm NANDs, and those NANDs all * expose a valid JEDEC ID. SLC NANDs don't require read-retry.
*/ if (valid_jedecid && nanddev_bits_per_cell(&chip->base) > 1) {
u8 nand_tech = chip->id.data[5] >> 4;
/* 1xnm technology */ if (nand_tech == 4) { for (i = 0; i < ARRAY_SIZE(hynix_mlc_1xnm_rr_otps);
i++) { /* * FIXME: Hynix recommend to copy the * read-retry OTP area into a normal page.
*/
ret = hynix_mlc_1xnm_rr_init(chip,
hynix_mlc_1xnm_rr_otps); if (!ret) break;
}
}
}
if (ret)
pr_warn("failed to initialize read-retry infrastructure");
if (valid_jedecid) { switch (oobsize) { case 0:
memorg->oobsize = 2048; break; case 1:
memorg->oobsize = 1664; break; case 2:
memorg->oobsize = 1024; break; case 3:
memorg->oobsize = 640; break; default: /* * We should never reach this case, but if that * happens, this probably means Hynix decided to use * a different extended ID format, and we should find * a way to support it.
*/
WARN(1, "Invalid OOB size"); break;
}
} else { switch (oobsize) { case 0:
memorg->oobsize = 128; break; case 1:
memorg->oobsize = 224; break; case 2:
memorg->oobsize = 448; break; case 3:
memorg->oobsize = 64; break; case 4:
memorg->oobsize = 32; break; case 5:
memorg->oobsize = 16; break; case 6:
memorg->oobsize = 640; break; default: /* * We should never reach this case, but if that * happens, this probably means Hynix decided to use * a different extended ID format, and we should find * a way to support it.
*/
WARN(1, "Invalid OOB size"); break;
}
/* * The datasheet of H27UCG8T2BTR mentions that the "Redundant * Area Size" is encoded "per 8KB" (page size). This chip uses * a page size of 16KiB. The datasheet mentions an OOB size of * 1.280 bytes, but the OOB size encoded in the ID bytes (using * the existing logic above) is 640 bytes. * Update the OOB size for this chip by taking the value * determined above and scaling it to the actual page size (so * the actual OOB size for this chip is: 640 * 16k / 8k).
*/ if (chip->id.data[1] == 0xde)
memorg->oobsize *= memorg->pagesize / SZ_8K;
}
switch (ecc_level) { case 0:
requirements.step_size = 0;
requirements.strength = 0; break; case 1:
requirements.strength = 4; break; case 2:
requirements.strength = 24; break; case 3:
requirements.strength = 32; break; case 4:
requirements.strength = 40; break; case 5:
requirements.strength = 50; break; case 6:
requirements.strength = 60; break; default: /* * We should never reach this case, but if that * happens, this probably means Hynix decided to use * a different extended ID format, and we should find * a way to support it.
*/
WARN(1, "Invalid ECC requirements");
}
} else { /* * The ECC requirements field meaning depends on the * NAND technology.
*/
u8 nand_tech = chip->id.data[5] & 0x7;
if (nand_tech < 3) { /* > 26nm, reference: H27UBG8T2A datasheet */ if (ecc_level < 5) {
requirements.step_size = 512;
requirements.strength = 1 << ecc_level;
} elseif (ecc_level < 7) { if (ecc_level == 5)
requirements.step_size = 2048; else
requirements.step_size = 1024;
requirements.strength = 24;
} else { /* * We should never reach this case, but if that * happens, this probably means Hynix decided * to use a different extended ID format, and * we should find a way to support it.
*/
WARN(1, "Invalid ECC requirements");
}
} else { /* <= 26nm, reference: H27UBG8T2B datasheet */ if (!ecc_level) {
requirements.step_size = 0;
requirements.strength = 0;
} elseif (ecc_level < 5) {
requirements.step_size = 512;
requirements.strength = 1 << (ecc_level - 1);
} else {
requirements.step_size = 1024;
requirements.strength = 24 +
(8 * (ecc_level - 5));
}
}
}
/* * Exclude all SLC NANDs from this advanced detection scheme. * According to the ranges defined in several datasheets, it might * appear that even SLC NANDs could fall in this extended ID scheme. * If that the case rework the test to let SLC NANDs go through the * detection process.
*/ if (chip->id.len < 6 || nand_is_slc(chip)) {
nand_decode_ext_id(chip); return;
}
tmp = (chip->id.data[3] >> 4) & 0x3; /* * When bit7 is set that means we start counting at 1MiB, otherwise * we start counting at 128KiB and shift this value the content of * ID[3][4:5]. * The only exception is when ID[3][4:5] == 3 and ID[3][7] == 0, in * this case the erasesize is set to 768KiB.
*/ if (chip->id.data[3] & 0x80) {
memorg->pages_per_eraseblock = (SZ_1M << tmp) /
memorg->pagesize;
mtd->erasesize = SZ_1M << tmp;
} elseif (tmp == 3) {
memorg->pages_per_eraseblock = (SZ_512K + SZ_256K) /
memorg->pagesize;
mtd->erasesize = SZ_512K + SZ_256K;
} else {
memorg->pages_per_eraseblock = (SZ_128K << tmp) /
memorg->pagesize;
mtd->erasesize = SZ_128K << tmp;
}
/* * Modern Toggle DDR NANDs have a valid JEDECID even though they are * not exposing a valid JEDEC parameter table. * These NANDs use a different NAND ID scheme.
*/
valid_jedecid = hynix_nand_has_valid_jedecid(chip);
hynix = kzalloc(sizeof(*hynix), GFP_KERNEL); if (!hynix) return -ENOMEM;
nand_set_manufacturer_data(chip, hynix);
if (!strncmp("H27UCG8T2ATR-BC", chip->parameters.model, sizeof("H27UCG8T2ATR-BC") - 1))
chip->ops.choose_interface_config =
h27ucg8t2atrbc_choose_interface_config;
if (!strncmp("H27UCG8T2ETR-BC", chip->parameters.model, sizeof("H27UCG8T2ETR-BC") - 1))
h27ucg8t2etrbc_init(chip);
ret = hynix_nand_rr_init(chip); if (ret)
hynix_nand_cleanup(chip);
return ret;
}
staticvoid hynix_fixup_onfi_param_page(struct nand_chip *chip, struct nand_onfi_params *p)
{ /* * Certain chips might report a 0 on sdr_timing_mode field * (bytes 129-130). This has been seen on H27U4G8F2GDA-BI. * According to ONFI specification, bit 0 of this field "shall be 1". * Forcibly set this bit.
*/
p->sdr_timing_modes |= cpu_to_le16(BIT(0));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.