--- /dev/null
+
+======================================================================
+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
+
+======================================================================
--- /dev/null
+#########################################################################
+# #
+# 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 #
+#########################################################################
--- /dev/null
+/*
+ * (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);
+}
+
+/*-----------------------------------------------------------------------
+ */
--- /dev/null
+
+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.
--- /dev/null
+/*
+ * 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;
+}
+
+/*-----------------------------------------------------------------------
+ */
--- /dev/null
+/*
+ * 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();
+}
+
--- /dev/null
+/*
+ * (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);
+}
--- /dev/null
+/*
+ * (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);
+}
+
+/*-----------------------------------------------------------------------
+ */
--- /dev/null
+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
--- /dev/null
+/*
+ * (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) */
--- /dev/null
+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.
+
--- /dev/null
+/*
+ * (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.
+
--- /dev/null
+/*
+ * (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
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * (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 */
--- /dev/null
+/*
+ * (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 */
--- /dev/null
+/*
+ * 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 */