Chinaunix首页 | 论坛 | 博客
  • 博客访问: 607526
  • 博文数量: 107
  • 博客积分: 713
  • 博客等级: 上士
  • 技术积分: 1050
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-05 00:14
个人简介

呵呵

文章分类

全部博文(107)

文章存档

2015年(2)

2014年(17)

2013年(29)

2012年(52)

2011年(7)

分类: LINUX

2014-09-26 15:19:28

第一部分:Nandflash控制部分

arch/mips/lib/board.c    ->    driver/mtd/nand/nand.c

点击(此处)折叠或打开

  1. void nand_init(void)
  2. {
  3.     int i;
  4.     unsigned int size = 0;
  5.     for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
  6.         nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]);
  7.         size += nand_info[i].size / 1024;
  8.         if (nand_curr_device == -1)
  9.             nand_curr_device = i;
  10.     }
  11.     if(size)
  12.         printf("%u MiB\n", size / 1024);

  13. #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
  14.     /*
  15.      * Select the chip in the board/cpu specific driver
  16.      */
  17.     board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);
  18. #endif
  19. }
nand初始化最先调用nand_init(),然后调用 nand_init_chip()对nand进行初始化


点击(此处)折叠或打开

  1. static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand,
  2.              ulong base_addr)
  3. {
  4.     int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;
  5.     int __attribute__((unused)) i = 0;

  6.     if (maxchips < 1)
  7.         maxchips = 1;
  8.     mtd->priv = nand;    //用mtd->priv指向nand_chip结构的nand

  9.     nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;        //base_addr = 0xbc045300,在blx.h中定义
  10.     if (board_nand_init(nand) == 0) {                     //调用board_nand_init(nand)对板子初始化
  11.         if (nand_scan(mtd, maxchips) == 0) {
  12.             if (!mtd->name)
  13.                 mtd->name = (char *)default_nand_name;
  14. #ifdef CONFIG_NEEDS_MANUAL_RELOC
  15.             else
  16.                 mtd->name += gd->reloc_off;
  17. #endif

  18. #ifdef CONFIG_MTD_DEVICE
  19.             /*
  20.              * Add MTD device so that we can reference it later
  21.              * via the mtdcore infrastructure (e.g. ubi).
  22.              */
  23.             sprintf(dev_name[i], "nand%d", i);
  24.             mtd->name = dev_name[i++];
  25.             add_mtd_device(mtd);
  26. #endif
  27.             board_nand_init_snd(mtd);
  28.         } else
  29.             mtd->name = NULL;
  30.     } else {
  31.         mtd->name = NULL;
  32.         mtd->size = 0;
  33.     }
  34. }


点击(此处)折叠或打开

  1. int board_nand_init(struct nand_chip *nand)
  2. {
  3.     u_int32_t cfg;
  4.     u_int32_t ctrl;

  5.     cfg = GSC3280_FLCONF_PSM;
  6.     cfg |= GSC3280_FLCONF_TWB;
  7.     cfg |= GSC3280_FLCONF_TWHR;
  8.     cfg |= GSC3280_FLCONF_TWP;
  9.     cfg |= GSC3280_FLCONF_TRP;
  10.     cfg |= GSC3280_FLCONF_TWH;
  11.     writel(cfg,GSC3280_REGADDR_NFC_CONF);

  12.     /* initialize nand_chip data structure */
  13.     nand->IO_ADDR_R = (void *)GSC3280_REGADDR_NFC_DATA;
  14.     nand->IO_ADDR_W = (void *)GSC3280_REGADDR_NFC_DATA;
  15.     nand->select_chip = NULL;

  16.     /* hwcontrol always must be implemented */
  17.     nand->cmd_ctrl = gsc3280_hwcontrol;
  18.     nand->dev_ready = gsc3280_dev_ready;
  19.     nand->set_pb = gsc3280_set_pb;
  20. #ifdef CONFIG_GSC3280_USE_DMA
  21.     nand->dma_trans=gsc3280_nand_dma_transfer;
  22. #endif
  23.     nand->write_page=gsc3280_nand_write_page;
  24.     nand->ecc.read_page=gsc3280_nand_read_page_ecc;
  25.     nand->ecc.write_page=gsc3280_nand_write_page_ecc;
  26.     nand->ecc.read_page_raw = gsc3280_nand_read_page_raw;
  27.     nand->ecc.write_page_raw = gsc3280_nand_write_page_raw;
  28.     nand->ecc.size = 256;
  29.     nand->ecc.bytes = 3;
  30. #ifdef CONFIG_GSC3280_NAND_HWECC
  31.         nand->ecc.mode = NAND_ECC_HW;
  32.         nand->ecc.correct = gsc3280_nand_check_hwecc;
  33. #else
  34.         nand->ecc.mode = NAND_ECC_SOFT;
  35. #endif
  36. #ifdef CONFIG_GSC3280_NAND_BBT
  37.         nand->options = NAND_USE_FLASH_BBT;
  38. #else
  39.         nand->options = NAND_SKIP_BBTSCAN;
  40. #endif
  41.     return 0;
  42. }
这部分的详细注释看第二部分。



点击(此处)折叠或打开

  1. int nand_scan(struct mtd_info *mtd, int maxchips)
  2. {
  3.     int ret;

  4.     ret = nand_scan_ident(mtd, maxchips);
  5.     if (!ret)
  6.         ret = nand_scan_tail(mtd);
  7.     return ret;
  8. }



点击(此处)折叠或打开

  1. int nand_scan_ident(struct mtd_info *mtd, int maxchips)
  2. {
  3.     int i, busw, nand_maf_id;
  4.     struct nand_chip *chip = mtd->priv;
  5.     struct nand_flash_dev *type;

  6.     /* Get buswidth to select the correct functions */
  7.     busw = chip->options & NAND_BUSWIDTH_16;
  8.     /* Set the default functions */
  9.     nand_set_defaults(chip, busw);

  10.     /* Read the flash type */
  11.     type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);

  12.     if (IS_ERR(type)) {
  13. #ifndef CONFIG_SYS_NAND_QUIET_TEST
  14.         printk(KERN_WARNING "No NAND device found!!!\n");
  15. #endif
  16.         chip->select_chip(mtd, -1);
  17.         return PTR_ERR(type);
  18.     }

  19.     /* Check for a chip array */
  20.     for (i = 1; i < maxchips; i++) {
  21.         chip->select_chip(mtd, i);
  22.         /* See comment in nand_get_flash_type for reset */
  23.         chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
  24.         /* Send the command for reading device ID */
  25.         chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
  26.         /* Read manufacturer and device IDs */
  27.         if (nand_maf_id != chip->read_byte(mtd) ||
  28.          type->id != chip->read_byte(mtd))
  29.             break;
  30.     }
  31. #ifdef DEBUG
  32.     if (i > 1)
  33.         printk(KERN_INFO "%d NAND chips detected\n", i);
  34. #endif

  35.     /* Store the number of chips and calc total size for mtd */
  36.     chip->numchips = i;
  37.     mtd->size = i * chip->chipsize;

  38.     return 0;
  39. }











第二部分:GSC3280控制部分

nandflash-S34ML01G1_04G1参数图如下:






点击(此处)折叠或打开

  1. int board_nand_init(struct nand_chip *nand)
  2. {
  3.     u_int32_t cfg;
  4.     u_int32_t ctrl;
  5.                                  //hclk = 166M,所以thclk = 1/(0.166 G) = 6 ns,根据上表,再将这个值带入
  6.     cfg = GSC3280_FLCONF_PSM;    //GSC3280_FLCONF_PSM = (1<<31),表示正常模式
  7.     cfg |= GSC3280_FLCONF_TWB;   //GSC3280_FLCONF_TWB (0x13)<<23 ,    twb = thclk*(TWB+1)>100,可得TWB>15.6 或TWB>0x10;    
  8.     cfg |= GSC3280_FLCONF_TWHR;  //GSC3280_FLCONF_TWHR (0x13)<<17,    twhr = thclk*(TWHR+1)>60,可得TWHR>9    
  9.     cfg |= GSC3280_FLCONF_TWP;    //GSC3280_FLCONF_TWP   (0x9)<<11,    twp = thclk*(TWP+1)>12,可得TWP>1   
  10.     cfg |= GSC3280_FLCONF_TRP;    //GSC3280_FLCONF_TRP (0x9)<<5 ,    trp = thclk*(TRP+1)>12,可得TRP>1    
  11.     cfg |= GSC3280_FLCONF_TWH;    //GSC3280_FLCONF_TWH       0x4,    twh = thclk*(TWH+1)>10,可得TWH>1    
  12.     writel(cfg,GSC3280_REGADDR_NFC_CONF);

  13.     /* initialize nand_chip data structure */
  14.     nand->IO_ADDR_R = (void *)GSC3280_REGADDR_NFC_DATA;        //设置IO_ADDR_X的地址为数据寄存器
  15.     nand->IO_ADDR_W = (void *)GSC3280_REGADDR_NFC_DATA;
  16.     nand->select_chip = NULL;

  17.     /* hwcontrol always must be implemented */
  18.     nand->cmd_ctrl = gsc3280_hwcontrol;            //根据控制命令来设置IO_ADDR_X
  19.     nand->dev_ready = gsc3280_dev_ready;
  20.     nand->set_pb = gsc3280_set_pb;
  21. #ifdef CONFIG_GSC3280_USE_DMA
  22.     nand->dma_trans=gsc3280_nand_dma_transfer;
  23. #endif
  24.     nand->write_page=gsc3280_nand_write_page;
  25.     nand->ecc.read_page=gsc3280_nand_read_page_ecc;
  26.     nand->ecc.write_page=gsc3280_nand_write_page_ecc;
  27.     nand->ecc.read_page_raw = gsc3280_nand_read_page_raw;
  28.     nand->ecc.write_page_raw = gsc3280_nand_write_page_raw;
  29.     nand->ecc.size = 256;
  30.     nand->ecc.bytes = 3;
  31. #ifdef CONFIG_GSC3280_NAND_HWECC
  32.         nand->ecc.mode = NAND_ECC_HW;
  33.         nand->ecc.correct = gsc3280_nand_check_hwecc;
  34. #else
  35.         nand->ecc.mode = NAND_ECC_SOFT;
  36. #endif
  37. #ifdef CONFIG_GSC3280_NAND_BBT
  38.         nand->options = NAND_USE_FLASH_BBT;
  39. #else
  40.         nand->options = NAND_SKIP_BBTSCAN;
  41. #endif
  42.     return 0;
  43. }


点击(此处)折叠或打开

  1. int board_nand_init_snd(struct mtd_info *mtd)
  2. {
  3.     uint32_t ctrl;
  4.     
  5.     ctrl=readl((void*)GSC3280_REGADDR_NFC_CTRL);

  6. #ifdef CONFIG_MTD_GSC3280_NAND_HWECC
  7.     ctrl |= GSC3280_FLCTRL_EEN;

  8. #endif
  9.     if(mtd->writesize == 0x800)
  10.         ctrl |= GSC3280_FLCTRL_PS;/*page=2k*/
  11.     if(mtd->erasesize/mtd->writesize == 128)
  12.         ctrl |= GSC3280_FLCTRL_BS;/*Block=128pages*/
  13.     if(mtd->oobsize != 0x40 && mtd->oobsize != 0x80)
  14.         ctrl |= GSC3280_FLCTRL_SS;/*Extended mode*/
  15.     ctrl |= GSC3280_FLCTRL_ADDRC;/*Default 5 ADDR CYCLES*/
  16.     writel(ctrl, (void *)GSC3280_REGADDR_NFC_CTRL);
  17.     return 0;    

  18. }




