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

📄 cmd_nand.c

📁 基于S3C2440 对 K9F1208 Nand Flash 的读写,取自uboot,对其进行了修改
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * (C) 2004 Samsung Electronics *        Young-jun Jang <yj03.jang@samsung.com> *        - add/modify nandw,nandr, nande, nandv *        - bad block management (bbcheck, bbmark) *        - yaffs image r/w (nandyw, nandyr) * (C) 2004 Samsung Electronics *        SW.LEE <hitchcar@samsung.com> *        - add  nande, nandE *        - support 16Bit / 3 Addr cycle nand * (C) 2003 Samsung Electronics *        - getfree * * Driver for NAND support, Rick Bronson * borrowed heavily from: * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org> */#include <common.h>#if defined(CONFIG_S3C24XX)#if (CONFIG_COMMANDS & CFG_CMD_NAND)#include <command.h>#include <malloc.h>#include <asm/io.h>#include <regs.h>#include <linux/mtd/nand.h>#include <jffs2/jffs2.h>#ifdef CONFIG_SHOW_BOOT_PROGRESS#include <status_led.h>#define SHOW_BOOT_PROGRESS(arg)	show_boot_progress(arg)#else#define SHOW_BOOT_PROGRESS(arg)#endif#define BAD_CHECK//#undef	ECC_CHECK	/* XXX: we will do in the future */#define ECC_CHECK#ifdef	ECC_CHECK#define		ECC_COUNT_BIT	256#endif#define ROUND_DOWN(value,boundary)      ((value) & (~((boundary)-1)))static int NF_EraseBlock(u32 blockNum);static int NF_WritePage(u32 block, u32 page, u8 * buffer);static int NF_WriteOob(u32 block, u32 page, u8 * buffer, int yaffs_option);static int NF_IsBadBlock(u32 block);static int NF_MarkBadBlock(u32 block, int mark_flag);static void NF_Reset(void);static u8 seBuf[NAND_OOB_SIZE] = {	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};/* * address format *              17 16         9 8            0 * -------------------------------------------- * | block(12bit) | page(5bit) | offset(9bit) | * -------------------------------------------- */static int nandll_read_page(uchar *buf, ulong addr){        int i;	int loop = 0;	int j = 0;#ifdef ECC_CHECK	u8 oobbuf[NAND_OOB_SIZE] = {0};#endif#ifdef S3C24X0_16BIT_NAND	ushort *ptr16 = (ushort *)buf;#endif        if (addr & NAND_PAGE_MASK) {                return -1;      /* invalid alignment */        }	//        NFCONT_REG &= ~(1<<1); //NFCONT_REG &= ~(1<<1); //NAND_ENABLE_CE();        NFCONT_REG &= ~(1<<1);#ifdef ECC_CHECK		NF_RSTECC();		// Initialize ECC	NF_MECC_UnLock();	NF_CLRRnB();#endif        NFCMD_REG = NAND_CMD_READ0;		//0x0        /* Write Address */        NFADDR_REG = addr & 0xff;        NFADDR_REG = (addr >> 7) & 0x0f;        NFADDR_REG = (addr >> 11) & 0xff;        NFADDR_REG = (addr >> 19) & 0xff;		NFCMD_REG = 0x30;        NF_TRANSRnB();#ifndef	   ECC_CHECK		for(i=0; i < NAND_PAGE_SIZE; i++) {                *buf = NFDATA8_REG;		buf++;        }#else	seBuf[0] = 0xff;        seBuf[1] = 0xff;        loop = 0;	for(i = 0;i<NAND_PAGE_SIZE;){		for(j= 0; j <ECC_COUNT_BIT;j++){			*buf = NFDATA8_REG;			buf++;			i++;			}		NF_MECC_Lock();		seBuf[40+loop] = (NFMECC0_REG  & 0x0ff);		seBuf[41+loop] = ((NFMECC0_REG >>8)&0xff); 		seBuf[42+loop] = ((NFMECC0_REG >>16)&0xff);		seBuf[42+loop] |= 0x03;		loop += 3;		NF_RSTECC();		// Initialize ECC		NF_MECC_UnLock();		NF_CLRRnB();			}#endif	NFCONT_REG |= (1<<1);#if 0#ifdef ECC_CHECK	nandll_read_oob(oobbuf,addr);	printf("\nRead ECC :");	for(i = 0;i < 5; i++)		printf("%x ",oobbuf[i]);	printf("\nECC CODE :");	for(i = 0;i < 5; i++)		printf("%x ",seBuf[i]);#endif#endif        return 0;}static int nandll_read_oob(char *buf, ulong addr){        int i;#ifdef S3C24X0_16BIT_NAND	ushort *ptr16 = (ushort *)buf;#else	u8 *oobptr8 = (u8 *)buf;#endif        /* Chip Enable */        NFCONT_REG &= ~(1<<1); //NFCONT_REG &= ~(1<<1); //NAND_ENABLE_CE();	NF_CLRRnB();        /* READOOB */        NFCMD_REG = 0x0;//NAND_CMD_READOOB;        /* Write Address */        NFADDR_REG = 0x00;//addr & 0xff ;        NFADDR_REG =  0x08;//(addr >> 0x07)&0x0f;        NFADDR_REG = (addr >> 11) & 0xff;        NFADDR_REG = (addr >> 19) & 0xff;	NFCMD_REG = 0x30;        NF_TRANSRnB();		for(i=0; i < NAND_OOB_SIZE; i++) {                *oobptr8 = NFDATA8_REG;		oobptr8++;        }        NFCONT_REG |= (1<<1); //NAND_DISABLE_CE();/*        printf("\nLast OOB :");	for(i = 0;i < NAND_OOB_SIZE;i++)		printf(" %2x ",buf[i]);*/        return 0;}static int is_bad_block(unsigned long addr){	char oob_buf[64];	nandll_read_oob((char *)oob_buf, addr);   /* culprit */#ifdef S3C24X0_16BIT_NAND	if ( (oob_buf[0] != 0xFF) ||  (oob_buf[1] != 0xFF) )		return 1;#else	if (oob_buf[0] != 0xFF)		return 1;#endif	else		return 0;}#ifdef OREIAS#define adjust_bank(x)	\	do { \		if(x>=0x11e00000) \			x=x+0x6200000;\	} while(0)#endif#define check_blk_range(blk) \	do { \		if (blk<0 || blk>=4096) { \			printf( "out of block range\n" ); \			return 1; \		} \	} while(0)#define check_page_range(page) \	do { \		if (page<0 || page>=32) { \			printf( "out of page range\n" ); \			return 1; \		} \	} while(0)static int s3c24x0_nand_read(uint blockIndex, int size, uint destAddress, int flag){	char *buf = (char *) destAddress;	char page_buf[NAND_PAGE_SIZE];	char oob_buf[NAND_OOB_SIZE];	int i, j;	u32 src_addr = blockIndex * NAND_BLOCK_SIZE;	printf("block read : ");	while (size > 0) {		if (flag != NF_RW_YAFFS) {			/* If this block is bad, go next block */			if (is_bad_block(src_addr)) {				src_addr += NAND_BLOCK_SIZE;				continue;			}		}		printf("%X ", (src_addr >> 17));		/* Read block */		for (i = 0; i < NAND_PAGES_IN_BLOCK; i++) {			nandll_read_page((uchar *) page_buf, src_addr);			for (j = 0; j < NAND_PAGE_SIZE; j++) {				*buf++ = page_buf[j];			}			size -= NAND_PAGE_SIZE;			if (size <= 0)				break;			if (flag == NF_RW_YAFFS) {				/* read oob */				nandll_read_oob((char *) oob_buf, src_addr);				for (j = 0; j < NAND_OOB_SIZE; j++) {					*buf++ = oob_buf[j];				}				size -= NAND_OOB_SIZE;				if (size <= 0)					break;			}			src_addr += NAND_PAGE_SIZE;		}	}	printf("\n");	return 0;}/* * s3c24x0_nand_write * * yaffs_option : only used when flag is yaffs mode. */static int s3c24x0_nand_write( uint targetBlock, uint targetSize, uint srcAddress, int flag, int yaffs_option){	int i;	int programError = 0;	u8 *srcPt, *saveSrcPt;	u32 blockIndex;	printf("\nNAND Flash Write\n");	printf("Source base address        = 0x%x\n", srcAddress);	printf("Target start block number  = 0x%x (%d)\n", targetBlock, targetBlock);	printf("Target size    (0x4000*n)  = 0x%x\n", targetSize);	printf("block written :\n");	srcPt = (u8 *) srcAddress;	blockIndex = targetBlock;	while (1) {		saveSrcPt = srcPt;#if 1#ifdef BAD_CHECK		if (NF_IsBadBlock(blockIndex)) {			blockIndex++;	// for next block			continue;		}#endif		if (!NF_EraseBlock(blockIndex)) {			blockIndex++;	// for next block			printf(" Error->  Erase Block %d  \n", (int) blockIndex);			continue;		}#endif		for (i = 0; i < NAND_PAGES_IN_BLOCK; i++) {			if (!NF_WritePage(blockIndex, i, srcPt)) {				programError = 1;				break;			}/*#ifdef ECC_CHECK			if (flag != NF_RW_YAFFS) {				if (!NF_ReadPage(blockIndex, i, srcPt)) {					printf("ECC Error(block=%d,page=%d!!!\n", (int) blockIndex, i);				}			}#endif*/			srcPt += NAND_PAGE_SIZE;/*			if (flag == NF_RW_YAFFS) {				if (!NF_WriteOob(blockIndex, i, srcPt, yaffs_option)) {					programError = 1;					break;				}				srcPt += NAND_OOB_SIZE;			}*/			//printf(".");			if ((u32) srcPt >= (srcAddress + targetSize)) {	// Check end of buffer				break;	// Exit for loop			}		}		if (programError == 1) {			blockIndex++;			srcPt = saveSrcPt;			programError = 0;			continue;		}		printf("%3x ", blockIndex);		if (!((blockIndex+1) % 16))			printf("\n");		if ((u32) srcPt >= (srcAddress + targetSize))			break;	// Exit while loop		blockIndex++;	}	printf("\n\n");	return 0;}int do_nandE(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){	int startblk, size, eraseblocks, i;	if (argc != 3) {		printf("Usage:\n%s\n", cmdtp->usage);		return 1;	}	startblk = simple_strtoul(argv[1], NULL, 16);	size = simple_strtoul(argv[2], NULL, 16);	printf("StartBlock %d (0x%x) : Size %d (0x%x) \n", startblk, startblk, size, size);	eraseblocks = size / NAND_BLOCK_SIZE;	printf("Total Erase Blocks %d (0x%x) \n", eraseblocks, eraseblocks);	udelay(10000);	NF_Reset();	for (i = 0; i < eraseblocks; i++) {		NF_EraseBlock(startblk);		startblk++;	}	return 0;}int do_nandw(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){	ulong startblk, size, memadr;	if (argc != 4) {		printf("Usage:\n%s\n", cmdtp->usage);		return 1;	}	startblk = simple_strtoul(argv[1], NULL, 16);	size = simple_strtoul(argv[2], NULL, 16);	memadr = simple_strtoul(argv[3], NULL, 16);	NF_Reset();	s3c24x0_nand_write(startblk, size, memadr, NF_RW_NORMAL, 0);	{		uint *magic = (uint*)(PHYS_SDRAM_1);		magic[0] = 0x27051956;	}	return 0;}int do_nandr(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){	ulong startblk, size, memadr;	if (argc != 4) {		printf("Usage:\n%s\n", cmdtp->usage);		return 1;	}	startblk = simple_strtoul(argv[1], NULL, 16);	size = simple_strtoul(argv[2], NULL, 16);	memadr = simple_strtoul(argv[3], NULL, 16);	NF_Reset();	s3c24x0_nand_read(startblk, size, memadr, NF_RW_NORMAL);	return 0;}int do_nande(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){	int i;	ulong blk_start, blk_end;	if (argc != 3) {		printf("Usage:\n%s\n", cmdtp->usage);		return 1;	}	blk_start = simple_strtoul(argv[1], NULL, 16);	blk_end = simple_strtoul(argv[2], NULL, 16);	for (i = blk_start; i <= blk_end; i++) {		if (!NF_EraseBlock(i)) {			printf("nand flash erase error : at block %x\n", i);		}	}	printf("nand flash erase complete\n");	return 0;}int do_bbmark(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){	ulong blk;	if (argc != 3) {		printf("Usage:\n%s\n", cmdtp->usage);		return 1;	}	blk = simple_strtoul(argv[1], NULL, 16);	check_blk_range(blk);	if (!NF_EraseBlock(blk)) {		printf("erase error\n");	}	if (strcmp(argv[2], "on") == 0)		NF_MarkBadBlock(blk, NF_BB_ON);	else		NF_MarkBadBlock(blk, NF_BB_OFF);	return 0;}int do_bbcheck(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){	int i, bb_cnt;	printf("Bad block list : \n");	for (bb_cnt = 0, i = 0; i < 4096; i++) {		if (NF_IsBadBlock(i)) {			bb_cnt++;		}	}	if (bb_cnt > 0) {		printf("\n Total bad block count : %d \n", bb_cnt);	}	else {		printf("No bad block\n");	}	return 0;}/* show page data */int do_nandv(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){	int blk, page, i;	u32 oob_buf[16 / 4];	u32 page_buf[512 / 4];	if (argc != 3) {		printf("Usage:\n%s\n", cmdtp->usage);		return 1;

⌨️ 快捷键说明

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