Browse Source

Initial revision

wdenk 21 years ago
parent
commit
cc1c8a136f

+ 12 - 0
CHANGELOG

@@ -0,0 +1,12 @@
+
+======================================================================
+Notes for U-Boot 1.0.0:
+======================================================================
+
+This is the initial version of "Das U-Boot", the Universal Boot Loader.
+
+It is based on version 2.0.0 (the "Halloween Release") of PPCBoot.
+For information about the history of the project please see the
+PPCBoot project page at http://sourceforge.net/projects/ppcboot
+
+======================================================================

+ 249 - 0
MAINTAINERS

@@ -0,0 +1,249 @@
+#########################################################################
+#									#
+# Regular Maintainers for U-Boot board support:				#
+#									#
+# For any board without permanent maintainer, please contact		#
+#    for PowerPC systems:						#
+#	Wolfgang Denk <wd@denx.de>					#
+#    for ARM systems:							#
+#	Marius Gröger <mag@sysgo.de>					#
+# and Cc: the <U-Boot-Users@lists.sourceforge.net> mailing lists.	#
+#									#
+# Note: lists sorted by Maintainer Name					#
+#########################################################################
+
+
+#########################################################################
+#									#
+# Maintainer Name, Email Address					#
+#	Board			CPU					#
+#########################################################################
+
+Greg Allen <gallen@arlut.utexas.edu>
+
+	UTX8245			MPC8245
+
+Pantelis Antoniou <panto@intracom.gr>
+
+	NETVIA			MPC8xx
+
+Jerry Van Baren <vanbaren_gerald@si.com>
+
+	sacsng			MPC8260
+
+Oliver Brown <obrown@adventnetworks.com>
+
+	sbc8260			MPC8260
+	gw8260			MPC8260
+
+Conn Clark <clark@esteem.com>
+
+	ESTEEM192E		MPC8xx
+
+Kári Davíðsson <kd@flaga.is>
+
+	FLAGADM			MPC823
+
+Wolfgang Denk <wd@denx.de>
+
+	AMX860			MPC860
+	ETX094			MPC850
+	FPS850L			MPC850
+	ICU862			MPC862
+	IP860			MPC860
+	IVML24			MPC860
+	IVML24_128		MPC860
+	IVML24_256		MPC860
+	IVMS8			MPC860
+	IVMS8_128		MPC860
+	IVMS8_256		MPC860
+	LANTEC			MPC850
+	RRvision		MPC823
+	SM850			MPC850
+	SPD823TS		MPC823
+	TQM823L			MPC823
+	TQM823L_LCD		MPC823
+	TQM850L			MPC850
+	TQM855L			MPC855
+	TQM860L			MPC860
+	TQM860L_FEC		MPC860
+	c2mon			MPC855
+	hermes			MPC860
+	lwmon			MPC823
+	pcu_e			MPC855
+
+	CU824			MPC8240
+	Sandpoint8240		MPC8240
+
+	CPU86			MPC8260
+	PM826			MPC8260
+	TQM8260			MPC8260
+
+	PCIPPC2			MPC750
+	PCIPPC6			MPC750
+
+Jon Diekema <diekema_jon@si.com>
+
+	sbc8260			MPC8260
+
+Dave Ellis <DGE@sixnetio.com>
+
+	SXNI855T		MPC8xx
+
+Frank Gottschling <fgottschling@eltec.de>
+
+	MHPC			MPC8xx
+
+	BAB7xx			MPC740/MPC750
+
+Wolfgang Grandegger <wg@denx.de>
+
+	CCM			MPC855
+
+	PN62			MPC8240
+
+	IPHASE4539		MPC8260
+	SCM			MPC8260
+
+Howard Gray <mvsensor@matrix-vision.de>
+
+	MVS1			MPC823
+
+Murray Jensen <Murray.Jensen@cmst.csiro.au>
+
+	cogent_mpc8xx		MPC8xx
+
+	cogent_mpc8260		MPC8260
+	hymod			MPC8260
+
+Brad Kemp <Brad.Kemp@seranoa.com>
+
+	ppmc8260		MPC8260
+
+Nye Liu <nyet@zumanetworks.com>
+
+	ZUMA			MPC7xx_74xx
+
+Thomas Lange <thomas@corelatus.com>
+
+	GTH			MPC860
+
+Eran Man <eran@nbase.co.il>
+
+	EVB64260_750CX		MPC750CX
+
+Scott McNutt <smcnutt@artesyncp.com>
+
+	EBONY			PPC440GP
+
+Keith Outwater <Keith_Outwater@mvis.com>
+
+	GEN860T			MPC860T
+
+Frank Panno <fpanno@delphintech.com>
+
+	ep8260			MPC8260
+
+Denis Peter <d.peter@mpl.ch>
+
+	MIP405			PPC4xx
+	PIP405			PPC4xx
+
+Stefan Roese <stefan.roese@esd-electronics.com>
+
+	ADCIOP			IOP480 (PPC401)
+	AR405			PPC405GP
+	CANBT			PPC405CR
+	CPCI405			PPC405GP
+	CPCI440			PPC440GP
+	CPCIISER4		PPC405GP
+	DASA_SIM		IOP480 (PPC401)
+	DU405			PPC405GP
+	OCRTC			PPC405GP
+	ORSG			PPC405GP
+
+Peter De Schrijver <p2@mind.be>
+
+	ML2			PPC4xx
+
+Erik Theisen <etheisen@mindspring.com>
+
+	W7OLMC			PPC4xx
+	W7OLMG			PPC4xx
+
+Jim Thompson <jim@musenki.com>
+
+	MUSENKI			MPC8245/8241
+	Sandpoint8245		MPC8245
+
+-------------------------------------------------------------------------
+
+Unknown / orphaned boards:
+
+	ADS860			MPC8xx
+	FADS823			MPC8xx
+	FADS850SAR		MPC8xx
+	FADS860T		MPC8xx
+	GENIETV			MPC8xx
+	IAD210			MPC8xx
+	MBX			MPC8xx
+	MBX860T			MPC8xx
+	NX823			MPC8xx
+	RPXClassic		MPC8xx
+	RPXlite			MPC8xx
+
+	CRAYL1			PPC4xx
+	ERIC			PPC4xx
+	WALNUT405		PPC4xx
+
+	MOUSSE			MPC824x
+
+	MPC8260ADS		MPC8260
+	RPXsuper		MPC8260
+	rsdproto		MPC8260
+
+	EVB64260		MPC7xx_74xx
+
+
+#########################################################################
+# ARM Systems:								#
+#									#
+# Maintainer Name, Email Address					#
+#	Board			CPU					#
+#########################################################################
+
+Marius Gröger <mag@sysgo.de>
+
+	impa7			ARM720T (EP7211)
+	ep7312			ARM720T (EP7312)
+
+Kyle Harris <kharris@nexus-tech.net>
+
+	lubbock			xscale
+	cradle			xscale
+
+Gary Jennejohn <gj@denx.de>
+
+	smdk2400		ARM920T
+	trab			ARM920T
+
+David Müller <d.mueller@elsoft.ch>
+
+	smdk2410		ARM920T
+
+Rolf Offermanns <rof@sysgo.de>
+
+	shannon			SA1100
+
+Robert Schwebel <r.schwebel@pengutronix.de>
+
+	csb226			xscale
+
+Alex Züpke <azu@sysgo.de>
+
+	lart			SA1100
+	dnp1110			SA1110
+
+#########################################################################
+# End of MAINTAINERS list						#
+#########################################################################

+ 615 - 0
board/cpu86/flash.c

@@ -0,0 +1,615 @@
+/*
+ * (C) Copyright 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for Intel 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 "cpu86.h"
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+/*-----------------------------------------------------------------------
+ */
+ulong flash_int_get_size (volatile unsigned long *baseaddr,
+					  flash_info_t * info)
+{
+	short i;
+	unsigned long flashtest_h, flashtest_l;
+
+	info->sector_count = info->size = 0;
+	info->flash_id = FLASH_UNKNOWN;
+
+	/* Write query command sequence and test FLASH answer
+	 */
+	baseaddr[0] = 0x00980098;
+	baseaddr[1] = 0x00980098;
+
+	flashtest_h = baseaddr[0];	/* manufacturer ID	*/
+	flashtest_l = baseaddr[1];
+
+	if (flashtest_h != INTEL_MANUFACT || flashtest_l != INTEL_MANUFACT)
+		return (0);		/* no or unknown flash	*/
+
+	flashtest_h = baseaddr[2];	/* device ID	        */
+	flashtest_l = baseaddr[3];
+
+	if (flashtest_h != flashtest_l)
+		return (0);
+
+	switch (flashtest_h) {
+	case INTEL_ID_28F160C3B:
+		info->flash_id = FLASH_28F160C3B;
+		info->sector_count = 39;
+		info->size = 0x00800000;	/* 4 * 2 MB = 8 MB	*/
+		break;
+	case INTEL_ID_28F160F3B:
+		info->flash_id = FLASH_28F160F3B;
+		info->sector_count = 39;
+		info->size = 0x00800000;	/* 4 * 2 MB = 8 MB      */
+		break;
+	default:
+		return (0);			/* no or unknown flash	*/
+	}
+
+	info->flash_id |= INTEL_MANUFACT << 16; /* set manufacturer offset */
+
+	if (info->flash_id & FLASH_BTYPE) {
+		volatile unsigned long *tmp = baseaddr;
+
+		/* set up sector start adress table (bottom sector type)
+		 * AND unlock the sectors (if our chip is 160C3)
+		 */
+		for (i = 0; i < info->sector_count; i++) {
+			if ((info->flash_id & FLASH_TYPEMASK) == FLASH_28F160C3B) {
+				tmp[0] = 0x00600060;
+				tmp[1] = 0x00600060;
+				tmp[0] = 0x00D000D0;
+				tmp[1] = 0x00D000D0;
+			}
+			info->start[i] = (uint) tmp;
+			tmp += i < 8 ? 0x2000 : 0x10000; /* pointer arith       */
+		}
+	}
+
+	memset (info->protect, 0, info->sector_count);
+
+	baseaddr[0] = 0x00FF00FF;
+	baseaddr[1] = 0x00FF00FF;
+
+	return (info->size);
+}
+
+static ulong flash_amd_get_size (vu_char *addr, flash_info_t *info)
+{
+	short i;
+	uchar vendor, devid;
+	ulong base = (ulong)addr;
+
+	/* Write auto select command: read Manufacturer ID */
+	addr[0x0555] = 0xAA;
+	addr[0x02AA] = 0x55;
+	addr[0x0555] = 0x90;
+
+	udelay(1000);
+
+	vendor = addr[0];
+	devid = addr[1] & 0xff;
+
+	/* only support AMD */
+	if (vendor != 0x01) {
+		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: %02x\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 char *)(info->start[i]);
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (vu_char *)info->start[0];
+		addr[0] = 0xF0; /* reset bank */
+	}
+
+	return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+	unsigned long size_b0 = 0;
+	unsigned long size_b1 = 0;
+	int i;
+
+	/* Init: no FLASHes known
+	 */
+	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+	}
+
+	/* Disable flash protection */
+	CPU86_BCR |= (CPU86_BCR_FWPT | CPU86_BCR_FWRE);
+
+	/* Static FLASH Bank configuration here (only one bank) */
+
+	size_b0 = flash_int_get_size ((ulong *) CFG_FLASH_BASE, &flash_info[0]);
+	size_b1 = flash_amd_get_size ((uchar *) CFG_BOOTROM_BASE, &flash_info[1]);
+
+	if (size_b0 > 0 || size_b1 > 0) {
+
+		printf("(");
+
+		if (size_b0 > 0) {
+			puts ("Bank#1 - ");
+			print_size (size_b0, (size_b1 > 0) ? ", " : ") ");
+		}
+
+		if (size_b1 > 0) {
+			puts ("Bank#2 - ");
+			print_size (size_b1, ") ");
+		}
+	}
+	else {
+		printf ("## No FLASH found.\n");
+		return 0;
+	}
+	/* protect monitor and environment sectors
+	 */
+
+#if CFG_MONITOR_BASE >= CFG_BOOTROM_BASE
+	if (size_b1) {
+		/* If U-Boot is booted from ROM the CFG_MONITOR_BASE > CFG_FLASH_BASE
+		 * but we shouldn't protect it.
+		 */
+
+		flash_protect  (FLAG_PROTECT_SET,
+				CFG_MONITOR_BASE,
+				CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, &flash_info[1]
+		);
+	}
+#else
+#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
+#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
+# if CFG_ENV_ADDR >= CFG_BOOTROM_BASE
+	if (size_b1) {
+		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
+
+	return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+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 0x89:
+		printf ("INTEL ");
+		break;
+	case 0x1:
+		printf ("AMD ");
+		break;
+	default:
+		printf ("Unknown Vendor ");
+		break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_28F160C3B:
+		printf ("28F160C3B (16 Mbit, bottom sector)\n");
+		break;
+	case FLASH_28F160F3B:
+		printf ("28F160F3B (16 Mbit, bottom sector)\n");
+		break;
+	case AMD_ID_F040B:
+		printf ("AM29F040B (4 Mbit)\n");
+		break;
+	default:
+		printf ("Unknown Chip Type\n");
+		break;
+	}
+
+	if (info->size < 0x100000)
+		printf ("  Size: %ld KB in %d Sectors\n",
+				info->size >> 10, info->sector_count);
+	else
+		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");
+}
+
+/*-----------------------------------------------------------------------
+ */
+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;
+	}
+
+	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");
+	}
+
+	/* Check the type of erased flash
+	 */
+	if (info->flash_id >> 16 == 0x1) {
+		/* Erase AMD flash
+		 */
+		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;
+
+		/* wait at least 80us - let's wait 1 ms */
+		udelay (1000);
+
+		/* 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 AMD_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 */
+				serial_putc ('.');
+				last = now;
+			}
+		}
+
+AMD_DONE:
+		/* reset to read mode */
+		addr = (volatile unsigned char *)info->start[0];
+		addr[0] = 0xF0;     /* reset bank */
+
+	} else {
+		/* Erase Intel flash
+		 */
+
+		/* Start erase on unprotected sectors
+		 */
+		for (sect = s_first; sect <= s_last; sect++) {
+			volatile ulong *addr =
+				(volatile unsigned long *) info->start[sect];
+
+			start = get_timer (0);
+			last = start;
+			if (info->protect[sect] == 0) {
+			/* Disable interrupts which might cause a timeout here
+			 */
+				flag = disable_interrupts ();
+
+				/* Erase the block
+				 */
+				addr[0] = 0x00200020;
+				addr[1] = 0x00200020;
+				addr[0] = 0x00D000D0;
+				addr[1] = 0x00D000D0;
+
+				/* re-enable interrupts if necessary
+				 */
+				if (flag)
+					enable_interrupts ();
+
+				/* wait at least 80us - let's wait 1 ms
+				 */
+				udelay (1000);
+
+				last = start;
+				while ((addr[0] & 0x00800080) != 0x00800080 ||
+				   (addr[1] & 0x00800080) != 0x00800080) {
+					if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
+						printf ("Timeout (erase suspended!)\n");
+						/* Suspend erase
+						 */
+						addr[0] = 0x00B000B0;
+						addr[1] = 0x00B000B0;
+						goto DONE;
+					}
+					/* show that we're waiting
+					 */
+					if ((now - last) > 1000) {	/* every second */
+						serial_putc ('.');
+						last = now;
+					}
+				}
+				if (addr[0] & 0x00220022 || addr[1] & 0x00220022) {
+					printf ("*** ERROR: erase failed!\n");
+					goto DONE;
+				}
+			}
+			/* Clear status register and reset to read mode
+			 */
+			addr[0] = 0x00500050;
+			addr[1] = 0x00500050;
+			addr[0] = 0x00FF00FF;
+			addr[1] = 0x00FF00FF;
+		}
+	}
+
+	printf (" done\n");
+
+DONE:
+	return 0;
+}
+
+static int write_word (flash_info_t *, volatile unsigned long *, ulong);
+static int write_byte (flash_info_t *info, ulong dest, uchar data);
+
+/*-----------------------------------------------------------------------
+ * 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 v;
+	int i, l, rc, cc = cnt, res = 0;
+
+	if (info->flash_id >> 16 == 0x1) {
+
+		/* Write to AMD 8-bit flash
+		 */
+		while (cnt > 0) {
+			if ((rc = write_byte(info, addr, *src)) != 0) {
+				return (rc);
+			}
+			addr++;
+			src++;
+			cnt--;
+		}
+
+		return (0);
+	} else {
+
+		/* Write to Intel 64-bit flash
+		 */
+		for (v=0; cc > 0; addr += 4, cc -= 4 - l) {
+			l = (addr & 3);
+			addr &= ~3;
+
+			for (i = 0; i < 4; i++) {
+				v = (v << 8) + (i < l || i - l >= cc ?
+					*((unsigned char *) addr + i) : *src++);
+			}
+
+			if ((res = write_word (info, (volatile unsigned long *) addr, v)) != 0)
+				break;
+		}
+	}
+
+	return (res);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t * info, volatile unsigned long *addr,
+					   ulong data)
+{
+	int flag, res = 0;
+	ulong start;
+
+	/* Check if Flash is (sufficiently) erased
+	 */
+	if ((*addr & data) != data)
+		return (2);
+
+	/* Disable interrupts which might cause a timeout here
+	 */
+	flag = disable_interrupts ();
+
+	*addr = 0x00400040;
+	*addr = data;
+
+	/* re-enable interrupts if necessary
+	 */
+	if (flag)
+		enable_interrupts ();
+
+	start = get_timer (0);
+	while ((*addr & 0x00800080) != 0x00800080) {
+		if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
+			/* Suspend program
+			 */
+			*addr = 0x00B000B0;
+			res = 1;
+			goto OUT;
+		}
+	}
+
+	if (*addr & 0x00220022) {
+		printf ("*** ERROR: program failed!\n");
+		res = 1;
+	}
+
+OUT:
+	/* Clear status register and reset to read mode
+	 */
+	*addr = 0x00500050;
+	*addr = 0x00FF00FF;
+
+	return (res);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a byte 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[0x0555] = 0xAA;
+	addr[0x02AA] = 0x55;
+	addr[0x0555] = 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);
+}
+
+/*-----------------------------------------------------------------------
+ */

+ 127 - 0
board/lwmon/README.keybd

