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

📄 nand_mtd.c

📁 8032底层驱动部分。因为可以移植 所以单独来拿出来
💻 C
📖 第 1 页 / 共 5 页
字号:
   { 0x75EC,  32,  16,  512, 3,  8, NAND_PLANE_BLOCK_BIT0/*0x01*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* K9K1208X0C */
   { 0x76EC,  64,  16,  512, 4,  8, NAND_PLANE_BLOCK_BIT0|NAND_PLANE_BLOCK_BIT1|NAND_PLANE_BLOCK_BIT11/*0x803*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* K9K1G08X0A */
   { 0x79EC, 128,  16,  512, 4,  8, NAND_PLANE_BLOCK_BIT0|NAND_PLANE_BLOCK_BIT1|NAND_PLANE_BLOCK_BIT12/*0x1003*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* K9F1G08X0M */
   { 0xF1EC, 128, 128, 2048, 4,  8, 0, &NANDFlashMtd_2K_hw_enhanced},
    /* K9F1G16X0M */
   { 0xC1EC, 128, 128, 2048, 4,  16, 0, &NANDFlashMtd_2K_hw_enhanced},
    /* K9F2G08X0M */
   { 0xDAEC, 256, 128, 2048, 5,  8, 0, &NANDFlashMtd_2K_hw_enhanced},
    /* K9K8G08U0M */
   { 0xD3EC, 1024, 128, 2048, 5,  8, NAND_PLANE_BLOCK_BIT0|NAND_PLANE_BLOCK_BIT12/*0x1001*/, &NANDFlashMtd_2K_hw_enhanced},
    /* K9K4G08U0M */
   { 0xDCEC, 512, 128, 2048, 5,  8, NAND_PLANE_BLOCK_BIT11/*0x800*/, &NANDFlashMtd_2K_hw_enhanced},

    /* Toshiba series: manufacture ID - 98 */
    /* TC58DVM82A1FT*/
   { 0x7598,  32,  16,  512, 3,  8, 0, &NANDFlashMtd_512_default},
    /* TC58DVM92A1FT */
   { 0x7698,  64,  16,  512, 4,  8, 0, &NANDFlashMtd_512_default},
    /* TC58DVG02A1FT */
   { 0x7998, 128,  16,  512, 4,  8, 0, &NANDFlashMtd_512_default},
    /* TC58NVG0S3AFT */
   { 0xF198, 128, 128, 2048, 4,  8, 0, &NANDFlashMtd_Toshiba_2K_hw_enhanced},
    /* TC58NVG0S8BFTI0 */
   { 0xC198, 128, 128, 2048, 5,  16, 0, &NANDFlashMtd_2K_default},
    /* TC58NVG1S8BFTI0 */
   { 0xCA98, 256, 128, 2048, 5,  16, 0, &NANDFlashMtd_2K_default},
    /* TH58NVG1S3AFT */
   { 0xDA98, 256, 128, 2048, 5, 16, 0, &NANDFlashMtd_2K_default},
    /* TH58NVG2S3BT */
   { 0xDC98, 512, 128, 2048, 5,  8, NAND_PLANE_BLOCK_BIT10|NAND_PLANE_BLOCK_BIT11/*0xC00*/, &NANDFlashMtd_Toshiba_2K_hw_enhanced},    // Dual NAND test

    /* Hynix series: manufacture ID - AD */
    /* HY27XS08561M */
   { 0x75AD,  32,  16,  512, 3,  8, NAND_PLANE_BLOCK_BIT11/*0x800*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* HY27XS08121M */
   { 0x76AD,  64,  16,  512, 4,  8, NAND_PLANE_BLOCK_BIT12/*0x1000*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* HY27XA081G1M */
   { 0x79AD, 128,  16,  512, 4,  8, NAND_PLANE_BLOCK_BIT12|NAND_PLANE_BLOCK_BIT13/*0x3000*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* HY27UF081G2M */
   { 0xF1AD, 128,  128, 2048, 4,  8, 0, &NANDFlashMtd_2K_default/*&NANDFlashMtd_Samsung_512_hw_enhanced*/},

   /* ST series: manufacture ID - 20 */
    /* ST128W3A */
   { 0x7320,  16,  16,  512, 3,  8, NAND_PLANE_BLOCK_BIT9/*0x200*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* ST128W4A */
   { 0x5320,  16,  16,  512, 3, 16, NAND_PLANE_BLOCK_BIT9/*0x200*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* ST256W3A */
   { 0x7520,  32,  16,  512, 3,  8, NAND_PLANE_BLOCK_BIT10/*0x400*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* ST256W4A */
   { 0x5520,  32,  16,  512, 3, 16, NAND_PLANE_BLOCK_BIT10/*0x400*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* ST512W3A */
   { 0x7620,  64,  16,  512, 4,  8, NAND_PLANE_BLOCK_BIT11/*0x800*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* ST512W4A */
   { 0x5620,  64,  16,  512, 4, 16, NAND_PLANE_BLOCK_BIT11/*0x800*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* ST01GW3A */
   { 0x7920, 128,  16,  512, 4,  8, NAND_PLANE_BLOCK_BIT11|NAND_PLANE_BLOCK_BIT12/*0x1800*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* ST01GW4A */
   { 0x5920, 128,  16,  512, 4, 16, NAND_PLANE_BLOCK_BIT11|NAND_PLANE_BLOCK_BIT12/*0x1800*/, &NANDFlashMtd_Samsung_512_hw_enhanced},
    /* ST01GW3B */
   { 0xF120, 128, 128, 2048, 4,  8, 0, &NANDFlashMtd_2K_hw_enhanced},

   /* Micron series: manufacture ID - 2C */
    /* MT29F2G08AAC */
   { 0xDA2C,  256,  128,  2048, 5, 8, NAND_PLANE_BLOCK_BIT12/*0x1000*/, &NANDFlashMtd_2K_hw_enhanced},
    /* MT29F4G08BAB */
   { 0xDC2C,  512,  128,  2048, 5, 8, NAND_PLANE_BLOCK_BIT12/*0x1000*/, &NANDFlashMtd_2K_hw_enhanced},

   /* Infineon series: manufacture ID - C1 */
    /* HYF33DS51280 */
   { 0x66C1,  64,    16,   512, 4, 8, 0, &NANDFlashMtd_512_default},
    /* HYF33DS1G80 */
   { 0xF1C1,  128,  128,  2048, 4, 8, 0, &NANDFlashMtd_2K_hw_enhanced},

   { 0xFFFF,   0,   0,    0, 0,  0, 0}	 // End of ID Table

};

const DWORD CUSTOMIZED_RESERVED_POOL_SIZE = 12;

/*******************************************************************************
 *  NFI bus semaphore
 *******************************************************************************/
static kal_semid nfi_bus;

void init_NFI_bus_semaphore(void)
{
    if(nfi_bus == NULL)
    	nfi_bus = kal_create_sem("NFI_BUS", 1);
}

void get_NFI_bus(void)
{
    if(nfi_bus != NULL)
        kal_take_sem(nfi_bus, KAL_INFINITE_WAIT);
}

void free_NFI_bus(void)
{
    if(nfi_bus != NULL)
        kal_give_sem(nfi_bus);
}


#if(! ( (defined(MT6205)) || (defined(MT6205B)) || (defined(MT6208)) || (defined(FPGA)) ) )

static DMA_FULLSIZE_HWMENU nfi_menu;
static kal_uint8       nfi_dmaport;
static DMA_INPUT       nfi_input;
//static kal_hisrid      nfi_hisr_id;
static kal_eventgrpid  nfi_egid = NULL;
static kal_bool is_initialized;

/* for copy back support */
kal_uint32 mtd_copy_counts = 0;
static kal_uint32 mtd_buffer[MAX_PAGE_BUFFER_SIZE/sizeof(kal_uint32)];
static kal_uint32 mtd_spare[MAX_SPARE_BUFFER_SIZE/sizeof(kal_uint32)];
/* for copy back support */
/*******************************************************************************
 *  Declaration for NAND flash booting
 *******************************************************************************/

#ifdef _NAND_FLASH_BOOTING_

typedef int (*NFBReadFunc_T)(void *, DWORD, BYTE *, BYTE *, BYTE);

DWORD NFB_FLASH_BASE_PAGE;
NFBReadFunc_T        NFBReadFunc;
int                  NFBPageSize;
extern const DWORD   NFB_BASE_ADDRESS;
extern const DWORD NFB_ALLOCATED_FAT_SPACE;

int NFB_ReadPage_2K_default(void *, DWORD, BYTE *, BYTE *, BYTE);
int NFB_ReadPage_512_default(void *, DWORD, BYTE *, BYTE *, BYTE);

#endif
// For NAND flash booting
extern kal_bool use_interrupt;	// KAL_TRUE for using interrupt; KAL_FALSE for using polling



const DWORD NFI_DEBUG_VERSION = 532; // SW ver.05.30

/*******************************************************************************
 *  MTD functions
 *******************************************************************************/


int MTD_MountDevice(void * DriveData)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_int32 check_value = 0;

    init_NFI_bus_semaphore();

    if(SuperAND_MTD_MountDevice(DriveData) == FS_NO_ERROR)
    {
        SuperAND_MTD_Init();
        return SUPERAND_MOUNTED;
    }


   if(is_initialized)
   {
      pdn_nfi(1);

      /* In case that NFI is performing an operation */
      while (*NFI_PSTA & STATUS_BUSY);
      
      *NFI_FIFOCON = RESET;
      *NFI_OPCON = 0;
      *NFI_CON = 0;
      
      /* use 512-byte page and 8-bit IO format for read ID  */
      *NFI_PAGEFMT = PAGEFMT_512_8BIT;

      check_value = InitializeMTD(D);

      *NFI_OPCON = 0;
      pdn_nfi(0);
      if(check_value == MTD_STATUS_NO_ERROR)
         return FS_NO_ERROR;
      else if( check_value == MTD_STATUS_ID_NOT_SUPPORT )
         return FS_NAND_DEVICE_NOT_SUPPORTED;
      else
         return FS_FLASH_MOUNT_ERROR;
   }

	pdn_nfi(1);


// set NFI conrol bin in GPIO
#if ((defined(MT6228)) || (defined(MT6229) ))
	*NFI_GPIO_CON &= 0x000F;
#elif defined MT6217
	*NFI_GPIO_CON &= 0xC003;
	*NFI_GPIO_CON |= 0x1554;
#else
	*NFI_GPIO_CON &= 0xC003;
	*NFI_GPIO_CON |= 0x1554;
#endif


	*NFI_ACCCON = ACCCON | (((NFI_W2R<<6)|(NFI_WH<<4)) | ((NFI_WST<<2)|NFI_RLC));

	/* initialize DMA and interrupt*/
	*PDN_CON0 &= ~0x0001;  // enable DMA
	*NFI_INTR_EN = 0x0;	   // disable interrupt


	if ( stack_query_boot_mode() != USBMS_BOOT )
	{
		nfi_egid = kal_create_event_group("NFI_EG");

		//nfi_hisr_id = kal_create_hisr("NFI_HISR",1,512,nfi_hisr,NULL);
		DRV_Register_HISR(DRV_NFI_HISR_ID, nfi_hisr);

		IRQ_Register_LISR(IRQ_NFI_CODE, nfi_lisr, "NFI_LISR");
		IRQSensitivity(IRQ_NFI_CODE, EDGE_SENSITIVE);
		IRQUnmask(IRQ_NFI_CODE);
	}

	nfi_menu.TMOD.burst_mode = 0;
	nfi_menu.master = DMA_NFI;
	nfi_menu.source = NULL;
	nfi_menu.destination = NULL;

	nfi_input.type = DMA_HWTX;
	nfi_input.size = DMA_BYTE;
	nfi_input.menu = &nfi_menu;
	nfi_input.count = 0;

	if (nfi_egid == 0)
		nfi_input.callback = NULL;
	else
		nfi_input.callback = NFI_DMA_Callback;


	// initially set NFI chip select dir and out data
	INITIALIZE_NFI_DIR_DOUT;

	/* use 512-byte page and 8-bit IO format for read ID  */
	*NFI_PAGEFMT = PAGEFMT_512_8BIT;
   check_value = InitializeMTD(D);

	*NFI_OPCON = 0;
	pdn_nfi(0);

   is_initialized = KAL_TRUE;

	if (check_value == MTD_STATUS_NO_ERROR)
		return FS_NO_ERROR;
	else if( check_value == MTD_STATUS_ID_NOT_SUPPORT )
		return FS_NAND_DEVICE_NOT_SUPPORTED;
	else
		return FS_FLASH_MOUNT_ERROR;
}	/*  End of MountDevice */


/*******************************************************************************/
int MTD_ShutDown(void * DriveData)
{

#ifdef _NAND_FLASH_BOOTING_

	while (IS_NFI_DMA_RUN);
	while (*NFI_PSTA & STATUS_BUSY);

#endif

	return FS_NO_ERROR;
} /*  End of ShutDown */

/*******************************************************************************/

#ifdef _NAND_FLASH_BOOTING_
int NFB_ReadPhysicalPage(DWORD PhyBlock, DWORD PhyPage, void * Data)
{

   extern NAND_FLASH_DRV_DATA  NANDFlashDriveData;   
   
   NAND_FLASH_DRV_DATA * D = &NANDFlashDriveData;
   int NFBStatus=-1;   
   
   if ( PhyBlock==0xFFFFFFFF && PhyPage==0xFFFFFFFF )
   {
      if ( D->MTD==NULL )
      {
         NFBStatus = MTD_MountDevice((void *)D);
         EXT_ASSERT(NFBStatus==FS_NO_ERROR, NFBStatus, 0, 0);
         
         D->MTD = &NANDFlashMtd;
         
         if ( D->flash_info.page_type==PAGE_2K )
         {
            NFBReadFunc = (NFBReadFunc_T)NFB_ReadPage_2K_default;
            NFBPageSize = 2048;
         }
         else
         {
            NFBReadFunc = (NFBReadFunc_T)NFB_ReadPage_512_default;
            NFBPageSize = 512;
         }
         
         return (D->flash_info.io_width);
      }
      else 
         return -1;
   }

   NFB_FLASH_BASE_PAGE = 0;

	// Bad block checking
	D->MTD->ReadSpare(D, PhyBlock*B_PAGES, (BYTE*)D->spare0);
	D->MTD->ReadSpare(D, PhyBlock*B_PAGES+1, (BYTE*)D->spare1);

	if ( (!IsGoodBlock(D,D->spare0)) || (!IsGoodBlock(D,D->spare1)) )
	   return -1;
	else
	{
	   pdn_nfi(1);
	   
	   NFBStatus = NFBReadFunc(D,PhyBlock*B_PAGES+PhyPage,(BYTE*)Data,NULL,0);
	   
	   pdn_nfi(0);
           
      if ( NFBStatus != FS_NO_ERROR )
         return -1;
       
      return NFBPageSize;
   }
   
   return FS_NO_ERROR;
   
} /*  End of NFB_ReadPhysicalPage */
#endif   
/*******************************************************************************/

int MTD_EraseBlock(void * DriveData, DWORD BlockIndex)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint32 addr;
	kal_uint16 block_add_num;
	kal_uint8 status, cs;
	kal_uint32 event_group;


	pdn_nfi(1);

#ifdef _NAND_FLASH_BOOTING_
	BlockIndex += NFB_FLASH_BASE_PAGE/B_PAGES;
#endif

	if((BlockIndex<(NANDSUBDriveData[1].base_page/B_PAGES)) || (NANDSUBDriveData[1].base_page==0) )		// chip select 0
	{
		cs = 0;
		SET_NFI_CS0;
	}
	else		// chip select 1
	{
		cs = 1;
		SET_NFI_CS1;
	}


	//switch (B_PAGES)
	switch(NANDSUBDriveData[cs].page_size)
	{
	//case 64:	// 2K page-size
	case 2048:
		if (NANDSUBDriveData[cs].io_width == IO_ACCESS_8BIT)
		{
			*NFI_PAGEFMT = PAGEFMT_2K_8BIT;
		}
	   else
	   {
			*NFI_PAGEFMT = PAGEFMT_2K_16BIT;

			#if ((defined(MT6228)) || (defined(MT6229) ))
				*NFI_GPIO_DATA1 &= 0x0FFF;
				*NFI_GPIO_DATA2 &= 0xF000;
			#endif
		}
		addr = (BlockIndex - (NANDSUBDriveData[cs].base_page/B_PAGES) ) << 6;
		block_add_num = (kal_uint16)(NANDSUBDriveData[cs].address_cycle - 2);
		break;
	//case 32:	// 512 page-siae
	case 512:
		if (NANDSUBDriveData[cs].io_width == IO_ACCESS_8BIT)
		{
			*NFI_PAGEFMT = PAGEFMT_512_8BIT;
		}
	   else
	   {
			*NFI_PAGEFMT = PAGEFMT_512_16BIT;

			#if ((defined(MT6228)) || (defined(MT6229) ))
				*NFI_GPIO_DATA1 &= 0x0FFF;
				*NFI_GPIO_DATA2 &= 0xF000;
			#endif
		}
		addr = (BlockIndex - (NANDSUBDriveData[cs].base_page/B_PAGES) ) << 5;
		block_add_num = (kal_uint16)(NANDSUBDriveData[cs].address_cycle - 1);
		break;
	default:   // avoid unassignment warning
      addr = 0;
	   block_add_num = 0;
		EXT_ASSERT(0, NANDSUBDriveData[cs].page_size, cs, NANDSUBDriveData[cs].base_page);
	}

	*NFI_CON = 0x0;
	*NFI_OPCON = 0x0;

	if (nfi_egid && use_interrupt == KAL_TRUE)
	   *NFI_INTR_EN = ERASE_COMPLETE_EN;

	*NFI_CMD = BLOCK_ERASE1_CMD;		// erase command phase 1
	while (*NFI_PSTA & STATUS_CMD);


	*NFI_ADDRL = addr;							// erase block address

	*NFI_ADDNOB = block_add_num;		// no. of block address
	while (*NFI_PSTA & STATUS_ADDR);
	*NFI_CMD = BLOCK_ERASE2_CMD;		// erase command phase 2
	while (*NFI_PSTA & STATUS_CMD);

	if (nfi_egid && use_interrupt == KAL_TRUE)
	{
		kal_retrieve_eg_events(nfi_egid, NFI_EVENT, KAL_OR_CONSUME,
									&event_group, KAL_SUSPEND);
	}
	else
	{
		// using interrupt instead of polling after system initialization and before exception in normal mode
		if(nfi_egid && (kal_query_systemInit() == KAL_FALSE && INT_QueryExceptionStatus() == KAL_FALSE))
			use_interrupt = KAL_TRUE;
	}


	while (!((status = read_status())&RDY_BUSY)); // NFI ready

	if(cs)
		SET_NFI_CS1_END;

	*NFI_OPCON = 0;
	pdn_nfi(0);

	if (status&PASS_FAIL)
	{
		return FS_DATA_ERROR;
	}

	return FS_NO_ERROR;
} /*  End of EraseBlock */

/*******************************************************************************
 *  MTD functions for 512 page-size
 *******************************************************************************/

int ProgramPage_512 (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE ECCFlag)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint8 status, cs;


	pdn_nfi(1);

#ifdef _NAND_FLASH_BOOTING_
	PageIndex += NFB_FLASH_BASE_PAGE;
#endif

	if((PageIndex<NANDSUBDriveData[1].base_page) || (NANDSUBDriveData[1].base_page==0) )		// chip select 0
	{
		cs = 0;
		SET_NFI_CS0;
	}

⌨️ 快捷键说明

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