All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot-Users] [PATCH v2] NAND FSL UPM: driver re-write using the hwcontrol callback
@ 2008-06-03  7:44 Wolfgang Grandegger
  0 siblings, 0 replies; only message in thread
From: Wolfgang Grandegger @ 2008-06-03  7:44 UTC (permalink / raw)
  To: u-boot

NAND FSL UPM: driver re-write using the hwcontrol callback

This is a re-write of the NAND FSL UPM driver using the more universal
hwcontrol callback (instead of the cmdfunc callback). Here is a brief
list of furher modifications:

- For the time being, the UPM setup writing the UPM array has been
  removed from the driver and must now be done by the board specific
  code.

- The bus width definition in "struct fsl_upm_nand" is now in bits to
  comply with the corresponding Linux driver and 8, 16 and 32 bit
  accesses are supported.

- chip->dev_read is only set if fun->dev_ready != NULL, which is
  required for boards not connecting the R/B pin.

- A few issue have been fixed with MxMR bit manipulation like in the
  corresponding Linux driver.

Note: I think the "io_addr" field of "struct fsl_upm" could be removed
      as well, because the address is already determined by
      "nand->IO_ADDR_[RW]", but I'm not 100% sure.

This patch has been tested on a TQM8548 modules with the NAND chip
Micron MT29F8G08FABWP.

This patch is based on the following patches posted to this list a few
minutes ago:

  [PATCH] PPC: add accessor macros to clear and set bits in one shot
  [PATCH] 83xx/85xx/86xx: add more MxMR local bus definitions

In principle, the NAND driver of the TQM8272 should work with it as
well.

Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Acked-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 drivers/mtd/nand/fsl_upm.c  |  128 +++++++++++++++-----------------------------
 include/linux/mtd/fsl_upm.h |    1 
 2 files changed, 46 insertions(+), 83 deletions(-)

Index: u-boot/drivers/mtd/nand/fsl_upm.c
===================================================================
--- u-boot.orig/drivers/mtd/nand/fsl_upm.c
+++ u-boot/drivers/mtd/nand/fsl_upm.c
@@ -20,112 +20,83 @@
 #include <linux/mtd/fsl_upm.h>
 #include <nand.h>
 
-#define FSL_UPM_MxMR_OP_NO (0 << 28) /* normal operation */
-#define FSL_UPM_MxMR_OP_WA (1 << 28) /* write array */
-#define FSL_UPM_MxMR_OP_RA (2 << 28) /* read array */
-#define FSL_UPM_MxMR_OP_RP (3 << 28) /* run pattern */
+static int fsl_upm_in_pattern;
 
 static void fsl_upm_start_pattern(struct fsl_upm *upm, u32 pat_offset)
 {
-	out_be32(upm->mxmr, FSL_UPM_MxMR_OP_RP | pat_offset);
+	clrsetbits_be32(upm->mxmr, MxMR_MAD_MSK, MxMR_OP_RUNP | pat_offset);
 }
 
 static void fsl_upm_end_pattern(struct fsl_upm *upm)
 {
-	out_be32(upm->mxmr, FSL_UPM_MxMR_OP_NO);
-	while (in_be32(upm->mxmr) != FSL_UPM_MxMR_OP_NO)
+	clrbits32(upm->mxmr, MxMR_OP_RUNP);
+
+	while (in_be32(upm->mxmr) & MxMR_OP_RUNP)
 		eieio();
 }
 
 static void fsl_upm_run_pattern(struct fsl_upm *upm, int width, u32 cmd)
 {
-	out_be32(upm->mar, cmd << (32 - width * 8));
-	out_8(upm->io_addr, 0x0);
-}
-
-static void fsl_upm_setup(struct fsl_upm *upm)
-{
-	int i;
-
-	/* write upm array */
-	out_be32(upm->mxmr, FSL_UPM_MxMR_OP_WA);
-
-	for (i = 0; i < 64; i++) {
-		out_be32(upm->mdr, upm->array[i]);
+	out_be32(upm->mar, cmd << (32 - width));
+	switch (width) {
+	case 8:
 		out_8(upm->io_addr, 0x0);
+		break;
+	case 16:
+		out_be16(upm->io_addr, 0x0);
+		break;
+	case 32:
+		out_be32(upm->io_addr, 0x0);
+		break;
 	}
-
-	/* normal operation */
-	out_be32(upm->mxmr, FSL_UPM_MxMR_OP_NO);
-	while (in_be32(upm->mxmr) != FSL_UPM_MxMR_OP_NO)
-		eieio();
 }
 
-static void fun_cmdfunc(struct mtd_info *mtd, unsigned command, int column,
-			int page_addr)
+static void nand_hwcontrol (struct mtd_info *mtd, int cmd)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_upm_nand *fun = chip->priv;
 
-	fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset);
-
-	if (command == NAND_CMD_SEQIN) {
-		int readcmd;
-
-		if (column >= mtd->oobblock) {
-			/* OOB area */
-			column -= mtd->oobblock;
-			readcmd = NAND_CMD_READOOB;
-		} else if (column < 256) {
-			/* First 256 bytes --> READ0 */
-			readcmd = NAND_CMD_READ0;
-		} else {
-			column -= 256;
-			readcmd = NAND_CMD_READ1;
-		}
-		fsl_upm_run_pattern(&fun->upm, fun->width, readcmd);
+	switch (cmd) {
+	case NAND_CTL_SETCLE:
+		fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset);
+		fsl_upm_in_pattern++;
+		break;
+	case NAND_CTL_SETALE:
+		fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset);
+		fsl_upm_in_pattern++;
+		break;
+	case NAND_CTL_CLRCLE:
+	case NAND_CTL_CLRALE:
+		fsl_upm_end_pattern(&fun->upm);
+		fsl_upm_in_pattern--;
+		break;
 	}
