ppc4xx: Fix 460EX errata with CPU lockup upon high AHB traffic
[oweals/u-boot.git] / cpu / ppc4xx / 4xx_enet.c
index 697e038d5eb43767febff9e1d05f8051e137391a..c40e0ca48098bfbf4d22af3214c67efba47b6fcd 100644 (file)
 #include <net.h>
 #include <asm/processor.h>
 #include <asm/io.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
 #include <commproc.h>
 #include <ppc4xx.h>
 #include <ppc4xx_enet.h>
 #include <405_mal.h>
 #include <miiphy.h>
 #include <malloc.h>
-#include "vecnum.h"
+#include <asm/ppc4xx-intvec.h>
 
 /*
  * Only compile for platform with AMCC EMAC ethernet controller and
 #define BI_PHYMODE_RTBI  4
 #define BI_PHYMODE_TBI   5
 #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 #define BI_PHYMODE_SMII  6
 #define BI_PHYMODE_MII   7
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define BI_PHYMODE_RMII  8
+#endif
 #endif
 
 #if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 #define SDR0_MFR_ETH_CLK_SEL_V(n)      ((0x01<<27) / (n+1))
 #endif
 
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define SDR0_ETH_CFG_CLK_SEL_V(n)      (0x01 << (8 + n))
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define MAL_RX_CHAN_MUL        8       /* 460EX/GT uses MAL channel 8 for EMAC1 */
+#else
+#define MAL_RX_CHAN_MUL        1
+#endif
+
 /*-----------------------------------------------------------------------------+
  * Global variables. TX and RX descriptors and buffers.
  *-----------------------------------------------------------------------------*/
@@ -189,6 +206,10 @@ struct eth_device *emac0_dev = NULL;
 #define ETH_IRQ_NUM(dev)       (VECNUM_ETH0 + ((dev) * 2))
 #endif
 
+#define MAL_RX_DESC_SIZE       2048
+#define MAL_TX_DESC_SIZE       2048
+#define MAL_ALLOC_SIZE         (MAL_TX_DESC_SIZE + MAL_RX_DESC_SIZE)
+
 /*-----------------------------------------------------------------------------+
  * Prototypes and externals.
  *-----------------------------------------------------------------------------*/
@@ -208,6 +229,44 @@ extern int emac4xx_miiphy_write (char *devname, unsigned char addr,
 
 int board_emac_count(void);
 
+static void emac_loopback_enable(EMAC_4XX_HW_PST hw_p)
+{
+#if defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_405EX)
+       u32 val;
+
+       mfsdr(sdr_mfr, val);
+       val |= SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
+       mtsdr(sdr_mfr, val);
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+       u32 val;
+
+       mfsdr(SDR0_ETH_CFG, val);
+       val |= SDR0_ETH_CFG_CLK_SEL_V(hw_p->devnum);
+       mtsdr(SDR0_ETH_CFG, val);
+#endif
+}
+
+static void emac_loopback_disable(EMAC_4XX_HW_PST hw_p)
+{
+#if defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_405EX)
+       u32 val;
+
+       mfsdr(sdr_mfr, val);
+       val &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
+       mtsdr(sdr_mfr, val);
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+       u32 val;
+
+       mfsdr(SDR0_ETH_CFG, val);
+       val &= ~SDR0_ETH_CFG_CLK_SEL_V(hw_p->devnum);
+       mtsdr(SDR0_ETH_CFG, val);
+#endif
+}
+
 /*-----------------------------------------------------------------------------+
 | ppc_4xx_eth_halt
 | Disable MAL channel, and EMACn
@@ -215,12 +274,7 @@ int board_emac_count(void);
 static void ppc_4xx_eth_halt (struct eth_device *dev)
 {
        EMAC_4XX_HW_PST hw_p = dev->priv;
-       uint32_t failsafe = 10000;
-#if defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
-       unsigned long mfr;
-#endif
+       u32 val = 10000;
 
        out_be32((void *)EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */
 
@@ -236,37 +290,31 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
        /* wait for reset */
        while (mfdcr (malrxcasr) & (MAL_CR_MMSR >> hw_p->devnum)) {
                udelay (1000);  /* Delay 1 MS so as not to hammer the register */
-               failsafe--;
-               if (failsafe == 0)
+               val--;
+               if (val == 0)
                        break;
        }
 
-       /* EMAC RESET */
-#if defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
        /* provide clocks for EMAC internal loopback  */
-       mfsdr (sdr_mfr, mfr);
-       mfr |= SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
-       mtsdr(sdr_mfr, mfr);
-#endif
+       emac_loopback_enable(hw_p);
 
+       /* EMAC RESET */
        out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
 
-#if defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
        /* remove clocks for EMAC internal loopback  */
-       mfsdr (sdr_mfr, mfr);
-       mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
-       mtsdr(sdr_mfr, mfr);
-#endif
-
+       emac_loopback_disable(hw_p);
 
 #ifndef CONFIG_NETCONSOLE
        hw_p->print_speed = 1;  /* print speed message again next time */
 #endif
 
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+       /* don't bypass the TAHOE0/TAHOE1 cores for Linux */
+       mfsdr(SDR0_ETH_CFG, val);
+       val &= ~(SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS);
+       mtsdr(SDR0_ETH_CFG, val);
+#endif
+
        return;
 }
 
@@ -354,8 +402,8 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
        /* Ensure we setup mdio for this devnum and ONLY this devnum */
        zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum);
 
-       out_be32(ZMII_FER, zmiifer);
-       out_be32(RGMII_FER, rmiifer);
+       out_be32((void *)ZMII_FER, zmiifer);
+       out_be32((void *)RGMII_FER, rmiifer);
 
        return ((int)pfc1);
 }
@@ -446,9 +494,203 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
 }
 #endif  /* CONFIG_405EX */
 
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
+{
+       u32 eth_cfg;
+       u32 zmiifer;            /* ZMII0_FER reg. */
+       u32 rmiifer;            /* RGMII0_FER reg. Bridge 0 */
+       u32 rmiifer1;           /* RGMII0_FER reg. Bridge 1 */
+       int mode;
+
+       zmiifer  = 0;
+       rmiifer  = 0;
+       rmiifer1 = 0;
+
+#if defined(CONFIG_460EX)
+       mode = 9;
+#else
+       mode = 10;
+#endif
+
+       /* TODO:
+        * NOTE: 460GT has 2 RGMII bridge cores:
+        *              emac0 ------ RGMII0_BASE
+        *                         |
+        *              emac1 -----+
+        *
+        *              emac2 ------ RGMII1_BASE
+        *                         |
+        *              emac3 -----+
+        *
+        *      460EX has 1 RGMII bridge core:
+        *      and RGMII1_BASE is disabled
+        *              emac0 ------ RGMII0_BASE
+        *                         |
+        *              emac1 -----+
+        */
+
+       /*
+        * Right now only 2*RGMII is supported. Please extend when needed.
+        * sr - 2008-02-19
+        */
+       switch (mode) {
+       case 1:
+               /* 1 MII - 460EX */
+               /* GMC0 EMAC4_0, ZMII Bridge */
+               zmiifer |= ZMII_FER_MII << ZMII_FER_V(0);
+               bis->bi_phymode[0] = BI_PHYMODE_MII;
+               bis->bi_phymode[1] = BI_PHYMODE_NONE;
+               bis->bi_phymode[2] = BI_PHYMODE_NONE;
+               bis->bi_phymode[3] = BI_PHYMODE_NONE;
+               break;
+       case 2:
+               /* 2 MII - 460GT */
+               /* GMC0 EMAC4_0, GMC1 EMAC4_2, ZMII Bridge */
+               zmiifer |= ZMII_FER_MII << ZMII_FER_V(0);
+               zmiifer |= ZMII_FER_MII << ZMII_FER_V(2);
+               bis->bi_phymode[0] = BI_PHYMODE_MII;
+               bis->bi_phymode[1] = BI_PHYMODE_NONE;
+               bis->bi_phymode[2] = BI_PHYMODE_MII;
+               bis->bi_phymode[3] = BI_PHYMODE_NONE;
+               break;
+       case 3:
+               /* 2 RMII - 460EX */
+               /* GMC0 EMAC4_0, GMC0 EMAC4_1, ZMII Bridge */
+               zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
+               zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1);
+               bis->bi_phymode[0] = BI_PHYMODE_RMII;
+               bis->bi_phymode[1] = BI_PHYMODE_RMII;
+               bis->bi_phymode[2] = BI_PHYMODE_NONE;
+               bis->bi_phymode[3] = BI_PHYMODE_NONE;
+               break;
+       case 4:
+               /* 4 RMII - 460GT */
+               /* GMC0 EMAC4_0, GMC0 EMAC4_1, GMC1 EMAC4_2, GMC1, EMAC4_3 */
+               /* ZMII Bridge */
+               zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
+               zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1);
+               zmiifer |= ZMII_FER_RMII << ZMII_FER_V(2);
+               zmiifer |= ZMII_FER_RMII << ZMII_FER_V(3);
+               bis->bi_phymode[0] = BI_PHYMODE_RMII;
+               bis->bi_phymode[1] = BI_PHYMODE_RMII;
+               bis->bi_phymode[2] = BI_PHYMODE_RMII;
+               bis->bi_phymode[3] = BI_PHYMODE_RMII;
+               break;
+       case 5:
+               /* 2 SMII - 460EX */
+               /* GMC0 EMAC4_0, GMC0 EMAC4_1, ZMII Bridge */
+               zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0);
+               zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1);
+               bis->bi_phymode[0] = BI_PHYMODE_SMII;
+               bis->bi_phymode[1] = BI_PHYMODE_SMII;
+               bis->bi_phymode[2] = BI_PHYMODE_NONE;
+               bis->bi_phymode[3] = BI_PHYMODE_NONE;
+               break;
+       case 6:
+               /* 4 SMII - 460GT */
+               /* GMC0 EMAC4_0, GMC0 EMAC4_1, GMC0 EMAC4_3, GMC0 EMAC4_3 */
+               /* ZMII Bridge */
+               zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0);
+               zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1);
+               zmiifer |= ZMII_FER_SMII << ZMII_FER_V(2);
+               zmiifer |= ZMII_FER_SMII << ZMII_FER_V(3);
+               bis->bi_phymode[0] = BI_PHYMODE_SMII;
+               bis->bi_phymode[1] = BI_PHYMODE_SMII;
+               bis->bi_phymode[2] = BI_PHYMODE_SMII;
+               bis->bi_phymode[3] = BI_PHYMODE_SMII;
+               break;
+       case 7:
+               /* This is the default mode that we want for board bringup - Maple */
+               /* 1 GMII - 460EX */
+               /* GMC0 EMAC4_0, RGMII Bridge 0 */
+               rmiifer |= RGMII_FER_MDIO(0);
+
+               if (devnum == 0) {
+                       rmiifer |= RGMII_FER_GMII << RGMII_FER_V(2); /* CH0CFG - EMAC0 */
+                       bis->bi_phymode[0] = BI_PHYMODE_GMII;
+                       bis->bi_phymode[1] = BI_PHYMODE_NONE;
+                       bis->bi_phymode[2] = BI_PHYMODE_NONE;
+                       bis->bi_phymode[3] = BI_PHYMODE_NONE;
+               } else {
+                       rmiifer |= RGMII_FER_GMII << RGMII_FER_V(3); /* CH1CFG - EMAC1 */
+                       bis->bi_phymode[0] = BI_PHYMODE_NONE;
+                       bis->bi_phymode[1] = BI_PHYMODE_GMII;
+                       bis->bi_phymode[2] = BI_PHYMODE_NONE;
+                       bis->bi_phymode[3] = BI_PHYMODE_NONE;
+               }
+               break;
+       case 8:
+               /* 2 GMII - 460GT */
+               /* GMC0 EMAC4_0, RGMII Bridge 0 */
+               /* GMC1 EMAC4_2, RGMII Bridge 1 */
+               rmiifer |= RGMII_FER_GMII << RGMII_FER_V(2);    /* CH0CFG - EMAC0 */
+               rmiifer1 |= RGMII_FER_GMII << RGMII_FER_V(2);   /* CH0CFG - EMAC2 */
+               rmiifer |= RGMII_FER_MDIO(0);                   /* enable MDIO - EMAC0 */
+               rmiifer1 |= RGMII_FER_MDIO(0);                  /* enable MDIO - EMAC2 */
+
+               bis->bi_phymode[0] = BI_PHYMODE_GMII;
+               bis->bi_phymode[1] = BI_PHYMODE_NONE;
+               bis->bi_phymode[2] = BI_PHYMODE_GMII;
+               bis->bi_phymode[3] = BI_PHYMODE_NONE;
+               break;
+       case 9:
+               /* 2 RGMII - 460EX */
+               /* GMC0 EMAC4_0, GMC0 EMAC4_1, RGMII Bridge 0 */
+               rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
+               rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
+               rmiifer |= RGMII_FER_MDIO(0);                   /* enable MDIO - EMAC0 */
+
+               bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+               bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+               bis->bi_phymode[2] = BI_PHYMODE_NONE;
+               bis->bi_phymode[3] = BI_PHYMODE_NONE;
+               break;
+       case 10:
+               /* 4 RGMII - 460GT */
+               /* GMC0 EMAC4_0, GMC0 EMAC4_1, RGMII Bridge 0 */
+               /* GMC1 EMAC4_2, GMC1 EMAC4_3, RGMII Bridge 1 */
+               rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
+               rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
+               rmiifer1 |= RGMII_FER_RGMII << RGMII_FER_V(2);
+               rmiifer1 |= RGMII_FER_RGMII << RGMII_FER_V(3);
+               bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+               bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+               bis->bi_phymode[2] = BI_PHYMODE_RGMII;
+               bis->bi_phymode[3] = BI_PHYMODE_RGMII;
+               break;
+       default:
+               break;
+       }
+
+       /* Set EMAC for MDIO */
+       mfsdr(SDR0_ETH_CFG, eth_cfg);
+       eth_cfg |= SDR0_ETH_CFG_MDIO_SEL_EMAC0;
+       mtsdr(SDR0_ETH_CFG, eth_cfg);
+
+       out_be32((void *)RGMII_FER, rmiifer);
+#if defined(CONFIG_460GT)
+       out_be32((void *)RGMII_FER + RGMII1_BASE_OFFSET, rmiifer1);
+#endif
+
+       /* bypass the TAHOE0/TAHOE1 cores for U-Boot */
+       mfsdr(SDR0_ETH_CFG, eth_cfg);
+       eth_cfg |= (SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS);
+       mtsdr(SDR0_ETH_CFG, eth_cfg);
+
+       return 0;
+}
+#endif /* CONFIG_460EX || CONFIG_460GT */
+
+static inline void *malloc_aligned(u32 size, u32 align)
+{
+       return (void *)(((u32)malloc(size + align) + align - 1) &
+                       ~(align - 1));
+}
+
 static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 {
-       int i, j;
+       int i;
        unsigned long reg = 0;
        unsigned long msr;
        unsigned long speed;
@@ -460,18 +702,25 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #if defined(CONFIG_440GX) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
        sys_info_t sysinfo;
 #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
        int ethgroup = -1;
 #endif
+#endif
+       u32 bd_cached;
+       u32 bd_uncached = 0;
+#ifdef CONFIG_4xx_DCACHE
+       static u32 last_used_ea = 0;
 #endif
 #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
-       unsigned long mfr;
+       int rgmii_channel;
 #endif
 
        EMAC_4XX_HW_PST hw_p = dev->priv;
@@ -486,6 +735,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #if defined(CONFIG_440GX) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
        /* Need to get the OPB frequency so we can access the PHY */
        get_sys_info (&sysinfo);
@@ -539,21 +789,12 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
        out_be32((void *)ZMII_FER, 0);
        udelay (100);
 
-#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#if defined(CONFIG_440GP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
        out_be32((void *)ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
-#elif defined(CONFIG_440GX) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#elif defined(CONFIG_440GX) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT)
        ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
-#elif defined(CONFIG_440GP)
-       /* set RMII mode */
-       out_be32((void *)ZMII_FER, ZMII_RMII | ZMII_MDI0);
-#else
-       if ((devnum == 0) || (devnum == 1)) {
-               out_be32((void *)ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
-       } else { /* ((devnum == 2) || (devnum == 3)) */
-               out_be32((void *)ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum));
-               out_be32((void *)RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) |
-                                            (RGMII_FER_RGMII << RGMII_FER_V (3))));
-       }
 #endif
 
        out_be32((void *)ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum));
@@ -562,20 +803,17 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
        ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
 #endif
 
-       __asm__ volatile ("eieio");
+       sync();
 
-       /* reset emac so we have access to the phy */
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
        /* provide clocks for EMAC internal loopback  */
-       mfsdr (sdr_mfr, mfr);
-       mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum);
-       mtsdr(sdr_mfr, mfr);
-#endif
+       emac_loopback_enable(hw_p);
 
+       /* EMAC RESET */
        out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
 
+       /* remove clocks for EMAC internal loopback  */
+       emac_loopback_disable(hw_p);
+
        failsafe = 1000;
        while ((in_be32((void *)EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) {
                udelay (1000);
@@ -584,18 +822,10 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
        if (failsafe <= 0)
                printf("\nProblem resetting EMAC!\n");
 
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
-       /* remove clocks for EMAC internal loopback  */
-       mfsdr (sdr_mfr, mfr);
-       mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum);
-       mtsdr(sdr_mfr, mfr);
-#endif
-
 #if defined(CONFIG_440GX) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
        /* Whack the M1 register */
        mode_reg = 0x0;
@@ -625,10 +855,12 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
                reg = CONFIG_PHY1_ADDR;
                break;
 #endif
-#if defined (CONFIG_440GX)
+#if defined (CONFIG_PHY2_ADDR)
        case 2:
                reg = CONFIG_PHY2_ADDR;
                break;
+#endif
+#if defined (CONFIG_PHY3_ADDR)
        case 3:
                reg = CONFIG_PHY3_ADDR;
                break;
@@ -657,6 +889,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #if defined(CONFIG_440GX) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
 
 #if defined(CONFIG_CIS8201_PHY)
@@ -755,8 +988,10 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
                        hw_p->devnum);
        }
 
