]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/mtd/nand/fsl_elbc_nand.c
mtd: nand: Allow caller to pass alternative ID table to nand_scan_ident()
[net-next-2.6.git] / drivers / mtd / nand / fsl_elbc_nand.c
index ddd37d2554ede02c08044642d4f30c2d3307ee57..3f38fb8e66668c37f36a86d29fb7c08766e752e6 100644 (file)
@@ -237,12 +237,15 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 
        ctrl->use_mdr = 0;
 
-       dev_vdbg(ctrl->dev,
-                "fsl_elbc_run_command: stat=%08x mdr=%08x fmr=%08x\n",
-                ctrl->status, ctrl->mdr, in_be32(&lbc->fmr));
+       if (ctrl->status != LTESR_CC) {
+               dev_info(ctrl->dev,
+                        "command failed: fir %x fcr %x status %x mdr %x\n",
+                        in_be32(&lbc->fir), in_be32(&lbc->fcr),
+                        ctrl->status, ctrl->mdr);
+               return -EIO;
+       }
 
-       /* returns 0 on success otherwise non-zero) */
-       return ctrl->status == LTESR_CC ? 0 : -EIO;
+       return 0;
 }
 
 static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
@@ -253,17 +256,17 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
 
        if (priv->page_size) {
                out_be32(&lbc->fir,
-                        (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+                        (FIR_OP_CM0 << FIR_OP0_SHIFT) |
                         (FIR_OP_CA  << FIR_OP1_SHIFT) |
                         (FIR_OP_PA  << FIR_OP2_SHIFT) |
-                        (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+                        (FIR_OP_CM1 << FIR_OP3_SHIFT) |
                         (FIR_OP_RBW << FIR_OP4_SHIFT));
 
                out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
                                    (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
        } else {
                out_be32(&lbc->fir,
-                        (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+                        (FIR_OP_CM0 << FIR_OP0_SHIFT) |
                         (FIR_OP_CA  << FIR_OP1_SHIFT) |
                         (FIR_OP_PA  << FIR_OP2_SHIFT) |
                         (FIR_OP_RBW << FIR_OP3_SHIFT));
@@ -332,7 +335,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
        case NAND_CMD_READID:
                dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
 
-               out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+               out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
                                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
                                    (FIR_OP_RBW << FIR_OP2_SHIFT));
                out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
@@ -359,16 +362,20 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
                dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
 
                out_be32(&lbc->fir,
-                        (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+                        (FIR_OP_CM0 << FIR_OP0_SHIFT) |
                         (FIR_OP_PA  << FIR_OP1_SHIFT) |
-                        (FIR_OP_CM1 << FIR_OP2_SHIFT));
+                        (FIR_OP_CM2 << FIR_OP2_SHIFT) |
+                        (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+                        (FIR_OP_RS  << FIR_OP4_SHIFT));
 
                out_be32(&lbc->fcr,
                         (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
-                        (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT));
+                        (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
+                        (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
 
                out_be32(&lbc->fbcr, 0);
                ctrl->read_bytes = 0;
+               ctrl->use_mdr = 1;
 
                fsl_elbc_run_command(mtd);
                return;
@@ -383,40 +390,41 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
                ctrl->column = column;
                ctrl->oob = 0;
+               ctrl->use_mdr = 1;
 
-               if (priv->page_size) {
-                       fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) |
-                             (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT);
+               fcr = (NAND_CMD_STATUS   << FCR_CMD1_SHIFT) |
+                     (NAND_CMD_SEQIN    << FCR_CMD2_SHIFT) |
+                     (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT);
 
+               if (priv->page_size) {
                        out_be32(&lbc->fir,
-                                (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+                                (FIR_OP_CM2 << 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));
+                                (FIR_OP_CM3 << FIR_OP4_SHIFT) |
+                                (FIR_OP_CW1 << FIR_OP5_SHIFT) |
+                                (FIR_OP_RS  << FIR_OP6_SHIFT));
                } else {
-                       fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
-                             (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
-
                        out_be32(&lbc->fir,
-                                (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+                                (FIR_OP_CM0 << 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));
+                                (FIR_OP_CM3 << FIR_OP5_SHIFT) |
+                                (FIR_OP_CW1 << FIR_OP6_SHIFT) |
+                                (FIR_OP_RS  << FIR_OP7_SHIFT));
 
                        if (column >= mtd->writesize) {
                                /* OOB area --> READOOB */
                                column -= mtd->writesize;
                                fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
                                ctrl->oob = 1;
-                       } else if (column < 256) {
+                       } else {
+                               WARN_ON(column != 0);
                                /* First 256 bytes --> READ0 */
                                fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
-                       } else {
-                               /* Second 256 bytes --> READ1 */
-                               fcr |= NAND_CMD_READ1 << FCR_CMD0_SHIFT;
                        }
                }
 
@@ -628,22 +636,6 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
        struct fsl_elbc_mtd *priv = chip->priv;
        struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-       struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-
-       if (ctrl->status != LTESR_CC)
-               return NAND_STATUS_FAIL;
-
-       /* Use READ_STATUS command, but wait for the device to be ready */
-       ctrl->use_mdr = 0;
-       out_be32(&lbc->fir,
-                (FIR_OP_CW0 << FIR_OP0_SHIFT) |
-                (FIR_OP_RBW << FIR_OP1_SHIFT));
-       out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
-       out_be32(&lbc->fbcr, 1);
-       set_addr(mtd, 0, 0, 0);
-       ctrl->read_bytes = 1;
-
-       fsl_elbc_run_command(mtd);
 
        if (ctrl->status != LTESR_CC)
                return NAND_STATUS_FAIL;
@@ -651,8 +643,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
        /* The chip always seems to report that it is
         * write-protected, even when it is not.
         */
-       setbits8(ctrl->addr, NAND_STATUS_WP);
-       return fsl_elbc_read_byte(mtd);
+       return (ctrl->mdr & 0xff) | NAND_STATUS_WP;
 }
 
 static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
@@ -883,7 +874,7 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
        priv->ctrl = ctrl;
        priv->dev = ctrl->dev;
 
-       priv->vbase = ioremap(res.start, res.end - res.start + 1);
+       priv->vbase = ioremap(res.start, resource_size(&res));
        if (!priv->vbase) {
                dev_err(ctrl->dev, "failed to map chip region\n");
                ret = -ENOMEM;
@@ -900,7 +891,7 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
        if (ret)
                goto err;
 
-       ret = nand_scan_ident(&priv->mtd, 1);
+       ret = nand_scan_ident(&priv->mtd, 1, NULL);
        if (ret)
                goto err;
 
@@ -946,6 +937,13 @@ static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
 {
        struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
+       /*
+        * NAND transactions can tie up the bus for a long time, so set the
+        * bus timeout to max by clearing LBCR[BMT] (highest base counter
+        * value) and setting LBCR[BMTPS] to the highest prescaler value.
+        */
+       clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
+
        /* clear event registers */
        setbits32(&lbc->ltesr, LTESR_NAND_MASK);
        out_be32(&lbc->lteatr, 0);