您的位置 首页 解答

S5PV210(TQ210)学习笔记——Nand驱动之HWECC

前几天匆忙间发了一篇关于S5PV210的8位HWECC驱动的文章,但是后来发现存在严重的Bug,就将原来那篇文章删除了,这里先说声抱歉,但是,HWEC

前几天匆忙间发了一篇关于S5PV210的8位HWECC驱动的文章,可是后来发现存在严峻的Bug,就将本来那篇文章删除了,这儿先说声抱愧,可是,HWECC能有用的节约CPU占用量,我细心调试了S5PV210的HWECC部分,现在刚调好1位的HWECC,为了表明误发本来那篇文章的抱歉,现在将代码放在这儿,与我们共享:

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #defineNFCONT_MECCLOCK(1<<7)
  10. #defineNFCONT_SECCLOCK(1<<6)
  11. #defineNFCONT_INITMECC(1<<5)
  12. #defineNFCONT_INITSECC(1<<4)
  13. #defineNFCONT_INITECC(NFCONT_INITMECC|NFCONT_INITSECC)
  14. structs5p_nand_regs{
  15. unsignedlongnfconf;
  16. unsignedlongnfcont;
  17. unsignedlongnfcmmd;
  18. unsignedlongnfaddr;
  19. unsignedlongnfdata;
  20. unsignedlongnfmeccd0;
  21. unsignedlongnfmeccd1;
  22. unsignedlongnfseccd;
  23. unsignedlongnfsblk;
  24. unsignedlongnfeblk;
  25. unsignedlongnfstat;
  26. unsignedlongnfeccerr0;
  27. unsignedlongnfeccerr1;
  28. unsignedlongnfmecc0;
  29. unsignedlongnfmecc1;
  30. unsignedlongnfsecc;
  31. unsignedlongnfmlcbitpt;
  32. };
  33. staticvolatilestructs5p_nand_regs*s5p_nand_regs;
  34. staticstructnand_chip*nand_chip;
  35. staticstructmtd_info*s5p_mtd_info;
  36. staticstructclk*s5p_nand_clk;
  37. staticinteccmode;
  38. staticstructnand_ecclayouts5p_nand_oob_64={
  39. .eccbytes=16,
  40. .eccpos={
  41. 40,41,42,43,44,45,46,47,
  42. 48,49,50,51,52,53,54,55
  43. },
  44. .oobfree={
  45. {
  46. .offset=2,
  47. .length=38
  48. }
  49. }
  50. };
  51. staticstructmtd_partitions5p_nand_partions[]={
  52. [0]={
  53. .name=”bootloader”,
  54. .offset=0,
  55. .size=SZ_1M,
  56. },
  57. [1]={
  58. .name=”kernel”,
  59. .offset=MTDPART_OFS_APPEND,
  60. .size=5*SZ_1M,
  61. },
  62. [2]={
  63. .name=”rootfs”,
  64. .offset=MTDPART_OFS_APPEND,
  65. .size=MTDPART_SIZ_FULL,
  66. },
  67. };
  68. staticvoids5p_nand_cmd_ctrl(structmtd_info*mtd,intcmd,unsignedintctrl)
  69. {
  70. if(ctrl&NAND_CTRL_CHANGE){
  71. if(ctrl&NAND_NCE){
  72. if(cmd!=NAND_CMD_NONE){
  73. s5p_nand_regs->nfcont&=~(1<<1);
  74. }
  75. }else{
  76. s5p_nand_regs->nfcont|=(1<<1);
  77. }
  78. }
  79. if(cmd!=NAND_CMD_NONE){
  80. if(ctrl&NAND_CLE)
  81. s5p_nand_regs->nfcmmd=cmd;
  82. elseif(ctrl&NAND_ALE)
  83. s5p_nand_regs->nfaddr=cmd;
  84. }
  85. }
  86. staticints5p_nand_ready(structmtd_info*mtd){
  87. return(s5p_nand_regs->nfstat&0x1);
  88. }
  89. staticvoids5p_ecc_hwctl(structmtd_info*mtd,intmode){
  90. eccmode=mode;
  91. s5p_nand_regs->nfconf&=~(0x3<<23);
  92. /*InitmainECC&unlock*/
  93. s5p_nand_regs->nfcont|=NFCONT_INITMECC;
  94. s5p_nand_regs->nfcont&=~NFCONT_MECCLOCK;
  95. }
  96. staticints5p_ecc_calculate(structmtd_info*mtd,constuint8_t*dat,
  97. uint8_t*ecc_code){
  98. unsignedlongnfmecc0=s5p_nand_regs->nfmecc0;
  99. /*Lock*/
  100. s5p_nand_regs->nfcont|=NFCONT_MECCLOCK;
  101. ecc_code[0]=(nfmecc0)&0xff;
  102. ecc_code[1]=(nfmecc0>>8)&0xff;
  103. ecc_code[2]=(nfmecc0>>16)&0xff;
  104. ecc_code[3]=(nfmecc0>>24)&0xff;
  105. return0;
  106. }
  107. staticints5p_ecc_correct(structmtd_info*mtd,uint8_t*dat,uint8_t*read_ecc,uint8_t*calc_ecc){
  108. unsignednfmeccd0,nfmeccd1;
  109. unsignedlongnfeccerr0;
  110. nfmeccd0=(read_ecc[1]<<16)|read_ecc[0];
  111. nfmeccd1=(read_ecc[3]<<16)|read_ecc[2];
  112. s5p_nand_regs->nfmeccd0=nfmeccd0;
  113. s5p_nand_regs->nfmeccd1=nfmeccd1;
  114. nfeccerr0=s5p_nand_regs->nfeccerr0;
  115. switch(nfeccerr0&0x3){
  116. case0:
  117. return0;
  118. case1:
  119. printk(“s5p-nand:detectedonebiterror”);
  120. dat[(nfeccerr0>>7)&0x7ff]^=1<<((nfeccerr0>>4)&0x3);
  121. return1;
  122. case2:
  123. case3:
  124. printk(“s5p-nand:detecteduncorrectederror”);
  125. return3;
  126. default:
  127. return-EIO;
  128. }
  129. }
  130. staticints5p_nand_read_page(structmtd_info*mtd,structnand_chip*chip,
  131. uint8_t*buf,intoob_required,intpage)
  132. {
  133. inti,stat,eccsize=chip->ecc.size;
  134. inteccbytes=chip->ecc.bytes;
  135. inteccsteps=chip->ecc.steps;
  136. intsecc_start=mtd->oobsize-eccbytes;
  137. intcol=0;
  138. uint8_t*p=buf;
  139. uint32_t*mecc_pos=chip->ecc.layout->eccpos;
  140. uint8_t*ecc_calc=chip->buffers->ecccalc;
  141. col=mtd->writesize;
  142. chip->cmdfunc(mtd,NAND_CMD_RNDOUT,col,-1);
  143. /*sparearea*/
  144. chip->ecc.hwctl(mtd,NAND_ECC_READ);
  145. chip->read_buf(mtd,chip->oob_poi,secc_start);
  146. chip->ecc.calculate(mtd,p,&ecc_calc[chip->ecc.total]);
  147. chip->read_buf(mtd,chip->oob_poi+secc_start,eccbytes);
  148. col=0;
  149. /*mainarea*/
  150. for(i=0;eccsteps;eccsteps–,i+=eccbytes,p+=eccsize){
  151. chip->cmdfunc(mtd,NAND_CMD_RNDOUT,col,-1);
  152. chip->ecc.hwctl(mtd,NAND_ECC_READ);
  153. chip->read_buf(mtd,p,eccsize);
  154. chip->ecc.calculate(mtd,p,&ecc_calc[i]);
  155. stat=chip->ecc.correct(mtd,p,chip->oob_poi+mecc_pos[0]+
  156. ((chip->ecc.steps-eccsteps)*eccbytes),0);
  157. if(stat==-1)
  158. mtd->ecc_stats.failed++;
  159. col=eccsize*(chip->ecc.steps+1-eccsteps);
  160. }
  161. return0;
  162. }
  163. staticints5p_nand_write_page(structmtd_info*mtd,structnand_chip*chip,
  164. constuint8_t*buf,intoob_required)
  165. {
  166. inti,eccsize=chip->ecc.size;
  167. inteccbytes=chip->ecc.bytes;
  168. inteccsteps=chip->ecc.steps;
  169. intsecc_start=mtd->oobsize-eccbytes;
  170. uint8_t*ecc_calc=chip->buffers->ecccalc;
  171. constuint8_t*p=buf;
  172. uint32_t*eccpos=chip->ecc.layout->eccpos;
  173. /*mainarea*/
  174. for(i=0;eccsteps;eccsteps–,i+=eccbytes,p+=eccsize){
  175. chip->ecc.hwctl(mtd,NAND_ECC_WRITE);
  176. chip->write_buf(mtd,p,eccsize);
  177. chip->ecc.calculate(mtd,p,&ecc_calc[i]);
  178. }
  179. for(i=0;iecc.total;i++)
  180. chip->oob_poi[eccpos[i]]=ecc_calc[i];
  181. /*sparearea*/
  182. chip->ecc.hwctl(mtd,NAND_ECC_WRITE);
  183. chip->write_buf(mtd,chip->oob_poi,secc_start);
  184. chip->ecc.calculate(mtd,p,&ecc_calc[chip->ecc.total]);
  185. for(i=0;i
  186. chip->oob_poi[secc_start+i]=ecc_calc[chip->ecc.total+i];
  187. chip->write_buf(mtd,chip->oob_poi+secc_start,eccbytes);
  188. return0;
  189. }
  190. staticints5p_nand_read_oob(structmtd_info*mtd,structnand_chip*chip,
  191. intpage)
  192. {
  193. uint8_t*ecc_calc=chip->buffers->ecccalc;
  194. inteccbytes=chip->ecc.bytes;
  195. intsecc_start=mtd->oobsize-eccbytes;
  196. chip->cmdfunc(mtd,NAND_CMD_READOOB,0,page);
  197. chip->ecc.hwctl(mtd,NAND_ECC_READ);
  198. chip->read_buf(mtd,chip->oob_poi,secc_start);
  199. chip->ecc.calculate(mtd,0,&ecc_calc[chip->ecc.total]);
  200. chip->read_buf(mtd,chip->oob_poi+secc_start,eccbytes);
  201. return0;
  202. }
  203. staticints5p_nand_write_oob(structmtd_info*mtd,structnand_chip*chip,
  204. intpage)
  205. {
  206. intstatus=0;
  207. inteccbytes=chip->ecc.bytes;
  208. intsecc_start=mtd->oobsize-eccbytes;
  209. uint8_t*ecc_calc=chip->buffers->ecccalc;
  210. inti;
  211. chip->cmdfunc(mtd,NAND_CMD_SEQIN,mtd->writesize,page);
  212. /*sparearea*/
  213. chip->ecc.hwctl(mtd,NAND_ECC_WRITE);
  214. chip->write_buf(mtd,chip->oob_poi,secc_start);
  215. chip->ecc.calculate(mtd,0,&ecc_calc[chip->ecc.total]);
  216. for(i=0;i
  217. chip->oob_poi[secc_start+i]=ecc_calc[chip->ecc.total+i];
  218. chip->write_buf(mtd,chip->oob_poi+secc_start,eccbytes);
  219. /*SendcommandtoprogramtheOOBdata*/
  220. chip->cmdfunc(mtd,NAND_CMD_PAGEPROG,-1,-1);
  221. status=chip->waitfunc(mtd,chip);
  222. returnstatus&NAND_STATUS_FAIL?-EIO:0;
  223. }
  224. staticints5p_nand_probe(structplatform_device*pdev){
  225. intret=0;
  226. structresource*mem;
  227. //硬件部分初始化
  228. mem=platform_get_resource(pdev,IORESOURCE_MEM,0);
  229. if(!mem){
  230. dev_err(&pdev->dev,”cantgetI/Oresourcemem”);
  231. return-ENXIO;
  232. }
  233. s5p_nand_regs=(volatilestructs5p_nand_regs*)ioremap(mem->start,resource_size(mem));
  234. if(s5p_nand_regs==NULL){
  235. dev_err(&pdev->dev,”ioremapfailed”);
  236. ret=-EIO;
  237. gotoerr_exit;
  238. }
  239. s5p_nand_clk=clk_get(&pdev->dev,”nand”);
  240. if(s5p_nand_clk==NULL){
  241. dev_dbg(&pdev->dev,”getclkfailed”);
  242. ret=-ENODEV;
  243. gotoerr_iounmap;
  244. }
  245. clk_enable(s5p_nand_clk);
  246. //s5p_nand_regs->nfconf&=~(0xfff<<4);
  247. //s5p_nand_regs->nfconf|=(3<<12)|(5<<8)|(3<<4);
  248. //s5p_nand_regs->nfcont|=3;
  249. //分配驱动相关结构体
  250. nand_chip=(structnand_chip*)kzalloc(sizeof(structnand_chip),GFP_KERNEL);
  251. if(nand_chip==NULL){
  252. dev_err(&pdev->dev,”failedtoallocatenand_chipstructure”);
  253. ret=-ENOMEM;
  254. gotoerr_clk_put;
  255. }
  256. s5p_mtd_info=(structmtd_info*)kzalloc(sizeof(structmtd_info),GFP_KERNEL);
  257. if(s5p_mtd_info==NULL){
  258. dev_err(&pdev->dev,”failedtoallocatemtd_infostructure”);
  259. ret=-ENOMEM;
  260. gotoerr_free_chip;
  261. }
  262. //设置驱动相关结构体
  263. nand_chip->IO_ADDR_R=(unsignedchar*)&s5p_nand_regs->nfdata;
  264. nand_chip->IO_ADDR_W=(unsignedchar*)&s5p_nand_regs->nfdata;
  265. nand_chip->cmd_ctrl=s5p_nand_cmd_ctrl;
  266. nand_chip->dev_ready=s5p_nand_ready;
  267. nand_chip->ecc.mode=NAND_ECC_HW;
  268. nand_chip->ecc.hwctl=s5p_ecc_hwctl;
  269. nand_chip->ecc.calculate=s5p_ecc_calculate;
  270. nand_chip->ecc.correct=s5p_ecc_correct;
  271. nand_chip->ecc.read_oob=s5p_nand_read_oob;
  272. nand_chip->ecc.write_oob=s5p_nand_write_oob;
  273. nand_chip->ecc.read_page=s5p_nand_read_page;
  274. nand_chip->ecc.write_page=s5p_nand_write_page;
  275. nand_chip->ecc.size=512;
  276. nand_chip->ecc.bytes=4;
  277. nand_chip->ecc.strength=1;
  278. nand_chip->ecc.layout=&s5p_nand_oob_64;
  279. s5p_mtd_info->priv=nand_chip;
  280. s5p_mtd_info->owner=THIS_MODULE;
  281. //扫描Nandflash设备
  282. if(nand_scan(s5p_mtd_info,1)){
  283. dev_dbg(&pdev->dev,”nandscanerror”);
  284. gotoerr_free_info;
  285. }
  286. //增加分区信息
  287. ret=mtd_device_parse_register(s5p_mtd_info,NULL,NULL,s5p_nand_partions,ARRAY_SIZE(s5p_nand_partions));
  288. if(!ret)
  289. return0;
  290. err_free_info:
  291. kfree(s5p_mtd_info);
  292. err_free_chip:
  293. kfree(nand_chip);
  294. err_clk_put:
  295. clk_disable(s5p_nand_clk);
  296. clk_put(s5p_nand_clk);
  297. err_iounmap:
  298. iounmap(s5p_nand_regs);
  299. err_exit:
  300. returnret;
  301. }
  302. staticints5p_nand_remove(structplatform_device*pdev){
  303. nand_release(s5p_mtd_info);
  304. kfree(s5p_mtd_info);
  305. kfree(nand_chip);
  306. clk_disable(s5p_nand_clk);
  307. clk_put(s5p_nand_clk);
  308. iounmap(s5p_nand_regs);
  309. return0;
  310. }
  311. staticstructplatform_drivers5p_nand_drv={
  312. .driver={
  313. .owner=THIS_MODULE,
  314. .name=”s5p-nand”,
  315. },
  316. .probe=s5p_nand_probe,
  317. .remove=s5p_nand_remove,
  318. };
  319. module_platform_driver(s5p_nand_drv);
  320. MODULE_LICENSE(“GPL”);

接下来的几天我会持续调试一下8位HWECC,不知道能不能调好,从天嵌技术支持那里得悉,天嵌技术人员其时也调试过8位HWECC,他们从三星的某个材料中发现S5PV210的HWECC模块只能运用1位HWECC,不知道是不是真的,我要自己来验证一下。

如果有什么问题欢迎留言评论,转载本来那篇HWECC文章的朋友请自己批改一下吧。

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

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

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

微信扫一扫关注我们

返回顶部