NAND FLASH学习笔记之MTD下nand flash驱动(五)

转自http://blog.youkuaiyun.com/wang_zheng_kai/article/details/19037953

驱动中probe函数的分析

其中探测函数代码执行流程为:


 probe函数中主要是完成了NAND芯片级的初始化,主要有以下几个作用:

  -分配nand_chip内存,根据目标板及NAND控制器初始化nand_chip中成员函数(若未初始化则使用nand_base.c中的默认函数),将mtd_info中的priv指向nand_chip(或板相关私有结构),设置ecc模式及处理函数

  -mtd_info为参数调用nand_scan_ident()

nand_scan_tail()函数,探测NAND Flash并进行初始化

    nand_scan_ident()会读取nand芯片ID,并根据mtd->privnand_chip中成员初始化mtd_info

  nand_scan_tail()进行了ECC的设置和剩下的MTD驱动函数的初始化。

  -若有分区,则以mtd_infomtd_partition为参数调用add_mtd_partitions()添加分区信息

nand_scan_ident()

首先初始化mtd_info中一个重要的指针priv,使这个指针指向nand_chip变量;

然后调用了同文件下的nand_set_defaults()和nand_get_flash_type(),nand_set_defaults()函数对struct nand_chip结构体的函数指针进行了赋值。在此函数中cmdfunc映射到了nand_command,nand_get_flash_type()读取了厂商和设备ID进行匹配,并对struct nand_chip结构体的变量进行初始化操作。 


nand_scan_tail()

1、初始化oob区、ecc校验相关参数和函数指针。

2初始化MTD驱动接口函数。

3调用nand_bbt()创建坏块表。


