Initial revision
diff --git a/board/c2mon/flash.c b/board/c2mon/flash.c
new file mode 100644
index 0000000..181f82a
--- /dev/null
+++ b/board/c2mon/flash.c
@@ -0,0 +1,570 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+#ifndef	CFG_ENV_ADDR
+#define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+#endif
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+	size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+
+	if (size_b1 > size_b0) {
+		printf ("## ERROR: "
+			"Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
+			size_b1, size_b1<<20,
+			size_b0, size_b0<<20
+		);
+		flash_info[0].flash_id	= FLASH_UNKNOWN;
+		flash_info[1].flash_id	= FLASH_UNKNOWN;
+		flash_info[0].sector_count	= -1;
+		flash_info[1].sector_count	= -1;
+		flash_info[0].size		= 0;
+		flash_info[1].size		= 0;
+		return (0);
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK);
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+	/* ENV protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR+CFG_ENV_SIZE-1,
+		      &flash_info[0]);
+#endif
+
+	if (size_b1) {
+		memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
+		memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
+				    BR_MS_GPCM | BR_V;
+
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0),
+					  &flash_info[1]);
+
+		flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+		/* monitor protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_MONITOR_BASE,
+			      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+			      &flash_info[1]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+		/* ENV protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_ENV_ADDR,
+			      CFG_ENV_ADDR+CFG_ENV_SIZE-1,
+			      &flash_info[1]);
+#endif
+	} else {
+		memctl->memc_br1 = 0;		/* invalidate bank */
+
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+	}
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	ulong value;
+	ulong base = (ulong)addr;
+
+	/* Write auto select command: read Manufacturer ID */
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00900090;
+
+	value = addr[0];
+
+	switch (value) {
+	case AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	switch (value) {
+	case AMD_ID_LV400T:
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV400B:
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV800T:
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV800B:
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV160T:
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case AMD_ID_LV160B:
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+	case AMD_ID_LV320T:
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case AMD_ID_LV320B:
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+#endif
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+	}
+
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr = (volatile unsigned long *)(info->start[i]);
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (volatile unsigned long *)info->start[0];
+
+		*addr = 0x00F000F0;	/* reset bank */
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    (info->flash_id > FLASH_AMD_COMP)) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00800080;
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (vu_long*)(info->start[sect]);
+			addr[0] = 0x00300030;
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (vu_long*)(info->start[l_sect]);
+	while ((addr[0] & 0x00800080) != 0x00800080) {
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (volatile unsigned long *)info->start[0];
+	addr[0] = 0x00F000F0;	/* reset bank */
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *)dest) & data) != data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00A000A0;
+
+	*((vu_long *)dest) = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/cogent/dipsw.c b/board/cogent/dipsw.c
new file mode 100644
index 0000000..d2027c9
--- /dev/null
+++ b/board/cogent/dipsw.c
@@ -0,0 +1,50 @@
+#include <common.h>
+#include <board/cogent/dipsw.h>
+
+unsigned char
+dipsw_raw(void)
+{
+    return cma_mb_reg_read(&((cma_mb_dipsw *)CMA_MB_DIPSW_BASE)->dip_val);
+}
+
+unsigned char
+dipsw_cooked(void)
+{
+    unsigned char val1, val2, mask1, mask2;
+
+    val1 = dipsw_raw();
+
+    /*
+     * we want to mirror the bits because the low bit is switch 1 and high
+     * bit is switch 8 and also invert them because 1=off and 0=on, according
+     * to manual.
+     *
+     * this makes the value more intuitive i.e.
+     * - left most, or high, or top, bit is left most switch (1);
+     * - right most, or low, or bottom, bit is right most switch (8)
+     * - a set bit means "on" and a clear bit means "off"
+     */
+
+    val2 = 0;
+    for (mask1 = 1 << 7, mask2 = 1; mask1 > 0; mask1 >>= 1, mask2 <<= 1)
+	if ((val1 & mask1) == 0)
+	    val2 |= mask2;
+
+    return (val2);
+}
+
+void
+dipsw_init(void)
+{
+    unsigned char val, mask;
+
+    val = dipsw_cooked();
+
+    printf("|");
+    for (mask = 1 << 7; mask > 0; mask >>= 1)
+	if (val & mask)
+	    printf("on |");
+	else
+	    printf("off|");
+    printf("\n");
+}
diff --git a/board/cogent/flash.c b/board/cogent/flash.c
new file mode 100644
index 0000000..86da80e
--- /dev/null
+++ b/board/cogent/flash.c
@@ -0,0 +1,648 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <board/cogent/flash.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+
+/*-----------------------------------------------------------------------
+ */
+
+
+#if defined(CONFIG_CMA302)
+
+/*
+ * probe for the existence of flash at address "addr"
+ * 0 = yes, 1 = bad Manufacturer's Id, 2 = bad Device Id
+ */
+static int
+c302f_probe_word(c302f_addr_t addr)
+{
+	/* reset the flash */
+	*addr = C302F_BNK_CMD_RST;
+
+	/* check the manufacturer id */
+	*addr = C302F_BNK_CMD_RD_ID;
+	if (*C302F_BNK_ADDR_MAN(addr) != C302F_BNK_RD_ID_MAN)
+		return 1;
+
+	/* check the device id */
+	*addr = C302F_BNK_CMD_RD_ID;
+	if (*C302F_BNK_ADDR_DEV(addr) != C302F_BNK_RD_ID_DEV)
+		return 2;
+
+#ifdef FLASH_DEBUG
+	{
+		int i;
+
+		printf("\nMaster Lock Config = 0x%08lx\n",
+			*C302F_BNK_ADDR_CFGM(addr));
+		for (i = 0; i < C302F_BNK_NBLOCKS; i++)
+			printf("Block %2d Lock Config = 0x%08lx\n",
+				i, *C302F_BNK_ADDR_CFG(i, addr));
+	}
+#endif
+
+	/* reset the flash again */
+	*addr = C302F_BNK_CMD_RST;
+
+	return 0;
+}
+
+/*
+ * probe for Cogent CMA302 flash module at address "base" and store
+ * info for any found into flash_info entry "fip". Must find at least
+ * one bank.
+ */
+static void
+c302f_probe(flash_info_t *fip, c302f_addr_t base)
+{
+	c302f_addr_t addr, eaddr;
+	int nbanks;
+
+	fip->size = 0L;
+	fip->sector_count = 0;
+
+	addr = base;
+	eaddr = C302F_BNK_ADDR_BASE(addr, C302F_MAX_BANKS);
+	nbanks = 0;
+
+	while (addr < eaddr) {
+		c302f_addr_t addrw, eaddrw, addrb;
+		int i, osc, nsc;
+
+		addrw = addr;
+		eaddrw = C302F_BNK_ADDR_NEXT_WORD(addrw);
+
+		while (addrw < eaddrw)
+			if (c302f_probe_word(addrw++) != 0)
+				goto out;
+
+		/* bank exists - append info for this bank to *fip */
+		fip->flash_id = FLASH_MAN_INTEL|FLASH_28F008S5;
+		fip->size += C302F_BNK_SIZE;
+		osc = fip->sector_count;
+		fip->sector_count += C302F_BNK_NBLOCKS;
+		if ((nsc = fip->sector_count) >= CFG_MAX_FLASH_SECT)
+			panic("Too many sectors in flash at address 0x%08lx\n",
+				(unsigned long)base);
+
+		addrb = addr;
+		for (i = osc; i < nsc; i++) {
+			fip->start[i] = (ulong)addrb;
+			fip->protect[i] = 0;
+			addrb = C302F_BNK_ADDR_NEXT_BLK(addrb);
+		}
+
+		addr = C302F_BNK_ADDR_NEXT_BNK(addr);
+		nbanks++;
+	}
+
+out:
+	if (nbanks == 0)
+		panic("ERROR: no flash found at address 0x%08lx\n",
+			(unsigned long)base);
+}
+
+static void
+c302f_reset(flash_info_t *info, int sect)
+{
+	c302f_addr_t addrw, eaddrw;
+
+	addrw = (c302f_addr_t)info->start[sect];
+	eaddrw = C302F_BNK_ADDR_NEXT_WORD(addrw);
+
+	while (addrw < eaddrw) {
+#ifdef FLASH_DEBUG
+		printf("  writing reset cmd to addr 0x%08lx\n",
+			(unsigned long)addrw);
+#endif
+		*addrw = C302F_BNK_CMD_RST;
+		addrw++;
+	}
+}
+
+static void
+c302f_erase_init(flash_info_t *info, int sect)
+{
+	c302f_addr_t addrw, saddrw, eaddrw;
+	int flag;
+
+#ifdef FLASH_DEBUG
+	printf("0x%08lx C302F_BNK_CMD_PROG\n", C302F_BNK_CMD_PROG);
+	printf("0x%08lx C302F_BNK_CMD_ERASE1\n", C302F_BNK_CMD_ERASE1);
+	printf("0x%08lx C302F_BNK_CMD_ERASE2\n", C302F_BNK_CMD_ERASE2);
+	printf("0x%08lx C302F_BNK_CMD_CLR_STAT\n", C302F_BNK_CMD_CLR_STAT);
+	printf("0x%08lx C302F_BNK_CMD_RST\n", C302F_BNK_CMD_RST);
+	printf("0x%08lx C302F_BNK_STAT_RDY\n", C302F_BNK_STAT_RDY);
+	printf("0x%08lx C302F_BNK_STAT_ERR\n", C302F_BNK_STAT_ERR);
+#endif
+
+	saddrw = (c302f_addr_t)info->start[sect];
+	eaddrw = C302F_BNK_ADDR_NEXT_WORD(saddrw);
+
+#ifdef FLASH_DEBUG
+	printf("erasing sector %d, start addr = 0x%08lx "
+		"(bank next word addr = 0x%08lx)\n", sect,
+		(unsigned long)saddrw, (unsigned long)eaddrw);
+#endif
+
+	/* Disable intrs which might cause a timeout here */
+	flag = disable_interrupts();
+
+	for (addrw = saddrw; addrw < eaddrw; addrw++) {
+#ifdef FLASH_DEBUG
+		printf("  writing erase cmd to addr 0x%08lx\n",
+			(unsigned long)addrw);
+#endif
+		*addrw = C302F_BNK_CMD_ERASE1;
+		*addrw = C302F_BNK_CMD_ERASE2;
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+}
+
+static int
+c302f_erase_poll(flash_info_t *info, int sect)
+{
+	c302f_addr_t addrw, saddrw, eaddrw;
+	int sectdone, haderr;
+
+	saddrw = (c302f_addr_t)info->start[sect];
+	eaddrw = C302F_BNK_ADDR_NEXT_WORD(saddrw);
+
+	sectdone = 1;
+	haderr = 0;
+
+	for (addrw = saddrw; addrw < eaddrw; addrw++) {
+		c302f_word_t stat = *addrw;
+
+#ifdef FLASH_DEBUG
+		printf("  checking status at addr "
+			"0x%08lx [0x%08lx]\n",
+			(unsigned long)addrw, stat);
+#endif
+		if ((stat & C302F_BNK_STAT_RDY) != C302F_BNK_STAT_RDY)
+			sectdone = 0;
+		else if ((stat & C302F_BNK_STAT_ERR) != 0) {
+			printf(" failed on sector %d "
+				"(stat = 0x%08lx) at "
+				"address 0x%08lx\n",
+				sect, stat,
+				(unsigned long)addrw);
+			*addrw = C302F_BNK_CMD_CLR_STAT;
+			haderr = 1;
+		}
+	}
+
+	if (haderr)
+		return (-1);
+	else
+		return (sectdone);
+}
+
+static int
+c302f_write_word(c302f_addr_t addr, c302f_word_t value)
+{
+	c302f_word_t stat;
+	ulong start;
+	int flag, retval;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	*addr = C302F_BNK_CMD_PROG;
+
+	*addr = value;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	retval = 0;
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	do {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			retval = 1;
+			goto done;
+		}
+		stat = *addr;
+	} while ((stat & C302F_BNK_STAT_RDY) != C302F_BNK_STAT_RDY);
+
+	if ((stat & C302F_BNK_STAT_ERR) != 0) {
+		printf("flash program failed (stat = 0x%08lx) "
+			"at address 0x%08lx\n", (ulong)stat, (ulong)addr);
+		*addr = C302F_BNK_CMD_CLR_STAT;
+		retval = 3;
+	}
+
+done:
+	/* reset to read mode */
+	*addr = C302F_BNK_CMD_RST;
+
+	return (retval);
+}
+
+#endif	/* CONFIG_CMA302 */
+
+unsigned long
+flash_init(void)
+{
+	unsigned long total;
+	int i;
+	flash_info_t *fip;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	fip = &flash_info[0];
+	total = 0L;
+
+#if defined(CONFIG_CMA302)
+	c302f_probe(fip, (c302f_addr_t)CFG_FLASH_BASE);
+	total += fip->size;
+	fip++;
+#endif
+
+#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
+	/* not yet ...
+	cmbf_probe(fip, (cmbf_addr_t)CMA_MB_FLASH_BASE);
+	total += fip->size;
+	fip++;
+	*/
+#endif
+
+	/*
+	 * protect monitor and environment sectors
+	 */
+
+#if CFG_MONITOR_BASE == CFG_FLASH_BASE
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+	/* ENV protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+		      &flash_info[0]);
+#endif
+	return total;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void
+flash_print_info(flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_INTEL:	printf ("INTEL ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_28F008S5:	printf ("28F008S5\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 4) == 0)
+			printf ("\n   ");
+		printf (" %2d - %08lX%s", i,
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+int
+flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+	int prot, sect, haderr;
+	ulong start, now, last;
+	void (*erase_init)(flash_info_t *, int);
+	int (*erase_poll)(flash_info_t *, int);
+	void (*reset)(flash_info_t *, int);
+	int rcode = 0;
+
+#ifdef FLASH_DEBUG
+	printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
+		"  Bank # %d: ", s_last - s_first + 1, s_first, s_last,
+		(info - flash_info) + 1);
+	flash_print_info(info);
+#endif
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	switch (info->flash_id) {
+
+#if defined(CONFIG_CMA302)
+	case FLASH_MAN_INTEL|FLASH_28F008S5:
+		erase_init = c302f_erase_init;
+		erase_poll = c302f_erase_poll;
+		reset = c302f_reset;
+		break;
+#endif
+
+#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
+	case FLASH_MAN_INTEL|FLASH_28F800_B:
+	case FLASH_MAN_AMD|FLASH_AM29F800B:
+		/* not yet ...
+		erase_init = cmbf_erase_init;
+		erase_poll = cmbf_erase_poll;
+		reset = cmbf_reset;
+		break;
+		*/
+#endif
+
+	default:
+		printf ("Flash type %08lx not supported - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf("- Warning: %d protected sector%s will not be erased!\n",
+			prot, (prot > 1 ? "s" : ""));
+	}
+
+	start = get_timer (0);
+	last = 0;
+	haderr = 0;
+
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			ulong estart;
+			int sectdone;
+
+			(*erase_init)(info, sect);
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+
+			estart = get_timer(start);
+
+			do {
+				now = get_timer(start);
+
+				if (now - estart > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout (sect %d)\n", sect);
+					haderr = 1;
+					break;
+				}
+
+#ifndef FLASH_DEBUG
+				/* show that we're waiting */
+				if ((now - last) > 1000) { /* every second */
+					putc ('.');
+					last = now;
+				}
+#endif
+
+				sectdone = (*erase_poll)(info, sect);
+
+				if (sectdone < 0) {
+					haderr = 1;
+					break;
+				}
+
+			} while (!sectdone);
+
+			if (haderr)
+				break;
+		}
+	}
+
+	if (haderr > 0) {
+		printf (" failed\n");
+	        rcode = 1;
+	}
+	else
+		printf (" done\n");
+
+	/* reset to read mode */
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			(*reset)(info, sect);
+		}
+	}
+	return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 3 - write error
+ */
+
+int
+write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+	ulong start, now, last;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	start = get_timer (0);
+	last = 0;
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+
+		/* show that we're waiting */
+		now = get_timer(start);
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 3 - write error
+ */
+static int
+write_word(flash_info_t *info, ulong dest, ulong data)
+{
+	int retval;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*(ulong *)dest & data) != data) {
+		return (2);
+	}
+
+	switch (info->flash_id) {
+
+#if defined(CONFIG_CMA302)
+	case FLASH_MAN_INTEL|FLASH_28F008S5:
+		retval = c302f_write_word((c302f_addr_t)dest, (c302f_word_t)data);
+		break;
+#endif
+
+#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
+	case FLASH_MAN_INTEL|FLASH_28F800_B:
+	case FLASH_MAN_AMD|FLASH_AM29F800B:
+		/* not yet ...
+		retval = cmbf_write_word((cmbf_addr_t)dest, (cmbf_word_t)data);
+		*/
+		retval = 3;
+		break;
+#endif
+
+	default:
+		printf ("Flash type %08lx not supported - aborted\n",
+			info->flash_id);
+		retval = 3;
+		break;
+	}
+
+	return (retval);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/cu824/flash.c b/board/cu824/flash.c
new file mode 100644
index 0000000..0cec41e
--- /dev/null
+++ b/board/cu824/flash.c
@@ -0,0 +1,486 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc824x.h>
+#include <asm/processor.h>
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+#define FLASH_BANK_SIZE 0x800000
+#define MAIN_SECT_SIZE  0x40000
+#define PARAM_SECT_SIZE 0x8000
+
+#define BOARD_CTRL_REG 0xFE800013
+
+flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
+
+static int write_data (flash_info_t *info, ulong dest, ulong *data);
+static void write_via_fpu(vu_long *addr, ulong *data);
+static __inline__ unsigned long get_msr(void);
+static __inline__ void set_msr(unsigned long msr);
+
+/*---------------------------------------------------------------------*/
+#undef	DEBUG_FLASH
+
+/*---------------------------------------------------------------------*/
+#ifdef DEBUG_FLASH
+#define DEBUGF(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGF(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init(void)
+{
+    int i, j;
+    ulong size = 0;
+    volatile unsigned char *bcr = (volatile unsigned char *)(BOARD_CTRL_REG);
+
+    DEBUGF("Write protect was: 0x%02X\n", *bcr);
+    *bcr &= 0x1;	/* FWPT must be 0  */
+    *bcr |= 0x6;	/* FWP0 = FWP1 = 1 */
+    DEBUGF("Write protect is:  0x%02X\n", *bcr);
+
+    for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+    	vu_long *addr = (vu_long *)(CFG_FLASH_BASE + i * FLASH_BANK_SIZE);
+
+	addr[0] = 0x00900090;
+
+	DEBUGF ("Flash bank # %d:\n"
+		"\tManuf. ID @ 0x%08lX: 0x%08lX\n"
+		"\tDevice ID @ 0x%08lX: 0x%08lX\n",
+		i,
+		(ulong)(&addr[0]), addr[0],
+		(ulong)(&addr[2]), addr[2]);
+
+	if ((addr[0] == addr[1]) && (addr[0] == INTEL_MANUFACT) &&
+	    (addr[2] == addr[3]) && (addr[2] == INTEL_ID_28F160F3B))
+	{
+	    flash_info[i].flash_id = (FLASH_MAN_INTEL & FLASH_VENDMASK) |
+	    			     (INTEL_ID_28F160F3B & FLASH_TYPEMASK);
+	} else {
+	    flash_info[i].flash_id = FLASH_UNKNOWN;
+	    addr[0] = 0xFFFFFFFF;
+	    goto Done;
+	}
+
+	DEBUGF ("flash_id = 0x%08lX\n", flash_info[i].flash_id);
+
+	addr[0] = 0xFFFFFFFF;
+
+	flash_info[i].size = FLASH_BANK_SIZE;
+	flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
+	memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
+	for (j = 0; j < flash_info[i].sector_count; j++) {
+		if (j <= 7) {
+			flash_info[i].start[j] = CFG_FLASH_BASE +
+			                         i * FLASH_BANK_SIZE +
+			                         j * PARAM_SECT_SIZE;
+		} else {
+			flash_info[i].start[j] = CFG_FLASH_BASE +
+			                         i * FLASH_BANK_SIZE +
+			                         (j - 7)*MAIN_SECT_SIZE;
+		}
+	}
+	size += flash_info[i].size;
+    }
+
+    /* Protect monitor and environment sectors
+     */
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE + FLASH_BANK_SIZE
+    flash_protect(FLAG_PROTECT_SET,
+              CFG_MONITOR_BASE,
+              CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1,
+              &flash_info[1]);
+#else
+    flash_protect(FLAG_PROTECT_SET,
+              CFG_MONITOR_BASE,
+              CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1,
+              &flash_info[0]);
+#endif
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+#if CFG_ENV_ADDR >= CFG_FLASH_BASE + FLASH_BANK_SIZE
+    flash_protect(FLAG_PROTECT_SET,
+              CFG_ENV_ADDR,
+              CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+              &flash_info[1]);
+#else
+    flash_protect(FLAG_PROTECT_SET,
+              CFG_ENV_ADDR,
+              CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+              &flash_info[0]);
+#endif
+#endif
+
+Done:
+    return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+	int i;
+
+	switch ((i = info->flash_id & FLASH_VENDMASK)) {
+	case (FLASH_MAN_INTEL & FLASH_VENDMASK):
+		printf ("Intel: ");
+		break;
+	default:
+		printf ("Unknown Vendor 0x%04x ", i);
+		break;
+	}
+
+	switch ((i = info->flash_id & FLASH_TYPEMASK)) {
+	case (INTEL_ID_28F160F3B & FLASH_TYPEMASK):
+		printf ("28F160F3B (16Mbit)\n");
+		break;
+	default:
+		printf ("Unknown Chip Type 0x%04x\n", i);
+		goto Done;
+		break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+			info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i = 0; i < info->sector_count; i++) {
+		if ((i % 5) == 0) {
+			printf ("\n   ");
+		}
+		printf (" %08lX%s", info->start[i],
+				info->protect[i] ? " (RO)" : "     ");
+	}
+	printf ("\n");
+
+Done:
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	int flag, prot, sect;
+	ulong start, now, last;
+
+	DEBUGF ("Erase flash bank %d sect %d ... %d\n",
+		info - &flash_info[0], s_first, s_last);
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) !=
+	    (FLASH_MAN_INTEL & FLASH_VENDMASK)) {
+		printf ("Can erase only Intel flash types - aborted\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	start = get_timer (0);
+	last  = start;
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			vu_long *addr = (vu_long *)(info->start[sect]);
+
+			DEBUGF ("Erase sect %d @ 0x%08lX\n",
+				sect, (ulong)addr);
+
+			/* Disable interrupts which might cause a timeout
+			 * here.
+			 */
+			flag = disable_interrupts();
+
+			addr[0] = 0x00500050;	/* clear status register */
+			addr[0] = 0x00200020;	/* erase setup */
+			addr[0] = 0x00D000D0;	/* erase confirm */
+
+			addr[1] = 0x00500050;	/* clear status register */
+			addr[1] = 0x00200020;	/* erase setup */
+			addr[1] = 0x00D000D0;	/* erase confirm */
+
+			/* re-enable interrupts if necessary */
+			if (flag)
+				enable_interrupts();
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+
+			while (((addr[0] & 0x00800080) != 0x00800080) ||
+			       ((addr[1] & 0x00800080) != 0x00800080) ) {
+				if ((now=get_timer(start)) >
+				           CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout\n");
+					addr[0] = 0x00B000B0; /* suspend erase */
+					addr[0] = 0x00FF00FF; /* to read mode  */
+					return 1;
+				}
+
+				/* show that we're waiting */
+				if ((now - last) > 1000) {  /* every second  */
+					putc ('.');
+					last = now;
+				}
+			}
+
+			addr[0] = 0x00FF00FF;
+		}
+	}
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 4 - Flash not identified
+ */
+
+#define	FLASH_WIDTH	8	/* flash bus width in bytes */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong wp, cp, msr;
+	int l, rc, i;
+	ulong data[2];
+	ulong *datah = &data[0];
+	ulong *datal = &data[1];
+
+	DEBUGF ("Flash write_buff: @ 0x%08lx, src 0x%08lx len %ld\n",
+		addr, (ulong)src, cnt);
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return 4;
+	}
+
+	msr = get_msr();
+	set_msr(msr | MSR_FP);
+
+	wp = (addr & ~(FLASH_WIDTH-1));	/* get lower aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		*datah = *datal = 0;
+
+		for (i = 0, cp = wp; i < l; i++, cp++) {
+			if (i >= 4) {
+				*datah = (*datah << 8) |
+				                ((*datal & 0xFF000000) >> 24);
+			}
+
+			*datal = (*datal << 8) | (*(uchar *)cp);
+		}
+		for (; i < FLASH_WIDTH && cnt > 0; ++i) {
+			char tmp;
+
+			tmp = *src;
+
+			src++;
+
+			if (i >= 4) {
+				*datah = (*datah << 8) |
+			                        ((*datal & 0xFF000000) >> 24);
+			}
+
+			*datal = (*datal << 8) | tmp;
+
+			--cnt; ++cp;
+		}
+
+		for (; cnt == 0 && i < FLASH_WIDTH; ++i, ++cp) {
+			if (i >= 4) {
+				*datah = (*datah << 8) |
+				                ((*datal & 0xFF000000) >> 24);
+			}
+
+			*datal = (*datah << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_data(info, wp, data)) != 0) {
+			set_msr(msr);
+			return (rc);
+		}
+
+		wp += FLASH_WIDTH;
+	}
+
+	/*
+	 * handle FLASH_WIDTH aligned part
+	 */
+	while (cnt >= FLASH_WIDTH) {
+		*datah = *(ulong *)src;
+		*datal = *(ulong *)(src + 4);
+		if ((rc = write_data(info, wp, data)) != 0) {
+			set_msr(msr);
+			return (rc);
+		}
+		wp  += FLASH_WIDTH;
+		cnt -= FLASH_WIDTH;
+		src += FLASH_WIDTH;
+	}
+
+	if (cnt == 0) {
+		set_msr(msr);
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	*datah = *datal = 0;
+	for (i = 0, cp = wp; i < FLASH_WIDTH && cnt > 0; ++i, ++cp) {
+		char tmp;
+
+      		tmp = *src;
+
+		src++;
+
+		if (i >= 4) {
+			*datah = (*datah << 8) | ((*datal & 0xFF000000) >> 24);
+		}
+
+		*datal = (*datal << 8) | tmp;
+
+		--cnt;
+	}
+
+	for (; i < FLASH_WIDTH; ++i, ++cp) {
+		if (i >= 4) {
+			*datah = (*datah << 8) | ((*datal & 0xFF000000) >> 24);
+		}
+
+		*datal = (*datal << 8) | (*(uchar *)cp);
+	}
+
+	rc = write_data(info, wp, data);
+	set_msr(msr);
+
+	return (rc);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_data (flash_info_t *info, ulong dest, ulong *data)
+{
+	vu_long *addr = (vu_long *)dest;
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if (((addr[0] & data[0]) != data[0]) ||
+	    ((addr[1] & data[1]) != data[1]) ) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0] = 0x00400040;		/* write setup */
+	write_via_fpu(addr, data);
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	start = get_timer (0);
+
+	while (((addr[0] & 0x00800080) != 0x00800080) ||
+	       ((addr[1] & 0x00800080) != 0x00800080) ) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			addr[0] = 0x00FF00FF;	/* restore read mode */
+			return (1);
+		}
+	}
+
+	addr[0] = 0x00FF00FF;	/* restore read mode */
+
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void write_via_fpu(vu_long *addr, ulong *data)
+{
+	__asm__ __volatile__ ("lfd  1, 0(%0)" : : "r" (data));
+	__asm__ __volatile__ ("stfd 1, 0(%0)" : : "r" (addr));
+}
+/*-----------------------------------------------------------------------
+ */
+static __inline__ unsigned long get_msr(void)
+{
+    unsigned long msr;
+
+    __asm__ __volatile__ ("mfmsr %0" : "=r" (msr) :);
+    return msr;
+}
+
+static __inline__ void set_msr(unsigned long msr)
+{
+    __asm__ __volatile__ ("mtmsr %0" : : "r" (msr));
+}
diff --git a/board/eltec/mhpc/flash.c b/board/eltec/mhpc/flash.c
new file mode 100644
index 0000000..58cfd70
--- /dev/null
+++ b/board/eltec/mhpc/flash.c
@@ -0,0 +1,453 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+#include <linux/byteorder/swab.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Protection Flags:
+ */
+#define FLAG_PROTECT_SET	0x01
+#define FLAG_PROTECT_CLEAR	0x02
+
+/* Board support for 1 or 2 flash devices */
+#undef FLASH_PORT_WIDTH32
+#define FLASH_PORT_WIDTH16
+
+#ifdef FLASH_PORT_WIDTH16
+#define FLASH_PORT_WIDTH		ushort
+#define FLASH_PORT_WIDTHV		vu_short
+#define SWAP(x)                         __swab16(x)
+#else
+#define FLASH_PORT_WIDTH		ulong
+#define FLASH_PORT_WIDTHV		vu_long
+#define SWAP(x)                         __swab32(x)
+#endif
+
+#define FPW	FLASH_PORT_WIDTH
+#define FPWV	FLASH_PORT_WIDTHV
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (FPW *addr, flash_info_t *info);
+static int   write_data (flash_info_t *info, ulong dest, FPW data);
+static void  flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+	size_b0 = flash_get_size((FPW *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_PS_16 | BR_MS_GPCM | BR_V;
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((FPW *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+	/* monitor protection ON by default */
+	(void)flash_protect(FLAG_PROTECT_SET,
+			    CFG_FLASH_BASE,
+			    CFG_FLASH_BASE+CFG_MONITOR_LEN-1,
+			    &flash_info[0]);
+
+	flash_info[0].size = size_b0;
+
+	return (size_b0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
+		for (i = 0; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000);
+		}
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+		case FLASH_MAN_INTEL:	printf ("INTEL ");		break;
+		default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+   case FLASH_28F640J5 :
+				printf ("28F640J5 \n"); break;
+	default:		printf ("Unknown Chip Type=0x%lXh\n",
+					info->flash_id & FLASH_TYPEMASK); break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (FPW *addr, flash_info_t *info)
+{
+	FPW value;
+
+	/* Write auto select command: read Manufacturer ID */
+	addr[0x5555] = (FPW)0xAA00AA00;
+	addr[0x2AAA] = (FPW)0x55005500;
+	addr[0x5555] = (FPW)0x90009000;
+
+	value = SWAP(addr[0]);
+
+   switch (value) {
+   case (FPW)INTEL_MANUFACT:
+      info->flash_id = FLASH_MAN_INTEL;
+      break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		addr[0] = (FPW)0xFF00FF00;      /* restore read mode */
+		return (0);			      /* no or unknown flash	*/
+	}
+
+   value = SWAP(addr[1]);			        /* device ID no swap !*/
+
+   switch (value) {
+   case (FPW)INTEL_ID_28F640J5 :
+        info->flash_id += FLASH_28F640J5 ;
+        info->sector_count = 64;
+        info->size = 0x00800000;
+        break;            /* => 8 MB     */
+
+        default:
+                info->flash_id = FLASH_UNKNOWN;
+		break;
+	}
+
+	if (info->sector_count > CFG_MAX_FLASH_SECT) {
+		printf ("** ERROR: sector count %d > max (%d) **\n",
+			info->sector_count, CFG_MAX_FLASH_SECT);
+		info->sector_count = CFG_MAX_FLASH_SECT;
+	}
+
+	addr[0] = (FPW)0xFF00FF00;      /* restore read mode */
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	int flag, prot, sect;
+	ulong type, start, now, last;
+	int rc = 0;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	type = (info->flash_id & FLASH_VENDMASK);
+	if ((type != FLASH_MAN_INTEL)) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	start = get_timer (0);
+	last  = start;
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			FPWV *addr = (FPWV *)(info->start[sect]);
+			FPW status;
+
+			/* Disable interrupts which might cause a timeout here */
+			flag = disable_interrupts();
+
+			*addr = (FPW)0x50005000;	/* clear status register */
+			*addr = (FPW)0x20002000;	/* erase setup */
+			*addr = (FPW)0xD000D000;	/* erase confirm */
+
+			/* re-enable interrupts if necessary */
+			if (flag)
+				enable_interrupts();
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+
+			while (((status = SWAP(*addr)) & (FPW)0x00800080) != (FPW)0x00800080) {
+				if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout\n");
+					*addr = (FPW)0xB000B000; /* suspend erase */
+					*addr = (FPW)0xFF00FF00; /* reset to read mode */
+					rc = 1;
+					break;
+				}
+
+				/* show that we're waiting */
+			if ((now - last) > 1000) {	/* every second */
+					putc ('.');
+					last = now;
+				}
+			}
+
+			*addr = (FPW)0xFF00FF00;	/* reset to read mode */
+			printf (" done\n");
+		}
+	}
+	return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 4 - Flash not identified
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp;
+	FPW data;
+	int count, i, l, rc, port_width;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return 4;
+	}
+/* get lower word aligned address */
+#ifdef FLASH_PORT_WIDTH16
+	wp = (addr & ~1);
+	port_width = 2;
+#else
+	wp = (addr & ~3);
+	port_width = 4;
+#endif
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<port_width && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<port_width; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_data(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += port_width;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	count = 0;
+	while (cnt >= port_width) {
+		data = 0;
+		for (i=0; i<port_width; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_data(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += port_width;
+		cnt -= port_width;
+		if ((wp & 0xfff) == 0)
+		{
+			printf("%08lX",wp);
+			printf("\x1b[8D");
+		}
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<port_width && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<port_width; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_data(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word or halfword to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_data (flash_info_t *info, ulong dest, FPW data)
+{
+	FPWV *addr = (FPWV *)dest;
+	ulong status;
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*addr & data) != data) {
+		printf("not erased at %08lx (%x)\n",(ulong)addr,*addr);
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	*addr = (FPW)0x40004000;		/* write setup */
+	*addr = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	start = get_timer (0);
+
+	while (((status = SWAP(*addr)) & (FPW)0x00800080) != (FPW)0x00800080) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			*addr = (FPW)0xFF00FF00;	/* restore read mode */
+			return (1);
+		}
+	}
+
+	*addr = (FPW)0xFF00FF00;	/* restore read mode */
+
+	return (0);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/board/ep8260/flash.c b/board/ep8260/flash.c
new file mode 100644
index 0000000..cae8a13
--- /dev/null
+++ b/board/ep8260/flash.c
@@ -0,0 +1,396 @@
+/*
+ * (C) Copyright 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * Frank Panno <fpanno@delphintech.com>, Delphin Technology AG
+ *
+ * Flash Routines for AMD device AM29DL323DB on the EP8260 board.
+ *
+ * This file is based on board/tqm8260/flash.c.
+ *--------------------------------------------------------------------
+ * 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 <mpc8xx.h>
+
+#define V_ULONG(a)	(*(volatile unsigned long *)( a ))
+#define V_BYTE(a)	(*(volatile unsigned char *)( a ))
+
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+
+/*-----------------------------------------------------------------------
+ */
+void flash_reset(void)
+{
+  if( flash_info[0].flash_id != FLASH_UNKNOWN ) {
+    V_ULONG( flash_info[0].start[0] ) = 0x00F000F0;
+    V_ULONG( flash_info[0].start[0] + 4 ) = 0x00F000F0;
+  }
+}
+
+/*-----------------------------------------------------------------------
+ */
+ulong flash_get_size( ulong baseaddr, flash_info_t *info )
+{
+  short i;
+  unsigned long flashtest_h, flashtest_l;
+
+  /* Write auto select command sequence and test FLASH answer */
+  V_ULONG(baseaddr + ((ulong)0x0555 << 3)) = 0x00AA00AA;
+  V_ULONG(baseaddr + ((ulong)0x02AA << 3)) = 0x00550055;
+  V_ULONG(baseaddr + ((ulong)0x0555 << 3)) = 0x00900090;
+  V_ULONG(baseaddr + 4 + ((ulong)0x0555 << 3)) = 0x00AA00AA;
+  V_ULONG(baseaddr + 4 + ((ulong)0x02AA << 3)) = 0x00550055;
+  V_ULONG(baseaddr + 4 + ((ulong)0x0555 << 3)) = 0x00900090;
+
+  flashtest_h = V_ULONG(baseaddr);		/* manufacturer ID	   */
+  flashtest_l = V_ULONG(baseaddr + 4);
+
+  if ((int)flashtest_h == AMD_MANUFACT) {
+  	info->flash_id = FLASH_MAN_AMD;
+  } else {
+	info->flash_id = FLASH_UNKNOWN;
+	info->sector_count = 0;
+	info->size = 0;
+	return (0);  				/* no or unknown flash	   */
+  }
+
+  flashtest_h = V_ULONG(baseaddr + 8);	        /* device ID		   */
+  flashtest_l = V_ULONG(baseaddr + 12);
+  if (flashtest_h != flashtest_l) {
+    info->flash_id = FLASH_UNKNOWN;
+    return(0);
+  }
+  if (flashtest_h == AMD_ID_DL323B) {
+    info->flash_id += FLASH_AMDL323B;
+    info->sector_count = 71;
+    info->size = 0x01000000;	                /* 4 * 4 MB = 16 MB	*/
+  } else {
+    info->flash_id = FLASH_UNKNOWN;
+    return(0);  			 	/* no or unknown flash	   */
+  }
+
+  /* set up sector start adress table (bottom sector type) */
+  for (i = 0; i < 8; i++) {
+    info->start[i] = baseaddr + (i * 0x00008000);
+  }
+  for (i = 8; i < info->sector_count; i++) {
+    info->start[i] = baseaddr + (i * 0x00040000) - 0x001C0000;
+  }
+
+  /* check for protected sectors */
+  for (i = 0; i < info->sector_count; i++) {
+    /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+    if ((V_ULONG( info->start[i] + 16 ) & 0x00010001) ||
+        (V_ULONG( info->start[i] + 20 ) & 0x00010001)) {
+	info->protect[i] = 1;		/* D0 = 1 if protected */
+    } else {
+    	info->protect[i] = 0;
+    }
+  }
+
+  flash_reset();
+  return(info->size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+    unsigned long size_b0 = 0;
+    int i;
+
+    /* Init: no FLASHes known */
+    for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+	flash_info[i].flash_id = FLASH_UNKNOWN;
+    }
+
+    /* Static FLASH Bank configuration here (only one bank) */
+
+    size_b0 = flash_get_size(CFG_FLASH0_BASE, &flash_info[0]);
+    if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) {
+	printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+		size_b0, size_b0>>20);
+    }
+
+    /*
+     * protect monitor and environment sectors
+     */
+
+#if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
+    flash_protect(FLAG_PROTECT_SET,
+		  CFG_MONITOR_BASE,
+		  CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		  &flash_info[0]);
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+    flash_protect(FLAG_PROTECT_SET,
+		  CFG_ENV_ADDR,
+		  CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+		  &flash_info[0]);
+#endif
+
+    return (size_b0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+    int i;
+
+    if (info->flash_id == FLASH_UNKNOWN) {
+	printf ("missing or unknown FLASH type\n");
+	return;
+    }
+
+    switch ((info->flash_id >> 16) & 0xff) {
+    case FLASH_MAN_AMD:	    printf ("AMD ");		    break;
+    default:		    printf ("Unknown Vendor ");	    break;
+    }
+
+    switch (info->flash_id & FLASH_TYPEMASK) {
+    case FLASH_AMDL323B:	printf ("29DL323B (32 M, bottom sector)\n");
+				break;
+    default:			printf ("Unknown Chip Type\n");
+				break;
+    }
+
+    printf ("  Size: %ld MB in %d Sectors\n",
+	    info->size >> 20, info->sector_count);
+
+    printf ("  Sector Start Addresses:");
+    for (i=0; i<info->sector_count; ++i) {
+	if ((i % 5) == 0)
+	  printf ("\n   ");
+	printf (" %08lX%s",
+		info->start[i],
+		info->protect[i] ? " (RO)" : "     "
+		);
+    }
+    printf ("\n");
+    return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+    int flag, prot, sect, l_sect;
+    ulong start, now, last;
+
+    if ((s_first < 0) || (s_first > s_last)) {
+	if (info->flash_id == FLASH_UNKNOWN) {
+	    printf ("- missing\n");
+	} else {
+	    printf ("- no sectors to erase\n");
+	}
+	return 1;
+    }
+
+    prot = 0;
+    for (sect = s_first; sect <= s_last; sect++) {
+	if (info->protect[sect])
+	    prot++;
+    }
+
+    if (prot) {
+	printf ("- Warning: %d protected sectors will not be erased!\n",
+		prot);
+    } else {
+	printf ("\n");
+    }
+
+    l_sect = -1;
+
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
+    V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00800080;
+    V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
+    V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
+    V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00800080;
+    V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
+    udelay (1000);
+
+    /* Start erase on unprotected sectors */
+    for (sect = s_first; sect<=s_last; sect++) {
+	if (info->protect[sect] == 0) {	/* not protected */
+	    V_ULONG( info->start[sect] ) = 0x00300030;
+	    V_ULONG( info->start[sect] + 4 ) = 0x00300030;
+	    l_sect = sect;
+	}
+    }
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+      enable_interrupts();
+
+    /* wait at least 80us - let's wait 1 ms */
+    udelay (1000);
+
+    /*
+     * We wait for the last triggered sector
+     */
+    if (l_sect < 0)
+      goto DONE;
+
+    start = get_timer (0);
+    last  = start;
+    while ((V_ULONG( info->start[l_sect] ) & 0x00800080) != 0x00800080 ||
+	   (V_ULONG( info->start[l_sect] + 4 ) & 0x00800080) != 0x00800080)
+    {
+	if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+	    printf ("Timeout\n");
+	    return 1;
+	}
+	/* show that we're waiting */
+	if ((now - last) > 1000) {	/* every second */
+	    serial_putc ('.');
+	    last = now;
+	}
+    }
+
+    DONE:
+    /* reset to read mode */
+    flash_reset ();
+
+    printf (" done\n");
+    return 0;
+}
+
+static int write_dword (flash_info_t *, ulong, unsigned char *);
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+    ulong dp;
+    static unsigned char bb[8];
+    int i, l, rc, cc = cnt;
+
+    dp = (addr & ~7);	/* get lower dword aligned address */
+
+    /*
+     * handle unaligned start bytes
+     */
+    if ((l = addr - dp) != 0) {
+	for (i = 0; i < 8; i++)
+	    bb[i] = (i < l || (i-l) >= cc) ? V_BYTE(dp+i) : *src++;
+	if ((rc = write_dword(info, dp, bb)) != 0)
+	{
+	    return (rc);
+	}
+	dp += 8;
+	cc -= 8 - l;
+    }
+
+    /*
+     * handle word aligned part
+     */
+    while (cc >= 8) {
+	if ((rc = write_dword(info, dp, src)) != 0) {
+	    return (rc);
+	}
+	dp  += 8;
+	src += 8;
+	cc -= 8;
+    }
+
+    if (cc <= 0) {
+	return (0);
+    }
+
+    /*
+     * handle unaligned tail bytes
+     */
+    for (i = 0; i < 8; i++) {
+	bb[i] = (i < cc) ? *src++ : V_BYTE(dp+i);
+    }
+    return (write_dword(info, dp, bb));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a dword to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_dword (flash_info_t *info, ulong dest, unsigned char * pdata)
+{
+    ulong start;
+    ulong cl = 0, ch =0;
+    int flag, i;
+
+    for (ch=0, i=0; i < 4; i++)
+	ch = (ch << 8) + *pdata++;	/* high word	*/
+    for (cl=0, i=0; i < 4; i++)
+	cl = (cl << 8) + *pdata++;	/* low word	*/
+
+    /* Check if Flash is (sufficiently) erased */
+    if ((*((vu_long *)dest) & ch)	!= ch
+      ||(*((vu_long *)(dest + 4)) & cl)	!= cl)
+    {
+	return (2);
+    }
+
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
+    V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00A000A0;
+    V_ULONG( dest ) = ch;
+    V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
+    V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00A000A0;
+    V_ULONG( dest + 4 ) = cl;
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+      enable_interrupts();
+
+    /* data polling for D7 */
+    start = get_timer (0);
+    while (((V_ULONG( dest ) & 0x00800080) != (ch & 0x00800080)) ||
+           ((V_ULONG( dest + 4 ) & 0x00800080) != (cl & 0x00800080))) {
+	if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+	    return (1);
+	}
+    }
+    return (0);
+}
diff --git a/board/ep8260/mii_phy.c b/board/ep8260/mii_phy.c
new file mode 100644
index 0000000..e3b7878
--- /dev/null
+++ b/board/ep8260/mii_phy.c
@@ -0,0 +1,108 @@
+#include <common.h>
+#include <mii_phy.h>
+#include "ep8260.h"
+
+#define MII_MDIO	0x01
+#define MII_MDCK	0x02
+#define MII_MDIR	0x04
+
+void
+mii_discover_phy(void)
+{
+    int known;
+    unsigned short phy_reg;
+    unsigned long phy_id;
+
+    known = 0;
+    printf("Discovering phy @ 0: ");
+    phy_id = mii_phy_read(2) << 16;
+    phy_id |= mii_phy_read(3);
+    if ((phy_id & 0xFFFFFC00) == 0x00137800) {
+	printf("Level One ");
+	if ((phy_id & 0x000003F0) == 0xE0) {
+	    printf("LXT971A Revision %d\n", (int)(phy_id & 0xF));
+	    known = 1;
+	}
+	else printf("unknown type\n");
+    }
+    else printf("unknown OUI = 0x%08lX\n", phy_id);
+
+    phy_reg = mii_phy_read(1);
+    if (!(phy_reg & 0x0004)) printf("Link is down\n");
+    if (!(phy_reg & 0x0020)) printf("Auto-negotiation not complete\n");
+    if (phy_reg & 0x0002) printf("Jabber condition detected\n");
+    if (phy_reg & 0x0010) printf("Remote fault condition detected \n");
+
+    if (known) {
+	phy_reg = mii_phy_read(17);
+	if (phy_reg & 0x0400)
+	    printf("Phy operating at %d MBit/s in %s-duplex mode\n",
+		phy_reg & 0x4000 ? 100 : 10,
+	    	phy_reg & 0x0200 ? "full" : "half");
+	else
+	    printf("bad link!!\n");
+/*
+left  off: no link, green 100MBit, yellow 10MBit
+right off: no activity, green full-duplex, yellow half-duplex
+*/
+	mii_phy_write(20, 0x0452);
+    }
+}
+
+unsigned short
+mii_phy_read(unsigned short reg)
+{
+    int i;
+    unsigned short tmp, val = 0, adr = 0;
+    t_ep_regs *regs = (t_ep_regs*)CFG_REGS_BASE;
+
+    tmp = 0x6002 | (adr << 7) | (reg << 2);
+    regs->bcsr4 = 0xC3;
+    for (i = 0; i < 64; i++) {
+        regs->bcsr4 ^= MII_MDCK;
+    }
+    for (i = 0; i < 16; i++) {
+	regs->bcsr4 &= ~MII_MDCK;
+	if (tmp & 0x8000) regs->bcsr4 |= MII_MDIO;
+	else regs->bcsr4 &= ~MII_MDIO;
+	regs->bcsr4 |= MII_MDCK;
+	tmp <<= 1;
+    }
+    regs->bcsr4 |= MII_MDIR;
+    for (i = 0; i < 16; i++) {
+	val <<= 1;
+	regs->bcsr4 = MII_MDIO | (regs->bcsr4 | MII_MDCK);
+	if (regs->bcsr4 & MII_MDIO) val |= 1;
+	regs->bcsr4 = MII_MDIO | (regs->bcsr4 &= ~MII_MDCK);
+    }
+    return val;
+}
+
+void
+mii_phy_write(unsigned short reg, unsigned short val)
+{
+    int i;
+    unsigned short tmp, adr = 0;
+    t_ep_regs *regs = (t_ep_regs*)CFG_REGS_BASE;
+
+    tmp = 0x5002 | (adr << 7) | (reg << 2);
+    regs->bcsr4 = 0xC3;
+    for (i = 0; i < 64; i++) {
+	regs->bcsr4 ^= MII_MDCK;
+    }
+    for (i = 0; i < 16; i++) {
+	regs->bcsr4 &= ~MII_MDCK;
+        if (tmp & 0x8000) regs->bcsr4 |= MII_MDIO;
+	else regs->bcsr4 &= ~MII_MDIO;
+	regs->bcsr4 |= MII_MDCK;
+	tmp <<= 1;
+    }
+    for (i = 0; i < 16; i++) {
+	regs->bcsr4 &= ~MII_MDCK;
+	if (val & 0x8000) regs->bcsr4 |= MII_MDIO;
+	else regs->bcsr4 &= ~MII_MDIO;
+	regs->bcsr4 |= MII_MDCK;
+	val <<= 1;
+    }
+}
+
diff --git a/board/esd/adciop/flash.c b/board/esd/adciop/flash.c
new file mode 100644
index 0000000..46ae03b
--- /dev/null
+++ b/board/esd/adciop/flash.c
@@ -0,0 +1,113 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * 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 <ppc4xx.h>
+#include <asm/processor.h>
+
+/*
+ * include common flash code (for esd boards)
+ */
+#include "../common/flash.c"
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+	size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+
+	if (size_b1 > size_b0) {
+		printf ("## ERROR: "
+			"Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
+			size_b1, size_b1<<20,
+			size_b0, size_b0<<20
+		);
+		flash_info[0].flash_id	= FLASH_UNKNOWN;
+		flash_info[1].flash_id	= FLASH_UNKNOWN;
+		flash_info[0].sector_count	= -1;
+		flash_info[1].sector_count	= -1;
+		flash_info[0].size		= 0;
+		flash_info[1].size		= 0;
+		return (0);
+	}
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      FLASH_BASE0_PRELIM+size_b0-CFG_MONITOR_LEN,
+		      FLASH_BASE0_PRELIM+size_b0-1,
+		      &flash_info[0]);
+
+	if (size_b1) {
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size((vu_long *)(FLASH_BASE0_PRELIM + size_b0),
+					  &flash_info[1]);
+
+		flash_get_offsets (FLASH_BASE0_PRELIM + size_b0, &flash_info[1]);
+
+		/* monitor protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      FLASH_BASE0_PRELIM+size_b0+size_b1-CFG_MONITOR_LEN,
+			      FLASH_BASE0_PRELIM+size_b0+size_b1-1,
+			      &flash_info[1]);
+                /* monitor protection OFF by default (one is enough) */
+                flash_protect(FLAG_PROTECT_CLEAR,
+			      FLASH_BASE0_PRELIM+size_b0-CFG_MONITOR_LEN,
+			      FLASH_BASE0_PRELIM+size_b0-1,
+			      &flash_info[0]);
+	} else {
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+	}
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+}
diff --git a/board/esd/common/flash.c b/board/esd/common/flash.c
new file mode 100644
index 0000000..78a1e0f
--- /dev/null
+++ b/board/esd/common/flash.c
@@ -0,0 +1,646 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * 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 <ppc4xx.h>
+#include <asm/processor.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+	short n;
+
+	/* set up sector start address table */
+        if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
+	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U)) {
+	    for (i = 0; i < info->sector_count; i++)
+		info->start[i] = base + (i * 0x00010000);
+        } else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322B) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323B) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324B)) {
+		/* set sector offsets for bottom boot block type	*/
+		for (i=0; i<8; ++i) {		/*  8 x 8k boot sectors	*/
+			info->start[i] = base;
+			base += 8 << 10;
+		}
+		while (i < info->sector_count) {	/* 64k regular sectors	*/
+			info->start[i] = base;
+			base += 64 << 10;
+			++i;
+		}
+        } else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322T) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323T) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324T)) {
+		/* set sector offsets for top boot block type		*/
+		base += info->size;
+		i = info->sector_count;
+		for (n=0; n<8; ++n) {		/*  8 x 8k boot sectors	*/
+			base -= 8 << 10;
+			--i;
+			info->start[i] = base;
+		}
+		while (i > 0) {			/* 64k regular sectors	*/
+			base -= 64 << 10;
+			--i;
+			info->start[i] = base;
+		}
+        } else {
+	    if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00006000;
+		info->start[3] = base + 0x00008000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00010000) - 0x00030000;
+		}
+	    } else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00006000;
+		info->start[i--] = base + info->size - 0x00008000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00010000;
+		}
+	    }
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+        int k;
+        int size;
+        int erased;
+        volatile unsigned long *flash;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	case FLASH_MAN_SST:	printf ("SST ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 M, top sector)\n");
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 M, bottom sector)\n");
+				break;
+	case FLASH_AMDL322T:	printf ("AM29DL322T (32 M, top sector)\n");
+				break;
+	case FLASH_AMDL322B:	printf ("AM29DL322B (32 M, bottom sector)\n");
+				break;
+	case FLASH_AMDL323T:	printf ("AM29DL323T (32 M, top sector)\n");
+				break;
+	case FLASH_AMDL323B:	printf ("AM29DL323B (32 M, bottom sector)\n");
+				break;
+	case FLASH_AM640U:	printf ("AM29LV640D (64 M, uniform sector)\n");
+				break;
+	case FLASH_SST800A:	printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
+				break;
+	case FLASH_SST160A:	printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+#ifdef CFG_FLASH_EMPTY_INFO
+                /*
+                 * Check if whole sector is erased
+                 */
+                if (i != (info->sector_count-1))
+                  size = info->start[i+1] - info->start[i];
+                else
+                  size = info->start[0] + info->size - info->start[i];
+                erased = 1;
+                flash = (volatile unsigned long *)info->start[i];
+                size = size >> 2;        /* divide by 4 for longword access */
+                for (k=0; k<size; k++)
+                  {
+                    if (*flash++ != 0xffffffff)
+                      {
+                        erased = 0;
+                        break;
+                      }
+                  }
+
+		if ((i % 5) == 0)
+			printf ("\n   ");
+                /* print empty and read-only info */
+		printf (" %08lX%s%s",
+			info->start[i],
+			erased ? " E" : "  ",
+			info->protect[i] ? "RO " : "   ");
+#else
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     ");
+#endif
+
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	short n;
+	CFG_FLASH_WORD_SIZE value;
+	ulong base = (ulong)addr;
+        volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)addr;
+
+	/* Write auto select command: read Manufacturer ID */
+	addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
+	addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
+	addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090;
+
+	value = addr2[CFG_FLASH_READ0];
+
+	switch (value) {
+	case (CFG_FLASH_WORD_SIZE)AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case (CFG_FLASH_WORD_SIZE)FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	case (CFG_FLASH_WORD_SIZE)SST_MANUFACT:
+		info->flash_id = FLASH_MAN_SST;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr2[CFG_FLASH_READ1];		/* device ID		*/
+
+	switch (value) {
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400T:
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00080000;
+		break;				/* => 0.5 MB		*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400B:
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00080000;
+		break;				/* => 0.5 MB		*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800T:
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800B:
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160T:
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160B:
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320T:
+	        info->flash_id += FLASH_AM320T;
+	        info->sector_count = 71;
+		info->size = 0x00400000;  break;	/* => 4 MB	*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320B:
+	        info->flash_id += FLASH_AM320B;
+		info->sector_count = 71;
+		info->size = 0x00400000;  break;	/* => 4 MB	*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322T:
+	        info->flash_id += FLASH_AMDL322T;
+	        info->sector_count = 71;
+		info->size = 0x00400000;  break;	/* => 4 MB	*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322B:
+	        info->flash_id += FLASH_AMDL322B;
+		info->sector_count = 71;
+		info->size = 0x00400000;  break;	/* => 4 MB	*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323T:
+	        info->flash_id += FLASH_AMDL323T;
+		info->sector_count = 71;
+		info->size = 0x00400000;  break;	/* => 4 MB	*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323B:
+	        info->flash_id += FLASH_AMDL323B;
+		info->sector_count = 71;
+		info->size = 0x00400000;  break;	/* => 4 MB	*/
+
+	case (CFG_FLASH_WORD_SIZE)AMD_ID_LV640U:
+	        info->flash_id += FLASH_AM640U;
+		info->sector_count = 128;
+		info->size = 0x00800000;  break;	/* => 8 MB	*/
+
+	case (CFG_FLASH_WORD_SIZE)SST_ID_xF800A:
+		info->flash_id += FLASH_SST800A;
+		info->sector_count = 16;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (CFG_FLASH_WORD_SIZE)SST_ID_xF160A:
+		info->flash_id += FLASH_SST160A;
+		info->sector_count = 32;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	/* set up sector start address table */
+        if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
+	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U)) {
+	    for (i = 0; i < info->sector_count; i++)
+		info->start[i] = base + (i * 0x00010000);
+        } else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322B) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323B) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324B)) {
+		/* set sector offsets for bottom boot block type	*/
+		for (i=0; i<8; ++i) {		/*  8 x 8k boot sectors	*/
+			info->start[i] = base;
+			base += 8 << 10;
+		}
+		while (i < info->sector_count) {	/* 64k regular sectors	*/
+			info->start[i] = base;
+			base += 64 << 10;
+			++i;
+		}
+        } else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322T) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323T) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
+		   ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324T)) {
+		/* set sector offsets for top boot block type		*/
+		base += info->size;
+		i = info->sector_count;
+		for (n=0; n<8; ++n) {		/*  8 x 8k boot sectors	*/
+			base -= 8 << 10;
+			--i;
+			info->start[i] = base;
+		}
+		while (i > 0) {			/* 64k regular sectors	*/
+			base -= 64 << 10;
+			--i;
+			info->start[i] = base;
+		}
+        } else {
+	    if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00006000;
+		info->start[3] = base + 0x00008000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00010000) - 0x00030000;
+		}
+	    } else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00006000;
+		info->start[i--] = base + info->size - 0x00008000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00010000;
+		}
+	    }
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr2 = (volatile CFG_FLASH_WORD_SIZE *)(info->start[i]);
+                if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
+                  info->protect[i] = 0;
+                else
+                  info->protect[i] = addr2[CFG_FLASH_READ2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr2 = (CFG_FLASH_WORD_SIZE *)info->start[0];
+		*addr2 = (CFG_FLASH_WORD_SIZE)0x00F000F0;	/* reset bank */
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
+	volatile CFG_FLASH_WORD_SIZE *addr2;
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+        int i;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("Can't erase unknown flash type - aborted\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+		    addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]);
+                    if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
+                        addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
+                        addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
+                        addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
+                        addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
+                        addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
+                        addr2[0] = (CFG_FLASH_WORD_SIZE)0x00500050;  /* block erase */
+                        for (i=0; i<50; i++)
+                          udelay(1000);  /* wait 1 ms */
+                    } else {
+                        if (sect == s_first) {
+                            addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
+                            addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
+                            addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
+                            addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
+                            addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
+                        }
+                        addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030;  /* sector erase */
+                    }
+		    l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]);
+	while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080) {
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (CFG_FLASH_WORD_SIZE *)info->start[0];
+	addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0;	/* reset bank */
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+        volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
+        volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest;
+        volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)&data;
+	ulong start;
+	int flag;
+        int i;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((volatile CFG_FLASH_WORD_SIZE *)dest) &
+             (CFG_FLASH_WORD_SIZE)data) != (CFG_FLASH_WORD_SIZE)data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+        for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++)
+          {
+            addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
+            addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
+            addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00A000A0;
+
+            dest2[i] = data2[i];
+
+            /* re-enable interrupts if necessary */
+            if (flag)
+              enable_interrupts();
+
+            /* data polling for D7 */
+            start = get_timer (0);
+            while ((dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
+                   (data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) {
+              if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+                return (1);
+              }
+            }
+          }
+
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/esd/cpci405/flash.c b/board/esd/cpci405/flash.c
new file mode 100644
index 0000000..70f7de4
--- /dev/null
+++ b/board/esd/cpci405/flash.c
@@ -0,0 +1,160 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * 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 <ppc4xx.h>
+#include <asm/processor.h>
+
+/*
+ * include common flash code (for esd boards)
+ */
+#include "../common/flash.c"
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long * addr, flash_info_t * info);
+static void flash_get_offsets (ulong base, flash_info_t * info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	unsigned long size_b0, size_b1;
+	int i;
+	uint pbcr;
+	unsigned long base_b0, base_b1;
+	int size_val = 0;
+
+	/* Init: no FLASHes known */
+	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	base_b0 = FLASH_BASE0_PRELIM;
+	size_b0 = flash_get_size ((vu_long *) base_b0, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+				size_b0, size_b0 << 20);
+	}
+
+	base_b1 = FLASH_BASE1_PRELIM;
+	size_b1 = flash_get_size ((vu_long *) base_b1, &flash_info[1]);
+
+	/* Re-do sizing to get full correct info */
+
+	if (size_b1) {
+		mtdcr (ebccfga, pb0cr);
+		pbcr = mfdcr (ebccfgd);
+		mtdcr (ebccfga, pb0cr);
+		base_b1 = -size_b1;
+		switch (size_b1) {
+		case 1 << 20:
+			size_val = 0;
+			break;
+		case 2 << 20:
+			size_val = 1;
+			break;
+		case 4 << 20:
+			size_val = 2;
+			break;
+		case 8 << 20:
+			size_val = 3;
+			break;
+		case 16 << 20:
+			size_val = 4;
+			break;
+		default:
+			size_val = 0;
+			break;
+
+		}
+		pbcr = (pbcr & 0x0001ffff) | base_b1 | (size_val << 17);
+		mtdcr (ebccfgd, pbcr);
+		/*          printf("pb1cr = %x\n", pbcr); */
+	}
+
+	if (size_b0) {
+		mtdcr (ebccfga, pb1cr);
+		pbcr = mfdcr (ebccfgd);
+		mtdcr (ebccfga, pb1cr);
+		base_b0 = base_b1 - size_b0;
+		switch (size_b1) {
+		case 1 << 20:
+			size_val = 0;
+			break;
+		case 2 << 20:
+			size_val = 1;
+			break;
+		case 4 << 20:
+			size_val = 2;
+			break;
+		case 8 << 20:
+			size_val = 3;
+			break;
+		case 16 << 20:
+			size_val = 4;
+			break;
+		}
+		pbcr = (pbcr & 0x0001ffff) | base_b0 | (size_val << 17);
+		mtdcr (ebccfgd, pbcr);
+		/*            printf("pb0cr = %x\n", pbcr); */
+	}
+
+	size_b0 = flash_get_size ((vu_long *) base_b0, &flash_info[0]);
+
+	flash_get_offsets (base_b0, &flash_info[0]);
+
+	/* monitor protection ON by default */
+	flash_protect (FLAG_PROTECT_SET,
+			base_b0 + size_b0 - CFG_MONITOR_LEN,
+			base_b0 + size_b0 - 1, &flash_info[0]);
+
+	if (size_b1) {
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size ((vu_long *) base_b1, &flash_info[1]);
+
+		flash_get_offsets (base_b1, &flash_info[1]);
+
+		/* monitor protection ON by default */
+		flash_protect (FLAG_PROTECT_SET,
+				base_b1 + size_b1 - CFG_MONITOR_LEN,
+				base_b1 + size_b1 - 1, &flash_info[1]);
+		/* monitor protection OFF by default (one is enough) */
+		flash_protect (FLAG_PROTECT_CLEAR,
+				base_b0 + size_b0 - CFG_MONITOR_LEN,
+				base_b0 + size_b0 - 1, &flash_info[0]);
+	} else {
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+	}
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+}
diff --git a/board/esd/dasa_sim/cmd_dasa_sim.c b/board/esd/dasa_sim/cmd_dasa_sim.c
new file mode 100644
index 0000000..4608da7
--- /dev/null
+++ b/board/esd/dasa_sim/cmd_dasa_sim.c
@@ -0,0 +1,236 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * 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 <command.h>
+#include <pci.h>
+
+#define OK 0
+#define ERROR (-1)
+
+#define TRUE 1
+#define FALSE 0
+
+
+extern u_long pci9054_iobase;
+
+
+/***************************************************************************
+ *
+ * Routines for PLX PCI9054 eeprom access
+ *
+ */
+
+static unsigned int PciEepromReadLongVPD(int offs)
+{
+  unsigned int value;
+  unsigned int ret;
+  int count;
+
+  pci_write_config_dword(CFG_PCI9054_DEV_FN, 0x4c, (offs<<16) | 0x0003);
+  count = 0;
+
+  for (;;)
+    {
+      udelay(10 * 1000);
+      pci_read_config_dword(CFG_PCI9054_DEV_FN, 0x4c, &ret);
+      if ((ret & 0x80000000) != 0)
+        {
+          break;
+        }
+      else
+        {
+          count++;
+          if (count > 10)
+            {
+              printf("\nTimeout: ret=%08x - Please try again!\n", ret);
+              break;
+            }
+        }
+    }
+
+  pci_read_config_dword(CFG_PCI9054_DEV_FN, 0x50, &value);
+
+  return value;
+}
+
+
+static int PciEepromWriteLongVPD(int offs, unsigned int value)
+{
+  unsigned int ret;
+  int count;
+
+  pci_write_config_dword(CFG_PCI9054_DEV_FN, 0x50, value);
+  pci_write_config_dword(CFG_PCI9054_DEV_FN, 0x4c, (offs<<16) | 0x80000003);
+  count = 0;
+
+  for (;;)
+    {
+      udelay(10 * 1000);
+      pci_read_config_dword(CFG_PCI9054_DEV_FN, 0x4c, &ret);
+      if ((ret & 0x80000000) == 0)
+        {
+          break;
+        }
+      else
+        {
+          count++;
+          if (count > 10)
+            {
+              printf("\nTimeout: ret=%08x - Please try again!\n", ret);
+              break;
+            }
+        }
+    }
+
+  return TRUE;
+}
+
+
+static void showPci9054(void)
+{
+  int val;
+  int l, i;
+
+  /* read 9054-values */
+  for (l=0; l<6; l++)
+    {
+      printf("%02x: ", l*0x10);
+      for (i=0; i<4; i++)
+        {
+	  pci_read_config_dword(CFG_PCI9054_DEV_FN, l*16+i*4, &val);
+          printf("%08x ", val);
+        }
+      printf("\n");
+    }
+  printf("\n");
+
+  for (l=0; l<7; l++)
+    {
+      printf("%02x: ", l*0x10);
+      for (i=0; i<4; i++)
+        printf("%08x ", PciEepromReadLongVPD((i+l*4)*4));
+      printf("\n");
+    }
+  printf("\n");
+}
+
+
+static void updatePci9054(void)
+{
+  int val;
+
+  /*
+   * Set EEPROM write-protect register to 0
+   */
+  out32(pci9054_iobase+0x0c, in32(pci9054_iobase+0x0c) & 0xffff00ff);
+
+  /* Long Serial EEPROM Load Registers... */
+  val = PciEepromWriteLongVPD(0x00, 0x905410b5);
+  val = PciEepromWriteLongVPD(0x04, 0x09800001); /* other input controller */
+  val = PciEepromWriteLongVPD(0x08, 0x28140100);
+
+  val = PciEepromWriteLongVPD(0x0c, 0x00000000); /* MBOX0... */
+  val = PciEepromWriteLongVPD(0x10, 0x00000000);
+
+  /* las0: fpga access (0x0000.0000 ... 0x0003.ffff) */
+  val = PciEepromWriteLongVPD(0x14, 0xfffc0000); /* LAS0RR... */
+  val = PciEepromWriteLongVPD(0x18, 0x00000001); /* LAS0BA */
+
+  val = PciEepromWriteLongVPD(0x1c, 0x00200000); /* MARBR... */
+  val = PciEepromWriteLongVPD(0x20, 0x00300500); /* LMISC/BIGEND */
+
+  val = PciEepromWriteLongVPD(0x24, 0x00000000); /* EROMRR... */
+  val = PciEepromWriteLongVPD(0x28, 0x00000000); /* EROMBA */
+
+  val = PciEepromWriteLongVPD(0x2c, 0x43030000); /* LBRD0... */
+
+  val = PciEepromWriteLongVPD(0x30, 0x00000000); /* DMRR... */
+  val = PciEepromWriteLongVPD(0x34, 0x00000000);
+  val = PciEepromWriteLongVPD(0x38, 0x00000000);
+
+  val = PciEepromWriteLongVPD(0x3c, 0x00000000); /* DMPBAM... */
+  val = PciEepromWriteLongVPD(0x40, 0x00000000);
+
+  /* Extra Long Serial EEPROM Load Registers... */
+  val = PciEepromWriteLongVPD(0x44, 0x010212fe); /* PCISID... */
+
+  /* las1: 505-sram access (0x0004.0000 ... 0x001f.ffff) */
+  /* Offset to LAS1: Group 1: 0x00040000                 */
+  /*                 Group 2: 0x00080000                 */
+  /*                 Group 3: 0x000c0000                 */
+  val = PciEepromWriteLongVPD(0x48, 0xffe00000); /* LAS1RR */
+  val = PciEepromWriteLongVPD(0x4c, 0x00040001); /* LAS1BA */
+  val = PciEepromWriteLongVPD(0x50, 0x00000208); /* LBRD1 */ /* so wars bisher */
+
+  val = PciEepromWriteLongVPD(0x54, 0x00004c06); /* HotSwap... */
+
+  printf("Finished writing defaults into PLX PCI9054 EEPROM!\n");
+}
+
+
+static void clearPci9054(void)
+{
+  int val;
+
+  /*
+   * Set EEPROM write-protect register to 0
+   */
+  out32(pci9054_iobase+0x0c, in32(pci9054_iobase+0x0c) & 0xffff00ff);
+
+  /* Long Serial EEPROM Load Registers... */
+  val = PciEepromWriteLongVPD(0x00, 0xffffffff);
+  val = PciEepromWriteLongVPD(0x04, 0xffffffff); /* other input controller */
+
+  printf("Finished clearing PLX PCI9054 EEPROM!\n");
+}
+
+
+/* ------------------------------------------------------------------------- */
+int do_pci9054(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+  if (strcmp(argv[1], "info") == 0)
+    {
+      showPci9054();
+      return 0;
+    }
+
+  if (strcmp(argv[1], "update") == 0)
+    {
+      updatePci9054();
+      return 0;
+    }
+
+  if (strcmp(argv[1], "clear") == 0)
+    {
+      clearPci9054();
+      return 0;
+    }
+
+  printf("Usage:\n%s\n", cmdtp->usage);
+  return 1;
+
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/board/esd/dasa_sim/flash.c b/board/esd/dasa_sim/flash.c
new file mode 100644
index 0000000..2574eac
--- /dev/null
+++ b/board/esd/dasa_sim/flash.c
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * 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 <ppc4xx.h>
+#include <asm/processor.h>
+
+/*
+ * include common flash code (for esd boards)
+ */
+#include "../common/flash.c"
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	unsigned long size_b0;
+        int i;
+        unsigned long base_b0;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+        /* Setup offsets */
+        flash_get_offsets (-size_b0, &flash_info[0]);
+
+        base_b0 = -size_b0;
+
+        /* Monitor protection ON by default */
+        (void)flash_protect(FLAG_PROTECT_SET,
+                            -CFG_MONITOR_LEN,
+                            0xffffffff,
+                            &flash_info[0]);
+
+        flash_info[0].size = size_b0;
+
+	return (size_b0);
+}
diff --git a/board/esd/du405/flash.c b/board/esd/du405/flash.c
new file mode 100644
index 0000000..97d8322
--- /dev/null
+++ b/board/esd/du405/flash.c
@@ -0,0 +1,123 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * 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 <ppc4xx.h>
+#include <asm/processor.h>
+
+/*
+ * include common flash code (for esd boards)
+ */
+#include "../common/flash.c"
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long * addr, flash_info_t * info);
+static void flash_get_offsets (ulong base, flash_info_t * info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	unsigned long size_b0, size_b1;
+	int i;
+	uint pbcr;
+	unsigned long base_b0, base_b1;
+
+	/* Init: no FLASHes known */
+	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	base_b0 = FLASH_BASE0_PRELIM;
+	size_b0 = flash_get_size ((vu_long *) base_b0, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0 << 20);
+	}
+
+	base_b1 = FLASH_BASE1_PRELIM;
+	size_b1 = flash_get_size ((vu_long *) base_b1, &flash_info[1]);
+
+	/* Re-do sizing to get full correct info */
+
+	if (size_b1) {
+		mtdcr (ebccfga, pb0cr);
+		pbcr = mfdcr (ebccfgd);
+		mtdcr (ebccfga, pb0cr);
+		base_b1 = -size_b1;
+		pbcr = (pbcr & 0x0001ffff) | base_b1 |
+				(((size_b1 / 1024 / 1024) - 1) << 17);
+		mtdcr (ebccfgd, pbcr);
+		/*          printf("pb1cr = %x\n", pbcr); */
+	}
+
+	if (size_b0) {
+		mtdcr (ebccfga, pb1cr);
+		pbcr = mfdcr (ebccfgd);
+		mtdcr (ebccfga, pb1cr);
+		base_b0 = base_b1 - size_b0;
+		pbcr = (pbcr & 0x0001ffff) | base_b0 |
+				(((size_b0 / 1024 / 1024) - 1) << 17);
+		mtdcr (ebccfgd, pbcr);
+		/*            printf("pb0cr = %x\n", pbcr); */
+	}
+
+	size_b0 = flash_get_size ((vu_long *) base_b0, &flash_info[0]);
+
+	flash_get_offsets (base_b0, &flash_info[0]);
+
+	/* monitor protection ON by default */
+	flash_protect (FLAG_PROTECT_SET,
+			base_b0 + size_b0 - CFG_MONITOR_LEN,
+			base_b0 + size_b0 - 1, &flash_info[0]);
+
+	if (size_b1) {
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size ((vu_long *) base_b1, &flash_info[1]);
+
+		flash_get_offsets (base_b1, &flash_info[1]);
+
+		/* monitor protection ON by default */
+		flash_protect (FLAG_PROTECT_SET,
+				base_b1 + size_b1 - CFG_MONITOR_LEN,
+				base_b1 + size_b1 - 1, &flash_info[1]);
+		/* monitor protection OFF by default (one is enough) */
+		flash_protect (FLAG_PROTECT_CLEAR,
+				base_b0 + size_b0 - CFG_MONITOR_LEN,
+				base_b0 + size_b0 - 1, &flash_info[0]);
+	} else {
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+	}
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+}
diff --git a/board/esd/ocrtc/flash.c b/board/esd/ocrtc/flash.c
new file mode 100644
index 0000000..90965ea
--- /dev/null
+++ b/board/esd/ocrtc/flash.c
@@ -0,0 +1,156 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * 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 <ppc4xx.h>
+#include <asm/processor.h>
+
+/*
+ * include common flash code (for esd boards)
+ */
+#include "../common/flash.c"
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long * addr, flash_info_t * info);
+static void flash_get_offsets (ulong base, flash_info_t * info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	unsigned long size_b0, size_b1;
+	int i;
+	uint pbcr;
+	unsigned long base_b0, base_b1;
+	int size_val = 0;
+
+	/* Init: no FLASHes known */
+	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	base_b0 = FLASH_BASE0_PRELIM;
+	size_b0 = flash_get_size ((vu_long *) base_b0, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0 << 20);
+	}
+
+	base_b1 = FLASH_BASE1_PRELIM;
+	size_b1 = flash_get_size ((vu_long *) base_b1, &flash_info[1]);
+
+	/* Re-do sizing to get full correct info */
+
+	if (size_b1) {
+		mtdcr (ebccfga, pb0cr);
+		pbcr = mfdcr (ebccfgd);
+		mtdcr (ebccfga, pb0cr);
+		base_b1 = -size_b1;
+		switch (size_b1) {
+		case 1 << 20:
+			size_val = 0;
+			break;
+		case 2 << 20:
+			size_val = 1;
+			break;
+		case 4 << 20:
+			size_val = 2;
+			break;
+		case 8 << 20:
+			size_val = 3;
+			break;
+		case 16 << 20:
+			size_val = 4;
+			break;
+		}
+		pbcr = (pbcr & 0x0001ffff) | base_b1 | (size_val << 17);
+		mtdcr (ebccfgd, pbcr);
+		/*          printf("pb1cr = %x\n", pbcr); */
+	}
+
+	if (size_b0) {
+		mtdcr (ebccfga, pb1cr);
+		pbcr = mfdcr (ebccfgd);
+		mtdcr (ebccfga, pb1cr);
+		base_b0 = base_b1 - size_b0;
+		switch (size_b1) {
+		case 1 << 20:
+			size_val = 0;
+			break;
+		case 2 << 20:
+			size_val = 1;
+			break;
+		case 4 << 20:
+			size_val = 2;
+			break;
+		case 8 << 20:
+			size_val = 3;
+			break;
+		case 16 << 20:
+			size_val = 4;
+			break;
+		}
+		pbcr = (pbcr & 0x0001ffff) | base_b0 | (size_val << 17);
+		mtdcr (ebccfgd, pbcr);
+		/*            printf("pb0cr = %x\n", pbcr); */
+	}
+
+	size_b0 = flash_get_size ((vu_long *) base_b0, &flash_info[0]);
+
+	flash_get_offsets (base_b0, &flash_info[0]);
+
+	/* monitor protection ON by default */
+	flash_protect (FLAG_PROTECT_SET,
+			base_b0 + size_b0 - CFG_MONITOR_LEN,
+			base_b0 + size_b0 - 1, &flash_info[0]);
+
+	if (size_b1) {
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size ((vu_long *) base_b1, &flash_info[1]);
+
+		flash_get_offsets (base_b1, &flash_info[1]);
+
+		/* monitor protection ON by default */
+		flash_protect (FLAG_PROTECT_SET,
+				base_b1 + size_b1 - CFG_MONITOR_LEN,
+				base_b1 + size_b1 - 1, &flash_info[1]);
+		/* monitor protection OFF by default (one is enough) */
+		flash_protect (FLAG_PROTECT_CLEAR,
+				base_b0 + size_b0 - CFG_MONITOR_LEN,
+				base_b0 + size_b0 - 1, &flash_info[0]);
+	} else {
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+	}
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+}
diff --git a/board/esd/pci405/flash.c b/board/esd/pci405/flash.c
new file mode 100644
index 0000000..f904aff
--- /dev/null
+++ b/board/esd/pci405/flash.c
@@ -0,0 +1,101 @@
+/*
+ * (C) Copyright 2001
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * 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 <ppc4xx.h>
+#include <asm/processor.h>
+
+/*
+ * include common flash code (for esd boards)
+ */
+#include "../common/flash.c"
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long * addr, flash_info_t * info);
+static void flash_get_offsets (ulong base, flash_info_t * info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	unsigned long size_b0;
+	int i;
+        uint pbcr;
+        unsigned long base_b0;
+	int size_val = 0;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+        /* Setup offsets */
+        flash_get_offsets (-size_b0, &flash_info[0]);
+
+        /* Re-do sizing to get full correct info */
+        mtdcr(ebccfga, pb0cr);
+        pbcr = mfdcr(ebccfgd);
+        mtdcr(ebccfga, pb0cr);
+        base_b0 = -size_b0;
+	switch (size_b0) {
+	case 1 << 20:
+		size_val = 0;
+		break;
+	case 2 << 20:
+		size_val = 1;
+		break;
+	case 4 << 20:
+		size_val = 2;
+		break;
+	case 8 << 20:
+		size_val = 3;
+		break;
+	case 16 << 20:
+		size_val = 4;
+		break;
+	}
+	pbcr = (pbcr & 0x0001ffff) | base_b0 | (size_val << 17);
+        mtdcr(ebccfgd, pbcr);
+
+        /* Monitor protection ON by default */
+        (void)flash_protect(FLAG_PROTECT_SET,
+                            -CFG_MONITOR_LEN,
+                            0xffffffff,
+                            &flash_info[0]);
+
+        flash_info[0].size = size_b0;
+
+	return (size_b0);
+}
diff --git a/board/esteem192e/flash.c b/board/esteem192e/flash.c
new file mode 100644
index 0000000..55845fa
--- /dev/null
+++ b/board/esteem192e/flash.c
@@ -0,0 +1,1096 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+#ifdef CONFIG_FLASH_16BIT
+#define FLASH_WORD_SIZE	unsigned short
+#define	FLASH_ID_MASK	0xFFFF
+#else
+#define FLASH_WORD_SIZE unsigned long
+#define	FLASH_ID_MASK	0xFFFFFFFF
+#endif
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+
+ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info);
+#ifndef CONFIG_FLASH_16BIT
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+#else
+static int write_short (flash_info_t *info, ulong dest, ushort data);
+#endif
+/*int flash_write (uchar *, ulong, ulong); */
+/*flash_info_t *addr2info (ulong);   */
+
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size_b0 = flash_get_size((volatile FLASH_WORD_SIZE *)FLASH_BASE0_PRELIM,
+				 &flash_info[0]);
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+	size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)FLASH_BASE1_PRELIM,
+				 &flash_info[1]);
+
+	if (size_b1 > size_b0) {
+		printf ("## ERROR: "
+			"Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
+			size_b1, size_b1<<20,
+			size_b0, size_b0<<20
+		);
+		flash_info[0].flash_id	= FLASH_UNKNOWN;
+		flash_info[1].flash_id	= FLASH_UNKNOWN;
+		flash_info[0].sector_count	= -1;
+		flash_info[1].sector_count	= -1;
+		flash_info[0].size		= 0;
+		flash_info[1].size		= 0;
+		return (0);
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
+	memctl->memc_br0 = CFG_FLASH_BASE | 0x00000801; /*  (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;*/
+
+	/* Re-do sizing to get full correct info */
+
+	size_b0 = flash_get_size((volatile FLASH_WORD_SIZE *)CFG_FLASH_BASE,
+				 &flash_info[0]);
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	(void)flash_protect(FLAG_PROTECT_SET,
+			    CFG_MONITOR_BASE,
+			    CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+			    &flash_info[0]);
+#endif
+
+	if (size_b1) {
+		memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
+		memctl->memc_br1 = (CFG_FLASH_BASE | 0x00000801) + (size_b0 & BR_BA_MSK);
+                              /*((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
+				    BR_MS_GPCM | BR_V;*/
+
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)(CFG_FLASH_BASE + size_b0),
+					  &flash_info[1]);
+
+		flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+		/* monitor protection ON by default */
+		(void)flash_protect(FLAG_PROTECT_SET,
+				    CFG_MONITOR_BASE,
+				    CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+				    &flash_info[1]);
+#endif
+	} else {
+		memctl->memc_br1 = 0;		/* invalidate bank */
+
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+	}
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start adress table */
+	if (info->flash_id & FLASH_BTYPE) {
+             if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
+
+#ifndef CONFIG_FLASH_16BIT
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00008000;
+		info->start[3] = base + 0x0000C000;
+		info->start[4] = base + 0x00010000;
+		info->start[5] = base + 0x00014000;
+		info->start[6] = base + 0x00018000;
+		info->start[7] = base + 0x0001C000;
+		for (i = 8; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x000E0000;
+	        }
+               }
+             else {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	       }
+#else
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00002000;
+		info->start[2] = base + 0x00004000;
+		info->start[3] = base + 0x00006000;
+		info->start[4] = base + 0x00008000;
+		info->start[5] = base + 0x0000A000;
+		info->start[6] = base + 0x0000C000;
+		info->start[7] = base + 0x0000E000;
+		for (i = 8; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00010000) - 0x00070000;
+	        }
+	       }
+             else {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00006000;
+		info->start[3] = base + 0x00008000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00010000) - 0x00030000;
+		}
+	       }
+#endif
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+             if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
+
+#ifndef CONFIG_FLASH_16BIT
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		info->start[i--] = base + info->size - 0x00014000;
+		info->start[i--] = base + info->size - 0x00018000;
+		info->start[i--] = base + info->size - 0x0001C000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+
+               } else {
+
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	       }
+#else
+		info->start[i--] = base + info->size - 0x00002000;
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00006000;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000A000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x0000E000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00010000;
+		}
+
+               } else {
+
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00006000;
+		info->start[i--] = base + info->size - 0x00008000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00010000;
+		}
+	       }
+#endif
+	}
+
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+	uchar *boottype;
+	uchar botboot[]=", bottom boot sect)\n";
+	uchar topboot[]=", top boot sector)\n";
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	case FLASH_MAN_SST:	printf ("SST ");		break;
+	case FLASH_MAN_STM:	printf ("STM ");		break;
+	case FLASH_MAN_INTEL:	printf ("INTEL ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	if (info->flash_id & 0x0001 ) {
+	boottype = botboot;
+	} else {
+	boottype = topboot;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit%s",boottype);
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit%s",boottype);
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit%s",boottype);
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit%s",boottype);
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit%s",boottype);
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit%s",boottype);
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit%s",boottype);
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit%s",boottype);
+				break;
+	case FLASH_INTEL800B:	printf ("INTEL28F800B (8 Mbit%s",boottype);
+				break;
+	case FLASH_INTEL800T:	printf ("INTEL28F800T (8 Mbit%s",boottype);
+				break;
+	case FLASH_INTEL160B:	printf ("INTEL28F160B (16 Mbit%s",boottype);
+				break;
+	case FLASH_INTEL160T:	printf ("INTEL28F160T (16 Mbit%s",boottype);
+				break;
+	case FLASH_INTEL320B:	printf ("INTEL28F320B (32 Mbit%s",boottype);
+				break;
+	case FLASH_INTEL320T:	printf ("INTEL28F320T (32 Mbit%s",boottype);
+				break;
+
+#if 0 /* enable when devices are available */
+
+	case FLASH_INTEL640B:	printf ("INTEL28F640B (64 Mbit%s",boottype);
+				break;
+	case FLASH_INTEL640T:	printf ("INTEL28F640T (64 Mbit%s",boottype);
+				break;
+#endif
+
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+ulong flash_get_size (volatile FLASH_WORD_SIZE *addr, flash_info_t *info)
+{
+	short i;
+	ulong base = (ulong)addr;
+	FLASH_WORD_SIZE value;
+
+	/* Write auto select command: read Manufacturer ID */
+
+
+#ifndef CONFIG_FLASH_16BIT
+
+	/*
+	 * Note: if it is an AMD flash and the word at addr[0000]
+         * is 0x00890089 this routine will think it is an Intel
+         * flash device and may(most likely) cause trouble.
+	 */
+
+	addr[0x0000] = 0x00900090;
+	if(addr[0x0000] != 0x00890089){
+		addr[0x0555] = 0x00AA00AA;
+		addr[0x02AA] = 0x00550055;
+		addr[0x0555] = 0x00900090;
+#else
+
+	/*
+	 * Note: if it is an AMD flash and the word at addr[0000]
+         * is 0x0089 this routine will think it is an Intel
+         * flash device and may(most likely) cause trouble.
+	 */
+
+	addr[0x0000] = 0x0090;
+
+	if(addr[0x0000] != 0x0089){
+		addr[0x0555] = 0x00AA;
+		addr[0x02AA] = 0x0055;
+		addr[0x0555] = 0x0090;
+#endif
+	}
+	value = addr[0];
+
+	switch (value) {
+	case (AMD_MANUFACT & FLASH_ID_MASK):
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case (FUJ_MANUFACT & FLASH_ID_MASK):
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	case (STM_MANUFACT & FLASH_ID_MASK):
+		info->flash_id = FLASH_MAN_STM;
+		break;
+	case (SST_MANUFACT & FLASH_ID_MASK):
+		info->flash_id = FLASH_MAN_SST;
+		break;
+	case (INTEL_MANUFACT & FLASH_ID_MASK):
+		info->flash_id = FLASH_MAN_INTEL;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	switch (value) {
+
+	case (AMD_ID_LV400T & FLASH_ID_MASK):
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (AMD_ID_LV400B & FLASH_ID_MASK):
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (AMD_ID_LV800T & FLASH_ID_MASK):
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case (AMD_ID_LV800B & FLASH_ID_MASK):
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case (AMD_ID_LV160T & FLASH_ID_MASK):
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case (AMD_ID_LV160B & FLASH_ID_MASK):
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+	case (AMD_ID_LV320T & FLASH_ID_MASK):
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case (AMD_ID_LV320B & FLASH_ID_MASK):
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+#endif
+
+	case (INTEL_ID_28F800B3T & FLASH_ID_MASK):
+		info->flash_id += FLASH_INTEL800T;
+		info->sector_count = 23;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case (INTEL_ID_28F800B3B & FLASH_ID_MASK):
+		info->flash_id += FLASH_INTEL800B;
+		info->sector_count = 23;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case (INTEL_ID_28F160B3T & FLASH_ID_MASK):
+		info->flash_id += FLASH_INTEL160T;
+		info->sector_count = 39;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case (INTEL_ID_28F160B3B & FLASH_ID_MASK):
+		info->flash_id += FLASH_INTEL160B;
+		info->sector_count = 39;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case (INTEL_ID_28F320B3T & FLASH_ID_MASK):
+		info->flash_id += FLASH_INTEL320T;
+		info->sector_count = 71;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case (INTEL_ID_28F320B3B & FLASH_ID_MASK):
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 71;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+#if 0 /* enable when devices are available */
+	case (INTEL_ID_28F320B3T & FLASH_ID_MASK):
+		info->flash_id += FLASH_INTEL320T;
+		info->sector_count = 135;
+		info->size = 0x01000000;
+		break;				/* => 16 MB		*/
+
+	case (INTEL_ID_28F320B3B & FLASH_ID_MASK):
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 135;
+		info->size = 0x01000000;
+		break;				/* => 16 MB		*/
+#endif
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	/* set up sector start adress table */
+	if (info->flash_id & FLASH_BTYPE) {
+             if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
+
+#ifndef CONFIG_FLASH_16BIT
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00008000;
+		info->start[3] = base + 0x0000C000;
+		info->start[4] = base + 0x00010000;
+		info->start[5] = base + 0x00014000;
+		info->start[6] = base + 0x00018000;
+		info->start[7] = base + 0x0001C000;
+		for (i = 8; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x000E0000;
+	        }
+               }
+             else {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	       }
+#else
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00002000;
+		info->start[2] = base + 0x00004000;
+		info->start[3] = base + 0x00006000;
+		info->start[4] = base + 0x00008000;
+		info->start[5] = base + 0x0000A000;
+		info->start[6] = base + 0x0000C000;
+		info->start[7] = base + 0x0000E000;
+		for (i = 8; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00010000) - 0x00070000;
+	        }
+	       }
+             else {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00006000;
+		info->start[3] = base + 0x00008000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00010000) - 0x00030000;
+		}
+	       }
+#endif
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+             if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
+
+#ifndef CONFIG_FLASH_16BIT
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		info->start[i--] = base + info->size - 0x00014000;
+		info->start[i--] = base + info->size - 0x00018000;
+		info->start[i--] = base + info->size - 0x0001C000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+
+               } else {
+
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	       }
+#else
+		info->start[i--] = base + info->size - 0x00002000;
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00006000;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000A000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x0000E000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00010000;
+		}
+
+               } else {
+
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00006000;
+		info->start[i--] = base + info->size - 0x00008000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00010000;
+		}
+	       }
+#endif
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr = (volatile FLASH_WORD_SIZE *)(info->start[i]);
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (volatile FLASH_WORD_SIZE *)info->start[0];
+		if( (info->flash_id & 0xFF00) == FLASH_MAN_INTEL){
+		   *addr = (0x00F000F0 & FLASH_ID_MASK);	/* reset bank */
+		} else {
+		   *addr = (0x00FF00FF & FLASH_ID_MASK);	/* reset bank */
+		}
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+
+	volatile FLASH_WORD_SIZE *addr=(volatile FLASH_WORD_SIZE*)(info->start[0]);
+	int flag, prot, sect, l_sect, barf;
+	ulong start, now, last;
+	int rcode = 0;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    ((info->flash_id > FLASH_AMD_COMP) &&
+             ( (info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL ) ) ){
+		printf ("Can't erase unknown flash type - aborted\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+    if(info->flash_id < FLASH_AMD_COMP) {
+#ifndef CONFIG_FLASH_16BIT
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00800080;
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+#else
+	addr[0x0555] = 0x00AA;
+	addr[0x02AA] = 0x0055;
+	addr[0x0555] = 0x0080;
+	addr[0x0555] = 0x00AA;
+	addr[0x02AA] = 0x0055;
+#endif
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (volatile FLASH_WORD_SIZE *)(info->start[sect]);
+			addr[0] = (0x00300030 & FLASH_ID_MASK);
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (volatile FLASH_WORD_SIZE*)(info->start[l_sect]);
+	while ((addr[0] & (0x00800080&FLASH_ID_MASK)) !=
+			  (0x00800080&FLASH_ID_MASK)  )
+	{
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			serial_putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (volatile FLASH_WORD_SIZE *)info->start[0];
+	addr[0] = (0x00F000F0 & FLASH_ID_MASK);	/* reset bank */
+    } else {
+
+
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			barf = 0;
+#ifndef CONFIG_FLASH_16BIT
+			addr = (vu_long*)(info->start[sect]);
+			addr[0] = 0x00200020;
+			addr[0] = 0x00D000D0;
+			while(!(addr[0] & 0x00800080));	/* wait for error or finish */
+			if( addr[0] & 0x003A003A) {	/* check for error */
+				barf = addr[0] & 0x003A0000;
+				if( barf ) {
+					barf >>=16;
+				} else {
+					barf = addr[0] & 0x0000003A;
+				}
+			}
+#else
+			addr = (vu_short*)(info->start[sect]);
+			addr[0] = 0x0020;
+			addr[0] = 0x00D0;
+			while(!(addr[0] & 0x0080));	/* wait for error or finish */
+			if( addr[0] & 0x003A)	/* check for error */
+				barf = addr[0] & 0x003A;
+#endif
+			if(barf) {
+				printf("\nFlash error in sector at %lx\n",(unsigned long)addr);
+				if(barf & 0x0002) printf("Block locked, not erased.\n");
+				if((barf & 0x0030) == 0x0030)
+					printf("Command Sequence error.\n");
+				if((barf & 0x0030) == 0x0020)
+					printf("Block Erase error.\n");
+				if(barf & 0x0008) printf("Vpp Low error.\n");
+				rcode = 1;
+			} else printf(".");
+			l_sect = sect;
+		}
+	addr = (volatile FLASH_WORD_SIZE *)info->start[0];
+	addr[0] = (0x00FF00FF & FLASH_ID_MASK);	/* reset bank */
+
+	}
+
+    }
+	printf (" done\n");
+	return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+#ifndef CONFIG_FLASH_16BIT
+	ulong cp, wp, data;
+	int l;
+#else
+	ulong cp, wp;
+	ushort data;
+#endif
+	int i, rc;
+
+#ifndef CONFIG_FLASH_16BIT
+
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+
+#else
+	wp = (addr & ~1);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start byte
+	 */
+	if (addr - wp) {
+		data = 0;
+		data = (data << 8) | *src++;
+		--cnt;
+		if ((rc = write_short(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 2;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+/*	l = 0; used for debuging  */
+	while (cnt >= 2) {
+		data = 0;
+		for (i=0; i<2; ++i) {
+			data = (data << 8) | *src++;
+		}
+
+/*		if(!l){
+			printf("%x",data);
+			l = 1;
+		}  used for debuging */
+
+		if ((rc = write_short(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 2;
+		cnt -= 2;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<2; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_short(info, wp, data));
+
+
+#endif
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+#ifndef CONFIG_FLASH_16BIT
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	ulong start,barf;
+	int flag;
+
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *)dest) & data) != data) {
+		return (2);
+	}
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+     if(info->flash_id > FLASH_AMD_COMP) {
+	/* AMD stuff */
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00A000A0;
+     } else {
+	/* intel stuff */
+	*addr = 0x00400040;
+     }
+	*((vu_long *)dest) = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+
+     if(info->flash_id > FLASH_AMD_COMP) {
+
+	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+
+     } else {
+
+	while(!(addr[0] & 0x00800080)){  	/* wait for error or finish */
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+	}
+
+	if( addr[0] & 0x003A003A) {	/* check for error */
+		barf = addr[0] & 0x003A0000;
+		if( barf ) {
+			barf >>=16;
+		} else {
+		        barf = addr[0] & 0x0000003A;
+		}
+		printf("\nFlash write error at address %lx\n",(unsigned long)dest);
+		if(barf & 0x0002) printf("Block locked, not erased.\n");
+		if(barf & 0x0010) printf("Programming error.\n");
+		if(barf & 0x0008) printf("Vpp Low error.\n");
+	  	return(2);
+	}
+
+
+     }
+
+	return (0);
+
+}
+
+#else
+
+static int write_short (flash_info_t *info, ulong dest, ushort data)
+{
+	vu_short *addr = (vu_short*)(info->start[0]);
+	ulong start,barf;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_short *)dest) & data) != data) {
+		return (2);
+	}
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+     if(info->flash_id < FLASH_AMD_COMP) {
+	/* AMD stuff */
+	addr[0x0555] = 0x00AA;
+	addr[0x02AA] = 0x0055;
+	addr[0x0555] = 0x00A0;
+     } else {
+	/* intel stuff */
+        *addr = 0x00D0;
+	*addr = 0x0040;
+     }
+	*((vu_short *)dest) = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+
+     if(info->flash_id < FLASH_AMD_COMP) {
+          /* AMD stuff */
+	while ((*((vu_short *)dest) & 0x0080) != (data & 0x0080)) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+
+     } else {
+	/* intel stuff */
+	while(!(addr[0] & 0x0080)){  	/* wait for error or finish */
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) return (1);
+	}
+
+	if( addr[0] & 0x003A) {	/* check for error */
+		barf = addr[0] & 0x003A;
+		printf("\nFlash write error at address %lx\n",(unsigned long)dest);
+		if(barf & 0x0002) printf("Block locked, not erased.\n");
+		if(barf & 0x0010) printf("Programming error.\n");
+		if(barf & 0x0008) printf("Vpp Low error.\n");
+	  	return(2);
+	}
+	*addr = 0x00B0;
+	*addr = 0x0070;
+	while(!(addr[0] & 0x0080)){  	/* wait for error or finish */
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) return (1);
+	}
+
+	*addr = 0x00FF;
+
+     }
+
+	return (0);
+
+}
+
+
+#endif
+
+/*-----------------------------------------------------------------------
+ */
+
diff --git a/board/etx094/flash.c b/board/etx094/flash.c
new file mode 100644
index 0000000..b3c620e
--- /dev/null
+++ b/board/etx094/flash.c
@@ -0,0 +1,744 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+	size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+
+	if (size_b1 > size_b0) {
+		printf ("## ERROR: "
+			"Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
+			size_b1, size_b1<<20,
+			size_b0, size_b0<<20
+		);
+		flash_info[0].flash_id	= FLASH_UNKNOWN;
+		flash_info[1].flash_id	= FLASH_UNKNOWN;
+		flash_info[0].sector_count	= -1;
+		flash_info[1].sector_count	= -1;
+		flash_info[0].size		= 0;
+		flash_info[1].size		= 0;
+		return (0);
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
+#ifdef CONFIG_FLASH_16BIT
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V | BR_PS_16; /* 16 Bit data port */
+#else
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
+#endif
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+	if (size_b1) {
+		memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
+#ifdef CONFIG_FLASH_16BIT
+		memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
+				    BR_MS_GPCM | BR_V | BR_PS_16;
+#else
+		memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
+				    BR_MS_GPCM | BR_V;
+#endif
+
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0),
+					  &flash_info[1]);
+
+		flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+		/* monitor protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_MONITOR_BASE,
+			      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+			      &flash_info[1]);
+#endif
+	} else {
+		memctl->memc_br1 = 0;		/* invalidate bank */
+
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+	}
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
+		for (i = 0; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00002000);
+		}
+		return;
+	}
+
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+#ifdef CONFIG_FLASH_16BIT
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00006000;
+		info->start[3] = base + 0x00008000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00010000) - 0x00030000;
+#else
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+#endif
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	case FLASH_MAN_SST:	printf ("SST ");		break;
+	case FLASH_MAN_STM:	printf ("STM ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+				break;
+	case FLASH_SST200A:	printf ("39xF200A (2M = 128K x 16)\n");
+				break;
+	case FLASH_SST400A:	printf ("39xF400A (4M = 256K x 16)\n");
+				break;
+	case FLASH_SST800A:	printf ("39xF800A (8M = 512K x 16)\n");
+				break;
+	case FLASH_STM800AB:	printf ("M29W800AB (8M = 512K x 16)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	ulong value;
+	ulong base = (ulong)addr;
+
+	/* Write auto select command: read Manufacturer ID */
+#ifdef CONFIG_FLASH_16BIT
+	vu_short *s_addr = (vu_short*)addr;
+	s_addr[0x5555] = 0x00AA;
+	s_addr[0x2AAA] = 0x0055;
+	s_addr[0x5555] = 0x0090;
+	value = s_addr[0];
+	value = value|(value<<16);
+#else
+	addr[0x5555] = 0x00AA00AA;
+	addr[0x2AAA] = 0x00550055;
+	addr[0x5555] = 0x00900090;
+	value = addr[0];
+#endif
+
+	switch (value) {
+	case AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	case SST_MANUFACT:
+		info->flash_id = FLASH_MAN_SST;
+		break;
+	case STM_MANUFACT:
+		info->flash_id = FLASH_MAN_STM;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+#ifdef CONFIG_FLASH_16BIT
+	value = s_addr[1];
+	value = value|(value<<16);
+#else
+	value = addr[1];			/* device ID		*/
+#endif
+
+	switch (value) {
+	case AMD_ID_LV400T:
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV400B:
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV800T:
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV800B:
+		info->flash_id += FLASH_AM800B;
+#ifdef CONFIG_FLASH_16BIT
+		info->sector_count = 19;
+		info->size = 0x00100000;	/* => 1 MB */
+#else
+		info->sector_count = 19;
+		info->size = 0x00200000;	/* => 2 MB	*/
+#endif
+		break;
+
+	case AMD_ID_LV160T:
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case AMD_ID_LV160B:
+		info->flash_id += FLASH_AM160B;
+#ifdef CONFIG_FLASH_16BIT
+		info->sector_count = 35;
+		info->size = 0x00200000;	/* => 2 MB	*/
+#else
+		info->sector_count = 35;
+		info->size = 0x00400000;	/* => 4 MB	*/
+#endif
+
+		break;
+#if 0	/* enable when device IDs are available */
+	case AMD_ID_LV320T:
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case AMD_ID_LV320B:
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+#endif
+	case SST_ID_xF200A:
+		info->flash_id += FLASH_SST200A;
+		info->sector_count = 64;	/* 39xF200A ID ( 2M = 128K x 16	) */
+		info->size = 0x00080000;
+		break;
+	case SST_ID_xF400A:
+		info->flash_id += FLASH_SST400A;
+		info->sector_count = 128;	/* 39xF400A ID ( 4M = 256K x 16	) */
+		info->size = 0x00100000;
+		break;
+	case SST_ID_xF800A:
+		info->flash_id += FLASH_SST800A;
+		info->sector_count = 256;	/* 39xF800A ID ( 8M = 512K x 16	) */
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+	case STM_ID_x800AB:
+		info->flash_id += FLASH_STM800AB;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	if (info->sector_count > CFG_MAX_FLASH_SECT) {
+		printf ("** ERROR: sector count %d > max (%d) **\n",
+			info->sector_count, CFG_MAX_FLASH_SECT);
+		info->sector_count = CFG_MAX_FLASH_SECT;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
+		for (i = 0; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00002000);
+		}
+	} else {	/* AMD and Fujitsu types */
+		/* set up sector start address table */
+		if (info->flash_id & FLASH_BTYPE) {
+			/* set sector offsets for bottom boot block type	*/
+#ifdef CONFIG_FLASH_16BIT
+
+			info->start[0] = base + 0x00000000;
+			info->start[1] = base + 0x00004000;
+			info->start[2] = base + 0x00006000;
+			info->start[3] = base + 0x00008000;
+			for (i = 4; i < info->sector_count; i++) {
+				info->start[i] = base + (i * 0x00010000) - 0x00030000;
+#else
+			info->start[0] = base + 0x00000000;
+			info->start[1] = base + 0x00008000;
+			info->start[2] = base + 0x0000C000;
+			info->start[3] = base + 0x00010000;
+			for (i = 4; i < info->sector_count; i++) {
+				info->start[i] = base + (i * 0x00020000) - 0x00060000;
+#endif
+			}
+		} else {
+			/* set sector offsets for top boot block type		*/
+			i = info->sector_count - 1;
+			info->start[i--] = base + info->size - 0x00008000;
+			info->start[i--] = base + info->size - 0x0000C000;
+			info->start[i--] = base + info->size - 0x00010000;
+			for (; i >= 0; i--) {
+				info->start[i] = base + i * 0x00020000;
+			}
+		}
+
+		/* check for protected sectors */
+		for (i = 0; i < info->sector_count; i++) {
+			/* read sector protection at sector address:
+			 * (A7 .. A0) = 0x02
+			 * D0 = 1 if protected
+			 */
+#ifdef CONFIG_FLASH_16BIT
+			s_addr = (volatile unsigned short *)(info->start[i]);
+			info->protect[i] = s_addr[2] & 1;
+#else
+			addr = (volatile unsigned long *)(info->start[i]);
+			info->protect[i] = addr[2] & 1;
+#endif
+		}
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+#ifdef CONFIG_FLASH_16BIT
+		s_addr = (volatile unsigned short *)(info->start[0]);
+		*s_addr = 0x00F0;	/* reset bank */
+#else
+		addr = (volatile unsigned long *)info->start[0];
+		*addr = 0x00F000F0;	/* reset bank */
+#endif
+
+	}
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	int flag, prot, sect;
+	ulong start, now, last;
+#ifdef CONFIG_FLASH_16BIT
+	vu_short *s_addr = (vu_short*)addr;
+#endif
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+/*#ifndef CONFIG_FLASH_16BIT
+	ulong type;
+	type = (info->flash_id & FLASH_VENDMASK);
+	if ((type != FLASH_MAN_SST) && (type != FLASH_MAN_STM)) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return;
+	}
+#endif*/
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	start = get_timer (0);
+	last  = start;
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+#ifdef CONFIG_FLASH_16BIT
+			vu_short *s_sect_addr = (vu_short*)(info->start[sect]);
+#else
+			vu_long	*sect_addr = (vu_long*)(info->start[sect]);
+#endif
+			/* Disable interrupts which might cause a timeout here */
+			flag = disable_interrupts();
+
+#ifdef CONFIG_FLASH_16BIT
+
+			/*printf("\ns_sect_addr=%x",s_sect_addr);*/
+			s_addr[0x5555] = 0x00AA;
+			s_addr[0x2AAA] = 0x0055;
+			s_addr[0x5555] = 0x0080;
+			s_addr[0x5555] = 0x00AA;
+			s_addr[0x2AAA] = 0x0055;
+			s_sect_addr[0] = 0x0030;
+#else
+			addr[0x5555] = 0x00AA00AA;
+			addr[0x2AAA] = 0x00550055;
+			addr[0x5555] = 0x00800080;
+			addr[0x5555] = 0x00AA00AA;
+			addr[0x2AAA] = 0x00550055;
+			sect_addr[0] = 0x00300030;
+#endif
+			/* re-enable interrupts if necessary */
+			if (flag)
+				enable_interrupts();
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+
+#ifdef CONFIG_FLASH_16BIT
+			while ((s_sect_addr[0] & 0x0080) != 0x0080) {
+#else
+			while ((sect_addr[0] & 0x00800080) != 0x00800080) {
+#endif
+				if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout\n");
+					return 1;
+				}
+				/* show that we're waiting */
+				if ((now - last) > 1000) {	/* every second */
+					putc ('.');
+					last = now;
+				}
+			}
+		}
+	}
+
+	/* reset to read mode */
+	addr = (volatile unsigned long *)info->start[0];
+#ifdef CONFIG_FLASH_16BIT
+	s_addr[0] = 0x00F0;	/* reset bank */
+#else
+	addr[0] = 0x00F000F0;	/* reset bank */
+#endif
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 4 - Flash not identified
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return 4;
+	}
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+
+#ifdef CONFIG_FLASH_16BIT
+	vu_short high_data;
+	vu_short low_data;
+	vu_short *s_addr = (vu_short*)addr;
+#endif
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *)dest) & data) != data) {
+		return (2);
+	}
+
+#ifdef CONFIG_FLASH_16BIT
+	/* Write the 16 higher-bits */
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	high_data = ((data>>16) & 0x0000ffff);
+
+	s_addr[0x5555] = 0x00AA;
+	s_addr[0x2AAA] = 0x0055;
+	s_addr[0x5555] = 0x00A0;
+
+	*((vu_short *)dest) = high_data;
+
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	while ((*((vu_short *)dest) & 0x0080) != (high_data & 0x0080)) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+
+
+	/* Write the 16 lower-bits */
+#endif
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+#ifdef CONFIG_FLASH_16BIT
+	dest += 0x2;
+	low_data = (data & 0x0000ffff);
+
+	s_addr[0x5555] = 0x00AA;
+	s_addr[0x2AAA] = 0x0055;
+	s_addr[0x5555] = 0x00A0;
+	*((vu_short *)dest) = low_data;
+
+#else
+	addr[0x5555] = 0x00AA00AA;
+	addr[0x2AAA] = 0x00550055;
+	addr[0x5555] = 0x00A000A0;
+	*((vu_long *)dest) = data;
+#endif
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+
+#ifdef CONFIG_FLASH_16BIT
+	while ((*((vu_short *)dest) & 0x0080) != (low_data & 0x0080)) {
+#else
+	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
+#endif
+
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/evb64260/i2c.c b/board/evb64260/i2c.c
new file mode 100644
index 0000000..22cb809
--- /dev/null
+++ b/board/evb64260/i2c.c
@@ -0,0 +1,315 @@
+#include <common.h>
+#include <mpc8xx.h>
+#include <malloc.h>
+#include <galileo/gt64260R.h>
+#include <galileo/core.h>
+
+#define MAX_I2C_RETRYS	    10
+#define I2C_DELAY	    1000  /* Should be at least the # of MHz of Tclk */
+#undef	DEBUG_I2C
+
+#ifdef DEBUG_I2C
+#define DP(x) x
+#else
+#define DP(x)
+#endif
+
+/* Assuming that there is only one master on the bus (us) */
+
+static void
+i2c_init(int speed, int slaveaddr)
+{
+	unsigned int n, m, freq, margin, power;
+	unsigned int actualFreq, actualN=0, actualM=0;
+	unsigned int control, status;
+	unsigned int minMargin = 0xffffffff;
+	unsigned int tclk = 125000000;
+
+	DP(puts("i2c_init\n"));
+
+	for(n = 0 ; n < 8 ; n++)
+	{
+		for(m = 0 ; m < 16 ; m++)
+		{
+			power = 2<<n; /* power = 2^(n+1) */
+			freq = tclk/(10*(m+1)*power);
+			if (speed > freq)
+				margin = speed - freq;
+			else
+				margin = freq - speed;
+			if(margin < minMargin)
+			{
+				minMargin   = margin;
+				actualFreq  = freq;
+				actualN	    = n;
+				actualM	    = m;
+			}
+		}
+	}
+
+	DP(puts("setup i2c bus\n"));
+
+	/* Setup bus */
+
+	GT_REG_WRITE(I2C_SOFT_RESET, 0);
+
+	DP(puts("udelay...\n"));
+
+	udelay(I2C_DELAY);
+
+	DP(puts("set baudrate\n"));
+
+	GT_REG_WRITE(I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN);
+	GT_REG_WRITE(I2C_CONTROL, (0x1 << 2) | (0x1 << 6));
+
+	udelay(I2C_DELAY * 10);
+
+	DP(puts("read control, baudrate\n"));
+
+	GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+	GT_REG_READ(I2C_CONTROL, &control);
+}
+
+static uchar
+i2c_start(void)
+{
+	unsigned int control, status;
+	int count = 0;
+
+	DP(puts("i2c_start\n"));
+
+	/* Set the start bit */
+
+	GT_REG_READ(I2C_CONTROL, &control);
+	control |= (0x1 << 5);
+	GT_REG_WRITE(I2C_CONTROL, control);
+
+	GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+
+	count = 0;
+	while ((status & 0xff) != 0x08) {
+		udelay(I2C_DELAY);
+		if (count > 20) {
+			GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
+			return (status);
+		}
+		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+		count++;
+	}
+
+	return (0);
+}
+
+static uchar
+i2c_select_device(uchar dev_addr, uchar read, int ten_bit)
+{
+	unsigned int status, data, bits = 7;
+	int count = 0;
+
+	DP(puts("i2c_select_device\n"));
+
+	/* Output slave address */
+
+	if (ten_bit) {
+		bits = 10;
+	}
+
+	data = (dev_addr << 1);
+	/* set the read bit */
+	data |= read;
+	GT_REG_WRITE(I2C_DATA, data);
+	/* assert the address */
+	RESET_REG_BITS(I2C_CONTROL, BIT3);
+
+	udelay(I2C_DELAY);
+
+	GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+	count = 0;
+	while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) {
+		udelay(I2C_DELAY);
+		if (count > 20) {
+			GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
+			return(status);
+		}
+		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+		count++;
+	}
+
+	if (bits == 10) {
+		printf("10 bit I2C addressing not yet implemented\n");
+		return (0xff);
+	}
+
+	return (0);
+}
+
+static uchar
+i2c_get_data(uchar* return_data, int len) {
+
+	unsigned int data, status;
+	int count = 0;
+
+	DP(puts("i2c_get_data\n"));
+
+	while (len) {
+
+		/* Get and return the data */
+
+		RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
+
+		udelay(I2C_DELAY * 5);
+
+		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+		count++;
+		while ((status & 0xff) != 0x50) {
+			udelay(I2C_DELAY);
+			if(count > 2) {
+				GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
+				return 0;
+			}
+			GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+			count++;
+		}
+		GT_REG_READ(I2C_DATA, &data);
+		len--;
+		*return_data = (uchar)data;
+		return_data++;
+	}
+	RESET_REG_BITS(I2C_CONTROL, BIT2|BIT3);
+	while ((status & 0xff) != 0x58) {
+		udelay(I2C_DELAY);
+		if(count > 200) {
+			GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
+			return (status);
+		}
+		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+		count++;
+	}
+	GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /* stop */
+
+	return (0);
+}
+
+static uchar
+i2c_write_data(unsigned int data, int len)
+{
+	unsigned int status;
+	int count = 0;
+
+	DP(puts("i2c_write_data\n"));
+
+	if (len > 4)
+		return -1;
+
+	while (len) {
+		/* Set and assert the data */
+
+		GT_REG_WRITE(I2C_DATA, (unsigned int)data);
+		RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
+
+		udelay(I2C_DELAY);
+
+		GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+		count++;
+		while ((status & 0xff) != 0x28) {
+			udelay(I2C_DELAY);
+			if(count > 20) {
+				GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
+				return (status);
+			}
+			GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
+			count++;
+		}
+		len--;
+	}
+	GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4));
+	GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
+
+	udelay(I2C_DELAY * 10);
+
+	return (0);
+}
+
+static uchar
+i2c_set_dev_offset(uchar dev_addr, unsigned int offset, int ten_bit)
+{
+	uchar status;
+
+	DP(puts("i2c_set_dev_offset\n"));
+
+	status = i2c_select_device(dev_addr, 0, ten_bit);
+	if (status) {
+#ifdef DEBUG_I2C
+		printf("Failed to select device setting offset: 0x%02x\n",
+		       status);
+#endif
+		return status;
+	}
+
+	status = i2c_write_data(offset, 1);
+	if (status) {
+#ifdef DEBUG_I2C
+		printf("Failed to write data: 0x%02x\n", status);
+#endif
+		return status;
+	}
+
+	return (0);
+}
+
+uchar
+i2c_read(uchar dev_addr, unsigned int offset, int len, uchar* data,
+	 int ten_bit)
+{
+	uchar status = 0;
+	unsigned int i2cFreq = 400000;
+
+	DP(puts("i2c_read\n"));
+
+	i2c_init(i2cFreq,0);
+
+	status = i2c_start();
+
+	if (status) {
+#ifdef DEBUG_I2C
+		printf("Transaction start failed: 0x%02x\n", status);
+#endif
+		return status;
+	}
+
+	status = i2c_set_dev_offset(dev_addr, 0, 0);
+	if (status) {
+#ifdef DEBUG_I2C
+		printf("Failed to set offset: 0x%02x\n", status);
+#endif
+		return status;
+	}
+
+	i2c_init(i2cFreq,0);
+
+	status = i2c_start();
+	if (status) {
+#ifdef DEBUG_I2C
+		printf("Transaction restart failed: 0x%02x\n", status);
+#endif
+		return status;
+	}
+
+	status = i2c_select_device(dev_addr, 1, ten_bit);
+	if (status) {
+#ifdef DEBUG_I2C
+		printf("Address not acknowledged: 0x%02x\n", status);
+#endif
+		return status;
+	}
+
+	status = i2c_get_data(data, len);
+	if (status) {
+#ifdef DEBUG_I2C
+		printf("Data not recieved: 0x%02x\n", status);
+#endif
+		return status;
+	}
+
+	return 0;
+}
diff --git a/board/evb64260/intel_flash.c b/board/evb64260/intel_flash.c
new file mode 100644
index 0000000..ed6a2a0
--- /dev/null
+++ b/board/evb64260/intel_flash.c
@@ -0,0 +1,277 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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
+ *
+ * Hacked for the Hymod board by Murray.Jensen@cmst.csiro.au, 20-Oct-00
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <galileo/gt64260R.h>
+#include <galileo/memory.h>
+#include "intel_flash.h"
+
+
+/*-----------------------------------------------------------------------
+ * Protection Flags:
+ */
+#define FLAG_PROTECT_SET	0x01
+#define FLAG_PROTECT_CLEAR	0x02
+
+static void
+bank_reset(flash_info_t *info, int sect)
+{
+	bank_addr_t addrw, eaddrw;
+
+	addrw = (bank_addr_t)info->start[sect];
+	eaddrw = BANK_ADDR_NEXT_WORD(addrw);
+
+	while (addrw < eaddrw) {
+#ifdef FLASH_DEBUG
+		printf("  writing reset cmd to addr 0x%08lx\n",
+			(unsigned long)addrw);
+#endif
+		*addrw = BANK_CMD_RST;
+		addrw++;
+	}
+}
+
+static void
+bank_erase_init(flash_info_t *info, int sect)
+{
+	bank_addr_t addrw, saddrw, eaddrw;
+	int flag;
+
+#ifdef FLASH_DEBUG
+	printf("0x%08x BANK_CMD_PROG\n", BANK_CMD_PROG);
+	printf("0x%08x BANK_CMD_ERASE1\n", BANK_CMD_ERASE1);
+	printf("0x%08x BANK_CMD_ERASE2\n", BANK_CMD_ERASE2);
+	printf("0x%08x BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT);
+	printf("0x%08x BANK_CMD_RST\n", BANK_CMD_RST);
+	printf("0x%08x BANK_STAT_RDY\n", BANK_STAT_RDY);
+	printf("0x%08x BANK_STAT_ERR\n", BANK_STAT_ERR);
+#endif
+
+	saddrw = (bank_addr_t)info->start[sect];
+	eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
+
+#ifdef FLASH_DEBUG
+	printf("erasing sector %d, start addr = 0x%08lx "
+		"(bank next word addr = 0x%08lx)\n", sect,
+		(unsigned long)saddrw, (unsigned long)eaddrw);
+#endif
+
+	/* Disable intrs which might cause a timeout here */
+	flag = disable_interrupts();
+
+	for (addrw = saddrw; addrw < eaddrw; addrw++) {
+#ifdef FLASH_DEBUG
+		printf("  writing erase cmd to addr 0x%08lx\n",
+			(unsigned long)addrw);
+#endif
+		*addrw = BANK_CMD_ERASE1;
+		*addrw = BANK_CMD_ERASE2;
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+}
+
+static int
+bank_erase_poll(flash_info_t *info, int sect)
+{
+	bank_addr_t addrw, saddrw, eaddrw;
+	int sectdone, haderr;
+
+	saddrw = (bank_addr_t)info->start[sect];
+	eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
+
+	sectdone = 1;
+	haderr = 0;
+
+	for (addrw = saddrw; addrw < eaddrw; addrw++) {
+		bank_word_t stat = *addrw;
+
+#ifdef FLASH_DEBUG
+		printf("  checking status at addr "
+			"0x%08x [0x%08x]\n",
+			(unsigned long)addrw, stat);
+#endif
+		if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY)
+			sectdone = 0;
+		else if ((stat & BANK_STAT_ERR) != 0) {
+			printf(" failed on sector %d "
+				"(stat = 0x%08x) at "
+				"address 0x%p\n",
+				sect, stat, addrw);
+			*addrw = BANK_CMD_CLR_STAT;
+			haderr = 1;
+		}
+	}
+
+	if (haderr)
+		return (-1);
+	else
+		return (sectdone);
+}
+
+int
+write_word_intel(bank_addr_t addr, bank_word_t value)
+{
+	bank_word_t stat;
+	ulong start;
+	int flag, retval;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	*addr = BANK_CMD_PROG;
+
+	*addr = value;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	retval = 0;
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	do {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			retval = 1;
+			goto done;
+		}
+		stat = *addr;
+	} while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY);
+
+	if ((stat & BANK_STAT_ERR) != 0) {
+		printf("flash program failed (stat = 0x%08lx) "
+			"at address 0x%08lx\n", (ulong)stat, (ulong)addr);
+		*addr = BANK_CMD_CLR_STAT;
+		retval = 3;
+	}
+
+done:
+	/* reset to read mode */
+	*addr = BANK_CMD_RST;
+
+	return (retval);
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int
+flash_erase_intel(flash_info_t *info, int s_first, int s_last)
+{
+	int prot, sect, haderr;
+	ulong start, now, last;
+
+#ifdef FLASH_DEBUG
+	printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
+		"  Bank # %d: ", s_last - s_first + 1, s_first, s_last,
+		(info - flash_info) + 1);
+	flash_print_info(info);
+#endif
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf("- Warning: %d protected sector%s will not be erased!\n",
+			prot, (prot > 1 ? "s" : ""));
+	}
+
+	start = get_timer (0);
+	last = 0;
+	haderr = 0;
+
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			ulong estart;
+			int sectdone;
+
+			bank_erase_init(info, sect);
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+
+			estart = get_timer(start);
+
+			do {
+				now = get_timer(start);
+
+				if (now - estart > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout (sect %d)\n", sect);
+					haderr = 1;
+					break;
+				}
+
+#ifndef FLASH_DEBUG
+				/* show that we're waiting */
+				if ((now - last) > 1000) { /* every second */
+					putc ('.');
+					last = now;
+				}
+#endif
+
+				sectdone = bank_erase_poll(info, sect);
+
+				if (sectdone < 0) {
+					haderr = 1;
+					break;
+				}
+
+			} while (!sectdone);
+
+			if (haderr)
+				break;
+		}
+	}
+
+	if (haderr > 0)
+		printf (" failed\n");
+	else
+		printf (" done\n");
+
+	/* reset to read mode */
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			bank_reset(info, sect);
+		}
+	}
+	return haderr;
+}
diff --git a/board/fads/flash.c b/board/fads/flash.c
new file mode 100644
index 0000000..50b496e
--- /dev/null
+++ b/board/fads/flash.c
@@ -0,0 +1,624 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long total_size;
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i < CFG_MAX_FLASH_BANKS; ++i)
+	{
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	total_size = 0;
+	size_b0 = 0xffffffff;
+
+	for (i=0; i < CFG_MAX_FLASH_BANKS; ++i)
+	{
+		size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + total_size), &flash_info[i]);
+
+		if (flash_info[i].flash_id == FLASH_UNKNOWN)
+		{
+			printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", i, size_b1, size_b1>>20);
+		}
+
+		/* Is this really needed ? - LP */
+		if (size_b1 > size_b0) {
+			printf ("## ERROR: Bank %d (0x%08lx = %ld MB) > Bank %d (0x%08lx = %ld MB)\n",
+			        i, size_b1, size_b1>>20, i-1, size_b0, size_b0>>20);
+			goto out_error;
+		}
+		size_b0 = size_b1;
+		total_size += size_b1;
+	}
+
+	/* Compute the Address Mask */
+	for (i=0; (total_size >> i) != 0; ++i) {};
+	i--;
+
+	if (total_size != (1 << i)) {
+		printf ("## WARNING: Total FLASH size (0x%08lx = %ld MB) is not a power of 2\n",
+			total_size, total_size>>20);
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = ((((unsigned long)~1) << i) & OR_AM_MSK) | CFG_OR_TIMING_FLASH;
+	memctl->memc_br0 = CFG_BR0_PRELIM;
+
+	total_size = 0;
+
+	for (i=0; i < CFG_MAX_FLASH_BANKS && flash_info[i].size != 0; ++i)
+	{
+		/* Re-do sizing to get full correct info */
+		/* Why ? - LP */
+		size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + total_size), &flash_info[i]);
+
+		/* This is done by flash_get_size - LP */
+		/* flash_get_offsets (CFG_FLASH_BASE + total_size, &flash_info[i]); */
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+		/* monitor protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_MONITOR_BASE,
+			      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+			      &flash_info[i]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+		/* ENV protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_ENV_ADDR,
+			      CFG_ENV_ADDR+CFG_ENV_SIZE-1,
+			      &flash_info[i]);
+#endif
+
+		total_size += size_b1;
+	}
+
+	return (total_size);
+
+out_error:
+	for (i=0; i < CFG_MAX_FLASH_BANKS; ++i)
+	{
+		flash_info[i].flash_id		= FLASH_UNKNOWN;
+		flash_info[i].sector_count	= -1;
+		flash_info[i].size		= 0;
+	}
+
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start address table */
+	if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) {
+		/* set sector offsets for uniform sector type	*/
+		for (i = 0; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00040000);
+		}
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN)
+	{
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK)
+	{
+		case FLASH_MAN_AMD:	printf ("AMD ");		break;
+		case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+		case FLASH_MAN_BM:	printf ("BRIGHT MICRO ");	break;
+		default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK)
+	{
+		case FLASH_AM040:	printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n");
+			break;
+		case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+					break;
+		case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+					break;
+		case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+					break;
+		case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+					break;
+		case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+					break;
+		case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+					break;
+		case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+					break;
+		case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+					break;
+		default:		printf ("Unknown Chip Type\n");
+					break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+
+	for (i=0; i<info->sector_count; ++i)
+	{
+		if ((i % 5) == 0)
+		{
+			printf ("\n   ");
+		}
+
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     ");
+	}
+
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+#if 0
+	ulong base = (ulong)addr;
+#endif
+	uchar value;
+
+	/* Write auto select command: read Manufacturer ID */
+#if 0
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00900090;
+#else
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+	addr[0x0555] = 0x90909090;
+#endif
+
+	value = addr[0];
+
+	switch (value + (value << 16))
+	{
+		case AMD_MANUFACT:
+			info->flash_id = FLASH_MAN_AMD;
+			break;
+
+		case FUJ_MANUFACT:
+			info->flash_id = FLASH_MAN_FUJ;
+			break;
+
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			info->sector_count = 0;
+			info->size = 0;
+			break;
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	switch (value)
+	{
+		case AMD_ID_F040B:
+			info->flash_id += FLASH_AM040;
+			info->sector_count = 8;
+			info->size = 0x00200000;
+			break;				/* => 2 MB		*/
+
+		case AMD_ID_LV400T:
+			info->flash_id += FLASH_AM400T;
+			info->sector_count = 11;
+			info->size = 0x00100000;
+			break;				/* => 1 MB		*/
+
+		case AMD_ID_LV400B:
+			info->flash_id += FLASH_AM400B;
+			info->sector_count = 11;
+			info->size = 0x00100000;
+			break;				/* => 1 MB		*/
+
+		case AMD_ID_LV800T:
+			info->flash_id += FLASH_AM800T;
+			info->sector_count = 19;
+			info->size = 0x00200000;
+			break;				/* => 2 MB		*/
+
+		case AMD_ID_LV800B:
+			info->flash_id += FLASH_AM800B;
+			info->sector_count = 19;
+			info->size = 0x00200000;
+			break;				/* => 2 MB		*/
+
+		case AMD_ID_LV160T:
+			info->flash_id += FLASH_AM160T;
+			info->sector_count = 35;
+			info->size = 0x00400000;
+			break;				/* => 4 MB		*/
+
+		case AMD_ID_LV160B:
+			info->flash_id += FLASH_AM160B;
+			info->sector_count = 35;
+			info->size = 0x00400000;
+			break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+		case AMD_ID_LV320T:
+			info->flash_id += FLASH_AM320T;
+			info->sector_count = 67;
+			info->size = 0x00800000;
+			break;				/* => 8 MB		*/
+
+		case AMD_ID_LV320B:
+			info->flash_id += FLASH_AM320B;
+			info->sector_count = 67;
+			info->size = 0x00800000;
+			break;				/* => 8 MB		*/
+#endif
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			return (0);			/* => no or unknown flash */
+
+	}
+
+#if 0
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+#else
+	flash_get_offsets ((ulong)addr, info);
+#endif
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++)
+	{
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr = (volatile unsigned long *)(info->start[i]);
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN)
+	{
+		addr = (volatile unsigned long *)info->start[0];
+#if 0
+		*addr = 0x00F000F0;	/* reset bank */
+#else
+		*addr = 0xF0F0F0F0;	/* reset bank */
+#endif
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    (info->flash_id > FLASH_AMD_COMP)) {
+		printf ("Can't erase unknown flash type - aborted\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+#if 0
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00800080;
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+#else
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+	addr[0x0555] = 0x80808080;
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+#endif
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (vu_long*)(info->start[sect]);
+#if 0
+			addr[0] = 0x00300030;
+#else
+			addr[0] = 0x30303030;
+#endif
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (vu_long*)(info->start[l_sect]);
+#if 0
+	while ((addr[0] & 0x00800080) != 0x00800080)
+#else
+	while ((addr[0] & 0xFFFFFFFF) != 0xFFFFFFFF)
+#endif
+	{
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (volatile unsigned long *)info->start[0];
+#if 0
+	addr[0] = 0x00F000F0;	/* reset bank */
+#else
+	addr[0] = 0xF0F0F0F0;	/* reset bank */
+#endif
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *)dest) & data) != data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+#if 0
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00A000A0;
+#else
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+	addr[0x0555] = 0xA0A0A0A0;
+#endif
+
+	*((vu_long *)dest) = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+#if 0
+	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080))
+#else
+	while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080))
+#endif
+	{
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/fads/lamp.c b/board/fads/lamp.c
new file mode 100644
index 0000000..b121477
--- /dev/null
+++ b/board/fads/lamp.c
@@ -0,0 +1,42 @@
+#include <config.h>
+#include <common.h>
+
+void
+signal_delay(unsigned int n)
+{
+  while (n--);
+}
+
+void
+signal_on(void)
+{
+  *((volatile uint *)BCSR4) &= ~(1<<(31-3)); /* led on */
+}
+
+void
+signal_off(void)
+{
+  *((volatile uint *)BCSR4) |= (1<<(31-3)); /* led off */
+}
+
+void
+slow_blink(unsigned int n)
+{
+  while (n--) {
+    signal_on();
+    signal_delay(0x00400000);
+    signal_off();
+    signal_delay(0x00400000);
+  }
+}
+
+void
+fast_blink(unsigned int n)
+{
+  while (n--) {
+    signal_on();
+    signal_delay(0x00100000);
+    signal_off();
+    signal_delay(0x00100000);
+  }
+}
diff --git a/board/genietv/flash.c b/board/genietv/flash.c
new file mode 100644
index 0000000..2314a53
--- /dev/null
+++ b/board/genietv/flash.c
@@ -0,0 +1,470 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i < CFG_MAX_FLASH_BANKS; ++i)
+	    flash_info[i].flash_id = FLASH_UNKNOWN;
+
+	/* Detect size */
+	size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	/* Setup offsets */
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* Monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+	size_b1 = 0 ;
+
+	flash_info[1].flash_id = FLASH_UNKNOWN;
+	flash_info[1].sector_count = -1;
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ * Fix this to support variable sector sizes
+*/
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start address table */
+	if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) {
+		/* set sector offsets for bottom boot block type	*/
+		for (i = 0; i < info->sector_count; i++)
+			info->start[i] = base + (i * 0x00010000);
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN)
+	{
+		puts ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK)
+	{
+		case FLASH_MAN_AMD:	printf ("AMD ");		break;
+		case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+		case FLASH_MAN_BM:	printf ("BRIGHT MICRO ");	break;
+		default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK)
+	{
+		case FLASH_AM040:	printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n");
+			break;
+		case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+					break;
+		case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+					break;
+		case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+					break;
+		case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+					break;
+		case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+					break;
+		case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+					break;
+		case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+					break;
+		case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+					break;
+		default:		printf ("Unknown Chip Type\n");
+					break;
+	}
+
+	if (info->size >> 20) {
+	    printf ("  Size: %ld MB in %d Sectors\n",
+	    	info->size >> 20,
+		info->sector_count);
+	} else {
+	    printf ("  Size: %ld KB in %d Sectors\n",
+	    	info->size >> 10,
+		info->sector_count);
+	}
+
+	puts ("  Sector Start Addresses:");
+
+	for (i=0; i<info->sector_count; ++i)
+	{
+		if ((i % 5) == 0)
+		{
+			puts ("\n   ");
+		}
+
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     ");
+	}
+
+	putc ('\n');
+	return;
+}
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	volatile unsigned char *caddr;
+	char value;
+
+	caddr = (volatile unsigned char *)addr ;
+
+	/* Write auto select command: read Manufacturer ID */
+
+#if 0
+	printf("Base address is: %08x\n", caddr);
+#endif
+
+	caddr[0x0555] = 0xAA;
+	caddr[0x02AA] = 0x55;
+	caddr[0x0555] = 0x90;
+
+	value = caddr[0];
+
+#if 0
+	printf("Manufact ID: %02x\n", value);
+#endif
+	switch (value)
+	{
+		case 0x01:
+		case AMD_MANUFACT:
+			info->flash_id = FLASH_MAN_AMD;
+		break;
+
+		case FUJ_MANUFACT:
+			info->flash_id = FLASH_MAN_FUJ;
+		break;
+
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			info->sector_count = 0;
+			info->size = 0;
+			break;
+	}
+
+	value = caddr[1];			/* device ID		*/
+#if 0
+	printf("Device ID: %02x\n", value);
+#endif
+	switch (value)
+	{
+		case AMD_ID_LV040B:
+			info->flash_id += FLASH_AM040;
+			info->sector_count = 8;
+			info->size = 0x00080000;
+			break;				/* => 512Kb 		*/
+
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			return (0);			/* => no or unknown flash */
+
+	}
+
+	flash_get_offsets ((ulong)addr, &flash_info[0]);
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++)
+	{
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		caddr = (volatile unsigned char *)(info->start[i]);
+		info->protect[i] = caddr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN)
+	{
+		caddr = (volatile unsigned char *)info->start[0];
+		*caddr = 0xF0;	/* reset bank */
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	volatile unsigned char *addr = (volatile unsigned char *)(info->start[0]);
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    (info->flash_id > FLASH_AMD_COMP)) {
+		printf ("Can't erase unknown flash type - aborted\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0xAA;
+	addr[0x02AA] = 0x55;
+	addr[0x0555] = 0x80;
+	addr[0x0555] = 0xAA;
+	addr[0x02AA] = 0x55;
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (volatile unsigned char *)(info->start[sect]);
+			addr[0] = 0x30;
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (volatile unsigned char *)(info->start[l_sect]);
+
+	while ((addr[0] & 0xFF) != 0xFF)
+	{
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (volatile unsigned char *)info->start[0];
+
+	addr[0] = 0xF0;	/* reset bank */
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	volatile unsigned char *addr = (volatile unsigned char*)(info->start[0]),
+				*cdest,*cdata;
+	ulong start;
+	int flag, count = 4 ;
+
+	cdest = (volatile unsigned char *)dest ;
+	cdata = (volatile unsigned char *)&data ;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *)dest) & data) != data) {
+		return (2);
+	}
+
+	while(count--)
+	{
+	    /* Disable interrupts which might cause a timeout here */
+	    flag = disable_interrupts();
+
+	    addr[0x0555] = 0xAA;
+	    addr[0x02AA] = 0x55;
+	    addr[0x0555] = 0xA0;
+
+	    *cdest = *cdata;
+
+	    /* re-enable interrupts if necessary */
+	    if (flag)
+	    	enable_interrupts();
+
+	    /* data polling for D7 */
+	    start = get_timer (0);
+	    while ((*cdest ^ *cdata) & 0x80)
+	    {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	    }
+
+	    cdata++ ;
+	    cdest++ ;
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/gth/ee_access.c b/board/gth/ee_access.c
new file mode 100644
index 0000000..716c90e
--- /dev/null
+++ b/board/gth/ee_access.c
@@ -0,0 +1,335 @@
+/* Module for handling DALLAS DS2438, smart battery monitor
+   Chip can store up to 40 bytes of user data in EEPROM,
+   perform temp, voltage and current measurements.
+   Chip also contains a unique serial number.
+
+   Always read/write LSb first
+
+   For documentaion, see data sheet for DS2438, 2438.pdf
+
+   By Thomas.Lange@corelatus.com 001025 */
+
+#include <common.h>
+#include <config.h>
+#include <mpc8xx.h>
+
+#include <../board/gth/ee_dev.h>
+
+/* We dont have kernel functions */
+#define printk printf
+#define KERN_DEBUG
+#define KERN_ERR
+#define EIO 1
+
+static int Debug = 0;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/*
+ * lookup table ripped from DS app note 17, understanding and using
+ * cyclic redundancy checks...
+ */
+
+static u8 crc_lookup[256] = {
+	0,	94,	188,	226,	97,	63,	221,	131,
+	194,	156,	126,	32,	163,	253,	31,	65,
+	157,	195,	33,	127,	252,	162,	64,	30,
+	95,	1,	227,	189,	62,	96,	130,	220,
+	35,	125,	159,	193,	66,	28,	254,	160,
+	225,	191,	93,	3,	128,	222,	60,	98,
+	190,	224,	2,	92,	223,	129,	99,	61,
+	124,	34,	192,	158,	29,	67,	161,	255,
+	70,	24,	250,	164,	39,	121,	155,	197,
+	132,	218,	56,	102,	229,	187,	89,	7,
+	219,	133,	103,	57,	186,	228,	6,	88,
+	25,	71,	165,	251,	120,	38,	196,	154,
+	101,	59,	217,	135,	4,	90,	184,	230,
+	167,	249,	27,	69,	198,	152,	122,	36,
+	248,	166,	68,	26,	153,	199,	37,	123,
+	58,	100,	134,	216,	91,	5,	231,	185,
+	140,	210,	48,	110,	237,	179,	81,	15,
+	78,	16,	242,	172,	47,	113,	147,	205,
+	17,	79,	173,	243,	112,	46,	204,	146,
+	211,	141,	111,	49,	178,	236,	14,	80,
+	175,	241,	19,	77,	206,	144,	114,	44,
+	109,	51,	209,	143,	12,	82,	176,	238,
+	50,	108,	142,	208,	83,	13,	239,	177,
+	240,	174,	76,	18,	145,	207,	45,	115,
+	202,	148,	118,	40,	171,	245,	23,	73,
+	8,	86,	180,	234,	105,	55,	213,	139,
+	87,	9,	235,	181,	54,	104,	138,	212,
+	149,	203,	41,	119,	244,	170,	72,	22,
+	233,	183,	85,	11,	136,	214,	52,	106,
+	43,	117,	151,	201,	74,	20,	246,	168,
+	116,	42,	200,	150,	21,	75,	169,	247,
+	182,	232,	10,	84,	215,	137,	107,	53
+};
+
+static u8 make_new_crc( u8 Old_crc, u8 New_value ){
+  /* Compute a new checksum with new byte, using previous checksum as input
+     See DS app note 17, understanding and using cyclic redundancy checks...
+     Also see DS2438, page 11 */
+  return( crc_lookup[Old_crc ^ New_value ]);
+}
+
+int ee_crc_ok( u8 *Buffer, int Len, u8 Crc ){
+  /* Check if the checksum for this buffer is correct */
+  u8 Curr_crc=0;
+  int i;
+  u8 *Curr_byte = Buffer;
+
+  for(i=0;i<Len;i++){
+    Curr_crc = make_new_crc( Curr_crc, *Curr_byte);
+    Curr_byte++;
+  }
+  E_DEBUG("Calculated CRC = 0x%x, read = 0x%x\n", Curr_crc, Crc);
+
+  if(Curr_crc == Crc){
+    /* Good */
+    return(TRUE);
+  }
+  printk(KERN_ERR"EE checksum error, Calculated CRC = 0x%x, read = 0x%x\n",
+	Curr_crc, Crc);
+  return(FALSE);
+}
+
+static void
+set_idle(void){
+  /* Send idle and keep start time
+     Continous 1 is idle */
+  WRITE_PORT(1);
+}
+
+static int
+do_reset(void){
+  /* Release reset and verify that chip responds with presence pulse */
+  int Retries = 0;
+  while(Retries<5){
+    udelay(RESET_LOW_TIME);
+
+    /* Send reset */
+    WRITE_PORT(0);
+    udelay(RESET_LOW_TIME);
+
+    /* Release reset */
+    WRITE_PORT(1);
+
+    /* Wait for EEPROM to drive output */
+    udelay(PRESENCE_TIMEOUT);
+    if(!READ_PORT){
+      /* Ok, EEPROM is driving a 0 */
+      E_DEBUG("Presence detected\n");
+      if(Retries){
+	E_DEBUG("Retries %d\n",Retries);
+      }
+      /* Make sure chip releases pin */
+      udelay(PRESENCE_LOW_TIME);
+      return 0;
+    }
+    Retries++;
+  }
+
+  printk(KERN_ERR"EEPROM did not respond when releasing reset\n");
+
+    /* Make sure chip releases pin */
+  udelay(PRESENCE_LOW_TIME);
+
+  /* Set to idle again */
+  set_idle();
+
+  return(-EIO);
+}
+
+static u8
+read_byte(void){
+  /* Read a single byte from EEPROM
+     Read LSb first */
+  int i;
+  int Value;
+  u8 Result=0;
+#ifndef CFG_IMMR
+  u32 Flags;
+#endif
+
+  E_DEBUG("Reading byte\n");
+
+  for(i=0;i<8;i++){
+    /* Small delay between pulses */
+    udelay(1);
+
+#ifndef CFG_IMMR
+    /* Disable irq */
+    save_flags(Flags);
+    cli();
+#endif
+
+    /* Pull down pin short time to start read
+       See page 26 in data sheet */
+
+    WRITE_PORT(0);
+    udelay(READ_LOW);
+    WRITE_PORT(1);
+
+    /* Wait for chip to drive pin */
+    udelay(READ_TIMEOUT);
+
+    Value = READ_PORT;
+    if(Value)
+      Value=1;
+
+#ifndef CFG_IMMR
+    /* Enable irq */
+    restore_flags(Flags);
+#endif
+
+    /* Wait for chip to release pin */
+    udelay(TOTAL_READ_LOW-READ_TIMEOUT);
+
+    /* LSb first */
+    Result|=Value<<i;
+  }
+
+  E_DEBUG("Read byte 0x%x\n",Result);
+
+  return(Result);
+}
+
+static void
+write_byte(u8 Byte){
+  /* Write a single byte to EEPROM
+     Write LSb first */
+  int i;
+  int Value;
+#ifndef CFG_IMMR
+  u32 Flags;
+#endif
+
+  E_DEBUG("Writing byte 0x%x\n",Byte);
+
+  for(i=0;i<8;i++){
+    /* Small delay between pulses */
+    udelay(1);
+    Value = Byte&1;
+
+#ifndef CFG_IMMR
+    /* Disable irq */
+    save_flags(Flags);
+    cli();
+#endif
+
+    /* Pull down pin short time for a 1, long time for a 0
+       See page 26 in data sheet */
+
+    WRITE_PORT(0);
+    if(Value){
+      /* Write a 1 */
+      udelay(WRITE_1_LOW);
+    }
+    else{
+      /* Write a 0 */
+      udelay(WRITE_0_LOW);
+    }
+
+    WRITE_PORT(1);
+
+#ifndef CFG_IMMR
+    /* Enable irq */
+    restore_flags(Flags);
+#endif
+
+    if(Value)
+      /* Wait for chip to read the 1 */
+      udelay(TOTAL_WRITE_LOW-WRITE_1_LOW);
+    Byte>>=1;
+  }
+}
+
+int ee_do_command( u8 *Tx, int Tx_len, u8 *Rx, int Rx_len, int Send_skip ){
+  /* Execute this command string, including
+     giving reset and setting to idle after command
+     if Rx_len is set, we read out data from EEPROM */
+  int i;
+
+  E_DEBUG("Command, Tx_len %d, Rx_len %d\n", Tx_len, Rx_len );
+
+  if(do_reset()){
+    /* Failed! */
+    return(-EIO);
+  }
+
+  if(Send_skip)
+    /* Always send SKIP_ROM first to tell chip we are sending a command,
+       except when we read out rom data for chip */
+    write_byte(SKIP_ROM);
+
+  /* Always have Tx data */
+  for(i=0;i<Tx_len;i++){
+    write_byte(Tx[i]);
+  }
+
+  if(Rx_len){
+    for(i=0;i<Rx_len;i++){
+      Rx[i]=read_byte();
+    }
+  }
+
+  set_idle();
+
+  E_DEBUG("Command done\n");
+
+  return(0);
+}
+
+int ee_init_data(void){
+  int i;
+  u8 Tx[10];
+  int tmp;
+  volatile immap_t *immap = (immap_t *)CFG_IMMR;
+
+  while(0){
+    tmp = 1-tmp;
+    if(tmp)
+      immap->im_ioport.iop_padat &= ~PA_FRONT_LED;
+    else
+      immap->im_ioport.iop_padat |= PA_FRONT_LED;
+    udelay(1);
+  }
+
+  /* Set port to open drain to be able to read data from
+     port without setting it to input */
+  PORT_B_PAR &= ~PB_EEPROM;
+  PORT_B_ODR |= PB_EEPROM;
+  SET_PORT_B_OUTPUT(PB_EEPROM);
+
+  /* Set idle mode */
+  set_idle();
+
+  /* Copy all User EEPROM data to scratchpad */
+  for(i=0;i<USER_PAGES;i++){
+    Tx[0]=RECALL_MEMORY;
+    Tx[1]=EE_USER_PAGE_0+i;
+    if(ee_do_command(Tx,2,NULL,0,TRUE)) return(-EIO);
+  }
+
+  /* Make sure chip doesnt store measurements in NVRAM */
+  Tx[0]=WRITE_SCRATCHPAD;
+  Tx[1]=0; /* Page */
+  Tx[2]=9;
+  if(ee_do_command(Tx,3,NULL,0,TRUE)) return(-EIO);
+
+  Tx[0]=COPY_SCRATCHPAD;
+  if(ee_do_command(Tx,2,NULL,0,TRUE)) return(-EIO);
+
+  /* FIXME check status bit instead
+     Could take 10 ms to store in EEPROM */
+  for(i=0;i<10;i++){
+    udelay(1000);
+  }
+
+  return(0);
+}
diff --git a/board/gth/flash.c b/board/gth/flash.c
new file mode 100644
index 0000000..562a349
--- /dev/null
+++ b/board/gth/flash.c
@@ -0,0 +1,649 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ * Protection Flags:
+ */
+#define FLAG_PROTECT_SET	0x01
+#define FLAG_PROTECT_CLEAR	0x02
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/*printf("faking");*/
+
+	return(0x1fffff);
+
+	/* Init: no FLASHes known */
+	for (i=0; i < CFG_MAX_FLASH_BANKS; ++i)
+	{
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN)
+	{
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+#if 0
+	if (FLASH_BASE1_PRELIM != 0x0) {
+	  size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+
+	  if (size_b1 > size_b0) {
+	    printf ("## ERROR: Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
+	    	size_b1, size_b1<<20,size_b0, size_b0<<20);
+
+	    flash_info[0].flash_id	= FLASH_UNKNOWN;
+	    flash_info[1].flash_id	= FLASH_UNKNOWN;
+	    flash_info[0].sector_count	= -1;
+	    flash_info[1].sector_count	= -1;
+	    flash_info[0].size		= 0;
+	    flash_info[1].size		= 0;
+	    return (0);
+	  }
+	} else {
+#endif
+	  size_b1 = 0;
+
+	  /* Remap FLASH according to real size */
+	  memctl->memc_or0 = CFG_OR0_PRELIM;
+	  memctl->memc_br0 = CFG_BR0_PRELIM;
+
+	  /* Re-do sizing to get full correct info */
+	  size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	  flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	  /* monitor protection ON by default */
+	  (void)flash_protect(FLAG_PROTECT_SET,
+			    CFG_MONITOR_BASE,
+			    CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+			    &flash_info[0]);
+#endif
+
+	if (size_b1)
+	{
+	  /* memctl->memc_or1 = CFG_OR1_PRELIM;
+	     memctl->memc_br1 = CFG_BR1_PRELIM; */
+
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0),
+					 &flash_info[1]);
+
+		flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+		/* monitor protection ON by default */
+		(void)flash_protect(FLAG_PROTECT_SET,
+				    CFG_MONITOR_BASE,
+				    CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+				    &flash_info[1]);
+#endif
+	}
+	else
+	{
+/*	    memctl->memc_or1 = CFG_OR1_PRELIM;
+ FIXME	    memctl->memc_br1 = CFG_BR1_PRELIM;  */
+
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+	}
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+}
+
+
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start adress table */
+	if (info->flash_id & FLASH_BTYPE)
+	{
+		/* set sector offsets for bottom boot block type	*/
+		for (i = 0; i < info->sector_count; i++)
+		{
+			info->start[i] = base + (i * 0x00040000);
+		}
+	}
+	else
+	{
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		for (; i >= 0; i--)
+		{
+			info->start[i] = base + i * 0x00040000;
+		}
+	}
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+
+#if 0
+	case FLASH_AM040B:
+		printf ("AM29F040B (4 Mbit, bottom boot sect)\n");
+		break;
+	case FLASH_AM040T:
+		printf ("AM29F040T (4 Mbit, top boot sect)\n");
+		break;
+#endif
+	case FLASH_AM400B:
+		printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+		break;
+	case FLASH_AM400T:
+		printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+		break;
+	case FLASH_AM800B:
+		printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+		break;
+	case FLASH_AM800T:
+		printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+		break;
+	case FLASH_AM160B:
+		printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+		break;
+	case FLASH_AM160T:
+		printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+		break;
+	case FLASH_AM320B:
+		printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+		break;
+	case FLASH_AM320T:
+		printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+		break;
+	default:
+		printf ("Unknown Chip Type\n");
+		break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20,
+		info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+
+	for (i=0; i<info->sector_count; ++i)
+	{
+		if ((i % 5) == 0)
+		{
+			printf ("\n   ");
+		}
+
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     ");
+	}
+
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+#if 0
+	ulong base = (ulong)addr;
+#endif
+	uchar value;
+
+	/* Write auto select command: read Manufacturer ID */
+#if 0
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00900090;
+#else
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+	addr[0x0555] = 0x90909090;
+#endif
+
+	value = addr[0];
+
+	switch (value)
+	{
+		case AMD_MANUFACT:case 0x01:
+			info->flash_id = FLASH_MAN_AMD;
+		break;
+
+		case FUJ_MANUFACT:
+			info->flash_id = FLASH_MAN_FUJ;
+		break;
+
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			info->sector_count = 0;
+			info->size = 0;
+			break;
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	switch (value)
+	{
+#if 0
+		case AMD_ID_F040B:
+			info->flash_id += FLASH_AM040B;
+			info->sector_count = 8;
+			info->size = 0x00200000;
+			break;				/* => 2 MB		*/
+#endif
+		case AMD_ID_LV400T:
+			info->flash_id += FLASH_AM400T;
+			info->sector_count = 11;
+			info->size = 0x00100000;
+			break;				/* => 1 MB		*/
+
+		case AMD_ID_LV400B:
+			info->flash_id += FLASH_AM400B;
+			info->sector_count = 11;
+			info->size = 0x00100000;
+			break;				/* => 1 MB		*/
+
+		case AMD_ID_LV800T:
+			info->flash_id += FLASH_AM800T;
+			info->sector_count = 19;
+			info->size = 0x00200000;
+			break;				/* => 2 MB		*/
+
+		case AMD_ID_LV800B:
+			info->flash_id += FLASH_AM800B;
+			info->sector_count = 19;
+			info->size = 0x00200000;
+			break;				/* => 2 MB		*/
+
+		case AMD_ID_LV160T:
+			info->flash_id += FLASH_AM160T;
+			info->sector_count = 35;
+			info->size = 0x00400000;
+			break;				/* => 4 MB		*/
+
+		case AMD_ID_LV160B:
+			info->flash_id += FLASH_AM160B;
+			info->sector_count = 35;
+			info->size = 0x00400000;
+			break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+		case AMD_ID_LV320T:
+			info->flash_id += FLASH_AM320T;
+			info->sector_count = 67;
+			info->size = 0x00800000;
+			break;				/* => 8 MB		*/
+
+		case AMD_ID_LV320B:
+			info->flash_id += FLASH_AM320B;
+			info->sector_count = 67;
+			info->size = 0x00800000;
+			break;				/* => 8 MB		*/
+#endif
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			return (0);			/* => no or unknown flash */
+
+	}
+
+#if 0
+	/* set up sector start adress table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+#else
+	flash_get_offsets ((ulong)addr, &flash_info[0]);
+#endif
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++)
+	{
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr = (volatile unsigned long *)(info->start[i]);
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN)
+	{
+		addr = (volatile unsigned long *)info->start[0];
+#if 0
+		*addr = 0x00F000F0;	/* reset bank */
+#else
+		*addr = 0xF0F0F0F0;	/* reset bank */
+#endif
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    (info->flash_id > FLASH_AMD_COMP)) {
+		printf ("Can't erase unknown flash type - aborted\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+#if 0
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00800080;
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+#else
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+	addr[0x0555] = 0x80808080;
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+#endif
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (vu_long*)(info->start[sect]);
+#if 0
+			addr[0] = 0x00300030;
+#else
+			addr[0] = 0x30303030;
+#endif
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (vu_long*)(info->start[l_sect]);
+#if 0
+	while ((addr[0] & 0x00800080) != 0x00800080)
+#else
+	while ((addr[0] & 0xFFFFFFFF) != 0xFFFFFFFF)
+#endif
+	{
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (volatile unsigned long *)info->start[0];
+#if 0
+	addr[0] = 0x00F000F0;	/* reset bank */
+#else
+	addr[0] = 0xF0F0F0F0;	/* reset bank */
+#endif
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *)dest) & data) != data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+#if 0
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00A000A0;
+#else
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+	addr[0x0555] = 0xA0A0A0A0;
+#endif
+
+	*((vu_long *)dest) = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+#if 0
+	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080))
+#else
+	while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080))
+#endif
+	{
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/hermes/flash.c b/board/hermes/flash.c
new file mode 100644
index 0000000..bb7635e
--- /dev/null
+++ b/board/hermes/flash.c
@@ -0,0 +1,460 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_byte (flash_info_t *info, ulong dest, uchar data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size, size<<20);
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size & 0xFFFF8000);
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) |
+				(memctl->memc_br0 & ~(BR_BA_MSK));
+
+	/* Re-do sizing to get full correct info */
+	size = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+	flash_info[0].size = size;
+
+	return (size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00006000;
+		info->start[3] = base + 0x00008000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00010000) - 0x00030000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00006000;
+		info->start[i--] = base + info->size - 0x00008000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00010000;
+		}
+	}
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	uchar value;
+	vu_char *caddr = (vu_char *)addr;
+	ulong base = (ulong)addr;
+
+
+	/* Write auto select command: read Manufacturer ID */
+	caddr[0x0AAA] = 0xAA;
+	caddr[0x0555] = 0x55;
+	caddr[0x0AAA] = 0x90;
+
+	value = caddr[0];
+	switch (value) {
+	case (AMD_MANUFACT & 0xFF):
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case (FUJ_MANUFACT & 0xFF):
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = caddr[2];			/* device ID		*/
+
+	switch (value) {
+	case (AMD_ID_LV400T & 0xFF):
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00080000;
+		break;				/* => 512 kB		*/
+
+	case (AMD_ID_LV400B & 0xFF):
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00080000;
+		break;				/* => 512 kB		*/
+
+	case (AMD_ID_LV800T & 0xFF):
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (AMD_ID_LV800B & 0xFF):
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (AMD_ID_LV160T & 0xFF):
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case (AMD_ID_LV160B & 0xFF):
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+#if 0	/* enable when device IDs are available */
+	case (AMD_ID_LV320T & 0xFF):
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case (AMD_ID_LV320B & 0xFF):
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+#endif
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00006000;
+		info->start[3] = base + 0x00008000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00010000) - 0x00030000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00006000;
+		info->start[i--] = base + info->size - 0x00008000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00010000;
+		}
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection: D0 = 1 if protected */
+		caddr = (volatile unsigned char *)(info->start[i]);
+		info->protect[i] = caddr[4] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		caddr = (vu_char *)info->start[0];
+
+		*caddr = 0xF0;	/* reset bank */
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	vu_char *addr = (vu_char*)(info->start[0]);
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    (info->flash_id > FLASH_AMD_COMP)) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0AAA] = 0xAA;
+	addr[0x0555] = 0x55;
+	addr[0x0AAA] = 0x80;
+	addr[0x0AAA] = 0xAA;
+	addr[0x0555] = 0x55;
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (vu_char*)(info->start[sect]);
+			addr[0] = 0x30;
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (vu_char*)(info->start[l_sect]);
+	while ((addr[0] & 0x80) != 0x80) {
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (vu_char *)info->start[0];
+	addr[0] = 0xF0;	/* reset bank */
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	int rc;
+
+	while (cnt > 0) {
+		if ((rc = write_byte(info, addr++, *src++)) != 0) {
+			return (rc);
+		}
+		--cnt;
+	}
+
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_byte (flash_info_t *info, ulong dest, uchar data)
+{
+	vu_char *addr = (vu_char*)(info->start[0]);
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_char *)dest) & data) != data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0AAA] = 0xAA;
+	addr[0x0555] = 0x55;
+	addr[0x0AAA] = 0xA0;
+
+	*((vu_char *)dest) = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	while ((*((vu_char *)dest) & 0x80) != (data & 0x80)) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/hymod/eeprom.c b/board/hymod/eeprom.c
new file mode 100644
index 0000000..9d50646
--- /dev/null
+++ b/board/hymod/eeprom.c
@@ -0,0 +1,597 @@
+/*
+ * (C) Copyright 2001
+ * Murray Jensen, CSIRO Manufacturing Science and Technology,
+ * <Murray.Jensen@cmst.csiro.au>
+ *
+ * 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 <mpc8260.h>
+
+/* imports from fetch.c */
+extern int fetch_and_parse(bd_t *, char *, ulong, int (*)(uchar *, uchar *));
+
+int
+eeprom_load(unsigned offset, hymod_eeprom_t *ep)
+{
+    uchar data[HYMOD_EEPROM_SIZE], *dp, *edp;
+    hymod_eehdr_t *hp;
+    ulong len, crc;
+
+    memset(ep, 0, sizeof *ep);
+    memset(data, 0, HYMOD_EEPROM_SIZE);
+    crc = 0;
+
+    hp = (hymod_eehdr_t *)data;
+    eeprom_read(CFG_DEF_EEPROM_ADDR, offset, (uchar *)hp, sizeof (*hp));
+    offset += sizeof (*hp);
+
+    if (hp->id != HYMOD_EEPROM_ID || hp->ver > HYMOD_EEPROM_VER ||
+      (len = hp->len) > HYMOD_EEPROM_MAXLEN)
+	return (0);
+
+    dp = (uchar *)(hp + 1); edp = dp + len;
+    eeprom_read(CFG_DEF_EEPROM_ADDR, offset, dp, len);
+    offset += len;
+
+    eeprom_read(CFG_DEF_EEPROM_ADDR, offset, (uchar *)&crc, sizeof (ulong));
+
+    if (crc32(0, data, edp - data) != crc)
+	return (0);
+
+    ep->ver = hp->ver;
+
+    for (;;) {
+	hymod_eerec_t *rp = (hymod_eerec_t *)dp;
+	ulong rtyp;
+	uchar rlen, *rdat;
+	uint rsiz;
+
+	if (rp->small.topbit == 0) {
+	    rtyp = rp->small.type;
+	    rlen = rp->small.len;
+	    rdat = rp->small.data;
+	    rsiz = offsetof(hymod_eerec_t, small.data) + rlen;
+	}
+	else if (rp->medium.nxtbit == 0) {
+	    rtyp = rp->medium.type;
+	    rlen = rp->medium.len;
+	    rdat = rp->medium.data;
+	    rsiz = offsetof(hymod_eerec_t, medium.data) + rlen;
+	}
+	else {
+	    rtyp = rp->large.type;
+	    rlen = rp->large.len;
+	    rdat = rp->large.data;
+	    rsiz = offsetof(hymod_eerec_t, large.data) + rlen;
+	}
+
+	if (rtyp == 0)
+	    break;
+
+	dp += rsiz;
+	if (dp > edp)	/* error? */
+	    break;
+
+	switch (rtyp) {
+
+	case HYMOD_EEREC_SERNO:		/* serial number */
+	    if (rlen == sizeof (ulong))
+		memcpy(&ep->serno, rdat, sizeof (ulong));
+	    break;
+
+	case HYMOD_EEREC_DATE:		/* date */
+	    if (rlen == sizeof (hymod_date_t))
+		memcpy(&ep->date, rdat, sizeof (hymod_date_t));
+	    break;
+
+	case HYMOD_EEREC_BATCH:		/* batch */
+	    if (rlen <= HYMOD_MAX_BATCH)
+		memcpy(ep->batch, rdat, ep->batchlen = rlen);
+	    break;
+
+	case HYMOD_EEREC_TYPE:		/* board type */
+	    if (rlen == 1)
+		ep->bdtype = *rdat;
+	    break;
+
+	case HYMOD_EEREC_REV:		/* board revision */
+	    if (rlen == 1)
+		ep->bdrev = *rdat;
+	    break;
+
+	case HYMOD_EEREC_SDRAM:		/* sdram size(s) */
+	    if (rlen > 0 && rlen <= HYMOD_MAX_SDRAM) {
+		int i;
+
+		for (i = 0; i < rlen; i++)
+		    ep->sdramsz[i] = rdat[i];
+		ep->nsdram = rlen;
+	    }
+	    break;
+
+	case HYMOD_EEREC_FLASH:		/* flash size(s) */
+	    if (rlen > 0 && rlen <= HYMOD_MAX_FLASH) {
+		int i;
+
+		for (i = 0; i < rlen; i++)
+		    ep->flashsz[i] = rdat[i];
+		ep->nflash = rlen;
+	    }
+	    break;
+
+	case HYMOD_EEREC_ZBT:		/* zbt ram size(s) */
+	    if (rlen > 0 && rlen <= HYMOD_MAX_ZBT) {
+		int i;
+
+		for (i = 0; i < rlen; i++)
+		    ep->zbtsz[i] = rdat[i];
+		ep->nzbt = rlen;
+	    }
+	    break;
+
+	case HYMOD_EEREC_XLXTYP:	/* xilinx fpga type(s) */
+	    if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
+		int i;
+
+		for (i = 0; i < rlen; i++)
+		    ep->xlx[i].type = rdat[i];
+		ep->nxlx = rlen;
+	    }
+	    break;
+
+	case HYMOD_EEREC_XLXSPD:	/* xilinx fpga speed(s) */
+	    if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
+		int i;
+
+		for (i = 0; i < rlen; i++)
+		    ep->xlx[i].speed = rdat[i];
+	    }
+	    break;
+
+	case HYMOD_EEREC_XLXTMP:	/* xilinx fpga temperature(s) */
+	    if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
+		int i;
+
+		for (i = 0; i < rlen; i++)
+		    ep->xlx[i].temp = rdat[i];
+	    }
+	    break;
+
+	case HYMOD_EEREC_XLXGRD:	/* xilinx fpga grade(s) */
+	    if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
+		int i;
+
+		for (i = 0; i < rlen; i++)
+		    ep->xlx[i].grade = rdat[i];
+	    }
+	    break;
+
+	case HYMOD_EEREC_CPUTYP:	/* CPU type */
+	    if (rlen == 1)
+		ep->mpc.type = *rdat;
+	    break;
+
+	case HYMOD_EEREC_CPUSPD:	/* CPU speed */
+	    if (rlen == 1)
+		ep->mpc.cpuspd = *rdat;
+	    break;
+
+	case HYMOD_EEREC_CPMSPD:	/* CPM speed */
+	    if (rlen == 1)
+		ep->mpc.cpmspd = *rdat;
+	    break;
+
+	case HYMOD_EEREC_BUSSPD:	/* bus speed */
+	    if (rlen == 1)
+		ep->mpc.busspd = *rdat;
+	    break;
+
+	case HYMOD_EEREC_HSTYPE:	/* high-speed serial chip type */
+	    if (rlen == 1)
+		ep->hss.type = *rdat;
+	    break;
+
+	case HYMOD_EEREC_HSCHIN:	/* high-speed serial input channels */
+	    if (rlen == 1)
+		ep->hss.nchin = *rdat;
+	    break;
+
+	case HYMOD_EEREC_HSCHOUT:	/* high-speed serial output channels */
+	    if (rlen == 1)
+		ep->hss.nchout = *rdat;
+	    break;
+
+	default:	/* ignore */
+	    break;
+	}
+    }
+
+    return (1);
+}
+
+/* maps an ascii "name=value" into a binary eeprom data record */
+typedef
+    struct _eerec_map {
+	char *name;
+	uint type;
+	uchar *(*handler)(struct _eerec_map *, uchar *, uchar *, uchar *);
+	uint length;
+	uint maxlen;
+    }
+eerec_map_t;
+
+static uchar *
+uint_handler(eerec_map_t *rp, uchar *value, uchar *dp, uchar *edp)
+{
+    uchar *eval;
+    union {
+	uchar cval[4];
+	ushort sval[2];
+	ulong lval;
+    } rdata;
+
+    rdata.lval = simple_strtol(value, (char **)&eval, 10);
+
+    if (eval == value || *eval != '\0') {
+	printf("%s record (%s) is not a valid uint\n", rp->name, value);
+	return (NULL);
+    }
+
+    if (dp + 2 + rp->length > edp) {
+	printf("can't fit %s record into eeprom\n", rp->name);
+	return (NULL);
+    }
+
+    *dp++ = rp->type;
+    *dp++ = rp->length;
+
+    switch (rp->length) {
+
+    case 1:
+	if (rdata.lval >= 256) {
+	    printf("%s record value (%lu) out of range (0-255)\n",
+		rp->name, rdata.lval);
+	    return (NULL);
+	}
+	*dp++ = rdata.cval[3];
+	break;
+
+    case 2:
+	if (rdata.lval >= 65536) {
+	    printf("%s record value (%lu) out of range (0-65535)\n",
+		rp->name, rdata.lval);
+	    return (NULL);
+	}
+	memcpy(dp, &rdata.sval[1], 2);
+	dp += 2;
+	break;
+
+    case 4:
+	memcpy(dp, &rdata.lval, 4);
+	dp += 4;
+	break;
+
+    default:
+	printf("huh? rp->length not 1, 2 or 4! (%d)\n", rp->length);
+	return (NULL);
+    }
+
+    return (dp);
+}
+
+static uchar *
+date_handler(eerec_map_t *rp, uchar *value, uchar *dp, uchar *edp)
+{
+    hymod_date_t date;
+    uchar *p = value, *ep;
+
+    date.year = simple_strtol(p, (char **)&ep, 10);
+    if (ep == p || *ep++ != '-') {
+bad_date:
+	printf("%s record (%s) is not a valid date\n", rp->name, value);
+	return (NULL);
+    }
+
+    date.month = simple_strtol(p = ep, (char **)&ep, 10);
+    if (ep == p || *ep++ != '-' || date.month == 0 || date.month > 12)
+	goto bad_date;
+
+    date.day = simple_strtol(p = ep, (char **)&ep, 10);
+    if (ep == p || *ep != '\0' || date.day == 0 || date.day > 31)
+	goto bad_date;
+
+    if (dp + 2 + sizeof (hymod_date_t) > edp) {
+	printf("can't fit %s record into eeprom\n", rp->name);
+	return (NULL);
+    }
+
+    *dp++ = rp->type;
+    *dp++ = sizeof (hymod_date_t);
+    memcpy(dp, &date, sizeof (hymod_date_t));
+    dp += sizeof (hymod_date_t);
+
+    return (dp);
+}
+
+static uchar *
+string_handler(eerec_map_t *rp, uchar *value, uchar *dp, uchar *edp)
+{
+    uint len;
+
+    if ((len = strlen(value)) > rp->maxlen) {
+	printf("%s record (%s) string is too long (%d>%d)\n",
+	    rp->name, value, len, rp->maxlen);
+	return (NULL);
+    }
+
+    if (dp + 2 + len > edp) {
+	printf("can't fit %s record into eeprom\n", rp->name);
+	return (NULL);
+    }
+
+    *dp++ = rp->type;
+    *dp++ = len;
+    memcpy(dp, value, len);
+    dp += len;
+
+    return (dp);
+}
+
+static uchar *
+bytes_handler(eerec_map_t *rp, uchar *value, uchar *dp, uchar *edp)
+{
+    uchar bytes[HYMOD_MAX_BYTES], nbytes = 0;
+    uchar *p = value, *ep;
+
+    for (;;) {
+
+	if (nbytes >= HYMOD_MAX_BYTES) {
+	    printf("%s record (%s) byte array too long\n", rp->name, value);
+	    return (NULL);
+	}
+
+	bytes[nbytes++] = simple_strtol(p, (char **)&ep, 10);
+
+	if (ep == p || (*ep != '\0' && *ep != ',')) {
+	    printf("%s record (%s) byte array has invalid uint\n",
+		rp->name, value);
+	    return (NULL);
+	}
+
+	if (*ep++ == '\0')
+	    break;
+
+	p = ep;
+    }
+
+    if (dp + 2 + nbytes > edp) {
+	printf("can't fit %s record into eeprom\n", rp->name);
+	return (NULL);
+    }
+
+    *dp++ = rp->type;
+    *dp++ = nbytes;
+    memcpy(dp, bytes, nbytes);
+    dp += nbytes;
+
+    return (dp);
+}
+
+static eerec_map_t eerec_map[] = {
+   /* name       type                 handler         len max             */
+    { "serno",   HYMOD_EEREC_SERNO,   uint_handler,   4,  0               },
+    { "date",    HYMOD_EEREC_DATE,    date_handler,   4,  0               },
+    { "batch",   HYMOD_EEREC_BATCH,   string_handler, 0,  HYMOD_MAX_BATCH },
+    { "type",    HYMOD_EEREC_TYPE,    uint_handler,   1,  0               },
+    { "rev",     HYMOD_EEREC_REV,     uint_handler,   1,  0               },
+    { "sdram",   HYMOD_EEREC_SDRAM,   bytes_handler,  0,  HYMOD_MAX_SDRAM },
+    { "flash",   HYMOD_EEREC_FLASH,   bytes_handler,  0,  HYMOD_MAX_FLASH },
+    { "zbt",     HYMOD_EEREC_ZBT,     bytes_handler,  0,  HYMOD_MAX_ZBT   },
+    { "xlxtyp",  HYMOD_EEREC_XLXTYP,  bytes_handler,  0,  HYMOD_MAX_XLX   },
+    { "xlxspd",  HYMOD_EEREC_XLXSPD,  bytes_handler,  0,  HYMOD_MAX_XLX   },
+    { "xlxtmp",  HYMOD_EEREC_XLXTMP,  bytes_handler,  0,  HYMOD_MAX_XLX   },
+    { "xlxgrd",  HYMOD_EEREC_XLXGRD,  bytes_handler,  0,  HYMOD_MAX_XLX   },
+    { "cputyp",  HYMOD_EEREC_CPUTYP,  uint_handler,   1,  0               },
+    { "cpuspd",  HYMOD_EEREC_CPUSPD,  uint_handler,   1,  0               },
+    { "cpmspd",  HYMOD_EEREC_CPMSPD,  uint_handler,   1,  0               },
+    { "busspd",  HYMOD_EEREC_BUSSPD,  uint_handler,   1,  0               },
+    { "hstype",  HYMOD_EEREC_HSTYPE,  uint_handler,   1,  0               },
+    { "hschin",  HYMOD_EEREC_HSCHIN,  uint_handler,   1,  0               },
+    { "hschout", HYMOD_EEREC_HSCHOUT, uint_handler,   1,  0               },
+};
+
+static int neerecs = sizeof eerec_map / sizeof eerec_map[0];
+
+static uchar data[HYMOD_EEPROM_SIZE], *sdp, *dp, *edp;
+
+static int
+eeprom_fetch_callback(uchar *name, uchar *value)
+{
+    eerec_map_t *rp;
+
+    for (rp = eerec_map; rp < &eerec_map[neerecs]; rp++)
+	if (strcmp(name, rp->name) == 0)
+	    break;
+
+    if (rp >= &eerec_map[neerecs])
+	return (0);
+
+    if ((dp = (*rp->handler)(rp, value, dp, edp)) == NULL)
+	return (0);
+
+    return (1);
+}
+
+int
+eeprom_fetch(unsigned offset, bd_t *bd, char *filename, ulong addr)
+{
+    hymod_eehdr_t *hp = (hymod_eehdr_t *)&data[0];
+    ulong crc;
+
+    hp->id = HYMOD_EEPROM_ID;
+    hp->ver = HYMOD_EEPROM_VER;
+
+    dp = sdp = (uchar *)(hp + 1);
+    edp = dp + HYMOD_EEPROM_MAXLEN;
+
+    if (fetch_and_parse(bd, filename, addr, eeprom_fetch_callback) == 0)
+	return (0);
+
+    hp->len = dp - sdp;
+
+    crc = crc32(0, data, dp - data);
+    memcpy(dp, &crc, sizeof (ulong));
+    dp += sizeof (ulong);
+
+    eeprom_write(CFG_DEF_EEPROM_ADDR, offset, data, dp - data);
+
+    return (1);
+}
+
+static char *type_vals[] = {
+    "NONE", "IO", "CLP", "DSP", "INPUT", "ALT-INPUT", "DISPLAY"
+};
+
+static char *xlxtyp_vals[] = {
+    "NONE", "XCV300E", "XCV400E", "XCV600E"
+};
+
+static char *xlxspd_vals[] = {
+    "NONE", "6", "7", "8"
+};
+
+static char *xlxtmp_vals[] = {
+    "NONE", "COM", "IND"
+};
+
+static char *xlxgrd_vals[] = {
+    "NONE", "NORMAL", "ENGSAMP"
+};
+
+static char *cputyp_vals[] = {
+    "NONE", "MPC8260"
+};
+
+static char *clk_vals[] = {
+    "NONE", "33", "66", "100", "133", "166", "200"
+};
+
+static char *hstype_vals[] = {
+    "NONE", "AMCC-S2064A"
+};
+
+static void
+print_mem(char *l, char *s, uchar n, uchar a[])
+{
+    if (n > 0) {
+	if (n == 1)
+	    printf("%s%dMB %s", s, 1 << (a[0] - 20), l);
+	else {
+	    ulong t = 0;
+	    int i;
+
+	    for (i = 0; i < n; i++)
+		t += 1 << (a[i] - 20);
+
+	    printf("%s%luMB %s (%d banks:", s, t, l, n);
+
+	    for (i = 0; i < n; i++)
+		printf("%dMB%s", 1 << (a[i] - 20), (i == n - 1) ? ")" : ",");
+	}
+    }
+    else
+	printf("%sNO %s", s, l);
+}
+
+void
+eeprom_print(hymod_eeprom_t *ep)
+{
+    int i;
+
+    printf("         Hymod %s board, rev %03d\n",
+	type_vals[ep->bdtype], ep->bdrev);
+
+    printf("         serial #: %010lu, date %04d-%02d-%02d",
+	ep->serno, ep->date.year, ep->date.month, ep->date.day);
+    if (ep->batchlen > 0)
+	printf(", batch \"%.*s\"", ep->batchlen, ep->batch);
+    puts("\n");
+
+    switch (ep->bdtype) {
+
+    case HYMOD_BDTYPE_IO:
+    case HYMOD_BDTYPE_CLP:
+    case HYMOD_BDTYPE_DSP:
+	printf("         Motorola %s CPU, speeds: %s/%s/%s",
+	    cputyp_vals[ep->mpc.type], clk_vals[ep->mpc.cpuspd],
+	    clk_vals[ep->mpc.cpmspd], clk_vals[ep->mpc.busspd]);
+
+	print_mem("SDRAM", ", ", ep->nsdram, ep->sdramsz);
+
+	print_mem("FLASH", ", ", ep->nflash, ep->flashsz);
+
+	puts("\n");
+
+	print_mem("ZBT", "         ", ep->nzbt, ep->zbtsz);
+
+	if (ep->nxlx > 0) {
+	    hymod_xlx_t *xp;
+
+	    if (ep->nxlx == 1) {
+		xp = &ep->xlx[0];
+		printf(", Xilinx %s FPGA (%s/%s/%s)",
+		    xlxtyp_vals[xp->type], xlxspd_vals[xp->speed],
+		    xlxtmp_vals[xp->temp], xlxgrd_vals[xp->grade]);
+	    }
+	    else {
+		printf(", %d Xilinx FPGAs (", ep->nxlx);
+		for (i = 0; i < ep->nxlx; i++) {
+		    xp = &ep->xlx[i];
+		    printf("%s[%s/%s/%s]%s",
+			xlxtyp_vals[xp->type], xlxspd_vals[xp->speed],
+			xlxtmp_vals[xp->temp], xlxgrd_vals[xp->grade],
+			(i == ep->nxlx - 1) ? ")" : ", ");
+		}
+	    }
+	}
+	else
+	    puts(", NO FPGAs");
+
+	puts("\n");
+
+	if (ep->hss.type > 0)
+	    printf("         High Speed Serial: %s, %d input%s, %d output%s\n",
+		hstype_vals[ep->hss.type],
+		ep->hss.nchin, (ep->hss.nchin == 1 ? "" : "s"),
+		ep->hss.nchout, (ep->hss.nchout == 1 ? "" : "s"));
+	break;
+
+    case HYMOD_BDTYPE_INPUT:
+    case HYMOD_BDTYPE_ALTINPUT:
+    case HYMOD_BDTYPE_DISPLAY:
+	break;
+
+    default:
+	/* crap! */
+	printf("         UNKNOWN BOARD TYPE: %d\n", ep->bdtype);
+	break;
+    }
+}
diff --git a/board/hymod/flash.c b/board/hymod/flash.c
new file mode 100644
index 0000000..ee052e3
--- /dev/null
+++ b/board/hymod/flash.c
@@ -0,0 +1,745 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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
+ *
+ * Hacked for the Hymod board by Murray.Jensen@cmst.csiro.au, 20-Oct-00
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <board/hymod/flash.h>
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];	/* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * Protection Flags:
+ */
+#define FLAG_PROTECT_SET	0x01
+#define FLAG_PROTECT_CLEAR	0x02
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+#if 0
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+#endif
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * probe for the existence of flash at bank word address "addr"
+ * 0 = yes, 1 = bad Manufacturer's Id, 2 = bad Device Id
+ */
+static int
+bank_probe_word(bank_addr_t addr)
+{
+	int retval;
+
+	/* reset the flash */
+	*addr = BANK_CMD_RST;
+
+	/* check the manufacturer id */
+	*addr = BANK_CMD_RD_ID;
+	if (*BANK_ADDR_REG_MAN(addr) != BANK_RD_ID_MAN) {
+		retval = -1;
+		goto out;
+	}
+
+	/* check the device id */
+	*addr = BANK_CMD_RD_ID;
+	if (*BANK_ADDR_REG_DEV(addr) != BANK_RD_ID_DEV) {
+		retval = -2;
+		goto out;
+	}
+
+	retval = CFG_FLASH_TYPE;
+
+out:
+	/* reset the flash again */
+	*addr = BANK_CMD_RST;
+
+	return retval;
+}
+
+/*
+ * probe for flash banks at address "base" and store info for any found
+ * into flash_info entry "fip". Must find at least one bank.
+ */
+static void
+bank_probe(flash_info_t *fip, bank_addr_t base)
+{
+	bank_addr_t addr, eaddr;
+	int nbanks;
+
+	fip->flash_id = FLASH_UNKNOWN;
+	fip->size = 0L;
+	fip->sector_count = 0;
+
+	addr = base;
+	eaddr = BANK_ADDR_BASE(addr, MAX_BANKS);
+	nbanks = 0;
+
+	while (addr < eaddr) {
+		bank_addr_t addrw, eaddrw, addrb;
+		int i, osc, nsc, curtype = -1;
+
+		addrw = addr;
+		eaddrw = BANK_ADDR_NEXT_WORD(addrw);
+
+		while (addrw < eaddrw) {
+			int thistype;
+
+#ifdef FLASH_DEBUG
+			printf("  probing for flash at addr 0x%08lx\n",
+				(unsigned long)addrw);
+#endif
+			if ((thistype = bank_probe_word(addrw++)) < 0)
+				goto out;
+
+			if (curtype < 0)
+				curtype = thistype;
+			else {
+				if (thistype != curtype) {
+					printf("Differing flash type found!\n");
+					goto out;
+				}
+			}
+		}
+
+		if (curtype < 0)
+			goto out;
+
+		/* bank exists - append info for this bank to *fip */
+		fip->flash_id = FLASH_MAN_INTEL|curtype;
+		fip->size += BANK_SIZE;
+		osc = fip->sector_count;
+		fip->sector_count += BANK_NBLOCKS;
+		if ((nsc = fip->sector_count) >= CFG_MAX_FLASH_SECT)
+			panic("Too many sectors in flash at address 0x%08lx\n",
+				(unsigned long)base);
+
+		addrb = addr;
+		for (i = osc; i < nsc; i++) {
+			fip->start[i] = (ulong)addrb;
+			fip->protect[i] = 0;
+			addrb = BANK_ADDR_NEXT_BLK(addrb);
+		}
+
+		addr = BANK_ADDR_NEXT_BANK(addr);
+		nbanks++;
+	}
+
+out:
+	if (nbanks == 0)
+		panic("ERROR: no flash found at address 0x%08lx\n",
+			(unsigned long)base);
+}
+
+static void
+bank_reset(flash_info_t *info, int sect)
+{
+	bank_addr_t addrw, eaddrw;
+
+	addrw = (bank_addr_t)info->start[sect];
+	eaddrw = BANK_ADDR_NEXT_WORD(addrw);
+
+	while (addrw < eaddrw) {
+#ifdef FLASH_DEBUG
+		printf("  writing reset cmd to addr 0x%08lx\n",
+			(unsigned long)addrw);
+#endif
+		*addrw = BANK_CMD_RST;
+		addrw++;
+	}
+}
+
+static void
+bank_erase_init(flash_info_t *info, int sect)
+{
+	bank_addr_t addrw, saddrw, eaddrw;
+	int flag;
+
+#ifdef FLASH_DEBUG
+	printf("0x%08lx BANK_CMD_PROG\n", BANK_CMD_PROG);
+	printf("0x%08lx BANK_CMD_ERASE1\n", BANK_CMD_ERASE1);
+	printf("0x%08lx BANK_CMD_ERASE2\n", BANK_CMD_ERASE2);
+	printf("0x%08lx BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT);
+	printf("0x%08lx BANK_CMD_RST\n", BANK_CMD_RST);
+	printf("0x%08lx BANK_STAT_RDY\n", BANK_STAT_RDY);
+	printf("0x%08lx BANK_STAT_ERR\n", BANK_STAT_ERR);
+#endif
+
+	saddrw = (bank_addr_t)info->start[sect];
+	eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
+
+#ifdef FLASH_DEBUG
+	printf("erasing sector %d, start addr = 0x%08lx "
+		"(bank next word addr = 0x%08lx)\n", sect,
+		(unsigned long)saddrw, (unsigned long)eaddrw);
+#endif
+
+	/* Disable intrs which might cause a timeout here */
+	flag = disable_interrupts();
+
+	for (addrw = saddrw; addrw < eaddrw; addrw++) {
+#ifdef FLASH_DEBUG
+		printf("  writing erase cmd to addr 0x%08lx\n",
+			(unsigned long)addrw);
+#endif
+		*addrw = BANK_CMD_ERASE1;
+		*addrw = BANK_CMD_ERASE2;
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+}
+
+static int
+bank_erase_poll(flash_info_t *info, int sect)
+{
+	bank_addr_t addrw, saddrw, eaddrw;
+	int sectdone, haderr;
+
+	saddrw = (bank_addr_t)info->start[sect];
+	eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
+
+	sectdone = 1;
+	haderr = 0;
+
+	for (addrw = saddrw; addrw < eaddrw; addrw++) {
+		bank_word_t stat = *addrw;
+
+#ifdef FLASH_DEBUG
+		printf("  checking status at addr "
+			"0x%08lx [0x%08lx]\n",
+			(unsigned long)addrw, stat);
+#endif
+		if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY)
+			sectdone = 0;
+		else if ((stat & BANK_STAT_ERR) != 0) {
+			printf(" failed on sector %d "
+				"(stat = 0x%08lx) at "
+				"address 0x%08lx\n",
+				sect, stat,
+				(unsigned long)addrw);
+			*addrw = BANK_CMD_CLR_STAT;
+			haderr = 1;
+		}
+	}
+
+	if (haderr)
+		return (-1);
+	else
+		return (sectdone);
+}
+
+static int
+bank_write_word(bank_addr_t addr, bank_word_t value)
+{
+	bank_word_t stat;
+	ulong start;
+	int flag, retval;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	*addr = BANK_CMD_PROG;
+
+	*addr = value;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	retval = 0;
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	do {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			retval = 1;
+			goto done;
+		}
+		stat = *addr;
+	} while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY);
+
+	if ((stat & BANK_STAT_ERR) != 0) {
+		printf("flash program failed (stat = 0x%08lx) "
+			"at address 0x%08lx\n", (ulong)stat, (ulong)addr);
+		*addr = BANK_CMD_CLR_STAT;
+		retval = 3;
+	}
+
+done:
+	/* reset to read mode */
+	*addr = BANK_CMD_RST;
+
+	return (retval);
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long
+flash_init(void)
+{
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	bank_probe(&flash_info[0], (bank_addr_t)CFG_FLASH_BASE);
+
+	/*
+	 * protect monitor and environment sectors
+	 */
+
+#if CFG_MONITOR_BASE == CFG_FLASH_BASE
+	(void)flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+#if defined(CFG_FLASH_ENV_ADDR)
+	(void)flash_protect(FLAG_PROTECT_SET,
+		      CFG_FLASH_ENV_ADDR,
+#if defined(CFG_FLASH_ENV_BUF)
+		      CFG_FLASH_ENV_ADDR + CFG_FLASH_ENV_BUF - 1,
+#else
+		      CFG_FLASH_ENV_ADDR + CFG_FLASH_ENV_SIZE - 1,
+#endif
+		      &flash_info[0]);
+#endif
+
+	return flash_info[0].size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+#if 0
+static void
+flash_get_offsets(ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start adress table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+
+}
+#endif	/* 0 */
+
+/*-----------------------------------------------------------------------
+ */
+void
+flash_print_info(flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_INTEL:	printf ("INTEL ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_28F320J5:	printf ("28F320J5 (32 Mbit, 2 x 16bit)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+#if 0
+static ulong
+flash_get_size(vu_long *addr, flash_info_t *info)
+{
+	short i;
+	ulong value;
+	ulong base = (ulong)addr;
+
+
+	/* Write auto select command: read Manufacturer ID */
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00900090;
+
+	value = addr[0];
+
+	switch (value) {
+	case AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	switch (value) {
+	case AMD_ID_LV400T:
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV400B:
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV800T:
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV800B:
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV160T:
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case AMD_ID_LV160B:
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+	case AMD_ID_LV320T:
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case AMD_ID_LV320B:
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+#endif
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	/* set up sector start adress table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr = (volatile unsigned long *)(info->start[i]);
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (volatile unsigned long *)info->start[0];
+
+		*addr = 0x00F000F0;	/* reset bank */
+	}
+
+	return (info->size);
+}
+#endif /* 0 */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int
+flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+	int prot, sect, haderr;
+	ulong start, now, last;
+	int rcode = 0;
+
+#ifdef FLASH_DEBUG
+	printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
+		"  Bank # %d: ", s_last - s_first + 1, s_first, s_last,
+		(info - flash_info) + 1);
+	flash_print_info(info);
+#endif
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf("- Warning: %d protected sector%s will not be erased!\n",
+			prot, (prot > 1 ? "s" : ""));
+	}
+
+	start = get_timer (0);
+	last = 0;
+	haderr = 0;
+
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			ulong estart;
+			int sectdone;
+
+			bank_erase_init(info, sect);
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+
+			estart = get_timer(start);
+
+			do {
+				now = get_timer(start);
+
+				if (now - estart > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout (sect %d)\n", sect);
+					haderr = 1;
+					rcode = 1;
+					break;
+				}
+
+#ifndef FLASH_DEBUG
+				/* show that we're waiting */
+				if ((now - last) > 1000) { /* every second */
+					putc ('.');
+					last = now;
+				}
+#endif
+
+				sectdone = bank_erase_poll(info, sect);
+
+				if (sectdone < 0) {
+					haderr = 1;
+					rcode = 1;
+					break;
+				}
+
+			} while (!sectdone);
+
+			if (haderr)
+				break;
+		}
+	}
+
+	if (haderr > 0)
+		printf (" failed\n");
+	else
+		printf (" done\n");
+
+	/* reset to read mode */
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			bank_reset(info, sect);
+		}
+	}
+	return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int
+write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int
+write_word(flash_info_t *info, ulong dest, ulong data)
+{
+	int retval;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*(ulong *)dest & data) != data) {
+		return (2);
+	}
+
+	retval = bank_write_word((bank_addr_t)dest, (bank_word_t)data);
+
+	return (retval);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/icu862/flash.c b/board/icu862/flash.c
new file mode 100644
index 0000000..79e7cc2
--- /dev/null
+++ b/board/icu862/flash.c
@@ -0,0 +1,617 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i < CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0,
+			size_b0 >> 20);
+	}
+
+	if (FLASH_BASE1_PRELIM != 0x0) {
+		size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+
+		if (size_b1 > size_b0) {
+			printf ("## ERROR: Bank 1 (0x%08lx = %ld MB)"
+				" > Bank 0 (0x%08lx = %ld MB)\n",
+				size_b1, size_b1 >> 20,
+				size_b0, size_b0 >> 20);
+
+			flash_info[0].flash_id	= FLASH_UNKNOWN;
+			flash_info[1].flash_id	= FLASH_UNKNOWN;
+			flash_info[0].sector_count	= -1;
+			flash_info[1].sector_count	= -1;
+			flash_info[0].size		= 0;
+			flash_info[1].size		= 0;
+			return (0);
+		}
+	} else {
+		size_b1 = 0;
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK);
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+	/* ENV protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR+CFG_ENV_SIZE-1,
+		      &flash_info[0]);
+#endif
+
+	/* ICU862 Board has only one Flash Bank */
+	flash_info[1].flash_id = FLASH_UNKNOWN;
+	flash_info[1].sector_count = -1;
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start address table */
+	if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) ||
+		((info->flash_id & FLASH_TYPEMASK) == FLASH_AM033C)) {
+		/* set sector offsets for uniform sector type	*/
+		for (i = 0; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00040000);
+		}
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		puts ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	puts ("AMD ");		break;
+	case FLASH_MAN_FUJ:	puts ("FUJITSU ");	break;
+	case FLASH_MAN_BM:	puts ("BRIGHT MICRO ");	break;
+	default:		puts ("Unknown Vendor "); break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM040:	puts ("29F040/29LV040 (4 Mbit, uniform sectors)\n");
+				break;
+	case FLASH_AM400B:	puts ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	puts ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	puts ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	puts ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	puts ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	puts ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320B:	puts ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM320T:	puts ("AM29LV320T (32 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM033C:	puts ("AM29LV033C (32 Mbit)\n");
+				break;
+	default:		puts ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	puts ("  Sector Start Addresses:");
+
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0) {
+			puts ("\n   ");
+		}
+
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+
+	puts ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+#if 0
+	ulong base = (ulong)addr;
+#endif
+	uchar value;
+
+	/* Write auto select command: read Manufacturer ID */
+#if 0
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00900090;
+#else
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+	addr[0x0555] = 0x90909090;
+#endif
+
+	value = addr[0];
+
+	switch (value + (value << 16)) {
+	case AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+
+	case FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		break;
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	switch (value) {
+	case AMD_ID_F040B:
+		info->flash_id += FLASH_AM040;
+		info->sector_count = 8;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV400T:
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV400B:
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV800T:
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV800B:
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV160T:
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case AMD_ID_LV160B:
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+	case AMD_ID_LV320T:
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case AMD_ID_LV320B:
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+#endif
+	case AMD_ID_LV033C:
+		info->flash_id += FLASH_AM033C;
+		info->sector_count = 64;
+		info->size = 0x01000000;
+		break;				/* => 16Mb		*/
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+#if 0
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+#else
+	flash_get_offsets ((ulong)addr, &flash_info[0]);
+#endif
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr = (volatile unsigned long *)(info->start[i]);
+#if 1
+		/* We don't know why it happens, but on ICU Board	*
+		 * for AMD29033C flash we need to resend the command of	*
+		 * reading flash protection for upper 8 Mb of flash	*/
+		if ( i == 32 ) {
+			addr[0x0555] = 0xAAAAAAAA;
+			addr[0x02AA] = 0x55555555;
+			addr[0x0555] = 0x90909090;
+		}
+#endif
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (volatile unsigned long *)info->start[0];
+#if 0
+		*addr = 0x00F000F0;	/* reset bank */
+#else
+		*addr = 0xF0F0F0F0;	/* reset bank */
+#endif
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			puts ("- missing\n");
+		} else {
+			puts ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    (info->flash_id > FLASH_AMD_COMP)) {
+		puts ("Can't erase unknown flash type - aborted\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		puts ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+#if 0
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00800080;
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+#else
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+	addr[0x0555] = 0x80808080;
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+#endif
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (vu_long*)(info->start[sect]);
+#if 0
+			addr[0] = 0x00300030;
+#else
+			addr[0] = 0x30303030;
+#endif
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (vu_long*)(info->start[l_sect]);
+#if 0
+	while ((addr[0] & 0x00800080) != 0x00800080)
+#else
+	while ((addr[0] & 0xFFFFFFFF) != 0xFFFFFFFF)
+#endif
+	{
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			puts ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (volatile unsigned long *)info->start[0];
+#if 0
+	addr[0] = 0x00F000F0;	/* reset bank */
+#else
+	addr[0] = 0xF0F0F0F0;	/* reset bank */
+#endif
+
+	puts (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *)dest) & data) != data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+#if 0
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00A000A0;
+#else
+	addr[0x0555] = 0xAAAAAAAA;
+	addr[0x02AA] = 0x55555555;
+	addr[0x0555] = 0xA0A0A0A0;
+#endif
+
+	*((vu_long *)dest) = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+#if 0
+	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080))
+#else
+	while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080))
+#endif
+	{
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/ip860/flash.c b/board/ip860/flash.c
new file mode 100644
index 0000000..4b0ea9b
--- /dev/null
+++ b/board/ip860/flash.c
@@ -0,0 +1,456 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t	*immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t	*memctl = &immap->im_memctl;
+	volatile ip860_bcsr_t	*bcsr   = (ip860_bcsr_t *)BCSR_BASE;
+	unsigned long size;
+	int i;
+
+	/* Init: enable write,
+	 * or we cannot even write flash commands
+	 */
+	bcsr->bd_ctrl |= BD_CTRL_FLWE;
+
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size = flash_get_size((vu_long *)FLASH_BASE, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size, size<<20);
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size & 0xFFFF8000);
+	memctl->memc_br1 = (CFG_FLASH_BASE & BR_BA_MSK) |
+				(memctl->memc_br1 & ~(BR_BA_MSK));
+
+	/* Re-do sizing to get full correct info */
+	size = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_info[0].size = size;
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+	/* ENV protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+		      &flash_info[0]);
+#endif
+	return (size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* all possible flash types
+	 * (28F016SV, 28F160S3, 28F320S3)
+	 * have the same erase block size: 64 kB per chip,
+	 * of 128 kB per bank
+	 */
+
+	/* set up sector start address table */
+	for (i = 0; i < info->sector_count; i++) {
+		info->start[i] = base;
+		base += 0x00020000;
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_INTEL:	printf ("Intel ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_28F016SV:	printf ("28F016SV (16 Mbit, 32 x 64k)\n");
+				break;
+	case FLASH_28F160S3:	printf ("28F160S3 (16 Mbit, 32 x 512K)\n");
+				break;
+	case FLASH_28F320S3:	printf ("28F320S3 (32 Mbit, 64 x 512K)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	ulong value;
+	ulong base = (ulong)addr;
+
+	/* Write "Intelligent Identifier" command: read Manufacturer ID */
+	*addr = 0x90909090;
+
+	value = addr[0];
+	switch (value) {
+	case (MT_MANUFACT & 0x00FF00FF):	/* MT or => Intel */
+	case (INTEL_ALT_MANU & 0x00FF00FF):
+		info->flash_id = FLASH_MAN_INTEL;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	switch (value) {
+	case (INTEL_ID_28F016S):
+		info->flash_id += FLASH_28F016SV;
+		info->sector_count = 32;
+		info->size = 0x00400000;
+		break;				/* => 2x2 MB		*/
+
+	case (INTEL_ID_28F160S3):
+		info->flash_id += FLASH_28F160S3;
+		info->sector_count = 32;
+		info->size = 0x00400000;
+		break;				/* => 2x2 MB		*/
+
+	case (INTEL_ID_28F320S3):
+		info->flash_id += FLASH_28F320S3;
+		info->sector_count = 64;
+		info->size = 0x00800000;
+		break;				/* => 2x4 MB		*/
+
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	/* set up sector start address table */
+	for (i = 0; i < info->sector_count; i++) {
+		info->start[i] = base + (i * 0x00020000);
+		/* don't know how to check sector protection */
+		info->protect[i] = 0;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (vu_long *)info->start[0];
+
+		*addr = 0xFFFFFF;	/* reset bank to read array mode */
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	int flag, prot, sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	start = get_timer (0);
+	last  = start;
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			vu_long *addr = (vu_long *)(info->start[sect]);
+
+			/* Disable interrupts which might cause a timeout here */
+			flag = disable_interrupts();
+
+			/* Single Block Erase Command */
+			*addr = 0x20202020;
+			/* Confirm */
+			*addr = 0xD0D0D0D0;
+			/* Resume Command, as per errata update */
+			*addr = 0xD0D0D0D0;
+
+			/* re-enable interrupts if necessary */
+			if (flag)
+				enable_interrupts();
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+
+			while ((*addr & 0x00800080) != 0x00800080) {
+				if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout\n");
+					*addr = 0xFFFFFFFF;	/* reset bank */
+					return 1;
+				}
+				/* show that we're waiting */
+				if ((now - last) > 1000) {	/* every second */
+					putc ('.');
+					last = now;
+				}
+			}
+
+			/* reset to read mode */
+			*addr = 0xFFFFFFFF;
+		}
+	}
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long *)dest;
+	ulong start, csr;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*addr & data) != data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	/* Write Command */
+	*addr = 0x10101010;
+
+	/* Write Data */
+	*addr = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	flag  = 0;
+	while (((csr = *addr) & 0x00800080) != 0x00800080) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			flag = 1;
+			break;
+		}
+	}
+	if (csr & 0x00400040) {
+printf ("CSR indicates write error (%08lx) at %08lx\n", csr, (ulong)addr);
+		flag = 1;
+	}
+
+	/* Clear Status Registers Command */
+	*addr = 0x50505050;
+	/* Reset to read array mode */
+	*addr = 0xFFFFFFFF;
+
+	return (flag);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/ivm/flash.c b/board/ivm/flash.c
new file mode 100644
index 0000000..b5453df
--- /dev/null
+++ b/board/ivm/flash.c
@@ -0,0 +1,598 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_data (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0: "
+			"ID 0x%lx, Size = 0x%08lx = %ld MB\n",
+			flash_info[0].flash_id,
+			size_b0, size_b0<<20);
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | \
+				BR_MS_GPCM | BR_PS_16 | BR_V;
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_info[0].size = size_b0;
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+	/* ENV protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+		      &flash_info[0]);
+#endif
+
+	return (size_b0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_MT:
+	    if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00006000;
+		info->start[3] = base + 0x00008000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + ((i-3) * 0x00020000);
+		}
+	    } else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00006000;
+		info->start[i--] = base + info->size - 0x00008000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	    }
+	    return;
+
+	case FLASH_MAN_SST:
+	    for (i = 0; i < info->sector_count; i++) {
+		info->start[i] = base + (i * 0x00002000);
+	    }
+	    return;
+
+	case FLASH_MAN_AMD:
+	case FLASH_MAN_FUJ:
+
+	    /* set up sector start address table */
+	    if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	    } else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	    }
+	    return;
+	default:
+	    printf ("Don't know sector ofsets for flash type 0x%lx\n",
+		info->flash_id);
+	    return;
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("Fujitsu ");		break;
+	case FLASH_MAN_SST:	printf ("SST ");		break;
+	case FLASH_MAN_STM:	printf ("STM ");		break;
+	case FLASH_MAN_MT:	printf ("MT ");			break;
+	case FLASH_MAN_INTEL:	printf ("Intel ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+				break;
+	case FLASH_SST200A:	printf ("39xF200A (2M = 128K x 16)\n");
+				break;
+	case FLASH_SST400A:	printf ("39xF400A (4M = 256K x 16)\n");
+				break;
+	case FLASH_SST800A:	printf ("39xF800A (8M = 512K x 16)\n");
+				break;
+	case FLASH_STM800AB:	printf ("M29W800AB (8M = 512K x 16)\n");
+				break;
+	case FLASH_28F008S5:	printf ("28F008S5 (1M = 64K x 16)\n");
+				break;
+	case FLASH_28F400_T:	printf ("28F400B3 (4Mbit, top boot sector)\n");
+				break;
+	case FLASH_28F400_B:	printf ("28F400B3 (4Mbit, bottom boot sector)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	if (info->size >= (1 << 20)) {
+		i = 20;
+	} else {
+		i = 10;
+	}
+	printf ("  Size: %ld %cB in %d Sectors\n",
+		info->size >> i,
+		(i == 20) ? 'M' : 'k',
+		info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	ushort value;
+	vu_short *saddr = (vu_short *)addr;
+
+	/* Read Manufacturer ID */
+	saddr[0] = 0x0090;
+	value = saddr[0];
+
+	switch (value) {
+	case (AMD_MANUFACT & 0xFFFF):
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case (FUJ_MANUFACT & 0xFFFF):
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	case (SST_MANUFACT & 0xFFFF):
+		info->flash_id = FLASH_MAN_SST;
+		break;
+	case (STM_MANUFACT & 0xFFFF):
+		info->flash_id = FLASH_MAN_STM;
+		break;
+	case (MT_MANUFACT & 0xFFFF):
+		info->flash_id = FLASH_MAN_MT;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		saddr[0] = 0x00FF;		/* restore read mode */
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = saddr[1];			/* device ID		*/
+
+	switch (value) {
+	case (AMD_ID_LV400T & 0xFFFF):
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (AMD_ID_LV400B & 0xFFFF):
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (AMD_ID_LV800T & 0xFFFF):
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case (AMD_ID_LV800B & 0xFFFF):
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case (AMD_ID_LV160T & 0xFFFF):
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case (AMD_ID_LV160B & 0xFFFF):
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+	case (AMD_ID_LV320T & 0xFFFF):
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case (AMD_ID_LV320B & 0xFFFF):
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+#endif
+	case (SST_ID_xF200A & 0xFFFF):
+		info->flash_id += FLASH_SST200A;
+		info->sector_count = 64;	/* 39xF200A ID ( 2M = 128K x 16	) */
+		info->size = 0x00080000;
+		break;
+	case (SST_ID_xF400A & 0xFFFF):
+		info->flash_id += FLASH_SST400A;
+		info->sector_count = 128;	/* 39xF400A ID ( 4M = 256K x 16	) */
+		info->size = 0x00100000;
+		break;
+	case (SST_ID_xF800A & 0xFFFF):
+		info->flash_id += FLASH_SST800A;
+		info->sector_count = 256;	/* 39xF800A ID ( 8M = 512K x 16	) */
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+	case (STM_ID_x800AB & 0xFFFF):
+		info->flash_id += FLASH_STM800AB;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+	case (MT_ID_28F400_T & 0xFFFF):
+		info->flash_id += FLASH_28F400_T;
+		info->sector_count = 7;
+		info->size = 0x00080000;
+		break;				/* => 512 kB		*/
+	case (MT_ID_28F400_B & 0xFFFF):
+		info->flash_id += FLASH_28F400_B;
+		info->sector_count = 7;
+		info->size = 0x00080000;
+		break;				/* => 512 kB		*/
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		saddr[0] = 0x00FF;		/* restore read mode */
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	if (info->sector_count > CFG_MAX_FLASH_SECT) {
+		printf ("** ERROR: sector count %d > max (%d) **\n",
+			info->sector_count, CFG_MAX_FLASH_SECT);
+		info->sector_count = CFG_MAX_FLASH_SECT;
+	}
+
+	saddr[0] = 0x00FF;		/* restore read mode */
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	int flag, prot, sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_MT) {
+		printf ("Can erase only MT flash types - aborted\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	start = get_timer (0);
+	last  = start;
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			vu_short *addr = (vu_short *)(info->start[sect]);
+			unsigned short status;
+
+			/* Disable interrupts which might cause a timeout here */
+			flag = disable_interrupts();
+
+			*addr = 0x0050;	/* clear status register */
+			*addr = 0x0020;	/* erase setup */
+			*addr = 0x00D0;	/* erase confirm */
+
+			/* re-enable interrupts if necessary */
+			if (flag)
+				enable_interrupts();
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+
+			while (((status = *addr) & 0x0080) != 0x0080) {
+				if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout\n");
+					*addr = 0x00FF;	/* reset to read mode */
+					return 1;
+				}
+
+				/* show that we're waiting */
+				if ((now - last) > 1000) {	/* every second */
+					putc ('.');
+					last = now;
+				}
+			}
+
+			*addr = 0x00FF;	/* reset to read mode */
+		}
+	}
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 4 - Flash not identified
+ */
+
+#define	FLASH_WIDTH	2	/* flash bus width in bytes */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return 4;
+	}
+
+	wp = (addr & ~(FLASH_WIDTH-1));	/* get lower FLASH_WIDTH aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<FLASH_WIDTH && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_data(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += FLASH_WIDTH;
+	}
+
+	/*
+	 * handle FLASH_WIDTH aligned part
+	 */
+	while (cnt >= FLASH_WIDTH) {
+		data = 0;
+		for (i=0; i<FLASH_WIDTH; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_data(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += FLASH_WIDTH;
+		cnt -= FLASH_WIDTH;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<FLASH_WIDTH; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_data(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_data (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_short *addr = (vu_short *)dest;
+	ushort sdata = (ushort)data;
+	ushort status;
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*addr & sdata) != sdata) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	*addr = 0x0040;		/* write setup */
+	*addr = sdata;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	start = get_timer (0);
+
+	while (((status = *addr) & 0x0080) != 0x0080) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			*addr = 0x00FF;	/* restore read mode */
+			return (1);
+		}
+	}
+
+	*addr = 0x00FF;		/* restore read mode */
+
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/lantec/flash.c b/board/lantec/flash.c
new file mode 100644
index 0000000..df58510
--- /dev/null
+++ b/board/lantec/flash.c
@@ -0,0 +1,625 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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
+ */
+
+/*
+ * Derived from ../tqm8xx/flash.c
+ * [Torsten Stevens, FHG IMS; Bruno Achauer, Exet AG]
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_FLASH
+
+#ifdef DEBUG_FLASH
+#define DEBUGF(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGF(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	DEBUGF("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_PRELIM);
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0: "
+			"ID 0x%lx, Size = 0x%08lx = %ld MB\n",
+			flash_info[0].flash_id,
+			size_b0, size_b0<<20);
+	}
+
+	DEBUGF("## Get flash bank 2 size @ 0x%08x\n",FLASH_BASE5_PRELIM);
+
+	size_b1 = flash_get_size((vu_long *)FLASH_BASE5_PRELIM, &flash_info[1]);
+
+	DEBUGF("## Prelim. Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1);
+
+	if (size_b1 > size_b0) {
+		printf ("## ERROR: "
+			"Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
+			size_b1, size_b1<<20,
+			size_b0, size_b0<<20
+		);
+		flash_info[0].flash_id	= FLASH_UNKNOWN;
+		flash_info[1].flash_id	= FLASH_UNKNOWN;
+		flash_info[0].sector_count	= -1;
+		flash_info[1].sector_count	= -1;
+		flash_info[0].size		= 0;
+		flash_info[1].size		= 0;
+		return (0);
+	}
+
+	DEBUGF ("## Before remap: "
+		"BR0: 0x%08x    OR0: 0x%08x    "
+		"BR1: 0x%08x    OR1: 0x%08x\n",
+		memctl->memc_br0, memctl->memc_or0,
+		memctl->memc_br1, memctl->memc_or1);
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | \
+				BR_MS_GPCM | BR_PS_32 | BR_V;
+
+	DEBUGF("## BR0: 0x%08x    OR0: 0x%08x\n",
+		memctl->memc_br0, memctl->memc_or0);
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_info[0].size = size_b0;
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+	/* ENV protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+		      &flash_info[0]);
+#endif
+
+	if (size_b1) {
+		memctl->memc_or5 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
+		memctl->memc_br5 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
+				    BR_MS_GPCM | BR_PS_32 | BR_V;
+
+		DEBUGF("## BR5: 0x%08x    OR5: 0x%08x\n",
+			memctl->memc_br5, memctl->memc_or5);
+
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0),
+					  &flash_info[1]);
+
+		flash_info[1].size = size_b1;
+
+		flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+		/* monitor protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_MONITOR_BASE,
+			      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+			      &flash_info[1]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+		/* ENV protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_ENV_ADDR,
+			      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+			      &flash_info[1]);
+#endif
+	} else {
+		memctl->memc_br5 = 0;		/* invalidate bank */
+		memctl->memc_or5 = 0;		/* invalidate bank */
+
+		DEBUGF("## DISABLE BR5: 0x%08x    OR5: 0x%08x\n",
+			memctl->memc_br5, memctl->memc_or5);
+
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+		flash_info[1].size = 0;
+	}
+
+	DEBUGF("## Final Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1);
+
+	return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	ulong value;
+	ulong base = (ulong)addr;
+
+
+	/* Write auto select command: read Manufacturer ID */
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00900090;
+
+	value = addr[0];
+
+	switch (value) {
+	case AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	switch (value) {
+	case AMD_ID_LV400T:
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV400B:
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV800T:
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV800B:
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV160T:
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case AMD_ID_LV160B:
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+	case AMD_ID_LV320T:
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case AMD_ID_LV320B:
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+#endif
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr = (volatile unsigned long *)(info->start[i]);
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (volatile unsigned long *)info->start[0];
+
+		*addr = 0x00F000F0;	/* reset bank */
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    (info->flash_id > FLASH_AMD_COMP)) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00800080;
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (vu_long*)(info->start[sect]);
+			addr[0] = 0x00300030;
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (vu_long*)(info->start[l_sect]);
+	while ((addr[0] & 0x00800080) != 0x00800080) {
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (volatile unsigned long *)info->start[0];
+	addr[0] = 0x00F000F0;	/* reset bank */
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *)dest) & data) != data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00A000A0;
+
+	*((vu_long *)dest) = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/mbx8xx/flash.c b/board/mbx8xx/flash.c
new file mode 100644
index 0000000..e1aa47b
--- /dev/null
+++ b/board/mbx8xx/flash.c
@@ -0,0 +1,408 @@
+/*
+ * (C) Copyright 2000
+ * Marius Groeger <mgroeger@sysgo.de>
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for AM290[48]0B devices
+ *
+ *--------------------------------------------------------------------
+ * 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 <mpc8xx.h>
+#include "vpd.h"
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+    unsigned long size, totsize;
+    int i;
+    ulong addr;
+
+    /* Init: no FLASHes known */
+    for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+	flash_info[i].flash_id = FLASH_UNKNOWN;
+    }
+
+    totsize = 0;
+    addr = 0xfc000000;
+    for(i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+	size = flash_get_size((vu_long *)addr, &flash_info[i]);
+	if (flash_info[i].flash_id == FLASH_UNKNOWN)
+	  break;
+	totsize += size;
+	addr += size;
+    }
+
+    addr = 0xfe000000;
+    for(i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+
+	size = flash_get_size((vu_long *)addr, &flash_info[i]);
+	if (flash_info[i].flash_id == FLASH_UNKNOWN)
+	  break;
+	totsize += size;
+	addr += size;
+    }
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+    /* monitor protection ON by default */
+    flash_protect(FLAG_PROTECT_SET,
+		  CFG_MONITOR_BASE,
+		  CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		  &flash_info[0]);
+#endif
+
+    return (totsize);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+    int i;
+
+    if (info->flash_id == FLASH_UNKNOWN) {
+	printf ("missing or unknown FLASH type\n");
+	return;
+    }
+
+    switch (info->flash_id >> 16) {
+    case 0x1:
+	printf ("AMD ");
+	break;
+    default:
+	printf ("Unknown Vendor ");
+	break;
+    }
+
+    switch (info->flash_id & FLASH_TYPEMASK) {
+    case AMD_ID_F040B:
+	printf ("AM29F040B (4 Mbit)\n");
+	break;
+    case AMD_ID_F080B:
+	printf ("AM29F080B (8 Mbit)\n");
+	break;
+    case AMD_ID_F016D:
+	printf ("AM29F016D (16 Mbit)\n");
+	break;
+    default:
+	printf ("Unknown Chip Type\n");
+	break;
+    }
+
+    printf ("  Size: %ld MB in %d Sectors\n",
+	    info->size >> 20, info->sector_count);
+
+    printf ("  Sector Start Addresses:");
+    for (i=0; i<info->sector_count; ++i) {
+	if ((i % 5) == 0)
+	  printf ("\n   ");
+	printf (" %08lX%s",
+		info->start[i],
+		info->protect[i] ? " (RO)" : "     "
+		);
+    }
+    printf ("\n");
+    return;
+}
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+    short i;
+    ulong vendor, devid;
+    ulong base = (ulong)addr;
+
+    /* Write auto select command: read Manufacturer ID */
+    addr[0x0555] = 0xAAAAAAAA;
+    addr[0x02AA] = 0x55555555;
+    addr[0x0555] = 0x90909090;
+
+    vendor = addr[0];
+    devid = addr[1] & 0xff;
+
+    /* only support AMD */
+    if (vendor != 0x01010101) {
+	return 0;
+    }
+
+    vendor &= 0xf;
+    devid &= 0xff;
+
+    if (devid == AMD_ID_F040B) {
+	info->flash_id     = vendor << 16 | devid;
+	info->sector_count = 8;
+	info->size         = info->sector_count * 0x10000;
+    }
+    else if (devid == AMD_ID_F080B) {
+	info->flash_id     = vendor << 16 | devid;
+	info->sector_count = 16;
+	info->size         = 4 * info->sector_count * 0x10000;
+    }
+    else if (devid == AMD_ID_F016D) {
+	info->flash_id     = vendor << 16 | devid;
+	info->sector_count = 32;
+	info->size         = 4 * info->sector_count * 0x10000;
+    }
+    else {
+	printf ("## Unknown Flash Type: %08lx\n", devid);
+	return 0;
+    }
+
+    /* check for protected sectors */
+    for (i = 0; i < info->sector_count; i++) {
+	/* sector base address */
+	info->start[i] = base + i * (info->size / info->sector_count);
+	/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+	/* D0 = 1 if protected */
+	addr = (volatile unsigned long *)(info->start[i]);
+	info->protect[i] = addr[2] & 1;
+    }
+
+    /*
+     * Prevent writes to uninitialized FLASH.
+     */
+    if (info->flash_id != FLASH_UNKNOWN) {
+	addr = (vu_long *)info->start[0];
+	addr[0] = 0xF0;	/* reset bank */
+    }
+
+    return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+    vu_long *addr = (vu_long*)(info->start[0]);
+    int flag, prot, sect, l_sect;
+    ulong start, now, last;
+
+    if ((s_first < 0) || (s_first > s_last)) {
+	if (info->flash_id == FLASH_UNKNOWN) {
+	    printf ("- missing\n");
+	} else {
+	    printf ("- no sectors to erase\n");
+	}
+	return 1;
+    }
+
+    prot = 0;
+    for (sect = s_first; sect <= s_last; sect++) {
+	if (info->protect[sect]) {
+	    prot++;
+	}
+    }
+
+    if (prot) {
+	printf ("- Warning: %d protected sectors will not be erased!\n",
+		prot);
+    } else {
+	printf ("\n");
+    }
+
+    l_sect = -1;
+
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    addr[0x0555] = 0XAAAAAAAA;
+    addr[0x02AA] = 0x55555555;
+    addr[0x0555] = 0x80808080;
+    addr[0x0555] = 0XAAAAAAAA;
+    addr[0x02AA] = 0x55555555;
+
+    /* Start erase on unprotected sectors */
+    for (sect = s_first; sect<=s_last; sect++) {
+	if (info->protect[sect] == 0) {	/* not protected */
+	    addr = (vu_long*)(info->start[sect]);
+	    addr[0] = 0x30303030;
+	    l_sect = sect;
+	}
+    }
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+      enable_interrupts();
+
+    /* wait at least 80us - let's wait 1 ms */
+    udelay (1000);
+
+    /*
+     * We wait for the last triggered sector
+     */
+    if (l_sect < 0)
+      goto DONE;
+
+    start = get_timer (0);
+    last  = start;
+    addr = (vu_long*)(info->start[l_sect]);
+    while ((addr[0] & 0x80808080) != 0x80808080) {
+	if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+	    printf ("Timeout\n");
+	    return 1;
+	}
+	/* show that we're waiting */
+	if ((now - last) > 1000) {	/* every second */
+	    serial_putc ('.');
+	    last = now;
+	}
+    }
+
+    DONE:
+    /* reset to read mode */
+    addr = (volatile unsigned long *)info->start[0];
+    addr[0] = 0xF0F0F0F0;	/* reset bank */
+
+    printf (" done\n");
+    return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+    ulong cp, wp, data;
+    int i, l, rc;
+
+    wp = (addr & ~3);	/* get lower word aligned address */
+
+    /*
+     * handle unaligned start bytes
+     */
+    if ((l = addr - wp) != 0) {
+	data = 0;
+	for (i=0, cp=wp; i<l; ++i, ++cp) {
+	    data = (data << 8) | (*(uchar *)cp);
+	}
+	for (; i<4 && cnt>0; ++i) {
+	    data = (data << 8) | *src++;
+	    --cnt;
+	    ++cp;
+	}
+	for (; cnt==0 && i<4; ++i, ++cp) {
+	    data = (data << 8) | (*(uchar *)cp);
+	}
+
+	if ((rc = write_word(info, wp, data)) != 0) {
+	    return (rc);
+	}
+	wp += 4;
+    }
+
+    /*
+     * handle word aligned part
+     */
+    while (cnt >= 4) {
+	data = 0;
+	for (i=0; i<4; ++i) {
+	    data = (data << 8) | *src++;
+	}
+	if ((rc = write_word(info, wp, data)) != 0) {
+	    return (rc);
+	}
+	wp  += 4;
+	cnt -= 4;
+    }
+
+    if (cnt == 0) {
+	return (0);
+    }
+
+    /*
+     * handle unaligned tail bytes
+     */
+    data = 0;
+    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+	data = (data << 8) | *src++;
+	--cnt;
+    }
+    for (; i<4; ++i, ++cp) {
+	data = (data << 8) | (*(uchar *)cp);
+    }
+
+    return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+    vu_long *addr = (vu_long*)(info->start[0]);
+    ulong start;
+    int flag;
+
+    /* Check if Flash is (sufficiently) erased */
+    if ((*((vu_long *)dest) & data) != data) {
+	return (2);
+    }
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    addr[0x0555] = 0xAAAAAAAA;
+    addr[0x02AA] = 0x55555555;
+    addr[0x0555] = 0xA0A0A0A0;
+
+    *((vu_long *)dest) = data;
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+      enable_interrupts();
+
+    /* data polling for D7 */
+    start = get_timer (0);
+    while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
+	if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+	    return (1);
+	}
+    }
+    return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/mbx8xx/vpd.c b/board/mbx8xx/vpd.c
new file mode 100644
index 0000000..6f88352
--- /dev/null
+++ b/board/mbx8xx/vpd.c
@@ -0,0 +1,196 @@
+/*
+ * (C) Copyright 2000
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Code in faintly related to linux/arch/ppc/8xx_io:
+ * MPC8xx CPM I2C interface. Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
+ *
+ * This file implements functions to read the MBX's Vital Product Data
+ * (VPD). I can't use the more general i2c code in mpc8xx/... since I need
+ * the VPD at a time where there is no RAM available yet. Hence the VPD is
+ * read into a special area in the DPRAM (see config_MBX.h::CFG_DPRAMVPD).
+ *
+ * -----------------------------------------------------------------
+ * 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>
+#ifdef CONFIG_8xx
+#include <commproc.h>
+#endif
+#include "vpd.h"
+
+/* Location of receive/transmit buffer descriptors
+ * Allocate one transmit bd and one receive bd.
+ * IIC_BD_FREE points to free bd space which we'll use as tx buffer.
+ */
+#define IIC_BD_TX1     (BD_IIC_START + 0*sizeof(cbd_t))
+#define IIC_BD_TX2     (BD_IIC_START + 1*sizeof(cbd_t))
+#define IIC_BD_RX      (BD_IIC_START + 2*sizeof(cbd_t))
+#define IIC_BD_FREE    (BD_IIC_START + 3*sizeof(cbd_t))
+
+/* FIXME -- replace 0x2000 with offsetof */
+#define VPD_P ((vpd_t *)(CFG_IMMR + 0x2000 + CFG_DPRAMVPD))
+
+/* transmit/receive buffers */
+#define IIC_RX_LENGTH 128
+
+#define WITH_MICROCODE_PATCH
+
+vpd_packet_t * vpd_find_packet(u_char ident)
+{
+    vpd_packet_t *packet;
+    vpd_t *vpd = VPD_P;
+
+    packet = (vpd_packet_t *)&vpd->packets;
+    while ((packet->identifier != ident) && packet->identifier != 0xFF)
+    {
+	packet = (vpd_packet_t *)((char *)packet + packet->size + 2);
+    }
+    return packet;
+}
+
+void vpd_init(void)
+{
+    volatile immap_t  *im = (immap_t *)CFG_IMMR;
+    volatile cpm8xx_t *cp = &(im->im_cpm);
+    volatile i2c8xx_t *i2c = (i2c8xx_t *)&(im->im_i2c);
+    volatile iic_t *iip;
+#ifdef WITH_MICROCODE_PATCH
+    ulong reloc = 0;
+#endif
+
+    iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+
+    /*
+     * kludge: when running from flash, no microcode patch can be
+     * installed. However, the DPMEM usually contains non-zero
+     * garbage at the relocatable patch base location, so lets clear
+     * it now. This way the rest of the code can support the microcode
+     * patch dynamically.
+     */
+    if ((ulong)vpd_init & 0xff000000)
+      iip->iic_rpbase = 0;
+
+#ifdef WITH_MICROCODE_PATCH
+    /* Check for and use a microcode relocation patch. */
+    if ((reloc = iip->iic_rpbase))
+      iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
+#endif
+    /* Initialize Port B IIC pins */
+    cp->cp_pbpar |= 0x00000030;
+    cp->cp_pbdir |= 0x00000030;
+    cp->cp_pbodr |= 0x00000030;
+
+    i2c->i2c_i2mod = 0x04;  /* filter clock */
+    i2c->i2c_i2add = 0x34;	/* select an arbitrary (unique) address */
+    i2c->i2c_i2brg = 0x07;  /* make clock run maximum slow	*/
+    i2c->i2c_i2cmr = 0x00;  /* disable interrupts */
+    i2c->i2c_i2cer = 0x1f;  /* clear events */
+    i2c->i2c_i2com = 0x01;  /* configure i2c to work as master */
+
+    if (vpd_read(0xa4, (uchar*)VPD_P, VPD_EEPROM_SIZE, 0) != VPD_EEPROM_SIZE)
+    {
+	hang();
+    }
+}
+
+
+/* Read from I2C.
+ * This is a two step process.  First, we send the "dummy" write
+ * to set the device offset for the read.  Second, we perform
+ * the read operation.
+ */
+int vpd_read(uint iic_device, uchar *buf, int count, int offset)
+{
+    volatile immap_t  *im = (immap_t *)CFG_IMMR;
+    volatile cpm8xx_t *cp = &(im->im_cpm);
+    volatile i2c8xx_t *i2c = (i2c8xx_t *)&(im->im_i2c);
+    volatile iic_t *iip;
+    volatile cbd_t *tbdf1, *tbdf2, *rbdf;
+    uchar *tb;
+    uchar event;
+#ifdef WITH_MICROCODE_PATCH
+    ulong reloc = 0;
+#endif
+
+    iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+#ifdef WITH_MICROCODE_PATCH
+    /* Check for and use a microcode relocation patch. */
+    if ((reloc = iip->iic_rpbase))
+      iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
+#endif
+    tbdf1 = (cbd_t *)&cp->cp_dpmem[IIC_BD_TX1];
+    tbdf2 = (cbd_t *)&cp->cp_dpmem[IIC_BD_TX2];
+    rbdf  = (cbd_t *)&cp->cp_dpmem[IIC_BD_RX];
+
+    /* Send a "dummy write" operation.  This is a write request with
+     * only the offset sent, followed by another start condition.
+     * This will ensure we start reading from the first location
+     * of the EEPROM.
+     */
+    tb = (uchar*)&cp->cp_dpmem[IIC_BD_FREE];
+    tb[0] = iic_device & 0xfe;	/* device address */
+    tb[1] = offset;	        /* offset */
+    tbdf1->cbd_bufaddr = (uint)tb;
+    tbdf1->cbd_datlen = 2;
+    tbdf1->cbd_sc = 0x8400;
+
+    tb += 2;
+    tb[0] = iic_device | 1;	/* device address */
+    tbdf2->cbd_bufaddr = (uint)tb;
+    tbdf2->cbd_datlen = count+1;
+    tbdf2->cbd_sc = 0xbc00;
+
+    rbdf->cbd_bufaddr = (uint)buf;
+    rbdf->cbd_datlen = 0;
+    rbdf->cbd_sc = 0xb000;
+
+    iip->iic_tbase = IIC_BD_TX1;
+    iip->iic_tbptr = IIC_BD_TX1;
+    iip->iic_rbase = IIC_BD_RX;
+    iip->iic_rbptr = IIC_BD_RX;
+    iip->iic_rfcr = 0x15;
+    iip->iic_tfcr = 0x15;
+    iip->iic_mrblr = count;
+    iip->iic_rstate = 0;
+    iip->iic_tstate = 0;
+
+    i2c->i2c_i2cer = 0x1f;  /* clear event mask */
+    i2c->i2c_i2mod |= 1;    /* enable iic operation */
+    i2c->i2c_i2com |= 0x80;	/* start master */
+
+    /* wait for IIC transfer */
+    do {
+	__asm__ volatile ("eieio");
+	event = i2c->i2c_i2cer;
+    } while (event == 0);
+
+    if ((event & 0x10) || (event & 0x04)) {
+	count = -1;
+	goto bailout;
+    }
+
+bailout:
+    i2c->i2c_i2mod &= ~1;   /* turn off iic operation */
+    i2c->i2c_i2cer = 0x1f;  /* clear event mask */
+
+    return count;
+}
diff --git a/board/mousse/flash.h b/board/mousse/flash.h
new file mode 100644
index 0000000..b7e4619
--- /dev/null
+++ b/board/mousse/flash.h
@@ -0,0 +1,78 @@
+#ifndef	FLASH_LIB_H
+#define	FLASH_LIB_H
+
+#include <common.h>
+
+/* PIO operations max */
+#define	FLASH_PROGRAM_POLLS		100000
+
+/* 10 Seconds default */
+#define	FLASH_ERASE_SECTOR_TIMEOUT	(10*1000 /*SEC*/ )
+
+/* Flash device info structure */
+typedef struct flash_dev_s {
+    char        name[24];               /* Bank Name */
+    int		bank;			/* Bank 0 or 1 */
+    unsigned int base;			/* Base address */
+    int		sectors;		/* Sector count */
+    int		lgSectorSize;		/* Log2(usable bytes/sector) */
+    int		vendorID;		/* Expected vendor ID */
+    int		deviceID;		/* Expected device ID */
+    int		found;			/* Set if found by flashLibInit */
+    int		swap;			/* Set for bank 1 if byte swap req'd */
+} flash_dev_t;
+
+#define FLASH_MAX_POS(dev) \
+	((dev)->sectors << (dev)->lgSectorSize)
+
+#define FLASH_SECTOR_POS(dev, sector) \
+	((sector) << (dev)->lgSectorSize)
+
+/* AMD 29F040 */
+#define FLASH0_BANK			0
+#define FLASH0_VENDOR_ID		0x01
+#define FLASH0_DEVICE_ID		0x49
+
+/* AMD29LV160DB */
+#define FLASH1_BANK			1
+#define FLASH1_VENDOR_ID		0x0001
+#define FLASH1_DEVICE_ID		0x2249
+
+extern	flash_dev_t			flashDev[];
+extern	int				flashDevCount;
+
+/*
+ * Device pointers
+ *
+ * These must be kept in sync with the table in flashLib.c.
+ */
+#define FLASH_DEV_BANK0_SA0		(&flashDev[0])
+#define FLASH_DEV_BANK0_SA1		(&flashDev[1])
+#define FLASH_DEV_BANK0_SA2		(&flashDev[2])
+#define FLASH_DEV_BANK0_LOW		(&flashDev[3]) /* 960K */
+#define FLASH_DEV_BANK0_BOOT		(&flashDev[4]) /* PLCC */
+#define FLASH_DEV_BANK0_HIGH		(&flashDev[5]) /* 512K PLCC shadow */
+
+unsigned long flash_init(void);
+int flashEraseSector(flash_dev_t *dev, int sector);
+int flashErase(flash_dev_t *dev);
+int flashRead(flash_dev_t *dev, int pos, char *buf, int len);
+int flashWrite(flash_dev_t *dev, int pos, char *buf, int len);
+int flashWritable(flash_dev_t *dev, int pos, int len);
+int flashDiag(flash_dev_t *dev);
+int flashDiagAll(void);
+
+ulong flash_get_size (vu_long *addr, flash_info_t *info);
+void flash_print_info  (flash_info_t *info);
+int  flash_erase (flash_info_t *info, int s_first, int s_last);
+int  write_buff  (flash_info_t *info, uchar *src, ulong addr, ulong cnt);
+
+/*
+ * Flash info indices.
+ */
+#define FLASH_BANK_KERNEL 0
+#define FLASH_BANK_BOOT   1
+#define FLASH_BANK_AUX    2
+#define FIRST_SECTOR      0
+
+#endif	/* !FLASH_LIB_H */
diff --git a/board/mpc8260ads/flash.c b/board/mpc8260ads/flash.c
new file mode 100644
index 0000000..ec6a3b3
--- /dev/null
+++ b/board/mpc8260ads/flash.c
@@ -0,0 +1,508 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2001, Stuart Hughes, Lineo Inc, stuarth@lineo.com
+ * Add support the Sharp chips on the mpc8260ads.
+ * I started with board/ip860/flash.c and made changes I found in
+ * the MTD project by David Schleef.
+ *
+ * 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>
+
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static int clear_block_lock_bit(vu_long * addr);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+#ifndef CONFIG_MPC8260ADS
+	volatile immap_t	*immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t	*memctl = &immap->im_memctl;
+	volatile ip860_bcsr_t	*bcsr   = (ip860_bcsr_t *)BCSR_BASE;
+#endif
+	unsigned long size;
+	int i;
+
+	/* Init: enable write,
+	 * or we cannot even write flash commands
+	 */
+#ifndef CONFIG_MPC8260ADS
+	bcsr->bd_ctrl |= BD_CTRL_FLWE;
+#endif
+
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+
+		/* set the default sector offset */
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size = flash_get_size((vu_long *)FLASH_BASE, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size, size<<20);
+	}
+#ifndef CONFIG_MPC8260ADS
+	/* Remap FLASH according to real size */
+	memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size & 0xFFFF8000);
+	memctl->memc_br1 = (CFG_FLASH_BASE & BR_BA_MSK) |
+				(memctl->memc_br1 & ~(BR_BA_MSK));
+#endif
+
+	/* Re-do sizing to get full correct info */
+	size = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_info[0].size = size;
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+	/* ENV protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+		      &flash_info[0]);
+#endif
+	return (size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_INTEL:	printf ("Intel ");		break;
+	case FLASH_MAN_SHARP:   printf ("Sharp ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_28F016SV:	printf ("28F016SV (16 Mbit, 32 x 64k)\n");
+				break;
+	case FLASH_28F160S3:	printf ("28F160S3 (16 Mbit, 32 x 512K)\n");
+				break;
+	case FLASH_28F320S3:	printf ("28F320S3 (32 Mbit, 64 x 512K)\n");
+				break;
+	case FLASH_LH28F016SCT: printf ("28F016SC (16 Mbit, 32 x 64K)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	ulong value;
+	ulong base = (ulong)addr;
+	ulong sector_offset;
+
+	/* Write "Intelligent Identifier" command: read Manufacturer ID */
+	*addr = 0x90909090;
+
+	value = addr[0] & 0x00FF00FF;
+	switch (value) {
+	case MT_MANUFACT:	/* SHARP, MT or => Intel */
+	case INTEL_ALT_MANU:
+		info->flash_id = FLASH_MAN_INTEL;
+		break;
+	default:
+		printf("unknown manufacturer: %x\n", (unsigned int)value);
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	switch (value) {
+	case (INTEL_ID_28F016S):
+		info->flash_id += FLASH_28F016SV;
+		info->sector_count = 32;
+		info->size = 0x00400000;
+		sector_offset = 0x20000;
+		break;				/* => 2x2 MB		*/
+
+	case (INTEL_ID_28F160S3):
+		info->flash_id += FLASH_28F160S3;
+		info->sector_count = 32;
+		info->size = 0x00400000;
+		sector_offset = 0x20000;
+		break;				/* => 2x2 MB		*/
+
+	case (INTEL_ID_28F320S3):
+		info->flash_id += FLASH_28F320S3;
+		info->sector_count = 64;
+		info->size = 0x00800000;
+		sector_offset = 0x20000;
+		break;				/* => 2x4 MB		*/
+
+	case SHARP_ID_28F016SCL:
+	case SHARP_ID_28F016SCZ:
+		info->flash_id      = FLASH_MAN_SHARP | FLASH_LH28F016SCT;
+		info->sector_count  = 32;
+		info->size          = 0x00800000;
+		sector_offset = 0x40000;
+		break;				/* => 4x2 MB		*/
+
+
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	/* set up sector start address table */
+	for (i = 0; i < info->sector_count; i++) {
+		info->start[i] = base;
+		base += sector_offset;
+		/* don't know how to check sector protection */
+		info->protect[i] = 0;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (vu_long *)info->start[0];
+
+		*addr = 0xFFFFFF;	/* reset bank to read array mode */
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	int flag, prot, sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if (    ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL)
+	     && ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_SHARP) ) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	/* Make Sure Block Lock Bit is not set. */
+	if(clear_block_lock_bit((vu_long *)(info->start[s_first]))){
+		return 1;
+	}
+
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			vu_long *addr = (vu_long *)(info->start[sect]);
+
+			last = start = get_timer (0);
+
+			/* Disable interrupts which might cause a timeout here */
+			flag = disable_interrupts();
+
+			/* Reset Array */
+			*addr = 0xffffffff;
+			/* Clear Status Register */
+			*addr = 0x50505050;
+			/* Single Block Erase Command */
+			*addr = 0x20202020;
+			/* Confirm */
+			*addr = 0xD0D0D0D0;
+
+			if((info->flash_id & FLASH_TYPEMASK) != FLASH_LH28F016SCT) {
+			    /* Resume Command, as per errata update */
+			    *addr = 0xD0D0D0D0;
+			}
+
+			/* re-enable interrupts if necessary */
+			if (flag)
+				enable_interrupts();
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+			while ((*addr & 0x80808080) != 0x80808080) {
+				if(*addr & 0x20202020){
+					printf("Error in Block Erase - Lock Bit may be set!\n");
+					printf("Status Register = 0x%X\n", (uint)*addr);
+					*addr = 0xFFFFFFFF;	/* reset bank */
+					return 1;
+				}
+				if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout\n");
+					*addr = 0xFFFFFFFF;	/* reset bank */
+					return 1;
+				}
+				/* show that we're waiting */
+				if ((now - last) > 1000) {	/* every second */
+					putc ('.');
+					last = now;
+				}
+			}
+
+			/* reset to read mode */
+			*addr = 0xFFFFFFFF;
+		}
+	}
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long *)dest;
+	ulong start, csr;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*addr & data) != data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	/* Write Command */
+	*addr = 0x10101010;
+
+	/* Write Data */
+	*addr = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	flag  = 0;
+	while (((csr = *addr) & 0x80808080) != 0x80808080) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			flag = 1;
+			break;
+		}
+	}
+	if (csr & 0x40404040) {
+		printf ("CSR indicates write error (%08lx) at %08lx\n", csr, (ulong)addr);
+		flag = 1;
+	}
+
+	/* Clear Status Registers Command */
+	*addr = 0x50505050;
+	/* Reset to read array mode */
+	*addr = 0xFFFFFFFF;
+
+	return (flag);
+}
+
+/*-----------------------------------------------------------------------
+ * Clear Block Lock Bit, returns:
+ * 0 - OK
+ * 1 - Timeout
+ */
+
+static int clear_block_lock_bit(vu_long  * addr)
+{
+	ulong start, now;
+
+	/* Reset Array */
+	*addr = 0xffffffff;
+	/* Clear Status Register */
+	*addr = 0x50505050;
+
+	*addr = 0x60606060;
+	*addr = 0xd0d0d0d0;
+
+	start = get_timer (0);
+	while(*addr != 0x80808080){
+		if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout on clearing Block Lock Bit\n");
+			*addr = 0xFFFFFFFF;	/* reset bank */
+			return 1;
+		}
+	}
+	return 0;
+}
diff --git a/board/mpl/common/flash.c b/board/mpl/common/flash.c
new file mode 100644
index 0000000..f0c541b
--- /dev/null
+++ b/board/mpl/common/flash.c
@@ -0,0 +1,860 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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
+ */
+
+/*
+ * Modified 4/5/2001
+ * Wait for completion of each sector erase command issued
+ * 4/5/2001
+ * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
+ */
+
+/*
+ * Modified 3/7/2001
+ * - adopted for pip405, Denis Peter, MPL AG Switzerland
+ * TODO:
+ * clean-up
+ */
+
+#include <common.h>
+#include <ppc4xx.h>
+#include <asm/processor.h>
+#ifdef CONFIG_PIP405
+#include "../pip405/pip405.h"
+#endif
+#ifdef CONFIG_MIP405
+#include "../mip405/mip405.h"
+#endif
+#include "common_util.h"
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt);
+
+
+#ifdef CONFIG_ADCIOP
+#define ADDR0           0x0aa9
+#define ADDR1           0x0556
+#define FLASH_WORD_SIZE unsigned char
+#endif
+
+#ifdef CONFIG_CPCI405
+#define ADDR0           0x5555
+#define ADDR1           0x2aaa
+#define FLASH_WORD_SIZE unsigned short
+#endif
+
+#ifdef CONFIG_PIP405
+#define ADDR0           0x5555
+#define ADDR1           0x2aaa
+#define FLASH_WORD_SIZE unsigned short
+#endif
+
+#ifdef CONFIG_MIP405
+#define ADDR0           0x5555
+#define ADDR1           0x2aaa
+#define FLASH_WORD_SIZE unsigned short
+#endif
+
+#define FALSE           0
+#define TRUE            1
+
+/*-----------------------------------------------------------------------
+ */
+
+
+unsigned long flash_init (void)
+{
+	unsigned long size_b0, size_b1;
+	int i;
+  unsigned long pbcr;
+  unsigned long base_b0, base_b1;
+  unsigned char rc;
+
+  rc=switch_cs(FALSE); /* map Flash High */
+
+	if(rc)
+		printf("(MPS Boot) ");
+	else
+		printf("(Flash Boot) ");
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+	/* Only one bank */
+	if (CFG_MAX_FLASH_BANKS == 1)
+	  {
+	    /* Setup offsets */
+			/*  flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]); */
+	    /* Monitor protection ON by default */
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	 	    flash_protect(FLAG_PROTECT_SET,
+				CFG_MONITOR_BASE,
+				CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+				&flash_info[0]);
+#endif
+	    size_b1 = 0 ;
+	    flash_info[0].size = size_b0;
+	  }
+
+	/* 2 banks */
+	else
+	  {
+	    size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+
+	    /* Re-do sizing to get full correct info */
+
+	    if (size_b1)
+	      {
+		mtdcr(ebccfga, pb0cr);
+		pbcr = mfdcr(ebccfgd);
+		mtdcr(ebccfga, pb0cr);
+		base_b1 = -size_b1;
+		pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17);
+		mtdcr(ebccfgd, pbcr);
+		/*          printf("pb1cr = %x\n", pbcr); */
+	      }
+
+	    if (size_b0)
+	      {
+		mtdcr(ebccfga, pb1cr);
+		pbcr = mfdcr(ebccfgd);
+		mtdcr(ebccfga, pb1cr);
+		base_b0 = base_b1 - size_b0;
+		pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17);
+		mtdcr(ebccfgd, pbcr);
+		/*            printf("pb0cr = %x\n", pbcr); */
+	      }
+
+	    size_b0 = flash_get_size((vu_long *)base_b0, &flash_info[0]);
+
+	    flash_get_offsets (base_b0, &flash_info[0]);
+
+	    /* monitor protection ON by default */
+	    (void)flash_protect(FLAG_PROTECT_SET,
+				base_b0+size_b0-CFG_MONITOR_LEN,
+				base_b0+size_b0-1,
+				&flash_info[0]);
+
+	    if (size_b1) {
+	      /* Re-do sizing to get full correct info */
+	      size_b1 = flash_get_size((vu_long *)base_b1, &flash_info[1]);
+
+	      flash_get_offsets (base_b1, &flash_info[1]);
+
+	      /* monitor protection ON by default */
+	      (void)flash_protect(FLAG_PROTECT_SET,
+				  base_b1+size_b1-CFG_MONITOR_LEN,
+				  base_b1+size_b1-1,
+				  &flash_info[1]);
+	      /* monitor protection OFF by default (one is enough) */
+	      (void)flash_protect(FLAG_PROTECT_CLEAR,
+				  base_b0+size_b0-CFG_MONITOR_LEN,
+				  base_b0+size_b0-1,
+				  &flash_info[0]);
+	    } else {
+	      flash_info[1].flash_id = FLASH_UNKNOWN;
+	      flash_info[1].sector_count = -1;
+	    }
+
+	    flash_info[0].size = size_b0;
+	    flash_info[1].size = size_b1;
+	  }/* else 2 banks */
+	switch_cs(rc); /* switch mode back */
+	return (size_b0 + size_b1);
+}
+
+
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	return;
+}
+#if 0
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start address table */
+  if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
+	    (info->flash_id  == FLASH_AM040)){
+		for (i = 0; i < info->sector_count; i++)
+			info->start[i] = base + (i * 0x00010000);
+  }
+  else {
+		if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00006000;
+		info->start[3] = base + 0x00008000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00010000) - 0x00030000;
+		}
+	    } else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00004000;
+		info->start[i--] = base + info->size - 0x00006000;
+		info->start[i--] = base + info->size - 0x00008000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00010000;
+		}
+	    }
+	}
+}
+
+#endif
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+    int k;
+   	int size;
+    int erased;
+    volatile unsigned long *flash;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	case FLASH_MAN_SST:	printf ("SST ");		break;
+	case FLASH_MAN_INTEL:	printf ("Intel ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM040:	printf ("AM29F040 (512 Kbit, uniform sector size)\n");
+				break;
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+				break;
+	case FLASH_SST800A:	printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
+				break;
+	case FLASH_SST160A:	printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
+				break;
+	case FLASH_INTEL320T:	printf ("TE28F320C3 (32 Mbit, top sector size)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld KB in %d Sectors\n",
+		info->size >> 10, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+  	/*
+     * Check if whole sector is erased
+     */
+		if (i != (info->sector_count-1))
+    	size = info->start[i+1] - info->start[i];
+		else
+      size = info->start[0] + info->size - info->start[i];
+    erased = 1;
+    flash = (volatile unsigned long *)info->start[i];
+    size = size >> 2;        /* divide by 4 for longword access */
+    for (k=0; k<size; k++)
+    {
+    	if (*flash++ != 0xffffffff)
+			{
+ 				erased = 0;
+				break;
+			}
+ 		}
+		if ((i % 5) == 0)
+			printf ("\n   ");
+#if 0 /* test-only */
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+#else
+		printf (" %08lX%s%s",
+			info->start[i],
+			erased ? " E" : "  ",
+			info->protect[i] ? "RO " : "   "
+#endif
+		);
+	}
+	printf ("\n");
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	FLASH_WORD_SIZE value;
+	ulong base = (ulong)addr;
+	volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
+
+	/* Write auto select command: read Manufacturer ID */
+	addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+	addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+	addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090;
+
+	value = addr2[0];
+	/*	printf("flash_get_size value: %x\n",value); */
+	switch (value) {
+	case (FLASH_WORD_SIZE)AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case (FLASH_WORD_SIZE)FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	case (FLASH_WORD_SIZE)INTEL_MANUFACT:
+		info->flash_id = FLASH_MAN_INTEL;
+		break;
+	case (FLASH_WORD_SIZE)SST_MANUFACT:
+		info->flash_id = FLASH_MAN_SST;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+	value = addr2[1];			/* device ID		*/
+	/*	printf("Device value %x\n",value); */
+	switch (value) {
+	case (FLASH_WORD_SIZE)AMD_ID_F040B:
+	        info->flash_id += FLASH_AM040;
+		info->sector_count = 8;
+		info->size = 0x0080000; /* => 512 ko */
+		break;
+	case (FLASH_WORD_SIZE)AMD_ID_LV400T:
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00080000;
+		break;				/* => 0.5 MB		*/
+
+	case (FLASH_WORD_SIZE)AMD_ID_LV400B:
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00080000;
+		break;				/* => 0.5 MB		*/
+
+	case (FLASH_WORD_SIZE)AMD_ID_LV800T:
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (FLASH_WORD_SIZE)AMD_ID_LV800B:
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case (FLASH_WORD_SIZE)AMD_ID_LV160T:
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case (FLASH_WORD_SIZE)AMD_ID_LV160B:
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+#if 0	/* enable when device IDs are available */
+	case (FLASH_WORD_SIZE)AMD_ID_LV320T:
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case (FLASH_WORD_SIZE)AMD_ID_LV320B:
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+#endif
+	case (FLASH_WORD_SIZE)SST_ID_xF800A:
+		info->flash_id += FLASH_SST800A;
+		info->sector_count = 16;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+	case (FLASH_WORD_SIZE)INTEL_ID_28F320C3T:
+		info->flash_id += FLASH_INTEL320T;
+		info->sector_count = 71;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+
+	case (FLASH_WORD_SIZE)SST_ID_xF160A:
+		info->flash_id += FLASH_SST160A;
+		info->sector_count = 32;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	/* set up sector start address table */
+  if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
+	    (info->flash_id  == FLASH_AM040)){
+		for (i = 0; i < info->sector_count; i++)
+			info->start[i] = base + (i * 0x00010000);
+  } else {
+		if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00004000;
+		info->start[2] = base + 0x00006000;
+		info->start[3] = base + 0x00008000;
+		for (i = 4; i < info->sector_count; i++)
+			info->start[i] = base + (i * 0x00010000) - 0x00030000;
+	  }
+	  else {
+			/* set sector offsets for top boot block type		*/
+			i = info->sector_count - 1;
+			if(info->sector_count==71) {
+
+				info->start[i--] = base + info->size - 0x00002000;
+				info->start[i--] = base + info->size - 0x00004000;
+				info->start[i--] = base + info->size - 0x00006000;
+				info->start[i--] = base + info->size - 0x00008000;
+				info->start[i--] = base + info->size - 0x0000A000;
+				info->start[i--] = base + info->size - 0x0000C000;
+				info->start[i--] = base + info->size - 0x0000E000;
+				for (; i >= 0; i--)
+					info->start[i] = base + i * 0x000010000;
+			}
+			else {
+				info->start[i--] = base + info->size - 0x00004000;
+				info->start[i--] = base + info->size - 0x00006000;
+				info->start[i--] = base + info->size - 0x00008000;
+				for (; i >= 0; i--)
+					info->start[i] = base + i * 0x00010000;
+			}
+		}
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
+    	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
+      	info->protect[i] = 0;
+      else
+        info->protect[i] = addr2[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+#if 0 /* test-only */
+#ifdef CONFIG_ADCIOP
+		addr2 = (volatile unsigned char *)info->start[0];
+                addr2[ADDR0] = 0xAA;
+                addr2[ADDR1] = 0x55;
+                addr2[ADDR0] = 0xF0;  /* reset bank */
+#else
+		addr2 = (FLASH_WORD_SIZE *)info->start[0];
+		*addr2 = (FLASH_WORD_SIZE)0x00F000F0;	/* reset bank */
+#endif
+#else /* test-only */
+		addr2 = (FLASH_WORD_SIZE *)info->start[0];
+		*addr2 = (FLASH_WORD_SIZE)0x00F000F0;	/* reset bank */
+#endif /* test-only */
+	}
+	return (info->size);
+}
+
+int wait_for_DQ7(flash_info_t *info, int sect)
+{
+	ulong start, now, last;
+	volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
+
+	start = get_timer (0);
+    last  = start;
+    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
+        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+            printf ("Timeout\n");
+            return -1;
+        }
+        /* show that we're waiting */
+        if ((now - last) > 1000) {  /* every second */
+	    			putc ('.');
+            last = now;
+        }
+    }
+	return 0;
+}
+
+int intel_wait_for_DQ7(flash_info_t *info, int sect)
+{
+	ulong start, now, last;
+	volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
+
+		start = get_timer (0);
+    last  = start;
+    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
+        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+            printf ("Timeout\n");
+            return -1;
+        }
+        /* show that we're waiting */
+        if ((now - last) > 1000) {  /* every second */
+	    			putc ('.');
+            last = now;
+        }
+    }
+    addr[0]=(FLASH_WORD_SIZE)0x00500050;
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
+	volatile FLASH_WORD_SIZE *addr2;
+	int flag, prot, sect, l_sect;
+	int i;
+
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("Can't erase unknown flash type - aborted\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr2 = (FLASH_WORD_SIZE *)(info->start[sect]);
+			/*  printf("Erasing sector %p\n", addr2); */ /* CLH */
+	    if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
+				addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+				addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+				addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
+				addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+				addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+				addr2[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
+				for (i=0; i<50; i++)
+					udelay(1000);  /* wait 1 ms */
+		    wait_for_DQ7(info, sect);
+		  }
+		  else {
+		  	if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
+					addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector */
+					addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */
+			    intel_wait_for_DQ7(info, sect);
+					addr2[0] = (FLASH_WORD_SIZE)0x00200020;  /* sector erase */
+					addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */
+			    intel_wait_for_DQ7(info, sect);
+				}
+				else {
+					addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+					addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+					addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
+					addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+					addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+					addr2[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
+			    wait_for_DQ7(info, sect);
+		 		}
+		 }
+		 l_sect = sect;
+		    /*
+		     * Wait for each sector to complete, it's more
+		     * reliable.  According to AMD Spec, you must
+		     * issue all erase commands within a specified
+		     * timeout.  This has been seen to fail, especially
+		     * if printf()s are included (for debug)!!
+		     */
+		 /*   wait_for_DQ7(info, sect); */
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+#if 0
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+	wait_for_DQ7(info, l_sect);
+
+DONE:
+#endif
+	/* reset to read mode */
+	addr = (FLASH_WORD_SIZE *)info->start[0];
+	addr[0] = (FLASH_WORD_SIZE)0x00F000F0;	/* reset bank */
+
+	printf (" done\n");
+	return 0;
+}
+
+void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt)
+{
+	int i;
+	volatile FLASH_WORD_SIZE *addr2;
+	long c;
+	c= (long)cnt;
+	for(i=info->sector_count-1;i>0;i--)
+	{
+		if(addr>=info->start[i])
+			break;
+	}
+	do {
+		addr2 = (FLASH_WORD_SIZE *)(info->start[i]);
+		addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector setup */
+		addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* unlock sector */
+		intel_wait_for_DQ7(info, i);
+		i++;
+		c-=(info->start[i]-info->start[i-1]);
+	}while(c>0);
+
+
+}
+
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
+		unlock_intel_sectors(info,addr,cnt);
+	}
+	wp = (addr & ~3);	/* get lower word aligned address */
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		if((wp % 0x10000)==0)
+			printf("."); /* show Progress */
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+	rc=write_word(info, wp, data);
+	return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static FLASH_WORD_SIZE *read_val = (FLASH_WORD_SIZE *)0x200000;
+
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]);
+	volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest;
+ 	volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
+	ulong start;
+	int flag;
+	int i;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((volatile FLASH_WORD_SIZE *)dest) &
+		(FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+	for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
+	{
+		if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
+			/* intel style writting */
+			dest2[i] = (FLASH_WORD_SIZE)0x00500050;
+			dest2[i] = (FLASH_WORD_SIZE)0x00400040;
+			*read_val++ = data2[i];
+			dest2[i] = data2[i];
+			if (flag)
+				enable_interrupts();
+			/* data polling for D7 */
+			start = get_timer (0);
+			udelay(10);
+			while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080)
+			{
+				if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
+					return (1);
+			}
+			dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
+			udelay(10);
+			dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
+			if(dest2[i]!=data2[i])
+				printf("Error at %p 0x%04X != 0x%04X\n",&dest2[i],dest2[i],data2[i]);
+		}
+		else {
+			addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+			addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+			addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0;
+			dest2[i] = data2[i];
+			/* re-enable interrupts if necessary */
+			if (flag)
+				enable_interrupts();
+			/* data polling for D7 */
+			start = get_timer (0);
+			while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) !=
+				(data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
+				if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+        				return (1);
+				}
+			}
+		}
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/mpl/common/isa.c b/board/mpl/common/isa.c
new file mode 100644
index 0000000..40731fc
--- /dev/null
+++ b/board/mpl/common/isa.c
@@ -0,0 +1,469 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ *
+ * TODO: clean-up
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <devices.h>
+#include "isa.h"
+#include "piix4_pci.h"
+#include "kbd.h"
+#include "video.h"
+
+extern int drv_isa_kbd_init (void);
+
+#undef	ISA_DEBUG
+
+#ifdef	ISA_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#ifndef	TRUE
+#define TRUE            1
+#endif
+#ifndef FALSE
+#define FALSE           0
+#endif
+
+
+
+/* fdc (logical device 0) */
+const SIO_LOGDEV_TABLE sio_fdc[] = {
+	{0x60, 3},			/* set IO to FDPort (3F0) */
+	{0x61, 0xF0},		/* set IO to FDPort (3F0) */
+	{0x70, 06},			/* set IRQ 6 for FDPort */
+	{0x74, 02},			/* set DMA 2 for FDPort */
+	{0xF0, 0x05},		/* set to PS2 type */
+	{0xF1, 0x00},	  /* default value */
+	{0x30, 1},			/* and activate the device */
+	{0xFF, 0}				/* end of device table */
+};
+/* paralell port (logical device 3) */
+const SIO_LOGDEV_TABLE sio_pport[] = {
+	{0x60, 3},			/* set IO to PPort (378) */
+	{0x61, 0x78},		/* set IO to PPort (378) */
+	{0x70, 07},			/* set IRQ 7 for PPort */
+	{0xF1, 00},			/* set PPort to normal */
+	{0x30, 1},			/* and activate the device */
+	{0xFF, 0}				/* end of device table */
+};
+/* paralell port (logical device 3) Floppy assigned to lpt */
+const SIO_LOGDEV_TABLE sio_pport_fdc[] = {
+	{0x60, 3},			/* set IO to PPort (378) */
+	{0x61, 0x78},		/* set IO to PPort (378) */
+	{0x70, 07},			/* set IRQ 7 for PPort */
+	{0xF1, 02},			/* set PPort to Floppy */
+	{0x30, 1},			/* and activate the device */
+	{0xFF, 0}				/* end of device table */
+};
+/* uart 1 (logical device 4) */
+const SIO_LOGDEV_TABLE sio_com1[] = {
+	{0x60, 3},			/* set IO to COM1 (3F8) */
+	{0x61, 0xF8},		/* set IO to COM1 (3F8) */
+	{0x70, 04},			/* set IRQ 4 for COM1 */
+	{0x30, 1},			/* and activate the device */
+	{0xFF, 0}				/* end of device table */
+};
+/* uart 2 (logical device 5) */
+const SIO_LOGDEV_TABLE sio_com2[] = {
+	{0x60, 2},			/* set IO to COM2 (2F8) */
+	{0x61, 0xF8},		/* set IO to COM2 (2F8) */
+	{0x70, 03},			/* set IRQ 3 for COM2 */
+	{0x30, 1},			/* and activate the device */
+	{0xFF, 0}				/* end of device table */
+};
+
+/* keyboard controller (logical device 7) */
+const SIO_LOGDEV_TABLE sio_keyboard[] = {
+	{0x70, 1},			/* set IRQ 1 for keyboard */
+	{0x72, 12},			/* set IRQ 12 for mouse */
+	{0xF0, 0},			/* disable Port92 (this is a PowerPC!!) */
+	{0x30, 1},			/* and activate the device */
+	{0xFF, 0}				/* end of device table */
+};
+
+
+/*******************************************************************************
+* Config SuperIO FDC37C672
+********************************************************************************/
+unsigned char open_cfg_super_IO(int address)
+{
+	out8(CFG_ISA_IO_BASE_ADDRESS | address,0x55); /* open config */
+	out8(CFG_ISA_IO_BASE_ADDRESS | address,0x20); /* set address to DEV ID */
+	if(in8(CFG_ISA_IO_BASE_ADDRESS | address | 0x1)==0x40) /* ok Device ID is correct */
+		return TRUE;
+	else
+		return FALSE;
+}
+
+void close_cfg_super_IO(int address)
+{
+	out8(CFG_ISA_IO_BASE_ADDRESS | address,0xAA); /* close config */
+}
+
+
+unsigned char read_cfg_super_IO(int address, unsigned char function, unsigned char regaddr)
+{
+	/* assuming config reg is open */
+	out8(CFG_ISA_IO_BASE_ADDRESS | address,0x7); /* points to the function reg */
+	out8(CFG_ISA_IO_BASE_ADDRESS | address | 1,function); /* set the function no */
+	out8(CFG_ISA_IO_BASE_ADDRESS | address,regaddr); /* sets the address in the function */
+	return in8(CFG_ISA_IO_BASE_ADDRESS | address | 1);
+}
+
+void write_cfg_super_IO(int address, unsigned char function, unsigned char regaddr, unsigned char data)
+{
+	/* assuming config reg is open */
+	out8(CFG_ISA_IO_BASE_ADDRESS | address,0x7); /* points to the function reg */
+	out8(CFG_ISA_IO_BASE_ADDRESS | address | 1,function); /* set the function no */
+	out8(CFG_ISA_IO_BASE_ADDRESS | address,regaddr); /* sets the address in the function */
+	out8(CFG_ISA_IO_BASE_ADDRESS | address | 1,data); /* writes the data */
+}
+
+void isa_write_table(SIO_LOGDEV_TABLE *ldt,unsigned char ldev)
+{
+	while (ldt->index != 0xFF) {
+		write_cfg_super_IO(SIO_CFG_PORT, ldev, ldt->index, ldt->val);
+		ldt++;
+	} /* endwhile */
+}
+
+void isa_sio_loadtable(void)
+{
+	unsigned char *s = getenv("floppy");
+	/* setup Floppy device 0*/
+	isa_write_table((SIO_LOGDEV_TABLE *)&sio_fdc,0);
+	/* setup parallel port device 3 */
+	if(s && !strncmp(s, "lpt", 3)) {
+		printf("SIO:   Floppy assigned to LPT\n");
+		/* floppy is assigned to the LPT */
+		isa_write_table((SIO_LOGDEV_TABLE *)&sio_pport_fdc,3);
+	}
+	else {
+		/*printf("Floppy assigned to internal port\n");*/
+		isa_write_table((SIO_LOGDEV_TABLE *)&sio_pport,3);
+	}
+	/* setup Com1 port device 4 */
+	isa_write_table((SIO_LOGDEV_TABLE *)&sio_com1,4);
+	/* setup Com2 port device 5 */
+	isa_write_table((SIO_LOGDEV_TABLE *)&sio_com2,5);
+	/* setup keyboards device 7 */
+	isa_write_table((SIO_LOGDEV_TABLE *)&sio_keyboard,7);
+}
+
+
+void isa_sio_setup(void)
+{
+	if(open_cfg_super_IO(SIO_CFG_PORT)==TRUE)
+	{
+		isa_sio_loadtable();
+		close_cfg_super_IO(0x3F0);
+	}
+}
+
+
+
+/******************************************************************************
+ * IRQ Controller
+ * we use the Vector mode
+ */
+
+struct	isa_irq_action {
+	 interrupt_handler_t *handler;
+	 void *arg;
+	 int count;
+};
+
+static struct isa_irq_action isa_irqs[16];
+
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define cached_imr1	(unsigned char)cached_irq_mask
+#define cached_imr2	(unsigned char)(cached_irq_mask>>8)
+#define IMR_1		CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_OCW1
+#define IMR_2		CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_OCW1
+#define ICW1_1	CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_ICW1
+#define ICW1_2	CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_ICW1
+#define ICW2_1	CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_ICW2
+#define ICW2_2	CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_ICW2
+#define ICW3_1	ICW2_1
+#define ICW3_2	ICW2_2
+#define ICW4_1	ICW2_1
+#define ICW4_2	ICW2_2
+#define ISR_1		ICW1_1
+#define ISR_2		ICW1_2
+
+
+void disable_8259A_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << irq;
+
+	cached_irq_mask |= mask;
+	if (irq & 8)
+		out8(IMR_2,cached_imr2);
+	else
+		out8(IMR_1,cached_imr1);
+}
+
+void enable_8259A_irq(unsigned int irq)
+{
+	unsigned int mask = ~(1 << irq);
+
+	cached_irq_mask &= mask;
+	if (irq & 8)
+		out8(IMR_2,cached_imr2);
+	else
+		out8(IMR_1,cached_imr1);
+}
+/*
+int i8259A_irq_pending(unsigned int irq)
+{
+	unsigned int mask = 1<<irq;
+	int ret;
+
+	if (irq < 8)
+		ret = inb(0x20) & mask;
+	else
+		ret = inb(0xA0) & (mask >> 8);
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+
+	return ret;
+}
+*/
+
+/*
+ * This function assumes to be called rarely. Switching between
+ * 8259A registers is slow.
+ */
+int i8259A_irq_real(unsigned int irq)
+{
+	int value;
+	int irqmask = 1<<irq;
+
+	if (irq < 8) {
+		out8(ISR_1,0x0B);		/* ISR register */
+		value = in8(ISR_1) & irqmask;
+		out8(ISR_1,0x0A);		/* back to the IRR register */
+		return value;
+	}
+	out8(ISR_2,0x0B);		/* ISR register */
+	value = in8(ISR_2) & (irqmask >> 8);
+	out8(ISR_2,0x0A);		/* back to the IRR register */
+	return value;
+}
+
+/*
+ * Careful! The 8259A is a fragile beast, it pretty
+ * much _has_ to be done exactly like this (mask it
+ * first, _then_ send the EOI, and the order of EOI
+ * to the two 8259s is important!
+ */
+void mask_and_ack_8259A(unsigned int irq)
+{
+	unsigned int irqmask = 1 << irq;
+	unsigned int temp_irqmask = cached_irq_mask;
+	/*
+	 * Lightweight spurious IRQ detection. We do not want
+	 * to overdo spurious IRQ handling - it's usually a sign
+	 * of hardware problems, so we only do the checks we can
+	 * do without slowing down good hardware unnecesserily.
+	 *
+	 * Note that IRQ7 and IRQ15 (the two spurious IRQs
+	 * usually resulting from the 8259A-1|2 PICs) occur
+	 * even if the IRQ is masked in the 8259A. Thus we
+	 * can check spurious 8259A IRQs without doing the
+	 * quite slow i8259A_irq_real() call for every IRQ.
+	 * This does not cover 100% of spurious interrupts,
+	 * but should be enough to warn the user that there
+	 * is something bad going on ...
+	 */
+	if (temp_irqmask & irqmask)
+		goto spurious_8259A_irq;
+	temp_irqmask |= irqmask;
+
+handle_real_irq:
+	if (irq & 8) {
+		in8(IMR_2);		/* DUMMY - (do we need this?) */
+		out8(IMR_2,(unsigned char)(temp_irqmask>>8));
+		out8(ISR_2,0x60+(irq&7));/* 'Specific EOI' to slave */
+		out8(ISR_1,0x62);	/* 'Specific EOI' to master-IRQ2 */
+		out8(IMR_2,cached_imr2); /* turn it on again */
+	} else {
+		in8(IMR_1);		/* DUMMY - (do we need this?) */
+		out8(IMR_1,(unsigned char)temp_irqmask);
+		out8(ISR_1,0x60+irq);	/* 'Specific EOI' to master */
+		out8(IMR_1,cached_imr1); /* turn it on again */
+	}
+
+	return;
+
+spurious_8259A_irq:
+	/*
+	 * this is the slow path - should happen rarely.
+	 */
+	if (i8259A_irq_real(irq))
+		/*
+		 * oops, the IRQ _is_ in service according to the
+		 * 8259A - not spurious, go handle it.
+		 */
+		goto handle_real_irq;
+
+	{
+		static int spurious_irq_mask;
+		/*
+		 * At this point we can be sure the IRQ is spurious,
+		 * lets ACK and report it. [once per IRQ]
+		 */
+		if (!(spurious_irq_mask & irqmask)) {
+			PRINTF("spurious 8259A interrupt: IRQ%d.\n", irq);
+			spurious_irq_mask |= irqmask;
+		}
+		/* irq_err_count++; */
+		/*
+		 * Theoretically we do not have to handle this IRQ,
+		 * but in Linux this does not cause problems and is
+		 * simpler for us.
+		 */
+		goto handle_real_irq;
+	}
+}
+
+void init_8259A(void)
+{
+	out8(IMR_1,0xff);	/* mask all of 8259A-1 */
+	out8(IMR_2,0xff);	/* mask all of 8259A-2 */
+
+	out8(ICW1_1,0x11);	/* ICW1: select 8259A-1 init */
+	out8(ICW2_1,0x20 + 0);	/* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
+	out8(ICW3_1,0x04);	/* 8259A-1 (the master) has a slave on IR2 */
+	out8(ICW4_1,0x01);	/* master expects normal EOI */
+	out8(ICW1_2,0x11);	/* ICW2: select 8259A-2 init */
+	out8(ICW2_2,0x20 + 8);	/* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
+	out8(ICW3_2,0x02);	/* 8259A-2 is a slave on master's IR2 */
+	out8(ICW4_2,0x01);	/* (slave's support for AEOI in flat mode
+				    is to be investigated) */
+	udelay(10000);		/* wait for 8259A to initialize */
+	out8(IMR_1,cached_imr1);	/* restore master IRQ mask */
+	udelay(10000);		/* wait for 8259A to initialize */
+	out8(IMR_2,cached_imr2);	/* restore slave IRQ mask */
+}
+
+
+#define PCI_INT_ACK_ADDR 0xEED00000
+
+int handle_isa_int(void)
+{
+	unsigned long irqack;
+	unsigned char isr1,isr2,irq;
+	/* first we acknokledge the int via the PCI bus */
+	irqack=in32(PCI_INT_ACK_ADDR);
+	/* now we get the ISRs */
+	isr2=in8(ISR_2);
+	isr1=in8(ISR_1);
+	irq=(unsigned char)irqack;
+	if((irq==7)&&((isr1&0x80)==0)) {
+		PRINTF("IRQ7 detected but not in ISR\n");
+	}
+	else {
+		/* we should handle cascaded interrupts here also */
+		/* printf("ISA Irq %d\n",irq); */
+		isa_irqs[irq].count++;
+  	if (isa_irqs[irq].handler != NULL)
+  		(*isa_irqs[irq].handler)(isa_irqs[irq].arg);      /* call isr */
+  	else
+  	{
+     	PRINTF ("bogus interrupt vector 0x%x\n", irq);
+  	}
+	}
+	/* issue EOI instruction to clear the IRQ */
+	mask_and_ack_8259A(irq);
+	return 0;
+}
+
+
+
+/******************************************************************
+ * Install and free an ISA interrupt handler.
+ */
+
+void isa_irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+  if (isa_irqs[vec].handler != NULL) {
+   printf ("ISA Interrupt vector %d: handler 0x%x replacing 0x%x\n",
+           vec, (uint)handler, (uint)isa_irqs[vec].handler);
+  }
+  isa_irqs[vec].handler = handler;
+  isa_irqs[vec].arg     = arg;
+  enable_8259A_irq(vec);
+ 	PRINTF ("Install ISA IRQ %d ==> %p, @ %p mask=%04x\n", vec, handler, &isa_irqs[vec].handler,cached_irq_mask);
+
+}
+
+void isa_irq_free_handler(int vec)
+{
+	disable_8259A_irq(vec);
+  isa_irqs[vec].handler = NULL;
+  isa_irqs[vec].arg     = NULL;
+ 	printf ("Free ISA IRQ %d mask=%04x\n", vec, cached_irq_mask);
+
+}
+
+/****************************************************************************/
+void isa_init_irq_contr(void)
+{
+	int i;
+	/* disable all Interrupts */
+	/* first write icws controller 1 */
+	for(i=0;i<16;i++)
+	{
+		isa_irqs[i].handler=NULL;
+		isa_irqs[i].arg=NULL;
+		isa_irqs[i].count=0;
+	}
+	init_8259A();
+	out8(IMR_2,0xFF);
+}
+
+
+/******************************************************************
+ * Init the ISA bus and devices.
+ */
+
+
+int isa_init(void)
+{
+	isa_sio_setup();
+	drv_isa_kbd_init();
+	return 0;
+}
+
+
+
diff --git a/board/mpl/common/kbd.c b/board/mpl/common/kbd.c
new file mode 100644
index 0000000..5b87cdb
--- /dev/null
+++ b/board/mpl/common/kbd.c
@@ -0,0 +1,655 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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
+ *
+ *
+ * Source partly derived from:
+ * linux/drivers/char/pc_keyb.c
+ *
+ *
+ */
+#include <common.h>
+#include <asm/processor.h>
+#include <devices.h>
+#include "isa.h"
+#include "kbd.h"
+
+
+unsigned char kbd_read_status(void);
+unsigned char kbd_read_input(void);
+void kbd_send_data(unsigned char data);
+void disable_8259A_irq(unsigned int irq);
+void enable_8259A_irq(unsigned int irq);
+
+/* used only by send_data - set by keyboard_interrupt */
+
+
+#undef KBG_DEBUG
+
+#ifdef KBG_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#define KBD_STAT_KOBF		0x01
+#define KBD_STAT_IBF		0x02
+#define KBD_STAT_SYS		0x04
+#define KBD_STAT_CD			0x08
+#define KBD_STAT_LOCK		0x10
+#define KBD_STAT_MOBF		0x20
+#define KBD_STAT_TI_OUT	0x40
+#define KBD_STAT_PARERR	0x80
+
+#define KBD_INIT_TIMEOUT 1000		/* Timeout in ms for initializing the keyboard */
+#define KBC_TIMEOUT 250			/* Timeout in ms for sending to keyboard controller */
+#define KBD_TIMEOUT 2000		/* Timeout in ms for keyboard command acknowledge */
+/*
+ *	Keyboard Controller Commands
+ */
+
+#define KBD_CCMD_READ_MODE			0x20	/* Read mode bits */
+#define KBD_CCMD_WRITE_MODE			0x60	/* Write mode bits */
+#define KBD_CCMD_GET_VERSION		0xA1	/* Get controller version */
+#define KBD_CCMD_MOUSE_DISABLE	0xA7	/* Disable mouse interface */
+#define KBD_CCMD_MOUSE_ENABLE		0xA8	/* Enable mouse interface */
+#define KBD_CCMD_TEST_MOUSE			0xA9	/* Mouse interface test */
+#define KBD_CCMD_SELF_TEST			0xAA	/* Controller self test */
+#define KBD_CCMD_KBD_TEST				0xAB	/* Keyboard interface test */
+#define KBD_CCMD_KBD_DISABLE		0xAD	/* Keyboard interface disable */
+#define KBD_CCMD_KBD_ENABLE			0xAE	/* Keyboard interface enable */
+#define KBD_CCMD_WRITE_AUX_OBUF	0xD3    /* Write to output buffer as if
+					   initiated by the auxiliary device */
+#define KBD_CCMD_WRITE_MOUSE		0xD4	/* Write the following byte to the mouse */
+
+/*
+ *	Keyboard Commands
+ */
+
+#define KBD_CMD_SET_LEDS				0xED	/* Set keyboard leds */
+#define KBD_CMD_SET_RATE				0xF3	/* Set typematic rate */
+#define KBD_CMD_ENABLE					0xF4	/* Enable scanning */
+#define KBD_CMD_DISABLE					0xF5	/* Disable scanning */
+#define KBD_CMD_RESET						0xFF	/* Reset */
+
+/*
+ *	Keyboard Replies
+ */
+
+#define KBD_REPLY_POR						0xAA	/* Power on reset */
+#define KBD_REPLY_ACK						0xFA	/* Command ACK */
+#define KBD_REPLY_RESEND				0xFE	/* Command NACK, send the cmd again */
+
+/*
+ *	Status Register Bits
+ */
+
+#define KBD_STAT_OBF 						0x01	/* Keyboard output buffer full */
+#define KBD_STAT_IBF 						0x02	/* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST				0x04	/* Self test successful */
+#define KBD_STAT_CMD						0x08	/* Last write was a command write (0=data) */
+#define KBD_STAT_UNLOCKED				0x10	/* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF			0x20	/* Mouse output buffer full */
+#define KBD_STAT_GTO 						0x40	/* General receive/xmit timeout */
+#define KBD_STAT_PERR 					0x80	/* Parity error */
+
+#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
+
+/*
+ *	Controller Mode Register Bits
+ */
+
+#define KBD_MODE_KBD_INT				0x01	/* Keyboard data generate IRQ1 */
+#define KBD_MODE_MOUSE_INT			0x02	/* Mouse data generate IRQ12 */
+#define KBD_MODE_SYS 						0x04	/* The system flag (?) */
+#define KBD_MODE_NO_KEYLOCK			0x08	/* The keylock doesn't affect the keyboard if set */
+#define KBD_MODE_DISABLE_KBD		0x10	/* Disable keyboard interface */
+#define KBD_MODE_DISABLE_MOUSE	0x20	/* Disable mouse interface */
+#define KBD_MODE_KCC 						0x40	/* Scan code conversion to PC format */
+#define KBD_MODE_RFU						0x80
+
+
+#define KDB_DATA_PORT			0x60
+#define KDB_COMMAND_PORT	0x64
+
+#define 	LED_SCR		0x01	/* scroll lock led */
+#define 	LED_CAP		0x04	/* caps lock led */
+#define 	LED_NUM		0x02	/* num lock led */
+
+#define 	KBD_BUFFER_LEN 0x20  /* size of the keyboardbuffer */
+
+
+
+
+static volatile char kbd_buffer[KBD_BUFFER_LEN];
+static volatile int in_pointer = 0;
+static volatile int out_pointer = 0;
+
+
+static unsigned char num_lock = 0;
+static unsigned char caps_lock = 0;
+static unsigned char scroll_lock = 0;
+static unsigned char shift = 0;
+static unsigned char ctrl = 0;
+static unsigned char alt = 0;
+static unsigned char e0 = 0;
+static unsigned char leds = 0;
+
+#define DEVNAME "kbd"
+
+/* Simple translation table for the keys */
+
+static unsigned char kbd_plain_xlate[] = {
+	0xff,0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b','\t',	/* 0x00 - 0x0f */
+	 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\r',0xff, 'a', 's',	/* 0x10 - 0x1f */
+	 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',0xff,'\\', 'z', 'x', 'c', 'v',	/* 0x20 - 0x2f */
+	 'b', 'n', 'm', ',', '.', '/',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff,	/* 0x30 - 0x3f */
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1',	/* 0x40 - 0x4f */
+	 '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  /* 0x50 - 0x5F */
+	'\r',0xff,0xff
+	};
+
+static unsigned char kbd_shift_xlate[] = {
+	0xff,0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b','\t',	/* 0x00 - 0x0f */
+	 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\r',0xff, 'A', 'S',	/* 0x10 - 0x1f */
+	 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',0xff, '|', 'Z', 'X', 'C', 'V',	/* 0x20 - 0x2f */
+	 'B', 'N', 'M', '<', '>', '?',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff,	/* 0x30 - 0x3f */
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1',	/* 0x40 - 0x4f */
+	 '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  /* 0x50 - 0x5F */
+	'\r',0xff,0xff
+	};
+
+static unsigned char kbd_ctrl_xlate[] = {
+	0xff,0x1b, '1',0x00, '3', '4', '5',0x1E, '7', '8', '9', '0',0x1F, '=','\b','\t',	/* 0x00 - 0x0f */
+	0x11,0x17,0x05,0x12,0x14,0x18,0x15,0x09,0x0f,0x10,0x1b,0x1d,'\n',0xff,0x01,0x13,	/* 0x10 - 0x1f */
+	0x04,0x06,0x08,0x09,0x0a,0x0b,0x0c, ';','\'', '~',0x00,0x1c,0x1a,0x18,0x03,0x16,	/* 0x20 - 0x2f */
+	0x02,0x0e,0x0d, '<', '>', '?',0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff,	/* 0x30 - 0x3f */
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1',	/* 0x40 - 0x4f */
+	 '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  /* 0x50 - 0x5F */
+	'\r',0xff,0xff
+	};
+
+/******************************************************************
+ * Init
+ ******************************************************************/
+int isa_kbd_init(void)
+{
+	char* result;
+	result=kbd_initialize();
+	if(result==NULL) {
+		PRINTF("AT Keyboard initialized\n");
+		irq_install_handler(25, (interrupt_handler_t *)handle_isa_int, NULL);
+		isa_irq_install_handler(KBD_INTERRUPT, (interrupt_handler_t *)kbd_interrupt, NULL);
+		return (1);
+	}
+	else {
+		printf("%s\n",result);
+		return (-1);
+	}
+}
+
+#ifdef CFG_CONSOLE_OVERWRITE_ROUTINE
+extern int overwrite_console (void);
+#else
+int overwrite_console (void)
+{
+	return (0);
+}
+#endif
+
+int drv_isa_kbd_init (void)
+{
+	int error;
+  	device_t kbddev ;
+	char *stdinname  = getenv ("stdin");
+
+	if(isa_kbd_init()==-1)
+		return -1;
+  	memset (&kbddev, 0, sizeof(kbddev));
+  	strcpy(kbddev.name, DEVNAME);
+  	kbddev.flags =  DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+  	kbddev.putc = NULL ;
+	kbddev.puts = NULL ;
+	kbddev.getc = kbd_getc ;
+	kbddev.tstc = kbd_testc ;
+
+ 	error = device_register (&kbddev);
+	if(error==0) {
+		/* check if this is the standard input device */
+		if(strcmp(stdinname,DEVNAME)==0) {
+			/* reassign the console */
+			if(overwrite_console()) {
+				return 1;
+			}
+			error=console_assign(stdin,DEVNAME);
+			if(error==0)
+				return 1;
+			else
+				return error;
+		}
+		return 1;
+	}
+	return error;
+}
+
+/******************************************************************
+ * Queue handling
+ ******************************************************************/
+/* puts character in the queue and sets up the in and out pointer */
+void kbd_put_queue(char data)
+{
+	if((in_pointer+1)==KBD_BUFFER_LEN) {
+		if(out_pointer==0) {
+			return; /* buffer full */
+		} else{
+			in_pointer=0;
+		}
+	} else {
+		if((in_pointer+1)==out_pointer)
+			return; /* buffer full */
+		in_pointer++;
+	}
+	kbd_buffer[in_pointer]=data;
+	return;
+}
+
+/* test if a character is in the queue */
+int kbd_testc(void)
+{
+	if(in_pointer==out_pointer)
+		return(0); /* no data */
+	else
+		return(1);
+}
+/* gets the character from the queue */
+int kbd_getc(void)
+{
+	char c;
+	while(in_pointer==out_pointer);
+	if((out_pointer+1)==KBD_BUFFER_LEN)
+		out_pointer=0;
+	else
+		out_pointer++;
+	c=kbd_buffer[out_pointer];
+	return (int)c;
+
+}
+
+
+/* set LEDs */
+
+void kbd_set_leds(void)
+{
+	if(caps_lock==0)
+		leds&=~LED_CAP; /* switch caps_lock off */
+	else
+		leds|=LED_CAP; /* switch on LED */
+	if(num_lock==0)
+		leds&=~LED_NUM; /* switch LED off */
+	else
+		leds|=LED_NUM;  /* switch on LED */
+	if(scroll_lock==0)
+		leds&=~LED_SCR; /* switch LED off */
+	else
+		leds|=LED_SCR; /* switch on LED */
+	kbd_send_data(KBD_CMD_SET_LEDS);
+	kbd_send_data(leds);
+}
+
+
+void handle_keyboard_event(unsigned char scancode)
+{
+	unsigned char keycode;
+
+	/*  Convert scancode to keycode */
+	PRINTF("scancode %x\n",scancode);
+	if(scancode==0xe0) {
+		e0=1; /* special charakters */
+		return;
+	}
+	if(e0==1) {
+		e0=0; /* delete flag */
+		if(!(	((scancode&0x7F)==0x38)|| /* the right ctrl key */
+					((scancode&0x7F)==0x1D)|| /* the right alt key */
+					((scancode&0x7F)==0x35)||	/* the right '/' key */
+					((scancode&0x7F)==0x1C) ))  /* the right enter key */
+			/* we swallow unknown e0 codes */
+			return;
+	}
+	/* special cntrl keys */
+	switch(scancode)
+	{
+		case 0x2A:
+		case 0x36: /* shift pressed */
+			shift=1;
+			return; /* do nothing else */
+		case 0xAA:
+		case 0xB6: /* shift released */
+			shift=0;
+			return; /* do nothing else */
+		case 0x38: /* alt pressed */
+			alt=1;
+			return; /* do nothing else */
+		case 0xB8: /* alt released */
+			alt=0;
+			return; /* do nothing else */
+		case 0x1d: /* ctrl pressed */
+			ctrl=1;
+			return; /* do nothing else */
+		case 0x9d: /* ctrl released */
+			ctrl=0;
+			return; /* do nothing else */
+		case 0x46: /* scrollock pressed */
+			scroll_lock=~scroll_lock;
+			kbd_set_leds();
+			return; /* do nothing else */
+		case 0x3A: /* capslock pressed */
+			caps_lock=~caps_lock;
+			kbd_set_leds();
+			return;
+		case 0x45: /* numlock pressed */
+			num_lock=~num_lock;
+			kbd_set_leds();
+			return;
+		case 0xC6: /* scroll lock released */
+		case 0xC5: /* num lock released */
+		case 0xBA: /* caps lock released */
+			return; /* just swallow */
+	}
+	if((scancode&0x80)==0x80) /* key released */
+		return;
+	/* now, decide which table we need */
+	if(scancode > (sizeof(kbd_plain_xlate)/sizeof(kbd_plain_xlate[0]))) { /* scancode not in list */
+		PRINTF("unkown scancode %X\n",scancode);
+		return; /* swallow it */
+	}
+	/* setup plain code first */
+	keycode=kbd_plain_xlate[scancode];
+	if(caps_lock==1) { /* caps_lock is pressed, overwrite plain code */
+		if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */
+			PRINTF("unkown caps-locked scancode %X\n",scancode);
+			return; /* swallow it */
+		}
+		keycode=kbd_shift_xlate[scancode];
+		if(keycode<'A') { /* we only want the alphas capital */
+			keycode=kbd_plain_xlate[scancode];
+		}
+	}
+	if(shift==1) { /* shift overwrites caps_lock */
+		if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */
+			PRINTF("unkown shifted scancode %X\n",scancode);
+			return; /* swallow it */
+		}
+		keycode=kbd_shift_xlate[scancode];
+	}
+	if(ctrl==1) { /* ctrl overwrites caps_lock and shift */
+		if(scancode > (sizeof(kbd_ctrl_xlate)/sizeof(kbd_ctrl_xlate[0]))) { /* scancode not in list */
+			PRINTF("unkown ctrl scancode %X\n",scancode);
+			return; /* swallow it */
+		}
+		keycode=kbd_ctrl_xlate[scancode];
+	}
+	/* check if valid keycode */
+	if(keycode==0xff) {
+		PRINTF("unkown scancode %X\n",scancode);
+		return; /* swallow unknown codes */
+	}
+
+	kbd_put_queue(keycode);
+	PRINTF("%x\n",keycode);
+}
+
+/*
+ * This reads the keyboard status port, and does the
+ * appropriate action.
+ *
+ */
+unsigned char handle_kbd_event(void)
+{
+	unsigned char status = kbd_read_status();
+	unsigned int work = 10000;
+
+	while ((--work > 0) && (status & KBD_STAT_OBF)) {
+		unsigned char scancode;
+
+		scancode = kbd_read_input();
+
+		/* Error bytes must be ignored to make the
+		   Synaptics touchpads compaq use work */
+		/* Ignore error bytes */
+		if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR)))
+		{
+			if (status & KBD_STAT_MOUSE_OBF)
+				; /* not supported: handle_mouse_event(scancode); */
+			else
+				handle_keyboard_event(scancode);
+		}
+		status = kbd_read_status();
+	}
+	if (!work)
+		PRINTF("pc_keyb: controller jammed (0x%02X).\n", status);
+	return status;
+}
+
+
+
+/******************************************************************************
+ * Lowlevel Part of keyboard section
+ */
+unsigned char kbd_read_status(void)
+{
+	return(in8(CFG_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT));
+}
+
+unsigned char kbd_read_input(void)
+{
+	return(in8(CFG_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT));
+}
+
+void kbd_write_command(unsigned char cmd)
+{
+	out8(CFG_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT,cmd);
+}
+
+void kbd_write_output(unsigned char data)
+{
+	out8(CFG_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT, data);
+}
+
+int kbd_read_data(void)
+{
+	int val;
+	unsigned char status;
+
+	val=-1;
+	status = kbd_read_status();
+	if (status & KBD_STAT_OBF) {
+		val = kbd_read_input();
+		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
+			val = -2;
+	}
+	return val;
+}
+
+int kbd_wait_for_input(void)
+{
+	unsigned long timeout;
+	int val;
+
+	timeout = KBD_TIMEOUT;
+	val=kbd_read_data();
+	while(val < 0)
+	{
+		if(timeout--==0)
+			return -1;
+		udelay(1000);
+		val=kbd_read_data();
+	}
+	return val;
+}
+
+
+int kb_wait(void)
+{
+	unsigned long timeout = KBC_TIMEOUT * 10;
+
+	do {
+		unsigned char status = handle_kbd_event();
+		if (!(status & KBD_STAT_IBF))
+			return 0; /* ok */
+		udelay(1000);
+		timeout--;
+	} while (timeout);
+	return 1;
+}
+
+void kbd_write_command_w(int data)
+{
+	if(kb_wait())
+		PRINTF("timeout in kbd_write_command_w\n");
+	kbd_write_command(data);
+}
+
+void kbd_write_output_w(int data)
+{
+	if(kb_wait())
+		PRINTF("timeout in kbd_write_output_w\n");
+	kbd_write_output(data);
+}
+
+void kbd_send_data(unsigned char data)
+{
+	unsigned char status;
+	disable_8259A_irq(1); /* disable interrupt */
+	kbd_write_output_w(data);
+	status = kbd_wait_for_input();
+	if (status == KBD_REPLY_ACK)
+		enable_8259A_irq(1); /* enable interrupt */
+}
+
+
+char * kbd_initialize(void)
+{
+	int status;
+
+	in_pointer = 0; /* delete in Buffer */
+	out_pointer = 0;
+	/*
+	 * Test the keyboard interface.
+	 * This seems to be the only way to get it going.
+	 * If the test is successful a x55 is placed in the input buffer.
+	 */
+	kbd_write_command_w(KBD_CCMD_SELF_TEST);
+	if (kbd_wait_for_input() != 0x55)
+		return "Kbd:   failed self test";
+	/*
+	 * Perform a keyboard interface test.  This causes the controller
+	 * to test the keyboard clock and data lines.  The results of the
+	 * test are placed in the input buffer.
+	 */
+	kbd_write_command_w(KBD_CCMD_KBD_TEST);
+	if (kbd_wait_for_input() != 0x00)
+		return "Kbd:   interface failed self test";
+	/*
+	 * Enable the keyboard by allowing the keyboard clock to run.
+	 */
+	kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
+	status = kbd_wait_for_input();
+	/*
+	 * Reset keyboard. If the read times out
+	 * then the assumption is that no keyboard is
+	 * plugged into the machine.
+	 * This defaults the keyboard to scan-code set 2.
+	 *
+	 * Set up to try again if the keyboard asks for RESEND.
+	 */
+	do {
+		kbd_write_output_w(KBD_CMD_RESET);
+		status = kbd_wait_for_input();
+		if (status == KBD_REPLY_ACK)
+			break;
+		if (status != KBD_REPLY_RESEND)
+		{
+			PRINTF("status: %X\n",status);
+			return "Kbd:   reset failed, no ACK";
+		}
+	} while (1);
+	if (kbd_wait_for_input() != KBD_REPLY_POR)
+		return "Kbd:   reset failed, no POR";
+
+	/*
+	 * Set keyboard controller mode. During this, the keyboard should be
+	 * in the disabled state.
+	 *
+	 * Set up to try again if the keyboard asks for RESEND.
+	 */
+	do {
+		kbd_write_output_w(KBD_CMD_DISABLE);
+		status = kbd_wait_for_input();
+		if (status == KBD_REPLY_ACK)
+			break;
+		if (status != KBD_REPLY_RESEND)
+			return "Kbd:   disable keyboard: no ACK";
+	} while (1);
+
+	kbd_write_command_w(KBD_CCMD_WRITE_MODE);
+	kbd_write_output_w(KBD_MODE_KBD_INT
+			      | KBD_MODE_SYS
+			      | KBD_MODE_DISABLE_MOUSE
+			      | KBD_MODE_KCC);
+
+	/* ibm powerpc portables need this to use scan-code set 1 -- Cort */
+	kbd_write_command_w(KBD_CCMD_READ_MODE);
+	if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
+		/*
+		 * If the controller does not support conversion,
+		 * Set the keyboard to scan-code set 1.
+		 */
+		kbd_write_output_w(0xF0);
+		kbd_wait_for_input();
+		kbd_write_output_w(0x01);
+		kbd_wait_for_input();
+	}
+	kbd_write_output_w(KBD_CMD_ENABLE);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Kbd:   enable keyboard: no ACK";
+
+	/*
+	 * Finally, set the typematic rate to maximum.
+	 */
+	kbd_write_output_w(KBD_CMD_SET_RATE);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Kbd:   Set rate: no ACK";
+	kbd_write_output_w(0x00);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Kbd:   Set rate: no ACK";
+	return NULL;
+}
+
+void kbd_interrupt(void)
+{
+	handle_kbd_event();
+}
+
+
+
+/* eof */
+
diff --git a/board/mpl/common/usb_uhci.c b/board/mpl/common/usb_uhci.c
new file mode 100644
index 0000000..83624a9
--- /dev/null
+++ b/board/mpl/common/usb_uhci.c
@@ -0,0 +1,1152 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ * Note: Part of this code has been derived from linux
+ *
+ */
+
+/**********************************************************************
+ * How it works:
+ * -------------
+ * The framelist / Transfer descriptor / Queue Heads are similar like
+ * in the linux usb_uhci.c.
+ *
+ * During initialization, the following skeleton is allocated in init_skel:
+ *
+ *         framespecific           |           common chain
+ *
+ * framelist[]
+ * [  0 ]-----> TD ---------\
+ * [  1 ]-----> TD ----------> TD ------> QH -------> QH -------> QH ---> NULL
+ *   ...        TD ---------/
+ * [1023]-----> TD --------/
+ *
+ *              ^^             ^^         ^^          ^^          ^^
+ *              7 TDs for      1 TD for   Start of    Start of    End Chain
+ *              INT (2-128ms)  1ms-INT    CTRL Chain  BULK Chain
+ *
+ *
+ * Since this is a bootloader, the isochronous transfer descriptor have been removed.
+ *
+ * Interrupt Transfers.
+ * --------------------
+ * For Interupt transfers USB_MAX_TEMP_INT_TD Transfer descriptor are available. They
+ * will be inserted after the appropriate (depending the interval setting) skeleton TD.
+ * If an interrupt has been detected the dev->irqhandler is called. The status and number
+ * of transfered bytes is stored in dev->irq_status resp. dev->irq_act_len. If the
+ * dev->irqhandler returns 0, the interrupt TD is removed and disabled. If an 1 is returned,
+ * the interrupt TD will be reactivated.
+ *
+ * Control Transfers
+ * -----------------
+ * Control Transfers are issued by filling the tmp_td with the appropriate data and connect
+ * them to the qh_cntrl queue header. Before other control/bulk transfers can be issued,
+ * the programm has to wait for completion. This does not allows asynchronous data transfer.
+ *
+ * Bulk Transfers
+ * --------------
+ * Bulk Transfers are issued by filling the tmp_td with the appropriate data and connect
+ * them to the qh_bulk queue header. Before other control/bulk transfers can be issued,
+ * the programm has to wait for completion. This does not allows asynchronous data transfer.
+ *
+ *
+ */
+
+#include <common.h>
+#include <pci.h>
+
+#ifdef CONFIG_USB_UHCI
+
+#include <usb.h>
+#include "usb_uhci.h"
+
+#define USB_MAX_TEMP_TD      128  /* number of temporary TDs for bulk and control transfers */
+#define USB_MAX_TEMP_INT_TD  32   /* number of temporary TDs for Interrupt transfers */
+
+
+#undef USB_UHCI_DEBUG
+
+#ifdef	USB_UHCI_DEBUG
+#define	USB_UHCI_PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define USB_UHCI_PRINTF(fmt,args...)
+#endif
+
+
+static int irqvec = -1;            /* irq vector, if -1 uhci is stopped / reseted */
+unsigned int usb_base_addr;       /* base address */
+
+static uhci_td_t td_int[8];        /* Interrupt Transfer descriptors */
+static uhci_qh_t qh_cntrl;         /* control Queue Head */
+static uhci_qh_t qh_bulk;          /*  bulk Queue Head */
+static uhci_qh_t qh_end;           /* end Queue Head */
+static uhci_td_t td_last;          /* last TD (linked with end chain) */
+
+/* temporary tds */
+static uhci_td_t tmp_td[USB_MAX_TEMP_TD];          /* temporary bulk/control td's  */
+static uhci_td_t tmp_int_td[USB_MAX_TEMP_INT_TD];  /* temporary interrupt td's  */
+
+static unsigned long framelist[1024] __attribute__ ((aligned (0x1000))); /* frame list */
+
+static struct virt_root_hub rh;   /* struct for root hub */
+
+/**********************************************************************
+ * some forward decleration
+ */
+int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+						void *buffer, int transfer_len,struct devrequest *setup);
+
+/* fill a td with the approproiate data. Link, status, info and buffer
+ * are used by the USB controller itselfes, dev is used to identify the
+ * "connected" device
+ */
+void usb_fill_td(uhci_td_t* td,unsigned long link,unsigned long status,
+					unsigned long info, unsigned long buffer, unsigned long dev)
+{
+	td->link=swap_32(link);
+	td->status=swap_32(status);
+	td->info=swap_32(info);
+	td->buffer=swap_32(buffer);
+	td->dev_ptr=dev;
+}
+
+/* fill a qh with the approproiate data. Head and element are used by the USB controller
+ * itselfes. As soon as a valid dev_ptr is filled, a td chain is connected to the qh.
+ * Please note, that after completion of the td chain, the entry element is removed /
+ * marked invalid by the USB controller.
+ */
+void usb_fill_qh(uhci_qh_t* qh,unsigned long head,unsigned long element)
+{
+	qh->head=swap_32(head);
+	qh->element=swap_32(element);
+	qh->dev_ptr=0L;
+}
+
+/* get the status of a td->status
+ */
+unsigned long usb_uhci_td_stat(unsigned long status)
+{
+	unsigned long result=0;
+	result |= (status & TD_CTRL_NAK)      ? USB_ST_NAK_REC : 0;
+	result |= (status & TD_CTRL_STALLED)  ? USB_ST_STALLED : 0;
+	result |= (status & TD_CTRL_DBUFERR)  ? USB_ST_BUF_ERR : 0;
+	result |= (status & TD_CTRL_BABBLE)   ? USB_ST_BABBLE_DET : 0;
+	result |= (status & TD_CTRL_CRCTIMEO) ? USB_ST_CRC_ERR : 0;
+	result |= (status & TD_CTRL_BITSTUFF) ? USB_ST_BIT_ERR : 0;
+	result |= (status & TD_CTRL_ACTIVE)   ? USB_ST_NOT_PROC : 0;
+	return result;
+}
+
+/* get the status and the transfered len of a td chain.
+ * called from the completion handler
+ */
+int usb_get_td_status(uhci_td_t *td,struct usb_device *dev)
+{
+	unsigned long temp,info;
+	unsigned long stat;
+	uhci_td_t *mytd=td;
+
+	if(dev->devnum==rh.devnum)
+		return 0;
+	dev->act_len=0;
+	stat=0;
+	do {
+		temp=swap_32((unsigned long)mytd->status);
+		stat=usb_uhci_td_stat(temp);
+		info=swap_32((unsigned long)mytd->info);
+		if(((info & 0xff)!= USB_PID_SETUP) &&
+				(((info >> 21) & 0x7ff)!= 0x7ff) &&
+				(temp & 0x7FF)!=0x7ff)
+		{  /* if not setup and not null data pack */
+			dev->act_len+=(temp & 0x7FF) + 1; /* the transfered len is act_len + 1 */
+		}
+		if(stat) {           /* status no ok */
+			dev->status=stat;
+			return -1;
+		}
+		temp=swap_32((unsigned long)mytd->link);
+		mytd=(uhci_td_t *)(temp & 0xfffffff0);
+	}while((temp & 0x1)==0); /* process all TDs */
+	dev->status=stat;
+	return 0; /* Ok */
+}
+
+
+/*-------------------------------------------------------------------
+ *                         LOW LEVEL STUFF
+ *          assembles QHs und TDs for control, bulk and iso
+ *-------------------------------------------------------------------*/
+
+/* Submits a control message. That is a Setup, Data and Status transfer.
+ * Routine does not wait for completion.
+ */
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+										int transfer_len,struct devrequest *setup)
+{
+	unsigned long destination, status;
+	int maxsze = usb_maxpacket(dev, pipe);
+	unsigned long dataptr;
+	int len;
+	int pktsze;
+	int i=0;
+
+	if (!maxsze) {
+		USB_UHCI_PRINTF("uhci_submit_control_urb: pipesize for pipe %lx is zero\n", pipe);
+		return -1;
+	}
+	if(((pipe>>8)&0x7f)==rh.devnum) {
+		/* this is the root hub -> redirect it */
+		return uhci_submit_rh_msg(dev,pipe,buffer,transfer_len,setup);
+	}
+	USB_UHCI_PRINTF("uhci_submit_control start len %x, maxsize %x\n",transfer_len,maxsze);
+	/* The "pipe" thing contains the destination in bits 8--18 */
+	destination = (pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; /* Setup stage */
+	/* 3 errors */
+	status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
+	/* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD); */
+	/*  Build the TD for the control request, try forever, 8 bytes of data */
+	usb_fill_td(&tmp_td[i],UHCI_PTR_TERM ,status, destination | (7 << 21),(unsigned long)setup,(unsigned long)dev);
+#if 0
+	{
+		char *sp=(char *)setup;
+		printf("SETUP to pipe %lx: %x %x %x %x %x %x %x %x\n", pipe,
+		    sp[0],sp[1],sp[2],sp[3],sp[4],sp[5],sp[6],sp[7]);
+	}
+#endif
+	dataptr = (unsigned long)buffer;
+	len=transfer_len;
+
+	/* If direction is "send", change the frame from SETUP (0x2D)
+	   to OUT (0xE1). Else change it from SETUP to IN (0x69). */
+	destination = (pipe & PIPE_DEVEP_MASK) | ((pipe & USB_DIR_IN)==0 ? USB_PID_OUT : USB_PID_IN);
+	while (len > 0) {
+		/* data stage */
+		pktsze = len;
+		i++;
+		if (pktsze > maxsze)
+			pktsze = maxsze;
+		destination ^= 1 << TD_TOKEN_TOGGLE;	/* toggle DATA0/1 */
+		usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status, destination | ((pktsze - 1) << 21),dataptr,(unsigned long)dev);	/* Status, pktsze bytes of data */
+		tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]);
+
+		dataptr += pktsze;
+		len -= pktsze;
+	}
+
+	/*  Build the final TD for control status */
+	/* It's only IN if the pipe is out AND we aren't expecting data */
+
+	destination &= ~UHCI_PID;
+	if (((pipe & USB_DIR_IN)==0) || (transfer_len == 0))
+		destination |= USB_PID_IN;
+	else
+		destination |= USB_PID_OUT;
+	destination |= 1 << TD_TOKEN_TOGGLE;	/* End in Data1 */
+	i++;
+	status &=~TD_CTRL_SPD;
+	/* no limit on errors on final packet , 0 bytes of data */
+	usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21),0,(unsigned long)dev);
+	tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]);	/* queue status td */
+	/*	usb_show_td(i+1);*/
+	USB_UHCI_PRINTF("uhci_submit_control end (%d tmp_tds used)\n",i);
+	/* first mark the control QH element terminated */
+	qh_cntrl.element=0xffffffffL;
+	/* set qh active */
+	qh_cntrl.dev_ptr=(unsigned long)dev;
+	/* fill in tmp_td_chain */
+	qh_cntrl.element=swap_32((unsigned long)&tmp_td[0]);
+	return 0;
+}
+
+/*-------------------------------------------------------------------
+ * Prepare TDs for bulk transfers.
+ */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len)
+{
+	unsigned long destination, status,info;
+	unsigned long dataptr;
+	int maxsze = usb_maxpacket(dev, pipe);
+	int len;
+	int i=0;
+
+	if(transfer_len < 0) {
+		printf("Negative transfer length in submit_bulk\n");
+		return -1;
+	}
+	if (!maxsze)
+		return -1;
+	/* The "pipe" thing contains the destination in bits 8--18. */
+	destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
+	/* 3 errors */
+	status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
+	/*	((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); */
+	/* Build the TDs for the bulk request */
+	len = transfer_len;
+	dataptr = (unsigned long)buffer;
+	do {
+		int pktsze = len;
+		if (pktsze > maxsze)
+			pktsze = maxsze;
+		/* pktsze bytes of data  */
+		info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) |
+			(usb_gettoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
+
+		if((len-pktsze)==0)
+			status |= TD_CTRL_IOC;	/* last one generates INT */
+
+		usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status, info,dataptr,(unsigned long)dev);	/* Status, pktsze bytes of data */
+		if(i>0)
+			tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]);
+		i++;
+		dataptr += pktsze;
+		len -= pktsze;
+		usb_dotoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
+	} while (len > 0);
+	/* first mark the bulk QH element terminated */
+	qh_bulk.element=0xffffffffL;
+	/* set qh active */
+	qh_bulk.dev_ptr=(unsigned long)dev;
+	/* fill in tmp_td_chain */
+	qh_bulk.element=swap_32((unsigned long)&tmp_td[0]);
+	return 0;
+}
+
+
+/* search a free interrupt td
+ */
+uhci_td_t *uhci_alloc_int_td(void)
+{
+	int i;
+	for(i=0;i<USB_MAX_TEMP_INT_TD;i++) {
+		if(tmp_int_td[i].dev_ptr==0) /* no device assigned -> free TD */
+			return &tmp_int_td[i];
+	}
+	return NULL;
+}
+
+#if 0
+void uhci_show_temp_int_td(void)
+{
+	int i;
+	for(i=0;i<USB_MAX_TEMP_INT_TD;i++) {
+		if((tmp_int_td[i].dev_ptr&0x01)!=0x1L) /* no device assigned -> free TD */
+			printf("temp_td %d is assigned to dev %lx\n",i,tmp_int_td[i].dev_ptr);
+	}
+	printf("all others temp_tds are free\n");
+}
+#endif
+/*-------------------------------------------------------------------
+ * submits USB interrupt (ie. polling ;-)
+ */
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len, int interval)
+{
+	int nint, n;
+	unsigned long status, destination;
+	unsigned long info,tmp;
+	uhci_td_t *mytd;
+	if (interval < 0 || interval >= 256)
+		return -1;
+
+	if (interval == 0)
+		nint = 0;
+	else {
+		for (nint = 0, n = 1; nint <= 8; nint++, n += n)	/* round interval down to 2^n */
+		 {
+			if(interval < n) {
+				interval = n / 2;
+				break;
+			}
+		}
+		nint--;
+	}
+
+	USB_UHCI_PRINTF("Rounded interval to %i, chain  %i\n", interval, nint);
+	mytd=uhci_alloc_int_td();
+	if(mytd==NULL) {
+		printf("No free INT TDs found\n");
+		return -1;
+	}
+	status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | (3 << 27);
+/*		(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+*/
+
+	destination =(pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe) | (((transfer_len - 1) & 0x7ff) << 21);
+
+	info = destination | (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << TD_TOKEN_TOGGLE);
+	tmp = swap_32(td_int[nint].link);
+	usb_fill_td(mytd,tmp,status, info,(unsigned long)buffer,(unsigned long)dev);
+	/* Link it */
+	tmp = swap_32((unsigned long)mytd);
+	td_int[nint].link=tmp;
+
+	usb_dotoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
+
+	return 0;
+}
+
+/**********************************************************************
+ * Low Level functions
+ */
+
+
+void reset_hc(void)
+{
+
+	/* Global reset for 100ms */
+	out16r( usb_base_addr + USBPORTSC1,0x0204);
+	out16r( usb_base_addr + USBPORTSC2,0x0204);
+	out16r( usb_base_addr + USBCMD,USBCMD_GRESET | USBCMD_RS);
+	/* Turn off all interrupts */
+	out16r(usb_base_addr + USBINTR,0);
+	wait_ms(50);
+	out16r( usb_base_addr + USBCMD,0);
+	wait_ms(10);
+}
+
+void start_hc(void)
+{
+	int timeout = 1000;
+
+	while(in16r(usb_base_addr + USBCMD) & USBCMD_HCRESET) {
+		if (!--timeout) {
+			printf("USBCMD_HCRESET timed out!\n");
+			break;
+		}
+	}
+	/* Turn on all interrupts */
+	out16r(usb_base_addr + USBINTR,USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP);
+	/* Start at frame 0 */
+	out16r(usb_base_addr + USBFRNUM,0);
+	/* set Framebuffer base address */
+	out32r(usb_base_addr+USBFLBASEADD,(unsigned long)&framelist);
+	/* Run and mark it configured with a 64-byte max packet */
+	out16r(usb_base_addr + USBCMD,USBCMD_RS | USBCMD_CF | USBCMD_MAXP);
+}
+
+/* Initialize the skeleton
+ */
+void usb_init_skel(void)
+{
+	unsigned long temp;
+	int n;
+
+	for(n=0;n<USB_MAX_TEMP_INT_TD;n++)
+		tmp_int_td[n].dev_ptr=0L; /* no devices connected */
+	/* last td */
+	usb_fill_td(&td_last,UHCI_PTR_TERM,TD_CTRL_IOC ,0,0,0L);
+  /* usb_fill_td(&td_last,UHCI_PTR_TERM,0,0,0); */
+	/* End Queue Header */
+	usb_fill_qh(&qh_end,UHCI_PTR_TERM,(unsigned long)&td_last);
+	/* Bulk Queue Header */
+	temp=(unsigned long)&qh_end;
+	usb_fill_qh(&qh_bulk,temp | UHCI_PTR_QH,UHCI_PTR_TERM);
+	/* Control Queue Header */
+	temp=(unsigned long)&qh_bulk;
+	usb_fill_qh(&qh_cntrl, temp | UHCI_PTR_QH,UHCI_PTR_TERM);
+	/* 1ms Interrupt td */
+	temp=(unsigned long)&qh_cntrl;
+	usb_fill_td(&td_int[0],temp | UHCI_PTR_QH,0,0,0,0L);
+	temp=(unsigned long)&td_int[0];
+	for(n=1; n<8; n++)
+		usb_fill_td(&td_int[n],temp,0,0,0,0L);
+	for (n = 0; n < 1024; n++) {
+	/* link all framelist pointers to one of the interrupts */
+		int m, o;
+		if ((n&127)==127)
+			framelist[n]= swap_32((unsigned long)&td_int[0]);
+		else
+			for (o = 1, m = 2; m <= 128; o++, m += m)
+				if ((n & (m - 1)) == ((m - 1) / 2))
+						framelist[n]= swap_32((unsigned long)&td_int[o]);
+	}
+}
+
+/* check the common skeleton for completed transfers, and update the status
+ * of the "connected" device. Called from the IRQ routine.
+ */
+void usb_check_skel(void)
+{
+	struct usb_device *dev;
+	/* start with the control qh */
+	if(qh_cntrl.dev_ptr!=0) /* it's a device assigned check if this caused IRQ */
+	{
+		dev=(struct usb_device *)qh_cntrl.dev_ptr;
+		usb_get_td_status(&tmp_td[0],dev); /* update status */
+		if(!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */
+			qh_cntrl.dev_ptr=0;
+		}
+	}
+	/* now process the bulk */
+	if(qh_bulk.dev_ptr!=0) /* it's a device assigned check if this caused IRQ */
+	{
+		dev=(struct usb_device *)qh_bulk.dev_ptr;
+		usb_get_td_status(&tmp_td[0],dev); /* update status */
+		if(!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */
+			qh_bulk.dev_ptr=0;
+		}
+	}
+}
+
+/* check the interrupt chain, ubdate the status of the appropriate device,
+ * call the appropriate irqhandler and reactivate the TD if the irqhandler
+ * returns with 1
+ */
+void usb_check_int_chain(void)
+{
+	int i,res;
+	unsigned long link,status;
+	struct usb_device *dev;
+	uhci_td_t *td,*prevtd;
+
+	for(i=0;i<8;i++) {
+		prevtd=&td_int[i]; /* the first previous td is the skeleton td */
+		link=swap_32(td_int[i].link) & 0xfffffff0; /* next in chain */
+		td=(uhci_td_t *)link; /* assign it */
+		/* all interrupt TDs are finally linked to the td_int[0].
+ 		 * so we process all until we find the td_int[0].
+		 * if int0 chain points to a QH, we're also done
+	   */
+		while(((i>0) && (link != (unsigned long)&td_int[0])) ||
+					((i==0) && !(swap_32(td->link) &  UHCI_PTR_QH)))
+		{
+			/* check if a device is assigned with this td */
+			status=swap_32(td->status);
+			if((td->dev_ptr!=0L) && !(status & TD_CTRL_ACTIVE)) {
+				/* td is not active and a device is assigned -> call irqhandler */
+				dev=(struct usb_device *)td->dev_ptr;
+				dev->irq_act_len=((status & 0x7FF)==0x7FF) ? 0 : (status & 0x7FF) + 1; /* transfered length */
+				dev->irq_status=usb_uhci_td_stat(status); /* get status */
+				res=dev->irq_handle(dev); /* call irqhandler */
+				if(res==1) {
+					/* reactivate */
+					status|=TD_CTRL_ACTIVE;
+					td->status=swap_32(status);
+					prevtd=td; /* previous td = this td */
+				}
+				else {
+					prevtd->link=td->link; /* link previous td directly to the nex td -> unlinked */
+					/* remove device pointer */
+					td->dev_ptr=0L;
+				}
+			} /* if we call the irq handler */
+			link=swap_32(td->link) & 0xfffffff0; /* next in chain */
+			td=(uhci_td_t *)link; /* assign it */
+		} /* process all td in this int chain */
+	} /* next interrupt chain */
+}
+
+
+/* usb interrupt service routine.
+ */
+void handle_usb_interrupt(void)
+{
+	unsigned short status;
+
+	/*
+	 * Read the interrupt status, and write it back to clear the
+	 * interrupt cause
+	 */
+
+	status = in16r(usb_base_addr + USBSTS);
+
+	if (!status)		/* shared interrupt, not mine */
+		return;
+	if (status != 1) {
+		/* remove host controller halted state */
+		if ((status&0x20) && ((in16r(usb_base_addr+USBCMD) && USBCMD_RS)==0)) {
+			out16r(usb_base_addr + USBCMD, USBCMD_RS | in16r(usb_base_addr + USBCMD));
+		}
+	}
+	usb_check_int_chain(); /* call interrupt handlers for int tds */
+	usb_check_skel(); /* call completion handler for common transfer routines */
+	out16r(usb_base_addr+USBSTS,status);
+}
+
+
+/* init uhci
+ */
+int usb_lowlevel_init(void)
+{
+	unsigned char temp;
+	int	busdevfunc;
+
+	busdevfunc=pci_find_device(USB_UHCI_VEND_ID,USB_UHCI_DEV_ID,0); /* get PCI Device ID */
+	if(busdevfunc==-1) {
+		printf("Error USB UHCI (%04X,%04X) not found\n",USB_UHCI_VEND_ID,USB_UHCI_DEV_ID);
+		return -1;
+	}
+	pci_read_config_byte(busdevfunc,PCI_INTERRUPT_LINE,&temp);
+	irqvec = temp;
+	irq_free_handler(irqvec);
+	USB_UHCI_PRINTF("Interrupt Line = %d, is %d\n",irqvec);
+	pci_read_config_byte(busdevfunc,PCI_INTERRUPT_PIN,&temp);
+	USB_UHCI_PRINTF("Interrupt Pin = %ld\n",temp);
+	pci_read_config_dword(busdevfunc,PCI_BASE_ADDRESS_4,&usb_base_addr);
+	USB_UHCI_PRINTF("IO Base Address = 0x%lx\n",usb_base_addr);
+	usb_base_addr&=0xFFFFFFF0;
+	usb_base_addr+=CFG_ISA_IO_BASE_ADDRESS;
+	rh.devnum = 0;
+	usb_init_skel();
+	reset_hc();
+	start_hc();
+	irq_install_handler(irqvec, (interrupt_handler_t *)handle_usb_interrupt, NULL);
+	return 0;
+}
+
+/* stop uhci
+ */
+int usb_lowlevel_stop(void)
+{
+	if(irqvec==-1)
+		return 1;
+	irq_free_handler(irqvec);
+	reset_hc();
+	irqvec=-1;
+	return 0;
+}
+
+/*******************************************************************************************
+ * Virtual Root Hub
+ * Since the uhci does not have a real HUB, we simulate one ;-)
+ */
+#undef	USB_RH_DEBUG
+
+#ifdef	USB_RH_DEBUG
+#define	USB_RH_PRINTF(fmt,args...)	printf (fmt ,##args)
+static void usb_display_wValue(unsigned short wValue,unsigned short wIndex);
+static void usb_display_Req(unsigned short req);
+#else
+#define USB_RH_PRINTF(fmt,args...)
+static void usb_display_wValue(unsigned short wValue,unsigned short wIndex) {}
+static void usb_display_Req(unsigned short req) {}
+#endif
+
+static unsigned char root_hub_dev_des[] =
+{
+	0x12,			/*  __u8  bLength; */
+	0x01,			/*  __u8  bDescriptorType; Device */
+	0x00,			/*  __u16 bcdUSB; v1.0 */
+	0x01,
+	0x09,			/*  __u8  bDeviceClass; HUB_CLASSCODE */
+	0x00,			/*  __u8  bDeviceSubClass; */
+	0x00,			/*  __u8  bDeviceProtocol; */
+	0x08,			/*  __u8  bMaxPacketSize0; 8 Bytes */
+	0x00,			/*  __u16 idVendor; */
+	0x00,
+	0x00,			/*  __u16 idProduct; */
+	0x00,
+	0x00,			/*  __u16 bcdDevice; */
+	0x00,
+	0x01,			/*  __u8  iManufacturer; */
+	0x00,			/*  __u8  iProduct; */
+	0x00,			/*  __u8  iSerialNumber; */
+	0x01			/*  __u8  bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static unsigned char root_hub_config_des[] =
+{
+	0x09,			/*  __u8  bLength; */
+	0x02,			/*  __u8  bDescriptorType; Configuration */
+	0x19,			/*  __u16 wTotalLength; */
+	0x00,
+	0x01,			/*  __u8  bNumInterfaces; */
+	0x01,			/*  __u8  bConfigurationValue; */
+	0x00,			/*  __u8  iConfiguration; */
+	0x40,			/*  __u8  bmAttributes;
+				   Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+	0x00,			/*  __u8  MaxPower; */
+
+     /* interface */
+	0x09,			/*  __u8  if_bLength; */
+	0x04,			/*  __u8  if_bDescriptorType; Interface */
+	0x00,			/*  __u8  if_bInterfaceNumber; */
+	0x00,			/*  __u8  if_bAlternateSetting; */
+	0x01,			/*  __u8  if_bNumEndpoints; */
+	0x09,			/*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,			/*  __u8  if_bInterfaceSubClass; */
+	0x00,			/*  __u8  if_bInterfaceProtocol; */
+	0x00,			/*  __u8  if_iInterface; */
+
+     /* endpoint */
+	0x07,			/*  __u8  ep_bLength; */
+	0x05,			/*  __u8  ep_bDescriptorType; Endpoint */
+	0x81,			/*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+	0x03,			/*  __u8  ep_bmAttributes; Interrupt */
+	0x08,			/*  __u16 ep_wMaxPacketSize; 8 Bytes */
+	0x00,
+	0xff			/*  __u8  ep_bInterval; 255 ms */
+};
+
+
+static unsigned char root_hub_hub_des[] =
+{
+	0x09,			/*  __u8  bLength; */
+	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
+	0x02,			/*  __u8  bNbrPorts; */
+	0x00,			/* __u16  wHubCharacteristics; */
+	0x00,
+	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */
+	0x00,			/*  __u8  bHubContrCurrent; 0 mA */
+	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */
+	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+	0x04,			/*  __u8  bLength; */
+	0x03,			/*  __u8  bDescriptorType; String-descriptor */
+	0x09,			/*  __u8  lang ID */
+	0x04,			/*  __u8  lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+	28,			/*  __u8  bLength; */
+	0x03,			/*  __u8  bDescriptorType; String-descriptor */
+	'U',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'H',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'C',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'I',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	' ',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'R',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'o',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'o',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	't',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	' ',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'H',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'u',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+	'b',			/*  __u8  Unicode */
+	0,				/*  __u8  Unicode */
+};
+
+
+/*
+ * Root Hub Control Pipe (interrupt Pipes are not supported)
+ */
+
+
+int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len,struct devrequest *cmd)
+{
+	void *data = buffer;
+	int leni = transfer_len;
+	int len = 0;
+	int status = 0;
+	int stat = 0;
+	int i;
+
+	unsigned short cstatus;
+
+	unsigned short bmRType_bReq;
+	unsigned short wValue;
+	unsigned short wIndex;
+	unsigned short wLength;
+
+	if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) {
+		printf("Root-Hub submit IRQ: NOT implemented\n");
+#if 0
+		uhci->rh.urb = urb;
+		uhci->rh.send = 1;
+		uhci->rh.interval = urb->interval;
+		rh_init_int_timer (urb);
+#endif
+		return 0;
+	}
+	bmRType_bReq = cmd->requesttype | cmd->request << 8;
+	wValue = swap_16(cmd->value);
+	wIndex = swap_16(cmd->index);
+	wLength = swap_16(cmd->length);
+	usb_display_Req(bmRType_bReq);
+	for (i = 0; i < 8; i++)
+		rh.c_p_r[i] = 0;
+	USB_RH_PRINTF("Root-Hub: adr: %2x cmd(%1x): %02x%02x %04x %04x %04x\n",
+	     dev->devnum, 8, cmd->requesttype,cmd->request, wValue, wIndex, wLength);
+
+	switch (bmRType_bReq) {
+		/* Request Destination:
+		   without flags: Device,
+		   RH_INTERFACE: interface,
+		   RH_ENDPOINT: endpoint,
+		   RH_CLASS means HUB here,
+		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here
+		 */
+
+	case RH_GET_STATUS:
+		*(unsigned short *) data = swap_16(1);
+		len=2;
+		break;
+	case RH_GET_STATUS | RH_INTERFACE:
+		*(unsigned short *) data = swap_16(0);
+		len=2;
+		break;
+	case RH_GET_STATUS | RH_ENDPOINT:
+		*(unsigned short *) data = swap_16(0);
+		len=2;
+		break;
+	case RH_GET_STATUS | RH_CLASS:
+		*(unsigned long *) data = swap_32(0);
+		len=4;
+		break;	/* hub power ** */
+	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+
+		status = in16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1));
+		cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
+			((status & USBPORTSC_PEC) >> (3 - 1)) |
+			(rh.c_p_r[wIndex - 1] << (0 + 4));
+		status = (status & USBPORTSC_CCS) |
+			((status & USBPORTSC_PE) >> (2 - 1)) |
+			((status & USBPORTSC_SUSP) >> (12 - 2)) |
+			((status & USBPORTSC_PR) >> (9 - 4)) |
+			(1 << 8) |	/* power on ** */
+			((status & USBPORTSC_LSDA) << (-8 + 9));
+
+		*(unsigned short *) data = swap_16(status);
+		*(unsigned short *) (data + 2) = swap_16(cstatus);
+		len=4;
+		break;
+	case RH_CLEAR_FEATURE | RH_ENDPOINT:
+		switch (wValue) {
+		case (RH_ENDPOINT_STALL):
+			len=0;
+			break;
+		}
+		break;
+
+	case RH_CLEAR_FEATURE | RH_CLASS:
+		switch (wValue) {
+		case (RH_C_HUB_OVER_CURRENT):
+			len=0;	/* hub power over current ** */
+			break;
+		}
+		break;
+
+	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+		usb_display_wValue(wValue,wIndex);
+		switch (wValue) {
+		case (RH_PORT_ENABLE):
+			status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
+			status = (status & 0xfff5) & ~USBPORTSC_PE;
+			out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+			len=0;
+			break;
+		case (RH_PORT_SUSPEND):
+			status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
+			status = (status & 0xfff5) & ~USBPORTSC_SUSP;
+			out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+			len=0;
+			break;
+		case (RH_PORT_POWER):
+			len=0;	/* port power ** */
+			break;
+		case (RH_C_PORT_CONNECTION):
+			status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
+			status = (status & 0xfff5) | USBPORTSC_CSC;
+			out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+			len=0;
+			break;
+		case (RH_C_PORT_ENABLE):
+			status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
+			status = (status & 0xfff5) | USBPORTSC_PEC;
+			out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+			len=0;
+			break;
+		case (RH_C_PORT_SUSPEND):
+/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
+			len=0;
+			break;
+		case (RH_C_PORT_OVER_CURRENT):
+			len=0;
+			break;
+		case (RH_C_PORT_RESET):
+			rh.c_p_r[wIndex - 1] = 0;
+			len=0;
+			break;
+		}
+		break;
+	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+		usb_display_wValue(wValue,wIndex);
+		switch (wValue) {
+		case (RH_PORT_SUSPEND):
+			status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
+			status = (status & 0xfff5) | USBPORTSC_SUSP;
+			out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+			len=0;
+			break;
+		case (RH_PORT_RESET):
+			status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
+			status = (status & 0xfff5) | USBPORTSC_PR;
+			out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+			wait_ms(10);
+			status = (status & 0xfff5) & ~USBPORTSC_PR;
+			out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+			udelay(10);
+			status = (status & 0xfff5) | USBPORTSC_PE;
+			out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+			wait_ms(10);
+			status = (status & 0xfff5) | 0xa;
+			out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+			len=0;
+			break;
+		case (RH_PORT_POWER):
+			len=0;	/* port power ** */
+			break;
+		case (RH_PORT_ENABLE):
+			status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1));
+			status = (status & 0xfff5) | USBPORTSC_PE;
+			out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+			len=0;
+			break;
+		}
+		break;
+
+	case RH_SET_ADDRESS:
+		rh.devnum = wValue;
+		len=0;
+		break;
+	case RH_GET_DESCRIPTOR:
+		switch ((wValue & 0xff00) >> 8) {
+		case (0x01):	/* device descriptor */
+			i=sizeof(root_hub_config_des);
+			status=i > wLength ? wLength : i;
+			len = leni > status ? status : leni;
+			memcpy (data, root_hub_dev_des, len);
+			break;
+		case (0x02):	/* configuration descriptor */
+			i=sizeof(root_hub_config_des);
+			status=i > wLength ? wLength : i;
+			len = leni > status ? status : leni;
+			memcpy (data, root_hub_config_des, len);
+			break;
+		case (0x03):	/*string descriptors */
+			if(wValue==0x0300) {
+				i=sizeof(root_hub_str_index0);
+				status = i > wLength ? wLength : i;
+				len = leni > status ? status : leni;
+				memcpy (data, root_hub_str_index0, len);
+				break;
+			}
+			if(wValue==0x0301) {
+				i=sizeof(root_hub_str_index1);
+				status = i > wLength ? wLength : i;
+				len = leni > status ? status : leni;
+				memcpy (data, root_hub_str_index1, len);
+				break;
+			}
+			stat = USB_ST_STALLED;
+		}
+		break;
+
+	case RH_GET_DESCRIPTOR | RH_CLASS:
+		root_hub_hub_des[2] = 2;
+		i=sizeof(root_hub_hub_des);
+		status= i > wLength ? wLength : i;
+		len = leni > status ? status : leni;
+		memcpy (data, root_hub_hub_des, len);
+		break;
+	case RH_GET_CONFIGURATION:
+		*(unsigned char *) data = 0x01;
+		len = 1;
+		break;
+	case RH_SET_CONFIGURATION:
+		len=0;
+		break;
+	default:
+		stat = USB_ST_STALLED;
+	}
+	USB_RH_PRINTF("Root-Hub stat %lx port1: %x port2: %x\n\n",stat,
+	     in16r(usb_base_addr + USBPORTSC1), in16r(usb_base_addr + USBPORTSC2));
+	dev->act_len=len;
+	dev->status=stat;
+	return stat;
+
+}
+
+/********************************************************************************
+ * Some Debug Routines
+ */
+
+#ifdef	USB_RH_DEBUG
+
+static void usb_display_Req(unsigned short req)
+{
+	USB_RH_PRINTF("- Root-Hub Request: ");
+	switch (req) {
+	case RH_GET_STATUS:
+		USB_RH_PRINTF("Get Status ");
+		break;
+	case RH_GET_STATUS | RH_INTERFACE:
+		USB_RH_PRINTF("Get Status Interface ");
+		break;
+	case RH_GET_STATUS | RH_ENDPOINT:
+		USB_RH_PRINTF("Get Status Endpoint ");
+		break;
+	case RH_GET_STATUS | RH_CLASS:
+		USB_RH_PRINTF("Get Status Class");
+		break;	/* hub power ** */
+	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+		USB_RH_PRINTF("Get Status Class Others");
+		break;
+	case RH_CLEAR_FEATURE | RH_ENDPOINT:
+		USB_RH_PRINTF("Clear Feature Endpoint ");
+		break;
+	case RH_CLEAR_FEATURE | RH_CLASS:
+		USB_RH_PRINTF("Clear Feature Class ");
+		break;
+	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+		USB_RH_PRINTF("Clear Feature Other Class ");
+		break;
+	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+		USB_RH_PRINTF("Set Feature Other Class ");
+		break;
+	case RH_SET_ADDRESS:
+		USB_RH_PRINTF("Set Address ");
+		break;
+	case RH_GET_DESCRIPTOR:
+		USB_RH_PRINTF("Get Descriptor ");
+		break;
+	case RH_GET_DESCRIPTOR | RH_CLASS:
+		USB_RH_PRINTF("Get Descriptor Class ");
+		break;
+	case RH_GET_CONFIGURATION:
+		USB_RH_PRINTF("Get Configuration ");
+		break;
+	case RH_SET_CONFIGURATION:
+		USB_RH_PRINTF("Get Configuration ");
+		break;
+	default:
+		USB_RH_PRINTF("****UNKNOWN**** 0x%04X ",req);
+	}
+	USB_RH_PRINTF("\n");
+
+}
+
+static void usb_display_wValue(unsigned short wValue,unsigned short wIndex)
+{
+	switch (wValue) {
+		case (RH_PORT_ENABLE):
+			USB_RH_PRINTF("Root-Hub: Enable Port %d\n",wIndex);
+			break;
+		case (RH_PORT_SUSPEND):
+			USB_RH_PRINTF("Root-Hub: Suspend Port %d\n",wIndex);
+			break;
+		case (RH_PORT_POWER):
+			USB_RH_PRINTF("Root-Hub: Port Power %d\n",wIndex);
+			break;
+		case (RH_C_PORT_CONNECTION):
+			USB_RH_PRINTF("Root-Hub: C Port Connection Port %d\n",wIndex);
+			break;
+		case (RH_C_PORT_ENABLE):
+			USB_RH_PRINTF("Root-Hub: C Port Enable Port %d\n",wIndex);
+			break;
+		case (RH_C_PORT_SUSPEND):
+			USB_RH_PRINTF("Root-Hub: C Port Suspend Port %d\n",wIndex);
+			break;
+		case (RH_C_PORT_OVER_CURRENT):
+			USB_RH_PRINTF("Root-Hub: C Port Over Current Port %d\n",wIndex);
+			break;
+		case (RH_C_PORT_RESET):
+			USB_RH_PRINTF("Root-Hub: C Port reset Port %d\n",wIndex);
+			break;
+		default:
+			USB_RH_PRINTF("Root-Hub: unknown %x %x\n",wValue,wIndex);
+			break;
+	}
+}
+
+#endif
+
+
+
+#ifdef	USB_UHCI_DEBUG
+
+static int usb_display_td(uhci_td_t *td)
+{
+	unsigned long tmp;
+	int valid;
+
+	printf("TD at %p:\n",td);
+
+	tmp=swap_32(td->link);
+	printf("Link points to 0x%08lX, %s first, %s, %s\n",tmp&0xfffffff0,
+		((tmp & 0x4)==0x4) ? "Depth" : "Breath",
+		((tmp & 0x2)==0x2) ? "QH" : "TD",
+		((tmp & 0x1)==0x1) ? "invalid" : "valid");
+	valid=((tmp & 0x1)==0x0);
+	tmp=swap_32(td->status);
+	printf("     %s %ld Errors %s %s %s \n     %s %s %s %s %s %s\n     Len 0x%lX\n",
+		(((tmp>>29)&0x1)==0x1) ? "SPD Enable" : "SPD Disable",
+		((tmp>>28)&0x3),
+		(((tmp>>26)&0x1)==0x1) ? "Low Speed" : "Full Speed",
+		(((tmp>>25)&0x1)==0x1) ? "ISO " : "",
+		(((tmp>>24)&0x1)==0x1) ? "IOC " : "",
+		(((tmp>>23)&0x1)==0x1) ? "Active " : "Inactive ",
+		(((tmp>>22)&0x1)==0x1) ? "Stalled" : "",
+		(((tmp>>21)&0x1)==0x1) ? "Data Buffer Error" : "",
+		(((tmp>>20)&0x1)==0x1) ? "Babble" : "",
+		(((tmp>>19)&0x1)==0x1) ? "NAK" : "",
+		(((tmp>>18)&0x1)==0x1) ? "Bitstuff Error" : "",
+		(tmp&0x7ff));
+	tmp=swap_32(td->info);
+	printf("     MaxLen 0x%lX\n",((tmp>>21)&0x7FF));
+	printf("     %s Endpoint 0x%lX Dev Addr 0x%lX PID 0x%lX\n",((tmp>>19)&0x1)==0x1 ? "TOGGLE" : "",
+		((tmp>>15)&0xF),((tmp>>8)&0x7F),tmp&0xFF);
+	tmp=swap_32(td->buffer);
+	printf("     Buffer 0x%08lX\n",tmp);
+	printf("     DEV %08lX\n",td->dev_ptr);
+	return valid;
+}
+
+
+void usb_show_td(int max)
+{
+	int i;
+	if(max>0) {
+		for(i=0;i<max;i++) {
+			usb_display_td(&tmp_td[i]);
+		}
+	}
+	else {
+		i=0;
+		do {
+			printf("tmp_td[%d]\n",i);
+		}while(usb_display_td(&tmp_td[i++]));
+	}
+}
+
+
+#endif
+#endif /* CONFIG_USB_UHCI */
+
+/* EOF */
diff --git a/board/musenki/flash.c b/board/musenki/flash.c
new file mode 100644
index 0000000..a0a038f
--- /dev/null
+++ b/board/musenki/flash.c
@@ -0,0 +1,513 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc824x.h>
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_FLASH
+
+#ifdef DEBUG_FLASH
+#define DEBUGF(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGF(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_char *addr, flash_info_t *info);
+static int write_data (flash_info_t *info, uchar *dest, uchar data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+
+
+/*
+ * don't ask.  its stupid, but more than one soul has had to live with this mistake
+ * "swaptab[i]" is the value of "i" with the bits reversed.
+ */
+
+#define  MUSENKI_BROKEN_FLASH 1
+
+#ifdef MUSENKI_BROKEN_FLASH
+unsigned char swaptab[256] = {
+  0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+  0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+  0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+  0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+  0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+  0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+  0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+  0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+  0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+  0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+  0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+  0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+  0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+  0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+  0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+  0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+  0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+  0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+  0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+  0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+  0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+  0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+  0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+  0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+  0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+  0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+  0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+  0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+  0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+  0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+  0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+  0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+#define BS(b)     (swaptab[b])
+
+#else
+
+#define BS(b)     (b)
+
+#endif
+
+#define BYTEME(x) ((x) & 0xFF)
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	DEBUGF("\n## Get flash bank 1 size @ 0x%08x\n",CFG_FLASH_BASE0_PRELIM);
+
+	size_b0 = flash_get_size((vu_char *)CFG_FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0: "
+			"ID 0x%lx, Size = 0x%08lx = %ld MB\n",
+			flash_info[0].flash_id,
+			size_b0, size_b0<<20);
+	}
+
+	DEBUGF("## Get flash bank 2 size @ 0x%08x\n",CFG_FLASH_BASE1_PRELIM);
+	size_b1 = flash_get_size((vu_char *)CFG_FLASH_BASE1_PRELIM, &flash_info[1]);
+
+	DEBUGF("## Prelim. Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_info[0].size = size_b0;
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	DEBUGF("protect monitor %x @ %x\n", CFG_MONITOR_BASE, CFG_MONITOR_LEN);
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+	/* ENV protection ON by default */
+	DEBUGF("protect environtment %x @ %x\n", CFG_ENV_ADDR, CFG_ENV_SECT_SIZE);
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+		      &flash_info[0]);
+#endif
+
+	if (size_b1) {
+		flash_info[1].size = size_b1;
+		flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+		/* monitor protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_MONITOR_BASE,
+			      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+			      &flash_info[1]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+		/* ENV protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_ENV_ADDR,
+			      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+			      &flash_info[1]);
+#endif
+	} else {
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+		flash_info[1].size = 0;
+	}
+
+	DEBUGF("## Final Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1);
+
+	return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_INTEL:
+	    for (i = 0; i < info->sector_count; i++) {
+		info->start[i] = base;
+		base += 0x00020000;		/* 128k per bank */
+	    }
+	    return;
+
+	default:
+	    printf ("Don't know sector ofsets for flash type 0x%lx\n", info->flash_id);
+	    return;
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("Fujitsu ");		break;
+	case FLASH_MAN_SST:	printf ("SST ");		break;
+	case FLASH_MAN_STM:	printf ("STM ");		break;
+	case FLASH_MAN_INTEL:	printf ("Intel ");		break;
+	case FLASH_MAN_MT:	printf ("MT ");			break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_28F320J3A:	printf ("28F320J3A (32Mbit = 128K x 32)\n");
+				break;
+	case FLASH_28F640J3A:	printf ("28F640J3A (64Mbit = 128K x 64)\n");
+				break;
+	case FLASH_28F128J3A:	printf ("28F128J3A (128Mbit = 128K x 128)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	if (info->size >= (1 << 20)) {
+		i = 20;
+	} else {
+		i = 10;
+	}
+	printf ("  Size: %ld %cB in %d Sectors\n",
+		info->size >> i,
+		(i == 20) ? 'M' : 'k',
+		info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+static ulong flash_get_size (vu_char *addr, flash_info_t *info)
+{
+	vu_char manuf, device;
+
+	addr[0] = BS(0x90);
+	manuf = BS(addr[0]);
+	DEBUGF("Manuf. ID @ 0x%08lx: 0x%08x\n", (vu_char *)addr, manuf);
+
+	switch (manuf) {
+	case BYTEME(AMD_MANUFACT):
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case BYTEME(FUJ_MANUFACT):
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	case BYTEME(SST_MANUFACT):
+		info->flash_id = FLASH_MAN_SST;
+		break;
+	case BYTEME(STM_MANUFACT):
+		info->flash_id = FLASH_MAN_STM;
+		break;
+	case BYTEME(INTEL_MANUFACT):
+		info->flash_id = FLASH_MAN_INTEL;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		addr[0] = BS(0xFF);		/* restore read mode, (yes, BS is a NOP) */
+		return 0;			/* no or unknown flash	*/
+	}
+
+	device = BS(addr[2]);			/* device ID		*/
+
+	DEBUGF("Device ID @ 0x%08x: 0x%08x\n", (&addr[1]), device);
+
+	switch (device) {
+	case BYTEME(INTEL_ID_28F320J3A):
+		info->flash_id += FLASH_28F320J3A;
+		info->sector_count = 32;
+		info->size = 0x00400000;
+		break;				/* =>  4 MB		*/
+
+	case BYTEME(INTEL_ID_28F640J3A):
+		info->flash_id += FLASH_28F640J3A;
+		info->sector_count = 64;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case BYTEME(INTEL_ID_28F128J3A):
+		info->flash_id += FLASH_28F128J3A;
+		info->sector_count = 128;
+		info->size = 0x01000000;
+		break;				/* => 16 MB		*/
+
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		addr[0] = BS(0xFF);		/* restore read mode (yes, a NOP) */
+		return 0;			/* => no or unknown flash */
+
+	}
+
+	if (info->sector_count > CFG_MAX_FLASH_SECT) {
+		printf ("** ERROR: sector count %d > max (%d) **\n",
+			info->sector_count, CFG_MAX_FLASH_SECT);
+		info->sector_count = CFG_MAX_FLASH_SECT;
+	}
+
+	addr[0] = BS(0xFF);		/* restore read mode */
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	int flag, prot, sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
+		printf ("Can erase only Intel flash types - aborted\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n", prot);
+	} else {
+		printf ("\n");
+	}
+
+	start = get_timer (0);
+	last  = start;
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			vu_char *addr = (vu_char *)(info->start[sect]);
+			unsigned long status;
+
+			/* Disable interrupts which might cause a timeout here */
+			flag = disable_interrupts();
+
+			*addr = BS(0x50);	/* clear status register */
+			*addr = BS(0x20);	/* erase setup */
+			*addr = BS(0xD0);	/* erase confirm */
+
+			/* re-enable interrupts if necessary */
+			if (flag) {
+				enable_interrupts();
+			}
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+
+			while (((status = BS(*addr)) & BYTEME(0x00800080)) != BYTEME(0x00800080)) {
+				if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout\n");
+					*addr = BS(0xB0); /* suspend erase	  */
+					*addr = BS(0xFF); /* reset to read mode */
+					return 1;
+				}
+
+				/* show that we're waiting */
+				if ((now - last) > 1000) {	/* every second */
+					putc ('.');
+					last = now;
+				}
+			}
+
+			*addr = BS(0xFF);	/* reset to read mode */
+		}
+	}
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 4 - Flash not identified
+ */
+
+#define	FLASH_WIDTH	1	/* flash bus width in bytes */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	uchar *wp = (uchar *)addr;
+	int rc;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return 4;
+	}
+
+	while (cnt > 0) {
+		if ((rc = write_data(info, wp, *src)) != 0) {
+			return rc;
+		}
+		wp++;
+		src++;
+		cnt--;
+	}
+
+	return cnt;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_data (flash_info_t *info, uchar *dest, uchar data)
+{
+	vu_char *addr = (vu_char *)dest;
+	ulong status;
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((BS(*addr) & data) != data) {
+		return 2;
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	*addr = BS(0x40);		/* write setup */
+	*addr = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag) {
+		enable_interrupts();
+	}
+
+	start = get_timer (0);
+
+	while (((status = BS(*addr)) & BYTEME(0x00800080)) != BYTEME(0x00800080)) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			*addr = BS(0xFF);	/* restore read mode */
+			return 1;
+		}
+	}
+
+	*addr = BS(0xFF);	/* restore read mode */
+
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/nx823/flash.c b/board/nx823/flash.c
new file mode 100644
index 0000000..616a13f
--- /dev/null
+++ b/board/nx823/flash.c
@@ -0,0 +1,465 @@
+/*
+ * (C) Copyright 2001
+ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
+ *
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+extern u_long  *my_sernum;		/* from nx823.c */
+
+/*-----------------------------------------------------------------------
+ * Protection Flags:
+ */
+#define FLAG_PROTECT_SET	0x01
+#define FLAG_PROTECT_CLEAR	0x02
+
+/* Board support for 1 or 2 flash devices */
+#undef FLASH_PORT_WIDTH32
+#define FLASH_PORT_WIDTH16
+
+#ifdef FLASH_PORT_WIDTH16
+#define FLASH_PORT_WIDTH		ushort
+#define FLASH_PORT_WIDTHV		vu_short
+#else
+#define FLASH_PORT_WIDTH		ulong
+#define FLASH_PORT_WIDTHV		vu_long
+#endif
+
+#define FPW		FLASH_PORT_WIDTH
+#define FPWV	FLASH_PORT_WIDTHV
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (FPW *addr, flash_info_t *info);
+static int   write_data (flash_info_t *info, ulong dest, FPW data);
+static void  flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+	size_b0 = flash_get_size((FPW *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_PS_16 | BR_MS_GPCM | BR_V;
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((FPW *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+	/* monitor protection ON by default */
+	(void)flash_protect(FLAG_PROTECT_SET,
+			    CFG_FLASH_BASE,
+			    CFG_FLASH_BASE+CFG_MONITOR_LEN-1,
+			    &flash_info[0]);
+
+	flash_info[0].size = size_b0;
+
+	return (size_b0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
+		for (i = 0; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000);
+		}
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+		case FLASH_MAN_INTEL:	printf ("INTEL ");		break;
+		default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+   case FLASH_28F320J3A:
+				printf ("28F320J3A\n"); break;
+   case FLASH_28F640J3A:
+				printf ("28F640J3A\n"); break;
+   case FLASH_28F128J3A:
+				printf ("28F128J3A\n"); break;
+	default:		printf ("Unknown Chip Type\n"); break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (FPW *addr, flash_info_t *info)
+{
+	FPW value;
+
+	/* Write auto select command: read Manufacturer ID */
+	addr[0x5555] = (FPW)0x00AA00AA;
+	addr[0x2AAA] = (FPW)0x00550055;
+	addr[0x5555] = (FPW)0x00900090;
+
+	value = addr[0];
+
+   switch (value) {
+   case (FPW)INTEL_MANUFACT:
+      info->flash_id = FLASH_MAN_INTEL;
+      break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		addr[0] = (FPW)0x00FF00FF;      /* restore read mode */
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr[1];			/* device ID		*/
+
+   switch (value) {
+   case (FPW)INTEL_ID_28F320J3A:
+      info->flash_id += FLASH_28F320J3A;
+      info->sector_count = 32;
+      info->size = 0x00400000;
+      break;            /* => 4 MB     */
+
+   case (FPW)INTEL_ID_28F640J3A:
+      info->flash_id += FLASH_28F640J3A;
+      info->sector_count = 64;
+      info->size = 0x00800000;
+      break;            /* => 8 MB     */
+
+   case (FPW)INTEL_ID_28F128J3A:
+      info->flash_id += FLASH_28F128J3A;
+      info->sector_count = 128;
+      info->size = 0x01000000;
+      break;            /* => 16 MB     */
+
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		break;
+	}
+
+	if (info->sector_count > CFG_MAX_FLASH_SECT) {
+		printf ("** ERROR: sector count %d > max (%d) **\n",
+			info->sector_count, CFG_MAX_FLASH_SECT);
+		info->sector_count = CFG_MAX_FLASH_SECT;
+	}
+
+	addr[0] = (FPW)0x00FF00FF;      /* restore read mode */
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	int flag, prot, sect;
+	ulong type, start, now, last;
+	int rcode = 0;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	type = (info->flash_id & FLASH_VENDMASK);
+	if ((type != FLASH_MAN_INTEL)) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	start = get_timer (0);
+	last  = start;
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			FPWV *addr = (FPWV *)(info->start[sect]);
+			FPW status;
+
+			/* Disable interrupts which might cause a timeout here */
+			flag = disable_interrupts();
+
+			*addr = (FPW)0x00500050;	/* clear status register */
+			*addr = (FPW)0x00200020;	/* erase setup */
+			*addr = (FPW)0x00D000D0;	/* erase confirm */
+
+			/* re-enable interrupts if necessary */
+			if (flag)
+				enable_interrupts();
+
+			/* wait at least 80us - let's wait 1 ms */
+			udelay (1000);
+
+			while (((status = *addr) & (FPW)0x00800080) != (FPW)0x00800080) {
+				if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout\n");
+					*addr = (FPW)0x00B000B0; /* suspend erase	  */
+					*addr = (FPW)0x00FF00FF; /* reset to read mode */
+					rcode = 1;
+					break;
+				}
+
+				/* show that we're waiting */
+			if ((now - last) > 1000) {	/* every second */
+					putc ('.');
+					last = now;
+				}
+			}
+
+			*addr = (FPW)0x00FF00FF;	/* reset to read mode */
+			printf (" done\n");
+		}
+	}
+	return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 4 - Flash not identified
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp;
+	FPW data;
+	int count, i, l, rc, port_width;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return 4;
+	}
+/* get lower word aligned address */
+#ifdef FLASH_PORT_WIDTH16
+	wp = (addr & ~1);
+	port_width = 2;
+#else
+	wp = (addr & ~3);
+	port_width = 4;
+#endif
+
+	/* save sernum if needed */
+	if (addr >= CFG_FLASH_SN_SECTOR && addr < CFG_FLASH_SN_BASE)
+	{
+		u_long dest = CFG_FLASH_SN_BASE;
+		u_short *sn = (u_short *)my_sernum;
+
+		printf("(saving sernum)");
+		for (i=0; i<4; i++)
+		{
+			if ((rc = write_data(info, dest, sn[i])) != 0) {
+				return (rc);
+			}
+			dest += port_width;
+		}
+	}
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<port_width && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<port_width; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_data(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += port_width;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	count = 0;
+	while (cnt >= port_width) {
+		data = 0;
+		for (i=0; i<port_width; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_data(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += port_width;
+		cnt -= port_width;
+		if (count++ > 0x800)
+		{
+			putc('.');
+			count = 0;
+		}
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<port_width && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<port_width; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_data(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word or halfword to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_data (flash_info_t *info, ulong dest, FPW data)
+{
+	FPWV *addr = (FPWV *)dest;
+	ulong status;
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*addr & data) != data) {
+		printf("not erased at %08lx (%x)\n",(ulong)addr,*addr);
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	*addr = (FPW)0x00400040;		/* write setup */
+	*addr = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	start = get_timer (0);
+
+	while (((status = *addr) & (FPW)0x00800080) != (FPW)0x00800080) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			*addr = (FPW)0x00FF00FF;	/* restore read mode */
+			return (1);
+		}
+	}
+
+	*addr = (FPW)0x00FF00FF;	/* restore read mode */
+
+	return (0);
+}
+
diff --git a/board/pcippc2/flash.c b/board/pcippc2/flash.c
new file mode 100644
index 0000000..20f4d03
--- /dev/null
+++ b/board/pcippc2/flash.c
@@ -0,0 +1,573 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <config.h>
+#include <common.h>
+#include <flash.h>
+#include <asm/io.h>
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_FLASH
+
+#ifdef DEBUG_FLASH
+#define DEBUGF(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGF(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS];
+
+static ulong flash_get_size (ulong addr, flash_info_t *info);
+static int flash_get_offsets (ulong base, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_reset (ulong addr);
+
+unsigned long flash_init (void)
+{
+	unsigned int i;
+	unsigned long flash_size = 0;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+		flash_info[i].sector_count = 0;
+		flash_info[i].size = 0;
+	}
+
+	DEBUGF("\n## Get flash size @ 0x%08x\n", CFG_FLASH_BASE);
+
+	flash_size = flash_get_size (CFG_FLASH_BASE, flash_info);
+
+	DEBUGF("## Flash bank size: %08lx\n", flash_size);
+
+	if (flash_size) {
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE && \
+    CFG_MONITOR_BASE < CFG_FLASH_BASE + CFG_FLASH_MAX_SIZE
+		/* monitor protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_MONITOR_BASE,
+			      CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1,
+			      &flash_info[0]);
+#endif
+
+#ifdef CFG_ENV_IS_IN_FLASH
+		/* ENV protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_ENV_ADDR,
+			      CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
+			      &flash_info[0]);
+#endif
+
+	} else {
+		puts ("Warning: the BOOT Flash is not initialised !");
+	}
+
+	return flash_size;
+}
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+static ulong flash_get_size (ulong addr, flash_info_t *info)
+{
+	short i;
+	uchar value;
+
+	/* Write auto select command: read Manufacturer ID */
+	out8(addr + 0x0555, 0xAA);
+	iobarrier_rw();
+	out8(addr + 0x02AA, 0x55);
+	iobarrier_rw();
+	out8(addr + 0x0555, 0x90);
+	iobarrier_rw();
+
+	value = in8(addr);
+	iobarrier_rw();
+
+	DEBUGF("Manuf. ID @ 0x%08lx: 0x%08x\n", (ulong)addr, value);
+
+	switch (value | (value << 16)) {
+		case AMD_MANUFACT:
+			info->flash_id = FLASH_MAN_AMD;
+			break;
+
+		case FUJ_MANUFACT:
+			info->flash_id = FLASH_MAN_FUJ;
+			break;
+
+		case STM_MANUFACT:
+			info->flash_id = FLASH_MAN_STM;
+			break;
+
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			info->sector_count = 0;
+			info->size = 0;
+			flash_reset (addr);
+			return 0;
+	}
+
+	value = in8(addr + 1);			/* device ID		*/
+	iobarrier_rw();
+
+	DEBUGF("Device ID @ 0x%08lx: 0x%08x\n", addr+1, value);
+
+	switch (value) {
+		case AMD_ID_F040B:
+			DEBUGF("Am29F040B\n");
+			info->flash_id += FLASH_AM040;
+			info->sector_count = 8;
+			info->size = 0x00080000;
+			break;			/* => 512 kB		*/
+
+		case AMD_ID_LV040B:
+			DEBUGF("Am29LV040B\n");
+			info->flash_id += FLASH_AM040;
+			info->sector_count = 8;
+			info->size = 0x00080000;
+			break;			/* => 512 kB		*/
+
+		case AMD_ID_LV400T:
+			DEBUGF("Am29LV400T\n");
+			info->flash_id += FLASH_AM400T;
+			info->sector_count = 11;
+			info->size = 0x00100000;
+			break;			/* => 1 MB		*/
+
+		case AMD_ID_LV400B:
+			DEBUGF("Am29LV400B\n");
+			info->flash_id += FLASH_AM400B;
+			info->sector_count = 11;
+			info->size = 0x00100000;
+			break;			/* => 1 MB		*/
+
+		case AMD_ID_LV800T:
+			DEBUGF("Am29LV800T\n");
+			info->flash_id += FLASH_AM800T;
+			info->sector_count = 19;
+			info->size = 0x00200000;
+			break;			/* => 2 MB		*/
+
+		case AMD_ID_LV800B:
+			DEBUGF("Am29LV400B\n");
+			info->flash_id += FLASH_AM800B;
+			info->sector_count = 19;
+			info->size = 0x00200000;
+			break;			/* => 2 MB		*/
+
+		case AMD_ID_LV160T:
+			DEBUGF("Am29LV160T\n");
+			info->flash_id += FLASH_AM160T;
+			info->sector_count = 35;
+			info->size = 0x00400000;
+			break;			/* => 4 MB		*/
+
+		case AMD_ID_LV160B:
+			DEBUGF("Am29LV160B\n");
+			info->flash_id += FLASH_AM160B;
+			info->sector_count = 35;
+			info->size = 0x00400000;
+			break;			/* => 4 MB		*/
+
+		case AMD_ID_LV320T:
+			DEBUGF("Am29LV320T\n");
+			info->flash_id += FLASH_AM320T;
+			info->sector_count = 67;
+			info->size = 0x00800000;
+			break;			/* => 8 MB		*/
+
+#if 0
+		/* Has the same ID as AMD_ID_LV320T, to be fixed */
+		case AMD_ID_LV320B:
+			DEBUGF("Am29LV320B\n");
+			info->flash_id += FLASH_AM320B;
+			info->sector_count = 67;
+			info->size = 0x00800000;
+			break;			/* => 8 MB		*/
+#endif
+
+		case AMD_ID_LV033C:
+			DEBUGF("Am29LV033C\n");
+			info->flash_id += FLASH_AM033C;
+			info->sector_count = 64;
+			info->size = 0x01000000;
+			break;			/* => 16Mb		*/
+
+		case STM_ID_F040B:
+			DEBUGF("M29F040B\n");
+			info->flash_id += FLASH_AM040;
+			info->sector_count = 8;
+			info->size = 0x00080000;
+			break;			/* => 512 kB		*/
+
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			flash_reset (addr);
+			return (0);		/* => no or unknown flash */
+
+	}
+
+	if (info->sector_count > CFG_MAX_FLASH_SECT) {
+		printf ("** ERROR: sector count %d > max (%d) **\n",
+			info->sector_count, CFG_MAX_FLASH_SECT);
+		info->sector_count = CFG_MAX_FLASH_SECT;
+	}
+
+	if (! flash_get_offsets (addr, info)) {
+		flash_reset (addr);
+		return 0;
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		value = in8(info->start[i] + 2);
+		iobarrier_rw();
+		info->protect[i] = (value & 1) != 0;
+	}
+
+	/*
+	 * Reset bank to read mode
+	 */
+	flash_reset (addr);
+
+	return (info->size);
+}
+
+static int flash_get_offsets (ulong base, flash_info_t *info)
+{
+	unsigned int i;
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+		case FLASH_AM040:
+			/* set sector offsets for uniform sector type	*/
+			for (i = 0; i < info->sector_count; i++) {
+				info->start[i] = base + i * info->size /
+				                            info->sector_count;
+			}
+			break;
+		default:
+			return 0;
+	}
+
+	return 1;
+}
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	volatile ulong addr = info->start[0];
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if (s_first < 0 || s_first > s_last) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	out8(addr + 0x555, 0xAA);
+	iobarrier_rw();
+	out8(addr + 0x2AA, 0x55);
+	iobarrier_rw();
+	out8(addr + 0x555, 0x80);
+	iobarrier_rw();
+	out8(addr + 0x555, 0xAA);
+	iobarrier_rw();
+	out8(addr + 0x2AA, 0x55);
+	iobarrier_rw();
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = info->start[sect];
+			out8(addr, 0x30);
+			iobarrier_rw();
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = info->start[l_sect];
+
+	DEBUGF ("Start erase timeout: %d\n", CFG_FLASH_ERASE_TOUT);
+
+	while ((in8(addr) & 0x80) != 0x80) {
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			flash_reset (info->start[0]);
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+		iobarrier_rw();
+	}
+
+DONE:
+	/* reset to read mode */
+	flash_reset (info->start[0]);
+
+	printf (" done\n");
+	return 0;
+}
+
+/*
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	volatile ulong addr = info->start[0];
+	ulong start;
+	int i;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((in32(dest) & data) != data) {
+		return (2);
+	}
+
+	/* write each byte out */
+	for (i = 0; i < 4; i++) {
+		char *data_ch = (char *)&data;
+		int flag = disable_interrupts();
+
+		out8(addr + 0x555, 0xAA);
+		iobarrier_rw();
+		out8(addr + 0x2AA, 0x55);
+		iobarrier_rw();
+		out8(addr + 0x555, 0xA0);
+		iobarrier_rw();
+		out8(dest+i, data_ch[i]);
+		iobarrier_rw();
+
+		/* re-enable interrupts if necessary */
+		if (flag)
+			enable_interrupts();
+
+		/* data polling for D7 */
+		start = get_timer (0);
+		while ((in8(dest+i) & 0x80) != (data_ch[i] & 0x80)) {
+			if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+				flash_reset (addr);
+				return (1);
+			}
+			iobarrier_rw();
+		}
+	}
+
+	flash_reset (addr);
+	return (0);
+}
+
+/*
+ * Reset bank to read mode
+ */
+static void flash_reset (ulong addr)
+{
+	out8(addr, 0xF0);	/* reset bank */
+	iobarrier_rw();
+}
+
+void flash_print_info (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	case FLASH_MAN_BM:	printf ("BRIGHT MICRO ");	break;
+	case FLASH_MAN_STM:	printf ("SGS THOMSON ");	break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM040:	printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n");
+				break;
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	if (info->size % 0x100000 == 0) {
+		printf ("  Size: %ld MB in %d Sectors\n",
+			info->size / 0x100000, info->sector_count);
+	} else if (info->size % 0x400 == 0) {
+		printf ("  Size: %ld KB in %d Sectors\n",
+		        info->size / 0x400, info->sector_count);
+	} else {
+		printf ("  Size: %ld B in %d Sectors\n",
+		        info->size, info->sector_count);
+	}
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+}
diff --git a/board/pcippc2/pcippc2.h b/board/pcippc2/pcippc2.h
new file mode 100644
index 0000000..6e9e2ff
--- /dev/null
+++ b/board/pcippc2/pcippc2.h
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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
+ */
+
+#ifndef _PCIPPC2_H_
+#define _PCIPPC2_H_
+
+#include <config.h>
+#include <common.h>
+
+#include "hardware.h"
+
+#define FPGA(r, p)	(pcippc2_fpga0_phys + HW_FPGA0_##r##_##p)
+#define UART(r)		(pcippc2_fpga0_phys + HW_FPGA0_UART1 + NS16550_##r * 4)
+#define RTC(r)		(pcippc2_fpga1_phys + HW_FPGA1_RTC + r)
+
+extern u32		pcippc2_fpga0_phys;
+extern u32		pcippc2_fpga1_phys;
+
+extern u32	pcippc2_sdram_size		(void);
+
+extern void 	pcippc2_fpga_init		(void);
+
+extern void 	cpc710_pci_init			(void);
+extern void	cpc710_pci_enable_timeout	(void);
+
+extern unsigned long
+		cpc710_ram_init			(void);
+
+#endif
diff --git a/board/pcippc2/pcippc2_fpga.c b/board/pcippc2/pcippc2_fpga.c
new file mode 100644
index 0000000..7f6739d
--- /dev/null
+++ b/board/pcippc2/pcippc2_fpga.c
@@ -0,0 +1,87 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <config.h>
+#include <common.h>
+#include <asm/io.h>
+
+#include "pci.h"
+
+#include "hardware.h"
+#include "pcippc2.h"
+
+u32		pcippc2_fpga0_phys;
+u32		pcippc2_fpga1_phys;
+
+void pcippc2_fpga_init (void)
+{
+  pci_dev_t		bdf = pci_find_device(FPGA_VENDOR_ID, FPGA_DEVICE_ID, 0);
+  unsigned int		addr;
+  u16			cmd;
+
+  if (bdf == -1)
+  {
+    puts("Unable to find FPGA !\n");
+    hang();
+  }
+
+  pci_read_config_word(bdf, PCI_COMMAND, &cmd);
+  if ((cmd & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)) != (PCI_COMMAND_MEMORY | PCI_COMMAND_IO))
+  {
+    puts("FPGA is not configured !\n");
+    hang();
+  }
+
+  pci_read_config_dword(bdf, PCI_BASE_ADDRESS_0, &addr);
+  if (addr & 0x1)
+  {
+      /* IO space
+       */
+    pcippc2_fpga0_phys = pci_io_to_phys(bdf, addr & 0xfffffffc);
+  }
+  else
+  {
+      /* Memory space
+       */
+    pcippc2_fpga0_phys = pci_mem_to_phys(bdf, addr & 0xfffffff0);
+  }
+
+  pci_read_config_dword(bdf, PCI_BASE_ADDRESS_1, &addr);
+  if (addr & 0x1)
+  {
+      /* IO space
+       */
+    pcippc2_fpga1_phys = pci_io_to_phys(bdf, addr & 0xfffffffc);
+  }
+  else
+  {
+      /* Memory space
+       */
+    pcippc2_fpga1_phys = pci_mem_to_phys(bdf, addr & 0xfffffff0);
+  }
+
+    /* Interrupts are not used
+     */
+  out32(FPGA(INT, INTR_MASK), 0xffffffff);
+  iobarrier_rw();
+}
diff --git a/board/rpxsuper/flash.c b/board/rpxsuper/flash.c
new file mode 100644
index 0000000..0c298ba
--- /dev/null
+++ b/board/rpxsuper/flash.c
@@ -0,0 +1,434 @@
+/*
+ * (C) Copyright 2000
+ * Marius Groeger <mgroeger@sysgo.de>
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for AMD 29F080B devices
+ * Added support for 64bit and AMD 29DL323B
+ *
+ *--------------------------------------------------------------------
+ * 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 <mpc8xx.h>
+#include <asm/io.h>
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+#define RD_SWP32(x) in_le32((volatile u32*)x)
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+    unsigned long size;
+    int i;
+
+    /* Init: no FLASHes known */
+    for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+	flash_info[i].flash_id = FLASH_UNKNOWN;
+    }
+
+    /* for now, only support the 4 MB Flash SIMM */
+    size = flash_get_size((vu_long *)CFG_FLASH0_BASE, &flash_info[0]);
+
+    /*
+     * protect monitor and environment sectors
+     */
+
+#if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
+    flash_protect(FLAG_PROTECT_SET,
+		  CFG_MONITOR_BASE,
+		  CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		  &flash_info[0]);
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+    flash_protect(FLAG_PROTECT_SET,
+		  CFG_ENV_ADDR,
+		  CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+		  &flash_info[0]);
+#endif
+
+    return /*size*/ (CFG_FLASH0_SIZE * 1024 * 1024);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+    int i;
+
+    if (info->flash_id == FLASH_UNKNOWN) {
+	printf ("missing or unknown FLASH type\n");
+	return;
+    }
+
+    switch (info->flash_id & FLASH_VENDMASK) {
+    case (AMD_MANUFACT & FLASH_VENDMASK):
+	printf ("AMD ");
+	break;
+    case (FUJ_MANUFACT & FLASH_VENDMASK):
+	printf ("FUJITSU ");
+	break;
+    case (SST_MANUFACT & FLASH_VENDMASK):
+	printf ("SST ");
+	break;
+    default:
+	printf ("Unknown Vendor ");
+	break;
+    }
+
+    switch (info->flash_id & FLASH_TYPEMASK) {
+    case (AMD_ID_DL323B & FLASH_TYPEMASK):
+	printf("AM29DL323B (32 MBit)\n");
+	break;
+    default:
+	printf ("Unknown Chip Type\n");
+	break;
+    }
+
+    printf ("  Size: %ld MB in %d Sectors\n",
+	    info->size >> 20, info->sector_count);
+
+    printf ("  Sector Start Addresses:");
+    for (i = 0; i < info->sector_count; ++i) {
+	if ((i % 5) == 0) printf ("\n   ");
+	printf (" %08lX%s",
+		info->start[i],
+		info->protect[i] ? " (RO)" : "     "
+		);
+    }
+    printf ("\n");
+    return;
+}
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+    short i;
+    vu_long vendor[2], devid[2];
+    ulong base = (ulong)addr;
+
+    /* Reset and Write auto select command: read Manufacturer ID */
+    addr[0] = 0xf0f0f0f0;
+    addr[2 * 0x0555] = 0xAAAAAAAA;
+    addr[2 * 0x02AA] = 0x55555555;
+    addr[2 * 0x0555] = 0x90909090;
+    addr[1] = 0xf0f0f0f0;
+    addr[2 * 0x0555 + 1] = 0xAAAAAAAA;
+    addr[2 * 0x02AA + 1] = 0x55555555;
+    addr[2 * 0x0555 + 1] = 0x90909090;
+    udelay (1000);
+
+    vendor[0] = RD_SWP32(&addr[0]);
+    vendor[1] = RD_SWP32(&addr[1]);
+    if (vendor[0] != vendor[1] || vendor[0] != AMD_MANUFACT) {
+	info->size = 0;
+	goto out;
+    }
+
+    devid[0] = RD_SWP32(&addr[2]);
+    devid[1] = RD_SWP32(&addr[3]);
+
+    if (devid[0] == AMD_ID_DL323B) {
+	/*
+	* we have 2 Banks
+	* Bank 1 (23 Sectors): 0-7=8kbyte, 8-22=64kbyte
+	* Bank 2 (48 Sectors): 23-70=64kbyte
+	*/
+	info->flash_id     = (AMD_MANUFACT & FLASH_VENDMASK) |
+                             (AMD_ID_DL323B & FLASH_TYPEMASK);
+	info->sector_count = 71;
+	info->size         = 4 * (8 * 8 + 63 * 64) * 1024;
+    }
+    else {
+	info->size = 0;
+	goto out;
+    }
+
+    /* set up sector start address table */
+    for (i = 0; i < 8; i++) {
+        info->start[i] = base + (i * 0x8000);
+    }
+    for (i = 8; i < info->sector_count; i++) {
+        info->start[i] = base + (i * 0x40000) + 8 * 0x8000 - 8 * 0x40000;
+    }
+
+    /* check for protected sectors */
+    for (i = 0; i < info->sector_count; i++) {
+        /* read sector protection at sector address */
+	addr = (volatile unsigned long *)(info->start[i]);
+        addr[2 * 0x0555] = 0xAAAAAAAA;
+	addr[2 * 0x02AA] = 0x55555555;
+	addr[2 * 0x0555] = 0x90909090;
+	addr[2 * 0x0555 + 1] = 0xAAAAAAAA;
+	addr[2 * 0x02AA + 1] = 0x55555555;
+	addr[2 * 0x0555 + 1] = 0x90909090;
+	udelay (1000);
+    	base = RD_SWP32(&addr[4]);
+	base |= RD_SWP32(&addr[5]);
+	info->protect[i] = base & 0x00010001 ? 1 : 0;
+    }
+    addr = (vu_long*)info->start[0];
+
+out:
+    /* reset command */
+    addr[0] = 0xf0f0f0f0;
+    addr[1] = 0xf0f0f0f0;
+
+    return info->size;
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+    vu_long *addr = (vu_long*)(info->start[0]);
+    int flag, prot, sect, l_sect;
+    ulong start, now, last;
+
+    if ((s_first < 0) || (s_first > s_last)) {
+	if (info->flash_id == FLASH_UNKNOWN) {
+	    printf ("- missing\n");
+	} else {
+	    printf ("- no sectors to erase\n");
+	}
+	return 1;
+    }
+
+    prot = 0;
+    for (sect = s_first; sect <= s_last; sect++) {
+	if (info->protect[sect]) {
+	    prot++;
+	}
+    }
+
+    if (prot) {
+	printf ("- Warning: %d protected sectors will not be erased!\n",
+		prot);
+    } else {
+	printf ("\n");
+    }
+
+    l_sect = -1;
+
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    addr[2 * 0x0555] = 0xAAAAAAAA;
+    addr[2 * 0x02AA] = 0x55555555;
+    addr[2 * 0x0555] = 0x80808080;
+    addr[2 * 0x0555] = 0xAAAAAAAA;
+    addr[2 * 0x02AA] = 0x55555555;
+    addr[2 * 0x0555 + 1] = 0xAAAAAAAA;
+    addr[2 * 0x02AA + 1] = 0x55555555;
+    addr[2 * 0x0555 + 1] = 0x80808080;
+    addr[2 * 0x0555 + 1] = 0xAAAAAAAA;
+    addr[2 * 0x02AA + 1] = 0x55555555;
+    udelay (100);
+
+    /* Start erase on unprotected sectors */
+    for (sect = s_first; sect<=s_last; sect++) {
+	if (info->protect[sect] == 0) {	/* not protected */
+	    addr = (vu_long*)(info->start[sect]);
+	    addr[0] = 0x30303030;
+	    addr[1] = 0x30303030;
+	    l_sect = sect;
+	}
+    }
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+      enable_interrupts();
+
+    /* wait at least 80us - let's wait 1 ms */
+    udelay (1000);
+
+    /*
+     * We wait for the last triggered sector
+     */
+    if (l_sect < 0)
+      goto DONE;
+
+    start = get_timer (0);
+    last  = start;
+    addr = (vu_long*)(info->start[l_sect]);
+    while (	(addr[0] & 0x80808080) != 0x80808080 ||
+		(addr[1] & 0x80808080) != 0x80808080) {
+	if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+	    printf ("Timeout\n");
+	    return 1;
+	}
+	/* show that we're waiting */
+	if ((now - last) > 1000) {	/* every second */
+	    serial_putc ('.');
+	    last = now;
+	}
+    }
+
+    DONE:
+    /* reset to read mode */
+    addr = (volatile unsigned long *)info->start[0];
+    addr[0] = 0xF0F0F0F0;	/* reset bank */
+    addr[1] = 0xF0F0F0F0;	/* reset bank */
+
+    printf (" done\n");
+    return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+    ulong cp, wp, data;
+    int i, l, rc;
+
+    wp = (addr & ~3);	/* get lower word aligned address */
+
+    /*
+     * handle unaligned start bytes
+     */
+    if ((l = addr - wp) != 0) {
+	data = 0;
+	for (i=0, cp=wp; i<l; ++i, ++cp) {
+	    data = (data << 8) | (*(uchar *)cp);
+	}
+	for (; i<4 && cnt>0; ++i) {
+	    data = (data << 8) | *src++;
+	    --cnt;
+	    ++cp;
+	}
+	for (; cnt==0 && i<4; ++i, ++cp) {
+	    data = (data << 8) | (*(uchar *)cp);
+	}
+
+	if ((rc = write_word(info, wp, data)) != 0) {
+	    return (rc);
+	}
+	wp += 4;
+    }
+
+    /*
+     * handle word aligned part
+     */
+    while (cnt >= 4) {
+	data = 0;
+	for (i=0; i<4; ++i) {
+	    data = (data << 8) | *src++;
+	}
+	if ((rc = write_word(info, wp, data)) != 0) {
+	    return (rc);
+	}
+	wp  += 4;
+	cnt -= 4;
+    }
+
+    if (cnt == 0) {
+	return (0);
+    }
+
+    /*
+     * handle unaligned tail bytes
+     */
+    data = 0;
+    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+	data = (data << 8) | *src++;
+	--cnt;
+    }
+    for (; i<4; ++i, ++cp) {
+	data = (data << 8) | (*(uchar *)cp);
+    }
+
+    return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+    vu_long *addr = (vu_long*)(info->start[0]);
+    ulong start;
+    int flag;
+
+    /* Check if Flash is (sufficiently) erased */
+    if ((*((vu_long *)dest) & data) != data) {
+	return (2);
+    }
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    if ((dest & 0x00000004) == 0) {
+        addr[2 * 0x0555] = 0xAAAAAAAA;
+	addr[2 * 0x02AA] = 0x55555555;
+        addr[2 * 0x0555] = 0xA0A0A0A0;
+    }
+    else {
+        addr[2 * 0x0555 + 1] = 0xAAAAAAAA;
+	addr[2 * 0x02AA + 1] = 0x55555555;
+        addr[2 * 0x0555 + 1] = 0xA0A0A0A0;
+    }
+
+    *((vu_long *)dest) = data;
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+      enable_interrupts();
+
+    /* data polling for D7 */
+    start = get_timer (0);
+    while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
+	if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+	    return (1);
+	}
+    }
+    return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/rpxsuper/mii_phy.c b/board/rpxsuper/mii_phy.c
new file mode 100644
index 0000000..319f959
--- /dev/null
+++ b/board/rpxsuper/mii_phy.c
@@ -0,0 +1,108 @@
+#include <common.h>
+#include <mii_phy.h>
+#include "rpxsuper.h"
+
+#define MII_MDIO	0x01
+#define MII_MDCK	0x02
+#define MII_MDIR	0x04
+
+void
+mii_discover_phy(void)
+{
+    int known;
+    unsigned short phy_reg;
+    unsigned long phy_id;
+
+    known = 0;
+    printf("Discovering phy @ 0: ");
+    phy_id = mii_phy_read(2) << 16;
+    phy_id |= mii_phy_read(3);
+    if ((phy_id & 0xFFFFFC00) == 0x00137800) {
+	printf("Level One ");
+	if ((phy_id & 0x000003F0) == 0xE0) {
+	    printf("LXT971A Revision %d\n", (int)(phy_id & 0xF));
+	    known = 1;
+	}
+	else printf("unknown type\n");
+    }
+    else printf("unknown OUI = 0x%08lX\n", phy_id);
+
+    phy_reg = mii_phy_read(1);
+    if (!(phy_reg & 0x0004)) printf("Link is down\n");
+    if (!(phy_reg & 0x0020)) printf("Auto-negotiation not complete\n");
+    if (phy_reg & 0x0002) printf("Jabber condition detected\n");
+    if (phy_reg & 0x0010) printf("Remote fault condition detected \n");
+
+    if (known) {
+	phy_reg = mii_phy_read(17);
+	if (phy_reg & 0x0400)
+	    printf("Phy operating at %d MBit/s in %s-duplex mode\n",
+		phy_reg & 0x4000 ? 100 : 10,
+	    	phy_reg & 0x0200 ? "full" : "half");
+	else
+	    printf("bad link!!\n");
+/*
+left  off: no link, green 100MBit, yellow 10MBit
+right off: no activity, green full-duplex, yellow half-duplex
+*/
+	mii_phy_write(20, 0x0452);
+    }
+}
+
+unsigned short
+mii_phy_read(unsigned short reg)
+{
+    int i;
+    unsigned short tmp, val = 0, adr = 0;
+    t_rpx_regs *regs = (t_rpx_regs*)CFG_REGS_BASE;
+
+    tmp = 0x6002 | (adr << 7) | (reg << 2);
+    regs->bcsr4 = 0xC3;
+    for (i = 0; i < 64; i++) {
+        regs->bcsr4 ^= MII_MDCK;
+    }
+    for (i = 0; i < 16; i++) {
+	regs->bcsr4 &= ~MII_MDCK;
+	if (tmp & 0x8000) regs->bcsr4 |= MII_MDIO;
+	else regs->bcsr4 &= ~MII_MDIO;
+	regs->bcsr4 |= MII_MDCK;
+	tmp <<= 1;
+    }
+    regs->bcsr4 |= MII_MDIR;
+    for (i = 0; i < 16; i++) {
+	val <<= 1;
+	regs->bcsr4 = MII_MDIO | (regs->bcsr4 | MII_MDCK);
+	if (regs->bcsr4 & MII_MDIO) val |= 1;
+	regs->bcsr4 = MII_MDIO | (regs->bcsr4 &= ~MII_MDCK);
+    }
+    return val;
+}
+
+void
+mii_phy_write(unsigned short reg, unsigned short val)
+{
+    int i;
+    unsigned short tmp, adr = 0;
+    t_rpx_regs *regs = (t_rpx_regs*)CFG_REGS_BASE;
+
+    tmp = 0x5002 | (adr << 7) | (reg << 2);
+    regs->bcsr4 = 0xC3;
+    for (i = 0; i < 64; i++) {
+	regs->bcsr4 ^= MII_MDCK;
+    }
+    for (i = 0; i < 16; i++) {
+	regs->bcsr4 &= ~MII_MDCK;
+        if (tmp & 0x8000) regs->bcsr4 |= MII_MDIO;
+	else regs->bcsr4 &= ~MII_MDIO;
+	regs->bcsr4 |= MII_MDCK;
+	tmp <<= 1;
+    }
+    for (i = 0; i < 16; i++) {
+	regs->bcsr4 &= ~MII_MDCK;
+	if (val & 0x8000) regs->bcsr4 |= MII_MDIO;
+	else regs->bcsr4 &= ~MII_MDIO;
+	regs->bcsr4 |= MII_MDCK;
+	val <<= 1;
+    }
+}
+
diff --git a/board/rsdproto/flash.c b/board/rsdproto/flash.c
new file mode 100644
index 0000000..654012f
--- /dev/null
+++ b/board/rsdproto/flash.c
@@ -0,0 +1,402 @@
+/*
+ * (C) Copyright 2000
+ * Marius Groeger <mgroeger@sysgo.de>
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for AM290[48]0B devices
+ *
+ *--------------------------------------------------------------------
+ * 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 <mpc8xx.h>
+
+/* flash hardware ids */
+#define VENDOR_AMD     0x0001
+#define AMD_29DL323C_B 0x2253
+
+/* Define this to include autoselect sequence in flash_init(). Does NOT
+ * work when executing from flash itself, so this should be turned
+ * on only when debugging the RAM version.
+ */
+#undef WITH_AUTOSELECT
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+#if 1
+#define D(x)
+#else
+#define D(x) printf x
+#endif
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+
+static unsigned char write_ull(flash_info_t *info,
+			       unsigned long address,
+			       volatile unsigned long long data);
+
+/* from flash_asm.S */
+extern void ull_write(unsigned long long volatile *address,
+                      unsigned long long volatile *data);
+extern void ull_read(unsigned long long volatile *address,
+                     unsigned long long volatile *data);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+    int i;
+    ulong addr;
+
+#ifdef WITH_AUTOSELECT
+	{
+		unsigned long long *f_addr = (unsigned long long *)PHYS_FLASH;
+		unsigned long long f_command, vendor, device;
+		/* Perform Autoselect */
+		f_command 	= 0x00AA00AA00AA00AAULL;
+		ull_write(&f_addr[0x555], &f_command);
+		f_command 	= 0x0055005500550055ULL;
+		ull_write(&f_addr[0x2AA], &f_command);
+		f_command 	= 0x0090009000900090ULL;
+		ull_write(&f_addr[0x555], &f_command);
+		ull_read(&f_addr[0], &vendor);
+		vendor &= 0xffff;
+		ull_read(&f_addr[1], &device);
+		device &= 0xffff;
+		f_command 	= 0x00F000F000F000F0ULL;
+		ull_write(&f_addr[0x555], &f_command);
+		if (vendor != VENDOR_AMD || device != AMD_29DL323C_B)
+		  return 0;
+	}
+#endif
+
+    /* Init: no FLASHes known */
+    for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+    }
+
+	/* 1st bank: 8 x 32 KB sectors */
+	flash_info[0].flash_id = VENDOR_AMD << 16 | AMD_29DL323C_B;
+	flash_info[0].sector_count = 8;
+	flash_info[0].size = flash_info[0].sector_count * 32 * 1024;
+	addr = PHYS_FLASH;
+    for(i = 0; i < flash_info[0].sector_count; i++) {
+		flash_info[0].start[i] = addr;
+		addr += flash_info[0].size / flash_info[0].sector_count;
+	}
+	/* 1st bank: 63 x 256 KB sectors */
+	flash_info[1].flash_id = VENDOR_AMD << 16 | AMD_29DL323C_B;
+	flash_info[1].sector_count = 63;
+	flash_info[1].size = flash_info[1].sector_count * 256 * 1024;
+    for(i = 0; i < flash_info[1].sector_count; i++) {
+		flash_info[1].start[i] = addr;
+		addr += flash_info[1].size / flash_info[1].sector_count;
+	}
+
+	/*
+	 * protect monitor and environment sectors
+	 */
+
+#if CFG_MONITOR_BASE >= PHYS_FLASH
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[1]);
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+		      &flash_info[0]);
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+		      &flash_info[1]);
+#endif
+
+    return flash_info[0].size + flash_info[1].size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+    int i;
+
+    if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+    }
+
+    switch (info->flash_id >> 16) {
+    case VENDOR_AMD:
+		printf ("AMD ");
+		break;
+    default:
+		printf ("Unknown Vendor ");
+		break;
+    }
+
+    switch (info->flash_id & FLASH_TYPEMASK) {
+    case AMD_29DL323C_B:
+		printf ("AM29DL323CB (32 Mbit)\n");
+		break;
+    default:
+		printf ("Unknown Chip Type\n");
+		break;
+    }
+
+    printf ("  Size: %ld MB in %d Sectors\n",
+			info->size >> 20, info->sector_count);
+
+    printf ("  Sector Start Addresses:");
+    for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+		  printf ("\n   ");
+		printf (" %08lX%s",
+				info->start[i],
+				info->protect[i] ? " (RO)" : "     "
+				);
+    }
+    printf ("\n");
+    return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+    int flag, prot, sect, l_sect;
+    ulong start;
+	unsigned long long volatile *f_addr;
+	unsigned long long volatile f_command;
+
+    if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+    }
+
+    prot = 0;
+    for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+    }
+    if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+				prot);
+    } else {
+		printf ("\n");
+    }
+
+	f_addr 	= (unsigned long long *)info->start[0];
+	f_command 	= 0x00AA00AA00AA00AAULL;
+	ull_write(&f_addr[0x555], &f_command);
+	f_command 	= 0x0055005500550055ULL;
+	ull_write(&f_addr[0x2AA], &f_command);
+	f_command 	= 0x0080008000800080ULL;
+	ull_write(&f_addr[0x555], &f_command);
+	f_command 	= 0x00AA00AA00AA00AAULL;
+	ull_write(&f_addr[0x555], &f_command);
+	f_command 	= 0x0055005500550055ULL;
+	ull_write(&f_addr[0x2AA], &f_command);
+
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    /* Start erase on unprotected sectors */
+    for (l_sect = -1, sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+
+			f_addr 	=
+			  (unsigned long long *)(info->start[sect]);
+			f_command 	= 0x0030003000300030ULL;
+			ull_write(f_addr, &f_command);
+			l_sect = sect;
+		}
+    }
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+      enable_interrupts();
+
+	start = get_timer (0);
+	do
+	{
+		if (get_timer(start) > CFG_FLASH_ERASE_TOUT)
+		{	/* write reset command, command address is unimportant */
+			/* this command turns the flash back to read mode     */
+			f_addr =
+			  (unsigned long long *)(info->start[l_sect]);
+			f_command 	= 0x00F000F000F000F0ULL;
+			ull_write(f_addr, &f_command);
+			printf (" timeout\n");
+			return 1;
+        }
+	} while(*f_addr != 0xFFFFFFFFFFFFFFFFULL);
+
+    printf (" done\n");
+    return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+    unsigned long cp, wp;
+	unsigned long long data;
+    int i, l, rc;
+
+    wp = (addr & ~7);	/* get lower long long aligned address */
+
+    /*
+     * handle unaligned start bytes
+     */
+    if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<8 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<8; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_ull(info, wp, data)) != 0) {
+			return rc;
+		}
+		wp += 4;
+    }
+
+    /*
+     * handle long long aligned part
+     */
+    while (cnt >= 8) {
+		data = 0;
+		for (i=0; i<8; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_ull(info, wp, data)) != 0) {
+			return rc;
+		}
+		wp  += 8;
+		cnt -= 8;
+    }
+
+    if (cnt == 0) {
+		return ERR_OK;
+    }
+
+    /*
+     * handle unaligned tail bytes
+     */
+    data = 0;
+    for (i=0, cp=wp; i<8 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+    }
+    for (; i<8; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+    }
+
+    return write_ull(info, wp, data);
+}
+
+/*---------------------------------------------------------------------------
+*
+* FUNCTION NAME:  write_ull
+*
+* DESCRIPTION:   writes 8 bytes to flash
+*
+* EXTERNAL EFFECT: nothing
+*
+* PARAMETERS:   32 bit long pointer to address, 64 bit long pointer to data
+*
+* RETURNS: 	0 if OK, 1 if timeout, 4 if parameter error
+*--------------------------------------------------------------------------*/
+
+static unsigned char write_ull(flash_info_t *info,
+							   unsigned long address,
+							   volatile unsigned long long data)
+{
+	static unsigned long long f_command;
+	static unsigned long long *f_addr;
+	ulong start;
+
+	/* address muss be 8-aligned! */
+	if (address & 0x7)
+	  return ERR_ALIGN;
+
+	f_addr 	= (unsigned long long *)info->start[0];
+	f_command 	= 0x00AA00AA00AA00AAULL;
+	ull_write(&f_addr[0x555], &f_command);
+	f_command 	= 0x0055005500550055ULL;
+	ull_write(&f_addr[0x2AA], &f_command);
+	f_command 	= 0x00A000A000A000A0ULL;
+	ull_write(&f_addr[0x555], &f_command);
+
+	f_addr 	= (unsigned long long *)address;
+	f_command 	= data;
+	ull_write(f_addr, &f_command);
+
+	start = get_timer (0);
+	do
+	{
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
+		{
+			/* write reset command, command address is unimportant */
+			/* this command turns the flash back to read mode     */
+			f_addr 	= (unsigned long long *)info->start[0];
+			f_command 	= 0x00F000F000F000F0ULL;
+			ull_write(f_addr, &f_command);
+			return ERR_TIMOUT;
+		}
+	} while(*((unsigned long long *)address) != data);
+
+	return 0;
+}
diff --git a/board/siemens/CCM/flash.c b/board/siemens/CCM/flash.c
new file mode 100644
index 0000000..e56114f
--- /dev/null
+++ b/board/siemens/CCM/flash.c
@@ -0,0 +1,553 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+	size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+
+	if (size_b1 > size_b0) {
+		printf ("## ERROR: "
+			"Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
+			size_b1, size_b1<<20,
+			size_b0, size_b0<<20
+		);
+		flash_info[0].flash_id	= FLASH_UNKNOWN;
+		flash_info[1].flash_id	= FLASH_UNKNOWN;
+		flash_info[0].sector_count	= -1;
+		flash_info[1].sector_count	= -1;
+		flash_info[0].size		= 0;
+		flash_info[1].size		= 0;
+		return (0);
+	}
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+	if (size_b1) {
+		memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
+		memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
+				    BR_MS_GPCM | BR_V;
+
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0),
+					  &flash_info[1]);
+
+		flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+		/* monitor protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_MONITOR_BASE,
+			      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+			      &flash_info[1]);
+#endif
+	} else {
+		memctl->memc_br1 = 0;		/* invalidate bank */
+
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+	}
+
+	flash_info[0].size = size_b0;
+	flash_info[1].size = size_b1;
+
+	return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	ulong value;
+	ulong base = (ulong)addr;
+
+
+	/* Write auto select command: read Manufacturer ID */
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00900090;
+
+	value = addr[0];
+
+	switch (value) {
+	case AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	switch (value) {
+	case AMD_ID_LV400T:
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV400B:
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV800T:
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV800B:
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV160T:
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case AMD_ID_LV160B:
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+	case AMD_ID_LV320T:
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case AMD_ID_LV320B:
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+#endif
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr = (volatile unsigned long *)(info->start[i]);
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (volatile unsigned long *)info->start[0];
+
+		*addr = 0x00F000F0;	/* reset bank */
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    (info->flash_id > FLASH_AMD_COMP)) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00800080;
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (vu_long*)(info->start[sect]);
+			addr[0] = 0x00300030;
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (vu_long*)(info->start[l_sect]);
+	while ((addr[0] & 0x00800080) != 0x00800080) {
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (volatile unsigned long *)info->start[0];
+	addr[0] = 0x00F000F0;	/* reset bank */
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *)dest) & data) != data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00A000A0;
+
+	*((vu_long *)dest) = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/siemens/IAD210/atm.c b/board/siemens/IAD210/atm.c
new file mode 100644
index 0000000..c77e359
--- /dev/null
+++ b/board/siemens/IAD210/atm.c
@@ -0,0 +1,653 @@
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <commproc.h>
+
+#include "atm.h"
+#include <linux/stddef.h>
+
+#define SYNC __asm__("sync")
+#define ALIGN(p, a) ((char *)(((uint32)(p)+(a)-1) & ~((uint32)(a)-1)))
+
+#define FALSE  1
+#define TRUE   0
+#define OK     0
+#define ERROR -1
+
+struct atm_connection_t g_conn[NUM_CONNECTIONS] =
+{
+  { NULL, 10, NULL, 10,  NULL, NULL, NULL, NULL }, /* OAM  */
+};
+
+struct atm_driver_t g_atm =
+{
+  FALSE,   /* loaded */
+  FALSE,   /* started */
+  NULL,    /* csram */
+  0,       /* csram_size */
+  NULL,    /* am_top */
+  NULL,    /* ap_top */
+  NULL,    /* int_reload_ptr */
+  NULL,    /* int_serv_ptr */
+  NULL,    /* rbd_base_ptr */
+  NULL,    /* tbd_base_ptr */
+  0        /* linerate */
+};
+
+char csram[1024]; /* more than enough for doing nothing*/
+
+int    atmLoad(void);
+void   atmUnload(void);
+int    atmMemInit(void);
+void   atmIntInit(void);
+void   atmApcInit(void);
+void   atmAmtInit(void);
+void   atmCpmInit(void);
+void   atmUtpInit(void);
+
+/*****************************************************************************
+ *
+ * FUNCTION NAME: atmLoad
+ *
+ * DESCRIPTION: Basic ATM initialization.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: OK or ERROR
+ *
+ ****************************************************************************/
+int atmLoad()
+{
+  volatile immap_t       *immap  = (immap_t *)CFG_IMMR;
+  volatile cpmtimer8xx_t *timers = &immap->im_cpmtimer;
+  volatile iop8xx_t      *iop    = &immap->im_ioport;
+
+  timers->cpmt_tgcr &=  0x0FFF; SYNC;             /* Disable Timer 4 */
+  immap->im_cpm.cp_scc[4].scc_gsmrl = 0x0; SYNC; /* Disable SCC4 */
+  iop->iop_pdpar &= 0x3FFF; SYNC;                 /* Disable SAR and UTOPIA */
+
+  if ( atmMemInit() != OK ) return ERROR;
+
+  atmIntInit();
+  atmApcInit();
+  atmAmtInit();
+  atmCpmInit();
+  atmUtpInit();
+
+  g_atm.loaded = TRUE;
+
+  return OK;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION NAME: atmUnload
+ *
+ * DESCRIPTION: Disables ATM and UTOPIA.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: void
+ *
+ ****************************************************************************/
+void atmUnload()
+{
+  volatile immap_t       *immap  = (immap_t *)CFG_IMMR;
+  volatile cpmtimer8xx_t *timers = &immap->im_cpmtimer;
+  volatile iop8xx_t      *iop    = &immap->im_ioport;
+
+  timers->cpmt_tgcr &=  0x0FFF; SYNC;             /* Disable Timer 4 */
+  immap->im_cpm.cp_scc[4].scc_gsmrl = 0x0; SYNC;  /* Disable SCC4 */
+  iop->iop_pdpar &= 0x3FFF; SYNC;                 /* Disable SAR and UTOPIA */
+  g_atm.loaded = FALSE;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION NAME: atmMemInit
+ *
+ * DESCRIPTION:
+ *
+ * The ATM driver uses the following resources:
+ *
+ * A. Memory in DPRAM to hold
+ *
+ *     1/ CT          = Connection Table ( RCT & TCT )
+ *     2/ TCTE        = Transmit Connection Table Extension
+ *     3/ MPHYPT      = Multi-PHY Pointing Table
+ *     4/ APCP        = APC Parameter Table
+ *     5/ APCT_PRIO_1 = APC Table ( priority 1 for AAL1/2 )
+ *     6/ APCT_PRIO_2 = APC Table ( priority 2 for VBR )
+ *     7/ APCT_PRIO_3 = APC Table ( priority 3 for UBR )
+ *     8/ TQ          = Transmit Queue
+ *     9/ AM          = Address Matching Table
+ *    10/ AP          = Address Pointing Table
+ *
+ * B. Memory in cache safe RAM to hold
+ *
+ *     1/ INT         = Interrupt Queue
+ *     2/ RBD         = Receive Buffer Descriptors
+ *     3/ TBD         = Transmit Buffer Descriptors
+ *
+ * This function
+ * 1. clears the ATM DPRAM area,
+ * 2. Allocates and clears cache safe memory,
+ * 3. Initializes 'g_conn'.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: OK or ERROR
+ *
+ ****************************************************************************/
+int atmMemInit()
+{
+  int i;
+  unsigned immr = CFG_IMMR;
+  int total_num_rbd = 0;
+  int total_num_tbd = 0;
+
+  memset((char *)CFG_IMMR + 0x2000 + ATM_DPRAM_BEGIN, 0x00, ATM_DPRAM_SIZE);
+
+  g_atm.csram_size = NUM_INT_ENTRIES * SIZE_OF_INT_ENTRY;
+
+  for ( i = 0; i < NUM_CONNECTIONS; ++i ) {
+    total_num_rbd += g_conn[i].num_rbd;
+    total_num_tbd += g_conn[i].num_tbd;
+  }
+
+  g_atm.csram_size += total_num_rbd * SIZE_OF_RBD + total_num_tbd * SIZE_OF_TBD + 4;
+
+  g_atm.csram = &csram[0];
+  memset(&(g_atm.csram), 0x00, g_atm.csram_size);
+
+  g_atm.int_reload_ptr = (uint32 *)ALIGN(g_atm.csram, 4);
+  g_atm.rbd_base_ptr = (struct atm_bd_t *)(g_atm.int_reload_ptr + NUM_INT_ENTRIES);
+  g_atm.tbd_base_ptr = (struct atm_bd_t *)(g_atm.rbd_base_ptr + total_num_rbd);
+
+  g_conn[0].rbd_ptr = g_atm.rbd_base_ptr;
+  g_conn[0].tbd_ptr = g_atm.tbd_base_ptr;
+  g_conn[0].ct_ptr = CT_PTR(immr);
+  g_conn[0].tcte_ptr = TCTE_PTR(immr);
+
+  return OK;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION NAME: atmIntInit
+ *
+ * DESCRIPTION:
+ *
+ * Initialization of the MPC860 ESAR Interrupt Queue.
+ * This function
+ * - clears all entries in the INT,
+ * - sets the WRAP bit of the last INT entry,
+ * - initializes the 'int_serv_ptr' attribuut of the AtmDriver structure
+ *   to the first INT entry.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: void
+ *
+ * REMARKS:
+ *
+ * - The INT resides in external cache safe memory.
+ * - The base address of the INT is stored in g_atm.int_reload_ptr.
+ * - The number of entries in the INT is given by NUM_INT_ENTRIES.
+ * - The INTBASE field in SAR Parameter RAM is set by atmCpmInit().
+ *
+ ****************************************************************************/
+void atmIntInit()
+{
+  int i;
+  for ( i = 0; i < NUM_INT_ENTRIES - 1; ++i) g_atm.int_reload_ptr[i] = 0;
+  g_atm.int_reload_ptr[i] = INT_WRAP;
+  g_atm.int_serv_ptr = g_atm.int_reload_ptr;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION NAME: atmApcInit
+ *
+ * DESCRIPTION:
+ *
+ * This function initializes the following ATM Pace Controller related
+ * data structures:
+ *
+ * - 1 MPHY Pointing Table (contains only one entry)
+ * - 3 APC Parameter Tables (one PHY with 3 priorities)
+ * - 3 APC Tables (one table for each priority)
+ * - 1 Transmit Queue (one transmit queue per PHY)
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: void
+ *
+ ****************************************************************************/
+void atmApcInit()
+{
+  int i;
+  /* unsigned immr = CFG_IMMR; */
+  uint16 * mphypt_ptr = MPHYPT_PTR(CFG_IMMR);
+  struct apc_params_t * apcp_ptr = APCP_PTR(CFG_IMMR);
+  uint16 * apct_prio1_ptr = APCT1_PTR(CFG_IMMR);
+  uint16 * tq_ptr = TQ_PTR(CFG_IMMR);
+  /***************************************************/
+  /* Initialize MPHY Pointing Table (only one entry) */
+  /***************************************************/
+  *mphypt_ptr = APCP_BASE;
+
+  /********************************************/
+  /* Initialize APC parameters for priority 1 */
+  /********************************************/
+  apcp_ptr->apct_base1 = APCT_PRIO_1_BASE;
+  apcp_ptr->apct_end1  =  APCT_PRIO_1_BASE + NUM_APCT_PRIO_1_ENTRIES * 2;
+  apcp_ptr->apct_ptr1  =  APCT_PRIO_1_BASE;
+  apcp_ptr->apct_sptr1 = APCT_PRIO_1_BASE;
+  apcp_ptr->etqbase    = TQ_BASE;
+  apcp_ptr->etqend     =  TQ_BASE + ( NUM_TQ_ENTRIES - 1 ) * 2;
+  apcp_ptr->etqaptr    = TQ_BASE;
+  apcp_ptr->etqtptr    = TQ_BASE;
+  apcp_ptr->apc_mi     = 8;
+  apcp_ptr->ncits      = 0x0100;   /* NCITS = 1 */
+  apcp_ptr->apcnt      = 0;
+  apcp_ptr->reserved1  = 0;
+  apcp_ptr->eapcst     = 0x2009;  /* LAST, ESAR, MPHY */
+  apcp_ptr->ptp_counter = 0;
+  apcp_ptr->ptp_txch   = 0;
+  apcp_ptr->reserved2  = 0;
+
+
+  /***************************************************/
+  /* Initialize APC Tables with empty slots (0xFFFF) */
+  /***************************************************/
+  for ( i = 0; i < NUM_APCT_PRIO_1_ENTRIES; ++i ) *(apct_prio1_ptr++) = 0xFFFF;
+
+  /************************/
+  /* Clear Transmit Queue */
+  /************************/
+  for ( i = 0; i < NUM_TQ_ENTRIES; ++i ) *(tq_ptr++) = 0;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION NAME: atmAmtInit
+ *
+ * DESCRIPTION:
+ *
+ * This function clears the first entry in the Address Matching Table and
+ * lets the first entry in the Address Pointing table point to the first
+ * entry in the TCT table (i.e. the raw cell channel).
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: void
+ *
+ * REMARKS:
+ *
+ * The values for the AMBASE, AMEND and APBASE registers in SAR parameter
+ * RAM are initialized by atmCpmInit().
+ *
+ ****************************************************************************/
+void atmAmtInit()
+{
+  unsigned immr = CFG_IMMR;
+
+  g_atm.am_top = AM_PTR(immr);
+  g_atm.ap_top = AP_PTR(immr);
+
+  *(g_atm.ap_top--) = CT_BASE;
+  *(g_atm.am_top--) = 0;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION NAME: atmCpmInit
+ *
+ * DESCRIPTION:
+ *
+ * This function initializes the Utopia Interface Parameter RAM Map
+ * (SCC4, ATM Protocol) of the Communication Processor Modudule.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: void
+ *
+ ****************************************************************************/
+void atmCpmInit()
+{
+  unsigned immr = CFG_IMMR;
+
+  memset((char *)immr + 0x3F00, 0x00, 0xC0);
+
+  /*-----------------------------------------------------------------*/
+  /* RBDBASE - Receive buffer descriptors base address               */
+  /* The RBDs reside in cache safe external memory.                  */
+  /*-----------------------------------------------------------------*/
+  *RBDBASE(immr) = (uint32)g_atm.rbd_base_ptr;
+
+  /*-----------------------------------------------------------------*/
+  /* SRFCR - SAR receive function code                               */
+  /* 0-2 rsvd = 000                                                  */
+  /* 3-4 BO   = 11  Byte ordering (big endian).                      */
+  /* 5-7 FC   = 000 Value driven on the address type signals AT[1-3] */
+  /*                when the SDMA channel accesses memory.           */
+  /*-----------------------------------------------------------------*/
+  *SRFCR(immr) = 0x18;
+
+  /*-----------------------------------------------------------------*/
+  /* SRSTATE - SAR receive status                                    */
+  /* 0 EXT  = 0 Extended mode off.                                   */
+  /* 1 ACP  = 0 Valid only if EXT = 1.                               */
+  /* 2 EC   = 0 Standard 53-byte ATM cell.                           */
+  /* 3 SNC  = 0 In sync. Must be set to 0 during initialization.     */
+  /* 4 ESAR = 1 Enhanced SAR functionality enabled.                  */
+  /* 5 MCF  = 1 Management Cell Filter active.                       */
+  /* 6 SER  = 0 UTOPIA mode.                                         */
+  /* 7 MPY  = 1 Multiple PHY mode.                                   */
+  /*-----------------------------------------------------------------*/
+  *SRSTATE(immr) = 0x0D;
+
+  /*-----------------------------------------------------------------*/
+  /* MRBLR - Maximum receive buffer length register.                 */
+  /* Must be cleared for ATM operation (see also SMRBLR).            */
+  /*-----------------------------------------------------------------*/
+  *MRBLR(immr) = 0;
+
+  /*-----------------------------------------------------------------*/
+  /* RSTATE - SCC internal receive state parameters                  */
+  /* The first byte must be initialized with the value of SRFCR.     */
+  /*-----------------------------------------------------------------*/
+  *RSTATE(immr) = (uint32)(*SRFCR(immr)) << 24;
+
+  /*-----------------------------------------------------------------*/
+  /* STFCR - SAR transmit function code                              */
+  /* 0-2 rsvd = 000                                                  */
+  /* 3-4 BO   = 11  Byte ordering (big endian).                      */
+  /* 5-7 FC   = 000 Value driven on the address type signals AT[1-3] */
+  /*                when the SDMA channel accesses memory.           */
+  /*-----------------------------------------------------------------*/
+  *STFCR(immr) = 0x18;
+
+  /*-----------------------------------------------------------------*/
+  /* SRSTATE - SAR transmit status                                   */
+  /* 0 EXT  = 0 : Extended mode off                                  */
+  /* 1 rsvd = 0 :                                                    */
+  /* 2 EC   = 0 : Standard 53-byte ATM cell                          */
+  /* 3 rsvd = 0 :                                                    */
+  /* 4 ESAR = 1 : Enhanced SAR functionality enabled                 */
+  /* 5 rsvd = 0 :                                                    */
+  /* 6 SER  = 0 : UTOPIA mode                                        */
+  /* 7 MPY  = 1 : Multiple PHY mode                                  */
+  /*-----------------------------------------------------------------*/
+  *STSTATE(immr) = 0x09;
+
+  /*-----------------------------------------------------------------*/
+  /* TBDBASE - Transmit buffer descriptors base address              */
+  /* The TBDs reside in cache safe external memory.                  */
+  /*-----------------------------------------------------------------*/
+  *TBDBASE(immr) = (uint32)g_atm.tbd_base_ptr;
+
+  /*-----------------------------------------------------------------*/
+  /* TSTATE - SCC internal transmit state parameters                 */
+  /* The first byte must be initialized with the value of STFCR.     */
+  /*-----------------------------------------------------------------*/
+  *TSTATE(immr) = (uint32)(*STFCR(immr)) << 24;
+
+  /*-----------------------------------------------------------------*/
+  /* CTBASE - Connection table base address                          */
+  /* Offset from the beginning of DPRAM (64-byte aligned).           */
+  /*-----------------------------------------------------------------*/
+  *CTBASE(immr) = CT_BASE;
+
+  /*-----------------------------------------------------------------*/
+  /* INTBASE - Interrupt queue base pointer.                         */
+  /* The interrupt queue resides in cache safe external memory.      */
+  /*-----------------------------------------------------------------*/
+  *INTBASE(immr) = (uint32)g_atm.int_reload_ptr;
+
+  /*-----------------------------------------------------------------*/
+  /* INTPTR - Pointer into interrupt queue.                          */
+  /* Initialize to INTBASE.                                          */
+  /*-----------------------------------------------------------------*/
+  *INTPTR(immr) = *INTBASE(immr);
+
+  /*-----------------------------------------------------------------*/
+  /* C_MASK - Constant mask for CRC32                                */
+  /* Must be initialized to 0xDEBB20E3.                              */
+  /*-----------------------------------------------------------------*/
+  *C_MASK(immr) = 0xDEBB20E3;
+
+  /*-----------------------------------------------------------------*/
+  /* INT_ICNT - Interrupt threshold value                            */
+  /*-----------------------------------------------------------------*/
+  *INT_ICNT(immr) = 1;
+
+  /*-----------------------------------------------------------------*/
+  /* INT_CNT - Interrupt counter                                     */
+  /* Initalize to INT_ICNT. Decremented for each interrupt entry     */
+  /* reported in the interrupt queue. On zero an interrupt is        */
+  /* signaled to the host by setting the GINT bit in the event       */
+  /* register. The counter is reinitialized with INT_ICNT.           */
+  /*-----------------------------------------------------------------*/
+  *INT_CNT(immr) = *INT_ICNT(immr);
+
+  /*-----------------------------------------------------------------*/
+  /* SMRBLR - SAR maximum receive buffer length register.            */
+  /* Must be a multiple of 48 bytes. Common for all ATM connections. */
+  /*-----------------------------------------------------------------*/
+  *SMRBLR(immr) = SAR_RXB_SIZE;
+
+  /*-----------------------------------------------------------------*/
+  /* APCST - APC status register.                                    */
+  /* 0     rsvd 0                                                    */
+  /* 1-2   CSER 11  Initialize with the same value as NSER.          */
+  /* 3-4   NSER 11  Next serial or UTOPIA channel.                   */
+  /* 5-7   rsvd 000                                                  */
+  /* 8-10  rsvd 000                                                  */
+  /* 11    rsvd 0                                                    */
+  /* 12    ESAR 1   UTOPIA Level 2 MPHY enabled.                     */
+  /* 13    DIS  0   APC disable. Must be initiazed to 0.             */
+  /* 14    PL2  0   Not used.                                        */
+  /* 15    MPY  1   Multiple PHY mode on.                            */
+  /*-----------------------------------------------------------------*/
+  *APCST(immr) = 0x7809;
+
+  /*-----------------------------------------------------------------*/
+  /* APCPTR - Pointer to the APC parameter table                     */
+  /* In MPHY master mode this parameter points to the MPHY pointing  */
+  /* table. 2-byte aligned.                                          */
+  /*-----------------------------------------------------------------*/
+  *APCPTR(immr) = MPHYPT_BASE;
+
+  /*-----------------------------------------------------------------*/
+  /* HMASK - Header mask                                             */
+  /* Each incoming cell is masked with HMASK before being compared   */
+  /* to the entries in the address matching table.                   */
+  /*-----------------------------------------------------------------*/
+  *HMASK(immr) = AM_HMASK;
+
+  /*-----------------------------------------------------------------*/
+  /* AMBASE - Address matching table base address                    */
+  /*-----------------------------------------------------------------*/
+  *AMBASE(immr) = AM_BASE;
+
+  /*-----------------------------------------------------------------*/
+  /* AMEND - Address matching table end address                      */
+  /*-----------------------------------------------------------------*/
+  *AMEND(immr) = AM_BASE;
+
+  /*-----------------------------------------------------------------*/
+  /* APBASE - Address pointing table base address                    */
+  /*-----------------------------------------------------------------*/
+  *APBASE(immr) = AP_BASE;
+
+  /*-----------------------------------------------------------------*/
+  /* MPHYST - MPHY status register                                   */
+  /* 0-1   rsvd  00                                                  */
+  /* 2-6   NMPHY 00000 1 PHY                                         */
+  /* 7-9   rsvd  000                                                 */
+  /* 10-14 CMPHY 00000 Initialize with same value as NMPHY           */
+  /*-----------------------------------------------------------------*/
+  *MPHYST(immr) = 0x0000;
+
+  /*-----------------------------------------------------------------*/
+  /* TCTEBASE - Transmit connection table extension base address     */
+  /* Offset from the beginning of DPRAM (32-byte aligned).           */
+  /*-----------------------------------------------------------------*/
+  *TCTEBASE(immr) = TCTE_BASE;
+
+  /*-----------------------------------------------------------------*/
+  /* Clear not used registers.                                       */
+  /*-----------------------------------------------------------------*/
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION NAME: atmUtpInit
+ *
+ * DESCRIPTION:
+ *
+ * This function initializes the ATM interface for
+ *
+ * - UTOPIA mode
+ * - muxed bus
+ * - master operation
+ * - multi PHY (because of a bug in the MPC860P rev. E.0)
+ * - internal clock = SYSCLK / 2
+ *
+ * EXTERNAL EFFECTS:
+ *
+ * After calling this function, the MPC860ESAR UTOPIA bus is
+ * active and uses the following ports/pins:
+ *
+ * Port    Pin  Signal   Description
+ * ------  ---  -------  -------------------------------------------
+ * PB[15]  R17  TxClav   Transmit cell available input/output signal
+ * PC[15]  D16  RxClav   Receive cell available input/output signal
+ * PD[15]  U17  UTPB[0]  UTOPIA bus bit 0 input/output signal
+ * PD[14]  V19  UTPB[1]  UTOPIA bus bit 1 input/output signal
+ * PD[13]  V18  UTPB[2]  UTOPIA bus bit 2 input/output signal
+ * PD[12]  R16  UTPB[3]  UTOPIA bus bit 3 input/output signal
+ * PD[11]  T16  RXENB    Receive enable input/output signal
+ * PD[10]  W18  TXENB    Transmit enable input/output signal
+ * PD[9]   V17  UTPCLK   UTOPIA clock input/output signal
+ * PD[7]   T15  UTPB[4]  UTOPIA bus bit 4 input/output signal
+ * PD[6]   V16  UTPB[5]  UTOPIA bus bit 5 input/output signal
+ * PD[5]   U15  UTPB[6]  UTOPIA bus bit 6 input/output signal
+ * PD[4]   U16  UTPB[7]  UTOPIA bus bit 7 input/output signal
+ * PD[3]   W16  SOC      Start of cell input/output signal
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: void
+ *
+ * REMARK:
+ *
+ * The ATM parameters and data structures must be configured before
+ * initializing the UTOPIA port. The UTOPIA port activates immediately
+ * upon initialization, and if its associated data structures are not
+ * initialized, the CPM will lock up.
+ *
+ ****************************************************************************/
+void atmUtpInit()
+{
+  volatile immap_t       *immap  = (immap_t *)CFG_IMMR;
+  volatile iop8xx_t      *iop    = &immap->im_ioport;
+  volatile car8xx_t	 *car    = &immap->im_clkrst;
+  volatile cpm8xx_t	 *cpm    = &immap->im_cpm;
+  int flag;
+
+  flag = disable_interrupts();
+
+  /*-----------------------------------------------------------------*/
+  /* SCCR - System Clock Control Register                            */
+  /*                                                                 */
+  /* The UTOPIA clock can be selected to be internal clock or        */
+  /* external clock (selected by the UTOPIA mode register).          */
+  /* In case of internal clock, the UTOPIA clock is derived from     */
+  /* the system frequency divided by two dividers.                   */
+  /* Bits 27-31 of the SCCR register are defined to control the      */
+  /* UTOPIA clock.                                                   */
+  /*                                                                 */
+  /* SCCR[27:29] DFUTP  Division factor. Divide the system clock     */
+  /*                    by 2^DFUTP.                                  */
+  /* SCCR[30:31] DFAUTP Additional division factor. Divide the       */
+  /*                    system clock by the following value:         */
+  /*                    00 = divide by 1                             */
+  /*                    00 = divide by 3                             */
+  /*                    10 = divide by 5                             */
+  /*                    11 = divide by 7                             */
+  /*                                                                 */
+  /* Note that the UTOPIA clock must be programmed as to operate     */
+  /* within the range SYSCLK/10 .. 50Mhz.                            */
+  /*-----------------------------------------------------------------*/
+  car->car_sccr &= 0xFFFFFFE0;
+  car->car_sccr |= 0x00000008; /* UTPCLK = SYSCLK / 4 */
+
+  /*-----------------------------------------------------------------*/
+  /* RCCR - RISC Controller Configuration Register                   */
+  /*                                                                 */
+  /* RCCR[8]     DR1M IDMA Request 0 Mode                            */
+  /*                  0 = edge sensitive                             */
+  /*                  1 = level sensitive                            */
+  /* RCCR[9]     DR0M IDMA Request 0 Mode                            */
+  /*                  0 = edge sensitive                             */
+  /*                  1 = level sensitive                            */
+  /* RCCR[10:11] DRQP IDMA Request Priority                          */
+  /*                  00 = IDMA req. have more prio. than SCCs       */
+  /*                  01 = IDMA req. have less prio. then SCCs       */
+  /*                  10 = IDMA requests have the lowest prio.       */
+  /*                  11 = reserved                                  */
+  /*                                                                 */
+  /* The RCCR[DR0M] and RCCR[DR1M] bits must be set to enable UTOPIA */
+  /* operation. Also, program RCCR[DPQP] to 01 to give SCC transfers */
+  /* higher priority.                                                */
+  /*-----------------------------------------------------------------*/
+  cpm->cp_rccr &= 0xFF0F;
+  cpm->cp_rccr |= 0x00D0;
+
+  /*-----------------------------------------------------------------*/
+  /* Port B - TxClav Signal                                          */
+  /*-----------------------------------------------------------------*/
+  cpm->cp_pbpar |= 0x00010000; /* PBPAR[15] = 1 */
+  cpm->cp_pbdir &= 0xFFFEFFFF; /* PBDIR[15] = 0 */
+
+  /*-----------------------------------------------------------------*/
+  /* UTOPIA Mode Register                                            */
+  /*                                                                 */
+  /* - muxed bus (master operation only)                             */
+  /* - multi PHY (because of a bug in the MPC860P rev.E.0)           */
+  /* - internal clock                                                */
+  /* - no loopback                                                   */
+  /* - do no activate statistical counters                           */
+  /*-----------------------------------------------------------------*/
+  iop->utmode = 0x00000004; SYNC;
+
+  /*-----------------------------------------------------------------*/
+  /* Port D - UTOPIA Data and Control Signals                        */
+  /*                                                                 */
+  /* 15-12 UTPB[0:3] UTOPIA bus bit 0 - 3 input/output signals       */
+  /* 11    RXENB     UTOPIA receive enable input/output signal       */
+  /* 10    TXENB     UTOPIA transmit enable input/output signal      */
+  /* 9     TUPCLK    UTOPIA clock input/output signal                */
+  /* 8     MII-MDC   Used by MII in simult. MII and UTOPIA operation */
+  /* 7-4   UTPB[4:7] UTOPIA bus bit 4 - 7 input/output signals       */
+  /* 3     SOC       UTOPIA Start of cell input/output signal        */
+  /* 2               Reserved                                        */
+  /* 1               Enable UTOPIA mode                              */
+  /* 0               Enable SAR                                      */
+  /*-----------------------------------------------------------------*/
+  iop->iop_pdpar |= 0xDF7F; SYNC;
+  iop->iop_pddir &= 0x2080; SYNC;
+
+  /*-----------------------------------------------------------------*/
+  /* Port C - RxClav Signal                                          */
+  /*-----------------------------------------------------------------*/
+  iop->iop_pcpar  |= 0x0001; /* PCPAR[15] = 1 */
+  iop->iop_pcdir  &= 0xFFFE; /* PCDIR[15] = 0 */
+  iop->iop_pcso   &= 0xFFFE; /* PCSO[15]  = 0 */
+
+  if (flag)
+    enable_interrupts();
+}
diff --git a/board/siemens/IAD210/flash.c b/board/siemens/IAD210/flash.c
new file mode 100644
index 0000000..1ed5262
--- /dev/null
+++ b/board/siemens/IAD210/flash.c
@@ -0,0 +1,502 @@
+/*
+ * (C) Copyright 2000, 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+  volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+  volatile memctl8xx_t *memctl = &immap->im_memctl;
+  unsigned long size;
+  int i;
+
+  /* Init: no FLASHes known */
+  for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+    flash_info[i].flash_id = FLASH_UNKNOWN;
+  }
+
+  /* Static FLASH Bank configuration here - FIXME XXX */
+
+  size = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+  if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+    printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size, size<<20);
+  }
+
+
+  /* Remap FLASH according to real size */
+  memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size & 0xFFFF8000);
+  memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
+
+  /* Re-do sizing to get full correct info */
+  size = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+  flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+  flash_info[0].size = size;
+
+  return (size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+  int i;
+
+  /* set up sector start address table */
+  if (info->flash_id & FLASH_BTYPE) {
+    /* set sector offsets for bottom boot block type	*/
+    info->start[0] = base + 0x00000000;
+    info->start[1] = base + 0x00008000;
+    info->start[2] = base + 0x0000C000;
+    info->start[3] = base + 0x00010000;
+    for (i = 4; i < info->sector_count; i++) {
+      info->start[i] = base + (i * 0x00020000) - 0x00060000;
+    }
+  } else {
+    /* set sector offsets for top boot block type		*/
+    i = info->sector_count - 1;
+    info->start[i--] = base + info->size - 0x00008000;
+    info->start[i--] = base + info->size - 0x0000C000;
+    info->start[i--] = base + info->size - 0x00010000;
+    for (; i >= 0; i--) {
+      info->start[i] = base + i * 0x00020000;
+    }
+  }
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+  int i;
+
+  if (info->flash_id == FLASH_UNKNOWN) {
+    printf ("missing or unknown FLASH type\n");
+    return;
+  }
+
+  switch (info->flash_id & FLASH_VENDMASK) {
+  case FLASH_MAN_AMD:	printf ("AMD ");		break;
+  case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+  default:		printf ("Unknown Vendor ");	break;
+  }
+
+  switch (info->flash_id & FLASH_TYPEMASK) {
+  case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+    break;
+  case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+    break;
+  case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+    break;
+  case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+    break;
+  case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+    break;
+  case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+    break;
+  case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+    break;
+  case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+    break;
+  default:		printf ("Unknown Chip Type\n");
+    break;
+  }
+
+  printf ("  Size: %ld MB in %d Sectors\n",
+          info->size >> 20, info->sector_count);
+
+  printf ("  Sector Start Addresses:");
+  for (i=0; i<info->sector_count; ++i) {
+    if ((i % 5) == 0)
+      printf ("\n   ");
+    printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+            );
+  }
+  printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+  short i;
+  ulong value;
+  ulong base = (ulong)addr;
+
+
+  /* Write auto select command: read Manufacturer ID */
+  addr[0x0555] = 0x00AA00AA;
+  addr[0x02AA] = 0x00550055;
+  addr[0x0555] = 0x00900090;
+
+  value = addr[0];
+
+  switch (value) {
+  case AMD_MANUFACT:
+    info->flash_id = FLASH_MAN_AMD;
+    break;
+  case FUJ_MANUFACT:
+    info->flash_id = FLASH_MAN_FUJ;
+    break;
+  default:
+    info->flash_id = FLASH_UNKNOWN;
+    info->sector_count = 0;
+    info->size = 0;
+    return (0);			/* no or unknown flash	*/
+  }
+
+  value = addr[1];			/* device ID		*/
+
+  switch (value) {
+  case AMD_ID_LV400T:
+    info->flash_id += FLASH_AM400T;
+    info->sector_count = 11;
+    info->size = 0x00100000;
+    break;				/* => 1 MB		*/
+
+  case AMD_ID_LV400B:
+    info->flash_id += FLASH_AM400B;
+    info->sector_count = 11;
+    info->size = 0x00100000;
+    break;				/* => 1 MB		*/
+
+  case AMD_ID_LV800T:
+    info->flash_id += FLASH_AM800T;
+    info->sector_count = 19;
+    info->size = 0x00200000;
+    break;				/* => 2 MB		*/
+
+  case AMD_ID_LV800B:
+    info->flash_id += FLASH_AM800B;
+    info->sector_count = 19;
+    info->size = 0x00200000;
+    break;				/* => 2 MB		*/
+
+  case AMD_ID_LV160T:
+    info->flash_id += FLASH_AM160T;
+    info->sector_count = 35;
+    info->size = 0x00400000;
+    break;				/* => 4 MB		*/
+
+  case AMD_ID_LV160B:
+    info->flash_id += FLASH_AM160B;
+    info->sector_count = 35;
+    info->size = 0x00400000;
+    break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+  case AMD_ID_LV320T:
+    info->flash_id += FLASH_AM320T;
+    info->sector_count = 67;
+    info->size = 0x00800000;
+    break;				/* => 8 MB		*/
+
+  case AMD_ID_LV320B:
+    info->flash_id += FLASH_AM320B;
+    info->sector_count = 67;
+    info->size = 0x00800000;
+    break;				/* => 8 MB		*/
+#endif
+  default:
+    info->flash_id = FLASH_UNKNOWN;
+    return (0);			/* => no or unknown flash */
+
+  }
+
+  /* set up sector start address table */
+  if (info->flash_id & FLASH_BTYPE) {
+    /* set sector offsets for bottom boot block type	*/
+    info->start[0] = base + 0x00000000;
+    info->start[1] = base + 0x00008000;
+    info->start[2] = base + 0x0000C000;
+    info->start[3] = base + 0x00010000;
+    for (i = 4; i < info->sector_count; i++) {
+      info->start[i] = base + (i * 0x00020000) - 0x00060000;
+    }
+  } else {
+    /* set sector offsets for top boot block type		*/
+    i = info->sector_count - 1;
+    info->start[i--] = base + info->size - 0x00008000;
+    info->start[i--] = base + info->size - 0x0000C000;
+    info->start[i--] = base + info->size - 0x00010000;
+    for (; i >= 0; i--) {
+      info->start[i] = base + i * 0x00020000;
+    }
+  }
+
+  /* check for protected sectors */
+  for (i = 0; i < info->sector_count; i++) {
+    /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+    /* D0 = 1 if protected */
+    addr = (volatile unsigned long *)(info->start[i]);
+    info->protect[i] = addr[2] & 1;
+  }
+
+  /*
+   * Prevent writes to uninitialized FLASH.
+   */
+  if (info->flash_id != FLASH_UNKNOWN) {
+    addr = (volatile unsigned long *)info->start[0];
+
+    *addr = 0x00F000F0;	/* reset bank */
+  }
+
+  return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+  vu_long *addr = (vu_long*)(info->start[0]);
+  int flag, prot, sect, l_sect;
+  ulong start, now, last;
+
+  if ((s_first < 0) || (s_first > s_last)) {
+    if (info->flash_id == FLASH_UNKNOWN) {
+      printf ("- missing\n");
+    } else {
+      printf ("- no sectors to erase\n");
+    }
+    return 1;
+  }
+
+  if ((info->flash_id == FLASH_UNKNOWN) ||
+      (info->flash_id > FLASH_AMD_COMP)) {
+    printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+    return 1;
+  }
+
+  prot = 0;
+  for (sect=s_first; sect<=s_last; ++sect) {
+    if (info->protect[sect]) {
+      prot++;
+    }
+  }
+
+  if (prot) {
+    printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+  } else {
+    printf ("\n");
+  }
+
+  l_sect = -1;
+
+  /* Disable interrupts which might cause a timeout here */
+  flag = disable_interrupts();
+
+  addr[0x0555] = 0x00AA00AA;
+  addr[0x02AA] = 0x00550055;
+  addr[0x0555] = 0x00800080;
+  addr[0x0555] = 0x00AA00AA;
+  addr[0x02AA] = 0x00550055;
+
+  /* Start erase on unprotected sectors */
+  for (sect = s_first; sect<=s_last; sect++) {
+    if (info->protect[sect] == 0) {	/* not protected */
+      addr = (vu_long*)(info->start[sect]);
+      addr[0] = 0x00300030;
+      l_sect = sect;
+    }
+  }
+
+  /* re-enable interrupts if necessary */
+  if (flag)
+    enable_interrupts();
+
+  /* wait at least 80us - let's wait 1 ms */
+  udelay (1000);
+
+  /*
+   * We wait for the last triggered sector
+   */
+  if (l_sect < 0)
+    goto DONE;
+
+  start = get_timer (0);
+  last  = start;
+  addr = (vu_long*)(info->start[l_sect]);
+  while ((addr[0] & 0x00800080) != 0x00800080) {
+    if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+      printf ("Timeout\n");
+      return 1;
+    }
+    /* show that we're waiting */
+    if ((now - last) > 1000) {	/* every second */
+      putc ('.');
+      last = now;
+    }
+  }
+
+ DONE:
+  /* reset to read mode */
+  addr = (volatile unsigned long *)info->start[0];
+  addr[0] = 0x00F000F0;	/* reset bank */
+
+  printf (" done\n");
+  return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+  ulong cp, wp, data;
+  int i, l, rc;
+
+  wp = (addr & ~3);	/* get lower word aligned address */
+
+  /*
+   * handle unaligned start bytes
+   */
+  if ((l = addr - wp) != 0) {
+    data = 0;
+    for (i=0, cp=wp; i<l; ++i, ++cp) {
+      data = (data << 8) | (*(uchar *)cp);
+    }
+    for (; i<4 && cnt>0; ++i) {
+      data = (data << 8) | *src++;
+      --cnt;
+      ++cp;
+    }
+    for (; cnt==0 && i<4; ++i, ++cp) {
+      data = (data << 8) | (*(uchar *)cp);
+    }
+
+    if ((rc = write_word(info, wp, data)) != 0) {
+      return (rc);
+    }
+    wp += 4;
+  }
+
+  /*
+   * handle word aligned part
+   */
+  while (cnt >= 4) {
+    data = 0;
+    for (i=0; i<4; ++i) {
+      data = (data << 8) | *src++;
+    }
+    if ((rc = write_word(info, wp, data)) != 0) {
+      return (rc);
+    }
+    wp  += 4;
+    cnt -= 4;
+  }
+
+  if (cnt == 0) {
+    return (0);
+  }
+
+  /*
+   * handle unaligned tail bytes
+   */
+  data = 0;
+  for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+    data = (data << 8) | *src++;
+    --cnt;
+  }
+  for (; i<4; ++i, ++cp) {
+    data = (data << 8) | (*(uchar *)cp);
+  }
+
+  return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+  vu_long *addr = (vu_long*)(info->start[0]);
+  ulong start;
+  int flag;
+
+  /* Check if Flash is (sufficiently) erased */
+  if ((*((vu_long *)dest) & data) != data) {
+    return (2);
+  }
+  /* Disable interrupts which might cause a timeout here */
+  flag = disable_interrupts();
+
+  addr[0x0555] = 0x00AA00AA;
+  addr[0x02AA] = 0x00550055;
+  addr[0x0555] = 0x00A000A0;
+
+  *((vu_long *)dest) = data;
+
+  /* re-enable interrupts if necessary */
+  if (flag)
+    enable_interrupts();
+
+  /* data polling for D7 */
+  start = get_timer (0);
+  while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
+    if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+      return (1);
+    }
+  }
+  return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/siemens/SCM/flash.c b/board/siemens/SCM/flash.c
new file mode 100644
index 0000000..dd7a4cc
--- /dev/null
+++ b/board/siemens/SCM/flash.c
@@ -0,0 +1,488 @@
+/*
+ * (C) Copyright 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for AMD devices on the TQM8260 board
+ *
+ *--------------------------------------------------------------------
+ * 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 <mpc8xx.h>
+
+#define V_ULONG(a)	(*(volatile unsigned long *)( a ))
+#define V_BYTE(a)	(*(volatile unsigned char *)( a ))
+
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+
+/*-----------------------------------------------------------------------
+ */
+void flash_reset (void)
+{
+	if (flash_info[0].flash_id != FLASH_UNKNOWN) {
+		V_ULONG (flash_info[0].start[0]) = 0x00F000F0;
+		V_ULONG (flash_info[0].start[0] + 4) = 0x00F000F0;
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+ulong flash_get_size (ulong baseaddr, flash_info_t * info)
+{
+	short i;
+	unsigned long flashtest_h, flashtest_l;
+
+	/* Write auto select command sequence and test FLASH answer */
+	V_ULONG (baseaddr + ((ulong) 0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (baseaddr + ((ulong) 0x02AA << 3)) = 0x00550055;
+	V_ULONG (baseaddr + ((ulong) 0x0555 << 3)) = 0x00900090;
+	V_ULONG (baseaddr + 4 + ((ulong) 0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (baseaddr + 4 + ((ulong) 0x02AA << 3)) = 0x00550055;
+	V_ULONG (baseaddr + 4 + ((ulong) 0x0555 << 3)) = 0x00900090;
+
+	flashtest_h = V_ULONG (baseaddr);	/* manufacturer ID     */
+	flashtest_l = V_ULONG (baseaddr + 4);
+
+	switch ((int) flashtest_h) {
+	case AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash     */
+	}
+
+	flashtest_h = V_ULONG (baseaddr + 8);	/* device ID           */
+	flashtest_l = V_ULONG (baseaddr + 12);
+	if (flashtest_h != flashtest_l) {
+		info->flash_id = FLASH_UNKNOWN;
+	} else {
+		switch (flashtest_h) {
+		case AMD_ID_LV800T:
+			info->flash_id += FLASH_AM800T;
+			info->sector_count = 19;
+			info->size = 0x00400000;
+			break;			/* 4 * 1 MB = 4 MB  */
+		case AMD_ID_LV800B:
+			info->flash_id += FLASH_AM800B;
+			info->sector_count = 19;
+			info->size = 0x00400000;
+			break;			/* 4 * 1 MB = 4 MB  */
+		case AMD_ID_LV160T:
+			info->flash_id += FLASH_AM160T;
+			info->sector_count = 35;
+			info->size = 0x00800000;
+			break;			/* 4 * 2 MB = 8 MB  */
+		case AMD_ID_LV160B:
+			info->flash_id += FLASH_AM160B;
+			info->sector_count = 35;
+			info->size = 0x00800000;
+			break;			/* 4 * 2 MB = 8 MB  */
+		case AMD_ID_DL322T:
+			info->flash_id += FLASH_AMDL322T;
+			info->sector_count = 71;
+			info->size = 0x01000000;
+			break;			/* 4 * 4 MB = 16 MB */
+		case AMD_ID_DL322B:
+			info->flash_id += FLASH_AMDL322B;
+			info->sector_count = 71;
+			info->size = 0x01000000;
+			break;			/* 4 * 4 MB = 16 MB */
+		case AMD_ID_DL323T:
+			info->flash_id += FLASH_AMDL323T;
+			info->sector_count = 71;
+			info->size = 0x01000000;
+			break;			/* 4 * 4 MB = 16 MB */
+		case AMD_ID_DL323B:
+			info->flash_id += FLASH_AMDL323B;
+			info->sector_count = 71;
+			info->size = 0x01000000;
+			break;			/* 4 * 4 MB = 16 MB */
+		case AMD_ID_LV640U:
+			info->flash_id += FLASH_AM640U;
+			info->sector_count = 128;
+			info->size = 0x02000000;
+			break;			/* 4 * 8 MB = 32 MB */
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			return (0);		/* no or unknown flash     */
+		}
+	}
+
+	if (flashtest_h == AMD_ID_LV640U) {
+
+		/* set up sector start adress table (uniform sector type) */
+		for (i = 0; i < info->sector_count; i++)
+			info->start[i] = baseaddr + (i * 0x00040000);
+
+	} else if (info->flash_id & FLASH_BTYPE) {
+
+		/* set up sector start adress table (bottom sector type) */
+		info->start[0] = baseaddr + 0x00000000;
+		info->start[1] = baseaddr + 0x00010000;
+		info->start[2] = baseaddr + 0x00018000;
+		info->start[3] = baseaddr + 0x00020000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = baseaddr + (i * 0x00040000) - 0x000C0000;
+		}
+
+	} else {
+
+		/* set up sector start adress table (top sector type) */
+		i = info->sector_count - 1;
+		info->start[i--] = baseaddr + info->size - 0x00010000;
+		info->start[i--] = baseaddr + info->size - 0x00018000;
+		info->start[i--] = baseaddr + info->size - 0x00020000;
+		for (; i >= 0; i--) {
+			info->start[i] = baseaddr + i * 0x00040000;
+		}
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		if ((V_ULONG (info->start[i] + 16) & 0x00010001) ||
+			(V_ULONG (info->start[i] + 20) & 0x00010001)) {
+			info->protect[i] = 1;	/* D0 = 1 if protected */
+		} else {
+			info->protect[i] = 0;
+		}
+	}
+
+	flash_reset ();
+	return (info->size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+	unsigned long size_b0 = 0;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here (only one bank) */
+
+	size_b0 = flash_get_size (CFG_FLASH0_BASE, &flash_info[0]);
+	if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+				size_b0, size_b0 >> 20);
+	}
+
+	/*
+	 * protect monitor and environment sectors
+	 */
+
+#if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
+	flash_protect (FLAG_PROTECT_SET,
+		       CFG_MONITOR_BASE,
+		       CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, &flash_info[0]);
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+	flash_protect (FLAG_PROTECT_SET,
+		       CFG_ENV_ADDR,
+		       CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
+#endif
+
+	return (size_b0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:
+		printf ("AMD ");
+		break;
+	case FLASH_MAN_FUJ:
+		printf ("FUJITSU ");
+		break;
+	default:
+		printf ("Unknown Vendor ");
+		break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM800T:
+		printf ("29LV800T (8 M, top sector)\n");
+		break;
+	case FLASH_AM800B:
+		printf ("29LV800T (8 M, bottom sector)\n");
+		break;
+	case FLASH_AM160T:
+		printf ("29LV160T (16 M, top sector)\n");
+		break;
+	case FLASH_AM160B:
+		printf ("29LV160B (16 M, bottom sector)\n");
+		break;
+	case FLASH_AMDL322T:
+		printf ("29DL322T (32 M, top sector)\n");
+		break;
+	case FLASH_AMDL322B:
+		printf ("29DL322B (32 M, bottom sector)\n");
+		break;
+	case FLASH_AMDL323T:
+		printf ("29DL323T (32 M, top sector)\n");
+		break;
+	case FLASH_AMDL323B:
+		printf ("29DL323B (32 M, bottom sector)\n");
+		break;
+	case FLASH_AM640U:
+		printf ("29LV640D (64 M, uniform sector)\n");
+		break;
+	default:
+		printf ("Unknown Chip Type\n");
+		break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+			info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i = 0; i < info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	prot = 0;
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect])
+			prot++;
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts ();
+
+	V_ULONG (info->start[0] + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + (0x02AA << 3)) = 0x00550055;
+	V_ULONG (info->start[0] + (0x0555 << 3)) = 0x00800080;
+	V_ULONG (info->start[0] + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + (0x02AA << 3)) = 0x00550055;
+	V_ULONG (info->start[0] + 4 + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + 4 + (0x02AA << 3)) = 0x00550055;
+	V_ULONG (info->start[0] + 4 + (0x0555 << 3)) = 0x00800080;
+	V_ULONG (info->start[0] + 4 + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + 4 + (0x02AA << 3)) = 0x00550055;
+	udelay (1000);
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			V_ULONG (info->start[sect]) = 0x00300030;
+			V_ULONG (info->start[sect] + 4) = 0x00300030;
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts ();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last = start;
+	while ((V_ULONG (info->start[l_sect]) & 0x00800080) != 0x00800080 ||
+	       (V_ULONG (info->start[l_sect] + 4) & 0x00800080) != 0x00800080)
+	{
+		if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			serial_putc ('.');
+			last = now;
+		}
+	}
+
+  DONE:
+	/* reset to read mode */
+	flash_reset ();
+
+	printf (" done\n");
+	return 0;
+}
+
+static int write_dword (flash_info_t *, ulong, unsigned char *);
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+	ulong dp;
+	static unsigned char bb[8];
+	int i, l, rc, cc = cnt;
+
+	dp = (addr & ~7);		/* get lower dword aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - dp) != 0) {
+		for (i = 0; i < 8; i++)
+			bb[i] = (i < l || (i - l) >= cc) ? V_BYTE (dp + i) : *src++;
+		if ((rc = write_dword (info, dp, bb)) != 0) {
+			return (rc);
+		}
+		dp += 8;
+		cc -= 8 - l;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cc >= 8) {
+		if ((rc = write_dword (info, dp, src)) != 0) {
+			return (rc);
+		}
+		dp += 8;
+		src += 8;
+		cc -= 8;
+	}
+
+	if (cc <= 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	for (i = 0; i < 8; i++) {
+		bb[i] = (i < cc) ? *src++ : V_BYTE (dp + i);
+	}
+	return (write_dword (info, dp, bb));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a dword to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_dword (flash_info_t * info, ulong dest, unsigned char *pdata)
+{
+	ulong start, cl, ch;
+	int flag, i;
+
+	for (ch = 0, i = 0; i < 4; i++)
+		ch = (ch << 8) + *pdata++;	/* high word    */
+	for (cl = 0, i = 0; i < 4; i++)
+		cl = (cl << 8) + *pdata++;	/* low word */
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *) dest) & ch) != ch
+		|| (*((vu_long *) (dest + 4)) & cl) != cl) {
+		return (2);
+	}
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts ();
+
+	V_ULONG (info->start[0] + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + (0x02AA << 3)) = 0x00550055;
+	V_ULONG (info->start[0] + (0x0555 << 3)) = 0x00A000A0;
+	V_ULONG (dest) = ch;
+	V_ULONG (info->start[0] + 4 + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + 4 + (0x02AA << 3)) = 0x00550055;
+	V_ULONG (info->start[0] + 4 + (0x0555 << 3)) = 0x00A000A0;
+	V_ULONG (dest + 4) = cl;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts ();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	while (((V_ULONG (dest) & 0x00800080) != (ch & 0x00800080)) ||
+		   ((V_ULONG (dest + 4) & 0x00800080) != (cl & 0x00800080))) {
+		if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
diff --git a/board/siemens/pcu_e/flash.c b/board/siemens/pcu_e/flash.c
new file mode 100644
index 0000000..b8c0df7
--- /dev/null
+++ b/board/siemens/pcu_e/flash.c
@@ -0,0 +1,700 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_FLASH
+
+#ifdef DEBUG_FLASH
+#define DEBUGF(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGF(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_data (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ *
+ * The PCU E uses an address map where flash banks are aligned top
+ * down, so that the "first" flash bank ends at top of memory, and
+ * the monitor entry point is at address (0xFFF00100). The second
+ * flash bank is mapped immediately below bank 0.
+ *
+ * This is NOT in conformance to the "official" memory map!
+ *
+ */
+
+#define PCU_MONITOR_BASE   ( (flash_info[0].start[0] + flash_info[0].size - 1) \
+			   - (0xFFFFFFFF - CFG_MONITOR_BASE) )
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long base, size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	/*
+	 * Warning:
+	 *
+	 * Since the PCU E memory map assigns flash banks top down,
+	 * we swap the numbering later if both banks are equipped,
+	 * so they look like a contiguous area of memory.
+	 */
+	DEBUGF("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_PRELIM);
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+	DEBUGF("## Get flash bank 2 size @ 0x%08x\n",FLASH_BASE6_PRELIM);
+	size_b1 = flash_get_size((vu_long *)FLASH_BASE6_PRELIM, &flash_info[1]);
+
+	DEBUGF("## Prelim. Flash bank sizes: %08lx + 0x%08lx\n", size_b0, size_b1);
+
+	if (size_b1 > size_b0) {
+		printf ("## ERROR: "
+			"Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
+			size_b1, size_b1<<20,
+			size_b0, size_b0<<20
+		);
+		flash_info[0].flash_id	= FLASH_UNKNOWN;
+		flash_info[1].flash_id	= FLASH_UNKNOWN;
+		flash_info[0].sector_count	= -1;
+		flash_info[1].sector_count	= -1;
+		flash_info[0].size		= 0;
+		flash_info[1].size		= 0;
+		return (0);
+	}
+
+	DEBUGF ("## Before remap: "
+		"BR0: 0x%08x    OR0: 0x%08x    "
+		"BR6: 0x%08x    OR6: 0x%08x\n",
+		memctl->memc_br0, memctl->memc_or0,
+		memctl->memc_br6, memctl->memc_or6);
+
+	/* Remap FLASH according to real size */
+	base = 0 - size_b0;
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
+	memctl->memc_br0 = (base & BR_BA_MSK) | BR_PS_16 | BR_MS_GPCM | BR_V;
+
+	DEBUGF("## BR0: 0x%08x    OR0: 0x%08x\n",
+		memctl->memc_br0, memctl->memc_or0);
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((vu_long *)base, &flash_info[0]);
+	base = 0 - size_b0;
+
+	flash_info[0].size = size_b0;
+
+	flash_get_offsets (base, &flash_info[0]);
+
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      PCU_MONITOR_BASE,
+		      PCU_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+	/* ENV protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+		      &flash_info[0]);
+#endif
+
+	if (size_b1) {
+		flash_info_t tmp_info;
+
+		memctl->memc_or6 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000);
+		memctl->memc_br6 = ((base - size_b1) & BR_BA_MSK) |
+				    BR_PS_16 | BR_MS_GPCM | BR_V;
+
+		DEBUGF("## New BR6: 0x%08x    OR6: 0x%08x\n",
+			memctl->memc_br6, memctl->memc_or6);
+
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size((vu_long *)(base - size_b1),
+					  &flash_info[1]);
+		base -= size_b1;
+
+		flash_get_offsets (base, &flash_info[1]);
+
+		flash_info[1].size = size_b1;
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+		/* ENV protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_ENV_ADDR,
+			      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+			      &flash_info[1]);
+#endif
+		/*
+		 * Swap bank numbers so that addresses are in ascending order
+		 */
+		tmp_info = flash_info[0];
+		flash_info[0] = flash_info[1];
+		flash_info[1] = tmp_info;
+	} else {
+		memctl->memc_br1 = 0;		/* invalidate bank */
+
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+	}
+
+
+	DEBUGF("## Final Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1);
+
+	return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+	short n;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		return;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_AMD) {
+		return;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AMDL322T:
+	case FLASH_AMDL323T:
+	case FLASH_AMDL324T:
+		/* set sector offsets for top boot block type		*/
+
+		base += info->size;
+		i = info->sector_count;
+		for (n=0; n<8; ++n) {		/*  8 x 8k boot sectors	*/
+			base -= 8 << 10;
+			--i;
+			info->start[i] = base;
+		}
+		while (i > 0) {			/* 64k regular sectors	*/
+			base -= 64 << 10;
+			--i;
+			info->start[i] = base;
+		}
+		return;
+	case FLASH_AMDL322B:
+	case FLASH_AMDL323B:
+	case FLASH_AMDL324B:
+		/* set sector offsets for bottom boot block type	*/
+		for (i=0; i<8; ++i) {		/*  8 x 8k boot sectors	*/
+			info->start[i] = base;
+			base += 8 << 10;
+		}
+		while (base < info->size) {	/* 64k regular sectors	*/
+			info->start[i] = base;
+			base += 64 << 10;
+			++i;
+		}
+		return;
+	case FLASH_AMDL640:
+		/* set sector offsets for dual boot block type		*/
+		for (i=0; i<8; ++i) {		/*  8 x 8k boot sectors	*/
+			info->start[i] = base;
+			base += 8 << 10;
+		}
+		n = info->sector_count - 8;
+		while (i < n) {			/* 64k regular sectors	*/
+			info->start[i] = base;
+			base += 64 << 10;
+			++i;
+		}
+		while (i < info->sector_count) { /* 8 x 8k boot sectors	*/
+			info->start[i] = base;
+			base += 8 << 10;
+			++i;
+		}
+		return;
+	default:
+		return;
+	}
+	/* NOTREACHED */
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AMDL322B:	printf ("AM29DL322B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AMDL322T:	printf ("AM29DL322T (32 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AMDL323B:	printf ("AM29DL323B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AMDL323T:	printf ("AM29DL323T (32 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AMDL324B:	printf ("AM29DL324B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AMDL324T:	printf ("AM29DL324T (32 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AMDL640:	printf ("AM29DL640D (64 Mbit, dual boot sector)\n");
+				break;
+	default:		printf ("Unknown Chip Type 0x%lX\n",
+					info->flash_id);
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	ushort value;
+	vu_short *saddr = (vu_short *)addr;
+
+	/* Write auto select command: read Manufacturer ID */
+	saddr[0x0555] = 0x00AA;
+	saddr[0x02AA] = 0x0055;
+	saddr[0x0555] = 0x0090;
+
+	value = saddr[0];
+
+	DEBUGF("Manuf. ID @ 0x%08lx: 0x%04x\n", (ulong)addr, value);
+
+	switch (value) {
+	case (AMD_MANUFACT & 0xFFFF):
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case (FUJ_MANUFACT & 0xFFFF):
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	default:
+		DEBUGF("Unknown Manufacturer ID\n");
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = saddr[1];			/* device ID		*/
+
+	DEBUGF("Device ID @ 0x%08lx: 0x%04x\n", (ulong)(&addr[1]), value);
+
+	switch (value) {
+
+	case (AMD_ID_DL322T & 0xFFFF):
+		info->flash_id += FLASH_AMDL322T;
+		info->sector_count = 71;
+		info->size = 0x00400000;
+		break;				/* => 8 MB		*/
+
+	case (AMD_ID_DL322B & 0xFFFF):
+		info->flash_id += FLASH_AMDL322B;
+		info->sector_count = 71;
+		info->size = 0x00400000;
+		break;				/* => 8 MB		*/
+
+	case (AMD_ID_DL323T & 0xFFFF):
+		info->flash_id += FLASH_AMDL323T;
+		info->sector_count = 71;
+		info->size = 0x00400000;
+		break;				/* => 8 MB		*/
+
+	case (AMD_ID_DL323B & 0xFFFF):
+		info->flash_id += FLASH_AMDL323B;
+		info->sector_count = 71;
+		info->size = 0x00400000;
+		break;				/* => 8 MB		*/
+
+	case (AMD_ID_DL324T & 0xFFFF):
+		info->flash_id += FLASH_AMDL324T;
+		info->sector_count = 71;
+		info->size = 0x00400000;
+		break;				/* => 8 MB		*/
+
+	case (AMD_ID_DL324B & 0xFFFF):
+		info->flash_id += FLASH_AMDL324B;
+		info->sector_count = 71;
+		info->size = 0x00400000;
+		break;				/* => 8 MB		*/
+	case (AMD_ID_DL640  & 0xFFFF):
+		info->flash_id += FLASH_AMDL640;
+		info->sector_count = 142;
+		info->size = 0x00800000;
+		break;
+	default:
+		DEBUGF("Unknown Device ID\n");
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+
+	}
+
+	flash_get_offsets ((ulong)addr, info);
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+#if 0
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		saddr = (vu_short *)(info->start[i]);
+		info->protect[i] = saddr[2] & 1;
+#else
+		info->protect[i] =0;
+#endif
+	}
+
+	if (info->sector_count > CFG_MAX_FLASH_SECT) {
+		printf ("** ERROR: sector count %d > max (%d) **\n",
+			info->sector_count, CFG_MAX_FLASH_SECT);
+		info->sector_count = CFG_MAX_FLASH_SECT;
+	}
+
+	saddr = (vu_short *)info->start[0];
+	*saddr = 0x00F0;	/* restore read mode */
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	vu_short *addr = (vu_short*)(info->start[0]);
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    (info->flash_id > FLASH_AMD_COMP)) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0x00AA;
+	addr[0x02AA] = 0x0055;
+	addr[0x0555] = 0x0080;
+	addr[0x0555] = 0x00AA;
+	addr[0x02AA] = 0x0055;
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (vu_short*)(info->start[sect]);
+			addr[0] = 0x0030;
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (vu_short*)(info->start[l_sect]);
+	while ((addr[0] & 0x0080) != 0x0080) {
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (vu_short *)info->start[0];
+	addr[0] = 0x00F0;	/* reset bank */
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+#define FLASH_WIDTH	2	/* flash bus width in bytes */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~(FLASH_WIDTH-1));	/* get lower FLASH_WIDTH aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<FLASH_WIDTH && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_data(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += FLASH_WIDTH;
+	}
+
+	/*
+	 * handle FLASH_WIDTH aligned part
+	 */
+	while (cnt >= FLASH_WIDTH) {
+		data = 0;
+		for (i=0; i<FLASH_WIDTH; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_data(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += FLASH_WIDTH;
+		cnt -= FLASH_WIDTH;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<FLASH_WIDTH; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_data(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_data (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_short *addr  = (vu_short*)(info->start[0]);
+	vu_short *sdest = (vu_short *)dest;
+	ushort sdata = (ushort)data;
+	ushort sval;
+	ulong start, passed;
+	int flag, rc;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*sdest & sdata) != sdata) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0x00AA;
+	addr[0x02AA] = 0x0055;
+	addr[0x0555] = 0x00A0;
+
+#ifdef WORKAROUND_FOR_BROKEN_HARDWARE
+	/* work around the timeout bugs */
+	udelay(20);
+#endif
+
+	*sdest = sdata;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	rc = 0;
+	/* data polling for D7 */
+	start = get_timer (0);
+
+	for (passed=0; passed < CFG_FLASH_WRITE_TOUT; passed=get_timer(start)) {
+
+		sval = *sdest;
+
+		if ((sval & 0x0080) == (sdata & 0x0080))
+			break;
+
+		if ((sval & 0x0020) == 0)	/* DQ5: Timeout? */
+			continue;
+
+		sval = *sdest;
+
+		if ((sval & 0x0080) != (sdata & 0x0080))
+			rc = 1;
+
+		break;
+	}
+
+	if (rc) {
+	    DEBUGF ("Program cycle failed @ addr 0x%08lX: val %04X data %04X\n",
+		 dest, sval, sdata);
+	}
+
+	if (passed >= CFG_FLASH_WRITE_TOUT) {
+		DEBUGF ("Timeout @ addr 0x%08lX: val %04X data %04X\n",
+			dest, sval, sdata);
+		rc = 1;
+	}
+
+	/* reset to read mode */
+	addr = (vu_short *)info->start[0];
+	addr[0] = 0x00F0;	/* reset bank */
+
+	return (rc);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/sixnet/flash.c b/board/sixnet/flash.c
new file mode 100644
index 0000000..c201875
--- /dev/null
+++ b/board/sixnet/flash.c
@@ -0,0 +1,746 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
+ *        has nothing to do with the flash chip being 8-bit or 16-bit.
+ */
+#ifdef CONFIG_FLASH_16BIT
+typedef unsigned short FLASH_PORT_WIDTH;
+typedef volatile unsigned short FLASH_PORT_WIDTHV;
+#define	FLASH_ID_MASK	0xFFFF
+#else
+typedef unsigned long FLASH_PORT_WIDTH;
+typedef volatile unsigned long FLASH_PORT_WIDTHV;
+#define	FLASH_ID_MASK	0xFFFFFFFF
+#endif
+
+#define FPW	FLASH_PORT_WIDTH
+#define FPWV	FLASH_PORT_WIDTHV
+
+#define ORMASK(size) ((-size) & OR_AM_MSK)
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size(FPWV *addr, flash_info_t *info);
+static void flash_reset(flash_info_t *info);
+static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data);
+static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
+static void flash_get_offsets(ulong base, flash_info_t *info);
+#ifdef CFG_FLASH_PROTECTION
+static void flash_sync_real_protect(flash_info_t *info);
+#endif
+
+/*-----------------------------------------------------------------------
+ * flash_init()
+ *
+ * sets up flash_info and returns size of FLASH (bytes)
+ */
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i < CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	size_b = flash_get_size((FPW *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_info[0].size = size_b;
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx\n",size_b);
+	}
+
+	/* Remap FLASH according to real size, so only at proper address */
+	memctl->memc_or0 = (memctl->memc_or0 & ~OR_AM_MSK) | ORMASK(size_b);
+
+	/* Do this again (was done already in flast_get_size), just
+	 * in case we move it when remap the FLASH.
+	 */
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+#ifdef CFG_FLASH_PROTECTION
+	/* read the hardware protection status (if any) into the
+	 * protection array in flash_info.
+	 */
+	flash_sync_real_protect(&flash_info[0]);
+#endif
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+	return (size_b);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_reset(flash_info_t *info)
+{
+	FPWV *base = (FPWV *)(info->start[0]);
+
+	/* Put FLASH back in read mode */
+	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
+		*base = (FPW)0x00FF00FF;	/* Intel Read Mode */
+	else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
+		*base = (FPW)0x00F000F0;	/* AMD Read Mode */
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start address table */
+	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
+	    && (info->flash_id & FLASH_BTYPE)) {
+		int bootsect_size;	/* number of bytes/boot sector	*/
+		int sect_size;		/* number of bytes/regular sector */
+
+		bootsect_size = 0x00002000 * (sizeof(FPW)/2);
+		sect_size =     0x00010000 * (sizeof(FPW)/2);
+
+		/* set sector offsets for bottom boot block type	*/
+		for (i = 0; i < 8; ++i) {
+			info->start[i] = base + (i * bootsect_size);
+		}
+		for (i = 8; i < info->sector_count; i++) {
+			info->start[i] = base + ((i - 7) * sect_size);
+		}
+	}
+	else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
+		 && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
+
+		int sect_size;		/* number of bytes/sector */
+
+		sect_size = 0x00010000 * (sizeof(FPW)/2);
+
+		/* set up sector start address table (uniform sector type) */
+		for( i = 0; i < info->sector_count; i++ )
+			info->start[i] = base + (i * sect_size);
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+void flash_print_info (flash_info_t *info)
+{
+	int i;
+	uchar *boottype;
+	uchar *bootletter;
+	uchar *fmt;
+	uchar botbootletter[] = "B";
+	uchar topbootletter[] = "T";
+	uchar botboottype[] = "bottom boot sector";
+	uchar topboottype[] = "top boot sector";
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_BM:	printf ("BRIGHT MICRO ");	break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	case FLASH_MAN_SST:	printf ("SST ");		break;
+	case FLASH_MAN_STM:	printf ("STM ");		break;
+	case FLASH_MAN_INTEL:	printf ("INTEL ");		break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	/* check for top or bottom boot, if it applies */
+	if (info->flash_id & FLASH_BTYPE) {
+		boottype = botboottype;
+		bootletter = botbootletter;
+	}
+	else {
+		boottype = topboottype;
+		bootletter = topbootletter;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM640U:
+		fmt = "29LV641D (64 Mbit, uniform sectors)\n";
+		break;
+        case FLASH_28F800C3B:
+        case FLASH_28F800C3T:
+		fmt = "28F800C3%s (8 Mbit, %s)\n";
+		break;
+	case FLASH_INTEL800B:
+	case FLASH_INTEL800T:
+		fmt = "28F800B3%s (8 Mbit, %s)\n";
+		break;
+        case FLASH_28F160C3B:
+        case FLASH_28F160C3T:
+		fmt = "28F160C3%s (16 Mbit, %s)\n";
+		break;
+	case FLASH_INTEL160B:
+	case FLASH_INTEL160T:
+		fmt = "28F160B3%s (16 Mbit, %s)\n";
+		break;
+        case FLASH_28F320C3B:
+        case FLASH_28F320C3T:
+		fmt = "28F320C3%s (32 Mbit, %s)\n";
+		break;
+	case FLASH_INTEL320B:
+	case FLASH_INTEL320T:
+		fmt = "28F320B3%s (32 Mbit, %s)\n";
+		break;
+        case FLASH_28F640C3B:
+        case FLASH_28F640C3T:
+		fmt = "28F640C3%s (64 Mbit, %s)\n";
+		break;
+	case FLASH_INTEL640B:
+	case FLASH_INTEL640T:
+		fmt = "28F640B3%s (64 Mbit, %s)\n";
+		break;
+	default:
+		fmt = "Unknown Chip Type\n";
+		break;
+	}
+
+	printf (fmt, bootletter, boottype);
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20,
+		info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0) {
+			printf ("\n   ");
+		}
+
+		printf (" %08lX%s", info->start[i],
+			info->protect[i] ? " (RO)" : "     ");
+	}
+
+	printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+ulong flash_get_size (FPWV *addr, flash_info_t *info)
+{
+	/* Write auto select command: read Manufacturer ID */
+
+	/* Write auto select command sequence and test FLASH answer */
+	addr[0x0555] = (FPW)0x00AA00AA;	/* for AMD, Intel ignores this */
+	addr[0x02AA] = (FPW)0x00550055;	/* for AMD, Intel ignores this */
+	addr[0x0555] = (FPW)0x00900090;	/* selects Intel or AMD */
+
+	/* The manufacturer codes are only 1 byte, so just use 1 byte.
+	 * This works for any bus width and any FLASH device width.
+	 */
+	switch (addr[0] & 0xff) {
+
+	case (uchar)AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+
+	case (uchar)INTEL_MANUFACT:
+		info->flash_id = FLASH_MAN_INTEL;
+		break;
+
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		break;
+	}
+
+	/* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
+	if (info->flash_id != FLASH_UNKNOWN) switch (addr[1]) {
+
+	case (FPW)AMD_ID_LV640U:	/* 29LV640 and 29LV641 have same ID */
+		info->flash_id += FLASH_AM640U;
+		info->sector_count = 128;
+		info->size = 0x00800000 * (sizeof(FPW)/2);
+		break;				/* => 8 or 16 MB	*/
+
+	case (FPW)INTEL_ID_28F800C3B:
+		info->flash_id += FLASH_28F800C3B;
+		info->sector_count = 23;
+		info->size = 0x00100000 * (sizeof(FPW)/2);
+		break;				/* => 1 or 2 MB		*/
+
+	case (FPW)INTEL_ID_28F800B3B:
+		info->flash_id += FLASH_INTEL800B;
+		info->sector_count = 23;
+		info->size = 0x00100000 * (sizeof(FPW)/2);
+		break;				/* => 1 or 2 MB		*/
+
+	case (FPW)INTEL_ID_28F160C3B:
+		info->flash_id += FLASH_28F160C3B;
+		info->sector_count = 39;
+		info->size = 0x00200000 * (sizeof(FPW)/2);
+		break;				/* => 2 or 4 MB		*/
+
+	case (FPW)INTEL_ID_28F160B3B:
+		info->flash_id += FLASH_INTEL160B;
+		info->sector_count = 39;
+		info->size = 0x00200000 * (sizeof(FPW)/2);
+		break;				/* => 2 or 4 MB		*/
+
+	case (FPW)INTEL_ID_28F320C3B:
+		info->flash_id += FLASH_28F320C3B;
+		info->sector_count = 71;
+		info->size = 0x00400000 * (sizeof(FPW)/2);
+		break;				/* => 4 or 8 MB		*/
+
+	case (FPW)INTEL_ID_28F320B3B:
+		info->flash_id += FLASH_INTEL320B;
+		info->sector_count = 71;
+		info->size = 0x00400000 * (sizeof(FPW)/2);
+		break;				/* => 4 or 8 MB		*/
+
+	case (FPW)INTEL_ID_28F640C3B:
+		info->flash_id += FLASH_28F640C3B;
+		info->sector_count = 135;
+		info->size = 0x00800000 * (sizeof(FPW)/2);
+		break;				/* => 8 or 16 MB	*/
+
+	case (FPW)INTEL_ID_28F640B3B:
+		info->flash_id += FLASH_INTEL640B;
+		info->sector_count = 135;
+		info->size = 0x00800000 * (sizeof(FPW)/2);
+		break;				/* => 8 or 16 MB	*/
+
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* => no or unknown flash */
+	}
+
+	flash_get_offsets((ulong)addr, info);
+
+	/* Put FLASH back in read mode */
+	flash_reset(info);
+
+	return (info->size);
+}
+
+#ifdef CFG_FLASH_PROTECTION
+/*-----------------------------------------------------------------------
+ */
+
+static void flash_sync_real_protect(flash_info_t *info)
+{
+    FPWV *addr = (FPWV *)(info->start[0]);
+    FPWV *sect;
+    int i;
+
+    switch (info->flash_id & FLASH_TYPEMASK) {
+    case FLASH_28F800C3B:
+    case FLASH_28F800C3T:
+    case FLASH_28F160C3B:
+    case FLASH_28F160C3T:
+    case FLASH_28F320C3B:
+    case FLASH_28F320C3T:
+    case FLASH_28F640C3B:
+    case FLASH_28F640C3T:
+	/* check for protected sectors */
+	*addr = (FPW)0x00900090;
+	for (i = 0; i < info->sector_count; i++) {
+	    /* read sector protection at sector address, (A7 .. A0) = 0x02.
+	     * D0 = 1 for each device if protected.
+	     * If at least one device is protected the sector is marked
+	     * protected, but mixed protected and  unprotected devices
+	     * within a sector should never happen.
+	     */
+	    sect = (FPWV *)(info->start[i]);
+	    info->protect[i] = (sect[2] & (FPW)(0x00010001)) ? 1 : 0;
+	}
+
+	/* Put FLASH back in read mode */
+	flash_reset(info);
+	break;
+
+    case FLASH_AM640U:
+    default:
+	/* no hardware protect that we support */
+	break;
+    }
+}
+#endif
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	FPWV *addr;
+	int flag, prot, sect;
+	int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
+	ulong start, now, last;
+	int rcode = 0;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_INTEL800B:
+	case FLASH_INTEL160B:
+	case FLASH_INTEL320B:
+	case FLASH_INTEL640B:
+	case FLASH_28F800C3B:
+	case FLASH_28F160C3B:
+	case FLASH_28F320C3B:
+	case FLASH_28F640C3B:
+	case FLASH_AM640U:
+		break;
+	case FLASH_UNKNOWN:
+	default:
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	start = get_timer(0);
+	last  = start;
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
+
+		if (info->protect[sect] != 0)	/* protected, skip it */
+			continue;
+
+		/* Disable interrupts which might cause a timeout here */
+		flag = disable_interrupts();
+
+		addr = (FPWV *)(info->start[sect]);
+		if (intel) {
+			*addr = (FPW)0x00500050; /* clear status register */
+			*addr = (FPW)0x00200020; /* erase setup */
+			*addr = (FPW)0x00D000D0; /* erase confirm */
+		}
+		else {
+			/* must be AMD style if not Intel */
+			FPWV *base;		/* first address in bank */
+
+			base = (FPWV *)(info->start[0]);
+			base[0x0555] = (FPW)0x00AA00AA;	/* unlock */
+			base[0x02AA] = (FPW)0x00550055;	/* unlock */
+			base[0x0555] = (FPW)0x00800080;	/* erase mode */
+			base[0x0555] = (FPW)0x00AA00AA;	/* unlock */
+			base[0x02AA] = (FPW)0x00550055;	/* unlock */
+			*addr = (FPW)0x00300030;	/* erase sector */
+		}
+
+		/* re-enable interrupts if necessary */
+		if (flag)
+			enable_interrupts();
+
+		/* wait at least 50us for AMD, 80us for Intel.
+		 * Let's wait 1 ms.
+		 */
+		udelay (1000);
+
+		while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
+			if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+				printf ("Timeout\n");
+
+				if (intel) {
+					/* suspend erase	*/
+					*addr = (FPW)0x00B000B0;
+				}
+
+				flash_reset(info);	/* reset to read mode */
+				rcode = 1;		/* failed */
+				break;
+			}
+
+			/* show that we're waiting */
+			if ((now - last) > 1000) {	/* every second */
+				putc ('.');
+				last = now;
+			}
+		}
+
+		flash_reset(info);	/* reset to read mode	*/
+	}
+
+	printf (" done\n");
+	return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+    FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
+    int bytes;	  /* number of bytes to program in current word		*/
+    int left;	  /* number of bytes left to program			*/
+    int i, res;
+
+    for (left = cnt, res = 0;
+	 left > 0 && res == 0;
+	 addr += sizeof(data), left -= sizeof(data) - bytes) {
+
+        bytes = addr & (sizeof(data) - 1);
+        addr &= ~(sizeof(data) - 1);
+
+	/* combine source and destination data so can program
+	 * an entire word of 16 or 32 bits
+	 */
+        for (i = 0; i < sizeof(data); i++) {
+            data <<= 8;
+            if (i < bytes || i - bytes >= left )
+		data += *((uchar *)addr + i);
+	    else
+		data += *src++;
+	}
+
+	/* write one word to the flash */
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:
+		res = write_word_amd(info, (FPWV *)addr, data);
+		break;
+	case FLASH_MAN_INTEL:
+		res = write_word_intel(info, (FPWV *)addr, data);
+		break;
+	default:
+		/* unknown flash type, error! */
+		printf ("missing or unknown FLASH type\n");
+		res = 1;	/* not really a timeout, but gives error */
+		break;
+	}
+    }
+
+    return (res);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for AMD FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data)
+{
+    ulong start;
+    int flag;
+    int res = 0;	/* result, assume success	*/
+    FPWV *base;		/* first address in flash bank	*/
+
+    /* Check if Flash is (sufficiently) erased */
+    if ((*dest & data) != data) {
+	return (2);
+    }
+
+
+    base = (FPWV *)(info->start[0]);
+
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    base[0x0555] = (FPW)0x00AA00AA;	/* unlock */
+    base[0x02AA] = (FPW)0x00550055;	/* unlock */
+    base[0x0555] = (FPW)0x00A000A0;	/* selects program mode */
+
+    *dest = data;		/* start programming the data	*/
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+	enable_interrupts();
+
+    start = get_timer (0);
+
+    /* data polling for D7 */
+    while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
+	if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+	    *dest = (FPW)0x00F000F0;	/* reset bank */
+	    res = 1;
+	}
+    }
+
+    return (res);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash for Intel FLASH
+ * A word is 16 or 32 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word_intel (flash_info_t *info, FPWV *dest, FPW data)
+{
+    ulong start;
+    int flag;
+    int res = 0;	/* result, assume success	*/
+
+    /* Check if Flash is (sufficiently) erased */
+    if ((*dest & data) != data) {
+	return (2);
+    }
+
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    *dest = (FPW)0x00500050;	/* clear status register	*/
+    *dest = (FPW)0x00FF00FF;	/* make sure in read mode	*/
+    *dest = (FPW)0x00400040;	/* program setup		*/
+
+    *dest = data;		/* start programming the data	*/
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+	enable_interrupts();
+
+    start = get_timer (0);
+
+    while (res == 0 && (*dest & (FPW)0x00800080) != (FPW)0x00800080) {
+	if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+	    *dest = (FPW)0x00B000B0;	/* Suspend program	*/
+	    res = 1;
+	}
+    }
+
+    if (res == 0 && (*dest & (FPW)0x00100010))
+	res = 1;	/* write failed, time out error is close enough	*/
+
+    *dest = (FPW)0x00500050;	/* clear status register	*/
+    *dest = (FPW)0x00FF00FF;	/* make sure in read mode	*/
+
+    return (res);
+}
+
+#ifdef CFG_FLASH_PROTECTION
+/*-----------------------------------------------------------------------
+ */
+int flash_real_protect (flash_info_t * info, long sector, int prot)
+{
+	int rcode = 0;		/* assume success */
+	FPWV *addr;		/* address of sector */
+	FPW value;
+
+	addr = (FPWV *) (info->start[sector]);
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_28F800C3B:
+	case FLASH_28F800C3T:
+	case FLASH_28F160C3B:
+	case FLASH_28F160C3T:
+	case FLASH_28F320C3B:
+	case FLASH_28F320C3T:
+	case FLASH_28F640C3B:
+	case FLASH_28F640C3T:
+		flash_reset (info);		/* make sure in read mode */
+		*addr = (FPW) 0x00600060L;	/* lock command setup */
+		if (prot)
+			*addr = (FPW) 0x00010001L;	/* lock sector */
+		else
+			*addr = (FPW) 0x00D000D0L;	/* unlock sector */
+		flash_reset (info);		/* reset to read mode */
+
+		/* now see if it really is locked/unlocked as requested */
+		*addr = (FPW) 0x00900090;
+		/* read sector protection at sector address, (A7 .. A0) = 0x02.
+		 * D0 = 1 for each device if protected.
+		 * If at least one device is protected the sector is marked
+		 * protected, but return failure. Mixed protected and
+		 * unprotected devices within a sector should never happen.
+		 */
+		value = addr[2] & (FPW) 0x00010001;
+		if (value == 0)
+			info->protect[sector] = 0;
+		else if (value == (FPW) 0x00010001)
+			info->protect[sector] = 1;
+		else {
+			/* error, mixed protected and unprotected */
+			rcode = 1;
+			info->protect[sector] = 1;
+		}
+		if (info->protect[sector] != prot)
+			rcode = 1;	/* failed to protect/unprotect as requested */
+
+		/* reload all protection bits from hardware for now */
+		flash_sync_real_protect (info);
+		break;
+
+	case FLASH_AM640U:
+	default:
+		/* no hardware protect that we support */
+		info->protect[sector] = prot;
+		break;
+	}
+
+	return rcode;
+}
+#endif
diff --git a/board/spd8xx/flash.c b/board/spd8xx/flash.c
new file mode 100644
index 0000000..8c0bb4f
--- /dev/null
+++ b/board/spd8xx/flash.c
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	/* All Speech Design board memory (DRAM and EPROM) initialisation is
+	done in dram_init().
+	The caller of ths function here expects the total size and will hang,
+	if we give here back 0. So we return the EPROM size. */
+
+	return (1024 * 1024); /* 1 MB */
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+void flash_print_info (flash_info_t *info)
+{
+	printf("no FLASH memory in MPC823TS board\n");
+	return;
+}
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	return 1;
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/tqm8260/flash.c b/board/tqm8260/flash.c
new file mode 100644
index 0000000..dd7a4cc
--- /dev/null
+++ b/board/tqm8260/flash.c
@@ -0,0 +1,488 @@
+/*
+ * (C) Copyright 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for AMD devices on the TQM8260 board
+ *
+ *--------------------------------------------------------------------
+ * 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 <mpc8xx.h>
+
+#define V_ULONG(a)	(*(volatile unsigned long *)( a ))
+#define V_BYTE(a)	(*(volatile unsigned char *)( a ))
+
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+
+/*-----------------------------------------------------------------------
+ */
+void flash_reset (void)
+{
+	if (flash_info[0].flash_id != FLASH_UNKNOWN) {
+		V_ULONG (flash_info[0].start[0]) = 0x00F000F0;
+		V_ULONG (flash_info[0].start[0] + 4) = 0x00F000F0;
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+ulong flash_get_size (ulong baseaddr, flash_info_t * info)
+{
+	short i;
+	unsigned long flashtest_h, flashtest_l;
+
+	/* Write auto select command sequence and test FLASH answer */
+	V_ULONG (baseaddr + ((ulong) 0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (baseaddr + ((ulong) 0x02AA << 3)) = 0x00550055;
+	V_ULONG (baseaddr + ((ulong) 0x0555 << 3)) = 0x00900090;
+	V_ULONG (baseaddr + 4 + ((ulong) 0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (baseaddr + 4 + ((ulong) 0x02AA << 3)) = 0x00550055;
+	V_ULONG (baseaddr + 4 + ((ulong) 0x0555 << 3)) = 0x00900090;
+
+	flashtest_h = V_ULONG (baseaddr);	/* manufacturer ID     */
+	flashtest_l = V_ULONG (baseaddr + 4);
+
+	switch ((int) flashtest_h) {
+	case AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash     */
+	}
+
+	flashtest_h = V_ULONG (baseaddr + 8);	/* device ID           */
+	flashtest_l = V_ULONG (baseaddr + 12);
+	if (flashtest_h != flashtest_l) {
+		info->flash_id = FLASH_UNKNOWN;
+	} else {
+		switch (flashtest_h) {
+		case AMD_ID_LV800T:
+			info->flash_id += FLASH_AM800T;
+			info->sector_count = 19;
+			info->size = 0x00400000;
+			break;			/* 4 * 1 MB = 4 MB  */
+		case AMD_ID_LV800B:
+			info->flash_id += FLASH_AM800B;
+			info->sector_count = 19;
+			info->size = 0x00400000;
+			break;			/* 4 * 1 MB = 4 MB  */
+		case AMD_ID_LV160T:
+			info->flash_id += FLASH_AM160T;
+			info->sector_count = 35;
+			info->size = 0x00800000;
+			break;			/* 4 * 2 MB = 8 MB  */
+		case AMD_ID_LV160B:
+			info->flash_id += FLASH_AM160B;
+			info->sector_count = 35;
+			info->size = 0x00800000;
+			break;			/* 4 * 2 MB = 8 MB  */
+		case AMD_ID_DL322T:
+			info->flash_id += FLASH_AMDL322T;
+			info->sector_count = 71;
+			info->size = 0x01000000;
+			break;			/* 4 * 4 MB = 16 MB */
+		case AMD_ID_DL322B:
+			info->flash_id += FLASH_AMDL322B;
+			info->sector_count = 71;
+			info->size = 0x01000000;
+			break;			/* 4 * 4 MB = 16 MB */
+		case AMD_ID_DL323T:
+			info->flash_id += FLASH_AMDL323T;
+			info->sector_count = 71;
+			info->size = 0x01000000;
+			break;			/* 4 * 4 MB = 16 MB */
+		case AMD_ID_DL323B:
+			info->flash_id += FLASH_AMDL323B;
+			info->sector_count = 71;
+			info->size = 0x01000000;
+			break;			/* 4 * 4 MB = 16 MB */
+		case AMD_ID_LV640U:
+			info->flash_id += FLASH_AM640U;
+			info->sector_count = 128;
+			info->size = 0x02000000;
+			break;			/* 4 * 8 MB = 32 MB */
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			return (0);		/* no or unknown flash     */
+		}
+	}
+
+	if (flashtest_h == AMD_ID_LV640U) {
+
+		/* set up sector start adress table (uniform sector type) */
+		for (i = 0; i < info->sector_count; i++)
+			info->start[i] = baseaddr + (i * 0x00040000);
+
+	} else if (info->flash_id & FLASH_BTYPE) {
+
+		/* set up sector start adress table (bottom sector type) */
+		info->start[0] = baseaddr + 0x00000000;
+		info->start[1] = baseaddr + 0x00010000;
+		info->start[2] = baseaddr + 0x00018000;
+		info->start[3] = baseaddr + 0x00020000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = baseaddr + (i * 0x00040000) - 0x000C0000;
+		}
+
+	} else {
+
+		/* set up sector start adress table (top sector type) */
+		i = info->sector_count - 1;
+		info->start[i--] = baseaddr + info->size - 0x00010000;
+		info->start[i--] = baseaddr + info->size - 0x00018000;
+		info->start[i--] = baseaddr + info->size - 0x00020000;
+		for (; i >= 0; i--) {
+			info->start[i] = baseaddr + i * 0x00040000;
+		}
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		if ((V_ULONG (info->start[i] + 16) & 0x00010001) ||
+			(V_ULONG (info->start[i] + 20) & 0x00010001)) {
+			info->protect[i] = 1;	/* D0 = 1 if protected */
+		} else {
+			info->protect[i] = 0;
+		}
+	}
+
+	flash_reset ();
+	return (info->size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+	unsigned long size_b0 = 0;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here (only one bank) */
+
+	size_b0 = flash_get_size (CFG_FLASH0_BASE, &flash_info[0]);
+	if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+				size_b0, size_b0 >> 20);
+	}
+
+	/*
+	 * protect monitor and environment sectors
+	 */
+
+#if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
+	flash_protect (FLAG_PROTECT_SET,
+		       CFG_MONITOR_BASE,
+		       CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, &flash_info[0]);
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+	flash_protect (FLAG_PROTECT_SET,
+		       CFG_ENV_ADDR,
+		       CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
+#endif
+
+	return (size_b0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:
+		printf ("AMD ");
+		break;
+	case FLASH_MAN_FUJ:
+		printf ("FUJITSU ");
+		break;
+	default:
+		printf ("Unknown Vendor ");
+		break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM800T:
+		printf ("29LV800T (8 M, top sector)\n");
+		break;
+	case FLASH_AM800B:
+		printf ("29LV800T (8 M, bottom sector)\n");
+		break;
+	case FLASH_AM160T:
+		printf ("29LV160T (16 M, top sector)\n");
+		break;
+	case FLASH_AM160B:
+		printf ("29LV160B (16 M, bottom sector)\n");
+		break;
+	case FLASH_AMDL322T:
+		printf ("29DL322T (32 M, top sector)\n");
+		break;
+	case FLASH_AMDL322B:
+		printf ("29DL322B (32 M, bottom sector)\n");
+		break;
+	case FLASH_AMDL323T:
+		printf ("29DL323T (32 M, top sector)\n");
+		break;
+	case FLASH_AMDL323B:
+		printf ("29DL323B (32 M, bottom sector)\n");
+		break;
+	case FLASH_AM640U:
+		printf ("29LV640D (64 M, uniform sector)\n");
+		break;
+	default:
+		printf ("Unknown Chip Type\n");
+		break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+			info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i = 0; i < info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	prot = 0;
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect])
+			prot++;
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts ();
+
+	V_ULONG (info->start[0] + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + (0x02AA << 3)) = 0x00550055;
+	V_ULONG (info->start[0] + (0x0555 << 3)) = 0x00800080;
+	V_ULONG (info->start[0] + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + (0x02AA << 3)) = 0x00550055;
+	V_ULONG (info->start[0] + 4 + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + 4 + (0x02AA << 3)) = 0x00550055;
+	V_ULONG (info->start[0] + 4 + (0x0555 << 3)) = 0x00800080;
+	V_ULONG (info->start[0] + 4 + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + 4 + (0x02AA << 3)) = 0x00550055;
+	udelay (1000);
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			V_ULONG (info->start[sect]) = 0x00300030;
+			V_ULONG (info->start[sect] + 4) = 0x00300030;
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts ();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last = start;
+	while ((V_ULONG (info->start[l_sect]) & 0x00800080) != 0x00800080 ||
+	       (V_ULONG (info->start[l_sect] + 4) & 0x00800080) != 0x00800080)
+	{
+		if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			serial_putc ('.');
+			last = now;
+		}
+	}
+
+  DONE:
+	/* reset to read mode */
+	flash_reset ();
+
+	printf (" done\n");
+	return 0;
+}
+
+static int write_dword (flash_info_t *, ulong, unsigned char *);
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+	ulong dp;
+	static unsigned char bb[8];
+	int i, l, rc, cc = cnt;
+
+	dp = (addr & ~7);		/* get lower dword aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - dp) != 0) {
+		for (i = 0; i < 8; i++)
+			bb[i] = (i < l || (i - l) >= cc) ? V_BYTE (dp + i) : *src++;
+		if ((rc = write_dword (info, dp, bb)) != 0) {
+			return (rc);
+		}
+		dp += 8;
+		cc -= 8 - l;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cc >= 8) {
+		if ((rc = write_dword (info, dp, src)) != 0) {
+			return (rc);
+		}
+		dp += 8;
+		src += 8;
+		cc -= 8;
+	}
+
+	if (cc <= 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	for (i = 0; i < 8; i++) {
+		bb[i] = (i < cc) ? *src++ : V_BYTE (dp + i);
+	}
+	return (write_dword (info, dp, bb));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a dword to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_dword (flash_info_t * info, ulong dest, unsigned char *pdata)
+{
+	ulong start, cl, ch;
+	int flag, i;
+
+	for (ch = 0, i = 0; i < 4; i++)
+		ch = (ch << 8) + *pdata++;	/* high word    */
+	for (cl = 0, i = 0; i < 4; i++)
+		cl = (cl << 8) + *pdata++;	/* low word */
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *) dest) & ch) != ch
+		|| (*((vu_long *) (dest + 4)) & cl) != cl) {
+		return (2);
+	}
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts ();
+
+	V_ULONG (info->start[0] + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + (0x02AA << 3)) = 0x00550055;
+	V_ULONG (info->start[0] + (0x0555 << 3)) = 0x00A000A0;
+	V_ULONG (dest) = ch;
+	V_ULONG (info->start[0] + 4 + (0x0555 << 3)) = 0x00AA00AA;
+	V_ULONG (info->start[0] + 4 + (0x02AA << 3)) = 0x00550055;
+	V_ULONG (info->start[0] + 4 + (0x0555 << 3)) = 0x00A000A0;
+	V_ULONG (dest + 4) = cl;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts ();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	while (((V_ULONG (dest) & 0x00800080) != (ch & 0x00800080)) ||
+		   ((V_ULONG (dest + 4) & 0x00800080) != (cl & 0x00800080))) {
+		if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
diff --git a/board/w7o/fsboot.c b/board/w7o/fsboot.c
new file mode 100644
index 0000000..800583d
--- /dev/null
+++ b/board/w7o/fsboot.c
@@ -0,0 +1,90 @@
+/*
+ * (C) Copyright 2001
+ * Wave 7 Optics, Inc.
+ *
+ * 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 <config.h>
+#include <command.h>
+#include <cmd_elf.h>
+
+/*
+ * FIXME: Add code to test image and it's header.
+ */
+static int
+image_check(ulong addr)
+{
+    return valid_elf_image(addr);
+}
+
+void
+init_fsboot(void)
+{
+    char  *envp;
+    ulong loadaddr;
+    ulong testaddr;
+    ulong alt_loadaddr;
+    char buf[9];
+
+    /*
+     * Get test image address
+     */
+    if ((envp = getenv("testaddr")) != NULL)
+	testaddr = simple_strtoul(envp, NULL, 16);
+    else
+	testaddr = -1;
+
+    /*
+     * Are we going to test boot and image?
+     */
+    if ((testaddr != -1) && image_check(testaddr)) {
+
+	/* Set alt_loadaddr */
+	alt_loadaddr = testaddr;
+	sprintf(buf, "%lX", alt_loadaddr);
+	setenv("alt_loadaddr", buf);
+
+	/* Clear test_addr */
+	setenv("testaddr", NULL);
+
+	/*
+	 * Save current environment with alt_loadaddr,
+	 * and cleared testaddr.
+	 */
+	saveenv();
+
+	/*
+	 * Setup temporary loadaddr to alt_loadaddr
+	 * XXX - DO NOT SAVE ENVIRONMENT!
+	 */
+	loadaddr = alt_loadaddr;
+	sprintf(buf, "%lX", loadaddr);
+	setenv("loadaddr", buf);
+
+    } else { /* Normal boot */
+	setenv("alt_loadaddr", NULL);		/* Clear alt_loadaddr */
+	setenv("testaddr", NULL);		/* Clear testaddr */
+	saveenv();
+    }
+
+    return;
+}
+
diff --git a/board/w7o/watchdog.c b/board/w7o/watchdog.c
new file mode 100644
index 0000000..3fca5d3
--- /dev/null
+++ b/board/w7o/watchdog.c
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
+ *
+ * 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
+ */
+
+/*
+ * W7O board level hardware watchdog.
+ */
+#include <common.h>
+#include <config.h>
+
+#ifdef CONFIG_HW_WATCHDOG
+#include <watchdog.h>
+
+void hw_watchdog_reset(void)
+{
+    volatile ushort *hwd = (ushort *)(CFG_W7O_EBC_PB7CR & 0xfff00000);
+
+    /*
+     * Read the LMG's hwd register and toggle the
+     * watchdog bit to reset it.   On the LMC, just
+     * reading it is enough, but toggling the bit
+     * doen't hurt either.
+     */
+    *hwd = *hwd ^ 0x8000;
+
+} /* hw_watchdog_reset() */
+
+#endif /* CONFIG_HW_WATCHDOG */
+
diff --git a/board/westel/amx860/flash.c b/board/westel/amx860/flash.c
new file mode 100644
index 0000000..28238c1
--- /dev/null
+++ b/board/westel/amx860/flash.c
@@ -0,0 +1,637 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.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 <mpc8xx.h>
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+#if defined(CFG_ENV_IS_IN_FLASH)
+# ifndef  CFG_ENV_ADDR
+#  define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET)
+# endif
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE	CFG_ENV_SECT_SIZE
+# endif
+# ifndef  CFG_ENV_SECT_SIZE
+#  define CFG_ENV_SECT_SIZE  CFG_ENV_SIZE
+# endif
+#endif
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_FLASH
+
+#ifdef DEBUG_FLASH
+#define DEBUGF(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGF(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+	volatile immap_t     *immap  = (immap_t *)CFG_IMMR;
+	volatile memctl8xx_t *memctl = &immap->im_memctl;
+	unsigned long size_b0, size_b1;
+	int i;
+
+	/* Init: no FLASHes known */
+	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Static FLASH Bank configuration here - FIXME XXX */
+
+	DEBUGF("\n## Get flash bank 1 size @ 0x%08x\n",FLASH_BASE0_PRELIM);
+
+	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+			size_b0, size_b0<<20);
+	}
+
+#if defined(FLASH_BASE1_PRELIM) && (FLASH_BASE1_PRELIM != 0)
+	DEBUGF("## Get flash bank 2 size @ 0x%08x\n",FLASH_BASE1_PRELIM);
+
+	size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+
+	if (size_b1 > size_b0) {
+		printf ("## ERROR: "
+			"Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
+			size_b1, size_b1<<20,
+			size_b0, size_b0<<20
+		);
+		flash_info[0].flash_id	= FLASH_UNKNOWN;
+		flash_info[1].flash_id	= FLASH_UNKNOWN;
+		flash_info[0].sector_count	= -1;
+		flash_info[1].sector_count	= -1;
+		flash_info[0].size		= 0;
+		flash_info[1].size		= 0;
+		return (0);
+	}
+#else
+	size_b1 = 0;
+#endif	/* FLASH_BASE1_PRELIM */
+
+	DEBUGF("## Prelim. Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1);
+
+	DEBUGF ("## Before remap: "
+		"BR0: 0x%08x    OR0: 0x%08x    "
+		"BR1: 0x%08x    OR1: 0x%08x\n",
+		memctl->memc_br0, memctl->memc_or0,
+		memctl->memc_br1, memctl->memc_or1);
+
+	/* Remap FLASH according to real size */
+	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK);
+	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
+
+	DEBUGF("## BR0: 0x%08x    OR0: 0x%08x\n",
+		memctl->memc_br0, memctl->memc_or0);
+
+	/* Re-do sizing to get full correct info */
+	size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
+
+	flash_info[0].size = size_b0;
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+	/* monitor protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_MONITOR_BASE,
+		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+		      &flash_info[0]);
+#endif
+
+#ifdef	CFG_ENV_IS_IN_FLASH
+	/* ENV protection ON by default */
+	flash_protect(FLAG_PROTECT_SET,
+		      CFG_ENV_ADDR,
+		      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+		      &flash_info[0]);
+#endif
+
+	if (size_b1) {
+		memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & OR_AM_MSK);
+		memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) |
+				   BR_MS_GPCM | BR_V;
+
+		DEBUGF("## BR1: 0x%08x    OR1: 0x%08x\n",
+			memctl->memc_br1, memctl->memc_or1);
+
+		/* Re-do sizing to get full correct info */
+		size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0),
+					  &flash_info[1]);
+
+		flash_info[1].size = size_b1;
+
+		flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]);
+
+# if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+		/* monitor protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_MONITOR_BASE,
+			      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+			      &flash_info[1]);
+# endif
+
+# ifdef CFG_ENV_IS_IN_FLASH
+		/* ENV protection ON by default */
+		flash_protect(FLAG_PROTECT_SET,
+			      CFG_ENV_ADDR,
+			      CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
+			      &flash_info[1]);
+#endif
+	} else {
+#ifndef CONFIG_AMX_RAM_EXT
+		memctl->memc_br1 = 0;		/* invalidate bank */
+		memctl->memc_or1 = 0;		/* invalidate bank */
+#endif
+
+		DEBUGF("## DISABLE BR1: 0x%08x    OR1: 0x%08x\n",
+			memctl->memc_br1, memctl->memc_or1);
+
+		flash_info[1].flash_id = FLASH_UNKNOWN;
+		flash_info[1].sector_count = -1;
+		flash_info[1].size = 0;
+	}
+
+	DEBUGF("## Final Flash bank sizes: %08lx + 0x%08lx\n",size_b0,size_b1);
+
+	return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+	int i;
+
+	/* set up sector start address table */
+	if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) {
+		/* set sector offsets for uniform sector type	*/
+		for (i = 0; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00040000);
+		}
+	} else if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id == FLASH_UNKNOWN) {
+		printf ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FLASH_MAN_AMD:	printf ("AMD ");		break;
+	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break;
+	case FLASH_MAN_BM:	printf ("BRIGHT MICRO ");	break;
+	default:		printf ("Unknown Vendor ");	break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_AM040:	printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n");
+				break;
+	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+				break;
+	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+				break;
+	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+				break;
+	default:		printf ("Unknown Chip Type\n");
+				break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i=0; i<info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
+		printf (" %08lX%s",
+			info->start[i],
+			info->protect[i] ? " (RO)" : "     "
+		);
+	}
+	printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+	short i;
+	ulong value;
+	ulong base = (ulong)addr;
+
+	/* Write auto select command: read Manufacturer ID */
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00900090;
+
+	value = addr[0];
+
+	DEBUGF("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value);
+
+	switch (value) {
+	case AMD_MANUFACT:
+		info->flash_id = FLASH_MAN_AMD;
+		break;
+	case FUJ_MANUFACT:
+		info->flash_id = FLASH_MAN_FUJ;
+		break;
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr[1];			/* device ID		*/
+
+	DEBUGF("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value);
+
+	switch (value) {
+	case AMD_ID_F040B:
+		info->flash_id += FLASH_AM040;
+		info->sector_count = 8;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV400T:
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV400B:
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00100000;
+		break;				/* => 1 MB		*/
+
+	case AMD_ID_LV800T:
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV800B:
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00200000;
+		break;				/* => 2 MB		*/
+
+	case AMD_ID_LV160T:
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+
+	case AMD_ID_LV160B:
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00400000;
+		break;				/* => 4 MB		*/
+#if 0	/* enable when device IDs are available */
+	case AMD_ID_LV320T:
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+
+	case AMD_ID_LV320B:
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00800000;
+		break;				/* => 8 MB		*/
+#endif
+	default:
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+	}
+
+	/* set up sector start address table */
+	if (info->flash_id & FLASH_BTYPE) {
+		/* set sector offsets for bottom boot block type	*/
+		info->start[0] = base + 0x00000000;
+		info->start[1] = base + 0x00008000;
+		info->start[2] = base + 0x0000C000;
+		info->start[3] = base + 0x00010000;
+		for (i = 4; i < info->sector_count; i++) {
+			info->start[i] = base + (i * 0x00020000) - 0x00060000;
+		}
+	} else {
+		/* set sector offsets for top boot block type		*/
+		i = info->sector_count - 1;
+		info->start[i--] = base + info->size - 0x00008000;
+		info->start[i--] = base + info->size - 0x0000C000;
+		info->start[i--] = base + info->size - 0x00010000;
+		for (; i >= 0; i--) {
+			info->start[i] = base + i * 0x00020000;
+		}
+	}
+
+	/* check for protected sectors */
+	for (i = 0; i < info->sector_count; i++) {
+		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
+		/* D0 = 1 if protected */
+		addr = (volatile unsigned long *)(info->start[i]);
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (volatile unsigned long *)info->start[0];
+
+		*addr = 0x00F000F0;	/* reset bank */
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	int flag, prot, sect, l_sect;
+	ulong start, now, last;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		if (info->flash_id == FLASH_UNKNOWN) {
+			printf ("- missing\n");
+		} else {
+			printf ("- no sectors to erase\n");
+		}
+		return 1;
+	}
+
+	if ((info->flash_id == FLASH_UNKNOWN) ||
+	    (info->flash_id > FLASH_AMD_COMP)) {
+		printf ("Can't erase unknown flash type %08lx - aborted\n",
+			info->flash_id);
+		return 1;
+	}
+
+	prot = 0;
+	for (sect=s_first; sect<=s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		printf ("\n");
+	}
+
+	l_sect = -1;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00800080;
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect<=s_last; sect++) {
+		if (info->protect[sect] == 0) {	/* not protected */
+			addr = (vu_long*)(info->start[sect]);
+			addr[0] = 0x00300030;
+			l_sect = sect;
+		}
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* wait at least 80us - let's wait 1 ms */
+	udelay (1000);
+
+	/*
+	 * We wait for the last triggered sector
+	 */
+	if (l_sect < 0)
+		goto DONE;
+
+	start = get_timer (0);
+	last  = start;
+	addr = (vu_long*)(info->start[l_sect]);
+	while ((addr[0] & 0x00800080) != 0x00800080) {
+		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+			printf ("Timeout\n");
+			return 1;
+		}
+		/* show that we're waiting */
+		if ((now - last) > 1000) {	/* every second */
+			putc ('.');
+			last = now;
+		}
+	}
+
+DONE:
+	/* reset to read mode */
+	addr = (volatile unsigned long *)info->start[0];
+	addr[0] = 0x00F000F0;	/* reset bank */
+
+	printf (" done\n");
+	return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong cp, wp, data;
+	int i, l, rc;
+
+	wp = (addr & ~3);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i=0, cp=wp; i<l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+		for (; i<4 && cnt>0; ++i) {
+			data = (data << 8) | *src++;
+			--cnt;
+			++cp;
+		}
+		for (; cnt==0 && i<4; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *)cp);
+		}
+
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 4;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 4) {
+		data = 0;
+		for (i=0; i<4; ++i) {
+			data = (data << 8) | *src++;
+		}
+		if ((rc = write_word(info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp  += 4;
+		cnt -= 4;
+	}
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+		data = (data << 8) | *src++;
+		--cnt;
+	}
+	for (; i<4; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *)cp);
+	}
+
+	return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+	vu_long *addr = (vu_long*)(info->start[0]);
+	ulong start;
+	int flag;
+
+	/* Check if Flash is (sufficiently) erased */
+	if ((*((vu_long *)dest) & data) != data) {
+		return (2);
+	}
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	addr[0x0555] = 0x00AA00AA;
+	addr[0x02AA] = 0x00550055;
+	addr[0x0555] = 0x00A000A0;
+
+	*((vu_long *)dest) = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	/* data polling for D7 */
+	start = get_timer (0);
+	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */