--- a/drivers/net/arm/ixp4xx_eth.c
+++ b/drivers/net/arm/ixp4xx_eth.c
@@ -165,14 +165,15 @@
 	struct net_device *netdev;
 	struct napi_struct napi;
 	struct net_device_stats stat;
-	struct mii_if_info mii;
+	struct mii_if_info mii[IXP4XX_ETH_PHY_MAX_ADDR];
 	struct delayed_work mdio_thread;
 	struct eth_plat_info *plat;
 	buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS];
 	struct desc *desc_tab;	/* coherent */
 	u32 desc_tab_phys;
 	int id;			/* logical port ID */
-	u16 mii_bmcr;
+	u16 mii_bmcr[IXP4XX_ETH_PHY_MAX_ADDR];
+	int phy_count;
 };
 
 /* NPE message structure */
@@ -316,12 +317,13 @@
 	spin_unlock_irqrestore(&mdio_lock, flags);
 }
 
-static void phy_reset(struct net_device *dev, int phy_id)
+static void phy_reset(struct net_device *dev, int idx)
 {
 	struct port *port = netdev_priv(dev);
+	int phy_id = port->mii[idx].phy_id;
 	int cycles = 0;
 
-	mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr | BMCR_RESET);
+	mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_RESET);
 
 	while (cycles < MAX_MII_RESET_RETRIES) {
 		if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) {
@@ -335,12 +337,12 @@
 		cycles++;
 	}
 
-	printk(KERN_ERR "%s: MII reset failed\n", dev->name);
+	printk(KERN_ERR "%s: MII reset failed on PHY%2d\n", dev->name, phy_id);
 }
 
-static void eth_set_duplex(struct port *port)
+static void eth_set_duplex(struct port *port, int full_duplex)
 {
-	if (port->mii.full_duplex)
+	if (full_duplex)
 		__raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
 			     &port->regs->tx_control[0]);
 	else
@@ -348,7 +350,7 @@
 			     &port->regs->tx_control[0]);
 }
 
-
+#if 0
 static void phy_check_media(struct port *port, int init)
 {
 	if (mii_check_media(&port->mii, 1, init))
@@ -367,7 +369,63 @@
 		}
 	}
 }
+#else
+static void phy_update_link(struct net_device *dev, int link)
+{
+	int prev_link = netif_carrier_ok(dev);
+
+	if (!prev_link && link) {
+		printk(KERN_INFO "%s: link up\n", dev->name);
+		netif_carrier_on(dev);
+	} else if (prev_link && !link) {
+		printk(KERN_INFO "%s: link down\n", dev->name);
+		netif_carrier_off(dev);
+	}
+}
+
+static void phy_check_media(struct port *port, int init)
+{
+	struct net_device *dev = port->netdev;
+
+	if (port->phy_count == 1) {
+		struct mii_if_info *mii = &port->mii[0];
+
+		if (mii_check_media(mii, 1, init))
+			eth_set_duplex(port, mii->full_duplex);
+
+		if (mii->force_media) /* mii_check_media() doesn't work */
+			phy_update_link(dev, mii_link_ok(mii));
+	} else {
+		int cur_link = 0;
+		int i;
+
+		if (init)
+			eth_set_duplex(port, 1);
+
+		for (i = 0; i < port->phy_count; i++)
+			cur_link |= mii_link_ok(&port->mii[i]);
+
+		phy_update_link(dev, cur_link);
+	}
+}
+#endif
+
+static void phy_power_down(struct net_device *dev, int idx)
+{
+	struct port *port = netdev_priv(dev);
+	int phy_id = port->mii[idx].phy_id;
+
+	port->mii_bmcr[idx] = mdio_read(dev, phy_id, MII_BMCR) &
+						~(BMCR_RESET | BMCR_PDOWN);
+	mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_PDOWN);
+}
+
+static void phy_power_up(struct net_device *dev, int idx)
+{
+	struct port *port = netdev_priv(dev);
 
+	mdio_write(dev, port->mii[idx].phy_id, MII_BMCR, port->mii_bmcr[idx]);
+}
 
 static void mdio_thread(struct work_struct *work)
 {
@@ -792,9 +850,12 @@
 
 	if (!netif_running(dev))
 		return -EINVAL;
-	err = generic_mii_ioctl(&port->mii, if_mii(req), cmd, &duplex_chg);
+	if (port->phy_count != 1)
+		return -EOPNOTSUPP;
+
+	err = generic_mii_ioctl(&port->mii[0], if_mii(req), cmd, &duplex_chg);
 	if (duplex_chg)
-		eth_set_duplex(port);
+		eth_set_duplex(port, port->mii[0].full_duplex);
 	return err;
 }
 
