S5PV210(TQ210)學(xué)習(xí)筆記——Nand flash驅(qū)動編寫
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- structs5p_nand_regs{
- unsignedlongnfconf;
- unsignedlongnfcont;
- unsignedlongnfcmmd;
- unsignedlongnfaddr;
- unsignedlongnfdata;
- unsignedlongnfmeccd0;
- unsignedlongnfmeccd1;
- unsignedlongnfseccd;
- unsignedlongnfsblk;
- unsignedlongnfeblk;
- unsignedlongnfstat;
- unsignedlongnfeccerr0;
- unsignedlongnfeccerr1;
- unsignedlongnfmecc0;
- unsignedlongnfmecc1;
- unsignedlongnfsecc;
- unsignedlongnfmlcbitpt;
- };
- structs5p_nand_ecc{
- unsignedlongnfeccconf;
- unsignedlongnfecccont;
- unsignedlongnfeccstat;
- unsignedlongnfeccsecstat;
- unsignedlongnfeccprgecc0;
- unsignedlongnfeccprgecc1;
- unsignedlongnfeccprgecc2;
- unsignedlongnfeccprgecc3;
- unsignedlongnfeccprgecc4;
- unsignedlongnfeccprgecc5;
- unsignedlongnfeccprgecc6;
- unsignedlongnfeccerl0;
- unsignedlongnfeccerl1;
- unsignedlongnfeccerl2;
- unsignedlongnfeccerl3;
- unsignedlongnfeccerl4;
- unsignedlongnfeccerl5;
- unsignedlongnfeccerl6;
- unsignedlongnfeccerl7;
- unsignedlongnfeccerp0;
- unsignedlongnfeccerp1;
- unsignedlongnfeccerp2;
- unsignedlongnfeccerp3;
- unsignedlongnfeccconecc0;
- unsignedlongnfeccconecc1;
- unsignedlongnfeccconecc2;
- unsignedlongnfeccconecc3;
- unsignedlongnfeccconecc4;
- unsignedlongnfeccconecc5;
- unsignedlongnfeccconecc6;
- };
- staticstructnand_chip*nand_chip;
- staticstructmtd_info*s5p_mtd_info;
- staticstructs5p_nand_regs*s5p_nand_regs;
- staticstructs5p_nand_ecc*s5p_nand_ecc;
- staticstructclk*s5p_nand_clk;
- staticstructmtd_partitions5p_nand_partions[]={
- [0]={
- .name="bootloader",
- .offset=0,
- .size=SZ_1M,
- },
- [1]={
- .name="kernel",
- .offset=MTDPART_OFS_APPEND,
- .size=5*SZ_1M,
- },
- [2]={
- .name="rootfs",
- .offset=MTDPART_OFS_APPEND,
- .size=MTDPART_SIZ_FULL,
- },
- };
- staticvoids5p_nand_select_chip(structmtd_info*mtd,intchipnr){
- if(chipnr==-1){
- s5p_nand_regs->nfcont|=(1<<1);
- }
- else{
- s5p_nand_regs->nfcont&=~(1<<1);
- }
- }
- staticvoids5p_nand_cmd_ctrl(structmtd_info*mtd,intcmd,unsignedintctrl)
- {
- if(ctrl&NAND_CLE){
- s5p_nand_regs->nfcmmd=cmd;
- }
- else{
- s5p_nand_regs->nfaddr=cmd;
- }
- }
- staticints5p_nand_ready(structmtd_info*mtd){
- return(s5p_nand_regs->nfstat&0x1);
- }
- staticints5p_nand_probe(structplatform_device*pdev){
- intret=0;
- structresource*mem;
- //硬件部分初始化
- mem=platform_get_resource(pdev,IORESOURCE_MEM,0);
- if(!mem){
- dev_err(&pdev->dev,"cantgetI/Oresourcemem");
- return-ENXIO;
- }
- s5p_nand_regs=(structs5p_nand_regs*)ioremap(mem->start,resource_size(mem));
- if(s5p_nand_regs==NULL){
- dev_err(&pdev->dev,"ioremapfailed");
- ret=-EIO;
- gotoerr_exit;
- }
- s5p_nand_ecc=(structs5p_nand_ecc*)ioremap(0xB0E20000,sizeof(structs5p_nand_ecc));
- if(s5p_nand_ecc==NULL){
- dev_err(&pdev->dev,"ioremapfailed");
- ret=-EIO;
- gotoerr_iounmap;
- }
- s5p_nand_clk=clk_get(&pdev->dev,"nand");
- if(s5p_nand_clk==NULL){
- dev_dbg(&pdev->dev,"getclkfailed");
- ret=-ENODEV;
- gotoerr_iounmap;
- }
- clk_enable(s5p_nand_clk);
- s5p_nand_regs->nfconf=(3<<12)|(5<<8)|(3<<4)|(1<<1);
- s5p_nand_regs->nfcont|=3;
- //分配驅(qū)動相關(guān)結(jié)構(gòu)體
- nand_chip=(structnand_chip*)kzalloc(sizeof(structnand_chip),GFP_KERNEL);
- if(nand_chip==NULL){
- dev_err(&pdev->dev,"failedtoallocatenand_chipstructure");
- ret=-ENOMEM;
- gotoerr_clk_put;
- }
- s5p_mtd_info=(structmtd_info*)kzalloc(sizeof(structmtd_info),GFP_KERNEL);
- if(s5p_mtd_info==NULL){
- dev_err(&pdev->dev,"failedtoallocatemtd_infostructure");
- ret=-ENOMEM;
- gotoerr_free_chip;
- }
- //設(shè)置驅(qū)動相關(guān)結(jié)構(gòu)體
- nand_chip->select_chip=s5p_nand_select_chip;
- nand_chip->cmd_ctrl=s5p_nand_cmd_ctrl;
- nand_chip->IO_ADDR_R=&s5p_nand_regs->nfdata;
- nand_chip->IO_ADDR_W=&s5p_nand_regs->nfdata;
- nand_chip->dev_ready=s5p_nand_ready;
- nand_chip->ecc.mode=NAND_ECC_SOFT;
- s5p_mtd_info->priv=nand_chip;
- s5p_mtd_info->owner=THIS_MODULE;
- //掃描Nandflash設(shè)備
- if(nand_scan(s5p_mtd_info,1)){
- dev_dbg(&pdev->dev,"nandscanerror");
- gotoerr_free_info;
- }
- //添加分區(qū)信息
- ret=mtd_device_parse_register(s5p_mtd_info,NULL,NULL,s5p_nand_partions,ARRAY_SIZE(s5p_nand_partions));
- if(!ret)
- return0;
- err_free_info:
- kfree(s5p_mtd_info);
- err_free_chip:
- kfree(nand_chip);
- err_clk_put:
- clk_disable(s5p_nand_clk);
- clk_put(s5p_nand_clk);
- err_iounmap:
- //if(s5p_nand_ecc==NULL)
- //iounmap(s5p_nand_ecc);
- if(s5p_nand_regs==NULL)
- iounmap(s5p_nand_regs);
- err_exit:
- returnret;
- }
- staticints5p_nand_remove(structplatform_device*pdev){
- nand_release(s5p_mtd_info);
- kfree(s5p_mtd_info);
- kfree(nand_chip);
- clk_disable(s5p_nand_clk);
- clk_put(s5p_nand_clk);
- if(s5p_nand_regs==NULL)
- iounmap(s5p_nand_regs);
- return0;
- }
- staticstructplatform_drivers5p_nand_drv={
- .driver={
- .owner=THIS_MODULE,
- .name="s5p-nand",
- },
- .probe=s5p_nand_probe,
- .remove=s5p_nand_remove,
- };
- module_platform_driver(s5p_nand_drv);
- MODULE_LICENSE("GPL");
源碼都在上面,具體的原理還是參考視頻或者其他資料,這里就不多說了,如果有任何問題,歡迎留言討論。
本文引用地址:http://www.ex-cimer.com/article/201611/322812.htm
評論