All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wolfgang Grandegger <wg@grandegger.com>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] [PATCH] TQM85xx: NAND support via local bus UPMB
Date: Sat, 31 May 2008 09:11:36 +0200	[thread overview]
Message-ID: <4840FA28.8010801@grandegger.com> (raw)
In-Reply-To: <4840F902.7020103@grandegger.com>

Wolfgang Grandegger wrote:
> Anton Vorontsov wrote:
>> On Fri, May 30, 2008 at 08:00:32PM +0200, Wolfgang Grandegger wrote:
>> [...]
>>> Fix that, but I can still not access the device properly. I'm a bit
>>> puzzled because it uses a different algorithm to access the device.
>>> While my and the Linux fsl_upm driver uses NAND_ALE, NAND_CLE and
>>> friends to manage the access via hwcontrol callback, the fsl_upm driver
>>> of U-Boot uses the cmdfunc callback doing different things. 
>> I wonder if your NAND chip is a large page one? Because currently
>> fsl_upm_nand hardcodes OOB stuff (bad thing, but with old mtd subsystem
>> I didn't find better way ;-).
> 
> On my TQM8548 there is a Micron MT29F8G08FABWP, page size 2048 + 64
> bytes, block size 128K + 4K bytes.
> 
>> As for u-boot and linux doing different things... with this patch
>> u-boot and linux are identical:
>>
>> http://www.denx.de/cgi-bin/gitweb.cgi?p=u-boot/u-boot-nand-flash.git;a=commitdiff;h=dffa9a8b31b2c21fd3a72ba1f58dd04911b95b6f
>>
>> This is in U-Boot's mtd-2.6.22.1 branch though. :-/ Your approach with hwctl
>> seem to be more universal (for old mtd subsystem), since it doesn't duplicate
>> MTD cmdfunc, thus should work for all NAND chips...
> 
> A closer look to the code confirms that.
> 
>> Could you prepare a patch that replacing fsl_upm_nand.c's current logic
>> with yours (that should work for your NAND chip), and I'll test it
>> on MPC8360E-RDK?
> 
> The attached preliminary patch works for me. Compared to my specific
> driver, it saves start_pattern and end_pattern calls :-).
> It now also supports a bus width of 8, 16 and 32 bits and width is now
> in bits like in the Linux driver. I'm going to prepare a proper patch
> series beginning of next week.

Here is the missing patch:

---
 drivers/mtd/nand/fsl_upm.c |  132 +++++++++++++++++----------------------------
 include/asm-ppc/io.h       |   28 +++++++++
 2 files changed, 79 insertions(+), 81 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,89 @@
 #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, MxMR_OP_RUN | 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_RUN);
+
+	while (in_be32(upm->mxmr) & MxMR_OP_RUN)
 		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_8(upm->io_addr, 0x0);
+	out_be32(upm->mar, cmd << (32 - width));
+	switch (width) {
+	case 8:
+		out_8(io_base, 0x0);
+		break;
+	case 16:
+		out_be16(io_base, 0x0);
+		break;
+	case 32:
+		out_be32(io_base, 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;
 	}
+#if 1
+	/* Temorary check */
+	if (fsl_upm_in_pattern < 0 || fsl_upm_in_pattern > 1)
+		printf("fsl_upm: Oops, unexpected fsl_upm_in_pattern %d\n",
+		       fsl_upm_in_pattern);
+#endif
+}
 
-	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 +141,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;
@@ -179,15 +152,12 @@ 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;
Index: u-boot/include/asm-ppc/io.h
===================================================================
--- u-boot.orig/include/asm-ppc/io.h
+++ u-boot/include/asm-ppc/io.h
@@ -238,6 +238,34 @@ extern inline void out_be32(volatile uns
 	__asm__ __volatile__("sync; stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
 }
 
+/* access ports */
+#define setbits32(_addr, _v) out_be32((_addr), in_be32(_addr) |  (_v))
+#define clrbits32(_addr, _v) out_be32((_addr), in_be32(_addr) & ~(_v))
+
+#define setbits16(_addr, _v) out_be16((_addr), in_be16(_addr) |  (_v))
+#define clrbits16(_addr, _v) out_be16((_addr), in_be16(_addr) & ~(_v))
+
+#define setbits8(_addr, _v) out_8((_addr), in_8(_addr) |  (_v))
+#define clrbits8(_addr, _v) out_8((_addr), in_8(_addr) & ~(_v))
+
+/* Clear and set bits in one shot.  These macros can be used to clear and
+ * set multiple bits in a register using a single read-modify-write.  These
+ * macros can also be used to set a multiple-bit bit pattern using a mask,
+ * by specifying the mask in the 'clear' parameter and the new bit pattern
+ * in the 'set' parameter.
+ */
+
+#define clrsetbits(type, addr, clear, set) \
+	out_##type((addr), (in_##type(addr) & ~(clear)) | (set))
+
+#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set)
+#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set)
+
+#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set)
+#define clrsetbits_le16(addr, clear, set) clrsetbits(le32, addr, clear, set)
+
+#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
+
 /*
  * Given a physical address and a length, return a virtual address
  * that can be used to access the memory range with the caching

  reply	other threads:[~2008-05-31  7:11 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-28 18:12 [U-Boot-Users] [PATCH 0/12] 85xx: various fixes for TQM85xx and support for TQM8548 Wolfgang Grandegger
2008-05-28 18:12 ` [U-Boot-Users] [PATCH] MPC85xx: Beatify boot output of L2 cache configuration Wolfgang Grandegger
2008-05-28 18:12   ` [U-Boot-Users] [PATCH] TQM85xx: Various coding style fixes Wolfgang Grandegger
2008-05-28 18:12     ` [U-Boot-Users] [PATCH] TQM85xx: Fix CPM port pin configuration Wolfgang Grandegger
2008-05-28 18:12       ` [U-Boot-Users] [PATCH] TQM85xx: Support for Spansion 'N' type flashes added Wolfgang Grandegger
2008-05-28 18:12         ` [U-Boot-Users] [PATCH] TQM85xx: Fix chip select configuration for second FLASH bank Wolfgang Grandegger
2008-05-28 18:12           ` [U-Boot-Users] [PATCH] TQM85xx: Bugfix in the SDRAM initialisation Wolfgang Grandegger
2008-05-28 18:12             ` [U-Boot-Users] [PATCH] TQM85xx: Support for Intel 82527 compatible CAN controller Wolfgang Grandegger
2008-05-28 18:12               ` [U-Boot-Users] [PATCH] TQM85xx: Support for Flat Device Tree Wolfgang Grandegger
2008-05-28 18:12                 ` [U-Boot-Users] [PATCH] TQM8548: Basic support for the TQM8548 modules Wolfgang Grandegger
2008-05-28 18:12                   ` [U-Boot-Users] [PATCH] TQM8548: PCI express support Wolfgang Grandegger
2008-05-28 18:12                     ` [U-Boot-Users] [PATCH] TQM85xx: NAND support via local bus UPMB Wolfgang Grandegger
2008-05-28 18:12                       ` [U-Boot-Users] [PATCH] TQM85xx: Change memory map to support Flash memory > 128 MiB Wolfgang Grandegger
2008-05-28 18:25                       ` [U-Boot-Users] [PATCH] TQM85xx: NAND support via local bus UPMB Scott Wood
2008-05-28 18:38                         ` Wolfgang Grandegger
2008-05-29 11:39                           ` Anton Vorontsov
2008-05-29 11:58                             ` Wolfgang Grandegger
2008-05-29 12:44                               ` Anton Vorontsov
2008-05-30 18:00                                 ` Wolfgang Grandegger
2008-05-30 18:28                                   ` Anton Vorontsov
2008-05-31  7:06                                     ` Wolfgang Grandegger
2008-05-31  7:11                                       ` Wolfgang Grandegger [this message]
2008-06-02 10:06                                     ` Wolfgang Grandegger
2008-06-03  3:15   ` [U-Boot-Users] [PATCH] MPC85xx: Beatify boot output of L2 cache configuration Andy Fleming
2008-06-03  7:28     ` Wolfgang Grandegger
2008-06-03 16:50       ` Detlev Zundel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4840FA28.8010801@grandegger.com \
    --to=wg@grandegger.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.