uboot之nandflash MT29F1G08ABAEA

手册请到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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xx-xx-xxx-xxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值