]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - cpu/ppc4xx/4xx_enet.c
rename CFG_ macros to CONFIG_SYS
[people/ms/u-boot.git] / cpu / ppc4xx / 4xx_enet.c
index 4541a1468c98623b9f51c9e163fc3d5da65aa62e..d7b16daf394344761617cfae4d2526ca0fbebb19 100644 (file)
@@ -90,7 +90,6 @@
 #include <405_mal.h>
 #include <miiphy.h>
 #include <malloc.h>
-#include <asm/ppc4xx-intvec.h>
 
 /*
  * Only compile for platform with AMCC EMAC ethernet controller and
  * 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
-#define EMAC_UIC_DEF1 UIC_ENET1
-#define SEL_UIC_DEF(p) (p ? UIC_ENET1 : UIC_ENET )
+#define ETH_IRQ_NUM(dev)       (VECNUM_ETH0 + ((dev) * VECNUM_ETH1_OFFS))
+
+#if defined(CONFIG_HAS_ETH3)
+#if !defined(CONFIG_440GX)
+#define UIC_ETHx       (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)) || \
+                        UIC_MASK(ETH_IRQ_NUM(2)) || UIC_MASK(ETH_IRQ_NUM(3)))
+#else
+/* Unfortunately 440GX spreads EMAC interrupts on multiple UIC's */
+#define UIC_ETHx       (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)))
+#define UIC_ETHxB      (UIC_MASK(ETH_IRQ_NUM(2)) || UIC_MASK(ETH_IRQ_NUM(3)))
+#endif /* !defined(CONFIG_440GX) */
+#elif defined(CONFIG_HAS_ETH2)
+#define UIC_ETHx       (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)) || \
+                        UIC_MASK(ETH_IRQ_NUM(2)))
+#elif defined(CONFIG_HAS_ETH1)
+#define UIC_ETHx       (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)))
+#else
+#define UIC_ETHx       UIC_MASK(ETH_IRQ_NUM(0))
+#endif
+
+/*
+ * Define a default version for UIC_ETHxB for non 440GX so that we can
+ * use common code for all 4xx variants
+ */
+#if !defined(UIC_ETHxB)
+#define UIC_ETHxB      0
+#endif
+
+#define UIC_MAL_SERR   UIC_MASK(VECNUM_MAL_SERR)
+#define UIC_MAL_TXDE   UIC_MASK(VECNUM_MAL_TXDE)
+#define UIC_MAL_RXDE   UIC_MASK(VECNUM_MAL_RXDE)
+#define UIC_MAL_TXEOB  UIC_MASK(VECNUM_MAL_TXEOB)
+#define UIC_MAL_RXEOB  UIC_MASK(VECNUM_MAL_RXEOB)
+
+#define MAL_UIC_ERR    (UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE)
+#define MAL_UIC_DEF    (UIC_MAL_RXEOB | MAL_UIC_ERR)
+
+/*
+ * We have 3 different interrupt types:
+ * - MAL interrupts indicating successful transfer
+ * - MAL error interrupts indicating MAL related errors
+ * - EMAC interrupts indicating EMAC related errors
+ *
+ * All those interrupts can be on different UIC's, but since
+ * now at least all interrupts from one type are on the same
+ * UIC. Only exception is 440GX where the EMAC interrupts are
+ * spread over two UIC's!
+ */
+#if defined(CONFIG_440GX)
+#define UIC_BASE_MAL   UIC1_DCR_BASE
+#define UIC_BASE_MAL_ERR UIC2_DCR_BASE
+#define UIC_BASE_EMAC  UIC2_DCR_BASE
+#define UIC_BASE_EMAC_B        UIC3_DCR_BASE
+#else
+#define UIC_BASE_MAL   (UIC0_DCR_BASE + (UIC_NR(VECNUM_MAL_TXEOB) * 0x10))
+#define UIC_BASE_MAL_ERR (UIC0_DCR_BASE + (UIC_NR(VECNUM_MAL_SERR) * 0x10))
+#define UIC_BASE_EMAC  (UIC0_DCR_BASE + (UIC_NR(ETH_IRQ_NUM(0)) * 0x10))
+#define UIC_BASE_EMAC_B        (UIC0_DCR_BASE + (UIC_NR(ETH_IRQ_NUM(0)) * 0x10))
+#endif
 
 #undef INFO_4XX_ENET
 
 #define BI_PHYMODE_RMII  8
 #endif
 #endif