+}
 
-	fsl_upm_run_pattern(&fun->upm, fun->width, command);
-
-	fsl_upm_end_pattern(&fun->upm);
-
-	fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset);
-
-	if (column != -1)
-		fsl_upm_run_pattern(&fun->upm, fun->width, column);
+static void nand_write_byte(struct mtd_info *mtd, u_char byte)
+{
+	struct nand_chip *chip = mtd->priv;
 
-	if (page_addr != -1) {
-		fsl_upm_run_pattern(&fun->upm, fun->width, page_addr);
-		fsl_upm_run_pattern(&fun->upm, fun->width,
-				    (page_addr >> 8) & 0xFF);
-		if (chip->chipsize > (32 << 20)) {
-			fsl_upm_run_pattern(&fun->upm, fun->width,
-					    (page_addr >> 16) & 0x0f);
-		}
-	}
+	if (fsl_upm_in_pattern) {
+		struct fsl_upm_nand *fun = chip->priv;
 
-	fsl_upm_end_pattern(&fun->upm);
+		fsl_upm_run_pattern(&fun->upm, fun->width, byte);
 
-	if (fun->wait_pattern) {
 		/*
 		 * 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.
 		 */
-		while (!fun->dev_ready())
-			debug("unexpected busy state\n");
+		if (fun->wait_pattern) {
+			while (!fun->dev_ready())
+				debug("unexpected busy state\n");
+		}
+	} else {
+		out_8(chip->IO_ADDR_W, byte);
 	}
 }
 
-static void nand_write_byte(struct mtd_info *mtd, u_char byte)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	out_8(chip->IO_ADDR_W, byte);
-}
-
 static u8 nand_read_byte(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
@@ -164,10 +135,6 @@ static int nand_verify_buf(struct mtd_in
 	return 0;
 }
 
-static void nand_hwcontrol(struct mtd_info *mtd, int cmd)
-{
-}
-
 static int nand_dev_ready(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
@@ -178,23 +145,20 @@ static int nand_dev_ready(struct mtd_inf
 
 int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun)
 {
-	/* yet only 8 bit accessors implemented */
-	if (fun->width != 1)
+	if (fun->width != 8 && fun->width != 16 && fun->width != 32)
 		return -ENOSYS;
 
-	fsl_upm_setup(&fun->upm);
-
 	chip->priv = fun;
 	chip->chip_delay = fun->chip_delay;
 	chip->eccmode = NAND_ECC_SOFT;
-	chip->cmdfunc = fun_cmdfunc;
 	chip->hwcontrol = nand_hwcontrol;
 	chip->read_byte = nand_read_byte;
 	chip->read_buf = nand_read_buf;
 	chip->write_byte = nand_write_byte;
 	chip->write_buf = nand_write_buf;
 	chip->verify_buf = nand_verify_buf;
-	chip->dev_ready = nand_dev_ready;
+	if (fun->dev_ready)
+		chip->dev_ready = nand_dev_ready;
 
 	return 0;
 }
Index: u-boot/include/linux/mtd/fsl_upm.h
===================================================================
--- u-boot.orig/include/linux/mtd/fsl_upm.h
+++ u-boot/include/linux/mtd/fsl_upm.h
@@ -16,7 +16,6 @@
 #include <linux/mtd/nand.h>
 
 struct fsl_upm {
-	const u32 *array;
 	void __iomem *mdr;
 	void __iomem *mxmr;
 	void __iomem *mar;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-06-03  7:44 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-03  7:44 [U-Boot-Users] [PATCH v2] NAND FSL UPM: driver re-write using the hwcontrol callback Wolfgang Grandegger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.