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

📄 onenand.c

📁 Samsung S3C2443 Test program source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/*======================================================================

 Project Name : S3C2443

 Copyright 2006 by Samsung Electronics, Inc.
 All rights reserved.

 Project Description :
 This software is only for verifying functions of the S3C2443. 
 Anybody can use this code without our permission.

 File Name    : OneNAND.c
 Description  : S3C2443 OneNAND access module
 Author       : Junon Jeon
 Dept         : AP
 Created Date : 2006.06.02
 Version      : 0.0
 History
   R0.0 (2006.06.02): Junon draft
		- This code is derived from S5I3000 OneNAND driver.
		
=======================================================================*/

#include <stdio.h>
#include <string.h>

#include "2443addr.h"
#include "Option.h"
#include "OneNand.h"
#include "System.h"
#include "Console.h"
#include "PLL.h"

// Setting address of OneNAND device
//****** Setting base address by using CSn ******
#define OND_BANK				0 	// 0:nCS0 ~ 5:nCS5
#define	__OND_BASEADDR			(OND_BANK * 0x08000000)	
#define __OND_BootRAM_BASE		(__OND_BASEADDR + 0x0)
#define __OND_DataRAM0_BASE		(__OND_BASEADDR + 0x0400)
#define __OND_DataRAM1_BASE		(__OND_BASEADDR + 0x0c00)

#define __OND_BootRAM_Spare		(__OND_BASEADDR + 0x10000)
#define __OND_DataRAM0_Spare	(__OND_BASEADDR + 0x10020)
#define __OND_DataRAM1_Spare	(__OND_BASEADDR + 0x10060)

// Register address of OneNAND device
#define	rOND_MANU				(*(volatile U16 *)(__OND_BASEADDR + 0x1e000))
#define	rOND_DEV				(*(volatile U16 *)(__OND_BASEADDR + 0x1e002))
#define	rOND_VER				(*(volatile U16 *)(__OND_BASEADDR + 0x1e004))
#define	rOND_DBUFSIZE			(*(volatile U16 *)(__OND_BASEADDR + 0x1e006))
#define	rOND_BBUFSIZE			(*(volatile U16 *)(__OND_BASEADDR + 0x1e008))
#define	rOND_BUFAMOUNT			(*(volatile U16 *)(__OND_BASEADDR + 0x1e00a))
#define	rOND_TECH				(*(volatile U16 *)(__OND_BASEADDR + 0x1e00c))

#define	rOND_START_ADDR1		(*(volatile U16 *)(__OND_BASEADDR + 0x1e200))
#define	rOND_START_ADDR2		(*(volatile U16 *)(__OND_BASEADDR + 0x1e202))
#define	rOND_START_ADDR3		(*(volatile U16 *)(__OND_BASEADDR + 0x1e204))
#define	rOND_START_ADDR4		(*(volatile U16 *)(__OND_BASEADDR + 0x1e206))
#define	rOND_START_ADDR5		(*(volatile U16 *)(__OND_BASEADDR + 0x1e208))
#define	rOND_START_ADDR6		(*(volatile U16 *)(__OND_BASEADDR + 0x1e20a))
#define	rOND_START_ADDR7		(*(volatile U16 *)(__OND_BASEADDR + 0x1e20c))
#define	rOND_START_ADDR8		(*(volatile U16 *)(__OND_BASEADDR + 0x1e20e))

#define	rOND_START_BUFFER		(*(volatile U16 *)(__OND_BASEADDR + 0x1e400))
#define	rOND_COMMAND			(*(volatile U16 *)(__OND_BASEADDR + 0x1e440))
#define	rOND_SYS_CONFIG1		(*(volatile U16 *)(__OND_BASEADDR + 0x1e442))
#define	rOND_SYS_CONFIG2		(*(volatile U16 *)(__OND_BASEADDR + 0x1e444))
#define	rOND_CON_STATUS			(*(volatile U16 *)(__OND_BASEADDR + 0x1e480))
#define	rOND_INT_STATUS			(*(volatile U16 *)(__OND_BASEADDR + 0x1e482))
#define	rOND_START_BADDR		(*(volatile U16 *)(__OND_BASEADDR + 0x1e498))
#define	rOND_WPROT_STATUS		(*(volatile U16 *)(__OND_BASEADDR + 0x1e49c))

#define rOND_ECC_STATUS			(*(volatile U16 *)(__OND_BASEADDR + 0x1fe00))
#define rOND_ECC_RES_M0			(*(volatile U16 *)(__OND_BASEADDR + 0x1fe02))
#define rOND_ECC_RES_S0			(*(volatile U16 *)(__OND_BASEADDR + 0x1fe04))
#define rOND_ECC_RES_M1			(*(volatile U16 *)(__OND_BASEADDR + 0x1fe06))
#define rOND_ECC_RES_S1			(*(volatile U16 *)(__OND_BASEADDR + 0x1fe08))
#define rOND_ECC_RES_M2			(*(volatile U16 *)(__OND_BASEADDR + 0x1fe0a))
#define rOND_ECC_RES_S2			(*(volatile U16 *)(__OND_BASEADDR + 0x1fe0c))
#define rOND_ECC_RES_M3			(*(volatile U16 *)(__OND_BASEADDR + 0x1fe0e))
#define rOND_ECC_RES_S3			(*(volatile U16 *)(__OND_BASEADDR + 0x1fe10))

// Values of Command Register - CMD 
#define OND_LD_MS_TO_BUF	0x0000
#define OND_LD_SS_TO_BUF	0x0013
#define OND_PG_MS_FR_BUF	0x0080
#define OND_PG_SS_FR_BUF	0x001a
#define OND_CP_BACK_PRG		0x001b
#define OND_UNLOCK			0x0023
#define OND_LOCK			0x002a
#define OND_LOCK_TIGHT		0x002c
#define OND_ERASE_VERIFY	0x0071
#define OND_BLK_ERASE		0x0094
#define OND_MULTY_ERASE		0x0095
#define	OND_ERASE_SUS		0x00b0
#define OND_ERASE_RESUME	0x0030
#define OND_RST_CORE		0x00f0
#define OND_RST_OND			0x00f3
#define	OND_OTP_ACS			0x0065

#define	DBS(b)		((b<<5)&0x8000)		// BufferRAM of DDP (Device BufferRAM Select)
#define	DFS(b)		((b<<5)&0x8000)		// flash core of DDP (Device Flash Core Select)
#define	FBA(b)		(b&0x03ff)			// NAND Flash Block Address	
#define	FPA(p)		((p<<2)&0xfc)		// NAND Flash Page Address
#define	FSA(s)		(s&0x3)				// NAND Flash Sector Address
#define	BSA(r)		((r<<8)&0x0f00)		// BufferRAM Sector Address
#define	BSC(n)		(n&0x3)				// BufferRAM Sector Count
#define	SBA(b)		(b&0x03ff)			// Start Block Address

// Others
#define	DATABUFFERSIZE	((rOND_DBUFSIZE<<1)/(rOND_BUFAMOUNT>>8))
#define USE_DMA	0


// OneNAND interface library
void OND_HotReset( void);
U32 OND_erase_block( U16);
U32 OND_erase_multi_block_verify( U16, U16, U16);
U32 OND_page_program( U16, U16);
U32 OND_page_load( U16, U16);
void OND_lock_block( U16);
void OND_lock_tight_block( U16);
void OND_unlock_block( U16);
void OND_read( U32 *, U32, U16);
void OND_write( U32 *, U32, U16);

void OneNAND_TimingCheck(void);
void OneNAND_Burst_Read(void);

// Temporary library
void set_dma_control(U8 burst, U8 tw);
void dma_memcpy(U32 s_addr, U32 d_addr, U32 N_LLI, U32 trans_size);
void SMC_Config4OneNAND(U32 nBank);

	
void * function_OND[][2]=
{	
	(void *)OneNAND_ReadID,					"OneNAND Read ID  ",
	(void *)OneNAND_Program,				"OneNAND program  ",
	(void *)OneNAND_Read_Page,				"Read page        ",
	(void *)OneNAND_Write_Page,				"Write page       ",
	(void *)OneNAND_Erase_All,				"Erase all blocks ",
	(void *)OneNAND_Erase_Block,			"Erase block      ",
	(void *)OneNAND_Unlock_Block,			"Unlock block     ",
	(void *)OneNAND_Lock_Block,				"Lock block       ",
	(void *)OneNAND_Performance_Test,		"Performance Test ",
	(void *)OneNAND_TimingCheck,			"Timing Check     ",
	(void *)OneNAND_Burst_Read,				"Read burst(page) ",
	0,0
};

void Test_OneNAND( void)
{
	int	i;

	OND_HotReset();
	SMC_Config4OneNAND(OND_BANK);

	while(1)
	{
		i=0;
		
		while(1)
		{
			printf("%2d:%s",i,function_OND[i][1]);
			i++;
			if((int)(function_OND[i][0])==0)
			{
				printf("\n");
				break;
			}
			if((i%4)==0)
			printf("\n");
		}

		printf("\nPress Enter key to exit : ");

		i = GetIntNum();
		if( i == (-1) ) break;
		if( (i>=0) && (i<sizeof(function_OND)/8-1) )
			( (void (*)(void)) (function_OND[i][0]) )();
	}	
}


//========================= [Drivers] ============================
void OND_HotReset( void)
{
	rOND_INT_STATUS	=	0x0;
	rOND_COMMAND	=	OND_RST_OND;
	
	while ((rOND_INT_STATUS & 0x8010) != 0x8010);	
}


U32 OND_erase_block( U16 block)
{

	rOND_START_ADDR1 = DFS(block) | FBA(block);
	
	rOND_INT_STATUS = 0;
	rOND_COMMAND = OND_BLK_ERASE;

	while (!(rOND_INT_STATUS & (1<<15)));
	
	if (rOND_CON_STATUS & (1<<10)) {
		printf("Fail to erase the block %d\n", block);
		return 0x3;
	}
	
	return 0x0;
}


U32 OND_erase_multi_block_verify( U16 start_block, U16 end_block, U16 do_verify)
{
	U16	block;

	if (end_block < start_block) return 0x1;

	for (block = start_block; block <= end_block; block++)
	{
		OND_unlock_block( block);
		
		rOND_START_ADDR1 = FBA(block);

		rOND_INT_STATUS = 0;
		rOND_COMMAND = OND_MULTY_ERASE;
		
		while (!(rOND_INT_STATUS & (1<<15)));
	}

	rOND_START_ADDR1 = FBA(end_block);
	
	rOND_INT_STATUS = 0;
	rOND_COMMAND = OND_BLK_ERASE;

	while (!(rOND_INT_STATUS & (1<<15)));

	if (do_verify)
	{
		for (block = start_block; block <= end_block; block++)
		{
		
			rOND_START_ADDR1 = FBA(block);
			
			rOND_INT_STATUS = 0;
			rOND_COMMAND = OND_ERASE_VERIFY;
			
			while (!(rOND_INT_STATUS & (1<<15)));

			if (rOND_CON_STATUS & (1<<10)) 
				printf(" Fail to erase-verify the block %d\n", block);
		}
	}
	
	return 0x0;
}


U32 OND_page_program( U16 block, U16 page)
{
		
	rOND_START_ADDR2 = DBS(block);

	rOND_START_ADDR1 = DFS(block) | FBA(block);

	rOND_START_ADDR8 = FPA(page) | FSA(0);

	rOND_START_BUFFER = BSA(0x8) | BSC(0);
	
	rOND_INT_STATUS = 0;
	rOND_COMMAND = OND_PG_MS_FR_BUF;
	
	while (!(rOND_INT_STATUS & (1<<15)));
	
	if (rOND_CON_STATUS & (1<<10)) {
		printf("Fail to program the page (B: %d, P: %d)\n", block, page);
		return 0x1;
	}
	
	return 0x0;
}


U32 OND_page_load( U16 block, U16 page)
{
	
	rOND_START_ADDR1 = DFS(block) | FBA(block);

	rOND_START_ADDR8 = FPA(page) | FSA(0);

	rOND_START_BUFFER = BSA(0x8) | BSC(0);

	rOND_START_ADDR2 = DBS(block);

	rOND_INT_STATUS = 0;
	rOND_COMMAND = OND_LD_MS_TO_BUF;

	while (!(rOND_INT_STATUS & (1<<15)));

	if (rOND_CON_STATUS & (1<<10)) {
		printf("Fail to load the page (B: %d, P: %d)\n", block, page);
		return 0x1;
	}
	
	return 0x0;
}


void OND_write_protection_block( U16 cmd, U16 block)
{

	rOND_START_ADDR1 = DFS(block) | FBA(block);

	rOND_START_BADDR = SBA(block);	
	
	rOND_INT_STATUS = 0;
	rOND_COMMAND = cmd;

	while (!(rOND_INT_STATUS & (1<<15)));
}


void OND_lock_block( U16 block)
{
	OND_write_protection_block( OND_LOCK, block);
}


