]> git.sur5r.net Git - u-boot/blobdiff - drivers/mtd/nand/fsl_ifc_nand.c
dfu, nand: before write a buffer to nand, erase the nand sectors
[u-boot] / drivers / mtd / nand / fsl_ifc_nand.c
index 0878bece675bd3267d044919dbf0c870d966042b..439822c5a24563cce7fa9bc1fee54436f1a30d88 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <nand.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -41,7 +42,6 @@ struct fsl_ifc_ctrl;
 
 /* mtd information per set */
 struct fsl_ifc_mtd {
-       struct mtd_info mtd;
        struct nand_chip chip;
        struct fsl_ifc_ctrl *ctrl;
 
@@ -391,7 +391,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
                        timing = IFC_FIR_OP_RBCD;
 
                out_be32(&ifc->ifc_nand.nand_fir0,
-                               (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                               (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
                                (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
                                (timing << IFC_NAND_FIR0_OP2_SHIFT));
                out_be32(&ifc->ifc_nand.nand_fcr0,
@@ -686,9 +686,8 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
        return nand_fsr;
 }
 
-static int fsl_ifc_read_page(struct mtd_info *mtd,
-                             struct nand_chip *chip,
-                             uint8_t *buf, int page)
+static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+                            uint8_t *buf, int oob_required, int page)
 {
        struct fsl_ifc_mtd *priv = chip->priv;
        struct fsl_ifc_ctrl *ctrl = priv->ctrl;
@@ -705,12 +704,13 @@ static int fsl_ifc_read_page(struct mtd_info *mtd,
 /* ECC will be calculated automatically, and errors will be detected in
  * waitfunc.
  */
-static void fsl_ifc_write_page(struct mtd_info *mtd,
-                               struct nand_chip *chip,
-                               const uint8_t *buf)
+static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+                              const uint8_t *buf, int oob_required)
 {
        fsl_ifc_write_buf(mtd, buf, mtd->writesize);
        fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
 }
 
 static void fsl_ifc_ctrl_init(void)
@@ -758,7 +758,7 @@ static void fsl_ifc_sram_init(void)
 
        /* READID */
        out_be32(&ifc->ifc_nand.nand_fir0,
-                       (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                       (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
                        (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
                        (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
        out_be32(&ifc->ifc_nand.nand_fcr0,
@@ -794,11 +794,14 @@ static void fsl_ifc_sram_init(void)
        out_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext);
 }
 
-int board_nand_init(struct nand_chip *nand)
+static int fsl_ifc_chip_init(int devnum, u8 *addr)
 {
+       struct mtd_info *mtd = &nand_info[devnum];
+       struct nand_chip *nand;
        struct fsl_ifc_mtd *priv;
        struct nand_ecclayout *layout;
        uint32_t cspr = 0, csor = 0, ver = 0;
+       int ret;
 
        if (!ifc_ctrl) {
                fsl_ifc_ctrl_init();
@@ -811,18 +814,18 @@ int board_nand_init(struct nand_chip *nand)
                return -ENOMEM;
 
        priv->ctrl = ifc_ctrl;
-       priv->vbase = nand->IO_ADDR_R;
+       priv->vbase = addr;
 
        /* Find which chip select it is connected to.
         */
        for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
-               phys_addr_t base_addr = virt_to_phys(nand->IO_ADDR_R);
+               phys_addr_t phys_addr = virt_to_phys(addr);
 
                cspr = in_be32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr);
                csor = in_be32(&ifc_ctrl->regs->csor_cs[priv->bank].csor);
 
                if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
-                   (cspr & CSPR_BA) == CSPR_PHYS_ADDR(base_addr)) {
+                   (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
                        ifc_ctrl->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT;
                        break;
                }
@@ -835,6 +838,9 @@ int board_nand_init(struct nand_chip *nand)
                return -ENODEV;
        }
 
+       nand = &priv->chip;
+       mtd->priv = nand;
+
        ifc_ctrl->chips[priv->bank] = priv;
 
        /* fill in nand_chip structure */
@@ -852,8 +858,8 @@ int board_nand_init(struct nand_chip *nand)
        nand->bbt_md = &bbt_mirror_descr;
 
        /* set up nand options */
-       nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
-                       NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE;
+       nand->options = NAND_NO_SUBPAGE_WRITE;
+       nand->bbt_options = NAND_BBT_USE_FLASH;
 
        if (cspr & CSPR_PORT_SIZE_16) {
                nand->read_byte = fsl_ifc_read_byte16;
@@ -884,11 +890,13 @@ int board_nand_init(struct nand_chip *nand)
                        bbt_mirror_descr.offs = 0;
                }
 
+               nand->ecc.strength = 4;
                priv->bufnum_mask = 15;
                break;
 
        case CSOR_NAND_PGS_2K:
                layout = &oob_2048_ecc4;
+               nand->ecc.strength = 4;
                priv->bufnum_mask = 3;
                break;
 
@@ -896,8 +904,10 @@ int board_nand_init(struct nand_chip *nand)
                if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
                    CSOR_NAND_ECC_MODE_4) {
                        layout = &oob_4096_ecc4;
+                       nand->ecc.strength = 4;
                } else {
                        layout = &oob_4096_ecc8;
+                       nand->ecc.strength = 8;
                        nand->ecc.bytes = 16;
                }
 
@@ -921,5 +931,31 @@ int board_nand_init(struct nand_chip *nand)
        if (ver == FSL_IFC_V1_1_0)
                fsl_ifc_sram_init();
 
+       ret = nand_scan_ident(mtd, 1, NULL);
+       if (ret)
+               return ret;
+
+       ret = nand_scan_tail(mtd);
+       if (ret)
+               return ret;
+
+       ret = nand_register(devnum);
+       if (ret)
+               return ret;
        return 0;
 }
+
+#ifndef CONFIG_SYS_NAND_BASE_LIST
+#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
+#endif
+
+static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
+       CONFIG_SYS_NAND_BASE_LIST;
+
+void board_nand_init(void)
+{
+       int i;
+
+       for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
+               fsl_ifc_chip_init(i, (u8 *)base_address[i]);
+}