-#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
-    !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX)
+#if defined(CONFIG_440) && \
+    !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
+    !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \
+    !defined(CONFIG_460EX) && !defined(CONFIG_460GT)
 #if defined(CONFIG_440EP) || defined(CONFIG_440GR)
        mfsdr(sdr_mfr, reg);
        if (speed == 100) {
@@ -768,11 +1003,11 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #endif
 
        /* Set ZMII/RGMII speed according to the phy link speed */
-       reg = in_be32(ZMII_SSR);
+       reg = in_be32((void *)ZMII_SSR);
        if ( (speed == 100) || (speed == 1000) )
-               out_be32(ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum)));
+               out_be32((void *)ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum)));
        else
-               out_be32(ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum))));
+               out_be32((void *)ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum))));
 
        if ((devnum == 2) || (devnum == 3)) {
                if (speed == 1000)
@@ -785,29 +1020,40 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
                        printf("Error in RGMII Speed\n");
                        return -1;
                }
-               out_be32(RGMII_SSR, reg);
+               out_be32((void *)RGMII_SSR, reg);
        }
 #endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */
 
 #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
+       if (devnum >= 2)
+               rgmii_channel = devnum - 2;
+       else
+               rgmii_channel = devnum;
+
        if (speed == 1000)
-               reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum));
+               reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V(rgmii_channel));
        else if (speed == 100)
