注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

Linux MTD子系统学习5—s3c24xx_nand_probe()函数之一  

2011-12-31 17:39:01|  分类: LINUX内核驱动 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
 

说明一下:排列顺序弄混了,所以直接从2跳到5

Linux MTD子系统学习3—s3c24xx_nand_probe()函数之一

前面讲了不少,但真正的路,是从这里开始的,s3c24xx_nand_probe这个函数是总线bus查找到相应的设备后调用匹配的驱动时,调用的一个主要的函数,从这里,驱动就开始真正的按照编写的驱动一步步的运行了。这个函数在s3c2410.c中:

/* s3c24xx_nand_probe

 *

 * called by device layer when it finds a device matching

 * one our driver can handled. This code checks to see if

 * it can allocate all necessary resources then calls the

 * nand layer to look for devices

*/

static int s3c24xx_nand_probe(struct platform_device *pdev)

{

         struct s3c2410_platform_nand *plat = to_nand_plat(pdev);

         enum s3c_cpu_type cpu_type;

         struct s3c2410_nand_info *info;

         struct s3c2410_nand_mtd *nmtd;

         struct s3c2410_nand_set *sets;

         struct resource *res;

         int err = 0;

         int size;

         int nr_sets;

         int setno;

 

         cpu_type = platform_get_device_id(pdev)->driver_data;

 

         pr_debug("s3c2410_nand_probe(%p)\n", pdev);

 

         info = kmalloc(sizeof(*info), GFP_KERNEL);

         if (info == NULL) {

                   dev_err(&pdev->dev, "no memory for flash info\n");

                   err = -ENOMEM;

                   goto exit_error;

         }

 

         memset(info, 0, sizeof(*info));

         platform_set_drvdata(pdev, info);

 

         spin_lock_init(&info->controller.lock);

         init_waitqueue_head(&info->controller.wq);

 

         /* get the clock source and enable it */

 

         info->clk = clk_get(&pdev->dev, "nand");

         if (IS_ERR(info->clk)) {

                   dev_err(&pdev->dev, "failed to get clock\n");

                   err = -ENOENT;

                   goto exit_error;

         }

 

         clk_enable(info->clk);

 

         /* allocate and map the resource */

 

         /* currently we assume we have the one resource */

         res  = pdev->resource;

         size = res->end - res->start + 1;

 

         info->area = request_mem_region(res->start, size, pdev->name);

 

         if (info->area == NULL) {

                   dev_err(&pdev->dev, "cannot reserve register region\n");

                   err = -ENOENT;

                   goto exit_error;

         }

 

         info->device     = &pdev->dev;

         info->platform   = plat;

         info->regs       = ioremap(res->start, size);

         info->cpu_type   = cpu_type;

 

         if (info->regs == NULL) {

                   dev_err(&pdev->dev, "cannot reserve register region\n");

                   err = -EIO;

                   goto exit_error;

         }

 

         dev_dbg(&pdev->dev, "mapped registers at %p\n", info->regs);

 

         /* initialise the hardware */

 

         err = s3c2410_nand_inithw(info);

         if (err != 0)

                   goto exit_error;

 

         sets = (plat != NULL) ? plat->sets : NULL;

         nr_sets = (plat != NULL) ? plat->nr_sets : 1;

 

         info->mtd_count = nr_sets;

 

         /* allocate our information */

 

         size = nr_sets * sizeof(*info->mtds);

         info->mtds = kmalloc(size, GFP_KERNEL);

         if (info->mtds == NULL) {

                   dev_err(&pdev->dev, "failed to allocate mtd storage\n");

                   err = -ENOMEM;

                   goto exit_error;

         }

 

         memset(info->mtds, 0, size);

 

         /* initialise all possible chips */

 

         nmtd = info->mtds;

 

         for (setno = 0; setno < nr_sets; setno++, nmtd++) {

                   pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info);

 

                   s3c2410_nand_init_chip(info, nmtd, sets);

 

                   nmtd->scan_res = nand_scan_ident(&nmtd->mtd,

                                                         (sets) ? sets->nr_chips : 1);

 

                   if (nmtd->scan_res == 0) {

                            s3c2410_nand_update_chip(info, nmtd);

                            nand_scan_tail(&nmtd->mtd);

                            s3c2410_nand_add_partition(info, nmtd, sets);

                   }

 

                   if (sets != NULL)

                            sets++;

         }

 

         err = s3c2410_nand_cpufreq_register(info);

         if (err < 0) {

                   dev_err(&pdev->dev, "failed to init cpufreq support\n");

                   goto exit_error;

         }

 

         if (allow_clk_stop(info)) {

                   dev_info(&pdev->dev, "clock idle support enabled\n");

                   clk_disable(info->clk);

         }

 

         pr_debug("initialised ok\n");

         return 0;

 

 exit_error:

         s3c24xx_nand_remove(pdev);

 

         if (err == 0)

                   err = -EINVAL;

         return err;

}

前面的一些数据结构,如果我们用到的很重要的地方会详细讲一下,如果不是很重要,大家就自己去查资料,毕竟重复很多东西也没什么具体的意义,徒增烦恼罢了。

重要的几行代码如下:

1、info = kmalloc(sizeof(*info), GFP_KERNEL);负责分配s3c2410_nand_info结构变量的空间。

2、err = s3c2410_nand_inithw(info);硬件参数的初始化。

3、info->mtds = kmalloc(size, GFP_KERNEL);MTD设备结构体的空间分配。

4、s3c2410_nand_init_chip(info, nmtd, sets);一些基本量的赋值。这个很重要。

5、nmtd->scan_res = nand_scan_ident(&nmtd->mtd, (sets) ? sets->nr_chips : 1);读取设备参数到nand_chip结构体变量,并进行默认初始化。

6、s3c2410_nand_update_chip(info, nmtd);ECC的设置。

7、nand_scan_tail(&nmtd->mtd);设置未被上面设置的参数,并进行坏块的处理。

8、s3c2410_nand_add_partition(info, nmtd, sets);分区的添加。

下面的介绍基本沿着这几个函数来进行,有什么其它细节,会穿插着进行介绍。

最后一句话:

今天是2011年的最后一天,明天就是2012年了,努力,在这新旧交替的时刻。

  评论这张
 
阅读(1108)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017