1 Index: linux-2.6.24.2/drivers/net/arm/ixp4xx_eth.c
2 ===================================================================
3 --- linux-2.6.24.2.orig/drivers/net/arm/ixp4xx_eth.c
4 +++ linux-2.6.24.2/drivers/net/arm/ixp4xx_eth.c
5 @@ -165,14 +165,15 @@ struct port {
6 struct net_device *netdev;
7 struct napi_struct napi;
8 struct net_device_stats stat;
9 - struct mii_if_info mii;
10 + struct mii_if_info mii[IXP4XX_ETH_PHY_MAX_ADDR];
11 struct delayed_work mdio_thread;
12 struct eth_plat_info *plat;
13 buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS];
14 struct desc *desc_tab; /* coherent */
16 int id; /* logical port ID */
18 + u16 mii_bmcr[IXP4XX_ETH_PHY_MAX_ADDR];
22 /* NPE message structure */
23 @@ -316,13 +317,14 @@ static void mdio_write(struct net_device
24 spin_unlock_irqrestore(&mdio_lock, flags);
27 -static void phy_reset(struct net_device *dev, int phy_id)
28 +static void phy_reset(struct net_device *dev, int idx)
30 struct port *port = netdev_priv(dev);
31 + int phy_id = port->mii[idx].phy_id;
34 - mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr | BMCR_RESET);
36 + mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_RESET);
38 while (cycles < MAX_MII_RESET_RETRIES) {
39 if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) {
41 @@ -335,12 +337,12 @@ static void phy_reset(struct net_device
45 - printk(KERN_ERR "%s: MII reset failed\n", dev->name);
46 + printk(KERN_ERR "%s: MII reset failed on PHY%2d\n", dev->name, phy_id);
49 -static void eth_set_duplex(struct port *port)
50 +static void eth_set_duplex(struct port *port, int full_duplex)
52 - if (port->mii.full_duplex)
54 __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
55 &port->regs->tx_control[0]);
57 @@ -348,7 +350,7 @@ static void eth_set_duplex(struct port *
58 &port->regs->tx_control[0]);
63 static void phy_check_media(struct port *port, int init)
65 if (mii_check_media(&port->mii, 1, init))
66 @@ -367,7 +369,63 @@ static void phy_check_media(struct port
71 +static void phy_update_link(struct net_device *dev, int link)
73 + int prev_link = netif_carrier_ok(dev);
75 + if (!prev_link && link) {
76 + printk(KERN_INFO "%s: link up\n", dev->name);
77 + netif_carrier_on(dev);
78 + } else if (prev_link && !link) {
79 + printk(KERN_INFO "%s: link down\n", dev->name);
80 + netif_carrier_off(dev);
84 +static void phy_check_media(struct port *port, int init)
86 + struct net_device *dev = port->netdev;
88 + if (port->phy_count == 1) {
89 + struct mii_if_info *mii = &port->mii[0];
91 + if (mii_check_media(mii, 1, init))
92 + eth_set_duplex(port, mii->full_duplex);
94 + if (mii->force_media) /* mii_check_media() doesn't work */
95 + phy_update_link(dev, mii_link_ok(mii));
101 + eth_set_duplex(port, 1);
103 + for (i = 0; i < port->phy_count; i++)
104 + cur_link |= mii_link_ok(&port->mii[i]);
106 + phy_update_link(dev, cur_link);
111 +static void phy_power_down(struct net_device *dev, int idx)
113 + struct port *port = netdev_priv(dev);
114 + int phy_id = port->mii[idx].phy_id;
116 + port->mii_bmcr[idx] = mdio_read(dev, phy_id, MII_BMCR) &
117 + ~(BMCR_RESET | BMCR_PDOWN);
118 + mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_PDOWN);
121 +static void phy_power_up(struct net_device *dev, int idx)
123 + struct port *port = netdev_priv(dev);
125 + mdio_write(dev, port->mii[idx].phy_id, MII_BMCR, port->mii_bmcr[idx]);
128 static void mdio_thread(struct work_struct *work)
130 @@ -790,9 +848,12 @@ static int eth_ioctl(struct net_device *
132 if (!netif_running(dev))
134 - err = generic_mii_ioctl(&port->mii, if_mii(req), cmd, &duplex_chg);
135 + if (port->phy_count != 1)
136 + return -EOPNOTSUPP;
138 + err = generic_mii_ioctl(&port->mii[0], if_mii(req), cmd, &duplex_chg);
140 - eth_set_duplex(port);
141 + eth_set_duplex(port, port->mii[0].full_duplex);
145 @@ -944,7 +1005,8 @@ static int eth_open(struct net_device *d
149 - mdio_write(dev, port->plat->phy, MII_BMCR, port->mii_bmcr);
150 + for (i = 0; i < port->phy_count; i++)
151 + phy_power_up(dev, i);
153 memset(&msg, 0, sizeof(msg));
154 msg.cmd = NPE_VLAN_SETRXQOSENTRY;
155 @@ -1103,10 +1165,8 @@ static int eth_close(struct net_device *
156 printk(KERN_CRIT "%s: unable to disable loopback\n",
159 - port->mii_bmcr = mdio_read(dev, port->plat->phy, MII_BMCR) &
160 - ~(BMCR_RESET | BMCR_PDOWN); /* may have been altered */
161 - mdio_write(dev, port->plat->phy, MII_BMCR,
162 - port->mii_bmcr | BMCR_PDOWN);
163 + for (i = 0; i < port->phy_count; i++)
164 + phy_power_down(dev, i);
167 qmgr_disable_irq(TXDONE_QUEUE);
168 @@ -1117,6 +1177,42 @@ static int eth_close(struct net_device *
172 +static void eth_add_phy(struct net_device *dev, int phy_id)
174 + struct port *port = netdev_priv(dev);
177 + i = port->phy_count++;
179 + port->mii[i].dev = dev;
180 + port->mii[i].mdio_read = mdio_read;
181 + port->mii[i].mdio_write = mdio_write;
182 + port->mii[i].phy_id = phy_id;
183 + port->mii[i].phy_id_mask = 0x1F;
184 + port->mii[i].reg_num_mask = 0x1F;
186 + printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, phy_id,
187 + npe_name(port->npe));
190 + phy_power_down(dev, i);
193 +static void eth_init_mii(struct net_device *dev)
195 + struct port *port = netdev_priv(dev);
197 + if (port->plat->phy < IXP4XX_ETH_PHY_MAX_ADDR) {
198 + eth_add_phy(dev, port->plat->phy);
201 + for (i = 0; i < IXP4XX_ETH_PHY_MAX_ADDR; i++)
202 + if (port->plat->phy_mask & (1U << i))
203 + eth_add_phy(dev, i);
208 static int __devinit eth_init_one(struct platform_device *pdev)
211 @@ -1189,20 +1285,7 @@ static int __devinit eth_init_one(struct
212 __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
215 - port->mii.dev = dev;
216 - port->mii.mdio_read = mdio_read;
217 - port->mii.mdio_write = mdio_write;
218 - port->mii.phy_id = plat->phy;
219 - port->mii.phy_id_mask = 0x1F;
220 - port->mii.reg_num_mask = 0x1F;
222 - printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
223 - npe_name(port->npe));
225 - phy_reset(dev, plat->phy);
226 - port->mii_bmcr = mdio_read(dev, plat->phy, MII_BMCR) &
227 - ~(BMCR_RESET | BMCR_PDOWN);
228 - mdio_write(dev, plat->phy, MII_BMCR, port->mii_bmcr | BMCR_PDOWN);
231 INIT_DELAYED_WORK(&port->mdio_thread, mdio_thread);
233 Index: linux-2.6.24.2/include/asm-arm/arch-ixp4xx/platform.h
234 ===================================================================
235 --- linux-2.6.24.2.orig/include/asm-arm/arch-ixp4xx/platform.h
236 +++ linux-2.6.24.2/include/asm-arm/arch-ixp4xx/platform.h
237 @@ -106,12 +106,15 @@ struct sys_timer;
238 #define IXP4XX_ETH_NPEB 0x10
239 #define IXP4XX_ETH_NPEC 0x20
241 +#define IXP4XX_ETH_PHY_MAX_ADDR 32
243 /* Information about built-in Ethernet MAC interfaces */
244 struct eth_plat_info {
245 u8 phy; /* MII PHY ID, 0 - 31 */
246 u8 rxq; /* configurable, currently 0 - 31 only */
252 /* Information about built-in HSS (synchronous serial) interfaces */