]> git.sur5r.net Git - u-boot/commitdiff
Das U-Boot: Universal Boot Loader
authorwdenk <wdenk>
Sat, 2 Nov 2002 22:58:18 +0000 (22:58 +0000)
committerwdenk <wdenk>
Sat, 2 Nov 2002 22:58:18 +0000 (22:58 +0000)
17 files changed:
CHANGELOG [new file with mode: 0644]
MAINTAINERS [new file with mode: 0644]
board/cpu86/flash.c [new file with mode: 0644]
board/lwmon/README.keybd [new file with mode: 0644]
board/mousse/flash.c [new file with mode: 0644]
board/mousse/m48t59y.c [new file with mode: 0644]
board/pm826/flash.c [new file with mode: 0644]
board/sacsng/flash.c [new file with mode: 0644]
board/sandpoint/README [new file with mode: 0644]
disk/part_iso.c [new file with mode: 0644]
doc/README.OXC [new file with mode: 0644]
doc/README.autoboot [new file with mode: 0644]
doc/README.console [new file with mode: 0644]
drivers/bcm570x.c [new file with mode: 0644]
include/cmd_disk.h [new file with mode: 0644]
include/configs/AMX860.h [new file with mode: 0644]
include/configs/SXNI855T.h [new file with mode: 0644]

diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644 (file)
index 0000000..094060f
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,12 @@
+
+======================================================================
+Notes for U-Boot 1.0.0:
+======================================================================
+
+This is the initial version of "Das U-Boot", the Universal Boot Loader.
+
+It is based on version 2.0.0 (the "Halloween Release") of PPCBoot.
+For information about the history of the project please see the
+PPCBoot project page at http://sourceforge.net/projects/ppcboot
+
+======================================================================
diff --git a/MAINTAINERS b/MAINTAINERS
new file mode 100644 (file)
index 0000000..de37086
--- /dev/null
@@ -0,0 +1,249 @@
+#########################################################################
+#                                                                      #
+# Regular Maintainers for U-Boot board support:                                #
+#                                                                      #
+# For any board without permanent maintainer, please contact           #
+#    for PowerPC systems:                                              #
+#      Wolfgang Denk <wd@denx.de>                                      #
+#    for ARM systems:                                                  #
+#      Marius Gröger <mag@sysgo.de>                                    #
+# and Cc: the <U-Boot-Users@lists.sourceforge.net> mailing lists.      #
+#                                                                      #
+# Note: lists sorted by Maintainer Name                                        #
+#########################################################################
+
+
+#########################################################################
+#                                                                      #
+# Maintainer Name, Email Address                                       #
+#      Board                   CPU                                     #
+#########################################################################
+
+Greg Allen <gallen@arlut.utexas.edu>
+
+       UTX8245                 MPC8245
+
+Pantelis Antoniou <panto@intracom.gr>
+
+       NETVIA                  MPC8xx
+
+Jerry Van Baren <vanbaren_gerald@si.com>
+
+       sacsng                  MPC8260
+
+Oliver Brown <obrown@adventnetworks.com>
+
+       sbc8260                 MPC8260
+       gw8260                  MPC8260
+
+Conn Clark <clark@esteem.com>
+
+       ESTEEM192E              MPC8xx
+
+Kári Davíðsson <kd@flaga.is>
+
+       FLAGADM                 MPC823
+
+Wolfgang Denk <wd@denx.de>
+
+       AMX860                  MPC860
+       ETX094                  MPC850
+       FPS850L                 MPC850
+       ICU862                  MPC862
+       IP860                   MPC860
+       IVML24                  MPC860
+       IVML24_128              MPC860
+       IVML24_256              MPC860
+       IVMS8                   MPC860
+       IVMS8_128               MPC860
+       IVMS8_256               MPC860
+       LANTEC                  MPC850
+       RRvision                MPC823
+       SM850                   MPC850
+       SPD823TS                MPC823
+       TQM823L                 MPC823
+       TQM823L_LCD             MPC823
+       TQM850L                 MPC850
+       TQM855L                 MPC855
+       TQM860L                 MPC860
+       TQM860L_FEC             MPC860
+       c2mon                   MPC855
+       hermes                  MPC860
+       lwmon                   MPC823
+       pcu_e                   MPC855
+
+       CU824                   MPC8240
+       Sandpoint8240           MPC8240
+
+       CPU86                   MPC8260
+       PM826                   MPC8260
+       TQM8260                 MPC8260
+
+       PCIPPC2                 MPC750
+       PCIPPC6                 MPC750
+
+Jon Diekema <diekema_jon@si.com>
+
+       sbc8260                 MPC8260
+
+Dave Ellis <DGE@sixnetio.com>
+
+       SXNI855T                MPC8xx
+
+Frank Gottschling <fgottschling@eltec.de>
+
+       MHPC                    MPC8xx
+
+       BAB7xx                  MPC740/MPC750
+
+Wolfgang Grandegger <wg@denx.de>
+
+       CCM                     MPC855
+
+       PN62                    MPC8240
+
+       IPHASE4539              MPC8260
+       SCM                     MPC8260
+
+Howard Gray <mvsensor@matrix-vision.de>
+
+       MVS1                    MPC823
+
+Murray Jensen <Murray.Jensen@cmst.csiro.au>
+
+       cogent_mpc8xx           MPC8xx
+
+       cogent_mpc8260          MPC8260
+       hymod                   MPC8260
+
+Brad Kemp <Brad.Kemp@seranoa.com>
+
+       ppmc8260                MPC8260
+
+Nye Liu <nyet@zumanetworks.com>
+
+       ZUMA                    MPC7xx_74xx
+
+Thomas Lange <thomas@corelatus.com>
+
+       GTH                     MPC860
+
+Eran Man <eran@nbase.co.il>
+
+       EVB64260_750CX          MPC750CX
+
+Scott McNutt <smcnutt@artesyncp.com>
+
+       EBONY                   PPC440GP
+
+Keith Outwater <Keith_Outwater@mvis.com>
+
+       GEN860T                 MPC860T
+
+Frank Panno <fpanno@delphintech.com>
+
+       ep8260                  MPC8260
+
+Denis Peter <d.peter@mpl.ch>
+
+       MIP405                  PPC4xx
+       PIP405                  PPC4xx
+
+Stefan Roese <stefan.roese@esd-electronics.com>
+
+       ADCIOP                  IOP480 (PPC401)
+       AR405                   PPC405GP
+       CANBT                   PPC405CR
+       CPCI405                 PPC405GP
+       CPCI440                 PPC440GP
+       CPCIISER4               PPC405GP
+       DASA_SIM                IOP480 (PPC401)
+       DU405                   PPC405GP
+       OCRTC                   PPC405GP
+       ORSG                    PPC405GP
+
+Peter De Schrijver <p2@mind.be>
+
+       ML2                     PPC4xx
+
+Erik Theisen <etheisen@mindspring.com>
+
+       W7OLMC                  PPC4xx
+       W7OLMG                  PPC4xx
+
+Jim Thompson <jim@musenki.com>
+
+       MUSENKI                 MPC8245/8241
+       Sandpoint8245           MPC8245
+
+-------------------------------------------------------------------------
+
+Unknown / orphaned boards:
+
+       ADS860                  MPC8xx
+       FADS823                 MPC8xx
+       FADS850SAR              MPC8xx
+       FADS860T                MPC8xx
+       GENIETV                 MPC8xx
+       IAD210                  MPC8xx
+       MBX                     MPC8xx
+       MBX860T                 MPC8xx
+       NX823                   MPC8xx
+       RPXClassic              MPC8xx
+       RPXlite                 MPC8xx
+
+       CRAYL1                  PPC4xx
+       ERIC                    PPC4xx
+       WALNUT405               PPC4xx
+
+       MOUSSE                  MPC824x
+
+       MPC8260ADS              MPC8260
+       RPXsuper                MPC8260
+       rsdproto                MPC8260
+
+       EVB64260                MPC7xx_74xx
+
+
+#########################################################################
+# ARM Systems:                                                         #
+#                                                                      #
+# Maintainer Name, Email Address                                       #
+#      Board                   CPU                                     #
+#########################################################################
+
+Marius Gröger <mag@sysgo.de>
+
+       impa7                   ARM720T (EP7211)
+       ep7312                  ARM720T (EP7312)
+
+Kyle Harris <kharris@nexus-tech.net>
+
+       lubbock                 xscale
+       cradle                  xscale
+
+Gary Jennejohn <gj@denx.de>
+
+       smdk2400                ARM920T
+       trab                    ARM920T
+
+David Müller <d.mueller@elsoft.ch>
+
+       smdk2410                ARM920T
+
+Rolf Offermanns <rof@sysgo.de>
+
+       shannon                 SA1100
+
+Robert Schwebel <r.schwebel@pengutronix.de>
+
+       csb226                  xscale
+
+Alex Züpke <azu@sysgo.de>
+
+       lart                    SA1100
+       dnp1110                 SA1110
+
+#########################################################################
+# End of MAINTAINERS list                                              #
+#########################################################################
diff --git a/board/cpu86/flash.c b/board/cpu86/flash.c
new file mode 100644 (file)
index 0000000..8cf761f
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * (C) Copyright 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for Intel devices
+ *
+ *--------------------------------------------------------------------
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include "cpu86.h"
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+/*-----------------------------------------------------------------------
+ */
+ulong flash_int_get_size (volatile unsigned long *baseaddr,
+                                         flash_info_t * info)
+{
+       short i;
+       unsigned long flashtest_h, flashtest_l;
+
+       info->sector_count = info->size = 0;
+       info->flash_id = FLASH_UNKNOWN;
+
+       /* Write query command sequence and test FLASH answer
+        */
+       baseaddr[0] = 0x00980098;
+       baseaddr[1] = 0x00980098;
+
+       flashtest_h = baseaddr[0];      /* manufacturer ID      */
+       flashtest_l = baseaddr[1];
+
+       if (flashtest_h != INTEL_MANUFACT || flashtest_l != INTEL_MANUFACT)
+               return (0);             /* no or unknown flash  */
+
+       flashtest_h = baseaddr[2];      /* device ID            */
+       flashtest_l = baseaddr[3];
+
+       if (flashtest_h != flashtest_l)
+               return (0);
+
+       switch (flashtest_h) {
+       case INTEL_ID_28F160C3B:
+               info->flash_id = FLASH_28F160C3B;
+               info->sector_count = 39;
+               info->size = 0x00800000;        /* 4 * 2 MB = 8 MB      */
+               break;
+       case INTEL_ID_28F160F3B:
+               info->flash_id = FLASH_28F160F3B;
+               info->sector_count = 39;
+               info->size = 0x00800000;        /* 4 * 2 MB = 8 MB      */
+               break;
+       default:
+               return (0);                     /* no or unknown flash  */
+       }
+
+       info->flash_id |= INTEL_MANUFACT << 16; /* set manufacturer offset */
+
+       if (info->flash_id & FLASH_BTYPE) {
+               volatile unsigned long *tmp = baseaddr;
+
+               /* set up sector start adress table (bottom sector type)
+                * AND unlock the sectors (if our chip is 160C3)
+                */
+               for (i = 0; i < info->sector_count; i++) {
+                       if ((info->flash_id & FLASH_TYPEMASK) == FLASH_28F160C3B) {
+                               tmp[0] = 0x00600060;
+                               tmp[1] = 0x00600060;
+                               tmp[0] = 0x00D000D0;
+                               tmp[1] = 0x00D000D0;
+                       }
+                       info->start[i] = (uint) tmp;
+                       tmp += i < 8 ? 0x2000 : 0x10000; /* pointer arith       */
+               }
+       }
+
+       memset (info->protect, 0, info->sector_count);
+
+       baseaddr[0] = 0x00FF00FF;
+       baseaddr[1] = 0x00FF00FF;
+
+       return (info->size);
+}
+
+static ulong flash_amd_get_size (vu_char *addr, flash_info_t *info)
+{
+       short i;
+       uchar vendor, devid;
+       ulong base = (ulong)addr;
+
+       /* Write auto select command: read Manufacturer ID */
+       addr[0x0555] = 0xAA;
+       addr[0x02AA] = 0x55;
+       addr[0x0555] = 0x90;
+
+       udelay(1000);
+
+       vendor = addr[0];
+       devid = addr[1] & 0xff;
+
+       /* only support AMD */
+       if (vendor != 0x01) {
+               return 0;
+       }
+
+       vendor &= 0xf;
+       devid &= 0xff;
+
+       if (devid == AMD_ID_F040B) {
+               info->flash_id     = vendor << 16 | devid;
+               info->sector_count = 8;
+               info->size         = info->sector_count * 0x10000;
+       }
+       else if (devid == AMD_ID_F080B) {
+               info->flash_id     = vendor << 16 | devid;
+               info->sector_count = 16;
+               info->size         = 4 * info->sector_count * 0x10000;
+       }
+       else if (devid == AMD_ID_F016D) {
+               info->flash_id     = vendor << 16 | devid;
+               info->sector_count = 32;
+               info->size         = 4 * info->sector_count * 0x10000;
+       }
+       else {
+               printf ("## Unknown Flash Type: %02x\n", devid);
+               return 0;
+       }
+
+       /* check for protected sectors */
+       for (i = 0; i < info->sector_count; i++) {
+               /* sector base address */
+               info->start[i] = base + i * (info->size / info->sector_count);
+               /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+               /* D0 = 1 if protected */
+               addr = (volatile unsigned char *)(info->start[i]);
+               info->protect[i] = addr[2] & 1;
+       }
+
+       /*
+        * Prevent writes to uninitialized FLASH.
+        */
+       if (info->flash_id != FLASH_UNKNOWN) {
+               addr = (vu_char *)info->start[0];
+               addr[0] = 0xF0; /* reset bank */
+       }
+
+       return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+       unsigned long size_b0 = 0;
+       unsigned long size_b1 = 0;
+       int i;
+
+       /* Init: no FLASHes known
+        */
+       for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+               flash_info[i].flash_id = FLASH_UNKNOWN;
+       }
+
+       /* Disable flash protection */
+       CPU86_BCR |= (CPU86_BCR_FWPT | CPU86_BCR_FWRE);
+
+       /* Static FLASH Bank configuration here (only one bank) */
+
+       size_b0 = flash_int_get_size ((ulong *) CFG_FLASH_BASE, &flash_info[0]);
+       size_b1 = flash_amd_get_size ((uchar *) CFG_BOOTROM_BASE, &flash_info[1]);
+
+       if (size_b0 > 0 || size_b1 > 0) {
+
+               printf("(");
+
+               if (size_b0 > 0) {
+                       puts ("Bank#1 - ");
+                       print_size (size_b0, (size_b1 > 0) ? ", " : ") ");
+               }
+
+               if (size_b1 > 0) {
+                       puts ("Bank#2 - ");
+                       print_size (size_b1, ") ");
+               }
+       }
+       else {
+               printf ("## No FLASH found.\n");
+               return 0;
+       }
+       /* protect monitor and environment sectors
+        */
+
+#if CFG_MONITOR_BASE >= CFG_BOOTROM_BASE
+       if (size_b1) {
+               /* If U-Boot is booted from ROM the CFG_MONITOR_BASE > CFG_FLASH_BASE
+                * but we shouldn't protect it.
+                */
+
+               flash_protect  (FLAG_PROTECT_SET,
+                               CFG_MONITOR_BASE,
+                               CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, &flash_info[1]
+               );
+       }
+#else
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+       flash_protect (FLAG_PROTECT_SET,
+                      CFG_MONITOR_BASE,
+                      CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, &flash_info[0]
+       );
+#endif
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
+# endif
+# if CFG_ENV_ADDR >= CFG_BOOTROM_BASE
+       if (size_b1) {
+               flash_protect (FLAG_PROTECT_SET,
+                               CFG_ENV_ADDR,
+                               CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[1]);
+       }
+# else
+       flash_protect (FLAG_PROTECT_SET,
+                      CFG_ENV_ADDR,
+                      CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
+# endif
+#endif
+
+       return (size_b0 + size_b1);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+       int i;
+
+       if (info->flash_id == FLASH_UNKNOWN) {
+               printf ("missing or unknown FLASH type\n");
+               return;
+       }
+
+       switch ((info->flash_id >> 16) & 0xff) {
+       case 0x89:
+               printf ("INTEL ");
+               break;
+       case 0x1:
+               printf ("AMD ");
+               break;
+       default:
+               printf ("Unknown Vendor ");
+               break;
+       }
+
+       switch (info->flash_id & FLASH_TYPEMASK) {
+       case FLASH_28F160C3B:
+               printf ("28F160C3B (16 Mbit, bottom sector)\n");
+               break;
+       case FLASH_28F160F3B:
+               printf ("28F160F3B (16 Mbit, bottom sector)\n");
+               break;
+       case AMD_ID_F040B:
+               printf ("AM29F040B (4 Mbit)\n");
+               break;
+       default:
+               printf ("Unknown Chip Type\n");
+               break;
+       }
+
+       if (info->size < 0x100000)
+               printf ("  Size: %ld KB in %d Sectors\n",
+                               info->size >> 10, info->sector_count);
+       else
+               printf ("  Size: %ld MB in %d Sectors\n",
+                               info->size >> 20, info->sector_count);
+
+       printf ("  Sector Start Addresses:");
+       for (i = 0; i < info->sector_count; ++i) {
+               if ((i % 5) == 0)
+                       printf ("\n   ");
+               printf (" %08lX%s",
+                       info->start[i],
+                       info->protect[i] ? " (RO)" : "     "
+               );
+       }
+       printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+       vu_char *addr = (vu_char *)(info->start[0]);
+       int flag, prot, sect, l_sect;
+       ulong start, now, last;
+
+       if ((s_first < 0) || (s_first > s_last)) {
+               if (info->flash_id == FLASH_UNKNOWN) {
+                       printf ("- missing\n");
+               } else {
+                       printf ("- no sectors to erase\n");
+               }
+               return 1;
+       }
+
+       prot = 0;
+       for (sect = s_first; sect <= s_last; sect++) {
+               if (info->protect[sect])
+                       prot++;
+       }
+
+       if (prot) {
+               printf ("- Warning: %d protected sectors will not be erased!\n",
+                               prot);
+       } else {
+               printf ("\n");
+       }
+
+       /* Check the type of erased flash
+        */
+       if (info->flash_id >> 16 == 0x1) {
+               /* Erase AMD flash
+                */
+               l_sect = -1;
+
+               /* Disable interrupts which might cause a timeout here */
+               flag = disable_interrupts();
+
+               addr[0x0555] = 0xAA;
+               addr[0x02AA] = 0x55;
+               addr[0x0555] = 0x80;
+               addr[0x0555] = 0xAA;
+               addr[0x02AA] = 0x55;
+
+               /* wait at least 80us - let's wait 1 ms */
+               udelay (1000);
+
+               /* Start erase on unprotected sectors */
+               for (sect = s_first; sect<=s_last; sect++) {
+                       if (info->protect[sect] == 0) { /* not protected */
+                               addr = (vu_char *)(info->start[sect]);
+                               addr[0] = 0x30;
+                               l_sect = sect;
+                       }
+               }
+
+               /* re-enable interrupts if necessary */
+               if (flag)
+                       enable_interrupts();
+
+               /* wait at least 80us - let's wait 1 ms */
+               udelay (1000);
+
+               /*
+                * We wait for the last triggered sector
+                */
+               if (l_sect < 0)
+                       goto AMD_DONE;
+
+               start = get_timer (0);
+               last  = start;
+               addr = (vu_char *)(info->start[l_sect]);
+               while ((addr[0] & 0x80) != 0x80) {
+                       if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+                               printf ("Timeout\n");
+                               return 1;
+                       }
+                       /* show that we're waiting */
+                       if ((now - last) > 1000) {      /* every second */
+                               serial_putc ('.');
+                               last = now;
+                       }
+               }
+
+AMD_DONE:
+               /* reset to read mode */
+               addr = (volatile unsigned char *)info->start[0];
+               addr[0] = 0xF0;     /* reset bank */
+
+       } else {
+               /* Erase Intel flash
+                */
+
+               /* Start erase on unprotected sectors
+                */
+               for (sect = s_first; sect <= s_last; sect++) {
+                       volatile ulong *addr =
+                               (volatile unsigned long *) info->start[sect];
+
+                       start = get_timer (0);
+                       last = start;
+                       if (info->protect[sect] == 0) {
+                       /* Disable interrupts which might cause a timeout here
+                        */
+                               flag = disable_interrupts ();
+
+                               /* Erase the block
+                                */
+                               addr[0] = 0x00200020;
+                               addr[1] = 0x00200020;
+                               addr[0] = 0x00D000D0;
+                               addr[1] = 0x00D000D0;
+
+                               /* re-enable interrupts if necessary
+                                */
+                               if (flag)
+                                       enable_interrupts ();
+
+                               /* wait at least 80us - let's wait 1 ms
+                                */
+                               udelay (1000);
+
+                               last = start;
+                               while ((addr[0] & 0x00800080) != 0x00800080 ||
+                                  (addr[1] & 0x00800080) != 0x00800080) {
+                                       if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
+                                               printf ("Timeout (erase suspended!)\n");
+                                               /* Suspend erase
+                                                */
+                                               addr[0] = 0x00B000B0;
+                                               addr[1] = 0x00B000B0;
+                                               goto DONE;
+                                       }
+                                       /* show that we're waiting
+                                        */
+                                       if ((now - last) > 1000) {      /* every second */
+                                               serial_putc ('.');
+                                               last = now;
+                                       }
+                               }
+                               if (addr[0] & 0x00220022 || addr[1] & 0x00220022) {
+                                       printf ("*** ERROR: erase failed!\n");
+                                       goto DONE;
+                               }
+                       }
+                       /* Clear status register and reset to read mode
+                        */
+                       addr[0] = 0x00500050;
+                       addr[1] = 0x00500050;
+                       addr[0] = 0x00FF00FF;
+                       addr[1] = 0x00FF00FF;
+               }
+       }
+
+       printf (" done\n");
+
+DONE:
+       return 0;
+}
+
+static int write_word (flash_info_t *, volatile unsigned long *, ulong);
+static int write_byte (flash_info_t *info, ulong dest, uchar data);
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+       ulong v;
+       int i, l, rc, cc = cnt, res = 0;
+
+       if (info->flash_id >> 16 == 0x1) {
+
+               /* Write to AMD 8-bit flash
+                */
+               while (cnt > 0) {
+                       if ((rc = write_byte(info, addr, *src)) != 0) {
+                               return (rc);
+                       }
+                       addr++;
+                       src++;
+                       cnt--;
+               }
+
+               return (0);
+       } else {
+
+               /* Write to Intel 64-bit flash
+                */
+               for (v=0; cc > 0; addr += 4, cc -= 4 - l) {
+                       l = (addr & 3);
+                       addr &= ~3;
+
+                       for (i = 0; i < 4; i++) {
+                               v = (v << 8) + (i < l || i - l >= cc ?
+                                       *((unsigned char *) addr + i) : *src++);
+                       }
+
+                       if ((res = write_word (info, (volatile unsigned long *) addr, v)) != 0)
+                               break;
+               }
+       }
+
+       return (res);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t * info, volatile unsigned long *addr,
+                                          ulong data)
+{
+       int flag, res = 0;
+       ulong start;
+
+       /* Check if Flash is (sufficiently) erased
+        */
+       if ((*addr & data) != data)
+               return (2);
+
+       /* Disable interrupts which might cause a timeout here
+        */
+       flag = disable_interrupts ();
+
+       *addr = 0x00400040;
+       *addr = data;
+
+       /* re-enable interrupts if necessary
+        */
+       if (flag)
+               enable_interrupts ();
+
+       start = get_timer (0);
+       while ((*addr & 0x00800080) != 0x00800080) {
+               if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
+                       /* Suspend program
+                        */
+                       *addr = 0x00B000B0;
+                       res = 1;
+                       goto OUT;
+               }
+       }
+
+       if (*addr & 0x00220022) {
+               printf ("*** ERROR: program failed!\n");
+               res = 1;
+       }
+
+OUT:
+       /* Clear status register and reset to read mode
+        */
+       *addr = 0x00500050;
+       *addr = 0x00FF00FF;
+
+       return (res);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a byte to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_byte (flash_info_t *info, ulong dest, uchar data)
+{
+       vu_char *addr = (vu_char *)(info->start[0]);
+       ulong start;
+       int flag;
+
+       /* Check if Flash is (sufficiently) erased */
+       if ((*((vu_char *)dest) & data) != data) {
+               return (2);
+       }
+       /* Disable interrupts which might cause a timeout here */
+       flag = disable_interrupts();
+
+       addr[0x0555] = 0xAA;
+       addr[0x02AA] = 0x55;
+       addr[0x0555] = 0xA0;
+
+       *((vu_char *)dest) = data;
+
+       /* re-enable interrupts if necessary */
+       if (flag)
+               enable_interrupts();
+
+       /* data polling for D7 */
+       start = get_timer (0);
+       while ((*((vu_char *)dest) & 0x80) != (data & 0x80)) {
+               if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+                       return (1);
+               }
+       }
+       return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/lwmon/README.keybd b/board/lwmon/README.keybd
new file mode 100644 (file)
index 0000000..bf759c6
--- /dev/null
@@ -0,0 +1,127 @@
+
+Tastaturabfrage:
+
+Die Implementierung / Decodierung beruht auf den Angaben aus dem  Do-
+kument  "PIC LWE-Tastatur" in der Fassung vom 9. 3. 2001, insbesonde-
+re Tabelle 3 im Kapitel 4.3 Tastencodes. In  U-Boot  werden  die  vom
+Keyboard-Controller  gelesenen Daten hexadezimal codiert in der auto-
+matisch angelegten Environment-Variablen "keybd" übergeben. Ist  kei-
+ne Taste gedrückt worden, steht dort:
+
+       keybd=000000000000000000
+
+Der decodierte Tastencode ("keybd") kann mit den  "bootargs"  an  den
+Linux-Kernel  übergeben  und  dort z. B. in einem Device-Treiber oder
+einer Applikation ausgewertet werden.
+
+
+
+Sonderfunktionen beim Booten:
+
+Es lassen sich eine oder mehrere (beliebig viele) Tasten oder Tasten-
+kombinationen definieren, die Sonderfunktionen auslösen,  wenn  diese
+Tasten beim Booten (Reset) gedrückt sind.
+
+Wird eine eingestellte Taste bzw. Tastenkombination erkannt, so  wird
+in  U-Boot noch vor dem Start des "Countdown" und somit vor jedem an-
+deren Kommando der Inhalt einer dieser Taste  bzw.  Tastenkombination
+zugeordneten Environment-Variablen ausführen.
+
+
+Die Environment-Variable "magic_keys" wird als Liste von Zeichen ver-
+standen, die als Suffix an den Namen "key_magic" angefügt werden  und
+so  die  Namen  der  Environment-Variablen  definieren, mit denen die
+Tasten (-kombinationen) festgelegt werden:
+
+Ist "magic_keys" NICHT definiert, so wird nur die in der Environment-
+Variablen "key_magic" codierte  Tasten  (-kombination)  geprüft,  und
+ggf.  der  Inhalt der Environment-Variablen "key_cmd" ausgeführt (ge-
+nauer: der Inhalt von "key_cmd" wird der Variablen "preboot" zugewie-
+sen, die ausgeführt wird, unmittelbar bevor die interaktive Kommando-
+interpretation beginnt).
+
+Enthält "magic_keys" z. B.  die  Zeichenkette  "0123CB*",  so  werden
+nacheinander folgende Aktionen ausgeführt:
+
+       prüfe Tastencode        ggf. führe aus Kommando
+       in Variable             in Variable
+       -----------------------------------
+       key_magic0      ==>     key_cmd0
+       key_magic1      ==>     key_cmd1
+       key_magic2      ==>     key_cmd2
+       key_magic3      ==>     key_cmd3
+       key_magicC      ==>     key_cmdC
+       key_magicB      ==>     key_cmdB
+       key_magicA      ==>     key_cmdA
+       key_magic*      ==>     key_cmd*
+
+Hinweis: sobald ein aktivierter Tastencode erkannt  wurde,  wird  die
+Bearbeitung  abgebrochen; es wird daher höchstens eines der definier-
+ten Kommandos ausgeführt, wobei die Priorität durch  die  Suchreihen-
+folge  festgelegt wird, also durch die Reihenfolge der Zeichen in der
+Varuiablen "magic_keys".
+
+
+Die Codierung der Tasten, die beim Booten gedrückt werden müssen, um
+eine Funktion auszulösen, erfolgt nach der Tastaturtabelle.
+
+Die Definitionen
+
+       => setenv key_magic0 3a+3b
+       => setenv key_cmd0 setenv bootdelay 30
+
+bedeuten dementsprechend, daß die Tasten mit den  Codes  0x3A  (Taste
+"F1")  und 0x3B (Taste "F2") gleichzeitig gedrückt werden müssen. Sie
+können dort eine beliebige  Tastenkombination  eintragen  (jeweils  2
+Zeichen für die Hex-Codes der Tasten, und '+' als Trennzeichen).
+
+Wird die eingestellte Tastenkombination erkannt, so  wird  in  U-Boot
+noch  vor  dem Start des "Countdown" und somit vor jedem anderen Kom-
+mando das angebene Kommando ausgeführt und  somit  ein  langes  Boot-
+Delay eingetragen.
+
+Praktisch könnten Sie also in U-Boot "bootdelay"  auf  0  setzen  und
+somit  stets  ohne  jede  User-Interaktion automatisch booten, außer,
+wenn die beiden Tasten "F1" und "F2"  beim  Booten  gedrückt  werden:
+dann würde ein Boot-Delay von 30 Sekunden eingefügt.
+
+
+Hinweis: dem Zeichen '#' kommt innerhalb von "magic_keys" eine beson-
+dere Bedeutung zu: die dadurch definierte  Key-Sequenz  schaltet  den
+Monitor in den "Debug-Modus" - das bedeutet zunächst, daß alle weite-
+ren  Meldungen  von  U-Boot  über  das LCD-Display ausgegeben werden;
+außerdem kann man durch das mit dieser  Tastenkombination  verknüpfte
+Kommando  z. B. die Linux-Bootmeldungen ebenfalls auf das LCD-Display
+legen, so daß der Boot-Vorgang direkt und  ohne  weitere  Hilfsmittel
+analysiert werden kann.
+
+Beispiel:
+
+In U-Boot werden folgende Environment-Variablen gesetzt und abgespei-
+chert:
+
+(1)    => setenv magic_keys 01234#X
+(2)    => setenv key_cmd# setenv addfb setenv bootargs \\$(bootargs) console=tty0 console=ttyS1,\\$(baudrate)
+(3)    => setenv nfsargs setenv bootargs root=/dev/nfs rw nfsroot=\$(serverip):\$(rootpath)
+(4)    => setenv addip setenv bootargs \$(bootargs) ip=\$(ipaddr):\$(serverip):\$(gatewayip):\$(netmask):\$(hostname)::off panic=1
+(5)    => setenv addfb setenv bootargs \$(bootargs) console=ttyS1,\$(baudrate)
+(6)    => setenv bootcmd bootp\;run nfsargs\;run addip\;run addfb\;bootm
+
+Hierbei wird die Linux Commandline (in der Variablen  "bootargs")  im
+Boot-Kommando  "bootcmd"  (6)  schrittweise zusammengesetzt: zunächst
+werden die für Root-Filesystem über NFS erforderlichen  Optionen  ge-
+setzt  ("run  nfsargs", vgl. (3)), dann die Netzwerkkonfiguration an-
+gefügt ("run addip", vgl. (4)),  und  schließlich  die  Systemconsole
+definiert ("run addfb").
+
+Dabei wird im Normalfall die Definition (5)  verwendt;  wurde  aller-
+dings  beim  Reset die entsprechende Taste gedrückt gehalten, so wird
+diese Definition bei der Ausführung des in (2) definierten  Kommandos
+überschrieben,  so  daß  Linux die Bootmeldungen auch über das Frame-
+buffer-Device (=LCD-Display) ausgibt.
+
+Beachten Sie die Verdoppelung der '\'-Escapes in der  Definition  von
+"key_cmd#" - diese ist erforderlich, weil der String _zweimal_ inter-
+pretiert  wird:  das  erste  Mal  bei der Eingabe von "key_cmd#", das
+zweite Mal, wenn der String (als  Inhalt  von  "preboot")  ausgeführt
+wird.
diff --git a/board/mousse/flash.c b/board/mousse/flash.c
new file mode 100644 (file)
index 0000000..3c4a802
--- /dev/null
@@ -0,0 +1,944 @@
+/*
+ * MOUSSE/MPC8240 Board definitions.
+ * Flash Routines for MOUSSE onboard AMD29LV106DB devices
+ *
+ * (C) Copyright 2000
+ * Marius Groeger <mgroeger@sysgo.de>
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 1999, by Curt McDowell, 08-06-99, Broadcom Corp.
+ * (C) Copyright 2001, James Dougherty, 07/18/01, Broadcom Corp.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <malloc.h>
+#include "mousse.h"
+#include "flash.h"
+
+int flashLibDebug = 0;
+int flashLibInited = 0;
+
+#define OK  0
+#define ERROR -1
+#define STATUS int
+#define PRINTF                 if (flashLibDebug) printf
+#if 0
+#define PRIVATE                        static
+#else
+#define PRIVATE
+#endif
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+#define SLEEP_DELAY    166
+#define FLASH_SECTOR_SIZE   (64*1024)
+/***********************************************************************
+ *
+ * Virtual Flash Devices on Mousse board
+ *
+ * These must be kept in sync with the definitions in flashLib.h.
+ *
+ ***********************************************************************/
+
+PRIVATE flash_dev_t flashDev[] = {
+    /* Bank 0 sector SA0 (16 kB) */
+    {  "SA0",FLASH0_BANK, FLASH0_SEG0_START, 1, 14,
+       FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+    /* Bank 0 sector SA1 (8 kB) */
+    {  "SA1", FLASH0_BANK, FLASH0_SEG0_START + 0x4000, 1, 13,
+       FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+    /* Bank 0 sector SA2 (8 kB) */
+    {  "SA2", FLASH0_BANK, FLASH0_SEG0_START + 0x6000, 1, 13,
+       FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+    /* Bank 0 sector SA3 is occluded by Mousse I/O devices */
+    /* Bank 0 sectors SA4-SA18, after Mousse devices up to PLCC (960 kB)  */
+    {  "KERNEL", FLASH0_BANK, FLASH0_SEG1_START, 15, 16,
+       FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+    /* Bank 0 sectors SA19-SA26, jumper can occlude this by PLCC (512 kB) */
+    /* This is where the Kahlua boot vector and boot ROM code resides. */
+    {  "BOOT",FLASH0_BANK, FLASH0_SEG2_START, 8, 16,
+       FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+    /* Bank 0 sectors SA27-SA34 (512 kB) */
+    {  "RAMDISK",FLASH0_BANK, FLASH0_SEG3_START, 8, 16,
+       FLASH0_VENDOR_ID, FLASH0_DEVICE_ID
+    },
+};
+
+int flashDevCount = (sizeof (flashDev) / sizeof (flashDev[0]));
+
+#define DEV(no)                        (&flashDev[no])
+#define DEV_NO(dev)            ((dev) - flashDev)
+
+/***********************************************************************
+ *
+ * Private Flash Routines
+ *
+ ***********************************************************************/
+
+/*
+ * The convention is:
+ *
+ * "addr" is always the PROM raw address, which is the address of an
+ * 8-bit quantity for flash 0 and 16-bit quantity for flash 1.
+ *
+ * "pos" is always a logical byte position from the PROM beginning.
+ */
+
+#define FLASH0_ADDR(dev, addr) \
+       ((unsigned char *) ((dev)->base + (addr)))
+
+#define FLASH0_WRITE(dev, addr, value) \
+       (*FLASH0_ADDR(dev, addr) = (value))
+
+#define FLASH0_READ(dev, addr) \
+       (*FLASH0_ADDR(dev, addr))
+
+PRIVATE int flashCheck(flash_dev_t *dev)
+{
+    if (! flashLibInited) {
+       printf("flashCheck: flashLib not initialized\n");
+       return ERROR;
+    }
+
+    if (dev < &flashDev[0] || dev >= &flashDev[flashDevCount]) {
+       printf("flashCheck: Bad dev parameter\n");
+       return ERROR;
+    }
+
+    if (! dev->found) {
+       printf("flashCheck: Device %d not available\n", DEV_NO(dev));
+       return ERROR;
+    }
+
+    return OK;
+}
+
+PRIVATE void flashReset(flash_dev_t *dev)
+{
+    PRINTF("flashReset: dev=%d\n", DEV_NO(dev));
+
+    if (dev->bank == FLASH0_BANK) {
+       FLASH0_WRITE(dev, 0x555, 0xaa);
+       FLASH0_WRITE(dev, 0xaaa, 0x55);
+       FLASH0_WRITE(dev, 0x555, 0xf0);
+    }
+
+    udelay(SLEEP_DELAY);
+
+    PRINTF("flashReset: done\n");
+}
+
+PRIVATE int flashProbe(flash_dev_t *dev)
+{
+    int                        rv, deviceID, vendorID;
+
+    PRINTF("flashProbe: dev=%d\n", DEV_NO(dev));
+
+    if (dev->bank != FLASH0_BANK) {
+       rv = ERROR;
+       goto DONE;
+    }
+
+    FLASH0_WRITE(dev, 0xaaa, 0xaa);
+    FLASH0_WRITE(dev, 0x555, 0x55);
+    FLASH0_WRITE(dev, 0xaaa, 0x90);
+
+    udelay(SLEEP_DELAY);
+
+    vendorID = FLASH0_READ(dev, 0);
+    deviceID = FLASH0_READ(dev, 2);
+
+    FLASH0_WRITE(dev, 0, 0xf0);
+
+    PRINTF("flashProbe: vendor=0x%x device=0x%x\n", vendorID, deviceID);
+
+    if (vendorID == dev->vendorID && deviceID == dev->deviceID)
+       rv = OK;
+    else
+       rv = ERROR;
+
+DONE:
+    PRINTF("flashProbe: rv=%d\n", rv);
+
+    return rv;
+}
+
+PRIVATE int flashWait(flash_dev_t *dev, int addr, int expect, int erase)
+{
+    int                        rv = ERROR;
+    int                        i, data;
+    int                        polls;
+#if 0
+    PRINTF("flashWait: dev=%d addr=0x%x expect=0x%x erase=%d\n",
+          DEV_NO(dev), addr, expect, erase);
+#endif
+
+    if (dev->bank != FLASH0_BANK) {
+       rv = ERROR;
+       goto done;
+    }
+
+    if (erase)
+       polls = FLASH_ERASE_SECTOR_TIMEOUT;     /* Ticks */
+    else
+       polls = FLASH_PROGRAM_POLLS;            /* Loops */
+
+    for (i = 0; i < polls; i++) {
+       if (erase)
+           udelay(SLEEP_DELAY);
+
+       data = FLASH0_READ(dev, addr);
+
+       if (((data ^ expect) & 0x80) == 0) {
+           rv = OK;
+           goto done;
+       }
+
+       if (data & 0x20) {
+           /*
+            * If the 0x20 bit has come on, it could actually be because
+            * the operation succeeded, so check the done bit again.
+            */
+
+           data = FLASH0_READ(dev, addr);
+
+           if (((data ^ expect) & 0x80) == 0) {
+               rv = OK;
+               goto done;
+           }
+
+           printf("flashWait: Program error (dev: %d, addr: 0x%x)\n",
+                  DEV_NO(dev), addr);
+
+           flashReset(dev);
+           rv = ERROR;
+           goto done;
+       }
+    }
+
+    printf("flashWait: Timeout %s (dev: %d, addr: 0x%x)\n",
+          erase ? "erasing sector" : "programming byte",
+          DEV_NO(dev), addr);
+
+done:
+
+#if 0
+    PRINTF("flashWait: rv=%d\n", rv);
+#endif
+
+    return rv;
+}
+
+/***********************************************************************
+ *
+ * Public Flash Routines
+ *
+ ***********************************************************************/
+
+STATUS flashLibInit(void)
+{
+    int                        i;
+
+    PRINTF("flashLibInit: devices=%d\n", flashDevCount);
+
+    for (i = 0; i < flashDevCount; i++) {
+       flash_dev_t     *dev = &flashDev[i];
+       /*
+        * For bank 1, probe both without and with byte swappage,
+        * so that this module works on both old and new Mousse boards.
+        */
+
+       flashReset(dev);
+
+       if (flashProbe(dev) != ERROR)
+           dev->found = 1;
+
+           flashReset(dev);
+
+           if (flashProbe(dev) != ERROR)
+               dev->found = 1;
+
+           dev->swap = 0;
+
+           if(dev->found){
+             PRINTF("\n  FLASH %s[%d]: iobase=0x%x - %d sectors %d KB",
+                    flashDev[i].name,i,flashDev[i].base, flashDev[i].sectors,
+                    (flashDev[i].sectors * FLASH_SECTOR_SIZE)/1024);
+
+           }
+    }
+
+    flashLibInited = 1;
+
+    PRINTF("flashLibInit: done\n");
+
+    return OK;
+}
+
+STATUS flashEraseSector(flash_dev_t *dev, int sector)
+{
+    int                        pos, addr;
+
+    PRINTF("flashErasesector: dev=%d sector=%d\n", DEV_NO(dev), sector);
+
+    if (flashCheck(dev) == ERROR)
+       return ERROR;
+
+    if (sector < 0 || sector >= dev->sectors) {
+       printf("flashEraseSector: Sector out of range (dev: %d, sector: %d)\n",
+              DEV_NO(dev), sector);
+       return ERROR;
+    }
+
+    pos = FLASH_SECTOR_POS(dev, sector);
+
+    if (dev->bank != FLASH0_BANK) {
+       return ERROR;
+    }
+
+    addr = pos;
+
+    FLASH0_WRITE(dev, 0xaaa, 0xaa);
+    FLASH0_WRITE(dev, 0x555, 0x55);
+    FLASH0_WRITE(dev, 0xaaa, 0x80);
+    FLASH0_WRITE(dev, 0xaaa, 0xaa);
+    FLASH0_WRITE(dev, 0x555, 0x55);
+    FLASH0_WRITE(dev, addr, 0x30);
+
+    return flashWait(dev, addr, 0xff, 1);
+}
+
+/*
+ * Note: it takes about as long to flash all sectors together with Chip
+ * Erase as it does to flash them one at a time (about 30 seconds for 2
+ * MB).  Also since we want to be able to treat subsets of sectors as if
+ * they were complete devices, we don't use Chip Erase.
+ */
+
+STATUS flashErase(flash_dev_t *dev)
+{
+    int                        sector;
+
+    PRINTF("flashErase: dev=%d sectors=%d\n", DEV_NO(dev), dev->sectors);
+
+    if (flashCheck(dev) == ERROR)
+       return ERROR;
+
+    for (sector = 0; sector < dev->sectors; sector++) {
+      if (flashEraseSector(dev, sector) == ERROR)
+           return ERROR;
+    }
+    return OK;
+}
+
+/*
+ * Read and write bytes
+ */
+
+STATUS flashRead(flash_dev_t *dev, int pos, char *buf, int len)
+{
+    int                        addr, words;
+
+    PRINTF("flashRead: dev=%d pos=0x%x buf=0x%x len=0x%x\n",
+          DEV_NO(dev), pos, (int) buf, len);
+
+    if (flashCheck(dev) == ERROR)
+       return ERROR;
+
+    if (pos < 0 || len < 0 || pos + len > FLASH_MAX_POS(dev)) {
+       printf("flashRead: Position out of range "
+              "(dev: %d, pos: 0x%x, len: 0x%x)\n",
+              DEV_NO(dev), pos, len);
+       return ERROR;
+    }
+
+    if (len == 0)
+       return OK;
+
+    if (dev->bank == FLASH0_BANK) {
+       addr = pos;
+       words = len;
+
+       PRINTF("flashRead: memcpy(0x%x, 0x%x, 0x%x)\n",
+              (int) buf, (int) FLASH0_ADDR(dev, pos), len);
+
+       memcpy(buf, FLASH0_ADDR(dev, addr), words);
+
+    }
+    PRINTF("flashRead: rv=OK\n");
+
+    return OK;
+}
+
+STATUS flashWrite(flash_dev_t *dev, int pos, char *buf, int len)
+{
+    int                addr, words;
+
+    PRINTF("flashWrite: dev=%d pos=0x%x buf=0x%x len=0x%x\n",
+          DEV_NO(dev), pos, (int) buf, len);
+
+    if (flashCheck(dev) == ERROR)
+       return ERROR;
+
+    if (pos < 0 || len < 0 || pos + len > FLASH_MAX_POS(dev)) {
+       printf("flashWrite: Position out of range "
+              "(dev: %d, pos: 0x%x, len: 0x%x)\n",
+              DEV_NO(dev), pos, len);
+       return ERROR;
+    }
+
+    if (len == 0)
+       return OK;
+
+    if (dev->bank == FLASH0_BANK) {
+       unsigned char tmp;
+
+       addr = pos;
+       words = len;
+
+       while (words--) {
+           tmp = *buf;
+           if (~FLASH0_READ(dev, addr) & tmp) {
+               printf("flashWrite: Attempt to program 0 to 1 "
+                      "(dev: %d, addr: 0x%x, data: 0x%x)\n",
+                      DEV_NO(dev), addr, tmp);
+               return ERROR;
+           }
+           FLASH0_WRITE(dev, 0xaaa, 0xaa);
+           FLASH0_WRITE(dev, 0x555, 0x55);
+           FLASH0_WRITE(dev, 0xaaa, 0xa0);
+           FLASH0_WRITE(dev, addr, tmp);
+           if (flashWait(dev, addr, tmp, 0) < 0)
+               return ERROR;
+           buf++;
+           addr++;
+       }
+    }
+
+    PRINTF("flashWrite: rv=OK\n");
+
+    return OK;
+}
+
+/*
+ * flashWritable returns TRUE if a range contains all F's.
+ */
+
+STATUS flashWritable(flash_dev_t *dev, int pos, int len)
+{
+    int                addr, words;
+    int                        rv = ERROR;
+
+    PRINTF("flashWritable: dev=%d pos=0x%x len=0x%x\n",
+          DEV_NO(dev), pos, len);
+
+    if (flashCheck(dev) == ERROR)
+       goto done;
+
+    if (pos < 0 || len < 0 || pos + len > FLASH_MAX_POS(dev)) {
+       printf("flashWritable: Position out of range "
+              "(dev: %d, pos: 0x%x, len: 0x%x)\n",
+              DEV_NO(dev), pos, len);
+       goto done;
+    }
+
+    if (len == 0) {
+       rv = 1;
+       goto done;
+    }
+
+    if (dev->bank == FLASH0_BANK) {
+       addr = pos;
+       words = len;
+
+       while (words--) {
+           if (FLASH0_READ(dev, addr) != 0xff) {
+               rv = 0;
+               goto done;
+           }
+           addr++;
+       }
+    }
+
+    rv = 1;
+
+ done:
+    PRINTF("flashWrite: rv=%d\n", rv);
+    return rv;
+}
+
+
+/*
+ * NOTE: the below code cannot run from FLASH!!!
+ */
+/***********************************************************************
+ *
+ * Flash Diagnostics
+ *
+ ***********************************************************************/
+
+STATUS flashDiag(flash_dev_t *dev)
+{
+    unsigned int       *buf = 0;
+    int                        i, len, sector;
+    int                        rv = ERROR;
+
+    if (flashCheck(dev) == ERROR)
+       return ERROR;
+
+    printf("flashDiag: Testing device %d, "
+          "base: 0x%x, %d sectors @ %d kB = %d kB\n",
+          DEV_NO(dev), dev->base,
+          dev->sectors,
+          1 << (dev->lgSectorSize - 10),
+          dev->sectors << (dev->lgSectorSize - 10));
+
+    len = 1 << dev->lgSectorSize;
+
+    printf("flashDiag: Erasing\n");
+
+    if (flashErase(dev) == ERROR) {
+       printf("flashDiag: Erase failed\n");
+       goto done;
+    }
+    printf("%d bytes requested ...\n", len);
+    buf = malloc(len);
+    printf("allocated %d bytes ...\n", len);
+    if (buf == 0) {
+       printf("flashDiag: Out of memory\n");
+       goto done;
+    }
+
+    /*
+     * Write unique counting pattern to each sector
+     */
+
+    for (sector = 0; sector < dev->sectors; sector++) {
+       printf("flashDiag: Write sector %d\n", sector);
+
+       for (i = 0; i < len / 4; i++)
+           buf[i] = sector << 24 | i;
+
+       if (flashWrite(dev,
+                      sector << dev->lgSectorSize,
+                      (char *) buf,
+                      len) == ERROR) {
+           printf("flashDiag: Write failed (dev: %d, sector: %d)\n",
+                  DEV_NO(dev), sector);
+           goto done;
+       }
+    }
+
+    /*
+     * Verify
+     */
+
+    for (sector = 0; sector < dev->sectors; sector++) {
+       printf("flashDiag: Verify sector %d\n", sector);
+
+       if (flashRead(dev,
+                     sector << dev->lgSectorSize,
+                     (char *) buf,
+                     len) == ERROR) {
+           printf("flashDiag: Read failed (dev: %d, sector: %d)\n",
+                  DEV_NO(dev), sector);
+           goto done;
+       }
+
+       for (i = 0; i < len / 4; i++) {
+           if (buf[i] != (sector << 24 | i)) {
+               printf("flashDiag: Verify error "
+                      "(dev: %d, sector: %d, offset: 0x%x)\n",
+                      DEV_NO(dev), sector, i);
+               printf("flashDiag: Expected 0x%08x, got 0x%08x\n",
+                      sector << 24 | i, buf[i]);
+
+               goto done;
+           }
+       }
+    }
+
+    printf("flashDiag: Erasing\n");
+
+    if (flashErase(dev) == ERROR) {
+       printf("flashDiag: Final erase failed\n");
+       goto done;
+    }
+
+    rv = OK;
+
+ done:
+    if (buf)
+       free(buf);
+
+    if (rv == OK)
+       printf("flashDiag: Device %d passed\n", DEV_NO(dev));
+    else
+       printf("flashDiag: Device %d failed\n", DEV_NO(dev));
+
+    return rv;
+}
+
+STATUS flashDiagAll(void)
+{
+    int                        i;
+    int                        rv = OK;
+
+    PRINTF("flashDiagAll: devices=%d\n", flashDevCount);
+
+    for (i = 0; i < flashDevCount; i++) {
+       flash_dev_t     *dev = &flashDev[i];
+
+       if (dev->found && flashDiag(dev) == ERROR)
+           rv = ERROR;
+    }
+
+    if (rv == OK)
+       printf("flashDiagAll: Passed\n");
+    else
+       printf("flashDiagAll: Failed because of earlier errors\n");
+
+    return OK;
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+    unsigned long size = 0;
+    flash_dev_t        *dev = NULL;
+    flashLibInit();
+
+    /*
+     * Provide info for FLASH (up to 960K) of Kernel Image data.
+     */
+    dev = FLASH_DEV_BANK0_LOW;
+    flash_info[FLASH_BANK_KERNEL].flash_id =
+      (dev->vendorID << 16) | dev->deviceID;
+    flash_info[FLASH_BANK_KERNEL].sector_count = dev->sectors;
+    flash_info[FLASH_BANK_KERNEL].size =
+      flash_info[FLASH_BANK_KERNEL].sector_count * FLASH_SECTOR_SIZE;
+    flash_info[FLASH_BANK_KERNEL].start[FIRST_SECTOR] = dev->base;
+    size += flash_info[FLASH_BANK_KERNEL].size;
+
+    /*
+     * Provide info for 512K PLCC FLASH ROM (U-Boot)
+     */
+    dev = FLASH_DEV_BANK0_BOOT;
+    flash_info[FLASH_BANK_BOOT].flash_id =
+      (dev->vendorID << 16) | dev->deviceID;
+    flash_info[FLASH_BANK_BOOT].sector_count = dev->sectors;
+    flash_info[FLASH_BANK_BOOT].size =
+      flash_info[FLASH_BANK_BOOT].sector_count * FLASH_SECTOR_SIZE;
+    flash_info[FLASH_BANK_BOOT].start[FIRST_SECTOR] = dev->base;
+    size += flash_info[FLASH_BANK_BOOT].size;
+
+
+    /*
+     * Provide info for 512K FLASH0 segment (U-Boot)
+     */
+    dev = FLASH_DEV_BANK0_HIGH;
+    flash_info[FLASH_BANK_AUX].flash_id =
+      (dev->vendorID << 16) | dev->deviceID;
+    flash_info[FLASH_BANK_AUX].sector_count = dev->sectors;
+    flash_info[FLASH_BANK_AUX].size =
+      flash_info[FLASH_BANK_AUX].sector_count * FLASH_SECTOR_SIZE;
+    flash_info[FLASH_BANK_AUX].start[FIRST_SECTOR] = dev->base;
+    size += flash_info[FLASH_BANK_AUX].size;
+
+
+    return  size;
+}
+
+/*
+ * Get flash device from U-Boot flash info.
+ */
+flash_dev_t*
+getFlashDevFromInfo(flash_info_t* info)
+{
+  int i;
+
+  if(!info)
+    return NULL;
+
+  for (i = 0; i < flashDevCount; i++) {
+    flash_dev_t        *dev = &flashDev[i];
+    if(dev->found && (dev->base == info->start[0]))
+      return dev;
+  }
+  printf("ERROR: notice, no FLASH mapped at address 0x%x\n",
+        (unsigned int)info->start[0]);
+  return NULL;
+}
+
+ulong
+flash_get_size (vu_long *addr, flash_info_t *info)
+{
+    int i;
+    for(i = 0; i < flashDevCount; i++) {
+      flash_dev_t      *dev = &flashDev[i];
+      if(dev->found){
+       if(dev->base == (unsigned int)addr){
+         info->flash_id = (dev->vendorID << 16) | dev->deviceID;
+         info->sector_count = dev->sectors;
+         info->size = info->sector_count * FLASH_SECTOR_SIZE;
+         return dev->sectors * FLASH_SECTOR_SIZE;
+       }
+      }
+    }
+    return 0;
+}
+
+void
+flash_print_info  (flash_info_t *info)
+{
+  int i;
+  unsigned int chip;
+
+    if (info->flash_id == FLASH_UNKNOWN) {
+       printf ("missing or unknown FLASH type\n");
+       return;
+    }
+
+    switch ((info->flash_id >> 16) & 0xff) {
+    case 0x1:
+       printf ("AMD ");
+       break;
+    default:
+       printf ("Unknown Vendor ");
+       break;
+    }
+    chip = (unsigned int) info->flash_id & 0x000000ff;
+
+    switch (chip) {
+
+    case AMD_ID_F040B:
+       printf ("AM29F040B (4 Mbit)\n");
+       break;
+
+    case AMD_ID_LV160B:
+    case FLASH_AM160LV:
+    case 0x49:
+       printf ("AM29LV160B (16 Mbit / 2M x 8bit)\n");
+       break;
+
+    default:
+      printf ("Unknown Chip Type:0x%x\n", chip);
+       break;
+    }
+
+    printf ("  Size: %ld bytes in %d Sectors\n",
+           info->size, info->sector_count);
+
+    printf ("  Sector Start Addresses:");
+    for (i=0; i<info->sector_count; ++i) {
+      if ((i % 5) == 0)
+         printf ("\n   ");
+       printf (" %08lX%s",
+               info->start[FIRST_SECTOR] + i*FLASH_SECTOR_SIZE,
+               info->protect[i] ? " (RO)" : "     "
+               );
+    }
+    printf ("\n");
+}
+
+
+/*
+ * Erase a range of flash sectors.
+ */
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+    vu_long *addr = (vu_long*)(info->start[0]);
+    int prot, sect, l_sect;
+    flash_dev_t* dev = NULL;
+
+    if ((s_first < 0) || (s_first > s_last)) {
+       if (info->flash_id == FLASH_UNKNOWN) {
+           printf ("- missing\n");
+       } else {
+           printf ("- no sectors to erase\n");
+       }
+       return 1;
+    }
+
+    prot = 0;
+    for (sect = s_first; sect <= s_last; sect++) {
+       if (info->protect[sect]) {
+           prot++;
+       }
+    }
+
+    if (prot) {
+       printf ("- Warning: %d protected sectors will not be erased!\n",
+               prot);
+    } else {
+       printf ("\n");
+    }
+
+    l_sect = -1;
+
+    /* Start erase on unprotected sectors */
+    dev = getFlashDevFromInfo(info);
+    if(dev){
+      printf("Erase FLASH[%s] -%d sectors:", dev->name, dev->sectors);
+      for (sect = s_first; sect<=s_last; sect++) {
+       if (info->protect[sect] == 0) { /* not protected */
+         addr = (vu_long*)(dev->base);
+         /*   printf("erase_sector: sector=%d, addr=0x%x\n",
+              sect, addr); */
+         printf(".");
+         if(ERROR == flashEraseSector(dev, sect)){
+           printf("ERROR: could not erase sector %d on FLASH[%s]\n",
+                  sect, dev->name);
+           return 1;
+         }
+       }
+      }
+    }
+    printf (" done\n");
+    return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int
+write_word (flash_info_t *info, ulong dest, ulong data)
+{
+
+  flash_dev_t* dev = getFlashDevFromInfo(info);
+  int addr = dest - info->start[0];
+
+  if (! dev)
+    return 1;
+
+  if(OK != flashWrite(dev, addr, (char*)&data, sizeof(ulong))){
+    printf("ERROR: could not write to addr=0x%x, data=0x%x\n",
+          (unsigned int)addr, (unsigned)data);
+    return 1;
+  }
+
+  if((addr % FLASH_SECTOR_SIZE) == 0)
+    printf(".");
+
+
+  PRINTF("write_word:0x%x, base=0x%x, addr=0x%x, data=0x%x\n",
+        (unsigned)info->start[0],
+        (unsigned)dest,
+        (unsigned)(dest - info->start[0]),
+        (unsigned)data);
+
+
+
+    return (0);
+}
+
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+    ulong cp, wp, data;
+    int i, l, rc;
+    flash_dev_t* dev = getFlashDevFromInfo(info);
+
+    if( dev ) {
+      printf("FLASH[%s]:", dev->name);
+      wp = (addr & ~3);        /* get lower word aligned address */
+
+      /*
+       * handle unaligned start bytes
+       */
+      if ((l = addr - wp) != 0) {
+       data = 0;
+       for (i=0, cp=wp; i<l; ++i, ++cp) {
+         data = (data << 8) | (*(uchar *)cp);
+       }
+       for (; i<4 && cnt>0; ++i) {
+         data = (data << 8) | *src++;
+         --cnt;
+         ++cp;
+       }
+       for (; cnt==0 && i<4; ++i, ++cp) {
+         data = (data << 8) | (*(uchar *)cp);
+       }
+       if ((rc = write_word(info, wp, data)) != 0) {
+         return (rc);
+       }
+       wp += 4;
+      }
+
+      /*
+       * handle word aligned part
+       */
+      while (cnt >= 4) {
+       data = 0;
+       for (i=0; i<4; ++i) {
+         data = (data << 8) | *src++;
+       }
+       if ((rc = write_word(info, wp, data)) != 0) {
+         return (rc);
+       }
+       wp  += 4;
+       cnt -= 4;
+      }
+
+      if (cnt == 0) {
+       return (0);
+      }
+
+      /*
+       * handle unaligned tail bytes
+       */
+      data = 0;
+      for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+       data = (data << 8) | *src++;
+       --cnt;
+      }
+      for (; i<4; ++i, ++cp) {
+       data = (data << 8) | (*(uchar *)cp);
+      }
+
+      return (write_word(info, wp, data));
+    }
+    return 1;
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/mousse/m48t59y.c b/board/mousse/m48t59y.c
new file mode 100644 (file)
index 0000000..7205a96
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * SGS M48-T59Y TOD/NVRAM Driver
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 1999, by Curt McDowell, 08-06-99, Broadcom Corp.
+ *
+ * (C) Copyright 2001, James Dougherty, 07/18/01, Broadcom Corp.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * SGS M48-T59Y TOD/NVRAM Driver
+ *
+ * The SGS M48 an 8K NVRAM starting at offset M48_BASE_ADDR and
+ * continuing for 8176 bytes. After that starts the Time-Of-Day (TOD)
+ * registers which are used to set/get the internal date/time functions.
+ *
+ * This module implements Y2K compliance by taking full year numbers
+ * and translating back and forth from the TOD 2-digit year.
+ *
+ * NOTE: for proper interaction with an operating system, the TOD should
+ * be used to store Universal Coordinated Time (GMT) and timezone
+ * conversions should be used.
+ *
+ * Here is a diagram of the memory layout:
+ *
+ * +---------------------------------------------+ 0xffe0a000
+ * | Non-volatile memory                         | .
+ * |                                             | .
+ * | (8176 bytes of Non-volatile memory)         | .
+ * |                                             | .
+ * +---------------------------------------------+ 0xffe0bff0
+ * | Flags                                       |
+ * +---------------------------------------------+ 0xffe0bff1
+ * | Unused                                      |
+ * +---------------------------------------------+ 0xffe0bff2
+ * | Alarm Seconds                               |
+ * +---------------------------------------------+ 0xffe0bff3
+ * | Alarm Minutes                               |
+ * +---------------------------------------------+ 0xffe0bff4
+ * | Alarm Date                                  |
+ * +---------------------------------------------+ 0xffe0bff5
+ * | Interrupts                                  |
+ * +---------------------------------------------+ 0xffe0bff6
+ * | WatchDog                                    |
+ * +---------------------------------------------+ 0xffe0bff7
+ * | Calibration                                 |
+ * +---------------------------------------------+ 0xffe0bff8
+ * | Seconds                                     |
+ * +---------------------------------------------+ 0xffe0bff9
+ * | Minutes                                     |
+ * +---------------------------------------------+ 0xffe0bffa
+ * | Hours                                       |
+ * +---------------------------------------------+ 0xffe0bffb
+ * | Day                                         |
+ * +---------------------------------------------+ 0xffe0bffc
+ * | Date                                        |
+ * +---------------------------------------------+ 0xffe0bffd
+ * | Month                                       |
+ * +---------------------------------------------+ 0xffe0bffe
+ * | Year (2 digits only)                        |
+ * +---------------------------------------------+ 0xffe0bfff
+ */
+#include <common.h>
+#include <rtc.h>
+#include "mousse.h"
+
+/*
+ * Imported from mousse.h:
+ *
+ *   TOD_REG_BASE              Base of m48t59y TOD registers
+ *   SYS_TOD_UNPROTECT()       Disable NVRAM write protect
+ *   SYS_TOD_PROTECT()         Re-enable NVRAM write protect
+ */
+
+#define YEAR           0xf
+#define MONTH          0xe
+#define DAY            0xd
+#define DAY_OF_WEEK    0xc
+#define HOUR           0xb
+#define MINUTE         0xa
+#define SECOND         0x9
+#define CONTROL                0x8
+#define WATCH          0x7
+#define INTCTL         0x6
+#define WD_DATE                0x5
+#define WD_HOUR                0x4
+#define WD_MIN         0x3
+#define WD_SEC         0x2
+#define _UNUSED                0x1
+#define FLAGS          0x0
+
+#define M48_ADDR       ((volatile unsigned char *) TOD_REG_BASE)
+
+int m48_tod_init(void)
+{
+    SYS_TOD_UNPROTECT();
+
+    M48_ADDR[CONTROL] = 0;
+    M48_ADDR[WATCH] = 0;
+    M48_ADDR[INTCTL] = 0;
+
+    /*
+     * If the oscillator is currently stopped (as on a new part shipped
+     * from the factory), start it running.
+     *
+     * Here is an example of the TOD bytes on a brand new M48T59Y part:
+     *         00 00 00 00 00 00 00 00 00 88 8c c3 bf c8 f5 01
+     */
+
+    if (M48_ADDR[SECOND] & 0x80)
+       M48_ADDR[SECOND] = 0;
+
+    /* Is battery low */
+    if ( M48_ADDR[FLAGS] & 0x10) {
+        printf("NOTICE: Battery low on Real-Time Clock (replace SNAPHAT).\n");
+    }
+
+    SYS_TOD_PROTECT();
+
+    return 0;
+}
+
+/*
+ * m48_tod_set
+ */
+
+static int to_bcd(int value)
+{
+    return value / 10 * 16 + value % 10;
+}
+
+static int from_bcd(int value)
+{
+    return value / 16 * 10 + value % 16;
+}
+
+static int day_of_week(int y, int m, int d)    /* 0-6 ==> Sun-Sat */
+{
+    static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
+    y -= m < 3;
+    return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
+}
+
+/*
+ * Note: the TOD should store the current GMT
+ */
+
+int m48_tod_set(int year,              /* 1980-2079 */
+               int month,              /* 01-12 */
+               int day,                /* 01-31 */
+               int hour,               /* 00-23 */
+               int minute,             /* 00-59 */
+               int second)             /* 00-59 */
+
+{
+    SYS_TOD_UNPROTECT();
+
+    M48_ADDR[CONTROL] |= 0x80; /* Set WRITE bit */
+
+    M48_ADDR[YEAR] = to_bcd(year % 100);
+    M48_ADDR[MONTH] = to_bcd(month);
+    M48_ADDR[DAY] = to_bcd(day);
+    M48_ADDR[DAY_OF_WEEK] = day_of_week(year, month, day) + 1;
+    M48_ADDR[HOUR] = to_bcd(hour);
+    M48_ADDR[MINUTE] = to_bcd(minute);
+    M48_ADDR[SECOND] = to_bcd(second);
+
+    M48_ADDR[CONTROL] &= ~0x80;        /* Clear WRITE bit */
+
+    SYS_TOD_PROTECT();
+
+    return 0;
+}
+
+/*
+ * Note: the TOD should store the current GMT
+ */
+
+int m48_tod_get(int *year,             /* 1980-2079 */
+               int *month,             /* 01-12 */
+               int *day,               /* 01-31 */
+               int *hour,              /* 00-23 */
+               int *minute,            /* 00-59 */
+               int *second)            /* 00-59 */
+{
+    int y;
+
+    SYS_TOD_UNPROTECT();
+
+    M48_ADDR[CONTROL] |= 0x40; /* Set READ bit */
+
+    y = from_bcd(M48_ADDR[YEAR]);
+    *year = y < 80 ? 2000 + y : 1900 + y;
+    *month = from_bcd(M48_ADDR[MONTH]);
+    *day = from_bcd(M48_ADDR[DAY]);
+    /* day_of_week = M48_ADDR[DAY_OF_WEEK] & 0xf; */
+    *hour = from_bcd(M48_ADDR[HOUR]);
+    *minute = from_bcd(M48_ADDR[MINUTE]);
+    *second = from_bcd(M48_ADDR[SECOND] & 0x7f);
+
+    M48_ADDR[CONTROL] &= ~0x40;        /* Clear READ bit */
+
+    SYS_TOD_PROTECT();
+
+    return 0;
+}
+
+int m48_tod_get_second(void)
+{
+    return from_bcd(M48_ADDR[SECOND] & 0x7f);
+}
+
+/*
+ * Watchdog function
+ *
+ *  If usec is 0, the watchdog timer is disarmed.
+ *
+ *  If usec is non-zero, the watchdog timer is armed (or re-armed) for
+ *    approximately usec microseconds (if the exact requested usec is
+ *    not supported by the chip, the next higher available value is used).
+ *
+ *  Minimum watchdog timeout = 62500 usec
+ *  Maximum watchdog timeout = 124 sec (124000000 usec)
+ */
+
+void m48_watchdog_arm(int usec)
+{
+    int                mpy, res;
+
+    SYS_TOD_UNPROTECT();
+
+    if (usec == 0) {
+       res = 0;
+       mpy = 0;
+    } else if (usec < 2000000) {       /* Resolution: 1/16s if below 2s */
+       res = 0;
+       mpy = (usec + 62499) / 62500;
+    } else if (usec < 8000000) {       /* Resolution: 1/4s if below 8s */
+       res = 1;
+       mpy = (usec + 249999) / 250000;
+    } else if (usec < 32000000) {      /* Resolution: 1s if below 32s */
+       res = 2;
+       mpy = (usec + 999999) / 1000000;
+    } else {                           /* Resolution: 4s up to 124s */
+       res = 3;
+       mpy = (usec + 3999999) / 4000000;
+       if (mpy > 31)
+           mpy = 31;
+    }
+
+    M48_ADDR[WATCH] = (0x80 |          /* Steer to RST signal (IRQ = N/C) */
+                      mpy << 2 |
+                      res);
+
+    SYS_TOD_PROTECT();
+}
+
+/*
+ * U-Boot RTC support.
+ */
+void
+rtc_get( struct rtc_time *tmp )
+{
+       m48_tod_get(&tmp->tm_year,
+                   &tmp->tm_mon,
+                   &tmp->tm_mday,
+                   &tmp->tm_hour,
+                   &tmp->tm_min,
+                   &tmp->tm_sec);
+       tmp->tm_yday = 0;
+       tmp->tm_isdst= 0;
+
+#ifdef RTC_DEBUG
+       printf( "Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+               tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+               tmp->tm_hour, tmp->tm_min, tmp->tm_sec );
+#endif
+}
+
+void
+rtc_set( struct rtc_time *tmp )
+{
+       m48_tod_set(tmp->tm_year,               /* 1980-2079 */
+                   tmp->tm_mon,                /* 01-12 */
+                   tmp->tm_mday,              /* 01-31 */
+                   tmp->tm_hour,               /* 00-23 */
+                   tmp->tm_min,                /* 00-59 */
+                   tmp->tm_sec);               /* 00-59 */
+
+#ifdef RTC_DEBUG
+       printf( "Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+               tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+               tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+#endif
+
+}
+
+void
+rtc_reset (void)
+{
+  m48_tod_init();
+}
+
diff --git a/board/pm826/flash.c b/board/pm826/flash.c
new file mode 100644 (file)
index 0000000..4d5147b
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * (C) Copyright 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for Intel devices
+ *
+ *--------------------------------------------------------------------
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+/*-----------------------------------------------------------------------
+ */
+ulong flash_get_size (volatile unsigned long *baseaddr,
+                                         flash_info_t * info)
+{
+       short i;
+       unsigned long flashtest_h, flashtest_l;
+
+       info->sector_count = info->size = 0;
+       info->flash_id = FLASH_UNKNOWN;
+
+       /* Write query command sequence and test FLASH answer
+        */
+       baseaddr[0] = 0x00980098;
+       baseaddr[1] = 0x00980098;
+
+       flashtest_h = baseaddr[0];      /* manufacturer ID      */
+       flashtest_l = baseaddr[1];
+
+       if (flashtest_h != INTEL_MANUFACT || flashtest_l != INTEL_MANUFACT)
+               return (0);             /* no or unknown flash  */
+
+       flashtest_h = baseaddr[2];      /* device ID            */
+       flashtest_l = baseaddr[3];
+
+       if (flashtest_h != flashtest_l)
+               return (0);
+
+       switch (flashtest_h) {
+       case INTEL_ID_28F160C3B:
+               info->flash_id = FLASH_28F160C3B;
+               info->sector_count = 39;
+               info->size = 0x00800000;        /* 4 * 2 MB = 8 MB      */
+               break;
+       case INTEL_ID_28F160F3B:
+               info->flash_id = FLASH_28F160F3B;
+               info->sector_count = 39;
+               info->size = 0x00800000;        /* 4 * 2 MB = 8 MB      */
+               break;
+       default:
+               return (0);                     /* no or unknown flash  */
+       }
+
+       info->flash_id |= INTEL_MANUFACT << 16; /* set manufacturer offset */
+
+       if (info->flash_id & FLASH_BTYPE) {
+               volatile unsigned long *tmp = baseaddr;
+
+               /* set up sector start adress table (bottom sector type)
+                * AND unlock the sectors (if our chip is 160C3)
+                */
+               for (i = 0; i < info->sector_count; i++) {
+                       if ((info->flash_id & FLASH_TYPEMASK) == FLASH_28F160C3B) {
+                               tmp[0] = 0x00600060;
+                               tmp[1] = 0x00600060;
+                               tmp[0] = 0x00D000D0;
+                               tmp[1] = 0x00D000D0;
+                       }
+                       info->start[i] = (uint) tmp;
+                       tmp += i < 8 ? 0x2000 : 0x10000; /* pointer arith       */
+               }
+       }
+
+       memset (info->protect, 0, info->sector_count);
+
+       baseaddr[0] = 0x00FF00FF;
+       baseaddr[1] = 0x00FF00FF;
+
+       return (info->size);
+}
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+       unsigned long size_b0 = 0;
+       int i;
+
+       /* Init: no FLASHes known
+        */
+       for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+               flash_info[i].flash_id = FLASH_UNKNOWN;
+       }
+
+       /* Static FLASH Bank configuration here (only one bank) */
+
+       size_b0 = flash_get_size ((ulong *) CFG_FLASH0_BASE, &flash_info[0]);
+       if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) {
+               printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+                               size_b0, size_b0 >> 20);
+       }
+
+       /* protect monitor and environment sectors
+        */
+
+#ifndef CONFIG_BOOT_ROM
+       /* If U-Boot is  booted from ROM the CFG_MONITOR_BASE > CFG_FLASH0_BASE
+        * but we shouldn't protect it.
+        */
+
+# if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
+       flash_protect (FLAG_PROTECT_SET,
+                      CFG_MONITOR_BASE,
+                      CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, &flash_info[0]
+       );
+# endif
+#endif /* CONFIG_BOOT_ROM */
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
+# endif
+       flash_protect (FLAG_PROTECT_SET,
+                      CFG_ENV_ADDR,
+                      CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
+#endif
+
+       return (size_b0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+       int i;
+
+       if (info->flash_id == FLASH_UNKNOWN) {
+               printf ("missing or unknown FLASH type\n");
+               return;
+       }
+
+       switch ((info->flash_id >> 16) & 0xff) {
+       case 0x89:
+               printf ("INTEL ");
+               break;
+       default:
+               printf ("Unknown Vendor ");
+               break;
+       }
+
+       switch (info->flash_id & FLASH_TYPEMASK) {
+       case FLASH_28F160C3B:
+               printf ("28F160C3B (16 M, bottom sector)\n");
+               break;
+       case FLASH_28F160F3B:
+               printf ("28F160F3B (16 M, bottom sector)\n");
+               break;
+       default:
+               printf ("Unknown Chip Type\n");
+               break;
+       }
+
+       printf ("  Size: %ld MB in %d Sectors\n",
+                       info->size >> 20, info->sector_count);
+
+       printf ("  Sector Start Addresses:");
+       for (i = 0; i < info->sector_count; ++i) {
+               if ((i % 5) == 0)
+                       printf ("\n   ");
+               printf (" %08lX%s",
+                       info->start[i],
+                       info->protect[i] ? " (RO)" : "     "
+               );
+       }
+       printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+       int flag, prot, sect;
+       ulong start, now, last;
+
+       if ((s_first < 0) || (s_first > s_last)) {
+               if (info->flash_id == FLASH_UNKNOWN) {
+                       printf ("- missing\n");
+               } else {
+                       printf ("- no sectors to erase\n");
+               }
+               return 1;
+       }
+
+       prot = 0;
+       for (sect = s_first; sect <= s_last; sect++) {
+               if (info->protect[sect])
+                       prot++;
+       }
+
+       if (prot) {
+               printf ("- Warning: %d protected sectors will not be erased!\n",
+                               prot);
+       } else {
+               printf ("\n");
+       }
+
+       /* Start erase on unprotected sectors
+        */
+       for (sect = s_first; sect <= s_last; sect++) {
+               volatile ulong *addr =
+                               (volatile unsigned long *) info->start[sect];
+
+               start = get_timer (0);
+               last = start;
+               if (info->protect[sect] == 0) {
+                       /* Disable interrupts which might cause a timeout here
+                        */
+                       flag = disable_interrupts ();
+
+                       /* Erase the block
+                        */
+                       addr[0] = 0x00200020;
+                       addr[1] = 0x00200020;
+                       addr[0] = 0x00D000D0;
+                       addr[1] = 0x00D000D0;
+
+                       /* re-enable interrupts if necessary
+                        */
+                       if (flag)
+                               enable_interrupts ();
+
+                       /* wait at least 80us - let's wait 1 ms
+                        */
+                       udelay (1000);
+
+                       last = start;
+                       while ((addr[0] & 0x00800080) != 0x00800080 ||
+                                  (addr[1] & 0x00800080) != 0x00800080) {
+                               if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
+                                       printf ("Timeout (erase suspended!)\n");
+                                       /* Suspend erase
+                                        */
+                                       addr[0] = 0x00B000B0;
+                                       addr[1] = 0x00B000B0;
+                                       goto DONE;
+                               }
+                               /* show that we're waiting
+                                */
+                               if ((now - last) > 1000) {      /* every second */
+                                       serial_putc ('.');
+                                       last = now;
+                               }
+                       }
+                       if (addr[0] & 0x00220022 || addr[1] & 0x00220022) {
+                               printf ("*** ERROR: erase failed!\n");
+                               goto DONE;
+                       }
+               }
+               /* Clear status register and reset to read mode
+                */
+               addr[0] = 0x00500050;
+               addr[1] = 0x00500050;
+               addr[0] = 0x00FF00FF;
+               addr[1] = 0x00FF00FF;
+       }
+
+       printf (" done\n");
+
+DONE:
+       return 0;
+}
+
+static int write_word (flash_info_t *, volatile unsigned long *, ulong);
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+       ulong v;
+       int i, l, cc = cnt, res = 0;
+
+
+       for (v=0; cc > 0; addr += 4, cc -= 4 - l) {
+               l = (addr & 3);
+               addr &= ~3;
+
+               for (i = 0; i < 4; i++) {
+                       v = (v << 8) + (i < l || i - l >= cc ?
+                               *((unsigned char *) addr + i) : *src++);
+               }
+
+               if ((res = write_word (info, (volatile unsigned long *) addr, v)) != 0)
+                       break;
+       }
+
+       return (res);
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t * info, volatile unsigned long *addr,
+                                          ulong data)
+{
+       int flag, res = 0;
+       ulong start;
+
+       /* Check if Flash is (sufficiently) erased
+        */
+       if ((*addr & data) != data)
+               return (2);
+
+       /* Disable interrupts which might cause a timeout here
+        */
+       flag = disable_interrupts ();
+
+       *addr = 0x00400040;
+       *addr = data;
+
+       /* re-enable interrupts if necessary
+        */
+       if (flag)
+               enable_interrupts ();
+
+       start = get_timer (0);
+       while ((*addr & 0x00800080) != 0x00800080) {
+               if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
+                       /* Suspend program
+                        */
+                       *addr = 0x00B000B0;
+                       res = 1;
+                       goto OUT;
+               }
+       }
+
+       if (*addr & 0x00220022) {
+               printf ("*** ERROR: program failed!\n");
+               res = 1;
+       }
+
+OUT:
+       /* Clear status register and reset to read mode
+        */
+       *addr = 0x00500050;
+       *addr = 0x00FF00FF;
+
+       return (res);
+}
diff --git a/board/sacsng/flash.c b/board/sacsng/flash.c
new file mode 100644 (file)
index 0000000..4fd04df
--- /dev/null
@@ -0,0 +1,523 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <configs/sacsng.h>
+
+
+#undef  DEBUG
+
+#ifndef        CFG_ENV_ADDR
+#define CFG_ENV_ADDR   (CFG_FLASH_BASE + CFG_ENV_OFFSET)
+#endif
+#ifndef CFG_ENV_SIZE
+#define CFG_ENV_SIZE   CFG_ENV_SECT_SIZE
+#endif
+
+
+flash_info_t   flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_short *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+       unsigned long size_b0, size_b1;
+       int i;
+
+       /* Init: no FLASHes known */
+       for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+               flash_info[i].flash_id = FLASH_UNKNOWN;
+       }
+
+       size_b0 = flash_get_size((vu_short *)CFG_FLASH0_BASE, &flash_info[0]);
+
+       if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+               printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+                       size_b0, size_b0<<20);
+       }
+
+       size_b1 = flash_get_size((vu_short *)CFG_FLASH1_BASE, &flash_info[1]);
+
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+       /* monitor protection ON by default */
+       flash_protect(FLAG_PROTECT_SET,
+                     CFG_MONITOR_BASE,
+                     CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+                     &flash_info[0]);
+#endif
+
+#ifdef CFG_ENV_IS_IN_FLASH
+       /* ENV protection ON by default */
+       flash_protect(FLAG_PROTECT_SET,
+                     CFG_ENV_ADDR,
+                     CFG_ENV_ADDR+CFG_ENV_SIZE-1,
+                     &flash_info[0]);
+#endif
+
+       if (size_b1) {
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+               /* monitor protection ON by default */
+               flash_protect(FLAG_PROTECT_SET,
+                             CFG_MONITOR_BASE,
+                             CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+                             &flash_info[1]);
+#endif
+
+#ifdef CFG_ENV_IS_IN_FLASH
+               /* ENV protection ON by default */
+               flash_protect(FLAG_PROTECT_SET,
+                             CFG_ENV_ADDR,
+                             CFG_ENV_ADDR+CFG_ENV_SIZE-1,
+                             &flash_info[1]);
+#endif
+       } else {
+               flash_info[1].flash_id = FLASH_UNKNOWN;
+               flash_info[1].sector_count = -1;
+       }
+
+       flash_info[0].size = size_b0;
+       flash_info[1].size = size_b1;
+
+       /*
+        * We only report the primary flash for U-Boot's use.
+        */
+       return (size_b0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+       int i;
+
+       if (info->flash_id == FLASH_UNKNOWN) {
+               printf ("missing or unknown FLASH type\n");
+               return;
+       }
+
+       switch (info->flash_id & FLASH_VENDMASK) {
+       case FLASH_MAN_AMD:     printf ("AMD ");                break;
+       case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
+       default:                printf ("Unknown Vendor ");     break;
+       }
+
+       switch (info->flash_id & FLASH_TYPEMASK) {
+       case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+                               break;
+       case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+                               break;
+       case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+                               break;
+       case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+                               break;
+       case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+                               break;
+       case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+                               break;
+       case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+                               break;
+       case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+                               break;
+       default:                printf ("Unknown Chip Type\n");
+                               break;
+       }
+
+       printf ("  Size: %ld MB in %d Sectors\n",
+               info->size >> 20, info->sector_count);
+
+       printf ("  Sector Start Addresses:");
+       for (i=0; i<info->sector_count; ++i) {
+               if ((i % 5) == 0)
+                       printf ("\n   ");
+               printf (" %08lX%s",
+                       info->start[i],
+                       info->protect[i] ? " (RO)" : "     "
+               );
+       }
+       printf ("\n");
+       return;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+
+static ulong flash_get_size (vu_short *addr, flash_info_t *info)
+{
+       short i;
+       ushort value;
+       ulong  base = (ulong)addr;
+
+       /* Write auto select command: read Manufacturer ID */
+       addr[0x0555] = 0xAAAA;
+       addr[0x02AA] = 0x5555;
+       addr[0x0555] = 0x9090;
+       __asm__ __volatile__(" sync\n ");
+
+       value = addr[0];
+#ifdef DEBUG
+       printf("Flash manufacturer 0x%04X\n", value);
+#endif
+
+       if(value == (ushort)AMD_MANUFACT) {
+               info->flash_id = FLASH_MAN_AMD;
+       } else if (value == (ushort)FUJ_MANUFACT) {
+               info->flash_id = FLASH_MAN_FUJ;
+       } else {
+#ifdef DEBUG
+               printf("Unknown flash manufacturer 0x%04X\n", value);
+#endif
+               info->flash_id = FLASH_UNKNOWN;
+               info->sector_count = 0;
+               info->size = 0;
+               return (0);                     /* no or unknown flash  */
+       }
+
+       value = addr[1];                        /* device ID            */
+#ifdef DEBUG
+       printf("Flash type 0x%04X\n", value);
+#endif
+
+       if(value == (ushort)AMD_ID_LV400T) {
+               info->flash_id += FLASH_AM400T;
+               info->sector_count = 11;
+               info->size = 0x00080000;        /* => 0.5 MB            */
+       } else if(value == (ushort)AMD_ID_LV400B) {
+               info->flash_id += FLASH_AM400B;
+               info->sector_count = 11;
+               info->size = 0x00080000;        /* => 0.5 MB            */
+       } else if(value == (ushort)AMD_ID_LV800T) {
+               info->flash_id += FLASH_AM800T;
+               info->sector_count = 19;
+               info->size = 0x00100000;        /* => 1 MB              */
+       } else if(value == (ushort)AMD_ID_LV800B) {
+               info->flash_id += FLASH_AM800B;
+               info->sector_count = 19;
+               info->size = 0x00100000;        /* => 1 MB              */
+       } else if(value == (ushort)AMD_ID_LV160T) {
+               info->flash_id += FLASH_AM160T;
+               info->sector_count = 35;
+               info->size = 0x00200000;        /* => 2 MB              */
+       } else if(value == (ushort)AMD_ID_LV160B) {
+               info->flash_id += FLASH_AM160B;
+               info->sector_count = 35;
+               info->size = 0x00200000;        /* => 2 MB              */
+       } else if(value == (ushort)AMD_ID_LV320T) {
+               info->flash_id += FLASH_AM320T;
+               info->sector_count = 67;
+               info->size = 0x00400000;        /* => 4 MB              */
+       } else if(value == (ushort)AMD_ID_LV320B) {
+               info->flash_id += FLASH_AM320B;
+               info->sector_count = 67;
+               info->size = 0x00400000;        /* => 4 MB              */
+       } else {
+#ifdef DEBUG
+               printf("Unknown flash type 0x%04X\n", value);
+               info->size = CFG_FLASH_SIZE;
+#else
+               info->flash_id = FLASH_UNKNOWN;
+               return (0);                     /* => no or unknown flash */
+#endif
+       }
+
+       /* set up sector start address table */
+       if (info->flash_id & FLASH_BTYPE) {
+               /* set sector offsets for bottom boot block type        */
+               info->start[0] = base + 0x00000000;
+               info->start[1] = base + 0x00004000;
+               info->start[2] = base + 0x00006000;
+               info->start[3] = base + 0x00008000;
+               for (i = 4; i < info->sector_count; i++) {
+                       info->start[i] = base + ((i - 3) * 0x00010000);
+               }
+       } else {
+               /* set sector offsets for top boot block type           */
+               i = info->sector_count - 1;
+               info->start[i--] = base + info->size - 0x00004000;
+               info->start[i--] = base + info->size - 0x00006000;
+               info->start[i--] = base + info->size - 0x00008000;
+               for (; i >= 0; i--) {
+                       info->start[i] = base + (i * 0x00010000);
+               }
+       }
+
+       /* check for protected sectors */
+       for (i = 0; i < info->sector_count; i++) {
+               /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+               /* D0 = 1 if protected */
+               addr = (volatile unsigned short *)(info->start[i]);
+               info->protect[i] = addr[2] & 1;
+       }
+
+       /*
+        * Prevent writes to uninitialized FLASH.
+        */
+       if (info->flash_id != FLASH_UNKNOWN) {
+               addr = (volatile unsigned short *)info->start[0];
+
+       }
+
+       addr[0] = 0xF0F0;       /* reset bank */
+       __asm__ __volatile__(" sync\n ");
+       return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int    flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+       vu_short *addr = (vu_short*)(info->start[0]);
+       int flag, prot, sect, l_sect;
+       ulong start, now, last;
+
+       if ((s_first < 0) || (s_first > s_last)) {
+               if (info->flash_id == FLASH_UNKNOWN) {
+                       printf ("- missing\n");
+               } else {
+                       printf ("- no sectors to erase\n");
+               }
+               return 1;
+       }
+
+       if ((info->flash_id == FLASH_UNKNOWN) ||
+           (info->flash_id > FLASH_AMD_COMP)) {
+               printf ("Can't erase unknown flash type %08lx - aborted\n",
+                       info->flash_id);
+               return 1;
+       }
+
+       prot = 0;
+       for (sect=s_first; sect<=s_last; ++sect) {
+               if (info->protect[sect]) {
+                       prot++;
+               }
+       }
+
+       if (prot) {
+               printf ("- Warning: %d protected sectors will not be erased!\n",
+                       prot);
+       } else {
+               printf ("\n");
+       }
+
+       l_sect = -1;
+
+       /* Disable interrupts which might cause a timeout here */
+       flag = disable_interrupts();
+
+       addr[0x0555] = 0xAAAA;
+       addr[0x02AA] = 0x5555;
+       addr[0x0555] = 0x8080;
+       addr[0x0555] = 0xAAAA;
+       addr[0x02AA] = 0x5555;
+       __asm__ __volatile__(" sync\n ");
+
+       /* Start erase on unprotected sectors */
+       for (sect = s_first; sect<=s_last; sect++) {
+               if (info->protect[sect] == 0) { /* not protected */
+                       addr = (vu_short*)(info->start[sect]);
+                       addr[0] = 0x3030;
+                       l_sect = sect;
+               }
+       }
+
+       /* re-enable interrupts if necessary */
+       if (flag)
+               enable_interrupts();
+
+       /* wait at least 80us - let's wait 1 ms */
+       udelay (1000);
+
+       /*
+        * We wait for the last triggered sector
+        */
+       if (l_sect < 0)
+               goto DONE;
+
+       start = get_timer (0);
+       last  = start;
+       addr = (vu_short*)(info->start[l_sect]);
+       while ((addr[0] & 0x0080) != 0x0080) {
+               if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+                       printf ("Timeout\n");
+                       addr[0] = 0xF0F0;       /* reset bank */
+                       __asm__ __volatile__(" sync\n ");
+                       return 1;
+               }
+               /* show that we're waiting */
+               if ((now - last) > 1000) {      /* every second */
+                       putc ('.');
+                       last = now;
+               }
+       }
+
+DONE:
+       /* reset to read mode */
+       addr = (vu_short*)info->start[0];
+       addr[0] = 0xF0F0;       /* reset bank */
+       __asm__ __volatile__(" sync\n ");
+
+       printf (" done\n");
+       return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+       ulong cp, wp, data;
+       int i, l, rc;
+
+       wp = (addr & ~3);       /* get lower word aligned address */
+
+       /*
+        * handle unaligned start bytes
+        */
+       if ((l = addr - wp) != 0) {
+               data = 0;
+               for (i=0, cp=wp; i<l; ++i, ++cp) {
+                       data = (data << 8) | (*(uchar *)cp);
+               }
+               for (; i<4 && cnt>0; ++i) {
+                       data = (data << 8) | *src++;
+                       --cnt;
+                       ++cp;
+               }
+               for (; cnt==0 && i<4; ++i, ++cp) {
+                       data = (data << 8) | (*(uchar *)cp);
+               }
+
+               if ((rc = write_word(info, wp, data)) != 0) {
+                       return (rc);
+               }
+               wp += 4;
+       }
+
+       /*
+        * handle word aligned part
+        */
+       while (cnt >= 4) {
+               data = 0;
+               for (i=0; i<4; ++i) {
+                       data = (data << 8) | *src++;
+               }
+               if ((rc = write_word(info, wp, data)) != 0) {
+                       return (rc);
+               }
+               wp  += 4;
+               cnt -= 4;
+       }
+
+       if (cnt == 0) {
+               return (0);
+       }
+
+       /*
+        * handle unaligned tail bytes
+        */
+       data = 0;
+       for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+               data = (data << 8) | *src++;
+               --cnt;
+       }
+       for (; i<4; ++i, ++cp) {
+               data = (data << 8) | (*(uchar *)cp);
+       }
+
+       return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+       vu_short *addr = (vu_short*)(info->start[0]);
+       ulong start;
+       int flag;
+       int j;
+
+       /* Check if Flash is (sufficiently) erased */
+       if (((*(vu_long *)dest) & data) != data) {
+               return (2);
+       }
+       /* Disable interrupts which might cause a timeout here */
+       flag = disable_interrupts();
+
+       /* The original routine was designed to write 32 bit words to
+        * 32 bit wide memory.  We have 16 bit wide memory so we do
+        * two writes.  We write the LSB first at dest+2 and then the
+        * MSB at dest (lousy big endian).
+        */
+       dest += 2;
+       for(j = 0; j < 2; j++) {
+               addr[0x0555] = 0xAAAA;
+               addr[0x02AA] = 0x5555;
+               addr[0x0555] = 0xA0A0;
+               __asm__ __volatile__(" sync\n ");
+
+               *((vu_short *)dest) = (ushort)data;
+
+               /* re-enable interrupts if necessary */
+               if (flag)
+                       enable_interrupts();
+
+               /* data polling for D7 */
+               start = get_timer (0);
+               while (*(vu_short *)dest != (ushort)data) {
+                       if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+                               return (1);
+                       }
+               }
+               dest -= 2;
+               data >>= 16;
+       }
+       return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/sandpoint/README b/board/sandpoint/README
new file mode 100644 (file)
index 0000000..9e48168
--- /dev/null
@@ -0,0 +1,15 @@
+This port of U-Boot will run on a Motorola Sandpoint 3 development
+system equipped with a Unity X4 PPMC card (MPC8240 CPU) only. It is a
+snapshot of work in progress and far from being completed. In order
+to run it on the target system, it has to be downloaded using the
+DINK32 monitor program that came with your Sandpoint system. Please
+note that DINK32 does not accept the S-Record file created by the
+U-Boot build process unmodified, because it contains CR/LF line
+terminators. You have to strip the CR characters first. There is a
+tiny script named 'dinkdl' I created for this purpose.
+
+The Sandpoint port is based on the work of Rob Taylor, who does not
+seem to maintain it any more. I can be reached by mail as
+tkoeller@gmx.net.
+
+Thomas Koeller
diff --git a/disk/part_iso.c b/disk/part_iso.c
new file mode 100644 (file)
index 0000000..a98539d
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cmd_disk.h>
+#include "part_iso.h"
+
+#if ((CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI)) && defined(CONFIG_ISO_PARTITION)
+
+#undef ISO_PART_DEBUG
+
+#ifdef ISO_PART_DEBUG
+#define        PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* enable this if CDs are written with the PowerPC Platform ID */
+#undef CHECK_FOR_POWERPC_PLATTFORM
+#define CD_SECTSIZE 2048
+
+static unsigned char tmpbuf[CD_SECTSIZE];
+
+/* Convert char[4] in little endian format to the host format integer
+ */
+static inline unsigned long le32_to_int(unsigned char *le32)
+{
+    return ((le32[3] << 24) +
+           (le32[2] << 16) +
+           (le32[1] << 8) +
+            le32[0]
+          );
+}
+/* Convert char[2] in little endian format to the host format integer
+ */
+static inline unsigned short le16_to_int(unsigned char *le16)
+{
+    return ((le16[1] << 8) +
+          le16[0]
+          );
+}
+
+
+/* only boot records will be listed as valid partitions */
+int get_partition_info_iso_verb(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info, int verb)
+{
+       int i,offset,entry_num;
+       unsigned short *chksumbuf;
+       unsigned short chksum;
+       unsigned long newblkaddr,blkaddr,lastsect,bootaddr;
+       iso_boot_rec_t *pbr = (iso_boot_rec_t   *)tmpbuf; /* boot record */
+       iso_pri_rec_t *ppr = (iso_pri_rec_t     *)tmpbuf;       /* primary desc */
+       iso_val_entry_t *pve = (iso_val_entry_t *)tmpbuf;
+       iso_init_def_entry_t *pide;
+
+       /* the first sector (sector 0x10) must be a primary volume desc */
+       blkaddr=PVD_OFFSET;
+       if (dev_desc->block_read (dev_desc->dev, PVD_OFFSET, 1, (ulong *) tmpbuf) != 1)
+       return (-1);
+       if(ppr->desctype!=0x01) {
+               if(verb)
+                       printf ("** First descriptor is NOT a primary desc on %d:%d **\n",
+                               dev_desc->dev, part_num);
+               return (-1);
+       }
+       if(strncmp(ppr->stand_ident,"CD001",5)!=0) {
+               if(verb)
+                       printf ("** Wrong ISO Ident: %s on %d:%d **\n",
+                               ppr->stand_ident,dev_desc->dev, part_num);
+               return (-1);
+       }
+       lastsect= ((ppr->firstsek_LEpathtab1_LE & 0x000000ff)<<24) +
+                 ((ppr->firstsek_LEpathtab1_LE & 0x0000ff00)<< 8) +
+                 ((ppr->firstsek_LEpathtab1_LE & 0x00ff0000)>> 8) +
+                 ((ppr->firstsek_LEpathtab1_LE & 0xff000000)>>24) ;
+       info->blksz=ppr->secsize_BE; /* assuming same block size for all entries */
+       PRINTF(" Lastsect:%08lx\n",lastsect);
+       for(i=blkaddr;i<lastsect;i++) {
+               if (dev_desc->block_read (dev_desc->dev, i, 1, (ulong *) tmpbuf) != 1)
+               return (-1);
+               if(ppr->desctype==0x00)
+                       break; /* boot entry found */
+               if(ppr->desctype==0xff) {
+                       if(verb)
+                               printf ("** No valid boot catalog found on %d:%d **\n",
+                                       dev_desc->dev, part_num);
+                       return (-1);
+               }
+       }
+       /* boot entry found */
+       if(strncmp(pbr->ident_str,"EL TORITO SPECIFICATION",23)!=0) {
+               if(verb)
+                       printf ("** Wrong El Torito ident: %s on %d:%d **\n",
+                               pbr->ident_str,dev_desc->dev, part_num);
+               return (-1);
+       }
+       bootaddr=le32_to_int(pbr->pointer);
+       PRINTF(" Boot Entry at: %08lX\n",bootaddr);
+       if (dev_desc->block_read (dev_desc->dev, bootaddr, 1, (ulong *) tmpbuf) != 1) {
+               if(verb)
+                       printf ("** Can't read Boot Entry at %lX on %d:%d **\n",
+                               bootaddr,dev_desc->dev, part_num);
+               return (-1);
+       }
+       chksum=0;
+       chksumbuf = (unsigned short *)tmpbuf;
+       for(i=0;i<0x10;i++)
+               chksum+=((chksumbuf[i] &0xff)<<8)+((chksumbuf[i] &0xff00)>>8);
+       if(chksum!=0) {
+               if(verb)
+                       printf ("** Checksum Error in booting catalog validation entry on %d:%d **\n",
+                               dev_desc->dev, part_num);
+               return (-1);
+       }
+       if((pve->key[0]!=0x55)||(pve->key[1]!=0xAA)) {
+               if(verb)
+                       printf ("** Key 0x55 0xAA error on %d:%d **\n",
+                               dev_desc->dev, part_num);
+               return(-1);
+       }
+#ifdef CHECK_FOR_POWERPC_PLATTFORM
+       if(pve->platform!=0x01) {
+               if(verb)
+                       printf ("** No PowerPC platform CD on %d:%d **\n",
+                               dev_desc->dev, part_num);
+               return(-1);
+       }
+#endif
+       /* the validation entry seems to be ok, now search the "partition" */
+       entry_num=0;
+       offset=0x20;
+       sprintf (info->type, "U-Boot");
+       switch(dev_desc->if_type) {
+               case IF_TYPE_IDE:
+               case IF_TYPE_ATAPI:
+                       sprintf (info->name, "hd%c%d\n", 'a' + dev_desc->dev, part_num);
+                       break;
+               case IF_TYPE_SCSI:
+                       sprintf (info->name, "sd%c%d\n", 'a' + dev_desc->dev, part_num);
+                       break;
+               case IF_TYPE_USB:
+                       sprintf (info->name, "usbd%c%d\n", 'a' + dev_desc->dev, part_num);
+                       break;
+               case IF_TYPE_DOC:
+                       sprintf (info->name, "docd%c%d\n", 'a' + dev_desc->dev, part_num);
+                       break;
+               default:
+                       sprintf (info->name, "xx%c%d\n", 'a' + dev_desc->dev, part_num);
+                       break;
+       }
+       /* the bootcatalog (including validation Entry) is limited to 2048Bytes
+        * (63 boot entries + validation entry) */
+        while(offset<2048) {
+               pide=(iso_init_def_entry_t *)&tmpbuf[offset];
+               if ((pide->boot_ind==0x88) ||
+                   (pide->boot_ind==0x00)) { /* Header Id for default Sections Entries */
+                       if(entry_num==part_num) { /* part found */
+                               goto found;
+                       }
+                       entry_num++; /* count partitions Entries (boot and non bootables */
+                       offset+=0x20;
+                       continue;
+               }
+               if ((pide->boot_ind==0x90) ||   /* Section Header Entry */
+                   (pide->boot_ind==0x91) ||   /* Section Header Entry (last) */
+                   (pide->boot_ind==0x44)) {   /* Extension Indicator */
+                       offset+=0x20; /* skip unused entries */
+               }
+               else {
+                       if(verb)
+                               printf ("** Partition %d not found on device %d **\n",
+                                       part_num,dev_desc->dev);
+                       return(-1);
+               }
+       }
+       /* if we reach this point entire sector has been
+        * searched w/o succsess */
+       if(verb)
+               printf ("** Partition %d not found on device %d **\n",
+                       part_num,dev_desc->dev);
+       return(-1);
+found:
+       if(pide->boot_ind!=0x88) {
+               if(verb)
+                       printf ("** Partition %d is not bootable on device %d **\n",
+                               part_num,dev_desc->dev);
+               return (-1);
+       }
+       switch(pide->boot_media) {
+               case 0x00: /* no emulation */
+                       info->size=le16_to_int(pide->sec_cnt)>>2;
+                       break;
+               case 0x01:      info->size=2400>>2; break; /* 1.2MByte Floppy */
+               case 0x02:      info->size=2880>>2; break; /* 1.44MByte Floppy */
+               case 0x03:      info->size=5760>>2; break; /* 2.88MByte Floppy */
+               case 0x04:      info->size=2880>>2; break; /* dummy (HD Emulation) */
+               default:        info->size=0; break;
+       }
+       newblkaddr=le32_to_int(pide->rel_block_addr);
+       info->start=newblkaddr;
+       PRINTF(" part %d found @ %lx size %lx\n",part_num,newblkaddr,info->size);
+       return 0;
+}
+
+int get_partition_info_iso(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info)
+{
+       return(get_partition_info_iso_verb(dev_desc, part_num, info, 1));
+}
+
+
+
+void print_part_iso(block_dev_desc_t * dev_desc)
+{
+       disk_partition_t info;
+       int i;
+       if(get_partition_info_iso_verb(dev_desc,0,&info,0)==-1) {
+               printf("** No boot partition found on device %d **\n",dev_desc->dev);
+               return;
+       }
+       printf("Part   Start     Sect x Size Type\n");
+       i=0;
+       do {
+               printf (" %2d %8ld %8ld %6ld %.32s\n",
+                       i, info.start, info.size, info.blksz, info.type);
+               i++;
+       } while (get_partition_info_iso_verb(dev_desc,i,&info,0)!=-1);
+}
+
+int test_part_iso (block_dev_desc_t *dev_desc)
+{
+       disk_partition_t info;
+
+       return(get_partition_info_iso_verb(dev_desc,0,&info,0));
+}
+
+#endif /* ((CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI)) && defined(CONFIG_ISO_PARTITION) */
diff --git a/doc/README.OXC b/doc/README.OXC
new file mode 100644 (file)
index 0000000..e7bb76f
--- /dev/null
@@ -0,0 +1,25 @@
+This document contains different information about the port
+of U-Boot for the OXC board designed by Lucent Technologies,
+Inc.
+
+1. Showing activity
+
+U-Boot for the OXC board can show its current status using
+the Active LED. This feature is configured by the following
+options:
+
+CONFIG_SHOW_ACTIVITY
+
+  When this option is on, the Active LED is blinking fast
+when U-Boot runs in the idle loop (i.e. waits for user
+commands from serial console) and blinking slow when it
+downloads an image over network. When U-Boot loads an image
+over serial line the Active LED does not blink and its state
+is random (i.e. either constant on or constant off).
+
+CONFIG_SHOW_BOOT_PROGRESS
+
+  When this option is on, U-Boot switches the Active LED
+off before booting an image and switches it on if booting
+failed due to some reasons.
+
diff --git a/doc/README.autoboot b/doc/README.autoboot
new file mode 100644 (file)
index 0000000..20736ca
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * (C) Copyright 2001
+ * Dave Ellis, SIXNET, dge@sixnetio.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+Using autoboot configuration options
+====================================
+
+The basic autoboot configuration options are documented in the main
+U-Boot README. See it for details. They are:
+
+  bootdelay
+  bootcmd
+  CONFIG_BOOTDELAY
+  CONFIG_BOOTCOMMAND
+
+Some additional options that make autoboot safer in a production
+product are documented here.
+
+Why use them?
+-------------
+
+The basic autoboot feature allows a system to automatically boot to
+the real application (such as Linux) without a user having to enter
+any commands. If any key is pressed before the boot delay time
+expires, U-Boot stops the autoboot process, gives a U-Boot prompt
+and waits forever for a command. That's a good thing if you pressed a
+key because you wanted to get the prompt.
+
+It's not so good if the key press was a stray character on the
+console serial port, say because a user who knows nothing about
+U-Boot pressed a key before the system had time to boot. It's even
+worse on an embedded product that doesn't have a console during
+normal use. The modem plugged into that console port sends a
+character at the wrong time and the system hangs, with no clue as to
+why it isn't working.
+
+You might want the system to autoboot to recover after an external
+configuration program stops autoboot. If the configuration program
+dies or loses its connection (modems can disconnect at the worst
+time) U-Boot will patiently wait forever for it to finish.
+
+These additional configuration options can help provide a system that
+boots when it should, but still allows access to U-Boot.
+
+What they do
+------------
+
+  CONFIG_BOOT_RETRY_TIME
+  CONFIG_BOOT_RETRY_MIN
+
+  bootretry environment variable
+
+        These options determine what happens after autoboot is
+        stopped and U-Boot is waiting for commands.
+
+        CONFIG_BOOT_RETRY_TIME must be defined to enable the boot
+        retry feature. If the environment variable 'bootretry' is
+        found then its value is used, otherwise the retry timeout is
+        CONFIG_BOOT_RETRY_TIME. CONFIG_BOOT_RETRY_MIN is optional and
+        defaults to CONFIG_BOOT_RETRY_TIME. All times are in seconds.
+
+        If the retry timeout is negative, the U-Boot command prompt
+        never times out. Otherwise it is forced to be at least
+        CONFIG_BOOT_RETRY_MIN seconds. If no valid U-Boot command is
+        entered before the specified time the boot delay sequence is
+        restarted. Each command that U-Boot executes restarts the
+        timeout.
+
+        If CONFIG_BOOT_RETRY_TIME < 0 the feature is there, but
+        doesn't do anything unless the environment variable
+        'bootretry' is >= 0.
+
+  CONFIG_AUTOBOOT_KEYED
+  CONFIG_AUTOBOOT_PROMPT
+  CONFIG_AUTOBOOT_DELAY_STR
+  CONFIG_AUTOBOOT_STOP_STR
+  CONFIG_AUTOBOOT_DELAY_STR2
+  CONFIG_AUTOBOOT_STOP_STR2
+
+  bootdelaykey environment variable
+  bootstopkey  environment variable
+  bootdelaykey2        environment variable
+  bootstopkey2 environment variable
+
+        These options give more control over stopping autoboot. When
+        they are used a specific character or string is required to
+        stop or delay autoboot.
+
+       Define CONFIG_AUTOBOOT_KEYED (no value required) to enable
+       this group of options.  CONFIG_AUTOBOOT_DELAY_STR,
+       CONFIG_AUTOBOOT_STOP_STR or both should be specified (or
+       specified by the corresponding environment variable),
+       otherwise there is no way to stop autoboot.
+
+        CONFIG_AUTOBOOT_PROMPT is displayed before the boot delay
+        selected by CONFIG_BOOTDELAY starts. If it is not defined
+        there is no output indicating that autoboot is in progress.
+        If "%d" is included, it is replaced by the number of seconds
+        remaining before autoboot will start, but it does not count
+        down the seconds. "autoboot in %d seconds\n" is a reasonable
+        prompt.
+
+        If CONFIG_AUTOBOOT_DELAY_STR or bootdelaykey is specified and
+        this string is received from console input before autoboot
+        starts booting, U-Boot gives a command prompt. The U-Boot
+        prompt will time out if CONFIG_BOOT_RETRY_TIME is used,
+        otherwise it never times out.
+
+        If CONFIG_AUTOBOOT_STOP_STR or bootstopkey is specified and
+        this string is received from console input before autoboot
+        starts booting, U-Boot gives a command prompt. The U-Boot
+        prompt never times out, even if CONFIG_BOOT_RETRY_TIME is
+        used.
+
+        The string recognition is not very sophisticated. If a
+        partial match is detected, the first non-matching character
+        is checked to see if starts a new match. There is no check
+        for a shorter partial match, so it's best if the first
+        character of a key string does not appear in the rest of the
+        string.
+
+        Using the CONFIG_AUTOBOOT_DELAY_STR2 /  bootdelaykey2  and/or
+        CONFIG_AUTOBOOT_STOP_STR2   /   bootstopkey  #defines  and/or
+        environment variables you can  specify  a  second,  alternate
+        string (which allows you to haw two "password" strings).
+
+  CONFIG_ZERO_BOOTDELAY_CHECK
+
+        If this option is defined, you can stop the autoboot process
+        by hitting a key even in that case when "bootdelay" has been
+        set to 0. You can set "bootdelay" to a negative value to
+        prevent the check for console input.
+
+  CONFIG_RESET_TO_RETRY
+
+        (Only effective when CONFIG_BOOT_RETRY_TIME is also set)
+        After the countdown timed out, the board will be reset to restart
+        again.
+
diff --git a/doc/README.console b/doc/README.console
new file mode 100644 (file)
index 0000000..6d477df
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+U-Boot console handling
+========================
+
+HOW THE CONSOLE WORKS?
+----------------------
+
+At system startup U-Boot initializes a serial console. When U-Boot
+relocates itself to RAM, all console drivers are initialized (they
+will register all detected console devices to the system for further
+use).
+
+If not defined in the environment, the first input device is assigned
+to the 'stdin' file, the first output one to 'stdout' and 'stderr'.
+
+You can use the command "coninfo" to see all registered console
+devices and their flags. You can assign a standard file (stdin,
+stdout or stderr) to any device you see in that list simply by
+assigning its name to the corresponding environment variable. For
+example:
+
+    setenv stdin wl_kbd                <- To use the wireless keyboard
+    setenv stdout video                <- To use the video console
+
+Do a simple "saveenv" to save the console settings in the environment
+and get them working on the next startup, too.
+
+HOW CAN I USE STANDARD FILE INTO THE SOURCES?
+---------------------------------------------
+
+You can use the following functions to access the console:
+
+* STDOUT:
+    putc       (to put a char to stdout)
+    puts       (to put a string to stdout)
+    printf     (to format and put a string to stdout)
+
+* STDIN:
+    tstc       (to test for the presence of a char in stdin)
+    getc       (to get a char from stdin)
+
+* STDERR:
+    eputc      (to put a char to stderr)
+    eputs      (to put a string to stderr)
+    eprintf    (to format and put a string to stderr)
+
+* FILE (can be 'stdin', 'stdout', 'stderr'):
+    fputc      (like putc but redirected to a file)
+    fputs      (like puts but redirected to a file)
+    fprintf    (like printf but redirected to a file)
+    ftstc      (like tstc but redirected to a file)
+    fgetc      (like getc but redirected to a file)
+
+Remember that all FILE-related functions CANNOT be used before
+U-Boot relocation (done in 'board_init_r' in common/board.c).
+
+HOW CAN I USE STANDARD FILE INTO APPLICATIONS?
+----------------------------------------------
+
+Use the 'bd_mon_fnc' field of the bd_t structure passed to the
+application to do everything you want with the console.
+
+But REMEMBER that that will work only if you have not overwritten any
+U-Boot code while loading (or uncompressing) the image of your
+application.
+
+For example, you won't get the console stuff running in the Linux
+kernel because the kernel overwrites U-Boot before running. Only
+some parameters like the framebuffer descriptors are passed to the
+kernel in the high memory area to let the applications (the kernel)
+use the framebuffers initialized by U-Boot.
+
+SUPPORTED DRIVERS
+-----------------
+
+Working drivers:
+
+    serial     (architecture dependent serial stuff)
+    video      (mpc8xx video controller)
+
+Work in progress:
+
+    wl_kbd     (Wireless 4PPM keyboard)
+
+Waiting for volounteers:
+
+    lcd        (mpc8xx lcd controller; to )
+
+TESTED CONFIGURATIONS
+---------------------
+
+The driver has been tested with the following configurations (see
+CREDITS for other contact informations):
+
+- MPC823FADS with AD7176 on a PAL TV (YCbYCr)  - arsenio@tin.it
+- GENIETV    with AD7177 on a PAL TV (YCbYCr)  - arsenio@tin.it
diff --git a/drivers/bcm570x.c b/drivers/bcm570x.c
new file mode 100644 (file)
index 0000000..a88880a
--- /dev/null
@@ -0,0 +1,1709 @@
+/*
+ * Broadcom BCM570x Ethernet Driver for U-Boot.
+ * Support 5701, 5702, 5703, and 5704. Single instance driver.
+ * Copyright (C) 2002 James F. Dougherty (jfd@broadcom.com)
+ */
+
+#include <common.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && (!defined(CONFIG_NET_MULTI)) && \
+       defined(CONFIG_BCM570x)
+
+#ifdef CONFIG_BMW
+#include <mpc824x.h>
+#endif
+#include <net.h>
+#include "bcm570x_mm.h"
+#include "bcm570x_autoneg.h"
+#include <pci.h>
+#include <malloc.h>
+
+
+
+/*
+ * PCI Registers and definitions.
+ */
+#define PCI_CMD_MASK   0xffff0000      /* mask to save status bits */
+#define PCI_ANY_ID (~0)
+
+/*
+ * PCI memory base for Ethernet device as well as device Interrupt.
+ */
+#define BCM570X_MBAR   0x80100000
+#define BCM570X_ILINE   1
+
+
+
+#define SECOND_USEC    1000000
+#define MAX_PACKET_SIZE 1600
+#define MAX_UNITS       4
+
+/* Globals to this module */
+int initialized = 0;
+unsigned int ioBase = 0;
+volatile PLM_DEVICE_BLOCK    pDevice = NULL;        /* 570x softc */
+volatile PUM_DEVICE_BLOCK    pUmDevice = NULL;
+
+/* Used to pass the full-duplex flag, etc. */
+int line_speed[MAX_UNITS] = {0,0,0,0};
+static int full_duplex[MAX_UNITS] = {1,1,1,1};
+static int rx_flow_control[MAX_UNITS] = {0,0,0,0};
+static int tx_flow_control[MAX_UNITS] = {0,0,0,0};
+static int auto_flow_control[MAX_UNITS] = {0,0,0,0};
+static int tx_checksum[MAX_UNITS] = {1,1,1,1};
+static int rx_checksum[MAX_UNITS] = {1,1,1,1};
+static int auto_speed[MAX_UNITS] = {1,1,1,1};
+
+#if JUMBO_FRAMES
+/* Jumbo MTU for interfaces. */
+static int mtu[MAX_UNITS] = {0,0,0,0};
+#endif
+
+/* Turn on Wake-on lan for a device unit */
+static int enable_wol[MAX_UNITS] = {0,0,0,0};
+
+#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
+static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
+       {TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT, TX_DESC_CNT};
+
+#define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT
+static unsigned int rx_std_desc_cnt[MAX_UNITS] =
+       {RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT};
+
+static unsigned int rx_adaptive_coalesce[MAX_UNITS] = {1,1,1,1};
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+#define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT
+static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] =
+       {JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT};
+#endif
+#define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS
+static unsigned int rx_coalesce_ticks[MAX_UNITS] =
+       {RX_COAL_TK, RX_COAL_TK, RX_COAL_TK, RX_COAL_TK};
+
+#define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES
+static unsigned int rx_max_coalesce_frames[MAX_UNITS] =
+       {RX_COAL_FM, RX_COAL_FM, RX_COAL_FM, RX_COAL_FM};
+
+#define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS
+static unsigned int tx_coalesce_ticks[MAX_UNITS] =
+       {TX_COAL_TK, TX_COAL_TK, TX_COAL_TK, TX_COAL_TK};
+
+#define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES
+static unsigned int tx_max_coalesce_frames[MAX_UNITS] =
+       {TX_COAL_FM, TX_COAL_FM, TX_COAL_FM, TX_COAL_FM};
+
+#define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS
+static unsigned int stats_coalesce_ticks[MAX_UNITS] =
+       {ST_COAL_TK, ST_COAL_TK, ST_COAL_TK, ST_COAL_TK};
+
+
+
+/*
+ * Legitimate values for BCM570x device types
+ */
+typedef enum {
+       BCM5700VIGIL = 0,
+       BCM5700A6,
+       BCM5700T6,
+       BCM5700A9,
+       BCM5700T9,
+       BCM5700,
+       BCM5701A5,
+       BCM5701T1,
+       BCM5701T8,
+       BCM5701A7,
+       BCM5701A10,
+       BCM5701A12,
+       BCM5701,
+       BCM5702,
+       BCM5703,
+       BCM5703A31,
+       TC996T,
+       TC996ST,
+       TC996SSX,
+       TC996SX,
+       TC996BT,
+       TC997T,
+       TC997SX,
+       TC1000T,
+       TC940BR01,
+       TC942BR01,
+       NC6770,
+       NC7760,
+       NC7770,
+       NC7780
+} board_t;
+
+/* Chip-Rev names for each device-type */
+static struct {
+    char* name;
+} chip_rev[] = {
+       {"BCM5700VIGIL"},
+       {"BCM5700A6"},
+       {"BCM5700T6"},
+       {"BCM5700A9"},
+       {"BCM5700T9"},
+       {"BCM5700"},
+       {"BCM5701A5"},
+       {"BCM5701T1"},
+       {"BCM5701T8"},
+       {"BCM5701A7"},
+       {"BCM5701A10"},
+       {"BCM5701A12"},
+       {"BCM5701"},
+       {"BCM5702"},
+       {"BCM5703"},
+       {"BCM5703A31"},
+       {"TC996T"},
+       {"TC996ST"},
+       {"TC996SSX"},
+       {"TC996SX"},
+       {"TC996BT"},
+       {"TC997T"},
+       {"TC997SX"},
+       {"TC1000T"},
+       {"TC940BR01"},
+       {"TC942BR01"},
+       {"NC6770"},
+       {"NC7760"},
+       {"NC7770"},
+       {"NC7780"},
+       {0}
+};
+
+
+/* indexed by board_t, above */
+static struct {
+    char *name;
+} board_info[] = {
+       { "Broadcom Vigil B5700 1000Base-T" },
+       { "Broadcom BCM5700 1000Base-T" },
+       { "Broadcom BCM5700 1000Base-SX" },
+       { "Broadcom BCM5700 1000Base-SX" },
+       { "Broadcom BCM5700 1000Base-T" },
+       { "Broadcom BCM5700" },
+       { "Broadcom BCM5701 1000Base-T" },
+       { "Broadcom BCM5701 1000Base-T" },
+       { "Broadcom BCM5701 1000Base-T" },
+       { "Broadcom BCM5701 1000Base-SX" },
+       { "Broadcom BCM5701 1000Base-T" },
+       { "Broadcom BCM5701 1000Base-T" },
+       { "Broadcom BCM5701" },
+       { "Broadcom BCM5702 1000Base-T" },
+       { "Broadcom BCM5703 1000Base-T" },
+       { "Broadcom BCM5703 1000Base-SX" },
+       { "3Com 3C996 10/100/1000 Server NIC" },
+       { "3Com 3C996 10/100/1000 Server NIC" },
+       { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
+       { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
+       { "3Com 3C996B Gigabit Server NIC" },
+       { "3Com 3C997 Gigabit Server NIC" },
+       { "3Com 3C997 Gigabit Fiber-SX Server NIC" },
+       { "3Com 3C1000 Gigabit NIC" },
+       { "3Com 3C940 Gigabit LOM (21X21)" },
+       { "3Com 3C942 Gigabit LOM (31X31)" },
+       { "Compaq NC6770 Gigabit Server Adapter" },
+       { "Compaq NC7760 Gigabit Server Adapter" },
+       { "Compaq NC7770 Gigabit Server Adapter" },
+       { "Compaq NC7780 Gigabit Server Adapter" },
+       { 0 },
+};
+
+/* PCI Devices which use the 570x chipset */
+struct pci_device_table {
+    unsigned short vendor_id, device_id; /* Vendor/DeviceID */
+    unsigned short subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
+    unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
+    unsigned long board_id;        /* Data private to the driver */
+    int io_size, min_latency;
+} bcm570xDevices[] = {
+       {0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL ,128,32},
+       {0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6 ,128,32},
+       {0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6 ,128,32},
+       {0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9 ,128,32},
+       {0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9 ,128,32},
+       {0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700 ,128,32},
+       {0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700 ,128,32},
+       {0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700 ,128,32},
+       {0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700 ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX ,128,32},
+       {0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01 ,128,32},
+       {0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10 ,128,32},
+       {0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12 ,128,32},
+       {0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770 ,128,32},
+       {0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770 ,128,32},
+       {0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780 ,128,32},
+       {0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701 ,128,32},
+       {0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX ,128,32},
+       {0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT ,128,32},
+       {0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T ,128,32},
+       {0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01 ,128,32},
+       {0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701 ,128,32},
+       {0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 ,128,32},
+       {0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760 ,128,32},
+       {0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 ,128,32},
+       {0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 ,128,32},
+       {0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 ,128,32},
+       {0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 ,128,32},
+       {0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31 ,128,32},
+       {0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x1647, 0x0e11, 0x9a, 0, 0, NC7770 ,128,32},
+       {0x14e4, 0x1647, 0x0e11, 0x99, 0, 0, NC7780 ,128,32},
+       {0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31 ,128,32},
+       {0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703 ,128,32},
+       {0x14e4, 0x16a7, 0x0e11, 0x9a, 0, 0, NC7770 ,128,32},
+       {0x14e4, 0x16a7, 0x0e11, 0x99, 0, 0, NC7780 ,128,32},
+       {0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 ,128,32}
+};
+
+#define n570xDevices   (sizeof(bcm570xDevices)/sizeof(bcm570xDevices[0]))
+
+
+
+/*
+ * Allocate a packet buffer from the bcm570x packet pool.
+ */
+void *
+bcm570xPktAlloc(int u, int pksize)
+{
+    return malloc(pksize);
+}
+
+/*
+ * Free a packet previously allocated from the bcm570x packet
+ * buffer pool.
+ */
+void
+bcm570xPktFree(int u, void *p)
+{
+    free(p);
+}
+
+int
+bcm570xReplenishRxBuffers(PUM_DEVICE_BLOCK pUmDevice)
+{
+    PLM_PACKET pPacket;
+    PUM_PACKET pUmPacket;
+    void *skb;
+    int queue_rx = 0;
+    int ret = 0;
+
+    while ((pUmPacket = (PUM_PACKET)
+           QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
+
+       pPacket = (PLM_PACKET) pUmPacket;
+
+       /* reuse an old skb */
+       if (pUmPacket->skbuff) {
+           QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+           queue_rx = 1;
+           continue;
+       }
+       if ( ( skb = bcm570xPktAlloc(pUmDevice->index,
+                                    pPacket->u.Rx.RxBufferSize + 2)) == 0) {
+           QQ_PushHead(&pUmDevice->rx_out_of_buf_q.Container,pPacket);
+           printf("NOTICE: Out of RX memory.\n");
+           ret = 1;
+           break;
+       }
+
+       pUmPacket->skbuff = skb;
+       QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+       queue_rx = 1;
+    }
+
+    if (queue_rx) {
+       LM_QueueRxPackets(pDevice);
+    }
+
+    return ret;
+}
+
+/*
+ * Probe, Map, and Init 570x device.
+ */
+int eth_init(bd_t *bis)
+{
+    int i, rv, devFound = FALSE;
+    pci_dev_t  devbusfn;
+    unsigned short status;
+
+    /* Find PCI device, if it exists, configure ...  */
+    for( i = 0; i < n570xDevices; i++){
+       devbusfn = pci_find_device(bcm570xDevices[i].vendor_id,
+                                  bcm570xDevices[i].device_id, 0);
+       if(devbusfn == -1) {
+           continue; /* No device of that vendor/device ID */
+       } else {
+
+           /* Set ILINE */
+           pci_write_config_byte(devbusfn,
+                                 PCI_INTERRUPT_LINE, BCM570X_ILINE);
+
+           /*
+            * 0x10 - 0x14 define one 64-bit MBAR.
+            * 0x14 is the higher-order address bits of the BAR.
+            */
+           pci_write_config_dword(devbusfn,
+                                  PCI_BASE_ADDRESS_1, 0);
+
+           ioBase = BCM570X_MBAR;
+
+           pci_write_config_dword(devbusfn,
+                                  PCI_BASE_ADDRESS_0, ioBase);
+
+           /*
+            * Enable PCI memory, IO, and Master -- don't
+            * reset any status bits in doing so.
+            */
+           pci_read_config_word(devbusfn,
+                                PCI_COMMAND, &status);
+
+           status |= PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER;
+
+           pci_write_config_word(devbusfn,
+                                 PCI_COMMAND, status);
+
+           printf("\n%s: bus %d, device %d, function %d: MBAR=0x%x\n",
+                  board_info[bcm570xDevices[i].board_id].name,
+                  PCI_BUS(devbusfn),
+                  PCI_DEV(devbusfn),
+                  PCI_FUNC(devbusfn),
+                  ioBase);
+
+           /* Allocate once, but always clear on init */
+           if (!pDevice) {
+               pDevice = malloc(sizeof(UM_DEVICE_BLOCK));
+               pUmDevice = (PUM_DEVICE_BLOCK)pDevice;
+               memset(pDevice, 0x0, sizeof(UM_DEVICE_BLOCK));
+           }
+
+           /* Configure pci dev structure */
+           pUmDevice->pdev = devbusfn;
+           pUmDevice->index = 0;
+           pUmDevice->tx_pkt = 0;
+           pUmDevice->rx_pkt = 0;
+           devFound = TRUE;
+           break;
+       }
+    }
+
+    if(!devFound){
+       printf("eth_init: FAILURE: no BCM570x Ethernet devices found.\n");
+       return -1;
+    }
+
+    /* Setup defaults for chip */
+    pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+
+    if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) {
+       pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
+    } else {
+
+       if (rx_checksum[i]) {
+           pDevice->TaskToOffload |=
+               LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
+               LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
+       }
+
+       if (tx_checksum[i]) {
+           pDevice->TaskToOffload |=
+               LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
+               LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
+           pDevice->NoTxPseudoHdrChksum = TRUE;
+       }
+    }
+
+    /* Set Device PCI Memory base address */
+    pDevice->pMappedMemBase = (PLM_UINT8) ioBase;
+
+    /* Pull down adapter info */
+    if ((rv = LM_GetAdapterInfo(pDevice)) != LM_STATUS_SUCCESS) {
+       printf("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv );
+       return -2;
+    }
+
+    /* Lock not needed */
+    pUmDevice->do_global_lock = 0;
+
+    if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
+       /* The 5700 chip works best without interleaved register */
+       /* accesses on certain machines. */
+       pUmDevice->do_global_lock = 1;
+    }
+
+    /* Setup timer delays */
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) {
+       pDevice->UseTaggedStatus = TRUE;
+       pUmDevice->timer_interval = CFG_HZ;
+    }
+    else {
+       pUmDevice->timer_interval = CFG_HZ / 50;
+    }
+
+    /* Grab name .... */
+    pUmDevice->name =
+       (char*)malloc(strlen(board_info[bcm570xDevices[i].board_id].name)+1);
+    strcpy(pUmDevice->name,board_info[bcm570xDevices[i].board_id].name);
+
+    memcpy(pDevice->NodeAddress, bis->bi_enetaddr, 6);
+    LM_SetMacAddress(pDevice, bis->bi_enetaddr);
+    /* Init queues  .. */
+    QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container,
+                MAX_RX_PACKET_DESC_COUNT);
+    pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0;
+
+    /* delay for 4 seconds */
+    pUmDevice->delayed_link_ind =
+       (4 * CFG_HZ) / pUmDevice->timer_interval;
+
+    pUmDevice->adaptive_expiry =
+       CFG_HZ / pUmDevice->timer_interval;
+
+    /* Sometimes we get spurious ints. after reset when link is down. */
+    /* This field tells the isr to service the int. even if there is */
+    /* no status block update. */
+    pUmDevice->adapter_just_inited =
+       (3 * CFG_HZ) / pUmDevice->timer_interval;
+
+    /* Initialize 570x */
+    if (LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) {
+       printf("ERROR: Adapter initialization failed.\n");
+       return ERROR;
+    }
+
+    /* Enable chip ISR */
+    LM_EnableInterrupt(pDevice);
+
+    /* Clear MC table */
+    LM_MulticastClear(pDevice);
+
+    /* Enable Multicast */
+    LM_SetReceiveMask(pDevice,
+                     pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
+
+    pUmDevice->opened = 1;
+    pUmDevice->tx_full = 0;
+    pUmDevice->tx_pkt = 0;
+    pUmDevice->rx_pkt = 0;
+    printf("eth%d: %s @0x%lx,",
+          pDevice->index, pUmDevice->name, (unsigned long)ioBase);
+    printf(    "node addr ");
+    for (i = 0; i < 6; i++) {
+       printf("%2.2x", pDevice->NodeAddress[i]);
+    }
+    printf("\n");
+
+    printf("eth%d: ", pDevice->index);
+    printf("%s with ",
+          chip_rev[bcm570xDevices[i].board_id].name);
+
+    if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
+       printf("Broadcom BCM5400 Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
+       printf("Broadcom BCM5401 Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
+       printf("Broadcom BCM5411 Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID)
+       printf("Broadcom BCM5701 Integrated Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID)
+        printf("Broadcom BCM5703 Integrated Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
+       printf("Broadcom BCM8002 SerDes ");
+    else if (pDevice->EnableTbi)
+       printf("Agilent HDMP-1636 SerDes ");
+    else
+       printf("Unknown ");
+    printf("transceiver found\n");
+
+    printf("eth%d: %s, MTU: %d,",
+          pDevice->index, pDevice->BusSpeedStr, 1500);
+
+    if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) &&
+       rx_checksum[i])
+       printf("Rx Checksum ON\n");
+    else
+       printf("Rx Checksum OFF\n");
+    initialized++;
+
+    return 0;
+}
+
+/* Ethernet Interrupt service routine */
+void
+eth_isr(void)
+{
+    LM_UINT32 oldtag, newtag;
+    int i;
+
+    pUmDevice->interrupt = 1;
+
+    if (pDevice->UseTaggedStatus) {
+       if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
+           pUmDevice->adapter_just_inited) {
+            MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
+            oldtag = pDevice->pStatusBlkVirt->StatusTag;
+
+            for (i = 0; ; i++) {
+                pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
+                LM_ServiceInterrupts(pDevice);
+                newtag = pDevice->pStatusBlkVirt->StatusTag;
+                if ((newtag == oldtag) || (i > 50)) {
+                    MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, newtag << 24);
+                    if (pDevice->UndiFix) {
+                        REG_WR(pDevice, Grc.LocalCtrl,
+                              pDevice->GrcLocalCtrl | 0x2);
+                    }
+                    break;
+                 }
+               oldtag = newtag;
+           }
+       }
+    }
+    else {
+       while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
+           unsigned int dummy;
+
+           pDevice->pMemView->Mailbox.Interrupt[0].Low = 1;
+           pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
+           LM_ServiceInterrupts(pDevice);
+           pDevice->pMemView->Mailbox.Interrupt[0].Low = 0;
+           dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low;
+       }
+    }
+
+    /* Allocate new RX buffers */
+    if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
+       bcm570xReplenishRxBuffers(pUmDevice);
+    }
+
+    /* Queue packets */
+    if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container)) {
+       LM_QueueRxPackets(pDevice);
+    }
+
+    if (pUmDevice->tx_queued) {
+       pUmDevice->tx_queued = 0;
+    }
+
+    if(pUmDevice->tx_full){
+       if(pDevice->LinkStatus != LM_STATUS_LINK_DOWN){
+           printf("NOTICE: tx was previously blocked, restarting MUX\n");
+           pUmDevice->tx_full = 0;
+       }
+    }
+
+    pUmDevice->interrupt = 0;
+
+}
+
+int
+eth_send(volatile void *packet, int length)
+{
+    int status = 0;
+#if ET_DEBUG
+    unsigned char* ptr = (unsigned char*)packet;
+#endif
+    PLM_PACKET pPacket;
+    PUM_PACKET pUmPacket;
+
+    /* Link down, return */
+    while(pDevice->LinkStatus == LM_STATUS_LINK_DOWN) {
+#if 0
+        printf("eth%d: link down - check cable or link partner.\n",
+               pUmDevice->index);
+#endif
+       eth_isr();
+
+       /* Wait to see link for one-half a second before sending ... */
+       udelay(1500000);
+
+    }
+
+    /* Clear sent flag */
+    pUmDevice->tx_pkt = 0;
+
+    /* Previously blocked */
+    if(pUmDevice->tx_full){
+       printf("eth%d: tx blocked.\n", pUmDevice->index);
+       return 0;
+    }
+
+    pPacket = (PLM_PACKET)
+       QQ_PopHead(&pDevice->TxPacketFreeQ.Container);
+
+    if (pPacket == 0) {
+       pUmDevice->tx_full = 1;
+       printf("bcm570xEndSend: TX full!\n");
+       return 0;
+    }
+
+    if (pDevice->SendBdLeft.counter == 0) {
+       pUmDevice->tx_full = 1;
+       printf("bcm570xEndSend: no more TX descriptors!\n");
+       QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+       return 0;
+    }
+
+    if (length <= 0){
+       printf("eth: bad packet size: %d\n", length);
+       goto out;
+    }
+
+    /* Get packet buffers and fragment list */
+    pUmPacket = (PUM_PACKET) pPacket;
+    /* Single DMA Descriptor transmit.
+     * Fragments may be provided, but one DMA descriptor max is
+     * used to send the packet.
+     */
+    if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) {
+        if (pUmPacket->skbuff == NULL){
+           /* Packet was discarded */
+           printf("TX: failed (1)\n");
+           status = 1;
+       } else{
+           printf("TX: failed (2)\n");
+           status = 2;
+       }
+        QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
+        return status;
+    }
+
+    /* Copy packet to DMA buffer */
+    memset(pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE);
+    memcpy((void*)pUmPacket->skbuff, (void*)packet, length);
+    pPacket->PacketSize = length;
+    pPacket->Flags |= SND_BD_FLAG_END|SND_BD_FLAG_COAL_NOW;
+    pPacket->u.Tx.FragCount = 1;
+    /* We've already provided a frame ready for transmission */
+    pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
+
+    if ( LM_SendPacket(pDevice, pPacket) == LM_STATUS_FAILURE){
+        /*
+         *  A lower level send failure will push the packet descriptor back
+         *  in the free queue, so just deal with the VxWorks clusters.
+         */
+        if (pUmPacket->skbuff == NULL){
+           printf("TX failed (1)!\n");
+           /* Packet was discarded */
+           status = 3;
+       } else {
+           /* A resource problem ... */
+           printf("TX failed (2)!\n");
+           status = 4;
+       }
+
+       if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) == 0) {
+           printf("TX: emptyQ!\n");
+           pUmDevice->tx_full = 1;
+       }
+    }
+
+    while(pUmDevice->tx_pkt == 0){
+       /* Service TX */
+       eth_isr();
+    }
+#if ET_DEBUG
+    printf("eth_send: 0x%x, %d bytes\n"
+          "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n",
+          (int)pPacket, length,
+          ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5],
+          ptr[6],ptr[7],ptr[8],ptr[9],ptr[10],ptr[11],ptr[12],
+          ptr[13],ptr[14],ptr[15]);
+#endif
+    pUmDevice->tx_pkt = 0;
+    QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
+
+    /* Done with send */
+ out:
+    return status;
+}
+
+
+/* Ethernet receive */
+int
+eth_rx(void)
+{
+    PLM_PACKET          pPacket = NULL;
+    PUM_PACKET          pUmPacket = NULL;
+    void *skb;
+    int size=0;
+
+    while(TRUE) {
+
+    bcm570x_service_isr:
+       /* Pull down packet if it is there */
+       eth_isr();
+
+       /* Indicate RX packets called */
+       if(pUmDevice->rx_pkt){
+           /* printf("eth_rx: got a packet...\n"); */
+           pUmDevice->rx_pkt = 0;
+       } else {
+           /* printf("eth_rx: waiting for packet...\n"); */
+           goto bcm570x_service_isr;
+       }
+
+       pPacket = (PLM_PACKET)
+           QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);
+
+       if (pPacket == 0){
+           printf("eth_rx: empty packet!\n");
+           goto bcm570x_service_isr;
+       }
+
+       pUmPacket = (PUM_PACKET) pPacket;
+#if ET_DEBUG
+       printf("eth_rx: packet @0x%x\n",
+              (int)pPacket);
+#endif
+       /* If the packet generated an error, reuse buffer */
+       if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
+           ((size = pPacket->PacketSize) > pDevice->RxMtu)) {
+
+           /* reuse skb */
+           QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+           printf("eth_rx: error in packet dma!\n");
+           goto bcm570x_service_isr;
+       }
+
+       /* Set size and address */
+       skb = pUmPacket->skbuff;
+       size = pPacket->PacketSize;
+
+       /* Pass the packet up to the protocol
+        * layers.
+        */
+       NetReceive(skb, size);
+
+       /* Free packet buffer */
+       bcm570xPktFree (pUmDevice->index, skb);
+       pUmPacket->skbuff = NULL;
+
+       /* Reuse SKB */
+       QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+
+       return 0; /* Got a packet, bail ... */
+    }
+    return size;
+}
+
+
+
+/* Shut down device */
+void
+eth_halt(void)
+{
+    int i;
+    if ( initialized)
+    if (pDevice && pUmDevice && pUmDevice->opened){
+       printf("\neth%d:%s,", pUmDevice->index, pUmDevice->name);
+       printf("HALT,");
+        /* stop device */
+        LM_Halt(pDevice);
+       printf("POWER DOWN,");
+        LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
+
+        /* Free the memory allocated by the device in tigon3 */
+        for (i = 0; i < pUmDevice->mem_list_num; i++)  {
+            if (pUmDevice->mem_list[i])  {
+               /* sanity check */
+                if (pUmDevice->dma_list[i]) {  /* cache-safe memory */
+                    free(pUmDevice->mem_list[i]);
+               } else {
+                    free(pUmDevice->mem_list[i]);  /* normal memory   */
+               }
+           }
+       }
+       pUmDevice->opened = 0;
+       free(pDevice);
+       pDevice = NULL;
+       pUmDevice = NULL;
+       initialized = 0;
+       printf("done - offline.\n");
+    }
+}
+
+
+
+
+/*
+ *
+ * Middle Module: Interface between the HW driver (tigon3 modules) and
+ * the native (SENS) driver.  These routines implement the system
+ * interface for tigon3 on VxWorks.
+ */
+
+/* Middle module dependency - size of a packet descriptor */
+int MM_Packet_Desc_Size = sizeof(UM_PACKET);
+
+
+LM_STATUS
+MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice,
+               LM_UINT32 Offset,
+               LM_UINT32 *pValue32)
+{
+    UM_DEVICE_BLOCK *pUmDevice;
+    pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+    pci_read_config_dword(pUmDevice->pdev,
+                         Offset, (u32 *) pValue32);
+    return LM_STATUS_SUCCESS;
+}
+
+
+LM_STATUS
+MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice,
+                LM_UINT32 Offset,
+                LM_UINT32 Value32)
+{
+    UM_DEVICE_BLOCK *pUmDevice;
+    pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+    pci_write_config_dword(pUmDevice->pdev,
+                          Offset, Value32);
+    return LM_STATUS_SUCCESS;
+}
+
+
+LM_STATUS
+MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice,
+               LM_UINT32 Offset,
+               LM_UINT16 *pValue16)
+{
+    UM_DEVICE_BLOCK *pUmDevice;
+    pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+    pci_read_config_word(pUmDevice->pdev,
+                        Offset, (u16*) pValue16);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice,
+                LM_UINT32 Offset,
+                LM_UINT16 Value16)
+{
+    UM_DEVICE_BLOCK *pUmDevice;
+    pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
+    pci_write_config_word(pUmDevice->pdev,
+                         Offset, Value16);
+    return LM_STATUS_SUCCESS;
+}
+
+
+LM_STATUS
+MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+                       PLM_VOID *pMemoryBlockVirt,
+                       PLM_PHYSICAL_ADDRESS pMemoryBlockPhy,
+                       LM_BOOL Cached)
+{
+    PLM_VOID pvirt;
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    dma_addr_t mapping;
+
+    pvirt = malloc(BlockSize);
+    mapping = (dma_addr_t)(pvirt);
+    if (!pvirt)
+       return LM_STATUS_FAILURE;
+
+    pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+    pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
+    pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
+    memset(pvirt, 0, BlockSize);
+
+    *pMemoryBlockVirt = (PLM_VOID) pvirt;
+    MM_SetAddr (pMemoryBlockPhy, (dma_addr_t) mapping);
+
+    return LM_STATUS_SUCCESS;
+}
+
+
+
+LM_STATUS
+MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
+       PLM_VOID *pMemoryBlockVirt)
+{
+    PLM_VOID pvirt;
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+
+    pvirt = malloc(BlockSize);
+
+    if (!pvirt)
+       return LM_STATUS_FAILURE;
+
+    pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
+    pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
+    pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
+    memset(pvirt, 0, BlockSize);
+    *pMemoryBlockVirt = pvirt;
+
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_MapMemBase(PLM_DEVICE_BLOCK pDevice)
+{
+    printf("BCM570x PCI Memory base address @0x%x\n",
+          (unsigned int)pDevice->pMappedMemBase);
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice)
+{
+    int i;
+    void* skb;
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    PUM_PACKET pUmPacket = NULL;
+    PLM_PACKET pPacket = NULL;
+
+    for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
+       pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
+       pUmPacket = (PUM_PACKET) pPacket;
+
+       if (pPacket == 0) {
+           printf("MM_InitializeUmPackets: Bad RxPacketFreeQ\n");
+       }
+
+       skb = bcm570xPktAlloc(pUmDevice->index,
+                             pPacket->u.Rx.RxBufferSize + 2);
+
+       if (skb == 0) {
+           pUmPacket->skbuff = 0;
+           QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
+           printf("MM_InitializeUmPackets: out of buffer.\n");
+           continue;
+       }
+
+       pUmPacket->skbuff = skb;
+       QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+    }
+
+    pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8;
+
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_GetConfig(PLM_DEVICE_BLOCK pDevice)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    int index = pDevice->index;
+
+    if (auto_speed[index] == 0)
+       pDevice->DisableAutoNeg = TRUE;
+    else
+       pDevice->DisableAutoNeg = FALSE;
+
+    if (line_speed[index] == 0) {
+       pDevice->RequestedMediaType =
+           LM_REQUESTED_MEDIA_TYPE_AUTO;
+       pDevice->DisableAutoNeg = FALSE;
+    }
+    else {
+       if (line_speed[index] == 1000) {
+           if (pDevice->EnableTbi) {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX;
+           }
+           else if (full_duplex[index]) {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX;
+           }
+           else {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS;
+           }
+           if (!pDevice->EnableTbi)
+               pDevice->DisableAutoNeg = FALSE;
+       }
+       else if (line_speed[index] == 100) {
+           if (full_duplex[index]) {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX;
+           }
+           else {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS;
+           }
+       }
+       else if (line_speed[index] == 10) {
+           if (full_duplex[index]) {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX;
+           }
+           else {
+               pDevice->RequestedMediaType =
+                   LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
+           }
+       }
+       else {
+           pDevice->RequestedMediaType =
+               LM_REQUESTED_MEDIA_TYPE_AUTO;
+           pDevice->DisableAutoNeg = FALSE;
+       }
+
+    }
+    pDevice->FlowControlCap = 0;
+    if (rx_flow_control[index] != 0) {
+       pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
+    }
+    if (tx_flow_control[index] != 0) {
+       pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
+    }
+    if ((auto_flow_control[index] != 0) &&
+       (pDevice->DisableAutoNeg == FALSE)) {
+
+       pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
+       if ((tx_flow_control[index] == 0) &&
+           (rx_flow_control[index] == 0)) {
+           pDevice->FlowControlCap |=
+               LM_FLOW_CONTROL_TRANSMIT_PAUSE |
+               LM_FLOW_CONTROL_RECEIVE_PAUSE;
+       }
+    }
+
+    /* Default MTU for now */
+    pUmDevice->mtu = 1500;
+
+#if T3_JUMBO_RCV_RCB_ENTRY_COUNT
+    if (pUmDevice->mtu > 1500) {
+       pDevice->RxMtu = pUmDevice->mtu;
+       pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
+    }
+    else {
+       pDevice->RxJumboDescCnt = 0;
+    }
+    pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
+#else
+    pDevice->RxMtu = pUmDevice->mtu;
+#endif
+
+    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) {
+       pDevice->UseTaggedStatus = TRUE;
+       pUmDevice->timer_interval = CFG_HZ;
+    }
+    else {
+       pUmDevice->timer_interval = CFG_HZ/50;
+    }
+
+    pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
+    pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
+    /* Note:  adaptive coalescence really isn't adaptive in this driver */
+    pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index];
+    if (!pUmDevice->rx_adaptive_coalesce) {
+       pDevice->RxCoalescingTicks = rx_coalesce_ticks[index];
+       if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS)
+           pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS;
+       pUmDevice->rx_curr_coalesce_ticks =pDevice->RxCoalescingTicks;
+
+       pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index];
+       if (pDevice->RxMaxCoalescedFrames>MAX_RX_MAX_COALESCED_FRAMES)
+           pDevice->RxMaxCoalescedFrames =
+                               MAX_RX_MAX_COALESCED_FRAMES;
+       pUmDevice->rx_curr_coalesce_frames =
+           pDevice->RxMaxCoalescedFrames;
+       pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
+       if (pDevice->StatsCoalescingTicks>MAX_STATS_COALESCING_TICKS)
+           pDevice->StatsCoalescingTicks=
+               MAX_STATS_COALESCING_TICKS;
+       }
+       else {
+           pUmDevice->rx_curr_coalesce_frames =
+               DEFAULT_RX_MAX_COALESCED_FRAMES;
+           pUmDevice->rx_curr_coalesce_ticks =
+               DEFAULT_RX_COALESCING_TICKS;
+       }
+    pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
+    if (pDevice->TxCoalescingTicks > MAX_TX_COALESCING_TICKS)
+       pDevice->TxCoalescingTicks = MAX_TX_COALESCING_TICKS;
+    pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
+    if (pDevice->TxMaxCoalescedFrames > MAX_TX_MAX_COALESCED_FRAMES)
+       pDevice->TxMaxCoalescedFrames = MAX_TX_MAX_COALESCED_FRAMES;
+
+    if (enable_wol[index]) {
+       pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
+       pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
+    }
+    pDevice->NicSendBd = TRUE;
+
+    /* Don't update status blocks during interrupt */
+    pDevice->RxCoalescingTicksDuringInt = 0;
+    pDevice->TxCoalescingTicksDuringInt = 0;
+
+    return LM_STATUS_SUCCESS;
+
+}
+
+
+LM_STATUS
+MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    printf("Start TX DMA: dev=%d packet @0x%x\n",
+          (int)pUmDevice->index, (unsigned int)pPacket);
+
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    printf("Complete TX DMA: dev=%d packet @0x%x\n",
+          (int)pUmDevice->index, (unsigned int)pPacket);
+    return LM_STATUS_SUCCESS;
+}
+
+
+LM_STATUS
+MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
+{
+    char buf[128];
+    char lcd[4];
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    LM_FLOW_CONTROL flow_control;
+
+    pUmDevice->delayed_link_ind = 0;
+    memset(lcd, 0x0, 4);
+
+    if (Status == LM_STATUS_LINK_DOWN) {
+       sprintf(buf,"eth%d: %s: NIC Link is down\n",
+               pUmDevice->index,pUmDevice->name);
+        lcd[0] = 'L';lcd[1]='N';lcd[2]='K';lcd[3] = '?';
+    } else if (Status == LM_STATUS_LINK_ACTIVE) {
+       sprintf(buf,"eth%d:%s: ", pUmDevice->index, pUmDevice->name);
+
+       if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS){
+           strcat(buf,"1000 Mbps ");
+            lcd[0] = '1';lcd[1]='G';lcd[2]='B';
+       } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS){
+           strcat(buf,"100 Mbps ");
+            lcd[0] = '1';lcd[1]='0';lcd[2]='0';
+       } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS){
+           strcat(buf,"10 Mbps ");
+            lcd[0] = '1';lcd[1]='0';lcd[2]=' ';
+       }
+       if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL){
+           strcat(buf, "full duplex");
+            lcd[3] = 'F';
+       } else {
+           strcat(buf, "half duplex");
+            lcd[3] = 'H';
+       }
+       strcat(buf, " link up");
+
+       flow_control = pDevice->FlowControl &
+           (LM_FLOW_CONTROL_RECEIVE_PAUSE |
+            LM_FLOW_CONTROL_TRANSMIT_PAUSE);
+
+       if (flow_control) {
+           if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
+               strcat(buf,", receive ");
+               if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
+                   strcat(buf," & transmit ");
+           }
+           else {
+               strcat(buf,", transmit ");
+           }
+           strcat(buf,"flow control ON");
+       } else {
+           strcat(buf, ", flow control OFF");
+       }
+        strcat(buf,"\n");
+       printf("%s",buf);
+    }
+#if 0
+    sysLedDsply(lcd[0],lcd[1],lcd[2],lcd[3]);
+#endif
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    PUM_PACKET pUmPacket;
+    void *skb;
+
+    pUmPacket = (PUM_PACKET) pPacket;
+
+    if ((skb = pUmPacket->skbuff))
+       bcm570xPktFree(pUmDevice->index, skb);
+
+    pUmPacket->skbuff = 0;
+
+    return LM_STATUS_SUCCESS;
+}
+
+unsigned long
+MM_AnGetCurrentTime_us(PAN_STATE_INFO pAnInfo)
+{
+    return get_timer(0);
+}
+
+/*
+ *   Transform an MBUF chain into a single MBUF.
+ *   This routine will fail if the amount of data in the
+ *   chain overflows a transmit buffer.  In that case,
+ *   the incoming MBUF chain will be freed.  This routine can
+ *   also fail by not being able to allocate a new MBUF (including
+ *   cluster and mbuf headers).  In that case the failure is
+ *   non-fatal.  The incoming cluster chain is not freed, giving
+ *   the caller the choice of whether to try a retransmit later.
+ */
+LM_STATUS
+MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
+{
+    PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    void *skbnew;
+    int len = 0;
+
+    if (len == 0)
+        return (LM_STATUS_SUCCESS);
+
+    if (len > MAX_PACKET_SIZE){
+        printf ("eth%d: xmit frame discarded, too big!, size = %d\n",
+               pUmDevice->index, len);
+        return (LM_STATUS_FAILURE);
+    }
+
+    skbnew = bcm570xPktAlloc(pUmDevice->index, MAX_PACKET_SIZE);
+
+    if (skbnew == NULL) {
+        pUmDevice->tx_full = 1;
+        printf ("eth%d: out of transmit buffers", pUmDevice->index);
+        return (LM_STATUS_FAILURE);
+    }
+
+    /* New packet values */
+    pUmPacket->skbuff = skbnew;
+    pUmPacket->lm_packet.u.Tx.FragCount = 1;
+
+    return (LM_STATUS_SUCCESS);
+}
+
+
+LM_STATUS
+MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    pUmDevice->rx_pkt = 1;
+    return LM_STATUS_SUCCESS;
+}
+
+LM_STATUS
+MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
+{
+    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
+    PLM_PACKET pPacket;
+    PUM_PACKET pUmPacket;
+    void *skb;
+    while ( TRUE ) {
+
+       pPacket = (PLM_PACKET)
+           QQ_PopHead(&pDevice->TxPacketXmittedQ.Container);
+
+       if (pPacket == 0)
+           break;
+
+       pUmPacket = (PUM_PACKET) pPacket;
+       skb = (void*)pUmPacket->skbuff;
+
+        /*
+        * Free MBLK if we transmitted a fragmented packet or a
+        * non-fragmented packet straight from the VxWorks
+        * buffer pool. If packet was copied to a local transmit
+        * buffer, then there's no MBUF to free, just free
+        * the transmit buffer back to the cluster pool.
+        */
+
+       if (skb)
+           bcm570xPktFree (pUmDevice->index, skb);
+
+       pUmPacket->skbuff = 0;
+       QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
+       pUmDevice->tx_pkt = 1;
+    }
+    if (pUmDevice->tx_full) {
+       if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) >=
+           (QQ_GetSize(&pDevice->TxPacketFreeQ.Container) >> 1))
+           pUmDevice->tx_full = 0;
+    }
+    return LM_STATUS_SUCCESS;
+}
+
+/*
+ *  Scan an MBUF chain until we reach fragment number "frag"
+ *  Return its length and physical address.
+ */
+void MM_MapTxDma
+    (
+    PLM_DEVICE_BLOCK pDevice,
+    struct _LM_PACKET *pPacket,
+    T3_64BIT_HOST_ADDR *paddr,
+    LM_UINT32 *len,
+    int frag)
+{
+    PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+    *len = pPacket->PacketSize;
+    MM_SetT3Addr(paddr, (dma_addr_t) pUmPacket->skbuff);
+}
+
+/*
+ *  Convert an mbuf address, a CPU local virtual address,
+ *  to a physical address as seen from a PCI device.  Store the
+ *  result at paddr.
+ */
+void MM_MapRxDma(
+                PLM_DEVICE_BLOCK pDevice,
+                struct _LM_PACKET *pPacket,
+                T3_64BIT_HOST_ADDR *paddr)
+{
+    PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
+    MM_SetT3Addr(paddr, (dma_addr_t) pUmPacket->skbuff);
+}
+
+void
+MM_SetAddr (LM_PHYSICAL_ADDRESS *paddr, dma_addr_t addr)
+{
+#if (BITS_PER_LONG == 64)
+        paddr->High = ((unsigned long) addr) >> 32;
+        paddr->Low = ((unsigned long) addr) & 0xffffffff;
+#else
+        paddr->High = 0;
+        paddr->Low = (unsigned long) addr;
+#endif
+}
+
+void
+MM_SetT3Addr(T3_64BIT_HOST_ADDR *paddr, dma_addr_t addr)
+{
+        unsigned long baddr = (unsigned long) addr;
+#if (BITS_PER_LONG == 64)
+        set_64bit_addr(paddr, baddr & 0xffffffff, baddr >> 32);
+#else
+        set_64bit_addr(paddr, baddr, 0);
+#endif
+}
+
+/*
+ * This combination of `inline' and `extern' has almost the effect of a
+ * macro.  The way to use it is to put a function definition in a header
+ * file with these keywords, and put another copy of the definition
+ * (lacking `inline' and `extern') in a library file.  The definition in
+ * the header file will cause most calls to the function to be inlined.
+ * If any uses of the function remain, they will refer to the single copy
+ * in the library.
+ */
+void
+atomic_set(atomic_t* entry, int val)
+{
+    entry->counter = val;
+}
+int
+atomic_read(atomic_t* entry)
+{
+    return entry->counter;
+}
+void
+atomic_inc(atomic_t* entry)
+{
+    if(entry)
+       entry->counter++;
+}
+
+void
+atomic_dec(atomic_t* entry)
+{
+    if(entry)
+       entry->counter--;
+}
+
+void
+atomic_sub(int a, atomic_t* entry)
+{
+    if(entry)
+       entry->counter -= a;
+}
+
+void
+atomic_add(int a, atomic_t* entry)
+{
+    if(entry)
+       entry->counter += a;
+}
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+void
+QQ_InitQueue(
+PQQ_CONTAINER pQueue,
+unsigned int QueueSize) {
+    pQueue->Head = 0;
+    pQueue->Tail = 0;
+    pQueue->Size = QueueSize+1;
+    atomic_set(&pQueue->EntryCnt, 0);
+} /* QQ_InitQueue */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+char
+QQ_Full(
+PQQ_CONTAINER pQueue) {
+    unsigned int NewHead;
+
+    NewHead = (pQueue->Head + 1) % pQueue->Size;
+
+    return(NewHead == pQueue->Tail);
+} /* QQ_Full */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+char
+QQ_Empty(
+PQQ_CONTAINER pQueue) {
+    return(pQueue->Head == pQueue->Tail);
+} /* QQ_Empty */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+unsigned int
+QQ_GetSize(
+PQQ_CONTAINER pQueue) {
+    return pQueue->Size;
+} /* QQ_GetSize */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+unsigned int
+QQ_GetEntryCnt(
+PQQ_CONTAINER pQueue) {
+    return atomic_read(&pQueue->EntryCnt);
+} /* QQ_GetEntryCnt */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+char
+QQ_PushHead(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Head;
+
+    Head = (pQueue->Head + 1) % pQueue->Size;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[pQueue->Head] = pEntry;
+    wmb();
+    pQueue->Head = Head;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/*    TRUE entry was added successfully.                                      */
+/*    FALSE queue is full.                                                    */
+/******************************************************************************/
+char
+QQ_PushTail(
+PQQ_CONTAINER pQueue,
+PQQ_ENTRY pEntry) {
+    unsigned int Tail;
+
+    Tail = pQueue->Tail;
+    if(Tail == 0) {
+        Tail = pQueue->Size;
+    } /* if */
+    Tail--;
+
+#if !defined(QQ_NO_OVERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return 0;
+    } /* if */
+#endif /* QQ_NO_OVERFLOW_CHECK */
+
+    pQueue->Array[Tail] = pEntry;
+    wmb();
+    pQueue->Tail = Tail;
+    atomic_inc(&pQueue->EntryCnt);
+
+    return -1;
+} /* QQ_PushTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_PopHead(
+PQQ_CONTAINER pQueue) {
+    unsigned int Head;
+    PQQ_ENTRY Entry;
+
+    Head = pQueue->Head;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Head == pQueue->Tail) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    if(Head == 0) {
+        Head = pQueue->Size;
+    } /* if */
+    Head--;
+
+    Entry = pQueue->Array[Head];
+    membar();
+
+    pQueue->Head = Head;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopHead */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_PopTail(
+PQQ_CONTAINER pQueue) {
+    unsigned int Tail;
+    PQQ_ENTRY Entry;
+
+    Tail = pQueue->Tail;
+
+#if !defined(QQ_NO_UNDERFLOW_CHECK)
+    if(Tail == pQueue->Head) {
+        return (PQQ_ENTRY) 0;
+    } /* if */
+#endif /* QQ_NO_UNDERFLOW_CHECK */
+
+    Entry = pQueue->Array[Tail];
+    membar();
+    pQueue->Tail = (Tail + 1) % pQueue->Size;
+    atomic_dec(&pQueue->EntryCnt);
+
+    return Entry;
+} /* QQ_PopTail */
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_GetHead(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    if(pQueue->Head > Idx)
+    {
+        Idx = pQueue->Head - Idx;
+    }
+    else
+    {
+        Idx = pQueue->Size - (Idx - pQueue->Head);
+    }
+    Idx--;
+
+    return pQueue->Array[Idx];
+}
+
+
+
+/******************************************************************************/
+/* Description:                                                               */
+/*                                                                            */
+/* Return:                                                                    */
+/******************************************************************************/
+PQQ_ENTRY
+QQ_GetTail(
+    PQQ_CONTAINER pQueue,
+    unsigned int Idx)
+{
+    if(Idx >= atomic_read(&pQueue->EntryCnt))
+    {
+        return (PQQ_ENTRY) 0;
+    }
+
+    Idx += pQueue->Tail;
+    if(Idx >= pQueue->Size)
+    {
+        Idx = Idx - pQueue->Size;
+    }
+
+    return pQueue->Array[Idx];
+}
+
+#endif /* CFG_CMD_NET, !CONFIG_NET_MULTI, CONFIG_BCM570x */
diff --git a/include/cmd_disk.h b/include/cmd_disk.h
new file mode 100644 (file)
index 0000000..d3bdb31
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Harddisk support
+ */
+#ifndef        _CMD_DISK_H
+#define        _CMD_DISK_H
+
+#include <common.h>
+#include <command.h>
+
+/*
+ * Type string for PPC bootable partitions
+ */
+#define BOOT_PART_TYPE "U-Boot"
+
+#if 0
+
+typedef        struct disk_partition {
+       ulong   start;          /* # of first block in partition        */
+       ulong   size;           /* number of blocks in partition        */
+       ulong   blksz;          /* block size in bytes                  */
+       uchar   name[32];       /* partition name                       */
+       uchar   type[32];       /* string type description              */
+} disk_partition_t;
+
+int get_partition_info     (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
+#ifdef CONFIG_MAC_PARTITION
+int get_partition_info_mac (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
+#endif
+#ifdef CONFIG_DOS_PARTITION
+int get_partition_info_dos (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
+#endif
+#endif /* 0 */
+
+#endif /* _CMD_DISK_H */
diff --git a/include/configs/AMX860.h b/include/configs/AMX860.h
new file mode 100644 (file)
index 0000000..420cd08
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC860          1
+#define CONFIG_AMX860          1
+
+#undef CONFIG_8xx_CONS_SMC1            /* Console is on SCC2           */
+#undef CONFIG_8xx_CONS_SMC2
+#define        CONFIG_8xx_CONS_SCC2    1
+#undef CONFIG_8xx_CONS_NONE
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+
+#define MPC8XX_FACT            10              /* Multiply by 10       */
+#define MPC8XX_XIN             5000000                 /* 5 MHz in     */
+#define MPC8XX_HZ ((MPC8XX_XIN) * (MPC8XX_FACT))
+
+#define        CONFIG_CLOCKS_IN_MHZ    1       /* clocks passsed to Linux in MHz */
+
+#if 0
+#define CONFIG_BOOTDELAY       -1      /* autoboot disabled            */
+#else
+#define CONFIG_BOOTDELAY       5       /* autoboot after 5 seconds     */
+#endif
+
+#define CONFIG_BOOTCOMMAND                                                     \
+       "bootp;"                                                                \
+       "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) "     \
+       "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off;"    \
+       "bootm"                         /* autoboot command */
+
+#undef CONFIG_BOOTARGS
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#undef CONFIG_KGDB_ON_SMC              /* define if kgdb on SMC */
+#define        CONFIG_KGDB_ON_SCC              /* define if kgdb on SCC */
+#undef CONFIG_KGDB_NONE                /* define if kgdb on something else */
+#define CONFIG_KGDB_INDEX      1       /* which serial channel for kgdb */
+#define CONFIG_KGDB_BAUDRATE   9600    /* speed to run kgdb serial port at */
+#endif
+
+
+#undef CONFIG_WATCHDOG                 /* watchdog disabled            */
+
+#define        CONFIG_SCC1_ENET        1       /* use SCC1 ethernet */
+
+#define        CONFIG_RTC_MPC8xx               /* use internal RTC of MPC8xx   */
+
+#define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
+                               CFG_CMD_DHCP    | \
+                               CFG_CMD_DATE    )
+
+#define CONFIG_BOOTP_MASK      (CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_BOOTFILESIZE)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP                   /* undef to save memory         */
+#define        CFG_PROMPT              "=> "   /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define        CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define        CFG_MAXARGS     16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x0100000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0200000       /* 1 ... 4 MB in DRAM   */
+
+#define CFG_LOAD_ADDR          0x00100000
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+/*-----------------------------------------------------------------------
+ * Internal Memory Mapped Register
+ */
+#define CFG_IMMR                       0xFF000000
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR      CFG_IMMR
+#define        CFG_INIT_RAM_END        0x2F00  /* End of used area in DPRAM    */
+#define        CFG_GBL_DATA_SIZE       64  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define        CFG_INIT_SP_OFFSET      CFG_GBL_DATA_OFFSET
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define        CFG_SDRAM_BASE          0x00000000
+#define CFG_FLASH_BASE         0x40000000
+#if defined(DEBUG)
+#define        CFG_MONITOR_LEN         (256 << 10)     /* Reserve 256 kB for Monitor   */
+#else
+#define        CFG_MONITOR_LEN         (192 << 10)     /* Reserve 192 kB for Monitor   */
+#endif
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define        CFG_MALLOC_LEN          (128 << 10)     /* Reserve 128 kB for malloc()  */
+
+/*
+ * U-Boot for AMX board supports two types of memory extension
+ * modules: one that provides 4 MB flash memory, and another one with
+ * 16 MB EDO DRAM.
+ *
+ * The flash module swaps the CS0 and CS1 signals: if the module is
+ * installed, CS0 is connected to Flash on the module and CS1 is
+ * connected to the on-board Flash. This means that you must intall
+ * U-Boot when the Flash module is plugged in, if you plan to use
+ * it.
+ *
+ * To enable support for the DRAM extension card, CONFIG_AMX_RAM_EXT
+ * must be defined. The DRAM module uses CS1.
+ *
+ * Only one of these modules may be installed at a time. If U-Boot
+ * is compiled with the CONFIG_AMX_RAM_EXT option set, it will not
+ * work if the Flash extension module is installed instead of the
+ * DRAM module.
+ */
+#define CONFIG_AMX_RAM_EXT     /* 16Mb Ext. DRAM module support */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ *
+ * Use 4 MB for without and 8 MB with 16 MB DRAM extension module
+ * (CONFIG_AMX_RAM_EXT)
+ */
+#ifdef CONFIG_AMX_RAM_EXT
+# define       CFG_BOOTMAPSZ   (8 << 20)       /* Initial Memory map for Linux */
+#else
+# define       CFG_BOOTMAPSZ   (4 << 20)       /* Initial Memory map for Linux */
+#endif
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     35      /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+#define        CFG_ENV_IS_IN_FLASH     1
+#define        CFG_ENV_OFFSET          0x8000  /*   Offset   of Environment Sector     */
+#define        CFG_ENV_SIZE            0x4000  /* Total Size of Environment Sector     */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     16      /* For all MPC8xx CPUs                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    4       /* log base 2 of the above value        */
+#endif
+
+/*-----------------------------------------------------------------------
+ * SYPCR - System Protection Control                                   11-9
+ * SYPCR can only be written once after reset!
+ *-----------------------------------------------------------------------
+ * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze
+ */
+#if defined(CONFIG_WATCHDOG)
+#define CFG_SYPCR      (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \
+                        SYPCR_SWE  | SYPCR_SWRI| SYPCR_SWP)
+#else
+#define CFG_SYPCR      (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | SYPCR_SWP)
+#endif
+
+/*-----------------------------------------------------------------------
+ * SIUMCR - SIU Module Configuration                                   11-6
+ *-----------------------------------------------------------------------
+ * PCMCIA config., multi-function pin tri-state
+ */
+#define CFG_SIUMCR     (SIUMCR_DBGC00 | SIUMCR_DBPC00 | SIUMCR_MLRC01)
+
+/*-----------------------------------------------------------------------
+ * TBSCR - Time Base Status and Control                                        11-26
+ *-----------------------------------------------------------------------
+ * Clear Reference Interrupt Status, Timebase freezing enabled
+ */
+#define CFG_TBSCR      (TBSCR_REFA | TBSCR_REFB | TBSCR_TBE)
+
+/*-----------------------------------------------------------------------
+ * PISCR - Periodic Interrupt Status and Control               11-31
+ *-----------------------------------------------------------------------
+ * Clear Periodic Interrupt Status, Interrupt Timer freezing enabled
+ */
+#define CFG_PISCR      (PISCR_PS | PISCR_PITF)
+
+/*-----------------------------------------------------------------------
+ * PLPRCR - PLL, Low-Power, and Reset Control Register 15-30
+ *-----------------------------------------------------------------------
+ * set the PLL, the low-power modes and the reset control (15-29)
+ */
+#define CFG_PLPRCR     (((MPC8XX_FACT-1) << PLPRCR_MF_SHIFT) | \
+                               PLPRCR_SPLSS | PLPRCR_TEXPS | PLPRCR_TMIST)
+
+/*-----------------------------------------------------------------------
+ * SCCR - System Clock and reset Control Register              15-27
+ *-----------------------------------------------------------------------
+ * Set clock output, timebase and RTC source and divider,
+ * power management and some other internal clocks
+ */
+#define SCCR_MASK      SCCR_EBDF11
+#define CFG_SCCR       (SCCR_TBS|SCCR_COM00|SCCR_DFSYNC00|SCCR_DFBRG00|SCCR_DFNL000|SCCR_DFNH000|SCCR_DFLCD000|SCCR_DFALCD00)
+
+#define CFG_DER                0
+
+/*
+ * Init Memory Controller:
+ *
+ * BR0/1 and OR0/1 (FLASH)
+ */
+
+#define FLASH_BASE0_PRELIM     0x40000000      /* FLASH bank #0        */
+#ifndef CONFIG_AMX_RAM_EXT
+#define FLASH_BASE1_PRELIM     0x60000000      /* FLASH bank #1        */
+#endif
+
+#define CFG_REMAP_OR_AM                0x80000000      /* OR addr mask */
+#define CFG_PRELIM_OR_AM       0xFFC00000      /* OR addr mask */
+
+/* FLASH timing: ACS = 10, TRLX = 1, CSNT = 1, SCY = 3, EHTR = 0       */
+/*                              0x00000800     0x00000400 0x00000100 0x00000030     0x00000004 */
+#define CFG_OR_TIMING_FLASH    (OR_CSNT_SAM  | OR_ACS_DIV4 | OR_BI | OR_SCY_5_CLK | OR_TRLX)
+
+#define CFG_OR0_REMAP  (CFG_REMAP_OR_AM  | CFG_OR_TIMING_FLASH)
+
+#define CFG_OR0_PRELIM 0xFFC00954      /* Real values for the board */
+#define CFG_BR0_PRELIM 0x40000001      /* Real values for the board */
+
+#ifndef CONFIG_AMX_RAM_EXT
+#define CFG_OR1_REMAP  CFG_OR0_REMAP
+#define CFG_OR1_PRELIM 0xFFC00954      /* Real values for the board */
+#define CFG_BR1_PRELIM 0x60000001      /* Real values for the board */
+#endif
+
+/* DSP ("Glue") Xilinx */
+#define CFG_OR6_PRELIM 0xFFFF8000      /* 32kB, 15 waits, cs after addr, no bursts */
+#define CFG_BR6_PRELIM 0x60000401      /* use GPCM for CS generation, 8 bit port */
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define        BOOTFLAG_COLD   0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/SXNI855T.h b/include/configs/SXNI855T.h
new file mode 100644 (file)
index 0000000..8725f27
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * U-Boot configuration for SIXNET SXNI855T CPU board.
+ * This board is based (loosely) on the Motorola FADS board, so this
+ * file is based (loosely) on config_FADS860T.h, see it for additional
+ * credits.
+ *
+ * Copyright (c) 2000-2002 Dave Ellis, SIXNET, dge@sixnetio.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/*
+ * Memory map:
+ *
+ *   ff100000 -> ff13ffff : FPGA        CS1
+ *   ff030000 -> ff03ffff : EXPANSION   CS7
+ *   ff020000 -> ff02ffff : DATA FLASH  CS4
+ *   ff018000 -> ff01ffff : UART B      CS6/UPMB
+ *   ff010000 -> ff017fff : UART A      CS5/UPMB
+ *   ff000000 -> ff00ffff : IMAP                   internal to the MPC855T
+ *   f8000000 -> fbffffff : FLASH       CS0        up to 64MB
+ *   f4000000 -> f7ffffff : NVSRAM      CS2        up to 64MB
+ *   00000000 -> 0fffffff : SDRAM       CS3/UPMA   up to 256MB
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#include <mpc8xx_irq.h>
+
+#define CONFIG_SXNI855T                1       /* SIXNET IPm 855T CPU module */
+
+/* The 855T is just a stripped 860T and needs code for 860, so for now
+ * at least define 860, 860T and 855T
+ */
+#define CONFIG_MPC860          1
+#define CONFIG_MPC860T         1
+#define CONFIG_MPC855T         1
+
+#define        CONFIG_8xx_CONS_SMC1    1       /* Console is on SMC1           */
+#undef CONFIG_8xx_CONS_SMC2
+#undef CONFIG_8xx_CONS_SCC1
+#undef CONFIG_8xx_CONS_NONE
+#define CONFIG_BAUDRATE                9600
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+
+#define MPC8XX_FACT            10      /* 50 MHz is 5 MHz in times 10  */
+
+#define        CONFIG_CLOCKS_IN_MHZ    1       /* clocks passsed to Linux in MHz */
+
+#if 0
+#define CONFIG_BOOTDELAY       -1      /* autoboot disabled            */
+#else
+#define CONFIG_BOOTDELAY       5       /* autoboot after 5 seconds     */
+#endif
+
+#define CONFIG_BOOTCOMMAND     "bootm f8040000 f8100000" /* autoboot command */
+#define CONFIG_BOOTARGS                "root=/dev/ram ip=off"
+
+#define CONFIG_MISC_INIT_R             /* have misc_init_r() function */
+#define CONFIG_BOARD_POSTCLK_INIT      /* have board_postclk_init() function */
+
+#undef CONFIG_WATCHDOG                 /* watchdog disabled            */
+
+#define        CONFIG_RTC_DS1306               /* Dallas 1306 real time clock  */
+
+#define        CONFIG_SOFT_I2C                 /* I2C bit-banged               */
+/*
+ * Software (bit-bang) I2C driver configuration
+ */
+#define PB_SCL         0x00000020      /* PB 26 */
+#define PB_SDA         0x00000010      /* PB 27 */
+
+#define I2C_INIT       (immr->im_cpm.cp_pbdir |=  PB_SCL)
+#define I2C_ACTIVE     (immr->im_cpm.cp_pbdir |=  PB_SDA)
+#define I2C_TRISTATE   (immr->im_cpm.cp_pbdir &= ~PB_SDA)
+#define I2C_READ       ((immr->im_cpm.cp_pbdat & PB_SDA) != 0)
+#define I2C_SDA(bit)   if(bit) immr->im_cpm.cp_pbdat |=  PB_SDA; \
+                       else    immr->im_cpm.cp_pbdat &= ~PB_SDA
+#define I2C_SCL(bit)   if(bit) immr->im_cpm.cp_pbdat |=  PB_SCL; \
+                       else    immr->im_cpm.cp_pbdat &= ~PB_SCL
+#define I2C_DELAY      udelay(5)       /* 1/4 I2C clock duration */
+
+# define CFG_I2C_SPEED         50000
+# define CFG_I2C_SLAVE         0xFE
+# define CFG_I2C_EEPROM_ADDR   0x50    /* Atmel 24C64                  */
+# define CFG_I2C_EEPROM_ADDR_LEN 2     /* two byte address             */
+
+#define        CONFIG_FEC_ENET         1       /* use FEC ethernet  */
+
+#define CFG_DISCOVER_PHY
+
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | CFG_CMD_EEPROM | CFG_CMD_DATE)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define        CFG_LONGHELP                    /* undef to save a little memory */
+#define        CFG_PROMPT              "=>"    /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define        CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define        CFG_MAXARGS     16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x0100000       /* memtest works on     */
+#define CFG_MEMTEST_END                0x0400000       /* 1 ... 4 MB in DRAM   */
+
+#define CFG_LOAD_ADDR          0x00100000
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+/*-----------------------------------------------------------------------
+ * Internal Memory Mapped Register
+ */
+#define CFG_IMMR               0xFF000000
+#define CFG_IMMR_SIZE          ((uint)(64 * 1024))
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR      CFG_IMMR
+#define        CFG_INIT_RAM_END        0x2F00  /* End of used area in DPRAM    */
+#define        CFG_GBL_DATA_SIZE       64  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define        CFG_INIT_SP_OFFSET      CFG_GBL_DATA_OFFSET
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define        CFG_SDRAM_BASE          0x00000000
+#define        CFG_SRAM_BASE           0xF4000000
+#define        CFG_SRAM_SIZE           0x04000000      /* autosize up to 64Mbyte */
+
+#define CFG_FLASH_BASE         0xF8000000
+#define CFG_FLASH_SIZE         ((uint)(8 * 1024 * 1024))       /* max 8Mbyte */
+
+#define CFG_DFLASH_BASE                0xff020000 /* DiskOnChip or NAND FLASH */
+#define CFG_DFLASH_SIZE                0x00010000
+
+#define CFG_FPGA_BASE          0xFF100000      /* Xilinx FPGA */
+#define CFG_FPGA_PROG          0xFF130000      /* Programming address */
+#define CFG_FPGA_SIZE          0x00040000      /* 256KiB usable */
+
+#define        CFG_MONITOR_LEN         (256 << 10)     /* Reserve 256 kB for Monitor   */
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define        CFG_MALLOC_LEN          (128 << 10)     /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define        CFG_BOOTMAPSZ           (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    1       /* max number of memory banks           */
+/* Intel 28F640 has 135, 127 64K sectors in 8MB, + 8 more for 8K boot blocks.
+ * AMD 29LV641 has 128 64K sectors in 8MB
+ */
+#define CFG_MAX_FLASH_SECT     135     /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     16      /* For all MPC8xx CPUs                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    4       /* log base 2 of the above value        */
+#endif
+
+/*-----------------------------------------------------------------------
+ * SYPCR - System Protection Control                                   11-9
+ * SYPCR can only be written once after reset!
+ *-----------------------------------------------------------------------
+ * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze
+ */
+#if defined(CONFIG_WATCHDOG)
+#define CFG_SYPCR      (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \
+                        SYPCR_SWE  | SYPCR_SWRI| SYPCR_SWP)
+#else
+#define CFG_SYPCR      (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | SYPCR_SWP)
+#endif
+
+/*-----------------------------------------------------------------------
+ * SIUMCR - SIU Module Configuration                                   11-6
+ *-----------------------------------------------------------------------
+ * PCMCIA config., multi-function pin tri-state
+ */
+#define CFG_SIUMCR     (SIUMCR_DBGC00 | SIUMCR_DBPC00 | SIUMCR_MLRC01)
+
+/*-----------------------------------------------------------------------
+ * TBSCR - Time Base Status and Control                                        11-26
+ *-----------------------------------------------------------------------
+ * Clear Reference Interrupt Status, Timebase freezing enabled
+ */
+#define CFG_TBSCR      (TBSCR_REFA | TBSCR_REFB | TBSCR_TBE)
+
+/*-----------------------------------------------------------------------
+ * PISCR - Periodic Interrupt Status and Control               11-31
+ *-----------------------------------------------------------------------
+ * Clear Periodic Interrupt Status, Interrupt Timer freezing enabled
+ */
+#define CFG_PISCR      (PISCR_PS | PISCR_PITF)
+
+/*-----------------------------------------------------------------------
+ * PLPRCR - PLL, Low-Power, and Reset Control Register 15-30
+ *-----------------------------------------------------------------------
+ * set the PLL, the low-power modes and the reset control (15-29)
+ */
+#define CFG_PLPRCR     (((MPC8XX_FACT-1) << PLPRCR_MF_SHIFT) | \
+                               PLPRCR_SPLSS | PLPRCR_TEXPS | PLPRCR_TMIST)
+
+/*-----------------------------------------------------------------------
+ * SCCR - System Clock and reset Control Register              15-27
+ *-----------------------------------------------------------------------
+ * Set clock output, timebase and RTC source and divider,
+ * power management and some other internal clocks
+ */
+#define SCCR_MASK      SCCR_EBDF11
+#define CFG_SCCR       (SCCR_TBS|SCCR_COM00|SCCR_DFSYNC00|SCCR_DFBRG00|SCCR_DFNL000|SCCR_DFNH000|SCCR_DFLCD000|SCCR_DFALCD00)
+
+ /*-----------------------------------------------------------------------
+ *
+ *-----------------------------------------------------------------------
+ *
+ */
+#define CFG_DER                0
+
+/* Because of the way the 860 starts up and assigns CS0 the
+ * entire address space, we have to set the memory controller
+ * differently.  Normally, you write the option register
+ * first, and then enable the chip select by writing the
+ * base register.  For CS0, you must write the base register
+ * first, followed by the option register.
+ */
+
+/*
+ * Init Memory Controller:
+ *
+ **********************************************************
+ * BR0 and OR0 (FLASH)
+ */
+
+#define CFG_PRELIM_OR0_AM      0xFC000000      /* OR addr mask */
+
+/* FLASH timing: ACS = 10, TRLX = 1, CSNT = 1, SCY = 3, EHTR = 0       */
+#define CFG_OR_TIMING_FLASH    (OR_CSNT_SAM  | OR_ACS_DIV4 | OR_BI | OR_SCY_3_CLK | OR_TRLX)
+
+#define CFG_OR0_PRELIM (CFG_PRELIM_OR0_AM | CFG_OR_TIMING_FLASH)
+
+#define CONFIG_FLASH_16BIT
+#define CFG_BR0_PRELIM ((CFG_FLASH_BASE & BR_BA_MSK) | BR_PS_16 | BR_V )
+#define CFG_FLASH_PROTECTION   /* need to lock/unlock sectors in hardware */
+
+/**********************************************************
+ * BR1 and OR1 (FPGA)
+ * These preliminary values are also the final values.
+ */
+#define CFG_OR_TIMING_FPGA \
+       (OR_CSNT_SAM | OR_ACS_DIV2 | OR_BI | OR_SCY_5_CLK | OR_EHTR)
+#define CFG_BR1_PRELIM ((CFG_FPGA_BASE & BR_BA_MSK) | BR_PS_8 | BR_V )
+#define CFG_OR1_PRELIM (((-CFG_FPGA_SIZE) & OR_AM_MSK) | CFG_OR_TIMING_FPGA)
+
+/**********************************************************
+ * BR4 and OR4 (data flash)
+ * These preliminary values are also the final values.
+ */
+#define CFG_OR_TIMING_DFLASH \
+       (OR_CSNT_SAM | OR_ACS_DIV4 | OR_BI | OR_SCY_5_CLK | OR_EHTR)
+#define CFG_BR4_PRELIM ((CFG_DFLASH_BASE & BR_BA_MSK) | BR_PS_8 | BR_V )
+#define CFG_OR4_PRELIM (((-CFG_DFLASH_SIZE) & OR_AM_MSK) | CFG_OR_TIMING_DFLASH)
+
+/**********************************************************
+ * BR5/6 and OR5/6 (Dual UART)
+ */
+#define CFG_DUART_SIZE 0x8000  /* 32K window, only uses 8 bytes */
+#define CFG_DUARTA_BASE        0xff010000
+#define CFG_DUARTB_BASE        0xff018000
+
+#define DUART_MBMR     0
+#define DUART_OR_VALUE (ORMASK(CFG_DUART_SIZE) | OR_G5LS| OR_BI)
+#define DUART_BR_VALUE (BR_MS_UPMB | BR_PS_8 | BR_V)
+#define DUART_BR5_VALUE ((CFG_DUARTA_BASE & BR_BA_MSK ) | DUART_BR_VALUE)
+#define DUART_BR6_VALUE ((CFG_DUARTB_BASE & BR_BA_MSK ) | DUART_BR_VALUE)
+
+/**********************************************************
+ *
+ * Boot Flags
+ */
+#define        BOOTFLAG_COLD   0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+#define CONFIG_RESET_ON_PANIC          /* reset if system panic() */
+
+/* to put environment in EEROM */
+#define        CFG_ENV_IS_IN_EEPROM    1
+#define CFG_ENV_OFFSET         0       /* Start right at beginning of NVRAM */
+#define CFG_ENV_SIZE           1024    /* Use only a part of it*/
+
+#if 1
+#define CONFIG_BOOT_RETRY_TIME 60      /* boot if no command in 60 seconds */
+#endif
+
+#if 1
+#define CONFIG_AUTOBOOT_KEYED          /* use key strings to stop autoboot */
+#define CONFIG_AUTOBOOT_PROMPT         "autoboot in %d seconds\n"
+#define CONFIG_AUTOBOOT_DELAY_STR      "delayabit"
+#define CONFIG_AUTOBOOT_STOP_STR       " " /* easy to stop for now */
+#endif
+
+#endif /* __CONFIG_H */