点击(此处)折叠或打开

  1. static void gsc3280_hwcontrol(struct mtd_info *mtd, long cmd, unsigned int ctrl)
  2. {
  3.     struct nand_chip *chip = mtd->priv;

  4.         
  5.     if(ctrl & NAND_CA){
  6.             switch(cmd){
  7.                 case NAND_CMD_READ0:
  8. //                    chip->addrflag=3;//dma buffer
  9.                 case NAND_CMD_READ1:
  10.                 case NAND_CMD_READID:
  11.                 case NAND_CMD_READOOB:
  12.                 case NAND_CMD_RNDOUT:
  13. //                case NAND_CMD_RNDOUTSTART:
  14.                     chip->addrflag=0;
  15.                     break;
  16.                 case NAND_CMD_WRITE0:
  17.                 case NAND_CMD_SEQIN:
  18.                     chip->addrflag=1;
  19.                     break;
  20.                 case NAND_CMD_ERASE1:    
  21.                     chip->addrflag=2;    
  22.                     break;
  23.             }

  24.     }
  25.     
  26.     if (ctrl & NAND_CTRL_CHANGE) {
  27.         ulong IO_ADDR_W = GSC3280_REGADDR_NFC_CONF;
  28.         if (ctrl & NAND_CLE){
  29.             IO_ADDR_W = GSC3280_REGADDR_NFC_COMM;//cmd reg
  30.         }
  31.         else if (ctrl & NAND_ALE){

  32.             switch(chip->addrflag){
  33.                 case 0:
  34.                     IO_ADDR_W = GSC3280_REGADDR_NFC_ADDR0L;
  35.                     break;
  36.                 case 1:
  37.                     IO_ADDR_W = GSC3280_REGADDR_NFC_ADDR1L;
  38.                     break;
  39.                 case 2:
  40.                     IO_ADDR_W = GSC3280_REGADDR_NFC_ADDR1L;
  41.                     break;
  42.                 case 3:
  43.                     IO_ADDR_W = GSC3280_NFC_BASEADDR;
  44.                     break;
  45.             }
  46.         }
  47.         else{
  48.             IO_ADDR_W = GSC3280_REGADDR_NFC_DATA;//data reg
  49.         }
  50.         chip->IO_ADDR_W = (void *)IO_ADDR_W;
  51.         chip->IO_ADDR_R = (void *)IO_ADDR_W;
  52.     }
  53.     if (cmd != NAND_CMD_NONE && !(ctrl & NAND_CA) ){
  54.         writel(cmd, chip->IO_ADDR_W);
  55.     }
  56. }
gsc3280_hwcontrol功能:主要是根据命令来设定IO_ADDR_W和IO_ADDR_R地址。
这个函数会在 nand_command(struct mtd_info *mtd, unsigned int command,int column, int page_addr) 中被调用,如下


