Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1206684
  • 博文数量: 56
  • 博客积分: 400
  • 博客等级: 一等列兵
  • 技术积分: 2800
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-30 13:08
个人简介

一个人的差异在于业余时间

文章分类

全部博文(56)

文章存档

2023年(1)

2019年(1)

2018年(1)

2017年(1)

2016年(2)

2015年(20)

2014年(10)

2013年(7)

2012年(12)

2011年(1)

分类: LINUX

2013-06-14 22:11:21

    在上一篇mtd框架中我们真正的东西并不多,也就是明白到底当我们看/dev/mtd0 /dev/mtdblock0 为什么会一样的效果. 理清了它们之间的关系.这里我们就nand flash驱动代码和mtd框架是如何结合的.
   话不多说了,从初始化代码我们来分析: 
  

点击(此处)折叠或打开

  1. int __init XXX_nand_init(void)
  2. {
  3.     struct nand_chip *this;
  4.     int err = 0;
  5.     int num_of_parts = 0;
  6.     const char *part_type = 0;
  7.     struct mtd_partition *mtd_parts = 0;
  8.     u32 physaddr;
  9.     int nand_dev_num;
  10.     MV_CPU_DEC_WIN addr_win;
  11.     ...

  12.     physaddr = addr_win.addrWin.baseLow;

  13.     mv_mtd = kmalloc(sizeof(struct mtd_info)+sizeof(struct nand_chip), GFP_KERNEL);
  14.     if (!mv_mtd) {
  15.         printk(KERN_INFO "Failed to allocate NAND MTD structuren");
  16.         err = -ENOMEM;
  17.         goto out;
  18.     }

  19.     memset((char *)mv_mtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip));

  20.     baseaddr = (unsigned long)ioremap(physaddr, 1024);
  21.     if (!baseaddr) {
  22.         printk(KERN_INFO "Failed to remap NAND MTDn");
  23.         err = -EIO;
  24.         goto out_mtd;
  25.     }

  26.     this = (struct nand_chip *)((char *)mv_mtd+sizeof(struct mtd_info));
  27.     mv_mtd->priv = this;
  28.     this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)baseaddr;
  29.     this->cmd_ctrl = board_hwcontrol;
  30. #ifdef CONFIG_MTD_NAND_LNC_8BYTE_READ
  31.     this->read_buf = mv_nand_read_buf;
  32. #endif

  33. this->ecc.mode = NAND_ECC_NONE;

  34.     this->chip_delay = 100;
  35.     if (nand_scan(mv_mtd, 1)) {
  36.         err = -ENXIO;
  37.         goto out_ior;
  38.     }

  39. #ifdef CONFIG_MTD_PARTITIONS
  40.     mv_mtd->name = "nand_mtd";
  41.     num_of_parts = parse_mtd_partitions(mv_mtd, part_probes, &mtd_parts, 0, "");
  42.     if (num_of_parts > 0)
  43.         part_type = "command line";
  44.     else
  45.         num_of_parts = 0;
  46.     if (num_of_parts == 0) {
  47.         mtd_parts = nand_parts_info;
  48.         num_of_parts = MV_NUM_OF_NAND_PARTS;
  49.         part_type = "static";
  50.     }

  51.     printk(KERN_INFO "Using %s partition definitionn", part_type);
  52.     add_mtd_partitions(mv_mtd, mtd_parts, num_of_parts);
  53. #endif
  54.     goto out;

  55. out_ior:
  56.     iounmap((void *)baseaddr);
  57. out_mtd:
  58.     kfree(mv_mtd);
  59. out:
  60.     return err;
  61. }
这里是硬件驱动的一个框架,关键部分黑体表示.
我们来看这一行: this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)baseaddr;
这里的IO地址表示的nand flash映射的reg地址,直接操作即可操作nandflash控制器,进而操作nandflash存储芯片.
具体的时序操作控制我们这里看到:  this->cmd_ctrl = board_hwcontrol;

点击(此处)折叠或打开

  1. static void board_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
  2. {
  3.     struct nand_chip *this = (struct nand_chip *)mtd->priv;
  4.     if (ctrl & NAND_CTRL_CHANGE) {
  5.         this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~3);
  6.         ctrl &= ~NAND_CTRL_CHANGE;
  7.         switch (ctrl) {
  8.         case NAND_CTRL_CLE:
  9.             this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | 1); /*x8=>1, x16=>2*/
  10.             break;
  11.         case NAND_CTRL_ALE:
  12.             this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | 2); /*x8=>2, x16=>4*/
  13.             break;
  14.         }
  15.     }
  16.     if (cmd != NAND_CMD_NONE)
  17.         writeb(cmd, this->IO_ADDR_W);
  18. }