@@ -0,0 +1,127 @@
+
+Tastaturabfrage:
+
+Die Implementierung / Decodierung beruht auf den Angaben aus dem  Do-
+kument  "PIC LWE-Tastatur" in der Fassung vom 9. 3. 2001, insbesonde-
+re Tabelle 3 im Kapitel 4.3 Tastencodes. In  U-Boot  werden  die  vom
+Keyboard-Controller  gelesenen Daten hexadezimal codiert in der auto-
+matisch angelegten Environment-Variablen "keybd" übergeben. Ist  kei-
+ne Taste gedrückt worden, steht dort:
+
+	keybd=000000000000000000
+
+Der decodierte Tastencode ("keybd") kann mit den  "bootargs"  an  den
+Linux-Kernel  übergeben  und  dort z. B. in einem Device-Treiber oder
+einer Applikation ausgewertet werden.
+
+
+
+Sonderfunktionen beim Booten:
+
+Es lassen sich eine oder mehrere (beliebig viele) Tasten oder Tasten-
+kombinationen definieren, die Sonderfunktionen auslösen,  wenn  diese
+Tasten beim Booten (Reset) gedrückt sind.
+
+Wird eine eingestellte Taste bzw. Tastenkombination erkannt, so  wird
+in  U-Boot noch vor dem Start des "Countdown" und somit vor jedem an-
+deren Kommando der Inhalt einer dieser Taste  bzw.  Tastenkombination
+zugeordneten Environment-Variablen ausführen.
+
+
+Die Environment-Variable "magic_keys" wird als Liste von Zeichen ver-
+standen, die als Suffix an den Namen "key_magic" angefügt werden  und
+so  die  Namen  der  Environment-Variablen  definieren, mit denen die
+Tasten (-kombinationen) festgelegt werden:
+
+Ist "magic_keys" NICHT definiert, so wird nur die in der Environment-
+Variablen "key_magic" codierte  Tasten  (-kombination)  geprüft,  und
+ggf.  der  Inhalt der Environment-Variablen "key_cmd" ausgeführt (ge-
+nauer: der Inhalt von "key_cmd" wird der Variablen "preboot" zugewie-
+sen, die ausgeführt wird, unmittelbar bevor die interaktive Kommando-
+interpretation beginnt).
+
+Enthält "magic_keys" z. B.  die  Zeichenkette  "0123CB*",  so  werden
+nacheinander folgende Aktionen ausgeführt:
+
+	prüfe Tastencode	ggf. führe aus Kommando
+	in Variable		in Variable
+	-----------------------------------
+	key_magic0	==>	key_cmd0
+	key_magic1	==>	key_cmd1
+	key_magic2	==>	key_cmd2
+	key_magic3	==>	key_cmd3
+	key_magicC	==>	key_cmdC
+	key_magicB	==>	key_cmdB
+	key_magicA	==>	key_cmdA
+	key_magic*	==>	key_cmd*
+
+Hinweis: sobald ein aktivierter Tastencode erkannt  wurde,  wird  die
+Bearbeitung  abgebrochen; es wird daher höchstens eines der definier-
+ten Kommandos ausgeführt, wobei die Priorität durch  die  Suchreihen-
+folge  festgelegt wird, also durch die Reihenfolge der Zeichen in der
+Varuiablen "magic_keys".
+
+
+Die Codierung der Tasten, die beim Booten gedrückt werden müssen, um
+eine Funktion auszulösen, erfolgt nach der Tastaturtabelle.
+
+Die Definitionen
+
+	=> setenv key_magic0 3a+3b
+	=> setenv key_cmd0 setenv bootdelay 30
+
+bedeuten dementsprechend, daß die Tasten mit den  Codes  0x3A  (Taste
+"F1")  und 0x3B (Taste "F2") gleichzeitig gedrückt werden müssen. Sie
+können dort eine beliebige  Tastenkombination  eintragen  (jeweils  2
+Zeichen für die Hex-Codes der Tasten, und '+' als Trennzeichen).
+
+Wird die eingestellte Tastenkombination erkannt, so  wird  in  U-Boot
+noch  vor  dem Start des "Countdown" und somit vor jedem anderen Kom-
+mando das angebene Kommando ausgeführt und  somit  ein  langes  Boot-
+Delay eingetragen.
+
+Praktisch könnten Sie also in U-Boot "bootdelay"  auf  0  setzen  und
+somit  stets  ohne  jede  User-Interaktion automatisch booten, außer,
+wenn die beiden Tasten "F1" und "F2"  beim  Booten  gedrückt  werden:
+dann würde ein Boot-Delay von 30 Sekunden eingefügt.
+
+
+Hinweis: dem Zeichen '#' kommt innerhalb von "magic_keys" eine beson-
+dere Bedeutung zu: die dadurch definierte  Key-Sequenz  schaltet  den
+Monitor in den "Debug-Modus" - das bedeutet zunächst, daß alle weite-
+ren  Meldungen  von  U-Boot  über  das LCD-Display ausgegeben werden;
+außerdem kann man durch das mit dieser  Tastenkombination  verknüpfte
+Kommando  z. B. die Linux-Bootmeldungen ebenfalls auf das LCD-Display
+legen, so daß der Boot-Vorgang direkt und  ohne  weitere  Hilfsmittel
+analysiert werden kann.
+
+Beispiel:
+
+In U-Boot werden folgende Environment-Variablen gesetzt und abgespei-
+chert:
+
+(1)	=> setenv magic_keys 01234#X
+(2)	=> setenv key_cmd# setenv addfb setenv bootargs \\$(bootargs) console=tty0 console=ttyS1,\\$(baudrate)
+(3)	=> setenv nfsargs setenv bootargs root=/dev/nfs rw nfsroot=\$(serverip):\$(rootpath)
+(4)	=> setenv addip setenv bootargs \$(bootargs) ip=\$(ipaddr):\$(serverip):\$(gatewayip):\$(netmask):\$(hostname)::off panic=1
+(5)	=> setenv addfb setenv bootargs \$(bootargs) console=ttyS1,\$(baudrate)
+(6)	=> setenv bootcmd bootp\;run nfsargs\;run addip\;run addfb\;bootm
+
+Hierbei wird die Linux Commandline (in der Variablen  "bootargs")  im
+Boot-Kommando  "bootcmd"  (6)  schrittweise zusammengesetzt: zunächst
+werden die für Root-Filesystem über NFS erforderlichen  Optionen  ge-
+setzt  ("run  nfsargs", vgl. (3)), dann die Netzwerkkonfiguration an-
+gefügt ("run addip", vgl. (4)),  und  schließlich  die  Systemconsole
+definiert ("run addfb").
+
+Dabei wird im Normalfall die Definition (5)  verwendt;  wurde  aller-
+dings  beim  Reset die entsprechende Taste gedrückt gehalten, so wird
+diese Definition bei der Ausführung des in (2) definierten  Kommandos
+überschrieben,  so  daß  Linux die Bootmeldungen auch über das Frame-
+buffer-Device (=LCD-Display) ausgibt.
+
+Beachten Sie die Verdoppelung der '\'-Escapes in der  Definition  von
+"key_cmd#" - diese ist erforderlich, weil der String _zweimal_ inter-
+pretiert  wird:  das  erste  Mal  bei der Eingabe von "key_cmd#", das
+zweite Mal, wenn der String (als  Inhalt  von  "preboot")  ausgeführt
+wird.

+ 944 - 0
board/mousse/flash.c