-               reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum));
+               reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V(rgmii_channel));
        else if (speed == 10)
-               reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum));
+               reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V(rgmii_channel));
        else {
                printf("Error in RGMII Speed\n");
                return -1;
        }
        out_be32((void *)RGMII_SSR, reg);
+#if defined(CONFIG_460GT)
+       if ((devnum == 2) || (devnum == 3))
+               out_be32((void *)RGMII_SSR + RGMII1_BASE_OFFSET, reg);
+#endif
 #endif
 
        /* set the Mal configuration reg */
 #if defined(CONFIG_440GX) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
        mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
               MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
@@ -819,91 +1065,67 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
        }
 #endif
 
-       /* Free "old" buffers */
-       if (hw_p->alloc_tx_buf)
-               free (hw_p->alloc_tx_buf);
-       if (hw_p->alloc_rx_buf)
-               free (hw_p->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.
         */
-       hw_p->alloc_tx_buf =
-               (mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_TX_BUFF) +
-                                      ((2 * CFG_CACHELINE_SIZE) - 2));
-       if (NULL == hw_p->alloc_tx_buf)
-               return -1;
-       if (((int) hw_p->alloc_tx_buf & CACHELINE_MASK) != 0) {
-               hw_p->tx =
-                       (mal_desc_t *) ((int) hw_p->alloc_tx_buf +
-                                       CFG_CACHELINE_SIZE -
-                                       ((int) hw_p->
-                                        alloc_tx_buf & CACHELINE_MASK));
-       } else {
-               hw_p->tx = hw_p->alloc_tx_buf;
-       }
+       if (hw_p->first_init == 0) {
+               debug("*** Allocating descriptor memory ***\n");
 
-       hw_p->alloc_rx_buf =
-               (mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_RX_BUFF) +
-                                      ((2 * CFG_CACHELINE_SIZE) - 2));
-       if (NULL == hw_p->alloc_rx_buf) {
-               free(hw_p->alloc_tx_buf);
-               hw_p->alloc_tx_buf = NULL;
-               return -1;
-       }
+               bd_cached = (u32)malloc_aligned(MAL_ALLOC_SIZE, 4096);
+               if (!bd_cached) {
+                       printf("%s: Error allocating MAL descriptor buffers!\n");
+                       return -1;
+               }
 
-       if (((int) hw_p->alloc_rx_buf & CACHELINE_MASK) != 0) {
-               hw_p->rx =
-                       (mal_desc_t *) ((int) hw_p->alloc_rx_buf +
-                                       CFG_CACHELINE_SIZE -
-                                       ((int) hw_p->
-                                        alloc_rx_buf & CACHELINE_MASK));
-       } else {
-               hw_p->rx = hw_p->alloc_rx_buf;
+#ifdef CONFIG_4xx_DCACHE
+               flush_dcache_range(bd_cached, bd_cached + MAL_ALLOC_SIZE);
+               if (!last_used_ea)
+#if defined(CFG_MEM_TOP_HIDE)
+                       bd_uncached = bis->bi_memsize + CFG_MEM_TOP_HIDE;
+#else
+                       bd_uncached = bis->bi_memsize;
+#endif
+               else
+                       bd_uncached = last_used_ea + MAL_ALLOC_SIZE;
+
+               last_used_ea = bd_uncached;
+               program_tlb(bd_cached, bd_uncached, MAL_ALLOC_SIZE,
+                           TLB_WORD2_I_ENABLE);
+#else
+               bd_uncached = bd_cached;
+#endif
+               hw_p->tx_phys = bd_cached;
+               hw_p->rx_phys = bd_cached + MAL_TX_DESC_SIZE;
+               hw_p->tx = (mal_desc_t *)(bd_uncached);
+               hw_p->rx = (mal_desc_t *)(bd_uncached + MAL_TX_DESC_SIZE);
+               debug("hw_p->tx=%08x, hw_p->rx=%08x\n", hw_p->tx, hw_p->rx);
        }
 
        for (i = 0; i < NUM_TX_BUFF; i++) {
                hw_p->tx[i].ctrl = 0;
                hw_p->tx[i].data_len = 0;
-               if (hw_p->first_init == 0) {
-                       hw_p->txbuf_ptr =
-                               (char *) malloc (ENET_MAX_MTU_ALIGNED);
-                       if (NULL == hw_p->txbuf_ptr) {
-                               free(hw_p->alloc_rx_buf);
-                               free(hw_p->alloc_tx_buf);
-                               hw_p->alloc_rx_buf = NULL;
-                               hw_p->alloc_tx_buf = NULL;
-                               for(j = 0; j < i; j++) {
-                                       free(hw_p->tx[i].data_ptr);
-                                       hw_p->tx[i].data_ptr = NULL;
-                               }
-                       }
-               }
+               if (hw_p->first_init == 0)
+                       hw_p->txbuf_ptr = malloc_aligned(MAL_ALLOC_SIZE,
+                                                        L1_CACHE_BYTES);
                hw_p->tx[i].data_ptr = hw_p->txbuf_ptr;
                if ((NUM_TX_BUFF - 1) == i)
                        hw_p->tx[i].ctrl |= MAL_TX_CTRL_WRAP;
                hw_p->tx_run[i] = -1;
-#if 0
-               printf ("TX_BUFF %d @ 0x%08lx\n", i,
-                       (ulong) hw_p->tx[i].data_ptr);
-#endif
+               debug("TX_BUFF %d @ 0x%08lx\n", i, (u32)hw_p->tx[i].data_ptr);
        }
 
        for (i = 0; i < NUM_RX_BUFF; i++) {
                hw_p->rx[i].ctrl = 0;
                hw_p->rx[i].data_len = 0;
-               /*       rx[i].data_ptr = (char *) &rx_buff[i]; */
-               hw_p->rx[i].data_ptr = (char *) NetRxPackets[i];
+               hw_p->rx[i].data_ptr = (char *)NetRxPackets[i];
                if ((NUM_RX_BUFF - 1) == i)
                        hw_p->rx[i].ctrl |= MAL_RX_CTRL_WRAP;
                hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR;
                hw_p->rx_ready[i] = -1;
-#if 0
-               printf ("RX_BUFF %d @ 0x%08lx\n", i, (ulong) hw_p->rx[i].data_ptr);
-#endif
+               debug("RX_BUFF %d @ 0x%08lx\n", i, (u32)hw_p->rx[i].data_ptr);
        }
 
        reg = 0x00000000;
