<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

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

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

          作者: 時(shí)間:2016-11-28 來源:網(wǎng)絡(luò) 收藏
          前幾天匆忙間發(fā)了一篇關(guān)于S5PV210的8位HWECC驅(qū)動(dòng)的文章,但是后來發(fā)現(xiàn)存在嚴(yán)重的Bug,就將原來那篇文章刪除了,這里先說聲抱歉,但是,HWECC能有效的節(jié)省CPU占用量,我仔細(xì)調(diào)試了S5PV210的HWECC部分,現(xiàn)在剛調(diào)好1位的HWECC,為了表示誤發(fā)原來那篇文章的歉意,現(xiàn)在將代碼放在這里,與大家分享:
          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. //分配驅(qū)動(dòng)相關(guān)結(jié)構(gòu)體
          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. //設(shè)置驅(qū)動(dòng)相關(guān)結(jié)構(gòu)體
          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設(shè)備
          282. if(nand_scan(s5p_mtd_info,1)){
          283. dev_dbg(&pdev->dev,"nandscanerror");
          284. gotoerr_free_info;
          285. }
          286. //添加分區(qū)信息
          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");

          本文引用地址:http://www.ex-cimer.com/article/201611/322813.htm

          接下來的幾天我會(huì)繼續(xù)調(diào)試一下8位HWECC,不知道能不能調(diào)好,從天嵌技術(shù)支持那里獲悉,天嵌技術(shù)人員當(dāng)時(shí)也調(diào)試過8位HWECC,他們從三星的某個(gè)資料中發(fā)現(xiàn)S5PV210的HWECC模塊只能使用1位HWECC,不知道是不是真的,我要自己來驗(yàn)證一下。

          如果有什么問題歡迎留言討論,轉(zhuǎn)載原來那篇HWECC文章的朋友請(qǐng)自己修正一下吧。



          評(píng)論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();