Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
authorWolfgang Denk <wd@denx.de>
Tue, 4 Oct 2011 20:20:25 +0000 (22:20 +0200)
committerWolfgang Denk <wd@denx.de>
Tue, 4 Oct 2011 20:20:25 +0000 (22:20 +0200)
* 'master' of git://git.denx.de/u-boot-nand-flash:
  PPC: Fix socrates NAND problem
  PPC: Fix fsl_upm.c by renaming nand handling functions
  NAND: Make page, erase, oob size available via cmd_nand
  mtd: eLBC NAND: remove elbc_fcm_ctrl->oob_poi
  NAND: Add -y option to nand scrub command
  NAND: Add nand read.raw and write.raw commands
  NAND: Really ignore bad blocks when scrubbing
  spl, nand: add 4bit HW ecc oob first nand_read_page function
  mxc_nand: fix a problem writing more than 32MB
  mxc_nand: fixed some typos (cosmetic)
  nand: increase chip_delay in mv kirkwood nand driver

board/socrates/nand.c
common/cmd_nand.c
doc/README.nand
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsl_upm.c
drivers/mtd/nand/kirkwood_nand.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_util.c
include/linux/mtd/mtd.h
nand_spl/nand_boot.c

index 7d76f422224b227fe7a484bc313a98b394d405ac..823fe80d2ada9094883397f6450d58ce1e4e60a6 100644 (file)
 #include <asm/io.h>
 
 static int state;
-static void nand_write_byte(struct mtd_info *mtd, u_char byte);
-static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
-static u_char nand_read_byte(struct mtd_info *mtd);
-static u16 nand_read_word(struct mtd_info *mtd);
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
-static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
-static int nand_device_ready(struct mtd_info *mtdinfo);
+static void sc_nand_write_byte(struct mtd_info *mtd, u_char byte);
+static void sc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
+static u_char sc_nand_read_byte(struct mtd_info *mtd);
+static u16 sc_nand_read_word(struct mtd_info *mtd);
+static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
+static int sc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
+static int sc_nand_device_ready(struct mtd_info *mtdinfo);
 
 #define FPGA_NAND_CMD_MASK             (0x7 << 28)
 #define FPGA_NAND_CMD_COMMAND          (0x0 << 28)
@@ -47,22 +47,22 @@ static int nand_device_ready(struct mtd_info *mtdinfo);
 #define FPGA_NAND_DATA_SHIFT           16
 
 /**
- * nand_write_byte -  write one byte to the chip
+ * sc_nand_write_byte -  write one byte to the chip
  * @mtd:       MTD device structure
  * @byte:      pointer to data byte to write
  */
-static void nand_write_byte(struct mtd_info *mtd, u_char byte)
+static void sc_nand_write_byte(struct mtd_info *mtd, u_char byte)
 {
-       nand_write_buf(mtd, (const uchar *)&byte, sizeof(byte));
+       sc_nand_write_buf(mtd, (const uchar *)&byte, sizeof(byte));
 }
 
 /**
- * nand_write_buf -  write buffer to chip
+ * sc_nand_write_buf -  write buffer to chip
  * @mtd:       MTD device structure
  * @buf:       data buffer
  * @len:       number of bytes to write
  */
-static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static void sc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        int i;
        struct nand_chip *this = mtd->priv;
@@ -75,34 +75,34 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 
 
 /**
- * nand_read_byte -  read one byte from the chip
+ * sc_nand_read_byte -  read one byte from the chip
  * @mtd:       MTD device structure
  */
-static u_char nand_read_byte(struct mtd_info *mtd)
+static u_char sc_nand_read_byte(struct mtd_info *mtd)
 {
        u8 byte;
-       nand_read_buf(mtd, (uchar *)&byte, sizeof(byte));
+       sc_nand_read_buf(mtd, (uchar *)&byte, sizeof(byte));
        return byte;
 }
 
 /**
- * nand_read_word -  read one word from the chip
+ * sc_nand_read_word -  read one word from the chip
  * @mtd:       MTD device structure
  */
-static u16 nand_read_word(struct mtd_info *mtd)
+static u16 sc_nand_read_word(struct mtd_info *mtd)
 {
        u16 word;
-       nand_read_buf(mtd, (uchar *)&word, sizeof(word));
+       sc_nand_read_buf(mtd, (uchar *)&word, sizeof(word));
        return word;
 }
 
 /**
- * nand_read_buf -  read chip data into buffer
+ * sc_nand_read_buf -  read chip data into buffer
  * @mtd:       MTD device structure
  * @buf:       buffer to store date
  * @len:       number of bytes to read
  */
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
        int i;
        struct nand_chip *this = mtd->priv;
