⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bl_nfi.c

📁 MTK 平台启动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
      *NFI_ADDRL = addr1;
      if ( addr_no>4 )
         *NFI_ADDRM = addr2;
      *NFI_ADDNOB = addr_no;              // number of bytes for address      
      while (*NFI_PSTA & STATUS_ADDR);      
   }
   else
   {
      *NFI_CMD = RD_1ST_CMD;              // Issue data input command
      while (*NFI_PSTA & STATUS_CMD);      
      *NFI_ADDRL = addr1;
      if ( addr_no>4 )
         *NFI_ADDRM = addr2;
      *NFI_ADDNOB = addr_no;              // no. of bytes for address   
      while (*NFI_PSTA & STATUS_ADDR);      
      *NFI_CMD = RD_2ND_CYCLE_CMD;
      while (*NFI_PSTA & STATUS_CMD);      
   }

   *NFI_OPCON = BURST_RD | NOB_DWORD;    // set burst read
   
   while( *NFI_PSTA & STATUS_DATAR );
   
   NFI_Wait_Ready(timeout);
   
   if ( timeout==0 )
      return KAL_FALSE;

   // Activating DMA transfer
   if ( ECC )
      *NFI_CON = (DMA_RD_EN | AUTOECC_DEC_EN);
   else
      *NFI_CON = DMA_RD_EN;
   
   *(volatile kal_uint32 *)(0x80030118) = 0x0000;
   *(volatile kal_uint32 *)(0x80030100) = (kal_uint32)NFI_DATAR;
   *(volatile kal_uint32 *)(0x80030104) = (kal_uint32)destination;
   *(volatile kal_uint32 *)(0x80030110) = length>>2;
   *(volatile kal_uint32 *)(0x80030114) = 0x00f4001a;
   *(volatile kal_uint32 *)(0x80030128) = 0;
   *(volatile kal_uint32 *)(0x80030118) = 0x8000;
   
   timeout = 0xfff;
   
   while ( ((*(volatile kal_uint32 *)(0x80030000)&0x03)==0x01) && (timeout--) ); 
   
   if ( timeout==0 )
      return DMA_TRANSFER_DATA_TIMEOUT;
         
//   while (!(*NFI_FIFOCON & RD_EMPTY_MASK) || (*NFI_PSTA & STATUS_DATAR));
   while (*NFI_PSTA & STATUS_BUSY);   

   if ( ECC )
   {
      if ( parity==NULL )
         return NFI_ZERO_POINTER;
       
      if ( pageSize<1024 )
      {
         parity_ptr[0] = *NFI_PAR6;
         parity_ptr[0] |= (*NFI_PAR7) << 16;         
      }
      else
      {
         parity_ptr[0] = *NFI_PAR0;
         parity_ptr[0] |= (*NFI_PAR1) << 16;
         parity_ptr[1] = *NFI_PAR2;
         parity_ptr[1] |= (*NFI_PAR3) << 16;
         parity_ptr[2] = *NFI_PAR4;
         parity_ptr[2] |= (*NFI_PAR5) << 16;
         parity_ptr[3] = *NFI_PAR6;
         parity_ptr[3] |= (*NFI_PAR7) << 16;
      }         
   }
   
   // Caution: This line must not omitted!
   *NFI_OPCON = 0x0;
   
   if ( timeout )
      return NFI_SUCCESS;
   else 
      return NFI_READ_DATA_TIMEOUT;
}