@@ -0,0 +1,944 @@
+/*
+ * MOUSSE/MPC8240 Board definitions.
+ * Flash Routines for MOUSSE onboard AMD29LV106DB devices
+ *
+ * (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.
+ *
+ * (C) Copyright 1999, by Curt McDowell, 08-06-99, Broadcom Corp.
+ * (C) Copyright 2001, James Dougherty, 07/18/01, Broadcom Corp.
+ *
+ * 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 <malloc.h>
+#include "mousse.h"
+#include "flash.h"
+
+int flashLibDebug = 0;
+int flashLibInited = 0;
+
+#define OK  0
+#define ERROR -1
+#define STATUS int
+#define PRINTF			if (flashLibDebug) printf
+#if 0
+#define PRIVATE			static
+#else
+#define PRIVATE
+#endif
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+#define SLEEP_DELAY    166
+#define FLASH_SECTOR_SIZE   (64*1024)
+/***********************************************************************
+ *
+ * Virtual Flash Devices on Mousse board
+ *
+ * These must be kept in sync with the definitions in flashLib.h.
+ *
+ ***********************************************************************/
+
+PRIVATE flash_dev_t flashDev[] = {
+    /* Bank 0 sector SA0 (16 kB) */
+    {	"SA0",FLASH0_BANK, FLASH0_SEG0_START, 1, 14,
+	FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+    /* Bank 0 sector SA1 (8 kB) */
+    {	"SA1", FLASH0_BANK, FLASH0_SEG0_START + 0x4000, 1, 13,
+	FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+    /* Bank 0 sector SA2 (8 kB) */
+    {	"SA2", FLASH0_BANK, FLASH0_SEG0_START + 0x6000, 1, 13,
+	FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+    /* Bank 0 sector SA3 is occluded by Mousse I/O devices */
+    /* Bank 0 sectors SA4-SA18, after Mousse devices up to PLCC (960 kB)  */
+    {	"KERNEL", FLASH0_BANK, FLASH0_SEG1_START, 15, 16,
+	FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+    /* Bank 0 sectors SA19-SA26, jumper can occlude this by PLCC (512 kB) */
+    /* This is where the Kahlua boot vector and boot ROM code resides. */
+    {	"BOOT",FLASH0_BANK, FLASH0_SEG2_START, 8, 16,
+	FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+    /* Bank 0 sectors SA27-SA34 (512 kB) */
+    {	"RAMDISK",FLASH0_BANK, FLASH0_SEG3_START, 8, 16,
+	FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+};
+
+int flashDevCount = (sizeof (flashDev) / sizeof (flashDev[0]));
+
+#define DEV(no)			(&flashDev[no])
+#define DEV_NO(dev)		((dev) - flashDev)
+
+/***********************************************************************
+ *
+ * Private Flash Routines
+ *
+ ***********************************************************************/
+
+/*
+ * The convention is:
+ *
+ * "addr" is always the PROM raw address, which is the address of an
+ * 8-bit quantity for flash 0 and 16-bit quantity for flash 1.
+ *
+ * "pos" is always a logical byte position from the PROM beginning.
+ */
+
+#define FLASH0_ADDR(dev, addr) \
+	((unsigned char *) ((dev)->base + (addr)))
+
+#define FLASH0_WRITE(dev, addr, value) \
+	(*FLASH0_ADDR(dev, addr) = (value))
+
+#define FLASH0_READ(dev, addr) \
+	(*FLASH0_ADDR(dev, addr))
+
+PRIVATE int flashCheck(flash_dev_t *dev)
+{
+    if (! flashLibInited) {
+	printf("flashCheck: flashLib not initialized\n");
+	return ERROR;
+    }
+
+    if (dev < &flashDev[0] || dev >= &flashDev[flashDevCount]) {
+	printf("flashCheck: Bad dev parameter\n");
+	return ERROR;
+    }
+
+    if (! dev->found) {
+	printf("flashCheck: Device %d not available\n", DEV_NO(dev));
+	return ERROR;
+    }
+
+    return OK;
+}
+
+PRIVATE void flashReset(flash_dev_t *dev)
+{
+    PRINTF("flashReset: dev=%d\n", DEV_NO(dev));
+
+    if (dev->bank == FLASH0_BANK) {
+	FLASH0_WRITE(dev, 0x555, 0xaa);
+	FLASH0_WRITE(dev, 0xaaa, 0x55);
+	FLASH0_WRITE(dev, 0x555, 0xf0);
+    }
+
+    udelay(SLEEP_DELAY);
+
+    PRINTF("flashReset: done\n");
+}
+
+PRIVATE int flashProbe(flash_dev_t *dev)
+{
+    int			rv, deviceID, vendorID;
+
+    PRINTF("flashProbe: dev=%d\n", DEV_NO(dev));
+
+    if (dev->bank != FLASH0_BANK) {
+    	rv = ERROR;
+	goto DONE;
+    }
+
+    FLASH0_WRITE(dev, 0xaaa, 0xaa);
+    FLASH0_WRITE(dev, 0x555, 0x55);
+    FLASH0_WRITE(dev, 0xaaa, 0x90);
+
+    udelay(SLEEP_DELAY);
+
+    vendorID = FLASH0_READ(dev, 0);
+    deviceID = FLASH0_READ(dev, 2);
+
+    FLASH0_WRITE(dev, 0, 0xf0);
+
+    PRINTF("flashProbe: vendor=0x%x device=0x%x\n", vendorID, deviceID);
+
+    if (vendorID == dev->vendorID && deviceID == dev->deviceID)
+	rv = OK;
+    else
+	rv = ERROR;
+
+DONE:
+    PRINTF("flashProbe: rv=%d\n", rv);
+
+    return rv;
+}
+
+PRIVATE int flashWait(flash_dev_t *dev, int addr, int expect, int erase)
+{
+    int			rv = ERROR;
+    int			i, data;
+    int			polls;
+#if 0
+    PRINTF("flashWait: dev=%d addr=0x%x expect=0x%x erase=%d\n",
+	   DEV_NO(dev), addr, expect, erase);
+#endif
+
+    if (dev->bank != FLASH0_BANK) {
+	rv = ERROR;
+	goto done;
+    }
+
+    if (erase)
+	polls = FLASH_ERASE_SECTOR_TIMEOUT;	/* Ticks */
+    else
+	polls = FLASH_PROGRAM_POLLS;		/* Loops */
+
+    for (i = 0; i < polls; i++) {
+	if (erase)
+	    udelay(SLEEP_DELAY);
+
+	data = FLASH0_READ(dev, addr);
+
+	if (((data ^ expect) & 0x80) == 0) {
+	    rv = OK;
+	    goto done;
+	}
+
+	if (data & 0x20) {
+	    /*
+	     * If the 0x20 bit has come on, it could actually be because
+	     * the operation succeeded, so check the done bit again.
+	     */
+
+	    data = FLASH0_READ(dev, addr);
+
+	    if (((data ^ expect) & 0x80) == 0) {
+		rv = OK;
+		goto done;
+	    }
+
+	    printf("flashWait: Program error (dev: %d, addr: 0x%x)\n",
+		   DEV_NO(dev), addr);
+
+	    flashReset(dev);
+	    rv = ERROR;
+	    goto done;
+	}
+    }
+
+    printf("flashWait: Timeout %s (dev: %d, addr: 0x%x)\n",
+	   erase ? "erasing sector" : "programming byte",
+	   DEV_NO(dev), addr);
+
+done:
+
+#if 0
+    PRINTF("flashWait: rv=%d\n", rv);
+#endif
+
+    return rv;
+}
+
+/***********************************************************************
+ *
+ * Public Flash Routines
+ *
+ ***********************************************************************/
+
+STATUS flashLibInit(void)
+{
+    int			i;
+
+    PRINTF("flashLibInit: devices=%d\n", flashDevCount);
+
+    for (i = 0; i < flashDevCount; i++) {
+	flash_dev_t	*dev = &flashDev[i];
+	/*
+	 * For bank 1, probe both without and with byte swappage,
+	 * so that this module works on both old and new Mousse boards.
+	 */
+
+	flashReset(dev);
+
+	if (flashProbe(dev) != ERROR)
+	    dev->found = 1;
+
+	    flashReset(dev);
+
+	    if (flashProbe(dev) != ERROR)
+		dev->found = 1;
+
+	    dev->swap = 0;
+
+	    if(dev->found){
+	      PRINTF("\n  FLASH %s[%d]: iobase=0x%x - %d sectors %d KB",
+		     flashDev[i].name,i,flashDev[i].base, flashDev[i].sectors,
+		     (flashDev[i].sectors * FLASH_SECTOR_SIZE)/1024);
+
+	    }
+    }
+
+    flashLibInited = 1;
+
+    PRINTF("flashLibInit: done\n");
+
+    return OK;
+}
+
+STATUS flashEraseSector(flash_dev_t *dev, int sector)
+{
+    int			pos, addr;
+
+    PRINTF("flashErasesector: dev=%d sector=%d\n", DEV_NO(dev), sector);
+
+    if (flashCheck(dev) == ERROR)
+	return ERROR;
+
+    if (sector < 0 || sector >= dev->sectors) {
+	printf("flashEraseSector: Sector out of range (dev: %d, sector: %d)\n",
+	       DEV_NO(dev), sector);
+	return ERROR;
+    }
+
+    pos = FLASH_SECTOR_POS(dev, sector);
+
+    if (dev->bank != FLASH0_BANK) {
+	return ERROR;
+    }
+
+    addr = pos;
+
+    FLASH0_WRITE(dev, 0xaaa, 0xaa);
+    FLASH0_WRITE(dev, 0x555, 0x55);
+    FLASH0_WRITE(dev, 0xaaa, 0x80);
+    FLASH0_WRITE(dev, 0xaaa, 0xaa);
+    FLASH0_WRITE(dev, 0x555, 0x55);
+    FLASH0_WRITE(dev, addr, 0x30);
+
+    return flashWait(dev, addr, 0xff, 1);
+}
+
+/*
+ * Note: it takes about as long to flash all sectors together with Chip
+ * Erase as it does to flash them one at a time (about 30 seconds for 2
+ * MB).  Also since we want to be able to treat subsets of sectors as if
+ * they were complete devices, we don't use Chip Erase.
+ */
+
+STATUS flashErase(flash_dev_t *dev)
+{
+    int			sector;
+
+    PRINTF("flashErase: dev=%d sectors=%d\n", DEV_NO(dev), dev->sectors);
+
+    if (flashCheck(dev) == ERROR)
+	return ERROR;
+
+    for (sector = 0; sector < dev->sectors; sector++) {
+      if (flashEraseSector(dev, sector) == ERROR)
+	    return ERROR;
+    }
+    return OK;
+}
+
+/*
+ * Read and write bytes
+ */
+
+STATUS flashRead(flash_dev_t *dev, int pos, char *buf, int len)
+{
+    int			addr, words;
+
+    PRINTF("flashRead: dev=%d pos=0x%x buf=0x%x len=0x%x\n",
+	   DEV_NO(dev), pos, (int) buf, len);
+
+    if (flashCheck(dev) == ERROR)
+	return ERROR;
+
+    if (pos < 0 || len < 0 || pos + len > FLASH_MAX_POS(dev)) {
+	printf("flashRead: Position out of range "
+	       "(dev: %d, pos: 0x%x, len: 0x%x)\n",
+	       DEV_NO(dev), pos, len);
+	return ERROR;
+    }
+
+    if (len == 0)
+	return OK;
+
+    if (dev->bank == FLASH0_BANK) {
+	addr = pos;
+	words = len;
+
+	PRINTF("flashRead: memcpy(0x%x, 0x%x, 0x%x)\n",
+	       (int) buf, (int) FLASH0_ADDR(dev, pos), len);
+
+	memcpy(buf, FLASH0_ADDR(dev, addr), words);
+
+    }
+    PRINTF("flashRead: rv=OK\n");
+
+    return OK;
+}
+
+STATUS flashWrite(flash_dev_t *dev, int pos, char *buf, int len)
+{
+    int 		addr, words;
+
+    PRINTF("flashWrite: dev=%d pos=0x%x buf=0x%x len=0x%x\n",
+	   DEV_NO(dev), pos, (int) buf, len);
+
+    if (flashCheck(dev) == ERROR)
+	return ERROR;
+
+    if (pos < 0 || len < 0 || pos + len > FLASH_MAX_POS(dev)) {
+	printf("flashWrite: Position out of range "
+	       "(dev: %d, pos: 0x%x, len: 0x%x)\n",
+	       DEV_NO(dev), pos, len);
+	return ERROR;
+    }
+
+    if (len == 0)
+	return OK;
+
+    if (dev->bank == FLASH0_BANK) {
+	unsigned char tmp;
+
+	addr = pos;
+	words = len;
+
+	while (words--) {
+	    tmp = *buf;
+	    if (~FLASH0_READ(dev, addr) & tmp) {
+		printf("flashWrite: Attempt to program 0 to 1 "
+		       "(dev: %d, addr: 0x%x, data: 0x%x)\n",
+		       DEV_NO(dev), addr, tmp);
+		return ERROR;
+	    }
+	    FLASH0_WRITE(dev, 0xaaa, 0xaa);
+	    FLASH0_WRITE(dev, 0x555, 0x55);
+	    FLASH0_WRITE(dev, 0xaaa, 0xa0);
+	    FLASH0_WRITE(dev, addr, tmp);
+	    if (flashWait(dev, addr, tmp, 0) < 0)
+		return ERROR;
+	    buf++;
+	    addr++;
+	}
+    }
+
+    PRINTF("flashWrite: rv=OK\n");
+
+    return OK;
+}
+
+/*
+ * flashWritable returns TRUE if a range contains all F's.
+ */
+
+STATUS flashWritable(flash_dev_t *dev, int pos, int len)
+{
+    int 		addr, words;
+    int			rv = ERROR;
+
+    PRINTF("flashWritable: dev=%d pos=0x%x len=0x%x\n",
+	   DEV_NO(dev), pos, len);
+
+    if (flashCheck(dev) == ERROR)
+	goto done;
+
+    if (pos < 0 || len < 0 || pos + len > FLASH_MAX_POS(dev)) {
+	printf("flashWritable: Position out of range "
+	       "(dev: %d, pos: 0x%x, len: 0x%x)\n",
+	       DEV_NO(dev), pos, len);
+	goto done;
+    }
+
+    if (len == 0) {
+	rv = 1;
+	goto done;
+    }
+
+    if (dev->bank == FLASH0_BANK) {
+	addr = pos;
+	words = len;
+
+	while (words--) {
+	    if (FLASH0_READ(dev, addr) != 0xff) {
+		rv = 0;
+		goto done;
+	    }
+	    addr++;
+	}
+    }
+
+    rv = 1;
+
+ done:
+    PRINTF("flashWrite: rv=%d\n", rv);
+    return rv;
+}
+
+
+/*
+ * NOTE: the below code cannot run from FLASH!!!
+ */
+/***********************************************************************
+ *
+ * Flash Diagnostics
+ *
+ ***********************************************************************/
+
+STATUS flashDiag(flash_dev_t *dev)
+{
+    unsigned int	*buf = 0;
+    int			i, len, sector;
+    int			rv = ERROR;
+
+    if (flashCheck(dev) == ERROR)
+	return ERROR;
+
+    printf("flashDiag: Testing device %d, "
+	   "base: 0x%x, %d sectors @ %d kB = %d kB\n",
+	   DEV_NO(dev), dev->base,
+	   dev->sectors,
+	   1 << (dev->lgSectorSize - 10),
+	   dev->sectors << (dev->lgSectorSize - 10));
+
+    len = 1 << dev->lgSectorSize;
+
+    printf("flashDiag: Erasing\n");
+
+    if (flashErase(dev) == ERROR) {
+	printf("flashDiag: Erase failed\n");
+	goto done;
+    }
+    printf("%d bytes requested ...\n", len);
+    buf = malloc(len);
+    printf("allocated %d bytes ...\n", len);
+    if (buf == 0) {
+	printf("flashDiag: Out of memory\n");
+	goto done;
+    }
+
+    /*
+     * Write unique counting pattern to each sector
+     */
+
+    for (sector = 0; sector < dev->sectors; sector++) {
+	printf("flashDiag: Write sector %d\n", sector);
+
+	for (i = 0; i < len / 4; i++)
+	    buf[i] = sector << 24 | i;
+
+	if (flashWrite(dev,
+		       sector << dev->lgSectorSize,
+		       (char *) buf,
+		       len) == ERROR) {
+	    printf("flashDiag: Write failed (dev: %d, sector: %d)\n",
+		   DEV_NO(dev), sector);
+	    goto done;
+	}
+    }
+
+    /*
+     * Verify
+     */
+
+    for (sector = 0; sector < dev->sectors; sector++) {
+	printf("flashDiag: Verify sector %d\n", sector);
+
+	if (flashRead(dev,
+		      sector << dev->lgSectorSize,
+		      (char *) buf,
+		      len) == ERROR) {
+	    printf("flashDiag: Read failed (dev: %d, sector: %d)\n",
+		   DEV_NO(dev), sector);
+	    goto done;
+	}
+
+	for (i = 0; i < len / 4; i++) {
+	    if (buf[i] != (sector << 24 | i)) {
+		printf("flashDiag: Verify error "
+		       "(dev: %d, sector: %d, offset: 0x%x)\n",
+		       DEV_NO(dev), sector, i);
+		printf("flashDiag: Expected 0x%08x, got 0x%08x\n",
+		       sector << 24 | i, buf[i]);
+
+		goto done;
+	    }
+	}
+    }
+
+    printf("flashDiag: Erasing\n");
+
+    if (flashErase(dev) == ERROR) {
+	printf("flashDiag: Final erase failed\n");
+	goto done;
+    }
+
+    rv = OK;
+
+ done:
+    if (buf)
+	free(buf);
+
+    if (rv == OK)
+	printf("flashDiag: Device %d passed\n", DEV_NO(dev));
+    else
+	printf("flashDiag: Device %d failed\n", DEV_NO(dev));
+
+    return rv;
+}
+
+STATUS flashDiagAll(void)
+{
+    int			i;
+    int			rv = OK;
+
+    PRINTF("flashDiagAll: devices=%d\n", flashDevCount);
+
+    for (i = 0; i < flashDevCount; i++) {
+	flash_dev_t	*dev = &flashDev[i];
+
+	if (dev->found && flashDiag(dev) == ERROR)
+	    rv = ERROR;
+    }
+
+    if (rv == OK)
+	printf("flashDiagAll: Passed\n");
+    else
+	printf("flashDiagAll: Failed because of earlier errors\n");
+
+    return OK;
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+    unsigned long size = 0;
+    flash_dev_t	*dev = NULL;
+    flashLibInit();
+
+    /*
+     * Provide info for FLASH (up to 960K) of Kernel Image data.
+     */
+    dev = FLASH_DEV_BANK0_LOW;
+    flash_info[FLASH_BANK_KERNEL].flash_id =
+      (dev->vendorID << 16) | dev->deviceID;
+    flash_info[FLASH_BANK_KERNEL].sector_count = dev->sectors;
+    flash_info[FLASH_BANK_KERNEL].size =
+      flash_info[FLASH_BANK_KERNEL].sector_count * FLASH_SECTOR_SIZE;
+    flash_info[FLASH_BANK_KERNEL].start[FIRST_SECTOR] = dev->base;
+    size += flash_info[FLASH_BANK_KERNEL].size;
+
+    /*
+     * Provide info for 512K PLCC FLASH ROM (U-Boot)
+     */
+    dev = FLASH_DEV_BANK0_BOOT;
+    flash_info[FLASH_BANK_BOOT].flash_id =
+      (dev->vendorID << 16) | dev->deviceID;
+    flash_info[FLASH_BANK_BOOT].sector_count = dev->sectors;
+    flash_info[FLASH_BANK_BOOT].size =
+      flash_info[FLASH_BANK_BOOT].sector_count * FLASH_SECTOR_SIZE;
+    flash_info[FLASH_BANK_BOOT].start[FIRST_SECTOR] = dev->base;
+    size += flash_info[FLASH_BANK_BOOT].size;
+
+
+    /*
+     * Provide info for 512K FLASH0 segment (U-Boot)
+     */
+    dev = FLASH_DEV_BANK0_HIGH;
+    flash_info[FLASH_BANK_AUX].flash_id =
+      (dev->vendorID << 16) | dev->deviceID;
+    flash_info[FLASH_BANK_AUX].sector_count = dev->sectors;
+    flash_info[FLASH_BANK_AUX].size =
+      flash_info[FLASH_BANK_AUX].sector_count * FLASH_SECTOR_SIZE;
+    flash_info[FLASH_BANK_AUX].start[FIRST_SECTOR] = dev->base;
+    size += flash_info[FLASH_BANK_AUX].size;
+
+
+    return  size;
+}
+
+/*
+ * Get flash device from U-Boot flash info.
+ */
+flash_dev_t*
+getFlashDevFromInfo(flash_info_t* info)
+{
+  int i;
+
+  if(!info)
+    return NULL;
+
+  for (i = 0; i < flashDevCount; i++) {
+    flash_dev_t	*dev = &flashDev[i];
+    if(dev->found && (dev->base == info->start[0]))
+      return dev;
+  }
+  printf("ERROR: notice, no FLASH mapped at address 0x%x\n",
+	 (unsigned int)info->start[0]);
+  return NULL;
+}
+
+ulong
+flash_get_size (vu_long *addr, flash_info_t *info)
+{
+    int i;
+    for(i = 0; i < flashDevCount; i++) {
+      flash_dev_t	*dev = &flashDev[i];
+      if(dev->found){
+	if(dev->base == (unsigned int)addr){
+	  info->flash_id = (dev->vendorID << 16) | dev->deviceID;
+	  info->sector_count = dev->sectors;
+	  info->size = info->sector_count * FLASH_SECTOR_SIZE;
+	  return dev->sectors * FLASH_SECTOR_SIZE;
+	}
+      }
+    }
+    return 0;
+}
+
+void
+flash_print_info  (flash_info_t *info)
+{
+  int i;
+  unsigned int chip;
+
+    if (info->flash_id == FLASH_UNKNOWN) {
+	printf ("missing or unknown FLASH type\n");
+	return;
+    }
+
+    switch ((info->flash_id >> 16) & 0xff) {
+    case 0x1:
+	printf ("AMD ");
+	break;
+    default:
+	printf ("Unknown Vendor ");
+	break;
+    }
+    chip = (unsigned int) info->flash_id & 0x000000ff;
+
+    switch (chip) {
+
+    case AMD_ID_F040B:
+	printf ("AM29F040B (4 Mbit)\n");
+	break;
+
+    case AMD_ID_LV160B:
+    case FLASH_AM160LV:
+    case 0x49:
+	printf ("AM29LV160B (16 Mbit / 2M x 8bit)\n");
+	break;
+
+    default:
+      printf ("Unknown Chip Type:0x%x\n", chip);
+	break;
+    }
+
+    printf ("  Size: %ld bytes 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[FIRST_SECTOR] + i*FLASH_SECTOR_SIZE,
+		info->protect[i] ? " (RO)" : "     "
+		);
+    }
+    printf ("\n");
+}
+
+
+/*
+ * Erase a range of flash sectors.
+ */
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+    vu_long *addr = (vu_long*)(info->start[0]);
+    int prot, sect, l_sect;
+    flash_dev_t* dev = NULL;
+
+    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;
+
+    /* Start erase on unprotected sectors */
+    dev = getFlashDevFromInfo(info);
+    if(dev){
+      printf("Erase FLASH[%s] -%d sectors:", dev->name, dev->sectors);
+      for (sect = s_first; sect<=s_last; sect++) {
+	if (info->protect[sect] == 0) {	/* not protected */
+	  addr = (vu_long*)(dev->base);
+	  /*   printf("erase_sector: sector=%d, addr=0x%x\n",
+	       sect, addr); */
+	  printf(".");
+	  if(ERROR == flashEraseSector(dev, sect)){
+	    printf("ERROR: could not erase sector %d on FLASH[%s]\n",
+		   sect, dev->name);
+	    return 1;
+	  }
+	}
+      }
+    }
+    printf (" done\n");
+    return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * 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)
+{
+
+  flash_dev_t* dev = getFlashDevFromInfo(info);
+  int addr = dest - info->start[0];
+
+  if (! dev)
+    return 1;
+
+  if(OK != flashWrite(dev, addr, (char*)&data, sizeof(ulong))){
+    printf("ERROR: could not write to addr=0x%x, data=0x%x\n",
+	   (unsigned int)addr, (unsigned)data);
+    return 1;
+  }
+
+  if((addr % FLASH_SECTOR_SIZE) == 0)
+    printf(".");
+
+
+  PRINTF("write_word:0x%x, base=0x%x, addr=0x%x, data=0x%x\n",
+	 (unsigned)info->start[0],
+	 (unsigned)dest,
+	 (unsigned)(dest - info->start[0]),
+	 (unsigned)data);
+
+
+
+    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;
+    flash_dev_t* dev = getFlashDevFromInfo(info);
+
+    if( dev ) {
+      printf("FLASH[%s]:", dev->name);
+      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));
+    }
+    return 1;
+}
+
+/*-----------------------------------------------------------------------
+ */

+ 323 - 0
board/mousse/m48t59y.c

@@ -0,0 +1,323 @@
+/*
+ * SGS M48-T59Y TOD/NVRAM Driver
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 1999, by Curt McDowell, 08-06-99, Broadcom Corp.
+ *
+ * (C) Copyright 2001, James Dougherty, 07/18/01, Broadcom Corp.
+ *
+ * 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
+ */
+
+/*
+ * SGS M48-T59Y TOD/NVRAM Driver
+ *
+ * The SGS M48 an 8K NVRAM starting at offset M48_BASE_ADDR and
+ * continuing for 8176 bytes. After that starts the Time-Of-Day (TOD)
+ * registers which are used to set/get the internal date/time functions.
+ *
+ * This module implements Y2K compliance by taking full year numbers
+ * and translating back and forth from the TOD 2-digit year.
+ *
+ * NOTE: for proper interaction with an operating system, the TOD should
+ * be used to store Universal Coordinated Time (GMT) and timezone
+ * conversions should be used.
+ *
+ * Here is a diagram of the memory layout:
+ *
+ * +---------------------------------------------+ 0xffe0a000
+ * | Non-volatile memory                         | .
+ * |                                             | .
+ * | (8176 bytes of Non-volatile memory)         | .
+ * |                                             | .
+ * +---------------------------------------------+ 0xffe0bff0
+ * | Flags                                       |
+ * +---------------------------------------------+ 0xffe0bff1
+ * | Unused                                      |
+ * +---------------------------------------------+ 0xffe0bff2
+ * | Alarm Seconds                               |
+ * +---------------------------------------------+ 0xffe0bff3
+ * | Alarm Minutes                               |
+ * +---------------------------------------------+ 0xffe0bff4
+ * | Alarm Date                                  |
+ * +---------------------------------------------+ 0xffe0bff5
+ * | Interrupts                                  |
+ * +---------------------------------------------+ 0xffe0bff6
+ * | WatchDog                                    |
+ * +---------------------------------------------+ 0xffe0bff7
+ * | Calibration                                 |
+ * +---------------------------------------------+ 0xffe0bff8
+ * | Seconds                                     |
+ * +---------------------------------------------+ 0xffe0bff9
+ * | Minutes                                     |
+ * +---------------------------------------------+ 0xffe0bffa
+ * | Hours                                       |
+ * +---------------------------------------------+ 0xffe0bffb
+ * | Day                                         |
+ * +---------------------------------------------+ 0xffe0bffc
+ * | Date                                        |
+ * +---------------------------------------------+ 0xffe0bffd
+ * | Month                                       |
+ * +---------------------------------------------+ 0xffe0bffe
+ * | Year (2 digits only)                        |
+ * +---------------------------------------------+ 0xffe0bfff
+ */
+#include <common.h>
+#include <rtc.h>
+#include "mousse.h"
+
+/*
+ * Imported from mousse.h:
+ *
+ *   TOD_REG_BASE		Base of m48t59y TOD registers
+ *   SYS_TOD_UNPROTECT()	Disable NVRAM write protect
+ *   SYS_TOD_PROTECT()		Re-enable NVRAM write protect
+ */
+
+#define YEAR		0xf
+#define MONTH		0xe
+#define DAY		0xd
+#define DAY_OF_WEEK	0xc
+#define HOUR		0xb
+#define MINUTE		0xa
+#define SECOND		0x9
+#define CONTROL		0x8
+#define WATCH		0x7
+#define INTCTL		0x6
+#define WD_DATE		0x5
+#define WD_HOUR		0x4
+#define WD_MIN		0x3
+#define WD_SEC		0x2
+#define _UNUSED		0x1
+#define FLAGS		0x0
+
+#define M48_ADDR	((volatile unsigned char *) TOD_REG_BASE)
+
+int m48_tod_init(void)
+{
+    SYS_TOD_UNPROTECT();
+
+    M48_ADDR[CONTROL] = 0;
+    M48_ADDR[WATCH] = 0;
+    M48_ADDR[INTCTL] = 0;
+
+    /*
+     * If the oscillator is currently stopped (as on a new part shipped
+     * from the factory), start it running.
+     *
+     * Here is an example of the TOD bytes on a brand new M48T59Y part:
+     *		00 00 00 00 00 00 00 00 00 88 8c c3 bf c8 f5 01
+     */
+
+    if (M48_ADDR[SECOND] & 0x80)
+	M48_ADDR[SECOND] = 0;
+
+    /* Is battery low */
+    if ( M48_ADDR[FLAGS] & 0x10) {
+	 printf("NOTICE: Battery low on Real-Time Clock (replace SNAPHAT).\n");
+    }
+
+    SYS_TOD_PROTECT();
+
+    return 0;
+}
+
+/*
+ * m48_tod_set
+ */
+
+static int to_bcd(int value)
+{
+    return value / 10 * 16 + value % 10;
+}
+
+static int from_bcd(int value)
+{
+    return value / 16 * 10 + value % 16;
+}
+
+static int day_of_week(int y, int m, int d)	/* 0-6 ==> Sun-Sat */
+{
+    static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
+    y -= m < 3;
+    return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
+}
+
+/*
+ * Note: the TOD should store the current GMT
+ */
+
+int m48_tod_set(int year,		/* 1980-2079 */
+		int month,		/* 01-12 */
+		int day,		/* 01-31 */
+		int hour,		/* 00-23 */
+		int minute,		/* 00-59 */
+		int second)		/* 00-59 */
+
+{
+    SYS_TOD_UNPROTECT();
+
+    M48_ADDR[CONTROL] |= 0x80;	/* Set WRITE bit */
+
+    M48_ADDR[YEAR] = to_bcd(year % 100);
+    M48_ADDR[MONTH] = to_bcd(month);
+    M48_ADDR[DAY] = to_bcd(day);
+    M48_ADDR[DAY_OF_WEEK] = day_of_week(year, month, day) + 1;
+    M48_ADDR[HOUR] = to_bcd(hour);
+    M48_ADDR[MINUTE] = to_bcd(minute);
+    M48_ADDR[SECOND] = to_bcd(second);
+
+    M48_ADDR[CONTROL] &= ~0x80;	/* Clear WRITE bit */
+
+    SYS_TOD_PROTECT();
+
+    return 0;
+}
+
+/*
+ * Note: the TOD should store the current GMT
+ */
+
+int m48_tod_get(int *year,		/* 1980-2079 */
+		int *month,		/* 01-12 */
+		int *day,		/* 01-31 */
+		int *hour,		/* 00-23 */
+		int *minute,		/* 00-59 */
+		int *second)		/* 00-59 */
+{
+    int y;
+
+    SYS_TOD_UNPROTECT();
+
+    M48_ADDR[CONTROL] |= 0x40;	/* Set READ bit */
+
+    y = from_bcd(M48_ADDR[YEAR]);
+    *year = y < 80 ? 2000 + y : 1900 + y;
+    *month = from_bcd(M48_ADDR[MONTH]);
+    *day = from_bcd(M48_ADDR[DAY]);
+    /* day_of_week = M48_ADDR[DAY_OF_WEEK] & 0xf; */
+    *hour = from_bcd(M48_ADDR[HOUR]);
+    *minute = from_bcd(M48_ADDR[MINUTE]);
+    *second = from_bcd(M48_ADDR[SECOND] & 0x7f);
+
+    M48_ADDR[CONTROL] &= ~0x40;	/* Clear READ bit */
+
+    SYS_TOD_PROTECT();
+
+    return 0;
+}
+
+int m48_tod_get_second(void)
+{
+    return from_bcd(M48_ADDR[SECOND] & 0x7f);
+}
+
+/*
+ * Watchdog function
+ *
+ *  If usec is 0, the watchdog timer is disarmed.
+ *
+ *  If usec is non-zero, the watchdog timer is armed (or re-armed) for
+ *    approximately usec microseconds (if the exact requested usec is
+ *    not supported by the chip, the next higher available value is used).
+ *
+ *  Minimum watchdog timeout = 62500 usec
+ *  Maximum watchdog timeout = 124 sec (124000000 usec)
+ */
+
+void m48_watchdog_arm(int usec)
+{
+    int		mpy, res;
+
+    SYS_TOD_UNPROTECT();
+
+    if (usec == 0) {
+	res = 0;
+	mpy = 0;
+    } else if (usec < 2000000) {	/* Resolution: 1/16s if below 2s */
+	res = 0;
+	mpy = (usec + 62499) / 62500;
+    } else if (usec < 8000000) {	/* Resolution: 1/4s if below 8s */
+	res = 1;
+	mpy = (usec + 249999) / 250000;
+    } else if (usec < 32000000) {	/* Resolution: 1s if below 32s */
+	res = 2;
+	mpy = (usec + 999999) / 1000000;
+    } else {				/* Resolution: 4s up to 124s */
+	res = 3;
+	mpy = (usec + 3999999) / 4000000;
+	if (mpy > 31)
+	    mpy = 31;
+    }
+
+    M48_ADDR[WATCH] = (0x80 |		/* Steer to RST signal (IRQ = N/C) */
+		       mpy << 2 |
+		       res);
+
+    SYS_TOD_PROTECT();
+}
+
+/*
+ * U-Boot RTC support.
+ */
+void
+rtc_get( struct rtc_time *tmp )
+{
+	m48_tod_get(&tmp->tm_year,
+		    &tmp->tm_mon,
+		    &tmp->tm_mday,
+		    &tmp->tm_hour,
+		    &tmp->tm_min,
+		    &tmp->tm_sec);
+	tmp->tm_yday = 0;
+	tmp->tm_isdst= 0;
+
+#ifdef RTC_DEBUG
+	printf( "Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+		tmp->tm_hour, tmp->tm_min, tmp->tm_sec );
+#endif
+}
+
+void
+rtc_set( struct rtc_time *tmp )
+{
+	m48_tod_set(tmp->tm_year,		/* 1980-2079 */
+		    tmp->tm_mon,		/* 01-12 */
+		    tmp->tm_mday,              /* 01-31 */
+		    tmp->tm_hour,		/* 00-23 */
+		    tmp->tm_min,		/* 00-59 */
+		    tmp->tm_sec);		/* 00-59 */
+
+#ifdef RTC_DEBUG
+	printf( "Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+#endif
+
+}
+
+void
+rtc_reset (void)
+{
+  m48_tod_init();
+}
+

+ 377 - 0
board/pm826/flash.c

@@ -0,0 +1,377 @@
+/*
+ * (C) Copyright 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for Intel 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_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+/*-----------------------------------------------------------------------
+ */
+ulong flash_get_size (volatile unsigned long *baseaddr,
+					  flash_info_t * info)
+{
+	short i;
+	unsigned long flashtest_h, flashtest_l;
+
+	info->sector_count = info->size = 0;
+	info->flash_id = FLASH_UNKNOWN;
+
+	/* Write query command sequence and test FLASH answer
+	 */
+	baseaddr[0] = 0x00980098;
+	baseaddr[1] = 0x00980098;
+
+	flashtest_h = baseaddr[0];	/* manufacturer ID	*/
+	flashtest_l = baseaddr[1];
+
+	if (flashtest_h != INTEL_MANUFACT || flashtest_l != INTEL_MANUFACT)
+		return (0);		/* no or unknown flash	*/
+
+	flashtest_h = baseaddr[2];	/* device ID	        */
+	flashtest_l = baseaddr[3];
+
+	if (flashtest_h != flashtest_l)
+		return (0);
+
+	switch (flashtest_h) {
+	case INTEL_ID_28F160C3B:
+		info->flash_id = FLASH_28F160C3B;
+		info->sector_count = 39;
+		info->size = 0x00800000;	/* 4 * 2 MB = 8 MB	*/
+		break;
+	case INTEL_ID_28F160F3B:
+		info->flash_id = FLASH_28F160F3B;
+		info->sector_count = 39;
+		info->size = 0x00800000;	/* 4 * 2 MB = 8 MB      */
+		break;
+	default:
+		return (0);			/* no or unknown flash	*/
+	}
+
+	info->flash_id |= INTEL_MANUFACT << 16; /* set manufacturer offset */
+
+	if (info->flash_id & FLASH_BTYPE) {
+		volatile unsigned long *tmp = baseaddr;
+
+		/* set up sector start adress table (bottom sector type)
+		 * AND unlock the sectors (if our chip is 160C3)
+		 */
+		for (i = 0; i < info->sector_count; i++) {
+			if ((info->flash_id & FLASH_TYPEMASK) == FLASH_28F160C3B) {
+				tmp[0] = 0x00600060;
+				tmp[1] = 0x00600060;
+				tmp[0] = 0x00D000D0;
+				tmp[1] = 0x00D000D0;
+			}
+			info->start[i] = (uint) tmp;
+			tmp += i < 8 ? 0x2000 : 0x10000; /* pointer arith       */
+		}
+	}
+
+	memset (info->protect, 0, info->sector_count);
+
+	baseaddr[0] = 0x00FF00FF;
+	baseaddr[1] = 0x00FF00FF;
+
+	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 ((ulong *) 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
+	 */
+
+#ifndef CONFIG_BOOT_ROM
+	/* If U-Boot is  booted from ROM the CFG_MONITOR_BASE > CFG_FLASH0_BASE
+	 * but we shouldn't protect it.
+	 */
+
+# 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
+#endif	/* CONFIG_BOOT_ROM */
+
+#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 0x89:
+		printf ("INTEL ");
+		break;
+	default:
+		printf ("Unknown Vendor ");
+		break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FLASH_28F160C3B:
+		printf ("28F160C3B (16 M, bottom sector)\n");
+		break;
+	case FLASH_28F160F3B:
+		printf ("28F160F3B (16 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");
+}
+
+/*-----------------------------------------------------------------------
+ */
+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;
+	}
+
+	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 erase on unprotected sectors
+	 */
+	for (sect = s_first; sect <= s_last; sect++) {
+		volatile ulong *addr =
+				(volatile unsigned long *) info->start[sect];
+
+		start = get_timer (0);
+		last = start;
+		if (info->protect[sect] == 0) {
+			/* Disable interrupts which might cause a timeout here
+			 */
+			flag = disable_interrupts ();
+
+			/* Erase the block
+			 */
+			addr[0] = 0x00200020;
+			addr[1] = 0x00200020;
+			addr[0] = 0x00D000D0;
+			addr[1] = 0x00D000D0;
+
+			/* re-enable interrupts if necessary
+			 */
+			if (flag)
+				enable_interrupts ();
+
+			/* wait at least 80us - let's wait 1 ms
+			 */
+			udelay (1000);
+
+			last = start;
+			while ((addr[0] & 0x00800080) != 0x00800080 ||
+				   (addr[1] & 0x00800080) != 0x00800080) {
+				if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
+					printf ("Timeout (erase suspended!)\n");
+					/* Suspend erase
+					 */
+					addr[0] = 0x00B000B0;
+					addr[1] = 0x00B000B0;
+					goto DONE;
+				}
+				/* show that we're waiting
+				 */
+				if ((now - last) > 1000) {	/* every second */
+					serial_putc ('.');
+					last = now;
+				}
+			}
+			if (addr[0] & 0x00220022 || addr[1] & 0x00220022) {
+				printf ("*** ERROR: erase failed!\n");
+				goto DONE;
+			}
+		}
+		/* Clear status register and reset to read mode
+		 */
+		addr[0] = 0x00500050;
+		addr[1] = 0x00500050;
+		addr[0] = 0x00FF00FF;
+		addr[1] = 0x00FF00FF;
+	}
+
+	printf (" done\n");
+
+DONE:
+	return 0;
+}
+
+static int write_word (flash_info_t *, volatile unsigned long *, ulong);
+
+/*-----------------------------------------------------------------------
+ * 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 v;
+	int i, l, cc = cnt, res = 0;
+
+
+	for (v=0; cc > 0; addr += 4, cc -= 4 - l) {
+		l = (addr & 3);
+		addr &= ~3;
+
+		for (i = 0; i < 4; i++) {
+			v = (v << 8) + (i < l || i - l >= cc ?
+				*((unsigned char *) addr + i) : *src++);
+		}
+
+		if ((res = write_word (info, (volatile unsigned long *) addr, v)) != 0)
+			break;
+	}
+
+	return (res);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t * info, volatile unsigned long *addr,
+					   ulong data)
+{
+	int flag, res = 0;
+	ulong start;
+
+	/* Check if Flash is (sufficiently) erased
+	 */
+	if ((*addr & data) != data)
+		return (2);
+
+	/* Disable interrupts which might cause a timeout here
+	 */
+	flag = disable_interrupts ();
+
+	*addr = 0x00400040;
+	*addr = data;
+
+	/* re-enable interrupts if necessary
+	 */
+	if (flag)
+		enable_interrupts ();
+
+	start = get_timer (0);
+	while ((*addr & 0x00800080) != 0x00800080) {
+		if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
+			/* Suspend program
+			 */
+			*addr = 0x00B000B0;
+			res = 1;
+			goto OUT;
+		}
+	}
+
+	if (*addr & 0x00220022) {
+		printf ("*** ERROR: program failed!\n");
+		res = 1;
+	}
+
+OUT:
+	/* Clear status register and reset to read mode
+	 */
+	*addr = 0x00500050;
+	*addr = 0x00FF00FF;
+
+	return (res);
+}