@@ -929,38 +1151,65 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
        case 1:
                /* setup MAL tx & rx channel pointers */
 #if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR)
-               mtdcr (maltxctp2r, hw_p->tx);
+               mtdcr (maltxctp2r, hw_p->tx_phys);
 #else
-               mtdcr (maltxctp1r, hw_p->tx);
+               mtdcr (maltxctp1r, hw_p->tx_phys);
 #endif
 #if defined(CONFIG_440)
                mtdcr (maltxbattr, 0x0);
                mtdcr (malrxbattr, 0x0);
 #endif
-               mtdcr (malrxctp1r, hw_p->rx);
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+               mtdcr (malrxctp8r, hw_p->rx_phys);
+               /* set RX buffer size */
+               mtdcr (malrcbs8, ENET_MAX_MTU_ALIGNED / 16);
+#else
+               mtdcr (malrxctp1r, hw_p->rx_phys);
                /* set RX buffer size */
                mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16);
+#endif
                break;
 #if defined (CONFIG_440GX)
        case 2:
                /* setup MAL tx & rx channel pointers */
                mtdcr (maltxbattr, 0x0);
                mtdcr (malrxbattr, 0x0);
-               mtdcr (maltxctp2r, hw_p->tx);
-               mtdcr (malrxctp2r, hw_p->rx);
+               mtdcr (maltxctp2r, hw_p->tx_phys);
+               mtdcr (malrxctp2r, hw_p->rx_phys);
                /* set RX buffer size */
                mtdcr (malrcbs2, ENET_MAX_MTU_ALIGNED / 16);
                break;
        case 3:
                /* setup MAL tx & rx channel pointers */
                mtdcr (maltxbattr, 0x0);
-               mtdcr (maltxctp3r, hw_p->tx);
+               mtdcr (maltxctp3r, hw_p->tx_phys);
                mtdcr (malrxbattr, 0x0);
-               mtdcr (malrxctp3r, hw_p->rx);
+               mtdcr (malrxctp3r, hw_p->rx_phys);
                /* set RX buffer size */
                mtdcr (malrcbs3, ENET_MAX_MTU_ALIGNED / 16);
                break;
 #endif /* CONFIG_440GX */
+#if defined (CONFIG_460GT)
+       case 2:
+               /* setup MAL tx & rx channel pointers */
+               mtdcr (maltxbattr, 0x0);
+               mtdcr (malrxbattr, 0x0);
+               mtdcr (maltxctp2r, hw_p->tx_phys);
+               mtdcr (malrxctp16r, hw_p->rx_phys);
+               /* set RX buffer size */
+               mtdcr (malrcbs16, ENET_MAX_MTU_ALIGNED / 16);
+               break;
+       case 3:
+               /* setup MAL tx & rx channel pointers */
+               mtdcr (maltxbattr, 0x0);
+               mtdcr (malrxbattr, 0x0);
+               mtdcr (maltxctp3r, hw_p->tx_phys);
+               mtdcr (malrxctp24r, hw_p->rx_phys);
+               /* set RX buffer size */
+               mtdcr (malrcbs24, ENET_MAX_MTU_ALIGNED / 16);
+               break;
+#endif /* CONFIG_460GT */
        case 0:
        default:
                /* setup MAL tx & rx channel pointers */
