/* * check block is bad? * return 1 if it's a bad block, 0 if it's good. */ int K9F2G08_Check_badblk(u32 block) { u8 data; u32 _page;/* frist page in block */ _page = block*PAGES_PER_BLOCK; /* For 2'nd cycle I/O[7:5] */ nand_cs_en(); nand_write_cmd(NAND_CMD_READ0); /* Spare array read command */ nand_write_addr(PAGE_DATA_SIZE&0xff); /* Read the mark of bad block in spare array(M addr=5) */ nand_write_addr((PAGE_DATA_SIZE>>8)&0xff); nand_write_addr(_page&0xff); /* The mark of bad block is in 0 page */ nand_write_addr((_page>>8)&0xff); /* For block number A[24:17] */ nand_write_addr((_page>>16)&0xff); /* For block number A[25] */ nand_write_cmd(NAND_CMD_READSTART); nand_wait(); /* Wait tR(max 12us) */ data=nand_read(); nand_cs_ds(); if(data==0x00) return 1;/* bad */ else return 0;/* good */ }
int K9F2G08_ReadChunk(u32 chunk, u8 *data, u8 *tags) { int i; nand_cs_en(); nand_write_cmd(NAND_CMD_READ0); nand_write_addr(0x00); nand_write_addr(0x00); nand_write_addr(chunk & 0xff); nand_write_addr((chunk >> 8) & 0xff); nand_write_addr((chunk >> 16) & 0xff); // /* nand_Init_ECC(); */ nand_write_cmd(NAND_CMD_READ30); nand_wait(); /* Wait tR(max 12us) */ for(i = 0; i < PAGE_DATA_SIZE; i++) { data[i] = nand_read(); /* Read page data */ } for(i = 0; i < PAGE_SPARE_SIZE; i++) { tags[i] = nand_read(); /* Read spare array */ } nand_cs_ds(); return 1; }
/* * write one page data * return 0,successful * return 1,error */ int K9F2G08_WritePage(u32 block, u32 page, const u8 *buffer, int len, const u8 *ecc) { int i,stat; u32 _page = block*PAGES_PER_BLOCK + page; /* nand_Init_ECC(); */ /* nitialize ECC */ nand_cs_en(); nand_write_cmd(NAND_CMD_SEQIN); for(i=0;i<10;i++); nand_write_addr(0x00); /* Column 0 */ nand_write_addr(0x00); nand_write_addr(_page&0xff); nand_write_addr((_page>>8)&0xff); nand_write_addr((_page>>16)&0xff); for(i=0;i<len;i++) { nand_write(*buffer++); } nand_write_cmd(NAND_CMD_PAGEPROG); nand_wait(); /* wait tPROG 200~500us; */ stat = read_nand_stats(); nand_cs_ds(); return stat; }
int K9F2G08_ReadTags(u32 block, u32 page, u8 *spare, int ofs, int len) { int i; u32 _page = block*PAGES_PER_BLOCK + page; /* NF_RSTECC(); */ /* Initialize ECC */ nand_cs_en(); nand_write_cmd(NAND_CMD_READ0); nand_write_addr((PAGE_DATA_SIZE+ofs)&0xff); nand_write_addr(((PAGE_DATA_SIZE+ofs)>>8)&0xff); nand_write_addr(_page&0xff); nand_write_addr((_page>>8)&0xff); nand_write_addr((_page>>16)&0xff); nand_write_cmd(NAND_CMD_READSTART); nand_wait(); /* Wait tR(max 12us) */ for(i=0;i<len;i++) { spare[i] = nand_read(); /* Read one page */ } nand_cs_ds(); return 1; }
int K9F2G08_ReadPage(u32 block, u32 page, u8 *buffer, int len, u8 *ecc) { int i; u32 _page = block*PAGES_PER_BLOCK + page; /* NF_RSTECC(); */ /* Initialize ECC*/ nand_cs_en(); nand_write_cmd(NAND_CMD_READ0); /* Read command */ nand_write_addr(0x00); /* Column = 0 */ nand_write_addr(0x00); nand_write_addr(_page&0xff); nand_write_addr((_page>>8)&0xff); nand_write_addr((_page>>16)&0xff); nand_write_cmd(NAND_CMD_READSTART); nand_wait(); /* Wait tR(max 12us) */ for(i=0;i<len;i++) { buffer[i] = nand_read(); /* Read one page */ } nand_cs_ds(); return 1; }
/* * mark a block is bad * return 0 if ok, 1:fail */ int K9F2G08_Mark_badblk(u32 block) { u8 stat; u32 _page = block*PAGES_PER_BLOCK; nand_cs_en(); nand_write_cmd(NAND_CMD_SEQIN); /* Write 1st command */ nand_write_addr(PAGE_DATA_SIZE & 0xff);/* The mark of bad block */ nand_write_addr((PAGE_DATA_SIZE>>8)&0xff); nand_write_addr(_page&0xff); /* marked 1th spare array */ nand_write_addr((_page>>8)&0xff); /* in the 1st page. */ nand_write_addr((_page>>16)&0xff); nand_write(0x00); /* 0x00 is commendatory make of the bad block. */ nand_write_cmd(NAND_CMD_PAGEPROG); /* Write 2nd command */ nand_wait(); /* Wait tPROG(200~500us) */ stat = read_nand_stats(); nand_cs_ds(); return stat; }
static void nand_reset(){ int i; nand_select(); NFCMD=NAND_CMD_RESET; for(i=0;i<10;i++); nand_wait(); nand_deselect(); }
void K9F2G08_Reset(void) { nand_cs_en(); nand_write_cmd(0xFF); /* reset command */ nand_wait(); /* wait 200~500us */ nand_cs_ds(); K9F2G08_Init(); }
/* *erase a block *return 0,successful *return 1,error */ int K9F2G08_EraseBlock(u32 block) { int stat; u32 _page = block*PAGES_PER_BLOCK; nand_cs_en(); nand_write_cmd(NAND_CMD_ERASE1); /* Erase one block 1st command */ nand_write_addr(_page&0xff); /* Page number=0 */ nand_write_addr((_page>>8)&0xff); nand_write_addr((_page>>16)&0xff); nand_write_cmd(NAND_CMD_ERASE2); /* Erase one blcok 2nd command */ nand_wait(); /* Wait tBERS max 3ms. */ stat = read_nand_stats(); nand_cs_ds(); return stat; }
int K9F2G08_WriteTags(u32 block, u32 page, const u8 *spare, int ofs, int len) { int i,stat; u32 _page = block*PAGES_PER_BLOCK + page; /* nand_Init_ECC(); */ /* Initialize ECC */ nand_cs_en(); nand_write_cmd(NAND_CMD_SEQIN); for(i=0;i<10;i++); nand_write_addr((PAGE_DATA_SIZE+ofs)&0xff); nand_write_addr(((PAGE_DATA_SIZE+ofs)>>8)&0xff); nand_write_addr(_page&0xff); nand_write_addr((_page>>8)&0xff); nand_write_addr((_page>>16)&0xff); for(i=0;i<len;i++) { nand_write(*spare++); } nand_write_cmd(NAND_CMD_PAGEPROG); nand_wait(); /* wait tPROG 200~500us; */ stat = read_nand_stats(); if(!stat) /* Page write error */ { nand_cs_ds(); return 0; } else { nand_cs_ds(); return 1; } }
static void nand_load(unsigned int offs, int uboot_size, uchar *dst) { fsl_lbus_t *regs = (fsl_lbus_t *)(CONFIG_SYS_IMMR + 0x5000); uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE; int large = in_be32(®s->bank[0].or) & OR_FCM_PGS; int block_shift = large ? 17 : 14; int block_size = 1 << block_shift; int page_size = large ? 2048 : 512; int bad_marker = large ? page_size + 0 : page_size + 5; int fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT) | 2; int pos = 0; if (offs & (block_size - 1)) { puts("bad offset\n"); for (;;); } if (large) { fmr |= FMR_ECCM; out_be32(®s->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) | (NAND_CMD_READSTART << FCR_CMD1_SHIFT)); out_be32(®s->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) | (FIR_OP_CA << FIR_OP1_SHIFT) | (FIR_OP_PA << FIR_OP2_SHIFT) | (FIR_OP_CW1 << FIR_OP3_SHIFT) | (FIR_OP_RBW << FIR_OP4_SHIFT)); } else { out_be32(®s->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT); out_be32(®s->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) | (FIR_OP_CA << FIR_OP1_SHIFT) | (FIR_OP_PA << FIR_OP2_SHIFT) | (FIR_OP_RBW << FIR_OP3_SHIFT)); } out_be32(®s->fbcr, 0); clrsetbits_be32(®s->bank[0].br, BR_DECC, BR_DECC_CHK_GEN); while (pos < uboot_size) { int i = 0; out_be32(®s->fbar, offs >> block_shift); do { int j; unsigned int page_offs = (offs & (block_size - 1)) << 1; out_be32(®s->ltesr, ~0); out_be32(®s->lteatr, 0); out_be32(®s->fpar, page_offs); out_be32(®s->fmr, fmr); out_be32(®s->lsor, 0); nand_wait(); page_offs %= WINDOW_SIZE; /* * If either of the first two pages are marked bad, * continue to the next block. */ if (i++ < 2 && buf[page_offs + bad_marker] != 0xff) { puts("skipping\n"); offs = (offs + block_size) & ~(block_size - 1); pos &= ~(block_size - 1); break; } for (j = 0; j < page_size; j++) dst[pos + j] = buf[page_offs + j]; pos += page_size; offs += page_size; } while ((offs & (block_size - 1)) && (pos < uboot_size)); } }