其实就是根据nand flash时序的操作过程,来对io地址来进行不同的写值操作. 后面我们还很多函数用到它.
这里我们发现的是mv_mtd是如何初始化的呢? 包括struct nand_chip this;我们继续往后面看nand_scan函数

点击(此处)折叠或打开

  1. /**
  2.  * nand_scan - [NAND Interface] Scan for the NAND device
  3.  * @mtd:    MTD device structure
  4.  * @maxchips:    Number of chips to scan for
  5.  *
  6.  * This fills out all the uninitialized function pointers
  7.  * with the defaults.
  8.  * The flash ID is read and the mtd/chip structures are
  9.  * filled with the appropriate values.
  10.  * The mtd->owner field must be set to the module of the caller
  11.  *
  12.  */
  13. int nand_scan(struct mtd_info *mtd, int maxchips)
  14. {
  15.     int ret;

  16.     /* Many callers got this wrong, so check for it for a while... */
  17.     if (!mtd->owner && caller_is_module()) {
  18.         printk(KERN_CRIT "%s called with NULL mtd->owner!n",
  19.                 __func__);
  20.         BUG();
  21.     }

  22.     ret = nand_scan_ident(mtd, maxchips);
  23.     if (!ret)
  24.         ret = nand_scan_tail(mtd);
  25.     return ret;
  26. }
这个函数是在nand_base.c中实现的,它包含了两个重要的函数: 

点击(此处)折叠或打开

  1. /**
  2.  * nand_scan_ident - [NAND Interface] Scan for the NAND device
  3.  * @mtd:     MTD device structure
  4.  * @maxchips:     Number of chips to scan for
  5.  *
  6.  * This is the first phase of the normal nand_scan() function. It
  7.  * reads the flash ID and sets up MTD fields accordingly.
  8.  *
  9.  * The mtd->owner field must be set to the module of the caller.
  10.  */
  11. int nand_scan_ident(struct mtd_info *mtd, int maxchips)
  12. {
  13.     int i, busw, nand_maf_id;
  14.     struct nand_chip *chip = mtd->priv;
  15.     struct nand_flash_dev *type;

  16.     /* Get buswidth to select the correct functions */
  17.     busw = chip->options & NAND_BUSWIDTH_16;
  18.     /* Set the default functions */
  19.     nand_set_defaults(chip, busw);

  20.     /* Read the flash type */
  21.     type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);

  22.     if (IS_ERR(type)) {
  23.         printk(KERN_WARNING "No NAND device found!!!n");
  24.         chip->select_chip(mtd, -1);
  25.         return PTR_ERR(type);
  26.     }

  27.     /* Check for a chip array */
  28.     for (i = 1; i < maxchips; i++) {
  29.         chip->select_chip(mtd, i);
  30.         /* See comment in nand_get_flash_type for reset */
  31.         chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
  32.         /* Send the command for reading device ID */
  33.         chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
  34.         /* Read manufacturer and device IDs */
  35.         if (nand_maf_id != chip->read_byte(mtd) ||
  36.          type->id != chip->read_byte(mtd))
  37.             break;
  38.     }
  39.     if (i > 1)
  40.         printk(KERN_INFO "%d NAND chips detectedn", i);

  41.     /* Store the number of chips and calc total size for mtd */
  42.     chip->numchips = i;
  43.     mtd->size = i * chip->chipsize;

  44.     return 0;
  45. }
这里我们看粗体部分的它们是在什么地方初始化的呢? 
我们忽略了代码开始的一个函数: nand_set_defaults(chip, busw);

