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

小白的博客

嵌入式爱好者

 
 
 

日志

 
 

norflash框架搭建  

2012-09-24 21:17:46|  分类: 韦东山视频第二轮 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
norflash的框架和nandflash是一样的,我们要做的也是实现硬件相关层的工作,也就是提供实际的读写函数!我们参考内核自带的norflash驱动来看看具体要做哪些设置!参考:drivers/mtd/maps/physmap.c

platform_driver_register(&physmap_flash_driver);

static struct platform_driver physmap_flash_driver = {
.probe = physmap_flash_probe,
.remove = physmap_flash_remove,
.shutdown = physmap_flash_shutdown,
.driver = {
.name = "physmap-flash",
.owner = THIS_MODULE,
},
};

physmap_flash_probe
      struct physmap_flash_info *info;
      info = devm_kzalloc(&dev->dev, sizeof(struct physmap_flash_info),
      info->map[i].name = dev_name(&dev->dev);
      info->map[i].phys = dev->resource[i].start;
      info->map[i].size = resource_size(&dev->resource[i]);
      info->map[i].bankwidth = physmap_data->width;
      info->map[i].set_vpp = physmap_set_vpp;
      info->map[i].pfow_base = physmap_data->pfow_base;
      info->map[i].map_priv_1 = (unsigned long)dev;
      info->map[i].virt = devm_ioremap(&dev->dev, info->map[i].phys,
      simple_map_init(&info->map[i]);
            map->read = simple_map_read;
            map->write = simple_map_write;
            map->copy_from = simple_map_copy_from;
            map->copy_to = simple_map_copy_to;
      do_map_probe(*probe_type, &info->map[i])
            get_mtd_chip_driver(name);//我们以cfi识别为例,jedec请参见注释2
                  list_for_each(pos, &chip_drvs_list) //chip_drvs_list的由来可参见注释1
            ret = drv->probe(map);//找到cfi的probe函数
                  mtd_do_chip_probe(map, &cfi_chip_probe);//见注释3
                         genprobe_ident_chips(map, cp);
                              genprobe_new_chip(map, cp, &cfi)
                                    cfi_interleave_supported(nr_chips)//判断位宽是否被支持
                                    cp->probe_chip(map, 0, NULL, cfi)
                                            cfi_qry_mode_on(base, map, cfi)
                                                    cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);//复位
                                                    //往0x55写入0x98,进入cfi模式
                                                    cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
                                                    if (cfi_qry_present(map, base, cfi))  //下面主要是判断是否成功进入cfi模式
                                                          qry[0] = cfi_build_cmd('Q', map, cfi);//构造命令
                                                          qry[1] = cfi_build_cmd('R', map, cfi);
                                                          qry[2] = cfi_build_cmd('Y', map, cfi);
                                                          val[0] = map_read(map, base + osf*0x10);//到0x10地址处读数据
                                                          val[1] = map_read(map, base + osf*0x11);
                                                          val[2] = map_read(map, base + osf*0x12);
                                                          if (!map_word_equal(map, qry[0], val[0])) //判断构造的与读的是否一致
                                                          if (!map_word_equal(map, qry[1], val[1]))
                                                          if (!map_word_equal(map, qry[2], val[2]))
                                           cfi_chip_setup(map, cfi);
                                                   for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) //在cfi模式下读出各地址的信息
                                                           ((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);
                                                   cfi_send_gen_cmd(0xf0,     0, base, map, cfi, cfi->device_type, NULL);
                                                   cfi_send_gen_cmd(0xaa, addr_unlock1, base, map, cfi, cfi->device_type, NULL);
                                                   cfi_send_gen_cmd(0x55, addr_unlock2, base, map, cfi, cfi->device_type, NULL);
                                                   cfi_send_gen_cmd(0x90, addr_unlock1, base, map, cfi, cfi->device_type, NULL);
                                                   cfi->mfr = cfi_read_query16(map, base);
                                                   cfi->id = cfi_read_query16(map, base + ofs_factor); //读出设备id和厂家id
                  check_cmd_set(map, 1);
                         cfi_cmdset_0002(map, primary);
                                   mtd->priv = map;
                                   mtd->_erase   = cfi_amdstd_erase_varsize;//下面是一些默认函数
                                   mtd->_write   = cfi_amdstd_write_words
                                   mtd->_read    = cfi_amdstd_read;
      info->mtd[i]->owner = THIS_MODULE;
      mtd_device_parse_register(info->cmtd, part_types, NULL, physmap_data->parts, physmap_data->nr_parts);
调用mtd_device_parse_register添加分区,接着就会创建磁盘等操作,一旦发生读写就会调用等待队列里面的函数!

根据以上的分析,我们可以将norflash的驱动程序总结为四大步骤:
1、将一些硬件相关的信息,如位宽等初始化在mtd_info结构体里面
2、调用simple_map_init来将一些读写函数初始化在mtd_info结构体里面
3、调用do_map_probe来识别norflash
4、调用mtd_device_parse_register来添加分区,创建磁盘等!

注释1:
module_init(cfi_probe_init);
      register_mtd_chip_driver(&cfi_chipdrv);
            list_add(&drv->list, &chip_drvs_list);

static struct mtd_chip_driver cfi_chipdrv = {
.probe = cfi_probe,
.name = "cfi_probe",
.module = THIS_MODULE
};

注释2:
module_init(jedec_probe_init);
      register_mtd_chip_driver(&jedec_chipdrv);
           list_add(&drv->list, &chip_drvs_list);

static struct mtd_chip_driver jedec_chipdrv = {
.probe = jedec_probe,
.name = "jedec_probe",
.module = THIS_MODULE
};     

jedec_probe
   mtd_do_chip_probe(map, &jedec_chip_probe);
         genprobe_ident_chips(map, cp);
               genprobe_new_chip(map, cp, &cfi)
                      cp->probe_chip(map, 0, NULL, cfi)//jedec_probe_chip
                             jedec_reset(base, map, cfi);//复位
                                   cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
                             cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
                             cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
                             cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
                             cfi->mfr = jedec_read_mfr(map, base, cfi);
                             cfi->id = jedec_read_id(map, base, cfi);
                             //遍历jedec_table数组,找到设备id和厂家id相匹配的项,就匹配成功!
                             jedec_match( base, map, cfi, &jedec_table[i] )
                             cfi_jedec_setup(map, cfi, i)//将匹配项的信息放进cfi结构体里面
                                   cfi->cfiq->DevSize = jedec_table[index].dev_size;
                                   cfi->cfi_mode = CFI_MODE_JEDEC;

注释3:
static struct chip_probe cfi_chip_probe = {
.name = "CFI",
.probe_chip = cfi_probe_chip
};
  评论这张
 
阅读(1393)| 评论(0)
推荐 转载

历史上的今天

评论

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

页脚

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