?? cmd_nand_mba24x0.c.svn-base
字號:
/* * 2005 modified by Embedded Biz. Division, AIJI system * * (C) Samsung Electronics * SW.LEE <hitchcar@samsung.com> * - add nandE, 16Bit NAND * - delete dummy code for S3C2440A * (C) Samsung Electrocnis * 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>#include <command.h>#include <malloc.h>#include <asm/io.h>#if CONFIG_S3C2410#include <s3c2410.h>#elif CONFIG_S3C2440#include <s3c2440.h>#elif CONFIG_S3C2443#include <s3c2443.h>#endif#if (CONFIG_COMMANDS & CFG_CMD_NAND)#include <linux/mtd/nand.h>#include <linux/mtd/nand_ids.h>#if CONFIG_S3C2443 /**** This is not final DO MODIFY ***/#define NAND_LED (*(volatile unsigned *)(S3C24X0_GPIO_BASE+0x54)) #else#define NAND_LED (*(volatile unsigned *)(S3C24X0_GPIO_BASE+0x54))#endif#define WR_STATUS 1#define RD_STATUS 2extern u16 NF_CheckId(void);static int NF_Write(u8 *src_addr, u8 *start_nand_addr, u32 size);extern int NF_WriteBlock(u8 *src_addr, u32 blk_num);static int NF_WritePage(u32 block, u32 page, u8 *buffer);extern int NF_EraseBlock(u32 blockNum);static int NF_Read(u8 *dst_addr, u8 *start_nand_addr, u32 size);extern int NF_ReadBlock(u8 *dst_addr, u32 blk_num);static int NF_ReadPage(u32 block, u32 page, u8 *buffer);static int NF_IsBadBlock(u32 block);static int NF_MarkBadBlock(u32 block);static void NF_Reset(void);static void NF_Init(void);extern void nand_init(void);static void LED_blink(int status);//static int NF_WriteOob(u32 block, u32 page, u8 *buffer, int yaffs_option);static int nand_mem_size = 0;static int nand_blk_count = 0;void nand_init(void){ unsigned char manuf_id, model_id; unsigned short id = 0; int i; NF_Init(); id = NF_CheckId(); manuf_id = (id >> 8) & 0xff; model_id = id & 0xff; for(i=0; nand_flash_ids[i].name != NULL;i++){ if(manuf_id == nand_flash_ids[i].manufacture_id){ if(model_id == nand_flash_ids[i].model_id){ nand_mem_size = nand_flash_ids[i].memsize; nand_blk_count = nand_mem_size/NAND_BLOCK_SIZE; printf("%s mem size<%dMB>, Block count<%d>\n", nand_flash_ids[i].name, nand_mem_size>>20, nand_blk_count); } } } if(nand_mem_size == 0) printf("[NAND flash is not detected..]"); return;}/*int do_nandyw (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ ulong startblk,size,memadr; int ecc_option; if (argc != 5) { 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); ecc_option = (argv[4][0] == 'y') ? NF_USE_ECC : NF_USE_MTD_ECC; // yaffs image don't use 1st block startblk++; NF_Init(); s3c24x0_nand_write(startblk, size, memadr, NF_RW_YAFFS, ecc_option ); return 0;}*/int do_nandw (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ ulong blk_num, page_num, src_addr, size, mem_addr; if ((argc < 4) || (argc > 5)){ printf ("inadquate argument count\n%s\n", cmdtp->help); return -1; } NF_Init(); mem_addr = simple_strtoul(argv[2], NULL, 16); if(strcmp(argv[1], "b") == 0){ blk_num = simple_strtoul(argv[3], NULL, 10); printf("write block[%d].. read from memory address 0x%x, size is 0x%x\n" , blk_num, mem_addr, NAND_BLOCK_SIZE); NF_EraseBlock(blk_num); if(NF_WriteBlock((u8 *)mem_addr, blk_num) != 0) return -1; printf("\nWriting block is Completed\n\n"); }else if(strcmp(argv[1], "p") == 0){ blk_num = simple_strtoul(argv[3], NULL, 10); page_num = simple_strtoul(argv[4], NULL, 10); printf("write page[block:%d, page:%d].. read from memory address 0x%x, size is 0x%x\n" , blk_num, page_num, mem_addr, NAND_PAGE_SIZE); NF_EraseBlock(blk_num); if(NF_WritePage(blk_num, page_num, (u8 *)mem_addr) != 0) return -1; }else if(strcmp(argv[1], "t") == 0){ src_addr = simple_strtoul(argv[3], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); if(NF_Write((u8 *)mem_addr, (u8 *)src_addr, size) != 0) return -1; }else{ printf("unknown option.. 'b' or 'p' or 't' \n"); return -1; } return 0;}int do_nandr (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ ulong blk_num, page_num, dst_addr, size, mem_addr; if ((argc < 4) || (argc > 5)){ printf ("inadquate argument count\n%s\n", cmdtp->help); return -1; } NF_Init(); mem_addr = simple_strtoul(argv[2], NULL, 16); if(strcmp(argv[1], "b") == 0){ blk_num = simple_strtoul(argv[3], NULL, 10); printf("read block[%d].. copy to memory address 0x%x, size is 0x%x\n" , blk_num, mem_addr, NAND_BLOCK_SIZE); if(NF_ReadBlock((u8 *)mem_addr, blk_num) != 0) return -1; printf("\nReading block is Completed\n\n"); }else if(strcmp(argv[1], "p") == 0){ blk_num = simple_strtoul(argv[3], NULL, 10); page_num = simple_strtoul(argv[4], NULL, 10); printf("read page[block:%d, page:%d].. copy to memory address 0x%x, size is 0x%x\n" , blk_num, page_num, mem_addr, NAND_PAGE_SIZE); if(NF_ReadPage(blk_num, page_num, (u8 *)mem_addr) != 0) return -1; }else if(strcmp(argv[1], "t") == 0){ dst_addr = simple_strtoul(argv[3], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); if(NF_Read((u8 *)mem_addr, (u8 *)dst_addr, size) != 0) return -1; }else{ printf("unknown option.. 'b' or 'p' or 't' \n"); return -1; } return 0;}int do_nande (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ int startblock, endblock, i; if ((argc < 2) || (argc > 3)){ printf ("inadquate argument count\nUsage:\n%s\n", cmdtp->help); return -1; } NF_Init(); if(argc == 2){ if(strcmp(argv[1], "all") == 0){ startblock = 0; endblock = nand_blk_count-1; printf("erase all blocks [0 ~ %d]\n", endblock); }else{ startblock = simple_strtoul(argv[1], NULL, 10); endblock = startblock; printf("erase block [%d]\n", startblock); } }else{ //argc == 3 startblock = simple_strtoul(argv[1], NULL, 10); endblock = simple_strtoul(argv[2], NULL, 10); printf("erase block [%d ~ %d]\n", startblock, endblock); } printf("Erasing block ..."); for( i=startblock ; i <= endblock; i++){ if(NF_EraseBlock(i) == 1) spin_wheel(); else{ printf("\n[ERASE_ERROR: bad block[ %4d]\n", i); printf("Erasing block ... "); }// NF_CheckBadNande(i);// printf("%4d ", i);// if(i%16 == 15) printf("\n"); } printf("\nComplete erasing block\n\n\n"); return 0;}int do_nandb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ int startblock, endblock, i, chk_blk_cnt; if ((argc < 2) || (argc > 3)){ printf ("inadquate argument count\nUsage:\n%s\n", cmdtp->help); return -1; } NF_Init(); if(argc == 2){ if(strcmp(argv[1], "all") == 0){ startblock = 0; endblock = nand_blk_count-1; printf("check all blocks [0 ~ %d]\n", endblock); }else{ startblock = simple_strtoul(argv[1], NULL, 10); endblock = startblock; printf("check block number [%d]\n", startblock); } }else{ //argc == 3 startblock = simple_strtoul(argv[1], NULL, 10); endblock = simple_strtoul(argv[2], NULL, 10); printf("erase block [%d ~ %d]\n", startblock, endblock); } printf("Display block status :"); chk_blk_cnt = 0; for( i=startblock ; i <= endblock; i++){ if(NF_IsBadBlock(i) == 1){ if(chk_blk_cnt%8 == 0) printf("\n"); printf("%4d(bad) ", i); chk_blk_cnt++; }else{// printf("%4d(o) ", i); } } if(chk_blk_cnt == 0){ if(argc == 2){ if(startblock == endblock) printf("\nblock[%4d] is OK..", startblock); else printf("\nAll block is OK.."); }else printf("block[%4d] ~ block[%4d] OK..", startblock, endblock); } printf("\n\n\n"); return 0;}/*U_BOOT_CMD( nandyw, 5, 1, do_nandyw, "nandyw - HEX: targetblock targetsize mem_addr ecc_option(y/m)\n", "\n - MBA2410 NAND Flash Write Command for Yaffs\n" \ "nandyw targetblock 0~0xfff(4095), targetsize memory addr \n" \ " ecc_option : [y] : use yaffs ecc / [m] : use mtd ecc \n" \);*/U_BOOT_CMD( nandw, 5, 1, do_nandw, "nandw - MBA2410 NAND Flash Write program : write from memory to NAND flash\n", " - MBA2410 NAND Flash Write Program : write from NAND\n" \ "nandw [b/p/t] [src_mem_addr] [targetblock/src_addr] [targetpage/size]\n" \ " option b - read block, p - read page, t - read address you wanna write\n" \ " nandw b source_memory_addr(hex) targetblock(0~4095)\n" \ " nandw p source_memory_addr(hex) targetblock(0~4095) targetpage(0~31)\n" \ " nandw t source_memory_addr(hex) target_addr[hex] size[hex]\n" \ " The limits of target_addr must be from 0x0 to 0x4000000\n" \ " target_addr must be the multiple of page size 0x200\n" \);U_BOOT_CMD( nandr, 5, 1, do_nandr, "nandr - MBA2410 NAND Flash Read program : read and copy to memory \n", " - MBA2410 NAND Flash Read program : read and copy to memory \n" \ "nandr [b/p/t] [dst_mem_addr] [targetblock/src_addr] [targetpage/size]\n" \ " option b - read block, p - read page, t - read address you wanna read\n" \ " nandr b destination_memory_addr(hex) targetblock(0~4095)\n" \ " nandr p destination_memory_addr(hex) targetblock(0~4095) targetpage(0~31)\n" \ " nandr t destination_memory_addr(hex) target_addr[hex] size[hex]\n" \ " The limits of target_addr must be from 0x0 to 0x4000000\n" \ " target_addr must be the multiple of page size 0x200\n" \);U_BOOT_CMD( nande, 3, 1, do_nande, "nande - MBA2410 NAND Flash Erase program : erase blocks\n", " - MBA2410 NAND Flash Erase program : erase only blocks\n" \ " nande startblock(0~4095) endblock(0~4095)\n" \ " nande blocknumber(0~4095) - erase one block you select\n" \ " nande all - erase all blocks\n" \);U_BOOT_CMD( nandb, 3, 1, do_nandb, "nandb - MBA2410 NAND Flash Bad block check program\n", " - MBA2410 NAND Flash Bad block check program\n" \ " nandb startblock(0~4095) endblock(0~4095)\n" \ " nande blocknumber(0~4095) - check one block you select\n" \ " nande all - check all blocks\n" \);#define NF_CMD(cmd) {NFCMD = cmd;}#define NF_ADDR(addr) {NFADDR = addr;}#define NF_RDDATA() (NFDATA)#define NF_WRDATA(data) {NFDATA = data;}#if CONFIG_S3C2410#define NF_nFCE_L() {NFCONF &= ~(1<<11);}#define NF_nFCE_H() {NFCONF |= (1<<11);}#define NF_RSTECC() {NFCONF |= (1<<12);}#define NF_DETECT_RB() {while(!(NFSTAT & (1<<0)));}#define NF_CLEAR_RB() {NFSTAT |= (1<<2);} // Have write '1' to clear this bit.#define TACLS 0 // 1-clk(0ns) #define TWRPH0 3 // 3-clk(25ns)#define TWRPH1 0 // 1-clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns#elif CONFIG_S3C2440#define NF_SOFT_UnLock() {NFCONT&=~(1<<12);}#define NF_MECC_UnLock() {NFCONT&=~(1<<5);}#define NF_MECC_Lock() {NFCONT|=(1<<5);}#define NF_SECC_UnLock() {NFCONT&=~(1<<6);}#define NF_SECC_Lock() {NFCONT|=(1<<6);}#define NF_nFCE_L() {NFCONT&=~(1<<1);}#define NF_nFCE_H() {NFCONT|=(1<<1);}#define NF_RSTECC() {NFCONT|=(1<<4);}#define NF_RDDATA8() (NFDATA8)#define NF_WRDATA8(data) {NFDATA8=data;}// RnB Signal#define NF_DETECT_RB() {while(!(NFSTAT&(1<<2)));}#define NF_CLEAR_RB() {NFSTAT |= (1<<2);} // Have write '1' to clear this bit.#define TACLS 1#define TWRPH0 5#define TWRPH1 0static u32 se16Buf[32/2]={ 0xffffffff,0xffffffff,0xffffffff,0xffffffff, 0xffffffff,0xffffffff,0xffffffff,0xffffffff, 0xffffffff,0xffffffff,0xffffffff,0xffffffff, 0xffffffff,0xffffffff,0xffffffff,0xffffffff};#elif CONFIG_S3C2443#define NF_SOFT_UnLock() {NFCONT&=~(1<<16);}#define NF_MECC_UnLock() {NFCONT&=~(1<<7);}#define NF_MECC_Lock() {NFCONT|=(1<<7);}#define NF_SECC_UnLock() {NFCONT&=~(1<<6);}#define NF_SECC_Lock() {NFCONT|=(1<<6);}#define NF_nFCE_L() {NFCONT&=~(1<<1);}#define NF_nFCE_H() {NFCONT|=(1<<1);}#define NF_RSTECC() {NFCONT|=(1<<4);}#define NF_RDDATA8() (NFDATA8)#define NF_WRDATA8(data) {NFDATA8=data;}// RnB Signal#define NF_DETECT_RB() {while(!(NFSTAT & (1<<4)));}#define NF_CLEAR_RB() {NFSTAT |= (1<<4);} // Have write '1' to clear this bit.#define TACLS 1#define TWRPH0 5#define TWRPH1 0static u32 se16Buf[32/2]={ 0xffffffff,0xffffffff,0xffffffff,0xffffffff, 0xffffffff,0xffffffff,0xffffffff,0xffffffff, 0xffffffff,0xffffffff,0xffffffff,0xffffffff, 0xffffffff,0xffffffff,0xffffffff,0xffffffff};#endifstatic u8 seBuf[16]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};int NF_Write(u8 *src_addr, u8 *start_nand_addr, u32 size){ u32 s_blk_num, s_pg_num; u32 e_blk_num, e_pg_num; u8 * buf = src_addr; int i, j; if((start_nand_addr<0) || (start_nand_addr>=nand_mem_size)){ printf("target_addr must be within the range of 0x0 ~ 0x%x\n", nand_mem_size-1); return -1; } if(((u32)src_addr<CFG_MEMTEST_START) || ((u32)src_addr>=CFG_MEMTEST_END)){ printf("source_memory_addr must be within the range of 0x%x ~ 0x%x\n", CFG_MEMTEST_START, CFG_MEMTEST_END); return -1; } s_blk_num = (u32)start_nand_addr / (u32)NAND_BLOCK_SIZE; s_pg_num = ((u32)start_nand_addr&(NAND_BLOCK_SIZE -1)) / (u32)NAND_PAGE_SIZE; e_blk_num = ((size / (u32)NAND_BLOCK_SIZE)) + s_blk_num; e_pg_num = ((size&(NAND_BLOCK_SIZE -1)) / (u32)NAND_PAGE_SIZE) + s_pg_num; printf("Write start point : block[%d] page[%d] size = 0x%x\n", s_blk_num, s_pg_num, size); printf("Writing data ... "); for(i=s_blk_num; i<=e_blk_num; i++){ if(NF_EraseBlock(i) == 0){ printf("\nBlock[%d] is bad block. Write next block\n", i); e_blk_num++; printf("Writing data ... "); continue; } if((i==s_blk_num) && (s_pg_num != 0)){ for(j=s_pg_num; j<NAND_PAGES_IN_BLOCK; j++){ NF_WritePage(i, j, buf); spin_wheel(); buf += NAND_PAGE_SIZE; } }else if((i==e_blk_num) && (e_pg_num != 0)){ for(j=0; j<e_pg_num; j++){ NF_WritePage(i, j, buf); spin_wheel(); buf += NAND_PAGE_SIZE; } }else if((i==e_blk_num) && (e_pg_num == 0)){ break; }else{ NF_WriteBlock(buf, i); buf += NAND_BLOCK_SIZE; } } printf("\nWrite compelete(0x%x): from 0x%x SDRAM to 0x%x(%d) NAND flash\n", size, (u32)src_addr, start_nand_addr, s_blk_num); return 0; }int NF_WriteBlock(u8 *src_addr, u32 blk_num){ char *buf = src_addr; int i; for (i = 0; i < NAND_PAGES_IN_BLOCK; i++) { NF_WritePage(blk_num, i, buf); spin_wheel(); buf += NAND_PAGE_SIZE; } LED_blink(WR_STATUS); return 0;}int NF_WritePage(u32 block,u32 page,u8 *buffer){ int i; u32 blockPage = (block * NAND_PAGES_IN_BLOCK) + (page & 0x1f); u8 *ptr = buffer;#if CONFIG_S3C2440 || CONFIG_S3C2443 //added by maddy220109 u32 mecc, secc;#endif#if CONFIG_S3C2440 || CONFIG_S3C2443 //added by maddy220109 NF_SOFT_UnLock();#endif NF_RSTECC();#if CONFIG_S3C2440 || CONFIG_S3C2443 //added by maddy220109 NF_MECC_UnLock();#endif NF_nFCE_L(); NF_CLEAR_RB(); NF_CMD(NAND_CMD_READ0); //?????? NF_CMD(NAND_CMD_SEQIN); // Write 1st command NF_ADDR(0); // Column 0 NF_ADDR(blockPage&0xff); // NF_ADDR((blockPage>>8)&0xff); // Block & page num. NF_ADDR((blockPage>>16)&0xff); // // Write one page to NFM from buffer#if CONFIG_S3C2410
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -