您的位置 首页 观点

S5PV210(TQ210)学习笔记——Nand flash驱动编写

跟裸机程序一样,S5PV210的Nandflash模块跟S3C2440的Nandflash模块非常相似,如果不引入ECC,驱动程序的编写也非常简单,具体的分析及

跟裸机程序相同,S5PV210Nand flash模块跟S3C2440的Nand flash模块十分类似,假如不引进ECC,驱动程序的编写也十分简略,详细的剖析及编写进程强烈推荐观看韦东山教师的视频教程,我是运用的Linux-3.8.6(Linux-3.8.3也相同)内核,驱动的API函数有些改变,不过原理是相通的,略微看一下内核源码并参阅下其他渠道的相关代码就能够自己写出Nand flash驱动了,下面是Nand flash驱动的源码,没有启用ECC,当然,你也能够改成软件ECC,可是我的觉得已然软件ECC不如HWECC快,我就选用硬件ECC吧,我会鄙人篇文章中参加HWECC。

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. structs5p_nand_regs{
  10. unsignedlongnfconf;
  11. unsignedlongnfcont;
  12. unsignedlongnfcmmd;
  13. unsignedlongnfaddr;
  14. unsignedlongnfdata;
  15. unsignedlongnfmeccd0;
  16. unsignedlongnfmeccd1;
  17. unsignedlongnfseccd;
  18. unsignedlongnfsblk;
  19. unsignedlongnfeblk;
  20. unsignedlongnfstat;
  21. unsignedlongnfeccerr0;
  22. unsignedlongnfeccerr1;
  23. unsignedlongnfmecc0;
  24. unsignedlongnfmecc1;
  25. unsignedlongnfsecc;
  26. unsignedlongnfmlcbitpt;
  27. };
  28. structs5p_nand_ecc{
  29. unsignedlongnfeccconf;
  30. unsignedlongnfecccont;
  31. unsignedlongnfeccstat;
  32. unsignedlongnfeccsecstat;
  33. unsignedlongnfeccprgecc0;
  34. unsignedlongnfeccprgecc1;
  35. unsignedlongnfeccprgecc2;
  36. unsignedlongnfeccprgecc3;
  37. unsignedlongnfeccprgecc4;
  38. unsignedlongnfeccprgecc5;
  39. unsignedlongnfeccprgecc6;
  40. unsignedlongnfeccerl0;
  41. unsignedlongnfeccerl1;
  42. unsignedlongnfeccerl2;
  43. unsignedlongnfeccerl3;
  44. unsignedlongnfeccerl4;
  45. unsignedlongnfeccerl5;
  46. unsignedlongnfeccerl6;
  47. unsignedlongnfeccerl7;
  48. unsignedlongnfeccerp0;
  49. unsignedlongnfeccerp1;
  50. unsignedlongnfeccerp2;
  51. unsignedlongnfeccerp3;
  52. unsignedlongnfeccconecc0;
  53. unsignedlongnfeccconecc1;
  54. unsignedlongnfeccconecc2;
  55. unsignedlongnfeccconecc3;
  56. unsignedlongnfeccconecc4;
  57. unsignedlongnfeccconecc5;
  58. unsignedlongnfeccconecc6;
  59. };
  60. staticstructnand_chip*nand_chip;
  61. staticstructmtd_info*s5p_mtd_info;
  62. staticstructs5p_nand_regs*s5p_nand_regs;
  63. staticstructs5p_nand_ecc*s5p_nand_ecc;
  64. staticstructclk*s5p_nand_clk;
  65. staticstructmtd_partitions5p_nand_partions[]={
  66. [0]={
  67. .name=”bootloader”,
  68. .offset=0,
  69. .size=SZ_1M,
  70. },
  71. [1]={
  72. .name=”kernel”,
  73. .offset=MTDPART_OFS_APPEND,
  74. .size=5*SZ_1M,
  75. },
  76. [2]={
  77. .name=”rootfs”,
  78. .offset=MTDPART_OFS_APPEND,
  79. .size=MTDPART_SIZ_FULL,
  80. },
  81. };
  82. staticvoids5p_nand_select_chip(structmtd_info*mtd,intchipnr){
  83. if(chipnr==-1){
  84. s5p_nand_regs->nfcont|=(1<<1);
  85. }
  86. else{
  87. s5p_nand_regs->nfcont&=~(1<<1);
  88. }
  89. }
  90. staticvoids5p_nand_cmd_ctrl(structmtd_info*mtd,intcmd,unsignedintctrl)
  91. {
  92. if(ctrl&NAND_CLE){
  93. s5p_nand_regs->nfcmmd=cmd;
  94. }
  95. else{
  96. s5p_nand_regs->nfaddr=cmd;
  97. }
  98. }
  99. staticints5p_nand_ready(structmtd_info*mtd){
  100. return(s5p_nand_regs->nfstat&0x1);
  101. }
  102. staticints5p_nand_probe(structplatform_device*pdev){
  103. intret=0;
  104. structresource*mem;
  105. //硬件部分初始化
  106. mem=platform_get_resource(pdev,IORESOURCE_MEM,0);
  107. if(!mem){
  108. dev_err(&pdev->dev,”cantgetI/Oresourcemem”);
  109. return-ENXIO;
  110. }
  111. s5p_nand_regs=(structs5p_nand_regs*)ioremap(mem->start,resource_size(mem));
  112. if(s5p_nand_regs==NULL){
  113. dev_err(&pdev->dev,”ioremapfailed“);
  114. ret=-EIO;
  115. gotoerr_exit;
  116. }
  117. s5p_nand_ecc=(structs5p_nand_ecc*)ioremap(0xB0E20000,sizeof(structs5p_nand_ecc));
  118. if(s5p_nand_ecc==NULL){
  119. dev_err(&pdev->dev,”ioremapfailed”);
  120. ret=-EIO;
  121. gotoerr_iounmap;
  122. }
  123. s5p_nand_clk=clk_get(&pdev->dev,”nand”);
  124. if(s5p_nand_clk==NULL){
  125. dev_dbg(&pdev->dev,”getclkfailed”);
  126. ret=-ENODEV;
  127. gotoerr_iounmap;
  128. }
  129. clk_enable(s5p_nand_clk);
  130. s5p_nand_regs->nfconf=(3<<12)|(5<<8)|(3<<4)|(1<<1);
  131. s5p_nand_regs->nfcont|=3;
  132. //分配驱动相关结构体
  133. nand_chip=(structnand_chip*)kzalloc(sizeof(structnand_chip),GFP_KERNEL);
  134. if(nand_chip==NULL){
  135. dev_err(&pdev->dev,”failedtoallocatenand_chipstructure”);
  136. ret=-ENOMEM;
  137. gotoerr_clk_put;
  138. }
  139. s5p_mtd_info=(structmtd_info*)kzalloc(sizeof(structmtd_info),GFP_KERNEL);
  140. if(s5p_mtd_info==NULL){
  141. dev_err(&pdev->dev,”failedtoallocatemtd_infostructure”);
  142. ret=-ENOMEM;
  143. gotoerr_free_chip;
  144. }
  145. //设置驱动相关结构体
  146. nand_chip->select_chip=s5p_nand_select_chip;
  147. nand_chip->cmd_ctrl=s5p_nand_cmd_ctrl;
  148. nand_chip->IO_ADDR_R=&s5p_nand_regs->nfdata;
  149. nand_chip->IO_ADDR_W=&s5p_nand_regs->nfdata;
  150. nand_chip->dev_ready=s5p_nand_ready;
  151. nand_chip->ecc.mode=NAND_ECC_SOFT;
  152. s5p_mtd_info->priv=nand_chip;
  153. s5p_mtd_info->owner=THIS_MODULE;
  154. //扫描Nandflash设备
  155. if(nand_scan(s5p_mtd_info,1)){
  156. dev_dbg(&pdev->dev,”nandscanerror”);
  157. gotoerr_free_info;
  158. }
  159. //增加分区信息
  160. ret=mtd_device_parse_register(s5p_mtd_info,NULL,NULL,s5p_nand_partions,ARRAY_SIZE(s5p_nand_partions));
  161. if(!ret)
  162. return0;
  163. err_free_info:
  164. kfree(s5p_mtd_info);
  165. err_free_chip:
  166. kfree(nand_chip);
  167. err_clk_put:
  168. clk_disable(s5p_nand_clk);
  169. clk_put(s5p_nand_clk);
  170. err_iounmap:
  171. //if(s5p_nand_ecc==NULL)
  172. //iounmap(s5p_nand_ecc);
  173. if(s5p_nand_regs==NULL)
  174. iounmap(s5p_nand_regs);
  175. err_exit:
  176. returnret;
  177. }
  178. staticints5p_nand_remove(structplatform_device*pdev){
  179. nand_release(s5p_mtd_info);
  180. kfree(s5p_mtd_info);
  181. kfree(nand_chip);
  182. clk_disable(s5p_nand_clk);
  183. clk_put(s5p_nand_clk);
  184. if(s5p_nand_regs==NULL)
  185. iounmap(s5p_nand_regs);
  186. return0;
  187. }
  188. staticstructplatform_drivers5p_nand_drv={
  189. .driver={
  190. .owner=THIS_MODULE,
  191. .name=”s5p-nand”,
  192. },
  193. .probe=s5p_nand_probe,
  194. .remove=s5p_nand_remove,
  195. };
  196. module_platform_driver(s5p_nand_drv);
  197. MODULE_LICENSE(“GPL”);

源码都在上面,详细的原理仍是参阅视频或许其他材料,这儿就不多说了,假如有任何问题,欢迎留言评论。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/news/guandian/256205.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部