Initial revision
diff --git a/board/gen860t/README b/board/gen860t/README
new file mode 100644
index 0000000..761ceed
--- /dev/null
+++ b/board/gen860t/README
@@ -0,0 +1,142 @@
+
+This directory contains board specific code for a generic MPC860T based
+embedded computer, called 'GEN860T'.  The design is generic in the sense that
+common, readily available components are used and that the architecture of the
+system is i(relatively) straightforward:
+
+	One eight bit wide boot (FLASH) memory
+	32 bit main memory using SDRAM
+	DOC 2000+
+	Ethernet PHY
+	Some I2C peripheral devices: Atmel AT24C256 EEPROM, Maxim DS1337 RTC.
+	Some other miscellaneous peripherals
+
+NOTE: There are references to a XIlinx FPGA and Mil-Std 1553 databus in this
+port.  I guess the computer is not as generic as I first said 8)  However,
+these extras can be safely ignored.
+
+Given the GEN860T files, it should be pretty easy to reverse engineer the
+hardware configuration, if that's useful to you.  Hopefully, this code will
+be useful to someone as a basis for a port to a new system or as a head start
+on a custom design.  If you end up using any of this, I would appreciate
+hearing from you, especially if you discover bugs or find ways to improve the
+quality of this U-Boot port.
+
+Here are the salient features of the system:
+Clock						:	33 Mhz oscillator
+Processor core frequency	:	66 Mhz  if in 1:2:1 mode; can also run 1:1
+Bus frequency				:	33 Mhz
+
+Main memory:
+	Type	: SDRAM
+	Width	: 32 bits
+	Size	: 64 megabytes
+	Chip	: Two Micron MT48LC16M16A2TG-7E
+	CS		: MPC860T CS1*/UPMA
+	UPMA CONNECTIONS:
+		SDRAM A10	: GPLA0*
+		SDRAM CAS*	: GPLA2*
+		SDRAM WE*	: GPLA3*
+		SDRAM RAS*	: GPLA4*
+
+Boot memory:
+	Type	: FLASH
+	Width	: 8 bits
+	Size	: 16 megabytes
+	Chip	: One Intel 28F128J3A (StrataFlash)
+	CS		: MPC860T CS0*/GPCM (this is the "boot" chip select)
+
+EEPROM memory:
+	Type	: Serial I2C EEPROM
+	Width	: 8 bits
+	Size	: 32 kibibytes
+	Chip	: One Atmel AT25C256
+	CS		: 0x50 (external I2C address pins on device are tied to GND)
+
+Filesystem memory:
+	Type	: NAND FLASH (Toshiba)
+	Width	: 8 bits (i.e. interface to DOC is 8 bits)
+	Size	: 32 megabytes
+	Chip	: One DiskOnCHip Millenium Plus (DOC 2000+)
+	CS		: MPC860T CS2*/GPCM
+
+Network support:
+	MAC		: MPC86OT FEC (Fast Ethernet Controller)
+	PHY		: Intel LXT971A
+	MII Addr: 0x0 (hardwired on the board)
+	MII IRQ	:
+
+Console:
+	RS-232 on SMC1 (Maxim MAX3232 LVCMOS-RS232 level shifter)
+
+Real Time Clock:
+	Type	: Low power, I2C interface
+	Chip	: Maxim DS1337
+	CS		: Address 0x68 on I2C bus
+
+	The MPC860T's internal RTC has a defect in Mask rev D that increases
+	the current drain on the KAPWR line to 10 mA.  Since this is an
+	unreasonable amount of current draw for a RTC, and Motorola does not
+	plan to fix this in future mask revisions, a serial (I2C) RTC that
+	works has been included instead.  NOTE that the DS1337 can be
+	configured to output a 32768 Hz clock while the main power is on.
+	This clock output has been routed to the MPC860T's EXTAL pin to allow
+	the internal RTC to be used.  NOTE also that due to yet another
+	defect in the rev D mask, the RTC does not operate reliably when the
+	internal RTC divisor is set to use a 32768 Hz reference.  So just use
+	the I2C RTC.
+
+Miscellaneous:
+	Xilinx Virtex FPGA on CS3*/GPCM.
+	Virtex FPGA slave SelectMap interface on cs4*/UPMB.
+	Mil-Std 1553 databus interface on CS5*/GPCM.
+	Audio sounder (beeper) with digital volume control connected to SPKROUT.
+
+Issues:
+	The DOC 2000+ returns 0x40 as its device ID when probed using the method
+	desxribed in the DOC datasheet.  Unfortunately, the U-Boot DOC driver
+	does not recognize this device.  As of this writing, it seems that MTD
+	does not support the DOC 2000+ either.
+
+Status:
+	Everything appears to work except DOC support. As of this writing,
+	David Woodhouse has stated on the MTD mailing list that he has no
+	knowledge of the DOC Millineum Plus and therfore there is no support
+	in MTD for this device.  I wish I had known this sooner :(
+
+The GEN860T board specific files and configuration is based on the work
+of others who have contributed to U-Boot. The copright and license notices
+of these authors have been retained wherever their code has been reused.
+All new code to support the GEN860T board is:
+
+	(C) Copyright 2001-2002
+	Keith Outwater (keith_outwater@mvis.com)
+
+and the following license applies:
+
+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,
+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
+
+Thanks to Wolfgang Denk for a great software package and to everyone
+who contributed to its development.
+
+Keith Outwater
+Sr. Staff Engineer
+Microvision, Inc.
+<keith_outwater@mvis.com>
+<outwater@eskimo.com>
+
+vim: set ts=4 sw=4 tw=78:
+
diff --git a/board/gen860t/beeper.c b/board/gen860t/beeper.c
new file mode 100644
index 0000000..46fe66b
--- /dev/null
+++ b/board/gen860t/beeper.c
@@ -0,0 +1,213 @@
+/*
+ * (C) Copyright 2002
+ * Keith Outwater, keith_outwater@mvis.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 <mpc8xx.h>
+#include <asm/8xx_immap.h>
+#include <linux/ctype.h>
+
+/*
+ * Basic beeper support for the GEN860T board.  The GEN860T includes
+ * an audio sounder driven by a Phillips TDA8551 amplifier.  The
+ * TDA8551 features a digital volume control which uses a "trinary"
+ * input (high/high-Z/low) to set volume.  The 860's SPKROUT pin
+ * drives the amplifier input.
+ */
+
+
+/*
+ * Initialize beeper-related hardware. Initialize timer 1 for use with
+ * the beeper. Use 66 Mhz internal clock with prescale of 33 to get
+ * 1 uS period per count.
+ * FIXME: we should really compute the prescale based on the reported
+ * core clock frequency.
+ */
+void
+init_beeper(void)
+{
+    volatile immap_t *immap  = (immap_t *)CFG_IMMR;
+
+	immap->im_cpmtimer.cpmt_tgcr &= ~TGCR_RST1 | TGCR_STP1;
+	immap->im_cpmtimer.cpmt_tmr1 = ((33 << TMR_PS_SHIFT) & TMR_PS_MSK)
+								 | TMR_OM | TMR_FRR | TMR_ICLK_IN_GEN;
+	immap->im_cpmtimer.cpmt_tcn1 = 0;
+	immap->im_cpmtimer.cpmt_ter1 = 0xffff;
+	immap->im_cpmtimer.cpmt_tgcr |= TGCR_RST1;
+}
+
+
+/*
+ * Set beeper frequency.  Max allowed frequency is 2.5 KHz.  This limit
+ * is mostly arbitrary, but the beeper isn't really much good beyond this
+ * frequency.
+ */
+void
+set_beeper_frequency(uint frequency)
+{
+#define FREQ_LIMIT	2500
+
+    volatile immap_t *immap  = (immap_t *)CFG_IMMR;
+
+	/*
+	 * Compute timer ticks given desired frequency.  The timer is set up
+	 * to count 0.5 uS per tick and it takes two ticks per cycle (Hz).
+	 */
+	if (frequency > FREQ_LIMIT) frequency = FREQ_LIMIT;
+	frequency = 1000000/frequency;
+	immap->im_cpmtimer.cpmt_trr1 = (ushort)frequency;
+}
+
+
+/*
+ * Turn the beeper on
+ */
+void
+beeper_on(void)
+{
+    volatile immap_t *immap  = (immap_t *)CFG_IMMR;
+
+	immap->im_cpmtimer.cpmt_tgcr &= ~TGCR_STP1;
+}
+
+
+/*
+ * Turn the beeper off
+ */
+void
+beeper_off(void)
+{
+    volatile immap_t *immap  = (immap_t *)CFG_IMMR;
+
+	immap->im_cpmtimer.cpmt_tgcr |= TGCR_STP1;
+}
+
+
+/*
+ * Increase or decrease the beeper volume.  Volume can be set
+ * from off to full in 64 steps.  To increase volume, the output
+ * pin is actively driven high, then returned to tristate.
+ * To decrease volume, output a low on the port pin (no need to
+ * change pin mode to tristate) then output a high to go back to
+ * tristate.
+ */
+void
+set_beeper_volume(int steps)
+{
+    volatile immap_t *immap  = (immap_t *)CFG_IMMR;
+	int i;
+
+	if (steps >= 0) {
+		for (i = 0; i < (steps >= 64 ? 64 : steps); i++) {
+			immap->im_cpm.cp_pbodr &= ~(0x80000000 >> 19);
+			udelay(1);
+			immap->im_cpm.cp_pbodr |= (0x80000000 >> 19);
+			udelay(1);
+		}
+	}
+	else {
+		for (i = 0; i > (steps <= -64 ? -64 : steps); i--) {
+			immap->im_cpm.cp_pbdat &= ~(0x80000000 >> 19);
+			udelay(1);
+			immap->im_cpm.cp_pbdat |= (0x80000000 >> 19);
+			udelay(1);
+		}
+	}
+}
+
+
+/*
+ * Check the environment to see if the beeper needs beeping.
+ * Controlled by a sequence of the form:
+ * freq/delta volume/on time/off time;... where:
+ * freq 		= frequency in Hz (0 - 2500)
+ * delta volume = volume steps up or down (-64 <= vol <= 64)
+ * on time		= time in mS
+ * off time		= time in mS
+ *
+ * Return 1 on success, 0 on failure
+ */
+int
+do_beeper(char *sequence)
+{
+#define DELIMITER	';'
+
+int args[4];
+int i;
+int val;
+char *p = sequence;
+char *tp;
+
+	/*
+	 * Parse the control sequence.  This is a really simple parser
+	 * without any real error checking.  You can probably blow it
+	 * up really easily.
+	 */
+	if (*p == '\0' || !isdigit(*p)) {
+		printf("%s:%d: null or invalid string (%s)\n",
+				__FILE__, __LINE__, p);
+		return 0;
+	}
+
+	i = 0;
+	while (*p != '\0') {
+		while (*p != DELIMITER) {
+			if (i > 3) i = 0;
+			val = (int) simple_strtol(p, &tp, 0);
+			if (tp == p) {
+				printf("%s:%d: no digits or bad format\n",
+								__FILE__,__LINE__);
+				return 0;
+			}
+			else {
+				args[i] = val;
+			}
+
+			i++;
+			if (*tp == DELIMITER)
+				p = tp;
+			else
+				p = ++tp;
+		}
+		p++;
+
+		/*
+		 * Well, we got something that has a chance of being correct
+		 */
+#if 0
+		for (i = 0; i < 4; i++) {
+			printf("%s:%d:arg %d = %d\n", __FILE__, __LINE__, i, args[i]);
+		}
+		printf("\n");
+#endif
+
+		set_beeper_frequency(args[0]);
+		set_beeper_volume(args[1]);
+		beeper_on();
+		udelay(1000 * args[2]);
+		beeper_off();
+		udelay(1000 * args[3]);
+	}
+	return 1;
+}
+
+/* vim: set ts=4 sw=4 tw=78: */
diff --git a/board/gen860t/flash.c b/board/gen860t/flash.c
new file mode 100644
index 0000000..902b1b0
--- /dev/null
+++ b/board/gen860t/flash.c
@@ -0,0 +1,644 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Keith Outwater, keith_outwater@mvsi.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 <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
+
+/*
+ * Use buffered writes to flash by default - they are about 32x faster than
+ * single byte writes.
+ */
+#ifndef  CFG_GEN860T_FLASH_USE_WRITE_BUFFER
+#define CFG_GEN860T_FLASH_USE_WRITE_BUFFER
+#endif
+
+/*
+ * Max time to wait (in mS) for flash device to allocate a write buffer.
+ */
+#ifndef CFG_FLASH_ALLOC_BUFFER_TOUT
+#define CFG_FLASH_ALLOC_BUFFER_TOUT		100
+#endif
+
+/*
+ * These functions support a single Intel StrataFlash device (28F128J3A)
+ * in byte mode only!.  The flash routines are very basic and simple
+ * since there isn't really any remapping necessary.
+ */
+
+/*
+ * Intel SCS (Scalable Command Set) command definitions
+ * (taken from 28F128J3A datasheet)
+ */
+#define SCS_READ_CMD				0xff
+#define SCS_READ_ID_CMD				0x90
+#define SCS_QUERY_CMD				0x98
+#define SCS_READ_STATUS_CMD			0x70
+#define SCS_CLEAR_STATUS_CMD		0x50
+#define SCS_WRITE_BUF_CMD			0xe8
+#define SCS_PROGRAM_CMD				0x40
+#define SCS_BLOCK_ERASE_CMD			0x20
+#define SCS_BLOCK_ERASE_RESUME_CMD	0xd0
+#define SCS_PROGRAM_RESUME_CMD		0xd0
+#define SCS_BLOCK_ERASE_SUSPEND_CMD	0xb0
+#define SCS_SET_BLOCK_LOCK_CMD		0x60
+#define SCS_CLR_BLOCK_LOCK_CMD		0x60
+
+/*
+ * SCS status/extended status register bit definitions
+ */
+#define  SCS_SR7					0x80
+#define  SCS_XSR7					0x80
+
+/*---------------------------------------------------------------------*/
+#if 0
+#define DEBUG_FLASH
+#endif
+
+#ifdef DEBUG_FLASH
+#define PRINTF(fmt,args...) printf(fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS];
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_char *addr, flash_info_t *info);
+static int write_data8 (flash_info_t *info, ulong dest, uchar data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ * Initialize the flash memory.
+ */
+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;
+
+	for (i= 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/*
+	 * The gen860t board only has one FLASH memory device, so the
+	 * FLASH Bank configuration is done statically.
+	 */
+	PRINTF("\n## Get flash bank 1 size @ 0x%08x\n", FLASH_BASE0_PRELIM);
+	size_b0 = flash_get_size((vu_char *)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);
+	}
+
+	PRINTF("## Before remap:\n"
+		   "  BR0: 0x%08x    OR0: 0x%08x\n  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 |= (-size_b0 & 0xFFFF8000);
+	memctl->memc_br0 |= (CFG_FLASH_BASE & BR_BA_MSK);
+
+	PRINTF("## After remap:\n"
+		   "  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_char *)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 is 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
+	/*
+	 * Environment protection ON by default
+	 */
+	flash_protect(FLAG_PROTECT_SET,
+		      	  CFG_ENV_ADDR,
+		      	  CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
+		      	  &flash_info[0]);
+#endif
+
+	PRINTF("## Final Flash bank size: 0x%08lx\n",size_b0);
+	return (size_b0);
+}
+
+
+/*-----------------------------------------------------------------------
+ * Fill in the FLASH offset table
+ */
+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 += 1024 * 128;
+	    	}
+	    	return;
+
+		default:
+	   		printf ("Don't know sector offsets for FLASH"
+			        " type 0x%lx\n", info->flash_id);
+	    return;
+	}
+}
+
+
+/*-----------------------------------------------------------------------
+ * Display FLASH device info
+ */
+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_28F128J3A:
+			printf ("28F128J3A (128Mbit = 128K x 128)\n");
+			break;
+	default:
+			printf ("Unknown Chip Type\n");
+			break;
+	}
+
+	if (info->size >= (1024 * 1024)) {
+		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;
+}
+
+
+/*-----------------------------------------------------------------------
+ * Get size and other information for a FLASH device.
+ * NOTE: The following code cannot be run from FLASH!
+ */
+static
+ulong flash_get_size (vu_char *addr, flash_info_t *info)
+{
+#define NO_FLASH	0
+
+	vu_char value[2];
+
+	/*
+	 * Try to read the manufacturer ID
+	 */
+	addr[0] = SCS_READ_CMD;
+	addr[0] = SCS_READ_ID_CMD;
+	value[0] = addr[0];
+	value[1] = addr[2];
+	addr[0] = SCS_READ_CMD;
+
+	PRINTF("Manuf. ID @ 0x%08lx: 0x%02x\n", (ulong)addr, value[0]);
+	switch (value[0]) {
+		case (INTEL_MANUFACT & 0xff):
+			info->flash_id = FLASH_MAN_INTEL;
+			break;
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			info->sector_count = 0;
+			info->size = 0;
+			return (NO_FLASH);
+	}
+
+	/*
+	 * Read the device ID
+	 */
+	PRINTF("Device ID @ 0x%08lx: 0x%02x\n", (ulong)(&addr[2]), value[1]);
+	switch (value[1]) {
+		case (INTEL_ID_28F128J3A & 0xff):
+			info->flash_id += FLASH_28F128J3A;
+			info->sector_count = 128;
+			info->size = 16 * 1024 * 1024;
+			break;
+
+		default:
+			info->flash_id = FLASH_UNKNOWN;
+			return (NO_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;
+	}
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ * Erase the specified sectors in the specified FLASH device
+ */
+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 = (uchar *)(info->start[sect]);
+			vu_char status;
+
+			/*
+			 * Disable interrupts which might cause a timeout
+			 */
+			flag = disable_interrupts();
+
+			*addr = SCS_CLEAR_STATUS_CMD;
+			*addr = SCS_BLOCK_ERASE_CMD;
+			*addr = SCS_BLOCK_ERASE_RESUME_CMD;
+
+			/*
+			 * Re-enable interrupts if necessary
+			 */
+			if (flag)
+				enable_interrupts();
+
+			/*
+			 * Wait at least 80us - let's wait 1 ms
+			 */
+			udelay (1000);
+
+			while (((status = *addr) & SCS_SR7) != SCS_SR7) {
+				if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout\n");
+					*addr = SCS_BLOCK_ERASE_SUSPEND_CMD;
+					*addr = SCS_READ_CMD;
+					return 1;
+				}
+
+				/*
+				 * Show that we're waiting
+				 */
+				if ((now - last) > 1000) {	/* 1 second */
+					putc ('.');
+					last = now;
+				}
+			}
+			*addr = SCS_READ_CMD;
+		}
+	}
+	printf (" done\n");
+	return 0;
+}
+
+
+#ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
+/*
+ * Allocate a flash buffer, fill it with data and write it to the flash.
+ * 0 - OK
+ * 1 - Timeout on buffer request
+ *
+ * NOTE: After the last call to this function, WSM status needs to be checked!
+ */
+static int
+write_flash_buffer8(flash_info_t *info_p, vu_char *src_p, vu_char *dest_p,
+				    uint count)
+{
+	vu_char *block_addr_p = NULL;
+	vu_char *start_addr_p = NULL;
+	ulong blocksize = info_p->size / (ulong)info_p->sector_count;
+
+	int i;
+	uint time = get_timer(0);
+
+	PRINTF("%s:%d: src: 0x%p dest: 0x%p  count: %d\n",
+		   __FUNCTION__, __LINE__, src_p, dest_p, count);
+
+	/*
+	 * What block are we in? We already know that the source address is
+	 * in the flash address range, but we also can't cross a block boundary.
+	 * We assume that the block does not cross a boundary (we'll check before
+	 * calling this function).
+	 */
+ 	for (i = 0; i < info_p->sector_count; ++i) {
+		if ( ((ulong)dest_p >= info_p->start[i]) &&
+		    ((ulong)dest_p < (info_p->start[i] + blocksize)) ) {
+			PRINTF("%s:%d: Dest addr 0x%p is in block %d @ 0x%.8lx\n",
+				   __FUNCTION__, __LINE__, dest_p, i, info_p->start[i]);
+			block_addr_p = (vu_char *)info_p->start[i];
+			break;
+		}
+	}
+
+	/*
+	 * Request a buffer
+	 */
+	*block_addr_p = SCS_WRITE_BUF_CMD;
+	while ((*block_addr_p & SCS_XSR7) != SCS_XSR7) {
+		if (get_timer(time) >  CFG_FLASH_ALLOC_BUFFER_TOUT) {
+			PRINTF("%s:%d: Buffer allocation timeout @ 0x%p (waited %d mS)\n",
+				   __FUNCTION__, __LINE__, block_addr_p,
+				   CFG_FLASH_ALLOC_BUFFER_TOUT);
+			return 1;
+		}
+		*block_addr_p = SCS_WRITE_BUF_CMD;
+	}
+
+	/*
+	 * Fill the buffer with data
+	 */
+	start_addr_p = dest_p;
+	*block_addr_p = count - 1; /* flash device wants count - 1 */
+	PRINTF("%s:%d: Fill buffer at block addr 0x%p\n",
+		   __FUNCTION__, __LINE__, block_addr_p);
+	for (i = 0; i < count; i++) {
+		*start_addr_p++ = *src_p++;
+	}
+
+	/*
+	 * Flush buffer to flash
+	 */
+	*block_addr_p = SCS_PROGRAM_RESUME_CMD;
+#if 1
+	time = get_timer(0);
+	while ((*block_addr_p & SCS_SR7) != SCS_SR7) {
+		if (get_timer(time) >  CFG_FLASH_WRITE_TOUT) {
+			PRINTF("%s:%d: Write timeout @ 0x%p (waited %d mS)\n",
+				   __FUNCTION__, __LINE__, block_addr_p, CFG_FLASH_WRITE_TOUT);
+			return 1;
+		}
+	}
+
+#endif
+	return 0;
+}
+#endif
+
+
+/*-----------------------------------------------------------------------
+ * 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_p, uchar *src_p, ulong addr, ulong count)
+{
+	int rc = 0;
+#ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
+#define FLASH_WRITE_BUF_SIZE	0x00000020	/* 32 bytes */
+	int i;
+	uint bufs;
+	ulong buf_count;
+	vu_char *sp;
+	vu_char *dp;
+#else
+	ulong wp;
+#endif
+
+	PRINTF("\n%s:%d: src: 0x%.8lx dest: 0x%.8lx size: %d (0x%.8lx)\n",
+		   __FUNCTION__, __LINE__, (ulong)src_p, addr, (uint)count, count);
+
+	if (info_p->flash_id == FLASH_UNKNOWN) {
+		return 4;
+	}
+
+#ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
+	sp = src_p;
+	dp = (uchar *)addr;
+
+	/*
+	 * For maximum performance, we want to align the start address to
+	 * the beginning of a write buffer boundary (i.e. A4-A0 of the
+	 * start address = 0). See how many bytes are required to get to a
+	 * write-buffer-aligned address.  If that number is non-zero, do
+	 * non buffered writes of the non-aligned data.  By doing non-buffered
+	 * writes, we avoid the problem of crossing a block (sector) boundary
+	 * with buffered writes.
+	 */
+	buf_count = FLASH_WRITE_BUF_SIZE - (addr & (FLASH_WRITE_BUF_SIZE - 1));
+	if (buf_count == FLASH_WRITE_BUF_SIZE) { /* already on a boundary */
+		buf_count = 0;
+	}
+	if (buf_count > count) { /* not a full buffers worth of data to write */
+		buf_count = count;
+	}
+	count -= buf_count;
+
+	PRINTF("%s:%d: Write buffer alignment count = %ld\n",
+		   __FUNCTION__, __LINE__, buf_count);
+	while (buf_count-- >= 1) {
+		if ((rc = write_data8(info_p, (ulong)dp++, *sp++)) != 0)  {
+			return (rc);
+		}
+	}
+
+	PRINTF("%s:%d: count = %ld\n", __FUNCTION__, __LINE__, count);
+	if (count == 0) { /* all done */
+		PRINTF("%s:%d: Less than 1 buffer (%d) worth of bytes\n",
+			   __FUNCTION__, __LINE__, FLASH_WRITE_BUF_SIZE);
+		return (rc);
+	}
+
+	/*
+	 * Now that we are write buffer aligned, write full or partial buffers.
+	 * The fact that we are write buffer aligned automatically avoids
+	 * crossing a block address during a write buffer operation.
+	 */
+	bufs = count / FLASH_WRITE_BUF_SIZE;
+	PRINTF("%s:%d: %d (0x%x) buffers to write\n", __FUNCTION__, __LINE__,
+		   bufs, bufs);
+	while (bufs >= 1) {
+		rc = write_flash_buffer8(info_p, sp, dp, FLASH_WRITE_BUF_SIZE);
+		if (rc != 0) {
+			PRINTF("%s:%d: ** Error writing buf %d\n",
+				   __FUNCTION__, __LINE__, bufs);
+			return (rc);
+		}
+		bufs--;
+		sp += FLASH_WRITE_BUF_SIZE;
+		dp += FLASH_WRITE_BUF_SIZE;
+	}
+
+	/*
+	 * Do the leftovers
+	 */
+	i = count % FLASH_WRITE_BUF_SIZE;
+	PRINTF("%s:%d: %d (0x%x) leftover bytes\n", __FUNCTION__, __LINE__, i, i);
+	if (i > 0) {
+		rc = write_flash_buffer8(info_p, sp, dp, i);
+	}
+
+	sp = (vu_char*)info_p->start[0];
+	*sp = SCS_READ_CMD;
+	return (rc);
+
+#else
+	wp = addr;
+	while (count-- >= 1) {
+		if((rc = write_data8(info_p, wp++, *src_p++)) != 0)
+			return (rc);
+	}
+	return 0;
+#endif
+}
+
+
+/*-----------------------------------------------------------------------
+ * Write a byte to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int
+write_data8 (flash_info_t *info, ulong dest, uchar data)
+{
+	vu_char *addr = (vu_char *)dest;
+	vu_char status;
+	ulong start;
+	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();
+
+	*addr = SCS_PROGRAM_CMD;
+	*addr = data;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	start = get_timer (0);
+
+	while (((status = *addr) & SCS_SR7) != SCS_SR7) {
+		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+			*addr = SCS_READ_CMD;
+			return (1);
+		}
+	}
+	*addr = SCS_READ_CMD;
+	return (0);
+}
+
+/* vim: set ts=4 sw=4 tw=78: */
diff --git a/board/gen860t/fpga.c b/board/gen860t/fpga.c
new file mode 100644
index 0000000..2c4fbf1
--- /dev/null
+++ b/board/gen860t/fpga.c
@@ -0,0 +1,401 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.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
+ *
+ */
+
+/*
+ * Virtex2 FPGA configuration support for the GEN860T computer
+ */
+
+#include <common.h>
+#include <virtex2.h>
+#include <command.h>
+#include "fpga.h"
+
+#if (CONFIG_FPGA)
+
+#if 0
+#define GEN860T_FPGA_DEBUG
+#endif
+
+#ifdef GEN860T_FPGA_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define	PRINTF(fmt,args...)
+#endif
+
+/*
+ * Port bit numbers for the Selectmap controls
+ */
+#define FPGA_INIT_BIT_NUM		22	/* PB22 */
+#define FPGA_RESET_BIT_NUM		11	/* PC11 */
+#define FPGA_DONE_BIT_NUM		16	/* PB16 */
+#define FPGA_PROGRAM_BIT_NUM	7	/* PA7  */
+
+/* Note that these are pointers to code that is in Flash.  They will be
+ * relocated at runtime.
+ */
+Xilinx_Virtex2_Slave_SelectMap_fns fpga_fns = {
+	fpga_pre_config_fn,
+	fpga_pgm_fn,
+	fpga_init_fn,
+	fpga_err_fn,
+	fpga_done_fn,
+	fpga_clk_fn,
+	fpga_cs_fn,
+	fpga_wr_fn,
+	fpga_read_data_fn,
+	fpga_write_data_fn,
+	fpga_busy_fn,
+	fpga_abort_fn,
+	fpga_post_config_fn
+};
+
+Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
+	{ Xilinx_Virtex2,
+	  slave_selectmap,
+	  XILINX_XC2V3000_SIZE,
+	  (void *)&fpga_fns,
+	  0
+	}
+};
+
+/*
+ * Display FPGA revision information
+ */
+void
+print_fpga_revision(void)
+{
+	vu_long *rev_p = (vu_long *)0x60000008;
+
+	printf("FPGA Revision 0x%.8lx"
+		   " (Date %.2lx/%.2lx/%.2lx, Status \"%.1lx\", Version %.3lu)\n",
+		   *rev_p,
+		   ((*rev_p >> 28) & 0xf),
+		   ((*rev_p >> 20) & 0xff),
+		   ((*rev_p >> 12) & 0xff),
+		   ((*rev_p >> 8) & 0xf),
+		   (*rev_p & 0xff));
+}
+
+
+/*
+ * Perform a simple test of the FPGA to processor interface using the FPGA's
+ * inverting bus test register.  The great thing about doing a read/write
+ * test on a register that inverts it's contents is that you avoid any
+ * problems with bus charging.
+ * Return 0 on failure, 1 on success.
+ */
+int
+test_fpga_ibtr(void)
+{
+	vu_long *ibtr_p = (vu_long *)0x60000010;
+	vu_long readback;
+	vu_long compare;
+	int i;
+	int j;
+	int k;
+	int pass = 1;
+
+	static const ulong bitpattern[] = {
+		0xdeadbeef,	/* magic ID pattern for debug	*/
+		0x00000001,	/* single bit					*/
+		0x00000003,	/* two adjacent bits			*/
+		0x00000007,	/* three adjacent bits			*/
+		0x0000000F,	/* four adjacent bits			*/
+		0x00000005,	/* two non-adjacent bits		*/
+		0x00000015,	/* three non-adjacent bits		*/
+		0x00000055,	/* four non-adjacent bits		*/
+		0xaaaaaaaa,	/* alternating 1/0				*/
+	};
+
+	for (i = 0; i < 1024; i++) {
+		for (j = 0; j < 31; j++) {
+			for (k = 0; k < sizeof(bitpattern)/sizeof(bitpattern[0]); k++) {
+				*ibtr_p = compare = (bitpattern[k] << j);
+				readback = *ibtr_p;
+				if (readback != ~compare) {
+					printf("%s:%d: FPGA test fail: expected 0x%.8lx"
+						   " actual 0x%.8lx\n",
+						   __FUNCTION__, __LINE__, ~compare, readback);
+					pass = 0;
+					break;
+				}
+			}
+			if (!pass) break;
+		}
+		if (!pass) break;
+	}
+	if (pass) {
+		printf("FPGA inverting bus test passed\n");
+		print_fpga_revision();
+	}
+	else {
+		printf("** FPGA inverting bus test failed\n");
+	}
+	return pass;
+}
+
+
+/*
+ * Set the active-low FPGA reset signal.
+ */
+void
+fpga_reset(int assert)
+{
+    volatile immap_t *immap  = (immap_t *)CFG_IMMR;
+
+	PRINTF("%s:%d: RESET ", __FUNCTION__, __LINE__);
+	if (assert) {
+		immap->im_ioport.iop_pcdat &= ~(0x8000 >> FPGA_RESET_BIT_NUM);
+		PRINTF("asserted\n");
+	}
+	else {
+		immap->im_ioport.iop_pcdat |= (0x8000 >> FPGA_RESET_BIT_NUM);
+		PRINTF("deasserted\n");
+	}
+}
+
+
+/*
+ * Initialize the SelectMap interface.  We assume that the mode and the
+ * initial state of all of the port pins have already been set!
+ */
+void
+fpga_selectmap_init(void)
+{
+	PRINTF("%s:%d: Initialize SelectMap interface\n", __FUNCTION__, __LINE__);
+	fpga_pgm_fn(FALSE, FALSE, 0);   /* make sure program pin is inactive */
+}
+
+
+/*
+ * Initialize the fpga.  Return 1 on success, 0 on failure.
+ */
+int
+gen860t_init_fpga(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	int i;
+
+	PRINTF("%s:%d: Initialize FPGA interface (relocation offset = 0x%.8lx)\n",
+			__FUNCTION__, __LINE__, gd->reloc_off);
+	fpga_init(gd->reloc_off);
+	fpga_selectmap_init();
+
+	for(i=0; i < CONFIG_FPGA_COUNT; i++) {
+		PRINTF("%s:%d: Adding fpga %d\n", __FUNCTION__, __LINE__, i);
+		fpga_add(fpga_xilinx, &fpga[i]);
+	}
+ 	return 1;
+}
+
+
+/*
+ * Set the FPGA's active-low SelectMap program line to the specified level
+ */
+int
+fpga_pgm_fn(int assert, int flush, int cookie)
+{
+    volatile immap_t *immap  = (immap_t *)CFG_IMMR;
+
+	PRINTF("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
+
+	if (assert) {
+		immap->im_ioport.iop_padat &= ~(0x8000 >> FPGA_PROGRAM_BIT_NUM);
+		PRINTF("asserted\n");
+	}
+	else {
+		immap->im_ioport.iop_padat |= (0x8000 >> FPGA_PROGRAM_BIT_NUM);
+		PRINTF("deasserted\n");
+	}
+	return assert;
+}
+
+
+/*
+ * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
+ * asserted (low).
+ */
+int
+fpga_init_fn(int cookie)
+{
+    volatile immap_t *immap  = (immap_t *)CFG_IMMR;
+
+	PRINTF("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
+	if(immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_INIT_BIT_NUM)) {
+		PRINTF("high\n");
+		return 0;
+	}
+	else {
+		PRINTF("low\n");
+		return 1;
+	}
+}
+
+
+/*
+ * Test the state of the active-high FPGA DONE pin
+ */
+int
+fpga_done_fn(int cookie)
+{
+    volatile immap_t *immap  = (immap_t *)CFG_IMMR;
+
+	PRINTF("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
+	if (immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_DONE_BIT_NUM)) {
+		PRINTF("high\n");
+		return FPGA_SUCCESS;
+	}
+	else {
+		PRINTF("low\n");
+		return FPGA_FAIL;
+	}
+}
+
+
+/*
+ * Read FPGA SelectMap data.
+ */
+int
+fpga_read_data_fn(unsigned char *data, int cookie)
+{
+	vu_char *p = (vu_char *)SELECTMAP_BASE;
+
+	*data = *p;
+#if 0
+	PRINTF("%s: Read 0x%x into 0x%p\n", __FUNCTION__, (int)data, data);
+#endif
+	return (int)data;
+}
+
+
+/*
+ * Write data to the FPGA SelectMap port
+ */
+int
+fpga_write_data_fn(unsigned char data, int flush, int cookie)
+{
+	vu_char *p = (vu_char *)SELECTMAP_BASE;
+
+#if 0
+	PRINTF("%s: Write Data 0x%x\n", __FUNCTION__, (int)data);
+#endif
+	*p = data;
+	return (int)data;
+}
+
+
+/*
+ * Abort and FPGA operation
+ */
+int
+fpga_abort_fn(int cookie)
+{
+	PRINTF("%s:%d: FPGA program sequence aborted\n",
+		   __FUNCTION__, __LINE__);
+	return FPGA_FAIL;
+}
+
+
+/*
+ * FPGA pre-configuration function. Just make sure that
+ * FPGA reset is asserted to keep the FPGA from starting up after
+ * configuration.
+ */
+int
+fpga_pre_config_fn(int cookie)
+{
+	PRINTF("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
+	fpga_reset(TRUE);
+	return 0;
+}
+
+
+/*
+ * FPGA post configuration function. Blip the FPGA reset line and then see if
+ * the FPGA appears to be running.
+ */
+int
+fpga_post_config_fn(int cookie)
+{
+	int rc;
+
+	PRINTF("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__);
+	fpga_reset(TRUE);
+	udelay(1000);
+	fpga_reset(FALSE);
+	udelay (1000);
+
+	/*
+	 * Use the FPGA,s inverting bus test register to do a simple test of the
+	 * processor interface.
+	 */
+	rc = test_fpga_ibtr();
+	return rc;
+}
+
+
+/*
+ * Clock, chip select and write signal assert functions and error check
+ * and busy functions.  These are only stubs because the GEN860T selectmap
+ * interface handles sequencing of control signals automatically (it uses
+ * a memory-mapped interface to the FPGA SelectMap port).  The design of
+ * the interface guarantees that the SelectMap port cannot be overrun so
+ * no busy check is needed.  A configuration error is signalled by INIT
+ * going low during configuration, so there is no need for a separate error
+ * function.
+ */
+int
+fpga_clk_fn(int assert_clk, int flush, int cookie)
+{
+	return assert_clk;
+}
+
+int
+fpga_cs_fn(int assert_cs, int flush, int cookie)
+{
+	return assert_cs;
+}
+
+int
+fpga_wr_fn(int assert_write, int flush, int cookie)
+{
+	return assert_write;
+}
+
+int
+fpga_err_fn(int cookie)
+{
+	return 0;
+}
+
+int
+fpga_busy_fn(int cookie)
+{
+	return 0;
+}
+#endif
+
+/* vim: set ts=4 tw=78 sw=4: */
diff --git a/board/gen860t/gen860t.c b/board/gen860t/gen860t.c
new file mode 100644
index 0000000..16a3262
--- /dev/null
+++ b/board/gen860t/gen860t.c
@@ -0,0 +1,299 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Keith Outwater, keith_outwater@mvis.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 <virtex2.h>
+#include <common.h>
+#include <mpc8xx.h>
+#include <asm/8xx_immap.h>
+#include "beeper.h"
+#include "fpga.h"
+#include "ioport.h"
+
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
+
+#if defined(CFG_CMD_MII) && defined(CONFIG_MII)
+#include <net.h>
+#endif
+
+#if 0
+#define GEN860T_DEBUG
+#endif
+
+#ifdef GEN860T_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define	PRINTF(fmt,args...)
+#endif
+
+/*
+ * The following UPM init tables were generated automatically by
+ * Motorola's MCUINIT program. See the README file for UPM to
+ * SDRAM pin assignments if you want to type this data into
+ * MCUINIT in order to reverse engineer the waveforms.
+ */
+
+/*
+ * UPM initialization tables for MICRON MT48LC16M16A2TG SDRAM devices
+ * (UPMA) and Virtex FPGA SelectMap interface (UPMB).
+ * NOTE that unused areas of the table are used to hold NOP, precharge
+ * and mode register set sequences.
+ *
+ */
+#define	UPMA_NOP_ADDR			0x5
+#define	UPMA_PRECHARGE_ADDR		0x6
+#define UPMA_MRS_ADDR			0x12
+
+#define UPM_SINGLE_READ_ADDR	0x00
+#define UPM_BURST_READ_ADDR		0x08
+#define UPM_SINGLE_WRITE_ADDR	0x18
+#define UPM_BURST_WRITE_ADDR	0x20
+#define	UPM_REFRESH_ADDR		0x30
+
+const uint sdram_upm_table[] = {
+	/* single read   (offset 0x00 in upm ram) */
+	0x0e0fdc04, 0x01adfc04, 0x0fbffc00, 0x1fff5c05,
+	0xffffffff, 0x0fffffcd, 0x0fff0fce, 0xefcfffff,
+	/* burst read    (offset 0x08 in upm ram) */
+	0x0f0fdc04, 0x00fdfc04, 0xf0fffc00, 0xf0fffc00,
+	0xf1fffc00, 0xfffffc00, 0xfffffc05, 0xffffffff,
+	0xffffffff, 0xffffffff, 0x0ffffff4, 0x1f3d5ff4,
+	0xfffffff4, 0xfffffff5, 0xffffffff, 0xffffffff,
+	/* single write  (offset 0x18 in upm ram) */
+	0x0f0fdc04, 0x00ad3c00, 0x1fff5c05, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	/* burst write   (offset 0x20 in upm ram) */
+	0x0f0fdc00, 0x10fd7c00, 0xf0fffc00, 0xf0fffc00,
+	0xf1fffc04, 0xfffffc05, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xfffff7ff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	/* refresh       (offset 0x30 in upm ram) */
+	0x1ffddc84, 0xfffffc04, 0xfffffc04, 0xfffffc84,
+	0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	/* exception     (offset 0x3C in upm ram) */
+   };
+
+const uint selectmap_upm_table[] = {
+	/* single read   (offset 0x00 in upm ram) */
+	0x88fffc06, 0x00fff404, 0x00fffc04, 0x33fffc00,
+	0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff,
+	/* burst read    (offset 0x08 in upm ram) */
+	0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	/* single write  (offset 0x18 in upm ram) */
+	0x88fffc04, 0x00fff400, 0x77fffc05, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	/* burst write   (offset 0x20 in upm ram) */
+	0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	/* refresh       (offset 0x30 in upm ram) */
+	0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	/* exception     (offset 0x3C in upm ram) */
+	0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff
+};
+
+/*
+ * Check board identity.  Always successful (gives information only)
+ */
+int
+checkboard(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+    unsigned char *s;
+    unsigned char buf[64];
+    int i;
+
+    i = getenv_r("board_id", buf, sizeof(buf));
+    s = (i>0) ? buf : NULL;
+
+	if (s) {
+		printf("%s ", s);
+	} else {
+		printf("<unknown> ");
+	}
+
+    i = getenv_r("serial#", buf, sizeof(buf));
+    s = (i>0) ? buf : NULL;
+
+	if (s) {
+		printf("S/N %s\n", s);
+	} else {
+		printf("S/N <unknown>\n");
+	}
+
+    printf("CPU at %s MHz, ",strmhz(buf, gd->cpu_clk));
+	printf("local bus at %s MHz\n", strmhz(buf, gd->bus_clk));
+    return (0);
+}
+
+/*
+ * Initialize SDRAM
+ */
+long int
+initdram(int board_type)
+{
+    volatile immap_t     *immr  = (immap_t *)CFG_IMMR;
+    volatile memctl8xx_t *memctl = &immr->im_memctl;
+
+    upmconfig(UPMA,
+			  (uint *)sdram_upm_table,
+			  sizeof(sdram_upm_table) / sizeof(uint)
+			 );
+
+    /*
+     * Setup MAMR register
+     */
+    memctl->memc_mptpr = CFG_MPTPR_1BK_8K;
+    memctl->memc_mamr = CFG_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */
+
+    /*
+     * Map CS1* to SDRAM bank
+     */
+    memctl->memc_or1 = CFG_OR1;
+    memctl->memc_br1 = CFG_BR1;
+
+	/*
+	 * Perform SDRAM initialization sequence:
+	 * 1. Apply at least one NOP command
+	 * 2. 100 uS delay (JEDEC standard says 200 uS)
+	 * 3. Issue 4 precharge commands
+	 * 4. Perform two refresh cycles
+	 * 5. Program mode register
+	 *
+	 * Program SDRAM for standard operation, sequential burst, burst length
+	 * of 4, CAS latency of 2.
+	 */
+    memctl->memc_mar = 0x00000000;
+	memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 |
+					   MCR_MLCF(0) | UPMA_NOP_ADDR;
+	udelay(200);
+    memctl->memc_mar = 0x00000000;
+	memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 |
+					   MCR_MLCF(4) | UPMA_PRECHARGE_ADDR;
+
+    memctl->memc_mar = 0x00000000;
+	memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 |
+					   MCR_MLCF(2) | UPM_REFRESH_ADDR;
+
+    memctl->memc_mar = 0x00000088;
+	memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 |
+					   MCR_MLCF(1) | UPMA_MRS_ADDR;
+
+    memctl->memc_mar = 0x00000000;
+	memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 |
+					   MCR_MLCF(0) | UPMA_NOP_ADDR;
+	/*
+	 * Enable refresh
+	 */
+    memctl->memc_mamr |= MAMR_PTAE;
+
+    return (SDRAM_SIZE);
+}
+
+/*
+ * Disk On Chip (DOC) Millenium initialization.
+ * The DOC lives in the CS2* space
+ */
+#if (CONFIG_COMMANDS & CFG_CMD_DOC)
+extern void
+doc_probe(ulong physadr);
+
+void
+doc_init(void)
+{
+	printf("Probing at 0x%.8x: ", DOC_BASE);
+	doc_probe(DOC_BASE);
+}
+#endif
+
+/*
+ * Miscellaneous intialization
+ */
+int
+misc_init_r (void)
+{
+    volatile immap_t     *immr  = (immap_t *)CFG_IMMR;
+    volatile memctl8xx_t *memctl = &immr->im_memctl;
+
+	/*
+	 * Set up UPMB to handle the Virtex FPGA SelectMap interface
+	 */
+	upmconfig(UPMB, (uint *)selectmap_upm_table,
+			  sizeof(selectmap_upm_table) / sizeof(uint));
+
+    memctl->memc_mbmr = 0x0;
+
+	config_mpc8xx_ioports(immr);
+
+#if (CONFIG_COMMANDS & CFG_CMD_MII)
+	mii_init();
+#endif
+
+#if (CONFIG_FPGA)
+	gen860t_init_fpga();
+#endif
+	return 0;
+}
+
+/*
+ * Final init hook before entering command loop.
+ */
+int
+last_stage_init(void)
+{
+	unsigned char buf[256];
+	int i;
+
+	/*
+	 * Set LEDs here since status LED init code has already run
+	 */
+	status_led_set(STATUS_LED_BIT1, STATUS_LED_ON);
+	status_led_set(STATUS_LED_BIT3, STATUS_LED_ON);
+
+	/*
+	 * Turn the beeper volume all the way down in case this is a warm
+	 * boot.
+	 */
+	set_beeper_volume(-64);
+	init_beeper();
+
+	/*
+	 * Read the environment to see what to do with the beeper
+	 */
+    i = getenv_r("beeper", buf, sizeof(buf));
+	if (i > 0) {
+		do_beeper(buf);
+	}
+	return 0;
+}
+/* vim: set ts=4 sw=4 tw=78 : */
diff --git a/board/gen860t/ioport.c b/board/gen860t/ioport.c
new file mode 100644
index 0000000..5d6524d
--- /dev/null
+++ b/board/gen860t/ioport.c
@@ -0,0 +1,276 @@
+/*
+ * (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>
+#include <asm/8xx_immap.h>
+#include "ioport.h"
+
+#if 0
+#define IOPORT_DEBUG
+#endif
+
+#ifdef  IOPORT_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/*
+ * The ioport configuration table.
+ */
+const mpc8xx_iop_conf_t iop_conf_tab[NUM_PORTS][PORT_BITS] = {
+    /*
+	 * Port A configuration
+	 * Pin		Signal				Type	Active		Initial state
+	 * PA7 		fpgaProgramLowOut	Out		Low			High
+	 */
+    {	/*	    conf ppar psor pdir podr pdat pint	   function 		*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }, /* No pin			*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }, /* No pin			*/
+	/* PA15 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PA14 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PA13 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PA12 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PA11 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PA10 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PA9  */ { 1,   0,   0,   1,   0,   0,   0 }, /* grn bicolor LED 1*/
+	/* PA8  */ { 1,   0,   0,   1,   0,   0,   0 }, /* red bicolor LED 1*/
+	/* PA7  */ { 1,   0,   0,   1,   0,   1,   0 }, /* fpgaProgramLow	*/
+	/* PA6  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PA5  */ { 1,   0,   0,   1,   0,   0,   0 }, /* grn bicolor LED 0*/
+	/* PA4  */ { 1,   0,   0,   1,   0,   0,   0 }, /* red bicolor LED 0*/
+	/* PA3  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PA2  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PA1  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PA0  */ { 0,   0,   0,   0,   0,   0,   0 }  /*	*/
+    },
+
+	/*
+	 * Pin		Signal			Type		Active		Initial state
+	 * PB14		docBusyLowIn	In			Low			X
+	 * PB15		gpio1Sig		Out			High		Low
+	 * PB16		fpgaDoneBi		In			High		X
+	 * PB17		swBitOkLowOut	Out			Low			Low
+	 * PB19		speakerVolSig	Out/Hi-Z	High/Low	High (Hi-Z)
+	 * PB22		fpgaInitLowBi	In			Low			X
+	 * PB23		batteryOkSig	In			High		X
+     */
+    {	/*	    conf ppar psor pdir podr pdat pint 	  function			*/
+	/* PB31 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB30 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB29 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB28 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB27 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB26 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB25 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB24 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB23 */ { 1,   0,   0,   0,   0,   0,   0 }, /* batteryOk		*/
+	/* PB22 */ { 1,   0,   0,   0,   0,   0,   0 }, /* fpgaInitLowBi	*/
+	/* PB21 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB20 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB19 */ { 1,   0,   0,   1,   1,   1,   0 }, /* speakerVol		*/
+	/* PB18 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PB17 */ { 1,   0,   0,   1,   0,   0,   0 }, /* swBitOkLow		*/
+	/* PB16 */ { 1,   0,   0,   0,   0,   0,   0 }, /* fpgaDone			*/
+	/* PB15 */ { 1,   0,   0,   1,   0,   0,   0 }, /* gpio1			*/
+	/* PB14 */ { 1,   0,   0,   0,   0,   0,   0 }  /* docBusyLow		*/
+    },
+
+	/*
+	 * Pin		Signal				Type	Active		Initial state
+	 * PC4		i2cBus1EnSig		Out		High		High
+	 * PC5		i2cBus2EnSig		Out		High		High
+	 * PC6		gpio0Sig			Out		High		Low
+	 * PC8		i2cBus3EnSig		Out		High		High
+	 * PC10		i2cBus4EnSig		Out		High		High
+	 * PC11		fpgaResetLowOut		Out		Low			High
+	 * PC12		systemBitOkIn		In		High		X
+	 * PC15		selfDreqLow			In		Low			X
+	 */
+    {	/*	    conf ppar psor pdir podr pdat pint 	  function			*/
+	/* N/A	*/ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* N/A	*/ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PC15 */ { 1,   0,   0,   0,   0,   0,   0 }, /* selfDreqLowIn	*/
+	/* PC14 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PC13 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PC12 */ { 1,   0,   0,   0,   0,   0,   0 }, /* systemBitOkIn	*/
+	/* PC11 */ { 1,   0,   0,   1,   0,   1,   0 }, /* fpgaResetLowOut	*/
+	/* PC10 */ { 1,   0,   0,   1,   0,   1,   0 }, /* i2cBus4EnSig		*/
+	/* PC9  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PC8  */ { 1,   0,   0,   1,   0,   1,   0 }, /* i2cBus3EnSig		*/
+	/* PC7  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PC6  */ { 1,   0,   0,   1,   0,   1,   0 }, /* gpio0			*/
+	/* PC5  */ { 1,   0,   0,   1,   0,   1,   0 }, /* i2cBus2EnSig		*/
+	/* PC4  */ { 1,   0,   0,   1,   0,   1,   0 }, /* i2cBus1EnSig		*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }  /*	*/
+    },
+
+    /* Port D configuration */
+    {	/*	    conf ppar psor pdir podr pdat pint 	   function			*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD15 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD14 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD13 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD12 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD11 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD10 */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD9  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD8  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD7  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD6  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD5  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD4  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* PD3  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }, /*	*/
+	/* N/A  */ { 0,   0,   0,   0,   0,   0,   0 }  /*	*/
+    }
+};
+
+/*
+ * Configure the MPC8XX I/O ports per the ioport configuration table
+ * (taken from ./cpu/mpc8260/cpu_init.c)
+ */
+void
+config_mpc8xx_ioports(volatile immap_t *immr)
+{
+    int portnum;
+
+    for (portnum = 0; portnum < NUM_PORTS; portnum++) {
+		uint pmsk = 0, ppar = 0, psor = 0, pdir = 0;
+		uint podr = 0, pdat = 0, pint = 0;
+		uint msk = 1;
+		mpc8xx_iop_conf_t *iopc = (mpc8xx_iop_conf_t *)&iop_conf_tab[portnum][0];
+		mpc8xx_iop_conf_t *eiopc = iopc + PORT_BITS;
+
+		/*
+		 * For all ports except port B, ignore the two don't care entries
+		 * in the configuration tables.
+		 */
+		if (portnum != 1) {
+			iopc = (mpc8xx_iop_conf_t *)&iop_conf_tab[portnum][2];
+		}
+
+		/*
+		 * NOTE: index 0 refers to pin 17, index 17 refers to pin 0
+		 */
+		while (iopc < eiopc) {
+	    	if (iopc->conf) {
+				pmsk |= msk;
+				if (iopc->ppar) ppar |= msk;
+				if (iopc->psor) psor |= msk;
+				if (iopc->pdir) pdir |= msk;
+				if (iopc->podr) podr |= msk;
+				if (iopc->pdat) pdat |= msk;
+				if (iopc->pint) pint |= msk;
+		    }
+		    msk <<= 1;
+	  	  iopc++;
+		}
+
+		PRINTF("%s:%d:\n  portnum=%d ", __FUNCTION__, __LINE__, portnum);
+#ifdef IOPORT_DEBUG
+		switch(portnum) {
+			case 0: printf("(A)\n"); break;
+			case 1: printf("(B)\n"); break;
+			case 2: printf("(C)\n"); break;
+			case 3: printf("(D)\n"); break;
+			default: printf("(?)\n"); break;
+		}
+#endif
+		PRINTF("  ppar=0x%.8x  pdir=0x%.8x  podr=0x%.8x\n"
+			   "  pdat=0x%.8x  psor=0x%.8x  pint=0x%.8x  pmsk=0x%.8x\n",
+			   ppar, pdir, podr, pdat, psor, pint, pmsk);
+
+		/*
+		 * Have to handle the ioports on a port-by-port basis since there
+		 * are three different flavors.
+		 */
+		if (pmsk != 0) {
+		    uint tpmsk = ~pmsk;
+
+			if (0 == portnum) { /* port A */
+		    	immr->im_ioport.iop_papar &= tpmsk;
+		    	immr->im_ioport.iop_padat =
+					(immr->im_ioport.iop_padat & tpmsk) | pdat;
+		    	immr->im_ioport.iop_padir =
+					(immr->im_ioport.iop_padir & tpmsk) | pdir;
+		    	immr->im_ioport.iop_paodr =
+					(immr->im_ioport.iop_paodr & tpmsk) | podr;
+		    	immr->im_ioport.iop_papar |= ppar;
+			}
+			else if (1 == portnum) { /* port B */
+		    	immr->im_cpm.cp_pbpar &= tpmsk;
+		    	immr->im_cpm.cp_pbdat = (immr->im_cpm.cp_pbdat & tpmsk) | pdat;
+		    	immr->im_cpm.cp_pbdir = (immr->im_cpm.cp_pbdir & tpmsk) | pdir;
+		    	immr->im_cpm.cp_pbodr = (immr->im_cpm.cp_pbodr & tpmsk) | podr;
+		    	immr->im_cpm.cp_pbpar |= ppar;
+			}
+			else if (2 == portnum) { /* port C */
+		    	immr->im_ioport.iop_pcpar &= tpmsk;
+		    	immr->im_ioport.iop_pcdat =
+					(immr->im_ioport.iop_pcdat & tpmsk) | pdat;
+		    	immr->im_ioport.iop_pcdir =
+					(immr->im_ioport.iop_pcdir & tpmsk) | pdir;
+		    	immr->im_ioport.iop_pcint =
+					(immr->im_ioport.iop_pcint & tpmsk) | pint;
+		    	immr->im_ioport.iop_pcso =
+					(immr->im_ioport.iop_pcso & tpmsk) | psor;
+		    	immr->im_ioport.iop_pcpar |= ppar;
+			}
+			else if (3 == portnum) { /* port D */
+		    	immr->im_ioport.iop_pdpar &= tpmsk;
+		    	immr->im_ioport.iop_pddat =
+					(immr->im_ioport.iop_pddat & tpmsk) | pdat;
+		    	immr->im_ioport.iop_pddir =
+					(immr->im_ioport.iop_pddir & tpmsk) | pdir;
+		    	immr->im_ioport.iop_pdpar |= ppar;
+			}
+		}
+    }
+
+	PRINTF("%s:%d: Port A:\n  papar=0x%.4x  padir=0x%.4x"
+		   "  paodr=0x%.4x\n  padat=0x%.4x\n", __FUNCTION__, __LINE__,
+		   immr->im_ioport.iop_papar, immr->im_ioport.iop_padir,
+		   immr->im_ioport.iop_paodr, immr->im_ioport.iop_padat);
+	PRINTF("%s:%d: Port B:\n  pbpar=0x%.8x  pbdir=0x%.8x"
+		   "  pbodr=0x%.8x\n  pbdat=0x%.8x\n", __FUNCTION__, __LINE__,
+		   immr->im_cpm.cp_pbpar, immr->im_cpm.cp_pbdir,
+		   immr->im_cpm.cp_pbodr, immr->im_cpm.cp_pbdat);
+	PRINTF("%s:%d: Port C:\n  pcpar=0x%.4x  pcdir=0x%.4x"
+		   "  pcdat=0x%.4x\n  pcso=0x%.4x  pcint=0x%.4x\n  ",
+		   __FUNCTION__, __LINE__, immr->im_ioport.iop_pcpar,
+		   immr->im_ioport.iop_pcdir, immr->im_ioport.iop_pcdat,
+		   immr->im_ioport.iop_pcso, immr->im_ioport.iop_pcint);
+	PRINTF("%s:%d: Port D:\n  pdpar=0x%.4x  pddir=0x%.4x"
+		   "  pddat=0x%.4x\n", __FUNCTION__, __LINE__,
+		   immr->im_ioport.iop_pdpar, immr->im_ioport.iop_pddir,
+		   immr->im_ioport.iop_pddat);
+}
+
+/* vim: set ts=4 sw=4 tw=78: */
diff --git a/board/gen860t/u-boot.lds b/board/gen860t/u-boot.lds
new file mode 100644
index 0000000..1b53c72
--- /dev/null
+++ b/board/gen860t/u-boot.lds
@@ -0,0 +1,135 @@
+/*
+ * Linker command file for the GEN860T board.
+ *
+ * (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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+SECTIONS
+{
+  /*
+   * Read-only sections, merged into text segment:
+   */
+  . = + SIZEOF_HEADERS;
+  .interp        : { *(.interp)		}
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)	}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)	}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)	}
+  .rela.got      : { *(.rela.got)	}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)	}
+  .rela.bss      : { *(.rela.bss)	}
+  .rel.plt       : { *(.rel.plt)	}
+  .rela.plt      : { *(.rela.plt)	}
+  .init          : { *(.init)		}
+  .plt           : { *(.plt)		}
+  .text :
+  {
+    cpu/mpc8xx/start.o		(.text)
+    common/dlmalloc.o		(.text)
+    lib_ppc/ppcstring.o		(.text)
+    lib_generic/vsprintf.o	(.text)
+    lib_generic/crc32.o		(.text)
+    lib_generic/zlib.o		(.text)
+
+/*    . = env_offset;
+    common/environment.o(.text) */
+
+    *(.text)
+    *(.fixup)
+    *(.got1)
+  }
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata    :
+  {
+    *(.rodata)
+    *(.rodata1)
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /*
+   * Read-write section, merged into data segment:
+   */
+  . = (. + 0x00FF) & 0xFFFFFF00;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+  __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(256);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(256);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+
+  _end = . ;
+  PROVIDE (end = .);
+}
+