新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > S5PV210(TQ210)學習筆記——Nand驅動之HWECC

        S5PV210(TQ210)學習筆記——Nand驅動之HWECC

        作者: 時間:2016-11-28 來源:網絡 收藏
        前幾天匆忙間發了一篇關于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");

        本文引用地址:http://www.104case.com/article/201611/322813.htm

        接下來的幾天我會繼續調試一下8位HWECC,不知道能不能調好,從天嵌技術支持那里獲悉,天嵌技術人員當時也調試過8位HWECC,他們從三星的某個資料中發現S5PV210的HWECC模塊只能使用1位HWECC,不知道是不是真的,我要自己來驗證一下。

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



        關鍵詞: S5PV210Nand驅動HWEC

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 兰坪| 财经| 滁州市| 濉溪县| 井研县| 汝南县| 仪陇县| 田东县| 左权县| 桂东县| 睢宁县| 新郑市| 武隆县| 都匀市| 酒泉市| 雷山县| 青河县| 沙田区| 韶关市| 东海县| 肥城市| 准格尔旗| 登封市| 呼图壁县| 洛阳市| 黄大仙区| 梁平县| 抚宁县| 吉首市| 庆城县| 宝清县| 贡嘎县| 柳河县| 蒙山县| 金华市| 宜都市| 炎陵县| 资中县| 万盛区| 沅陵县| 中山市|