+ 523 - 0
board/sacsng/flash.c

@@ -0,0 +1,523 @@
+/*
+ * (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 <configs/sacsng.h>
+
+
+#undef  DEBUG
+
+#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
+
+
+flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_short *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_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_short *)CFG_FLASH0_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_b0, size_b0<<20);
+	}
+
+	size_b1 = flash_get_size((vu_short *)CFG_FLASH1_BASE, &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[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) {
+#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 {
+		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;
+
+	/*
+	 * We only report the primary flash for U-Boot's use.
+	 */
+	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_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_short *addr, flash_info_t *info)
+{
+	short i;
+	ushort value;
+	ulong  base = (ulong)addr;
+
+	/* Write auto select command: read Manufacturer ID */
+	addr[0x0555] = 0xAAAA;
+	addr[0x02AA] = 0x5555;
+	addr[0x0555] = 0x9090;
+	__asm__ __volatile__(" sync\n ");
+
+	value = addr[0];
+#ifdef DEBUG
+	printf("Flash manufacturer 0x%04X\n", value);
+#endif
+
+	if(value == (ushort)AMD_MANUFACT) {
+		info->flash_id = FLASH_MAN_AMD;
+	} else if (value == (ushort)FUJ_MANUFACT) {
+		info->flash_id = FLASH_MAN_FUJ;
+	} else {
+#ifdef DEBUG
+		printf("Unknown flash manufacturer 0x%04X\n", value);
+#endif
+		info->flash_id = FLASH_UNKNOWN;
+		info->sector_count = 0;
+		info->size = 0;
+		return (0);			/* no or unknown flash	*/
+	}
+
+	value = addr[1];			/* device ID		*/
+#ifdef DEBUG
+	printf("Flash type 0x%04X\n", value);
+#endif
+
+	if(value == (ushort)AMD_ID_LV400T) {
+		info->flash_id += FLASH_AM400T;
+		info->sector_count = 11;
+		info->size = 0x00080000;	/* => 0.5 MB		*/
+	} else if(value == (ushort)AMD_ID_LV400B) {
+		info->flash_id += FLASH_AM400B;
+		info->sector_count = 11;
+		info->size = 0x00080000;	/* => 0.5 MB		*/
+	} else if(value == (ushort)AMD_ID_LV800T) {
+		info->flash_id += FLASH_AM800T;
+		info->sector_count = 19;
+		info->size = 0x00100000;	/* => 1 MB		*/
+	} else if(value == (ushort)AMD_ID_LV800B) {
+		info->flash_id += FLASH_AM800B;
+		info->sector_count = 19;
+		info->size = 0x00100000;	/* => 1 MB		*/
+	} else if(value == (ushort)AMD_ID_LV160T) {
+		info->flash_id += FLASH_AM160T;
+		info->sector_count = 35;
+		info->size = 0x00200000;	/* => 2 MB		*/
+	} else if(value == (ushort)AMD_ID_LV160B) {
+		info->flash_id += FLASH_AM160B;
+		info->sector_count = 35;
+		info->size = 0x00200000;	/* => 2 MB		*/
+	} else if(value == (ushort)AMD_ID_LV320T) {
+		info->flash_id += FLASH_AM320T;
+		info->sector_count = 67;
+		info->size = 0x00400000;	/* => 4 MB		*/
+	} else if(value == (ushort)AMD_ID_LV320B) {
+		info->flash_id += FLASH_AM320B;
+		info->sector_count = 67;
+		info->size = 0x00400000;	/* => 4 MB		*/
+	} else {
+#ifdef DEBUG
+		printf("Unknown flash type 0x%04X\n", value);
+		info->size = CFG_FLASH_SIZE;
+#else
+		info->flash_id = FLASH_UNKNOWN;
+		return (0);			/* => no or unknown flash */
+#endif
+	}
+
+	/* 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 - 3) * 0x00010000);
+		}
+	} 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 */
+		addr = (volatile unsigned short *)(info->start[i]);
+		info->protect[i] = addr[2] & 1;
+	}
+
+	/*
+	 * Prevent writes to uninitialized FLASH.
+	 */
+	if (info->flash_id != FLASH_UNKNOWN) {
+		addr = (volatile unsigned short *)info->start[0];
+
+	}
+
+	addr[0] = 0xF0F0;	/* reset bank */
+	__asm__ __volatile__(" sync\n ");
+	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] = 0xAAAA;
+	addr[0x02AA] = 0x5555;
+	addr[0x0555] = 0x8080;
+	addr[0x0555] = 0xAAAA;
+	addr[0x02AA] = 0x5555;
+	__asm__ __volatile__(" sync\n ");
+
+	/* 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] = 0x3030;
+			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");
+			addr[0] = 0xF0F0;	/* reset bank */
+			__asm__ __volatile__(" sync\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] = 0xF0F0;	/* reset bank */
+	__asm__ __volatile__(" sync\n ");
+
+	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_short *addr = (vu_short*)(info->start[0]);
+	ulong start;
+	int flag;
+	int j;
+
+	/* 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();
+
+	/* The original routine was designed to write 32 bit words to
+	 * 32 bit wide memory.	We have 16 bit wide memory so we do
+	 * two writes.	We write the LSB first at dest+2 and then the
+	 * MSB at dest (lousy big endian).
+	 */
+	dest += 2;
+	for(j = 0; j < 2; j++) {
+		addr[0x0555] = 0xAAAA;
+		addr[0x02AA] = 0x5555;
+		addr[0x0555] = 0xA0A0;
+		__asm__ __volatile__(" sync\n ");
+
+		*((vu_short *)dest) = (ushort)data;
+
+		/* re-enable interrupts if necessary */
+		if (flag)
+			enable_interrupts();
+
+		/* data polling for D7 */
+		start = get_timer (0);
+		while (*(vu_short *)dest != (ushort)data) {
+			if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+				return (1);
+			}
+		}
+		dest -= 2;
+		data >>= 16;
+	}
+	return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */

+ 15 - 0
board/sandpoint/README

@@ -0,0 +1,15 @@
+This port of U-Boot will run on a Motorola Sandpoint 3 development
+system equipped with a Unity X4 PPMC card (MPC8240 CPU) only. It is a
+snapshot of work in progress and far from being completed. In order
+to run it on the target system, it has to be downloaded using the
+DINK32 monitor program that came with your Sandpoint system. Please
+note that DINK32 does not accept the S-Record file created by the
+U-Boot build process unmodified, because it contains CR/LF line
+terminators. You have to strip the CR characters first. There is a
+tiny script named 'dinkdl' I created for this purpose.
+
+The Sandpoint port is based on the work of Rob Taylor, who does not
+seem to maintain it any more. I can be reached by mail as
+tkoeller@gmx.net.
+
+Thomas Koeller

+ 257 - 0
disk/part_iso.c

@@ -0,0 +1,257 @@
+/*
+ * (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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cmd_disk.h>
+#include "part_iso.h"
+
+#if ((CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI)) && defined(CONFIG_ISO_PARTITION)
+
+#undef	ISO_PART_DEBUG
+
+#ifdef	ISO_PART_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* enable this if CDs are written with the PowerPC Platform ID */
+#undef CHECK_FOR_POWERPC_PLATTFORM
+#define CD_SECTSIZE 2048
+
+static unsigned char tmpbuf[CD_SECTSIZE];
+
+/* Convert char[4] in little endian format to the host format integer
+ */
+static inline unsigned long le32_to_int(unsigned char *le32)
+{
+    return ((le32[3] << 24) +
+	    (le32[2] << 16) +
+	    (le32[1] << 8) +
+	     le32[0]
+	   );
+}
+/* Convert char[2] in little endian format to the host format integer
+ */
+static inline unsigned short le16_to_int(unsigned char *le16)
+{
+    return ((le16[1] << 8) +
+	   le16[0]
+	   );
+}
+
+
+/* only boot records will be listed as valid partitions */
+int get_partition_info_iso_verb(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info, int verb)
+{
+	int i,offset,entry_num;
+	unsigned short *chksumbuf;
+	unsigned short chksum;
+	unsigned long newblkaddr,blkaddr,lastsect,bootaddr;
+	iso_boot_rec_t *pbr = (iso_boot_rec_t	*)tmpbuf; /* boot record */
+	iso_pri_rec_t *ppr = (iso_pri_rec_t	*)tmpbuf;	/* primary desc */
+	iso_val_entry_t *pve = (iso_val_entry_t *)tmpbuf;
+	iso_init_def_entry_t *pide;
+
+	/* the first sector (sector 0x10) must be a primary volume desc */
+	blkaddr=PVD_OFFSET;
+	if (dev_desc->block_read (dev_desc->dev, PVD_OFFSET, 1, (ulong *) tmpbuf) != 1)
+   	return (-1);
+	if(ppr->desctype!=0x01) {
+		if(verb)
+			printf ("** First descriptor is NOT a primary desc on %d:%d **\n",
+				dev_desc->dev, part_num);
+		return (-1);
+	}
+	if(strncmp(ppr->stand_ident,"CD001",5)!=0) {
+		if(verb)
+			printf ("** Wrong ISO Ident: %s on %d:%d **\n",
+				ppr->stand_ident,dev_desc->dev, part_num);
+		return (-1);
+	}
+	lastsect= ((ppr->firstsek_LEpathtab1_LE & 0x000000ff)<<24) +
+		  ((ppr->firstsek_LEpathtab1_LE & 0x0000ff00)<< 8) +
+		  ((ppr->firstsek_LEpathtab1_LE & 0x00ff0000)>> 8) +
+		  ((ppr->firstsek_LEpathtab1_LE & 0xff000000)>>24) ;
+	info->blksz=ppr->secsize_BE; /* assuming same block size for all entries */
+	PRINTF(" Lastsect:%08lx\n",lastsect);
+	for(i=blkaddr;i<lastsect;i++) {
+		if (dev_desc->block_read (dev_desc->dev, i, 1, (ulong *) tmpbuf) != 1)
+  	 	return (-1);
+		if(ppr->desctype==0x00)
+			break; /* boot entry found */
+		if(ppr->desctype==0xff) {
+			if(verb)
+				printf ("** No valid boot catalog found on %d:%d **\n",
+					dev_desc->dev, part_num);
+			return (-1);
+		}
+	}
+ 	/* boot entry found */
+	if(strncmp(pbr->ident_str,"EL TORITO SPECIFICATION",23)!=0) {
+		if(verb)
+			printf ("** Wrong El Torito ident: %s on %d:%d **\n",
+				pbr->ident_str,dev_desc->dev, part_num);
+		return (-1);
+	}
+	bootaddr=le32_to_int(pbr->pointer);
+	PRINTF(" Boot Entry at: %08lX\n",bootaddr);
+	if (dev_desc->block_read (dev_desc->dev, bootaddr, 1, (ulong *) tmpbuf) != 1) {
+		if(verb)
+			printf ("** Can't read Boot Entry at %lX on %d:%d **\n",
+				bootaddr,dev_desc->dev, part_num);
+		return (-1);
+	}
+	chksum=0;
+	chksumbuf = (unsigned short *)tmpbuf;
+	for(i=0;i<0x10;i++)
+		chksum+=((chksumbuf[i] &0xff)<<8)+((chksumbuf[i] &0xff00)>>8);
+	if(chksum!=0) {
+		if(verb)
+			printf ("** Checksum Error in booting catalog validation entry on %d:%d **\n",
+				dev_desc->dev, part_num);
+		return (-1);
+	}
+	if((pve->key[0]!=0x55)||(pve->key[1]!=0xAA)) {
+		if(verb)
+			printf ("** Key 0x55 0xAA error on %d:%d **\n",
+				dev_desc->dev, part_num);
+		return(-1);
+	}
+#ifdef CHECK_FOR_POWERPC_PLATTFORM
+	if(pve->platform!=0x01) {
+		if(verb)
+			printf ("** No PowerPC platform CD on %d:%d **\n",
+				dev_desc->dev, part_num);
+		return(-1);
+	}
+#endif
+	/* the validation entry seems to be ok, now search the "partition" */
+	entry_num=0;
+	offset=0x20;
+	sprintf (info->type, "U-Boot");
+	switch(dev_desc->if_type) {
+		case IF_TYPE_IDE:
+		case IF_TYPE_ATAPI:
+			sprintf (info->name, "hd%c%d\n", 'a' + dev_desc->dev, part_num);
+			break;
+		case IF_TYPE_SCSI:
+			sprintf (info->name, "sd%c%d\n", 'a' + dev_desc->dev, part_num);
+			break;
+		case IF_TYPE_USB:
+			sprintf (info->name, "usbd%c%d\n", 'a' + dev_desc->dev, part_num);
+			break;
+		case IF_TYPE_DOC:
+			sprintf (info->name, "docd%c%d\n", 'a' + dev_desc->dev, part_num);
+			break;
+		default:
+			sprintf (info->name, "xx%c%d\n", 'a' + dev_desc->dev, part_num);
+			break;
+	}
+	/* the bootcatalog (including validation Entry) is limited to 2048Bytes
+	 * (63 boot entries + validation entry) */
+	 while(offset<2048) {
+		pide=(iso_init_def_entry_t *)&tmpbuf[offset];
+		if ((pide->boot_ind==0x88) ||
+		    (pide->boot_ind==0x00)) { /* Header Id for default Sections Entries */
+			if(entry_num==part_num) { /* part found */
+				goto found;
+			}
+			entry_num++; /* count partitions Entries (boot and non bootables */
+			offset+=0x20;
+			continue;
+		}
+		if ((pide->boot_ind==0x90) ||	/* Section Header Entry */
+		    (pide->boot_ind==0x91) ||	/* Section Header Entry (last) */
+		    (pide->boot_ind==0x44)) {	/* Extension Indicator */
+			offset+=0x20; /* skip unused entries */
+		}
+		else {
+			if(verb)
+				printf ("** Partition %d not found on device %d **\n",
+					part_num,dev_desc->dev);
+			return(-1);
+		}
+	}
+	/* if we reach this point entire sector has been
+	 * searched w/o succsess */
+	if(verb)
+		printf ("** Partition %d not found on device %d **\n",
+			part_num,dev_desc->dev);
+	return(-1);
+found:
+	if(pide->boot_ind!=0x88) {
+		if(verb)
+			printf ("** Partition %d is not bootable on device %d **\n",
+				part_num,dev_desc->dev);
+		return (-1);
+	}
+	switch(pide->boot_media) {
+		case 0x00: /* no emulation */
+			info->size=le16_to_int(pide->sec_cnt)>>2;
+			break;
+		case 0x01:	info->size=2400>>2; break; /* 1.2MByte Floppy */
+		case 0x02:	info->size=2880>>2; break; /* 1.44MByte Floppy */
+		case 0x03:	info->size=5760>>2; break; /* 2.88MByte Floppy */
+		case 0x04:	info->size=2880>>2; break; /* dummy (HD Emulation) */
+		default:	info->size=0; break;
+	}
+	newblkaddr=le32_to_int(pide->rel_block_addr);
+	info->start=newblkaddr;
+	PRINTF(" part %d found @ %lx size %lx\n",part_num,newblkaddr,info->size);
+	return 0;
+}
+
+int get_partition_info_iso(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info)
+{
+	return(get_partition_info_iso_verb(dev_desc, part_num, info, 1));
+}
+
+
+
+void print_part_iso(block_dev_desc_t * dev_desc)
+{
+	disk_partition_t info;
+	int i;
+	if(get_partition_info_iso_verb(dev_desc,0,&info,0)==-1) {
+		printf("** No boot partition found on device %d **\n",dev_desc->dev);
+		return;
+	}
+	printf("Part   Start     Sect x Size Type\n");
+	i=0;
+	do {
+		printf (" %2d %8ld %8ld %6ld %.32s\n",
+			i, info.start, info.size, info.blksz, info.type);
+		i++;
+	} while (get_partition_info_iso_verb(dev_desc,i,&info,0)!=-1);
+}
+
+int test_part_iso (block_dev_desc_t *dev_desc)
+{
+	disk_partition_t info;
+
+	return(get_partition_info_iso_verb(dev_desc,0,&info,0));
+}
+
+#endif /* ((CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI)) && defined(CONFIG_ISO_PARTITION) */

+ 25 - 0
doc/README.OXC

@@ -0,0 +1,25 @@
+This document contains different information about the port
+of U-Boot for the OXC board designed by Lucent Technologies,
+Inc.
+
+1. Showing activity
+
+U-Boot for the OXC board can show its current status using
+the Active LED. This feature is configured by the following
+options:
+
+CONFIG_SHOW_ACTIVITY
+
+  When this option is on, the Active LED is blinking fast
+when U-Boot runs in the idle loop (i.e. waits for user
+commands from serial console) and blinking slow when it
+downloads an image over network. When U-Boot loads an image
+over serial line the Active LED does not blink and its state
+is random (i.e. either constant on or constant off).
+
+CONFIG_SHOW_BOOT_PROGRESS
+
+  When this option is on, U-Boot switches the Active LED
+off before booting an image and switches it on if booting
+failed due to some reasons.
+

+ 158 - 0
doc/README.autoboot

@@ -0,0 +1,158 @@
+/*
+ * (C) Copyright 2001
+ * Dave Ellis, SIXNET, dge@sixnetio.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
+ */
+
+Using autoboot configuration options
+====================================
+
+The basic autoboot configuration options are documented in the main
+U-Boot README. See it for details. They are:
+
+  bootdelay
+  bootcmd
+  CONFIG_BOOTDELAY
+  CONFIG_BOOTCOMMAND
+
+Some additional options that make autoboot safer in a production
+product are documented here.
+
+Why use them?
+-------------
+
+The basic autoboot feature allows a system to automatically boot to
+the real application (such as Linux) without a user having to enter
+any commands. If any key is pressed before the boot delay time
+expires, U-Boot stops the autoboot process, gives a U-Boot prompt
+and waits forever for a command. That's a good thing if you pressed a
+key because you wanted to get the prompt.
+
+It's not so good if the key press was a stray character on the
+console serial port, say because a user who knows nothing about
+U-Boot pressed a key before the system had time to boot. It's even
+worse on an embedded product that doesn't have a console during
+normal use. The modem plugged into that console port sends a
+character at the wrong time and the system hangs, with no clue as to
+why it isn't working.
+
+You might want the system to autoboot to recover after an external
+configuration program stops autoboot. If the configuration program
+dies or loses its connection (modems can disconnect at the worst
+time) U-Boot will patiently wait forever for it to finish.
+
+These additional configuration options can help provide a system that
+boots when it should, but still allows access to U-Boot.
+
+What they do
+------------
+
+  CONFIG_BOOT_RETRY_TIME
+  CONFIG_BOOT_RETRY_MIN
+
+  bootretry environment variable
+
+        These options determine what happens after autoboot is
+        stopped and U-Boot is waiting for commands.
+
+        CONFIG_BOOT_RETRY_TIME must be defined to enable the boot
+        retry feature. If the environment variable 'bootretry' is
+        found then its value is used, otherwise the retry timeout is
+        CONFIG_BOOT_RETRY_TIME. CONFIG_BOOT_RETRY_MIN is optional and
+        defaults to CONFIG_BOOT_RETRY_TIME. All times are in seconds.
+
+        If the retry timeout is negative, the U-Boot command prompt
+        never times out. Otherwise it is forced to be at least
+        CONFIG_BOOT_RETRY_MIN seconds. If no valid U-Boot command is
+        entered before the specified time the boot delay sequence is
+        restarted. Each command that U-Boot executes restarts the
+        timeout.
+
+        If CONFIG_BOOT_RETRY_TIME < 0 the feature is there, but
+        doesn't do anything unless the environment variable
+        'bootretry' is >= 0.
+
+  CONFIG_AUTOBOOT_KEYED
+  CONFIG_AUTOBOOT_PROMPT
+  CONFIG_AUTOBOOT_DELAY_STR
+  CONFIG_AUTOBOOT_STOP_STR
+  CONFIG_AUTOBOOT_DELAY_STR2
+  CONFIG_AUTOBOOT_STOP_STR2
+
+  bootdelaykey	environment variable
+  bootstopkey	environment variable
+  bootdelaykey2	environment variable
+  bootstopkey2	environment variable
+
+        These options give more control over stopping autoboot. When
+        they are used a specific character or string is required to
+        stop or delay autoboot.
+
+	Define CONFIG_AUTOBOOT_KEYED (no value required) to enable
+	this group of options.  CONFIG_AUTOBOOT_DELAY_STR,
+	CONFIG_AUTOBOOT_STOP_STR or both should be specified (or
+	specified by the corresponding environment variable),
+	otherwise there is no way to stop autoboot.
+
+        CONFIG_AUTOBOOT_PROMPT is displayed before the boot delay
+        selected by CONFIG_BOOTDELAY starts. If it is not defined
+        there is no output indicating that autoboot is in progress.
+        If "%d" is included, it is replaced by the number of seconds
+        remaining before autoboot will start, but it does not count
+        down the seconds. "autoboot in %d seconds\n" is a reasonable
+        prompt.
+
+        If CONFIG_AUTOBOOT_DELAY_STR or bootdelaykey is specified and
+        this string is received from console input before autoboot
+        starts booting, U-Boot gives a command prompt. The U-Boot
+        prompt will time out if CONFIG_BOOT_RETRY_TIME is used,
+        otherwise it never times out.
+
+        If CONFIG_AUTOBOOT_STOP_STR or bootstopkey is specified and
+        this string is received from console input before autoboot
+        starts booting, U-Boot gives a command prompt. The U-Boot
+        prompt never times out, even if CONFIG_BOOT_RETRY_TIME is
+        used.
+
+        The string recognition is not very sophisticated. If a
+        partial match is detected, the first non-matching character
+        is checked to see if starts a new match. There is no check
+        for a shorter partial match, so it's best if the first
+        character of a key string does not appear in the rest of the
+        string.
+
+        Using the CONFIG_AUTOBOOT_DELAY_STR2 /  bootdelaykey2  and/or
+        CONFIG_AUTOBOOT_STOP_STR2   /   bootstopkey  #defines  and/or
+        environment variables you can  specify  a  second,  alternate
+        string (which allows you to haw two "password" strings).
+
+  CONFIG_ZERO_BOOTDELAY_CHECK
+
+        If this option is defined, you can stop the autoboot process
+        by hitting a key even in that case when "bootdelay" has been
+        set to 0. You can set "bootdelay" to a negative value to
+        prevent the check for console input.
+
+  CONFIG_RESET_TO_RETRY
+
+        (Only effective when CONFIG_BOOT_RETRY_TIME is also set)
+        After the countdown timed out, the board will be reset to restart
+        again.
+

+ 118 - 0
doc/README.console

@@ -0,0 +1,118 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ *
+ * 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
+ */
+
+U-Boot console handling
+========================
+
+HOW THE CONSOLE WORKS?
+----------------------
+
+At system startup U-Boot initializes a serial console. When U-Boot
+relocates itself to RAM, all console drivers are initialized (they
+will register all detected console devices to the system for further
+use).
+
+If not defined in the environment, the first input device is assigned
+to the 'stdin' file, the first output one to 'stdout' and 'stderr'.
+
+You can use the command "coninfo" to see all registered console
+devices and their flags. You can assign a standard file (stdin,
+stdout or stderr) to any device you see in that list simply by
+assigning its name to the corresponding environment variable. For
+example:
+
+    setenv stdin wl_kbd		<- To use the wireless keyboard
+    setenv stdout video		<- To use the video console
+
+Do a simple "saveenv" to save the console settings in the environment
+and get them working on the next startup, too.
+
+HOW CAN I USE STANDARD FILE INTO THE SOURCES?
+---------------------------------------------
+
+You can use the following functions to access the console:
+
+* STDOUT:
+    putc	(to put a char to stdout)
+    puts	(to put a string to stdout)
+    printf	(to format and put a string to stdout)
+
+* STDIN:
+    tstc	(to test for the presence of a char in stdin)
+    getc	(to get a char from stdin)
+
+* STDERR:
+    eputc	(to put a char to stderr)
+    eputs	(to put a string to stderr)
+    eprintf	(to format and put a string to stderr)
+
+* FILE (can be 'stdin', 'stdout', 'stderr'):
+    fputc	(like putc but redirected to a file)
+    fputs	(like puts but redirected to a file)
+    fprintf	(like printf but redirected to a file)
+    ftstc	(like tstc but redirected to a file)
+    fgetc	(like getc but redirected to a file)
+
+Remember that all FILE-related functions CANNOT be used before
+U-Boot relocation (done in 'board_init_r' in common/board.c).
+
+HOW CAN I USE STANDARD FILE INTO APPLICATIONS?
+----------------------------------------------
+
+Use the 'bd_mon_fnc' field of the bd_t structure passed to the
+application to do everything you want with the console.
+
+But REMEMBER that that will work only if you have not overwritten any
+U-Boot code while loading (or uncompressing) the image of your
+application.
+
+For example, you won't get the console stuff running in the Linux
+kernel because the kernel overwrites U-Boot before running. Only
+some parameters like the framebuffer descriptors are passed to the
+kernel in the high memory area to let the applications (the kernel)
+use the framebuffers initialized by U-Boot.
+
+SUPPORTED DRIVERS
+-----------------
+
+Working drivers:
+
+    serial 	(architecture dependent serial stuff)
+    video 	(mpc8xx video controller)
+
+Work in progress:
+
+    wl_kbd	(Wireless 4PPM keyboard)
+
+Waiting for volounteers:
+
+    lcd	(mpc8xx lcd controller; to )
+
+TESTED CONFIGURATIONS
+---------------------
+
+The driver has been tested with the following configurations (see
+CREDITS for other contact informations):
+
+- MPC823FADS with AD7176 on a PAL TV (YCbYCr) 	- arsenio@tin.it
+- GENIETV    with AD7177 on a PAL TV (YCbYCr)	- arsenio@tin.it

+ 1709 - 0
drivers/bcm570x.c