点击(此处)折叠或打开

  1. static void nand_command(struct mtd_info *mtd, unsigned int command,
  2.              int column, int page_addr)
  3. {
  4.     register struct nand_chip *chip = mtd->priv;
  5.     int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;    //#define NAND_CTRL_CLE (NAND_NCE | NAND_CLE),   用来设置命令
  6.                                                     //#define NAND_CTRL_ALE (NAND_NCE | NAND_ALE),   用来设置读写地址
  7.                                                     //#define NAND_CTRL_CHANGE 0x80
  8.     uint32_t rst_sts_cnt = CONFIG_SYS_NAND_RESET_CNT;

  9.     /*
  10.      * Write out the command to the device.
  11.      */
  12.     if (command == NAND_CMD_SEQIN) {
  13.         int readcmd;

  14.         if (column >= mtd->writesize) {
  15.             /* OOB area */
  16.             column -= mtd->writesize;
  17.             readcmd = NAND_CMD_READOOB;
  18.         } else if (column < 256) {
  19.             /* First 256 bytes --> READ0 */
  20.             readcmd = NAND_CMD_READ0;
  21.         } else {
  22.             column -= 256;
  23.             readcmd = NAND_CMD_READ1;
  24.         }
  25.         chip->cmd_ctrl(mtd, readcmd, ctrl);
  26.         ctrl &= ~NAND_CTRL_CHANGE;
  27.     }
  28.     chip->cmd_ctrl(mtd, command, ctrl);    //写入命令

  29.     /*
  30.      * Address cycle, when necessary
  31.      */
  32.     ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
  33.     /* Serially input address */
  34.     if (column != -1) {
  35.         /* Adjust columns for 16 bit buswidth */
  36.         if (chip->options & NAND_BUSWIDTH_16)
  37.             column >>= 1;
  38.         chip->cmd_ctrl(mtd, column, ctrl);
  39.         ctrl &= ~NAND_CTRL_CHANGE;
  40.     }
  41.     if (page_addr != -1) {
  42.         chip->cmd_ctrl(mtd, page_addr, ctrl);
  43.         ctrl &= ~NAND_CTRL_CHANGE;
  44.         chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
  45.         /* One more address cycle for devices > 32MiB */
  46.         if (chip->chipsize > (32 << 20))
  47.             chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
  48.     }
  49.     chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);

  50.     /*
  51.      * program and erase have their own busy handlers
  52.      * status and sequential in needs no delay
  53.      */
  54.     switch (command) {

  55.     case NAND_CMD_PAGEPROG:
  56.     case NAND_CMD_ERASE1:
  57.     case NAND_CMD_ERASE2:
  58.     case NAND_CMD_SEQIN:
  59.     case NAND_CMD_STATUS:
  60.         return;

  61.     case NAND_CMD_RESET:
  62.         if (chip->dev_ready)
  63.             break;
  64.         udelay(chip->chip_delay);
  65.         chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
  66.              NAND_CTRL_CLE | NAND_CTRL_CHANGE);
  67.         chip->cmd_ctrl(mtd,
  68.              NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
  69.         while (!(chip->read_byte(mtd) & NAND_STATUS_READY) &&
  70.             (rst_sts_cnt--));
  71.         return;

  72.         /* This applies to read commands */
  73.     default:
  74.         /*
  75.          * If we don't have access to the busy pin, we apply the given
  76.          * command delay
  77.          */
  78.         if (!chip->dev_ready) {
  79.             udelay(chip->chip_delay);
  80.             return;
  81.         }
  82.     }
  83.     /* Apply this short delay always to ensure that we do wait tWB in
  84.      * any case on any machine. */
  85.     ndelay(100);

  86.     nand_wait_ready(mtd);
  87. }








点击(此处)折叠或打开

  1. static int gsc3280_dev_ready(struct mtd_info *mtd)
  2. {
  3.     uint8_t state = readb((const void *)GSC3280_REGADDR_NFC_STATE);
  4.     return (state&0x61)==0x1;
  5. }
 gsc3280_dev_ready:读取NFC_STATE状态标志位,0x61=1100001,第0位表示输入信号此时是否为忙,为1表示不忙,0表示忙,5-6为表示控制器是否为空闲状态,00表示空闲,01表示控制器正在处理 命令。gsc3280_dev_ready返回1表示空闲。

点击(此处)折叠或打开

  1. static int gsc3280_set_pb(struct mtd_info *mtd, loff_t lower_block ,loff_t upper_block)
  2. {
  3.     u_int32_t pb0;

  4.     struct nand_chip *chip=mtd->priv;

  5.     if((lower_block*mtd->erasesize)>chip->chipsize||(upper_block*mtd->erasesize)>chip->chipsize){
  6.         printf("outside the flash area \n");
  7.         return -1;
  8.     }

  9.     pb0=(lower_block>>16)|(upper_block&0x0000ffff);     //????????

  10.     writel(pb0,GSC3280_REGADDR_NFC_PB0);
  11.     printf("the blocks from %lld to %lld is protected!\n",lower_block,upper_block);
  12.     return 0;
  13. }
 gsc3280_set_pb:设置保护块的起始地址与结束地址,保护块区间不能进行写与擦除操作。
??????:pb0=(lower_block>>16)|(upper_block&0x0000ffff);

点击(此处)折叠或打开

  1. int gsc3280_nand_dma_transfer(struct mtd_info *mtd, uint8_t *buffer, int size, int col, int isread){
  2.     u_int32_t cntr;
  3.     unsigned long    memaddr=virt_to_phys((void *)buffer);  //????
  4.     
  5.     int state;
  6.     if(!col){
  7.         cntr=(size>>2)<<16;        
  8.     }
  9.     else{
  10.         cntr=((mtd->writesize-col)>>2)<<16 | col;   //?????
  11.     }
  12.     writel(cntr,GSC3280_REGADDR_NFC_DMACNTR);
  13.         writel(memaddr,GSC3280_REGADDR_NFC_DMAADDR);    //用于设置传输块大小以及要传输的地址

  14.     if(isread){
  15.         // 0x0101d000
  16.         writel(0x0101d000,GSC3280_REGADDR_NFC_DMACTRL);//使能DMA、读取buffer数据到AHB(DMA_DIR=1)、??、单向传输地址递增(DMA_BURST=010)
  17.     }
  18.     else
  19.         //ox0100d000
  20.         writel(0x0100d000,GSC3280_REGADDR_NFC_DMACTRL);   //使能DMA,将AHB总线数据写到buffer

  21.         do{
  22.                 state=readl(GSC3280_REGADDR_NFC_STATE);    //一直等待到DMA传输完毕
  23.         }while(state&0x80);
  24.     return 0;

  25. }


点击(此处)折叠或打开

  1. static int gsc3280_nand_check_hwecc(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc
  2. )
  3. {
  4.         u32 eccstatus;
  5.         u8 eccerror;
  6.         u8 ecccorrect;

  7.         eccstatus=readl(GSC3280_REGADDR_NFC_ECCSTATUS);    //读取校验信息

  8.         if(readl(GSC3280_REGADDR_NFC_CTRL)&GSC3280_FLCTRL_PS){    //检验需要校验多少位
  9.                 eccerror=(eccstatus>>16)&&0xff;
  10.                 ecccorrect=eccstatus&&0xff;
  11.         }
  12.         else{
  13.                 eccerror=(eccstatus>>16)&&0xf;
  14.                 ecccorrect=eccstatus&&0xf;
  15.         }


  16.         if(!eccerror||!(eccerror^ecccorrect)){        //检测校验是否正确
  17.                 return 0;
  18.         }
  19.         else{
  20.                 printf("gsc3280_nand_correct_data: not implemented\n");
  21.                 return -1;
  22.         }
  23. }



点击(此处)折叠或打开

  1. static int gsc3280_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
  2.              uint8_t *buf, int page)
  3. {
  4. #ifdef CONFIG_GSC3280_USE_DMA
  5.     chip->dma_trans(mtd,buf,mtd->writesize,0,1);
  6. #else
  7.     memcpy(buf,(const void *)GSC3280_NFC_BASEADDR,mtd->writesize);        //读取页
  8. #endif
  9.     return chip->ecc.read_oob(mtd, chip, page, 1);        //??????????
  10. }




点击(此处)折叠或打开

  1. static int gsc3280_nand_read_page_ecc(struct mtd_info *mtd, struct nand_chip *chip,
  2.                 uint8_t *buf, int page)
  3. {
  4. #ifdef CONFIG_GSC3280_NAND_HWECC
  5.         int ret;
  6.         ret=chip->ecc.correct(NULL,NULL,NULL,NULL);
  7.         if(ret)
  8.                 return -1;
  9.         else{
  10.                 chip->ecc.read_page_raw(mtd, chip, buf, page);
  11.         }
  12. #else
  13.     int i, eccsize = chip->ecc.size;
  14.     int eccbytes = chip->ecc.bytes;
  15.     int eccsteps = chip->ecc.steps;
  16.     uint8_t *p = buf;
  17.     uint8_t *ecc_calc = chip->buffers->ecccalc;
  18.     uint8_t *ecc_code = chip->buffers->ecccode;
  19.     uint32_t *eccpos = chip->ecc.layout->eccpos;

  20.     chip->ecc.read_page_raw(mtd, chip, buf, page);

  21.     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
  22.         chip->ecc.calculate(mtd, p, &ecc_calc[i]);

  23.     for (i = 0; i < chip->ecc.total; i++){
  24.         ecc_code[i] = chip->oob_poi[eccpos[i]];
  25.     }

  26.     eccsteps = chip->ecc.steps;
  27.     p = buf;

  28.     for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  29.         int stat;

  30.         stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
  31.         if (stat < 0)
  32.             mtd->ecc_stats.failed++;
  33.         else
  34.             mtd->ecc_stats.corrected += stat;
  35.     }
  36. #endif
  37.     return 0;
  38. }



点击(此处)折叠或打开

  1. static void gsc3280_nand_write_page_ecc(struct mtd_info *mtd, struct nand_chip *chip,
  2.                 uint8_t *buf)
  3. {
  4. #ifndef CONFIG_GSC3280_NAND_HWECC
  5.     int i, eccsize = chip->ecc.size;
  6.     int eccbytes = chip->ecc.bytes;
  7.     int eccsteps = chip->ecc.steps;
  8.     uint8_t *ecc_calc = chip->buffers->ecccalc;
  9.     const uint8_t *p = buf;
  10.     uint32_t *eccpos = chip->ecc.layout->eccpos;

  11.     /* Software ecc calculation */
  12.     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
  13.         chip->ecc.calculate(mtd, p, &ecc_calc[i]);

  14.     for (i = 0; i < chip->ecc.total; i++)
  15.         chip->oob_poi[eccpos[i]] = ecc_calc[i];
  16. #endif
  17.     chip->ecc.write_page_raw(mtd, chip, buf);

  18. }



点击(此处)折叠或打开

  1. static void gsc3280_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
  2.                 const uint8_t *buf)
  3. {
  4. #ifdef CONFIG_GSC3280_USE_DMA
  5.     chip->dma_trans(mtd,buf,mtd->writesize,0,0);
  6. #else
  7.     memcpy((void*)GSC3280_NFC_BASEADDR,buf,mtd->writesize);
  8. #endif
  9.     memset((void*)GSC3280_NFC_BASEADDR+mtd->writesize,0xff,mtd->oobsize);
  10. }




点击(此处)折叠或打开

  1. static int gsc3280_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
  2.              const uint8_t *buf, int page, int cached, int raw)
  3. {
  4.     int status;
  5.     
  6.     chip->ecc.write_page(mtd, chip, buf);
  7.     chip->cmdfunc(mtd, NAND_CMD_WRITE0, -1, page);
  8.     status = chip->waitfunc(mtd, chip);
  9.     /*
  10.      * See if operation failed and additional status checks are
  11.      * available
  12.      */
  13.     if ((status & NAND_STATUS_FAIL) && (chip->errstat))
  14.         status = chip->errstat(mtd, chip, FL_WRITING, status, page);

  15.     if (status & NAND_STATUS_FAIL){
  16.         return -1;
  17.     }

  18.     chip->ecc.write_oob(mtd, chip, page&chip->pagemask);
  19.     return 0;
  20. }






































































































阅读(1128) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~