]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - drivers/qe/uec.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[people/ms/u-boot.git] / drivers / qe / uec.c
index ba89247e4fc757ebb67502baffba8678b6a95425..68045733b8b8c223ceef99b132181e8124fe1e60 100644 (file)
@@ -1,22 +1,9 @@
 /*
- * Copyright (C) 2006 Freescale Semiconductor, Inc.
+ * Copyright (C) 2006-2011 Freescale Semiconductor, Inc.
  *
  * Dave Liu <daveliu@freescale.com>
  *
- * 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
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include "common.h"
 #include "uec.h"
 #include "uec_phy.h"
 #include "miiphy.h"
+#include <phy.h>
 
-#if defined(CONFIG_QE)
+/* Default UTBIPAR SMI address */
+#ifndef CONFIG_UTBIPAR_INIT_TBIPA
+#define CONFIG_UTBIPAR_INIT_TBIPA 0x1F
+#endif
 
+static uec_info_t uec_info[] = {
 #ifdef CONFIG_UEC_ETH1
-static uec_info_t eth1_uec_info = {
-       .uf_info                = {
-               .ucc_num        = CFG_UEC1_UCC_NUM,
-               .rx_clock       = CFG_UEC1_RX_CLK,
-               .tx_clock       = CFG_UEC1_TX_CLK,
-               .eth_type       = CFG_UEC1_ETH_TYPE,
-       },
-#if (CFG_UEC1_ETH_TYPE == FAST_ETH)
-       .num_threads_tx         = UEC_NUM_OF_THREADS_1,
-       .num_threads_rx         = UEC_NUM_OF_THREADS_1,
-#else
-       .num_threads_tx         = UEC_NUM_OF_THREADS_4,
-       .num_threads_rx         = UEC_NUM_OF_THREADS_4,
-#endif
-       .riscTx                 = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
-       .riscRx                 = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
-       .tx_bd_ring_len         = 16,
-       .rx_bd_ring_len         = 16,
-       .phy_address            = CFG_UEC1_PHY_ADDR,
-       .enet_interface         = CFG_UEC1_INTERFACE_MODE,
-};
+       STD_UEC_INFO(1),        /* UEC1 */
 #endif
 #ifdef CONFIG_UEC_ETH2
-static uec_info_t eth2_uec_info = {
-       .uf_info                = {
-               .ucc_num        = CFG_UEC2_UCC_NUM,
-               .rx_clock       = CFG_UEC2_RX_CLK,
-               .tx_clock       = CFG_UEC2_TX_CLK,
-               .eth_type       = CFG_UEC2_ETH_TYPE,
-       },
-#if (CFG_UEC2_ETH_TYPE == FAST_ETH)
-       .num_threads_tx         = UEC_NUM_OF_THREADS_1,
-       .num_threads_rx         = UEC_NUM_OF_THREADS_1,
-#else
-       .num_threads_tx         = UEC_NUM_OF_THREADS_4,
-       .num_threads_rx         = UEC_NUM_OF_THREADS_4,
-#endif
-       .riscTx                 = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
-       .riscRx                 = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
-       .tx_bd_ring_len         = 16,
-       .rx_bd_ring_len         = 16,
-       .phy_address            = CFG_UEC2_PHY_ADDR,
-       .enet_interface         = CFG_UEC2_INTERFACE_MODE,
-};
+       STD_UEC_INFO(2),        /* UEC2 */
 #endif
 #ifdef CONFIG_UEC_ETH3
-static uec_info_t eth3_uec_info = {
-       .uf_info                = {
-               .ucc_num        = CFG_UEC3_UCC_NUM,
-               .rx_clock       = CFG_UEC3_RX_CLK,
-               .tx_clock       = CFG_UEC3_TX_CLK,
-               .eth_type       = CFG_UEC3_ETH_TYPE,
-       },
-#if (CFG_UEC3_ETH_TYPE == FAST_ETH)
-       .num_threads_tx         = UEC_NUM_OF_THREADS_1,
-       .num_threads_rx         = UEC_NUM_OF_THREADS_1,
-#else
-       .num_threads_tx         = UEC_NUM_OF_THREADS_4,
-       .num_threads_rx         = UEC_NUM_OF_THREADS_4,
-#endif
-       .riscTx                 = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
-       .riscRx                 = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
-       .tx_bd_ring_len         = 16,
-       .rx_bd_ring_len         = 16,
-       .phy_address            = CFG_UEC3_PHY_ADDR,
-       .enet_interface         = CFG_UEC3_INTERFACE_MODE,
-};
+       STD_UEC_INFO(3),        /* UEC3 */
 #endif
 #ifdef CONFIG_UEC_ETH4
-static uec_info_t eth4_uec_info = {
-       .uf_info                = {
-               .ucc_num        = CFG_UEC4_UCC_NUM,
-               .rx_clock       = CFG_UEC4_RX_CLK,
-               .tx_clock       = CFG_UEC4_TX_CLK,
-               .eth_type       = CFG_UEC4_ETH_TYPE,
-       },
-#if (CFG_UEC4_ETH_TYPE == FAST_ETH)
-       .num_threads_tx         = UEC_NUM_OF_THREADS_1,
-       .num_threads_rx         = UEC_NUM_OF_THREADS_1,
-#else
-       .num_threads_tx         = UEC_NUM_OF_THREADS_4,
-       .num_threads_rx         = UEC_NUM_OF_THREADS_4,
+       STD_UEC_INFO(4),        /* UEC4 */
 #endif
-       .riscTx                 = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
-       .riscRx                 = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
-       .tx_bd_ring_len         = 16,
-       .rx_bd_ring_len         = 16,
-       .phy_address            = CFG_UEC4_PHY_ADDR,
-       .enet_interface         = CFG_UEC4_INTERFACE_MODE,
-};
+#ifdef CONFIG_UEC_ETH5
+       STD_UEC_INFO(5),        /* UEC5 */
+#endif
+#ifdef CONFIG_UEC_ETH6
+       STD_UEC_INFO(6),        /* UEC6 */
 #endif
+#ifdef CONFIG_UEC_ETH7
+       STD_UEC_INFO(7),        /* UEC7 */
+#endif
+#ifdef CONFIG_UEC_ETH8
+       STD_UEC_INFO(8),        /* UEC8 */
+#endif
+};
 
