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 + -
显示快捷键?