@@ -968,8 +1217,8 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
                mtdcr (maltxbattr, 0x0);
                mtdcr (malrxbattr, 0x0);
 #endif
-               mtdcr (maltxctp0r, hw_p->tx);
-               mtdcr (malrxctp0r, hw_p->rx);
+               mtdcr (maltxctp0r, hw_p->tx_phys);
+               mtdcr (malrxctp0r, hw_p->rx_phys);
                /* set RX buffer size */
                mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16);
                break;
@@ -986,9 +1235,10 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
        /* set transmit enable & receive enable */
        out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_TXE | EMAC_M0_RXE);
 
-       /* set receive fifo to 4k and tx fifo to 2k */
        mode_reg = in_be32((void *)EMAC_M1 + hw_p->hw_addr);
-       mode_reg |= EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K;
+
+       /* set rx-/tx-fifo size */
+       mode_reg = (mode_reg & ~EMAC_MR1_FIFO_MASK) | EMAC_MR1_FIFO_SIZE;
 
        /* set speed */
        if (speed == _1000BASET) {
@@ -1055,7 +1305,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
        hw_p->bis = bis;
        hw_p->first_init = 1;
 
-       return (1);
+       return 0;
 }
 
 
@@ -1083,6 +1333,7 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
 
        /*   memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len); */
        memcpy ((void *) hw_p->txbuf_ptr, (const void *) ptr, len);
+       flush_dcache_range((u32)hw_p->txbuf_ptr, (u32)hw_p->txbuf_ptr + len);
 
        /*-----------------------------------------------------------------------+
         * set TX Buffer busy, and send it
@@ -1096,7 +1347,7 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
        hw_p->tx[hw_p->tx_slot].data_len = (short) len;
        hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_READY;
 
-       __asm__ volatile ("eieio");
+       sync();
 
        out_be32((void *)EMAC_TXM0 + hw_p->hw_addr,
                 in_be32((void *)EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0);
@@ -1136,15 +1387,31 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
  */
 #define UIC0MSR                uic1msr
 #define UIC0SR         uic1sr
+#define UIC1MSR                uic1msr
+#define UIC1SR         uic1sr
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+/*
+ * Hack: On 460EX/GT all enet irq sources are located on UIC2
+ * Needs some cleanup. --ag
+ */
+#define UIC0MSR                uic2msr
+#define UIC0SR         uic2sr
+#define UIC1MSR                uic2msr
+#define UIC1SR         uic2sr
 #else
 #define UIC0MSR                uic0msr
 #define UIC0SR         uic0sr
+#define UIC1MSR                uic1msr
+#define UIC1SR         uic1sr
 #endif
 
 #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
     defined(CONFIG_405EX)
 #define UICMSR_ETHX    uic0msr
 #define UICSR_ETHX     uic0sr
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UICMSR_ETHX    uic2msr
+#define UICSR_ETHX     uic2sr
 #else
 #define UICMSR_ETHX    uic1msr
 #define UICSR_ETHX     uic1sr
@@ -1182,7 +1449,7 @@ int enetInt (struct eth_device *dev)
                serviced = 0;
 
                my_uic0msr = mfdcr (UIC0MSR);
-               my_uic1msr = mfdcr (uic1msr);
+               my_uic1msr = mfdcr (UIC1MSR);
 #if defined(CONFIG_440GX)
                my_uic2msr = mfdcr (uic2msr);
 #endif
@@ -1228,7 +1495,7 @@ int enetInt (struct eth_device *dev)
                        if ((hw_p->emac_ier & emac_isr)
                            || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
                                mtdcr (UIC0SR, UIC_MRE | UIC_MTE);      /* Clear */
-                               mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);   /* Clear */
+                               mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE);   /* Clear */
                                mtdcr (UICSR_ETHX, UIC_ETH0); /* Clear */
                                return (rc);    /* we had errors so get out */
                        }
@@ -1247,7 +1514,7 @@ int enetInt (struct eth_device *dev)
                        if ((hw_p->emac_ier & emac_isr)
                            || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
                                mtdcr (UIC0SR, UIC_MRE | UIC_MTE);      /* Clear */
-                               mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+                               mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
                                mtdcr (UICSR_ETHX, UIC_ETH1); /* Clear */
                                return (rc);    /* we had errors so get out */
                        }
