diff --git a/libcpu/arm/s3c24x0/nand_read.c b/libcpu/arm/s3c24x0/nand_read.c new file mode 100644 index 0000000000..8df617916b --- /dev/null +++ b/libcpu/arm/s3c24x0/nand_read.c @@ -0,0 +1,67 @@ +/* + * nand flash read + */ + +#define NFCONF (*(volatile unsigned int *)0x4e000000) +#define rNFCONT (*(volatile unsigned int *)0x4E000004) +#define NFCMD (*(volatile unsigned int *)0x4e000008) +#define NFADDR (*(volatile unsigned char *)0x4e00000C) +#define NFDATA (*(volatile unsigned char *)0x4e000010) +#define NFSTAT (*(volatile unsigned char *)0x4e000020) + +#define BUSY 1 + +#define NAND_SECTOR_SIZE 512 +#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1) + +void wait_idle(void) { + int i; + + while (!(NFSTAT & BUSY)) { + for(i=0; i<10; i++) { + ; + } + } +} + +/* low level nand read function */ +int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size) +{ + int i, j; + + /* + * K9F5608UOC asks for 512B per page, and read/write operation must + * do with page. Therefore, first judge whether start_addr and size + * are valid. + */ + if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) { + return -1; /* invalid alignment */ + } + + /* chip Enable */ + NFCONF &= ~0x800; + for (i=0; i<10; i++) { + ; + } + + for (i=start_addr; i < (start_addr + size); i+=NAND_SECTOR_SIZE) { + NFCMD = 0; + + /* Write Address */ + NFADDR = i & 0xff; + NFADDR = (i >> 9) & 0xff; + NFADDR = (i >> 17) & 0xff; + NFADDR = (i >> 25) & 0xff; + + wait_idle(); + + for(j=0; j < NAND_SECTOR_SIZE; j++) { + *buf++ = (NFDATA & 0xff); + } + } + + /* chip Disable */ + NFCONF |= 0x800; /* chip disable */ + + return 0; +}