add 16-bit nand flash support and speed up flash read & write
authorhxy <hxy@rock-chips.com>
Fri, 26 Nov 2010 01:11:49 +0000 (09:11 +0800)
committerhxy <hxy@rock-chips.com>
Fri, 26 Nov 2010 01:11:49 +0000 (09:11 +0800)
arch/arm/mach-rk29/include/mach/rk29_nand.h
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/rk29_nand.c

index 0d1b116ec20b0c76f357e182ac1364c6ffb2dcfe..57f7277a69f5dd49f8ef777bd996fdb83d17e087 100644 (file)
@@ -40,6 +40,7 @@
 #define     FMC_FRDY                           (0x1<<9)
 #define     FMC_FRDY_INT_EN    (0x1<<10)
 #define     FMC_FRDY_INT_CLR           (0x1<<11)
+#define     FMC_WIDTH_16                               (0x1<<12)
 //FMWAIT¼Ä´æÆ÷
 #define     FMW_RWCS_OFFSET            0
 #define     FMW_RWPW_OFFSET    5
index 65473c5c2f5b330e9435944ef0cef83948fe016e..b1221872dd3f90a9dff3f2c2f376c64f72f91a91 100644 (file)
@@ -2558,6 +2558,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
                        break;
        }
 
+       chip->options |= busw;
+       
        /*
         * Check, if buswidth is correct. Hardware drivers should set
         * chip correct !
index dc36e5fbd73f86575fa9784e3dd017631e16bcbc..d0ea1ed7f5d37831ae285393c8d583de309b85f9 100644 (file)
@@ -90,6 +90,22 @@ static struct nand_ecclayout nand_hw_eccoob_16 = {
 static const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
 
+static void rk29_nand_wait_ready( struct mtd_info *mtd )
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct rk29_nand_mtd *master = nand_chip->priv;
+       pNANDC pRK29NC=  (pNANDC)(master->regs);
+       uint32_t timeout = 1000;
+       
+       while (timeout>0)
+       {
+             timeout --;                  
+          if(pRK29NC->FMCTL&FMC_FRDY)
+                break;
+          udelay(1);     
+       }
+       return;
+}
 
 static void rk29_nand_wait_busy(struct mtd_info *mtd, uint32_t timeout)
 {
@@ -301,7 +317,6 @@ static void rk29_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int column,
        struct rk29_nand_mtd *master = nand_chip->priv;
        pNANDC pRK29NC=  (pNANDC)(master->regs);
 
-       uint32_t timeout = 1000;
        char status,ret;
 
        
@@ -309,21 +324,15 @@ static void rk29_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int column,
 
        case NAND_CMD_READID:
                pRK29NC ->chip[master->cs].cmd = command;
+               rk29_nand_wait_ready(mtd);
                pRK29NC ->chip[master->cs].addr = 0x0;
-               while (timeout>0)
-               {
-                 timeout --;
-                  udelay(1);  
-                 if(pRK29NC->FLCTL&FL_INTCLR)
-                        break;
-                 
-               }
-               
+               rk29_nand_wait_ready(mtd);
                rk29_nand_wait_busy(mtd,READ_BUSY_COUNT);
                break;
                
        case NAND_CMD_READ0:
               pRK29NC ->chip[master->cs].cmd = command;
+                       rk29_nand_wait_ready(mtd);
               if ( column>= 0 )
                 {
                    pRK29NC ->chip[master->cs].addr = column & 0xff;    
@@ -336,15 +345,18 @@ static void rk29_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int column,
                        pRK29NC ->chip[master->cs].addr = (page_addr >> 8) & 0xFF;
                        pRK29NC ->chip[master->cs].addr = (page_addr >> 16) & 0xff;
                   }
+               rk29_nand_wait_ready(mtd);
                if( mtd->writesize > 512)
                    pRK29NC ->chip[0].cmd = NAND_CMD_READSTART;
 
+               rk29_nand_wait_ready(mtd);
                rk29_nand_wait_busy(mtd,READ_BUSY_COUNT);
                
                break;
                
        case NAND_CMD_READ1:
               pRK29NC ->chip[master->cs].cmd = command;
+                       rk29_nand_wait_ready(mtd);
                break;
                
        case NAND_CMD_READOOB:
@@ -354,6 +366,7 @@ static void rk29_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int column,
                
                pRK29NC ->chip[master->cs].cmd = command;  
 
+                       rk29_nand_wait_ready(mtd);
               if ( mtd->writesize >512 )
                {
                        if ( column>= 0 )
@@ -373,6 +386,7 @@ static void rk29_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int column,
                {
                   pRK29NC ->chip[master->cs].addr = column;
                }
+                       rk29_nand_wait_ready(mtd);
                        
                rk29_nand_wait_busy(mtd,READ_BUSY_COUNT);
                
@@ -382,9 +396,11 @@ static void rk29_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int column,
        case NAND_CMD_PAGEPROG:
                pRK29NC ->FMCTL |= FMC_WP;  //½â³ýд±£»¤
                pRK29NC ->chip[master->cs].cmd = command;
+               rk29_nand_wait_ready(mtd);
                rk29_nand_wait_busy(mtd,PROGRAM_BUSY_COUNT);
                
                pRK29NC ->chip[master->cs].cmd  = NAND_CMD_STATUS;
+               rk29_nand_wait_ready(mtd);
                status = pRK29NC ->chip[master->cs].data;
                
                if(status&0x1)
@@ -398,6 +414,7 @@ static void rk29_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int column,
                pRK29NC ->FMCTL |= FMC_WP;  //½â³ýд±£»¤
                pRK29NC ->BCHCTL = 0x0;
                pRK29NC ->chip[master->cs].cmd  = command;
+               rk29_nand_wait_ready(mtd);
                if ( page_addr>=0 )
                   {
                        pRK29NC ->chip[master->cs].addr = page_addr & 0xff;
@@ -409,8 +426,10 @@ static void rk29_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int column,
        case NAND_CMD_ERASE2:
                pRK29NC ->FMCTL |= FMC_WP;  //½â³ýд±£»¤
                pRK29NC ->chip[master->cs].cmd  = command;             
+               rk29_nand_wait_ready(mtd);
                rk29_nand_wait_busy(mtd,ERASE_BUSY_COUNT);
                pRK29NC ->chip[master->cs].cmd  = NAND_CMD_STATUS;
+               rk29_nand_wait_ready(mtd);
                status = pRK29NC ->chip[master->cs].data;
                
                if(status&0x1)
@@ -423,7 +442,7 @@ static void rk29_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int column,
        case NAND_CMD_SEQIN:
                pRK29NC ->FMCTL |= FMC_WP;  //½â³ýд±£»¤
                pRK29NC ->chip[master->cs].cmd  = command;
-              udelay(1);
+               rk29_nand_wait_ready(mtd);
                if ( column>= 0 )
                  {
                    pRK29NC ->chip[master->cs].addr = column;
@@ -442,36 +461,22 @@ static void rk29_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int column,
        case NAND_CMD_STATUS:
                pRK29NC ->BCHCTL = 0x0;
                pRK29NC ->chip[master->cs].cmd = command;
-               while (timeout>0)
-               {
-                 timeout --;
-                  udelay(1);  
-                 if(pRK29NC->FLCTL&FL_INTCLR)
-                        break;
-                 
-               }
+               rk29_nand_wait_ready(mtd);
                break;
 
        case NAND_CMD_RESET:
                pRK29NC ->chip[master->cs].cmd = command;
-               while (timeout>0)
-               {
-                 timeout --;
-                  udelay(1);  
-                 if(pRK29NC->FLCTL&FL_INTCLR)
-                        break;
-                 
-               }
+               rk29_nand_wait_ready(mtd);
                rk29_nand_wait_busy(mtd,RESET_BUSY_COUNT);
                break;
 
        /* This applies to read commands */
        default:
               pRK29NC ->chip[master->cs].cmd = command;
