s3c2410nandflash驱动probe函数解析


/* s3c2410_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,
         enum s3c_cpu_type cpu_type)
{
 struct s3c2410_platform_nand *plat = to_nand_plat(pdev);//看下面to_nand_plat定义变知道是获取之前定义的单板nand平台数据
static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
{
 return dev->dev.platform_data;
}

 struct s3c2410_nand_info *info;//定义nand info指针
 struct s3c2410_nand_mtd *nmtd;定义mtd指针
 struct s3c2410_nand_set *sets;//定义启动指针
 struct resource *res;//定义资源指针

/*一些变量的申明*/
 int err = 0;
 int size;
 int nr_sets;
 int setno;

 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));//初始化nand结构体
 platform_set_drvdata(pdev, info);//建立驱动数据

 spin_lock_init(&info->controller.lock);
 init_waitqueue_head(&info->controller.wq);

 /* 得到时钟资源并使能它*/

 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);

 /* 申请同时映射资源*/


 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;
 }

/*初始化nand结构体*/

 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);

 /* 初始化硬件 */

 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;

 /* 申请mtd信息*/

 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);

 /* 初始化所有可能芯片 */

 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);//注册nand
 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:
 s3c2410_nand_remove(pdev);

 if (err == 0)
  err = -EINVAL;
 return err;
}

你可能感兴趣的:(c,struct,Flash,null,resources,layer)