Das U-Boot: Universal Boot Loader
authorwdenk <wdenk>
Sun, 3 Nov 2002 00:01:44 +0000 (00:01 +0000)
committerwdenk <wdenk>
Sun, 3 Nov 2002 00:01:44 +0000 (00:01 +0000)
board/cray/L1/L1.c [new file with mode: 0644]
board/cray/L1/L1.h [new file with mode: 0644]
board/evb64260/local.h [new file with mode: 0644]
board/genietv/genietv.h [new file with mode: 0644]
board/pn62/pn62.h [new file with mode: 0644]
common/cmd_bedbug.c [new file with mode: 0644]
common/cmd_bootm.c [new file with mode: 0644]
common/console.c [new file with mode: 0644]
cpu/74xx_7xx/start.S [new file with mode: 0644]
cpu/mpc8260/start.S [new file with mode: 0644]

diff --git a/board/cray/L1/L1.c b/board/cray/L1/L1.c
new file mode 100644 (file)
index 0000000..f5dfba4
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <405gp_i2c.h>
+#include <command.h>
+#include <cmd_nvedit.h>
+#include <cmd_bootm.h>
+#include <rtc.h>
+#include <net.h>
+#include <malloc.h>
+
+#define L1_MEMSIZE (32*1024*1024)
+
+/* the std. DHCP stufff */
+#define DHCP_ROUTER       3
+#define DHCP_NETMASK      1
+#define DHCP_BOOTFILE     67
+#define DHCP_ROOTPATH     17
+#define DHCP_HOSTNAME     12
+
+/* some extras used by CRAY
+ *
+ * on the server this looks like:
+ *
+ * option L1-initrd-image code 224 = string;
+ * option L1-initrd-image "/opt/craysv2/craymcu/l1/flash/initrd.image"
+ */
+#define DHCP_L1_INITRD  224
+
+/* new, [better?] way via official vendor-extensions, defining an option
+ * space.
+ * on the server this looks like:
+ *
+ * option space U-Boot;
+ * option U-Boot.initrd    code 3 = string;
+ * option U-Boot.bootcmd   code 4 = string;
+ * option U-Boot.bootflags code 5 = string;
+ * option U-Boot.rootdev   code 6 = string;
+ */
+#define DHCP_VENDOR_SPECX   43
+#define DHCP_VX_INITRD       3
+#define DHCP_VX_BOOTCMD      4
+#define DHCP_VX_BOOTFLAGS    5
+#define DHCP_VX_ROOTDEV      6
+
+/* Things DHCP server can tellme about.  If there's no flash address, then
+ * they dont participate in 'update' to flash, and we force their values
+ * back to '0' every boot to be sure to get them fresh from DHCP.  Yes, I
+ * know this is a pain...
+ *
+ * If I get no bootfile, boot from flash.  If rootpath, use that.  If no
+ * rootpath use initrd in flash.
+ */
+typedef struct dhcp_item_s {
+       u8 dhcp_option;
+       u8 dhcp_vendor_option;
+       char *dhcpvalue;
+       char *envname;
+} dhcp_item_t;
+static dhcp_item_t Things[] = {
+       {DHCP_ROUTER, 0, NULL, "gateway"},
+       {DHCP_NETMASK, 0, NULL, "netmask"},
+       {DHCP_BOOTFILE, 0, NULL, "bootfile"},
+       {DHCP_ROOTPATH, 0, NULL, "rootpath"},
+       {DHCP_HOSTNAME, 0, NULL, "hostname"},
+       {DHCP_L1_INITRD, 0, NULL, "initrd"},
+/* and the other way.. */
+       {DHCP_VENDOR_SPECX, DHCP_VX_INITRD, NULL, "initrd"},
+       {DHCP_VENDOR_SPECX, DHCP_VX_BOOTCMD, NULL, "bootcmd"},
+       {DHCP_VENDOR_SPECX, DHCP_VX_BOOTFLAGS, NULL, NULL},
+       {DHCP_VENDOR_SPECX, DHCP_VX_ROOTDEV, NULL, NULL},
+};
+
+#define N_THINGS ((sizeof(Things))/(sizeof(dhcp_item_t)))
+
+static void init_ecc_sdram (void);
+
+/* ------------------------------------------------------------------------- */
+int board_pre_init (void)
+{
+       init_ecc_sdram ();
+       mtdcr (uicsr, 0xFFFFFFFF);      /* clear all ints */
+       mtdcr (uicer, 0x00000000);      /* disable all ints */
+       mtdcr (uiccr, 0x00000020);      /* set all but FPGA SMI to be non-critical */
+       mtdcr (uicpr, 0xFFFFFFE0);      /* set int polarities */
+       mtdcr (uictr, 0x10000000);      /* set int trigger levels */
+       mtdcr (uicvcr, 0x00000001);     /* set vect base=0,INT0 highest priority */
+       mtdcr (uicsr, 0xFFFFFFFF);      /* clear all ints */
+       return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+int checkboard (void)
+{
+       return (0);
+}
+
+/* ------------------------------------------------------------------------- */
+int misc_init_r (void)
+{
+       unsigned char *s, *e;
+       image_header_t *hdr;
+       time_t timestamp;
+       struct rtc_time tm;
+
+       hdr = (image_header_t *) (CFG_MONITOR_BASE - sizeof (image_header_t));
+       timestamp = (time_t) hdr->ih_time;
+       to_tm (timestamp, &tm);
+       printf ("Welcome to U-Boot on Cray L1. Compiled %4d-%02d-%02d  %2d:%02d:%02d (UTC)\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+#define FACTORY_SETTINGS 0xFFFC0000
+       if ((s = getenv ("ethaddr")) == NULL) {
+               e = (unsigned char *) (FACTORY_SETTINGS);
+               if (*(e + 0) != '0'
+                       || *(e + 1) != '0'
+                       || *(e + 2) != ':'
+                       || *(e + 3) != '4' || *(e + 4) != '0' || *(e + 17) != '\0') {
+                       printf ("No valid MAC address in flash location 0x3C0000!\n");
+               } else {
+                       printf ("Factory MAC: %s\n", e);
+                       setenv ("ethaddr", e);
+               }
+       }
+       return (0);
+}
+
+/* ------------------------------------------------------------------------- */
+long int initdram (int board_type)
+{
+       return (L1_MEMSIZE);
+}
+
+/* ------------------------------------------------------------------------- */
+/* stubs so we can print dates w/o any nvram RTC.*/
+void rtc_get (struct rtc_time *tmp)
+{
+       return;
+}
+void rtc_set (struct rtc_time *tmp)
+{
+       return;
+}
+void rtc_reset (void)
+{
+       return;
+}
+
+/* ------------------------------------------------------------------------- */
+/*  Do sdram bank init in C so I can read it..
+ */
+static void init_ecc_sdram (void)
+{
+       unsigned long tmp, *p;
+
+       /* write SDRAM bank 0 register */
+       mtdcr (memcfga, mem_mb0cf);
+       mtdcr (memcfgd, 0x00062001);
+
+/* Set the SDRAM Timing reg, SDTR1 and the refresh timer reg, RTR.     */
+/* To set the appropriate timings, we need to know the SDRAM speed.    */
+/* We can use the PLB speed since the SDRAM speed is the same as       */
+/* the PLB speed. The PLB speed is the FBK divider times the           */
+/* 405GP reference clock, which on the L1 is 25Mhz.                    */
+/* Thus, if FBK div is 2, SDRAM is 50Mhz; if FBK div is 3, SDRAM is    */
+/* 150Mhz; if FBK is 3, SDRAM is 150Mhz.                               */
+
+       /* divisor = ((mfdcr(strap)>> 28) & 0x3); */
+
+/* write SDRAM timing for 100Mhz. */
+       mtdcr (memcfga, mem_sdtr1);
+       mtdcr (memcfgd, 0x0086400D);
+
+/* write SDRAM refresh interval register */
+       mtdcr (memcfga, mem_rtr);
+       mtdcr (memcfgd, 0x05F00000);
+       udelay (200);
+
+/* sdram controller.*/
+       mtdcr (memcfga, mem_mcopt1);
+       mtdcr (memcfgd, 0x90800000);
+       udelay (200);
+
+/* disable ECC on all banks */
+       mtdcr (memcfga, mem_ecccf);
+       tmp = mfdcr (memcfgd);
+       tmp &= 0xff0fffff;
+       mtdcr (memcfga, mem_ecccf);
+       mtdcr (memcfgd, tmp);
+
+/* set up SDRAM Controller with ECC enabled */
+       mtdcr (memcfga, mem_mcopt1);
+       tmp = (mfdcr (memcfgd) & ~0xFFE00000) | 0x90800000;
+       mtdcr (memcfga, mem_mcopt1);
+       mtdcr (memcfgd, tmp);
+       udelay (600);
+
+/* fill all the memory */
+       for (p = (unsigned long) 0; ((unsigned long) p < L1_MEMSIZE);
+                *p++ = 0L);
+       udelay (400);
+       mtdcr (memcfga, mem_ecccf);
+       tmp = mfdcr (memcfgd);
+
+/* enable ECC on bank 0 */
+       tmp |= 0x00800000;
+       mtdcr (memcfgd, tmp);
+       udelay (400);
+
+       return;
+}
+
+/* ------------------------------------------------------------------------- */
+static u8 *dhcp_env_update (u8 thing, u8 * pop)
+{
+       u8 i, oplen;
+
+       oplen = *(pop + 1);
+
+       if ((Things[thing].dhcpvalue = malloc (oplen)) == NULL) {
+               printf ("Whoops! failed to malloc space for DHCP thing %s\n",
+                               Things[thing].envname);
+               return NULL;
+       }
+       for (i = 0; (i < oplen); i++)
+               if ((*(Things[thing].dhcpvalue + i) = *(pop + 2 + i)) == ' ')
+                       break;
+       *(Things[thing].dhcpvalue + i) = '\0';
+
+/* set env. */
+       if (Things[thing].envname)
+               setenv (Things[thing].envname, Things[thing].dhcpvalue);
+       return (Things[thing].dhcpvalue);
+}
+
+/* ------------------------------------------------------------------------- */
+u8 *dhcp_vendorex_prep (u8 * e)
+{
+       u8 thing;
+
+/* ask for the things I want. */
+       *e++ = 55;                                      /* Parameter Request List */
+       *e++ = N_THINGS;
+       for (thing = 0; thing < N_THINGS; thing++)
+               *e++ = Things[thing].dhcp_option;
+       *e++ = 255;
+
+       return e;
+}
+
+/* ------------------------------------------------------------------------- */
+/* .. return NULL means it wasnt mine, non-null means I got it..*/
+u8 *dhcp_vendorex_proc (u8 * pop)
+{
+       u8 oplen, *sub_op, sub_oplen, *retval;
+       u8 thing = 0;
+
+       retval = NULL;
+       oplen = *(pop + 1);
+/* if pop is vender spec indicator, there are sub-options. */
+       if (*pop == DHCP_VENDOR_SPECX) {
+               for (sub_op = pop + 2;
+                    oplen && (sub_oplen = *(sub_op + 1));
+                    oplen -= sub_oplen, sub_op += (sub_oplen + 2)) {
+                       for (thing = 0; thing < N_THINGS; thing++) {
+                           if (*sub_op == Things[thing].dhcp_vendor_option) {
+                               if (!(retval = dhcp_env_update (thing, sub_op))) {
+                                       return NULL;
+                               }
+                           }
+                       }
+               }
+       } else {
+               for (thing = 0; thing < N_THINGS; thing++) {
+                       if (*pop == Things[thing].dhcp_option)
+                               if (!(retval = dhcp_env_update (thing, pop)))
+                                       return NULL;
+               }
+       }
+       return (thing >= N_THINGS ? NULL : pop);
+}
diff --git a/board/cray/L1/L1.h b/board/cray/L1/L1.h
new file mode 100644 (file)
index 0000000..1b41824
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * (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
+ */
+
+/****************************************************************************
+ * FLASH Memory Map as used by CRAY L1, 4MB AMD29F032B flash chip
+ *
+ *                          Start Address    Length
+ * +++++++++++++++++++++++++ 0xFFC0_0000     Start of Flash -----------------
+ * | Failsafe Linux Image  |   (1M)
+ * +=======================+ 0xFFD0_0000
+ * | (Reserved FlashFiles) |   (1M)
+ * +=======================+ 0xFFE0_0000
+ * | Failsafe RootFS       |   (1M)
+ * +=======================+ 0xFFF0_0000
+ * |                       |
+ * | U N U S E D           |
+ * |                       |
+ * +-----------------------+ 0xFFFD_0000       U-Boot image header (64 bytes)
+ * | environment settings  |   (64k)
+ * +-----------------------+ 0xFFFE_0000       U-Boot image header (64 bytes)
+ * | U-Boot                | 0xFFFE_0040    _start of U-Boot
+ * |                       | 0xFFFE_FFFC    reset vector - branch to _start
+ * +++++++++++++++++++++++++ 0xFFFF_FFFF     End of Flash -----------------
+ *****************************************************************************/
diff --git a/board/evb64260/local.h b/board/evb64260/local.h
new file mode 100644 (file)
index 0000000..6d1fb4c
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * include/local.h - local configuration options, board specific
+ */
+
+#ifndef __LOCAL_H
+#define __LOCAL_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+/* This tells U-Boot that the config options are compiled in */
+/* #undef ENV_IS_EMBEDDED */
+/* Don't touch this! U-Boot figures this out  based on other
+ * magic. */
+
+/* Uncomment and define any of the below options */
+
+/* #define CONFIG_750CX */ /* The 750CX doesn't support as many things in L2CR */
+                       /* Note: If you defined CONFIG_EVB64260_750CX this */
+                       /* gets defined automatically. */
+
+/* These want string arguments */
+/* #define CONFIG_BOOTARGS */
+/* #define CONFIG_BOOTCOMMAND */
+/* #define CONFIG_RAMBOOTCOMMAND */
+/* #define CONFIG_NFSBOOTCOMMAND */
+/* #define CFG_AUTOLOAD */
+/* #define CONFIG_PREBOOT */
+
+/* These don't */
+
+/* #define CONFIG_BOOTDELAY  */
+/* #define CONFIG_BAUDRATE */
+/* #define CONFIG_LOADS_ECHO */
+/* #define CONFIG_ETHADDR */
+/* #define CONFIG_ETH2ADDR */
+/* #define CONFIG_ETH3ADDR */
+/* #define CONFIG_IPADDR */
+/* #define CONFIG_SERVERIP */
+/* #define CONFIG_ROOTPATH */
+/* #define CONFIG_GATEWAYIP */
+/* #define CONFIG_NETMASK */
+/* #define CONFIG_HOSTNAME */
+/* #define CONFIG_BOOTFILE */
+/* #define CONFIG_LOADADDR */
+
+/* these hardware addresses are pretty bogus, please change them to
+   suit your needs */
+
+/* first ethernet */
+#define CONFIG_ETHADDR          00:11:22:33:44:55
+
+/* next two ethernet hwaddrs */
+#define CONFIG_ETH1ADDR                00:11:22:33:44:66
+#define CONFIG_ETH2ADDR                00:11:22:33:44:77
+
+#define CONFIG_ENV_OVERWRITE
+#endif /* __CONFIG_H */
diff --git a/board/genietv/genietv.h b/board/genietv/genietv.h
new file mode 100644 (file)
index 0000000..7c95b56
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * The GENIETV is using the following physical memorymap (copied from
+ * the FADS configuration):
+ *
+ * ff020000 -> ff02ffff : pcmcia
+ * ff010000 -> ff01ffff : BCSR       connected to CS1, setup by 8xxROM
+ * ff000000 -> ff00ffff : IMAP       internal in the cpu
+ * 02800000 -> 0287ffff : flash      connected to CS0
+ * 00000000 -> nnnnnnnn : sdram      setup by U-Boot
+ *
+ * CS pins are connected as follows:
+ *
+ * CS0 -512Kb boot flash
+ * CS1 - SDRAM #1
+ * CS2 - SDRAM #2
+ * CS3 - Flash #1
+ * CS4 - Flash #2
+ * CS5 - LON (if present)
+ * CS6 - PCMCIA #1
+ * CS7 - PCMCIA #2
+ *
+ * Ports are configured as follows:
+ *
+ * PA7 - SDRAM banks enable
+ */
diff --git a/board/pn62/pn62.h b/board/pn62/pn62.h
new file mode 100644 (file)
index 0000000..7bda0ad
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2002 Wolfgang Grandegger <wg@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PN62_H_
+#define _PN62_H_
+
+/*
+ * Definitions for the Intel Bridge 21554 or 21555.
+ */
+#define I2155X_VPD_ADDR        0xe6
+#define I2155X_VPD_DATA        0xe8
+
+#define I2155X_VPD_START       0x80
+#define I2155X_VPD_SN_START    0x80
+#define I2155X_VPD_SN_SIZE     0x10
+#define I2155X_VPD_MAC0_START  0x90
+#define I2155X_VPD_MAC1_START  0x96
+
+#define I2155X_SCRAPAD_ADDR    0xa8
+#define I2155X_SCRAPAD_MAX     8
+
+#define I2155X_BAR2_BASE       0x98
+#define I2155X_BAR3_BASE       0x9c
+#define I2155X_BAR4_BASE       0xa0
+
+#define I2155X_BAR2_SETUP      0xb0
+#define I2155X_BAR3_SETUP      0xb4
+#define I2155X_BAR4_SETUP      0xb8
+
+/*
+ * Interrupt request numbers
+ */
+#define PN62_IRQ_HOST          0x0
+#define PN62_IRQ_PLX9054       0x1
+#define PN62_IRQ_ETH0          0x2
+#define PN62_IRQ_ETH1          0x3
+#define PN62_IRQ_COM1          0x4
+#define PN62_IRQ_COM2          0x4
+
+/*
+ * Miscellaneous definitons.
+ */
+#define PN62_SMEM_DEFAULT      0x1f00000
+
+/*
+ * Definitions for boot protocol using Scratchpad registers.
+ */
+#define BOOT_DONE              0
+#define BOOT_DONE_CLEAR          0x00dead00
+#define BOOT_DONE_ERROR          0xbad0dead
+#define BOOT_DONE_U_BOOT         0x12345678
+#define BOOT_DONE_LINUX          0x87654321
+#define BOOT_CMD               1
+#define BOOT_CMD_MOVE            0x1
+#define BOOT_CMD_BOOT            0x2
+#define BOOT_DATA              2
+#define BOOT_PROTO             3
+#define BOOT_PROTO_READY         0x23456789
+#define BOOT_PROTO_CLEAR         0x00000000
+#define BOOT_STATUS            4
+
+/*
+ * LED Definitions:
+ */
+#define PN62_LED_BASE          0xff800300
+#define PN62_LED_MAX           12
+
+/*
+ * LED0 - 7 mounted on top of board, D1 - D8
+ * LED8 - 11 upper four LEDs on the front panel of the board.
+ */
+#define LED_0                  0x00    /* OFF */
+#define LED_1                  0x01    /* ON */
+#define LED_SLOW_CLOCK         0x02    /* SLOW 1Hz ish */
+#define LED_nSLOW_CLOCK                0x03    /* inverse of above */
+#define LED_WATCHDOG_OUT       0x06    /* Reset Watchdog level */
+#define LED_WATCHDOG_CLOCK     0x07    /* clock to watchdog */
+
+/*
+ * LED's currently setup in AMD79C973 device as the following:
+ * LED0 100Mbit
+ * LED1 LNKSE
+ * LED2 TX Activity
+ * LED3 RX Activity
+ */
+#define LED_E0_LED0            0x08    /* Ethernet Port 0 LED 0 */
+#define LED_E0_LED1            0x09    /* Ethernet Port 0 LED 1 */
+#define LED_E0_LED2            0x0A    /* Ethernet Port 0 LED 2 */
+#define LED_E0_LED3            0x0B    /* Ethernet Port 0 LED 3 */
+#define LED_E1_LED0            0x0C    /* Ethernet Port 1 LED 0 */
+#define LED_E1_LED1            0x0D    /* Ethernet Port 1 LED 1 */
+#define LED_E1_LED2            0x0E    /* Ethernet Port 1 LED 2 */
+#define LED_E1_LED3            0x0F    /* Ethernet Port 1 LED 3 */
+#define LED_STROBE0            0x10    /* Processor Strobe 0 */
+#define LED_STROBE1            0x11    /* Processor Strobe 1 */
+#define LED_STROBE2            0x12    /* Processor Strobe 2 */
+#define LED_STROBE3            0x13    /* Processor Strobe 3 */
+#define LED_STROBE4            0x14    /* Processor Strobe 4 */
+#define LED_STROBE5            0x15    /* Processor Strobe 5 */
+#define LED_STROBE6            0x16    /* Processor Strobe 6 */
+#define LED_STROBE7            0x17    /* Processor Strobe 7 */
+#define LED_HOST_STROBE0       0x18    /* Host strobe 0 */
+#define LED_HOST_STROBE1       0x19    /* Host strobe 1 */
+#define LED_HOST_STROBE2       0x1A    /* Host strobe 2 */
+#define LED_HOST_STROBE3       0x1B    /* Host strobe 3 */
+#define LED_HOST_STROBE4       0x1C    /* Host strobe 4 */
+#define LED_HOST_STROBE5       0x1D    /* Host strobe 5 */
+#define LED_HOST_STROBE6       0x1E    /* Host strobe 6 */
+#define LED_HOST_STROBE7       0x1F    /* Host strobe 7 */
+#define LED_MPC_INT0           0x20    /* MPC8240 INT 0 */
+#define LED_MPC_INT1           0x21    /* MPC8240 INT 1 */
+#define        LED_MPC_INT2            0x22    /* MPC8240 INT 2 */
+#define        LED_MPC_INT3            0x23    /* MPC8240 INT 3 */
+#define        LED_MPC_INT4            0x24    /* MPC8240 INT 4 */
+#define        LED_UART0_CS            0x25    /* UART 0 Chip Select */
+#define        LED_UART1_CS            0x26    /* UART 1 Chip Select */
+#define        LED_SRAM_CS             0x27    /* SRAM Chip Select */
+#define        LED_SRAM_WR             0x28    /* SRAM WR Signal */
+#define        LED_SRAM_RD             0x29    /* SRAM RD Signal */
+#define        LED_MPC_RCS0            0x2A    /* MPC8240 RCS0 Signal */
+#define        LED_S_PCI_FRAME         0x2B    /* Secondary PCI Frame Signal */
+#define        LED_MPC_CS0             0x2C    /* MPC8240 CS0 Signal */
+#define        LED_HOST_INT            0x2D    /* MPC8240 to Host Interrupt signal */
+#define LED_LAST_FUNCTION      LED_HOST_INT    /* last function */
+
+/*
+ * Forward declarations
+ */
+int  i2155x_init         (void);
+void i2155x_write_scrapad(int idx, u32 val);
+u32  i2155x_read_scrapad (int idx);
+void i2155x_set_bar_base (int bar, u32 addr);
+int  i2155x_read_vpd     (int offset, int size, unsigned char *data);
+
+int  am79c95x_init      (void);
+
+void set_led             (unsigned int number, unsigned int function);
+void fatal_error        (unsigned int error_code);
+void show_startup_phase  (int phase);
+
+
+#endif /* _PN62_H_ */
diff --git a/common/cmd_bedbug.c b/common/cmd_bedbug.c
new file mode 100644 (file)
index 0000000..75b74d5
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * BedBug Functions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <net.h>
+
+#include <cmd_bedbug.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+#include <elf.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+extern void show_regs __P((struct pt_regs*));
+extern int  run_command __P((const char*, int));
+extern char console_buffer[];
+
+ulong        dis_last_addr = 0;        /* Last address disassembled   */
+ulong        dis_last_len = 20;        /* Default disassembler length */
+CPU_DEBUG_CTX bug_ctx;                  /* Bedbug context structure    */
+
+\f
+/* ======================================================================
+ * U-Boot's puts function does not append a newline, so the bedbug stuff
+ * will use this for the output of the dis/assembler.
+ * ====================================================================== */
+
+int bedbug_puts(const char *str)
+{
+  /* -------------------------------------------------- */
+
+  printf( "%s\r\n", str );
+  return 0;
+} /* bedbug_puts */
+
+
+\f
+/* ======================================================================
+ * Initialize the bug_ctx structure used by the bedbug debugger.  This is
+ * specific to the CPU since each has different debug registers and
+ * settings.
+ * ====================================================================== */
+
+void bedbug_init( void )
+{
+  /* -------------------------------------------------- */
+
+#if defined(CONFIG_4xx)
+  void bedbug405_init( void );
+  bedbug405_init();
+#elif defined(CONFIG_MPC860)
+  void bedbug860_init( void );
+  bedbug860_init();
+#endif
+
+#if defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260)
+  /* Processors that are 603e core based */
+  void bedbug603e_init( void );
+
+  bedbug603e_init();
+#endif
+
+  return;
+} /* bedbug_init */
+
+
+\f
+/* ======================================================================
+ * Entry point from the interpreter to the disassembler.  Repeated calls
+ * will resume from the last disassembled address.
+ * ====================================================================== */
+int do_bedbug_dis (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+  ulong        addr;   /* Address to start disassembly from    */
+  ulong        len;    /* # of instructions to disassemble     */
+  /* -------------------------------------------------- */
+
+  /* Setup to go from the last address if none is given */
+  addr = dis_last_addr;
+  len  = dis_last_len;
+
+  if (argc < 2)
+  {
+    printf ("Usage:\n%s\n", cmdtp->usage);
+    return 1;
+  }
+
+  if(( flag & CMD_FLAG_REPEAT ) == 0 )
+  {
+    /* New command */
+    addr = simple_strtoul( argv[1], NULL, 16 );
+
+    /* If an extra param is given then it is the length */
+    if( argc > 2 )
+      len = simple_strtoul( argv[2], NULL, 16 );
+  }
+
+  /* Run the disassembler */
+  disppc( (unsigned char *)addr, 0, len, bedbug_puts, F_RADHEX );
+
+  dis_last_addr = addr + (len * 4);
+  dis_last_len = len;
+  return 0;
+} /* do_bedbug_dis */
+
+
+\f
+/* ======================================================================
+ * Entry point from the interpreter to the assembler.  Assembles
+ * instructions in consecutive memory locations until a '.' (period) is
+ * entered on a line by itself.
+ * ====================================================================== */
+int do_bedbug_asm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+  long         mem_addr;               /* Address to assemble into     */
+  unsigned long instr;                  /* Machine code for text        */
+  char         prompt[ 15 ];           /* Prompt string for user input */
+  int          asm_err;                /* Error code from the assembler*/
+  /* -------------------------------------------------- */
+   int          rcode = 0;
+
+  if (argc < 2)
+  {
+    printf ("Usage:\n%s\n", cmdtp->usage);
+    return 1;
+  }
+
+  printf( "\nEnter '.' when done\n" );
+  mem_addr = simple_strtoul( argv[ 1 ], NULL, 16 );
+
+  while( 1 )
+  {
+    putc( '\n' );
+    disppc( (unsigned char *)mem_addr, 0, 1, bedbug_puts, F_RADHEX );
+
+    sprintf( prompt, "%08lx:    ", mem_addr );
+    readline( prompt );
+
+    if( console_buffer[ 0 ] && strcmp( console_buffer, "." ))
+    {
+      if(( instr = asmppc( mem_addr, console_buffer, &asm_err )) != 0 )
+      {
+       *(unsigned long *)mem_addr = instr;
+       mem_addr += 4;
+      }
+      else
+      {
+       printf( "*** Error: %s ***\n", asm_error_str( asm_err ));
+        rcode = 1;
+      }
+    }
+    else
+    {
+      break;
+    }
+  }
+  return rcode;
+} /* do_bedbug_asm */
+
+
+\f
+/* ======================================================================
+ * Used to set a break point from the interpreter.  Simply calls into the
+ * CPU-specific break point set routine.
+ * ====================================================================== */
+
+int do_bedbug_break (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+  /* -------------------------------------------------- */
+  if( bug_ctx.do_break )
+    (*bug_ctx.do_break)( cmdtp, flag, argc, argv );
+    return 0;
+
+} /* do_bedbug_break */
+
+
+\f
+/* ======================================================================
+ * Called from the debug interrupt routine.  Simply calls the CPU-specific
+ * breakpoint handling routine.
+ * ====================================================================== */
+
+void do_bedbug_breakpoint (struct pt_regs *regs)
+{
+  /* -------------------------------------------------- */
+
+  if( bug_ctx.break_isr )
+    (*bug_ctx.break_isr)( regs );
+
+  return;
+} /* do_bedbug_breakpoint */
+
+
+\f
+/* ======================================================================
+ * Called from the CPU-specific breakpoint handling routine.  Enter a
+ * mini main loop until the stopped flag is cleared from the breakpoint
+ * context.
+ *
+ * This handles the parts of the debugger that are common to all CPU's.
+ * ====================================================================== */
+
+void bedbug_main_loop( unsigned long addr, struct pt_regs *regs )
+{
+  int          len;                    /* Length of command line */
+  int           flag;                   /* Command flags          */
+  int           rc = 0;                 /* Result from run_command*/
+  char          prompt_str[ 20 ];       /* Prompt string          */
+  static char   lastcommand[ CFG_CBSIZE ] = {0}; /* previous command */
+  /* -------------------------------------------------- */
+
+  if( bug_ctx.clear )
+    (*bug_ctx.clear)( bug_ctx.current_bp );
+
+  printf( "Breakpoint %d: ", bug_ctx.current_bp );
+  disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+
+  bug_ctx.stopped = 1;
+  bug_ctx.regs = regs;
+
+  sprintf( prompt_str, "BEDBUG.%d =>", bug_ctx.current_bp );
+
+  /* A miniature main loop */
+  while( bug_ctx.stopped )
+  {
+    len = readline( prompt_str );
+
+    flag = 0;  /* assume no special flags for now */
+
+    if (len > 0)
+      strcpy( lastcommand, console_buffer );
+    else if( len == 0 )
+      flag |= CMD_FLAG_REPEAT;
+
+    if (len == -1)
+      printf ("<INTERRUPT>\n");
+    else
+      rc = run_command( lastcommand, flag );
+
+    if (rc <= 0) {
+      /* invalid command or not repeatable, forget it */
+      lastcommand[0] = 0;
+    }
+  }
+
+  bug_ctx.regs = NULL;
+  bug_ctx.current_bp = 0;
+
+  return;
+} /* bedbug_main_loop */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to continue from a breakpoint.  Just clears the
+ * stopped flag in the context so that the breakpoint routine will
+ * return.
+ * ====================================================================== */
+int do_bedbug_continue (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+
+{
+  /* -------------------------------------------------- */
+
+  if( ! bug_ctx.stopped )
+  {
+    printf( "Not at a breakpoint\n" );
+    return 1;
+  }
+
+  bug_ctx.stopped = 0;
+  return 0;
+} /* do_bedbug_continue */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to continue to the next instruction, stepping into
+ * subroutines.  Works by calling the find_next_addr() routine to compute
+ * the address passes control to the CPU-specific set breakpoint routine
+ * for the current breakpoint number.
+ * ====================================================================== */
+int do_bedbug_step (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+  unsigned long addr;   /* Address to stop at */
+  /* -------------------------------------------------- */
+
+  if( ! bug_ctx.stopped )
+  {
+    printf( "Not at a breakpoint\n" );
+    return 1;
+  }
+
+  if( !find_next_address( (unsigned char *)&addr, FALSE, bug_ctx.regs ))
+    return 1;
+
+  if( bug_ctx.set )
+    (*bug_ctx.set)( bug_ctx.current_bp, addr );
+
+  bug_ctx.stopped = 0;
+  return 0;
+} /* do_bedbug_step */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to continue to the next instruction, stepping over
+ * subroutines.  Works by calling the find_next_addr() routine to compute
+ * the address passes control to the CPU-specific set breakpoint routine
+ * for the current breakpoint number.
+ * ====================================================================== */
+int do_bedbug_next (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+  unsigned long addr;   /* Address to stop at */
+  /* -------------------------------------------------- */
+
+  if( ! bug_ctx.stopped )
+  {
+    printf( "Not at a breakpoint\n" );
+    return 1;
+  }
+
+  if( !find_next_address( (unsigned char *)&addr, TRUE, bug_ctx.regs ))
+    return 1;
+
+  if( bug_ctx.set )
+    (*bug_ctx.set)( bug_ctx.current_bp, addr );
+
+  bug_ctx.stopped = 0;
+  return 0;
+} /* do_bedbug_next */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to print the current stack.  This assumes an EABI
+ * architecture, so it starts with GPR R1 and works back up the stack.
+ * ====================================================================== */
+int do_bedbug_stack (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+  unsigned long sp;             /* Stack pointer                */
+  unsigned long func;           /* LR from stack                */
+  int           depth;          /* Stack iteration level        */
+  int           skip = 1;       /* Flag to skip the first entry */
+  unsigned long top;            /* Top of memory address        */
+  /* -------------------------------------------------- */
+
+  if( ! bug_ctx.stopped )
+  {
+    printf( "Not at a breakpoint\n" );
+    return 1;
+  }
+
+  top = gd->bd->bi_memstart + gd->bd->bi_memsize;
+  depth = 0;
+
+  printf( "Depth     PC\n" );
+  printf( "-----  --------\n" );
+  printf( "%5d  %08lx\n", depth++, bug_ctx.regs->nip );
+
+  sp = bug_ctx.regs->gpr[ 1 ];
+  func = *(unsigned long *)(sp+4);
+
+  while(( func < top ) && ( sp < top ))
+  {
+    if( !skip )
+      printf( "%5d  %08lx\n", depth++, func );
+    else
+      --skip;
+
+    sp = *(unsigned long *)sp;
+    func = *(unsigned long *)(sp+4);
+  }
+  return 0;
+} /* do_bedbug_stack */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to dump the registers.  Calls the CPU-specific
+ * show registers routine.
+ * ====================================================================== */
+int do_bedbug_rdump (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+  /* -------------------------------------------------- */
+
+  if( ! bug_ctx.stopped )
+  {
+    printf( "Not at a breakpoint\n" );
+    return 1;
+  }
+
+  show_regs( bug_ctx.regs );
+  return 0;
+} /* do_bedbug_rdump */
+
+
+/* ====================================================================== */
+#endif /* CFG_CMD_BEDBUG */
+
+
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
new file mode 100644 (file)
index 0000000..e8ce40d
--- /dev/null
@@ -0,0 +1,931 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <cmd_boot.h>
+#include <image.h>
+#include <malloc.h>
+#include <zlib.h>
+#include <asm/byteorder.h>
+#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
+#include <rtc.h>
+#endif
+
+#ifdef CFG_HUSH_PARSER
+#include <hush.h>
+#endif
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg)       show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+#ifdef CFG_INIT_RAM_LOCK
+#include <asm/cache.h>
+#endif
+
+/*
+ * Some systems (for example LWMON) have very short watchdog periods;
+ * we must make sure to split long operations like memmove() or
+ * crc32() into reasonable chunks.
+ */
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+# define CHUNKSZ (64 * 1024)
+#endif
+
+int  gunzip (void *, int, unsigned char *, int *);
+
+static void *zalloc(void *, unsigned, unsigned);
+static void zfree(void *, void *, unsigned);
+
+#if (CONFIG_COMMANDS & CFG_CMD_IMI)
+static int image_info (unsigned long addr);
+#endif
+static void print_type (image_header_t *hdr);
+
+/*
+ *  Continue booting an OS image; caller already has:
+ *  - copied image header to global variable `header'
+ *  - checked header magic number, checksums (both header & image),
+ *  - verified image architecture (PPC) and type (KERNEL or MULTI),
+ *  - loaded (first part of) image to header load address,
+ *  - disabled interrupts.
+ */
+typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag,
+                         int   argc, char *argv[],
+                         ulong addr,           /* of image to boot */
+                         ulong *len_ptr,       /* multi-file image length table */
+                         int   verify);        /* getenv("verify")[0] != 'n' */
+
+#ifndef CONFIG_ARM
+static boot_os_Fcn do_bootm_linux;
+#else
+extern boot_os_Fcn do_bootm_linux;
+#endif
+static boot_os_Fcn do_bootm_netbsd;
+#if (CONFIG_COMMANDS & CFG_CMD_ELF)
+static boot_os_Fcn do_bootm_vxworks;
+static boot_os_Fcn do_bootm_qnxelf;
+int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
+int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
+#endif /* CFG_CMD_ELF */
+
+image_header_t header;
+
+ulong load_addr = CFG_LOAD_ADDR;               /* Default Load Address */
+
+int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       ulong   iflag;
+       ulong   addr;
+       ulong   data, len, checksum;
+       ulong  *len_ptr;
+       int     i, verify;
+       char    *name, *s;
+       int     (*appl)(cmd_tbl_t *, int, int, char *[]);
+       image_header_t *hdr = &header;
+
+       s = getenv ("verify");
+       verify = (s && (*s == 'n')) ? 0 : 1;
+
+       if (argc < 2) {
+               addr = load_addr;
+       } else {
+               addr = simple_strtoul(argv[1], NULL, 16);
+       }
+
+       SHOW_BOOT_PROGRESS (1);
+       printf ("## Booting image at %08lx ...\n", addr);
+
+       /* Copy header so we can blank CRC field for re-calculation */
+       memmove (&header, (char *)addr, sizeof(image_header_t));
+
+       if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+               printf ("Bad Magic Number\n");
+               SHOW_BOOT_PROGRESS (-1);
+               return 1;
+       }
+       SHOW_BOOT_PROGRESS (2);
+
+       data = (ulong)&header;
+       len  = sizeof(image_header_t);
+
+       checksum = ntohl(hdr->ih_hcrc);
+       hdr->ih_hcrc = 0;
+
+       if (crc32 (0, (char *)data, len) != checksum) {
+               printf ("Bad Header Checksum\n");
+               SHOW_BOOT_PROGRESS (-2);
+               return 1;
+       }
+       SHOW_BOOT_PROGRESS (3);
+
+       /* for multi-file images we need the data part, too */
+       print_image_hdr ((image_header_t *)addr);
+
+       data = addr + sizeof(image_header_t);
+       len  = ntohl(hdr->ih_size);
+
+       if (verify) {
+               printf ("   Verifying Checksum ... ");
+               if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
+                       printf ("Bad Data CRC\n");
+                       SHOW_BOOT_PROGRESS (-3);
+                       return 1;
+               }
+               printf ("OK\n");
+       }
+       SHOW_BOOT_PROGRESS (4);
+
+       len_ptr = (ulong *)data;
+
+       if (hdr->ih_arch != IH_CPU_PPC && hdr->ih_arch != IH_CPU_ARM) {
+               printf ("Unsupported Architecture\n");
+               SHOW_BOOT_PROGRESS (-4);
+               return 1;
+       }
+       SHOW_BOOT_PROGRESS (5);
+
+       switch (hdr->ih_type) {
+       case IH_TYPE_STANDALONE:        name = "Standalone Application";
+                                       break;
+       case IH_TYPE_KERNEL:            name = "Kernel Image";
+                                       break;
+       case IH_TYPE_MULTI:             name = "Multi-File Image";
+                                       len  = ntohl(len_ptr[0]);
+                                       /* OS kernel is always the first image */
+                                       data += 8; /* kernel_len + terminator */
+                                       for (i=1; len_ptr[i]; ++i)
+                                               data += 4;
+                                       break;
+       default: printf ("Wrong Image Type for %s command\n", cmdtp->name);
+               SHOW_BOOT_PROGRESS (-5);
+               return 1;
+       }
+       SHOW_BOOT_PROGRESS (6);
+
+       /*
+        * We have reached the point of no return: we are going to
+        * overwrite all exception vector code, so we cannot easily
+        * recover from any failures any more...
+        */
+
+       iflag = disable_interrupts();
+
+       switch (hdr->ih_comp) {
+       case IH_COMP_NONE:
+               if(hdr->ih_load == addr) {
+                       printf ("   XIP %s ... ", name);
+               } else {
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+                       size_t l = len;
+                       void *to = (void *)ntohl(hdr->ih_load);
+                       void *from = (void *)data;
+
+                       printf ("   Loading %s ... ", name);
+
+                       while (l > 0) {
+                               size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
+                               WATCHDOG_RESET();
+                               memmove (to, from, tail);
+                               to += tail;
+                               from += tail;
+                               l -= tail;
+                       }
+#else  /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
+                       memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
+#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
+               }
+               break;
+       case IH_COMP_GZIP:
+               printf ("   Uncompressing %s ... ", name);
+               if (gunzip ((void *)ntohl(hdr->ih_load), 0x400000,
+                           (uchar *)data, (int *)&len) != 0) {
+                       printf ("GUNZIP ERROR - must RESET board to recover\n");
+                       SHOW_BOOT_PROGRESS (-6);
+                       do_reset (cmdtp, flag, argc, argv);
+               }
+               break;
+       default:
+               if (iflag)
+                       enable_interrupts();
+               printf ("Unimplemented compression type %d\n", hdr->ih_comp);
+               SHOW_BOOT_PROGRESS (-7);
+               return 1;
+       }
+       printf ("OK\n");
+       SHOW_BOOT_PROGRESS (7);
+
+       switch (hdr->ih_type) {
+       case IH_TYPE_STANDALONE:
+               appl = (int (*)(cmd_tbl_t *, int, int, char *[]))ntohl(hdr->ih_ep);
+               if (iflag)
+                       enable_interrupts();
+
+               (*appl)(cmdtp, flag, argc-1, &argv[1]);
+               break;
+       case IH_TYPE_KERNEL:
+       case IH_TYPE_MULTI:
+               /* handled below */
+               break;
+       default:
+               if (iflag)
+                       enable_interrupts();
+               printf ("Can't boot image type %d\n", hdr->ih_type);
+               SHOW_BOOT_PROGRESS (-8);
+               return 1;
+       }
+       SHOW_BOOT_PROGRESS (8);
+
+       switch (hdr->ih_os) {
+       default:                        /* handled by (original) Linux case */
+       case IH_OS_LINUX:
+           do_bootm_linux  (cmdtp, flag, argc, argv,
+                            addr, len_ptr, verify);
+           break;
+       case IH_OS_NETBSD:
+           do_bootm_netbsd (cmdtp, flag, argc, argv,
+                            addr, len_ptr, verify);
+           break;
+#if (CONFIG_COMMANDS & CFG_CMD_ELF)
+       case IH_OS_VXWORKS:
+           do_bootm_vxworks (cmdtp, flag, argc, argv,
+                             addr, len_ptr, verify);
+           break;
+       case IH_OS_QNX:
+           do_bootm_qnxelf (cmdtp, flag, argc, argv,
+                             addr, len_ptr, verify);
+           break;
+#endif /* CFG_CMD_ELF */
+       }
+
+       SHOW_BOOT_PROGRESS (-9);
+#ifdef DEBUG
+       printf ("\n## Control returned to monitor - resetting...\n");
+       do_reset (cmdtp, flag, argc, argv);
+#endif
+       return 1;
+}
+
+#ifndef CONFIG_ARM
+static void
+do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
+               int     argc, char *argv[],
+               ulong   addr,
+               ulong   *len_ptr,
+               int     verify)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       ulong   sp;
+       ulong   len, checksum;
+       ulong   initrd_start, initrd_end;
+       ulong   cmd_start, cmd_end;
+       ulong   initrd_high;
+       ulong   data;
+       char    *cmdline;
+       char    *s;
+       bd_t    *kbd;
+       void    (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
+       image_header_t *hdr = &header;
+
+       if ((s = getenv ("initrd_high")) != NULL) {
+               /* a value of "no" or a similar string will act like 0,
+                * turning the "load high" feature off. This is intentional.
+                */
+               initrd_high = simple_strtoul(s, NULL, 16);
+       } else {                        /* not set, no restrictions to load high */
+               initrd_high = ~0;
+       }
+
+       /*
+        * Booting a (Linux) kernel image
+        *
+        * Allocate space for command line and board info - the
+        * address should be as high as possible within the reach of
+        * the kernel (see CFG_BOOTMAPSZ settings), but in unused
+        * memory, which means far enough below the current stack
+        * pointer.
+        */
+
+       asm( "mr %0,1": "=r"(sp) : );
+
+#ifdef DEBUG
+       printf ("## Current stack ends at 0x%08lX ", sp);
+#endif
+       sp -= 2048;             /* just to be sure */
+       if (sp > CFG_BOOTMAPSZ)
+               sp = CFG_BOOTMAPSZ;
+       sp &= ~0xF;
+
+#ifdef DEBUG
+       printf ("=> set upper limit to 0x%08lX\n", sp);
+#endif
+       cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF);
+       kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF);
+
+       if ((s = getenv("bootargs")) == NULL)
+               s = "";
+
+       strcpy (cmdline, s);
+
+       cmd_start    = (ulong)&cmdline[0];
+       cmd_end      = cmd_start + strlen(cmdline);
+
+       *kbd = *(gd->bd);
+
+#ifdef DEBUG
+       printf ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end);
+
+       do_bdinfo (NULL, 0, 0, NULL);
+#endif
+
+       if ((s = getenv ("clocks_in_mhz")) != NULL) {
+               /* convert all clock information to MHz */
+               kbd->bi_intfreq /= 1000000L;
+               kbd->bi_busfreq /= 1000000L;
+#if defined(CONFIG_8260)
+               kbd->bi_cpmfreq /= 1000000L;
+               kbd->bi_brgfreq /= 1000000L;
+               kbd->bi_sccfreq /= 1000000L;
+               kbd->bi_vco     /= 1000000L;
+#endif /* CONFIG_8260 */
+       }
+
+       kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))hdr->ih_ep;
+
+       /*
+        * Check if there is an initrd image
+        */
+       if (argc >= 3) {
+               SHOW_BOOT_PROGRESS (9);
+
+               addr = simple_strtoul(argv[2], NULL, 16);
+
+               printf ("## Loading RAMDisk Image at %08lx ...\n", addr);
+
+               /* Copy header so we can blank CRC field for re-calculation */
+               memmove (&header, (char *)addr, sizeof(image_header_t));
+
+               if (hdr->ih_magic  != IH_MAGIC) {
+                       printf ("Bad Magic Number\n");
+                       SHOW_BOOT_PROGRESS (-10);
+                       do_reset (cmdtp, flag, argc, argv);
+               }
+
+               data = (ulong)&header;
+               len  = sizeof(image_header_t);
+
+               checksum = hdr->ih_hcrc;
+               hdr->ih_hcrc = 0;
+
+               if (crc32 (0, (char *)data, len) != checksum) {
+                       printf ("Bad Header Checksum\n");
+                       SHOW_BOOT_PROGRESS (-11);
+                       do_reset (cmdtp, flag, argc, argv);
+               }
+
+               SHOW_BOOT_PROGRESS (10);
+
+               print_image_hdr (hdr);
+
+               data = addr + sizeof(image_header_t);
+               len  = hdr->ih_size;
+
+               if (verify) {
+                       ulong csum = 0;
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+                       ulong cdata = data, edata = cdata + len;
+#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
+
+                       printf ("   Verifying Checksum ... ");
+
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+
+                       while (cdata < edata) {
+                               ulong chunk = edata - cdata;
+
+                               if (chunk > CHUNKSZ)
+                                       chunk = CHUNKSZ;
+                               csum = crc32 (csum, (char *)cdata, chunk);
+                               cdata += chunk;
+
+                               WATCHDOG_RESET();
+                       }
+#else  /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
+                       csum = crc32 (0, (char *)data, len);
+#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
+
+                       if (csum != hdr->ih_dcrc) {
+                               printf ("Bad Data CRC\n");
+                               SHOW_BOOT_PROGRESS (-12);
+                               do_reset (cmdtp, flag, argc, argv);
+                       }
+                       printf ("OK\n");
+               }
+
+               SHOW_BOOT_PROGRESS (11);
+
+               if ((hdr->ih_os   != IH_OS_LINUX)       ||
+                   (hdr->ih_arch != IH_CPU_PPC)        ||
+                   (hdr->ih_type != IH_TYPE_RAMDISK)   ) {
+                       printf ("No Linux PPC Ramdisk Image\n");
+                       SHOW_BOOT_PROGRESS (-13);
+                       do_reset (cmdtp, flag, argc, argv);
+               }
+
+               /*
+                * Now check if we have a multifile image
+                */
+       } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
+               u_long tail    = ntohl(len_ptr[0]) % 4;
+               int i;
+
+               SHOW_BOOT_PROGRESS (13);
+
+               /* skip kernel length and terminator */
+               data = (ulong)(&len_ptr[2]);
+               /* skip any additional image length fields */
+               for (i=1; len_ptr[i]; ++i)
+                       data += 4;
+               /* add kernel length, and align */
+               data += ntohl(len_ptr[0]);
+               if (tail) {
+                       data += 4 - tail;
+               }
+
+               len   = ntohl(len_ptr[1]);
+
+       } else {
+               /*
+                * no initrd image
+                */
+               SHOW_BOOT_PROGRESS (14);
+
+               len = data = 0;
+       }
+
+#ifdef DEBUG
+       if (!data) {
+               printf ("No initrd\n");
+       }
+#endif
+
+       if (data) {
+               initrd_start  = (ulong)kbd - len;
+               initrd_start &= ~(4096 - 1);    /* align on page */
+
+               if (initrd_high) {
+                       ulong nsp;
+
+                       /*
+                        * the inital ramdisk does not need to be within
+                        * CFG_BOOTMAPSZ as it is not accessed until after
+                        * the mm system is initialised.
+                        *
+                        * do the stack bottom calculation again and see if
+                        * the initrd will fit just below the monitor stack
+                        * bottom without overwriting the area allocated
+                        * above for command line args and board info.
+                        */
+                       asm( "mr %0,1": "=r"(nsp) : );
+                       nsp -= 2048;            /* just to be sure */
+                       nsp &= ~0xF;
+                       if (nsp > initrd_high)  /* limit as specified */
+                               nsp = initrd_high;
+                       nsp -= len;
+                       nsp &= ~(4096 - 1);     /* align on page */
+                       if (nsp >= sp)
+                               initrd_start = nsp;
+               }
+
+               SHOW_BOOT_PROGRESS (12);
+#ifdef DEBUG
+               printf ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
+                       data, data + len - 1, len, len);
+#endif
+               initrd_end    = initrd_start + len;
+               printf ("   Loading Ramdisk to %08lx, end %08lx ... ",
+                       initrd_start, initrd_end);
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+               {
+                       size_t l = len;
+                       void *to = (void *)initrd_start;
+                       void *from = (void *)data;
+
+                       while (l > 0) {
+                               size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
+                               WATCHDOG_RESET();
+                               memmove (to, from, tail);
+                               to += tail;
+                               from += tail;
+                               l -= tail;
+                       }
+               }
+#else  /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
+               memmove ((void *)initrd_start, (void *)data, len);
+#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
+               printf ("OK\n");
+       } else {
+               initrd_start = 0;
+               initrd_end = 0;
+       }
+
+#ifdef DEBUG
+       printf ("## Transferring control to Linux (at address %08lx) ...\n",
+               (ulong)kernel);
+#endif
+       SHOW_BOOT_PROGRESS (15);
+
+#ifdef CFG_INIT_RAM_LOCK
+       unlock_ram_in_cache();
+#endif
+       /*
+        * Linux Kernel Parameters:
+        *   r3: ptr to board info data
+        *   r4: initrd_start or 0 if no initrd
+        *   r5: initrd_end - unused if r4 is 0
+        *   r6: Start of command line string
+        *   r7: End   of command line string
+        */
+       (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
+}
+#endif /* CONFIG_ARM */
+
+static void
+do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,
+               int     argc, char *argv[],
+               ulong   addr,
+               ulong   *len_ptr,
+               int     verify)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       image_header_t *hdr = &header;
+
+       void    (*loader)(bd_t *, image_header_t *, char *, char *);
+       image_header_t *img_addr;
+       char     *consdev;
+       char     *cmdline;
+
+
+       /*
+        * Booting a (NetBSD) kernel image
+        *
+        * This process is pretty similar to a standalone application:
+        * The (first part of an multi-) image must be a stage-2 loader,
+        * which in turn is responsible for loading & invoking the actual
+        * kernel.  The only differences are the parameters being passed:
+        * besides the board info strucure, the loader expects a command
+        * line, the name of the console device, and (optionally) the
+        * address of the original image header.
+        */
+
+       img_addr = 0;
+       if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]))
+               img_addr = (image_header_t *) addr;
+
+
+       consdev = "";
+#if   defined (CONFIG_8xx_CONS_SMC1)
+       consdev = "smc1";
+#elif defined (CONFIG_8xx_CONS_SMC2)
+       consdev = "smc2";
+#elif defined (CONFIG_8xx_CONS_SCC2)
+       consdev = "scc2";
+#elif defined (CONFIG_8xx_CONS_SCC3)
+       consdev = "scc3";
+#endif
+
+       if (argc > 2) {
+               ulong len;
+               int   i;
+
+               for (i=2, len=0 ; i<argc ; i+=1)
+                       len += strlen (argv[i]) + 1;
+               cmdline = malloc (len);
+
+               for (i=2, len=0 ; i<argc ; i+=1) {
+                       if (i > 2)
+                               cmdline[len++] = ' ';
+                       strcpy (&cmdline[len], argv[i]);
+                       len += strlen (argv[i]);
+               }
+       } else if ((cmdline = getenv("bootargs")) == NULL) {
+               cmdline = "";
+       }
+
+       loader = (void (*)(bd_t *, image_header_t *, char *, char *)) hdr->ih_ep;
+
+       printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",
+               (ulong)loader);
+
+       SHOW_BOOT_PROGRESS (15);
+
+       /*
+        * NetBSD Stage-2 Loader Parameters:
+        *   r3: ptr to board info data
+        *   r4: image address
+        *   r5: console device
+        *   r6: boot args string
+        */
+       (*loader) (gd->bd, img_addr, consdev, cmdline);
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
+int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       int rcode = 0;
+#ifndef CFG_HUSH_PARSER
+       if (run_command (getenv ("bootcmd"), flag) < 0) rcode = 1;
+#else
+       if (parse_string_outer(getenv("bootcmd"),
+               FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0 ) rcode = 1;
+#endif
+       return rcode;
+}
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_IMI)
+int do_iminfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       int     arg;
+       ulong   addr;
+       int     rcode=0;
+
+       if (argc < 2) {
+               return image_info (load_addr);
+       }
+
+       for (arg=1; arg <argc; ++arg) {
+               addr = simple_strtoul(argv[arg], NULL, 16);
+               if (image_info (addr) != 0) rcode = 1;
+       }
+       return rcode;
+}
+
+static int image_info (ulong addr)
+{
+       ulong   data, len, checksum;
+       image_header_t *hdr = &header;
+
+       printf ("\n## Checking Image at %08lx ...\n", addr);
+
+       /* Copy header so we can blank CRC field for re-calculation */
+       memmove (&header, (char *)addr, sizeof(image_header_t));
+
+       if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+               printf ("   Bad Magic Number\n");
+               return 1;
+       }
+
+       data = (ulong)&header;
+       len  = sizeof(image_header_t);
+
+       checksum = ntohl(hdr->ih_hcrc);
+       hdr->ih_hcrc = 0;
+
+       if (crc32 (0, (char *)data, len) != checksum) {
+               printf ("   Bad Header Checksum\n");
+               return 1;
+       }
+
+       /* for multi-file images we need the data part, too */
+       print_image_hdr ((image_header_t *)addr);
+
+       data = addr + sizeof(image_header_t);
+       len  = ntohl(hdr->ih_size);
+
+       printf ("   Verifying Checksum ... ");
+       if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
+               printf ("   Bad Data CRC\n");
+               return 1;
+       }
+       printf ("OK\n");
+       return 0;
+}
+#endif /* CFG_CMD_IMI */
+
+void
+print_image_hdr (image_header_t *hdr)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
+       time_t timestamp = (time_t)ntohl(hdr->ih_time);
+       struct rtc_time tm;
+#endif
+
+       printf ("   Image Name:   %.*s\n", IH_NMLEN, hdr->ih_name);
+#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
+       to_tm (timestamp, &tm);
+       printf ("   Created:      %4d-%02d-%02d  %2d:%02d:%02d UTC\n",
+               tm.tm_year, tm.tm_mon, tm.tm_mday,
+               tm.tm_hour, tm.tm_min, tm.tm_sec);
+#endif /* CFG_CMD_DATE, CONFIG_TIMESTAMP */
+       printf ("   Image Type:   "); print_type(hdr); printf ("\n");
+       printf ("   Data Size:    %d Bytes = ", ntohl(hdr->ih_size));
+       print_size (ntohl(hdr->ih_size), "\n");
+       printf ("   Load Address: %08x\n", ntohl(hdr->ih_load));
+       printf ("   Entry Point:  %08x\n", ntohl(hdr->ih_ep));
+
+       if (hdr->ih_type == IH_TYPE_MULTI) {
+               int i;
+               ulong len;
+               ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t));
+
+               printf ("   Contents:\n");
+               for (i=0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) {
+                       printf ("   Image %d: %8ld Bytes = ", i, len);
+                       print_size (len, "\n");
+               }
+       }
+}
+
+
+static void
+print_type (image_header_t *hdr)
+{
+       char *os, *arch, *type, *comp;
+
+       switch (hdr->ih_os) {
+       case IH_OS_INVALID:     os = "Invalid OS";              break;
+       case IH_OS_NETBSD:      os = "NetBSD";                  break;
+       case IH_OS_LINUX:       os = "Linux";                   break;
+       case IH_OS_VXWORKS:     os = "VxWorks";                 break;
+       case IH_OS_QNX:         os = "QNX";                     break;
+       case IH_OS_U_BOOT:      os = "U-Boot";                  break;
+       default:                os = "Unknown OS";              break;
+       }
+
+       switch (hdr->ih_arch) {
+       case IH_CPU_INVALID:    arch = "Invalid CPU";           break;
+       case IH_CPU_ALPHA:      arch = "Alpha";                 break;
+       case IH_CPU_ARM:        arch = "ARM";                   break;
+       case IH_CPU_I386:       arch = "Intel x86";             break;
+       case IH_CPU_IA64:       arch = "IA64";                  break;
+       case IH_CPU_MIPS:       arch = "MIPS";                  break;
+       case IH_CPU_MIPS64:     arch = "MIPS 64 Bit";           break;
+       case IH_CPU_PPC:        arch = "PowerPC";               break;
+       case IH_CPU_S390:       arch = "IBM S390";              break;
+       case IH_CPU_SH:         arch = "SuperH";                break;
+       case IH_CPU_SPARC:      arch = "SPARC";                 break;
+       case IH_CPU_SPARC64:    arch = "SPARC 64 Bit";          break;
+       default:                arch = "Unknown Architecture";  break;
+       }
+
+       switch (hdr->ih_type) {
+       case IH_TYPE_INVALID:   type = "Invalid Image";         break;
+       case IH_TYPE_STANDALONE:type = "Standalone Program";    break;
+       case IH_TYPE_KERNEL:    type = "Kernel Image";          break;
+       case IH_TYPE_RAMDISK:   type = "RAMDisk Image";         break;
+       case IH_TYPE_MULTI:     type = "Multi-File Image";      break;
+       case IH_TYPE_FIRMWARE:  type = "Firmware";              break;
+       case IH_TYPE_SCRIPT:    type = "Script";                break;
+       default:                type = "Unknown Image";         break;
+       }
+
+       switch (hdr->ih_comp) {
+       case IH_COMP_NONE:      comp = "uncompressed";          break;
+       case IH_COMP_GZIP:      comp = "gzip compressed";       break;
+       case IH_COMP_BZIP2:     comp = "bzip2 compressed";      break;
+       default:                comp = "unknown compression";   break;
+       }
+
+       printf ("%s %s %s (%s)", arch, os, type, comp);
+}
+
+#define        ZALLOC_ALIGNMENT        16
+
+static void *zalloc(void *x, unsigned items, unsigned size)
+{
+       void *p;
+
+       size *= items;
+       size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
+
+       p = malloc (size);
+
+       return (p);
+}
+
+static void zfree(void *x, void *addr, unsigned nb)
+{
+       free (addr);
+}
+
+#define HEAD_CRC       2
+#define EXTRA_FIELD    4
+#define ORIG_NAME      8
+#define COMMENT                0x10
+#define RESERVED       0xe0
+
+#define DEFLATED       8
+
+int gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+       z_stream s;
+       int r, i, flags;
+
+       /* skip header */
+       i = 10;
+       flags = src[3];
+       if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+               printf ("Error: Bad gzipped data\n");
+               return (-1);
+       }
+       if ((flags & EXTRA_FIELD) != 0)
+               i = 12 + src[10] + (src[11] << 8);
+       if ((flags & ORIG_NAME) != 0)
+               while (src[i++] != 0)
+                       ;
+       if ((flags & COMMENT) != 0)
+               while (src[i++] != 0)
+                       ;
+       if ((flags & HEAD_CRC) != 0)
+               i += 2;
+       if (i >= *lenp) {
+               printf ("Error: gunzip out of data in header\n");
+               return (-1);
+       }
+
+       s.zalloc = zalloc;
+       s.zfree = zfree;
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+       s.outcb = (cb_func)WATCHDOG_RESET;
+#else
+       s.outcb = Z_NULL;
+#endif /* CONFIG_HW_WATCHDOG */
+
+       r = inflateInit2(&s, -MAX_WBITS);
+       if (r != Z_OK) {
+               printf ("Error: inflateInit2() returned %d\n", r);
+               return (-1);
+       }
+       s.next_in = src + i;
+       s.avail_in = *lenp - i;
+       s.next_out = dst;
+       s.avail_out = dstlen;
+       r = inflate(&s, Z_FINISH);
+       if (r != Z_OK && r != Z_STREAM_END) {
+               printf ("Error: inflate() returned %d\n", r);
+               return (-1);
+       }
+       *lenp = s.next_out - (unsigned char *) dst;
+       inflateEnd(&s);
+
+       return (0);
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_ELF)
+static void
+do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
+                 ulong addr, ulong *len_ptr, int verify)
+{
+       image_header_t *hdr = &header;
+       char str[80];
+
+       sprintf(str, "%x", hdr->ih_ep); /* write entry-point into string */
+       setenv("loadaddr", str);
+       do_bootvx(cmdtp, 0, 0, NULL);
+}
+
+static void
+do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
+                ulong addr, ulong *len_ptr, int verify)
+{
+       image_header_t *hdr = &header;
+       char *local_args[2];
+       char str[16];
+
+       sprintf(str, "%x", hdr->ih_ep); /* write entry-point into string */
+       local_args[0] = argv[0];
+       local_args[1] = str;    /* and provide it via the arguments */
+       do_bootelf(cmdtp, 0, 2, local_args);
+}
+#endif /* CFG_CMD_ELF */
diff --git a/common/console.c b/common/console.c
new file mode 100644 (file)
index 0000000..f99dfcc
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * (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
+ */
+
+#include <common.h>
+#include <stdarg.h>
+#include <malloc.h>
+#include <console.h>
+#include <syscall.h>
+
+void **syscall_tbl;
+
+#ifdef CFG_CONSOLE_IS_IN_ENV
+/*
+ * if overwrite_console returns 1, the stdin, stderr and stdout
+ * are switched to the serial port, else the settings in the
+ * environment are used
+ */
+#ifdef CFG_CONSOLE_OVERWRITE_ROUTINE
+extern int overwrite_console (void);
+#else
+int overwrite_console (void)
+{
+       return (0);
+}
+#endif /* CFG_CONSOLE_OVERWRITE_ROUTINE */
+
+#endif /* CFG_CONSOLE_IS_IN_ENV */
+
+static int console_setfile (int file, device_t * dev)
+{
+       int error = 0;
+
+       if (dev == NULL)
+               return -1;
+
+       switch (file) {
+       case stdin:
+       case stdout:
+       case stderr:
+               /* Start new device */
+               if (dev->start) {
+                       error = dev->start ();
+                       /* If it's not started dont use it */
+                       if (error < 0)
+                               break;
+               }
+
+               /* Assign the new device (leaving the existing one started) */
+               stdio_devices[file] = dev;
+
+               /*
+                * Update monitor functions
+                * (to use the console stuff by other applications)
+                */
+               switch (file) {
+               case stdin:
+                       syscall_tbl[SYSCALL_GETC] = dev->getc;
+                       syscall_tbl[SYSCALL_TSTC] = dev->tstc;
+                       break;
+               case stdout:
+                       syscall_tbl[SYSCALL_PUTC] = dev->putc;
+                       syscall_tbl[SYSCALL_PUTS] = dev->puts;
+                       syscall_tbl[SYSCALL_PRINTF] = printf;
+                       break;
+               }
+               break;
+
+       default:                /* Invalid file ID */
+               error = -1;
+       }
+       return error;
+}
+
+/** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
+
+void serial_printf (const char *fmt, ...)
+{
+       va_list args;
+       uint i;
+       char printbuffer[CFG_PBSIZE];
+
+       va_start (args, fmt);
+
+       /* For this to work, printbuffer must be larger than
+        * anything we ever want to print.
+        */
+       i = vsprintf (printbuffer, fmt, args);
+       va_end (args);
+
+       serial_puts (printbuffer);
+}
+
+int fgetc (int file)
+{
+       if (file < MAX_FILES)
+               return stdio_devices[file]->getc ();
+
+       return -1;
+}
+
+int ftstc (int file)
+{
+       if (file < MAX_FILES)
+               return stdio_devices[file]->tstc ();
+
+       return -1;
+}
+
+void fputc (int file, const char c)
+{
+       if (file < MAX_FILES)
+               stdio_devices[file]->putc (c);
+}
+
+void fputs (int file, const char *s)
+{
+       if (file < MAX_FILES)
+               stdio_devices[file]->puts (s);
+}
+
+void fprintf (int file, const char *fmt, ...)
+{
+       va_list args;
+       uint i;
+       char printbuffer[CFG_PBSIZE];
+
+       va_start (args, fmt);
+
+       /* For this to work, printbuffer must be larger than
+        * anything we ever want to print.
+        */
+       i = vsprintf (printbuffer, fmt, args);
+       va_end (args);
+
+       /* Send to desired file */
+       fputs (file, printbuffer);
+}
+
+/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
+
+int getc (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       if (gd->flags & GD_FLG_DEVINIT) {
+               /* Get from the standard input */
+               return fgetc (stdin);
+       }
+
+       /* Send directly to the handler */
+       return serial_getc ();
+}
+
+int tstc (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       if (gd->flags & GD_FLG_DEVINIT) {
+               /* Test the standard input */
+               return ftstc (stdin);
+       }
+
+       /* Send directly to the handler */
+       return serial_tstc ();
+}
+
+void putc (const char c)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       if (gd->flags & GD_FLG_DEVINIT) {
+               /* Send to the standard output */
+               fputc (stdout, c);
+       } else {
+               /* Send directly to the handler */
+               serial_putc (c);
+       }
+}
+
+void puts (const char *s)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       if (gd->flags & GD_FLG_DEVINIT) {
+               /* Send to the standard output */
+               fputs (stdout, s);
+       } else {
+               /* Send directly to the handler */
+               serial_puts (s);
+       }
+}
+
+void printf (const char *fmt, ...)
+{
+       va_list args;
+       uint i;
+       char printbuffer[CFG_PBSIZE];
+
+       va_start (args, fmt);
+
+       /* For this to work, printbuffer must be larger than
+        * anything we ever want to print.
+        */
+       i = vsprintf (printbuffer, fmt, args);
+       va_end (args);
+
+       /* Print the string */
+       puts (printbuffer);
+}
+
+/* test if ctrl-c was pressed */
+static int ctrlc_disabled = 0; /* see disable_ctrl() */
+static int ctrlc_was_pressed = 0;
+int ctrlc (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       if (!ctrlc_disabled && gd->have_console) {
+               if (tstc ()) {
+                       switch (getc ()) {
+                       case 0x03:              /* ^C - Control C */
+                               ctrlc_was_pressed = 1;
+                               return 1;
+                       default:
+                               break;
+                       }
+               }
+       }
+       return 0;
+}
+
+/* pass 1 to disable ctrlc() checking, 0 to enable.
+ * returns previous state
+ */
+int disable_ctrlc (int disable)
+{
+       int prev = ctrlc_disabled;      /* save previous state */
+
+       ctrlc_disabled = disable;
+       return prev;
+}
+
+int had_ctrlc (void)
+{
+       return ctrlc_was_pressed;
+}
+
+void clear_ctrlc (void)
+{
+       ctrlc_was_pressed = 0;
+}
+
+#ifdef CONFIG_MODEM_SUPPORT_DEBUG
+char   screen[1024];
+char *cursor = screen;
+int once = 0;
+inline void dbg(const char *fmt, ...)
+{
+       va_list args;
+       uint    i;
+       char    printbuffer[CFG_PBSIZE];
+
+       if (!once) {
+               memset(screen, 0, sizeof(screen));
+               once++;
+       }
+
+       va_start(args, fmt);
+
+       /* For this to work, printbuffer must be larger than
+        * anything we ever want to print.
+        */
+       i = vsprintf(printbuffer, fmt, args);
+       va_end(args);
+
+       if ((screen + sizeof(screen) - 1 - cursor) < strlen(printbuffer)+1) {
+               memset(screen, 0, sizeof(screen));
+               cursor = screen;
+       }
+       sprintf(cursor, printbuffer);
+       cursor += strlen(printbuffer);
+
+}
+#else
+inline void dbg(const char *fmt, ...)
+{
+}
+#endif
+
+/** U-Boot INIT FUNCTIONS *************************************************/
+
+int console_assign (int file, char *devname)
+{
+       int flag, i;
+
+       /* Check for valid file */
+       switch (file) {
+       case stdin:
+               flag = DEV_FLAGS_INPUT;
+               break;
+       case stdout:
+       case stderr:
+               flag = DEV_FLAGS_OUTPUT;
+               break;
+       default:
+               return -1;
+       }
+
+       /* Check for valid device name */
+
+       for (i = 1; i <= ListNumItems (devlist); i++) {
+               device_t *dev = ListGetPtrToItem (devlist, i);
+
+               if (strcmp (devname, dev->name) == 0) {
+                       if (dev->flags & flag)
+                               return console_setfile (file, dev);
+
+                       return -1;
+               }
+       }
+
+       return -1;
+}
+
+/* Called before relocation - use serial functions */
+int console_init_f (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       gd->have_console = 1;
+       return (0);
+}
+
+#ifdef CFG_CONSOLE_IS_IN_ENV
+/* search a device */
+device_t *search_device (int flags, char *name)
+{
+       int i, items;
+       device_t *dev = NULL;
+
+       items = ListNumItems (devlist);
+       if (name == NULL)
+               return dev;
+
+       for (i = 1; i <= items; i++) {
+               dev = ListGetPtrToItem (devlist, i);
+               if ((dev->flags & flags) && (strcmp (name, dev->name) == 0)) {
+                       break;
+               }
+       }
+       return dev;
+}
+#endif /* CFG_CONSOLE_IS_IN_ENV */
+
+#ifdef CFG_CONSOLE_IS_IN_ENV
+/* Called after the relocation - use desired console functions */
+int console_init_r (void)
+{
+       char *stdinname, *stdoutname, *stderrname;
+       device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
+
+       /* set default handlers at first */
+       syscall_tbl[SYSCALL_GETC] = serial_getc;
+       syscall_tbl[SYSCALL_TSTC] = serial_tstc;
+       syscall_tbl[SYSCALL_PUTC] = serial_putc;
+       syscall_tbl[SYSCALL_PUTS] = serial_puts;
+       syscall_tbl[SYSCALL_PRINTF] = serial_printf;
+
+       /* stdin stdout and stderr are in environment */
+       /* scan for it */
+       stdinname  = getenv ("stdin");
+       stdoutname = getenv ("stdout");
+       stderrname = getenv ("stderr");
+
+       if (overwrite_console () == 0) { /* if not overwritten by config switch */
+               inputdev  = search_device (DEV_FLAGS_INPUT,  stdinname);
+               outputdev = search_device (DEV_FLAGS_OUTPUT, stdoutname);
+               errdev    = search_device (DEV_FLAGS_OUTPUT, stderrname);
+       }
+       /* if the devices are overwritten or not found, use default device */
+       if (inputdev == NULL) {
+               inputdev  = search_device (DEV_FLAGS_INPUT,  "serial");
+       }
+       if (outputdev == NULL) {
+               outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");
+       }
+       if (errdev == NULL) {
+               errdev    = search_device (DEV_FLAGS_OUTPUT, "serial");
+       }
+       /* Initializes output console first */
+       if (outputdev != NULL) {
+               console_setfile (stdout, outputdev);
+       }
+       if (errdev != NULL) {
+               console_setfile (stderr, errdev);
+       }
+       if (inputdev != NULL) {
+               console_setfile (stdin, inputdev);
+       }
+
+#ifndef CFG_CONSOLE_INFO_QUIET
+       /* Print information */
+       printf ("In:    ");
+       if (stdio_devices[stdin] == NULL) {
+               printf ("No input devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stdin]->name);
+       }
+
+       printf ("Out:   ");
+       if (stdio_devices[stdout] == NULL) {
+               printf ("No output devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stdout]->name);
+       }
+
+       printf ("Err:   ");
+       if (stdio_devices[stderr] == NULL) {
+               printf ("No error devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stderr]->name);
+       }
+#endif /* CFG_CONSOLE_INFO_QUIET */
+
+#ifdef CFG_CONSOLE_ENV_OVERWRITE
+       /* set the environment variables (will overwrite previous env settings) */
+       for (i = 0; i < 3; i++) {
+               setenv (stdio_names[i], stdio_devices[i]->name);
+       }
+#endif /*  CFG_CONSOLE_ENV_OVERWRITE */
+
+#if 0
+       /* If nothing usable installed, use only the initial console */
+       if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
+               return (0);
+#endif
+       return (0);
+}
+
+#else /* CFG_CONSOLE_IS_IN_ENV */
+
+/* Called after the relocation - use desired console functions */
+int console_init_r (void)
+{
+       device_t *inputdev = NULL, *outputdev = NULL;
+       int i, items = ListNumItems (devlist);
+
+       /* Scan devices looking for input and output devices */
+       for (i = 1;
+            (i <= items) && ((inputdev == NULL) || (outputdev == NULL));
+            i++
+           ) {
+               device_t *dev = ListGetPtrToItem (devlist, i);
+
+               if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
+                       inputdev = dev;
+               }
+               if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
+                       outputdev = dev;
+               }
+       }
+
+       /* Initializes output console first */
+       if (outputdev != NULL) {
+               console_setfile (stdout, outputdev);
+               console_setfile (stderr, outputdev);
+       }
+
+       /* Initializes input console */
+       if (inputdev != NULL) {
+               console_setfile (stdin, inputdev);
+       }
+
+#ifndef CFG_CONSOLE_INFO_QUIET
+       /* Print informations */
+       printf ("In:    ");
+       if (stdio_devices[stdin] == NULL) {
+               printf ("No input devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stdin]->name);
+       }
+
+       printf ("Out:   ");
+       if (stdio_devices[stdout] == NULL) {
+               printf ("No output devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stdout]->name);
+       }
+
+       printf ("Err:   ");
+       if (stdio_devices[stderr] == NULL) {
+               printf ("No error devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stderr]->name);
+       }
+#endif /* CFG_CONSOLE_INFO_QUIET */
+
+       /* Setting environment variables */
+       for (i = 0; i < 3; i++) {
+               setenv (stdio_names[i], stdio_devices[i]->name);
+       }
+
+#if 0
+       /* If nothing usable installed, use only the initial console */
+       if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
+               return (0);
+#endif
+
+       return (0);
+}
+
+#endif /* CFG_CONSOLE_IS_IN_ENV */
diff --git a/cpu/74xx_7xx/start.S b/cpu/74xx_7xx/start.S
new file mode 100644 (file)
index 0000000..fe08f8e
--- /dev/null
@@ -0,0 +1,860 @@
+/*
+ *  Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ *  Copyright (C) 2001  Josh Huber <huber@mclx.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
+ */
+
+/*  U-Boot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ *  The processor starts at 0xfff00100 and the code is executed
+ *  from flash. The code is organized to be at an other address
+ *  in memory, but as long we don't jump around before relocating.
+ *  board_init lies at a quite high address and when the cpu has
+ *  jumped there, everything is ok.
+ */
+#include <config.h>
+#include <74xx_7xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#include <galileo/gt64260R.h>
+
+#ifndef  CONFIG_IDENT_STRING
+#define  CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't want the  MMU yet.
+*/
+#undef MSR_KERNEL
+/* Machine Check and Recoverable Interr. */
+#define MSR_KERNEL ( MSR_ME | MSR_RI )
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r14 to access the GOT
+ */
+       START_GOT
+       GOT_ENTRY(_GOT2_TABLE_)
+       GOT_ENTRY(_FIXUP_TABLE_)
+
+       GOT_ENTRY(_start)
+       GOT_ENTRY(_start_of_vectors)
+       GOT_ENTRY(_end_of_vectors)
+       GOT_ENTRY(transfer_to_handler)
+
+       GOT_ENTRY(_end)
+       GOT_ENTRY(.bss)
+       END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+       .text
+       .long   0x27051956              /* U-Boot Magic Number          */
+       .globl  version_string
+version_string:
+       .ascii  U_BOOT_VERSION
+       .ascii  " (", __DATE__, " - ", __TIME__, ")"
+       .ascii  CONFIG_IDENT_STRING, "\0"
+
+       . = EXC_OFF_SYS_RESET
+       .globl  _start
+_start:
+       li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH */
+       b       boot_cold
+       sync
+
+       . = EXC_OFF_SYS_RESET + 0x10
+
+       .globl  _start_warm
+_start_warm:
+       li      r21, BOOTFLAG_WARM      /* Software reboot              */
+       b       boot_warm
+       sync
+
+       /* the boot code is located below the exception table */
+
+       .globl  _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+       STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception.  "Never" generated on the 860. */
+       STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception.  "Never" generated on the 860. */
+       STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+       STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+       . = 0x600
+Alignment:
+       EXCEPTION_PROLOG
+       mfspr   r4,DAR
+       stw     r4,_DAR(r21)
+       mfspr   r5,DSISR
+       stw     r5,_DSISR(r21)
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r20,MSR_KERNEL
+       rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
+       lwz     r6,GOT(transfer_to_handler)
+       mtlr    r6
+       blrl
+.L_Alignment:
+       .long   AlignmentException - _start + EXC_OFF_SYS_RESET
+       .long   int_return - _start + EXC_OFF_SYS_RESET
+
+/* Program check exception */
+       . = 0x700
+ProgramCheck:
+       EXCEPTION_PROLOG
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r20,MSR_KERNEL
+       rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
+       lwz     r6,GOT(transfer_to_handler)
+       mtlr    r6
+       blrl
+.L_ProgramCheck:
+       .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
+       .long   int_return - _start + EXC_OFF_SYS_RESET
+
+       /* No FPU on MPC8xx.  This exception is not supposed to happen.
+       */
+       STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+       /* I guess we could implement decrementer, and may have
+        * to someday for timekeeping.
+        */
+       STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+       STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+       STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+
+       . = 0xc00
+/*
+ * r0 - SYSCALL number
+ * r3-... arguments
+ */
+SystemCall:
+       addis   r11,r0,0                /* get functions table addr */
+       ori     r11,r11,0               /* Note: this code is patched in trap_init */
+       addis   r12,r0,0                /* get number of functions */
+       ori     r12,r12,0
+
+       cmplw   0, r0, r12
+       bge     1f
+
+       rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
+       add     r11,r11,r0
+       lwz     r11,0(r11)
+
+       li      r12,0xd00-4*3           /* save LR & SRRx */
+       mflr    r0
+       stw     r0,0(r12)
+       mfspr   r0,SRR0
+       stw     r0,4(r12)
+       mfspr   r0,SRR1
+       stw     r0,8(r12)
+
+       li      r12,0xc00+_back-SystemCall
+       mtlr    r12
+       mtspr   SRR0,r11
+
+1:     SYNC
+       rfi
+
+_back:
+
+       mfmsr   r11                     /* Disable interrupts */
+       li      r12,0
+       ori     r12,r12,MSR_EE
+       andc    r11,r11,r12
+       SYNC                            /* Some chip revs need this... */
+       mtmsr   r11
+       SYNC
+
+       li      r12,0xd00-4*3           /* restore regs */
+       lwz     r11,0(r12)
+       mtlr    r11
+       lwz     r11,4(r12)
+       mtspr   SRR0,r11
+       lwz     r11,8(r12)
+       mtspr   SRR1,r11
+
+       SYNC
+       rfi
+
+       STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+       STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+       STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+        /*
+         * On the MPC8xx, this is a software emulation interrupt. It
+         * occurs for all unimplemented and illegal instructions.
+        */
+       STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+
+       STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+       STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+       STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+       STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+       STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+       STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+       STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+       STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+       STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+       STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+       STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+       STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+       STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
+       STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+       STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+       .globl  _end_of_vectors
+_end_of_vectors:
+
+       . = 0x2000
+
+boot_cold:
+boot_warm:
+       /* disable everything */
+       li      r0, 0
+       mtspr   HID0, r0
+       sync
+       mtmsr   0
+       bl      invalidate_bats
+       sync
+
+#ifdef CFG_L2
+       /* init the L2 cache */
+       addis   r3, r0, L2_INIT@h
+       ori     r3, r3, L2_INIT@l
+       sync
+       mtspr   l2cr, r3
+#endif
+#if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
+       .long   0x7e00066c
+               /*
+                 * dssall instruction, gas doesn't have it yet
+                 * ...for altivec, data stream stop all this probably
+                 * isn't needed unless we warm (software) reboot U-Boot
+                */
+#endif
+
+#ifdef CFG_L2
+       /* invalidate the L2 cache */
+       bl      l2cache_invalidate
+       sync
+#endif
+#ifdef CFG_BOARD_ASM_INIT
+       /* do early init */
+       bl      board_asm_init
+#endif
+
+       /*
+        * Calculate absolute address in FLASH and jump there
+        *------------------------------------------------------*/
+       lis     r3, CFG_MONITOR_BASE@h
+       ori     r3, r3, CFG_MONITOR_BASE@l
+       addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+       mtlr    r3
+       blr
+
+in_flash:
+       /* let the C-code set up the rest                       */
+       /*                                                      */
+       /* Be careful to keep code relocatable !                */
+       /*------------------------------------------------------*/
+
+       /* perform low-level init */
+       /* sdram init, galileo init, etc */
+       /* r3:  NHR bit from HID0 */
+
+       /* setup the bats */
+       bl      setup_bats
+       sync
+
+       /*
+        * Cache must be enabled here for stack-in-cache trick.
+        * This means we need to enable the BATS.
+        * This means:
+         *   1) for the EVB, original gt regs need to be mapped
+        *   2) need to have an IBAT for the 0xf region,
+        *      we are running there!
+         * Cache should be turned on after BATs, since by default
+         * everything is write-through.
+         * The init-mem BAT can be reused after reloc. The old
+         * gt-regs BAT can be reused after board_init_f calls
+         * board_pre_init (EVB only).
+         */
+#if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC)
+       /* enable address translation */
+       bl      enable_addr_trans
+       sync
+
+       /* enable and invalidate the data cache */
+       bl      l1dcache_enable
+       sync
+#endif
+#ifdef CFG_INIT_RAM_LOCK
+       bl      lock_ram_in_cache
+       sync
+#endif
+
+       /* set up the stack pointer in our newly created
+        * cache-ram (r1) */
+       lis     r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
+       ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
+
+       li      r0, 0           /* Make room for stack frame header and */
+       stwu    r0, -4(r1)      /* clear final stack frame so that      */
+       stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
+
+       GET_GOT                 /* initialize GOT access        */
+
+       /* run low-level CPU init code     (from Flash) */
+       bl      cpu_init_f
+       sync
+
+       mr      r3, r21
+
+       /* r3: BOOTFLAG */
+       /* run 1st part of board init code (from Flash)   */
+       bl      board_init_f
+       sync
+
+       /* NOTREACHED */
+
+       .globl  invalidate_bats
+invalidate_bats:
+       /* invalidate BATs */
+       mtspr   IBAT0U, r0
+       mtspr   IBAT1U, r0
+       mtspr   IBAT2U, r0
+       mtspr   IBAT3U, r0
+       isync
+       mtspr   DBAT0U, r0
+       mtspr   DBAT1U, r0
+       mtspr   DBAT2U, r0
+       mtspr   DBAT3U, r0
+       isync
+       sync
+       blr
+
+       /* setup_bats - set them up to some initial state */
+       .globl  setup_bats
+setup_bats:
+       addis   r0, r0, 0x0000
+
+       /* IBAT 0 */
+       addis   r4, r0, CFG_IBAT0L@h
+       ori     r4, r4, CFG_IBAT0L@l
+       addis   r3, r0, CFG_IBAT0U@h
+       ori     r3, r3, CFG_IBAT0U@l
+       mtspr   IBAT0L, r4
+       mtspr   IBAT0U, r3
+       isync
+
+       /* DBAT 0 */
+       addis   r4, r0, CFG_DBAT0L@h
+       ori     r4, r4, CFG_DBAT0L@l
+       addis   r3, r0, CFG_DBAT0U@h
+       ori     r3, r3, CFG_DBAT0U@l
+       mtspr   DBAT0L, r4
+       mtspr   DBAT0U, r3
+       isync
+
+       /* IBAT 1 */
+       addis   r4, r0, CFG_IBAT1L@h
+       ori     r4, r4, CFG_IBAT1L@l
+       addis   r3, r0, CFG_IBAT1U@h
+       ori     r3, r3, CFG_IBAT1U@l
+       mtspr   IBAT1L, r4
+       mtspr   IBAT1U, r3
+       isync
+
+       /* DBAT 1 */
+       addis   r4, r0, CFG_DBAT1L@h
+       ori     r4, r4, CFG_DBAT1L@l
+       addis   r3, r0, CFG_DBAT1U@h
+       ori     r3, r3, CFG_DBAT1U@l
+       mtspr   DBAT1L, r4
+       mtspr   DBAT1U, r3
+       isync
+
+       /* IBAT 2 */
+       addis   r4, r0, CFG_IBAT2L@h
+       ori     r4, r4, CFG_IBAT2L@l
+       addis   r3, r0, CFG_IBAT2U@h
+       ori     r3, r3, CFG_IBAT2U@l
+       mtspr   IBAT2L, r4
+       mtspr   IBAT2U, r3
+       isync
+
+       /* DBAT 2 */
+       addis   r4, r0, CFG_DBAT2L@h
+       ori     r4, r4, CFG_DBAT2L@l
+       addis   r3, r0, CFG_DBAT2U@h
+       ori     r3, r3, CFG_DBAT2U@l
+       mtspr   DBAT2L, r4
+       mtspr   DBAT2U, r3
+       isync
+
+       /* IBAT 3 */
+       addis   r4, r0, CFG_IBAT3L@h
+       ori     r4, r4, CFG_IBAT3L@l
+       addis   r3, r0, CFG_IBAT3U@h
+       ori     r3, r3, CFG_IBAT3U@l
+       mtspr   IBAT3L, r4
+       mtspr   IBAT3U, r3
+       isync
+
+       /* DBAT 3 */
+       addis   r4, r0, CFG_DBAT3L@h
+       ori     r4, r4, CFG_DBAT3L@l
+       addis   r3, r0, CFG_DBAT3U@h
+       ori     r3, r3, CFG_DBAT3U@l
+       mtspr   DBAT3L, r4
+       mtspr   DBAT3U, r3
+       isync
+
+       /* bats are done, now invalidate the TLBs */
+
+       addis   r3, 0, 0x0000
+       addis   r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
+
+       isync
+
+tlblp:
+       tlbie   r3
+       sync
+       addi    r3, r3, 0x1000
+       cmp     0, 0, r3, r5
+       blt tlblp
+
+       blr
+
+       .globl enable_addr_trans
+enable_addr_trans:
+       /* enable address translation */
+       mfmsr   r5
+       ori     r5, r5, (MSR_IR | MSR_DR)
+       mtmsr   r5
+       isync
+       blr
+
+       .globl disable_addr_trans
+disable_addr_trans:
+       /* disable address translation */
+       mflr    r4
+       mfmsr   r3
+       andi.   r0, r3, (MSR_IR | MSR_DR)
+       beqlr
+       andc    r3, r3, r0
+       mtspr   SRR0, r4
+       mtspr   SRR1, r3
+       rfi
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+       .globl  transfer_to_handler
+transfer_to_handler:
+       stw     r22,_NIP(r21)
+       lis     r22,MSR_POW@h
+       andc    r23,r23,r22
+       stw     r23,_MSR(r21)
+       SAVE_GPR(7, r21)
+       SAVE_4GPRS(8, r21)
+       SAVE_8GPRS(12, r21)
+       SAVE_8GPRS(24, r21)
+       mflr    r23
+       andi.   r24,r23,0x3f00          /* get vector offset */
+       stw     r24,TRAP(r21)
+       li      r22,0
+       stw     r22,RESULT(r21)
+       mtspr   SPRG2,r22               /* r1 is now kernel sp */
+       lwz     r24,0(r23)              /* virtual address of handler */
+       lwz     r23,4(r23)              /* where to go when done */
+       mtspr   SRR0,r24
+       mtspr   SRR1,r20
+       mtlr    r23
+       SYNC
+       rfi                             /* jump to handler, enable MMU */
+
+int_return:
+       mfmsr   r28             /* Disable interrupts */
+       li      r4,0
+       ori     r4,r4,MSR_EE
+       andc    r28,r28,r4
+       SYNC                    /* Some chip revs need this... */
+       mtmsr   r28
+       SYNC
+       lwz     r2,_CTR(r1)
+       lwz     r0,_LINK(r1)
+       mtctr   r2
+       mtlr    r0
+       lwz     r2,_XER(r1)
+       lwz     r0,_CCR(r1)
+       mtspr   XER,r2
+       mtcrf   0xFF,r0
+       REST_10GPRS(3, r1)
+       REST_10GPRS(13, r1)
+       REST_8GPRS(23, r1)
+       REST_GPR(31, r1)
+       lwz     r2,_NIP(r1)     /* Restore environment */
+       lwz     r0,_MSR(r1)
+       mtspr   SRR0,r2
+       mtspr   SRR1,r0
+       lwz     r0,GPR0(r1)
+       lwz     r2,GPR2(r1)
+       lwz     r1,GPR1(r1)
+       SYNC
+       rfi
+
+       .globl  dc_read
+dc_read:
+       blr
+
+       .globl get_pvr
+get_pvr:
+       mfspr   r3, PVR
+       blr
+
+/*-----------------------------------------------------------------------*/
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+       .globl  relocate_code
+relocate_code:
+       mr      r1,  r3         /* Set new stack pointer                */
+       mr      r9,  r4         /* Save copy of Global Data pointer     */
+       mr      r10, r5         /* Save copy of Destination Address     */
+
+       mr      r3,  r5                         /* Destination Address  */
+       lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
+       ori     r4, r4, CFG_MONITOR_BASE@l
+       lis     r5, CFG_MONITOR_LEN@h           /* Length in Bytes      */
+       ori     r5, r5, CFG_MONITOR_LEN@l
+       li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
+
+       /*
+        * Fix GOT pointer:
+        *
+        * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
+        *
+        * Offset:
+        */
+       sub     r15, r10, r4
+
+       /* First our own GOT */
+       add     r14, r14, r15
+       /* then the one used by the C code */
+       add     r30, r30, r15
+
+       /*
+        * Now relocate code
+        */
+#ifdef CONFIG_ECC
+       bl      board_relocate_rom
+       sync
+       mr      r3, r10                         /* Destination Address  */
+       lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
+       ori     r4, r4, CFG_MONITOR_BASE@l
+       lis     r5, CFG_MONITOR_LEN@h           /* Length in Bytes      */
+       ori     r5, r5, CFG_MONITOR_LEN@l
+       li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
+#else
+       cmplw   cr1,r3,r4
+       addi    r0,r5,3
+       srwi.   r0,r0,2
+       beq     cr1,4f          /* In place copy is not necessary       */
+       beq     7f              /* Protect against 0 count              */
+       mtctr   r0
+       bge     cr1,2f
+
+       la      r8,-4(r4)
+       la      r7,-4(r3)
+1:     lwzu    r0,4(r8)
+       stwu    r0,4(r7)
+       bdnz    1b
+       b       4f
+
+2:     slwi    r0,r0,2
+       add     r8,r4,r0
+       add     r7,r3,r0
+3:     lwzu    r0,-4(r8)
+       stwu    r0,-4(r7)
+       bdnz    3b
+#endif
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:     cmpwi   r6,0
+       add     r5,r3,r5
+       beq     7f              /* Always flush prefetch queue in any case */
+       subi    r0,r6,1
+       andc    r3,r3,r0
+       mr      r4,r3
+5:     dcbst   0,r4
+       add     r4,r4,r6
+       cmplw   r4,r5
+       blt     5b
+       sync                    /* Wait for all dcbst to complete on bus */
+       mr      r4,r3
+6:     icbi    0,r4
+       add     r4,r4,r6
+       cmplw   r4,r5
+       blt     6b
+7:     sync                    /* Wait for all icbi to complete on bus */
+       isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+       addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+       mtlr    r0
+       blr
+
+in_ram:
+#ifdef CONFIG_ECC
+       bl      board_init_ecc
+#endif
+       /*
+        * Relocation Function, r14 point to got2+0x8000
+        *
+         * Adjust got2 pointers, no need to check for 0, this code
+         * already puts a few entries in the table.
+        */
+       li      r0,__got2_entries@sectoff@l
+       la      r3,GOT(_GOT2_TABLE_)
+       lwz     r11,GOT(_GOT2_TABLE_)
+       mtctr   r0
+       sub     r11,r3,r11
+       addi    r3,r3,-4
+1:     lwzu    r0,4(r3)
+       add     r0,r0,r11
+       stw     r0,0(r3)
+       bdnz    1b
+
+       /*
+         * Now adjust the fixups and the pointers to the fixups
+        * in case we need to move ourselves again.
+        */
+2:     li      r0,__fixup_entries@sectoff@l
+       lwz     r3,GOT(_FIXUP_TABLE_)
+       cmpwi   r0,0
+       mtctr   r0
+       addi    r3,r3,-4
+       beq     4f
+3:     lwzu    r4,4(r3)
+       lwzux   r0,r4,r11
+       add     r0,r0,r11
+       stw     r10,0(r3)
+       stw     r0,0(r4)
+       bdnz    3b
+4:
+/* clear_bss: */
+       /*
+        * Now clear BSS segment
+        */
+       lwz     r3,GOT(.bss)
+       lwz     r4,GOT(_end)
+
+       cmplw   0, r3, r4
+       beq     6f
+
+       li      r0, 0
+5:
+       stw     r0, 0(r3)
+       addi    r3, r3, 4
+       cmplw   0, r3, r4
+       bne     5b
+6:
+       mr      r3, r10         /* Destination Address          */
+       bl      after_reloc
+
+       /* not reached - end relocate_code */
+/*-----------------------------------------------------------------------*/
+
+       /* Problems accessing "end" in C, so do it here */
+       .globl  get_endaddr
+get_endaddr:
+       lwz     r3,GOT(_end)
+       blr
+
+       /*
+        * Copy exception vector code to low memory
+        *
+        * r3: dest_addr
+        * r7: source address, r8: end address, r9: target address
+        */
+       .globl  trap_init
+trap_init:
+       lwz     r7, GOT(_start)
+       lwz     r8, GOT(_end_of_vectors)
+
+       rlwinm  r9, r7, 0, 18, 31       /* _start & 0x3FFF      */
+
+       cmplw   0, r7, r8
+       bgelr                           /* return if r7>=r8 - just in case */
+
+       mflr    r4                      /* save link register           */
+1:
+       lwz     r0, 0(r7)
+       stw     r0, 0(r9)
+       addi    r7, r7, 4
+       addi    r9, r9, 4
+       cmplw   0, r7, r8
+       bne     1b
+
+       /*
+        * relocate `hdlr' and `int_return' entries
+        */
+       li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+       li      r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     2b
+
+       li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+       bl      trap_reloc
+
+       li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+       bl      trap_reloc
+
+       li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+       li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     3b
+
+       li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+       li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     4b
+
+       /* enable execptions from RAM vectors */
+       mfmsr   r7
+       li      r8,MSR_IP
+       andc    r7,r7,r8
+       mtmsr   r7
+
+       mtlr    r4                      /* restore link register        */
+       blr
+
+       /*
+        * Function: relocate entries for one exception vector
+        */
+trap_reloc:
+       lwz     r0, 0(r7)               /* hdlr ...                     */
+       add     r0, r0, r3              /*  ... += dest_addr            */
+       stw     r0, 0(r7)
+
+       lwz     r0, 4(r7)               /* int_return ...               */
+       add     r0, r0, r3              /*  ... += dest_addr            */
+       stw     r0, 4(r7)
+
+       sync
+       isync
+
+       blr
+
+#ifdef CFG_INIT_RAM_LOCK
+lock_ram_in_cache:
+       /* Allocate Initial RAM in data cache.
+        */
+       lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
+       ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
+       li      r2, ((CFG_INIT_RAM_END & ~31) + \
+                    (CFG_INIT_RAM_ADDR & 31) + 31) / 32
+       mtctr   r2
+1:
+       dcbz    r0, r3
+       addi    r3, r3, 32
+       bdnz    1b
+
+       /* Lock the data cache */
+       mfspr   r0, HID0
+       ori     r0, r0, 0x1000
+       sync
+       mtspr   HID0, r0
+       sync
+       blr
+
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+       /* invalidate the INIT_RAM section */
+       lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
+       ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
+       li      r2, ((CFG_INIT_RAM_END & ~31) + \
+                    (CFG_INIT_RAM_ADDR & 31) + 31) / 32
+       mtctr   r2
+1:     icbi    r0, r3
+       addi    r3, r3, 32
+       bdnz    1b
+       sync                    /* Wait for all icbi to complete on bus */
+       isync
+
+       /* Unlock the data cache and invalidate it */
+       mfspr   r0, HID0
+       li      r3,0x1000
+       andc    r0,r0,r3
+       li      r3,0x0400
+       or      r0,r0,r3
+       sync
+       mtspr   HID0, r0
+       sync
+       blr
+#endif
diff --git a/cpu/mpc8260/start.S b/cpu/mpc8260/start.S
new file mode 100644 (file)
index 0000000..10a8988
--- /dev/null
@@ -0,0 +1,1092 @@
+/*
+ *  Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000, 2001,2002 Wolfgang Denk <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
+ */
+
+/*
+ *  U-Boot - Startup Code for MPC8260 PowerPC based Embedded Boards
+ */
+#include <config.h>
+#include <mpc8260.h>
+#include <version.h>
+
+#define CONFIG_8260 1          /* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1      /* avoid reading Linux autoconf.h file  */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef  CONFIG_IDENT_STRING
+#define  CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't want the  MMU yet.
+*/
+#undef MSR_KERNEL
+/* Floating Point enable, Machine Check and Recoverable Interr. */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r14 to access the GOT
+ */
+       START_GOT
+       GOT_ENTRY(_GOT2_TABLE_)
+       GOT_ENTRY(_FIXUP_TABLE_)
+
+       GOT_ENTRY(_start)
+       GOT_ENTRY(_start_of_vectors)
+       GOT_ENTRY(_end_of_vectors)
+       GOT_ENTRY(transfer_to_handler)
+
+       GOT_ENTRY(_end)
+       GOT_ENTRY(.bss)
+#if defined(CONFIG_HYMOD)
+       GOT_ENTRY(environment)
+#endif
+       END_GOT
+
+/*
+ * Version string - must be in data segment because MPC8260 uses the first
+ * 256 bytes for the Hard Reset Configuration Word table (see below).
+ * Similarly, can't have the U-Boot Magic Number as the first thing in
+ * the image - don't know how this will affect the image tools, but I guess
+ * I'll find out soon
+ */
+       .data
+       .globl  version_string
+version_string:
+       .ascii U_BOOT_VERSION
+       .ascii " (", __DATE__, " - ", __TIME__, ")"
+       .ascii CONFIG_IDENT_STRING, "\0"
+
+/*
+ *  Hard Reset Configuration Word (HRCW) table
+ *
+ *  The Hard Reset Configuration Word (HRCW) sets a number of useful things
+ *  such as whether there is an external memory controller, whether the
+ *  PowerPC core is disabled (i.e. only the communications processor is
+ *  active, accessed by another CPU on the bus), whether using external
+ *  arbitration, external bus mode, boot port size, core initial prefix,
+ *  internal space base, boot memory space, etc.
+ *
+ *  These things dictate where the processor begins execution, where the
+ *  boot ROM appears in memory, the memory controller setup when access
+ *  boot ROM, etc. The HRCW is *extremely* important.
+ *
+ *  The HRCW is read from the bus during reset. One CPU on the bus will
+ *  be a hard reset configuration master, any others will be hard reset
+ *  configuration slaves. The master reads eight HRCWs from flash during
+ *  reset - the first it uses for itself, the other 7 it communicates to
+ *  up to 7 configuration slaves by some complicated mechanism, which is
+ *  not really important here.
+ *
+ *  The configuration master performs 32 successive reads starting at address
+ *  0 and incrementing by 8 each read (i.e. on 64 bit boundaries) but only 8
+ *  bits is read, and always from byte lane D[0-7] (so that port size of the
+ *  boot device does not matter). The first four reads form the 32 bit HRCW
+ *  for the master itself. The second four reads form the HRCW for the first
+ *  slave, and so on, up to seven slaves. The 32 bit HRCW is formed by
+ *  concatenating the four bytes, with the first read placed in byte 0 (the
+ *  most significant byte), and so on with the fourth read placed in byte 3
+ *  (the least significant byte).
+ */
+#define _HRCW_TABLE_ENTRY(w)           \
+       .fill   8,1,(((w)>>24)&0xff);   \
+       .fill   8,1,(((w)>>16)&0xff);   \
+       .fill   8,1,(((w)>> 8)&0xff);   \
+       .fill   8,1,(((w)    )&0xff)
+       .text
+       .globl  _hrcw_table
+_hrcw_table:
+       _HRCW_TABLE_ENTRY(CFG_HRCW_MASTER)
+       _HRCW_TABLE_ENTRY(CFG_HRCW_SLAVE1)
+       _HRCW_TABLE_ENTRY(CFG_HRCW_SLAVE2)
+       _HRCW_TABLE_ENTRY(CFG_HRCW_SLAVE3)
+       _HRCW_TABLE_ENTRY(CFG_HRCW_SLAVE4)
+       _HRCW_TABLE_ENTRY(CFG_HRCW_SLAVE5)
+       _HRCW_TABLE_ENTRY(CFG_HRCW_SLAVE6)
+       _HRCW_TABLE_ENTRY(CFG_HRCW_SLAVE7)
+/*
+ *  After configuration, a system reset exception is executed using the
+ *  vector at offset 0x100 relative to the base set by MSR[IP]. If MSR[IP]
+ *  is 0, the base address is 0x00000000. If MSR[IP] is 1, the base address
+ *  is 0xfff00000. In the case of a Power On Reset or Hard Reset, the value
+ *  of MSR[IP] is determined by the CIP field in the HRCW.
+ *
+ *  Other bits in the HRCW set up the Base Address and Port Size in BR0.
+ *  This determines the location of the boot ROM (flash or EPROM) in the
+ *  processor's address space at boot time. As long as the HRCW is set up
+ *  so that we eventually end up executing the code below when the processor
+ *  executes the reset exception, the actual values used should not matter.
+ *
+ *  Once we have got here, the address mask in OR0 is cleared so that the
+ *  bottom 32K of the boot ROM is effectively repeated all throughout the
+ *  processor's address space, after which we can jump to the absolute
+ *  address at which the boot ROM was linked at compile time, and proceed
+ *  to initialise the memory controller without worrying if the rug will be
+ *  pulled out from under us, so to speak (it will be fine as long as we
+ *  configure BR0 with the same boot ROM link address).
+ */
+       . = EXC_OFF_SYS_RESET
+
+       .globl  _start
+_start:
+       li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH*/
+       b       boot_cold
+
+       . = EXC_OFF_SYS_RESET + 0x10
+
+       .globl  _start_warm
+_start_warm:
+       li      r21, BOOTFLAG_WARM      /* Software reboot              */
+       b       boot_warm
+
+boot_cold:
+boot_warm:
+       mfmsr   r5                      /* save msr contents            */
+
+#if defined(CONFIG_COGENT)
+       /* this is what the cogent EPROM does */
+       li      r0, 0
+       mtmsr   r0
+       isync
+       bl      cogent_init_8260
+#endif /* CONFIG_COGENT */
+
+#if defined(CFG_DEFAULT_IMMR)
+       lis     r3, CFG_IMMR@h
+       ori     r3, r3, CFG_IMMR@l
+       lis     r4, CFG_DEFAULT_IMMR@h
+       stw     r3, 0x1A8(r4)
+#endif /* CFG_DEFAULT_IMMR */
+
+       /* Initialise the MPC8260 processor core                        */
+       /*--------------------------------------------------------------*/
+
+       bl      init_8260_core
+
+#ifndef CFG_RAMBOOT
+       /* When booting from ROM (Flash or EPROM), clear the            */
+       /* Address Mask in OR0 so ROM appears everywhere                */
+       /*--------------------------------------------------------------*/
+
+       lis     r3, (CFG_IMMR+IM_REGBASE)@h
+       lwz     r4, IM_OR0@l(r3)
+       li      r5, 0x7fff
+       and     r4, r4, r5
+       stw     r4, IM_OR0@l(r3)
+
+       /* Calculate absolute address in FLASH and jump there           */
+       /*--------------------------------------------------------------*/
+
+       lis     r3, CFG_MONITOR_BASE@h
+       ori     r3, r3, CFG_MONITOR_BASE@l
+       addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+       mtlr    r3
+       blr
+
+in_flash:
+#endif /* CFG_RAMBOOT */
+
+       /* initialize some things that are hard to access from C        */
+       /*--------------------------------------------------------------*/
+
+       lis     r3, CFG_IMMR@h          /* set up stack in internal DPRAM */
+       ori     r1, r3, CFG_INIT_SP_OFFSET
+       li      r0, 0                   /* Make room for stack frame header and */
+       stwu    r0, -4(r1)              /* clear final stack frame so that      */
+       stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
+
+       /* let the C-code set up the rest                               */
+       /*                                                              */
+       /* Be careful to keep code relocatable !                        */
+       /*--------------------------------------------------------------*/
+
+       GET_GOT                 /* initialize GOT access                */
+
+       /* r3: IMMR */
+       bl      cpu_init_f      /* run low-level CPU init code (in Flash)*/
+
+#ifdef DEBUG
+       bl      init_debug      /* set up debugging stuff               */
+#endif
+
+       mr      r3, r21
+       /* r3: BOOTFLAG */
+       bl      board_init_f    /* run 1st part of board init code (in Flash)*/
+
+/*
+ * Vector Table
+ */
+
+       .globl  _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+       STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+       STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+       STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+       STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+       . = 0x600
+Alignment:
+       EXCEPTION_PROLOG
+       mfspr   r4,DAR
+       stw     r4,_DAR(r21)
+       mfspr   r5,DSISR
+       stw     r5,_DSISR(r21)
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r20,MSR_KERNEL
+       rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
+       rlwimi  r20,r23,0,25,25         /* copy IP bit from saved MSR */
+       lwz     r6,GOT(transfer_to_handler)
+       mtlr    r6
+       blrl
+.L_Alignment:
+       .long   AlignmentException - _start + EXC_OFF_SYS_RESET
+       .long   int_return - _start + EXC_OFF_SYS_RESET
+
+/* Program check exception */
+       . = 0x700
+ProgramCheck:
+       EXCEPTION_PROLOG
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r20,MSR_KERNEL
+       rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
+       rlwimi  r20,r23,0,25,25         /* copy IP bit from saved MSR */
+       lwz     r6,GOT(transfer_to_handler)
+       mtlr    r6
+       blrl
+.L_ProgramCheck:
+       .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
+       .long   int_return - _start + EXC_OFF_SYS_RESET
+
+       STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+       /* I guess we could implement decrementer, and may have
+        * to someday for timekeeping.
+        */
+       STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+       STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+       STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+
+       . = 0xc00
+/*
+ * r0 - SYSCALL number
+ * r3-... arguments
+ */
+SystemCall:
+       addis   r11,r0,0                /* get functions table addr */
+       ori     r11,r11,0               /* Note: this code is patched in trap_init */
+       addis   r12,r0,0                /* get number of functions */
+       ori     r12,r12,0
+
+       cmplw   0, r0, r12
+       bge     1f
+
+       rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
+       add     r11,r11,r0
+       lwz     r11,0(r11)
+
+       li      r12,0xd00-4*3           /* save LR & SRRx */
+       mflr    r0
+       stw     r0,0(r12)
+       mfspr   r0,SRR0
+       stw     r0,4(r12)
+       mfspr   r0,SRR1
+       stw     r0,8(r12)
+
+       li      r12,0xc00+_back-SystemCall
+       mtlr    r12
+       mtspr   SRR0,r11
+
+1:     SYNC
+       rfi
+
+_back:
+
+       mfmsr   r11                     /* Disable interrupts */
+       li      r12,0
+       ori     r12,r12,MSR_EE
+       andc    r11,r11,r12
+       SYNC                            /* Some chip revs need this... */
+       mtmsr   r11
+       SYNC
+
+       li      r12,0xd00-4*3           /* restore regs */
+       lwz     r11,0(r12)
+       mtlr    r11
+       lwz     r11,4(r12)
+       mtspr   SRR0,r11
+       lwz     r11,8(r12)
+       mtspr   SRR1,r11
+
+       SYNC
+       rfi
+
+       STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+       STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+       STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+       STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+       STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+       STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+       . = 0x1300
+       /*
+        * This exception occurs when the program counter matches the
+        * Instruction Address Breakpoint Register (IABR).
+        *
+        * I want the cpu to halt if this occurs so I can hunt around
+        * with the debugger and look at things.
+        *
+        * When DEBUG is defined, both machine check enable (in the MSR)
+        * and checkstop reset enable (in the reset mode register) are
+        * turned off and so a checkstop condition will result in the cpu
+        * halting.
+        *
+        * I force the cpu into a checkstop condition by putting an illegal
+        * instruction here (at least this is the theory).
+        *
+        * well - that didnt work, so just do an infinite loop!
+        */
+1:     b       1b
+#else
+       STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+       STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+       STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+       STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+       STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+       STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+       STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+       STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+       STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+       STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+       STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+       STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+       STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+       STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+       STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+       STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+       STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+       STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+       STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+       STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+       STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+       STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+       STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+       STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+       STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+       STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+       STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+       STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+       STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+       .globl  _end_of_vectors
+_end_of_vectors:
+
+       . = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+       .globl  transfer_to_handler
+transfer_to_handler:
+       stw     r22,_NIP(r21)
+       lis     r22,MSR_POW@h
+       andc    r23,r23,r22
+       stw     r23,_MSR(r21)
+       SAVE_GPR(7, r21)
+       SAVE_4GPRS(8, r21)
+       SAVE_8GPRS(12, r21)
+       SAVE_8GPRS(24, r21)
+       mflr    r23
+       andi.   r24,r23,0x3f00          /* get vector offset */
+       stw     r24,TRAP(r21)
+       li      r22,0
+       stw     r22,RESULT(r21)
+       lwz     r24,0(r23)              /* virtual address of handler */
+       lwz     r23,4(r23)              /* where to go when done */
+       mtspr   SRR0,r24
+       mtspr   SRR1,r20
+       mtlr    r23
+       SYNC
+       rfi                             /* jump to handler, enable MMU */
+
+int_return:
+       mfmsr   r28             /* Disable interrupts */
+       li      r4,0
+       ori     r4,r4,MSR_EE
+       andc    r28,r28,r4
+       SYNC                    /* Some chip revs need this... */
+       mtmsr   r28
+       SYNC
+       lwz     r2,_CTR(r1)
+       lwz     r0,_LINK(r1)
+       mtctr   r2
+       mtlr    r0
+       lwz     r2,_XER(r1)
+       lwz     r0,_CCR(r1)
+       mtspr   XER,r2
+       mtcrf   0xFF,r0
+       REST_10GPRS(3, r1)
+       REST_10GPRS(13, r1)
+       REST_8GPRS(23, r1)
+       REST_GPR(31, r1)
+       lwz     r2,_NIP(r1)     /* Restore environment */
+       lwz     r0,_MSR(r1)
+       mtspr   SRR0,r2
+       mtspr   SRR1,r0
+       lwz     r0,GPR0(r1)
+       lwz     r2,GPR2(r1)
+       lwz     r1,GPR1(r1)
+       SYNC
+       rfi
+
+#if defined(CONFIG_COGENT)
+
+/*
+ * This code initialises the MPC8260 processor core
+ * (conforms to PowerPC 603e spec)
+ */
+
+       .globl  cogent_init_8260
+cogent_init_8260:
+
+       /* Taken from page 14 of CMA282 manual                          */
+       /*--------------------------------------------------------------*/
+
+       lis     r4, (CFG_IMMR+IM_REGBASE)@h
+       lis     r3, CFG_IMMR@h
+       stw     r3, IM_IMMR@l(r4)
+       lwz     r3, IM_IMMR@l(r4)
+       stw     r3, 0(r0)
+       lis     r3, CFG_SYPCR@h
+       ori     r3, r3, CFG_SYPCR@l
+       stw     r3, IM_SYPCR@l(r4)
+       lwz     r3, IM_SYPCR@l(r4)
+       stw     r3, 4(r0)
+       lis     r3, CFG_SCCR@h
+       ori     r3, r3, CFG_SCCR@l
+       stw     r3, IM_SCCR@l(r4)
+       lwz     r3, IM_SCCR@l(r4)
+       stw     r3, 8(r0)
+
+       /* the rest of this was disassembled from the                   */
+       /* EPROM code that came with my CMA282 CPU module               */
+       /*--------------------------------------------------------------*/
+
+       lis     r1, 0x1234
+       ori     r1, r1, 0x5678
+       stw     r1, 0x20(r0)
+       lwz     r1, 0x20(r0)
+       stw     r1, 0x24(r0)
+       lwz     r1, 0x24(r0)
+       lis     r3, 0x0e80
+       ori     r3, r3, 0
+       stw     r1, 4(r3)
+       lwz     r1, 4(r3)
+
+       /* Done!                                                        */
+       /*--------------------------------------------------------------*/
+
+       blr
+
+#endif /* CONFIG_COGENT */
+
+/*
+ * This code initialises the MPC8260 processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+
+       .globl  init_8260_core
+init_8260_core:
+
+       /* Initialize machine status; enable machine check interrupt    */
+       /*--------------------------------------------------------------*/
+
+       li      r3, MSR_KERNEL          /* Set ME and RI flags */
+       rlwimi  r3, r5, 0, 25, 25       /* preserve IP bit set by HRCW */
+#ifdef DEBUG
+       rlwimi  r3, r5, 0, 21, 22       /* debugger might set SE & BE bits */
+#endif
+       SYNC                            /* Some chip revs need this... */
+       mtmsr   r3
+       SYNC
+       mtspr   SRR1, r3                /* Make SRR1 match MSR */
+
+       /* Initialise the SYPCR early, and reset the watchdog (if req)  */
+       /*--------------------------------------------------------------*/
+
+       lis     r3, (CFG_IMMR+IM_REGBASE)@h
+#if !defined(CONFIG_COGENT)
+       lis     r4, CFG_SYPCR@h
+       ori     r4, r4, CFG_SYPCR@l
+       stw     r4, IM_SYPCR@l(r3)
+#endif /* !CONFIG_COGENT */
+#if defined(CONFIG_WATCHDOG)
+       li      r4, 21868               /* = 0x556c */
+       sth     r4, IM_SWSR@l(r3)
+       li      r4, -21959              /* = 0xaa39 */
+       sth     r4, IM_SWSR@l(r3)
+#endif /* CONFIG_WATCHDOG */
+
+       /* Initialize the Hardware Implementation-dependent Registers   */
+       /* HID0 also contains cache control                             */
+       /*--------------------------------------------------------------*/
+
+       lis     r3, CFG_HID0_INIT@h
+       ori     r3, r3, CFG_HID0_INIT@l
+       SYNC
+       mtspr   HID0, r3
+
+       lis     r3, CFG_HID0_FINAL@h
+       ori     r3, r3, CFG_HID0_FINAL@l
+       SYNC
+       mtspr   HID0, r3
+
+       lis     r3, CFG_HID2@h
+       ori     r3, r3, CFG_HID2@l
+       mtspr   HID2, r3
+
+       /* clear all BAT's                                              */
+       /*--------------------------------------------------------------*/
+
+       li      r0, 0
+       mtspr   DBAT0U, r0
+       mtspr   DBAT0L, r0
+       mtspr   DBAT1U, r0
+       mtspr   DBAT1L, r0
+       mtspr   DBAT2U, r0
+       mtspr   DBAT2L, r0
+       mtspr   DBAT3U, r0
+       mtspr   DBAT3L, r0
+       mtspr   IBAT0U, r0
+       mtspr   IBAT0L, r0
+       mtspr   IBAT1U, r0
+       mtspr   IBAT1L, r0
+       mtspr   IBAT2U, r0
+       mtspr   IBAT2L, r0
+       mtspr   IBAT3U, r0
+       mtspr   IBAT3L, r0
+       SYNC
+
+       /* invalidate all tlb's                                         */
+       /*                                                              */
+       /* From the 603e User Manual: "The 603e provides the ability to */
+       /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie)     */
+       /* instruction invalidates the TLB entry indexed by the EA, and */
+       /* operates on both the instruction and data TLBs simultaneously*/
+       /* invalidating four TLB entries (both sets in each TLB). The   */
+       /* index corresponds to bits 15-19 of the EA. To invalidate all */
+       /* entries within both TLBs, 32 tlbie instructions should be    */
+       /* issued, incrementing this field by one each time."           */
+       /*                                                              */
+       /* "Note that the tlbia instruction is not implemented on the   */
+       /* 603e."                                                       */
+       /*                                                              */
+       /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000  */
+       /* incrementing by 0x1000 each time. The code below is sort of  */
+       /* based on code in "flush_tlbs" from arch/ppc/kernel/head.S    */
+       /*                                                              */
+       /*--------------------------------------------------------------*/
+
+       li      r3, 32
+       mtctr   r3
+       li      r3, 0
+1:     tlbie   r3
+       addi    r3, r3, 0x1000
+       bdnz    1b
+       SYNC
+
+       /* Done!                                                        */
+       /*--------------------------------------------------------------*/
+
+       blr
+
+#ifdef DEBUG
+
+/*
+ * initialise things related to debugging.
+ *
+ * must be called after the global offset table (GOT) is initialised
+ * (GET_GOT) and after cpu_init_f() has executed.
+ */
+
+       .globl  init_debug
+init_debug:
+
+       lis     r3, (CFG_IMMR+IM_REGBASE)@h
+
+       /* Quick and dirty hack to enable the RAM and copy the          */
+       /* vectors so that we can take exceptions.                      */
+       /*--------------------------------------------------------------*/
+       /* write Memory Refresh Prescaler */
+       li      r4, CFG_MPTPR
+       sth     r4, IM_MPTPR@l(r3)
+       /* write 60x Refresh Timer */
+       li      r4, CFG_PSRT
+       stb     r4, IM_PSRT@l(r3)
+       /* init the 60x SDRAM Mode Register */
+       lis     r4, (CFG_PSDMR|PSDMR_OP_NORM)@h
+       ori     r4, r4, (CFG_PSDMR|PSDMR_OP_NORM)@l
+       stw     r4, IM_PSDMR@l(r3)
+       /* write Precharge All Banks command */
+       lis     r4, (CFG_PSDMR|PSDMR_OP_PREA)@h
+       ori     r4, r4, (CFG_PSDMR|PSDMR_OP_PREA)@l
+       stw     r4, IM_PSDMR@l(r3)
+       stb     r0, 0(0)
+       /* write eight CBR Refresh commands */
+       lis     r4, (CFG_PSDMR|PSDMR_OP_CBRR)@h
+       ori     r4, r4, (CFG_PSDMR|PSDMR_OP_CBRR)@l
+       stw     r4, IM_PSDMR@l(r3)
+       stb     r0, 0(0)
+       stb     r0, 0(0)
+       stb     r0, 0(0)
+       stb     r0, 0(0)
+       stb     r0, 0(0)
+       stb     r0, 0(0)
+       stb     r0, 0(0)
+       stb     r0, 0(0)
+       /* write Mode Register Write command */
+       lis     r4, (CFG_PSDMR|PSDMR_OP_MRW)@h
+       ori     r4, r4, (CFG_PSDMR|PSDMR_OP_MRW)@l
+       stw     r4, IM_PSDMR@l(r3)
+       stb     r0, 0(0)
+       /* write Normal Operation command and enable Refresh */
+       lis     r4, (CFG_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@h
+       ori     r4, r4, (CFG_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@l
+       stw     r4, IM_PSDMR@l(r3)
+       stb     r0, 0(0)
+       /* RAM should now be operational */
+
+#define VEC_WRD_CNT    ((_end_of_vectors - _start + EXC_OFF_SYS_RESET) / 4)
+
+       lwz     r3, GOT(_end_of_vectors)
+       rlwinm  r4, r3, 0, 18, 31       /* _end_of_vectors & 0x3FFF     */
+       lis     r5, VEC_WRD_CNT@h
+       ori     r5, r5, VEC_WRD_CNT@l
+       mtctr   r5
+1:
+       lwzu    r5, -4(r3)
+       stwu    r5, -4(r4)
+       bdnz    1b
+
+       /* Load the Instruction Address Breakpoint Register (IABR).     */
+       /*                                                              */
+       /* The address to load is stored in the first word of dual port */
+       /* ram and should be preserved while the power is on, so you    */
+       /* can plug addresses into that location then reset the cpu and */
+       /* this code will load that address into the IABR after the     */
+       /* reset.                                                       */
+       /*                                                              */
+       /* When the program counter matches the contents of the IABR,   */
+       /* an exception is generated (before the instruction at that    */
+       /* location completes). The vector for this exception is 0x1300 */
+       /*--------------------------------------------------------------*/
+       lis     r3, CFG_IMMR@h
+       lwz     r3, 0(r3)
+       mtspr   IABR, r3
+
+       /* Set the entire dual port RAM (where the initial stack        */
+       /* resides) to a known value - makes it easier to see where     */
+       /* the stack has been written                                   */
+       /*--------------------------------------------------------------*/
+       lis     r3, (CFG_IMMR + CFG_INIT_SP_OFFSET)@h
+       ori     r3, r3, (CFG_IMMR + CFG_INIT_SP_OFFSET)@l
+       li      r4, ((CFG_INIT_SP_OFFSET - 4) / 4)
+       mtctr   r4
+       lis     r4, 0xdeadbeaf@h
+       ori     r4, r4, 0xdeadbeaf@l
+1:
+       stwu    r4, -4(r3)
+       bdnz    1b
+
+       /* Done!                                                        */
+       /*--------------------------------------------------------------*/
+
+       blr
+#endif
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+       .globl  icache_enable
+icache_enable:
+       mfspr   r3, HID0
+       ori     r3, r3, HID0_ICE
+       lis     r4, 0
+       ori     r4, r4, HID0_ILOCK
+       andc    r3, r3, r4
+       ori     r4, r3, HID0_ICFI
+       isync
+       mtspr   HID0, r4        /* sets enable and invalidate, clears lock */
+       isync
+       mtspr   HID0, r3        /* clears invalidate */
+       blr
+
+       .globl  icache_disable
+icache_disable:
+       mfspr   r3, HID0
+       lis     r4, 0
+       ori     r4, r4, HID0_ICE|HID0_ILOCK
+       andc    r3, r3, r4
+       ori     r4, r3, HID0_ICFI
+       isync
+       mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
+       isync
+       mtspr   HID0, r3        /* clears invalidate */
+       blr
+
+       .globl  icache_status
+icache_status:
+       mfspr   r3, HID0
+       rlwinm  r3, r3, HID0_ICE_BITPOS + 1, 31, 31
+       blr
+
+       .globl  dcache_enable
+dcache_enable:
+       mfspr   r3, HID0
+       ori     r3, r3, HID0_DCE
+       lis     r4, 0
+       ori     r4, r4, HID0_DLOCK
+       andc    r3, r3, r4
+       ori     r4, r3, HID0_DCI
+       sync
+       mtspr   HID0, r4        /* sets enable and invalidate, clears lock */
+       sync
+       mtspr   HID0, r3        /* clears invalidate */
+       blr
+
+       .globl  dcache_disable
+dcache_disable:
+       mfspr   r3, HID0
+       lis     r4, 0
+       ori     r4, r4, HID0_DCE|HID0_DLOCK
+       andc    r3, r3, r4
+       ori     r4, r3, HID0_DCI
+       sync
+       mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
+       sync
+       mtspr   HID0, r3        /* clears invalidate */
+       blr
+
+       .globl  dcache_status
+dcache_status:
+       mfspr   r3, HID0
+       rlwinm  r3, r3, HID0_DCE_BITPOS + 1, 31, 31
+       blr
+
+       .globl get_pvr
+get_pvr:
+       mfspr   r3, PVR
+       blr
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+       .globl  relocate_code
+relocate_code:
+       mr      r1,  r3         /* Set new stack pointer                */
+       mr      r9,  r4         /* Save copy of Global Data pointer     */
+       mr      r10, r5         /* Save copy of Destination Address     */
+
+       mr      r3,  r5                         /* Destination Address  */
+       lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
+       ori     r4, r4, CFG_MONITOR_BASE@l
+       lis     r5, CFG_MONITOR_LEN@h           /* Length in Bytes      */
+       ori     r5, r5, CFG_MONITOR_LEN@l
+       li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
+
+       /*
+        * Fix GOT pointer:
+        *
+        * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
+        *
+        * Offset:
+        */
+       sub     r15, r10, r4
+
+       /* First our own GOT */
+       add     r14, r14, r15
+       /* then the one used by the C code */
+       add     r30, r30, r15
+
+       /*
+        * Now relocate code
+        */
+
+       cmplw   cr1,r3,r4
+       addi    r0,r5,3
+       srwi.   r0,r0,2
+       beq     cr1,4f          /* In place copy is not necessary       */
+       beq     7f              /* Protect against 0 count              */
+       mtctr   r0
+       bge     cr1,2f
+
+       la      r8,-4(r4)
+       la      r7,-4(r3)
+1:     lwzu    r0,4(r8)
+       stwu    r0,4(r7)
+       bdnz    1b
+       b       4f
+
+2:     slwi    r0,r0,2
+       add     r8,r4,r0
+       add     r7,r3,r0
+3:     lwzu    r0,-4(r8)
+       stwu    r0,-4(r7)
+       bdnz    3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:     cmpwi   r6,0
+       add     r5,r3,r5
+       beq     7f              /* Always flush prefetch queue in any case */
+       subi    r0,r6,1
+       andc    r3,r3,r0
+       mfspr   r7,HID0         /* don't do dcbst if dcache is disabled */
+       rlwinm  r7,r7,HID0_DCE_BITPOS+1,31,31
+       cmpwi   r7,0
+       beq     9f
+       mr      r4,r3
+5:     dcbst   0,r4
+       add     r4,r4,r6
+       cmplw   r4,r5
+       blt     5b
+       sync                    /* Wait for all dcbst to complete on bus */
+9:     mfspr   r7,HID0         /* don't do icbi if icache is disabled */
+       rlwinm  r7,r7,HID0_ICE_BITPOS+1,31,31
+       cmpwi   r7,0
+       beq     7f
+       mr      r4,r3
+6:     icbi    0,r4
+       add     r4,r4,r6
+       cmplw   r4,r5
+       blt     6b
+7:     sync                    /* Wait for all icbi to complete on bus */
+       isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+       addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+       mtlr    r0
+       blr
+
+in_ram:
+
+       /*
+        * Relocation Function, r14 point to got2+0x8000
+        *
+         * Adjust got2 pointers, no need to check for 0, this code
+         * already puts a few entries in the table.
+        */
+       li      r0,__got2_entries@sectoff@l
+       la      r3,GOT(_GOT2_TABLE_)
+       lwz     r11,GOT(_GOT2_TABLE_)
+       mtctr   r0
+       sub     r11,r3,r11
+       addi    r3,r3,-4
+1:     lwzu    r0,4(r3)
+       add     r0,r0,r11
+       stw     r0,0(r3)
+       bdnz    1b
+
+       /*
+         * Now adjust the fixups and the pointers to the fixups
+        * in case we need to move ourselves again.
+        */
+2:     li      r0,__fixup_entries@sectoff@l
+       lwz     r3,GOT(_FIXUP_TABLE_)
+       cmpwi   r0,0
+       mtctr   r0
+       addi    r3,r3,-4
+       beq     4f
+3:     lwzu    r4,4(r3)
+       lwzux   r0,r4,r11
+       add     r0,r0,r11
+       stw     r10,0(r3)
+       stw     r0,0(r4)
+       bdnz    3b
+4:
+clear_bss:
+       /*
+        * Now clear BSS segment
+        */
+       lwz     r3,GOT(.bss)
+#if defined(CONFIG_HYMOD)
+       /*
+        * For HYMOD - the environment is the very last item in flash.
+        * The real .bss stops just before environment starts, so only
+        * clear up to that point.
+        *
+        * taken from mods for FADS board
+        */
+       lwz     r4,GOT(environment)
+#else
+       lwz     r4,GOT(_end)
+#endif
+
+       cmplw   0, r3, r4
+       beq     6f
+
+       li      r0, 0
+5:
+       stw     r0, 0(r3)
+       addi    r3, r3, 4
+       cmplw   0, r3, r4
+       bne     5b
+6:
+
+       mr      r3, r9          /* Global Data pointer          */
+       mr      r4, r10         /* Destination Address          */
+       bl      board_init_r
+
+       /* Problems accessing "end" in C, so do it here */
+       .globl  get_endaddr
+get_endaddr:
+       lwz     r3,GOT(_end)
+       blr
+
+       /*
+        * Copy exception vector code to low memory
+        *
+        * r3: dest_addr
+        * r7: source address, r8: end address, r9: target address
+        */
+       .globl  trap_init
+trap_init:
+       lwz     r7, GOT(_start)
+       lwz     r8, GOT(_end_of_vectors)
+
+       rlwinm  r9, r7, 0, 18, 31       /* _start & 0x3FFF      */
+
+       cmplw   0, r7, r8
+       bgelr                           /* return if r7>=r8 - just in case */
+
+       mflr    r4                      /* save link register           */
+1:
+       lwz     r0, 0(r7)
+       stw     r0, 0(r9)
+       addi    r7, r7, 4
+       addi    r9, r9, 4
+       cmplw   0, r7, r8
+       bne     1b
+
+       /*
+        * relocate `hdlr' and `int_return' entries
+        */
+       li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+       li      r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     2b
+
+       li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+       bl      trap_reloc
+
+       li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+       bl      trap_reloc
+
+       li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+       li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     3b
+
+       li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+       li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     4b
+
+       mfmsr   r3                      /* now that the vectors have    */
+       lis     r7, MSR_IP@h            /* relocated into low memory    */
+       ori     r7, r7, MSR_IP@l        /* MSR[IP] can be turned off    */
+       andc    r3, r3, r7              /* (if it was on)               */
+       SYNC                            /* Some chip revs need this... */
+       mtmsr   r3
+       SYNC
+
+       mtlr    r4                      /* restore link register    */
+       blr
+
+       /*
+        * Function: relocate entries for one exception vector
+        */
+trap_reloc:
+       lwz     r0, 0(r7)               /* hdlr ...                     */
+       add     r0, r0, r3              /*  ... += dest_addr            */
+       stw     r0, 0(r7)
+
+       lwz     r0, 4(r7)               /* int_return ...               */
+       add     r0, r0, r3              /*  ... += dest_addr            */
+       stw     r0, 4(r7)
+
+       blr