@@ -117,27 +117,27 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 }
 
 /**
- * nand_verify_buf -  Verify chip data against buffer
+ * sc_nand_verify_buf -  Verify chip data against buffer
  * @mtd:       MTD device structure
  * @buf:       buffer containing the data to compare
  * @len:       number of bytes to compare
  */
-static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static int sc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        int i;
 
        for (i = 0; i < len; i++) {
-               if (buf[i] != nand_read_byte(mtd));
+               if (buf[i] != sc_nand_read_byte(mtd));
                        return -EFAULT;
        }
        return 0;
 }
 
 /**
- * nand_device_ready - Check the NAND device is ready for next command.
+ * sc_nand_device_ready - Check the NAND device is ready for next command.
  * @mtd:       MTD device structure
  */
-static int nand_device_ready(struct mtd_info *mtdinfo)
+static int sc_nand_device_ready(struct mtd_info *mtdinfo)
 {
        struct nand_chip *this = mtdinfo->priv;
 
@@ -147,11 +147,11 @@ static int nand_device_ready(struct mtd_info *mtdinfo)
 }
 
 /**
- * nand_hwcontrol - NAND control functions wrapper.
+ * sc_nand_hwcontrol - NAND control functions wrapper.
  * @mtd:       MTD device structure
  * @cmd:       Command
  */
-static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
+static void sc_nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
 {
        if (ctrl & NAND_CTRL_CHANGE) {
                state &= ~(FPGA_NAND_CMD_MASK | FPGA_NAND_ENABLE);
@@ -178,19 +178,19 @@ static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
        }
 
        if (cmd != NAND_CMD_NONE)
-               nand_write_byte(mtdinfo, cmd);
+               sc_nand_write_byte(mtdinfo, cmd);
 }
 
 int board_nand_init(struct nand_chip *nand)
 {
-       nand->cmd_ctrl = nand_hwcontrol;
+       nand->cmd_ctrl = sc_nand_hwcontrol;
        nand->ecc.mode = NAND_ECC_SOFT;
-       nand->dev_ready = nand_device_ready;
-       nand->read_byte = nand_read_byte;
-       nand->read_word = nand_read_word;
-       nand->write_buf = nand_write_buf;
-       nand->read_buf = nand_read_buf;
-       nand->verify_buf = nand_verify_buf;
+       nand->dev_ready = sc_nand_device_ready;
+       nand->read_byte = sc_nand_read_byte;
+       nand->read_word = sc_nand_read_word;
+       nand->write_buf = sc_nand_write_buf;
+       nand->read_buf = sc_nand_read_buf;
+       nand->verify_buf = sc_nand_verify_buf;
 
        return 0;
 }
index 6edca7607f6a025e71ba847c327d40bc8f9af819..3e2edb8aaabd4cf1c8ff32f0f6575a039944e3ca 100644 (file)
@@ -362,15 +362,31 @@ usage:
 
 #endif
 
-static void nand_print_info(int idx)
+static void nand_print_and_set_info(int idx)
 {
        nand_info_t *nand = &nand_info[idx];
        struct nand_chip *chip = nand->priv;
+       const int bufsz = 32;
+       char buf[bufsz];
+
        printf("Device %d: ", idx);
        if (chip->numchips > 1)
                printf("%dx ", chip->numchips);
        printf("%s, sector size %u KiB\n",
               nand->name, nand->erasesize >> 10);
+       printf("  Page size  %8d b\n", nand->writesize);
+       printf("  OOB size   %8d b\n", nand->oobsize);
+       printf("  Erase size %8d b\n", nand->erasesize);
+
+       /* Set geometry info */
+       sprintf(buf, "%x", nand->writesize);
+       setenv("nand_writesize", buf);
+
+       sprintf(buf, "%x", nand->oobsize);
+       setenv("nand_oobsize", buf);
+
+       sprintf(buf, "%x", nand->erasesize);
+       setenv("nand_erasesize", buf);
 }
 
 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
@@ -407,7 +423,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                putc('\n');
                for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
                        if (nand_info[i].name)
-                               nand_print_info(i);
+                               nand_print_and_set_info(i);
                }
                return 0;
        }
@@ -418,7 +434,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                        if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
                                puts("no devices available\n");
                        else
-                               nand_print_info(dev);
+                               nand_print_and_set_info(dev);
                        return 0;
                }
 
@@ -464,10 +480,21 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                nand_erase_options_t opts;
                /* "clean" at index 2 means request to write cleanmarker */
                int clean = argc > 2 && !strcmp("clean", argv[2]);
-               int o = clean ? 3 : 2;
+               int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
+               int o = (clean || scrub_yes) ? 3 : 2;
                int scrub = !strncmp(cmd, "scrub", 5);
                int spread = 0;
                int args = 2;
+               const char *scrub_warn =
+                       "Warning: "
+                       "scrub option will erase all factory set bad blocks!\n"
+                       "         "
+                       "There is no reliable way to recover them.\n"
+                       "         "
+                       "Use this command only for testing purposes if you\n"
+                       "         "
+                       "are sure of what you are doing!\n"
+                       "\nReally scrub this NAND flash? <y/N>\n";
 
                if (cmd[5] != 0) {
                        if (!strcmp(&cmd[5], ".spread")) {
@@ -504,19 +531,12 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                opts.spread = spread;
 
                if (scrub) {
-                       puts("Warning: "
-                            "scrub option will erase all factory set "
-                            "bad blocks!\n"
-                            "         "
-                            "There is no reliable way to recover them.\n"
-                            "         "
-                            "Use this command only for testing purposes "
-                            "if you\n"
-                            "         "
-                            "are sure of what you are doing!\n"
-                            "\nReally scrub this NAND flash? <y/N>\n");
-
-                       if (getc() == 'y') {
+                       if (!scrub_yes)
+                               puts(scrub_warn);
+
+                       if (scrub_yes)
+                               opts.scrub = 1;
+                       else if (getc() == 'y') {
                                puts("y");
                                if (getc() == '\r')
                                        opts.scrub = 1;
@@ -598,6 +618,22 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                                .mode = MTD_OOB_RAW
                        };
 
+                       if (read)
+                               ret = nand->read_oob(nand, off, &ops);
+                       else
+                               ret = nand->write_oob(nand, off, &ops);
+               } else if (!strcmp(s, ".raw")) {
+                       /* Raw access */
+                       mtd_oob_ops_t ops = {
+                               .datbuf = (u8 *)addr,
+                               .oobbuf = ((u8 *)addr) + nand->writesize,
+                               .len = nand->writesize,
+                               .ooblen = nand->oobsize,
+                               .mode = MTD_OOB_RAW
+                       };
+
+                       rwsize = nand->writesize + nand->oobsize;
+
                        if (read)
                                ret = nand->read_oob(nand, off, &ops);
                        else
@@ -695,6 +731,9 @@ U_BOOT_CMD(
        "nand write - addr off|partition size\n"
        "    read/write 'size' bytes starting at offset 'off'\n"
        "    to/from memory address 'addr', skipping bad blocks.\n"
+       "nand read.raw - addr off|partition\n"
+       "nand write.raw - addr off|partition\n"
+       "    Use read.raw/write.raw to avoid ECC and access the page as-is.\n"
 #ifdef CONFIG_CMD_NAND_TRIMFFS
        "nand write.trimffs - addr off|partition size\n"
        "    write 'size' bytes starting at offset 'off' from memory address\n"
@@ -714,7 +753,7 @@ U_BOOT_CMD(
        "nand erase.chip [clean] - erase entire chip'\n"
        "nand bad - show bad blocks\n"
        "nand dump[.oob] off - dump page\n"
-       "nand scrub off size | scrub.part partition | scrub.chip\n"
+       "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
        "    really clean NAND erasing bad blocks (UNSAFE)\n"
        "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
        "nand biterr off - make a bit error at offset (UNSAFE)"
index 751b6938435b7ebf6287b0fd0e1c92cc2916ef88..023740e1d364452f77316cf97968be48faf9cd40 100644 (file)
@@ -94,6 +94,15 @@ Commands:
       of data for one 512-byte page or 2 256-byte pages. There is no check
       for bad blocks.
 
+   nand read.raw addr ofs|partition
+      Read page from `ofs' in NAND flash to `addr'. This reads the raw page,
+      so ECC is avoided and the OOB area is read as well.
+
+   nand write.raw addr ofs|partition
+      Write page from `addr' to `ofs' in NAND flash. This writes the raw page,
+      so ECC is avoided and the OOB area is written as well, making the whole
+      page written as-is.
+
 Configuration Options:
 
    CONFIG_CMD_NAND
index acdb43112a6de395f2a31ba78c38c6af5ea481ea..4d1e527db103f54359f6744fa9df601007ca5ce6 100644 (file)
@@ -85,7 +85,6 @@ struct fsl_elbc_ctrl {
        unsigned int mdr;        /* UPM/FCM Data Register value           */
        unsigned int use_mdr;    /* Non zero if the MDR is to be set      */
        unsigned int oob;        /* Non zero if operating on OOB data     */
-       uint8_t *oob_poi;        /* Place to write ECC after read back    */
 };
 
 /* These map to the positions used by the FCM hardware ECC generator */
@@ -436,7 +435,6 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
        /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
        case NAND_CMD_PAGEPROG: {
-               int full_page;
                vdbg("fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
                     "writing %d bytes.\n", ctrl->index);
 
@@ -445,34 +443,13 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
                 * write so the HW generates the ECC.
                 */
                if (ctrl->oob || ctrl->column != 0 ||
-                   ctrl->index != mtd->writesize + mtd->oobsize) {
+                   ctrl->index != mtd->writesize + mtd->oobsize)
                        out_be32(&lbc->fbcr, ctrl->index);
-                       full_page = 0;
-               } else {
+               else
                        out_be32(&lbc->fbcr, 0);
-                       full_page = 1;
-               }
 
                fsl_elbc_run_command(mtd);
 
-               /* Read back the page in order to fill in the ECC for the
-                * caller.  Is this really needed?
-                */
-               if (full_page && ctrl->oob_poi) {
-                       out_be32(&lbc->fbcr, 3);
-                       set_addr(mtd, 6, page_addr, 1);
-
-                       ctrl->read_bytes = mtd->writesize + 9;
-
-                       fsl_elbc_do_read(chip, 1);
-                       fsl_elbc_run_command(mtd);
-
-                       memcpy_fromio(ctrl->oob_poi + 6,
-                                     &ctrl->addr[ctrl->index], 3);
-                       ctrl->index += 3;
-               }
-
-               ctrl->oob_poi = NULL;
                return;
        }
 
@@ -680,13 +657,8 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
                                struct nand_chip *chip,
                                const uint8_t *buf)
 {
-       struct fsl_elbc_mtd *priv = chip->priv;
-       struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
        fsl_elbc_write_buf(mtd, buf, mtd->writesize);
        fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-       ctrl->oob_poi = chip->oob_poi;
 }
 
 static struct fsl_elbc_ctrl *elbc_ctrl;
index c33e2786b2e81d43bbbde2de24f26ed48f049d9e..31c174bd3bc05bd18532f9ac820ee16d4acd248b 100644 (file)
@@ -124,14 +124,14 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
                fun_wait(fun);
 }
 
-static u8 nand_read_byte(struct mtd_info *mtd)
+static u8 upm_nand_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd->priv;
 
        return in_8(chip->IO_ADDR_R);
 }
 
-static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static void upm_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        int i;
        struct nand_chip *chip = mtd->priv;
@@ -147,7 +147,7 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
                fun_wait(fun);
 }
 
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+static void upm_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
        int i;
        struct nand_chip *chip = mtd->priv;
@@ -156,7 +156,7 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
                buf[i] = in_8(chip->IO_ADDR_R);
 }
 
-static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static int upm_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        int i;
        struct nand_chip *chip = mtd->priv;
@@ -191,10 +191,10 @@ int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun)
 #if CONFIG_SYS_NAND_MAX_CHIPS > 1
        chip->select_chip = fun_select_chip;
 #endif
-       chip->read_byte = nand_read_byte;
-       chip->read_buf = nand_read_buf;
-       chip->write_buf = nand_write_buf;
-       chip->verify_buf = nand_verify_buf;
+       chip->read_byte = upm_nand_read_byte;
+       chip->read_buf = upm_nand_read_buf;
+       chip->write_buf = upm_nand_write_buf;
+       chip->verify_buf = upm_nand_verify_buf;
        if (fun->dev_ready)
                chip->dev_ready = nand_dev_ready;
 
index 376378ed3f1179c6761a982a73b69098cb38f09b..bdab5aa795befc221e6c62d11c2b4a961d7ab499 100644 (file)
@@ -76,7 +76,7 @@ int board_nand_init(struct nand_chip *nand)
        nand->options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING;
        nand->ecc.mode = NAND_ECC_SOFT;
        nand->cmd_ctrl = kw_nand_hwcontrol;
-       nand->chip_delay = 30;
+       nand->chip_delay = 40;
        nand->select_chip = kw_nand_select_chip;
        return 0;
 }
index 2a8dd7e2395ea3b5d3ba1a937ba7627c4b2c0bce..35e89a0f4d69428878edcbe384263f02a7360b78 100644 (file)
@@ -350,7 +350,7 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr)
 }
 
 /*
- * This function requests the NANDFC to initate the transfer
+ * This function requests the NANDFC to initiate the transfer
  * of data currently in the NANDFC RAM buffer to the NAND device.
  */
 static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
@@ -394,7 +394,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
 }
 
 /*
- * Requests NANDFC to initated the transfer of data from the
+ * Requests NANDFC to initiate the transfer of data from the
  * NAND device into in the NANDFC ram buffer.
  */
 static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
@@ -637,7 +637,7 @@ static int mxc_nand_read_page_syndrome(struct mtd_info *mtd,
        MTDDEBUG(MTD_DEBUG_LEVEL1, "Reading page %u to buf %p oob %p\n",
              host->page_addr, buf, oob);
 
-       /* first read out the data area and the available portion of OOB */
+       /* first read the data area and the available portion of OOB */
        for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) {
                int stat;
 
@@ -1179,7 +1179,7 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command,
                        /*
                         * before sending SEQIN command for partial write,
                         * we need read one page out. FSL NFC does not support
-                        * partial write. It alway send out 512+ecc+512+ecc ...
+                        * partial write. It always sends out 512+ecc+512+ecc
                         * for large page nand flash. But for small page nand
                         * flash, it does support SPARE ONLY operation.
                         */
@@ -1209,7 +1209,7 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command,
                send_prog_page(host, 0, host->spare_only);
 
                if (host->pagesize_2k && !is_mxc_nfc_11()) {
-                       /* data in 4 areas datas */
+                       /* data in 4 areas */
                        send_prog_page(host, 1, host->spare_only);
                        send_prog_page(host, 2, host->spare_only);
                        send_prog_page(host, 3, host->spare_only);
@@ -1225,10 +1225,9 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command,
        if (column != -1) {
                /*
                 * MXC NANDFC can only perform full page+spare or
-                * spare-only read/write.  When the upper layers
-                * layers perform a read/write buf operation,
-                * we will used the saved column adress to index into
-                * the full page.
+                * spare-only read/write. When the upper layers perform
+                * a read/write buffer operation, we will use the saved
+                * column address to index into the full page.
                 */
                send_addr(host, 0);
                if (host->pagesize_2k)
@@ -1372,12 +1371,23 @@ int board_nand_init(struct nand_chip *this)
 
        /* Blocks to be unlocked */
        writew(0x0, &host->regs->nfc_unlockstart_blkaddr);
-       writew(0x4000, &host->regs->nfc_unlockend_blkaddr);
+       /* Originally (Freescale LTIB 2.6.21) 0x4000 was written to the
+        * unlockend_blkaddr, but the magic 0x4000 does not always work
+        * when writing more than some 32 megabytes (on 2k page nands)
+        * However 0xFFFF doesn't seem to have this kind
+        * of limitation (tried it back and forth several times).
+        * The linux kernel driver sets this to 0xFFFF for the v2 controller
+        * only, but probably this was not tested there for v1.
+        * The very same limitation seems to apply to this kernel driver.
+        * This might be NAND chip specific and the i.MX31 datasheet is
+        * extremely vague about the semantics of this register.
+        */
+       writew(0xFFFF, &host->regs->nfc_unlockend_blkaddr);
 
        /* Unlock Block Command for given address range */
        writew(0x4, &host->regs->nfc_wrprot);
 
-       /* NAND bus width determines access funtions used by upper layer */
+       /* NAND bus width determines access functions used by upper layer */
        if (is_16bit_nand())
                this->options |= NAND_BUSWIDTH_16;
 
index e7dfcb1568108194414b8676f6abe780dd4d2a7b..6aac6a2bf4189d8ff64cf5fb344148d8e69a54f7 100644 (file)
@@ -2224,7 +2224,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
                /*
                 * heck if we have a bad block, we do not erase bad blocks !
                 */
-               if (nand_block_checkbad(mtd, ((loff_t) page) <<
+               if (!instr->scrub && nand_block_checkbad(mtd, ((loff_t) page) <<
                                        chip->page_shift, 0, allowbbt)) {
                        printk(KERN_WARNING "nand_erase: attempt to erase a "
                               "bad block at page 0x%08x\n", page);
index 81bf366159e54fcca6057ba59f2d6760091dc0a1..60c778e637018ef350a4c021359ba55b2016032c 100644 (file)
@@ -57,12 +57,6 @@ typedef struct mtd_info        mtd_info_t;
 #define cpu_to_je16(x) (x)
 #define cpu_to_je32(x) (x)
 
-/*****************************************************************************/
-static int nand_block_bad_scrub(struct mtd_info *mtd, loff_t ofs, int getchip)
-{
-       return 0;
-}
-
 /**
  * nand_erase_opts: - erase NAND flash with support for various options
  *                   (jffs2 formating)
@@ -82,7 +76,6 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
        int bbtest = 1;
        int result;
        int percent_complete = -1;
-       int (*nand_block_bad_old)(struct mtd_info *, loff_t, int) = NULL;
        const char *mtd_device = meminfo->name;
        struct mtd_oob_ops oob_opts;
        struct nand_chip *chip = meminfo->priv;
@@ -110,17 +103,15 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
         * and disable bad block table while erasing.
         */
        if (opts->scrub) {
-               struct nand_chip *priv_nand = meminfo->priv;
-
-               nand_block_bad_old = priv_nand->block_bad;
-               priv_nand->block_bad = nand_block_bad_scrub;
-               /* we don't need the bad block table anymore...
+               erase.scrub = opts->scrub;
+               /*
+                * We don't need the bad block table anymore...
                 * after scrub, there are no bad blocks left!
                 */
-               if (priv_nand->bbt) {
-                       kfree(priv_nand->bbt);
+               if (chip->bbt) {
+                       kfree(chip->bbt);
                }
-               priv_nand->bbt = NULL;
+               chip->bbt = NULL;
        }
 
        for (erased_length = 0;
@@ -204,12 +195,8 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
        if (!opts->quiet)
                printf("\n");
 
-       if (nand_block_bad_old) {
-               struct nand_chip *priv_nand = meminfo->priv;
-
-               priv_nand->block_bad = nand_block_bad_old;
-               priv_nand->scan_bbt(meminfo);
-       }
+       if (opts->scrub)
+               chip->scan_bbt(meminfo);
 
        return 0;
 }
index d36d58440abed6c85143d4ad39421a58aa850b54..141c96024c57c5246f967f8e045c2a6abab6c3f9 100644 (file)
@@ -55,6 +55,7 @@ struct erase_info {
        u_long priv;
        u_char state;
        struct erase_info *next;
+       int scrub;
 };
 
 struct mtd_erase_region_info {
index 4683c7c52c33e216d7c64a677ee9322250e16b23..615ef258a8c6e5715398d587ce71d65abf4c884d 100644 (file)
@@ -135,6 +135,47 @@ static int nand_is_bad_block(struct mtd_info *mtd, int block)
        return 0;
 }
 
+#if defined(CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST)
+static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
+{
+       struct nand_chip *this = mtd->priv;
+       u_char *ecc_calc;
+       u_char *ecc_code;
+       u_char *oob_data;
+       int i;
+       int eccsize = CONFIG_SYS_NAND_ECCSIZE;
+       int eccbytes = CONFIG_SYS_NAND_ECCBYTES;
+       int eccsteps = CONFIG_SYS_NAND_ECCSTEPS;
+       uint8_t *p = dst;
+       int stat;
+
+       /*
+        * No malloc available for now, just use some temporary locations
+        * in SDRAM
+        */
+       ecc_calc = (u_char *)(CONFIG_SYS_SDRAM_BASE + 0x10000);
+       ecc_code = ecc_calc + 0x100;
+       oob_data = ecc_calc + 0x200;
+
+       nand_command(mtd, block, page, 0, NAND_CMD_READOOB);
+       this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
+       nand_command(mtd, block, page, 0, NAND_CMD_READ0);
+
+       /* Pick the ECC bytes out of the oob data */
+       for (i = 0; i < CONFIG_SYS_NAND_ECCTOTAL; i++)
+               ecc_code[i] = oob_data[nand_ecc_pos[i]];
+
+
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+               this->ecc.hwctl(mtd, NAND_ECC_READ);
+               this->read_buf(mtd, p, eccsize);
+               this->ecc.calculate(mtd, p, &ecc_calc[i]);
+               stat = this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
+       }
+
+       return 0;
+}
+#else
 static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
 {
        struct nand_chip *this = mtd->priv;
@@ -181,6 +222,7 @@ static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
 
        return 0;
 }
+#endif /* #if defined(CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST) */
 
 static int nand_load(struct mtd_info *mtd, unsigned int offs,
                     unsigned int uboot_size, uchar *dst)