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

📄 nanddrv.c

📁 最近在國外網站抓到的作業系統 以Arm為基礎去開發的
💻 C
字号:
/*
 *  drivers/mtd/nand.c
 *
 *  Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
 *
 * $Id: nand.c,v 1.12 2004/11/02 15:05:14 ASIC WUER 
 *
 *
 *
 *  Overview:
 *	ALL NAND operation.   
 *
 *
 */


/*
 * NAND low-level  interface functions
 */
#include <stdio.h>
#include "pcdisk.h"
 
#include "HA_TypeDef.h"
#include "hardware.h"
#include "hardware_reg.h"
#include "lmalloc.h"

#include "stdio.h"	

#include "M68328.h"     //gfd
#include "nand.h" 

/*
 *	Global variables
 */
U32 g_NIN = 0;
U32 g_NTN = 0;
//U32 g_flash_pagebuf[128];			//allocate for 512bytes
U32 g_Nand_ErrorInt;

U32 *g_flash_pagebuf=(U32 *)0x31800000;
U32 *g_flash_esrambuf = (U32 *)0x1fff3800;

/*
#define	NAND_INTREP_ERROR	-1;
#define	NAND_WRITECHECK_ERROR	-2;
#define	NAND_TIMER_OUT		-3;
#define	NAND_OTHER_ERROR	-4;
*/

///////////////////////////////////////041104 wuer
//int nor_rd_io(U16 driveno, U32 page, VOID  *buffer, U16 count, int do_read);
int nand_rd_page(U32 page, U32*buffer,  U32 do_read);
int nand_read_page_com (U32 page,  U32 *buf);
int nand_write_page_com (U32 page, U32 *buf);
int nand_rd_block (U32 page, U32*buffer);
int nand_erase_block(U32 blockhead);
int nand_writenand_erase_block(U32 to, U32 len, U8 *buf);
int nand_read(U32 from, U32 len, U8 *buf);
void init_nand(void);
void int_serv_emi(void);
int clear(U32 tempadd, U32 num);
void ENT_INT_EMI( void );
void HA_DMA_DATADEFINE(U32 beginadd, U32 num);

unsigned long  nand_psr_sysclk;

/*
  * System EMI Interrupt
  */
void ENT_INT_EMI( void )
{
	ent_int();

	mask_irq(INT_EMI);
	//ENABLE_INT;
	
	int_serv_emi();
	
	//DISABLE_INT;
	unmask_irq(INT_EMI);

	ret_int();
}

int nand_rd_page(U32 page, U32*buffer,  U32 do_read)
{
	U32 status,i;
	U32 tempg_NIN,tempg_NTN;
	U32 nand_addr = page<<9;	
	
	g_NIN = 0x0;
	g_NTN = 0x0;

	//printf("\tpage [%08d] [0x%08x] [%s]\n",page, (U32)buffer, do_read?"R":"Write");
							
	while((g_NIN < 2) & (g_NTN < 3))
	{
		if(do_read&1)
			nand_read_page_com(nand_addr,(U32*)g_flash_esrambuf);
		else 
		{
			for(i=0;i<128;i++)
			{
				g_flash_esrambuf[i] = buffer[i];
			}
			nand_write_page_com(nand_addr,(U32*)g_flash_esrambuf);
		}
		for(i=0;i<0x1000;i++);
		if(g_NIN >= 2) return NO;
		
		status = *(RP)GFD_NAND_IDLE;
		if((status&0x1) == 0x1)
		{
			if(do_read&1)	
			{		
				for(i=0;i<128;i++)
				{
					buffer[i] = g_flash_esrambuf[i];
				}
				return YES;						//read  success!
			}
			else 
			{	
				tempg_NIN = g_NIN; //aviod g_var be changed!
				tempg_NTN = g_NTN;
				//for(i=0;i<128;i++) g_flash_pagebuf[i] = 0;
				status = nand_rd_page(page,g_flash_pagebuf,0x1);
				g_NIN = tempg_NIN;
				g_NTN = tempg_NTN;
				if( status == 1 )
				{
					for(i=0; i<128; i++)
					{
						if(g_flash_pagebuf[i] !=buffer[i]) 
						{
							printf("error address is NO 0x%x word in page 0x%x!\n",i,page);
							printf("Value at g_flash_pagebuf[0x%08x] is 0x%x \n and at buffer[0x%08x] is 0x%x\n",g_flash_pagebuf[i],buffer[i]);
							return 0;
						}
					}
					return YES;	 //write  success!
				
				}
				else 
					return NO;	 //write Ok, but reread fail!										
			}
			
		}
		else
		{	
			for(i=0;i<0x1000;i++);
	 		g_NTN ++;
		}	
		
	}
	
	if(g_NTN >= 3) return NO;
	
}



int nand_erase_block(U32 page)
{
	U32 j,counter = 0x0;

	/* Do not allow erase past end of device */
	U32 blockhead = (U32)(page<<9);

	//printf("E: p[%04d]\n",page);
	//if(page == 2208)
		//printf("E:\n");
	
	g_NIN = 0x0;
	g_NTN = 0x0;
	
	while((g_NIN < 2) & (g_NTN < 3))
	{
		/*erase action now!*/
		*(RP)(GFD_NAND_CONF) = 0x00100aaa; 			// 3 addresses modle
		*(RP)GFD_NAND_ADDR = (U32)(blockhead >> 9);	
		*(RP)EMIADDR_NANDCOM = NAND_CMD_ERASE1;

		
		for(j=0;j<0x1000;j++);
		if(g_NIN >= 2) return NO;
		
		j = *(RP)GFD_NAND_IDLE;
		if((j&0x1) == 0x1)   return YES;		
		else
		{	
			j = *(volatile unsigned int *)GFD_NAND_IDLE;
			counter++;
			if(counter > 10000)
			break;
		}	
        	
		g_NTN ++;
	}
	
	
	if(g_NTN >= 3) return NO;
	
	return 0;
}

