新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > S5PV210(TQ210)學(xué)習(xí)筆記——Nand flash驅(qū)動(dòng)編寫

S5PV210(TQ210)學(xué)習(xí)筆記——Nand flash驅(qū)動(dòng)編寫

作者: 時(shí)間:2016-11-28 來源:網(wǎng)絡(luò) 收藏
跟裸機(jī)程序一樣,S5PV210Nand flash模塊跟S3C2440的Nand flash模塊非常相似,如果不引入ECC,驅(qū)動(dòng)程序的編寫也非常簡單,具體的分析及編寫過程強(qiáng)烈推薦觀看韋東山老師的視頻教程,我是使用的Linux-3.8.6(Linux-3.8.3也一樣)內(nèi)核,驅(qū)動(dòng)的API函數(shù)有些變化,不過原理是相通的,稍微看一下內(nèi)核源碼并參考下其他平臺(tái)的相關(guān)代碼就可以自己寫出Nand flash驅(qū)動(dòng)了,下面是Nand flash驅(qū)動(dòng)的源碼,沒有啟用ECC,當(dāng)然,你也可以改成軟件ECC,但是我的覺得既然軟件ECC不如HWECC快,我就采用硬件ECC吧,我會(huì)在下篇文章中加入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. //分配驅(qū)動(dòng)相關(guān)結(jié)構(gòu)體
  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. //設(shè)置驅(qū)動(dòng)相關(guān)結(jié)構(gòu)體
  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設(shè)備
  155. if(nand_scan(s5p_mtd_info,1)){
  156. dev_dbg(&pdev->dev,"nandscanerror");
  157. gotoerr_free_info;
  158. }
  159. //添加分區(qū)信息
  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");

源碼都在上面,具體的原理還是參考視頻或者其他資料,這里就不多說了,如果有任何問題,歡迎留言討論。

本文引用地址:http://m.butianyuan.cn/article/201611/322812.htm


評論


技術(shù)專區(qū)

關(guān)閉