手册请到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
12-09 23:35
查看更多