/**********************************************************
Description : NFI_SpareRead
Input       : .......
Output      : _RET_CODE
Remark      : Must be spare area aligned
***********************************************************/
_RET_CODE NFI_SpareRead(kal_uint32 *spare, kal_uint16 addr_no, kal_uint32 addr1, \
                        kal_uint16 addr2, kal_uint16 pageSize, kal_uint16 IO)
{
   kal_int16 timeout=0xfff, size, i;
     
   *NFI_OPCON = 0x00;
   *NFI_CON = 0x00;        
   *NFI_FIFOCON = 0x30;                  // Flushing FIFO

   if ( pageSize<1024 )
   {
      size = 16;
      *NFI_CON = SW_PROGSPARE_EN;        // program/read spare area enable
      *NFI_CMD = RD_SPARE_CMD;           // reading spare command      
      while (*NFI_PSTA & STATUS_CMD);     
      *NFI_ADDRL = (addr1&0xffffff00);    
      *NFI_ADDRM = 0;
      *NFI_ADDNOB = addr_no;             // number of bytes for address
      while (*NFI_PSTA & STATUS_ADDR);    
   }
   else
   {
      size = 64;
      *NFI_CON = SW_PROGSPARE_EN;        // program spare area enable
      *NFI_CMD = RD_1ST_CMD;             // read spare command
      while (*NFI_PSTA & STATUS_CMD);     
      if ( IO==IO_16BITS )
      {
         // addr1 >>= 1;      
         addr1 = addr1 + (2048/2);
      }
      else 
      {
         addr1 = addr1 + 2048;
      }
      *NFI_ADDRL = addr1;
      if ( addr_no>4 )
         *NFI_ADDRM = addr2;
      *NFI_ADDNOB = addr_no;             // number of bytes for address
      while (*NFI_PSTA & STATUS_ADDR);      
      *NFI_CMD = RD_2ND_CYCLE_CMD;            
      while (*NFI_PSTA & STATUS_CMD);      
   }      

   //   *NFI_OPCON = BURST_RD | NOB_WORD;     // set burst read   
   *NFI_OPCON = BURST_RD | NOB_DWORD;     // set burst read   

   while( *NFI_PSTA & STATUS_DATAR );

   NFI_Wait_Ready(timeout);

   if ( timeout==0 )
     return NFI_READ_SPARE_TIMEOUT;


   /*   *NFI_CON |= DMA_RD_EN;
   *(volatile kal_uint32 *)(0x80030118) = 0x0000;
   *(volatile kal_uint32 *)(0x80030100) = (kal_uint32)NFI_DATAR;
   *(volatile kal_uint32 *)(0x80030104) = (kal_uint32)spare;
   *(volatile kal_uint32 *)(0x80030110) = size>>2;
   *(volatile kal_uint32 *)(0x80030114) = 0x00f4001a;
   *(volatile kal_uint32 *)(0x80030128) = 0;
   *(volatile kal_uint32 *)(0x80030118) = 0x8000;

   timeout = 0xfff;

   while ( ((*(volatile kal_uint32 *)(0x80030000)&0x03)==0x01) && (timeout--) ); */


   for (i=0; i<(size/4); i++)
   {
      while ((*NFI_FIFOCON & RD_EMPTY_MASK));
      spare[i] = *NFI_DATAR;
   }   

/*   dbg_print("Spare area = ");
   for(i=0; i<(size/4); i++) {
        dbg_print("%x ", spare[i]);
   }
   dbg_print("\n\r");*/


   //   while (*NFI_PSTA & STATUS_DATAR);
   // Caution: This line must not omitted!
   *NFI_OPCON = 0x0;
   while (*NFI_PSTA & STATUS_BUSY);   

   if ( timeout )
      return NFI_SUCCESS;
   else 
      return DMA_TRANSFER_SPARE_TIMEOUT;
}

/**********************************************************
Description : NFI_ParityCheck
Input       : .......
Output      : _RET_CODE
Remark      : Must be page alignment.
***********************************************************/
_RET_CODE NFI_ParityCheck(kal_uint32 *destination, kal_uint32 *parity, kal_uint16 addr_no, \
                          kal_uint32 addr1, kal_uint16 addr2, kal_uint16 pageSize, kal_uint16 IO, \
                          kal_uint32 blockSize)
{
   _RET_CODE  status;
   kal_uint32 spare[64>>2];
   
   status = NFI_SpareRead(&spare[0], addr_no, addr1, addr2, pageSize, IO);
   
   if ( status!=NFI_SUCCESS )
      return status;
  
   if ( pageSize<1024 )
      status = NUTL_ECC_Correction(destination, parity, &spare[0], 512, blockSize);
   else
      status = NUTL_ECC_Correction(destination, parity, &spare[0], 2048, blockSize);
   
   return status;
}
                  