点击(此处)折叠或打开

  1. /*
  2.  * Set default functions
  3.  */
  4. static void nand_set_defaults(struct nand_chip *chip, int busw)
  5. {
  6.     /* check for proper chip_delay setup, set 20us if not */
  7.     if (!chip->chip_delay)
  8.         chip->chip_delay = 20;

  9.     /* check, if a user supplied command function given */
  10.     if (chip->cmdfunc == NULL)
  11.         chip->cmdfunc = nand_command;

  12.     /* check, if a user supplied wait function given */
  13.     if (chip->waitfunc == NULL)
  14.         chip->waitfunc = nand_wait;

  15.     if (!chip->select_chip)
  16.         chip->select_chip = nand_select_chip;
  17.     if (!chip->read_byte)
  18.         chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
  19.     if (!chip->read_word)
  20.         chip->read_word = nand_read_word;
  21.     if (!chip->block_bad)
  22.         chip->block_bad = nand_block_bad;
  23.     if (!chip->block_markbad)
  24.         chip->block_markbad = nand_default_block_markbad;
  25.     if (!chip->write_buf)
  26.         chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
  27.     if (!chip->read_buf)
  28.         chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
  29.     if (!chip->verify_buf)
  30.         chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
  31.     if (!chip->scan_bbt)
  32.         chip->scan_bbt = nand_default_bbt;

  33.     if (!chip->controller) {
  34.         chip->controller = &chip->hwcontrol;
  35.         spin_lock_init(&chip->controller->lock);
  36.         init_waitqueue_head(&chip->controller->wq);
  37.     }

  38. }
我们看到它们的默认初始化:
 chip->cmdfunc = nand_command;
 chip->select_chip = nand_select_chip;
 chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
... 这里我们不在一一列出.
我们明显看出它们初始化的函数都在mtd框架里的实现的函数,似乎和真正的nand flash驱动没有什么关系,它们是如何真正运作的呢?
我们那nand_command来做简单的分析,就会明白了.

点击(此处)折叠或打开

  1. /**
  2.  * nand_command - [DEFAULT] Send command to NAND device
  3.  * @mtd:    MTD device structure
  4.  * @command:    the command to be sent
  5.  * @column:    the column address for this command, -1 if none
  6.  * @page_addr:    the page address for this command, -1 if none
  7.  *
  8.  * Send command to NAND device. This function is used for small page
  9.  * devices (256/512 Bytes per page)
  10.  */
  11. static void nand_command(struct mtd_info *mtd, unsigned int command,
  12.              int column, int page_addr)
  13. {
  14.     register struct nand_chip *chip = mtd->priv;
  15.     int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;

  16.     /*
  17.      * Write out the command to the device.
  18.      */
  19.     if (command == NAND_CMD_SEQIN) {
  20.         int readcmd;

  21.         if (column >= mtd->writesize) {
  22.             /* OOB area */
  23.             column -= mtd->writesize;
  24.             readcmd = NAND_CMD_READOOB;
  25.         } else if (column < 256) {
  26.             /* First 256 bytes --> READ0 */
  27.             readcmd = NAND_CMD_READ0;
  28.         } else {
  29.             column -= 256;
  30.             readcmd = NAND_CMD_READ1;
  31.         }
  32.         chip->cmd_ctrl(mtd, readcmd, ctrl);
  33.         ctrl &= ~NAND_CTRL_CHANGE;
  34.     }
  35.     chip->cmd_ctrl(mtd, command, ctrl);

  36.     /*
  37.      * Address cycle, when necessary
  38.      */
  39.     ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
  40.     /* Serially input address */
  41.     if (column != -1) {
  42.         /* Adjust columns for 16 bit buswidth */
  43.         if (chip->options & NAND_BUSWIDTH_16)
  44.             column >>= 1;
  45.         chip->cmd_ctrl(mtd, column, ctrl);
  46.         ctrl &= ~NAND_CTRL_CHANGE;
  47.     }
  48.     if (page_addr != -1) {
  49.         chip->cmd_ctrl(mtd, page_addr, ctrl);
  50.         ctrl &= ~NAND_CTRL_CHANGE;
  51.         chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
  52.         /* One more address cycle for devices > 32MiB */
  53.         if (chip->chipsize > (32 << 20))
  54.             chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
  55.     }
  56.     chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);

  57.     /*
  58.      * program and erase have their own busy handlers
  59.      * status and sequential in needs no delay
  60.      */
  61.     switch (command) {

  62.     case NAND_CMD_PAGEPROG:
  63.     case NAND_CMD_ERASE1:
  64.     case NAND_CMD_ERASE2:
  65.     case NAND_CMD_SEQIN:
  66.     case NAND_CMD_STATUS:
  67.         return;

  68.     case NAND_CMD_RESET:
  69.         if (chip->dev_ready)
  70.             break;
  71.         udelay(chip->chip_delay);
  72.         chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
  73.              NAND_CTRL_CLE | NAND_CTRL_CHANGE);
  74.         chip->cmd_ctrl(mtd,
  75.              NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
  76.         while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
  77.         return;

  78.         /* This applies to read commands */
  79.     default:
  80.         /*
  81.          * If we don't have access to the busy pin, we apply the given
  82.          * command delay
  83.          */
  84.         if (!chip->dev_ready) {
  85.             udelay(chip->chip_delay);
  86.             return;
  87.         }
  88.     }
  89.     /* Apply this short delay always to ensure that we do wait tWB in
  90.      * any case on any machine. */
  91.     ndelay(100);

  92.     nand_wait_ready(mtd);
  93. }
看到粗体部分的函数,我们是否想起了,代码初始化的部分呢?   
 this->cmd_ctrl = board_hwcontrol
是的,后面的很多mtd代码里函数都会调用this->cmd_ctrl这个函数,我们就不再一一列举了.
在nand_set_defaults函数中,对struct nand_chip 结构的很多函数指针进行了初始化.
我们接着往下看这个函数:nand_get_flash_type  ,它的作用是什么呢?

点击(此处)折叠或打开

  1. /*
  2.  * Get the flash and manufacturer id and lookup if the type is supported
  3.  */
  4. static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
  5.                          struct nand_chip *chip,
  6.                          int busw, int *maf_id)
  7. {
  8.     struct nand_flash_dev *type = NULL;
  9.     int i, dev_id, maf_idx;
  10.     int tmp_id, tmp_manf;

  11.     /* Select the device */
  12.     chip->select_chip(mtd, 0);

  13.     /*
  14.      * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
  15.      * after power-up
  16.      */
  17.     chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);

  18.     /* Send the command for reading device ID */
  19.     chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);

  20.     /* Read manufacturer and device IDs */
  21.     *maf_id = chip->read_byte(mtd);
  22.     dev_id = chip->read_byte(mtd);

  23.     /* Try again to make sure, as some systems the bus-hold or other
  24.      * interface concerns can cause random data which looks like a
  25.      * possibly credible NAND flash to appear. If the two results do
  26.      * not match, ignore the device completely.
  27.      */

  28.     chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);

  29.     /* Read manufacturer and device IDs */

  30.     tmp_manf = chip->read_byte(mtd);
  31.     tmp_id = chip->read_byte(mtd);

  32.     if (tmp_manf != *maf_id || tmp_id != dev_id) {
  33.         printk(KERN_INFO "%s: second ID read did not match "
  34.          "%02x,%02x against %02x,%02xn", __func__,
  35.          *maf_id, dev_id, tmp_manf, tmp_id);
  36.         return ERR_PTR(-ENODEV);
  37.     }

  38.     /* Lookup the flash id */
  39.     for (i = 0; nand_flash_ids[i].name != NULL; i++) {
  40.         if (dev_id == nand_flash_ids[i].id) {
  41.             type = &nand_flash_ids[i];
  42.             break;
  43.         }
  44.     }

  45.     if (!type)
  46.         return ERR_PTR(-ENODEV);

  47.     if (!mtd->name) {
  48. #ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
  49.         sprintf(nand_name, "%s%s", type->name,
  50.                 (chip->num_devs == 2) ? " - Ganged" : "");
  51.         type->name = nand_name;
  52. #endif
  53.         mtd->name = type->name;
  54.     }

  55.     chip->chipsize = (uint64_t)type->chipsize << 20;
  56. #ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
  57.     chip->chipsize *= chip->num_devs;
  58.     if(chip->num_devs > 1)
  59.         type->options |= NAND_BUSWIDTH_16;
  60. #endif

  61.     /* Newer devices have all the information in additional id bytes */
  62.     if (!type->pagesize) {
  63.         int extid;
  64.         /* The 3rd id byte holds MLC / multichip data */
  65.         chip->cellinfo = chip->read_byte(mtd);
  66.         /* The 4th id byte is the important one */
  67.         extid = chip->read_byte(mtd);
  68.         /* Calc pagesize */
  69.         mtd->writesize = 1024 << (extid & 0x3);
  70.         extid >>= 2;
  71.         /* Calc oobsize */
  72.         mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
  73. #ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
  74.                         mtd->writesize *= chip->num_devs;
  75. #endif
  76.         extid >>= 2;
  77.         /* Calc blocksize. Blocksize is multiples of 64KiB */
  78.         mtd->erasesize = (64 * 1024) << (extid & 0x03);
  79. #ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
  80.                         mtd->erasesize *= chip->num_devs;
  81. #endif
  82.         extid >>= 2;
  83.         /* Get buswidth information */
  84.         busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
  85. #ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
  86.                         if(chip->num_devs > 1)
  87.                                 busw = NAND_BUSWIDTH_16;
  88. #endif
  89.     } else {
  90.         /*
  91.          * Old devices have chip data hardcoded in the device id table
  92.          */
  93.         mtd->erasesize = type->erasesize;
  94.         mtd->writesize = type->pagesize;
  95.         mtd->oobsize = mtd->writesize / 32;
  96. #ifdef CONFIG_MTD_NAND_NFC_MLC_SUPPORT
  97.         /* New devices have non standard OOB size */
  98.         if (chip->oobsize_ovrd)
  99.             mtd->oobsize = chip->oobsize_ovrd;
  100. #endif
  101.         busw = type->options & NAND_BUSWIDTH_16;
  102. #ifdef CONFIG_MTD_NAND_NFC_GANG_SUPPORT
  103.         mtd->erasesize *= chip->num_devs;
  104.         mtd->writesize *= chip->num_devs;
  105. #endif
  106.     }

  107.     /* Try to identify manufacturer */
  108.     for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
  109.         if (nand_manuf_ids[maf_idx].id == *maf_id)
  110.             break;
  111.     }

  112.     /*
  113.      * Check, if buswidth is correct. Hardware drivers should set
  114.      * chip correct !
  115.      */
  116.     if (busw != (chip->options & NAND_BUSWIDTH_16)) {
  117.         printk(KERN_INFO "NAND device: Manufacturer ID:"
  118.          " 0x%02x, Chip ID: 0x%02x (%s %s)n", *maf_id,
  119.          dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
  120.         printk(KERN_WARNING "NAND bus width %d instead %d bitn",
  121.          (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
  122.          busw ? 16 : 8);
  123.         return ERR_PTR(-EINVAL);
  124.     }

  125.     /* Calculate the address shift from the page size */
  126.     chip->page_shift = ffs(mtd->writesize) - 1;
  127.     /* Convert chipsize to number of pages per chip -1. */
  128.     chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;

  129.     chip->bbt_erase_shift = chip->phys_erase_shift =
  130.         ffs(mtd->erasesize) - 1;
  131.     if (chip->chipsize & 0xffffffff)
  132.         chip->chip_shift = ffs((unsigned)chip->chipsize) - 1;
  133.     else
  134.         chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;

  135.     /* Set the bad block position */
  136.     chip->badblockpos = mtd->writesize > 512 ?
  137.         NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;

  138.     /* Get chip options, preserve non chip based options */
  139.     chip->options &= ~NAND_CHIPOPTIONS_MSK;
  140.     chip->options |= type->options & NAND_CHIPOPTIONS_MSK;

  141.     /*
  142.      * Set chip as a default. Board drivers can override it, if necessary
  143.      */
  144.     chip->options |= NAND_NO_AUTOINCR;

  145.     /* Check if chip is a not a samsung device. Do not clear the
  146.      * options for chips which are not having an extended id.
  147.      */
  148.     if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
  149.         chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;

  150.     /* Check for AND chips with 4 page planes */
  151.     if (chip->options & NAND_4PAGE_ARRAY)
  152.         chip->erase_cmd = multi_erase_cmd;
  153.     else
  154.         chip->erase_cmd = single_erase_cmd;

  155.     /* Do not replace user supplied command function ! */
  156.     if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
  157.         chip->cmdfunc = nand_command_lp;

  158.     printk(KERN_INFO "NAND device: Manufacturer ID:"
  159.      " 0x%02x, Chip ID: 0x%02x (%s %s)n", *maf_id, dev_id,
  160.      nand_manuf_ids[maf_idx].name, type->name);

  161.     return type;
  162. }

从注释中我们已经很清晰了,但是这里不能忽略的是粗体部分,尤其是nand_flash_ids,在初始化的时候我们要把我们特定nand flash信息添加到这个表里。才能识别,不然驱动就没法往下继续执行了.
我们继续回到nand_scan函数中来,我们看另外一个关键的函数:

点击(此处)折叠或打开

  1. /**
  2.  * nand_scan_tail - [NAND Interface] Scan for the NAND device
  3.  * @mtd:     MTD device structure
  4.  *
  5.  * This is the second phase of the normal nand_scan() function. It
  6.  * fills out all the uninitialized function pointers with the defaults
  7.  * and scans for a bad block table if appropriate.
  8.  */
  9. int nand_scan_tail(struct mtd_info *mtd)
  10. {
  11.     int i;
  12.     struct nand_chip *chip = mtd->priv;

  13.     if (!(chip->options & NAND_OWN_BUFFERS))
  14.         chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);
  15.     if (!chip->buffers)
  16.         return -ENOMEM;

  17.     /* Set the internal oob buffer location, just after the page data */
  18.     chip->oob_poi = chip->buffers->databuf + mtd->writesize;

  19.     /*
  20.      * If no default placement scheme is given, select an appropriate one
  21.      */
  22.     if (!chip->ecc.layout) {
  23.         switch (mtd->oobsize) {
  24.         case 8:
  25.             chip->ecc.layout = &nand_oob_8;
  26.             break;
  27.         case 16:
  28.             chip->ecc.layout = &nand_oob_16;
  29.             break;
  30.         case 64:
  31.             chip->ecc.layout = &nand_oob_64;
  32.             break;
  33.         case 128:
  34.             chip->ecc.layout = &nand_oob_128;
  35.             break;
  36.         default:
  37.             printk(KERN_WARNING "No oob scheme defined for "
  38.              "oobsize %dn", mtd->oobsize);
  39.             BUG();
  40.         }
  41.     }

  42.     if (!chip->write_page)
  43.         chip->write_page = nand_write_page;

  44.     /*
  45.      * check ECC mode, default to software if 3byte/512byte hardware ECC is
  46.      * selected and we have 256 byte pagesize fallback to software ECC
  47.      */

  48.     switch (chip->ecc.mode) {
  49.     case NAND_ECC_HW_OOB_FIRST:
  50.         /* Similar to NAND_ECC_HW, but a separate read_page handle */
  51.         if (!chip->ecc.calculate || !chip->ecc.correct ||
  52.          !chip->ecc.hwctl) {
  53.             printk(KERN_WARNING "No ECC functions supplied; "
  54.              "Hardware ECC not possiblen");
  55.             BUG();
  56.         }
  57.         if (!chip->ecc.read_page)
  58.             chip->ecc.read_page = nand_read_page_hwecc_oob_first;

  59.     case NAND_ECC_HW:
  60.         /* Use standard hwecc read page function ? */
  61.         if (!chip->ecc.read_page)
  62.             chip->ecc.read_page = nand_read_page_hwecc;
  63.         if (!chip->ecc.write_page)
  64.             chip->ecc.write_page = nand_write_page_hwecc;
  65.         if (!chip->ecc.read_page_raw)
  66.             chip->ecc.read_page_raw = nand_read_page_raw;
  67.         if (!chip->ecc.write_page_raw)
  68.             chip->ecc.write_page_raw = nand_write_page_raw;
  69.         if (!chip->ecc.read_oob)
  70.             chip->ecc.read_oob = nand_read_oob_std;
  71.         if (!chip->ecc.write_oob)
  72.             chip->ecc.write_oob = nand_write_oob_std;

  73.     case NAND_ECC_HW_SYNDROME:
  74.         if ((!chip->ecc.calculate || !chip->ecc.correct ||
  75.          !chip->ecc.hwctl) &&
  76.          (!chip->ecc.read_page ||
  77.          chip->ecc.read_page == nand_read_page_hwecc ||
  78.          !chip->ecc.write_page ||
  79.          chip->ecc.write_page == nand_write_page_hwecc)) {
  80.             printk(KERN_WARNING "No ECC functions supplied; "
  81.              "Hardware ECC not possiblen");
  82.             BUG();
  83.         }
  84.         /* Use standard syndrome read/write page function ? */
  85.         if (!chip->ecc.read_page)
  86.             chip->ecc.read_page = nand_read_page_syndrome;
  87.         if (!chip->ecc.write_page)
  88.             chip->ecc.write_page = nand_write_page_syndrome;
  89.         if (!chip->ecc.read_page_raw)
  90.             chip->ecc.read_page_raw = nand_read_page_raw_syndrome;
  91.         if (!chip->ecc.write_page_raw)
  92.             chip->ecc.write_page_raw = nand_write_page_raw_syndrome;
  93.         if (!chip->ecc.read_oob)
  94.             chip->ecc.read_oob = nand_read_oob_syndrome;
  95.         if (!chip->ecc.write_oob)
  96.             chip->ecc.write_oob = nand_write_oob_syndrome;

  97.         if (mtd->writesize >= chip->ecc.size)
  98.             break;
  99.         printk(KERN_WARNING "%d byte HW ECC not possible on "
  100.          "%d byte page size, fallback to SW ECCn",
  101.          chip->ecc.size, mtd->writesize);
  102.         chip->ecc.mode = NAND_ECC_SOFT;

  103.     case NAND_ECC_SOFT:
  104.         chip->ecc.calculate = nand_calculate_ecc;
  105.         chip->ecc.correct = nand_correct_data;
  106.         chip->ecc.read_page = nand_read_page_swecc;
  107.         chip->ecc.read_subpage = nand_read_subpage;
  108.         chip->ecc.write_page = nand_write_page_swecc;
  109.         chip->ecc.read_page_raw = nand_read_page_raw;
  110.         chip->ecc.write_page_raw = nand_write_page_raw;
  111.         chip->ecc.read_oob = nand_read_oob_std;
  112.         chip->ecc.write_oob = nand_write_oob_std;
  113.         if (!chip->ecc.size)
  114.             chip->ecc.size = 256;
  115.         chip->ecc.bytes = 3;
  116.         break;

  117.     case NAND_ECC_NONE:
  118.         printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
  119.          "This is not recommended !!n");
  120.         #if 0
  121.                 /*close internal ecc */
  122.          nand_command(mtd, 0xEF, 0x90, -1);
  123.          writeb(0x00, chip->IO_ADDR_W);
  124.          writeb(0x00, chip->IO_ADDR_W);
  125.          writeb(0x00, chip->IO_ADDR_W);    
  126.          writeb(0x00, chip->IO_ADDR_W);
  127.          printk("close internal ecc ");
  128.          #endif
  129.         chip->ecc.read_page = nand_read_page_raw;
  130.         chip->ecc.write_page = nand_write_page_raw;
  131.         chip->ecc.read_oob = nand_read_oob_std;
  132.         chip->ecc.read_page_raw = nand_read_page_raw;
  133.         chip->ecc.write_page_raw = nand_write_page_raw;
  134.         chip->ecc.write_oob = nand_write_oob_std;
  135.         chip->ecc.size = 512;//mtd->writesize;
  136.         chip->ecc.bytes = 8;//0;
  137.         break;

  138.     default:
  139.         printk(KERN_WARNING "Invalid NAND_ECC_MODE %dn",
  140.          chip->ecc.mode);
  141.         BUG();
  142.     }

  143.     /*
  144.      * The number of bytes available for a client to place data into
  145.      * the out of band area
  146.      */
  147.     chip->ecc.layout->oobavail = 0;
  148.     for (i = 0; chip->ecc.layout->oobfree[i].length
  149.             && i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++)
  150.         chip->ecc.layout->oobavail +=
  151.             chip->ecc.layout->oobfree[i].length;
  152.     mtd->oobavail = chip->ecc.layout->oobavail;

  153.     /*
  154.      * Set the number of read / write steps for one page depending on ECC
  155.      * mode
  156.      */
  157.     chip->ecc.steps = mtd->writesize / chip->ecc.size;
  158.     if(chip->ecc.steps * chip->ecc.size != mtd->writesize) {
  159.         printk(KERN_WARNING "Invalid ecc parametersn");
  160.         BUG();
  161.     }
  162.     chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;

  163.     /*
  164.      * Allow subpage writes up to ecc.steps. Not possible for MLC
  165.      * FLASH.
  166.      */
  167.     if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
  168.      !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
  169.         switch(chip->ecc.steps) {
  170.         case 2:
  171.             mtd->subpage_sft = 1;
  172.             break;
  173.         case 4:
  174.         case 8:
  175.         case 16:
  176.             mtd->subpage_sft = 2;
  177.             break;
  178.         }
  179.     }
  180.     chip->subpagesize = mtd->writesize >> mtd->subpage_sft;

  181.     /* Initialize state */
  182.     chip->state = FL_READY;

  183.     /* De-select the device */
  184.     chip->select_chip(mtd, -1);

  185.     /* Invalidate the pagebuffer reference */
  186.     chip->pagebuf = -1;

  187.     /* Fill in remaining MTD driver data */
  188.     mtd->type = MTD_NANDFLASH;
  189.     mtd->flags = MTD_CAP_NANDFLASH;
  190.     mtd->erase = nand_erase;
  191.     mtd->point = NULL;
  192.     mtd->unpoint = NULL;
  193.     mtd->read = nand_read;
  194.     mtd->write = nand_write;
  195.     mtd->read_oob = nand_read_oob;
  196.     mtd->write_oob = nand_write_oob;
  197.     mtd->sync = nand_sync;
  198.     mtd->lock = NULL;
  199.     mtd->unlock = NULL;
  200.     mtd->suspend = nand_suspend;
  201.     mtd->resume = nand_resume;
  202.     mtd->block_isbad = nand_block_isbad;
  203.     mtd->block_markbad = nand_block_markbad;

  204.     /* propagate ecc.layout to mtd_info */
  205.     mtd->ecclayout = chip->ecc.layout;

  206.     /* Check, if we should skip the bad block table scan */
  207.     if (chip->options & NAND_SKIP_BBTSCAN)
  208.         return 0;

  209.     /* Build bad block table */
  210.     return chip->scan_bbt(mtd);
  211. }
