diff options
Diffstat (limited to 'packages/u-boot/u-boot-1.3.1/mpc8313e-rdb-nand.patch')
-rw-r--r-- | packages/u-boot/u-boot-1.3.1/mpc8313e-rdb-nand.patch | 895 |
1 files changed, 0 insertions, 895 deletions
diff --git a/packages/u-boot/u-boot-1.3.1/mpc8313e-rdb-nand.patch b/packages/u-boot/u-boot-1.3.1/mpc8313e-rdb-nand.patch deleted file mode 100644 index e653b75fb9..0000000000 --- a/packages/u-boot/u-boot-1.3.1/mpc8313e-rdb-nand.patch +++ /dev/null @@ -1,895 +0,0 @@ -diff -urN u-boot-1.3.1.orig/board/freescale/mpc8313erdb/Makefile u-boot-1.3.1/board/freescale/mpc8313erdb/Makefile ---- u-boot-1.3.1.orig/board/freescale/mpc8313erdb/Makefile 2007-12-06 10:21:19.000000000 +0100 -+++ u-boot-1.3.1/board/freescale/mpc8313erdb/Makefile 2008-01-31 17:35:43.000000000 +0100 -@@ -25,7 +25,7 @@ - - LIB = $(obj)lib$(BOARD).a - --COBJS := $(BOARD).o sdram.o -+COBJS := $(BOARD).o sdram.o nand.o - - SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) - OBJS := $(addprefix $(obj),$(COBJS)) -diff -urN u-boot-1.3.1.orig/board/freescale/mpc8313erdb/nand.c u-boot-1.3.1/board/freescale/mpc8313erdb/nand.c ---- u-boot-1.3.1.orig/board/freescale/mpc8313erdb/nand.c 1970-01-01 01:00:00.000000000 +0100 -+++ u-boot-1.3.1/board/freescale/mpc8313erdb/nand.c 2008-01-31 17:35:26.000000000 +0100 -@@ -0,0 +1,868 @@ -+/* -+ * Copyright (C) Freescale Semiconductor, Inc. 2006. -+ * -+ * Initialized by Nick.Spence@freescale.com -+ * Wilson.Lo@freescale.com -+ * -+ * See file CREDITS for list of people who contributed to this -+ * project. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+ -+#include <common.h> -+ -+#if defined(CONFIG_CMD_NAND) -+#if defined(CFG_NAND_LEGACY) -+ #error "U-Boot legacy NAND commands not supported." -+#else -+ -+#include <malloc.h> -+#include <asm/errno.h> -+#include <nand.h> -+ -+#undef CFG_FCM_DEBUG -+#define CFG_FCM_DEBUG_LVL 1 -+#ifdef CFG_FCM_DEBUG -+#define FCM_DEBUG(n, args...) \ -+ do { \ -+ if (n <= (CFG_FCM_DEBUG_LVL + 0)) \ -+ printf(args); \ -+ } while(0) -+#else /* CONFIG_FCM_DEBUG */ -+#define FCM_DEBUG(n, args...) do { } while(0) -+#endif -+ -+#define MIN(x, y) ((x < y) ? x : y) -+ -+#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ -+ -+#define FCM_TIMEOUT_USECS 100000 /* Maximum number of uSecs to wait for FCM */ -+ -+/* Private structure holding NAND Flash device specific information */ -+struct fcm_nand { -+ int bank; /* Chip select bank number */ -+ unsigned int base; /* Chip select base address */ -+ int pgs; /* NAND page size */ -+ int oobbuf; /* Pointer to OOB block */ -+ unsigned int page; /* Last page written to / read from */ -+ unsigned int fmr; /* FCM Flash Mode Register value */ -+ unsigned int mdr; /* UPM/FCM Data Register value */ -+ unsigned int use_mdr; /* Non zero if the MDR is to be set */ -+ u_char *addr; /* Address of assigned FCM buffer */ -+ unsigned int read_bytes; /* Number of bytes read during command */ -+ unsigned int index; /* Pointer to next byte to 'read' */ -+ unsigned int req_bytes; /* Number of bytes read if command ok */ -+ unsigned int req_index; /* New read index if command ok */ -+ unsigned int status; /* status read from LTESR after last op*/ -+}; -+ -+ -+/* These map to the positions used by the FCM hardware ECC generator */ -+ -+/* Small Page FLASH with FMR[ECCM] = 0 */ -+static struct nand_oobinfo fcm_oob_sp_eccm0 = { /* TODO */ -+ .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */ -+ .eccbytes = 3, -+ .eccpos = {6, 7, 8}, -+ .oobfree = { {0, 5}, {9, 7} } -+}; -+ -+/* Small Page FLASH with FMR[ECCM] = 1 */ -+static struct nand_oobinfo fcm_oob_sp_eccm1 = { /* TODO */ -+ .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */ -+ .eccbytes = 3, -+ .eccpos = {8, 9, 10}, -+ .oobfree = { {0, 5}, {6, 2}, {11, 5} } -+}; -+ -+/* Large Page FLASH with FMR[ECCM] = 0 */ -+static struct nand_oobinfo fcm_oob_lp_eccm0 = { -+ .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */ -+ .eccbytes = 12, -+ .eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56}, -+ .oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} } -+}; -+ -+/* Large Page FLASH with FMR[ECCM] = 1 */ -+static struct nand_oobinfo fcm_oob_lp_eccm1 = { -+ .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */ -+ .eccbytes = 12, -+ .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, -+ .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} } -+}; -+ -+/* -+ * execute FCM command and wait for it to complete -+ */ -+static int fcm_run_command(struct mtd_info *mtd) -+{ -+ volatile immap_t *im = (immap_t *) CFG_IMMR; -+ volatile lbus83xx_t *lbc= &im->lbus; -+ register struct nand_chip *this = mtd->priv; -+ struct fcm_nand *fcm = this->priv; -+ long long end_tick; -+ -+ /* Setup the FMR[OP] to execute without write protection */ -+ lbc->fmr = fcm->fmr | 3; -+ if (fcm->use_mdr) -+ lbc->mdr = fcm->mdr; -+ -+ FCM_DEBUG(5,"fcm_run_command: fmr= %08X fir= %08X fcr= %08X\n", -+ lbc->fmr, lbc->fir, lbc->fcr); -+ FCM_DEBUG(5,"fcm_run_command: fbar=%08X fpar=%08X fbcr=%08X bank=%d\n", -+ lbc->fbar, lbc->fpar, lbc->fbcr, fcm->bank); -+ -+ /* clear event registers */ -+ lbc->lteatr = 0; -+ lbc->ltesr |= (LTESR_FCT | LTESR_PAR | LTESR_CC); -+ -+ /* execute special operation */ -+ lbc->lsor = fcm->bank; -+ -+ /* wait for FCM complete flag or timeout */ -+ fcm->status = 0; -+ end_tick = usec2ticks(FCM_TIMEOUT_USECS) + get_ticks(); -+ -+ while (end_tick > get_ticks()) { -+ if (lbc->ltesr & LTESR_CC) { -+ fcm->status = lbc->ltesr & -+ (LTESR_FCT | LTESR_PAR | LTESR_CC); -+ break; -+ } -+ } -+ -+ /* store mdr value in case it was needed */ -+ if (fcm->use_mdr) -+ fcm->mdr = lbc->mdr; -+ -+ fcm->use_mdr = 0; -+ -+ FCM_DEBUG(5,"fcm_run_command: stat=%08X mdr= %08X fmr= %08X\n", -+ fcm->status, fcm->mdr, lbc->fmr); -+ -+ /* if the operation completed ok then set the read buffer pointers */ -+ if (fcm->status == LTESR_CC) { -+ fcm->read_bytes = fcm->req_bytes; -+ fcm->index = fcm->req_index; -+ return 0; -+ } -+ -+ return -1; -+} -+ -+/* -+ * Set up the FCM hardware block and page address fields, and the fcm -+ * structure addr field to point to the correct FCM buffer in memory -+ */ -+static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) -+{ -+ volatile immap_t *im = (immap_t *) CFG_IMMR; -+ volatile lbus83xx_t *lbc= &im->lbus; -+ register struct nand_chip *this = mtd->priv; -+ struct fcm_nand *fcm = this->priv; -+ int buf_num; -+ -+ fcm->page = page_addr; -+ -+ lbc->fbar = page_addr >> (this->phys_erase_shift - this->page_shift); -+ if (fcm->pgs) { -+ lbc->fpar = ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) | -+ ( oob ? FPAR_LP_MS : 0) | -+ column; -+ buf_num = (page_addr & 1) << 2; -+ } else { -+ lbc->fpar = ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) | -+ ( oob ? FPAR_SP_MS : 0) | -+ column; -+ buf_num = page_addr & 7; -+ } -+ fcm->addr = (unsigned char*)(fcm->base + (buf_num * 1024)); -+ -+ /* for OOB data point to the second half of the buffer */ -+ if (oob) { -+ fcm->addr += (fcm->pgs ? 2048 : 512); -+ } -+} -+ -+/* not required for FCM */ -+static void fcm_hwcontrol(struct mtd_info *mtdinfo, int cmd) -+{ -+ return; -+} -+ -+ -+/* -+ * FCM does not support 16 bit data busses -+ */ -+static u16 fcm_read_word(struct mtd_info *mtd) -+{ -+ printf("fcm_read_word: UNIMPLEMENTED.\n"); -+ return 0; -+} -+static void fcm_write_word(struct mtd_info *mtd, u16 word) -+{ -+ printf("fcm_write_word: UNIMPLEMENTED.\n"); -+} -+ -+/* -+ * Write buf to the FCM Controller Data Buffer -+ */ -+static void fcm_write_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ register struct nand_chip *this = mtd->priv; -+ struct fcm_nand *fcm = this->priv; -+ -+ FCM_DEBUG(3,"fcm_write_buf: writing %d bytes starting with 0x%x" -+ " at %d.\n", len, *((unsigned long*) buf), fcm->index); -+ -+ /* If armed catch the address of the OOB buffer so that it can be */ -+ /* updated with the real signature after the program comletes */ -+ if (!fcm->oobbuf) -+ fcm->oobbuf = (int) buf; -+ -+ /* copy the data into the FCM hardware buffer and update the index */ -+ memcpy(&(fcm->addr[fcm->index]), buf, len); -+ fcm->index += len; -+ return; -+} -+ -+ -+/* -+ * FCM does not support individual writes. Instead these are either commands -+ * or data being written, both of which are handled through the cmdfunc -+ * handler. -+ */ -+static void fcm_write_byte(struct mtd_info *mtd, u_char byte) -+{ -+ printf("fcm_write_byte: UNIMPLEMENTED.\n"); -+} -+ -+/* -+ * read a byte from either the FCM hardware buffer if it has any data left -+ * otherwise issue a command to read a single byte. -+ */ -+static u_char fcm_read_byte(struct mtd_info *mtd) -+{ -+ volatile immap_t *im = (immap_t *) CFG_IMMR; -+ volatile lbus83xx_t *lbc= &im->lbus; -+ register struct nand_chip *this = mtd->priv; -+ struct fcm_nand *fcm = this->priv; -+ unsigned char byte; -+ -+ /* If there are still bytes in the FCM then use the next byte */ -+ if(fcm->index < fcm->read_bytes) { -+ byte = fcm->addr[(fcm->index)++]; -+ FCM_DEBUG(4,"fcm_read_byte: byte %u (%02X): %d of %d.\n", -+ byte, byte, fcm->index-1, fcm->read_bytes); -+ } else { -+ /* otherwise issue a command to read 1 byte */ -+ lbc->fir = (FIR_OP_RSW << FIR_OP0_SHIFT); -+ fcm->use_mdr = 1; -+ fcm->read_bytes = 0; -+ fcm->index = 0; -+ fcm->req_bytes = 0; -+ fcm->req_index = 0; -+ byte = fcm_run_command(mtd) ? ERR_BYTE : fcm->mdr & 0xff; -+ FCM_DEBUG(4,"fcm_read_byte: byte %u (%02X) from bus.\n", -+ byte, byte); -+ } -+ -+ return byte; -+} -+ -+ -+/* -+ * Read from the FCM Controller Data Buffer -+ */ -+static void fcm_read_buf(struct mtd_info *mtd, u_char* buf, int len) -+{ -+ volatile immap_t *im = (immap_t *) CFG_IMMR; -+ volatile lbus83xx_t *lbc= &im->lbus; -+ register struct nand_chip *this = mtd->priv; -+ struct fcm_nand *fcm = this->priv; -+ int i; -+ int rest; -+ -+ FCM_DEBUG(3,"fcm_read_buf: reading %d bytes.\n", len); -+ -+ /* If last read failed then return error bytes */ -+ if (fcm->status != LTESR_CC) { -+ /* just keep copying bytes so that the oob works */ -+ memcpy(buf, &(fcm->addr[(fcm->index)]), len); -+ fcm->index += len; -+ } -+ else -+ { -+ /* see how much is still in the FCM buffer */ -+ i = min(len, (fcm->read_bytes - fcm->index)); -+ rest = i - len; -+ len = i; -+ -+ memcpy(buf, &(fcm->addr[(fcm->index)]), len); -+ fcm->index += len; -+ -+ /* If more data is needed then issue another block read */ -+ if (rest) { -+ FCM_DEBUG(3,"fcm_read_buf: getting %d more bytes.\n", -+ rest); -+ buf += len; -+ lbc->fir = (FIR_OP_RBW << FIR_OP0_SHIFT); -+ set_addr(mtd, 0, 0, 0); -+ lbc->fbcr = rest; -+ fcm->req_bytes = lbc->fbcr; -+ fcm->req_index = 0; -+ fcm->use_mdr = 0; -+ if (!fcm_run_command(mtd)) -+ fcm_read_buf(mtd, buf, rest); -+ else -+ memcpy(buf, fcm->addr, rest); -+ } -+ } -+ return; -+} -+ -+ -+/* -+ * Verify buffer against the FCM Controller Data Buffer -+ */ -+static int fcm_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ volatile immap_t *im = (immap_t *) CFG_IMMR; -+ volatile lbus83xx_t *lbc= &im->lbus; -+ register struct nand_chip *this = mtd->priv; -+ struct fcm_nand *fcm = this->priv; -+ int i; -+ int rest; -+ -+ FCM_DEBUG(3,"fcm_verify_buf: checking %d bytes starting with 0x%02x.\n", -+ len, *((unsigned long*) buf)); -+ /* If last read failed then return error bytes */ -+ if (fcm->status != LTESR_CC) { -+ return EFAULT; -+ } -+ -+ /* see how much is still in the FCM buffer */ -+ i = min(len, (fcm->read_bytes - fcm->index)); -+ rest = i - len; -+ len = i; -+ -+ if (memcmp(buf, &(fcm->addr[(fcm->index)]), len)) { -+ return EFAULT; -+ } -+ -+ fcm->index += len; -+ if (rest) { -+ FCM_DEBUG(3,"fcm_verify_buf: getting %d more bytes.\n", rest); -+ buf += len; -+ lbc->fir = (FIR_OP_RBW << FIR_OP0_SHIFT); -+ set_addr(mtd, 0, 0, 0); -+ lbc->fbcr = rest; -+ fcm->req_bytes = lbc->fbcr; -+ fcm->req_index = 0; -+ fcm->use_mdr = 0; -+ if (fcm_run_command(mtd)) -+ return EFAULT; -+ return fcm_verify_buf(mtd, buf, rest); -+ -+ } -+ return 0; -+} -+ -+/* this function is called after Program and Erase Operations to -+ * check for success or failure */ -+static int fcm_wait(struct mtd_info *mtd, struct nand_chip *this, int state) -+{ -+ volatile immap_t *im = (immap_t *) CFG_IMMR; -+ volatile lbus83xx_t *lbc= &im->lbus; -+ struct fcm_nand *fcm = this->priv; -+ -+ if (fcm->status != LTESR_CC) { -+ return(0x1); /* Status Read error */ -+ } -+ -+ /* Use READ_STATUS command, but wait for the device to be ready */ -+ fcm->use_mdr = 0; -+ fcm->req_index = 0; -+ fcm->read_bytes = 0; -+ fcm->index = 0; -+ fcm->oobbuf = -1; -+ lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) | -+ (FIR_OP_RBW << FIR_OP1_SHIFT); -+ lbc->fcr = (NAND_CMD_STATUS << FCR_CMD0_SHIFT); -+ set_addr(mtd, 0, 0, 0); -+ lbc->fbcr = 1; -+ fcm->req_bytes = lbc->fbcr; -+ fcm_run_command(mtd); -+ if (fcm->status != LTESR_CC) { -+ return(0x1); /* Status Read error */ -+ } -+ return this->read_byte(mtd); -+} -+ -+ -+/* cmdfunc send commands to the FCM */ -+static void fcm_cmdfunc(struct mtd_info *mtd, unsigned command, -+ int column, int page_addr) -+{ -+ volatile immap_t *im = (immap_t *) CFG_IMMR; -+ volatile lbus83xx_t *lbc= &im->lbus; -+ register struct nand_chip *this = mtd->priv; -+ struct fcm_nand *fcm = this->priv; -+ -+ fcm->use_mdr = 0; -+ fcm->req_index = 0; -+ -+ /* clear the read buffer */ -+ fcm->read_bytes = 0; -+ if (command != NAND_CMD_PAGEPROG) { -+ fcm->index = 0; -+ fcm->oobbuf = -1; -+ } -+ -+ switch (command) { -+ /* READ0 and READ1 read the entire buffer to use hardware ECC */ -+ case NAND_CMD_READ1: -+ FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_READ1, page_addr:" -+ " 0x%x, column: 0x%x.\n", page_addr, column); -+ fcm->req_index = column + 256; -+ goto read0; -+ case NAND_CMD_READ0: -+ FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_READ0, page_addr:" -+ " 0x%x, column: 0x%x.\n", page_addr, column); -+ fcm->req_index = column; -+read0: -+ if (fcm->pgs) { -+ lbc->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 { -+ lbc->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); -+ } -+ lbc->fcr = (NAND_CMD_READ0 << FCR_CMD0_SHIFT) | -+ (NAND_CMD_READSTART << FCR_CMD1_SHIFT); -+ lbc->fbcr = 0; /* read entire page to enable ECC */ -+ set_addr(mtd, 0, page_addr, 0); -+ fcm->req_bytes = mtd->oobblock + mtd->oobsize; -+ goto write_cmd2; -+ /* READOOB read only the OOB becasue no ECC is performed */ -+ case NAND_CMD_READOOB: -+ FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_READOOB, page_addr:" -+ " 0x%x, column: 0x%x.\n", page_addr, column); -+ if (fcm->pgs) { -+ lbc->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); -+ lbc->fcr = (NAND_CMD_READ0 << FCR_CMD0_SHIFT) | -+ (NAND_CMD_READSTART << FCR_CMD1_SHIFT); -+ } else { -+ lbc->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); -+ lbc->fcr = (NAND_CMD_READOOB << FCR_CMD0_SHIFT); -+ } -+ lbc->fbcr = mtd->oobsize - column; -+ set_addr(mtd, column, page_addr, 1); -+ goto write_cmd1; -+ /* READID must read all 5 possible bytes while CEB is active */ -+ case NAND_CMD_READID: -+ FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_READID.\n"); -+ lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) | -+ (FIR_OP_UA << FIR_OP1_SHIFT) | -+ (FIR_OP_RBW << FIR_OP2_SHIFT); -+ lbc->fcr = (NAND_CMD_READID << FCR_CMD0_SHIFT); -+ lbc->fbcr = 5; /* 5 bytes for manuf, device and exts */ -+ fcm->use_mdr = 1; -+ fcm->mdr = 0; -+ goto write_cmd0; -+ /* ERASE1 stores the block and page address */ -+ case NAND_CMD_ERASE1: -+ FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_ERASE1, page_addr:" -+ " 0x%x.\n", page_addr); -+ set_addr(mtd, 0, page_addr, 0); -+ goto end; -+ /* ERASE2 uses the block and page address from ERASE1 */ -+ case NAND_CMD_ERASE2: -+ FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_ERASE2.\n"); -+ lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) | -+ (FIR_OP_PA << FIR_OP1_SHIFT) | -+ (FIR_OP_CM1 << FIR_OP2_SHIFT); -+ lbc->fcr = (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) | -+ (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT); -+ lbc->fbcr = 0; -+ goto write_cmd1; -+ /* SEQIN sets up the addr buffer and all registers except the length */ -+ case NAND_CMD_SEQIN: -+ FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, page_addr:" -+ " 0x%x, column: 0x%x.\n", page_addr, column); -+ if (column == 0) { -+ lbc->fbcr = 0; /* write entire page to enable ECC */ -+ } else { -+ lbc->fbcr = 1; /* mark as partial page so no HW ECC */ -+ } -+ if (fcm->pgs) { -+ /* always use READ0 for large page devices */ -+ lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) | -+ (FIR_OP_CA << FIR_OP1_SHIFT) | -+ (FIR_OP_PA << FIR_OP2_SHIFT) | -+ (FIR_OP_WB << FIR_OP3_SHIFT) | -+ (FIR_OP_CW1 << FIR_OP4_SHIFT); -+ lbc->fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) | -+ (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT); -+ set_addr(mtd, column, page_addr, 0); -+ } else { -+ lbc->fir = (FIR_OP_CW0 << FIR_OP0_SHIFT) | -+ (FIR_OP_CM2 << FIR_OP1_SHIFT) | -+ (FIR_OP_CA << FIR_OP2_SHIFT) | -+ (FIR_OP_PA << FIR_OP3_SHIFT) | -+ (FIR_OP_WB << FIR_OP4_SHIFT) | -+ (FIR_OP_CW1 << FIR_OP5_SHIFT); -+ if (column >= mtd->oobblock) { -+ /* OOB area --> READOOB */ -+ column -= mtd->oobblock; -+ lbc->fcr = (NAND_CMD_READOOB << FCR_CMD0_SHIFT) -+ | (NAND_CMD_PAGEPROG<< FCR_CMD1_SHIFT) -+ | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT); -+ set_addr(mtd, column, page_addr, 1); -+ } else if (column < 256) { -+ /* First 256 bytes --> READ0 */ -+ lbc->fcr = (NAND_CMD_READ0 << FCR_CMD0_SHIFT) -+ | (NAND_CMD_PAGEPROG<< FCR_CMD1_SHIFT) -+ | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT); -+ set_addr(mtd, column, page_addr, 0); -+ } else { -+ /* Second 256 bytes --> READ1 */ -+ column -= 256; -+ lbc->fcr = (NAND_CMD_READ1 << FCR_CMD0_SHIFT) -+ | (NAND_CMD_PAGEPROG<< FCR_CMD1_SHIFT) -+ | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT); -+ set_addr(mtd, column, page_addr, 0); -+ } -+ } -+ goto end; -+ /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ -+ case NAND_CMD_PAGEPROG: -+ FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_PAGEPROG" -+ " writing %d bytes.\n",fcm->index); -+ /* if the write did not start at 0 or is not a full page */ -+ /* then set the exact length, otherwise use a full page */ -+ /* write so the HW generates the ECC. */ -+ if (lbc->fbcr || -+ (fcm->index != (mtd->oobblock + mtd->oobsize))) -+ lbc->fbcr = fcm->index; -+ fcm->req_bytes = 0; -+ goto write_cmd2; -+ /* CMD_STATUS must read the status byte while CEB is active */ -+ /* Note - it does not wait for the ready line */ -+ case NAND_CMD_STATUS: -+ FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_STATUS.\n"); -+ lbc->fir = (FIR_OP_CM0 << FIR_OP0_SHIFT) | -+ (FIR_OP_RBW << FIR_OP1_SHIFT); -+ lbc->fcr = (NAND_CMD_STATUS << FCR_CMD0_SHIFT); -+ lbc->fbcr = 1; -+ goto write_cmd0; -+ /* RESET without waiting for the ready line */ -+ case NAND_CMD_RESET: -+ FCM_DEBUG(2,"fcm_cmdfunc: NAND_CMD_RESET.\n"); -+ lbc->fir = (FIR_OP_CM0 << FIR_OP0_SHIFT); -+ lbc->fcr = (NAND_CMD_RESET << FCR_CMD0_SHIFT); -+ lbc->fbcr = 0; -+ goto write_cmd0; -+ default: -+ printk("fcm_cmdfunc: error, unsupported command.\n"); -+ goto end; -+ } -+ -+ /* Short cuts fall through to save code */ -+ write_cmd0: -+ set_addr(mtd, 0, 0, 0); -+ write_cmd1: -+ fcm->req_bytes = lbc->fbcr; -+ write_cmd2: -+ fcm_run_command(mtd); -+ -+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE -+ /* if we wrote a page then read back the oob to get the ECC */ -+ if ((command == NAND_CMD_PAGEPROG) && -+ (this->eccmode > NAND_ECC_SOFT) && -+ (lbc->fbcr == 0) && -+ (fcm->oobbuf != 0) && -+ (fcm->oobbuf != -1)) { -+ int i; -+ uint *oob_config; -+ unsigned char *oob_buf; -+ -+ i = fcm->page; -+ oob_buf = (unsigned char*) fcm->oobbuf; -+ oob_config = this->autooob->eccpos; -+ -+ /* wait for the write to complete and check it passed */ -+ if (!(this->waitfunc(mtd, this, FL_WRITING) & 0x01)) { -+ /* read back the OOB */ -+ fcm_cmdfunc(mtd, NAND_CMD_READOOB, 0, i); -+ /* if it succeeded then copy the ECC bytes */ -+ if (fcm->status == LTESR_CC) { -+ for (i = 0; i < this->eccbytes; i++) { -+ oob_buf[oob_config[i]] = -+ fcm->addr[oob_config[i]]; -+ } -+ } -+ } -+ } -+#endif -+ -+ end: -+ return; -+} -+ -+/* -+ * fcm_enable_hwecc - start ECC generation -+ */ -+static void fcm_enable_hwecc(struct mtd_info *mtd, int mode) -+{ -+ return; -+} -+ -+/* -+ * fcm_calculate_ecc - Calculate the ECC bytes -+ * This is done by hardware during the write process, so we use this -+ * to arm the oob buf capture on the next write_buf() call. The ECC bytes -+ * only need to be captured if CONFIG_MTD_NAND_VERIFY_WRITE is defined which -+ * reads back the pages and checks they match the data and oob buffers. -+ */ -+static int fcm_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) -+{ -+ register struct nand_chip *this = mtd->priv; -+ struct fcm_nand *fcm = this->priv; -+ -+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE -+ /* arm capture of oob buf ptr on next write_buf */ -+ fcm->oobbuf = 0; -+#endif -+ return 0; -+} -+ -+/* -+ * fcm_correct_data - Detect and correct bit error(s) -+ * The detection and correction is done automatically by the hardware, -+ * if the complete page was read. If the status code is okay then there -+ * was no error, otherwise we return an error code indicating an uncorrectable -+ * error. -+ */ -+static int fcm_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) -+{ -+ register struct nand_chip *this = mtd->priv; -+ struct fcm_nand *fcm = this->priv; -+ -+ /* No errors */ -+ if (fcm->status == LTESR_CC) -+ return 0; -+ -+ return -1; /* uncorrectable error */ -+} -+ -+ -+ -+/* -+ * Dummy scan_bbt to complete setup of the FMR based on NAND size -+ */ -+static int fcm_scan_bbt (struct mtd_info *mtd) -+{ -+ volatile immap_t *im = (immap_t *) CFG_IMMR; -+ volatile lbus83xx_t *lbc= &im->lbus; -+ register struct nand_chip *this = mtd->priv; -+ struct fcm_nand *fcm = this->priv; -+ unsigned int i; -+ unsigned int al; -+ -+ if (!fcm) { -+ printk (KERN_ERR "fcm_scan_bbt():" \ -+ " Failed to allocate chip specific data structure\n"); -+ return -1; -+ } -+ -+ /* calculate FMR Address Length field */ -+ al = 0; -+ for (i = this->pagemask >> 16; i ; i >>= 8) { -+ al++; -+ } -+ -+ /* add to ECCM mode set in fcm_init */ -+ fcm->fmr |= 12 << FMR_CWTO_SHIFT | /* Timeout > 12 mSecs */ -+ al << FMR_AL_SHIFT; -+ -+ FCM_DEBUG(1,"fcm_init: nand->options = %08X\n", this->options); -+ FCM_DEBUG(1,"fcm_init: nand->numchips = %10d\n", this->numchips); -+ FCM_DEBUG(1,"fcm_init: nand->chipsize = %10d\n", this->chipsize); -+ FCM_DEBUG(1,"fcm_init: nand->pagemask = %10X\n", this->pagemask); -+ FCM_DEBUG(1,"fcm_init: nand->eccmode = %10d\n", this->eccmode ); -+ FCM_DEBUG(1,"fcm_init: nand->eccsize = %10d\n", this->eccsize ); -+ FCM_DEBUG(1,"fcm_init: nand->eccbytes = %10d\n", this->eccbytes); -+ FCM_DEBUG(1,"fcm_init: nand->eccsteps = %10d\n", this->eccsteps); -+ FCM_DEBUG(1,"fcm_init: nand->chip_delay = %8d\n", this->chip_delay); -+ FCM_DEBUG(1,"fcm_init: nand->badblockpos = %7d\n", this->badblockpos); -+ FCM_DEBUG(1,"fcm_init: nand->chip_shift = %8d\n", this->chip_shift); -+ FCM_DEBUG(1,"fcm_init: nand->page_shift = %8d\n", this->page_shift); -+ FCM_DEBUG(1,"fcm_init: nand->phys_erase_shift = %2d\n", -+ this->phys_erase_shift); -+ FCM_DEBUG(1,"fcm_init: mtd->flags = %08X\n", mtd->flags); -+ FCM_DEBUG(1,"fcm_init: mtd->size = %10d\n", mtd->size); -+ FCM_DEBUG(1,"fcm_init: mtd->erasesize = %10d\n", mtd->erasesize); -+ FCM_DEBUG(1,"fcm_init: mtd->oobblock = %10d\n", mtd->oobblock); -+ FCM_DEBUG(1,"fcm_init: mtd->oobsize = %10d\n", mtd->oobsize); -+ FCM_DEBUG(1,"fcm_init: mtd->oobavail = %10d\n", mtd->oobavail); -+ FCM_DEBUG(1,"fcm_init: mtd->ecctype = %10d\n", mtd->ecctype); -+ FCM_DEBUG(1,"fcm_init: mtd->eccsize = %10d\n", mtd->eccsize); -+ -+ /* adjust Option Register and ECC to match Flash page size */ -+ if (mtd->oobblock == 512) -+ lbc->bank[fcm->bank].or &= ~(OR_FCM_PGS); -+ else if (mtd->oobblock == 2048) { -+ lbc->bank[fcm->bank].or |= OR_FCM_PGS; -+ /* adjust ecc setup if needed */ -+ if ( (lbc->bank[fcm->bank].br & BR_DECC) == BR_DECC_CHK_GEN) { -+ mtd->eccsize = 2048; -+ mtd->oobavail -= 9; -+ this->eccmode = NAND_ECC_HW12_2048; -+ this->eccsize = 2048; -+ this->eccbytes += 9; -+ this->eccsteps = 1; -+ this->autooob = (fcm->fmr & FMR_ECCM) ? -+ &fcm_oob_lp_eccm1 : &fcm_oob_lp_eccm0; -+ memcpy(&mtd->oobinfo, this->autooob, -+ sizeof(mtd->oobinfo)); -+ } -+ } -+ else { -+ printf("fcm_init: page size %d is not supported\n", -+ mtd->oobblock); -+ return -1; -+ } -+ fcm->pgs = (lbc->bank[fcm->bank].or>>OR_FCM_PGS_SHIFT) & 1; -+ -+ if (al > 2) { -+ printf("fcm_init: %d address bytes is not supported\n", al+2); -+ return -1; -+ } -+ -+ /* restore default scan_bbt function and call it */ -+ this->scan_bbt = nand_default_bbt; -+ return nand_default_bbt(mtd); -+} -+ -+/* -+ * Board-specific NAND initialization. The following members of the -+ * argument are board-specific (per include/linux/mtd/nand_new.h): -+ * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device -+ * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device -+ * - hwcontrol: hardwarespecific function for accesing control-lines -+ * - dev_ready: hardwarespecific function for accesing device ready/busy line -+ * - enable_hwecc: function to enable (reset) hardware ecc generator. Must -+ * only be provided if a hardware ECC is available -+ * - eccmode: mode of ecc, see defines -+ * - chip_delay: chip dependent delay for transfering data from array to -+ * read regs (tR) -+ * - options: various chip options. They can partly be set to inform -+ * nand_scan about special functionality. See the defines for further -+ * explanation -+ * Members with a "?" were not set in the merged testing-NAND branch, -+ * so they are not set here either. -+ */ -+int board_nand_init(struct nand_chip *nand) -+{ -+ volatile immap_t *im = (immap_t *) CFG_IMMR; -+ volatile lbus83xx_t *lbc= &im->lbus; -+ struct fcm_nand *fcm; -+ unsigned int bank; -+ -+ /* Enable FCM detection of timeouts, ECC errors and completion */ -+ lbc->ltedr &= ~(LTESR_FCT | LTESR_PAR | LTESR_CC); -+ -+ fcm = kmalloc (sizeof(struct fcm_nand), GFP_KERNEL); -+ if (!fcm) { -+ printk (KERN_ERR "board_nand_init():" \ -+ " Cannot allocate read buffer data structure\n"); -+ return; -+ } -+ -+ /* Find which chip select bank is being used for this device */ -+ for (bank=0; bank<8; bank++) { -+ if ( (lbc->bank[bank].br & BR_V) && -+ ( (lbc->bank[bank].br & BR_MSEL) == BR_MS_FCM ) && -+ ( (lbc->bank[bank].br & BR_BA) == -+ (lbc->bank[bank].or & OR_FCM_AM & -+ (unsigned int)(nand->IO_ADDR_R) ) ) ) { -+ fcm->bank = bank; -+// TODO fcm->fmr = FMR_ECCM; /* rest filled in later */ -+ fcm->fmr = 0; /* rest filled in later */ -+ fcm->read_bytes = 0; -+ fcm->index = 0; -+ fcm->pgs = (lbc->bank[bank].or>>OR_FCM_PGS_SHIFT) & 1; -+ fcm->base = lbc->bank[bank].br & BR_BA; -+ fcm->addr = (unsigned char*) (fcm->base); -+ nand->priv = fcm; -+ fcm->oobbuf = -1; -+ break; -+ } -+ } -+ -+ if (!nand->priv) { -+ printk (KERN_ERR "board_nand_init():" \ -+ " Could not find matching Chip Select\n"); -+ return -1; -+ } -+ -+ /* set up nand options */ -+ nand->options = 0; -+ /* set up function call table */ -+ nand->hwcontrol = fcm_hwcontrol; -+ nand->waitfunc = fcm_wait; -+ nand->read_byte = fcm_read_byte; -+ nand->write_byte = fcm_write_byte; -+ nand->read_word = fcm_read_word; -+ nand->write_word = fcm_write_word; -+ nand->read_buf = fcm_read_buf; -+ nand->verify_buf = fcm_verify_buf; -+ nand->write_buf = fcm_write_buf; -+ nand->cmdfunc = fcm_cmdfunc; -+ nand->scan_bbt = fcm_scan_bbt; -+ -+ /* If CS Base Register selects full hardware ECC then use it */ -+ if ( ( (lbc->bank[bank].br & BR_DECC) >> BR_DECC_SHIFT) == 2) { -+ /* put in small page settings and adjust later if needed */ -+ nand->eccmode = NAND_ECC_HW3_512; -+ nand->autooob = (fcm->fmr & FMR_ECCM) ? -+ &fcm_oob_sp_eccm1 : &fcm_oob_sp_eccm0; -+ nand->calculate_ecc = fcm_calculate_ecc; -+ nand->correct_data = fcm_correct_data; -+ nand->enable_hwecc = fcm_enable_hwecc; -+ } else { -+ /* otherwise fall back to default software ECC */ -+ nand->eccmode = NAND_ECC_SOFT; -+ } -+ return 0; -+} -+ -+#endif -+#endif -diff -urN u-boot-1.3.1.orig/include/configs/MPC8313ERDB.h u-boot-1.3.1/include/configs/MPC8313ERDB.h ---- u-boot-1.3.1.orig/include/configs/MPC8313ERDB.h 2007-12-06 10:21:19.000000000 +0100 -+++ u-boot-1.3.1/include/configs/MPC8313ERDB.h 2008-01-31 17:36:18.000000000 +0100 -@@ -360,6 +360,7 @@ - #define CONFIG_CMD_MII - #define CONFIG_CMD_DATE - #define CONFIG_CMD_PCI -+#define CONFIG_CMD_NAND - - #if defined(CFG_RAMBOOT) - #undef CONFIG_CMD_ENV |