probe程序代码分析如下:

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. NAND驱动的代码分析(二)  
  2. ----------probe程序的分析  
  3. Joe  
  4.   
  5. static int jz4780_nand_probe(struct platform_device *pdev)  
  6. {  
  7.   
  8.         int ret = 0;  
  9.         int bank = 0;  
  10.         int i = 0, j = 0, k = 0, m = 0;  
  11.         int eccpos_start;  
  12.         struct nand_chip *chip;  
  13.         struct mtd_info *mtd;  
  14.         struct jz4780_nand *nand;  
  15.         struct jz4780_nand_platform_data *pdata;  
  16.         nand_flash_if_t *nand_if;  
  17. 1》  
  18.         /* 
  19.          * sanity check主要是获取平台设备信息设备的相关参数 
  20.          */  
  21.         pdata = dev_get_platdata(&pdev->dev);//获取平台设备的数据  
  22.         if (!pdata) {  
  23.                 dev_err(&pdev->dev, "Failed to get platform_data.\n");  
  24.                 return -ENXIO;  
  25.         }  
  26.   
  27.         nand = kzalloc(sizeof(struct jz4780_nand), GFP_KERNEL);//为设备分配内存空间  
  28.         if (!nand) {  
  29.                 dev_err(&pdev->dev,  
  30.                         "Failed to allocate jz4780_nand.\n");  
  31.                 return -ENOMEM;  
  32.         }  
  33.   
  34.         nand->pdev = pdev;  
  35.         nand->pdata = pdata;  
  36.         platform_set_drvdata(pdev, nand);//将nand保存为平台总线的私有数据,将nand设备的数据信息传递到系统平台设备中去  
  37.   
  38.         nand->num_nand_flash_if = pdata->num_nand_flash_if;//所用nand flash的片数  
  39.         nand->xfer_type = pdata->xfer_type;  
  40.         nand->ecc_type = pdata->ecc_type;  
  41.   
  42.   
  43.   
  44. 2》  
  45.         /* 
  46.          * request GPEMC banks获取每一个bank的相关参数(busy,protect,timeout..)申请cs_gpio引脚 
  47.          */  
  48.         for (i = 0; i < nand->num_nand_flash_if; i++, j = i) {  
  49.   
  50.                 nand_if = &pdata->nand_flash_if_table[i];  
  51.                 nand->nand_flash_if_table[i] = nand_if;  
  52.                 bank = nand_if->bank;  
  53.   
  54.                 ret = gpemc_request_cs(&pdev->dev, &nand_if->cs, bank);  
  55.   
  56.                 if (ret) {  
  57.                         dev_err(&pdev->dev,  
  58.                                         "Failed to request busy"  
  59.                                         " gpio irq for bank%d\n", bank);  
  60.                                 goto err_free_busy_irq;  
  61.                         }  
  62.                 }  
  63. 3》  
  64.      /* 
  65.          * request busy GPIO interrupt申请busy_gpio引脚 
  66.          */  
  67.    switch (nand->xfer_type) {  
  68.   
  69.    case NAND_XFER_CPU_IRQ:  
  70.   
  71.    case NAND_XFER_DMA_IRQ://中断方式读取数据  
  72.   
  73.                 for (i = 0; i < nand->num_nand_flash_if; i++, k = i) {  
  74.                         nand_if = &pdata->nand_flash_if_table[i];  
  75.   
  76.                         if (nand_if->busy_gpio < 0)  
  77.                                 continue;  
  78.   
  79.                         ret = request_busy_irq(nand_if);  
  80.                         if (ret) {  
  81.                                 dev_err(&pdev->dev,  
  82.                                         "Failed to request busy"  
  83.   
  84.                                         " gpio irq for bank%d\n", bank);  
  85.                                 goto err_free_busy_irq;  
  86.                         }  
  87.                 }  
  88.   
  89.                 break;  
  90.   
  91.         case NAND_XFER_CPU_POLL:  
  92.         case NAND_XFER_DMA_POLL://poll机制轮询读取数据(类似与底半部方式)  
  93.   
  94.                 for (i = 0; i < nand->num_nand_flash_if; i++, k = i) {  
  95.   
  96.                         nand_if = &pdata->nand_flash_if_table[i];  
  97.                         if (nand_if->busy_gpio < 0)  
  98.                         continue;  
  99.   
  100.                         ret = request_busy_poll(nand_if);  
  101.   
  102.                         if (ret) {  
  103.                                 dev_err(&pdev->dev,  
  104.                                         "Failed to request busy"  
  105.                                         " gpio irq for bank%d\n", bank);  
  106.                                      goto err_free_busy_irq;  
  107.                         }  
  108.                 }  
  109.   
  110.                 nand->busy_poll = 1;  
  111.                 break;  
  112.   
  113.         default:  
  114.   
  115.                 WARN(1"Unsupport transfer type.\n");  
  116.                 BUG();  
  117.                 break;  
  118.   
  119.         }  
  120. 4》  
  121.         /* 
  122.          * request WP GPIO//申请写保护引脚 
  123.          */  
  124.         for (i = 0; i < nand->num_nand_flash_if; i++, m = i) {  
  125.   
  126.                 nand_if = &pdata->nand_flash_if_table[i];  
  127.                 if (nand_if->wp_gpio < 0)  
  128.                         continue;  
  129.                 if (!gpio_is_valid(nand_if->wp_gpio)) {  
  130.                         dev_err(&pdev->dev,  
  131.                                 "Invalid wp GPIO:%d\n", nand_if->wp_gpio);  
  132.                         ret = -EINVAL;  
  133.                         goto err_free_wp_gpio;  
  134.   
  135.                 }  
  136.   
  137.                 bank = nand_if->bank;  
  138.                 ret = gpio_request(nand_if->wp_gpio, label_wp_gpio[bank]);  
  139.                 if (ret) {  
  140.                         dev_err(&pdev->dev,  
  141.                                 "Failed to request wp GPIO:%d\n", nand_if->wp_gpio);  
  142.                         goto err_free_wp_gpio;  
  143.   
  144.                 }  
  145.   
  146.                 gpio_direction_output(nand_if->wp_gpio, 0);//设定gipo为输出模式  
  147.   
  148.                 /* Write protect disabled by default */  
  149.                 jz4780_nand_enable_wp(nand_if, 0);           //disable 写保护  
  150.   
  151.         }  
  152.   
  153. 5》  
  154.         /* 
  155.          * NAND flash devices support list override 
  156.          */  
  157.         nand->nand_flash_table = pdata->nand_flash_table ?  
  158.                 pdata->nand_flash_table : builtin_nand_flash_table;  
  159.         nand->num_nand_flash = pdata->nand_flash_table ?  
  160.                 pdata->num_nand_flash :  
  161.   
  162.                         ARRAY_SIZE(builtin_nand_flash_table);  
  163.         /* 
  164.          * attach to MTD subsystem  
  165.              链接MTD的子系统-----涉及到如何传输数据 
  166.          * struct nand_chip是一个与NAND芯片密切相关的结构体,主要包含三方面内 容: 
  167.          *指向一些操作NAND芯片的函数的指针; 
  168.          *表示NAND芯片特性的成员变量,主要有: 
  169.          *与ecc,oob和bbt (bad block table)相关的一些结构体,对于坏块及坏块管理 
  170.          */  
  171.         chip              = &nand->chip;  
  172.         chip->chip_delay  = MAX_RB_DELAY_US;  
  173.         chip->cmdfunc     = jz4780_nand_command;  
  174.         chip->dev_ready   = jz4780_nand_dev_is_ready;  
  175.         chip->select_chip = jz4780_nand_select_chip;  
  176.         chip->cmd_ctrl    = jz4780_nand_cmd_ctrl;  
  177.         chip->onfi_get_features = jz4780_nand_onfi_get_features;  
  178.         chip->onfi_set_features = jz4780_nand_onfi_set_features;  
  179.   
  180.         switch (nand->xfer_type) {  
  181.         case NAND_XFER_DMA_IRQ:  
  182.         case NAND_XFER_DMA_POLL:  
  183.                 /* 
  184.                  * DMA transfer DMA方式传输数据 
  185.                  */  
  186.   
  187.                 ret = jz4780_nand_request_dma(nand);  
  188.                 if (ret) {  
  189.                         dev_err(&pdev->dev, "Failed to request DMA channel.\n");  
  190.                         goto err_free_wp_gpio;  
  191.                 }  
  192.   
  193.                 chip->read_buf  = jz4780_nand_read_buf;//将芯片中的数据读到缓冲区中  
  194.                 chip->write_buf = jz4780_nand_write_buf;//将缓冲区中的数据写入芯片  
  195.                 nand->use_dma = 1;  
  196.                 break;  
  197.   
  198.         case NAND_XFER_CPU_IRQ:  
  199.         case NAND_XFER_CPU_POLL:  
  200.                 /* 
  201.                  * CPU transfer CPU方式传输数据 
  202.                  */  
  203.     
  204.                 chip->read_buf  = jz4780_nand_cpu_read_buf;  
  205.                 chip->write_buf = jz4780_nand_cpu_write_buf;  
  206. jz4780_nand_write_buf 和 jz4780_nand_read_buf:这是两个最基本的操作函数,其功能,就是往你的Nand Flash的控制器中的FIFO读写数据。一般情况下,是MTD上层的操作,比如要读取一页的数据,那么在发送完相关的读命令和等待时间之后,就会调用到你底层的read_buf,去Nand Flash的FIFO中,一点点把我们要的数据,读取出来,放到我们制定的内存的缓存中去。写操作也是类似,将我们内存中的数据,写到Nand Flash的FIFO中去。  
  207.                 break;  
  208.   
  209.         default:  
  210.   
  211.                 WARN(1"Unsupport transfer type.\n");  
  212.                 BUG();  
  213.                 break;  
  214.   
  215.         }  
  216.         mtd              = &nand->mtd;//填充mtd_info结构体相关信息  
  217.         mtd->priv        = chip;//把指向struct nand_chip结构体的指针赋给struct mtd_info的priv成员变量,  
  218.            //因为MTD Core中很多函数之间的调用都只传递struct mtd_info,它需要通过priv成员变量得到struct nand_chip。  
  219.         mtd->name        = dev_name(&pdev->dev);  
  220.         mtd->owner       = THIS_MODULE;  
  221.   
  222.         /* 
  223.          * if you use u-boot BBT creation code,specifying 
  224.          * this flag will let the kernel fish out the BBT 
  225.          * from the NAND, and also skip the full NAND scan 
  226.          * that can take 1/2s or so. little things... 
  227.          */  
  228.   
  229.         if (pdata->flash_bbt) {//当flashbbt=1的时候系统在启动的时候将跳过对bbt(bad block table)的扫描  
  230.   
  231.                 chip->bbt_options |= NAND_BBT_USE_FLASH;  
  232.                 chip->options |= NAND_SKIP_BBTSCAN;  
  233.   
  234.         }  
  235.   
  236.         /* 
  237.          * nand_base handle subpage write by fill space 
  238.          * where are outside of the subpage with 0xff, 
  239.          * that make things totally wrong, so disable it. 
  240.          */  
  241.   
  242.         chip->options |= NAND_NO_SUBPAGE_WRITE;  
  243.   
  244.         /* 
  245.          * for relocation 
  246.          */  
  247.   
  248.         nand->gpemc_enable_nand_flash = gpemc_enable_nand_flash;  
  249.         nand->nand_wait_ready = nand_wait_ready;  
  250.         nand->gpio_get_value = gpio_get_value;  
  251.         nand->wait_for_completion_timeout = wait_for_completion_timeout;  
  252.         nand->msecs_to_jiffies = msecs_to_jiffies;  
  253.         nand->printk = printk;  
  254.         nand->udelay = __udelay;  
  255.         nand->ndelay = __ndelay;  
  256. 6》  
  257.         /* 
  258.          * Detect NAND flash chips  侦测NAND flash chips 
  259.          */  
  260.     
  261.       /* step1. relax bank timings to scan 定时扫描空闲的bank*/  
  262.   
  263.         for (bank = 0; bank < nand->num_nand_flash_if; bank++) {  
  264.   
  265.                 nand_if = nand->nand_flash_if_table[bank];  
  266.                 gpemc_relax_bank_timing(&nand_if->cs);  
  267.   
  268.         }  
  269.   
  270.         if (nand_scan_ident(mtd, nand->num_nand_flash_if,  
  271.                         nand->nand_flash_table)) {  
  272.                 ret = -ENXIO;  
  273.                 dev_err(&pdev->dev, "Failed to detect NAND flash.\n");  
  274.                 goto err_dma_release_channel;  
  275.   
  276.         }  
  277.   
  278.         /* 
  279.          * post configure bank timing by detected NAND device  通过侦测的NAND设备配置bank时序寄存器 
  280.          */  
  281.   
  282.         /* step1. match NAND chip information */  
  283.   
  284.         nand->curr_nand_flash_info = jz4780_nand_match_nand_chip_info(nand);  
  285.   
  286.         if (!nand->curr_nand_flash_info) {  
  287.                 ret = -ENODEV;  
  288.                 goto err_dma_release_channel;  
  289.         }  
  290.   
  291.         /* 
  292.          * step2. preinitialize NAND flash 预初始化NAND闪存 
  293.          */  
  294.   
  295.         ret = jz4780_nand_pre_init(nand);  
  296.         if (ret) {  
  297.                 dev_err(&nand->pdev->dev, "Failed to"  
  298.                                 " preinitialize NAND chip.\n");  
  299.                 goto err_dma_release_channel;  
  300.         }  
  301.   
  302.        /* step3. replace NAND command function with large page version */// 用对页面的操作命令函数替代NAND的功能命令函数  
  303.   
  304.         if (mtd->writesize > 512)  
  305.                 chip->cmdfunc = jz4780_nand_command_lp;  
  306.   
  307.         /* step4. configure bank timings */ //配置BANK的时序  
  308.   
  309.         switch (nand->curr_nand_flash_info->type) {  
  310.         case BANK_TYPE_NAND:  
  311.                 for (bank = 0; bank < nand->num_nand_flash_if; bank++) {  
  312.                         nand_if = nand->nand_flash_if_table[bank];  
  313.                         gpemc_fill_timing_from_nand(&nand_if->cs,  
  314.                                 &nand->curr_nand_flash_info->  
  315.                                 nand_timing.common_nand_timing);//对bank时序进行赋值操作  
  316.   
  317.                         ret = gpemc_config_bank_timing(&nand_if->cs);//对bank时序寄存器进行配置  
  318.   
  319.                         if (ret) {  
  320.                                 dev_err(&pdev->dev,  
  321.                                         "Failed to configure timings for bank%d\n"  
  322.                                                 , nand_if->bank);  
  323.                                 goto err_dma_release_channel;  
  324.   
  325.                         }  
  326.                 }  
  327.                 break;  
  328.   
  329.         case BANK_TYPE_TOGGLE:  
  330.   
  331.                 for (bank = 0; bank < nand->num_nand_flash_if; bank++) {  
  332.                         nand_if = nand->nand_flash_if_table[bank];  
  333.                         gpemc_fill_timing_from_toggle(&nand_if->cs,  
  334.                                &nand->curr_nand_flash_info->  
  335.                                 nand_timing.toggle_nand_timing);  
  336.   
  337.                         ret = gpemc_config_bank_timing(&nand_if->cs);  
  338.   
  339.                         if (ret) {  
  340.                                 dev_err(&pdev->dev,  
  341.                                         "Failed to configure timings for bank%d\n"  
  342.                                                 , nand_if->bank);  
  343.                                 goto err_dma_release_channel;  
  344.                         }  
  345.   
  346.                 }  
  347.   
  348.                 break;  
  349.   
  350.         default:  
  351.                 WARN(1"Unsupported NAND type.\n");  
  352.                 BUG();  
  353.                 break;  
  354.   
  355.         }  
  356. 7》  
  357.         /* 
  358.          * initialize ECC control//初始化NAND ECC控制器 
  359.          */  
  360.         /* step1. configure ECC step */  
  361.   
  362.         switch (nand->ecc_type) {  
  363.   
  364.         case NAND_ECC_TYPE_SW:         //软件实现ECC检测  
  365.   
  366.                 /* 
  367.                  * valid ECC configuration ? 
  368.                  */  
  369.   
  370.                 if (nand->curr_nand_flash_info->  
  371.                                 ecc_step.data_size % 8  
  372.                                 || nand->curr_nand_flash_info->  
  373.                                         ecc_step.ecc_bits % 8) {  
  374.   
  375.                         ret = -EINVAL;  
  376.   
  377.                         dev_err(&nand->pdev->dev, "Failed when configure ECC,"  
  378.                                         " ECC size, and ECC bits must be a multiple of 8.\n");//ECC的大小和ECC位大小必须是8位  
  379.                         goto err_dma_release_channel;  
  380.   
  381.                 }  
  382.   
  383.   
  384.   
  385.                 chip->ecc.mode  = NAND_ECC_SOFT_BCH;//ECC算法的模式为软件BCH模式  
  386.                 chip->ecc.size  =  
  387.                         nand->curr_nand_flash_info->ecc_step.data_size;  
  388.                 chip->ecc.bytes = (fls(88 * chip->ecc.size) *  
  389.                         (nand->curr_nand_flash_info->ecc_step.ecc_bits) + 7) / 8;  
  390.   
  391.                 break;  
  392.   
  393.         case NAND_ECC_TYPE_HW:         //硬件实现ECC的检测,选取的算法同样是BCH  
  394.                 nand->bch_req.dev       = &nand->pdev->dev;  
  395.                 nand->bch_req.complete  = jz4780_nand_bch_req_complete;  
  396.                 nand->bch_req.ecc_level =  
  397.                                 nand->curr_nand_flash_info->ecc_step.ecc_bits;  
  398.                 nand->bch_req.blksz     =  
  399.                                 nand->curr_nand_flash_info->ecc_step.data_size;  
  400.                 nand->bch_req.errrept_data = kzalloc(MAX_ERRREPT_DATA_SIZE,  
  401.                                 GFP_KERNEL);  
  402.   
  403.                 if (!nand->bch_req.errrept_data) {  
  404.                         dev_err(&pdev->dev,  
  405.                                 "Failed to allocate ECC errrept_data buffer\n");  
  406.                         ret = -ENOMEM;  
  407.                         goto err_dma_release_channel;  
  408.   
  409.                 }  
  410.   
  411.                 init_completion(&nand->bch_req_done);  
  412.   
  413.   
  414.                 chip->ecc.mode      = NAND_ECC_HW;  
  415.                 chip->ecc.calculate = jz4780_nand_ecc_calculate_bch;  
  416.                 chip->ecc.correct   = jz4780_nand_ecc_correct_bch;  
  417.                 chip->ecc.hwctl     = jz4780_nand_ecc_hwctl;  
  418.                 chip->ecc.size  =  
  419.                         nand->curr_nand_flash_info->ecc_step.data_size;  
  420.                 chip->ecc.bytes = bch_ecc_bits_to_bytes(  
  421.                         nand->curr_nand_flash_info->ecc_step.ecc_bits);  
  422.                 chip->ecc.strength = nand->bch_req.ecc_level;  
  423.   
  424.                 break;  
  425.   
  426.         default :  
  427.   
  428.                 WARN(1"Unsupported ECC type.\n");  
  429.                 BUG();  
  430.                 break;  
  431.   
  432.         }  
  433.         /* 
  434.         /* step2. generate ECC layout *///产生出ECC的布局  
  435.         /* 
  436.          * eccbytes = eccsteps * eccbytes_prestep;//计算ECC的字节数 
  437.          */  
  438.   
  439.         nand->ecclayout.eccbytes =  
  440.                 mtd->writesize / chip->ecc.size * chip->ecc.bytes;  
  441.         //判断是否ECC字节数超出OOB的空间大小  
  442.         if (mtd->oobsize < (nand->ecclayout.eccbytes +  
  443.                         chip->badblockpos + 2)) {  
  444.                 WARN(1"ECC codes are out of OOB area.\n");  
  445.                 BUG();  
  446.   
  447.         }  
  448.        /* 
  449.          * ECC codes are right aligned  ECC码为右对齐 
  450.          * start position = oobsize - eccbytes  起始位置的计算 
  451.          */  
  452.         eccpos_start = mtd->oobsize - nand->ecclayout.eccbytes;  //ECC码的起始位置  
  453.   
  454.         for (bank = 0; bank < nand->ecclayout.eccbytes; bank++)  
  455.                 nand->ecclayout.eccpos[bank] = eccpos_start + bank;  
  456.   
  457.         nand->ecclayout.oobfree->offset = chip->badblockpos + 2;  
  458.         nand->ecclayout.oobfree->length =  
  459.                 mtd->oobsize - (nand->ecclayout.eccbytes  
  460.                         + chip->badblockpos + 2);  
  461.         chip->ecc.layout = &nand->ecclayout;  
  462. 8》  
  463.         /* 
  464.          * second phase NAND scan            //第二阶段NAND扫描 
  465.          */  
  466.         if (nand_scan_tail(mtd)) {  
  467.                 ret = -ENXIO;  
  468.                 goto err_free_ecc;  
  469.         }  
  470.   
  471. #ifdef CONFIG_DEBUG_FS  
  472.         nand->debugfs_entry = jz4780_nand_debugfs_init(nand);  
  473.         if (IS_ERR(nand->debugfs_entry)) {  
  474.                 dev_err(&pdev->dev, "Failed to register debugfs entry.\n");  
  475.                 ret = PTR_ERR(nand->debugfs_entry);  
  476.                 goto err_free_ecc;  
  477.         }  
  478. #endif  
  479.         /* 
  480.          * relocate hot functions to TCSM 
  481.          */  
  482.         if (pdata->try_to_reloc_hot) {  
  483.                 ret = jz4780_nand_reloc_hot_to_tcsm(nand);  
  484.                 if (ret) {  
  485.                         dev_err(&pdev->dev, "Failed to relocate hot functions.\n");  
  486.                         goto err_debugfs_remove;  
  487.                 }  
  488.         }  
  489.   
  490.   
  491.   
  492. 9》  
  493.         /* 
  494.          * MTD register 
  495.          */  
  496.         ret = mtd_device_parse_register(mtd, NULLNULL,  
  497.                         pdata->part_table, pdata->num_part);  
  498.         if (ret) {  
  499.                 dev_err(&pdev->dev, "Failed to add MTD device\n");  
  500.                 goto err_unreloc_hot;  
  501.         }  
  502.   
  503.         dev_info(&pdev->dev,  
  504.                 "Successfully registered JZ4780 SoC NAND controller driver.\n");  
  505.   
  506.         return 0;  
  507.   
  508. err_unreloc_hot:  
  509.         if (pdata->try_to_reloc_hot)  
  510.                 jz4780_nand_unreloc_hot_from_tcsm(nand);  
  511.   
  512. err_debugfs_remove:  
  513. #ifdef CONFIG_DEBUG_FS  
  514.         debugfs_remove_recursive(nand->debugfs_entry);  
  515. #endif  
  516. err_free_ecc:  
  517.   
  518.         if (pdata->ecc_type == NAND_ECC_TYPE_HW)  
  519.                 kfree(nand->bch_req.errrept_data);  
  520.   
  521. err_dma_release_channel:  
  522.   
  523.         if (nand->xfer_type == NAND_XFER_DMA_IRQ ||  
  524.                         nand->xfer_type == NAND_XFER_DMA_POLL)  
  525.                 dma_release_channel(nand->dma_pipe_nand.chan);  
  526.   
  527. err_free_wp_gpio:  
  528.   
  529.         for (bank = 0; bank < m; bank++) {  
  530.                 nand_if = &pdata->nand_flash_if_table[bank];  
  531.                 if (nand_if->wp_gpio < 0)  
  532.                         continue;  
  533.                 gpio_free(nand_if->wp_gpio);  
  534.         }  
  535.   
  536. err_free_busy_irq:  
  537.   
  538.         for (bank = 0; bank < k; bank++) {  
  539.                 nand_if = &pdata->nand_flash_if_table[bank];  
  540.                 if (nand_if->busy_gpio < 0)  
  541.                         continue;  
  542.                 if (pdata->xfer_type == NAND_XFER_CPU_IRQ ||  
  543.                                 pdata->xfer_type ==NAND_XFER_DMA_IRQ)  
  544.                         free_irq(nand_if->busy_irq, nand_if);  
  545.                 gpio_free(nand_if->busy_gpio);  
  546.   
  547.         }  
  548. err_release_cs:  
  549.         for (bank = 0; bank < j; bank++) {  
  550.                 nand_if = &pdata->nand_flash_if_table[bank];  
  551.                 gpemc_release_cs(&nand_if->cs);  
  552.         }  
  553.         kfree(nand);  
  554.         return ret;  
  555. }  

