summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/freescale/mpc8360erdk/nand.c2
-rw-r--r--drivers/mtd/nand/fsl_upm.c37
-rw-r--r--include/linux/mtd/fsl_upm.h6
3 files changed, 34 insertions, 11 deletions
diff --git a/board/freescale/mpc8360erdk/nand.c b/board/freescale/mpc8360erdk/nand.c
index aa43350..9ffffb4 100644
--- a/board/freescale/mpc8360erdk/nand.c
+++ b/board/freescale/mpc8360erdk/nand.c
@@ -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,
};
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index e7e746b..7cb99cb 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -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)
diff --git a/include/linux/mtd/fsl_upm.h b/include/linux/mtd/fsl_upm.h
index 10f5ddd..5d7156f 100644
--- a/include/linux/mtd/fsl_upm.h
+++ b/include/linux/mtd/fsl_upm.h
@@ -15,6 +15,10 @@
#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;