1 Index: linux-2.6.25.1/drivers/net/arm/ixp4xx_eth.c
2 ===================================================================
3 --- linux-2.6.25.1.orig/drivers/net/arm/ixp4xx_eth.c
4 +++ linux-2.6.25.1/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,12 +317,13 @@ 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);
35 + mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_RESET);
37 while (cycles < MAX_MII_RESET_RETRIES) {
38 if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) {
39 @@ -335,12 +337,12 @@ static void phy_reset(struct net_device
43 - printk(KERN_ERR "%s: MII reset failed\n", dev->name);
44 + printk(KERN_ERR "%s: MII reset failed on PHY%2d\n", dev->name, phy_id);
47 -static void eth_set_duplex(struct port *port)
48 +static void eth_set_duplex(struct port *port, int full_duplex)
50 - if (port->mii.full_duplex)
52 __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
53 &port->regs->tx_control[0]);
55 @@ -348,7 +350,7 @@ static void eth_set_duplex(struct port *
56 &port->regs->tx_control[0]);
61 static void phy_check_media(struct port *port, int init)
63 if (mii_check_media(&port->mii, 1, init))
64 @@ -367,7 +369,63 @@ static void phy_check_media(struct port
69 +static void phy_update_link(struct net_device *dev, int link)
71 + int prev_link = netif_carrier_ok(dev);
73 + if (!prev_link && link) {
74 + printk(KERN_INFO "%s: link up\n", dev->name);
75 + netif_carrier_on(dev);
76 + } else if (prev_link && !link) {
77 + printk(KERN_INFO "%s: link down\n", dev->name);
78 + netif_carrier_off(dev);
82 +static void phy_check_media(struct port *port, int init)
84 + struct net_device *dev = port->netdev;
86 + if (port->phy_count == 1) {
87 + struct mii_if_info *mii = &port->mii[0];
89 + if (mii_check_media(mii, 1, init))
90 + eth_set_duplex(port, mii->full_duplex);
92 + if (mii->force_media) /* mii_check_media() doesn't work */
93 + phy_update_link(dev, mii_link_ok(mii));
99 + eth_set_duplex(port, 1);
101 + for (i = 0; i < port->phy_count; i++)
102 + cur_link |= mii_link_ok(&port->mii[i]);
104 + phy_update_link(dev, cur_link);
109 +static void phy_power_down(struct net_device *dev, int idx)
111 + struct port *port = netdev_priv(dev);
112 + int phy_id = port->mii[idx].phy_id;
114 + port->mii_bmcr[idx] = mdio_read(dev, phy_id, MII_BMCR) &
115 + ~(BMCR_RESET | BMCR_PDOWN);
116 + mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_PDOWN);
119 +static void phy_power_up(struct net_device *dev, int idx)
121 + struct port *port = netdev_priv(dev);
123 + mdio_write(dev, port->mii[idx].phy_id, MII_BMCR, port->mii_bmcr[idx]);
126 static void mdio_thread(struct work_struct *work)
128 @@ -792,9 +850,12 @@ static int eth_ioctl(struct net_device *
130 if (!netif_running(dev))
132 - err = generic_mii_ioctl(&port->mii, if_mii(req), cmd, &duplex_chg);
133 + if (port->phy_count != 1)
134 + return -EOPNOTSUPP;
136 + err = generic_mii_ioctl(&port->mii[0], if_mii(req), cmd, &duplex_chg);
138 - eth_set_duplex(port);
139 + eth_set_duplex(port, port->mii[0].full_duplex);
143 @@ -947,7 +1008,8 @@ static int eth_open(struct net_device *d
147 - mdio_write(dev, port->plat->phy, MII_BMCR, port->mii_bmcr);
148 + for (i = 0; i < port->phy_count; i++)
149 + phy_power_up(dev, i);
151 memset(&msg, 0, sizeof(msg));
152 msg.cmd = NPE_VLAN_SETRXQOSENTRY;
153 @@ -1107,10 +1169,8 @@ static int eth_close(struct net_device *
154 printk(KERN_CRIT "%s: unable to disable loopback\n",
157 - port->mii_bmcr = mdio_read(dev, port->plat->phy, MII_BMCR) &
158 - ~(BMCR_RESET | BMCR_PDOWN); /* may have been altered */
159 - mdio_write(dev, port->plat->phy, MII_BMCR,
160 - port->mii_bmcr | BMCR_PDOWN);
161 + for (i = 0; i < port->phy_count; i++)
162 + phy_power_down(dev, i);
165 qmgr_disable_irq(TXDONE_QUEUE);
166 @@ -1120,6 +1180,42 @@ static int eth_close(struct net_device *
170 +static void eth_add_phy(struct net_device *dev, int phy_id)
172 + struct port *port = netdev_priv(dev);
175 + i = port->phy_count++;
177 + port->mii[i].dev = dev;
178 + port->mii[i].mdio_read = mdio_read;
179 + port->mii[i].mdio_write = mdio_write;
180 + port->mii[i].phy_id = phy_id;
181 + port->mii[i].phy_id_mask = 0x1F;
182 + port->mii[i].reg_num_mask = 0x1F;
184 + printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, phy_id,
185 + npe_name(port->npe));
188 + phy_power_down(dev, i);
191 +static void eth_init_mii(struct net_device *dev)
193 + struct port *port = netdev_priv(dev);
195 + if (port->plat->phy < IXP4XX_ETH_PHY_MAX_ADDR) {
196 + eth_add_phy(dev, port->plat->phy);
199 + for (i = 0; i < IXP4XX_ETH_PHY_MAX_ADDR; i++)
200 + if (port->plat->phy_mask & (1U << i))
201 + eth_add_phy(dev, i);
206 static int __devinit eth_init_one(struct platform_device *pdev)
209 @@ -1192,20 +1288,7 @@ static int __devinit eth_init_one(struct
210 __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
213 - port->mii.dev = dev;
214 - port->mii.mdio_read = mdio_read;
215 - port->mii.mdio_write = mdio_write;
216 - port->mii.phy_id = plat->phy;
217 - port->mii.phy_id_mask = 0x1F;
218 - port->mii.reg_num_mask = 0x1F;
220 - printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
221 - npe_name(port->npe));
223 - phy_reset(dev, plat->phy);
224 - port->mii_bmcr = mdio_read(dev, plat->phy, MII_BMCR) &
225 - ~(BMCR_RESET | BMCR_PDOWN);
226 - mdio_write(dev, plat->phy, MII_BMCR, port->mii_bmcr | BMCR_PDOWN);
229 INIT_DELAYED_WORK(&port->mdio_thread, mdio_thread);
231 Index: linux-2.6.25.1/include/asm-arm/arch-ixp4xx/platform.h
232 ===================================================================
233 --- linux-2.6.25.1.orig/include/asm-arm/arch-ixp4xx/platform.h
234 +++ linux-2.6.25.1/include/asm-arm/arch-ixp4xx/platform.h
235 @@ -95,12 +95,15 @@ struct sys_timer;
236 #define IXP4XX_ETH_NPEB 0x10
237 #define IXP4XX_ETH_NPEC 0x20
239 +#define IXP4XX_ETH_PHY_MAX_ADDR 32
241 /* Information about built-in Ethernet MAC interfaces */
242 struct eth_plat_info {
243 u8 phy; /* MII PHY ID, 0 - 31 */
244 u8 rxq; /* configurable, currently 0 - 31 only */
250 /* Information about built-in HSS (synchronous serial) interfaces */