/**********************************************************
Description : NFI_CheckGoodBlock
Input       : NFI_MENU, baseaddr must be page alignment
Output      : U32 return data
              512B/page, 8-bits interface, 0x????FF??
              otherwise, 0x????FFFF or 0x??????FF
              for good page
              2: Read error
***********************************************************/ 
static kal_uint32 NFI_CheckGoodBlock(NFI_MENU *input, kal_uint32 addr1, kal_uint16 addr2)
{
   kal_uint32 rb_data[4];
   kal_int16  timeout=0xfff, size;
   
   rb_data[0]= 0;
   rb_data[1]= 0;
   rb_data[2]= 0;
   rb_data[3]= 0;
   
   *NFI_OPCON = 0x00;
   *NFI_CON = 0x00;        
   *NFI_FIFOCON = 0x30;                  // Flushing FIFO
   
   if ( input->pageSize<1024 )
   {
      *NFI_CON = SW_PROGSPARE_EN;        // program/read spare area enable
      *NFI_CMD = RD_SPARE_CMD;           // reading spare command      
      while (*NFI_PSTA & STATUS_CMD);     
      *NFI_ADDRL = (addr1&0xffffff00);    
      *NFI_ADDRM = 0;
      *NFI_ADDNOB = input->addressCycle; // number of bytes for address
      while (*NFI_PSTA & STATUS_ADDR);    
   }
   else
   {
      *NFI_CON = SW_PROGSPARE_EN;        // program spare area enable
      *NFI_CMD = RD_1ST_CMD;             // read spare command
      while (*NFI_PSTA & STATUS_CMD);     
      if ( input->IOInterface == IO_8BITS )
         *NFI_ADDRL = addr1 + 2048;
      else
         *NFI_ADDRL = addr1 + 1024;
      if ( input->addressCycle>4 )
         *NFI_ADDRM = addr2;
      *NFI_ADDNOB = input->addressCycle; // number of bytes for address
      while (*NFI_PSTA & STATUS_ADDR);      
      *NFI_CMD = RD_2ND_CYCLE_CMD;            
      while (*NFI_PSTA & STATUS_CMD);      
   }      

   *NFI_OPCON = BURST_RD | NOB_WORD;  // set burst read   
   
   while( *NFI_PSTA & STATUS_DATAR );
   
   NFI_Wait_Ready(timeout);
   
   if ( timeout==0 )
      return 2;
   
   size = 0;
   timeout=0xfff;
   
   while ( (size<4) && timeout>0 )
    {
      if ( !(*NFI_FIFOCON&RD_EMPTY_MASK) )
      {
         rb_data[size] = *NFI_DATAR;
         size ++;
      }
      else 
         timeout--;
   }
   
   if ( timeout<=0 )
      return 2;
      
   // Caution: This line must not omitted!
   *NFI_OPCON = 0x0;
      
   if ( input->pageSize<1024 )
   {
      if ( input->IOInterface == IO_8BITS )
         return ( (kal_uint32)((rb_data[1]&0xff00)>>8) );
      else
         return ( ((kal_uint32)(rb_data[0]&0xff) | (rb_data[1]&0xff00)) );
   }
   else
   {
      if ( input->IOInterface == IO_8BITS )
         return ( (kal_uint32)(rb_data[0]&0xff) );
      else
         return ( (kal_uint32)(rb_data[0]&0xffff) );
   }
}


/**********************************************************
Description : NFIReconfigure
Input       : NO
Output      : NO
***********************************************************/
void NFIReconfigure(void)
{
   *NFI_FIFOCON = 0x30;                  // Flushing FIFO
   *NFI_OPCON = 0x00;
   *NFI_CON = 0x00;     
   // Force 512Bytes ECC block size for both 2KB and 512B NAND-flash
   *NFI_PAGEFMT |= 0x20;
   *NFI_ACCCON = 0x7FF;
}


/**********************************************************
Description : GoodBlockChecking
Input       : NFI_MENU, NFIReadPtr must be page alignment
Output      : TRUE, good block, FALSE, bad block
***********************************************************/
kal_bool GoodBlockChecking(NFI_MENU *input, kal_uint32 addr1, kal_uint16 addr2)
{
   kal_uint32 marking, i;
      
   for (i=0; i<2; i++)
   {
      // Read the bad block marking from the first page
      marking = NFI_CheckGoodBlock(input, addr1, addr2);
      if ( (marking!=0xff) && (marking!=0xffff) )
         return KAL_FALSE;
      addr1 = addr1 + (1<<input->pageShift);
   }
         
   return KAL_TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -