手册请到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 << 20;
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 << 20;
/* 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<<(0x95&0x03) == 1024<<1 == 2048 == _2K
mtd->writesize = 1024 << (extid & 0x3);
extid >>= 2; //0x95 >>=2 -->1001 0101b >>=2 -->100101b
/* Calc oobsize */
//8<<1 * 100b == 16*4 == 64
mtd->oobsize = (8 << (extid & 0x01))
* (mtd->writesize >> 9);
extid >>= 2;
/* Calc blocksize. Blocksize is multiples of 64KiB */
//0x95>>4 == 10010101b>>4 == 1001b
//1001b&0x03 = 1
//(64*1024)<<1 == 128K 也通过手册看出此处就是block size 128k
mtd->erasesize = (64 * 1024) << (extid & 0x03);
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 < 8; 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,
},
{
//
/* 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