int nand_read_page_com (U32 from,  U32 *buf)
{
	*(RP)GFD_NAND_ADDR = ((U32)from) >> 1;		//address config according to EMI refference		
	*(RP)GFD_NAND_CONF = 0x2200aaa;	                    // Nand 4 address mode config 
	*(RP)DMACC0SrcAddr = GFD_NAND_DATA;			//Nand data register is the source address of DMA
	*(RP)DMACC0DestAddr = (U32)buf;				//data buffer is the target address of DMA
	*(RP)DMACC0Control = 0x20249b;				//word-word burst=4  size=128words
	*(RP)DMACC0Configuration = 0x31d;				//enable DMA channel                   		

	*(RP)GFD_NAND_COM = (NAND_CMD_READ0 );		//send the read command, transportation begin now!!

	return 0;
	
}


int nand_write_page_com(U32 to, U32 *buf)
{
	*(RP)GFD_NAND_ADDR = ((U32)to) >> 1;			//address config according to EMI refference
	*(RP)GFD_NAND_CONF = 0x02200aaa;			// Nand 4 address mode config 
	*(RP)DMACC0SrcAddr = (U32)buf ;				//data buffer is the source address of DMA
	*(RP)DMACC0DestAddr = GFD_NAND_DATA;		//Nand data register is the target address of DMA
	*(RP)DMACC0Control = 0x0020149B;				//word-word burst=4  size=128words
	*(RP)DMACC0Configuration = 0x301b;				//enable DMA channel 
	
	*(RP)GFD_NAND_COM = (NAND_CMD_SEQIN);		//send the write command, transportation begin now!!
	
	return 0;
	
}



int nand_rd_block (U32 page, U32*buffer)
{
	int i;
	U32 tempaddr,status;
		
	tempaddr = (U32)buffer;
	
	for(i=0; i<32; i++){
		//printf("%d\n", i);
		status = nand_rd_page(page, (U32*)tempaddr, NO);
		if(status != YES)  return NO;		
		page ++;
		tempaddr += 512;
	}

	//printf("nand_rd_block():page [%08d] [0x%08x] [%s]\n",page, (U32)buffer, do_read?"R":"W");
	return YES;
	
}

void init_nand(void)						//Ph5 set to "1"
{
	U32	tempsel,tempdata,tempdir;
	
	tempsel = *(RP)GPIO_PH5_SEL;
	tempdata = *(RP)GPIO_PH5_DATA;
	tempdir = *(RP)GPIO_PH5_DIR;
	
	tempsel |= 0x20;
	tempdata |= 0x20;
	tempdir &= 0xffffffdf; 	
	
	*(RP)GPIO_PH5_SEL 	= tempsel;
 	*(RP)GPIO_PH5_DATA	 = tempdata;
 	*(RP)GPIO_PH5_DIR = tempdir;

	*(RP)0x10000000 |= 0x20000000;		//open int of EMI
	unmask_irq(INT_EMI);

}



 void int_serv_emi(void)
{
	*(RP)GFD_NAND_INTR = 0x0UL;			//clear interrupt bit
	g_NIN++;
}	






int clear(U32 tempadd, U32 num)
{
	U32 j;
	for(j = 0x0; j < num; j = j+1 )
	{
		*(RP)tempadd = 0x0;
		tempadd = tempadd + 4;
	}
	
	return 1;
}

int nand_write_page_format(U32 page, U32*buffer,  U32 do_read)
{
	do_read = NO;

	return nand_rd_page(page, buffer, do_read);
}

int nand_rd_io(U16 driveno, U32 page, void FAR *buffer, U16 count, int do_read)
{
	U32 *pbuffer = buffer;
	U32 *pdatabuf = NULL;
	U16 pageoffset = 0;
	U32 status = YES;
	U32 i=0;
	
	do_read &= 0x01;
	
	if(do_read == YES){
		pbuffer = buffer;
		for(i=0; i<count; i++)
		{
			status = nand_rd_page( page,  (U32 *)pbuffer, YES);
			if(status != YES)  return NO;
			page++; pbuffer += 0x80;			//one page has 512BYTES for common
		}
	}
	else
	{
			status = nand_erase_block(page);
			if(status != YES)  return NO;
			status = nand_rd_block(page, (U32 *)pbuffer);
	}

	//printf("nand_rd_io():page [%08d] [0x%08x] [%s]\n",page, (U32)buffer, do_read?"R":"W");
	
	return(status);
}

INT nand_rd_open(UINT16 driveno)
{
    return(YES);
}

INT nand_rd_close(UINT16 driveno)
{
    return(YES);
}

INT nand_rd_raw_open(UINT16 driveno)
{
    return(YES);
}

INT nand_rd_ioctl(UINT16 driveno, UINT16 command, VOID *buffer)
{
    return(YES);
}



void HA_DMA_DATADEFINE(U32 beginadd, U32 num)                //define a source data area,prepare to be tranfered or compared
{	
	U32 i;								//Write (num) WORD from the start address gvined
	U32 *p = (U32 *)beginadd;
	
	for(i = 0x0; i < num/4; i = i + 1 )	
	{
		*p++ = (U32)i;
	}	
	
}	

⌨️ 快捷键说明

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