Add wait flags to support board/chip specific delays
authorWolfgang Grandegger <wg@grandegger.com>
Wed, 11 Feb 2009 17:38:23 +0000 (18:38 +0100)
committerScott Wood <scottwood@freescale.com>
Mon, 23 Mar 2009 20:53:40 +0000 (15:53 -0500)
The NAND flash on the TQM8548_BE modules requires a short delay after
running the UPM pattern like the MPC8360ERDK board does. The TQM8548_BE
requires a further short delay after writing out a buffer. Normally the
R/B pin should be checked, but it's not connected on the TQM8548_BE.
The corresponding Linux FSL UPM driver uses similar delay points at the
same locations. To manage these extra delays in a more general way, I
introduced the "wait_flags" field allowing the board-specific driver to
specify various types of extra delay.

Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
board/freescale/mpc8360erdk/nand.c
drivers/mtd/nand/fsl_upm.c
include/linux/mtd/fsl_upm.h

index aa43350..9ffffb4 100644 (file)
@@ -76,7 +76,7 @@ static struct fsl_upm_nand fun = {
        .upm_cmd_offset = 8,
        .upm_addr_offset = 16,
        .dev_ready = dev_ready,
-       .wait_pattern = 1,
+       .wait_flags = FSL_UPM_WAIT_RUN_PATTERN,
        .chip_delay = 50,
 };
 
index e7e746b..7cb99cb 100644 (file)
@@ -48,6 +48,20 @@ static void fsl_upm_run_pattern(struct fsl_upm *upm, int width,
        }
 }
 
+static void fun_wait(struct fsl_upm_nand *fun)
+{
+       if (fun->dev_ready) {
+               while (!fun->dev_ready(fun->chip_nr))
+                       debug("unexpected busy state\n");
+       } else {
+               /*
+                * If the R/B pin is not connected, like on the TQM8548,
+                * a short delay is necessary.
+                */
+               udelay(1);
+       }
+}
+
 #if CONFIG_SYS_NAND_MAX_CHIPS > 1
 static void fun_select_chip(struct mtd_info *mtd, int chip_nr)
 {
@@ -99,15 +113,13 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
        fsl_upm_run_pattern(&fun->upm, fun->width, io_addr, mar);
 
        /*
-        * Some boards/chips needs this. At least on MPC8360E-RDK we
-        * need it. Probably weird chip, because I don't see any need
-        * for this on MPC8555E + Samsung K9F1G08U0A. Usually here are
-        * 0-2 unexpected busy states per block read.
+        * Some boards/chips needs this. At least the MPC8360E-RDK and
+        * TQM8548 need it. Probably weird chip, because I don't see
+        * any need for this on MPC8555E + Samsung K9F1G08U0A. Usually
+        * here are 0-2 unexpected busy states per block read.
         */
-       if (fun->wait_pattern) {
-               while (!fun->dev_ready(fun->chip_nr))
-                       debug("unexpected busy state\n");
-       }
+       if (fun->wait_flags & FSL_UPM_WAIT_RUN_PATTERN)
+               fun_wait(fun);
 }
 
 static u8 nand_read_byte(struct mtd_info *mtd)
@@ -121,9 +133,16 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        int i;
        struct nand_chip *chip = mtd->priv;
+       struct fsl_upm_nand *fun = chip->priv;
 
-       for (i = 0; i < len; i++)
+       for (i = 0; i < len; i++) {
                out_8(chip->IO_ADDR_W, buf[i]);
+               if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BYTE)
+                       fun_wait(fun);
+       }
+
+       if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BUFFER)
+               fun_wait(fun);
 }
 
 static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
index 10f5ddd..5d7156f 100644 (file)
 
 #include <linux/mtd/nand.h>
 
+#define FSL_UPM_WAIT_RUN_PATTERN  0x1
+#define FSL_UPM_WAIT_WRITE_BYTE   0x2
+#define FSL_UPM_WAIT_WRITE_BUFFER 0x4
+
 struct fsl_upm {
        void __iomem *mdr;
        void __iomem *mxmr;
@@ -29,7 +33,7 @@ struct fsl_upm_nand {
        int upm_cmd_offset;
        int upm_addr_offset;
        int upm_mar_chip_offset;
-       int wait_pattern;
+       int wait_flags;
        int (*dev_ready)(int chip_nr);
        int chip_delay;
        int chip_offset;