+#define BI_PHYMODE_SGMII 9
 
 #if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
 #define MAL_RX_CHAN_MUL        1
 #endif
 
+/*--------------------------------------------------------------------+
+ * Fixed PHY (PHY-less) support for Ethernet Ports.
+ *--------------------------------------------------------------------*/
+
+/*
+ * Some boards do not have a PHY for each ethernet port. These ports
+ * are known as Fixed PHY (or PHY-less) ports. For such ports, set
+ * the appropriate CONFIG_PHY_ADDR equal to CONFIG_FIXED_PHY and
+ * then define CONFIG_SYS_FIXED_PHY_PORTS to define what the speed and
+ * duplex should be for these ports in the board configuration
+ * file.
+ *
+ * For Example:
+ *     #define CONFIG_FIXED_PHY   0xFFFFFFFF
+ *
+ *     #define CONFIG_PHY_ADDR    CONFIG_FIXED_PHY
+ *     #define CONFIG_PHY1_ADDR   1
+ *     #define CONFIG_PHY2_ADDR   CONFIG_FIXED_PHY
+ *     #define CONFIG_PHY3_ADDR   3
+ *
+ *     #define CONFIG_SYS_FIXED_PHY_PORT(devnum,speed,duplex) \
+ *                     {devnum, speed, duplex},
+ *
+ *     #define CONFIG_SYS_FIXED_PHY_PORTS \
+ *                     CONFIG_SYS_FIXED_PHY_PORT(0,1000,FULL) \
+ *                     CONFIG_SYS_FIXED_PHY_PORT(2,100,HALF)
+ */
+
+#ifndef CONFIG_FIXED_PHY
+#define CONFIG_FIXED_PHY       0xFFFFFFFF /* Fixed PHY (PHY-less) */
+#endif
+
+#ifndef CONFIG_SYS_FIXED_PHY_PORTS
+#define CONFIG_SYS_FIXED_PHY_PORTS     /* default is an empty array */
+#endif
+
+struct fixed_phy_port {
+       unsigned int devnum;    /* ethernet port */
+       unsigned int speed;     /* specified speed 10,100 or 1000 */
+       unsigned int duplex;    /* specified duplex FULL or HALF */
+};
+
+static const struct fixed_phy_port fixed_phy_port[] = {
+       CONFIG_SYS_FIXED_PHY_PORTS      /* defined in board configuration file */
+};
+
 /*-----------------------------------------------------------------------------+
  * Global variables. TX and RX descriptors and buffers.
  *-----------------------------------------------------------------------------*/
-/* IER globals */
-static uint32_t mal_ier;
-
 #if !defined(CONFIG_NET_MULTI)
 struct eth_device *emac0_dev = NULL;
 #endif
@@ -200,12 +297,6 @@ struct eth_device *emac0_dev = NULL;
 #define CONFIG_EMAC_NR_START   0
 #endif
 