+                       rk29_nand_wait_ready(mtd);
                break;
        }
 
-       udelay (1);
    
 }
 
@@ -545,6 +550,11 @@ int rk29_nand_calculate_ecc(struct mtd_info *mtd,const uint8_t *dat,uint8_t *ecc
        rk29_nand_wait_busy(mtd,READ_BUSY_COUNT);
           
        pRK29NC->FLCTL |= FL_BYPASS;  // dma mode
+       
+       if(chip->options&NAND_BUSWIDTH_16)
+       {
+               pRK29NC ->FMCTL |= FMC_WIDTH_16;  // ÉèÖÃΪ16λ
+       }        
          
        for(i=0;i<mtd->writesize/0x400;i++)
        {
@@ -580,7 +590,11 @@ void  rk29_nand_write_page(struct mtd_info *mtd,struct nand_chip *chip,const uin
        
        pRK29NC->FLCTL |= FL_BYPASS;  // dma mode
 
-               
+  if(chip->options&NAND_BUSWIDTH_16)
+       {
+               pRK29NC ->FMCTL |= FMC_WIDTH_16;  // ÉèÖÃΪ16λ
+       }        
+                       
          for(i=0;i<mtd->writesize/0x400;i++)
           {
               memcpy((u_char *)(pRK29NC->buf),(buf+i*0x400),0x400);  //  only use nandc sram0          
@@ -630,7 +644,10 @@ int rk29_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page, i
        
        pRK29NC->FLCTL |= FL_BYPASS;  // dma mode
 
-       
+       if(chip->options&NAND_BUSWIDTH_16)
+       {
+               pRK29NC ->FMCTL |= FMC_WIDTH_16;  // ÉèÖÃΪ16λ
+       }        
 
        
        for(i=0;i<mtd->writesize/0x400;i++)
@@ -671,7 +688,10 @@ int        rk29_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, uint8_
           
        pRK29NC->FLCTL |= FL_BYPASS;  // dma mode
 
-       
+       if(chip->options&NAND_BUSWIDTH_16)
+       {
+               pRK29NC ->FMCTL |= FMC_WIDTH_16;  // ÉèÖÃΪ16λ
+       }        
           
        for(i=0;i<mtd->writesize/0x400;i++)
        {
@@ -872,7 +892,7 @@ static int rk29_nand_probe(struct platform_device *pdev)
        
        pRK29NC =  (pNANDC)(master->regs);
        pRK29NC ->FMCTL = FMC_WP|FMC_FRDY;
-       pRK29NC ->FMWAIT |=  (1<<FMW_RWCS_OFFSET)|(4<<FMW_RWPW_OFFSET)|(1<<FMW_CSRW_OFFSET);
+       pRK29NC ->FMWAIT |=  (1<<FMW_RWCS_OFFSET)|(4<<FMW_RWPW_OFFSET)|(2<<FMW_CSRW_OFFSET);
        pRK29NC ->BCHCTL = 0x1;
 
        this->select_chip(mtd, 0);
@@ -933,11 +953,6 @@ static int rk29_nand_probe(struct platform_device *pdev)
             DEBUG(MTD_DEBUG_LEVEL0, "RK2818 NAND: numchips error!!!\n");
     }
 #endif    
-#if 0
-      // rk281x dma mode bch must  (1k data + 32 oob) bytes align , so cheat system writesize =1024,oobsize=32
-       mtd->writesize = 1024;
-       mtd->oobsize = 32;
-#endif
 
 #ifdef CONFIG_MTD_PARTITIONS
         num_partitions = parse_mtd_partitions(mtd, part_probes, &partitions, 0);