这里加入关于ecc校验函数的一些初始化.对于nand flash的ecc对数据位的ecc校验的重要性和必要性,这么我们不多解释.当然关于nandflash芯片的具体oob信息需要在这里初始化和指定,不然读不到正确的数据(还有一些nand flash芯片支持内置校验,关于校验我们足够在写一篇了), 最后就是对mtd的一些操作函数的初始化.
这里我们还是在简单的说明下这个函数的一些部分: 

点击(此处)折叠或打开

  1. /**
  2.  * nand_read_page_raw - [Intern] read raw page data without ecc
  3.  * @mtd:    mtd info structure
  4.  * @chip:    nand chip info structure
  5.  * @buf:    buffer to store read data
  6.  * @page:    page number to read
  7.  *
  8.  * Not for syndrome calculating ecc controllers, which use a special oob layout
  9.  */
  10. static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
  11.              uint8_t *buf, int page)
  12. {
  13.     chip->read_buf(mtd, buf, mtd->writesize);
  14.     chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
  15.     return 0;
  16. }

看到没有chip->read_buf其实都是通过chip->cmd_ctrl的各种封装和操作.最后就是对mtd的初始化,这里我们终于看到了.
我们看一下:  mtd->read =nand_read;

点击(此处)折叠或打开

  1. /**
  2.  * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
  3.  * @mtd:    MTD device structure
  4.  * @from:    offset to read from
  5.  * @len:    number of bytes to read
  6.  * @retlen:    pointer to variable to store the number of read bytes
  7.  * @buf:    the databuffer to put data
  8.  *
  9.  * Get hold of the chip and call nand_do_read
  10.  */
  11. static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
  12.          size_t *retlen, uint8_t *buf)
  13. {
  14.     struct nand_chip *chip = mtd->priv;
  15.     int ret;

  16.     /* Do not allow reads past end of device */
  17.     if ((from + len) > mtd->size)
  18.         return -EINVAL;
  19.     if (!len)
  20.         return 0;

  21.     nand_get_device(chip, mtd, FL_READING);

  22.     chip->ops.len = len;
  23.     chip->ops.datbuf = buf;
  24.     chip->ops.oobbuf = NULL;

  25.     ret = nand_do_read_ops(mtd, from, &chip->ops);

  26.     *retlen = chip->ops.retlen;

  27.     nand_release_device(mtd);

  28.     return ret;
  29. }
 nand_do_read_ops(mtd, from, &chip->ops);关键的一行代码,它也是通过chip里一些函数来实现真正的操作.
关于文章开始代码的初始化函数的最后一个操作就是add_mtd_partitions了.网上很多文章对这个函数都解释的很好的.
这里为什么这么长篇大论的自己分析一番,当然只是一个小小的入门和开始.这里都是针对linux kernel里的代码来说明,有机会也要说下uboot下是如何初始化的.











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