Linux內(nèi)核的Nand驅(qū)動(dòng)流程分析
- staticints3c24xx_nand_probe(structplatform_device*pdev)
- {
- structs3c2410_platform_nand*plat=to_nand_plat(pdev);
- enums3c_cpu_typecpu_type;
- structs3c2410_nand_info*info;
- structs3c2410_nand_mtd*nmtd;
- structs3c2410_nand_set*sets;
- structresource*res;
- interr=0;
- intsize;
- intnr_sets;
- intsetno;
- cpu_type=platform_get_device_id(pdev)->driver_data;
- pr_debug("s3c2410_nand_probe(%p)",pdev);
- info=kzalloc(sizeof(*info),GFP_KERNEL);
- if(info==NULL){
- dev_err(&pdev->dev,"nomemoryforflashinfo");
- err=-ENOMEM;
- gotoexit_error;
- }
- platform_set_drvdata(pdev,info);
- spin_lock_init(&info->controller.lock);
- init_waitqueue_head(&info->controller.wq);
- /*gettheclocksourceandenableit*/
- info->clk=clk_get(&pdev->dev,"nand");
- if(IS_ERR(info->clk)){
- dev_err(&pdev->dev,"failedtogetclock");
- err=-ENOENT;
- gotoexit_error;
- }
- s3c2410_nand_clk_set_state(info,CLOCK_ENABLE);
- /*allocateandmaptheresource*/
- /*currentlyweassumewehavetheoneresource*/
- res=pdev->resource;
- size=resource_size(res);
- info->area=request_mem_region(res->start,size,pdev->name);
- if(info->area==NULL){
- dev_err(&pdev->dev,"cannotreserveregisterregion");
- err=-ENOENT;
- gotoexit_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,"cannotreserveregisterregion");
- err=-EIO;
- gotoexit_error;
- }
- dev_dbg(&pdev->dev,"mappedregistersat%p",info->regs);
- /*initialisethehardware*/
- err=s3c2410_nand_inithw(info);
- if(err!=0)
- gotoexit_error;
- sets=(plat!=NULL)?plat->sets:NULL;
- nr_sets=(plat!=NULL)?plat->nr_sets:1;
- info->mtd_count=nr_sets;
- /*allocateourinformation*/
- size=nr_sets*sizeof(*info->mtds);
- info->mtds=kzalloc(size,GFP_KERNEL);
- if(info->mtds==NULL){
- dev_err(&pdev->dev,"failedtoallocatemtdstorage");
- err=-ENOMEM;
- gotoexit_error;
- }
- /*initialiseallpossiblechips*/
- nmtd=info->mtds;
- for(setno=0;setno
- pr_debug("initialisingset%d(%p,info%p)",setno,nmtd,info);
- s3c2410_nand_init_chip(info,nmtd,sets);
- nmtd->scan_res=nand_scan_ident(&nmtd->mtd,
- (sets)?sets->nr_chips:1,
- NULL);
- 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,"failedtoinitcpufreqsupport");
- gotoexit_error;
- }
- if(allow_clk_suspend(info)){
- dev_info(&pdev->dev,"clockidlesupportenabled");
- s3c2410_nand_clk_set_state(info,CLOCK_SUSPEND);
- }
- pr_debug("initialisedok");
- return0;
- exit_error:
- s3c24xx_nand_remove(pdev);
- if(err==0)
- err=-EINVAL;
- returnerr;
- }
- res=pdev->resource;
- size=resource_size(res);
- info->area=request_mem_region(res->start,size,pdev->name);
- if(info->area==NULL){
- dev_err(&pdev->dev,"cannotreserveregisterregion");
- err=-ENOENT;
- gotoexit_error;
- }
- info->regs=ioremap(res->start,size);
繼續(xù)往下看代碼,到for循環(huán)處停下來,我們需要注意一下這部分代碼,因?yàn)槲覀兛吹搅藄3c2410_nand_init_chip,從函數(shù)名稱上很容易可以看出,這就是Nand的初始化代碼,但是這里為什么要使用一個(gè)for循環(huán)呢?我們看到循環(huán)控制變量是nr_sets,往上可以找到
- sets=(plat!=NULL)?plat->sets:NULL;
- nr_sets=(plat!=NULL)?plat->nr_sets:1;
- structs3c2410_platform_nand*plat=to_nand_plat(pdev);
- staticstructs3c2410_platform_nand*to_nand_plat(structplatform_device*dev)
- {
- returndev->dev.platform_data;
- }
評(píng)論