flash_mtd.amd.c

来自「8032底层驱动部分。因为可以移植 所以单独来拿出来」· C语言 代码 · 共 1,645 行 · 第 1/4 页

C
1,645
字号
               fp[i] = Cell;
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
               WaitReady_AMD((kal_uint32)&fp[i], (kal_uint16)Cell);
               RestoreIRQMask(savedMask);
#else               
               RestoreIRQMask(savedMask);
               WaitReady_AMD((kal_uint32)&fp[i], (kal_uint16)Cell);
#endif
            }
#else
            j = 0;
            Words = (Length/sizeof(FLASH_CELL));
            while(Words>0)
            {
               ProgramWords = Words > PAGE_BUFFER_SIZE ?  PAGE_BUFFER_SIZE : Words ;
               if ((kal_uint32)fp & (sizeof(FLASH_CELL)*PAGE_BUFFER_SIZE -1))
               {
                  FLASH_CELL *pageb = (FLASH_CELL *)((kal_uint32)(fp+ PAGE_BUFFER_SIZE) & (~(sizeof(FLASH_CELL)*PAGE_BUFFER_SIZE -1)));
                  if ( ProgramWords > (pageb-fp))
                     ProgramWords = pageb - fp;  
               }
               savedMask = SaveAndSetIRQMask();
               bp[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
               bp[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
               fp[0] = CMD_WRITETOBUFFER;
               fp[0] = ProgramWords -1;// set data count
               
               for(i = 0; i < ProgramWords; i++)
               {
                  b[0] = bdp[j++];
                  b[1] = bdp[j++];
                  fp[i] = Cell;
               }
               fp[0] = CMD_BUFFERTOFLASH;
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
               WaitReady_AMD((kal_uint32)&fp[ProgramWords -1], (kal_uint16)Cell);
               RestoreIRQMask(savedMask);
#else               
               RestoreIRQMask(savedMask);
#ifdef __SPANSION_PL_N__
               DelayAWhile_AMD();
#endif //__SPANSION_PL_N__
               WaitReady_AMD((kal_uint32)&fp[ProgramWords -1], (kal_uint16)Cell);               
#endif
               Words -= ProgramWords;
               fp += ProgramWords;
            }
#endif
         }
         else
         {
            FLASH_CELL *dp = (FLASH_CELL*)Data;
#ifndef __PAGE_BUFFER_PROGRAM__
            for(i = 0; i < Length/sizeof(FLASH_CELL); i++)
            {
               savedMask = SaveAndSetIRQMask();
               bp[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
               bp[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
               bp[ADDR_UNLOCK_1] = CMD_PROG;
               fp[i] = dp[i];
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
               WaitReady_AMD((kal_uint32)&fp[i], (kal_uint16)dp[i]);
               RestoreIRQMask(savedMask);
#else
               RestoreIRQMask(savedMask);
               WaitReady_AMD((kal_uint32)&fp[i], (kal_uint16)dp[i]);               
#endif
            }
#else
            Words = (Length/sizeof(FLASH_CELL));
            while(Words>0)
            {
               ProgramWords = Words > PAGE_BUFFER_SIZE ?  PAGE_BUFFER_SIZE : Words ;
               if ((kal_uint32)fp & (sizeof(FLASH_CELL)*PAGE_BUFFER_SIZE -1))
               {
                  FLASH_CELL *pageb = (FLASH_CELL *)((kal_uint32)(fp+ PAGE_BUFFER_SIZE) & (~(sizeof(FLASH_CELL)*PAGE_BUFFER_SIZE -1)));
                  if ( ProgramWords > (pageb-fp))
                     ProgramWords = pageb - fp;  
               }
               savedMask = SaveAndSetIRQMask();
               bp[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
               bp[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
               fp[0] = CMD_WRITETOBUFFER;
               fp[0] = ProgramWords -1;// set data count
               
               for(i = 0; i < ProgramWords; i++)
               {
                  fp[i] = dp[i];
               }
               fp[0] = CMD_BUFFERTOFLASH;
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
               WaitReady_AMD((kal_uint32)&fp[ProgramWords -1], (kal_uint16)dp[ProgramWords -1]);
               RestoreIRQMask(savedMask);
#else //_LOW_COST_SINGLE_BANK_FLASH_              
               RestoreIRQMask(savedMask);
#ifdef __SPANSION_PL_N__
               DelayAWhile_AMD();
#endif //__SPANSION_PL_N__
               WaitReady_AMD((kal_uint32)&fp[ProgramWords -1], (kal_uint16)dp[ProgramWords -1]);
#endif //_LOW_COST_SINGLE_BANK_FLASH_
               Words -= ProgramWords;
               fp += ProgramWords;
               dp += ProgramWords;
            }
#endif
         }
      }
      break;
   }
   return FS_NO_ERROR;
}
#endif //__TOSHIBA_TV__

/*-----------------------------------*/
static int NonBlockEraseBlock_AMD(void * DriveData, kal_uint32  BlockIndex) /* Added by Eric */
{

#ifndef __NOR_FDM5__
   NOR_Flash_MTD_Data * D = DriveData;
   volatile FLASH_CELL * fp = (volatile FLASH_CELL *) D->CurrAddr;
   #ifdef DEBUG
      //EraseBlock: block not mapped
      ASSERT(D->CurrAddr == BlockAddress(D, BlockIndex));
   #endif
   ASSERT((~D->Signature == (kal_uint32)D->RegionInfo));
#else 
   NOR_MTD_DATA *D= DriveData;
   volatile FLASH_CELL * fp = (volatile FLASH_CELL *)BlockAddress(D,BlockIndex);
   ASSERT(D->Signature == ~((kal_uint32)D->LayoutInfo));
#endif

   EraseCommand_AMD(fp);
#ifdef __SPANSION_PL_N__
   DelayAWhile_AMD();
#endif
   return FS_NO_ERROR;
}

/*-----------------------------------*/
static int CheckDeviceReady_AMD(void * DriveData, kal_uint32 BlockIndex) /* Added by Eric */
{
   FLASH_CELL s1, s2;
   kal_uint32 data_cache_id;
    
#ifndef __PRODUCTION_RELEASE__
   static kal_uint32 test_times=0;
#endif

#ifndef __NOR_FDM5__
   NOR_Flash_MTD_Data * D = DriveData;
   volatile FLASH_CELL * fp = (volatile FLASH_CELL *) D->CurrAddr;
   #ifdef DEBUG
      //EraseBlock: block not mapped
      ASSERT(D->CurrAddr == BlockAddress(D, BlockIndex));
   #endif
   ASSERT((~D->Signature == (kal_uint32)D->RegionInfo));
#else 
   NOR_MTD_DATA *D= DriveData;
   volatile FLASH_CELL * fp = (volatile FLASH_CELL *)BlockAddress(D,BlockIndex);
   ASSERT(D->Signature == ~((kal_uint32)D->LayoutInfo));
#endif
   
   data_cache_id = INT_DisableDataCache();

   s1 = fp[1];
   s2 = fp[1];
   if (((s1 ^ s2) & TOGGLE_ERASE_SUSPEND))
   {
      if(!((s1 ^ s2) & TOGGLE_BUSY))
      {
         /* flash is erase suspended */
         fp[0] = CMD_RESU_SEC_ERASE;
      }
      INT_RestoreDataCache(data_cache_id);
      return FS_FLASH_ERASE_BUSY;
   }
   else
   {
      s1 = fp[1];
      s2 = fp[1];
   
      if(s2 == 0xffff)
      {
         INT_RestoreDataCache(data_cache_id);
#ifndef __PRODUCTION_RELEASE__
         test_times = 0;
#endif
         return FS_NO_ERROR;
      }
      else
      {
         /* the erase operation is reset abnormally */
         if(!(s1 ^ s2))
         {
#ifndef __PRODUCTION_RELEASE__

            /* MAUI_00218339: S71PL129JB0BAW9U need another busy time before     */
            /* polling, modify to allow second erase command to solve this issue */
            test_times++;
            if (test_times > 1)  
               ASSERT(0);
#endif
            EraseCommand_AMD(fp);
         }
         INT_RestoreDataCache(data_cache_id);
         return FS_FLASH_ERASE_BUSY;
      }
   }
}

/*-----------------------------------*/
static int SuspendErase_AMD(void * DriveData, kal_uint32 BlockIndex) /* Added by Eric */
{
   FLASH_CELL s;
   kal_uint32 data_cache_id;
   
#ifndef __NOR_FDM5__
   NOR_Flash_MTD_Data * D = DriveData;
   volatile FLASH_CELL * fp = (volatile FLASH_CELL *) D->CurrAddr;
   #ifdef DEBUG
      //EraseBlock: block not mapped
      ASSERT(D->CurrAddr == BlockAddress(D, BlockIndex));
   #endif
#else 
   NOR_MTD_DATA *D= DriveData;
   volatile FLASH_CELL * fp = (volatile FLASH_CELL *)BlockAddress(D,BlockIndex);
#endif

#ifdef _LOW_COST_SINGLE_BANK_FLASH_
   kal_uint32 savedMask;
   savedMask = SaveAndSetIRQMask();
#endif   

   data_cache_id = INT_DisableDataCache();
   

#ifdef DEBUG
   #ifndef _LOW_COST_SINGLE_BANK_FLASH_
   //SuspendErase: block not mapped
   ASSERT(D->CurrAddr == BlockAddress(D, BlockIndex));
   #endif
#endif

   fp[0]     = CMD_SUSP_SEC_ERASE;

   s = fp[0];
   while(!(s&POLL_BUSY))
      s = fp[0];

   INT_RestoreDataCache(data_cache_id);

#ifdef _LOW_COST_SINGLE_BANK_FLASH_  
   RestoreIRQMask(savedMask);
#endif    

   return FS_NO_ERROR;
}

/*-----------------------------------*/
static int ResumeErase_AMD(void * DriveData, kal_uint32 BlockIndex) /* Added by Eric */
{
#ifndef __NOR_FDM5__
   NOR_Flash_MTD_Data * D = DriveData;
   volatile FLASH_CELL * fp = (volatile FLASH_CELL *) D->CurrAddr;
   #ifdef DEBUG
      //EraseBlock: block not mapped
      ASSERT(D->CurrAddr == BlockAddress(D, BlockIndex));
   #endif
#else 
   NOR_MTD_DATA *D= DriveData;
   volatile FLASH_CELL * fp = (volatile FLASH_CELL *)BlockAddress(D,BlockIndex);
#endif

   fp[0]     = CMD_RESU_SEC_ERASE;

   return FS_NO_ERROR;
}

/********************************************/
/*                                          */
/*           FDM5.0 MTD SUPPORT             */
/*                                          */
/********************************************/
#ifdef __NOR_FDM5__

static int MountDevice_AMD(void * DriveData, void * Info)
{
   NOR_MTD_DATA * D = DriveData;
   NORLayoutInfo * Layout = D->LayoutInfo;
   kal_uint32 TotalPhysicalPages;
   kal_uint32 TblEntryShift=0,j=1;

   // check and assign D->LayoutInfo
   TotalPhysicalPages = (Layout->BlkSize)/(Layout->PageSize)*(Layout->TotalBlks);
   while(j<TotalPhysicalPages)
   {
      j = j << 1;
      TblEntryShift++;
   }
   TblEntryShift = TblEntryShift>>1;
   if((TblEntryShift) >8)
	   TblEntryShift=8;
   Layout->TblEntrys = 1<<TblEntryShift;

   if ( (Layout->TblEntrys * Layout->TotalLSMT) < TotalPhysicalPages)
      ASSERT(0);

   return FS_NO_ERROR;
}

static int ShutDown_AMD(void * DriveData)
{
   NOR_MTD_DATA * D = DriveData;
   NORBankInfo * BankInfo = D->LayoutInfo->BankInfo;
   volatile FLASH_CELL *fp = (volatile FLASH_CELL*)D->BaseAddr; 
   FLASH_CELL s1, s2; 
   kal_uint32 i=0,j=0;

   for(i=0;BankInfo[i].Banks !=0;i++)
      for(j=0;j<BankInfo[i].Banks;j++)
      {
         while(1)
         {
            s1 = fp[0];
            s2 = fp[0];
            if ((s1 ^ s2)==0)
               break;
            else
            {
               if(s2 & TOGGLE_TIMEOUT)
               {
                  s1 = fp[0];
                  s2 = fp[0];
                  if ((s1 ^ s2)==0)
                     break;
                  else
                  {
                     fp[0] = CMD_RESET;
                     break;
                  }
               }
            }
         }
         fp= (volatile FLASH_CELL*)((kal_uint32)fp + (kal_uint32)BankInfo[i].BankSize);
      }

   return FS_NO_ERROR;
}
#endif

#ifdef _LOW_COST_SINGLE_BANK_FLASH_
#ifdef __MTK_TARGET__
#pragma arm section code
#endif /* __MTK_TARGET__ */
#endif


/****************************************************************************/
/*                                                                          */
/*                    Support NOR Flash OTP Function                        */
/*                                                                          */
/****************************************************************************/

#ifdef __SECURITY_OTP__

extern kal_uint32 INT_RetrieveFlashBaseAddr(void);

static const kal_uint32 NOR_OTPOffset=0x100;
static const kal_uint32 NOR_OTPLength=0x100;

#define CMD_OTP_ENTRY 0x88
#define CMD_OTP_EXIT  0x90
#define CMD_OTP_ZERO  0x00
#define CMD_AUTOSELECT_ENTRY 0x90
#define CMD_AUTOSELECT_EXIT  0xF0
#define CMD_LOCKREG_ENTRY    0x40
#define CMD_LOCKREG_PROG     0xA0
#define CMD_LOCKREG_EXIT1    0x90
#define CMD_LOCKREG_EXIT2    0x00


#define OTP_ERR_NONE 0
#define OTP_ERR_OVERSCOPE 1
#define OTP_ERR_BUSY 2
#define OTP_ERR_WAIT 3

#ifdef __MTK_TARGET__
#pragma arm section code = "SNORCODE"
#endif /* __MTK_TARGET__ */

kal_int32
OTPCheckWriteReady_AMD(kal_uint32 addr,kal_uint16 data)
{
   kal_uint16 data_test1,data_test2;
   kal_uint32 data_cache_id;
   kal_int32 status = OTP_ERR_NONE;

 
   data_cache_id = INT_DisableDataCache();
   data_test1 = *(volatile kal_uint16*)addr;
   if((data_test1 & POLL_BUSY) == (data & POLL_BUSY))
   {
      data_test1 = *(volatile kal_uint16*)addr;
      data_test2 = *(volatile kal_uint16*)addr;
      if (data_test2 == data)
         status = OTP_ERR_NONE;
      else
      {
         status = OTP_ERR_WAIT;
      }    
   }
   else if(data_test1 & POLL_TIMEOUT) //DQ5 = 1 may imply a timeout happens

⌨️ 快捷键说明

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