微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > S5PV210(TQ210)学习笔记——Nand驱动之HWECC

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

时间: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->stat=chip

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top