-#if defined(CONFIG_405EX) || defined(CONFIG_440EPX)
-#define ETH_IRQ_NUM(dev)       (VECNUM_ETH0 + ((dev)))
-#else
-#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)
@@ -274,8 +365,7 @@ static void emac_loopback_disable(EMAC_4XX_HW_PST hw_p)
 static void ppc_4xx_eth_halt (struct eth_device *dev)
 {
        EMAC_4XX_HW_PST hw_p = dev->priv;
-       uint32_t failsafe = 10000;
-       u32 eth_cfg = 0;
+       u32 val = 10000;
 
        out_be32((void *)EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */
 
@@ -291,8 +381,8 @@ 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;
        }
 
@@ -311,9 +401,9 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
 
 #if defined(CONFIG_460EX) || defined(CONFIG_460GT)
        /* don't bypass the TAHOE0/TAHOE1 cores for Linux */
-       mfsdr(SDR0_ETH_CFG, eth_cfg);
-       eth_cfg &= ~(SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS);
-       mtsdr(SDR0_ETH_CFG, eth_cfg);
+       mfsdr(SDR0_ETH_CFG, val);
+       val &= ~(SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS);
+       mtsdr(SDR0_ETH_CFG, val);
 #endif
 
        return;
@@ -466,30 +556,88 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
 #if defined(CONFIG_405EX)
 int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
 {
-       u32 gmiifer = 0;
+       u32 rgmiifer = 0;
 
        /*
-        * Right now only 2*RGMII is supported. Please extend when needed.
-        * sr - 2007-09-19
+        * The 405EX(r)'s RGMII bridge can operate in one of several
+        * modes, only one of which (2 x RGMII) allows the
+        * simultaneous use of both EMACs on the 405EX.
         */
-       switch (1) {
-       case 1:
+
+       switch (CONFIG_EMAC_PHY_MODE) {
+
+       case EMAC_PHY_MODE_NONE:
+               /* No ports */
+               rgmiifer |= RGMII_FER_DIS       << 0;
+               rgmiifer |= RGMII_FER_DIS       << 4;
+               out_be32((void *)RGMII_FER, rgmiifer);
+               bis->bi_phymode[0] = BI_PHYMODE_NONE;
+               bis->bi_phymode[1] = BI_PHYMODE_NONE;
+               break;
+       case EMAC_PHY_MODE_NONE_RGMII:
+               /* 1 x RGMII port on channel 0 */
+               rgmiifer |= RGMII_FER_RGMII     << 0;
+               rgmiifer |= RGMII_FER_DIS       << 4;
+               out_be32((void *)RGMII_FER, rgmiifer);
+               bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+               bis->bi_phymode[1] = BI_PHYMODE_NONE;
+               break;
+       case EMAC_PHY_MODE_RGMII_NONE:
+               /* 1 x RGMII port on channel 1 */
+               rgmiifer |= RGMII_FER_DIS       << 0;
+               rgmiifer |= RGMII_FER_RGMII     << 4;
+               out_be32((void *)RGMII_FER, rgmiifer);
+               bis->bi_phymode[0] = BI_PHYMODE_NONE;
+               bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+               break;
+       case EMAC_PHY_MODE_RGMII_RGMII:
                /* 2 x RGMII ports */
-               out_be32((void *)RGMII_FER, 0x00000055);
+               rgmiifer |= RGMII_FER_RGMII     << 0;
+               rgmiifer |= RGMII_FER_RGMII     << 4;
+               out_be32((void *)RGMII_FER, rgmiifer);
                bis->bi_phymode[0] = BI_PHYMODE_RGMII;
                bis->bi_phymode[1] = BI_PHYMODE_RGMII;
                break;
-       case 2:
-               /* 2 x SMII ports */
+       case EMAC_PHY_MODE_NONE_GMII:
+               /* 1 x GMII port on channel 0 */
+               rgmiifer |= RGMII_FER_GMII      << 0;
+               rgmiifer |= RGMII_FER_DIS       << 4;
+               out_be32((void *)RGMII_FER, rgmiifer);
+               bis->bi_phymode[0] = BI_PHYMODE_GMII;
+               bis->bi_phymode[1] = BI_PHYMODE_NONE;
+               break;
+       case EMAC_PHY_MODE_NONE_MII:
+               /* 1 x MII port on channel 0 */
+               rgmiifer |= RGMII_FER_MII       << 0;
+               rgmiifer |= RGMII_FER_DIS       << 4;
+               out_be32((void *)RGMII_FER, rgmiifer);
+               bis->bi_phymode[0] = BI_PHYMODE_MII;
+               bis->bi_phymode[1] = BI_PHYMODE_NONE;
+               break;
+       case EMAC_PHY_MODE_GMII_NONE:
+               /* 1 x GMII port on channel 1 */
+               rgmiifer |= RGMII_FER_DIS       << 0;
+               rgmiifer |= RGMII_FER_GMII      << 4;
+               out_be32((void *)RGMII_FER, rgmiifer);
+               bis->bi_phymode[0] = BI_PHYMODE_NONE;
+               bis->bi_phymode[1] = BI_PHYMODE_GMII;
+               break;
+       case EMAC_PHY_MODE_MII_NONE:
+               /* 1 x MII port on channel 1 */
+               rgmiifer |= RGMII_FER_DIS       << 0;
+               rgmiifer |= RGMII_FER_MII       << 4;
+               out_be32((void *)RGMII_FER, rgmiifer);
+               bis->bi_phymode[0] = BI_PHYMODE_NONE;
+               bis->bi_phymode[1] = BI_PHYMODE_MII;
                break;
        default:
                break;
        }
 
        /* Ensure we setup mdio for this devnum and ONLY this devnum */
-       gmiifer = in_be32((void *)RGMII_FER);
-       gmiifer |= (1 << (19-devnum));
-       out_be32((void *)RGMII_FER, gmiifer);
+       rgmiifer = in_be32((void *)RGMII_FER);
+       rgmiifer |= (1 << (19-devnum));
+       out_be32((void *)RGMII_FER, rgmiifer);
 
        return ((int)0x0);
 }
@@ -510,8 +658,17 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
 
 #if defined(CONFIG_460EX)
        mode = 9;
+       mfsdr(SDR0_ETH_CFG, eth_cfg);
+       if (((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) > 0) &&
+           ((eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE) > 0))
+               mode = 11; /* config SGMII */
 #else
        mode = 10;
+       mfsdr(SDR0_ETH_CFG, eth_cfg);
+       if (((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) > 0) &&
+           ((eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE) > 0) &&
+           ((eth_cfg & SDR0_ETH_CFG_SGMII2_ENABLE) > 0))
+               mode = 12; /* config SGMII */
 #endif
 
        /* TODO:
@@ -534,6 +691,8 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
        /*
         * Right now only 2*RGMII is supported. Please extend when needed.
         * sr - 2008-02-19
+        * Add SGMII support.
+        * vg - 2008-07-28
         */
        switch (mode) {
        case 1:
@@ -660,6 +819,20 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
                bis->bi_phymode[2] = BI_PHYMODE_RGMII;
                bis->bi_phymode[3] = BI_PHYMODE_RGMII;
                break;
+       case 11:
+               /* 2 SGMII - 460EX */
+               bis->bi_phymode[0] = BI_PHYMODE_SGMII;
+               bis->bi_phymode[1] = BI_PHYMODE_SGMII;
+               bis->bi_phymode[2] = BI_PHYMODE_NONE;
+               bis->bi_phymode[3] = BI_PHYMODE_NONE;
+               break;
+       case 12:
+               /* 3 SGMII - 460GT */
+               bis->bi_phymode[0] = BI_PHYMODE_SGMII;
+               bis->bi_phymode[1] = BI_PHYMODE_SGMII;
+               bis->bi_phymode[2] = BI_PHYMODE_SGMII;
+               bis->bi_phymode[3] = BI_PHYMODE_NONE;
+               break;
        default:
                break;
        }
@@ -718,6 +891,11 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #ifdef CONFIG_4xx_DCACHE
        static u32 last_used_ea = 0;
 #endif
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_405EX)
+       int rgmii_channel;
+#endif
 
        EMAC_4XX_HW_PST hw_p = dev->priv;
 
@@ -839,9 +1017,50 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
        out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
 #endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */
 
+#if defined(CONFIG_GPCS_PHY_ADDR) || defined(CONFIG_GPCS_PHY1_ADDR) || \
+    defined(CONFIG_GPCS_PHY2_ADDR) || defined(CONFIG_GPCS_PHY3_ADDR)
+       if (bis->bi_phymode[devnum] == BI_PHYMODE_SGMII) {
+               /*
+                * In SGMII mode, GPCS access is needed for
+                * communication with the internal SGMII SerDes.
+                */
+               switch (devnum) {
+#if defined(CONFIG_GPCS_PHY_ADDR)
+               case 0:
+                       reg = CONFIG_GPCS_PHY_ADDR;
+                       break;
+#endif
+#if defined(CONFIG_GPCS_PHY1_ADDR)
+               case 1:
+                       reg = CONFIG_GPCS_PHY1_ADDR;
+                       break;
+#endif
+#if defined(CONFIG_GPCS_PHY2_ADDR)
+               case 2:
+                       reg = CONFIG_GPCS_PHY2_ADDR;
+                       break;
+#endif
+#if defined(CONFIG_GPCS_PHY3_ADDR)
+               case 3:
+                       reg = CONFIG_GPCS_PHY3_ADDR;
+                       break;
+#endif
+               }
+
+               mode_reg = in_be32((void *)EMAC_M1 + hw_p->hw_addr);
+               mode_reg |= EMAC_M1_MF_1000GPCS | EMAC_M1_IPPA_SET(reg);
+               out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
+
+               /* Configure GPCS interface to recommended setting for SGMII */
+               miiphy_reset(dev->name, reg);
+               miiphy_write(dev->name, reg, 0x04, 0x8120); /* AsymPause, FDX */
+               miiphy_write(dev->name, reg, 0x07, 0x2801); /* msg_pg, toggle */
+               miiphy_write(dev->name, reg, 0x00, 0x0140); /* 1Gbps, FDX     */
+       }
+#endif /* defined(CONFIG_GPCS_PHY_ADDR) */
+
        /* wait for PHY to complete auto negotiation */
        reg_short = 0;
-#ifndef CONFIG_CS8952_PHY
        switch (devnum) {
        case 0:
                reg = CONFIG_PHY_ADDR;
@@ -868,6 +1087,9 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 
        bis->bi_phynum[devnum] = reg;
 
+       if (reg == CONFIG_FIXED_PHY)
+               goto get_speed;
+
 #if defined(CONFIG_PHY_RESET)
        /*
         * Reset the phy, only if its the first time through
@@ -880,6 +1102,27 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
                miiphy_write (dev->name, reg, 0x09, 0x0e00);
                miiphy_write (dev->name, reg, 0x04, 0x01e1);
 #endif
+#if defined(CONFIG_M88E1112_PHY)
+               if (bis->bi_phymode[devnum] == BI_PHYMODE_SGMII) {
+                       /*
+                        * Marvell 88E1112 PHY needs to have the SGMII MAC
+                        * interace (page 2) properly configured to
+                        * communicate with the 460EX/GT GPCS interface.
+                        */
+
+                       /* Set access to Page 2 */
+                       miiphy_write(dev->name, reg, 0x16, 0x0002);
+
+                       miiphy_write(dev->name, reg, 0x00, 0x0040); /* 1Gbps */
+                       miiphy_read(dev->name, reg, 0x1a, &reg_short);
+                       reg_short |= 0x8000; /* bypass Auto-Negotiation */
+                       miiphy_write(dev->name, reg, 0x1a, reg_short);
+                       miiphy_reset(dev->name, reg); /* reset MAC interface */
+
+                       /* Reset access to Page 0 */
+                       miiphy_write(dev->name, reg, 0x16, 0x0000);
+               }
+#endif /* defined(CONFIG_M88E1112_PHY) */
                miiphy_reset (dev->name, reg);
 
 #if defined(CONFIG_440GX) || \
@@ -916,7 +1159,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
                        miiphy_write (dev->name, reg, 0x1f, 0x0000);
                        /* end Vitesse/Cicada errata */
                }
-#endif
+#endif /* defined(CONFIG_CIS8201_PHY) */
 
 #if defined(CONFIG_ET1011C_PHY)
                /*
@@ -935,9 +1178,9 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 
                        miiphy_write(dev->name, reg, 0x1c, 0x74f0);
                }
-#endif
+#endif /* defined(CONFIG_ET1011C_PHY) */
 
-#endif
+#endif /* defined(CONFIG_440GX) ... */
                /* Start/Restart autonegotiation */
                phy_setup_aneg (dev->name, reg);
                udelay (1000);
@@ -967,15 +1210,30 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
                        }
                        udelay (1000);  /* 1 ms */
                        miiphy_read (dev->name, reg, PHY_BMSR, &reg_short);
-
                }
                puts (" done\n");
                udelay (500000);        /* another 500 ms (results in faster booting) */
        }
-#endif /* #ifndef CONFIG_CS8952_PHY */
 
-       speed = miiphy_speed (dev->name, reg);
-       duplex = miiphy_duplex (dev->name, reg);
+get_speed:
+       if (reg == CONFIG_FIXED_PHY) {
+               for (i = 0; i < ARRAY_SIZE(fixed_phy_port); i++) {
+                       if (devnum == fixed_phy_port[i].devnum) {
+                               speed = fixed_phy_port[i].speed;
+                               duplex = fixed_phy_port[i].duplex;
+                               break;
+                       }
+               }
+
+               if (i == ARRAY_SIZE(fixed_phy_port)) {
+                       printf("ERROR: PHY (%s) not configured correctly!\n",
+                               dev->name);
+                       return -1;
+               }
+       } else {
+               speed = miiphy_speed(dev->name, reg);
+               duplex = miiphy_duplex(dev->name, reg);
+       }
 
        if (hw_p->print_speed) {
                hw_p->print_speed = 0;
@@ -1023,12 +1281,17 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 #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;
@@ -1067,14 +1330,18 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
 
                bd_cached = (u32)malloc_aligned(MAL_ALLOC_SIZE, 4096);
                if (!bd_cached) {
-                       printf("%s: Error allocating MAL descriptor buffers!\n");
+                       printf("%s: Error allocating MAL descriptor buffers!\n", __func__);
                        return -1;
                }
 
 #ifdef CONFIG_4xx_DCACHE
                flush_dcache_range(bd_cached, bd_cached + MAL_ALLOC_SIZE);
                if (!last_used_ea)
+#if defined(CONFIG_SYS_MEM_TOP_HIDE)
+                       bd_uncached = bis->bi_memsize + CONFIG_SYS_MEM_TOP_HIDE;
+#else
                        bd_uncached = bis->bi_memsize;
+#endif
                else
                        bd_uncached = last_used_ea + MAL_ALLOC_SIZE;
 
@@ -1364,59 +1631,17 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
        }
 }
 
-
-#if defined (CONFIG_440) || defined(CONFIG_405EX)
-
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
-/*
- * Hack: On 440SP all enet irq sources are located on UIC1
- * Needs some cleanup. --sr
- */
-#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
-#endif
-
 int enetInt (struct eth_device *dev)
 {
        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;
-       unsigned long my_uicmsr_ethx;
-
-#if defined(CONFIG_440GX)
-       unsigned long my_uic2msr;
-#endif
+       u32 mal_isr;
+       u32 emac_isr = 0;
+       u32 mal_eob;
+       u32 uic_mal;
+       u32 uic_mal_err;
+       u32 uic_emac;
+       u32 uic_emac_b;
        EMAC_4XX_HW_PST hw_p;
 
        /*
@@ -1435,256 +1660,79 @@ int enetInt (struct eth_device *dev)
        do {
                serviced = 0;
 
-               my_uic0msr = mfdcr (UIC0MSR);
-               my_uic1msr = mfdcr (UIC1MSR);
-#if defined(CONFIG_440GX)
-               my_uic2msr = mfdcr (uic2msr);
-#endif
-               my_uicmsr_ethx = mfdcr (UICMSR_ETHX);
+               uic_mal = mfdcr(UIC_BASE_MAL + UIC_MSR);
+               uic_mal_err = mfdcr(UIC_BASE_MAL_ERR + UIC_MSR);
+               uic_emac = mfdcr(UIC_BASE_EMAC + UIC_MSR);
+               uic_emac_b = mfdcr(UIC_BASE_EMAC_B + UIC_MSR);
 
-               if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
-                   && !(my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))
-                   && !(my_uicmsr_ethx & (UIC_ETH0 | UIC_ETH1))) {
+               if (!(uic_mal & (UIC_MAL_RXEOB | UIC_MAL_TXEOB))
+                   && !(uic_mal_err & (UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE))
+                   && !(uic_emac & UIC_ETHx) && !(uic_emac_b & UIC_ETHxB)) {
                        /* not for us */
                        return (rc);
                }
