TQM85xx: NAND support via local bus UPMB

This patch adds support for NAND FLASH on the TQM8548. It is disabled by
default and can be enabled for the TQM8548 modules. It is now based on
the re-written FSL NAND UPM driver. A patch has been posted earlier today
with the subject:

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

Note that the R/B pin is not supported by that module requiring to use
the specified maximum delay time.

Note: With NAND support enabled the size of the U-Boot image exceeds
256 KB and TEXT_BASE must therefore be set to 0xfff80000 in config.mk,
doubling the image size :-(.

Signed-off-by: Thomas Waehner <thomas.waehner@tqs.de>
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
diff --git a/board/tqc/tqm85xx/Makefile b/board/tqc/tqm85xx/Makefile
index 52f5ef9..8ea07f2 100644
--- a/board/tqc/tqm85xx/Makefile
+++ b/board/tqc/tqm85xx/Makefile
@@ -25,8 +25,14 @@
 
 LIB	= $(obj)lib$(BOARD).a
 
-COBJS	:= $(BOARD).o sdram.o law.o tlb.o
+COBJS-y	+= $(BOARD).o
+COBJS-y	+= sdram.o
+COBJS-y	+= law.o
+COBJS-y	+= tlb.o
 
+COBJS-$(CONFIG_NAND) += nand.o
+
+COBJS	:= $(COBJS-y)
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
 SOBJS	:= $(addprefix $(obj),$(SOBJS))
diff --git a/board/tqc/tqm85xx/law.c b/board/tqc/tqm85xx/law.c
index bec1ed5..914ce68 100644
--- a/board/tqc/tqm85xx/law.c
+++ b/board/tqc/tqm85xx/law.c
@@ -35,7 +35,7 @@
  * 0xc000_0000	   0xdfff_ffff	   RapidIO or PCI express  512M
  * 0xe000_0000	   0xe000_ffff	   CCSR			   1M
  * 0xe200_0000	   0xe2ff_ffff	   PCI1 IO		   16M
- * 0xe300_0000	   0xe3ff_ffff	   CAN			   16M
+ * 0xe300_0000	   0xe3ff_ffff	   CAN and NAND Flash	   16M
  * 0xef00_0000	   0xefff_ffff     PCI express IO          16M
  * 0xfe00_0000	   0xffff_ffff	   FLASH (boot bank)	   32M
  *
@@ -54,9 +54,9 @@
 #else /* !CONFIG_PCIE1 */
 	SET_LAW_ENTRY (5, CFG_RIO_MEM_BASE, LAW_SIZE_512M, LAW_TRGT_IF_RIO),
 #endif /* CONFIG_PCIE1 */
-#ifdef CONFIG_CAN_DRIVER
+#if defined(CONFIG_CAN_DRIVER) || defined(CONFIG_NAND)
 	SET_LAW_ENTRY (6, CFG_CAN_BASE, LAW_SIZE_16M, LAW_TRGT_IF_LBC),
-#endif /* CONFIG_CAN_DRIVER */
+#endif /* CONFIG_CAN_DRIVER || CONFIG_NAND */
 #ifdef CONFIG_PCIE1
 	SET_LAW_ENTRY (7, CFG_PCIE1_IO_BASE, LAW_SIZE_16M, LAW_TRGT_IF_PCIE_1),
 #endif /* CONFIG_PCIE */
diff --git a/board/tqc/tqm85xx/nand.c b/board/tqc/tqm85xx/nand.c
new file mode 100644
index 0000000..fe3b31f
--- /dev/null
+++ b/board/tqc/tqm85xx/nand.c
@@ -0,0 +1,469 @@
+/*
+ * (C) Copyright 2008 Wolfgang Grandegger <wg@denx.de>
+ *
+ * (C) Copyright 2006
+ * Thomas Waehner, TQ-System GmbH, thomas.waehner@tqs.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/immap_85xx.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/fsl_upm.h>
+#include <ioports.h>
+
+#include <nand.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern uint get_lbc_clock (void);
+
+/* index of UPM RAM array run pattern for NAND command cycle */
+#define	CFG_NAN_UPM_WRITE_CMD_OFS	0x08
+
+/* index of UPM RAM array run pattern for NAND address cycle */
+#define	CFG_NAND_UPM_WRITE_ADDR_OFS	0x10
+
+/* Structure for table with supported UPM timings */
+struct upm_freq {
+	ulong freq;
+	const u32 *upm_patt;
+	uchar gpl4_disable;
+	uchar ehtr;
+	uchar ead;
+};
+
+/* NAND-FLASH UPM tables for TQM85XX according to TQM8548.pq.timing.101.doc */
+
+/* UPM pattern for bus clock = 25 MHz */
+static const u32 upm_patt_25[] = {
+	/* Offset *//* UPM Read Single RAM array entry -> NAND Read Data */
+	/* 0x00 */ 0x0ff32000, 0x0fa32000, 0x3fb32005, 0xfffffc00,
+	/* 0x04 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write CMD */
+	/* 0x08 */ 0x00ff2c30, 0x00ff2c30, 0x0fff2c35, 0xfffffc00,
+	/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write ADDR */
+	/* 0x10 */ 0x00f3ec30, 0x00f3ec30, 0x0ff3ec35, 0xfffffc00,
+	/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Single RAM array entry -> NAND Write Data */
+	/* 0x18 */ 0x00f32c00, 0x00f32c00, 0x0ff32c05, 0xfffffc00,
+	/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Burst RAM array entry -> unused */
+	/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Refresh Timer RAM array entry -> unused */
+	/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Exception RAM array entry -> unsused */
+	/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+};
+
+/* UPM pattern for bus clock = 33.3 MHz */
+static const u32 upm_patt_33[] = {
+	/* Offset *//* UPM Read Single RAM array entry -> NAND Read Data */
+	/* 0x00 */ 0x0ff32000, 0x0fa32100, 0x3fb32005, 0xfffffc00,
+	/* 0x04 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write CMD */
+	/* 0x08 */ 0x00ff2c30, 0x00ff2c30, 0x0fff2c35, 0xfffffc00,
+	/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write ADDR */
+	/* 0x10 */ 0x00f3ec30, 0x00f3ec30, 0x0ff3ec35, 0xfffffc00,
+	/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Single RAM array entry -> NAND Write Data */
+	/* 0x18 */ 0x00f32c00, 0x00f32c00, 0x0ff32c05, 0xfffffc00,
+	/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Burst RAM array entry -> unused */
+	/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Refresh Timer RAM array entry -> unused */
+	/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Exception RAM array entry -> unsused */
+	/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+};
+
+/* UPM pattern for bus clock = 41.7 MHz */
+static const u32 upm_patt_42[] = {
+	/* Offset *//* UPM Read Single RAM array entry -> NAND Read Data */
+	/* 0x00 */ 0x0ff32000, 0x0fa32100, 0x3fb32005, 0xfffffc00,
+	/* 0x04 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write CMD */
+	/* 0x08 */ 0x00ff2c30, 0x00ff2c30, 0x0fff2c35, 0xfffffc00,
+	/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write ADDR */
+	/* 0x10 */ 0x00f3ec30, 0x00f3ec30, 0x0ff3ec35, 0xfffffc00,
+	/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Single RAM array entry -> NAND Write Data */
+	/* 0x18 */ 0x00f32c00, 0x00f32c00, 0x0ff32c05, 0xfffffc00,
+	/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Burst RAM array entry -> unused */
+	/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Refresh Timer RAM array entry -> unused */
+	/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Exception RAM array entry -> unsused */
+	/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+};
+
+/* UPM pattern for bus clock = 50 MHz */
+static const u32 upm_patt_50[] = {
+	/* Offset *//* UPM Read Single RAM array entry -> NAND Read Data */
+	/* 0x00 */ 0x0ff33000, 0x0fa33100, 0x0fa33005, 0xfffffc00,
+	/* 0x04 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write CMD */
+	/* 0x08 */ 0x00ff3d30, 0x00ff3c30, 0x0fff3c35, 0xfffffc00,
+	/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write ADDR */
+	/* 0x10 */ 0x00f3fd30, 0x00f3fc30, 0x0ff3fc35, 0xfffffc00,
+	/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Single RAM array entry -> NAND Write Data */
+	/* 0x18 */ 0x00f33d00, 0x00f33c00, 0x0ff33c05, 0xfffffc00,
+	/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Burst RAM array entry -> unused */
+	/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Refresh Timer RAM array entry -> unused */
+	/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Exception RAM array entry -> unsused */
+	/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+};
+
+/* UPM pattern for bus clock = 66.7 MHz */
+static const u32 upm_patt_67[] = {
+	/* Offset *//* UPM Read Single RAM array entry -> NAND Read Data */
+	/* 0x00 */ 0x0ff33000, 0x0fe33000, 0x0fa33100, 0x0fa33000,
+	/* 0x04 */ 0x0fa33005, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write CMD */
+	/* 0x08 */ 0x00ff3d30, 0x00ff3c30, 0x0fff3c30, 0x0fff3c35,
+	/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write ADDR */
+	/* 0x10 */ 0x00f3fd30, 0x00f3fc30, 0x0ff3fc30, 0x0ff3fc35,
+	/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Single RAM array entry -> NAND Write Data */
+	/* 0x18 */ 0x00f33d00, 0x00f33c00, 0x0ff33c00, 0x0ff33c05,
+	/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Burst RAM array entry -> unused */
+	/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Refresh Timer RAM array entry -> unused */
+	/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Exception RAM array entry -> unsused */
+	/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+};
+
+/* UPM pattern for bus clock = 83.3 MHz */
+static const u32 upm_patt_83[] = {
+	/* Offset *//* UPM Read Single RAM array entry -> NAND Read Data */
+	/* 0x00 */ 0x0ff33000, 0x0fe33000, 0x0fa33100, 0x0fa33000,
+	/* 0x04 */ 0x0fa33005, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write CMD */
+	/* 0x08 */ 0x00ff3e30, 0x00ff3c30, 0x0fff3c30, 0x0fff3c35,
+	/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write ADDR */
+	/* 0x10 */ 0x00f3fe30, 0x00f3fc30, 0x0ff3fc30, 0x0ff3fc35,
+	/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Single RAM array entry -> NAND Write Data */
+	/* 0x18 */ 0x00f33e00, 0x00f33c00, 0x0ff33c00, 0x0ff33c05,
+	/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Burst RAM array entry -> unused */
+	/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Refresh Timer RAM array entry -> unused */
+	/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Exception RAM array entry -> unsused */
+	/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+};
+
+/* UPM pattern for bus clock = 100 MHz */
+static const u32 upm_patt_100[] = {
+	/* Offset *//* UPM Read Single RAM array entry -> NAND Read Data */
+	/* 0x00 */ 0x0ff33100, 0x0fe33000, 0x0fa33200, 0x0fa33000,
+	/* 0x04 */ 0x0fa33005, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write CMD */
+	/* 0x08 */ 0x00ff3f30, 0x00ff3c30, 0x0fff3c30, 0x0fff3c35,
+	/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write ADDR */
+	/* 0x10 */ 0x00f3ff30, 0x00f3fc30, 0x0ff3fc30, 0x0ff3fc35,
+	/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Single RAM array entry -> NAND Write Data */
+	/* 0x18 */ 0x00f33f00, 0x00f33c00, 0x0ff33c00, 0x0ff33c05,
+	/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Burst RAM array entry -> unused */
+	/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Refresh Timer RAM array entry -> unused */
+	/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Exception RAM array entry -> unsused */
+	/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+};
+
+/* UPM pattern for bus clock = 133.3 MHz */
+static const u32 upm_patt_133[] = {
+	/* Offset *//* UPM Read Single RAM array entry -> NAND Read Data */
+	/* 0x00 */ 0x0ff33100, 0x0fe33000, 0x0fa33300, 0x0fa33000,
+	/* 0x04 */ 0x0fa33000, 0x0fa33005, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write CMD */
+	/* 0x08 */ 0x00ff3f30, 0x00ff3d30, 0x0fff3d30, 0x0fff3c35,
+	/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write ADDR */
+	/* 0x10 */ 0x00f3ff30, 0x00f3fd30, 0x0ff3fd30, 0x0ff3fc35,
+	/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Single RAM array entry -> NAND Write Data */
+	/* 0x18 */ 0x00f33f00, 0x00f33d00, 0x0ff33d00, 0x0ff33c05,
+	/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Burst RAM array entry -> unused */
+	/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Refresh Timer RAM array entry -> unused */
+	/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Exception RAM array entry -> unsused */
+	/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+};
+
+/* UPM pattern for bus clock = 166.7 MHz */
+static const u32 upm_patt_167[] = {
+	/* Offset *//* UPM Read Single RAM array entry -> NAND Read Data */
+	/* 0x00 */ 0x0ff33200, 0x0fe33000, 0x0fa33300, 0x0fa33300,
+	/* 0x04 */ 0x0fa33005, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write CMD */
+	/* 0x08 */ 0x00ff3f30, 0x00ff3f30, 0x0fff3e30, 0xffff3c35,
+	/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Read Burst RAM array entry -> NAND Write ADDR */
+	/* 0x10 */ 0x00f3ff30, 0x00f3ff30, 0x0ff3fe30, 0x0ff3fc35,
+	/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Single RAM array entry -> NAND Write Data */
+	/* 0x18 */ 0x00f33f00, 0x00f33f00, 0x0ff33e00, 0x0ff33c05,
+	/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+
+	/* UPM Write Burst RAM array entry -> unused */
+	/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Refresh Timer RAM array entry -> unused */
+	/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
+	/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+
+	/* UPM Exception RAM array entry -> unsused */
+	/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
+};
+
+/* Supported UPM timings */
+struct upm_freq upm_freq_table[] = {
+	/* nominal freq. | ptr to table | GPL4 dis. | EHTR  | EAD */
+	{25000000, upm_patt_25, 1, 0, 0},
+	{33333333, upm_patt_33, 1, 0, 0},
+	{41666666, upm_patt_42, 1, 0, 0},
+	{50000000, upm_patt_50, 0, 0, 0},
+	{66666666, upm_patt_67, 0, 0, 0},
+	{83333333, upm_patt_83, 0, 0, 0},
+	{100000000, upm_patt_100, 0, 1, 1},
+	{133333333, upm_patt_133, 0, 1, 1},
+	{166666666, upm_patt_167, 0, 1, 1},
+};
+
+#define UPM_FREQS (sizeof(upm_freq_table) / sizeof(struct upm_freq))
+
+volatile const u32 *nand_upm_patt;
+
+/*
+ * write into UPMB ram
+ */
+static void upmb_write (u_char addr, ulong val)
+{
+	volatile ccsr_lbc_t *lbc = (void *)(CFG_MPC85xx_LBC_ADDR);
+
+	out_be32 (&lbc->mdr, val);
+
+	clrsetbits_be32(&lbc->mbmr, MxMR_MAD_MSK,
+			MxMR_OP_WARR | (addr & MxMR_MAD_MSK));
+
+	/* dummy access to perform write */
+	out_8 ((void __iomem *)CFG_NAND0_BASE, 0);
+
+	clrbits_be32(&lbc->mbmr, MxMR_OP_WARR);
+}
+
+/*
+ * Initialize UPM for NAND flash access.
+ */
+static void nand_upm_setup (volatile ccsr_lbc_t *lbc)
+{
+	uint i;
+	uint or3 = CFG_OR3_PRELIM;
+	uint clock = get_lbc_clock ();
+
+	out_be32 (&lbc->br3, 0);	/* disable bank and reset all bits */
+	out_be32 (&lbc->br3, CFG_BR3_PRELIM);
+
+	/*
+	 * Search appropriate UPM table for bus clock.
+	 * If the bus clock exceeds a tolerated value, take the UPM timing for
+	 * the next higher supported frequency to ensure that access works
+	 * (even the access may be slower then).
+	 */
+	for (i = 0; (i < UPM_FREQS) && (clock > upm_freq_table[i].freq); i++)
+		;
+
+	if (i >= UPM_FREQS)
+	/* no valid entry found */
+		/* take last entry with configuration for max. bus clock */
+		i--;
+
+	if (upm_freq_table[i].ehtr) {
+		/* EHTR must be set due to TQM8548 timing specification */
+		or3 |= OR_UPM_EHTR;
+	}
+	if (upm_freq_table[i].ead)
+		/* EAD must be set due to TQM8548 timing specification */
+		or3 |= OR_UPM_EAD;
+
+	out_be32 (&lbc->or3, or3);
+
+	/* Assign address of table */
+	nand_upm_patt = upm_freq_table[i].upm_patt;
+
+	for (i = 0; i < 64; i++) {
+		upmb_write (i, *nand_upm_patt);
+		nand_upm_patt++;
+	}
+
+	/* Put UPM back to normal operation mode */
+	if (upm_freq_table[i].gpl4_disable)
+		/* GPL4 must be disabled according to timing specification */
+		out_be32 (&lbc->mbmr, MxMR_OP_NORM | MxMR_GPL_x4DIS);
+
+	return;
+}
+
+static struct fsl_upm_nand fun = {
+	.width = 8,
+	.upm_cmd_offset = 0x08,
+	.upm_addr_offset = 0x10,
+	.chip_delay = NAND_BIG_DELAY_US,
+};
+
+void board_nand_select_device (struct nand_chip *nand, int chip)
+{
+}
+
+int board_nand_init (struct nand_chip *nand)
+{
+	volatile ccsr_lbc_t *lbc = (void *)(CFG_MPC85xx_LBC_ADDR);
+
+	if (!nand_upm_patt)
+		nand_upm_setup (lbc);
+
+	fun.upm.io_addr = nand->IO_ADDR_R;
+	fun.upm.mxmr = (void __iomem *)&lbc->mbmr;
+	fun.upm.mdr = (void __iomem *)&lbc->mdr;
+	fun.upm.mar = (void __iomem *)&lbc->mar;
+
+	return fsl_upm_nand_init (nand, &fun);
+}
diff --git a/board/tqc/tqm85xx/tlb.c b/board/tqc/tqm85xx/tlb.c
index 7c4b9a1..7f4efc1 100644
--- a/board/tqc/tqm85xx/tlb.c
+++ b/board/tqc/tqm85xx/tlb.c
@@ -114,7 +114,7 @@
 	 * TLB 6:	 64M	Non-cacheable, guarded
 	 * 0xe0000000	  1M	CCSRBAR
 	 * 0xe2000000	 16M	PCI1 IO
-	 * 0xe3000000	 16M	CAN
+	 * 0xe3000000	 16M	CAN and NAND Flash
 	 */
 	SET_TLB_ENTRY (1, CFG_CCSRBAR, CFG_CCSRBAR_PHYS,
 		       MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
diff --git a/include/configs/TQM85xx.h b/include/configs/TQM85xx.h
index 2155130..b188adf 100644
--- a/include/configs/TQM85xx.h
+++ b/include/configs/TQM85xx.h
@@ -55,6 +55,14 @@
 #define CONFIG_MISC_INIT_R	1	/* Call misc_init_r		*/
 
 /*
+ * NAND flash support (disabled by default)
+ *
+ * Warning: NAND support will likely increase the U-Boot image size
+ * to more than 256 KB. Please adjust TEXT_BASE if necessary.
+ */
+#undef CONFIG_NAND
+
+/*
  * MPC8540 and MPC8548 don't have CPM module
  */
 #if !defined(CONFIG_MPC8540) && !defined(CONFIG_MPC8548)
@@ -205,8 +213,8 @@
 #define CFG_GBL_DATA_OFFSET	(CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
 #define CFG_INIT_SP_OFFSET	CFG_GBL_DATA_OFFSET
 
-#define CFG_MONITOR_LEN		(256 * 1024)	/* Reserve 256kB for Mon */
-#define CFG_MALLOC_LEN		(256 * 1024)	/* Reserved for malloc	*/
+#define CFG_MONITOR_LEN		(~TEXT_BASE + 1)/* Reserved for Monitor	*/
+#define CFG_MALLOC_LEN		(384 * 1024)	/* Reserved for malloc	*/
 
 /* Serial Port */
 #if defined(CONFIG_TQM8560)
@@ -253,8 +261,8 @@
 #define CONFIG_OF_STDOUT_VIA_ALIAS	1
 
 /* CAN */
-#ifdef CONFIG_CAN_DRIVER
 #define CFG_CAN_BASE		0xE3000000	/* CAN base address     */
+#ifdef CONFIG_CAN_DRIVER
 #define CFG_CAN_OR_AM		0xFFFF8000	/* 32 KiB address mask  */
 #define CFG_OR2_CAN		(CFG_CAN_OR_AM | OR_UPM_BI)
 #define CFG_BR2_CAN		((CFG_CAN_BASE & BR_BA) | \
@@ -301,6 +309,53 @@
 #define CFG_RIO_MEM_SIZE	0x20000000	/* 512M			*/
 #endif /* CONFIG_PCIE1 */
 
+/* NAND FLASH */
+#ifdef CONFIG_NAND
+
+#undef CFG_NAND_LEGACY
+
+#define CONFIG_NAND_FSL_UPM	1
+
+#define	CONFIG_MTD_NAND_ECC_JFFS2	1	/* use JFFS2 ECC	*/
+
+/* address distance between chip selects */
+#define	CFG_NAND_SELECT_DEVICE	1
+#define	CFG_NAND_CS_DIST	0x200
+
+#define CFG_NAND_SIZE		0x8000
+#define CFG_NAND0_BASE		0xE3010000
+#define CFG_NAND1_BASE		(CFG_NAND0_BASE + CFG_NAND_CS_DIST)
+#define CFG_NAND2_BASE		(CFG_NAND1_BASE + CFG_NAND_CS_DIST)
+#define CFG_NAND3_BASE		(CFG_NAND2_BASE + CFG_NAND_CS_DIST)
+
+#define CFG_MAX_NAND_DEVICE     2	/* Max number of NAND devices	*/
+#define NAND_MAX_CHIPS		1
+
+#if (CFG_MAX_NAND_DEVICE == 1)
+#define CFG_NAND_BASE_LIST { CFG_NAND0_BASE }
+#elif (CFG_MAX_NAND_DEVICE == 2)
+#define	CFG_NAND_QUIET_TEST	1
+#define CFG_NAND_BASE_LIST { CFG_NAND0_BASE, \
+			     CFG_NAND1_BASE, \
+}
+#elif (CFG_MAX_NAND_DEVICE == 4)
+#define	CFG_NAND_QUIET_TEST	1
+#define CFG_NAND_BASE_LIST { CFG_NAND0_BASE, \
+			     CFG_NAND1_BASE, \
+			     CFG_NAND2_BASE, \
+			     CFG_NAND3_BASE, \
+}
+#endif
+
+/* CS3 for NAND Flash */
+#define CFG_BR3_PRELIM		((CFG_NAND0_BASE & BR_BA) | BR_PS_8 | \
+				 BR_MS_UPMB | BR_V)
+#define CFG_OR3_PRELIM		(P2SZ_TO_AM(CFG_NAND_SIZE) | OR_UPM_BI)
+
+#define NAND_BIG_DELAY_US       25	/* max tR for Samsung devices	*/
+
+#endif /* CONFIG_NAND */
+
 /*
  * General PCI
  * Addresses are mapped 1-1.
@@ -486,6 +541,26 @@
 #define CONFIG_BOOTP_GATEWAY
 #define CONFIG_BOOTP_HOSTNAME
 
+#ifdef CONFIG_NAND
+/*
+ * Use NAND-FLash as JFFS2 device
+ */
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_JFFS2
+
+#define	CONFIG_JFFS2_NAND	1
+
+#ifdef CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT		"nand0=TQM85xx-nand"
+#define MTDPARTS_DEFAULT	"mtdparts=TQM85xx-nand:-"
+#else
+#define CONFIG_JFFS2_DEV 	"nand0"	/* NAND device jffs2 lives on	*/
+#define CONFIG_JFFS2_PART_OFFSET 0	/* start of jffs2 partition	*/
+#define CONFIG_JFFS2_PART_SIZE	0x200000 /* size of jffs2 partition	*/
+#endif /* CONFIG_JFFS2_CMDLINE */
+
+#endif /* CONFIG_NAND */
+
 /*
  * Command line configuration.
  */