@@ -1265,7 +1532,7 @@ int enetInt (struct eth_device *dev)
                        if ((hw_p->emac_ier & emac_isr)
                            || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
                                mtdcr (UIC0SR, UIC_MRE | UIC_MTE);      /* Clear */
-                               mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);   /* Clear */
+                               mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE);   /* Clear */
                                mtdcr (uic2sr, UIC_ETH2);
                                return (rc);    /* we had errors so get out */
                        }
@@ -1283,7 +1550,7 @@ int enetInt (struct eth_device *dev)
                        if ((hw_p->emac_ier & emac_isr)
                            || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
                                mtdcr (UIC0SR, UIC_MRE | UIC_MTE);      /* Clear */
-                               mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);   /* Clear */
+                               mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE);   /* Clear */
                                mtdcr (uic2sr, UIC_ETH3);
                                return (rc);    /* we had errors so get out */
                        }
@@ -1301,7 +1568,9 @@ int enetInt (struct eth_device *dev)
                /* check for EOB on valid channels            */
                if (my_uic0msr & UIC_MRE) {
                        mal_rx_eob = mfdcr (malrxeobisr);
-                       if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */
+                       if ((mal_rx_eob &
+                            (0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL)))
+                           != 0) { /* call emac routine for channel x */
                                /* clear EOB
                                   mtdcr(malrxeobisr, mal_rx_eob); */
                                enet_rcv (dev, emac_isr);
@@ -1312,7 +1581,7 @@ int enetInt (struct eth_device *dev)
                }
 
                mtdcr (UIC0SR, UIC_MRE);        /* Clear */
-               mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);   /* Clear */
+               mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE);   /* Clear */
                switch (hw_p->devnum) {
                case 0:
                        mtdcr (UICSR_ETHX, UIC_ETH0);
@@ -1477,7 +1746,7 @@ static void enet_rcv (struct eth_device *dev, unsigned long malisr)
        int loop_count = 0;
 
        rx_eob_isr = mfdcr (malrxeobisr);
-       if ((0x80000000 >> hw_p->devnum) & rx_eob_isr) {
+       if ((0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL)) & rx_eob_isr) {
                /* clear EOB */
                mtdcr (malrxeobisr, rx_eob_isr);
 
@@ -1491,7 +1760,7 @@ static void enet_rcv (struct eth_device *dev, unsigned long malisr)
 
                        loop_count++;
                        handled++;
-                       data_len = (unsigned long) hw_p->rx[i].data_len       /* Get len */
+                       data_len = (unsigned long) hw_p->rx[i].data_len & 0x0fff;       /* Get len */
                        if (data_len) {
                                if (data_len > ENET_MAX_MTU)    /* Check len */
                                        data_len = 0;
@@ -1577,11 +1846,14 @@ static int ppc_4xx_eth_rx (struct eth_device *dev)
                msr = mfmsr ();
                mtmsr (msr & ~(MSR_EE));
 
-               length = hw_p->rx[user_index].data_len;
+               length = hw_p->rx[user_index].data_len & 0x0fff;
 
                /* Pass the packet up to the protocol layers. */
                /*       NetReceive(NetRxPackets[rxIdx], length - 4); */
                /*       NetReceive(NetRxPackets[i], length); */
+               invalidate_dcache_range((u32)hw_p->rx[user_index].data_ptr,
+                                       (u32)hw_p->rx[user_index].data_ptr +
+                                       length - 4);
                NetReceive (NetRxPackets[user_index], length - 4);
                /* Free Recv Buffer */
                hw_p->rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY;
@@ -1644,14 +1916,22 @@ int ppc_4xx_eth_initialize (bd_t * bis)
                case 2:
                        memcpy(ethaddr[eth_num + CONFIG_EMAC_NR_START],
                               bis->bi_enet2addr, 6);
+#if defined(CONFIG_460GT)
+                       hw_addr[eth_num] = 0x300;
+#else
                        hw_addr[eth_num] = 0x400;
+#endif
                        break;
 #endif
 #ifdef CONFIG_HAS_ETH3
                case 3:
                        memcpy(ethaddr[eth_num + CONFIG_EMAC_NR_START],
                               bis->bi_enet3addr, 6);
+#if defined(CONFIG_460GT)
+                       hw_addr[eth_num] = 0x400;
+#else
                        hw_addr[eth_num] = 0x600;
+#endif
                        break;
 #endif
                }
@@ -1724,6 +2004,7 @@ int ppc_4xx_eth_initialize (bd_t * bis)
                        /* set the MAL IER ??? names may change with new spec ??? */
 #if defined(CONFIG_440SPE) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
     defined(CONFIG_405EX)
                        mal_ier =
                                MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE |
@@ -1770,7 +2051,8 @@ int ppc_4xx_eth_initialize (bd_t * bis)
 #endif
 #endif
        }                       /* end for each supported device */
-       return (1);
+
+       return 0;
 }
 
 #if !defined(CONFIG_NET_MULTI)