Chinaunix首页 | 论坛 | 博客
  • 博客访问: 265645
  • 博文数量: 25
  • 博客积分: 329
  • 博客等级: 一等列兵
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-24 09:43
文章分类

全部博文(25)

文章存档

2014年(4)

2013年(12)

2012年(9)

分类: 嵌入式

2013-03-27 09:38:45

NAND FLASH在linux-2.6.32中的驱动框架

module_init(s3c2410_nand_init);

static int __init s3c2410_nand_init(void)
{
 ..................
 return platform_driver_register(&s3c24xx_nand_driver);
}

static struct platform_driver s3c24xx_nand_driver = {
 .probe  = s3c24xx_nand_probe,
 .remove  = s3c24xx_nand_remove,
 .suspend = s3c24xx_nand_suspend,
 .resume  = s3c24xx_nand_resume,
 .id_table = s3c24xx_driver_ids,
 .driver  = {
  .name = "s3c24xx-nand",
  .owner = THIS_MODULE,
 },
};

static int s3c24xx_nand_probe(struct platform_device *pdev)
{
 cpu_type = platform_get_device_id(pdev)->driver_data;  // cpu_type = pdev->id_entry->driver_data;
 
 platform_set_drvdata(pdev, info); // pdev->dev->p->driver_data = info;
 info->cpu_type   = cpu_type;
 
 s3c2410_nand_inithw(info);   // writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
 
 s3c2410_nand_init_chip(info, nmtd, sets);

 nmtd->scan_res = nand_scan_ident(&nmtd->mtd,(sets) ? sets->nr_chips : 1);
 
  /* Set the default functions */
  nand_set_defaults(chip, busw);
  
  /* Read the flash type */
  nand_get_flash_type(mtd, chip, busw, &nand_maf_id);

 nand_scan_tail(&nmtd->mtd);
 s3c2410_nand_add_partition(info, nmtd, sets);
  add_mtd_device(&mtd->mtd);
   device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL, "mtd%dro", i);
   //  在mtdcore.c的初始化函数中class_register(&mtd_class);创建类
   list_for_each_entry(not, &mtd_notifiers, list)   
    not->add(mtd);
    
    问. mtd_notifiers在哪里设置?
    答. 在void register_mtd_user (struct mtd_notifier *new)函数调用list_add(&new->list, &mtd_notifiers);添加到链表中
        在mtd_blkdevs.c中的int register_mtd_blktrans(struct mtd_blktrans_ops *tr)函数调用register_mtd_user(&blktrans_notifier),还调用了
          static struct mtd_notifier blktrans_notifier = {
     .add = blktrans_notify_add,
     .remove = blktrans_notify_remove,
     };
        
     static void blktrans_notify_add(struct mtd_info *mtd)
     {
      struct mtd_blktrans_ops *tr;
      
      list_for_each_entry(tr, &blktrans_majors, list)
       tr->add_mtd(tr, mtd);
      
      问. blktrans_majors在哪里设置?
      答. 在int register_mtd_blktrans(struct mtd_blktrans_ops *tr)函数中调用了list_add(&tr->list, &blktrans_majors);
          函数int register_mtd_blktrans(struct mtd_blktrans_ops *tr)又在/linux/mtd/mtdblock.c文件和mtdblock_ro.c文件的初始化函数中调用 register_mtd_blktrans(&mtdblock_tr);
          在/linux/mtd/mtdblock.c文件中:
       static struct mtd_blktrans_ops mtdblock_tr = {
        ........
        .add_mtd = mtdblock_add_mtd,
        ........
       };
       
       static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
       {
        add_mtd_blktrans_dev(dev); 
       }
       
       int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
       {
        gd = alloc_disk(1 << tr->part_bits);
        
        gd->major = tr->major;
        gd->first_minor = (new->devnum) << tr->part_bits;
        gd->fops = &mtd_blktrans_ops; 
        
        set_capacity(gd, (new->size * tr->blksize) >> 9);
        gd->queue = tr->blkcore_priv->rq;
        add_disk(gd);
       }
       问. 队列tr->blkcore_priv->rq在哪里设置的?
       答. 在mtd_blkdevs.c文件的int register_mtd_blktrans(struct mtd_blktrans_ops *tr)函数中调用tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock)初始化一个队列
 
          在/linux/mtd/mtdblock_ro.c文件中:
       static struct mtd_blktrans_ops mtdblock_tr = {
        ........
        .add_mtd = mtdblock_add_mtd,
        ........
       };
       static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
       {
        add_mtd_blktrans_dev(dev); 
       }

 

 

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