nand_drv.c
来自「ADS下的bios工程」· C语言 代码 · 共 277 行
C
277 行
#include <bios/config.h>#include <bios/boot.h>#include <bios/malloc.h>#include <bios/time.h>#include <bios/stdio.h>#include <bios/stdioint.h>#include <bios/string.h>#include <asm/hardware.h>#include <asm/arch/config.h>#include <bios/nand.h>/* extern variable */extern int _bss_start;extern unsigned long load_addr;int nand_state_read(void);unsigned char Spare[16];static void delay(int cnt){ int i; for (i = 0; i < cnt; i ++) ;}int Address_step;int Block_size;int Page_size;int Page_shift;int Block_shift;int nand_id_read(void){ unsigned int m_id, d_id = 0, ret = -1; sti(); /* NAND Flash ID read */ CSR_WRITE(NFCONF, CSR_READ(NFCONF) & ~(1 << 11)); CSR_WRITE(NFCMD, 0x90); /* ID read command : 0x90 */ CSR_WRITE(NFADDR, 0x00); /* address : 0x00 */ delay(0x10); /* Twb(max) : 100ns */ delay(0x6); /* Treadid(max) : 35ns */ switch (m_id = CSRB_READ(NFDATA)) { case SAMSUNG: switch (d_id = CSRB_READ(NFDATA)) { case K9S6408V0A: Address_step = 3; Block_size = 1024; Page_size = 16; ret = 0; break ; default : break; } default: break; } CSR_WRITE(NFCONF, CSR_READ(NFCONF) | (1 << 11)); cli(); printf("Maker ID : %x, Device ID : %x\n", m_id, d_id); return ret;}int nand_page_read(int block, int page, int column, unsigned char *Buffer, int len){ unsigned char ecc0, ecc1, ecc2; int i; sti(); //printf("block(%d), page(%d), buffer(%x)\n", block, page, Buffer); block = (block << 4) + page; //block = (block << 5) + page; /* Read Page : 0x0 */ CSR_WRITE(NFCONF, CSR_READ(NFCONF) | (1 << 12)); /* Initialize ECC */ CSR_WRITE(NFCONF, CSR_READ(NFCONF) & ~(1 << 11)); CSR_WRITE(NFCMD, 0x00); /* Sequential Raw Read command : 0x00 */ CSR_WRITE(NFADDR, 0x00); /* Column Address(A0~A7) : 0x00 */ CSR_WRITE(NFADDR, block & 0xFF); /* Column Address(A9~A16) */ CSR_WRITE(NFADDR, (block >> 8) & 0xFF); /* Column Address(A17~A22) */ //CSR_WRITE(NFADDR, (block >> 16) & 0x3); delay(0x10); /* Twb(max) : 100ns */ while (!(CSR_READ(NFSTAT) & 0x1) ); /* Tr(max) : 7us */ for (i = 0; i < len; i ++) *(Buffer + i) = CSRB_READ(NFDATA); ecc0 = CSRB_READ(NFECC0); ecc1 = CSRB_READ(NFECC1); ecc2 = CSRB_READ(NFECC2); for (i = 0; i < 16; i ++) Spare[i] = CSRB_READ(NFDATA); CSR_WRITE(NFCONF, CSR_READ(NFCONF) | (1 << 11)); cli(); if (ecc0 == Spare[0] && ecc1 == Spare[1] && ecc2 == Spare[2]) { return 1; } else { printf("[Block(%d,%d)ECC ERROR(RD):read:%x,%x,%x, reg:%x,%x,%x]\n", block >> 4, page, Spare[0], Spare[1], Spare[2], ecc0, ecc1, ecc2); return 0; } return 0;}int nand_page_write(int block, int page, int column, unsigned char *Buffer, int len){ int ret = 0, i; block = (block << 4) + page; sti(); //block = (block << 5) + page; for (i = 0; i < 16; i ++) Spare[i] = 0xFF; /* Write Page : 0x0 */ CSR_WRITE(NFCONF, CSR_READ(NFCONF) | (1 << 12)); /* Initialize ECC */ CSR_WRITE(NFCONF, CSR_READ(NFCONF) & ~(1 << 11)); /* not care ~CE */ CSR_WRITE(NFCMD, 0x00); /* Move Pointer Position command : 0x00 */ CSR_WRITE(NFCMD, 0x80); /* Page Data Input command : 0x80 */ CSR_WRITE(NFADDR, 0x00); /* Column Address(A0~A7) : 0x00 */ CSR_WRITE(NFADDR, block & 0xFF); /* First Page Address(A9~A16) */ CSR_WRITE(NFADDR, (block >> 8) & 0xFF); /* Second Page Address(A17~A22) */ //CSR_WRITE(NFADDR, (block >> 16) & 0x3); delay(0x10); /* Twb(max) : 100ns */ for (i = 0; i < len; i ++) CSRB_WRITE(NFDATA, Buffer[i]); Spare[0] = CSRB_READ(NFECC0); Spare[1] = CSRB_READ(NFECC1); Spare[2] = CSRB_READ(NFECC2); for (i = 0; i < 16; i ++) CSRB_WRITE(NFDATA, Spare[i]); CSR_WRITE(NFCMD, 0x10); /* Page Program command : 0x10 */ delay(0x10); /* Twb(max) : 100ns */ while (!(CSR_READ(NFSTAT) & 0x1)); /* Tr(max) : 7us */ ret = nand_state_read(); CSR_WRITE(NFCONF, CSR_READ(NFCONF) | (1 << 11)); cli(); return ret;}int nand_state_read(void){ CSRB_WRITE(NFCMD, 0x70); /* Read status command : 0x70 */ delay(0x6); /* Twhr(max) : 60ns */ if (CSRB_READ(NFDATA) & 0x1) { /* Check Status */ printf("Error....\n"); return 0; } else return 1;}int nand_block_erase(int block){ int ret; sti(); //printf("Erasing"); //block = block << 4; block <<= 5; /* Block Erase : 0x0 */ CSR_WRITE(NFCONF, CSR_READ(NFCONF) & ~(1 << 11)); CSR_WRITE(NFCMD, 0x60); /* Block Erase Setup command : 0x60 */ CSR_WRITE(NFADDR, block & 0xFF); /* Block Address(A9~A16) : 0x00 */ CSR_WRITE(NFADDR, (block >> 8) & 0xFF); /* Block Address(A17~A22) : 0x00 */ CSR_WRITE(NFADDR, (block >> 16) & 0xff); delay(0x8); /* Twc(min) : 50ns */ CSR_WRITE(NFCMD, 0xD0); /* Block Erase command : 0xD0 */ delay(0x10); /* Twb(max) : 100ns */ while (!(CSR_READ(NFSTAT) & 0x1)); ret = nand_state_read(); CSR_WRITE(NFCONF, CSR_READ(NFCONF) | (1 << 11)); cli(); return ret;}int nand_flash_control(int control, int block, int page, unsigned char *buf, int len){ int i; if (control == nand_read) { for (i = len; i > 0; i -= 512, page ++, buf += 512) { if (page == 32) { block ++; page = 0; } nand_page_read(block, page, 0, buf, (i > 512) ? 512 : i); } } else if (control == nand_write) { for (i = 0; i < len; i += 8192) { nand_block_erase(block + (i >> 13)); } for (i = len; i > 0; i -= 512, page ++, buf += 512) { if (page == 32) { block ++; page = 0; } nand_page_write(block, page, 0, buf, (i > 512) ? 512 : i); } } else if (control == nand_erase) { for (i = 0; i < len; i += 8192) nand_block_erase(block ++); } return 0;}static int nand_probe(void){ return nand_id_read();}static int nand_start(void){ return 0 ;}static int nand_load(void){ return 0 ;}static int nand_stop(void){ return 0 ;}struct bootdev boot_nand = { "nand", nand_probe, nand_start, nand_load, nand_stop};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?