Add wait flags to support board/chip specific delays

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>
master
Wolfgang Grandegger 16 years ago committed by Scott Wood
parent 06e9f7df05
commit 33846df28f
  1. 2
      board/freescale/mpc8360erdk/nand.c
  2. 37
      drivers/mtd/nand/fsl_upm.c
  3. 6
      include/linux/mtd/fsl_upm.h

@ -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,
};

@ -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)

@ -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;

Loading…
Cancel
Save