1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 293db446aSBoris Brezillon /* 393db446aSBoris Brezillon * Copyright (C) 2017 Free Electrons 493db446aSBoris Brezillon * Copyright (C) 2017 NextThing Co 593db446aSBoris Brezillon * 693db446aSBoris Brezillon * Author: Boris Brezillon <boris.brezillon@free-electrons.com> 793db446aSBoris Brezillon */ 893db446aSBoris Brezillon 9348d56a8SBoris Brezillon #include "internals.h" 1093db446aSBoris Brezillon samsung_nand_decode_id(struct nand_chip * chip)1193db446aSBoris Brezillonstatic void samsung_nand_decode_id(struct nand_chip *chip) 1293db446aSBoris Brezillon { 13*53576c7bSMiquel Raynal struct nand_device *base = &chip->base; 14*53576c7bSMiquel Raynal struct nand_ecc_props requirements = {}; 1593db446aSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(chip); 16629a442cSBoris Brezillon struct nand_memory_organization *memorg; 17629a442cSBoris Brezillon 18629a442cSBoris Brezillon memorg = nanddev_get_memorg(&chip->base); 1993db446aSBoris Brezillon 2093db446aSBoris Brezillon /* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */ 2193db446aSBoris Brezillon if (chip->id.len == 6 && !nand_is_slc(chip) && 2293db446aSBoris Brezillon chip->id.data[5] != 0x00) { 2393db446aSBoris Brezillon u8 extid = chip->id.data[3]; 2493db446aSBoris Brezillon 2593db446aSBoris Brezillon /* Get pagesize */ 26629a442cSBoris Brezillon memorg->pagesize = 2048 << (extid & 0x03); 27629a442cSBoris Brezillon mtd->writesize = memorg->pagesize; 2893db446aSBoris Brezillon 2993db446aSBoris Brezillon extid >>= 2; 3093db446aSBoris Brezillon 3193db446aSBoris Brezillon /* Get oobsize */ 3293db446aSBoris Brezillon switch (((extid >> 2) & 0x4) | (extid & 0x3)) { 3393db446aSBoris Brezillon case 1: 34629a442cSBoris Brezillon memorg->oobsize = 128; 3593db446aSBoris Brezillon break; 3693db446aSBoris Brezillon case 2: 37629a442cSBoris Brezillon memorg->oobsize = 218; 3893db446aSBoris Brezillon break; 3993db446aSBoris Brezillon case 3: 40629a442cSBoris Brezillon memorg->oobsize = 400; 4193db446aSBoris Brezillon break; 4293db446aSBoris Brezillon case 4: 43629a442cSBoris Brezillon memorg->oobsize = 436; 4493db446aSBoris Brezillon break; 4593db446aSBoris Brezillon case 5: 46629a442cSBoris Brezillon memorg->oobsize = 512; 4793db446aSBoris Brezillon break; 4893db446aSBoris Brezillon case 6: 49629a442cSBoris Brezillon memorg->oobsize = 640; 5093db446aSBoris Brezillon break; 5193db446aSBoris Brezillon default: 5293db446aSBoris Brezillon /* 5393db446aSBoris Brezillon * We should never reach this case, but if that 5493db446aSBoris Brezillon * happens, this probably means Samsung decided to use 5593db446aSBoris Brezillon * a different extended ID format, and we should find 5693db446aSBoris Brezillon * a way to support it. 5793db446aSBoris Brezillon */ 5893db446aSBoris Brezillon WARN(1, "Invalid OOB size value"); 5993db446aSBoris Brezillon break; 6093db446aSBoris Brezillon } 6193db446aSBoris Brezillon 62629a442cSBoris Brezillon mtd->oobsize = memorg->oobsize; 63629a442cSBoris Brezillon 6493db446aSBoris Brezillon /* Get blocksize */ 6593db446aSBoris Brezillon extid >>= 2; 66629a442cSBoris Brezillon memorg->pages_per_eraseblock = (128 * 1024) << 67629a442cSBoris Brezillon (((extid >> 1) & 0x04) | 68629a442cSBoris Brezillon (extid & 0x03)) / 69629a442cSBoris Brezillon memorg->pagesize; 7093db446aSBoris Brezillon mtd->erasesize = (128 * 1024) << 7193db446aSBoris Brezillon (((extid >> 1) & 0x04) | (extid & 0x03)); 7293db446aSBoris Brezillon 7393db446aSBoris Brezillon /* Extract ECC requirements from 5th id byte*/ 7493db446aSBoris Brezillon extid = (chip->id.data[4] >> 4) & 0x07; 7593db446aSBoris Brezillon if (extid < 5) { 76*53576c7bSMiquel Raynal requirements.step_size = 512; 77*53576c7bSMiquel Raynal requirements.strength = 1 << extid; 7893db446aSBoris Brezillon } else { 79*53576c7bSMiquel Raynal requirements.step_size = 1024; 8093db446aSBoris Brezillon switch (extid) { 8193db446aSBoris Brezillon case 5: 82*53576c7bSMiquel Raynal requirements.strength = 24; 8393db446aSBoris Brezillon break; 8493db446aSBoris Brezillon case 6: 85*53576c7bSMiquel Raynal requirements.strength = 40; 8693db446aSBoris Brezillon break; 8793db446aSBoris Brezillon case 7: 88*53576c7bSMiquel Raynal requirements.strength = 60; 8993db446aSBoris Brezillon break; 9093db446aSBoris Brezillon default: 9193db446aSBoris Brezillon WARN(1, "Could not decode ECC info"); 92*53576c7bSMiquel Raynal requirements.step_size = 0; 9393db446aSBoris Brezillon } 9493db446aSBoris Brezillon } 9593db446aSBoris Brezillon } else { 9693db446aSBoris Brezillon nand_decode_ext_id(chip); 9793db446aSBoris Brezillon 9893db446aSBoris Brezillon if (nand_is_slc(chip)) { 9993db446aSBoris Brezillon switch (chip->id.data[1]) { 10093db446aSBoris Brezillon /* K9F4G08U0D-S[I|C]B0(T00) */ 10193db446aSBoris Brezillon case 0xDC: 102*53576c7bSMiquel Raynal requirements.step_size = 512; 103*53576c7bSMiquel Raynal requirements.strength = 1; 10493db446aSBoris Brezillon break; 10593db446aSBoris Brezillon 10693db446aSBoris Brezillon /* K9F1G08U0E 21nm chips do not support subpage write */ 10793db446aSBoris Brezillon case 0xF1: 10893db446aSBoris Brezillon if (chip->id.len > 4 && 10993db446aSBoris Brezillon (chip->id.data[4] & GENMASK(1, 0)) == 0x1) 11093db446aSBoris Brezillon chip->options |= NAND_NO_SUBPAGE_WRITE; 11193db446aSBoris Brezillon break; 11293db446aSBoris Brezillon default: 11393db446aSBoris Brezillon break; 11493db446aSBoris Brezillon } 11593db446aSBoris Brezillon } 11693db446aSBoris Brezillon } 117*53576c7bSMiquel Raynal 118*53576c7bSMiquel Raynal nanddev_set_ecc_requirements(base, &requirements); 11993db446aSBoris Brezillon } 12093db446aSBoris Brezillon samsung_nand_init(struct nand_chip * chip)12193db446aSBoris Brezillonstatic int samsung_nand_init(struct nand_chip *chip) 12293db446aSBoris Brezillon { 12393db446aSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(chip); 12493db446aSBoris Brezillon 12593db446aSBoris Brezillon if (mtd->writesize > 512) 12693db446aSBoris Brezillon chip->options |= NAND_SAMSUNG_LP_OPTIONS; 12793db446aSBoris Brezillon 12893db446aSBoris Brezillon if (!nand_is_slc(chip)) 12904649ec1SFrieder Schrempf chip->options |= NAND_BBM_LASTPAGE; 13093db446aSBoris Brezillon else 131bb592548SFrieder Schrempf chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE; 13293db446aSBoris Brezillon 13393db446aSBoris Brezillon return 0; 13493db446aSBoris Brezillon } 13593db446aSBoris Brezillon 13693db446aSBoris Brezillon const struct nand_manufacturer_ops samsung_nand_manuf_ops = { 13793db446aSBoris Brezillon .detect = samsung_nand_decode_id, 13893db446aSBoris Brezillon .init = samsung_nand_init, 13993db446aSBoris Brezillon }; 140