rename patch
[openwrt.git] / target / linux / ixp4xx / patches-2.6.24 / 202-npe_driver_switch_support.patch
1 Index: linux-2.6.24.7/drivers/net/arm/ixp4xx_eth.c
2 ===================================================================
3 --- linux-2.6.24.7.orig/drivers/net/arm/ixp4xx_eth.c
4 +++ linux-2.6.24.7/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 */
15         u32 desc_tab_phys;
16         int id;                 /* logical port ID */
17 -       u16 mii_bmcr;
18 +       u16 mii_bmcr[IXP4XX_ETH_PHY_MAX_ADDR];
19 +       int phy_count;
20  };
21  
22  /* NPE message structure */
23 @@ -316,13 +317,14 @@ static void mdio_write(struct net_device
24         spin_unlock_irqrestore(&mdio_lock, flags);
25  }
26  
27 -static void phy_reset(struct net_device *dev, int phy_id)
28 +static void phy_reset(struct net_device *dev, int idx)
29  {
30         struct port *port = netdev_priv(dev);
31 +       int phy_id = port->mii[idx].phy_id;
32         int cycles = 0;
33  
34 -       mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr | BMCR_RESET);
35 -       
36 +       mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_RESET);
37 +
38         while (cycles < MAX_MII_RESET_RETRIES) {
39                 if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) {
40  #if DEBUG_MDIO
41 @@ -335,12 +337,12 @@ static void phy_reset(struct net_device 
42                 cycles++;
43         }
44  
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);
47  }
48  
49 -static void eth_set_duplex(struct port *port)
50 +static void eth_set_duplex(struct port *port, int full_duplex)
51  {
52 -       if (port->mii.full_duplex)
53 +       if (full_duplex)
54                 __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
55                              &port->regs->tx_control[0]);
56         else
57 @@ -348,7 +350,7 @@ static void eth_set_duplex(struct port *
58                              &port->regs->tx_control[0]);
59  }
60  
61 -
62 +#if 0
63  static void phy_check_media(struct port *port, int init)
64  {
65         if (mii_check_media(&port->mii, 1, init))
66 @@ -367,7 +369,63 @@ static void phy_check_media(struct port 
67                 }
68         }
69  }
70 +#else
71 +static void phy_update_link(struct net_device *dev, int link)
72 +{
73 +       int prev_link = netif_carrier_ok(dev);
74 +
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);
81 +       }
82 +}
83 +
84 +static void phy_check_media(struct port *port, int init)
85 +{
86 +       struct net_device *dev = port->netdev;
87 +
88 +       if (port->phy_count == 1) {
89 +               struct mii_if_info *mii = &port->mii[0];
90 +
91 +               if (mii_check_media(mii, 1, init))
92 +                       eth_set_duplex(port, mii->full_duplex);
93 +
94 +               if (mii->force_media) /* mii_check_media() doesn't work */
95 +                       phy_update_link(dev, mii_link_ok(mii));
96 +       } else {
97 +               int cur_link = 0;
98 +               int i;
99 +
100 +               if (init)
101 +                       eth_set_duplex(port, 1);
102 +
103 +               for (i = 0; i < port->phy_count; i++)
104 +                       cur_link |= mii_link_ok(&port->mii[i]);
105 +
106 +               phy_update_link(dev, cur_link);
107 +       }
108 +}
109 +#endif
110  
111 +static void phy_power_down(struct net_device *dev, int idx)
112 +{
113 +       struct port *port = netdev_priv(dev);
114 +       int phy_id = port->mii[idx].phy_id;
115 +
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);
119 +}
120 +
121 +static void phy_power_up(struct net_device *dev, int idx)
122 +{
123 +       struct port *port = netdev_priv(dev);
124 +
125 +       mdio_write(dev, port->mii[idx].phy_id, MII_BMCR, port->mii_bmcr[idx]);
126 +}
127  
128  static void mdio_thread(struct work_struct *work)
129  {
130 @@ -790,9 +848,12 @@ static int eth_ioctl(struct net_device *
131  
132         if (!netif_running(dev))
133                 return -EINVAL;
134 -       err = generic_mii_ioctl(&port->mii, if_mii(req), cmd, &duplex_chg);
135 +       if (port->phy_count != 1)
136 +               return -EOPNOTSUPP;
137 +
138 +       err = generic_mii_ioctl(&port->mii[0], if_mii(req), cmd, &duplex_chg);
139         if (duplex_chg)
140 -               eth_set_duplex(port);
141 +               eth_set_duplex(port, port->mii[0].full_duplex);
142         return err;
143  }
144  
145 @@ -944,7 +1005,8 @@ static int eth_open(struct net_device *d
146                 }
147         }
148  
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);
152  
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",
157                        dev->name);
158  
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);
165  
166         if (!ports_open)
167                 qmgr_disable_irq(TXDONE_QUEUE);
168 @@ -1117,6 +1177,42 @@ static int eth_close(struct net_device *
169         return 0;
170  }
171  
172 +static void eth_add_phy(struct net_device *dev, int phy_id)
173 +{
174 +       struct port *port = netdev_priv(dev);
175 +       int i;
176 +
177 +       i = port->phy_count++;
178 +
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;
185 +
186 +       printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, phy_id,
187 +              npe_name(port->npe));
188 +
189 +       phy_reset(dev, i);
190 +       phy_power_down(dev, i);
191 +}
192 +
193 +static void eth_init_mii(struct net_device *dev)
194 +{
195 +       struct port *port = netdev_priv(dev);
196 +
197 +       if (port->plat->phy < IXP4XX_ETH_PHY_MAX_ADDR) {
198 +               eth_add_phy(dev, port->plat->phy);
199 +       } else {
200 +               int i;
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);
204 +       }
205 +
206 +}
207 +
208  static int __devinit eth_init_one(struct platform_device *pdev)
209  {
210         struct port *port;
211 @@ -1189,20 +1285,7 @@ static int __devinit eth_init_one(struct
212         __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
213         udelay(50);
214  
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;
221 -
222 -       printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
223 -              npe_name(port->npe));
224 -
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);
229 +       eth_init_mii(dev);
230  
231         INIT_DELAYED_WORK(&port->mdio_thread, mdio_thread);
232         return 0;
233 Index: linux-2.6.24.7/include/asm-arm/arch-ixp4xx/platform.h
234 ===================================================================
235 --- linux-2.6.24.7.orig/include/asm-arm/arch-ixp4xx/platform.h
236 +++ linux-2.6.24.7/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
240  
241 +#define IXP4XX_ETH_PHY_MAX_ADDR        32
242 +
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 */
247         u8 txreadyq;
248         u8 hwaddr[6];
249 +       u32 phy_mask;
250  };
251  
252  /* Information about built-in HSS (synchronous serial) interfaces */