手册请到micron官方网站下载board.c void start_armboot (void) ----->nand_init(); nand.c void nand_init(void) ---> nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i])nand.c static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, ulong base_addr) ------------>nand_scan(mtd, maxchips) nand_base.c int nand_scan(struct mtd_info *mtd, int maxchips) ---> nand_scan_ident(mtd, maxchips);nand_base.c int nand_scan_ident(struct mtd_info *mtd, int maxchips) ---> nand_get_flash_type(mtd, chip, busw, &nand_maf_id);/* * Get the flash and manufacturer id and lookup if the type is supported */static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, struct nand_chip *chip, int busw, int *maf_id){ struct nand_flash_dev *type = NULL; int i, dev_id, maf_idx; int tmp_id, tmp_manf; struct nand_flash_dev_ex flash_dev_ex = {{0}, 0}; /* Select the device */ chip->select_chip(mtd, 0); /* * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) * after power-up */ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); /* Send the command for reading device ID */ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); /* Read manufacturer and device IDs *///读芯片手册里0x90地址的第一个字节 2C *maf_id = chip->read_byte(mtd);//读芯片手册里0x90地址的第二个字节 F1 dev_id = chip->read_byte(mtd); printf("nandflash *maf_id=%x\n",*maf_id); printf("nandflash dev_id=%x\n",dev_id); //从新读一遍 /* Try again to make sure, as some systems the bus-hold or other * interface concerns can cause random data which looks like a * possibly credible NAND flash to appear. If the two results do * not match, ignore the device completely. */ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); /* Read manufacturer and device IDs *///读芯片手册里0x90地址的第一个字节 2C tmp_manf = chip->read_byte(mtd);//读芯片手册里0x90地址的第二个字节 F1 tmp_id = chip->read_byte(mtd);//确认两次读的一样。 if (tmp_manf != *maf_id || tmp_id != dev_id) { printf("%s: second ID read did not match " \ "%02x,%02x against %02x,%02x\n", __func__, *maf_id, dev_id, tmp_manf, tmp_id); return ERR_PTR(-ENODEV); } /* * some nand, the id bytes signification is nonstandard * with the linux kernel. */ flash_dev_ex.ids[0] = tmp_manf; flash_dev_ex.ids[1] = tmp_id;//#define CONFIG_NAND_FLASH_HINFC610 这个宏是定义了的。#if defined(CONFIG_NAND_FLASH_HINFC504) \ || defined(CONFIG_NAND_FLASH_HINFC610) \ || defined(CONFIG_NAND_FLASH_HISNFC100) \ || defined(CONFIG_HIFMC_SPI_NAND) \ || defined(CONFIG_HIFMC_NAND)//此处调用了nand_get_special_flash_type这个函数 if (nand_get_spl_flash_type && nand_get_spl_flash_type(mtd, chip, &flash_dev_ex)) {#else#endif#if defined(CONFIG_NAND_FLASH_HINFC504) \ || defined(CONFIG_NAND_FLASH_HINFC610) \ || defined(CONFIG_NAND_FLASH_HISNFC100) \ || defined(CONFIG_HIFMC_SPI_NAND) \ || defined(CONFIG_HIFMC_NAND) type = &flash_dev_ex.flash_dev;#endif if (!mtd->name) mtd->name = type->name; //在nand_flash_special_dev表中的值通过type赋值过来给chip和mtd chip->chipsize = (uint64_t)type->chipsize mtd->erasesize = type->erasesize; mtd->writesize = type->pagesize;#if defined(CONFIG_NAND_FLASH_HINFC504) \ || defined(CONFIG_NAND_FLASH_HINFC610) \ || defined(CONFIG_NAND_FLASH_HISNFC100) \ || defined(CONFIG_HIFMC_SPI_NAND) \ || defined(CONFIG_HIFMC_NAND)//nand_flash_special_dev表中的值 oobsize mtd->oobsize = flash_dev_ex.oobsize;#else#endif busw = (type->options & NAND_BUSWIDTH_16); goto find_type; }//这个是如果在nand_flash_special_dev表中没有找到对应的芯片,则进入nand_flash_ids找通用的 /* Lookup the flash id */ for (i = 0; nand_flash_ids[i].name != NULL; i++) { //从芯片读出的dev_id字节对比nand_flash_ids表中是否有//(手册中READ ID Parameter Tables byte 1 device id) 第二个字节 if (dev_id == nand_flash_ids[i].id) { type = &nand_flash_ids[i]; break; } } if (!mtd->name) mtd->name = type->name;//nand_flash_ids表中有赋值chipsize,F1是128 chip->chipsize = (uint64_t)type->chipsize /* Newer devices have all the information in additional id bytes *///假如nand_flash_ids表中对应的那个pagesize为0的话,通过读出的ID的五个字节也是可以算出相关的值的。 if (!type->pagesize) { int extid;//第三个字节,见手册,读出的ID的五个字节也是可以算出相关的值的 /* The 3rd id byte holds MLC / multichip data */ chip->cellinfo = chip->read_byte(mtd);//第四个字节,见手册,读出的ID的五个字节也是可以算出相关的值的 /* The 4th id byte is the important one */ extid = chip->read_byte(mtd); /* Calc pagesize *///1024 mtd->writesize = 1024 extid >>= 2; //0x95 >>=2 -->1001 0101b >>=2 -->100101b /* Calc oobsize */ //8 mtd->oobsize = (8 * (mtd->writesize >> 9); extid >>= 2; /* Calc blocksize. Blocksize is multiples of 64KiB */ //0x95>>4 == 10010101b>>4 == 1001b //1001b&0x03 = 1 //(64*1024) mtd->erasesize = (64 * 1024) extid >>= 2; /* Get buswidth information */ busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; } else { /* * Old devices have chip data hardcoded in the * device id table */ mtd->erasesize = type->erasesize; mtd->writesize = type->pagesize; mtd->oobsize = mtd->writesize / 32; busw = type->options & NAND_BUSWIDTH_16; } flash_dev_ex.oobsize = mtd->oobsize; /* * the flash oobsize maybe larger than error correct * request oobsize, so I resize oobsize. */find_type:#if defined(CONFIG_NAND_FLASH_HINFC504) \ || defined(CONFIG_NAND_FLASH_HINFC610) \ || defined(CONFIG_NAND_FLASH_HISNFC100) \ || defined(CONFIG_HIFMC_SPI_NAND) \ || defined(CONFIG_HIFMC_NAND) if (nand_oob_resize && nand_oob_resize(mtd, chip, &flash_dev_ex)) return ERR_PTR(-ENODEV);#else#endif /* Try to identify manufacturer */ for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { if (nand_manuf_ids[maf_idx].id == *maf_id) break; } /* * Check, if buswidth is correct. Hardware drivers should set * chip correct ! */ if (busw != (chip->options & NAND_BUSWIDTH_16)) { printf("NAND device: Manufacturer ID:" \ " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, nand_manuf_ids[maf_idx].name, mtd->name); printf("NAND bus width %d instead %d bit\n", (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, busw ? 16 : 8); return ERR_PTR(-EINVAL); } if (nand_info_ex.type == 0) { memset(&nand_info_ex, 0, sizeof(struct mtd_info_ex)); nand_info_ex.type = MTD_NANDFLASH; nand_info_ex.chipsize = chip->chipsize; nand_info_ex.erasesize = mtd->erasesize; nand_info_ex.pagesize = mtd->writesize; /* smaller than nand chip space area */ nand_info_ex.oobsize = mtd->oobsize;#if defined(CONFIG_NAND_FLASH_HINFC504) \ || defined(CONFIG_NAND_FLASH_HINFC610) \ || defined(CONFIG_NAND_FLASH_HISNFC100) \ || defined(CONFIG_HIFMC_SPI_NAND) \ || defined(CONFIG_HIFMC_NAND) nand_info_ex.ecctype = flash_dev_ex.ecctype;#else#endif#if !defined(CONFIG_NAND_FLASH_HISNFC100) \ && !defined(CONFIG_HIFMC_SPI_NAND) nand_info_ex.id_length = 8;#else nand_info_ex.id_length = 2;#endif nand_info_ex.numchips = 1; memcpy(nand_info_ex.ids, flash_dev_ex.ids, nand_info_ex.id_length); strncpy(nand_info_ex.name, mtd->name, sizeof(nand_info_ex.name)); nand_info_ex.name[sizeof(nand_info_ex.name)-1] = '\0'; } /* Calculate the address shift from the page size */ chip->page_shift = ffs(mtd->writesize) - 1; /* Convert chipsize to number of pages per chip -1. */ chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1; if (chip->chipsize & 0xffffffff) chip->chip_shift = ffs((unsigned)chip->chipsize) - 1; else chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 31; /* Set the bad block position */ chip->badblockpos = mtd->writesize > 512 ? NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; /* Get chip options, preserve non chip based options */ chip->options &= ~NAND_CHIPOPTIONS_MSK; chip->options |= type->options & NAND_CHIPOPTIONS_MSK; /* * Set chip as a default. Board drivers can override it, * if necessary */ chip->options |= NAND_NO_AUTOINCR; /* Check if chip is a not a samsung device. Do not clear the * options for chips which are not having an extended id. */ if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; /* Check for AND chips with 4 page planes */ if (chip->options & NAND_4PAGE_ARRAY) chip->erase_cmd = multi_erase_cmd; else chip->erase_cmd = single_erase_cmd; /* Do not replace user supplied command function ! */ if (mtd->writesize > 512 && chip->cmdfunc == nand_command) chip->cmdfunc = nand_command_lp; MTDDEBUG(MTD_DEBUG_LEVEL0, "NAND device: Manufacturer ID:" \ " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, nand_manuf_ids[maf_idx].name, type->name); return type; }///////////////////////////////////////drivers/mtd/nand/nand_ids.c/** Manufacturer ID list*/struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_TOSHIBA, "Toshiba"}, {NAND_MFR_HYNIX, "Hynix"},//0x2c {NAND_MFR_MICRON, "Micron"}, {NAND_MFR_AMD, "AMD/Spansion"}, {NAND_MFR_MACRONIX, "Macronix"}, {0x0, "Unknown"}};Linux内核源码树drivers/mtd/nand/nand_ids.c文件里也有这个表//这是另外一个设备表(通用表)struct nand_flash_dev nand_flash_ids[] = { /*512 Megabit */ {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, /* 1 Gigabit */ {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS}, {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, LP_OPTIONS}, {"NAND 128MiB 3,3V 8-bit", 0xD1, 0, 128, 0, LP_OPTIONS}, {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16}, {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16}, {NULL,}};////////////////////////////////////////////////////////////void nand_spl_ids_register(void){ printf("Special NAND id table Version %s\n", DRV_VERSION); nand_get_spl_flash_type = nand_get_special_flash_type;}////////////////////////////////////////////////////////struct nand_flash_dev *nand_get_special_flash_type(struct mtd_info *mtd, struct nand_chip *chip, struct nand_flash_dev_ex *nand_dev){ int ix; struct nand_flash_special_dev *spl_dev; unsigned char *byte = nand_dev->ids; struct nand_flash_dev *flash_type = &nand_dev->flash_dev; for (ix = 2; ix byte[ix] = chip->read_byte(mtd); printf("Nand ID: 0x%02X 0x%02X 0x%02X 0x%02X" \ " 0x%02X 0x%02X 0x%02X 0x%02X\n", byte[0], byte[1], byte[2], byte[3], byte[4], byte[5], byte[6], byte[7]); for (spl_dev = nand_flash_special_dev; spl_dev->length; spl_dev++) {//查找表,找到表中8位ID值与读出的8位相同的,就是对上了。 if (memcmp(byte, spl_dev->id, spl_dev->length)) continue; printf("founded it same id flash!"); if (spl_dev->probe) { flash_type = spl_dev->probe(nand_dev); } else {//程序进入此处,赋值各个来自nand_flash_special_dev表的nandfalsh参数 flash_type->options = spl_dev->options; flash_type->pagesize = spl_dev->pagesize; flash_type->erasesize = spl_dev->erasesize; nand_dev->oobsize = spl_dev->oobsize; } nand_dev->read_retry_type = spl_dev->read_retry_type; nand_dev->flags = spl_dev->flags; flash_type->id = byte[1]; flash_type->chipsize = (unsigned long)(spl_dev->chipsize >> 20); flash_type->name = spl_dev->name; memcpy(nandtag->id, byte, 8); nandtag->length = spl_dev->length; nandtag->chipsize = spl_dev->chipsize; nandtag->pagesize = spl_dev->pagesize; nandtag->erasesize = spl_dev->erasesize; nandtag->oobsize = spl_dev->oobsize; nandtag->options = flash_type->options; strncpy(nandtag->name, flash_type->name, 16); nandtag->name[sizeof(nandtag->name)-1] = '\0'; return flash_type; } nand_dev->read_retry_type = NAND_RR_NONE; chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); chip->read_byte(mtd); chip->read_byte(mtd); return NULL;}///////////////////////////////////////////也有这个表//这是一个设备表static struct nand_flash_special_dev nand_flash_special_dev[] = { { /* SLC MT29F2G08ABAEA */ .name = "MT29F2G08ABAEA", .id = {0x2C, 0xF1, 0x00, 0x95, 0x82, 0x00, 0x00, 0x00}, .length = 5, .chipsize = _256M, .probe = NULL, .pagesize = _2K, .erasesize = _128K, .oobsize = 64, .options = 0, .read_retry_type = NAND_RR_NONE, .badblock_pos = BBP_FIRST_PAGE, .flags = 0, }, { //www.20171017 /* SLC MT29F1G08ABAEA */ .name = "MT29F1G08ABAEA", .id = {0x2C, 0xF1, 0x80, 0x95, 0x04, 0x00, 0x00, 0x00}, .length = 5, .chipsize = _128M, .probe = NULL, .pagesize = _2K, .erasesize = _128K, .oobsize = 64, .options = 0, .read_retry_type = NAND_RR_NONE, .badblock_pos = BBP_FIRST_PAGE, .flags = 0, },}/////////////////////////////////////从芯片读出的ID是Nand ID: 0x2C 0xF1 0x80 0x95 0x04 0x00 0x00 0x00