Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1183087
  • 博文数量: 221
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2139
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(221)

文章存档

2024年(6)

2023年(8)

2022年(2)

2021年(2)

2020年(29)

2019年(11)

2018年(23)

2017年(41)

2016年(76)

2015年(23)

我的朋友
最近访客

分类: LINUX

2017-10-18 11:58:55

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

阅读(6491) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~