@@ -947,7 +1008,8 @@
 		}
 	}
 
-	mdio_write(dev, port->plat->phy, MII_BMCR, port->mii_bmcr);
+	for (i = 0; i < port->phy_count; i++)
+		phy_power_up(dev, i);
 
 	memset(&msg, 0, sizeof(msg));
 	msg.cmd = NPE_VLAN_SETRXQOSENTRY;
@@ -1107,10 +1169,8 @@
 		printk(KERN_CRIT "%s: unable to disable loopback\n",
 		       dev->name);
 
-	port->mii_bmcr = mdio_read(dev, port->plat->phy, MII_BMCR) &
-		~(BMCR_RESET | BMCR_PDOWN); /* may have been altered */
-	mdio_write(dev, port->plat->phy, MII_BMCR,
-		   port->mii_bmcr | BMCR_PDOWN);
+	for (i = 0; i < port->phy_count; i++)
+		phy_power_down(dev, i);
 
 	if (!ports_open)
 		qmgr_disable_irq(TXDONE_QUEUE);
@@ -1120,6 +1180,42 @@
 	return 0;
 }
 
+static void eth_add_phy(struct net_device *dev, int phy_id)
+{
+	struct port *port = netdev_priv(dev);
+	int i;
+
+	i = port->phy_count++;
+
+	port->mii[i].dev = dev;
+	port->mii[i].mdio_read = mdio_read;
+	port->mii[i].mdio_write = mdio_write;
+	port->mii[i].phy_id = phy_id;
+	port->mii[i].phy_id_mask = 0x1F;
+	port->mii[i].reg_num_mask = 0x1F;
+
+	printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, phy_id,
+	       npe_name(port->npe));
+
+	phy_reset(dev, i);
+	phy_power_down(dev, i);
+}
+
+static void eth_init_mii(struct net_device *dev)
+{
+	struct port *port = netdev_priv(dev);
+
+	if (port->plat->phy < IXP4XX_ETH_PHY_MAX_ADDR) {
+		eth_add_phy(dev, port->plat->phy);
+	} else {
+		int i;
+		for (i = 0; i < IXP4XX_ETH_PHY_MAX_ADDR; i++)
+			if (port->plat->phy_mask & (1U << i))
+				eth_add_phy(dev, i);
+	}
+
+}
+
 static int __devinit eth_init_one(struct platform_device *pdev)
 {
 	struct port *port;
@@ -1192,20 +1288,7 @@
 	__raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
 	udelay(50);
 
-	port->mii.dev = dev;
-	port->mii.mdio_read = mdio_read;
-	port->mii.mdio_write = mdio_write;
-	port->mii.phy_id = plat->phy;
-	port->mii.phy_id_mask = 0x1F;
-	port->mii.reg_num_mask = 0x1F;
-
-	printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
-	       npe_name(port->npe));
-
-	phy_reset(dev, plat->phy);
-	port->mii_bmcr = mdio_read(dev, plat->phy, MII_BMCR) &
-		~(BMCR_RESET | BMCR_PDOWN);
-	mdio_write(dev, plat->phy, MII_BMCR, port->mii_bmcr | BMCR_PDOWN);
+	eth_init_mii(dev);
 
 	INIT_DELAYED_WORK(&port->mdio_thread, mdio_thread);
 	return 0;
--- a/include/asm-arm/arch-ixp4xx/platform.h
+++ b/include/asm-arm/arch-ixp4xx/platform.h
@@ -95,12 +95,15 @@
 #define IXP4XX_ETH_NPEB		0x10
 #define IXP4XX_ETH_NPEC		0x20
 
+#define IXP4XX_ETH_PHY_MAX_ADDR	32
+
 /* Information about built-in Ethernet MAC interfaces */
 struct eth_plat_info {
 	u8 phy;		/* MII PHY ID, 0 - 31 */
 	u8 rxq;		/* configurable, currently 0 - 31 only */
 	u8 txreadyq;
 	u8 hwaddr[6];
+	u32 phy_mask;
 };
 
 /* Information about built-in HSS (synchronous serial) interfaces */