void OND_lock_tight_block( U16 block)
{
	OND_write_protection_block( OND_LOCK_TIGHT, block);
}


void OND_unlock_block( U16 block)
{
	OND_write_protection_block( OND_UNLOCK, block);
}


//	Read-While-Load Operation
void OND_read( U32 *Address, U32 Size, U16 block)
{
	U32	size;
	U16	page;
	U16	b_temp;
	U32	data_load;
	U32	data_read;
//	U32	st_cnt = 1;
	

	b_temp = 0xffff;
	page = 0;
	data_load = 0;
	data_read = 0;
	
	if (!Size) {
		printf("The size is zero!! Retry this operation!! \n");	
		return;
	}

	while(Size > (data_read*DATABUFFERSIZE)) {  

		if (b_temp!=0xffff) {  // check int pending
			while (!(rOND_INT_STATUS & (1<<15)));

			if (rOND_CON_STATUS & (1<<10)) {
				printf("ECC Fail.\n");
			} else
				data_load++;
		}

		if (Size > (data_load*DATABUFFERSIZE)) {  // data load

			rOND_START_ADDR1 = DFS(block) | FBA(block);

			rOND_START_ADDR8 = FPA(page) | FSA(0);

			if (data_load&1)
				rOND_START_BUFFER = BSA(0xc) | BSC(0); // DataRAM1
			else
				rOND_START_BUFFER = BSA(0x8) | BSC(0); // DataRAM0

			rOND_START_ADDR2 = DBS(block);

			rOND_INT_STATUS = 0;

			rOND_COMMAND = OND_LD_MS_TO_BUF;

		}

		if (data_load > data_read) {  // data read. 105 us @50MHz 8,16,cont.-words

			rOND_START_ADDR2 = DBS(b_temp);
		
			if ((Size-(data_read*DATABUFFERSIZE)) >= DATABUFFERSIZE) // edit by junon
				size = DATABUFFERSIZE;
			else
				size = Size-(data_read*DATABUFFERSIZE);
			
// for memory copy time check			
//if (data_load == 3)
//	StartStopwatch();
//			printf("Address = 0x%x\n", (U32)Address);

#if USE_DMA
			if (data_read&0x1) // 87 us @50MHz 8,16,cont.-words
				dma_memcpy( __OND_DataRAM1_BASE, (U32)Address, 0, size );
			else
				dma_memcpy( __OND_DataRAM0_BASE, (U32)Address, 0, size );
#else
			if (data_read&0x1) // 87 us @50MHz 8,16,cont.-words
				memcpy( Address, (U32 *)__OND_DataRAM1_BASE, size );
			else
				memcpy( Address, (U32 *)__OND_DataRAM0_BASE, size );
#endif

// for memory copy time check			
//if (data_load == 3)
//{
//	st_cnt = EndStopwatch();
//	printf("\n load cycle time : %d us", st_cnt);
//}

			Address+=(DATABUFFERSIZE>>2);
			data_read++;
		}

		b_temp = block;		
		page = (page+1)&0x3f;
		if (page==0) block++;
	}
}


//	Write-While-Program Operation, unit : page
void OND_write( U32 *Address, U32 Size, U16 block)
{
	U16	page;
	U32	data_program;
	U32	data_write;

	page = 0;
	data_program = 0;
	data_write = 0;

	if (!Size) {
		printf("The size is zero!! Retry this operation!! \n");	
		return;
	}

	while( Size >= (data_program*DATABUFFERSIZE)) { // edit by junon

		if (data_write > 0) {

			if (page==0) {
				OND_unlock_block(block);
				OND_erase_block(block);
			}

			rOND_START_ADDR1 = DFS(block) | FBA(block);
			rOND_START_ADDR8 = FPA(page) | FSA(0);

			if (data_program&1)	
				rOND_START_BUFFER = BSA(0xc) | BSC(0);
			else				
				rOND_START_BUFFER = BSA(0x8) | BSC(0);

			rOND_INT_STATUS = 0;
			rOND_COMMAND = OND_PG_MS_FR_BUF;

			page = (page+1) & 0x3f;
			if (page==0) block++;
		}
		
		// write data to DataRAM0 or 1
		if (Size >= (data_write*DATABUFFERSIZE)) {  // edit by junon
			if (data_write <= (data_program+1)) {

				rOND_START_ADDR2 = DBS(block);

⌨️ 快捷键说明

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