[U-Boot] [PATCH 2/3] mtd/nand : workaround for Freescale FCM to support 4k pagesize Nand chip

2011-11-22 Thread Shengzhou Liu
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, 

Re: [U-Boot] [PATCH 2/3] mtd/nand : workaround for Freescale FCM to support 4k pagesize Nand chip

2011-11-22 Thread Scott Wood
On 11/22/2011 02:54 AM, Shengzhou Liu wrote:
 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(-)

Please see my feedback on the Linux version of this patch:
http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-November/094199.html

-Scott

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot