Freescale FCM controller has a 2K size limitation of buffer RAM. In order
to support the Nand flash chip whose page size is larger than 2K bytes,
we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB and save
them to a large buffer.
Signed-off-by: Shengzhou Liu shengzhou@freescale.com
Signed-off-by: Liu Shuo b35...@freescale.com
Signed-off-by: Li Yang le...@freescale.com
---
based on 'master' branch of Wolfgang's tree.
drivers/mtd/nand/fsl_elbc_nand.c | 225 ++---
1 files changed, 206 insertions(+), 19 deletions(-)
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 4d1e527..6d0639a 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -64,7 +64,7 @@ struct fsl_elbc_mtd {
struct device *dev;
int bank; /* Chip select bank number */
u8 __iomem *vbase; /* Chip select base virtual address */
- int page_size; /* NAND page size (0=512, 1=2048)*/
+ int page_size; /* NAND page size (0=512, 1=2048, 2=4096,...) */
unsigned int fmr; /* FCM Flash Mode Register value */
};
@@ -85,6 +85,8 @@ struct fsl_elbc_ctrl {
unsigned int mdr;/* UPM/FCM Data Register value */
unsigned int use_mdr;/* Non zero if the MDR is to be set */
unsigned int oob;/* Non zero if operating on OOB data */
+ char *buffer;/* just used when pagesize is greater*/
+/* than FCM RAM 2K limitation*/
};
/* These map to the positions used by the FCM hardware ECC generator */
@@ -159,6 +161,44 @@ static struct nand_bbt_descr bbt_mirror_descr = {
.pattern = mirror_pattern,
};
+static void io_to_buffer(struct mtd_info *mtd, int subpage, int oob)
+{
+ struct nand_chip *chip = mtd-priv;
+ struct fsl_elbc_mtd *priv = chip-priv;
+ struct fsl_elbc_ctrl *ctrl = priv-ctrl;
+ void *src, *dst;
+ int len = (oob ? 64 : 2048);
+
+ /* for emulating 4096+ bytes NAND using 2048-byte FCM RAM */
+ if (oob)
+ dst = ctrl-buffer + mtd-writesize + subpage * 64;
+ else
+ dst = ctrl-buffer + subpage * 2048;
+
+ src = ctrl-addr + (oob ? 2048 : 0);
+ memcpy_fromio(dst, src, len);
+}
+
+static void buffer_to_io(struct mtd_info *mtd, int subpage, int oob)
+{
+ struct nand_chip *chip = mtd-priv;
+ struct fsl_elbc_mtd *priv = chip-priv;
+ struct fsl_elbc_ctrl *ctrl = priv-ctrl;
+ void *src, *dst;
+ int len = (oob ? 64 : 2048);
+
+ if (oob)
+ src = ctrl-buffer + mtd-writesize + subpage * 64;
+ else
+ src = ctrl-buffer + subpage * 2048;
+
+ dst = ctrl-addr + (oob ? 2048 : 0);
+
+ memcpy_toio(dst, src, len);
+ /* See the in_8() in fsl_elbc_write_buf() */
+ in_8(ctrl-addr);
+}
+
/*=*/
/*
@@ -194,7 +234,7 @@ static void set_addr(struct mtd_info *mtd, int column, int
page_addr, int oob)
/* for OOB data point to the second half of the buffer */
if (oob)
- ctrl-index += priv-page_size ? 2048 : 512;
+ ctrl-index += mtd-writesize;
vdbg(set_addr: bank=%d, ctrl-addr=0x%p (0x%p),
index %x, pes %d ps %d\n,
@@ -295,6 +335,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned
int command,
struct fsl_elbc_mtd *priv = chip-priv;
struct fsl_elbc_ctrl *ctrl = priv-ctrl;
fsl_lbc_t *lbc = ctrl-regs;
+ int i;
ctrl-use_mdr = 0;
@@ -321,6 +362,25 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd,
unsigned int command,
fsl_elbc_do_read(chip, 0);
fsl_elbc_run_command(mtd);
+
+ if (priv-page_size = 1)
+ return;
+
+ /* Continue to read the rest bytes if writesize 2048 */
+ io_to_buffer(mtd, 0, 0);
+ io_to_buffer(mtd, 0, 1);
+ /*
+* Maybe there are some reasons of FCM hardware timming,
+* we must insert a FIR_OP_NOP(0x00) before FIR_OP_RB.
+*/
+ out_be32(lbc-fir, FIR_OP_RB FIR_OP1_SHIFT);
+
+ for (i = 1; i priv-page_size; i++) {
+ fsl_elbc_run_command(mtd);
+ io_to_buffer(mtd, i, 0);
+ io_to_buffer(mtd, i, 1);
+ }
+
return;
/* READOOB reads only the OOB because no ECC is performed. */
@@ -328,14 +388,34 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd,
unsigned int command,
vdbg(fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:
0x%x, column: 0x%x.\n, page_addr, column);
- out_be32(lbc-fbcr, mtd-oobsize - column);
- set_addr(mtd, column,