Initial revision
diff --git a/cpu/ppc4xx/405gp_enet.c b/cpu/ppc4xx/405gp_enet.c
new file mode 100644
index 0000000..49e9e42
--- /dev/null
+++ b/cpu/ppc4xx/405gp_enet.c
@@ -0,0 +1,867 @@
+/*-----------------------------------------------------------------------------+
+ *
+ *       This source code has been made available to you by IBM on an AS-IS
+ *       basis.  Anyone receiving this source is licensed under IBM
+ *       copyrights to use it in any way he or she deems fit, including
+ *       copying it, modifying it, compiling it, and redistributing it either
+ *       with or without modifications.  No license under IBM patents or
+ *       patent applications is to be implied by the copyright license.
+ *
+ *       Any user of this software should understand that IBM cannot provide
+ *       technical support for this software and will not be responsible for
+ *       any consequences resulting from the use of this software.
+ *
+ *       Any person who transfers this source code or any derivative work
+ *       must include the IBM copyright notice, this paragraph, and the
+ *       preceding two paragraphs in the transferred software.
+ *
+ *       COPYRIGHT   I B M   CORPORATION 1995
+ *       LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
+ *-----------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------+
+ *
+ *  File Name:  enetemac.c
+ *
+ *  Function:   Device driver for the ethernet EMAC3 macro on the 405GP.
+ *
+ *  Author:     Mark Wisner
+ *
+ *  Change Activity-
+ *
+ *  Date        Description of Change                                       BY
+ *  ---------   ---------------------                                       ---
+ *  05-May-99   Created                                                     MKW
+ *  27-Jun-99   Clean up                                                    JWB
+ *  16-Jul-99   Added MAL error recovery and better IP packet handling      MKW
+ *  29-Jul-99   Added Full duplex support                                   MKW
+ *  06-Aug-99   Changed names for Mal CR reg                                MKW
+ *  23-Aug-99   Turned off SYE when running at 10Mbs                        MKW
+ *  24-Aug-99   Marked descriptor empty after call_xlc                      MKW
+ *  07-Sep-99   Set MAL RX buffer size reg to ENET_MAX_MTU_ALIGNED / 16     MCG
+ *              to avoid chaining maximum sized packets. Push starting
+ *              RX descriptor address up to the next cache line boundary.
+ *  16-Jan-00   Added support for booting with IP of 0x0                    MKW
+ *  15-Mar-00   Updated enetInit() to enable broadcast addresses in the
+ *	        EMAC_RXM register.                                          JWB
+ *  12-Mar-01   anne-sophie.harnois@nextream.fr
+ *               - Variables are compatible with those already defined in
+ *                include/net.h
+ *              - Receive buffer descriptor ring is used to send buffers
+ *                to the user
+ *              - Info print about send/received/handled packet number if
+ *                INFO_405_ENET is set
+ *  17-Apr-01   stefan.roese@esd-electronics.com
+ *              - MAL reset in "eth_halt" included
+ *              - Enet speed and duplex output now in one line
+ *  08-May-01   stefan.roese@esd-electronics.com
+ *              - MAL error handling added (eth_init called again)
+ *  13-Nov-01   stefan.roese@esd-electronics.com
+ *              - Set IST bit in EMAC_M1 reg upon 100MBit or full duplex
+ *  04-Jan-02   stefan.roese@esd-electronics.com
+ *              - Wait for PHY auto negotiation to complete added
+ *  06-Feb-02   stefan.roese@esd-electronics.com
+ *              - Bug fixed in waiting for auto negotiation to complete
+ *  26-Feb-02   stefan.roese@esd-electronics.com
+ *              - rx and tx buffer descriptors now allocated (no fixed address
+ *                used anymore)
+ *  17-Jun-02   stefan.roese@esd-electronics.com
+ *              - MAL error debug printf 'M' removed (rx de interrupt may
+ *                occur upon many incoming packets with only 4 rx buffers).
+ *-----------------------------------------------------------------------------*/
+
+#include <common.h>
+#include <asm/processor.h>
+#include <ppc4xx.h>
+#include <commproc.h>
+#include <405gp_enet.h>
+#include <405_mal.h>
+#include <miiphy.h>
+#include <net.h>
+#include <malloc.h>
+#include "vecnum.h"
+
+#if defined(CONFIG_405GP) || defined(CONFIG_440)
+
+#define EMAC_RESET_TIMEOUT 1000	/* 1000 ms reset timeout */
+#define PHY_AUTONEGOTIATE_TIMEOUT 2000	/* 2000 ms autonegotiate timeout */
+
+#define NUM_TX_BUFF 1
+/* AS.HARNOIS
+ * Use PKTBUFSRX (include/net.h) instead of setting NUM_RX_BUFF again
+ * These both variables are used to define the same thing!
+ * #define NUM_RX_BUFF 4
+ */
+#define NUM_RX_BUFF PKTBUFSRX
+
+/* Ethernet Transmit and Receive Buffers */
+/* AS.HARNOIS
+ * In the same way ENET_MAX_MTU and ENET_MAX_MTU_ALIGNED are set from
+ * PKTSIZE and PKTSIZE_ALIGN (include/net.h)
+ */
+#define ENET_MAX_MTU           PKTSIZE
+#define ENET_MAX_MTU_ALIGNED   PKTSIZE_ALIGN
+
+static char *txbuf_ptr;
+
+/* define the number of channels implemented */
+#define EMAC_RXCHL      1
+#define EMAC_TXCHL      1
+
+/*-----------------------------------------------------------------------------+
+ * Defines for MAL/EMAC interrupt conditions as reported in the UIC (Universal
+ * Interrupt Controller).
+ *-----------------------------------------------------------------------------*/
+#define MAL_UIC_ERR ( UIC_MAL_SERR | UIC_MAL_TXDE  | UIC_MAL_RXDE)
+#define MAL_UIC_DEF  (UIC_MAL_RXEOB | MAL_UIC_ERR)
+#define EMAC_UIC_DEF UIC_ENET
+
+/*-----------------------------------------------------------------------------+
+ * Global variables. TX and RX descriptors and buffers.
+ *-----------------------------------------------------------------------------*/
+static volatile mal_desc_t *tx;
+static volatile mal_desc_t *rx;
+static mal_desc_t *alloc_tx_buf = NULL;
+static mal_desc_t *alloc_rx_buf = NULL;
+
+/* IER globals */
+static unsigned long emac_ier;
+static unsigned long mal_ier;
+
+
+/* Statistic Areas */
+#define MAX_ERR_LOG 10
+struct emac_stats {
+	int data_len_err;
+	int rx_frames;
+	int rx;
+	int rx_prot_err;
+};
+
+static struct stats {			/* Statistic Block */
+	struct emac_stats emac;
+	int int_err;
+	short tx_err_log[MAX_ERR_LOG];
+	short rx_err_log[MAX_ERR_LOG];
+} stats;
+
+static int first_init = 0;
+
+static int tx_err_index = 0;	/* Transmit Error Index for tx_err_log */
+static int rx_err_index = 0;	/* Receive Error Index for rx_err_log */
+
+static int rx_slot = 0;			/* MAL Receive Slot */
+static int rx_i_index = 0;		/* Receive Interrupt Queue Index */
+static int rx_u_index = 0;		/* Receive User Queue Index */
+static int rx_ready[NUM_RX_BUFF];	/* Receive Ready Queue */
+
+static int tx_slot = 0;			/* MAL Transmit Slot */
+static int tx_i_index = 0;		/* Transmit Interrupt Queue Index */
+static int tx_u_index = 0;		/* Transmit User Queue Index */
+static int tx_run[NUM_TX_BUFF];	/* Transmit Running Queue */
+
+#undef INFO_405_ENET 1
+#ifdef INFO_405_ENET
+static int packetSent = 0;
+static int packetReceived = 0;
+static int packetHandled = 0;
+#endif
+
+static char emac_hwd_addr[ENET_ADDR_LENGTH];
+
+static bd_t *bis_save = NULL;	/* for eth_init upon mal error */
+
+static int is_receiving = 0;	/* sync with eth interrupt */
+static int print_speed = 1;	/* print speed message upon start */
+
+static void enet_rcv (unsigned long malisr);
+
+/*-----------------------------------------------------------------------------+
+ * Prototypes and externals.
+ *-----------------------------------------------------------------------------*/
+void mal_err (unsigned long isr, unsigned long uic, unsigned long mal_def,
+	      unsigned long mal_errr);
+void emac_err (unsigned long isr);
+
+
+void eth_halt (void)
+{
+	mtdcr (malier, 0x00000000);	/* disable mal interrupts */
+	out32 (EMAC_IER, 0x00000000);	/* disable emac interrupts */
+
+	/* 1st reset MAL */
+	mtdcr (malmcr, MAL_CR_MMSR);
+
+	/* wait for reset */
+	while (mfdcr (malmcr) & MAL_CR_MMSR) {
+	};
+
+	/* EMAC RESET */
+	out32 (EMAC_M0, EMAC_M0_SRST);
+
+	print_speed = 1;		/* print speed message again next time */
+}
+
+
+int eth_init (bd_t * bis)
+{
+	int i;
+	unsigned long reg;
+	unsigned long msr;
+	unsigned long speed;
+	unsigned long duplex;
+	unsigned mode_reg;
+	unsigned short reg_short;
+
+	msr = mfmsr ();
+	mtmsr (msr & ~(MSR_EE));	/* disable interrupts */
+
+#ifdef INFO_405_ENET
+	/* AS.HARNOIS
+	 * We should have :
+	 * packetHandled <=  packetReceived <= packetHandled+PKTBUFSRX
+         * In the most cases packetHandled = packetReceived, but it
+         * is possible that new packets (without relationship with
+         * current transfer) have got the time to arrived before
+         * netloop calls eth_halt
+	 */
+	printf ("About preceeding transfer:\n"
+		"- Sent packet number %d\n"
+		"- Received packet number %d\n"
+		"- Handled packet number %d\n",
+		packetSent, packetReceived, packetHandled);
+	packetSent = 0;
+	packetReceived = 0;
+	packetHandled = 0;
+#endif
+
+	/* MAL RESET */
+	mtdcr (malmcr, MAL_CR_MMSR);
+	/* wait for reset */
+	while (mfdcr (malmcr) & MAL_CR_MMSR) {
+	};
+
+	tx_err_index = 0;		/* Transmit Error Index for tx_err_log */
+	rx_err_index = 0;		/* Receive Error Index for rx_err_log */
+
+	rx_slot = 0;			/* MAL Receive Slot */
+	rx_i_index = 0;			/* Receive Interrupt Queue Index */
+	rx_u_index = 0;			/* Receive User Queue Index */
+
+	tx_slot = 0;			/* MAL Transmit Slot */
+	tx_i_index = 0;			/* Transmit Interrupt Queue Index */
+	tx_u_index = 0;			/* Transmit User Queue Index */
+
+#if defined(CONFIG_440)
+        /* set RMII mode */
+        out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0);
+#endif /* CONFIG_440 */
+
+	/* EMAC RESET */
+	out32 (EMAC_M0, EMAC_M0_SRST);
+
+	/* wait for PHY to complete auto negotiation */
+	reg_short = 0;
+#ifndef CONFIG_CS8952_PHY
+	miiphy_read (CONFIG_PHY_ADDR, PHY_BMSR, &reg_short);
+
+	/*
+	 * Wait if PHY is able of autonegotiation and autonegotiation is not complete
+	 */
+	if ((reg_short & PHY_BMSR_AUTN_ABLE)
+	    && !(reg_short & PHY_BMSR_AUTN_COMP)) {
+		puts ("Waiting for PHY auto negotiation to complete");
+		i = 0;
+		while (!(reg_short & PHY_BMSR_AUTN_COMP)) {
+			if ((i++ % 100) == 0)
+				putc ('.');
+			udelay (10000);		/* 10 ms */
+			miiphy_read (CONFIG_PHY_ADDR, PHY_BMSR, &reg_short);
+
+			/*
+			 * Timeout reached ?
+			 */
+			if (i * 10 > PHY_AUTONEGOTIATE_TIMEOUT) {
+				puts (" TIMEOUT !\n");
+				break;
+			}
+		}
+		puts (" done\n");
+		udelay (500000);	/* another 500 ms (results in faster booting) */
+	}
+#endif
+	speed = miiphy_speed (CONFIG_PHY_ADDR);
+	duplex = miiphy_duplex (CONFIG_PHY_ADDR);
+	if (print_speed) {
+		print_speed = 0;
+		printf ("ENET Speed is %d Mbps - %s duplex connection\n",
+			(int) speed, (duplex == HALF) ? "HALF" : "FULL");
+	}
+
+	/* set the Mal configuration reg */
+#if defined(CONFIG_440)
+	/* Errata 1.12: MAL_1 -- Disable MAL bursting */
+	if( get_pvr() == PVR_440GP_RB )
+	    mtdcr (malmcr, MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
+	else
+#else
+	mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
+#endif
+
+	/* Free "old" buffers */
+	if (alloc_tx_buf) free(alloc_tx_buf);
+	if (alloc_rx_buf) free(alloc_rx_buf);
+
+	/*
+	 * Malloc MAL buffer desciptors, make sure they are
+	 * aligned on cache line boundary size
+	 * (401/403/IOP480 = 16, 405 = 32)
+	 * and doesn't cross cache block boundaries.
+	 */
+	alloc_tx_buf = (mal_desc_t *)malloc((sizeof(mal_desc_t) * NUM_TX_BUFF) +
+					    ((2 * CFG_CACHELINE_SIZE) - 2));
+	if (((int)alloc_tx_buf & CACHELINE_MASK) != 0) {
+		tx = (mal_desc_t *)((int)alloc_tx_buf + CFG_CACHELINE_SIZE -
+				    ((int)alloc_tx_buf & CACHELINE_MASK));
+	} else {
+		tx = alloc_tx_buf;
+	}
+
+	alloc_rx_buf = (mal_desc_t *)malloc((sizeof(mal_desc_t) * NUM_RX_BUFF) +
+					    ((2 * CFG_CACHELINE_SIZE) - 2));
+	if (((int)alloc_rx_buf & CACHELINE_MASK) != 0) {
+		rx = (mal_desc_t *)((int)alloc_rx_buf + CFG_CACHELINE_SIZE -
+				    ((int)alloc_rx_buf & CACHELINE_MASK));
+	} else {
+		rx = alloc_rx_buf;
+	}
+
+	for (i = 0; i < NUM_TX_BUFF; i++) {
+		tx[i].ctrl = 0;
+		tx[i].data_len = 0;
+		if (first_init == 0)
+			txbuf_ptr = (char *) malloc (ENET_MAX_MTU_ALIGNED);
+		tx[i].data_ptr = txbuf_ptr;
+		if ((NUM_TX_BUFF - 1) == i)
+			tx[i].ctrl |= MAL_TX_CTRL_WRAP;
+		tx_run[i] = -1;
+#if 0
+		printf ("TX_BUFF %d @ 0x%08lx\n", i, (ulong) tx[i].data_ptr);
+#endif
+	}
+
+	for (i = 0; i < NUM_RX_BUFF; i++) {
+		rx[i].ctrl = 0;
+		rx[i].data_len = 0;
+		/*       rx[i].data_ptr = (char *) &rx_buff[i]; */
+		rx[i].data_ptr = (char *) NetRxPackets[i];
+		if ((NUM_RX_BUFF - 1) == i)
+			rx[i].ctrl |= MAL_RX_CTRL_WRAP;
+		rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR;
+		rx_ready[i] = -1;
+#if 0
+		printf ("RX_BUFF %d @ 0x%08lx\n", i, (ulong) rx[i].data_ptr);
+#endif
+	}
+
+	memcpy (emac_hwd_addr, bis->bi_enetaddr, ENET_ADDR_LENGTH);
+
+	reg = 0x00000000;
+
+	reg |= emac_hwd_addr[0];	/* set high address */
+	reg = reg << 8;
+	reg |= emac_hwd_addr[1];
+
+	out32 (EMAC_IAH, reg);
+
+	reg = 0x00000000;
+	reg |= emac_hwd_addr[2];	/* set low address  */
+	reg = reg << 8;
+	reg |= emac_hwd_addr[3];
+	reg = reg << 8;
+	reg |= emac_hwd_addr[4];
+	reg = reg << 8;
+	reg |= emac_hwd_addr[5];
+
+	out32 (EMAC_IAL, reg);
+
+	/* setup MAL tx & rx channel pointers */
+	mtdcr (maltxctp0r, tx);
+	mtdcr (malrxctp0r, rx);
+
+	/* Reset transmit and receive channels */
+	mtdcr (malrxcarr, 0x80000000);	/* 2 channels */
+	mtdcr (maltxcarr, 0x80000000);	/* 2 channels */
+
+	/* Enable MAL transmit and receive channels */
+	mtdcr (maltxcasr, 0x80000000);	/* 1 channel */
+	mtdcr (malrxcasr, 0x80000000);	/* 1 channel */
+
+	/* set RX buffer size */
+	mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16);
+
+	/* set transmit enable & receive enable */
+	out32 (EMAC_M0, EMAC_M0_TXE | EMAC_M0_RXE);
+
+	/* set receive fifo to 4k and tx fifo to 2k */
+	mode_reg = EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K;
+
+	/* set speed */
+	if (speed == _100BASET)
+		mode_reg = mode_reg | EMAC_M1_MF_100MBPS | EMAC_M1_IST;
+	else
+		mode_reg = mode_reg & ~0x00C00000;	/* 10 MBPS */
+	if (duplex == FULL)
+		mode_reg = mode_reg | 0x80000000 | EMAC_M1_IST;
+
+	out32 (EMAC_M1, mode_reg);
+
+	/* Enable broadcast and indvidual address */
+	out32 (EMAC_RXM, EMAC_RMR_BAE | EMAC_RMR_IAE
+	       /*| EMAC_RMR_ARRP| EMAC_RMR_SFCS | EMAC_RMR_SP */ );
+
+	/* we probably need to set the tx mode1 reg? maybe at tx time */
+
+	/* set transmit request threshold register */
+	out32 (EMAC_TRTR, 0x18000000);	/* 256 byte threshold */
+
+	/* set receive  low/high water mark register */
+#if defined(CONFIG_440)
+	/* 440GP has a 64 byte burst length */
+        out32 (EMAC_RX_HI_LO_WMARK, 0x80009000);
+        out32 (EMAC_TXM1,           0xf8640000);
+#else /* CONFIG_440 */
+	/* 405s have a 16 byte burst length */
+	out32 (EMAC_RX_HI_LO_WMARK, 0x0f002000);
+#endif /* CONFIG_440 */
+
+	/* Frame gap set */
+	out32 (EMAC_I_FRAME_GAP_REG, 0x00000008);
+
+	if (first_init == 0) {
+		/*
+		 * Connect interrupt service routines
+		 */
+		irq_install_handler (VECNUM_EWU0, (interrupt_handler_t *) enetInt, NULL);
+		irq_install_handler (VECNUM_MS, (interrupt_handler_t *) enetInt, NULL);
+		irq_install_handler (VECNUM_MTE, (interrupt_handler_t *) enetInt, NULL);
+		irq_install_handler (VECNUM_MRE, (interrupt_handler_t *) enetInt, NULL);
+		irq_install_handler (VECNUM_TXDE, (interrupt_handler_t *) enetInt, NULL);
+		irq_install_handler (VECNUM_RXDE, (interrupt_handler_t *) enetInt, NULL);
+		irq_install_handler (VECNUM_ETH0, (interrupt_handler_t *) enetInt, NULL);
+	}
+
+	/* set up interrupt handler */
+	/* setup interrupt controler to take interrupts from the MAL &
+	   EMAC */
+	mtdcr (uicsr, 0xffffffff);	/* clear pending interrupts */
+	mtdcr (uicer, mfdcr (uicer) | MAL_UIC_DEF | EMAC_UIC_DEF);
+
+	/* set the MAL IER ??? names may change with new spec ??? */
+	mal_ier = MAL_IER_DE | MAL_IER_NE | MAL_IER_TE | MAL_IER_OPBE |
+		MAL_IER_PLBE;
+	mtdcr (malesr, 0xffffffff);	/* clear pending interrupts */
+	mtdcr (maltxdeir, 0xffffffff);	/* clear pending interrupts */
+	mtdcr (malrxdeir, 0xffffffff);	/* clear pending interrupts */
+	mtdcr (malier, mal_ier);
+
+	/* Set EMAC IER */
+	emac_ier = EMAC_ISR_PTLE | EMAC_ISR_BFCS |
+		EMAC_ISR_PTLE | EMAC_ISR_ORE  | EMAC_ISR_IRE;
+	if (speed == _100BASET)
+		emac_ier = emac_ier | EMAC_ISR_SYE;
+
+	out32 (EMAC_ISR, 0xffffffff);	/* clear pending interrupts */
+	out32 (EMAC_IER, emac_ier);
+
+	mtmsr (msr);				/* enable interrupts again */
+
+	bis_save = bis;
+	first_init = 1;
+
+	return (0);
+}
+
+
+int eth_send (volatile void *ptr, int len)
+{
+	struct enet_frame *ef_ptr;
+	ulong time_start, time_now;
+	unsigned long temp_txm0;
+
+	ef_ptr = (struct enet_frame *) ptr;
+
+	/*-----------------------------------------------------------------------+
+	 *  Copy in our address into the frame.
+	 *-----------------------------------------------------------------------*/
+	(void) memcpy (ef_ptr->source_addr, emac_hwd_addr, ENET_ADDR_LENGTH);
+
+	/*-----------------------------------------------------------------------+
+	 * If frame is too long or too short, modify length.
+	 *-----------------------------------------------------------------------*/
+	if (len > ENET_MAX_MTU)
+		len = ENET_MAX_MTU;
+
+	/*   memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len); */
+	memcpy ((void *) txbuf_ptr, (const void *) ptr, len);
+
+	/*-----------------------------------------------------------------------+
+	 * set TX Buffer busy, and send it
+	 *-----------------------------------------------------------------------*/
+	tx[tx_slot].ctrl = (MAL_TX_CTRL_LAST |
+			    EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP) &
+		~(EMAC_TX_CTRL_ISA | EMAC_TX_CTRL_RSA);
+	if ((NUM_TX_BUFF - 1) == tx_slot)
+		tx[tx_slot].ctrl |= MAL_TX_CTRL_WRAP;
+
+	tx[tx_slot].data_len = (short) len;
+	tx[tx_slot].ctrl |= MAL_TX_CTRL_READY;
+
+    __asm__ volatile ("eieio");
+	out32 (EMAC_TXM0, in32 (EMAC_TXM0) | EMAC_TXM0_GNP0);
+#ifdef INFO_405_ENET
+	packetSent++;
+#endif
+
+	/*-----------------------------------------------------------------------+
+	 * poll unitl the packet is sent and then make sure it is OK
+	 *-----------------------------------------------------------------------*/
+	time_start = get_timer (0);
+	while (1) {
+		temp_txm0 = in32 (EMAC_TXM0);
+		/* loop until either TINT turns on or 3 seconds elapse */
+		if ((temp_txm0 & EMAC_TXM0_GNP0) != 0) {
+			/* transmit is done, so now check for errors
+                         * If there is an error, an interrupt should
+                         * happen when we return
+			 */
+			time_now = get_timer (0);
+			if ((time_now - time_start) > 3000) {
+				return (-1);
+			}
+		} else {
+			return (0);
+		}
+	}
+}
+
+
+#if defined(CONFIG_440)
+/*-----------------------------------------------------------------------------+
+| EnetInt.
+| EnetInt is the interrupt handler.  It will determine the
+| cause of the interrupt and call the apporpriate servive
+| routine.
++-----------------------------------------------------------------------------*/
+int enetInt ()
+{
+	int serviced;
+	int rc = -1;				/* default to not us */
+	unsigned long mal_isr;
+	unsigned long emac_isr = 0;
+	unsigned long mal_rx_eob;
+	unsigned long my_uic0msr, my_uic1msr;
+
+	/* enter loop that stays in interrupt code until nothing to service */
+	do {
+		serviced = 0;
+
+		my_uic0msr = mfdcr (uic0msr);
+		my_uic1msr = mfdcr (uic1msr);
+
+		if (!(my_uic0msr & UIC_MRE)
+                    && !(my_uic1msr & (UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE))) {
+                        /* not for us */
+			return (rc);
+		}
+
+		/* get and clear controller status interrupts */
+		/* look at Mal and EMAC interrupts */
+		if ((my_uic0msr & UIC_MRE)
+                    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
+                        /* we have a MAL interrupt */
+			mal_isr = mfdcr (malesr);
+			/* look for mal error */
+			if (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) {
+				mal_err (mal_isr, my_uic0msr, MAL_UIC_DEF, MAL_UIC_ERR);
+				serviced = 1;
+				rc = 0;
+			}
+		}
+		if (UIC_ETH0 & my_uic1msr) {	/* look for EMAC errors */
+			emac_isr = in32 (EMAC_ISR);
+			if ((emac_ier & emac_isr) != 0) {
+				emac_err (emac_isr);
+				serviced = 1;
+				rc = 0;
+			}
+		}
+		if ((emac_ier & emac_isr)
+                    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
+			mtdcr (uic0sr, UIC_MRE); /* Clear */
+			mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+			return (rc);		/* we had errors so get out */
+		}
+
+		/* handle MAL RX EOB  interupt from a receive */
+		/* check for EOB on valid channels            */
+		if (my_uic0msr & UIC_MRE) {
+			mal_rx_eob = mfdcr (malrxeobisr);
+			if ((mal_rx_eob & 0x80000000) != 0) {	/* call emac routine for channel 0 */
+				/* clear EOB
+				   mtdcr(malrxeobisr, mal_rx_eob); */
+				enet_rcv (emac_isr);
+				/* indicate that we serviced an interrupt */
+				serviced = 1;
+				rc = 0;
+			}
+		}
+                mtdcr (uic0sr, UIC_MRE); /* Clear */
+                mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+	} while (serviced);
+
+	return (rc);
+}
+#else /* CONFIG_440 */
+/*-----------------------------------------------------------------------------+
+ * EnetInt.
+ * EnetInt is the interrupt handler.  It will determine the
+ * cause of the interrupt and call the apporpriate servive
+ * routine.
+ *-----------------------------------------------------------------------------*/
+int enetInt ()
+{
+	int serviced;
+	int rc = -1;				/* default to not us */
+	unsigned long mal_isr;
+	unsigned long emac_isr = 0;
+	unsigned long mal_rx_eob;
+	unsigned long my_uicmsr;
+
+	/* enter loop that stays in interrupt code until nothing to service */
+	do {
+		serviced = 0;
+
+		my_uicmsr = mfdcr (uicmsr);
+		if ((my_uicmsr & (MAL_UIC_DEF | EMAC_UIC_DEF)) == 0) {	/* not for us */
+			return (rc);
+		}
+
+
+		/* get and clear controller status interrupts */
+		/* look at Mal and EMAC interrupts */
+		if ((MAL_UIC_DEF & my_uicmsr) != 0) {	/* we have a MAL interrupt */
+			mal_isr = mfdcr (malesr);
+			/* look for mal error */
+			if ((my_uicmsr & MAL_UIC_ERR) != 0) {
+				mal_err (mal_isr, my_uicmsr, MAL_UIC_DEF, MAL_UIC_ERR);
+				serviced = 1;
+				rc = 0;
+			}
+		}
+		if ((EMAC_UIC_DEF & my_uicmsr) != 0) {	/* look for EMAC errors */
+			emac_isr = in32 (EMAC_ISR);
+			if ((emac_ier & emac_isr) != 0) {
+				emac_err (emac_isr);
+				serviced = 1;
+				rc = 0;
+			}
+		}
+		if (((emac_ier & emac_isr) != 0) | ((MAL_UIC_ERR & my_uicmsr) != 0)) {
+			mtdcr (uicsr, MAL_UIC_DEF | EMAC_UIC_DEF); /* Clear */
+			return (rc);		/* we had errors so get out */
+		}
+
+
+		/* handle MAL RX EOB  interupt from a receive */
+		/* check for EOB on valid channels            */
+		if ((my_uicmsr & UIC_MAL_RXEOB) != 0) {
+			mal_rx_eob = mfdcr (malrxeobisr);
+			if ((mal_rx_eob & 0x80000000) != 0) {	/* call emac routine for channel 0 */
+				/* clear EOB
+				   mtdcr(malrxeobisr, mal_rx_eob); */
+				enet_rcv (emac_isr);
+				/* indicate that we serviced an interrupt */
+				serviced = 1;
+				rc = 0;
+			}
+		}
+		mtdcr (uicsr, MAL_UIC_DEF | EMAC_UIC_DEF);	/* Clear */
+	}
+	while (serviced);
+
+	return (rc);
+}
+#endif /* CONFIG_440 */
+
+/*-----------------------------------------------------------------------------+
+ *  MAL Error Routine
+ *-----------------------------------------------------------------------------*/
+void mal_err (unsigned long isr, unsigned long uic, unsigned long maldef,
+	      unsigned long mal_errr)
+{
+	mtdcr (malesr, isr);		/* clear interrupt */
+
+	/* clear DE interrupt */
+	mtdcr (maltxdeir, 0xC0000000);
+	mtdcr (malrxdeir, 0x80000000);
+
+#if 1	/*sr */
+	printf ("\nMAL error occured.... ISR = %lx UIC = = %lx  MAL_DEF = %lx  MAL_ERR= %lx \n",
+		isr, uic, maldef, mal_errr);
+#else
+#if 0
+	/*
+	 * MAL error is RX DE error (out of rx buffers)! This is OK here, upon
+	 * many incoming packets with only 4 rx buffers.
+	 */
+	printf ("M");			/* just to see something upon mal error */
+#endif
+#endif	/*sr */
+
+	eth_init (bis_save);		/* start again... */
+}
+
+/*-----------------------------------------------------------------------------+
+ *  EMAC Error Routine
+ *-----------------------------------------------------------------------------*/
+void emac_err (unsigned long isr)
+{
+	printf ("EMAC error occured.... ISR = %lx\n", isr);
+	out32 (EMAC_ISR, isr);
+}
+
+/*-----------------------------------------------------------------------------+
+ *  enet_rcv() handles the ethernet receive data
+ *-----------------------------------------------------------------------------*/
+static void enet_rcv (unsigned long malisr)
+{
+	struct enet_frame *ef_ptr;
+	unsigned long data_len;
+	unsigned long rx_eob_isr;
+
+	int handled = 0;
+	int i;
+	int loop_count = 0;
+
+	rx_eob_isr = mfdcr (malrxeobisr);
+	if ((0x80000000 >> (EMAC_RXCHL - 1)) & rx_eob_isr) {
+		/* clear EOB */
+		mtdcr (malrxeobisr, rx_eob_isr);
+
+		/* EMAC RX done */
+		while (1) {				/* do all */
+			i = rx_slot;
+
+			if ((MAL_RX_CTRL_EMPTY & rx[i].ctrl)
+			    || (loop_count >= NUM_RX_BUFF))
+				break;
+			loop_count++;
+			rx_slot++;
+			if (NUM_RX_BUFF == rx_slot)
+				rx_slot = 0;
+			handled++;
+			data_len = (unsigned long) rx[i].data_len;	/* Get len */
+			if (data_len) {
+				if (data_len > ENET_MAX_MTU)	/* Check len */
+					data_len = 0;
+				else {
+					if (EMAC_RX_ERRORS & rx[i].ctrl) {	/* Check Errors */
+						data_len = 0;
+						stats.rx_err_log[rx_err_index] = rx[i].ctrl;
+						rx_err_index++;
+						if (rx_err_index == MAX_ERR_LOG)
+							rx_err_index = 0;
+					}	/* emac_erros         */
+				}		/* data_len < max mtu */
+			}			/* if data_len        */
+			if (!data_len) {	/* no data */
+				rx[i].ctrl |= MAL_RX_CTRL_EMPTY;	/* Free Recv Buffer */
+
+				stats.emac.data_len_err++;	/* Error at Rx */
+			}
+
+			/* !data_len */
+			/* AS.HARNOIS */
+			/* Check if user has already eaten buffer */
+			/* if not => ERROR */
+			else if (rx_ready[rx_i_index] != -1) {
+				if (is_receiving)
+					printf ("ERROR : Receive buffers are full!\n");
+				break;
+			} else {
+				stats.emac.rx_frames++;
+				stats.emac.rx += data_len;
+				ef_ptr = (struct enet_frame *) rx[i].data_ptr;
+#ifdef INFO_405_ENET
+				packetReceived++;
+#endif
+				/* AS.HARNOIS
+				 * use ring buffer
+				 */
+				rx_ready[rx_i_index] = i;
+				rx_i_index++;
+				if (NUM_RX_BUFF == rx_i_index)
+					rx_i_index = 0;
+
+				/* printf("X");  /|* test-only *|/ */
+
+				/*  AS.HARNOIS
+				 * free receive buffer only when
+				 * buffer has been handled (eth_rx)
+				 rx[i].ctrl |= MAL_RX_CTRL_EMPTY;
+				*/
+			}			/* if data_len */
+		}				/* while */
+	}					/* if EMACK_RXCHL */
+}
+
+
+int eth_rx (void)
+{
+	int length;
+	int user_index;
+	unsigned long msr;
+
+	is_receiving = 1;			/* tell driver */
+
+	for (;;) {
+		/* AS.HARNOIS
+		 * use ring buffer and
+		 * get index from rx buffer desciptor queue
+		 */
+		user_index = rx_ready[rx_u_index];
+		if (user_index == -1) {
+			length = -1;
+			break;	/* nothing received - leave for() loop */
+		}
+
+		msr = mfmsr ();
+		mtmsr (msr & ~(MSR_EE));
+
+		length = rx[user_index].data_len;
+
+		/* Pass the packet up to the protocol layers. */
+		/*       NetReceive(NetRxPackets[rxIdx], length - 4); */
+		/*       NetReceive(NetRxPackets[i], length); */
+		NetReceive (NetRxPackets[user_index], length - 4);
+		/* Free Recv Buffer */
+		rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY;
+		/* Free rx buffer descriptor queue */
+		rx_ready[rx_u_index] = -1;
+		rx_u_index++;
+		if (NUM_RX_BUFF == rx_u_index)
+			rx_u_index = 0;
+
+#ifdef INFO_405_ENET
+		packetHandled++;
+#endif
+
+		mtmsr (msr);			/* Enable IRQ's */
+	}
+
+	is_receiving = 0;			/* tell driver */
+
+	return length;
+}
+
+#endif	/* CONFIG_405GP */
diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c
new file mode 100644
index 0000000..1c2c59b
--- /dev/null
+++ b/cpu/ppc4xx/405gp_pci.c
@@ -0,0 +1,502 @@
+/*-----------------------------------------------------------------------------+
+ *
+ *       This source code has been made available to you by IBM on an AS-IS
+ *       basis.  Anyone receiving this source is licensed under IBM
+ *       copyrights to use it in any way he or she deems fit, including
+ *       copying it, modifying it, compiling it, and redistributing it either
+ *       with or without modifications.  No license under IBM patents or
+ *       patent applications is to be implied by the copyright license.
+ *
+ *       Any user of this software should understand that IBM cannot provide
+ *       technical support for this software and will not be responsible for
+ *       any consequences resulting from the use of this software.
+ *
+ *       Any person who transfers this source code or any derivative work
+ *       must include the IBM copyright notice, this paragraph, and the
+ *       preceding two paragraphs in the transferred software.
+ *
+ *       COPYRIGHT   I B M   CORPORATION 1995
+ *       LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
+ *-----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+ *
+ *  File Name:   405gp_pci.c
+ *
+ *  Function:    Initialization code for the 405GP PCI Configuration regs.
+ *
+ *  Author:      Mark Game
+ *
+ *  Change Activity-
+ *
+ *  Date        Description of Change                                       BY
+ *  ---------   ---------------------                                       ---
+ *  09-Sep-98   Created                                                     MCG
+ *  02-Nov-98   Removed External arbiter selected message                   JWB
+ *  27-Nov-98   Zero out PTMBAR2 and disable in PTM2MS                      JWB
+ *  04-Jan-99   Zero out other unused PMM and PTM regs. Change bus scan     MCG
+ *              from (0 to n) to (1 to n).
+ *  17-May-99   Port to Walnut                                              JWB
+ *  17-Jun-99   Updated for VGA support                                     JWB
+ *  21-Jun-99   Updated to allow SRAM region to be a target from PCI bus    JWB
+ *  19-Jul-99   Updated for 405GP pass 1 errata #26 (Low PCI subsequent     MCG
+ *              target latency timer values are not supported).
+ *              Should be fixed in pass 2.
+ *  09-Sep-99   Removed use of PTM2 since the SRAM region no longer needs   JWB
+ *              to be a PCI target. Zero out PTMBAR2 and disable in PTM2MS.
+ *  10-Dec-99   Updated PCI_Write_CFG_Reg for pass2 errata #6               JWB
+ *  11-Jan-00   Ensure PMMxMAs disabled before setting PMMxLAs. This is not
+ *              really required after a reset since PMMxMAs are already
+ * 	        disabled but is a good practice nonetheless.                JWB
+ *  12-Jun-01   stefan.roese@esd-electronics.com
+ *              - PCI host/adapter handling reworked
+ *  09-Jul-01   stefan.roese@esd-electronics.com
+ *              - PCI host now configures from device 0 (not 1) to max_dev,
+ *                (host configures itself)
+ *              - On CPCI-405 pci base address and size is generated from
+ *                SDRAM and FLASH size (CFG regs not used anymore)
+ *              - Some minor changes for CPCI-405-A (adapter version)
+ *  14-Sep-01   stefan.roese@esd-electronics.com
+ *              - CONFIG_PCI_SCAN_SHOW added to print pci devices upon startup
+ *  28-Sep-01   stefan.roese@esd-electronics.com
+ *              - Changed pci master configuration for linux compatibility
+ *                (no need for bios_fixup() anymore)
+ *  26-Feb-02   stefan.roese@esd-electronics.com
+ *              - Bug fixed in pci configuration (Andrew May)
+ *              - Removed pci class code init for CPCI405 board
+ *  15-May-02   stefan.roese@esd-electronics.com
+ *              - New vga device handling
+ *  29-May-02   stefan.roese@esd-electronics.com
+ *              - PCI class code init added (if defined)
+ *----------------------------------------------------------------------------*/
+
+#include <common.h>
+#include <command.h>
+#include <cmd_boot.h>
+#if !defined(CONFIG_440)
+#include <405gp_pci.h>
+#endif
+#include <asm/processor.h>
+#include <pci.h>
+
+#if defined(CONFIG_405GP)
+
+#ifdef CONFIG_PCI
+
+/*#define DEBUG*/
+
+/*-----------------------------------------------------------------------------+
+ * pci_init.  Initializes the 405GP PCI Configuration regs.
+ *-----------------------------------------------------------------------------*/
+void pci_405gp_init(struct pci_controller *hose)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	int i, reg_num = 0;
+	bd_t *bd = gd->bd;
+
+	unsigned short temp_short;
+	unsigned long ptmpcila[2] = {CFG_PCI_PTM1PCI, CFG_PCI_PTM2PCI};
+#if defined(CONFIG_CPCI405)
+	unsigned long ptmla[2]    = {bd->bi_memstart, bd->bi_flashstart};
+	unsigned long ptmms[2]    = {~(bd->bi_memsize - 1) | 1, ~(bd->bi_flashsize - 1) | 1};
+#else
+	unsigned long ptmla[2]    = {CFG_PCI_PTM1LA, CFG_PCI_PTM2LA};
+	unsigned long ptmms[2]    = {CFG_PCI_PTM1MS, CFG_PCI_PTM2MS};
+#endif
+#if defined(CONFIG_PIP405) || defined (CONFIG_MIP405)
+	unsigned long pmmla[3]    = {0x80000000, 0xA0000000, 0};
+	unsigned long pmmma[3]    = {0xE0000001, 0xE0000001, 0};
+	unsigned long pmmpcila[3] = {0x80000000, 0x00000000, 0};
+	unsigned long pmmpciha[3] = {0x00000000, 0x00000000, 0};
+#else
+	unsigned long pmmla[3]    = {0x80000000, 0,0};
+	unsigned long pmmma[3]    = {0xC0000001, 0,0};
+	unsigned long pmmpcila[3] = {0x80000000, 0,0};
+	unsigned long pmmpciha[3] = {0x00000000, 0,0};
+#endif
+
+	/*
+	 * Register the hose
+	 */
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	/* ISA/PCI I/O space */
+	pci_set_region(hose->regions + reg_num++,
+		       MIN_PCI_PCI_IOADDR,
+		       MIN_PLB_PCI_IOADDR,
+		       0x10000,
+		       PCI_REGION_IO);
+
+	/* PCI I/O space */
+	pci_set_region(hose->regions + reg_num++,
+		       0x00800000,
+		       0xe8800000,
+		       0x03800000,
+		       PCI_REGION_IO);
+
+	reg_num = 2;
+
+	/* Memory spaces */
+	for (i=0; i<2; i++)
+		if (ptmms[i] & 1)
+		{
+			if (!i) hose->pci_fb = hose->regions + reg_num;
+
+			pci_set_region(hose->regions + reg_num++,
+				       ptmpcila[i], ptmla[i],
+				       ~(ptmms[i] & 0xfffff000) + 1,
+				       PCI_REGION_MEM |
+				       PCI_REGION_MEMORY);
+		}
+
+	/* PCI memory spaces */
+	for (i=0; i<3; i++)
+		if (pmmma[i] & 1)
+		{
+			pci_set_region(hose->regions + reg_num++,
+				       pmmpcila[i], pmmla[i],
+				       ~(pmmma[i] & 0xfffff000) + 1,
+				       PCI_REGION_MEM);
+		}
+
+	hose->region_count = reg_num;
+
+	pci_setup_indirect(hose,
+			   PCICFGADR,
+			   PCICFGDATA);
+
+	if (hose->pci_fb)
+		pciauto_region_init(hose->pci_fb);
+
+	pci_register_hose(hose);
+
+	/*--------------------------------------------------------------------------+
+	 * 405GP PCI Master configuration.
+	 * Map one 512 MB range of PLB/processor addresses to PCI memory space.
+	 * PLB address 0x80000000-0xBFFFFFFF ==> PCI address 0x80000000-0xBFFFFFFF
+	 * Use byte reversed out routines to handle endianess.
+	 *--------------------------------------------------------------------------*/
+	out32r(PMM0MA,    pmmma[0]);          /* ensure disabled b4 setting PMM0LA */
+	out32r(PMM0LA,    pmmla[0]);
+	out32r(PMM0PCILA, pmmpcila[0]);
+	out32r(PMM0PCIHA, pmmpciha[0]);
+	out32r(PMM0MA,    pmmma[0]);
+
+	/*--------------------------------------------------------------------------+
+	 * PMM1 is not used.  Initialize them to zero.
+	 *--------------------------------------------------------------------------*/
+	out32r(PMM1MA,    pmmma[1]);          /* ensure disabled b4 setting PMM2LA */
+	out32r(PMM1LA,    pmmla[1]);
+	out32r(PMM1PCILA, pmmpcila[1]);
+	out32r(PMM1PCIHA, pmmpciha[1]);
+	out32r(PMM1MA,    pmmma[1]);
+
+	/*--------------------------------------------------------------------------+
+	 * PMM2 is not used.  Initialize them to zero.
+	 *--------------------------------------------------------------------------*/
+	out32r(PMM2MA,    pmmma[2]);          /* ensure disabled b4 setting PMM2LA */
+	out32r(PMM2LA,    pmmla[2]);
+	out32r(PMM2PCILA, pmmpcila[2]);
+	out32r(PMM2PCIHA, pmmpciha[2]);
+	out32r(PMM2MA,    pmmma[2]);
+
+	/*--------------------------------------------------------------------------+
+	 * 405GP PCI Target configuration.  (PTM1)
+	 * Note: PTM1MS is hardwire enabled but we set the enable bit anyway.
+	 *--------------------------------------------------------------------------*/
+	out32r(PTM1LA,    ptmla[0]);         /* insert address                     */
+	out32r(PTM1MS,    ptmms[0]);         /* insert size, enable bit is 1       */
+
+	/*--------------------------------------------------------------------------+
+	 * 405GP PCI Target configuration.  (PTM2)
+	 *--------------------------------------------------------------------------*/
+	out32r(PTM2LA, ptmla[1]);            /* insert address                     */
+	if (ptmms[1] == 0)
+	{
+		out32r(PTM2MS,    0x00000001);   /* set enable bit                     */
+		pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, 0x00000000);
+		out32r(PTM2MS,    0x00000000);   /* disable                            */
+	}
+	else
+	{
+		out32r(PTM2MS, ptmms[1]);        /* insert size, enable bit is 1       */
+	}
+
+	/*
+	 * Insert Subsystem Vendor and Device ID
+	 */
+	pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_VENDOR_ID, CFG_PCI_SUBSYS_VENDORID);
+#ifdef CONFIG_CPCI405
+	if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+		pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_DEVICEID);
+	else
+		pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_DEVICEID2);
+#else
+	pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_DEVICEID);
+#endif
+
+	/*
+	 * Insert Class-code
+	 */
+#ifdef CFG_PCI_CLASSCODE
+	pci_write_config_word(PCIDEVID_405GP, PCI_CLASS_SUB_CODE, CFG_PCI_CLASSCODE);
+#endif /* CFG_PCI_CLASSCODE */
+
+	/*--------------------------------------------------------------------------+
+	 * If PCI speed = 66Mhz, set 66Mhz capable bit.
+	 *--------------------------------------------------------------------------*/
+	if (bd->bi_pci_busfreq >= 66000000) {
+		pci_read_config_word(PCIDEVID_405GP, PCI_STATUS, &temp_short);
+		pci_write_config_word(PCIDEVID_405GP,PCI_STATUS,(temp_short|PCI_STATUS_66MHZ));
+	}
+
+#if (CONFIG_PCI_HOST != PCI_HOST_ADAPTER)
+#if (CONFIG_PCI_HOSE == PCI_HOST_AUTO)
+	if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+#endif
+	{
+		/*--------------------------------------------------------------------------+
+		 * Write the 405GP PCI Configuration regs.
+		 * Enable 405GP to be a master on the PCI bus (PMM).
+		 * Enable 405GP to act as a PCI memory target (PTM).
+		 *--------------------------------------------------------------------------*/
+		pci_read_config_word(PCIDEVID_405GP, PCI_COMMAND, &temp_short);
+		pci_write_config_word(PCIDEVID_405GP, PCI_COMMAND, temp_short |
+				      PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+	}
+#endif
+
+	/*
+	 * Set HCE bit (Host Configuration Enabled)
+	 */
+	pci_read_config_word(PCIDEVID_405GP, PCIBRDGOPT2, &temp_short);
+	pci_write_config_word(PCIDEVID_405GP, PCIBRDGOPT2, (temp_short | 0x0001));
+
+#ifdef CONFIG_PCI_PNP
+	/*--------------------------------------------------------------------------+
+	 * Scan the PCI bus and configure devices found.
+	 *--------------------------------------------------------------------------*/
+#if (CONFIG_PCI_HOST == PCI_HOST_AUTO)
+	if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+#endif
+	{
+#ifdef CONFIG_PCI_SCAN_SHOW
+		printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+
+		hose->last_busno = pci_hose_scan(hose);
+	}
+#endif  /* CONFIG_PCI_PNP */
+
+}
+
+/*
+ * drivers/pci.c skips every host bridge but the 405GP since it could
+ * be set as an Adapter.
+ *
+ * I (Andrew May) don't know what we should do here, but I don't want
+ * the auto setup of a PCI device disabling what is done pci_405gp_init
+ * as has happened before.
+ */
+void pci_405gp_setup_bridge(struct pci_controller *hose, pci_dev_t dev,
+			    struct pci_config_table *entry)
+{
+#ifdef DEBUG
+        printf("405gp_setup_bridge\n");
+#endif
+}
+
+/*
+ *
+ */
+
+void pci_405gp_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
+{
+	unsigned char int_line = 0xff;
+
+	/*
+	 * Write pci interrupt line register (cpci405 specific)
+	 */
+	switch (PCI_DEV(dev) & 0x03)
+	{
+	case 0:
+		int_line = 27 + 2;
+		break;
+	case 1:
+		int_line = 27 + 3;
+		break;
+	case 2:
+		int_line = 27 + 0;
+		break;
+	case 3:
+		int_line = 27 + 1;
+		break;
+	}
+
+	pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line);
+}
+
+void pci_405gp_setup_vga(struct pci_controller *hose, pci_dev_t dev,
+			 struct pci_config_table *entry)
+{
+	unsigned int cmdstat = 0;
+
+	pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
+
+	/* always enable io space on vga boards */
+	pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat);
+	cmdstat |= PCI_COMMAND_IO;
+	pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat);
+}
+
+#if !(defined(CONFIG_PIP405) || defined (CONFIG_MIP405))
+
+/*
+ *As is these functs get called out of flash Not a horrible
+ *thing, but something to keep in mind. (no statics?)
+ */
+static struct pci_config_table pci_405gp_config_table[] = {
+/*if VendID is 0 it terminates the table search (ie Walnut)*/
+#if CFG_PCI_SUBSYS_VENDORID
+	{CFG_PCI_SUBSYS_VENDORID, PCI_ANY_ID, PCI_CLASS_BRIDGE_HOST,
+	 PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_bridge},
+#endif
+	{PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA,
+	 PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_vga},
+
+	{PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NOT_DEFINED_VGA,
+	 PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_vga},
+
+	{ }
+};
+
+static struct pci_controller hose = {
+	fixup_irq: pci_405gp_fixup_irq,
+	config_table: pci_405gp_config_table,
+};
+
+void pci_init(void)
+{
+	/*we want the ptrs to RAM not flash (ie don't use init list)*/
+	hose.fixup_irq    = pci_405gp_fixup_irq;
+	hose.config_table = pci_405gp_config_table;
+	pci_405gp_init(&hose);
+}
+
+#endif
+
+#endif /* CONFIG_PCI */
+
+#endif /* CONFIG_405GP */
+
+/*-----------------------------------------------------------------------------+
+ * CONFIG_440
+ *-----------------------------------------------------------------------------*/
+#if defined(CONFIG_440) && defined(CONFIG_PCI)
+
+static struct pci_controller ppc440_hose = {0};
+
+
+void pci_440_init (struct pci_controller *hose)
+{
+	int reg_num = 0;
+	unsigned long strap;
+
+	/*--------------------------------------------------------------------------+
+	 * The PCI initialization sequence enable bit must be set ... if not abort
+     * pci setup since updating the bit requires chip reset.
+	 *--------------------------------------------------------------------------*/
+    strap = mfdcr(cpc0_strp1);
+    if( (strap & 0x00040000) == 0 ){
+        printf("PCI: CPC0_STRP1[PISE] not set.\n");
+        printf("PCI: Configuration aborted.\n");
+        return;
+    }
+
+	/*--------------------------------------------------------------------------+
+	 * PCI controller init
+	 *--------------------------------------------------------------------------*/
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	pci_set_region(hose->regions + reg_num++,
+		       0x00000000,
+			   PCIX0_IOBASE,
+			   0x10000,
+			   PCI_REGION_IO);
+
+	pci_set_region(hose->regions + reg_num++,
+		       CFG_PCI_TARGBASE,
+			   CFG_PCI_MEMBASE,
+			   0x10000000,
+			   PCI_REGION_MEM );
+	hose->region_count = reg_num;
+
+	pci_setup_indirect(hose, PCIX0_CFGADR, PCIX0_CFGDATA);
+
+#if defined(CFG_PCI_PRE_INIT)
+    /* Let board change/modify hose & do initial checks */
+    if( pci_pre_init (hose) == 0 ){
+        printf("PCI: Board-specific initialization failed.\n");
+        printf("PCI: Configuration aborted.\n");
+        return;
+    }
+#endif
+
+	pci_register_hose( hose );
+
+	/*--------------------------------------------------------------------------+
+	 * PCI target init
+	 *--------------------------------------------------------------------------*/
+#if defined(CFG_PCI_TARGET_INIT)
+	pci_target_init(hose);                /* Let board setup pci target */
+#else
+    out16r( PCIX0_SBSYSVID, CFG_PCI_SUBSYS_VENDORID );
+    out16r( PCIX0_SBSYSID, CFG_PCI_SUBSYS_ID );
+    out16r( PCIX0_CLS, 0x00060000 ); /* Bridge, host bridge */
+#endif
+
+    out32r( PCIX0_BRDGOPT1, 0x10000060 );               /* PLB Rq pri highest   */
+    out32r( PCIX0_BRDGOPT2, in32(PCIX0_BRDGOPT2) | 1 ); /* Enable host config   */
+
+	/*--------------------------------------------------------------------------+
+	 * PCI master init: default is one 256MB region for PCI memory:
+	 * 0x3_00000000 - 0x3_0FFFFFFF  ==> CFG_PCI_MEMBASE
+	 *--------------------------------------------------------------------------*/
+#if defined(CFG_PCI_MASTER_INIT)
+	pci_master_init(hose);          /* Let board setup pci master */
+#else
+	out32r( PCIX0_POM0SA, 0 ); /* disable */
+	out32r( PCIX0_POM1SA, 0 ); /* disable */
+	out32r( PCIX0_POM2SA, 0 ); /* disable */
+	out32r( PCIX0_POM0LAL, 0x00000000 );
+	out32r( PCIX0_POM0LAH, 0x00000003 );
+	out32r( PCIX0_POM0PCIAL, CFG_PCI_MEMBASE );
+	out32r( PCIX0_POM0PCIAH, 0x00000000 );
+	out32r( PCIX0_POM0SA, 0xf0000001 ); /* 256MB, enabled */
+    out32r( PCIX0_STS, in32r( PCIX0_STS ) & ~0x0000fff8 );
+#endif
+
+	/*--------------------------------------------------------------------------+
+	 * PCI host configuration -- we don't make any assumptions here ... the
+     * _board_must_indicate_ what to do -- there's just too many runtime
+     * scenarios in environments like cPCI, PPMC, etc. to make a determination
+     * based on hard-coded values or state of arbiter enable.
+	 *--------------------------------------------------------------------------*/
+    if( is_pci_host(hose) ){
+#ifdef CONFIG_PCI_SCAN_SHOW
+        printf("PCI:   Bus Dev VenId DevId Class Int\n");
+#endif
+        out16r( PCIX0_CMD, in16r( PCIX0_CMD ) | PCI_COMMAND_MASTER);
+        hose->last_busno = pci_hose_scan(hose);
+    }
+}
+
+
+void pci_init(void)
+{
+	pci_440_init (&ppc440_hose);
+}
+
+#endif /* CONFIG_440 & CONFIG_PCI */
diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c
new file mode 100644
index 0000000..8aaffb1
--- /dev/null
+++ b/cpu/ppc4xx/cpu.c
@@ -0,0 +1,253 @@
+/*
+ * (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
+ */
+
+/*
+ * m8xx.c
+ *
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/cache.h>
+#include <ppc4xx.h>
+
+
+#if defined(CONFIG_440)
+static int do_chip_reset( unsigned long sys0, unsigned long sys1 );
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+int checkcpu (void)
+{
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_IOP480) || defined(CONFIG_440)
+	uint pvr = get_pvr();
+#endif
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_IOP480)
+	DECLARE_GLOBAL_DATA_PTR;
+
+	ulong clock = gd->cpu_clk;
+	char buf[32];
+#endif
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR)
+	PPC405_SYS_INFO sys_info;
+
+	puts ("CPU:   ");
+
+	get_sys_info(&sys_info);
+
+#if CONFIG_405GP
+	puts("IBM PowerPC 405GP");
+	if (pvr == PVR_405GPR_RA) {
+		putc('r');
+	}
+	puts(" Rev. ");
+#endif
+#if CONFIG_405CR
+	puts("IBM PowerPC 405CR Rev. ");
+#endif
+	switch (pvr) {
+	case PVR_405GP_RB:
+		putc('B');
+		break;
+	case PVR_405GP_RC:
+#if CONFIG_405CR
+	case PVR_405CR_RC:
+#endif
+		putc('C');
+		break;
+	case PVR_405GP_RD:
+		putc('D');
+		break;
+#if CONFIG_405GP
+	case PVR_405GP_RE:
+		putc('E');
+		break;
+#endif
+	case PVR_405CR_RA:
+	case PVR_405GPR_RA:
+		putc('A');
+		break;
+	case PVR_405CR_RB:
+		putc('B');
+		break;
+	default:
+		printf("? (PVR=%08x)", pvr);
+		break;
+	}
+
+	printf(" at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf, clock),
+	       sys_info.freqPLB / 1000000,
+	       sys_info.freqPLB / sys_info.pllOpbDiv / 1000000,
+	       sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000);
+
+#if CONFIG_405GP
+	if (mfdcr(strap) & PSR_PCI_ASYNC_EN)
+		printf("           PCI async ext clock used, ");
+	else
+		printf("           PCI sync clock at %lu MHz, ",
+		       sys_info.freqPLB / sys_info.pllPciDiv / 1000000);
+	if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+		printf("internal PCI arbiter enabled\n");
+	else
+		printf("external PCI arbiter enabled\n");
+#endif
+
+	if ((pvr | 0x00000001) == PVR_405GPR_RA) {
+		printf("           16 kB I-Cache 16 kB D-Cache");
+	} else {
+		printf("           16 kB I-Cache 8 kB D-Cache");
+	}
+
+
+#endif  /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
+
+#ifdef CONFIG_IOP480
+	printf("PLX IOP480 (PVR=%08x)", pvr);
+	printf(" at %s MHz:", strmhz(buf, clock));
+	printf(" %u kB I-Cache", 4);
+	printf(" %u kB D-Cache", 2);
+#endif
+
+#if defined(CONFIG_440)
+	puts("IBM PowerPC 440 Rev. ");
+	switch(pvr)
+	{
+        case PVR_440GP_RB:
+		putc('B');
+        /* See errata 1.12: CHIP_4 */
+        if(   ( mfdcr(cpc0_sys0) != mfdcr(cpc0_strp0) )
+            ||( mfdcr(cpc0_sys1) != mfdcr(cpc0_strp1) ) ){
+            puts("\n\t CPC0_SYSx DCRs corrupted. Resetting chip ...\n");
+            udelay( 1000 * 1000 ); /* Give time for serial buf to clear */
+            do_chip_reset( mfdcr(cpc0_strp0), mfdcr(cpc0_strp1) );
+        }
+		break;
+        case PVR_440GP_RC:
+		putc('C');
+		break;
+        default:
+		printf("UNKNOWN (PVR=%08x)", pvr);
+		break;
+	}
+#endif
+
+	printf("\n");
+
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+        /*
+         * Initiate system reset in debug control register DBCR
+         */
+	__asm__ __volatile__("lis   3, 0x3000" ::: "r3");
+#if defined(CONFIG_440)
+	__asm__ __volatile__("mtspr 0x134, 3");
+#else
+	__asm__ __volatile__("mtspr 0x3f2, 3");
+#endif
+	return 1;
+}
+
+#if defined(CONFIG_440)
+static
+int do_chip_reset( unsigned long sys0, unsigned long sys1 )
+{
+    /* Changes to cpc0_sys0 and cpc0_sys1 require chip
+     * reset.
+     */
+    mtdcr( cntrl0, mfdcr(cntrl0) | 0x80000000 ); /* Set SWE */
+    mtdcr( cpc0_sys0, sys0 );
+    mtdcr( cpc0_sys1, sys1 );
+    mtdcr( cntrl0, mfdcr(cntrl0) & ~0x80000000 ); /* Clr SWE */
+    mtspr( dbcr0, 0x20000000);  /* Reset the chip */
+
+    return 1;
+}
+#endif
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long get_tbclk (void)
+{
+#if defined(CONFIG_440)
+
+	sys_info_t  sys_info;
+
+	get_sys_info(&sys_info);
+	return (sys_info.freqProcessor);
+
+#elif defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405)
+
+	PPC405_SYS_INFO sys_info;
+
+	get_sys_info(&sys_info);
+	return (sys_info.freqProcessor);
+
+#elif defined(CONFIG_IOP480)
+
+	return (66000000);
+
+#else
+
+# error get_tbclk() not implemented
+
+#endif
+
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void
+watchdog_reset(void)
+{
+	int re_enable = disable_interrupts();
+	reset_4xx_watchdog();
+	if (re_enable) enable_interrupts();
+}
+
+void
+reset_4xx_watchdog(void)
+{
+	/*
+	 * Clear TSR(WIS) bit
+	 */
+	mtspr(tsr, 0x40000000);
+}
+#endif	/* CONFIG_WATCHDOG */
diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c
new file mode 100644
index 0000000..68af057
--- /dev/null
+++ b/cpu/ppc4xx/i2c.c
@@ -0,0 +1,417 @@
+/*****************************************************************************/
+/* I2C Bus interface initialisation and I2C Commands                         */
+/* for PPC405GP		                                                     */
+/* Author : AS HARNOIS                                                       */
+/* Date   : 13.Dec.00                                                        */
+/*****************************************************************************/
+
+#include <common.h>
+#include <ppc4xx.h>
+#if defined(CONFIG_440)
+#   include <440_i2c.h>
+#else
+#   include <405gp_i2c.h>
+#endif
+#include <i2c.h>
+
+#ifdef CONFIG_HARD_I2C
+
+#define IIC_OK		0
+#define IIC_NOK		1
+#define IIC_NOK_LA	2		/* Lost arbitration */
+#define IIC_NOK_ICT	3		/* Incomplete transfer */
+#define IIC_NOK_XFRA	4		/* Transfer aborted */
+#define IIC_NOK_DATA	5		/* No data in buffer */
+#define IIC_NOK_TOUT	6		/* Transfer timeout */
+
+#define IIC_TIMEOUT 1			/* 1 seconde */
+
+
+static void _i2c_bus_reset (void)
+{
+	int i, status;
+
+	/* Reset status register */
+	/* write 1 in SCMP and IRQA to clear these fields */
+	out8 (IIC_STS, 0x0A);
+
+	/* write 1 in IRQP IRQD LA ICT XFRA to clear these fields */
+	out8 (IIC_EXTSTS, 0x8F);
+	__asm__ volatile ("eieio");
+
+	/*
+	 * Get current state, reset bus
+	 * only if no transfers are pending.
+	 */
+	i = 10;
+	do {
+		/* Get status */
+		status = in8 (IIC_STS);
+		udelay (500);			/* 500us */
+		i--;
+	} while ((status & IIC_STS_PT) && (i > 0));
+	/* Soft reset controller */
+	status = in8 (IIC_XTCNTLSS);
+	out8 (IIC_XTCNTLSS, (status | IIC_XTCNTLSS_SRST));
+	__asm__ volatile ("eieio");
+
+	/* make sure where in initial state, data hi, clock hi */
+	out8 (IIC_DIRECTCNTL, 0xC);
+	for (i = 0; i < 10; i++) {
+		if ((in8 (IIC_DIRECTCNTL) & 0x3) != 0x3) {
+			/* clock until we get to known state */
+			out8 (IIC_DIRECTCNTL, 0x8);	/* clock lo */
+			udelay (100);		/* 100us */
+			out8 (IIC_DIRECTCNTL, 0xC);	/* clock hi */
+			udelay (100);		/* 100us */
+		} else {
+			break;
+		}
+	}
+	/* send start condition */
+	out8 (IIC_DIRECTCNTL, 0x4);
+	udelay (1000);				/* 1ms */
+	/* send stop condition */
+	out8 (IIC_DIRECTCNTL, 0xC);
+	udelay (1000);				/* 1ms */
+	/* Unreset controller */
+	out8 (IIC_XTCNTLSS, (status & ~IIC_XTCNTLSS_SRST));
+	udelay (1000);				/* 1ms */
+}
+
+void i2c_init (int speed, int slaveadd)
+{
+	sys_info_t sysInfo;
+	unsigned long freqOPB;
+	int val, divisor;
+
+	/* Handle possible failed I2C state */
+	_i2c_bus_reset ();
+
+	/* clear lo master address */
+	out8 (IIC_LMADR, 0);
+
+	/* clear hi master address */
+	out8 (IIC_HMADR, 0);
+
+	/* clear lo slave address */
+	out8 (IIC_LSADR, 0);
+
+	/* clear hi slave address */
+	out8 (IIC_HSADR, 0);
+
+	/* Clock divide Register */
+	/* get OPB frequency */
+	get_sys_info (&sysInfo);
+	freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv;
+	/* set divisor according to freqOPB */
+	divisor = (freqOPB - 1) / 10000000;
+	if (divisor == 0)
+		divisor = 1;
+	out8 (IIC_CLKDIV, divisor);
+
+	/* no interrupts */
+	out8 (IIC_INTRMSK, 0);
+
+	/* clear transfer count */
+	out8 (IIC_XFRCNT, 0);
+
+	/* clear extended control & stat */
+	/* write 1 in SRC SRS SWC SWS to clear these fields */
+	out8 (IIC_XTCNTLSS, 0xF0);
+
+	/* Mode Control Register
+	   Flush Slave/Master data buffer */
+	out8 (IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB);
+	__asm__ volatile ("eieio");
+
+
+        val = in8(IIC_MDCNTL);
+        __asm__ volatile ("eieio");
+
+        /* Ignore General Call, slave transfers are ignored,
+           disable interrupts, exit unknown bus state, enable hold
+           SCL
+           100kHz normaly or FastMode for 400kHz and above
+        */
+
+        val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL;
+        if( speed >= 400000 ){
+                val |= IIC_MDCNTL_FSM;
+        }
+	out8 (IIC_MDCNTL, val);
+
+	/* clear control reg */
+	out8 (IIC_CNTL, 0x00);
+	__asm__ volatile ("eieio");
+
+}
+
+/*
+  This code tries to use the features of the 405GP i2c
+  controller. It will transfer up to 4 bytes in one pass
+  on the loop. It only does out8(lbz) to the buffer when it
+  is possible to do out16(lhz) transfers.
+
+  cmd_type is 0 for write 1 for read.
+
+  addr_len can take any value from 0-255, it is only limited
+  by the char, we could make it larger if needed. If it is
+  0 we skip the address write cycle.
+
+  Typical case is a Write of an addr followd by a Read. The
+  IBM FAQ does not cover this. On the last byte of the write
+  we don't set the creg CHT bit, and on the first bytes of the
+  read we set the RPST bit.
+
+  It does not support address only transfers, there must be
+  a data part. If you want to write the address yourself, put
+  it in the data pointer.
+
+  It does not support transfer to/from address 0.
+
+  It does not check XFRCNT.
+*/
+static
+int i2c_transfer(unsigned char cmd_type,
+                 unsigned char chip,
+                 unsigned char addr[],
+                 unsigned char addr_len,
+                 unsigned char data[],
+		 unsigned short data_len )
+{
+        unsigned char* ptr;
+        int reading;
+        int tran,cnt;
+        int result;
+        int status;
+        int i;
+        uchar creg;
+
+        if( data == 0 || data_len == 0 ){
+                /*Don't support data transfer of no length or to address 0*/
+                printf( "i2c_transfer: bad call\n" );
+                return IIC_NOK;
+        }
+        if( addr && addr_len ){
+                ptr = addr;
+                cnt = addr_len;
+                reading = 0;
+        }else{
+                ptr = data;
+                cnt = data_len;
+                reading = cmd_type;
+        }
+
+        /*Clear Stop Complete Bit*/
+        out8(IIC_STS,IIC_STS_SCMP);
+        /* Check init */
+        i=10;
+        do {
+                /* Get status */
+                status = in8(IIC_STS);
+                __asm__ volatile("eieio");
+                i--;
+        } while ((status & IIC_STS_PT) && (i>0));
+
+        if (status & IIC_STS_PT) {
+                result = IIC_NOK_TOUT;
+                return(result);
+        }
+        /*flush the Master/Slave Databuffers*/
+        out8(IIC_MDCNTL, ((in8(IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB));
+        /*need to wait 4 OPB clocks? code below should take that long*/
+
+        /* 7-bit adressing */
+        out8(IIC_HMADR,0);
+        out8(IIC_LMADR, chip);
+        __asm__ volatile("eieio");
+
+        tran = 0;
+        result = IIC_OK;
+        creg = 0;
+
+        while ( tran != cnt && (result == IIC_OK)) {
+                int  bc,j;
+
+                /* Control register =
+                   Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start,
+                   Transfer is a sequence of transfers
+                */
+                creg |= IIC_CNTL_PT;
+
+                bc = (cnt - tran) > 4 ? 4 :
+                        cnt - tran;
+                creg |= (bc-1)<<4;
+                /* if the real cmd type is write continue trans*/
+                if ( (!cmd_type && (ptr == addr)) || ((tran+bc) != cnt) )
+                        creg |= IIC_CNTL_CHT;
+
+                if (reading)
+                        creg |= IIC_CNTL_READ;
+                else {
+                        for(j=0; j<bc; j++) {
+                                /* Set buffer */
+                                out8(IIC_MDBUF,ptr[tran+j]);
+                                __asm__ volatile("eieio");
+                        }
+                }
+                out8(IIC_CNTL, creg );
+                __asm__ volatile("eieio");
+
+                /* Transfer is in progress
+                   we have to wait for upto 5 bytes of data
+                   1 byte chip address+r/w bit then bc bytes
+                   of data.
+                   udelay(10) is 1 bit time at 100khz
+                   Doubled for slop. 20 is too small.
+		*/
+                i=2*5*8;
+                do {
+                        /* Get status */
+                        status = in8(IIC_STS);
+                        __asm__ volatile("eieio");
+                        udelay (10);
+                        i--;
+                } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR)
+			 && (i>0));
+
+                if (status & IIC_STS_ERR) {
+                        result = IIC_NOK;
+                        status = in8 (IIC_EXTSTS);
+                        /* Lost arbitration? */
+                        if (status & IIC_EXTSTS_LA)
+                                result = IIC_NOK_LA;
+                        /* Incomplete transfer? */
+                        if (status & IIC_EXTSTS_ICT)
+                                result = IIC_NOK_ICT;
+                        /* Transfer aborted? */
+                        if (status & IIC_EXTSTS_XFRA)
+                                result = IIC_NOK_XFRA;
+                } else if ( status & IIC_STS_PT) {
+                        result = IIC_NOK_TOUT;
+                }
+                /* Command is reading => get buffer */
+                if ((reading) && (result == IIC_OK)) {
+                        /* Are there data in buffer */
+                        if (status & IIC_STS_MDBS) {
+                                /*
+                                  even if we have data we have to wait 4OPB clocks
+                                  for it to hit the front of the FIFO, after that
+                                  we can just read. We should check XFCNT here and
+                                  if the FIFO is full there is no need to wait.
+				*/
+                                udelay (1);
+                                for(j=0;j<bc;j++) {
+                                        ptr[tran+j] = in8(IIC_MDBUF);
+                                        __asm__ volatile("eieio");
+                                }
+                        } else
+                                result = IIC_NOK_DATA;
+                }
+                creg = 0;
+                tran+=bc;
+                if( ptr == addr && tran == cnt ) {
+                        ptr = data;
+                        cnt = data_len;
+                        tran = 0;
+                        reading = cmd_type;
+                        if( reading )
+                                creg = IIC_CNTL_RPST;
+                }
+        }
+        return (result);
+}
+
+int i2c_probe (uchar chip)
+{
+	uchar buf[1];
+
+	buf[0] = 0;
+
+        /*
+         * What is needed is to send the chip address and verify that the
+         * address was <ACK>ed (i.e. there was a chip at that address which
+         * drove the data line low).
+         */
+        return(i2c_transfer (1, chip << 1, 0,0, buf, 1) != 0);
+}
+
+
+
+int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+        uchar xaddr[4];
+        int ret;
+
+	if ( alen > 4 ) {
+		printf ("I2C read: addr len %d not supported\n", alen);
+		return 1;
+	}
+
+        if ( alen > 0 ) {
+                xaddr[0] = (addr >> 24) & 0xFF;
+                xaddr[1] = (addr >> 16) & 0xFF;
+                xaddr[2] = (addr >> 8) & 0xFF;
+                xaddr[3] = addr & 0xFF;
+        }
+
+
+#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
+	/*
+         * EEPROM chips that implement "address overflow" are ones
+         * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
+         * address and the extra bits end up in the "chip address"
+         * bit slots. This makes a 24WC08 (1Kbyte) chip look like
+         * four 256 byte chips.
+	 *
+         * Note that we consider the length of the address field to
+         * still be one byte because the extra address bits are
+         * hidden in the chip address.
+	 */
+        if( alen > 0 )
+                chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+        if( (ret = i2c_transfer( 1, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) {
+                printf( "I2c read: failed %d\n", ret);
+                return 1;
+        }
+        return 0;
+}
+
+int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+        uchar xaddr[4];
+
+	if ( alen > 4 ) {
+		printf ("I2C write: addr len %d not supported\n", alen);
+		return 1;
+
+	}
+        if ( alen > 0 ) {
+                xaddr[0] = (addr >> 24) & 0xFF;
+                xaddr[1] = (addr >> 16) & 0xFF;
+                xaddr[2] = (addr >> 8) & 0xFF;
+                xaddr[3] = addr & 0xFF;
+        }
+
+#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
+	/*
+         * EEPROM chips that implement "address overflow" are ones
+         * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
+         * address and the extra bits end up in the "chip address"
+         * bit slots. This makes a 24WC08 (1Kbyte) chip look like
+         * four 256 byte chips.
+	 *
+         * Note that we consider the length of the address field to
+         * still be one byte because the extra address bits are
+         * hidden in the chip address.
+	 */
+        if( alen > 0 )
+                chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+        return (i2c_transfer( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
+}
+
+#endif	/* CONFIG_HARD_I2C */
diff --git a/cpu/ppc4xx/sdram.c b/cpu/ppc4xx/sdram.c
new file mode 100644
index 0000000..d64bf96
--- /dev/null
+++ b/cpu/ppc4xx/sdram.c
@@ -0,0 +1,191 @@
+/*
+ * (C) Copyright 2002
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <ppc4xx.h>
+#include <asm/processor.h>
+#include <pci.h>
+
+
+#ifdef CONFIG_SDRAM_BANK0
+
+
+#define MAGIC0 0x00000000
+#define MAGIC1 0x11111111
+#define MAGIC2 0x22222222
+#define MAGIC3 0x33333333
+#define MAGIC4 0x44444444
+
+#define ADDR_ZERO 0x00000000
+#define ADDR_400  0x00000400
+#define ADDR_08MB 0x00800000
+#define ADDR_16MB 0x01000000
+#define ADDR_32MB 0x02000000
+#define ADDR_64MB 0x04000000
+
+#define mtsdram0(reg, data)  mtdcr(memcfga,reg);mtdcr(memcfgd,data)
+
+
+/*-----------------------------------------------------------------------
+ */
+void sdram_init(void)
+{
+	ulong speed;
+	ulong sdtr1;
+	ulong rtr;
+
+	/*
+	 * Determine SDRAM speed
+	 */
+	speed = get_bus_freq(0); /* parameter not used on ppc4xx */
+
+	/*
+	 * Support for 100MHz and 133MHz SDRAM
+	 */
+	if (speed > 100000000) {
+		/*
+		 * 133 MHz SDRAM
+		 */
+		sdtr1 = 0x01074015;
+		rtr = 0x07f00000;
+	} else {
+		/*
+		 * default: 100 MHz SDRAM
+		 */
+		sdtr1 = 0x0086400d;
+		rtr = 0x05f00000;
+	}
+
+	/*
+	 * Set MB0CF for bank 0. (0-64MB) Address Mode 3 since 13x9(4)
+	 */
+	mtsdram0(mem_mb0cf, 0x00084001);
+
+	mtsdram0(mem_sdtr1, sdtr1);
+	mtsdram0(mem_rtr, rtr);
+
+	/*
+	 * Wait for 200us
+	 */
+	udelay(200);
+
+	/*
+	 * Set memory controller options reg, MCOPT1.
+	 * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
+	 * read/prefetch.
+	 */
+	mtsdram0(mem_mcopt1, 0x80800000);
+
+	/*
+	 * Wait for 10ms
+	 */
+	udelay(10000);
+
+	/*
+	 * Test if 64 MByte are equipped (mirror test)
+	 */
+	*(volatile ulong *)ADDR_ZERO = MAGIC0;
+	*(volatile ulong *)ADDR_08MB = MAGIC1;
+	*(volatile ulong *)ADDR_16MB = MAGIC2;
+	*(volatile ulong *)ADDR_32MB = MAGIC3;
+
+	if ((*(volatile ulong *)ADDR_ZERO == MAGIC0) &&
+	    (*(volatile ulong *)ADDR_08MB == MAGIC1) &&
+	    (*(volatile ulong *)ADDR_16MB == MAGIC2)) {
+		/*
+		 * OK, 64MB detected -> all done
+		 */
+		return;
+	}
+
+	/*
+	 * Now test for 32 MByte...
+	 */
+
+        /*
+	 * Disable memory controller.
+	 */
+	mtsdram0(mem_mcopt1, 0x00000000);
+
+	/*
+	 * Set MB0CF for bank 0. (0-32MB) Address Mode 2 since 12x9(4)
+	 */
+	mtsdram0(mem_mb0cf, 0x00062001);
+
+	/*
+	 * Set memory controller options reg, MCOPT1.
+	 * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
+	 * read/prefetch.
+	 */
+	mtsdram0(mem_mcopt1, 0x80800000);
+
+	/*
+	 * Wait for 10ms
+	 */
+	udelay(10000);
+
+	/*
+	 * Test if 32 MByte are equipped (mirror test)
+	 */
+	*(volatile ulong *)ADDR_ZERO = MAGIC0;
+	*(volatile ulong *)ADDR_400  = MAGIC1;
+	*(volatile ulong *)ADDR_08MB = MAGIC2;
+	*(volatile ulong *)ADDR_16MB = MAGIC3;
+
+	if ((*(volatile ulong *)ADDR_ZERO == MAGIC0) &&
+	    (*(volatile ulong *)ADDR_400  == MAGIC1) &&
+	    (*(volatile ulong *)ADDR_08MB == MAGIC2)) {
+		/*
+		 * OK, 32MB detected -> all done
+		 */
+		return;
+	}
+
+	/*
+	 * Setup for 16 MByte...
+	 */
+
+        /*
+	 * Disable memory controller.
+	 */
+	mtsdram0(mem_mcopt1, 0x00000000);
+
+	/*
+	 * Set MB0CF for bank 0. (0-16MB) Address Mode 4 since 12x8(4)
+	 */
+	mtsdram0(mem_mb0cf, 0x00046001);
+
+	/*
+	 * Set memory controller options reg, MCOPT1.
+	 * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
+	 * read/prefetch.
+	 */
+	mtsdram0(mem_mcopt1, 0x80800000);
+
+	/*
+	 * Wait for 10ms
+	 */
+	udelay(10000);
+}
+
+#endif /* CONFIG_SDRAM_BANK0 */
diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c
new file mode 100644
index 0000000..4541529
--- /dev/null
+++ b/cpu/ppc4xx/speed.c
@@ -0,0 +1,308 @@
+/*
+ * (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 <ppc_asm.tmpl>
+#include <ppc4xx.h>
+#include <asm/processor.h>
+
+/* ------------------------------------------------------------------------- */
+
+#define ONE_BILLION        1000000000
+
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR)
+
+void get_sys_info (PPC405_SYS_INFO * sysInfo)
+{
+	unsigned long pllmr;
+	unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
+	uint pvr = get_pvr();
+	unsigned long psr;
+	unsigned long m;
+
+	/*
+	 * Read PLL Mode register
+	 */
+	pllmr = mfdcr (pllmd);
+
+	/*
+	 * Read Pin Strapping register
+	 */
+	psr = mfdcr (strap);
+
+	/*
+	 * Determine FWD_DIV.
+	 */
+	sysInfo->pllFwdDiv = 8 - ((pllmr & PLLMR_FWD_DIV_MASK) >> 29);
+
+	/*
+	 * Determine FBK_DIV.
+	 */
+	sysInfo->pllFbkDiv = ((pllmr & PLLMR_FB_DIV_MASK) >> 25);
+	if (sysInfo->pllFbkDiv == 0) {
+		sysInfo->pllFbkDiv = 16;
+	}
+
+	/*
+	 * Determine PLB_DIV.
+	 */
+	sysInfo->pllPlbDiv = ((pllmr & PLLMR_CPU_TO_PLB_MASK) >> 17) + 1;
+
+	/*
+	 * Determine PCI_DIV.
+	 */
+	sysInfo->pllPciDiv = ((pllmr & PLLMR_PCI_TO_PLB_MASK) >> 13) + 1;
+
+	/*
+	 * Determine EXTBUS_DIV.
+	 */
+	sysInfo->pllExtBusDiv = ((pllmr & PLLMR_EXB_TO_PLB_MASK) >> 11) + 2;
+
+	/*
+	 * Determine OPB_DIV.
+	 */
+	sysInfo->pllOpbDiv = ((pllmr & PLLMR_OPB_TO_PLB_MASK) >> 15) + 1;
+
+	/*
+	 * Check if PPC405GPr used (mask minor revision field)
+	 */
+	if ((pvr & 0xfffffff0) == (PVR_405GPR_RA & 0xfffffff0)) {
+		/*
+		 * Determine FWD_DIV B (only PPC405GPr with new mode strapping).
+		 */
+		sysInfo->pllFwdDivB = 8 - (pllmr & PLLMR_FWDB_DIV_MASK);
+
+		/*
+		 * Determine factor m depending on PLL feedback clock source
+		 */
+		if (!(psr & PSR_PCI_ASYNC_EN)) {
+			if (psr & PSR_NEW_MODE_EN) {
+				/*
+				 * sync pci clock used as feedback (new mode)
+				 */
+				m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllPciDiv;
+			} else {
+				/*
+				 * sync pci clock used as feedback (legacy mode)
+				 */
+				m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllPciDiv;
+			}
+		} else if (psr & PSR_NEW_MODE_EN) {
+			if (psr & PSR_PERCLK_SYNC_MODE_EN) {
+				/*
+				 * PerClk used as feedback (new mode)
+				 */
+				m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllExtBusDiv;
+			} else {
+				/*
+				 * CPU clock used as feedback (new mode)
+				 */
+				m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
+			}
+		} else if (sysInfo->pllExtBusDiv == sysInfo->pllFbkDiv) {
+			/*
+			 * PerClk used as feedback (legacy mode)
+			 */
+			m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllExtBusDiv;
+		} else {
+			/*
+			 * PLB clock used as feedback (legacy mode)
+			 */
+			m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv;
+		}
+
+		sysInfo->freqVCOMhz = (1000000 * m) / sysClkPeriodPs;
+		sysInfo->freqProcessor = (sysInfo->freqVCOMhz * 1000000) / sysInfo->pllFwdDiv;
+		sysInfo->freqPLB = (sysInfo->freqVCOMhz * 1000000) /
+			(sysInfo->pllFwdDivB * sysInfo->pllPlbDiv);
+	} else {
+		/*
+		 * Check pllFwdDiv to see if running in bypass mode where the CPU speed
+		 * is equal to the 405GP SYS_CLK_FREQ. If not in bypass mode, check VCO
+		 * to make sure it is within the proper range.
+		 *    spec:    VCO = SYS_CLOCK x FBKDIV x PLBDIV x FWDDIV
+		 * Note freqVCO is calculated in Mhz to avoid errors introduced by rounding.
+		 */
+		if (sysInfo->pllFwdDiv == 1) {
+			sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ;
+			sysInfo->freqPLB = CONFIG_SYS_CLK_FREQ / sysInfo->pllPlbDiv;
+		} else {
+			sysInfo->freqVCOMhz = ( 1000000 *
+						sysInfo->pllFwdDiv *
+						sysInfo->pllFbkDiv *
+						sysInfo->pllPlbDiv
+				) / sysClkPeriodPs;
+			if (sysInfo->freqVCOMhz >= VCO_MIN
+			    && sysInfo->freqVCOMhz <= VCO_MAX) {
+				sysInfo->freqPLB = (ONE_BILLION /
+						    ((sysClkPeriodPs * 10) /
+						     sysInfo->pllFbkDiv)) * 10000;
+				sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv;
+			} else {
+				printf ("\nInvalid VCO frequency calculated :  %ld MHz \a\n",
+					sysInfo->freqVCOMhz);
+				printf ("It must be between %d-%d MHz \a\n",
+					VCO_MIN, VCO_MAX);
+				printf ("PLL Mode reg           :  %8.8lx\a\n",
+					pllmr);
+				hang ();
+			}
+		}
+	}
+}
+
+
+/********************************************
+ * get_OPB_freq
+ * return OPB bus freq in Hz
+ *********************************************/
+ulong get_OPB_freq (void)
+{
+	ulong val = 0;
+
+	PPC405_SYS_INFO sys_info;
+
+	get_sys_info (&sys_info);
+	val = sys_info.freqPLB / sys_info.pllOpbDiv;
+
+	return val;
+}
+
+
+/********************************************
+ * get_PCI_freq
+ * return PCI bus freq in Hz
+ *********************************************/
+ulong get_PCI_freq (void)
+{
+	ulong val;
+	PPC405_SYS_INFO sys_info;
+
+	get_sys_info (&sys_info);
+	val = sys_info.freqPLB / sys_info.pllPciDiv;
+	return val;
+}
+
+
+#elif defined(CONFIG_440)
+void get_sys_info (sys_info_t * sysInfo)
+{
+	unsigned long strp0;
+	unsigned long temp;
+	unsigned long m;
+
+	/* Extract configured divisors */
+	strp0 = mfdcr( cpc0_strp0 );
+	sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15);
+	sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12);
+	temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18;
+	sysInfo->pllFbkDiv = temp ? temp : 16;
+	sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10);
+	sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8);
+
+	/* Calculate 'M' based on feedback source */
+	if( strp0 & PLLSYS0_EXTSL_MASK )
+		m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
+	else
+		m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
+
+	/* Now calculate the individual clocks */
+	sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
+	sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+	sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
+    if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
+        sysInfo->freqPLB >>= 1;
+	sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+	sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
+
+}
+
+ulong get_OPB_freq (void)
+{
+
+	sys_info_t sys_info;
+	get_sys_info (&sys_info);
+	return sys_info.freqOPB;
+}
+
+#elif defined(CONFIG_405)
+
+void get_sys_info (sys_info_t * sysInfo) {
+
+	sysInfo->freqVCOMhz=3125000;
+	sysInfo->freqProcessor=12*1000*1000;
+	sysInfo->freqPLB=50*1000*1000;
+	sysInfo->freqPCI=66*1000*1000;
+
+}
+
+#endif
+
+int get_clocks (void)
+{
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) || defined(CONFIG_405)
+	DECLARE_GLOBAL_DATA_PTR;
+
+	sys_info_t sys_info;
+
+	get_sys_info (&sys_info);
+	gd->cpu_clk = sys_info.freqProcessor;
+	gd->bus_clk = sys_info.freqPLB;
+
+#endif	/* defined(CONFIG_405GP) || defined(CONFIG_405CR) */
+
+#ifdef CONFIG_IOP480
+	DECLARE_GLOBAL_DATA_PTR;
+
+	gd->cpu_clk = 66000000;
+	gd->bus_clk = 66000000;
+#endif
+	return (0);
+}
+
+
+/********************************************
+ * get_bus_freq
+ * return PLB bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+	ulong val;
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405) || defined(CONFIG_440)
+	sys_info_t sys_info;
+
+	get_sys_info (&sys_info);
+	val = sys_info.freqPLB;
+
+#elif defined(CONFIG_IOP480)
+
+	val = 66;
+
+#else
+# error get_bus_freq() not implemented
+#endif
+
+	return val;
+}
diff --git a/cpu/ppc4xx/vecnum.h b/cpu/ppc4xx/vecnum.h
new file mode 100644
index 0000000..d493a5d
--- /dev/null
+++ b/cpu/ppc4xx/vecnum.h
@@ -0,0 +1,100 @@
+/*
+*  Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.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
+*/
+
+/*
+ * Interrupt vector number definitions to ease the
+ * 405 -- 440 porting pain ;-)
+ *
+ * NOTE: They're not all here yet ... update as needed.
+ *
+ */
+
+#ifndef _VECNUMS_H_
+#define _VECNUMS_H_
+
+#if defined(CONFIG_440)
+
+/* UIC 0 */
+#define VECNUM_U0           0           /* UART0                        */
+#define VECNUM_U1           1           /* UART1                        */
+#define VECNUM_IIC0         2           /* IIC0                         */
+#define VECNUM_IIC1         3           /* IIC1                         */
+#define VECNUM_PIM          4           /* PCI inbound message          */
+#define VECNUM_PCRW         5           /* PCI command reg write        */
+#define VECNUM_PPM          6           /* PCI power management         */
+#define VECNUM_MSI0         7           /* PCI MSI level 0              */
+#define VECNUM_MSI1         8           /* PCI MSI level 0              */
+#define VECNUM_MSI2         9           /* PCI MSI level 0              */
+#define VECNUM_MTE          10          /* MAL TXEOB                    */
+#define VECNUM_MRE          11          /* MAL RXEOB                    */
+#define VECNUM_D0           12          /* DMA channel 0                */
+#define VECNUM_D1           13          /* DMA channel 1                */
+#define VECNUM_D2           14          /* DMA channel 2                */
+#define VECNUM_D3           15          /* DMA channel 3                */
+#define VECNUM_CT0          18          /* GPT compare timer 0          */
+#define VECNUM_CT1          19          /* GPT compare timer 1          */
+#define VECNUM_CT2          20          /* GPT compare timer 2          */
+#define VECNUM_CT3          21          /* GPT compare timer 3          */
+#define VECNUM_CT4          22          /* GPT compare timer 4          */
+#define VECNUM_EIR0         23          /* External interrupt 0         */
+#define VECNUM_EIR1         24          /* External interrupt 1         */
+#define VECNUM_EIR2         25          /* External interrupt 2         */
+#define VECNUM_EIR3         26          /* External interrupt 3         */
+#define VECNUM_EIR4         27          /* External interrupt 4         */
+#define VECNUM_EIR5         28          /* External interrupt 5         */
+#define VECNUM_EIR6         29          /* External interrupt 6         */
+#define VECNUM_UIC1NC       30          /* UIC1 non-critical interrupt  */
+#define VECNUM_UIC1C        31          /* UIC1 critical interrupt      */
+
+/* UIC 1 */
+#define VECNUM_MS           (32 + 0 )   /* MAL SERR                     */
+#define VECNUM_TXDE         (32 + 1 )   /* MAL TXDE                     */
+#define VECNUM_RXDE         (32 + 2 )   /* MAL RXDE                     */
+#define VECNUM_ETH0         (32 + 28)   /* Ethernet 0 interrupt status  */
+#define VECNUM_EWU0         (32 + 29)   /* Ethernet 0 wakeup            */
+
+#else /* !defined(CONFIG_440) */
+
+#define VECNUM_U0           0           /* UART0                        */
+#define VECNUM_U1           1           /* UART1                        */
+#define VECNUM_D0           5           /* DMA channel 0                */
+#define VECNUM_D1           6           /* DMA channel 1                */
+#define VECNUM_D2           7           /* DMA channel 2                */
+#define VECNUM_D3           8           /* DMA channel 3                */
+#define VECNUM_EWU0         9           /* Ethernet wakeup              */
+#define VECNUM_MS           10          /* MAL SERR                     */
+#define VECNUM_MTE          11          /* MAL TXEOB                    */
+#define VECNUM_MRE          12          /* MAL RXEOB                    */
+#define VECNUM_TXDE         13          /* MAL TXDE                     */
+#define VECNUM_RXDE         14          /* MAL RXDE                     */
+#define VECNUM_ETH0         15          /* Ethernet interrupt status    */
+#define VECNUM_EIR0         25          /* External interrupt 0         */
+#define VECNUM_EIR1         26          /* External interrupt 1         */
+#define VECNUM_EIR2         27          /* External interrupt 2         */
+#define VECNUM_EIR3         28          /* External interrupt 3         */
+#define VECNUM_EIR4         29          /* External interrupt 4         */
+#define VECNUM_EIR5         30          /* External interrupt 5         */
+#define VECNUM_EIR6         31          /* External interrupt 6         */
+
+#endif /* defined(CONFIG_440) */
+
+#endif /* _VECNUMS_H_ */