[ar7] refresh 973-cpmac_handle_mvswitch.patch
[openwrt.git] / target / linux / ifxmips / files / drivers / net / ifxmips.c
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) 2005 Wu Qi Ming <Qi-Ming.Wu@infineon.com>
17 * Copyright (C) 2008 John Crispin <blogic@openwrt.org>
18 */
19
20 #include <linux/kernel.h>
21 #include <linux/slab.h>
22 #include <linux/errno.h>
23 #include <linux/types.h>
24 #include <linux/interrupt.h>
25 #include <linux/uaccess.h>
26 #include <linux/in.h>
27 #include <linux/netdevice.h>
28 #include <linux/etherdevice.h>
29 #include <linux/phy.h>
30 #include <linux/ip.h>
31 #include <linux/tcp.h>
32 #include <linux/skbuff.h>
33 #include <linux/mm.h>
34 #include <linux/platform_device.h>
35 #include <linux/ethtool.h>
36 #include <linux/init.h>
37 #include <linux/delay.h>
38
39 #include <asm/checksum.h>
40
41 #include <ifxmips.h>
42 #include <ifxmips_dma.h>
43 #include <ifxmips_pmu.h>
44 #include <ifxmips_platform.h>
45
46 struct ifxmips_mii_priv {
47 struct net_device_stats stats;
48 struct dma_device_info *dma_device;
49 struct sk_buff *skb;
50
51 struct mii_bus *mii_bus;
52 struct phy_device *phydev;
53 int oldlink, oldspeed, oldduplex;
54 };
55
56 static struct net_device *ifxmips_mii0_dev;
57 static unsigned char mac_addr[MAX_ADDR_LEN];
58
59 static int ifxmips_mdiobus_write(struct mii_bus *bus, int phy_addr,
60 int phy_reg, u16 phy_data)
61 {
62 u32 val = MDIO_ACC_REQUEST |
63 ((phy_addr & MDIO_ACC_ADDR_MASK) << MDIO_ACC_ADDR_OFFSET) |
64 ((phy_reg & MDIO_ACC_REG_MASK) << MDIO_ACC_REG_OFFSET) |
65 phy_data;
66
67 while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST)
68 ;
69 ifxmips_w32(val, IFXMIPS_PPE32_MDIO_ACC);
70
71 return 0;
72 }
73
74 static int ifxmips_mdiobus_read(struct mii_bus *bus, int phy_addr, int phy_reg)
75 {
76 u32 val = MDIO_ACC_REQUEST | MDIO_ACC_READ |
77 ((phy_addr & MDIO_ACC_ADDR_MASK) << MDIO_ACC_ADDR_OFFSET) |
78 ((phy_reg & MDIO_ACC_REG_MASK) << MDIO_ACC_REG_OFFSET);
79
80 while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST)
81 ;
82 ifxmips_w32(val, IFXMIPS_PPE32_MDIO_ACC);
83 while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST)
84 ;
85 val = ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_VAL_MASK;
86 return val;
87 }
88
89 int ifxmips_ifxmips_mii_open(struct net_device *dev)
90 {
91 struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
92 struct dma_device_info *dma_dev = priv->dma_device;
93 int i;
94
95 for (i = 0; i < dma_dev->max_rx_chan_num; i++) {
96 if ((dma_dev->rx_chan[i])->control == IFXMIPS_DMA_CH_ON)
97 (dma_dev->rx_chan[i])->open(dma_dev->rx_chan[i]);
98 }
99 netif_start_queue(dev);
100 return 0;
101 }
102
103 int ifxmips_mii_release(struct net_device *dev)
104 {
105 struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
106 struct dma_device_info *dma_dev = priv->dma_device;
107 int i;
108
109 for (i = 0; i < dma_dev->max_rx_chan_num; i++)
110 dma_dev->rx_chan[i]->close(dma_dev->rx_chan[i]);
111 netif_stop_queue(dev);
112 return 0;
113 }
114
115 int ifxmips_mii_hw_receive(struct net_device *dev, struct dma_device_info *dma_dev)
116 {
117 struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
118 unsigned char *buf = NULL;
119 struct sk_buff *skb = NULL;
120 int len = 0;
121
122 len = dma_device_read(dma_dev, &buf, (void **)&skb);
123
124 if (len >= ETHERNET_PACKET_DMA_BUFFER_SIZE) {
125 printk(KERN_INFO "ifxmips_mii0: packet too large %d\n", len);
126 goto ifxmips_mii_hw_receive_err_exit;
127 }
128
129 /* remove CRC */
130 len -= 4;
131 if (skb == NULL) {
132 printk(KERN_INFO "ifxmips_mii0: cannot restore pointer\n");
133 goto ifxmips_mii_hw_receive_err_exit;
134 }
135
136 if (len > (skb->end - skb->tail)) {
137 printk(KERN_INFO "ifxmips_mii0: BUG, len:%d end:%p tail:%p\n",
138 (len+4), skb->end, skb->tail);
139 goto ifxmips_mii_hw_receive_err_exit;
140 }
141
142 skb_put(skb, len);
143 skb->dev = dev;
144 skb->protocol = eth_type_trans(skb, dev);
145 netif_rx(skb);
146
147 priv->stats.rx_packets++;
148 priv->stats.rx_bytes += len;
149 return 0;
150
151 ifxmips_mii_hw_receive_err_exit:
152 if (len == 0) {
153 if (skb)
154 dev_kfree_skb_any(skb);
155 priv->stats.rx_errors++;
156 priv->stats.rx_dropped++;
157 return -EIO;
158 } else {
159 return len;
160 }
161 }
162
163 int ifxmips_mii_hw_tx(char *buf, int len, struct net_device *dev)
164 {
165 int ret = 0;
166 struct ifxmips_mii_priv *priv = netdev_priv(dev);
167 struct dma_device_info *dma_dev = priv->dma_device;
168 ret = dma_device_write(dma_dev, buf, len, priv->skb);
169 return ret;
170 }
171
172 int ifxmips_mii_tx(struct sk_buff *skb, struct net_device *dev)
173 {
174 int len;
175 char *data;
176 struct ifxmips_mii_priv *priv = netdev_priv(dev);
177 struct dma_device_info *dma_dev = priv->dma_device;
178
179 len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
180 data = skb->data;
181 priv->skb = skb;
182 dev->trans_start = jiffies;
183 /* TODO: we got more than 1 dma channel,
184 so we should do something intelligent here to select one */
185 dma_dev->current_tx_chan = 0;
186
187 wmb();
188
189 if (ifxmips_mii_hw_tx(data, len, dev) != len) {
190 dev_kfree_skb_any(skb);
191 priv->stats.tx_errors++;
192 priv->stats.tx_dropped++;
193 } else {
194 priv->stats.tx_packets++;
195 priv->stats.tx_bytes += len;
196 }
197
198 return 0;
199 }
200
201 void ifxmips_mii_tx_timeout(struct net_device *dev)
202 {
203 int i;
204 struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
205
206 priv->stats.tx_errors++;
207 for (i = 0; i < priv->dma_device->max_tx_chan_num; i++)
208 priv->dma_device->tx_chan[i]->disable_irq(priv->dma_device->tx_chan[i]);
209 netif_wake_queue(dev);
210 return;
211 }
212
213 int dma_intr_handler(struct dma_device_info *dma_dev, int status)
214 {
215 int i;
216
217 switch (status) {
218 case RCV_INT:
219 ifxmips_mii_hw_receive(ifxmips_mii0_dev, dma_dev);
220 break;
221
222 case TX_BUF_FULL_INT:
223 printk(KERN_INFO "ifxmips_mii0: tx buffer full\n");
224 netif_stop_queue(ifxmips_mii0_dev);
225 for (i = 0; i < dma_dev->max_tx_chan_num; i++) {
226 if ((dma_dev->tx_chan[i])->control == IFXMIPS_DMA_CH_ON)
227 dma_dev->tx_chan[i]->enable_irq(dma_dev->tx_chan[i]);
228 }
229 break;
230
231 case TRANSMIT_CPT_INT:
232 for (i = 0; i < dma_dev->max_tx_chan_num; i++)
233 dma_dev->tx_chan[i]->disable_irq(dma_dev->tx_chan[i]);
234
235 netif_wake_queue(ifxmips_mii0_dev);
236 break;
237 }
238
239 return 0;
240 }
241
242 unsigned char *ifxmips_etop_dma_buffer_alloc(int len, int *byte_offset, void **opt)
243 {
244 unsigned char *buffer = NULL;
245 struct sk_buff *skb = NULL;
246
247 skb = dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE);
248 if (skb == NULL)
249 return NULL;
250
251 buffer = (unsigned char *)(skb->data);
252 skb_reserve(skb, 2);
253 *(int *)opt = (int)skb;
254 *byte_offset = 2;
255
256 return buffer;
257 }
258
259 void ifxmips_etop_dma_buffer_free(unsigned char *dataptr, void *opt)
260 {
261 struct sk_buff *skb = NULL;
262
263 if (opt == NULL) {
264 kfree(dataptr);
265 } else {
266 skb = (struct sk_buff *)opt;
267 dev_kfree_skb_any(skb);
268 }
269 }
270
271 static void
272 ifxmips_adjust_link(struct net_device *dev)
273 {
274 struct ifxmips_mii_priv *priv = netdev_priv(dev);
275 struct phy_device *phydev = priv->phydev;
276 int new_state = 0;
277
278 /* Did anything change? */
279 if (priv->oldlink != phydev->link ||
280 priv->oldduplex != phydev->duplex ||
281 priv->oldspeed != phydev->speed) {
282 /* Yes, so update status and mark as changed */
283 new_state = 1;
284 priv->oldduplex = phydev->duplex;
285 priv->oldspeed = phydev->speed;
286 priv->oldlink = phydev->link;
287 }
288
289 /* If link status changed, show new status */
290 if (new_state)
291 phy_print_status(phydev);
292 }
293
294 static int mii_probe(struct net_device *dev)
295 {
296 struct ifxmips_mii_priv *priv = netdev_priv(dev);
297 struct phy_device *phydev = NULL;
298 int phy_addr;
299
300 priv->oldlink = 0;
301 priv->oldspeed = 0;
302 priv->oldduplex = -1;
303
304 /* find the first (lowest address) PHY on the current MAC's MII bus */
305 for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
306 if (priv->mii_bus->phy_map[phy_addr]) {
307 phydev = priv->mii_bus->phy_map[phy_addr];
308 break; /* break out with first one found */
309 }
310 }
311
312 if (!phydev) {
313 printk (KERN_ERR "%s: no PHY found\n", dev->name);
314 return -ENODEV;
315 }
316
317 /* now we are supposed to have a proper phydev, to attach to... */
318 BUG_ON(!phydev);
319 BUG_ON(phydev->attached_dev);
320
321 phydev = phy_connect(dev, dev_name(&phydev->dev), &ifxmips_adjust_link,
322 0, PHY_INTERFACE_MODE_MII);
323
324 if (IS_ERR(phydev)) {
325 printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
326 return PTR_ERR(phydev);
327 }
328
329 /* mask with MAC supported features */
330 phydev->supported &= (SUPPORTED_10baseT_Half
331 | SUPPORTED_10baseT_Full
332 | SUPPORTED_100baseT_Half
333 | SUPPORTED_100baseT_Full
334 | SUPPORTED_Autoneg
335 /* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */
336 | SUPPORTED_MII
337 | SUPPORTED_TP);
338
339 phydev->advertising = phydev->supported;
340
341 priv->phydev = phydev;
342
343 printk(KERN_INFO "%s: attached PHY driver [%s] "
344 "(mii_bus:phy_addr=%s, irq=%d)\n",
345 dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
346
347 return 0;
348 }
349
350
351 static int ifxmips_mii_dev_init(struct net_device *dev)
352 {
353 int i;
354 struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
355 ether_setup(dev);
356 dev->watchdog_timeo = 10 * HZ;
357 dev->mtu = 1500;
358 memset(priv, 0, sizeof(struct ifxmips_mii_priv));
359 priv->dma_device = dma_device_reserve("PPE");
360 if (!priv->dma_device) {
361 BUG();
362 return -ENODEV;
363 }
364 priv->dma_device->buffer_alloc = &ifxmips_etop_dma_buffer_alloc;
365 priv->dma_device->buffer_free = &ifxmips_etop_dma_buffer_free;
366 priv->dma_device->intr_handler = &dma_intr_handler;
367 priv->dma_device->max_rx_chan_num = 4;
368
369 for (i = 0; i < priv->dma_device->max_rx_chan_num; i++) {
370 priv->dma_device->rx_chan[i]->packet_size = ETHERNET_PACKET_DMA_BUFFER_SIZE;
371 priv->dma_device->rx_chan[i]->control = IFXMIPS_DMA_CH_ON;
372 }
373
374 for (i = 0; i < priv->dma_device->max_tx_chan_num; i++)
375 if (i == 0)
376 priv->dma_device->tx_chan[i]->control = IFXMIPS_DMA_CH_ON;
377 else
378 priv->dma_device->tx_chan[i]->control = IFXMIPS_DMA_CH_OFF;
379
380 dma_device_register(priv->dma_device);
381
382 printk(KERN_INFO "%s: using mac=", dev->name);
383 for (i = 0; i < 6; i++) {
384 dev->dev_addr[i] = mac_addr[i];
385 printk("%02X%c", dev->dev_addr[i], (i == 5) ? ('\n') : (':'));
386 }
387
388 priv->mii_bus = mdiobus_alloc();
389 if (priv->mii_bus == NULL)
390 return -ENOMEM;
391
392 priv->mii_bus->priv = dev;
393 priv->mii_bus->read = ifxmips_mdiobus_read;
394 priv->mii_bus->write = ifxmips_mdiobus_write;
395 priv->mii_bus->name = "ifxmips_mii";
396 snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
397 priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
398 for(i = 0; i < PHY_MAX_ADDR; ++i)
399 priv->mii_bus->irq[i] = PHY_POLL;
400
401 mdiobus_register(priv->mii_bus);
402
403 return mii_probe(dev);
404 }
405
406 static void ifxmips_mii_chip_init(int mode)
407 {
408 ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_DMA);
409 ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_PPE);
410
411 if (mode == REV_MII_MODE)
412 ifxmips_w32_mask(PPE32_MII_MASK, PPE32_MII_REVERSE, IFXMIPS_PPE32_CFG);
413 else if (mode == MII_MODE)
414 ifxmips_w32_mask(PPE32_MII_MASK, PPE32_MII_NORMAL, IFXMIPS_PPE32_CFG);
415 ifxmips_w32(PPE32_PLEN_UNDER | PPE32_PLEN_OVER, IFXMIPS_PPE32_IG_PLEN_CTRL);
416 ifxmips_w32(PPE32_CGEN, IFXMIPS_PPE32_ENET_MAC_CFG);
417 wmb();
418 }
419
420 static const struct net_device_ops ifxmips_eth_netdev_ops = {
421 .ndo_init = ifxmips_mii_dev_init,
422 .ndo_open = ifxmips_ifxmips_mii_open,
423 .ndo_stop = ifxmips_mii_release,
424 .ndo_start_xmit = ifxmips_mii_tx,
425 .ndo_tx_timeout = ifxmips_mii_tx_timeout,
426 .ndo_change_mtu = eth_change_mtu,
427 .ndo_set_mac_address = eth_mac_addr,
428 .ndo_validate_addr = eth_validate_addr,
429 };
430
431 static int
432 ifxmips_mii_probe(struct platform_device *dev)
433 {
434 int result = 0;
435 struct ifxmips_eth_data *eth = (struct ifxmips_eth_data*)dev->dev.platform_data;
436 ifxmips_mii0_dev = alloc_etherdev(sizeof(struct ifxmips_mii_priv));
437 ifxmips_mii0_dev->netdev_ops = &ifxmips_eth_netdev_ops;
438 memcpy(mac_addr, eth->mac, 6);
439 strcpy(ifxmips_mii0_dev->name, "eth%d");
440 ifxmips_mii_chip_init(eth->mii_mode);
441 result = register_netdev(ifxmips_mii0_dev);
442 if (result) {
443 printk(KERN_INFO "ifxmips_mii0: error %i registering device \"%s\"\n", result, ifxmips_mii0_dev->name);
444 goto out;
445 }
446
447 printk(KERN_INFO "ifxmips_mii0: driver loaded!\n");
448
449 out:
450 return result;
451 }
452
453 static int ifxmips_mii_remove(struct platform_device *dev)
454 {
455 struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(ifxmips_mii0_dev);
456
457 printk(KERN_INFO "ifxmips_mii0: ifxmips_mii0 cleanup\n");
458
459 dma_device_unregister(priv->dma_device);
460 dma_device_release(priv->dma_device);
461 kfree(priv->dma_device);
462 unregister_netdev(ifxmips_mii0_dev);
463 return 0;
464 }
465
466 static struct platform_driver ifxmips_mii_driver = {
467 .probe = ifxmips_mii_probe,
468 .remove = ifxmips_mii_remove,
469 .driver = {
470 .name = "ifxmips_mii0",
471 .owner = THIS_MODULE,
472 },
473 };
474
475 int __init ifxmips_mii_init(void)
476 {
477 int ret = platform_driver_register(&ifxmips_mii_driver);
478 if (ret)
479 printk(KERN_INFO "ifxmips_mii0: Error registering platfom driver!");
480 return ret;
481 }
482
483 static void __exit ifxmips_mii_cleanup(void)
484 {
485 platform_driver_unregister(&ifxmips_mii_driver);
486 }
487
488 module_init(ifxmips_mii_init);
489 module_exit(ifxmips_mii_cleanup);
490
491 MODULE_LICENSE("GPL");
492 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
493 MODULE_DESCRIPTION("ethernet driver for IFXMIPS boards");
This page took 0.067946 seconds and 5 git commands to generate.