Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1417399 > unrolled thread
| Started by | Boris Brezillon <boris.brezillon@free-electrons.com> |
|---|---|
| First post | 2016-06-08 15:10 +0200 |
| Last post | 2016-06-08 16:20 +0200 |
| Articles | 2 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH v2 14/15] mtd: nand: hynix: rework NAND ID decoding to extract more information Boris Brezillon <boris.brezillon@free-electrons.com> - 2016-06-08 15:10 +0200
Re: [PATCH v2 14/15] mtd: nand: hynix: rework NAND ID decoding to extract more information kbuild test robot <lkp@intel.com> - 2016-06-08 16:20 +0200
| From | Boris Brezillon <boris.brezillon@free-electrons.com> |
|---|---|
| Date | 2016-06-08 15:10 +0200 |
| Subject | [PATCH v2 14/15] mtd: nand: hynix: rework NAND ID decoding to extract more information |
| Message-ID | <rHLp8-yc-45@gated-at.bofh.it> |
The current NAND ID detection in nand_hynix.c is not handling the
different scheme used by Hynix, thus forcing developers to add new
entries in the nand_ids table each time they want to support a new MLC
NAND.
Enhance the detection logic to handle all known formats. This does not
necessarily mean we are handling all the cases, but if new formats are
discovered, the code should evolve to take them into account instead of
adding more full-id entries in the nand_ids table.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
---
drivers/mtd/nand/nand_hynix.c | 227 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 208 insertions(+), 19 deletions(-)
diff --git a/drivers/mtd/nand/nand_hynix.c b/drivers/mtd/nand/nand_hynix.c
index 06c8e8b..f73b99f 100644
--- a/drivers/mtd/nand/nand_hynix.c
+++ b/drivers/mtd/nand/nand_hynix.c
@@ -14,20 +14,54 @@
#include <linux/mtd/nand.h>
-static void hynix_nand_decode_id(struct nand_chip *chip)
+static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
+ u8 jedecid[6] = { };
+ int i = 0;
+
+ chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1);
+ for (i = 0; i < 5; i++)
+ jedecid[i] = chip->read_byte(mtd);
- /* Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) */
- if (chip->id.len == 6 && !nand_is_slc(chip)) {
- u8 tmp, extid = chip->id.data[3];
+ return !strcmp("JEDEC", jedecid);
+}
- /* Extract pagesize */
- mtd->writesize = 2048 << (extid & 0x03);
- extid >>= 2;
+static void hynix_nand_extract_oobsize(struct nand_chip *chip,
+ bool valid_jedecid)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ u8 oobsize;
- /* Extract oobsize */
- switch (((extid >> 2) & 0x4) | (extid & 0x3)) {
+ oobsize = ((chip->id.data[3] >> 2) & 0x3) |
+ ((chip->id.data[3] >> 4) & 0x4);
+
+ if (valid_jedecid) {
+ switch (oobsize) {
+ case 0:
+ mtd->oobsize = 2048;
+ break;
+ case 1:
+ mtd->oobsize = 1664;
+ break;
+ case 2:
+ mtd->oobsize = 1024;
+ break;
+ case 3:
+ mtd->oobsize = 640;
+ break;
+ default:
+ /*
+ * We should never reach this case, but if that
+ * happens, this probably means Samsung 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:
mtd->oobsize = 128;
break;
@@ -46,23 +80,178 @@ static void hynix_nand_decode_id(struct nand_chip *chip)
case 5:
mtd->oobsize = 16;
break;
- default:
+ case 6:
mtd->oobsize = 640;
break;
+ default:
+ /*
+ * We should never reach this case, but if that
+ * happens, this probably means Samsung decided to use
+ * a different extended ID format, and we should find
+ * a way to support it.
+ */
+ WARN(1, "Invalid OOB size");
+ break;
}
+ }
+}
+
+static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip,
+ bool valid_jedecid)
+{
+ u8 ecc_level = (chip->id.data[4] >> 4) & 0x7;
+
+ if (valid_jedecid) {
+ /* Reference: H27UCG8T2E datasheet */
+ chip->ecc_step_ds = 1024;
- /* Extract blocksize */
- extid >>= 2;
- tmp = ((extid >> 1) & 0x04) | (extid & 0x03);
- if (tmp < 0x03)
- mtd->erasesize = (128 * 1024) << tmp;
- else if (tmp == 0x03)
- mtd->erasesize = 768 * 1024;
- else
- mtd->erasesize = (64 * 1024) << tmp;
+ switch (ecc_level) {
+ case 0:
+ chip->ecc_step_ds = 0;
+ chip->ecc_strength_ds = 0;
+ break;
+ case 1:
+ chip->ecc_strength_ds = 4;
+ break;
+ case 2:
+ chip->ecc_strength_ds = 24;
+ break;
+ case 3:
+ chip->ecc_strength_ds = 32;
+ break;
+ case 4:
+ chip->ecc_strength_ds = 40;
+ break;
+ case 5:
+ chip->ecc_strength_ds = 50;
+ break;
+ case 6:
+ chip->ecc_strength_ds = 60;
+ break;
+ default:
+ /*
+ * We should never reach this case, but if that
+ * happens, this probably means Samsung 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] & 0x3;
+
+ if (nand_tech < 3) {
+ /* > 26nm, reference: H27UBG8T2A datasheet */
+ if (ecc_level < 5) {
+ chip->ecc_step_ds = 512;
+ chip->ecc_strength_ds = 1 << ecc_level;
+ } else if (ecc_level < 7) {
+ if (ecc_level == 5)
+ chip->ecc_step_ds = 2048;
+ else
+ chip->ecc_step_ds = 2048;
+ chip->ecc_strength_ds = 24;
+ } else {
+ /*
+ * We should never reach this case, but if that
+ * happens, this probably means Samsung 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) {
+ chip->ecc_step_ds = 0;
+ chip->ecc_strength_ds = 0;
+ } else if (ecc_level < 5) {
+ chip->ecc_step_ds = 512;
+ chip->ecc_strength_ds = 1 << (ecc_level - 1);
+ } else {
+ chip->ecc_step_ds = 1024;
+ chip->ecc_strength_ds = 24 +
+ (8 * (ecc_level - 5));
+ }
+ }
+ }
+}
+
+static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip,
+ bool valid_jedecid)
+{
+ u8 nand_tech;
+
+ /* We need scrambling on all TLC NANDs*/
+ if (chip->bits_per_cell > 2)
+ chip->options |= NAND_NEED_SCRAMBLING;
+
+ /* And on MLC NANDs with sub-3xnm process */
+ if (valid_jedecid) {
+ nand_tech = chip->id.data[5] >> 4;
+
+ /* < 3xnm */
+ if (nand_tech > 0)
+ chip->options |= NAND_NEED_SCRAMBLING;
} else {
+ nand_tech = chip->id.data[5] & 0x3;
+
+ /* < 32nm */
+ if (nand_tech > 2)
+ chip->options |= NAND_NEED_SCRAMBLING;
+ }
+}
+
+static void hynix_nand_decode_id(struct nand_chip *chip)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ bool valid_jedecid;
+ u8 tmp;
+
+ /*
+ * 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;
}
+
+ /* Extract pagesize */
+ mtd->writesize = 2048 << (chip->id.data[3] & 0x03);
+
+ 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)
+ mtd->erasesize = SZ_1M << tmp;
+ else if (tmp == 3)
+ mtd->erasesize = SZ_512K + SZ_256K;
+ else
+ 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_nand_extract_oobsize(chip, valid_jedecid);
+ hynix_nand_extract_ecc_requirements(chip, valid_jedecid);
+ hynix_nand_extract_scrambling_requirements(chip, valid_jedecid);
}
static int hynix_nand_init(struct nand_chip *chip)
--
2.7.4
[toc] | [next] | [standalone]
| From | kbuild test robot <lkp@intel.com> |
|---|---|
| Date | 2016-06-08 16:20 +0200 |
| Subject | Re: [PATCH v2 14/15] mtd: nand: hynix: rework NAND ID decoding to extract more information |
| Message-ID | <rHMuT-1eQ-49@gated-at.bofh.it> |
| In reply to | #1417399 |
[Multipart message — attachments visible in raw view] — view raw
Hi,
[auto build test ERROR on mtd/master]
[also build test ERROR on v4.7-rc2 next-20160608]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Boris-Brezillon/mtd-nand-allow-vendor-specific-detection-initialization/20160608-210755
base: git://git.infradead.org/linux-mtd.git master
config: x86_64-randconfig-s3-06081945 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
drivers/mtd/nand/nand_hynix.c: In function 'hynix_nand_decode_id':
>> drivers/mtd/nand/nand_hynix.c:239:20: error: 'SZ_1M' undeclared (first use in this function)
mtd->erasesize = SZ_1M << tmp;
^~~~~
drivers/mtd/nand/nand_hynix.c:239:20: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/mtd/nand/nand_hynix.c:241:20: error: 'SZ_512K' undeclared (first use in this function)
mtd->erasesize = SZ_512K + SZ_256K;
^~~~~~~
>> drivers/mtd/nand/nand_hynix.c:241:30: error: 'SZ_256K' undeclared (first use in this function)
mtd->erasesize = SZ_512K + SZ_256K;
^~~~~~~
>> drivers/mtd/nand/nand_hynix.c:243:20: error: 'SZ_128K' undeclared (first use in this function)
mtd->erasesize = SZ_128K << tmp;
^~~~~~~
vim +/SZ_1M +239 drivers/mtd/nand/nand_hynix.c
233 * we start counting at 128KiB and shift this value the content of
234 * ID[3][4:5].
235 * The only exception is when ID[3][4:5] == 3 and ID[3][7] == 0, in
236 * this case the erasesize is set to 768KiB.
237 */
238 if (chip->id.data[3] & 0x80)
> 239 mtd->erasesize = SZ_1M << tmp;
240 else if (tmp == 3)
> 241 mtd->erasesize = SZ_512K + SZ_256K;
242 else
> 243 mtd->erasesize = SZ_128K << tmp;
244
245 /*
246 * Modern Toggle DDR NANDs have a valid JEDECID even though they are
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web