-#if defined (CONFIG_440GX)
-               if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
-                   && !(my_uic2msr & (UIC_ETH2 | UIC_ETH3))) {
-                       /* not for us */
-                       return (rc);
-               }
-#endif
+
                /* get and clear controller status interrupts */
-               /* look at Mal and EMAC interrupts */
-               if ((my_uic0msr & (UIC_MRE | UIC_MTE))
-                   || (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 (dev, mal_isr, my_uic1msr, MAL_UIC_DEF, MAL_UIC_ERR);
-                               serviced = 1;
-                               rc = 0;
-                       }
-               }
+               /* look at MAL and EMAC error interrupts */
+               if (uic_mal_err & (UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE)) {
+                       /* we have a MAL error interrupt */
+                       mal_isr = mfdcr(malesr);
+                       mal_err(dev, mal_isr, uic_mal_err,
+                                MAL_UIC_DEF, MAL_UIC_ERR);
 
-               /* port by port dispatch of emac interrupts */
-               if (hw_p->devnum == 0) {
-                       if (UIC_ETH0 & my_uicmsr_ethx) {        /* look for EMAC errors */
-                               emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
-                               if ((hw_p->emac_ier & emac_isr) != 0) {
-                                       emac_err (dev, emac_isr);
-                                       serviced = 1;
-                                       rc = 0;
-                               }
-                       }
-                       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 (UICSR_ETHX, UIC_ETH0); /* Clear */
-                               return (rc);    /* we had errors so get out */
-                       }
-               }
+                       /* clear MAL error interrupt status bits */
+                       mtdcr(UIC_BASE_MAL_ERR + UIC_SR,
+                             UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE);
 