-#define MAXCONTROLLERS (4)
+#define MAXCONTROLLERS (8)
 
 static struct eth_device *devlist[MAXCONTROLLERS];
 
-u16 phy_read (struct uec_mii_info *mii_info, u16 regnum);
-void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val);
-
 static int uec_mac_enable(uec_private_t *uec, comm_dir_e mode)
 {
        uec_t           *uec_regs;
@@ -329,13 +251,10 @@ static int uec_open(uec_private_t *uec, comm_dir_e mode)
 
 static int uec_stop(uec_private_t *uec, comm_dir_e mode)
 {
-       ucc_fast_private_t      *uccf;
-
        if (!uec || !uec->uccf) {
                printf("%s: No handle passed.\n", __FUNCTION__);
                return -EINVAL;
        }
-       uccf = uec->uccf;
 
        /* check if the UCC number is in range. */
        if (uec->uec_info->uf_info.ucc_num >= UCC_MAX_NUM) {
@@ -386,10 +305,10 @@ static int uec_set_mac_duplex(uec_private_t *uec, int duplex)
        return 0;
 }
 
-static int uec_set_mac_if_mode(uec_private_t *uec, enet_interface_e if_mode)
+static int uec_set_mac_if_mode(uec_private_t *uec,
+               phy_interface_t if_mode, int speed)
 {
-       enet_interface_e        enet_if_mode;
-       uec_info_t              *uec_info;
+       phy_interface_t         enet_if_mode;
        uec_t                   *uec_regs;
        u32                     upsmr;
        u32                     maccfg2;
@@ -399,7 +318,6 @@ static int uec_set_mac_if_mode(uec_private_t *uec, enet_interface_e if_mode)
                return -EINVAL;
        }
 
-       uec_info = uec->uec_info;
        uec_regs = uec->uec_regs;
        enet_if_mode = if_mode;
 
@@ -409,47 +327,69 @@ static int uec_set_mac_if_mode(uec_private_t *uec, enet_interface_e if_mode)
        upsmr = in_be32(&uec->uccf->uf_regs->upsmr);
        upsmr &= ~(UPSMR_RPM | UPSMR_TBIM | UPSMR_R10M | UPSMR_RMM);
 
-       switch (enet_if_mode) {
-               case ENET_100_MII:
-               case ENET_10_MII:
-                       maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
-                       break;
-               case ENET_1000_GMII:
-                       maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
-                       break;
-               case ENET_1000_TBI:
-                       maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
-                       upsmr |= UPSMR_TBIM;
-                       break;
-               case ENET_1000_RTBI:
-                       maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
-                       upsmr |= (UPSMR_RPM | UPSMR_TBIM);
-                       break;
-               case ENET_1000_RGMII_RXID:
-               case ENET_1000_RGMII:
-                       maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
-                       upsmr |= UPSMR_RPM;
-                       break;
-               case ENET_100_RGMII:
+       switch (speed) {
+               case SPEED_10:
                        maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
-                       upsmr |= UPSMR_RPM;
-                       break;
-               case ENET_10_RGMII:
-                       maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
-                       upsmr |= (UPSMR_RPM | UPSMR_R10M);
+                       switch (enet_if_mode) {
+                               case PHY_INTERFACE_MODE_MII:
+                                       break;
+                               case PHY_INTERFACE_MODE_RGMII:
+                                       upsmr |= (UPSMR_RPM | UPSMR_R10M);
+                                       break;
+                               case PHY_INTERFACE_MODE_RMII:
+                                       upsmr |= (UPSMR_R10M | UPSMR_RMM);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                                       break;
+                       }
                        break;
-               case ENET_100_RMII:
+               case SPEED_100:
                        maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
-                       upsmr |= UPSMR_RMM;
+                       switch (enet_if_mode) {
+                               case PHY_INTERFACE_MODE_MII:
+                                       break;
+                               case PHY_INTERFACE_MODE_RGMII:
+                                       upsmr |= UPSMR_RPM;
+                                       break;
+                               case PHY_INTERFACE_MODE_RMII:
+                                       upsmr |= UPSMR_RMM;
+                                       break;
+                               default:
+                                       return -EINVAL;
+                                       break;
+                       }
                        break;
-               case ENET_10_RMII:
-                       maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
-                       upsmr |= (UPSMR_R10M | UPSMR_RMM);
+               case SPEED_1000:
+                       maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
+                       switch (enet_if_mode) {
+                               case PHY_INTERFACE_MODE_GMII:
+                                       break;
+                               case PHY_INTERFACE_MODE_TBI:
+                                       upsmr |= UPSMR_TBIM;
+                                       break;
+                               case PHY_INTERFACE_MODE_RTBI:
+                                       upsmr |= (UPSMR_RPM | UPSMR_TBIM);
+                                       break;
+                               case PHY_INTERFACE_MODE_RGMII_RXID:
+                               case PHY_INTERFACE_MODE_RGMII_TXID:
+                               case PHY_INTERFACE_MODE_RGMII_ID:
+                               case PHY_INTERFACE_MODE_RGMII:
+                                       upsmr |= UPSMR_RPM;
+                                       break;
+                               case PHY_INTERFACE_MODE_SGMII:
+                                       upsmr |= UPSMR_SGMM;
+                                       break;
+                               default:
+                                       return -EINVAL;
+                                       break;
+                       }
                        break;
                default:
                        return -EINVAL;
                        break;
        }
+
        out_be32(&uec_regs->maccfg2, maccfg2);
        out_be32(&uec->uccf->uf_regs->upsmr, upsmr);
 
@@ -558,12 +498,10 @@ bus_fail:
 static void adjust_link(struct eth_device *dev)
 {
        uec_private_t           *uec = (uec_private_t *)dev->priv;
-       uec_t                   *uec_regs;
        struct uec_mii_info     *mii_info = uec->mii_info;
 
        extern void change_phy_interface_mode(struct eth_device *dev,
-                                        enet_interface_e mode);
-       uec_regs = uec->uec_regs;
+                                phy_interface_t mode, int speed);
 
        if (mii_info->link) {
                /* Now we make sure that we can be in full duplex mode.
@@ -580,25 +518,19 @@ static void adjust_link(struct eth_device *dev)
                }
 
                if (mii_info->speed != uec->oldspeed) {
+                       phy_interface_t mode =
+                               uec->uec_info->enet_interface_type;
                        if (uec->uec_info->uf_info.eth_type == GIGA_ETH) {
                                switch (mii_info->speed) {
-                               case 1000:
+                               case SPEED_1000:
                                        break;
-                               case 100:
+                               case SPEED_100:
                                        printf ("switching to rgmii 100\n");
-                                       /* change phy to rgmii 100 */
-                                       change_phy_interface_mode(dev,
-                                                               ENET_100_RGMII);
-                                       /* change the MAC interface mode */
-                                       uec_set_mac_if_mode(uec,ENET_100_RGMII);
+                                       mode = PHY_INTERFACE_MODE_RGMII;
                                        break;
-                               case 10:
+                               case SPEED_10:
                                        printf ("switching to rgmii 10\n");
-                                       /* change phy to rgmii 10 */
-                                       change_phy_interface_mode(dev,
-                                                               ENET_10_RGMII);
-                                       /* change the MAC interface mode */
-                                       uec_set_mac_if_mode(uec,ENET_10_RGMII);
+                                       mode = PHY_INTERFACE_MODE_RGMII;
                                        break;
                                default:
                                        printf("%s: Ack,Speed(%d)is illegal\n",
@@ -607,6 +539,11 @@ static void adjust_link(struct eth_device *dev)
                                }
                        }
 
+                       /* change phy */
+                       change_phy_interface_mode(dev, mode, mii_info->speed);
+                       /* change the MAC interface mode */
+                       uec_set_mac_if_mode(uec, mode, mii_info->speed);
+
                        printf("%s: Speed %dBT\n", dev->name, mii_info->speed);
                        uec->oldspeed = mii_info->speed;
                }
@@ -630,15 +567,55 @@ static void phy_change(struct eth_device *dev)
 {
        uec_private_t   *uec = (uec_private_t *)dev->priv;
 
+#if defined(CONFIG_P1012) || defined(CONFIG_P1021) || defined(CONFIG_P1025)
+       ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+       /* QE9 and QE12 need to be set for enabling QE MII managment signals */
+       setbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR_QE9);
+       setbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR_QE12);
+#endif
+
        /* Update the link, speed, duplex */
        uec->mii_info->phyinfo->read_status(uec->mii_info);
 
+#if defined(CONFIG_P1012) || defined(CONFIG_P1021) || defined(CONFIG_P1025)
+       /*
+        * QE12 is muxed with LBCTL, it needs to be released for enabling
+        * LBCTL signal for LBC usage.
+        */
+       clrbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR_QE12);
+#endif
+
        /* Adjust the interface according to speed */
        adjust_link(dev);
 }
 
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
-       && !defined(BITBANGMII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+
+/*
+ * Find a device index from the devlist by name
+ *
+ * Returns:
+ *  The index where the device is located, -1 on error
+ */
+static int uec_miiphy_find_dev_by_name(const char *devname)
+{
+       int i;
+
+       for (i = 0; i < MAXCONTROLLERS; i++) {
+               if (strncmp(devname, devlist[i]->name, strlen(devname)) == 0) {
+                       break;
+               }
+       }
+
+       /* If device cannot be found, returns -1 */
+       if (i == MAXCONTROLLERS) {
+               debug ("%s: device %s not found in devlist\n", __FUNCTION__, devname);
+               i = -1;
+       }
+
+       return i;
+}
 
 /*
  * Read a MII PHY register.
@@ -646,11 +623,19 @@ static void phy_change(struct eth_device *dev)
  * Returns:
  *  0 on success
  */
-static int uec_miiphy_read(char *devname, unsigned char addr,
+static int uec_miiphy_read(const char *devname, unsigned char addr,
                            unsigned char reg, unsigned short *value)
 {
-       *value = uec_read_phy_reg(devlist[0], addr, reg);
+       int devindex = 0;
 
+       if (devname == NULL || value == NULL) {
+               debug("%s: NULL pointer given\n", __FUNCTION__);
+       } else {
+               devindex = uec_miiphy_find_dev_by_name(devname);
+               if (devindex >= 0) {
+                       *value = uec_read_phy_reg(devlist[devindex], addr, reg);
+               }
+       }
        return 0;
 }
 
@@ -660,14 +645,21 @@ static int uec_miiphy_read(char *devname, unsigned char addr,
  * Returns:
  *  0 on success
  */
-static int uec_miiphy_write(char *devname, unsigned char addr,
+static int uec_miiphy_write(const char *devname, unsigned char addr,
                             unsigned char reg, unsigned short value)
 {
-       uec_write_phy_reg(devlist[0], addr, reg, value);
+       int devindex = 0;
 
+       if (devname == NULL) {
+               debug("%s: NULL pointer given\n", __FUNCTION__);
+       } else {
+               devindex = uec_miiphy_find_dev_by_name(devname);
+               if (devindex >= 0) {
+                       uec_write_phy_reg(devlist[devindex], addr, reg, value);
+               }
+       }
        return 0;
 }
-
 #endif
 
 static int uec_set_mac_address(uec_private_t *uec, u8 *mac_addr)
@@ -935,7 +927,7 @@ static int uec_issue_init_enet_rxtx_cmd(uec_private_t *uec,
 
        /* Init Rx global parameter pointer */
        p_init_enet_param->rgftgfrxglobal |= uec->rx_glbl_pram_offset |
-                                                (u32)uec_info->riscRx;
+                                                (u32)uec_info->risc_rx;
 
        /* Init Rx threads */
        for (i = 0; i < (thread_rx + 1); i++) {
@@ -953,13 +945,13 @@ static int uec_issue_init_enet_rxtx_cmd(uec_private_t *uec,
                }
 
                entry_val = ((u32)snum << ENET_INIT_PARAM_SNUM_SHIFT) |
-                                init_enet_offset | (u32)uec_info->riscRx;
+                                init_enet_offset | (u32)uec_info->risc_rx;
                p_init_enet_param->rxthread[i] = entry_val;
        }
 
        /* Init Tx global parameter pointer */
        p_init_enet_param->txglobal = uec->tx_glbl_pram_offset |
-                                        (u32)uec_info->riscTx;
+                                        (u32)uec_info->risc_tx;
 
        /* Init Tx threads */
        for (i = 0; i < thread_tx; i++) {
@@ -972,7 +964,7 @@ static int uec_issue_init_enet_rxtx_cmd(uec_private_t *uec,
                                                 UEC_THREAD_TX_PRAM_ALIGNMENT);
 
                entry_val = ((u32)snum << ENET_INIT_PARAM_SNUM_SHIFT) |
-                                init_enet_offset | (u32)uec_info->riscTx;
+                                init_enet_offset | (u32)uec_info->risc_tx;
                p_init_enet_param->txthread[i] = entry_val;
        }
 
@@ -998,7 +990,6 @@ static int uec_startup(uec_private_t *uec)
        int                             num_threads_tx;
        int                             num_threads_rx;
        u32                             utbipar;
-       enet_interface_e                enet_interface;
        u32                             length;
        u32                             align;
        qe_bd_t                         *bd;
@@ -1078,7 +1069,7 @@ static int uec_startup(uec_private_t *uec)
        out_be32(&uec_regs->maccfg2, MACCFG2_INIT_VALUE);
 
        /* Setup MAC interface mode */
-       uec_set_mac_if_mode(uec, uec_info->enet_interface);
+       uec_set_mac_if_mode(uec, uec_info->enet_interface_type, uec_info->speed);
 
        /* Setup MII management base */
 #ifndef CONFIG_eTSEC_MDIO_BUS
@@ -1093,18 +1084,26 @@ static int uec_startup(uec_private_t *uec)
        /* Setup UTBIPAR */
        utbipar = in_be32(&uec_regs->utbipar);
        utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK;
-       enet_interface = uec->uec_info->enet_interface;
-       if (enet_interface == ENET_1000_TBI ||
-                enet_interface == ENET_1000_RTBI) {
-               utbipar |=  (uec_info->phy_address + uec_info->uf_info.ucc_num)
-                                                << UTBIPAR_PHY_ADDRESS_SHIFT;
-       } else {
-               utbipar |=  (0x10 + uec_info->uf_info.ucc_num)
-                                                << UTBIPAR_PHY_ADDRESS_SHIFT;
-       }
 
+       /* Initialize UTBIPAR address to CONFIG_UTBIPAR_INIT_TBIPA for ALL UEC.
+        * This frees up the remaining SMI addresses for use.
+        */
+       utbipar |= CONFIG_UTBIPAR_INIT_TBIPA << UTBIPAR_PHY_ADDRESS_SHIFT;
        out_be32(&uec_regs->utbipar, utbipar);
 
+       /* Configure the TBI for SGMII operation */
+       if ((uec->uec_info->enet_interface_type == PHY_INTERFACE_MODE_SGMII) &&
+          (uec->uec_info->speed == SPEED_1000)) {
+               uec_write_phy_reg(uec->dev, uec_regs->utbipar,
+                       ENET_TBI_MII_ANA, TBIANA_SETTINGS);
+
+               uec_write_phy_reg(uec->dev, uec_regs->utbipar,
+                       ENET_TBI_MII_TBICON, TBICON_CLK_SELECT);
+
+               uec_write_phy_reg(uec->dev, uec_regs->utbipar,
+                       ENET_TBI_MII_CR, TBICR_SETTINGS);
+       }
+
        /* Allocate Tx BDs */
        length = ((uec_info->tx_bd_ring_len * SIZEOFBD) /
                 UEC_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) *
@@ -1194,10 +1193,19 @@ static int uec_init(struct eth_device* dev, bd_t *bd)
        uec_private_t           *uec;
        int                     err, i;
        struct phy_info         *curphy;
+#if defined(CONFIG_P1012) || defined(CONFIG_P1021) || defined(CONFIG_P1025)
+       ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+#endif
 
        uec = (uec_private_t *)dev->priv;
 
        if (uec->the_first_run == 0) {
+#if defined(CONFIG_P1012) || defined(CONFIG_P1021) || defined(CONFIG_P1025)
+       /* QE9 and QE12 need to be set for enabling QE MII managment signals */
+       setbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR_QE9);
+       setbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR_QE12);
+#endif
+
                err = init_phy(dev);
                if (err) {
                        printf("%s: Cannot initialize PHY, aborting.\n",
@@ -1219,12 +1227,20 @@ static int uec_init(struct eth_device* dev, bd_t *bd)
                i = 50;
                do {
                        err = curphy->read_status(uec->mii_info);
+                       if (!(((i-- > 0) && !uec->mii_info->link) || err))
+                               break;
                        udelay(100000);
-               } while (((i-- > 0) && !uec->mii_info->link) || err);
+               } while (1);
+
+#if defined(CONFIG_P1012) || defined(CONFIG_P1021) || defined(CONFIG_P1025)
+               /* QE12 needs to be released for enabling LBCTL signal*/
+               clrbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR_QE12);
+#endif
 
                if (err || i <= 0)
                        printf("warning: %s: timeout on PHY link\n", dev->name);
 
+               adjust_link(dev);
                uec->the_first_run = 1;
        }
 
@@ -1254,7 +1270,7 @@ static void uec_halt(struct eth_device* dev)
        uec_stop(uec, COMM_DIR_RX_AND_TX);
 }
 
-static int uec_send(struct eth_device* dev, volatile void *buf, int len)
+static int uec_send(struct eth_device *dev, void *buf, int len)
 {
        uec_private_t           *uec;
        ucc_fast_private_t      *uccf;
@@ -1332,12 +1348,11 @@ static int uec_recv(struct eth_device* dev)
        return 1;
 }
 
-int uec_initialize(int index)
+int uec_initialize(bd_t *bis, uec_info_t *uec_info)
 {
        struct eth_device       *dev;
        int                     i;
        uec_private_t           *uec;
-       uec_info_t              *uec_info;
        int                     err;
 
        dev = (struct eth_device *)malloc(sizeof(struct eth_device));
@@ -1352,34 +1367,18 @@ int uec_initialize(int index)
        }
        memset(uec, 0, sizeof(uec_private_t));
 
-       /* Init UEC private struct, they come from board.h */
-       uec_info = NULL;
-       if (index == 0) {
-#ifdef CONFIG_UEC_ETH1
-               uec_info = &eth1_uec_info;
-#endif
-       } else if (index == 1) {
-#ifdef CONFIG_UEC_ETH2
-               uec_info = &eth2_uec_info;
+       /* Adjust uec_info */
+#if (MAX_QE_RISC == 4)
+       uec_info->risc_tx = QE_RISC_ALLOCATION_FOUR_RISCS;
+       uec_info->risc_rx = QE_RISC_ALLOCATION_FOUR_RISCS;
 #endif
-       } else if (index == 2) {
-#ifdef CONFIG_UEC_ETH3
-               uec_info = &eth3_uec_info;
-#endif
-       } else if (index == 3) {
-#ifdef CONFIG_UEC_ETH4
-               uec_info = &eth4_uec_info;
-#endif
-       } else {
-               printf("%s: index is illegal.\n", __FUNCTION__);
-               return -EINVAL;
-       }
 
-       devlist[index] = dev;
+       devlist[uec_info->uf_info.ucc_num] = dev;
 
        uec->uec_info = uec_info;
+       uec->dev = dev;
 
-       sprintf(dev->name, "FSL UEC%d", index);
+       sprintf(dev->name, "UEC%d", uec_info->uf_info.ucc_num);
        dev->iobase = 0;
        dev->priv = (void *)uec;
        dev->init = uec_init;
@@ -1399,13 +1398,24 @@ int uec_initialize(int index)
                return err;
        }
 
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
-       && !defined(BITBANGMII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
        miiphy_register(dev->name, uec_miiphy_read, uec_miiphy_write);
 #endif
 
        return 1;
 }
 
+int uec_eth_init(bd_t *bis, uec_info_t *uecs, int num)
+{
+       int i;
+
+       for (i = 0; i < num; i++)
+               uec_initialize(bis, &uecs[i]);
 
-#endif /* CONFIG_QE */
+       return 0;
+}
+
+int uec_standard_init(bd_t *bis)
+{
+       return uec_eth_init(bis, uec_info, ARRAY_SIZE(uec_info));
+}