@@ -0,0 +1,1709 @@
+/*
+ * Broadcom BCM570x Ethernet Driver for U-Boot.
+ * Support 5701, 5702, 5703, and 5704. Single instance driver.
+ * Copyright (C) 2002 James F. Dougherty (jfd@broadcom.com)
+ */
+
+#include <common.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && (!defined(CONFIG_NET_MULTI)) && \
+	defined(CONFIG_BCM570x)
+
+#ifdef CONFIG_BMW
+#include <mpc824x.h>
+#endif
+#include <net.h>
+#include "bcm570x_mm.h"
+#include "bcm570x_autoneg.h"
+#include <pci.h>
+#include <malloc.h>
+
+
+
+/*
+ * PCI Registers and definitions.
+ */
+#define PCI_CMD_MASK	0xffff0000	/* mask to save status bits */
+#define PCI_ANY_ID (~0)
+
+/*
+ * PCI memory base for Ethernet device as well as device Interrupt.
+ */
+#define BCM570X_MBAR 	0x80100000
+#define BCM570X_ILINE   1
+
+
+
+#define SECOND_USEC	1000000
+#define MAX_PACKET_SIZE 1600
+#define MAX_UNITS       4
+
+/* Globals to this module */
+int initialized = 0;
+unsigned int ioBase = 0;
+volatile PLM_DEVICE_BLOCK    pDevice = NULL;        /* 570x softc */
+volatile PUM_DEVICE_BLOCK    pUmDevice = NULL;
+
+/* Used to pass the full-duplex flag, etc. */
+int line_speed[MAX_UNITS] = {0,0,0,0};
+static int full_duplex[MAX_UNITS] = {1,1,1,1};
+static int rx_flow_control[MAX_UNITS] = {0,0,0,0};
+static int tx_flow_control[MAX_UNITS] = {0,0,0,0};
+static int auto_flow_control[MAX_UNITS] = {0,0,0,0};
+static int tx_checksum[MAX_UNITS] = {1,1,1,1};
+static int rx_checksum[MAX_UNITS] = {1,1,1,1};
+static int auto_speed[MAX_UNITS] = {1,1,1,1};
+
+#if JUMBO_FRAMES
+/* Jumbo MTU for interfaces. */
+static int mtu[MAX_UNITS] = {0,0,0,0};
+#endif
+
+/* Turn on Wake-on lan for a device unit */
+static int enable_wol[MAX_UNITS] = {0,0,0,0};
+
+#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
+static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
+	{TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT, TX_DESC_CNT};
+
+#define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT
+static unsigned int rx_std_desc_cnt[MAX_UNITS] =
+	{RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT};
+
+static unsigned int rx_adaptive_coalesce[MAX_UNITS] = {1,1,1,1};
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+#define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT
+static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] =
+	{JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT};
+#endif
+#define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS
+static unsigned int rx_coalesce_ticks[MAX_UNITS] =
+	{RX_COAL_TK, RX_COAL_TK, RX_COAL_TK, RX_COAL_TK};
+
+#define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES
+static unsigned int rx_max_coalesce_frames[MAX_UNITS] =
+	{RX_COAL_FM, RX_COAL_FM, RX_COAL_FM, RX_COAL_FM};
+
+#define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS
+static unsigned int tx_coalesce_ticks[MAX_UNITS] =
+	{TX_COAL_TK, TX_COAL_TK, TX_COAL_TK, TX_COAL_TK};
+
+#define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES
+static unsigned int tx_max_coalesce_frames[MAX_UNITS] =
+	{TX_COAL_FM, TX_COAL_FM, TX_COAL_FM, TX_COAL_FM};
+
+#define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS
+static unsigned int stats_coalesce_ticks[MAX_UNITS] =
+	{ST_COAL_TK, ST_COAL_TK, ST_COAL_TK, ST_COAL_TK};
+
+
+
+/*
+ * Legitimate values for BCM570x device types
+ */
+typedef enum {
+	BCM5700VIGIL = 0,
+	BCM5700A6,
+	BCM5700T6,
+	BCM5700A9,
+	BCM5700T9,
+	BCM5700,
+	BCM5701A5,
+	BCM5701T1,
+	BCM5701T8,
+	BCM5701A7,
+	BCM5701A10,
+	BCM5701A12,
+	BCM5701,
+	BCM5702,
+	BCM5703,
+	BCM5703A31,
+	TC996T,
+	TC996ST,
+	TC996SSX,
+	TC996SX,
+	TC996BT,
+	TC997T,
+	TC997SX,
+	TC1000T,
+	TC940BR01,
+	TC942BR01,
+	NC6770,
+	NC7760,
+	NC7770,
+	NC7780
+} board_t;
+
+/* Chip-Rev names for each device-type */
+static struct {
+    char* name;
+} chip_rev[] = {
+       {"BCM5700VIGIL"},
+       {"BCM5700A6"},
+       {"BCM5700T6"},
+       {"BCM5700A9"},
+       {"BCM5700T9"},
+       {"BCM5700"},
+       {"BCM5701A5"},
+       {"BCM5701T1"},
+       {"BCM5701T8"},
+       {"BCM5701A7"},
+       {"BCM5701A10"},
+       {"BCM5701A12"},
+       {"BCM5701"},
+       {"BCM5702"},
+       {"BCM5703"},
+       {"BCM5703A31"},
+       {"TC996T"},
+       {"TC996ST"},
+       {"TC996SSX"},
+       {"TC996SX"},
+       {"TC996BT"},
+       {"TC997T"},
+       {"TC997SX"},
+       {"TC1000T"},
+       {"TC940BR01"},
+       {"TC942BR01"},
+       {"NC6770"},
+       {"NC7760"},
+       {"NC7770"},
+       {"NC7780"},
+       {0}
+};
+
+
+/* indexed by board_t, above */
+static struct {
+    char *name;
+} board_info[] = {
+	{ "Broadcom Vigil B5700 1000Base-T" },
+	{ "Broadcom BCM5700 1000Base-T" },
+	{ "Broadcom BCM5700 1000Base-SX" },
+	{ "Broadcom BCM5700 1000Base-SX" },
+	{ "Broadcom BCM5700 1000Base-T" },
+	{ "Broadcom BCM5700" },
+	{ "Broadcom BCM5701 1000Base-T" },
+	{ "Broadcom BCM5701 1000Base-T" },
+	{ "Broadcom BCM5701 1000Base-T" },
+	{ "Broadcom BCM5701 1000Base-SX" },
+	{ "Broadcom BCM5701 1000Base-T" },
+	{ "Broadcom BCM5701 1000Base-T" },
+	{ "Broadcom BCM5701" },
+	{ "Broadcom BCM5702 1000Base-T" },
+	{ "Broadcom BCM5703 1000Base-T" },
+	{ "Broadcom BCM5703 1000Base-SX" },
+	{ "3Com 3C996 10/100/1000 Server NIC" },
+	{ "3Com 3C996 10/100/1000 Server NIC" },
+	{ "3Com 3C996 Gigabit Fiber-SX Server NIC" },
+	{ "3Com 3C996 Gigabit Fiber-SX Server NIC" },
+	{ "3Com 3C996B Gigabit Server NIC" },
+	{ "3Com 3C997 Gigabit Server NIC" },
+	{ "3Com 3C997 Gigabit Fiber-SX Server NIC" },
+	{ "3Com 3C1000 Gigabit NIC" },
+	{ "3Com 3C940 Gigabit LOM (21X21)" },
+	{ "3Com 3C942 Gigabit LOM (31X31)" },
+	{ "Compaq NC6770 Gigabit Server Adapter" },
+	{ "Compaq NC7760 Gigabit Server Adapter" },
+	{ "Compaq NC7770 Gigabit Server Adapter" },
+	{ "Compaq NC7780 Gigabit Server Adapter" },
+	{ 0 },
+};
+
+/* PCI Devices which use the 570x chipset */
+struct pci_device_table {
+    unsigned short vendor_id, device_id; /* Vendor/DeviceID */
+    unsigned short subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
+    unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
+    unsigned long board_id;	    /* Data private to the driver */
+    int io_size, min_latency;
+} bcm570xDevices[] = {
+	{0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL ,128,32},
+	{0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6 ,128,32},
+	{0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6 ,128,32},
+	{0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9 ,128,32},
+	{0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9 ,128,32},
+	{0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700 ,128,32},
+	{0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700 ,128,32},
+	{0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700 ,128,32},
+	{0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700 ,128,32},
+	{0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T ,128,32},
+	{0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST ,128,32},
+	{0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX ,128,32},
+	{0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T ,128,32},
+	{0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX ,128,32},
+	{0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01 ,128,32},
+	{0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700 ,128,32},
+	{0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5 ,128,32},
+	{0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1 ,128,32},
+	{0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8 ,128,32},
+	{0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7 ,128,32},
+	{0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10 ,128,32},
+	{0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12 ,128,32},
+	{0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770 ,128,32},
+	{0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770 ,128,32},
+	{0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780 ,128,32},
+	{0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701 ,128,32},
+	{0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX ,128,32},
+	{0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT ,128,32},
+	{0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T ,128,32},
+	{0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01 ,128,32},
+	{0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701 ,128,32},
+	{0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 ,128,32},
+	{0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760 ,128,32},
+	{0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 ,128,32},
+	{0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 ,128,32},
+	{0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 ,128,32},
+	{0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 ,128,32},
+	{0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703 ,128,32},
+	{0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31 ,128,32},
+	{0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703 ,128,32},
+	{0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703 ,128,32},
+	{0x14e4, 0x1647, 0x0e11, 0x9a, 0, 0, NC7770 ,128,32},
+	{0x14e4, 0x1647, 0x0e11, 0x99, 0, 0, NC7780 ,128,32},
+	{0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 ,128,32},
+	{0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703 ,128,32},
+	{0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31 ,128,32},
+	{0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703 ,128,32},
+	{0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703 ,128,32},
+	{0x14e4, 0x16a7, 0x0e11, 0x9a, 0, 0, NC7770 ,128,32},
+	{0x14e4, 0x16a7, 0x0e11, 0x99, 0, 0, NC7780 ,128,32},
+	{0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 ,128,32}
+};
+
+#define n570xDevices   (sizeof(bcm570xDevices)/sizeof(bcm570xDevices[0]))
+
+
+
+/*
+ * Allocate a packet buffer from the bcm570x packet pool.
+ */
+void *
+bcm570xPktAlloc(int u, int pksize)
+{
+    return malloc(pksize);
+}
+
+/*
+ * Free a packet previously allocated from the bcm570x packet
+ * buffer pool.
+ */
+void
+bcm570xPktFree(int u, void *p)
+{
+    free(p);
+}
+
+int
+bcm570xReplenishRxBuffers(PUM_DEVICE_BLOCK pUmDevice)
+{
+    PLM_PACKET pPacket;
+    PUM_PACKET pUmPacket;
+    void *skb;
+    int queue_rx = 0;
+    int ret = 0;
+
+    while ((pUmPacket = (PUM_PACKET)
+	    QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
+
+	pPacket = (PLM_PACKET) pUmPacket;
+
+	/* reuse an old skb */
+	if (pUmPacket->skbuff) {
+	    QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+	    queue_rx = 1;
+	    continue;
+	}
+	if ( ( skb = bcm570xPktAlloc(pUmDevice->index,
+				     pPacket->u.Rx.RxBufferSize + 2)) == 0) {
+	    QQ_PushHead(&pUmDevice->rx_out_of_buf_q.Container,pPacket);
+	    printf("NOTICE: Out of RX memory.\n");
+	    ret = 1;
+	    break;
+	}
+
+	pUmPacket->skbuff = skb;
+	QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+	queue_rx = 1;
+    }
+
+    if (queue_rx) {
+	LM_QueueRxPackets(pDevice);
+    }
+
+    return ret;
+}
+
+/*
+ * Probe, Map, and Init 570x device.
+ */
+int eth_init(bd_t *bis)
+{
+    int i, rv, devFound = FALSE;
+    pci_dev_t  devbusfn;
+    unsigned short status;
+
+    /* Find PCI device, if it exists, configure ...  */
+    for( i = 0; i < n570xDevices; i++){
+	devbusfn = pci_find_device(bcm570xDevices[i].vendor_id,
+				   bcm570xDevices[i].device_id, 0);
+	if(devbusfn == -1) {
+	    continue; /* No device of that vendor/device ID */
+	} else {
+
+	    /* Set ILINE */
+	    pci_write_config_byte(devbusfn,
+				  PCI_INTERRUPT_LINE, BCM570X_ILINE);
+
+	    /*
+	     * 0x10 - 0x14 define one 64-bit MBAR.
+	     * 0x14 is the higher-order address bits of the BAR.
+	     */
+	    pci_write_config_dword(devbusfn,
+				   PCI_BASE_ADDRESS_1, 0);
+
+	    ioBase = BCM570X_MBAR;
+
+	    pci_write_config_dword(devbusfn,
+				   PCI_BASE_ADDRESS_0, ioBase);
+
+	    /*
+	     * Enable PCI memory, IO, and Master -- don't
+	     * reset any status bits in doing so.
+	     */
+	    pci_read_config_word(devbusfn,
+				 PCI_COMMAND, &status);
+
+	    status |= PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER;
+
+	    pci_write_config_word(devbusfn,
+				  PCI_COMMAND, status);
+
+	    printf("\n%s: bus %d, device %d, function %d: MBAR=0x%x\n",
+		   board_info[bcm570xDevices[i].board_id].name,
+		   PCI_BUS(devbusfn),
+		   PCI_DEV(devbusfn),
+		   PCI_FUNC(devbusfn),
+		   ioBase);
+
+	    /* Allocate once, but always clear on init */
+	    if (!pDevice) {
+		pDevice = malloc(sizeof(UM_DEVICE_BLOCK));
+		pUmDevice = (PUM_DEVICE_BLOCK)pDevice;
+		memset(pDevice, 0x0, sizeof(UM_DEVICE_BLOCK));
+	    }
+
+	    /* Configure pci dev structure */
+	    pUmDevice->pdev = devbusfn;
+	    pUmDevice->index = 0;
+	    pUmDevice->tx_pkt = 0;
+	    pUmDevice->rx_pkt = 0;
+	    devFound = TRUE;
+	    break;
+	}
+    }
+
+    if(!devFound){
+	printf("eth_init: FAILURE: no BCM570x Ethernet devices found.\n");
+	return -1;
+    }
+
+    /* Setup defaults for chip */
+    pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+
+    if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) {
+	pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+    } else {
+
+	if (rx_checksum[i]) {
+	    pDevice->TaskToOffload |=
+		LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
+		LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
+	}
+
+	if (tx_checksum[i]) {
+	    pDevice->TaskToOffload |=
+		LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+		LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
+	    pDevice->NoTxPseudoHdrChksum = TRUE;
+	}
+    }
+
+    /* Set Device PCI Memory base address */
+    pDevice->pMappedMemBase = (PLM_UINT8) ioBase;
+
+    /* Pull down adapter info */
+    if ((rv = LM_GetAdapterInfo(pDevice)) != LM_STATUS_SUCCESS) {
+	printf("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv );
+	return -2;
+    }
+
+    /* Lock not needed */
+    pUmDevice->do_global_lock = 0;
+
+    if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
+	/* The 5700 chip works best without interleaved register */
+	/* accesses on certain machines. */
+	pUmDevice->do_global_lock = 1;
+    }
+
+    /* Setup timer delays */
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) {
+	pDevice->UseTaggedStatus = TRUE;
+	pUmDevice->timer_interval = CFG_HZ;
+    }
+    else {
+	pUmDevice->timer_interval = CFG_HZ / 50;
+    }
+
+    /* Grab name .... */
+    pUmDevice->name =
+	(char*)malloc(strlen(board_info[bcm570xDevices[i].board_id].name)+1);
+    strcpy(pUmDevice->name,board_info[bcm570xDevices[i].board_id].name);
+
+    memcpy(pDevice->NodeAddress, bis->bi_enetaddr, 6);
+    LM_SetMacAddress(pDevice, bis->bi_enetaddr);
+    /* Init queues  .. */
+    QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container,
+		 MAX_RX_PACKET_DESC_COUNT);
+    pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0;
+
+    /* delay for 4 seconds */
+    pUmDevice->delayed_link_ind =
+	(4 * CFG_HZ) / pUmDevice->timer_interval;
+
+    pUmDevice->adaptive_expiry =
+	CFG_HZ / pUmDevice->timer_interval;
+
+    /* Sometimes we get spurious ints. after reset when link is down. */
+    /* This field tells the isr to service the int. even if there is */
+    /* no status block update. */
+    pUmDevice->adapter_just_inited =
+	(3 * CFG_HZ) / pUmDevice->timer_interval;
+
+    /* Initialize 570x */
+    if (LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) {
+	printf("ERROR: Adapter initialization failed.\n");
+	return ERROR;
+    }
+
+    /* Enable chip ISR */
+    LM_EnableInterrupt(pDevice);
+
+    /* Clear MC table */
+    LM_MulticastClear(pDevice);
+
+    /* Enable Multicast */
+    LM_SetReceiveMask(pDevice,
+		      pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
+
+    pUmDevice->opened = 1;
+    pUmDevice->tx_full = 0;
+    pUmDevice->tx_pkt = 0;
+    pUmDevice->rx_pkt = 0;
+    printf("eth%d: %s @0x%lx,",
+	   pDevice->index, pUmDevice->name, (unsigned long)ioBase);
+    printf(	"node addr ");
+    for (i = 0; i < 6; i++) {
+	printf("%2.2x", pDevice->NodeAddress[i]);
+    }
+    printf("\n");
+
+    printf("eth%d: ", pDevice->index);
+    printf("%s with ",
+	   chip_rev[bcm570xDevices[i].board_id].name);
+
+    if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
+	printf("Broadcom BCM5400 Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+	printf("Broadcom BCM5401 Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
+	printf("Broadcom BCM5411 Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID)
+	printf("Broadcom BCM5701 Integrated Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID)
+        printf("Broadcom BCM5703 Integrated Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
+	printf("Broadcom BCM8002 SerDes ");
+    else if (pDevice->EnableTbi)
+	printf("Agilent HDMP-1636 SerDes ");
+    else
+	printf("Unknown ");
+    printf("transceiver found\n");
+
+    printf("eth%d: %s, MTU: %d,",
+	   pDevice->index, pDevice->BusSpeedStr, 1500);
+
+    if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) &&
+	rx_checksum[i])
+	printf("Rx Checksum ON\n");
+    else
+	printf("Rx Checksum OFF\n");
+    initialized++;
+
+    return 0;
+}
+
+/* Ethernet Interrupt service routine */
+void
+eth_isr(void)
+{
+    LM_UINT32 oldtag, newtag;
+    int i;
+
+    pUmDevice->interrupt = 1;
+
+    if (pDevice->UseTaggedStatus) {
+	if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
+	    pUmDevice->adapter_just_inited) {
+            MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
+            oldtag = pDevice->pStatusBlkVirt->StatusTag;
+
+            for (i = 0; ; i++) {
+                pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
+                LM_ServiceInterrupts(pDevice);
+                newtag = pDevice->pStatusBlkVirt->StatusTag;
+                if ((newtag == oldtag) || (i > 50)) {
+                    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, newtag << 24);
+                    if (pDevice->UndiFix) {
+                        REG_WR(pDevice, Grc.LocalCtrl,
+			       pDevice->GrcLocalCtrl | 0x2);
+                    }
+                    break;
+                 }
+		oldtag = newtag;
+	    }
+	}
+    }
+    else {
+	while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
+	    unsigned int dummy;
+
+	    pDevice->pMemView->Mailbox.Interrupt[0].Low = 1;
+	    pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
+	    LM_ServiceInterrupts(pDevice);
+	    pDevice->pMemView->Mailbox.Interrupt[0].Low = 0;
+	    dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low;
+	}
+    }
+
+    /* Allocate new RX buffers */
+    if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
+	bcm570xReplenishRxBuffers(pUmDevice);
+    }
+
+    /* Queue packets */
+    if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container)) {
+	LM_QueueRxPackets(pDevice);
+    }
+
+    if (pUmDevice->tx_queued) {
+	pUmDevice->tx_queued = 0;
+    }
+
+    if(pUmDevice->tx_full){
+	if(pDevice->LinkStatus != LM_STATUS_LINK_DOWN){
+	    printf("NOTICE: tx was previously blocked, restarting MUX\n");
+	    pUmDevice->tx_full = 0;
+	}
+    }
+
+    pUmDevice->interrupt = 0;
+
+}
+
+int
+eth_send(volatile void *packet, int length)
+{
+    int status = 0;
+#if ET_DEBUG
+    unsigned char* ptr = (unsigned char*)packet;
+#endif
+    PLM_PACKET pPacket;
+    PUM_PACKET pUmPacket;
+
+    /* Link down, return */
+    while(pDevice->LinkStatus == LM_STATUS_LINK_DOWN) {
+#if 0
+        printf("eth%d: link down - check cable or link partner.\n",
+               pUmDevice->index);
+#endif
+	eth_isr();
+
+	/* Wait to see link for one-half a second before sending ... */
+	udelay(1500000);
+
+    }
+
+    /* Clear sent flag */
+    pUmDevice->tx_pkt = 0;
+
+    /* Previously blocked */
+    if(pUmDevice->tx_full){
+	printf("eth%d: tx blocked.\n", pUmDevice->index);
+	return 0;
+    }
+
+    pPacket = (PLM_PACKET)
+	QQ_PopHead(&pDevice->TxPacketFreeQ.Container);
+
+    if (pPacket == 0) {
+	pUmDevice->tx_full = 1;
+	printf("bcm570xEndSend: TX full!\n");
+	return 0;
+    }
+
+    if (pDevice->SendBdLeft.counter == 0) {
+	pUmDevice->tx_full = 1;
+	printf("bcm570xEndSend: no more TX descriptors!\n");
+	QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+	return 0;
+    }
+
+    if (length <= 0){
+	printf("eth: bad packet size: %d\n", length);
+	goto out;
+    }
+
+    /* Get packet buffers and fragment list */
+    pUmPacket = (PUM_PACKET) pPacket;
+    /* Single DMA Descriptor transmit.
+     * Fragments may be provided, but one DMA descriptor max is
+     * used to send the packet.
+     */
+    if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) {
+        if (pUmPacket->skbuff == NULL){
+	    /* Packet was discarded */
+	    printf("TX: failed (1)\n");
+	    status = 1;
+	} else{
+	    printf("TX: failed (2)\n");
+	    status = 2;
+	}
+        QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
+        return status;
+    }
+
+    /* Copy packet to DMA buffer */
+    memset(pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE);
+    memcpy((void*)pUmPacket->skbuff, (void*)packet, length);
+    pPacket->PacketSize = length;
+    pPacket->Flags |= SND_BD_FLAG_END|SND_BD_FLAG_COAL_NOW;
+    pPacket->u.Tx.FragCount = 1;
+    /* We've already provided a frame ready for transmission */
+    pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
+
+    if ( LM_SendPacket(pDevice, pPacket) == LM_STATUS_FAILURE){
+        /*
+         *  A lower level send failure will push the packet descriptor back
+         *  in the free queue, so just deal with the VxWorks clusters.
+         */
+        if (pUmPacket->skbuff == NULL){
+	    printf("TX failed (1)!\n");
+	    /* Packet was discarded */
+	    status = 3;
+	} else {
+	    /* A resource problem ... */
+	    printf("TX failed (2)!\n");
+	    status = 4;
+	}
+
+	if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) == 0) {
+	    printf("TX: emptyQ!\n");
+	    pUmDevice->tx_full = 1;
+	}
+    }
+
+    while(pUmDevice->tx_pkt == 0){
+	/* Service TX */
+	eth_isr();
+    }
+#if ET_DEBUG
+    printf("eth_send: 0x%x, %d bytes\n"
+	   "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n",
+	   (int)pPacket, length,
+	   ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5],
+	   ptr[6],ptr[7],ptr[8],ptr[9],ptr[10],ptr[11],ptr[12],
+	   ptr[13],ptr[14],ptr[15]);
+#endif
+    pUmDevice->tx_pkt = 0;
+    QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+
+    /* Done with send */
+ out:
+    return status;
+}
+
+
+/* Ethernet receive */
+int
+eth_rx(void)
+{
+    PLM_PACKET          pPacket = NULL;
+    PUM_PACKET          pUmPacket = NULL;
+    void *skb;
+    int size=0;
+
+    while(TRUE) {
+
+    bcm570x_service_isr:
+	/* Pull down packet if it is there */
+	eth_isr();
+
+	/* Indicate RX packets called */
+	if(pUmDevice->rx_pkt){
+	    /* printf("eth_rx: got a packet...\n"); */
+	    pUmDevice->rx_pkt = 0;
+	} else {
+	    /* printf("eth_rx: waiting for packet...\n"); */
+	    goto bcm570x_service_isr;
+	}
+
+	pPacket = (PLM_PACKET)
+	    QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);
+
+	if (pPacket == 0){
+	    printf("eth_rx: empty packet!\n");
+	    goto bcm570x_service_isr;
+	}
+
+	pUmPacket = (PUM_PACKET) pPacket;
+#if ET_DEBUG
+	printf("eth_rx: packet @0x%x\n",
+	       (int)pPacket);
+#endif
+	/* If the packet generated an error, reuse buffer */
+	if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
+	    ((size = pPacket->PacketSize) > pDevice->RxMtu)) {
+
+	    /* reuse skb */
+	    QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+	    printf("eth_rx: error in packet dma!\n");
+	    goto bcm570x_service_isr;
+	}
+
+	/* Set size and address */
+	skb = pUmPacket->skbuff;
+	size = pPacket->PacketSize;
+
+	/* Pass the packet up to the protocol
+	 * layers.
+	 */
+	NetReceive(skb, size);
+
+	/* Free packet buffer */
+	bcm570xPktFree (pUmDevice->index, skb);
+	pUmPacket->skbuff = NULL;
+
+	/* Reuse SKB */
+	QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+	return 0; /* Got a packet, bail ... */
+    }
+    return size;
+}
+
+
+
+/* Shut down device */
+void
+eth_halt(void)
+{
+    int i;
+    if ( initialized)
+    if (pDevice && pUmDevice && pUmDevice->opened){
+	printf("\neth%d:%s,", pUmDevice->index, pUmDevice->name);
+	printf("HALT,");
+        /* stop device */
+        LM_Halt(pDevice);
+	printf("POWER DOWN,");
+        LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
+
+        /* Free the memory allocated by the device in tigon3 */
+        for (i = 0; i < pUmDevice->mem_list_num; i++)  {
+            if (pUmDevice->mem_list[i])  {
+		/* sanity check */
+                if (pUmDevice->dma_list[i]) {  /* cache-safe memory */
+                    free(pUmDevice->mem_list[i]);
+		} else {
+                    free(pUmDevice->mem_list[i]);  /* normal memory   */
+		}
+	    }
+	}
+	pUmDevice->opened = 0;
+	free(pDevice);
+	pDevice = NULL;
+	pUmDevice = NULL;
+	initialized = 0;
+	printf("done - offline.\n");
+    }
+}
+
+
+
+
+/*
+ *
+ * Middle Module: Interface between the HW driver (tigon3 modules) and
+ * the native (SENS) driver.  These routines implement the system
+ * interface for tigon3 on VxWorks.
+ */
+
+/* Middle module dependency - size of a packet descriptor */
+int MM_Packet_Desc_Size = sizeof(UM_PACKET);
+
+
+LM_STATUS
+MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice,
+		LM_UINT32 Offset,
+		LM_UINT32 *pValue32)
+{
+    UM_DEVICE_BLOCK *pUmDevice;
+    pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+    pci_read_config_dword(pUmDevice->pdev,
+			  Offset, (u32 *) pValue32);
+    return LM_STATUS_SUCCESS;
+}
+
+
+LM_STATUS
+MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice,
+		 LM_UINT32 Offset,
+		 LM_UINT32 Value32)
+{
+    UM_DEVICE_BLOCK *pUmDevice;
+    pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+    pci_write_config_dword(pUmDevice->pdev,
+			   Offset, Value32);
+    return LM_STATUS_SUCCESS;
+}
+
+
+LM_STATUS
+MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice,
+		LM_UINT32 Offset,
+		LM_UINT16 *pValue16)
+{
+    UM_DEVICE_BLOCK *pUmDevice;
+    pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+    pci_read_config_word(pUmDevice->pdev,
+			 Offset, (u16*) pValue16);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice,
+		 LM_UINT32 Offset,
+		 LM_UINT16 Value16)
+{
+    UM_DEVICE_BLOCK *pUmDevice;
+    pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+    pci_write_config_word(pUmDevice->pdev,
+			  Offset, Value16);
+    return LM_STATUS_SUCCESS;
+}
+
+
+LM_STATUS
+MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+			PLM_VOID *pMemoryBlockVirt,
+			PLM_PHYSICAL_ADDRESS pMemoryBlockPhy,
+			LM_BOOL Cached)
+{
+    PLM_VOID pvirt;
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    dma_addr_t mapping;
+
+    pvirt = malloc(BlockSize);
+    mapping = (dma_addr_t)(pvirt);
+    if (!pvirt)
+	return LM_STATUS_FAILURE;
+
+    pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+    pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
+    pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
+    memset(pvirt, 0, BlockSize);
+
+    *pMemoryBlockVirt = (PLM_VOID) pvirt;
+    MM_SetAddr (pMemoryBlockPhy, (dma_addr_t) mapping);
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+
+LM_STATUS
+MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+	PLM_VOID *pMemoryBlockVirt)
+{
+    PLM_VOID pvirt;
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+
+    pvirt = malloc(BlockSize);
+
+    if (!pvirt)
+	return LM_STATUS_FAILURE;
+
+    pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+    pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
+    pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
+    memset(pvirt, 0, BlockSize);
+    *pMemoryBlockVirt = pvirt;
+
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_MapMemBase(PLM_DEVICE_BLOCK pDevice)
+{
+    printf("BCM570x PCI Memory base address @0x%x\n",
+	   (unsigned int)pDevice->pMappedMemBase);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice)
+{
+    int i;
+    void* skb;
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    PUM_PACKET pUmPacket = NULL;
+    PLM_PACKET pPacket = NULL;
+
+    for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
+	pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+	pUmPacket = (PUM_PACKET) pPacket;
+
+	if (pPacket == 0) {
+	    printf("MM_InitializeUmPackets: Bad RxPacketFreeQ\n");
+	}
+
+	skb = bcm570xPktAlloc(pUmDevice->index,
+			      pPacket->u.Rx.RxBufferSize + 2);
+
+	if (skb == 0) {
+	    pUmPacket->skbuff = 0;
+	    QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+	    printf("MM_InitializeUmPackets: out of buffer.\n");
+	    continue;
+	}
+
+	pUmPacket->skbuff = skb;
+	QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+    }
+
+    pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8;
+
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_GetConfig(PLM_DEVICE_BLOCK pDevice)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    int index = pDevice->index;
+
+    if (auto_speed[index] == 0)
+	pDevice->DisableAutoNeg = TRUE;
+    else
+	pDevice->DisableAutoNeg = FALSE;
+
+    if (line_speed[index] == 0) {
+	pDevice->RequestedMediaType =
+	    LM_REQUESTED_MEDIA_TYPE_AUTO;
+	pDevice->DisableAutoNeg = FALSE;
+    }
+    else {
+	if (line_speed[index] == 1000) {
+	    if (pDevice->EnableTbi) {
+		pDevice->RequestedMediaType =
+		    LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX;
+	    }
+	    else if (full_duplex[index]) {
+		pDevice->RequestedMediaType =
+		    LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX;
+	    }
+	    else {
+		pDevice->RequestedMediaType =
+		    LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS;
+	    }
+	    if (!pDevice->EnableTbi)
+		pDevice->DisableAutoNeg = FALSE;
+	}
+	else if (line_speed[index] == 100) {
+	    if (full_duplex[index]) {
+		pDevice->RequestedMediaType =
+		    LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX;
+	    }
+	    else {
+		pDevice->RequestedMediaType =
+		    LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS;
+	    }
+	}
+	else if (line_speed[index] == 10) {
+	    if (full_duplex[index]) {
+		pDevice->RequestedMediaType =
+		    LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX;
+	    }
+	    else {
+		pDevice->RequestedMediaType =
+		    LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
+	    }
+	}
+	else {
+	    pDevice->RequestedMediaType =
+		LM_REQUESTED_MEDIA_TYPE_AUTO;
+	    pDevice->DisableAutoNeg = FALSE;
+	}
+
+    }
+    pDevice->FlowControlCap = 0;
+    if (rx_flow_control[index] != 0) {
+	pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
+    }
+    if (tx_flow_control[index] != 0) {
+	pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+    }
+    if ((auto_flow_control[index] != 0) &&
+	(pDevice->DisableAutoNeg == FALSE)) {
+
+	pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
+	if ((tx_flow_control[index] == 0) &&
+	    (rx_flow_control[index] == 0)) {
+	    pDevice->FlowControlCap |=
+		LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+		LM_FLOW_CONTROL_RECEIVE_PAUSE;
+	}
+    }
+
+    /* Default MTU for now */
+    pUmDevice->mtu = 1500;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    if (pUmDevice->mtu > 1500) {
+	pDevice->RxMtu = pUmDevice->mtu;
+	pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
+    }
+    else {
+	pDevice->RxJumboDescCnt = 0;
+    }
+    pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
+#else
+    pDevice->RxMtu = pUmDevice->mtu;
+#endif
+
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) {
+	pDevice->UseTaggedStatus = TRUE;
+	pUmDevice->timer_interval = CFG_HZ;
+    }
+    else {
+	pUmDevice->timer_interval = CFG_HZ/50;
+    }
+
+    pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
+    pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
+    /* Note:  adaptive coalescence really isn't adaptive in this driver */
+    pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index];
+    if (!pUmDevice->rx_adaptive_coalesce) {
+	pDevice->RxCoalescingTicks = rx_coalesce_ticks[index];
+	if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS)
+	    pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS;
+	pUmDevice->rx_curr_coalesce_ticks =pDevice->RxCoalescingTicks;
+
+	pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index];
+	if (pDevice->RxMaxCoalescedFrames>MAX_RX_MAX_COALESCED_FRAMES)
+	    pDevice->RxMaxCoalescedFrames =
+				MAX_RX_MAX_COALESCED_FRAMES;
+	pUmDevice->rx_curr_coalesce_frames =
+	    pDevice->RxMaxCoalescedFrames;
+	pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
+	if (pDevice->StatsCoalescingTicks>MAX_STATS_COALESCING_TICKS)
+	    pDevice->StatsCoalescingTicks=
+		MAX_STATS_COALESCING_TICKS;
+	}
+	else {
+	    pUmDevice->rx_curr_coalesce_frames =
+		DEFAULT_RX_MAX_COALESCED_FRAMES;
+	    pUmDevice->rx_curr_coalesce_ticks =
+		DEFAULT_RX_COALESCING_TICKS;
+	}
+    pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
+    if (pDevice->TxCoalescingTicks > MAX_TX_COALESCING_TICKS)
+	pDevice->TxCoalescingTicks = MAX_TX_COALESCING_TICKS;
+    pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
+    if (pDevice->TxMaxCoalescedFrames > MAX_TX_MAX_COALESCED_FRAMES)
+	pDevice->TxMaxCoalescedFrames = MAX_TX_MAX_COALESCED_FRAMES;
+
+    if (enable_wol[index]) {
+	pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
+	pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
+    }
+    pDevice->NicSendBd = TRUE;
+
+    /* Don't update status blocks during interrupt */
+    pDevice->RxCoalescingTicksDuringInt = 0;
+    pDevice->TxCoalescingTicksDuringInt = 0;
+
+    return LM_STATUS_SUCCESS;
+
+}
+
+
+LM_STATUS
+MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    printf("Start TX DMA: dev=%d packet @0x%x\n",
+	   (int)pUmDevice->index, (unsigned int)pPacket);
+
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    printf("Complete TX DMA: dev=%d packet @0x%x\n",
+	   (int)pUmDevice->index, (unsigned int)pPacket);
+    return LM_STATUS_SUCCESS;
+}
+
+
+LM_STATUS
+MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
+{
+    char buf[128];
+    char lcd[4];
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    LM_FLOW_CONTROL flow_control;
+
+    pUmDevice->delayed_link_ind = 0;
+    memset(lcd, 0x0, 4);
+
+    if (Status == LM_STATUS_LINK_DOWN) {
+	sprintf(buf,"eth%d: %s: NIC Link is down\n",
+		pUmDevice->index,pUmDevice->name);
+        lcd[0] = 'L';lcd[1]='N';lcd[2]='K';lcd[3] = '?';
+    } else if (Status == LM_STATUS_LINK_ACTIVE) {
+	sprintf(buf,"eth%d:%s: ", pUmDevice->index, pUmDevice->name);
+
+	if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS){
+	    strcat(buf,"1000 Mbps ");
+            lcd[0] = '1';lcd[1]='G';lcd[2]='B';
+	} else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS){
+	    strcat(buf,"100 Mbps ");
+            lcd[0] = '1';lcd[1]='0';lcd[2]='0';
+	} else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS){
+	    strcat(buf,"10 Mbps ");
+            lcd[0] = '1';lcd[1]='0';lcd[2]=' ';
+	}
+	if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL){
+	    strcat(buf, "full duplex");
+            lcd[3] = 'F';
+	} else {
+	    strcat(buf, "half duplex");
+            lcd[3] = 'H';
+	}
+	strcat(buf, " link up");
+
+	flow_control = pDevice->FlowControl &
+	    (LM_FLOW_CONTROL_RECEIVE_PAUSE |
+	     LM_FLOW_CONTROL_TRANSMIT_PAUSE);
+
+	if (flow_control) {
+	    if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
+		strcat(buf,", receive ");
+		if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+		    strcat(buf," & transmit ");
+	    }
+	    else {
+		strcat(buf,", transmit ");
+	    }
+	    strcat(buf,"flow control ON");
+	} else {
+	    strcat(buf, ", flow control OFF");
+	}
+        strcat(buf,"\n");
+	printf("%s",buf);
+    }
+#if 0
+    sysLedDsply(lcd[0],lcd[1],lcd[2],lcd[3]);
+#endif
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    PUM_PACKET pUmPacket;
+    void *skb;
+
+    pUmPacket = (PUM_PACKET) pPacket;
+
+    if ((skb = pUmPacket->skbuff))
+	bcm570xPktFree(pUmDevice->index, skb);
+
+    pUmPacket->skbuff = 0;
+
+    return LM_STATUS_SUCCESS;
+}
+
+unsigned long
+MM_AnGetCurrentTime_us(PAN_STATE_INFO pAnInfo)
+{
+    return get_timer(0);
+}
+
+/*
+ *   Transform an MBUF chain into a single MBUF.
+ *   This routine will fail if the amount of data in the
+ *   chain overflows a transmit buffer.  In that case,
+ *   the incoming MBUF chain will be freed.  This routine can
+ *   also fail by not being able to allocate a new MBUF (including
+ *   cluster and mbuf headers).  In that case the failure is
+ *   non-fatal.  The incoming cluster chain is not freed, giving
+ *   the caller the choice of whether to try a retransmit later.
+ */
+LM_STATUS
+MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    void *skbnew;
+    int len = 0;
+
+    if (len == 0)
+        return (LM_STATUS_SUCCESS);
+
+    if (len > MAX_PACKET_SIZE){
+        printf ("eth%d: xmit frame discarded, too big!, size = %d\n",
+		pUmDevice->index, len);
+        return (LM_STATUS_FAILURE);
+    }
+
+    skbnew = bcm570xPktAlloc(pUmDevice->index, MAX_PACKET_SIZE);
+
+    if (skbnew == NULL) {
+        pUmDevice->tx_full = 1;
+        printf ("eth%d: out of transmit buffers", pUmDevice->index);
+        return (LM_STATUS_FAILURE);
+    }
+
+    /* New packet values */
+    pUmPacket->skbuff = skbnew;
+    pUmPacket->lm_packet.u.Tx.FragCount = 1;
+
+    return (LM_STATUS_SUCCESS);
+}
+
+
+LM_STATUS
+MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    pUmDevice->rx_pkt = 1;
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    PLM_PACKET pPacket;
+    PUM_PACKET pUmPacket;
+    void *skb;
+    while ( TRUE ) {
+
+	pPacket = (PLM_PACKET)
+	    QQ_PopHead(&pDevice->TxPacketXmittedQ.Container);
+
+	if (pPacket == 0)
+	    break;
+
+	pUmPacket = (PUM_PACKET) pPacket;
+	skb = (void*)pUmPacket->skbuff;
+
+        /*
+        * Free MBLK if we transmitted a fragmented packet or a
+        * non-fragmented packet straight from the VxWorks
+        * buffer pool. If packet was copied to a local transmit
+        * buffer, then there's no MBUF to free, just free
+        * the transmit buffer back to the cluster pool.
+        */
+
+	if (skb)
+	    bcm570xPktFree (pUmDevice->index, skb);
+
+	pUmPacket->skbuff = 0;
+	QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
+	pUmDevice->tx_pkt = 1;
+    }
+    if (pUmDevice->tx_full) {
+	if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) >=
+	    (QQ_GetSize(&pDevice->TxPacketFreeQ.Container) >> 1))
+	    pUmDevice->tx_full = 0;
+    }
+    return LM_STATUS_SUCCESS;
+}
+
+/*
+ *  Scan an MBUF chain until we reach fragment number "frag"
+ *  Return its length and physical address.
+ */
+void MM_MapTxDma
+    (
+    PLM_DEVICE_BLOCK pDevice,
+    struct _LM_PACKET *pPacket,
+    T3_64BIT_HOST_ADDR *paddr,
+    LM_UINT32 *len,
+    int frag)
+{
+    PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+    *len = pPacket->PacketSize;
+    MM_SetT3Addr(paddr, (dma_addr_t) pUmPacket->skbuff);
+}
+
+/*
+ *  Convert an mbuf address, a CPU local virtual address,
+ *  to a physical address as seen from a PCI device.  Store the
+ *  result at paddr.
+ */
+void MM_MapRxDma(
+		 PLM_DEVICE_BLOCK pDevice,
+		 struct _LM_PACKET *pPacket,
+		 T3_64BIT_HOST_ADDR *paddr)
+{
+    PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+    MM_SetT3Addr(paddr, (dma_addr_t) pUmPacket->skbuff);
+}
+
+void
+MM_SetAddr (LM_PHYSICAL_ADDRESS *paddr, dma_addr_t addr)
+{
+#if (BITS_PER_LONG == 64)
+        paddr->High = ((unsigned long) addr) >> 32;
+        paddr->Low = ((unsigned long) addr) & 0xffffffff;
+#else
+        paddr->High = 0;
+        paddr->Low = (unsigned long) addr;
+#endif
+}
+
+void
+MM_SetT3Addr(T3_64BIT_HOST_ADDR *paddr, dma_addr_t addr)
+{
+        unsigned long baddr = (unsigned long) addr;
+#if (BITS_PER_LONG == 64)
+        set_64bit_addr(paddr, baddr & 0xffffffff, baddr >> 32);
+#else
+        set_64bit_addr(paddr, baddr, 0);
+#endif
+}
+
+/*
+ * This combination of `inline' and `extern' has almost the effect of a
+ * macro.  The way to use it is to put a function definition in a header
+ * file with these keywords, and put another copy of the definition
+ * (lacking `inline' and `extern') in a library file.  The definition in
+ * the header file will cause most calls to the function to be inlined.
+ * If any uses of the function remain, they will refer to the single copy
+ * in the library.
+ */
+void
+atomic_set(atomic_t* entry, int val)
+{
+    entry->counter = val;
+}
+int
+atomic_read(atomic_t* entry)
+{
+    return entry->counter;
+}
+void
+atomic_inc(atomic_t* entry)
+{
+    if(entry)
+	entry->counter++;
+}
+
+void
+atomic_dec(atomic_t* entry)
+{
+    if(entry)
+	entry->counter--;
+}
+
+void
+atomic_sub(int a, atomic_t* entry)
+{
+    if(entry)
+	entry->counter -= a;
+}
+
+void
+atomic_add(int a, atomic_t* entry)
+{
+    if(entry)
+	entry->counter += a;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+void
+QQ_InitQueue(
+PQQ_CONTAINER pQueue,
+unsigned int QueueSize) {
+    pQueue->Head = 0;
+    pQueue->Tail = 0;
+    pQueue->Size = QueueSize+1;
+    atomic_set(&pQueue->EntryCnt, 0);
+} /* QQ_InitQueue */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+char
+QQ_Full(
+PQQ_CONTAINER pQueue) {
+    unsigned int NewHead;
+
+    NewHead = (pQueue->Head + 1) % pQueue->Size;
+
+    return(NewHead == pQueue->Tail);
+} /* QQ_Full */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+char
+QQ_Empty(
+PQQ_CONTAINER pQueue) {
+    return(pQueue->Head == pQueue->Tail);
+} /* QQ_Empty */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+unsigned int
+QQ_GetSize(
+PQQ_CONTAINER pQueue) {
+    return pQueue->Size;
+} /* QQ_GetSize */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+unsigned int
+QQ_GetEntryCnt(
+PQQ_CONTAINER pQueue) {
+    return atomic_read(&pQueue->EntryCnt);
+} /* QQ_GetEntryCnt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+char
+QQ_PushHead(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Head;
+
+    Head = (pQueue->Head + 1) % pQueue->Size;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[pQueue->Head] = pEntry;
+    wmb();
+    pQueue->Head = Head;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+char
+QQ_PushTail(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Tail;
+
+    Tail = pQueue->Tail;
+    if(Tail == 0) {
+        Tail = pQueue->Size;
+    } /* if */
+    Tail--;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[Tail] = pEntry;
+    wmb();
+    pQueue->Tail = Tail;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_PopHead(
+PQQ_CONTAINER pQueue) {
+    unsigned int Head;
+    PQQ_ENTRY Entry;
+
+    Head = pQueue->Head;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    if(Head == 0) {
+        Head = pQueue->Size;
+    } /* if */
+    Head--;
+
+    Entry = pQueue->Array[Head];
+    membar();
+
+    pQueue->Head = Head;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_PopTail(
+PQQ_CONTAINER pQueue) {
+    unsigned int Tail;
+    PQQ_ENTRY Entry;
+
+    Tail = pQueue->Tail;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    Entry = pQueue->Array[Tail];
+    membar();
+    pQueue->Tail = (Tail + 1) % pQueue->Size;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_GetHead(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    if(pQueue->Head > Idx)
+    {
+        Idx = pQueue->Head - Idx;
+    }
+    else
+    {
+        Idx = pQueue->Size - (Idx - pQueue->Head);
+    }
+    Idx--;
+
+    return pQueue->Array[Idx];
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_GetTail(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    Idx += pQueue->Tail;
+    if(Idx >= pQueue->Size)
+    {
+        Idx = Idx - pQueue->Size;
+    }
+
+    return pQueue->Array[Idx];
+}
+
+#endif	/* CFG_CMD_NET, !CONFIG_NET_MULTI, CONFIG_BCM570x */

+ 57 - 0
include/cmd_disk.h

@@ -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
+ */
+
+/*
+ * Harddisk support
+ */
+#ifndef	_CMD_DISK_H
+#define	_CMD_DISK_H
+
+#include <common.h>
+#include <command.h>
+
+/*
+ * Type string for PPC bootable partitions
+ */
+#define BOOT_PART_TYPE	"U-Boot"
+
+#if 0
+
+typedef	struct disk_partition {
+	ulong	start;		/* # of first block in partition	*/
+	ulong	size;		/* number of blocks in partition	*/
+	ulong	blksz;		/* block size in bytes			*/
+	uchar	name[32];	/* partition name			*/
+	uchar	type[32];	/* string type description		*/
+} disk_partition_t;
+
+int get_partition_info     (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
+#ifdef CONFIG_MAC_PARTITION
+int get_partition_info_mac (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
+#endif
+#ifdef CONFIG_DOS_PARTITION
+int get_partition_info_dos (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
+#endif
+#endif	/* 0 */
+
+#endif	/* _CMD_DISK_H */

+ 297 - 0
include/configs/AMX860.h

@@ -0,0 +1,297 @@
+/*
+ * (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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC860		1
+#define CONFIG_AMX860		1
+
+#undef	CONFIG_8xx_CONS_SMC1		/* Console is on SCC2		*/
+#undef	CONFIG_8xx_CONS_SMC2
+#define	CONFIG_8xx_CONS_SCC2	1
+#undef	CONFIG_8xx_CONS_NONE
+#define CONFIG_BAUDRATE		9600
+#define CONFIG_LOADS_ECHO	1	/* echo on for serial download	*/
+
+#define MPC8XX_FACT		10		/* Multiply by 10	*/
+#define MPC8XX_XIN		5000000			/* 5 MHz in	*/
+#define MPC8XX_HZ ((MPC8XX_XIN) * (MPC8XX_FACT))
+
+#define	CONFIG_CLOCKS_IN_MHZ	1	/* clocks passsed to Linux in MHz */
+
+#if 0
+#define CONFIG_BOOTDELAY	-1	/* autoboot disabled		*/
+#else
+#define CONFIG_BOOTDELAY	5	/* autoboot after 5 seconds	*/
+#endif
+
+#define CONFIG_BOOTCOMMAND							\
+	"bootp;"								\
+	"setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) "	\
+	"ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off;"	\
+	"bootm"				/* autoboot command */
+
+#undef CONFIG_BOOTARGS
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#undef	CONFIG_KGDB_ON_SMC		/* define if kgdb on SMC */
+#define	CONFIG_KGDB_ON_SCC		/* define if kgdb on SCC */
+#undef	CONFIG_KGDB_NONE		/* define if kgdb on something else */
+#define CONFIG_KGDB_INDEX	1	/* which serial channel for kgdb */
+#define CONFIG_KGDB_BAUDRATE	9600	/* speed to run kgdb serial port at */
+#endif
+
+
+#undef	CONFIG_WATCHDOG			/* watchdog disabled		*/
+
+#define	CONFIG_SCC1_ENET	1	/* use SCC1 ethernet */
+
+#define	CONFIG_RTC_MPC8xx		/* use internal RTC of MPC8xx	*/
+
+#define CONFIG_COMMANDS	      ( CONFIG_CMD_DFL	| \
+				CFG_CMD_DHCP	| \
+				CFG_CMD_DATE	)
+
+#define CONFIG_BOOTP_MASK	(CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_BOOTFILESIZE)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP			/* undef to save memory		*/
+#define	CFG_PROMPT		"=> "	/* Monitor Command Prompt	*/
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define	CFG_CBSIZE	1024		/* Console I/O Buffer Size	*/
+#else
+#define	CFG_CBSIZE	256		/* Console I/O Buffer Size	*/
+#endif
+#define	CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define	CFG_MAXARGS	16		/* max number of command args	*/
+#define CFG_BARGSIZE	CFG_CBSIZE	/* Boot Argument Buffer Size	*/
+
+#define CFG_MEMTEST_START	0x0100000	/* memtest works on	*/
+#define CFG_MEMTEST_END		0x0200000	/* 1 ... 4 MB in DRAM	*/
+
+#define CFG_LOAD_ADDR	 	0x00100000
+
+#define	CFG_HZ		1000		/* decrementer freq: 1 ms ticks	*/
+
+#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+/*-----------------------------------------------------------------------
+ * Internal Memory Mapped Register
+ */
+#define CFG_IMMR			0xFF000000
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR	CFG_IMMR
+#define	CFG_INIT_RAM_END	0x2F00	/* End of used area in DPRAM	*/
+#define	CFG_GBL_DATA_SIZE	64  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET	(CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define	CFG_INIT_SP_OFFSET	CFG_GBL_DATA_OFFSET
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define	CFG_SDRAM_BASE		0x00000000
+#define CFG_FLASH_BASE		0x40000000
+#if defined(DEBUG)
+#define	CFG_MONITOR_LEN		(256 << 10)	/* Reserve 256 kB for Monitor	*/
+#else
+#define	CFG_MONITOR_LEN		(192 << 10)	/* Reserve 192 kB for Monitor	*/
+#endif
+#define CFG_MONITOR_BASE	CFG_FLASH_BASE
+#define	CFG_MALLOC_LEN		(128 << 10)	/* Reserve 128 kB for malloc()	*/
+
+/*
+ * U-Boot for AMX board supports two types of memory extension
+ * modules: one that provides 4 MB flash memory, and another one with
+ * 16 MB EDO DRAM.
+ *
+ * The flash module swaps the CS0 and CS1 signals: if the module is
+ * installed, CS0 is connected to Flash on the module and CS1 is
+ * connected to the on-board Flash. This means that you must intall
+ * U-Boot when the Flash module is plugged in, if you plan to use
+ * it.
+ *
+ * To enable support for the DRAM extension card, CONFIG_AMX_RAM_EXT
+ * must be defined. The DRAM module uses CS1.
+ *
+ * Only one of these modules may be installed at a time. If U-Boot
+ * is compiled with the CONFIG_AMX_RAM_EXT option set, it will not
+ * work if the Flash extension module is installed instead of the
+ * DRAM module.
+ */
+#define CONFIG_AMX_RAM_EXT	/* 16Mb Ext. DRAM module support */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ *
+ * Use 4 MB for without and 8 MB with 16 MB DRAM extension module
+ * (CONFIG_AMX_RAM_EXT)
+ */
+#ifdef CONFIG_AMX_RAM_EXT
+# define	CFG_BOOTMAPSZ	(8 << 20)	/* Initial Memory map for Linux	*/
+#else
+# define	CFG_BOOTMAPSZ	(4 << 20)	/* Initial Memory map for Linux	*/
+#endif
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS	2	/* max number of memory banks		*/
+#define CFG_MAX_FLASH_SECT	35	/* max number of sectors on one chip	*/
+
+#define CFG_FLASH_ERASE_TOUT	120000	/* Timeout for Flash Erase (in ms)	*/
+#define CFG_FLASH_WRITE_TOUT	500	/* Timeout for Flash Write (in ms)	*/
+
+#define	CFG_ENV_IS_IN_FLASH	1
+#define	CFG_ENV_OFFSET		0x8000	/*   Offset   of Environment Sector	*/
+#define	CFG_ENV_SIZE		0x4000	/* Total Size of Environment Sector	*/
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE	16	/* For all MPC8xx CPUs			*/
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT	4	/* log base 2 of the above value	*/
+#endif
+
+/*-----------------------------------------------------------------------
+ * SYPCR - System Protection Control					11-9
+ * SYPCR can only be written once after reset!
+ *-----------------------------------------------------------------------
+ * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze
+ */
+#if defined(CONFIG_WATCHDOG)
+#define CFG_SYPCR	(SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \
+			 SYPCR_SWE  | SYPCR_SWRI| SYPCR_SWP)
+#else
+#define CFG_SYPCR	(SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | SYPCR_SWP)
+#endif
+
+/*-----------------------------------------------------------------------
+ * SIUMCR - SIU Module Configuration					11-6
+ *-----------------------------------------------------------------------
+ * PCMCIA config., multi-function pin tri-state
+ */
+#define CFG_SIUMCR	(SIUMCR_DBGC00 | SIUMCR_DBPC00 | SIUMCR_MLRC01)
+
+/*-----------------------------------------------------------------------
+ * TBSCR - Time Base Status and Control					11-26
+ *-----------------------------------------------------------------------
+ * Clear Reference Interrupt Status, Timebase freezing enabled
+ */
+#define CFG_TBSCR	(TBSCR_REFA | TBSCR_REFB | TBSCR_TBE)
+
+/*-----------------------------------------------------------------------
+ * PISCR - Periodic Interrupt Status and Control		11-31
+ *-----------------------------------------------------------------------
+ * Clear Periodic Interrupt Status, Interrupt Timer freezing enabled
+ */
+#define CFG_PISCR	(PISCR_PS | PISCR_PITF)
+
+/*-----------------------------------------------------------------------
+ * PLPRCR - PLL, Low-Power, and Reset Control Register	15-30
+ *-----------------------------------------------------------------------
+ * set the PLL, the low-power modes and the reset control (15-29)
+ */
+#define CFG_PLPRCR	(((MPC8XX_FACT-1) << PLPRCR_MF_SHIFT) |	\
+				PLPRCR_SPLSS | PLPRCR_TEXPS | PLPRCR_TMIST)
+
+/*-----------------------------------------------------------------------
+ * SCCR - System Clock and reset Control Register		15-27
+ *-----------------------------------------------------------------------
+ * Set clock output, timebase and RTC source and divider,
+ * power management and some other internal clocks
+ */
+#define SCCR_MASK	SCCR_EBDF11
+#define CFG_SCCR	(SCCR_TBS|SCCR_COM00|SCCR_DFSYNC00|SCCR_DFBRG00|SCCR_DFNL000|SCCR_DFNH000|SCCR_DFLCD000|SCCR_DFALCD00)
+
+#define CFG_DER		0
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM	0x40000000	/* FLASH bank #0	*/
+#ifndef CONFIG_AMX_RAM_EXT
+#define FLASH_BASE1_PRELIM	0x60000000	/* FLASH bank #1	*/
+#endif
+
+#define CFG_REMAP_OR_AM		0x80000000	/* OR addr mask */
+#define CFG_PRELIM_OR_AM	0xFFC00000	/* OR addr mask */
+
+/* FLASH timing: ACS = 10, TRLX = 1, CSNT = 1, SCY = 3, EHTR = 0	*/
+/*				 0x00000800	0x00000400 0x00000100 0x00000030     0x00000004 */
+#define CFG_OR_TIMING_FLASH	(OR_CSNT_SAM  | OR_ACS_DIV4 | OR_BI | OR_SCY_5_CLK | OR_TRLX)
+
+#define CFG_OR0_REMAP	(CFG_REMAP_OR_AM  | CFG_OR_TIMING_FLASH)
+
+#define CFG_OR0_PRELIM	0xFFC00954	/* Real values for the board */
+#define CFG_BR0_PRELIM	0x40000001	/* Real values for the board */
+
+#ifndef CONFIG_AMX_RAM_EXT
+#define CFG_OR1_REMAP	CFG_OR0_REMAP
+#define CFG_OR1_PRELIM	0xFFC00954	/* Real values for the board */
+#define CFG_BR1_PRELIM	0x60000001	/* Real values for the board */
+#endif
+
+/* DSP ("Glue") Xilinx */
+#define CFG_OR6_PRELIM	0xFFFF8000	/* 32kB, 15 waits, cs after addr, no bursts */
+#define CFG_BR6_PRELIM	0x60000401	/* use GPCM for CS generation, 8 bit port */
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define	BOOTFLAG_COLD	0x01		/* Normal Power-On: Boot from FLASH	*/
+#define BOOTFLAG_WARM	0x02		/* Software reboot			*/
+
+#endif	/* __CONFIG_H */

+ 357 - 0
include/configs/SXNI855T.h

@@ -0,0 +1,357 @@
+/*
+ * U-Boot configuration for SIXNET SXNI855T CPU board.
+ * This board is based (loosely) on the Motorola FADS board, so this
+ * file is based (loosely) on config_FADS860T.h, see it for additional
+ * credits.
+ *
+ * Copyright (c) 2000-2002 Dave Ellis, SIXNET, dge@sixnetio.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
+ *
+ */
+
+/*
+ * Memory map:
+ *
+ *   ff100000 -> ff13ffff : FPGA        CS1
+ *   ff030000 -> ff03ffff : EXPANSION   CS7
+ *   ff020000 -> ff02ffff : DATA FLASH  CS4
+ *   ff018000 -> ff01ffff : UART B      CS6/UPMB
+ *   ff010000 -> ff017fff : UART A      CS5/UPMB
+ *   ff000000 -> ff00ffff : IMAP                   internal to the MPC855T
+ *   f8000000 -> fbffffff : FLASH       CS0        up to 64MB
+ *   f4000000 -> f7ffffff : NVSRAM      CS2        up to 64MB
+ *   00000000 -> 0fffffff : SDRAM       CS3/UPMA   up to 256MB
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#include <mpc8xx_irq.h>
+
+#define CONFIG_SXNI855T		1	/* SIXNET IPm 855T CPU module */
+
+/* The 855T is just a stripped 860T and needs code for 860, so for now
+ * at least define 860, 860T and 855T
+ */
+#define CONFIG_MPC860		1
+#define CONFIG_MPC860T		1
+#define CONFIG_MPC855T		1
+
+#define	CONFIG_8xx_CONS_SMC1	1	/* Console is on SMC1		*/
+#undef	CONFIG_8xx_CONS_SMC2
+#undef	CONFIG_8xx_CONS_SCC1
+#undef	CONFIG_8xx_CONS_NONE
+#define CONFIG_BAUDRATE		9600
+#define CONFIG_LOADS_ECHO	1	/* echo on for serial download	*/
+
+#define MPC8XX_FACT		10	/* 50 MHz is 5 MHz in times 10	*/
+
+#define	CONFIG_CLOCKS_IN_MHZ	1	/* clocks passsed to Linux in MHz */
+
+#if 0
+#define CONFIG_BOOTDELAY	-1	/* autoboot disabled		*/
+#else
+#define CONFIG_BOOTDELAY	5	/* autoboot after 5 seconds	*/
+#endif
+
+#define CONFIG_BOOTCOMMAND	"bootm f8040000 f8100000" /* autoboot command */
+#define CONFIG_BOOTARGS		"root=/dev/ram ip=off"
+
+#define CONFIG_MISC_INIT_R		/* have misc_init_r() function */
+#define CONFIG_BOARD_POSTCLK_INIT	/* have board_postclk_init() function */
+
+#undef	CONFIG_WATCHDOG			/* watchdog disabled		*/
+
+#define	CONFIG_RTC_DS1306		/* Dallas 1306 real time clock	*/
+
+#define	CONFIG_SOFT_I2C			/* I2C bit-banged		*/
+/*
+ * Software (bit-bang) I2C driver configuration
+ */
+#define PB_SCL		0x00000020	/* PB 26 */
+#define PB_SDA		0x00000010	/* PB 27 */
+
+#define I2C_INIT	(immr->im_cpm.cp_pbdir |=  PB_SCL)
+#define I2C_ACTIVE	(immr->im_cpm.cp_pbdir |=  PB_SDA)
+#define I2C_TRISTATE	(immr->im_cpm.cp_pbdir &= ~PB_SDA)
+#define I2C_READ	((immr->im_cpm.cp_pbdat & PB_SDA) != 0)
+#define I2C_SDA(bit)	if(bit) immr->im_cpm.cp_pbdat |=  PB_SDA; \
+			else    immr->im_cpm.cp_pbdat &= ~PB_SDA
+#define I2C_SCL(bit)	if(bit) immr->im_cpm.cp_pbdat |=  PB_SCL; \
+			else    immr->im_cpm.cp_pbdat &= ~PB_SCL
+#define I2C_DELAY	udelay(5)	/* 1/4 I2C clock duration */
+
+# define CFG_I2C_SPEED		50000
+# define CFG_I2C_SLAVE		0xFE
+# define CFG_I2C_EEPROM_ADDR	0x50	/* Atmel 24C64			*/
+# define CFG_I2C_EEPROM_ADDR_LEN 2	/* two byte address		*/
+
+#define	CONFIG_FEC_ENET		1	/* use FEC ethernet  */
+
+#define CFG_DISCOVER_PHY
+
+#define CONFIG_COMMANDS		(CONFIG_CMD_DFL | CFG_CMD_EEPROM | CFG_CMD_DATE)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define	CFG_LONGHELP			/* undef to save a little memory */
+#define	CFG_PROMPT		"=>"	/* Monitor Command Prompt	*/
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define	CFG_CBSIZE	1024		/* Console I/O Buffer Size	*/
+#else
+#define	CFG_CBSIZE	256		/* Console I/O Buffer Size	*/
+#endif
+#define	CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define	CFG_MAXARGS	16		/* max number of command args	*/
+#define CFG_BARGSIZE	CFG_CBSIZE	/* Boot Argument Buffer Size	*/
+
+#define CFG_MEMTEST_START	0x0100000	/* memtest works on	*/
+#define CFG_MEMTEST_END		0x0400000	/* 1 ... 4 MB in DRAM	*/
+
+#define CFG_LOAD_ADDR	 	0x00100000
+
+#define	CFG_HZ		1000		/* decrementer freq: 1 ms ticks	*/
+
+#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+/*-----------------------------------------------------------------------
+ * Internal Memory Mapped Register
+ */
+#define CFG_IMMR		0xFF000000
+#define CFG_IMMR_SIZE		((uint)(64 * 1024))
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR	CFG_IMMR
+#define	CFG_INIT_RAM_END	0x2F00	/* End of used area in DPRAM	*/
+#define	CFG_GBL_DATA_SIZE	64  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET	(CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define	CFG_INIT_SP_OFFSET	CFG_GBL_DATA_OFFSET
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define	CFG_SDRAM_BASE		0x00000000
+#define	CFG_SRAM_BASE		0xF4000000
+#define	CFG_SRAM_SIZE		0x04000000	/* autosize up to 64Mbyte */
+
+#define CFG_FLASH_BASE		0xF8000000
+#define CFG_FLASH_SIZE		((uint)(8 * 1024 * 1024))	/* max 8Mbyte */
+
+#define CFG_DFLASH_BASE		0xff020000 /* DiskOnChip or NAND FLASH */
+#define CFG_DFLASH_SIZE		0x00010000
+
+#define CFG_FPGA_BASE		0xFF100000	/* Xilinx FPGA */
+#define CFG_FPGA_PROG		0xFF130000	/* Programming address */
+#define CFG_FPGA_SIZE		0x00040000	/* 256KiB usable */
+
+#define	CFG_MONITOR_LEN		(256 << 10)	/* Reserve 256 kB for Monitor	*/
+#define CFG_MONITOR_BASE	CFG_FLASH_BASE
+#define	CFG_MALLOC_LEN		(128 << 10)	/* Reserve 128 kB for malloc()	*/
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define	CFG_BOOTMAPSZ		(8 << 20)	/* Initial Memory map for Linux	*/
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS	1	/* max number of memory banks		*/
+/* Intel 28F640 has 135, 127 64K sectors in 8MB, + 8 more for 8K boot blocks.
+ * AMD 29LV641 has 128 64K sectors in 8MB
+ */
+#define CFG_MAX_FLASH_SECT	135	/* max number of sectors on one chip	*/
+
+#define CFG_FLASH_ERASE_TOUT	120000	/* Timeout for Flash Erase (in ms)	*/
+#define CFG_FLASH_WRITE_TOUT	500	/* Timeout for Flash Write (in ms)	*/
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE	16	/* For all MPC8xx CPUs			*/
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT	4	/* log base 2 of the above value	*/
+#endif
+
+/*-----------------------------------------------------------------------
+ * SYPCR - System Protection Control					11-9
+ * SYPCR can only be written once after reset!
+ *-----------------------------------------------------------------------
+ * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze
+ */
+#if defined(CONFIG_WATCHDOG)
+#define CFG_SYPCR	(SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \
+			 SYPCR_SWE  | SYPCR_SWRI| SYPCR_SWP)
+#else
+#define CFG_SYPCR	(SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | SYPCR_SWP)
+#endif
+
+/*-----------------------------------------------------------------------
+ * SIUMCR - SIU Module Configuration					11-6
+ *-----------------------------------------------------------------------
+ * PCMCIA config., multi-function pin tri-state
+ */
+#define CFG_SIUMCR	(SIUMCR_DBGC00 | SIUMCR_DBPC00 | SIUMCR_MLRC01)
+
+/*-----------------------------------------------------------------------
+ * TBSCR - Time Base Status and Control					11-26
+ *-----------------------------------------------------------------------
+ * Clear Reference Interrupt Status, Timebase freezing enabled
+ */
+#define CFG_TBSCR	(TBSCR_REFA | TBSCR_REFB | TBSCR_TBE)
+
+/*-----------------------------------------------------------------------
+ * PISCR - Periodic Interrupt Status and Control		11-31
+ *-----------------------------------------------------------------------
+ * Clear Periodic Interrupt Status, Interrupt Timer freezing enabled
+ */
+#define CFG_PISCR	(PISCR_PS | PISCR_PITF)
+
+/*-----------------------------------------------------------------------
+ * PLPRCR - PLL, Low-Power, and Reset Control Register	15-30
+ *-----------------------------------------------------------------------
+ * set the PLL, the low-power modes and the reset control (15-29)
+ */
+#define CFG_PLPRCR	(((MPC8XX_FACT-1) << PLPRCR_MF_SHIFT) |	\
+				PLPRCR_SPLSS | PLPRCR_TEXPS | PLPRCR_TMIST)
+
+/*-----------------------------------------------------------------------
+ * SCCR - System Clock and reset Control Register		15-27
+ *-----------------------------------------------------------------------
+ * Set clock output, timebase and RTC source and divider,
+ * power management and some other internal clocks
+ */
+#define SCCR_MASK	SCCR_EBDF11
+#define CFG_SCCR	(SCCR_TBS|SCCR_COM00|SCCR_DFSYNC00|SCCR_DFBRG00|SCCR_DFNL000|SCCR_DFNH000|SCCR_DFLCD000|SCCR_DFALCD00)
+
+ /*-----------------------------------------------------------------------
+ *
+ *-----------------------------------------------------------------------
+ *
+ */
+#define CFG_DER		0
+
+/* Because of the way the 860 starts up and assigns CS0 the
+ * entire address space, we have to set the memory controller
+ * differently.  Normally, you write the option register
+ * first, and then enable the chip select by writing the
+ * base register.  For CS0, you must write the base register
+ * first, followed by the option register.
+ */
+
+/*
+ * Init Memory Controller:
+ *
+ **********************************************************
+ * BR0 and OR0 (FLASH)
+ */
+
+#define CFG_PRELIM_OR0_AM	0xFC000000	/* OR addr mask */
+
+/* FLASH timing: ACS = 10, TRLX = 1, CSNT = 1, SCY = 3, EHTR = 0	*/
+#define CFG_OR_TIMING_FLASH	(OR_CSNT_SAM  | OR_ACS_DIV4 | OR_BI | OR_SCY_3_CLK | OR_TRLX)
+
+#define CFG_OR0_PRELIM	(CFG_PRELIM_OR0_AM | CFG_OR_TIMING_FLASH)
+
+#define CONFIG_FLASH_16BIT
+#define CFG_BR0_PRELIM	((CFG_FLASH_BASE & BR_BA_MSK) | BR_PS_16 | BR_V )
+#define CFG_FLASH_PROTECTION	/* need to lock/unlock sectors in hardware */
+
+/**********************************************************
+ * BR1 and OR1 (FPGA)
+ * These preliminary values are also the final values.
+ */
+#define CFG_OR_TIMING_FPGA \
+	(OR_CSNT_SAM | OR_ACS_DIV2 | OR_BI | OR_SCY_5_CLK | OR_EHTR)
+#define CFG_BR1_PRELIM	((CFG_FPGA_BASE & BR_BA_MSK) | BR_PS_8 | BR_V )
+#define CFG_OR1_PRELIM	(((-CFG_FPGA_SIZE) & OR_AM_MSK) | CFG_OR_TIMING_FPGA)
+
+/**********************************************************
+ * BR4 and OR4 (data flash)
+ * These preliminary values are also the final values.
+ */
+#define CFG_OR_TIMING_DFLASH \
+	(OR_CSNT_SAM | OR_ACS_DIV4 | OR_BI | OR_SCY_5_CLK | OR_EHTR)
+#define CFG_BR4_PRELIM	((CFG_DFLASH_BASE & BR_BA_MSK) | BR_PS_8 | BR_V )
+#define CFG_OR4_PRELIM	(((-CFG_DFLASH_SIZE) & OR_AM_MSK) | CFG_OR_TIMING_DFLASH)
+
+/**********************************************************
+ * BR5/6 and OR5/6 (Dual UART)
+ */
+#define CFG_DUART_SIZE	0x8000	/* 32K window, only uses 8 bytes */
+#define CFG_DUARTA_BASE	0xff010000
+#define CFG_DUARTB_BASE	0xff018000
+
+#define DUART_MBMR	0
+#define DUART_OR_VALUE (ORMASK(CFG_DUART_SIZE) | OR_G5LS| OR_BI)
+#define DUART_BR_VALUE (BR_MS_UPMB | BR_PS_8 | BR_V)
+#define DUART_BR5_VALUE ((CFG_DUARTA_BASE & BR_BA_MSK ) | DUART_BR_VALUE)
+#define DUART_BR6_VALUE ((CFG_DUARTB_BASE & BR_BA_MSK ) | DUART_BR_VALUE)
+
+/**********************************************************
+ *
+ * Boot Flags
+ */
+#define	BOOTFLAG_COLD	0x01		/* Normal Power-On: Boot from FLASH	*/
+#define BOOTFLAG_WARM	0x02		/* Software reboot			*/
+
+#define CONFIG_RESET_ON_PANIC		/* reset if system panic() */
+
+/* to put environment in EEROM */
+#define	CFG_ENV_IS_IN_EEPROM	1
+#define CFG_ENV_OFFSET		0	/* Start right at beginning of NVRAM */
+#define CFG_ENV_SIZE		1024	/* Use only a part of it*/
+
+#if 1
+#define CONFIG_BOOT_RETRY_TIME	60	/* boot if no command in 60 seconds */
+#endif
+
+#if 1
+#define CONFIG_AUTOBOOT_KEYED		/* use key strings to stop autoboot */
+#define CONFIG_AUTOBOOT_PROMPT		"autoboot in %d seconds\n"
+#define CONFIG_AUTOBOOT_DELAY_STR	"delayabit"
+#define CONFIG_AUTOBOOT_STOP_STR	" " /* easy to stop for now */
+#endif
+
+#endif	/* __CONFIG_H */