-#if !defined(CONFIG_440SP)
-               if (hw_p->devnum == 1) {
-                       if (UIC_ETH1 & my_uicmsr_ethx) {        /* look for EMAC errors */
-                               emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
-                               if ((hw_p->emac_ier & emac_isr) != 0) {
-                                       emac_err (dev, emac_isr);
-                                       serviced = 1;
-                                       rc = 0;
-                               }
-                       }
-                       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 (UICSR_ETHX, UIC_ETH1); /* Clear */
-                               return (rc);    /* we had errors so get out */
-                       }
-               }
-#if defined (CONFIG_440GX)
-               if (hw_p->devnum == 2) {
-                       if (UIC_ETH2 & my_uic2msr) {    /* look for EMAC errors */
-                               emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
-                               if ((hw_p->emac_ier & emac_isr) != 0) {
-                                       emac_err (dev, emac_isr);
-                                       serviced = 1;
-                                       rc = 0;
-                               }
-                       }
-                       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 (uic2sr, UIC_ETH2);
-                               return (rc);    /* we had errors so get out */
-                       }
+                       return -1;
                }
 
-               if (hw_p->devnum == 3) {
-                       if (UIC_ETH3 & my_uic2msr) {    /* look for EMAC errors */
-                               emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
-                               if ((hw_p->emac_ier & emac_isr) != 0) {
-                                       emac_err (dev, emac_isr);
-                                       serviced = 1;
-                                       rc = 0;
-                               }
-                       }
-                       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 (uic2sr, UIC_ETH3);
-                               return (rc);    /* we had errors so get out */
-                       }
-               }
-#endif /* CONFIG_440GX */
-#endif /* !CONFIG_440SP */
+               /* look for EMAC errors */
+               if ((uic_emac & UIC_ETHx) || (uic_emac_b & UIC_ETHxB)) {
+                       emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
+                       emac_err(dev, emac_isr);
 
-               /* handle MAX TX EOB interrupt from a tx */
-               if (my_uic0msr & UIC_MTE) {
-                       mal_rx_eob = mfdcr (maltxeobisr);
-                       mtdcr (maltxeobisr, mal_rx_eob);
-                       mtdcr (UIC0SR, UIC_MTE);
-               }
-               /* 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 >> (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);
-                               /* indicate that we serviced an interrupt */
-                               serviced = 1;
-                               rc = 0;
-                       }
-               }
+                       /* clear EMAC error interrupt status bits */
+                       mtdcr(UIC_BASE_EMAC + UIC_SR, UIC_ETHx);
+                       mtdcr(UIC_BASE_EMAC_B + UIC_SR, UIC_ETHxB);
 
-               mtdcr (UIC0SR, UIC_MRE);        /* Clear */
-               mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE);   /* Clear */
-               switch (hw_p->devnum) {
-               case 0:
-                       mtdcr (UICSR_ETHX, UIC_ETH0);
-                       break;
-               case 1:
-                       mtdcr (UICSR_ETHX, UIC_ETH1);
-                       break;
-#if defined (CONFIG_440GX)
-               case 2:
-                       mtdcr (uic2sr, UIC_ETH2);
-                       break;
-               case 3:
-                       mtdcr (uic2sr, UIC_ETH3);
-                       break;
-#endif /* CONFIG_440GX */
-               default:
-                       break;
+                       return -1;
                }
-       } while (serviced);
-
-       return (rc);
-}
-
-#else /* CONFIG_440 */
 
-int enetInt (struct eth_device *dev)
-{
-       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;
-
-       EMAC_4XX_HW_PST hw_p;
-
-       /*
-        * Because the mal is generic, we need to get the current
-        * eth device
-        */
-#if defined(CONFIG_NET_MULTI)
-       dev = eth_get_dev();
-#else
-       dev = emac0_dev;
-#endif
-
-       hw_p = dev->priv;
-
-       /* 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 (dev, mal_isr, my_uicmsr, MAL_UIC_DEF, MAL_UIC_ERR);
-                               serviced = 1;
-                               rc = 0;
-                       }
+               /* handle MAX TX EOB interrupt from a tx */
+               if (uic_mal & UIC_MAL_TXEOB) {
+                       /* clear MAL interrupt status bits */
+                       mal_eob = mfdcr(maltxeobisr);
+                       mtdcr(maltxeobisr, mal_eob);
+                       mtdcr(UIC_BASE_MAL + UIC_SR, UIC_MAL_TXEOB);
+
+                       /* indicate that we serviced an interrupt */
+                       serviced = 1;
+                       rc = 0;
                }
 
-               /* port by port dispatch of emac interrupts */
+               /* handle MAL RX EOB interupt from a receive */
+               /* check for EOB on valid channels           */
+               if (uic_mal & UIC_MAL_RXEOB) {
+                       mal_eob = mfdcr(malrxeobisr);
+                       if (mal_eob &
+                           (0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL))) {
+                               /* push packet to upper layer */
+                               enet_rcv(dev, emac_isr);
 
-               if ((SEL_UIC_DEF(hw_p->devnum) & my_uicmsr) != 0) {     /* look for EMAC errors */
-                       emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
-                       if ((hw_p->emac_ier & emac_isr) != 0) {
-                               emac_err (dev, emac_isr);
-                               serviced = 1;
-                               rc = 0;
-                       }
-               }
-               if (((hw_p->emac_ier & emac_isr) != 0) || ((MAL_UIC_ERR & my_uicmsr) != 0)) {
-                       mtdcr (uicsr, MAL_UIC_DEF | SEL_UIC_DEF(hw_p->devnum)); /* Clear */
-                       return (rc);            /* we had errors so get out */
-               }
+                               /* clear MAL interrupt status bits */
+                               mtdcr(UIC_BASE_MAL + UIC_SR, UIC_MAL_RXEOB);
 
-               /* handle MAX TX EOB interrupt from a tx */
-               if (my_uicmsr & UIC_MAL_TXEOB) {
-                       mal_rx_eob = mfdcr (maltxeobisr);
-                       mtdcr (maltxeobisr, mal_rx_eob);
-                       mtdcr (uicsr, UIC_MAL_TXEOB);
-               }
-               /* handle MAL RX EOB  interupt from a receive */
-               /* check for EOB on valid channels            */
-               if (my_uicmsr & UIC_MAL_RXEOB)
-               {
-                       mal_rx_eob = mfdcr (malrxeobisr);
-                       if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */
-                               /* clear EOB
-                                mtdcr(malrxeobisr, mal_rx_eob); */
-                               enet_rcv (dev, emac_isr);
                                /* indicate that we serviced an interrupt */
                                serviced = 1;
                                rc = 0;
                        }
                }
-               mtdcr (uicsr, MAL_UIC_DEF|EMAC_UIC_DEF|EMAC_UIC_DEF1);  /* Clear */
-#if defined(CONFIG_405EZ)
-               mtsdr (sdricintstat, SDR_ICRX_STAT | SDR_ICTX0_STAT | SDR_ICTX1_STAT);
-#endif /* defined(CONFIG_405EZ) */
-       }
-       while (serviced);
+       } while (serviced);
 
        return (rc);
 }
 
-#endif /* CONFIG_440 */
-
 /*-----------------------------------------------------------------------------+
  *  MAL Error Routine
  *-----------------------------------------------------------------------------*/
@@ -1870,6 +1918,7 @@ int ppc_4xx_eth_initialize (bd_t * bis)
        EMAC_4XX_HW_PST hw = NULL;
        u8 ethaddr[4 + CONFIG_EMAC_NR_START][6];
        u32 hw_addr[4];
+       u32 mal_ier;
 
 #if defined(CONFIG_440GX)
        unsigned long pfc1;
@@ -2007,19 +2056,19 @@ int ppc_4xx_eth_initialize (bd_t * bis)
                        mtdcr (malier, mal_ier);
 
                        /* install MAL interrupt handler */
-                       irq_install_handler (VECNUM_MS,
+                       irq_install_handler (VECNUM_MAL_SERR,
                                             (interrupt_handler_t *) enetInt,
                                             dev);
-                       irq_install_handler (VECNUM_MTE,
+                       irq_install_handler (VECNUM_MAL_TXEOB,
                                             (interrupt_handler_t *) enetInt,
                                             dev);
-                       irq_install_handler (VECNUM_MRE,
+                       irq_install_handler (VECNUM_MAL_RXEOB,
                                             (interrupt_handler_t *) enetInt,
                                             dev);
-                       irq_install_handler (VECNUM_TXDE,
+                       irq_install_handler (VECNUM_MAL_TXDE,
                                             (interrupt_handler_t *) enetInt,
                                             dev);
-                       irq_install_handler (VECNUM_RXDE,
+                       irq_install_handler (VECNUM_MAL_RXDE,
                                             (interrupt_handler_t *) enetInt,
                                             dev);
                        virgin = 1;