nand_scan_ident()程序代码分析:

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <pre code_snippet_id="183770" snippet_file_name="blog_20140211_2_2449669" name="code" class="objc">int nand_scan_ident(struct mtd_info *mtd, int maxchips,struct nand_flash_dev *table)  
  2. {  
  3.         int i, busw, nand_maf_id, nand_dev_id;  
  4.         struct nand_chip *chip = mtd->priv;  
  5. // mtd->priv在probe函数中被初始化为数据结构nand_chip的变量nand_chip[i],所以这里的this指针指向的就是变量nand_chip[i]。  
  6.         struct nand_flash_dev *type;  
  7.   
  8.         /* Get buswidth to select the correct functions */  
  9.         busw = chip->options & NAND_BUSWIDTH_16;  
  10. //位宽设置,options bit1设置为0是busw为0,表示位宽为8。options会在该函数后续被初始化为nand_flash_ids[i].options。如果用户需要配置扩展功能只能在nand_flash_ids[i].options配置。  
  11.         /* Set the default functions */  
  12.         nand_set_defaults(chip, busw);  
  13. //nand_set_defaults()函数对struct nand_chip结构体的函数指针进行了赋值。在此函数中cmdfunc映射到了nand_command,  
  14. /* Set default functions */  
  15. static void nand_set_defaults(struct nand_chip *chip, int busw)  
  16. {  
  17.         /* check for proper chip_delay setup, set 20us if not */  
  18.         if (!chip->chip_delay)  
  19.                 chip->chip_delay = 20  
  20.   
  21.         /* check, if a user supplied command function given */  
  22.         if (chip->cmdfunc == NULL)  
  23.                 chip->cmdfunc = nand_command;  
  24.   
  25.         /* check, if a user supplied wait function given */  
  26.         if (chip->waitfunc == NULL)  
  27.                 chip->waitfunc = nand_wait;  
  28.   
  29.         if (!chip->select_chip)  
  30.                 chip->select_chip = nand_select_chip;  
  31.   
  32.         if (!chip->read_byte)  
  33.                 chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;  
  34.   
  35.         if (!chip->read_word)  
  36.                 chip->read_word = nand_read_word;  
  37.   
  38.         if (!chip->block_bad)  
  39.                 chip->block_bad = nand_block_bad;  
  40.   
  41.         if (!chip->block_markbad)  
  42.                 chip->block_markbad = nand_default_block_markbad;  
  43.   
  44.         if (!chip->write_buf)  
  45.                 chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;  
  46.   
  47.         if (!chip->read_buf)  
  48.                 chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;  
  49.   
  50.         if (!chip->scan_bbt)  
  51.                 chip->scan_bbt = nand_default_bbt;  
  52.   
  53.         if (!chip->controller) {  
  54.                 chip->controller = &chip->hwcontrol;  
  55.                 spin_lock_init(&chip->controller->lock);  
  56.                 init_waitqueue_head(&chip->controller->wq);  
  57.         }  
  58. }  
  59.   
  60.         /* Read the flash type */  
  61.         type = nand_get_flash_type(mtd, chip, busw,  
  62.                                 &nand_maf_id, &nand_dev_id, table);  
  63.   
  64. //nand_get_flash_type()读取了厂商和设备ID,并对struct nand_chip结构体的变量进行初始化操作  
  65.   
  66.         if (IS_ERR(type)) {  
  67.                 if (!(chip->options & NAND_SCAN_SILENT_NODEV))  
  68.                         pr_warn("No NAND device found\n");  
  69.                 chip->select_chip(mtd, -1);  
  70.                 return PTR_ERR(type);  
  71.         }  
  72.   
  73.         chip->select_chip(mtd, -1);  
  74.   
  75.         /* Check for a chip array */  
  76.         for (i = 1; i < maxchips; i++) {  
  77.                 chip->select_chip(mtd, i);  
  78.   
  79.                 /* See comment in nand_get_flash_type for reset */  
  80.                 chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);  
  81.                 /* Send the command for reading device ID */  
  82.                 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);  
  83.                 /* Read manufacturer and device IDs */  
  84.                 if (nand_maf_id != chip->read_byte(mtd) ||  
  85.                     nand_dev_id != chip->read_byte(mtd)) {  
  86.                         chip->select_chip(mtd, -1);  
  87.                         break;  
  88.                 }  
  89.                 chip->select_chip(mtd, -1);  
  90.  }  
  91.   
  92.         if (i > 1)  
  93.                 pr_info("%d NAND chips detected\n", i);  
  94.   
  95.         /* Store the number of chips and calc total size for mtd */  
  96.         chip->numchips = i;  
  97.         mtd->size = i * chip->chipsize;  
  98.         return 0;  
  99. }  
  100. EXPORT_SYMBOL(nand_scan_ident);  
  101. </pre><br>  
  102. <br>  
  103. <pre></pre>  
  104. <p></p>  
  105. <pre></pre>  
  106. <p></p>  
  107. <pre code_snippet_id="183770" snippet_file_name="blog_20140211_3_8339013" name="code" class="objc"><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">nand_scan_tail()代码分析:</span></pre><pre code_snippet_id="183770" snippet_file_name="blog_20140211_4_5623798" name="code" class="objc">int nand_scan_tail(struct mtd_info *mtd)  
  108. {  
  109.         int i;  
  110.         struct nand_chip *chip = mtd->priv;  
  111.   
  112.         /* New bad blocks should be marked in OOB, flash-based BBT, or both */  
  113.         BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&  
  114.                         !(chip->bbt_options & NAND_BBT_USE_FLASH));  
  115.   
  116.         if (!(chip->options & NAND_OWN_BUFFERS))  
  117.                 chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);  
  118.   
  119.         if (!chip->buffers)  
  120.                 return -ENOMEM;  
  121.   
  122.         /* Set the internal oob buffer location, just after the page data */  
  123.         chip->oob_poi = chip->buffers->databuf + mtd->writesize;//设置缓存位置,仅仅需要在数据页后面就行  
  124.          * If no default placement scheme is given, select an appropriate one.如果没有预设的方案,就选择合适的一个  
  125.          */  
  126.   
  127.         if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {  
  128.                 switch (mtd->oobsize) {  
  129.                 case 8:  
  130.                         chip->ecc.layout = &nand_oob_8;  
  131.                         break;  
  132.   
  133.                 case 16:  
  134.                         chip->ecc.layout = &nand_oob_16;  
  135.                         break;  
  136.   
  137.                 case 64:  
  138.                         chip->ecc.layout = &nand_oob_64;  
  139.                         break;  
  140.   
  141.                 case 128:  
  142.                         chip->ecc.layout = &nand_oob_128;  
  143.                         break;  
  144.   
  145.                 default:  
  146.                         pr_warn("No oob scheme defined for oobsize %d\n",  
  147.                                    mtd->oobsize);  
  148.                         BUG();  
  149.                 }  
  150.         }  
  151.   
  152.         if (!chip->write_page)  
  153.                 chip->write_page = nand_write_page;  
  154.   
  155.         /* set for ONFI nand *///设置ONFI NAND的功能  
  156.         if (!chip->onfi_set_features)  
  157.                 chip->onfi_set_features = nand_onfi_set_features;  
  158.         if (!chip->onfi_get_features)  
  159.                 chip->onfi_get_features = nand_onfi_get_features;  
  160.   
  161. //对chip结构题的ecc相关的初始化  
  162.         /* 
  163.          * Check ECC mode, default to software if 3byte/512byte hardware ECC is 
  164.          * selected and we have 256 byte pagesize fallback to software ECC 
  165.          *///如果硬件检测选择的是3/512那么我们默认软件ECC模式,我们每页有256bytes为ECC备用  
  166.         // /*以下都是对chip赋值,对应nand_chip中的函数*/  
  167.         /*Nand_scan是在初始化nand的时候对nand进行的一步非常好重要的操作, 
  168.         *在nand_scan中会对我们所写的关于特定芯片的读写函数重载到nand_chip结构中去, 
  169.         *并会将mtd_info结构体中的函数用nand的函数来重载,实现了mtd到底层驱动的联系。 
  170.         *并且在nand_scan函数中会通过读取nand芯片的设备号和厂家号自动在芯片列表中寻找相应的型号和参数,并将其注册进去。*/  
  171.   
  172.         switch (chip->ecc.mode) {  
  173.   
  174.         case NAND_ECC_HW_OOB_FIRST:  
  175.                 /* Similar to NAND_ECC_HW, but a separate read_page handle */  
  176.                 if (!chip->ecc.calculate || !chip->ecc.correct ||  
  177.                      !chip->ecc.hwctl) {  
  178.                         pr_warn("No ECC functions supplied; "  
  179.                                    "hardware ECC not possible\n");  
  180.                         BUG();  
  181.                 }  
  182.   
  183.                 if (!chip->ecc.read_page)  
  184.                         chip->ecc.read_page = nand_read_page_hwecc_oob_first;  
  185.   
  186.         case NAND_ECC_HW:  
  187.                 /* Use standard hwecc read page function? */  
  188.                 if (!chip->ecc.read_page)  
  189.                         chip->ecc.read_page = nand_read_page_hwecc;  
  190.                 if (!chip->ecc.write_page)  
  191.                         chip->ecc.write_page = nand_write_page_hwecc;  
  192.                 if (!chip->ecc.read_page_raw)  
  193.                         chip->ecc.read_page_raw = nand_read_page_raw;  
  194.                 if (!chip->ecc.write_page_raw)  
  195.                         chip->ecc.write_page_raw = nand_write_page_raw;  
  196.                 if (!chip->ecc.read_oob)  
  197.                         chip->ecc.read_oob = nand_read_oob_std;  
  198.                 if (!chip->ecc.write_oob)  
  199.                         chip->ecc.write_oob = nand_write_oob_std;  
  200.         case NAND_ECC_HW_SYNDROME:  
  201.                 if ((!chip->ecc.calculate || !chip->ecc.correct ||  
  202.                      !chip->ecc.hwctl) &&  
  203.                     (!chip->ecc.read_page ||  
  204.                      chip->ecc.read_page == nand_read_page_hwecc ||  
  205.                      !chip->ecc.write_page ||  
  206.                      chip->ecc.write_page == nand_write_page_hwecc)) {  
  207.                         pr_warn("No ECC functions supplied; "  
  208.                                    "hardware ECC not possible\n");  
  209.                         BUG();  
  210.   
  211.                 }  
  212.   
  213.                 /* Use standard syndrome read/write page function? */  
  214.                 if (!chip->ecc.read_page)  
  215.                         chip->ecc.read_page = nand_read_page_syndrome;  
  216.                 if (!chip->ecc.write_page)  
  217.                         chip->ecc.write_page = nand_write_page_syndrome;  
  218.                 if (!chip->ecc.read_page_raw)  
  219.                         chip->ecc.read_page_raw = nand_read_page_raw_syndrome;  
  220.                 if (!chip->ecc.write_page_raw)  
  221.                         chip->ecc.write_page_raw = nand_write_page_raw_syndrome;  
  222.                 if (!chip->ecc.read_oob)  
  223.                         chip->ecc.read_oob = nand_read_oob_syndrome;  
  224.                 if (!chip->ecc.write_oob)  
  225.                         chip->ecc.write_oob = nand_write_oob_syndrome;  
  226.                 if (mtd->writesize >= chip->ecc.size) {  
  227.                         if (!chip->ecc.strength) {  
  228.                                 pr_warn("Driver must set ecc.strength when using hardware ECC\n");  
  229.                                 BUG();  
  230.                         }  
  231.                         break;  
  232.                 }  
  233.                 pr_warn("%d byte HW ECC not possible on "  
  234.                            "%d byte page size, fallback to SW ECC\n",  
  235.                            chip->ecc.size, mtd->writesize);  
  236.                 chip->ecc.mode = NAND_ECC_SOFT;  
  237.   
  238.         case NAND_ECC_SOFT:  
  239.                 chip->ecc.calculate = nand_calculate_ecc;  
  240.                 chip->ecc.correct = nand_correct_data;  
  241.                 chip->ecc.read_page = nand_read_page_swecc;  
  242.                 chip->ecc.read_subpage = nand_read_subpage;  
  243.                 chip->ecc.write_page = nand_write_page_swecc;  
  244.                 chip->ecc.read_page_raw = nand_read_page_raw;  
  245.                 chip->ecc.write_page_raw = nand_write_page_raw;  
  246.                 chip->ecc.read_oob = nand_read_oob_std;  
  247.   chip->ecc.write_oob = nand_write_oob_std;  
  248.                 if (!chip->ecc.size)  
  249.                         chip->ecc.size = 256;  
  250.                 chip->ecc.bytes = 3;  
  251.                 chip->ecc.strength = 1;  
  252.                 break;  
  253.   
  254.         case NAND_ECC_SOFT_BCH:  
  255.                 if (!mtd_nand_has_bch()) {  
  256.                         pr_warn("CONFIG_MTD_ECC_BCH not enabled\n");  
  257.                         BUG();  
  258.                 }  
  259.   
  260.                 chip->ecc.calculate = nand_bch_calculate_ecc;  
  261.                 chip->ecc.correct = nand_bch_correct_data;  
  262.                 chip->ecc.read_page = nand_read_page_swecc;  
  263.                 chip->ecc.read_subpage = nand_read_subpage;  
  264.                 chip->ecc.write_page = nand_write_page_swecc;  
  265.                 chip->ecc.read_page_raw = nand_read_page_raw;  
  266.                 chip->ecc.write_page_raw = nand_write_page_raw;  
  267.                 chip->ecc.read_oob = nand_read_oob_std;  
  268.                 chip->ecc.write_oob = nand_write_oob_std;  
  269.                 /* 
  270.  
  271.                  * Board driver should supply ecc.size and ecc.bytes values to 
  272.                  * select how many bits are correctable; see nand_bch_init() 
  273.                  * for details. Otherwise, default to 4 bits for large pag 
  274.                  * devices. 
  275.                  */  
  276.   
  277.                 if (!chip->ecc.size && (mtd->oobsize >= 64)) {  
  278.                         chip->ecc.size = 512;  
  279.                         chip->ecc.bytes = 7;  
  280.                 }//初始化NAND BCH 纠错  
  281.                 chip->ecc.priv = nand_bch_init(mtd,  
  282.                                                chip->ecc.size,  
  283.                                                chip->ecc.bytes,  
  284.                                                &chip->ecc.layout);//建立坏块表  
  285.                 if (!chip->ecc.priv) {  
  286.                         pr_warn("BCH ECC initialization failed!\n");  
  287.                         BUG();  
  288.                 }  
  289.   
  290.                //Driver must set ecc.strength when using hardware ECC  
  291.                 chip->ecc.strength =  
  292.                         chip->ecc.bytes * 8 / fls(88 * chip->ecc.size);  
  293.                 break;  
  294.   
  295.         case NAND_ECC_NONE:  
  296.                 pr_warn("NAND_ECC_NONE selected by board driver. "  
  297.                            "This is not recommended!\n");  
  298.                 chip->ecc.read_page = nand_read_page_raw;  
  299.                 chip->ecc.write_page = nand_write_page_raw;  
  300.                 chip->ecc.read_oob = nand_read_oob_std;  
  301.                 chip->ecc.read_page_raw = nand_read_page_raw;  
  302.                 chip->ecc.write_page_raw = nand_write_page_raw;  
  303.                 chip->ecc.write_oob = nand_write_oob_std;  
  304.                 chip->ecc.size = mtd->writesize;  
  305.                 chip->ecc.bytes = 0;  
  306.                 chip->ecc.strength = 0;  
  307.                 break;  
  308.   
  309.   
  310.   
  311.         default:  
  312.                 pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode);  
  313.                 BUG();  
  314.   
  315.         }  
  316.         /* For many systems, the standard OOB write also works for raw */  
  317.         if (!chip->ecc.read_oob_raw)  
  318.                 chip->ecc.read_oob_raw = chip->ecc.read_oob;  
  319.         if (!chip->ecc.write_oob_raw)  
  320.                 chip->ecc.write_oob_raw = chip->ecc.write_oob;  
  321.   
  322.         /* 
  323.          * The number of bytes available for a client to place data into 
  324.          * the out of band area. 
  325.          */  
  326.         chip->ecc.layout->oobavail = 0;  
  327.         for (i = 0; chip->ecc.layout->oobfree[i].length  
  328.                         && i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++)  
  329.                 chip->ecc.layout->oobavail +=  
  330.                         chip->ecc.layout->oobfree[i].length;  
  331.         mtd->oobavail = chip->ecc.layout->oobavail;  
  332.   
  333.   
  334.   
  335.         /* 
  336.          * Set the number of read / write steps for one page depending on ECC 
  337.          * mode. 
  338.          */  
  339.         chip->ecc.steps = mtd->writesize / chip->ecc.size;  
  340.         if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {  
  341.                 pr_warn("Invalid ECC parameters\n");  
  342.                 BUG();  
  343.         }  
  344.         chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;  
  345.   
  346.   
  347. //subpage相关的初始化  
  348.         /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */  
  349.         if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&  
  350.             !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {  
  351.                 switch (chip->ecc.steps) {  
  352.   
  353.                 case 2:  
  354.                         mtd->subpage_sft = 1;  
  355.                         break;  
  356.   
  357.                 case 4:  
  358.                 case 8:  
  359.                 case 16:  
  360.                         mtd->subpage_sft = 2;  
  361.                         break;  
  362.                 }  
  363.         }  
  364.         chip->subpagesize = mtd->writesize >> mtd->subpage_sft;  
  365.   
  366.         /* Initialize state */  
  367.         chip->state = FL_READY;  
  368.   
  369.         /* Invalidate the pagebuffer reference */  
  370.         chip->pagebuf = -1;  
  371. //本开发板用不到  
  372.         /* Large page NAND with SOFT_ECC should support subpage reads */  
  373.         if ((chip->ecc.mode == NAND_ECC_SOFT) && (chip->page_shift > 9))  
  374.                 chip->options |= NAND_SUBPAGE_READ;  
  375.   
  376.   
  377. //初始化剩余的mtd_info结构题  
  378.         /* Fill in remaining MTD driver data */  
  379.         mtd->type = MTD_NANDFLASH;  
  380.         mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :  
  381.                                                 MTD_CAP_NANDFLASH;  
  382.   
  383.         mtd->_erase = nand_erase;  
  384.         mtd->_point = NULL;  
  385.         mtd->_unpoint = NULL;  
  386.         mtd->_read = nand_read;  
  387.         mtd->_write = nand_write;  
  388.         mtd->_panic_write = panic_nand_write;  
  389.         mtd->_read_oob = nand_read_oob;  
  390.         mtd->_write_oob = nand_write_oob;  
  391.         mtd->_sync = nand_sync;  
  392.         mtd->_lock = NULL;  
  393.         mtd->_unlock = NULL;  
  394.         mtd->_suspend = nand_suspend;  
  395.         mtd->_resume = nand_resume;  
  396.         mtd->_block_isbad = nand_block_isbad;  
  397.         mtd->_block_markbad = nand_block_markbad;  
  398.         mtd->writebufsize = mtd->writesize;  
  399. //把chip中的ecc信息传递给mtd结构题,初始化mtd_info  
  400.         /* propagate ecc info to mtd_info */  
  401.         mtd->ecclayout = chip->ecc.layout;  
  402.         mtd->ecc_strength = chip->ecc.strength;  
  403.         /* 
  404.          * Initialize bitflip_threshold to its default prior scan_bbt() call. 
  405.          * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be 
  406.          * properly set. 
  407.          */  
  408.         if (!mtd->bitflip_threshold)  
  409.                 mtd->bitflip_threshold = mtd->ecc_strength;  
  410.   
  411.         /* Check, if we should skip the bad block table scan */  
  412.     //判断是否跳过坏块表检测  
  413.         if (chip->options & NAND_SKIP_BBTSCAN)  
  414.                 return 0;  
  415.         /* Build bad block table *///扫描并建立坏块表  
  416.         return chip->scan_bbt(mtd);  
  417.   
  418. }  
  419.   
  420. EXPORT_SYMBOL(nand_scan_tail);  
  421. </pre><br>  
  422. <pre></pre>  
  423. <pre></pre>  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值