📄 nand_read.c
字号:
/* * vivi/s3c2410/nand_read.c: Simple NAND read functions for booting from NAND * * Copyright (C) 2002 MIZI Research, Inc. * * Author: Hwang, Chideok <hwang@mizi.com> * Date : $Date: 2004/03/25 04:42:41 $ * * $Revision: 1.12 $ * $Id: param.c,v 1.9 2002/07/11 06:17:20 nandy Exp * * History * * 2002-05-xx: Hwang, Chideok <hwang@mizi.com> * - 瞪芭扼绊 抄叼俊霸 淋. * * 2002-05-xx: Chan Gyun Jeong <cgjeong@mizi.com> * - 抄叼狼 何殴阑 罐绊 力措肺 悼累窍档废 荐沥. * * 2002-08-10: Yong-iL Joh <tolkien@mizi.com> * - SECTOR_SIZE啊 512牢 仇篮 促 佬档废 荐沥 * * 2003-04-08: Janghoon Lyu <nandy@mizi.com> * - Check bad block when vivi copy itself. * - Add a function called nand_read_oob_ll() * * NOTE: Don't use printk() */#include <config.h>#include <machine.h>#include <memory.h>/* * 构 汗棱窍变 窍瘤父, 捞犯霸扼档 东户篮 且 荐 乐嚼聪促. * 弊贰档 8M俊辑绰 悼累救钦聪促. 恐 弊繁瘤 葛福摆嚼聪促. */#undef CONFIG_SMC_SUPPORT_8M#if defined(CONFIG_SMC_SUPPORT_8M)#define CONFIG_SMC_3CYCLE_ADDRESSING#define VIVI_BLOCKS (16)#else#define CONFIG_SMC_4CYCLE_ADDRESSING#define VIVI_BLOCKS (8)#endif#ifdef CONFIG_SMC_SUPPORT_8M#define NAND_PAGES_IN_BLOCK (16)#else#define NAND_PAGES_IN_BLOCK (32)#endif#define NAND_PAGE_SIZE (512)#define NAND_PAGE_MASK (NAND_PAGE_SIZE - 1)#define NAND_BLOCK_SIZE (NAND_PAGE_SIZE*NAND_PAGES_IN_BLOCK)#define NAND_BLOCK_MASK (NAND_BLOCK_SIZE - 1)#define NAND_OOB_SIZE (16)#define TAKE_SOME_DELAY ({ for(i=0; i<10; i++); })#define BUSY 1static inline void wait_idle(void) { int i; for(i=0; i<10; i++); while(!(NFSTAT & BUSY)) ;}static voidset_address(unsigned long addr){ NFADDR = addr & 0xff; NFADDR = (addr >> 9) & 0xff; NFADDR = (addr >> 17) & 0xff;#ifdef CONFIG_SMC_4CYCLE_ADDRESSING NFADDR = (addr >> 25) & 0xff;#endif}static intnand_read_page_ll(unsigned char *buf, unsigned long addr){ int i; if (addr & NAND_PAGE_MASK) { return -1; /* invalid alignment */ } /* chip Enable */ NFCONF &= ~0x800; TAKE_SOME_DELAY; /* READ0 */ NFCMD = 0; /* Write Address */ set_address(addr); wait_idle(); /* Read data */ for(i=0; i < NAND_PAGE_SIZE; i++) { *buf = (NFDATA & 0xff); buf++; } /* chip Disable */ NFCONF |= 0x800; return 0;}/* low level nand read function */static intnand_read_oob_ll(char *buf, unsigned long addr){ int i; if ((addr & NAND_BLOCK_MASK)) { return -1; /* invalid alignment */ } /* Chip Enable */ NFCONF &= ~0x800; TAKE_SOME_DELAY; /* READOOB */ NFCMD = 0x50; /* Write Address */ set_address(addr); wait_idle(); /* Read oob data */ for(i=0; i < NAND_OOB_SIZE; i++) { *buf = (NFDATA & 0xff); buf++; } /* Chip Disable */ NFCONF |= 0x800; return 0;}static intis_bad_block(unsigned long addr){ char oob_buf[16]; nand_read_oob_ll((char *)oob_buf, addr); if (oob_buf[5] != 0xff) return 1; else return 0;}/* * Read data from NAND. */intnandll_read_blocks(unsigned long dst_addr, unsigned long src_addr, int size){ char *buf = (char *)dst_addr; int i; if ((src_addr & NAND_BLOCK_MASK) || (size & NAND_PAGE_MASK)) return -1; /* invalid alignment */ while (size > 0) { /* If this block is bad, go next block */ if (is_bad_block(src_addr)) { src_addr += NAND_BLOCK_SIZE; continue; } /* Read block */ for (i = 0; i < NAND_PAGES_IN_BLOCK; i++) { nand_read_page_ll((char *)buf, src_addr); buf += NAND_PAGE_SIZE; src_addr += NAND_PAGE_SIZE; size -= NAND_PAGE_SIZE; if (size == 0) break; } } return 0;}static voidnandll_reset(void){ NFCONF = 0xf830; /* initial value */ NFCONF &= ~(0x800); /* enable chip */ NFCMD = 0xff; /* RESET command */ wait_idle(); NFCONF |= (0x800); /* disable chip */}intcopy_vivi_to_ram(void){ nandll_reset(); /* Copy vivi to ram. 128k is enough. */ return nandll_read_blocks(VIVI_BASE, 0x0, (VIVI_BLOCKS*NAND_BLOCK_SIZE));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -