ethernet: remove mac from wifi
[firefly-linux-kernel-4.4.55.git] / drivers / net / rk29_vmac.c
1 /*\r
2  * linux/arch/arc/drivers/arcvmac.c\r
3  *\r
4  * Copyright (C) 2003-2006 Codito Technologies, for linux-2.4 port\r
5  * Copyright (C) 2006-2007 Celunite Inc, for linux-2.6 port\r
6  * Copyright (C) 2007-2008 Sagem Communications, Fehmi HAFSI\r
7  * Copyright (C) 2009 Sagem Communications, Andreas Fenkart\r
8  * All Rights Reserved.\r
9  *\r
10  * This program is free software; you can redistribute it and/or modify\r
11  * it under the terms of the GNU General Public License as published by\r
12  * the Free Software Foundation; either version 2 of the License, or\r
13  * (at your option) any later version.\r
14  *\r
15  * This program is distributed in the hope that it will be useful,\r
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
18  * GNU General Public License for more details.\r
19  *\r
20  * You should have received a copy of the GNU General Public License\r
21  * along with this program; if not, write to the Free Software\r
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
23  *\r
24  * external PHY support based on dnet.c\r
25  * ring management based on bcm63xx_enet.c\r
26  *\r
27  * Authors: amit.bhor@celunite.com, sameer.dhavale@celunite.com\r
28  */\r
29 \r
30 //#define DEBUG\r
31 \r
32 #include <linux/clk.h>\r
33 #include <linux/crc32.h>\r
34 #include <linux/delay.h>\r
35 #include <linux/dma-mapping.h>\r
36 #include <linux/etherdevice.h>\r
37 #include <linux/init.h>\r
38 #include <linux/io.h>\r
39 #include <linux/kernel.h>\r
40 #include <linux/module.h>\r
41 #include <linux/moduleparam.h>\r
42 #include <linux/netdevice.h>\r
43 #include <linux/phy.h>\r
44 #include <linux/platform_device.h>\r
45 #include <linux/slab.h>\r
46 #include <linux/types.h>\r
47 #include <linux/wakelock.h>\r
48 #include <linux/version.h>\r
49 \r
50 #include <mach/iomux.h>\r
51 #include <mach/gpio.h>\r
52 #include <mach/cru.h>\r
53 #include <mach/board.h>\r
54 \r
55 #include "rk29_vmac.h"\r
56 #include "eth_mac/eth_mac.h"\r
57 \r
58 static struct wake_lock idlelock; /* add by lyx @ 20110302 */\r
59 \r
60 /* Register access macros */\r
61 #define vmac_writel(port, value, reg)   \\r
62         writel((value), (port)->regs + reg##_OFFSET)\r
63 #define vmac_readl(port, reg)   readl((port)->regs + reg##_OFFSET)\r
64 \r
65 static unsigned char *read_mac_reg(struct net_device *dev,\r
66                 unsigned char hwaddr[ETH_ALEN])\r
67 {\r
68         struct vmac_priv *ap = netdev_priv(dev);\r
69         unsigned mac_lo, mac_hi;\r
70 \r
71         WARN_ON(!hwaddr);\r
72         mac_lo = vmac_readl(ap, ADDRL);\r
73         mac_hi = vmac_readl(ap, ADDRH);\r
74 \r
75         hwaddr[0] = (mac_lo >> 0) & 0xff;\r
76         hwaddr[1] = (mac_lo >> 8) & 0xff;\r
77         hwaddr[2] = (mac_lo >> 16) & 0xff;\r
78         hwaddr[3] = (mac_lo >> 24) & 0xff;\r
79         hwaddr[4] = (mac_hi >> 0) & 0xff;\r
80         hwaddr[5] = (mac_hi >> 8) & 0xff;\r
81         return hwaddr;\r
82 }\r
83 \r
84 static void write_mac_reg(struct net_device *dev, unsigned char* hwaddr)\r
85 {\r
86         struct vmac_priv *ap = netdev_priv(dev);\r
87         unsigned mac_lo, mac_hi;\r
88 \r
89         mac_lo = hwaddr[3] << 24 | hwaddr[2] << 16 | hwaddr[1] << 8 | hwaddr[0];\r
90         mac_hi = hwaddr[5] << 8 | hwaddr[4];\r
91 \r
92         vmac_writel(ap, mac_lo, ADDRL);\r
93         vmac_writel(ap, mac_hi, ADDRH);\r
94 }\r
95 \r
96 static void vmac_mdio_xmit(struct vmac_priv *ap, unsigned val)\r
97 {\r
98         init_completion(&ap->mdio_complete);\r
99         vmac_writel(ap, val, MDIO_DATA);\r
100         if(!wait_for_completion_timeout(&ap->mdio_complete, msecs_to_jiffies(1000)))\r
101                 printk("Time out for waiting mdio completion\n");\r
102 }\r
103 \r
104 static int vmac_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)\r
105 {\r
106         struct vmac_priv *vmac = bus->priv;\r
107         unsigned int val;\r
108         /* only 5 bits allowed for phy-addr and reg_offset */\r
109         WARN_ON(phy_id & ~0x1f || phy_reg & ~0x1f);\r
110 \r
111         val = MDIO_BASE | MDIO_OP_READ;\r
112         val |= phy_id << 23 | phy_reg << 18;\r
113         vmac_mdio_xmit(vmac, val);\r
114 \r
115         val = vmac_readl(vmac, MDIO_DATA);\r
116         return val & MDIO_DATA_MASK;\r
117 }\r
118 \r
119 static int vmac_mdio_write(struct mii_bus *bus, int phy_id, int phy_reg,\r
120                          u16 value)\r
121 {\r
122         struct vmac_priv *vmac = bus->priv;\r
123         unsigned int val;\r
124         /* only 5 bits allowed for phy-addr and reg_offset */\r
125         WARN_ON(phy_id & ~0x1f || phy_reg & ~0x1f);\r
126 \r
127         val = MDIO_BASE | MDIO_OP_WRITE;\r
128         val |= phy_id << 23 | phy_reg << 18;\r
129         val |= (value & MDIO_DATA_MASK);\r
130         vmac_mdio_xmit(vmac, val);\r
131         return 0;\r
132 }\r
133 \r
134 static void vmac_handle_link_change(struct net_device *dev)\r
135 {\r
136         struct vmac_priv *ap = netdev_priv(dev);\r
137         struct phy_device *phydev = ap->phy_dev;\r
138         unsigned long flags;\r
139         int report_change = 0;\r
140         struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
141 \r
142         spin_lock_irqsave(&ap->lock, flags);\r
143 \r
144         if (phydev->duplex != ap->duplex) {\r
145                 unsigned tmp;\r
146 \r
147                 tmp = vmac_readl(ap, CONTROL);\r
148 \r
149                 if (phydev->duplex)\r
150                         tmp |= ENFL_MASK;\r
151                 else\r
152                         tmp &= ~ENFL_MASK;\r
153 \r
154                 vmac_writel(ap, tmp, CONTROL);\r
155 \r
156                 ap->duplex = phydev->duplex;\r
157                 report_change = 1;\r
158         }\r
159 \r
160         if (phydev->speed != ap->speed) {\r
161                 ap->speed = phydev->speed;\r
162                 report_change = 1;\r
163         }\r
164 \r
165         if (pdata && pdata->rmii_speed_switch)\r
166                 pdata->rmii_speed_switch(phydev->speed);\r
167 \r
168         if (phydev->link != ap->link) {\r
169                 ap->link = phydev->link;\r
170                 report_change = 1;\r
171         }\r
172 \r
173         spin_unlock_irqrestore(&ap->lock, flags);\r
174 \r
175         if (report_change)\r
176                 phy_print_status(ap->phy_dev);\r
177 }\r
178 \r
179 static int __devinit vmac_mii_probe(struct net_device *dev)\r
180 {\r
181         struct vmac_priv *ap = netdev_priv(dev);\r
182         struct phy_device *phydev = NULL;       \r
183         //struct clk *sys_clk;\r
184         //unsigned long clock_rate;\r
185         int phy_addr, err;\r
186 \r
187         /* find the first phy */\r
188         for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {\r
189                 if (ap->mii_bus->phy_map[phy_addr]) {\r
190                         phydev = ap->mii_bus->phy_map[phy_addr];\r
191                         break;\r
192                 }\r
193         }\r
194 \r
195         if (!phydev) {\r
196                 dev_err(&dev->dev, "no PHY found\n");\r
197                 return -ENODEV;\r
198         }\r
199 \r
200         /* add pin_irq, if avail */\r
201         phydev = phy_connect(dev, dev_name(&phydev->dev),\r
202                         &vmac_handle_link_change, 0,\r
203                         //PHY_INTERFACE_MODE_MII);\r
204                         PHY_INTERFACE_MODE_RMII);//????????\r
205         if (IS_ERR(phydev)) {\r
206                 err = PTR_ERR(phydev);\r
207                 dev_err(&dev->dev, "could not attach to PHY %d\n", err);\r
208                 goto err_out;\r
209         }\r
210 \r
211         phydev->supported &= PHY_BASIC_FEATURES;\r
212         phydev->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause;\r
213 \r
214 #if 0\r
215         sys_clk = clk_get(NULL, "mac_ref");////////\r
216         if (IS_ERR(sys_clk)) {\r
217                 err = PTR_ERR(sys_clk);\r
218                 goto err_disconnect;\r
219         }\r
220         \r
221         clk_set_rate(sys_clk,50000000);\r
222         clock_rate = clk_get_rate(sys_clk);\r
223         clk_put(sys_clk);\r
224         \r
225         printk("%s::%d --mac clock = %d\n",__func__, __LINE__, clock_rate);\r
226         dev_dbg(&ap->pdev->dev, "clk_get: dev_name : %s %lu\n",\r
227                         dev_name(&ap->pdev->dev),\r
228                         clock_rate);\r
229 \r
230         if (clock_rate < 25000000)\r
231                 phydev->supported &= ~(SUPPORTED_100baseT_Half |\r
232                                 SUPPORTED_100baseT_Full);\r
233 #endif\r
234 \r
235         phydev->advertising = phydev->supported;\r
236 \r
237         ap->link = 0;\r
238         ap->speed = 0;\r
239         ap->duplex = -1;\r
240         ap->phy_dev = phydev;\r
241 \r
242         return 0;\r
243 //err_disconnect:\r
244 //      phy_disconnect(phydev);\r
245 err_out:\r
246         return err;\r
247 }\r
248 \r
249 static int __devinit vmac_mii_init(struct vmac_priv *ap)\r
250 {\r
251         int err, i;\r
252 \r
253         ap->mii_bus = mdiobus_alloc();\r
254         \r
255         if (ap->mii_bus == NULL)\r
256                 return -ENOMEM;\r
257 \r
258         ap->mii_bus->name = "vmac_mii_bus";\r
259         ap->mii_bus->read = &vmac_mdio_read;\r
260         ap->mii_bus->write = &vmac_mdio_write;\r
261 \r
262         snprintf(ap->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);\r
263 \r
264         ap->mii_bus->priv = ap;\r
265 \r
266         err = -ENOMEM;\r
267         ap->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);\r
268         if (!ap->mii_bus->irq)\r
269                 goto err_out;\r
270 \r
271         for (i = 0; i < PHY_MAX_ADDR; i++)\r
272                 ap->mii_bus->irq[i] = PHY_POLL;\r
273 \r
274 #if 0\r
275         /* FIXME: what is it used for? */\r
276         platform_set_drvdata(ap->dev, ap->mii_bus);\r
277 #endif\r
278 \r
279         err = mdiobus_register(ap->mii_bus);\r
280         if (err)\r
281                 goto err_out_free_mdio_irq;\r
282 \r
283         err = vmac_mii_probe(ap->dev);\r
284         if (err)\r
285                 goto err_out_unregister_bus;\r
286 \r
287         return 0;\r
288 \r
289 err_out_unregister_bus:\r
290         mdiobus_unregister(ap->mii_bus);\r
291 err_out_free_mdio_irq:\r
292         kfree(ap->mii_bus->irq);\r
293 err_out:\r
294         mdiobus_free(ap->mii_bus);\r
295         ap->mii_bus = NULL;\r
296         return err;\r
297 }\r
298 \r
299 static void vmac_mii_exit(struct net_device *dev)\r
300 {\r
301         struct vmac_priv *ap = netdev_priv(dev);\r
302 \r
303         if (ap->phy_dev)\r
304                 phy_disconnect(ap->phy_dev);\r
305         if (ap->mii_bus) {\r
306                 mdiobus_unregister(ap->mii_bus);\r
307                 kfree(ap->mii_bus->irq);\r
308                 mdiobus_free(ap->mii_bus);\r
309                 ap->mii_bus = NULL;\r
310         }\r
311 }\r
312 \r
313 static int vmacether_get_settings(struct net_device *dev,\r
314                 struct ethtool_cmd *cmd)\r
315 {\r
316         struct vmac_priv *ap = netdev_priv(dev);\r
317         struct phy_device *phydev = ap->phy_dev;\r
318 \r
319         if (!phydev)\r
320                 return -ENODEV;\r
321 \r
322         return phy_ethtool_gset(phydev, cmd);\r
323 }\r
324 \r
325 static int vmacether_set_settings(struct net_device *dev,\r
326                 struct ethtool_cmd *cmd)\r
327 {\r
328         struct vmac_priv *ap = netdev_priv(dev);\r
329         struct phy_device *phydev = ap->phy_dev;\r
330 \r
331         if (!phydev)\r
332                 return -ENODEV;\r
333 \r
334         return phy_ethtool_sset(phydev, cmd);\r
335 }\r
336 \r
337 static int vmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)\r
338 {\r
339         struct vmac_priv *ap = netdev_priv(dev);\r
340         struct phy_device *phydev = ap->phy_dev;\r
341 \r
342         if (!netif_running(dev))\r
343                 return -EINVAL;\r
344 \r
345         if (!phydev)\r
346                 return -ENODEV;\r
347 \r
348         return phy_mii_ioctl(phydev, rq, cmd);\r
349 }\r
350 \r
351 static void vmacether_get_drvinfo(struct net_device *dev,\r
352                 struct ethtool_drvinfo *info)\r
353 {\r
354         struct vmac_priv *ap = netdev_priv(dev);\r
355 \r
356         strlcpy(info->driver, VMAC_NAME, sizeof(info->driver));\r
357         strlcpy(info->version, VMAC_VERSION, sizeof(info->version));\r
358         snprintf(info->bus_info, sizeof(info->bus_info),\r
359                         "platform 0x%x", ap->mem_base);\r
360 }\r
361 \r
362 static int update_error_counters(struct net_device *dev, int status)\r
363 {\r
364         struct vmac_priv *ap = netdev_priv(dev);\r
365         dev_dbg(&ap->pdev->dev, "rx error counter overrun. status = 0x%x\n",\r
366                         status);\r
367 \r
368         /* programming error */\r
369         WARN_ON(status & TXCH_MASK);\r
370         WARN_ON(!(status & (MSER_MASK | RXCR_MASK | RXFR_MASK | RXFL_MASK)));\r
371 \r
372         if (status & MSER_MASK)\r
373                 ap->stats.rx_over_errors += 256; /* ran out of BD */\r
374         if (status & RXCR_MASK)\r
375                 ap->stats.rx_crc_errors += 256;\r
376         if (status & RXFR_MASK)\r
377                 ap->stats.rx_frame_errors += 256;\r
378         if (status & RXFL_MASK)\r
379                 ap->stats.rx_fifo_errors += 256;\r
380 \r
381         return 0;\r
382 }\r
383 \r
384 static void update_tx_errors(struct net_device *dev, int status)\r
385 {\r
386         struct vmac_priv *ap = netdev_priv(dev);\r
387 \r
388         if (status & UFLO)\r
389                 ap->stats.tx_fifo_errors++;\r
390 \r
391         if (ap->duplex)\r
392                 return;\r
393 \r
394         /* half duplex flags */\r
395         if (status & LTCL)\r
396                 ap->stats.tx_window_errors++;\r
397         if (status & RETRY_CT)\r
398                 ap->stats.collisions += (status & RETRY_CT) >> 24;\r
399         if (status & DROP)  /* too many retries */\r
400                 ap->stats.tx_aborted_errors++;\r
401         if (status & DEFER)\r
402                 dev_vdbg(&ap->pdev->dev, "\"defer to traffic\"\n");\r
403         if (status & CARLOSS)\r
404                 ap->stats.tx_carrier_errors++;\r
405 }\r
406 \r
407 static int vmac_rx_reclaim_force(struct net_device *dev)\r
408 {\r
409         struct vmac_priv *ap = netdev_priv(dev);\r
410         int ct;\r
411 \r
412         ct = 0;\r
413 \r
414         dev_dbg(&ap->pdev->dev, "%s need to release %d rx sk_buff\n",\r
415             __func__, fifo_used(&ap->rx_ring));\r
416 \r
417         while (!fifo_empty(&ap->rx_ring) && ct++ < ap->rx_ring.size) {\r
418                 struct vmac_buffer_desc *desc;\r
419                 struct sk_buff *skb;\r
420                 int desc_idx;\r
421 \r
422                 desc_idx = ap->rx_ring.tail;\r
423                 desc = &ap->rxbd[desc_idx];\r
424                 fifo_inc_tail(&ap->rx_ring);\r
425 \r
426                 if (!ap->rx_skbuff[desc_idx]) {\r
427                         dev_err(&ap->pdev->dev, "non-populated rx_skbuff found %d\n",\r
428                                         desc_idx);\r
429                         continue;\r
430                 }\r
431 \r
432                 skb = ap->rx_skbuff[desc_idx];\r
433                 ap->rx_skbuff[desc_idx] = NULL;\r
434 \r
435                 dma_unmap_single(&ap->pdev->dev, desc->data, skb->len,\r
436                     DMA_TO_DEVICE);\r
437 \r
438                 dev_kfree_skb(skb);\r
439         }\r
440 \r
441         if (!fifo_empty(&ap->rx_ring)) {\r
442                 dev_err(&ap->pdev->dev, "failed to reclaim %d rx sk_buff\n",\r
443                                 fifo_used(&ap->rx_ring));\r
444         }\r
445 \r
446         return 0;\r
447 }\r
448 \r
449 static int vmac_rx_refill(struct net_device *dev)\r
450 {\r
451         struct vmac_priv *ap = netdev_priv(dev);\r
452 \r
453         WARN_ON(fifo_full(&ap->rx_ring));\r
454 \r
455         while (!fifo_full(&ap->rx_ring)) {\r
456                 struct vmac_buffer_desc *desc;\r
457                 struct sk_buff *skb;\r
458                 dma_addr_t p;\r
459                 int desc_idx;\r
460 \r
461                 desc_idx = ap->rx_ring.head;\r
462                 desc = &ap->rxbd[desc_idx];\r
463 \r
464                 /* make sure we read the actual descriptor status */\r
465                 rmb();\r
466 \r
467                 if (ap->rx_skbuff[desc_idx]) {\r
468                         /* dropped packet / buffer chaining */\r
469                         fifo_inc_head(&ap->rx_ring);\r
470 \r
471                         /* return to DMA */\r
472                         wmb();\r
473                         desc->info = OWN_MASK | ap->rx_skb_size;\r
474                         continue;\r
475                 }\r
476 \r
477                 skb = netdev_alloc_skb(dev, ap->rx_skb_size + 2);\r
478                 if (!skb) {\r
479                         dev_info(&ap->pdev->dev, "failed to allocate rx_skb, skb's left %d\n",\r
480                                         fifo_used(&ap->rx_ring));\r
481                         break;\r
482                 }\r
483 \r
484                 /* IP header Alignment (14 byte Ethernet header) */\r
485                 skb_reserve(skb, 2);\r
486                 WARN_ON(skb->len != 0); /* nothing received yet */\r
487 \r
488                 ap->rx_skbuff[desc_idx] = skb;\r
489 \r
490                 p = dma_map_single(&ap->pdev->dev, skb->data, ap->rx_skb_size,\r
491                                 DMA_FROM_DEVICE);\r
492 \r
493                 desc->data = p;\r
494 \r
495                 wmb();\r
496                 desc->info = OWN_MASK | ap->rx_skb_size;\r
497 \r
498                 fifo_inc_head(&ap->rx_ring);\r
499         }\r
500 \r
501         /* If rx ring is still empty, set a timer to try allocating\r
502          * again at a later time. */\r
503         if (fifo_empty(&ap->rx_ring) && netif_running(dev)) {\r
504                 dev_warn(&ap->pdev->dev, "unable to refill rx ring\n");\r
505                 ap->rx_timeout.expires = jiffies + HZ;\r
506                 add_timer(&ap->rx_timeout);\r
507         }\r
508 \r
509         return 0;\r
510 }\r
511 \r
512 /*\r
513  * timer callback to defer refill rx queue in case we're OOM\r
514  */\r
515 static void vmac_refill_rx_timer(unsigned long data)\r
516 {\r
517         struct net_device *dev;\r
518         struct vmac_priv *ap;\r
519 \r
520         dev = (struct net_device *)data;\r
521         ap = netdev_priv(dev);\r
522 \r
523         spin_lock(&ap->rx_lock);\r
524         vmac_rx_refill(dev);\r
525         spin_unlock(&ap->rx_lock);\r
526 }\r
527 \r
528 /* merge buffer chaining  */\r
529 struct sk_buff *vmac_merge_rx_buffers(struct net_device *dev,\r
530                 struct vmac_buffer_desc *after,\r
531                 int pkt_len) /* data */\r
532 {\r
533         struct vmac_priv *ap = netdev_priv(dev);\r
534         struct sk_buff *merge_skb, *cur_skb;\r
535         struct dma_fifo *rx_ring;\r
536         struct vmac_buffer_desc *desc;\r
537 \r
538         rx_ring = &ap->rx_ring;\r
539         desc = &ap->rxbd[rx_ring->tail];\r
540 \r
541         WARN_ON(desc == after);\r
542 \r
543         /* strip FCS */\r
544         pkt_len -= 4;\r
545 \r
546         /* IP header Alignment (14 byte Ethernet header) */\r
547         merge_skb = netdev_alloc_skb(dev, pkt_len + 2);\r
548         if (!merge_skb) {\r
549                 dev_err(&ap->pdev->dev, "failed to allocate merged rx_skb, rx skb's left %d\n",\r
550                                 fifo_used(rx_ring));\r
551 \r
552                 return NULL;\r
553         }\r
554 \r
555         skb_reserve(merge_skb, 2);\r
556 \r
557         while (desc != after && pkt_len) {\r
558                 struct vmac_buffer_desc *desc;\r
559                 int buf_len, valid;\r
560 \r
561                 /* desc needs wrapping */\r
562                 desc = &ap->rxbd[rx_ring->tail];\r
563                 cur_skb = ap->rx_skbuff[rx_ring->tail];\r
564                 WARN_ON(!cur_skb);\r
565 \r
566                 dma_unmap_single(&ap->pdev->dev, desc->data, ap->rx_skb_size,\r
567                                 DMA_FROM_DEVICE);\r
568 \r
569                 /* do not copy FCS */\r
570                 buf_len = desc->info & LEN_MASK;\r
571                 valid = min(pkt_len, buf_len);\r
572                 pkt_len -= valid;\r
573 \r
574                 memcpy(skb_put(merge_skb, valid), cur_skb->data, valid);\r
575 \r
576                 fifo_inc_tail(rx_ring);\r
577         }\r
578 \r
579         /* merging_pressure++ */\r
580 \r
581         if (unlikely(pkt_len != 0))\r
582                 dev_err(&ap->pdev->dev, "buffer chaining bytes missing %d\n",\r
583                                 pkt_len);\r
584 \r
585         WARN_ON(desc != after);\r
586 \r
587         return merge_skb;\r
588 }\r
589 \r
590 int vmac_rx_receive(struct net_device *dev, int budget)\r
591 {\r
592         struct vmac_priv *ap = netdev_priv(dev);\r
593         struct vmac_buffer_desc *first;\r
594         int processed, pkt_len, pkt_err;\r
595         struct dma_fifo lookahead;\r
596 \r
597         processed = 0;\r
598 \r
599         first = NULL;\r
600         pkt_err = pkt_len = 0;\r
601 \r
602         /* look ahead, till packet complete */\r
603         lookahead = ap->rx_ring;\r
604 \r
605         do {\r
606                 struct vmac_buffer_desc *desc; /* cur_ */\r
607                 int desc_idx; /* cur_ */\r
608                 struct sk_buff *skb; /* pkt_ */\r
609 \r
610                 desc_idx = lookahead.tail;\r
611                 desc = &ap->rxbd[desc_idx];\r
612 \r
613                 /* make sure we read the actual descriptor status */\r
614                 rmb();\r
615 \r
616                 /* break if dma ownership belongs to hw */\r
617                 if (desc->info & OWN_MASK) {\r
618                         ap->mac_rxring_head = vmac_readl(ap, MAC_RXRING_HEAD);\r
619                         break;\r
620                 }\r
621 \r
622                 if (desc->info & FRST_MASK) {\r
623                         pkt_len = 0;\r
624                         pkt_err = 0;\r
625 \r
626                         /* don't free current */\r
627                         ap->rx_ring.tail = lookahead.tail;\r
628                         first = desc;\r
629                 }\r
630 \r
631                 fifo_inc_tail(&lookahead);\r
632 \r
633                 /* check bd */\r
634 \r
635                 pkt_len += desc->info & LEN_MASK;\r
636                 pkt_err |= (desc->info & BUFF);\r
637 \r
638                 if (!(desc->info & LAST_MASK))\r
639                         continue;\r
640 \r
641                 /* received complete packet */\r
642 \r
643                 if (unlikely(pkt_err || !first)) {\r
644                         /* recycle buffers */\r
645                         ap->rx_ring.tail = lookahead.tail;\r
646                         continue;\r
647                 }\r
648 \r
649                 WARN_ON(!(first->info & FRST_MASK) ||\r
650                                 !(desc->info & LAST_MASK));\r
651                 WARN_ON(pkt_err);\r
652 \r
653                 /* -- valid packet -- */\r
654 \r
655                 if (first != desc) {\r
656                         skb = vmac_merge_rx_buffers(dev, desc, pkt_len);\r
657 \r
658                         if (!skb) {\r
659                                 /* kill packet */\r
660                                 ap->rx_ring.tail = lookahead.tail;\r
661                                 ap->rx_merge_error++;\r
662                                 continue;\r
663                         }\r
664                 } else {\r
665                         dma_unmap_single(&ap->pdev->dev, desc->data,\r
666                                         ap->rx_skb_size, DMA_FROM_DEVICE);\r
667 \r
668                         skb = ap->rx_skbuff[desc_idx];\r
669                         ap->rx_skbuff[desc_idx] = NULL;\r
670                         /* desc->data != skb->data => desc->data DMA mapped */\r
671 \r
672                         /* strip FCS */\r
673                         skb_put(skb, pkt_len - 4);\r
674                 }\r
675 \r
676                 /* free buffers */\r
677                 ap->rx_ring.tail = lookahead.tail;\r
678 \r
679                 WARN_ON(skb->len != pkt_len - 4);\r
680                 processed++;\r
681                 skb->dev = dev;\r
682                 skb->protocol = eth_type_trans(skb, dev);\r
683                 ap->stats.rx_packets++;\r
684                 ap->stats.rx_bytes += skb->len;\r
685                 dev->last_rx = jiffies;\r
686                 netif_rx(skb);\r
687 \r
688         } while (!fifo_empty(&lookahead) && (processed < budget));\r
689 \r
690         dev_vdbg(&ap->pdev->dev, "processed pkt %d, remaining rx buff %d\n",\r
691                         processed,\r
692                         fifo_used(&ap->rx_ring));\r
693 \r
694         if (processed || fifo_empty(&ap->rx_ring))\r
695                 vmac_rx_refill(dev);\r
696 \r
697         return processed;\r
698 }\r
699 \r
700 static void vmac_toggle_irqmask(struct net_device *dev, int enable, int mask)\r
701 {\r
702         struct vmac_priv *ap = netdev_priv(dev);\r
703         unsigned long tmp;\r
704 \r
705         tmp = vmac_readl(ap, ENABLE);\r
706         if (enable)\r
707                 tmp |= mask;\r
708         else\r
709                 tmp &= ~mask;\r
710         vmac_writel(ap, tmp, ENABLE);\r
711 }\r
712 \r
713 static void vmac_toggle_txint(struct net_device *dev, int enable)\r
714 {\r
715         struct vmac_priv *ap = netdev_priv(dev);\r
716         unsigned long flags;\r
717 \r
718         spin_lock_irqsave(&ap->lock, flags);\r
719         vmac_toggle_irqmask(dev, enable, TXINT_MASK);\r
720         spin_unlock_irqrestore(&ap->lock, flags);\r
721 }\r
722 \r
723 static void vmac_toggle_rxint(struct net_device *dev, int enable)\r
724 {\r
725         vmac_toggle_irqmask(dev, enable, RXINT_MASK);\r
726 }\r
727 \r
728 static int vmac_poll(struct napi_struct *napi, int budget)\r
729 {\r
730         struct vmac_priv *ap;\r
731         struct net_device *dev;\r
732         int rx_work_done;\r
733         unsigned long flags;\r
734 \r
735         ap = container_of(napi, struct vmac_priv, napi);\r
736         dev = ap->dev;\r
737 \r
738         /* ack interrupt */\r
739         vmac_writel(ap, RXINT_MASK, STAT);\r
740 \r
741         spin_lock(&ap->rx_lock);\r
742         rx_work_done = vmac_rx_receive(dev, budget);\r
743         spin_unlock(&ap->rx_lock);\r
744 \r
745 #ifdef VERBOSE_DEBUG\r
746         if (printk_ratelimit()) {\r
747                 dev_vdbg(&ap->pdev->dev, "poll budget %d receive rx_work_done %d\n",\r
748                                 budget,\r
749                                 rx_work_done);\r
750         }\r
751 #endif\r
752 \r
753         if (rx_work_done >= budget) {\r
754                 /* rx queue is not yet empty/clean */\r
755                 return rx_work_done;\r
756         }\r
757 \r
758         /* no more packet in rx/tx queue, remove device from poll\r
759          * queue */\r
760         spin_lock_irqsave(&ap->lock, flags);\r
761         napi_complete(napi);\r
762         vmac_toggle_rxint(dev, 1);\r
763         spin_unlock_irqrestore(&ap->lock, flags);\r
764 \r
765         return rx_work_done;\r
766 }\r
767 \r
768 static int vmac_tx_reclaim(struct net_device *dev, int force);\r
769 \r
770 static irqreturn_t vmac_intr(int irq, void *dev_instance)\r
771 {\r
772         struct net_device *dev = dev_instance;\r
773         struct vmac_priv *ap = netdev_priv(dev);\r
774         unsigned int status;\r
775 \r
776         spin_lock(&ap->lock);\r
777 \r
778         status = vmac_readl(ap, STAT);\r
779         vmac_writel(ap, status, STAT);\r
780 \r
781 #ifdef DEBUG\r
782         if (unlikely(ap->shutdown))\r
783                 dev_err(&ap->pdev->dev, "ISR during close\n");\r
784 \r
785         if (unlikely(!status & (RXINT_MASK|MDIO_MASK|ERR_MASK)))\r
786                 dev_err(&ap->pdev->dev, "No source of IRQ found\n");\r
787 #endif\r
788 \r
789         if ((status & RXINT_MASK) &&\r
790                         (ap->mac_rxring_head !=\r
791                          vmac_readl(ap, MAC_RXRING_HEAD))) {\r
792                 vmac_toggle_rxint(dev, 0);\r
793                 napi_schedule(&ap->napi);\r
794         }\r
795 \r
796         if (unlikely(netif_queue_stopped(dev) && (status & TXINT_MASK)))\r
797                 vmac_tx_reclaim(dev, 0);\r
798 \r
799         if (status & MDIO_MASK)\r
800                 complete(&ap->mdio_complete);\r
801 \r
802         if (unlikely(status & ERR_MASK))\r
803                 update_error_counters(dev, status);\r
804 \r
805         spin_unlock(&ap->lock);\r
806 \r
807         return IRQ_HANDLED;\r
808 }\r
809 \r
810 static int vmac_tx_reclaim(struct net_device *dev, int force)\r
811 {\r
812         struct vmac_priv *ap = netdev_priv(dev);\r
813         int released = 0;\r
814 \r
815         /* buffer chaining not used, see vmac_start_xmit */\r
816 \r
817         while (!fifo_empty(&ap->tx_ring)) {\r
818                 struct vmac_buffer_desc *desc;\r
819                 struct sk_buff *skb;\r
820                 int desc_idx;\r
821 \r
822                 desc_idx = ap->tx_ring.tail;\r
823                 desc = &ap->txbd[desc_idx];\r
824 \r
825                 /* ensure other field of the descriptor were not read\r
826                  * before we checked ownership */\r
827                 rmb();\r
828 \r
829                 if ((desc->info & OWN_MASK) && !force)\r
830                         break;\r
831 \r
832                 if (desc->info & ERR_MSK_TX) {\r
833                         update_tx_errors(dev, desc->info);\r
834                         /* recycle packet, let upper level deal with it */\r
835                 }\r
836 \r
837                 skb = ap->tx_skbuff[desc_idx];\r
838                 ap->tx_skbuff[desc_idx] = NULL;\r
839                 WARN_ON(!skb);\r
840 \r
841                 dma_unmap_single(&ap->pdev->dev, desc->data, skb->len,\r
842                                 DMA_TO_DEVICE);\r
843 \r
844                 dev_kfree_skb_any(skb);\r
845 \r
846                 released++;\r
847                 fifo_inc_tail(&ap->tx_ring);\r
848         }\r
849 \r
850         if (netif_queue_stopped(dev) && released) {\r
851                 netif_wake_queue(dev);\r
852                 vmac_toggle_txint(dev, 0);\r
853         }\r
854 \r
855         if (unlikely(force && !fifo_empty(&ap->tx_ring))) {\r
856                 dev_err(&ap->pdev->dev, "failed to reclaim %d tx sk_buff\n",\r
857                                 fifo_used(&ap->tx_ring));\r
858         }\r
859 \r
860         return released;\r
861 }\r
862 \r
863 int vmac_start_xmit(struct sk_buff *skb, struct net_device *dev)\r
864 {\r
865         struct vmac_priv *ap = netdev_priv(dev);\r
866         struct vmac_buffer_desc *desc;\r
867         unsigned int tmp;\r
868 \r
869         /* running under xmit lock */\r
870 \r
871         /* no scatter/gatter see features below */\r
872         WARN_ON(skb_shinfo(skb)->nr_frags != 0);\r
873         WARN_ON(skb->len > MAX_TX_BUFFER_LEN);\r
874 \r
875         if (unlikely(fifo_full(&ap->tx_ring))) {\r
876                 netif_stop_queue(dev);\r
877                 vmac_toggle_txint(dev, 1);\r
878                 dev_err(&ap->pdev->dev, "xmit called with no tx desc available\n");\r
879                 return NETDEV_TX_BUSY;\r
880         }\r
881 \r
882         if (unlikely(skb->len < ETH_ZLEN)) {\r
883                 struct sk_buff *short_skb;\r
884                 short_skb = netdev_alloc_skb(dev, ETH_ZLEN);\r
885                 if (!short_skb)\r
886                         return NETDEV_TX_LOCKED;\r
887 \r
888                 memset(short_skb->data, 0, ETH_ZLEN);\r
889                 memcpy(skb_put(short_skb, ETH_ZLEN), skb->data, skb->len);\r
890                 dev_kfree_skb(skb);\r
891                 skb = short_skb;\r
892         }\r
893 \r
894         /* fill descriptor */\r
895         ap->tx_skbuff[ap->tx_ring.head] = skb;\r
896 \r
897         desc = &ap->txbd[ap->tx_ring.head];\r
898         desc->data = dma_map_single(&ap->pdev->dev, skb->data, skb->len,\r
899                         DMA_TO_DEVICE);\r
900 \r
901         /* dma might already be polling */\r
902         wmb();\r
903         desc->info = OWN_MASK | FRST_MASK | LAST_MASK | skb->len;\r
904         wmb();\r
905 \r
906         /* kick tx dma */\r
907         tmp = vmac_readl(ap, STAT);\r
908         vmac_writel(ap, tmp | TXPL_MASK, STAT);\r
909 \r
910         ap->stats.tx_packets++;\r
911         ap->stats.tx_bytes += skb->len;\r
912         dev->trans_start = jiffies;\r
913         fifo_inc_head(&ap->tx_ring);\r
914 \r
915         /* vmac_tx_reclaim independent of vmac_tx_timeout */\r
916         if (fifo_used(&ap->tx_ring) > 8)\r
917                 vmac_tx_reclaim(dev, 0);\r
918 \r
919         /* stop queue if no more desc available */\r
920         if (fifo_full(&ap->tx_ring)) {\r
921                 netif_stop_queue(dev);\r
922                 vmac_toggle_txint(dev, 1);\r
923         }\r
924 \r
925         return NETDEV_TX_OK;\r
926 }\r
927 \r
928 static int alloc_buffers(struct net_device *dev)\r
929 {\r
930         struct vmac_priv *ap = netdev_priv(dev);\r
931         int err = -ENOMEM;\r
932         int size;\r
933 \r
934         fifo_init(&ap->rx_ring, RX_BDT_LEN);\r
935         fifo_init(&ap->tx_ring, TX_BDT_LEN);\r
936 \r
937         /* initialize skb list */\r
938         memset(ap->rx_skbuff, 0, sizeof(ap->rx_skbuff));\r
939         memset(ap->tx_skbuff, 0, sizeof(ap->tx_skbuff));\r
940 \r
941         /* allocate DMA received descriptors */\r
942         size = sizeof(*ap->rxbd) * ap->rx_ring.size;\r
943         ap->rxbd = dma_alloc_coherent(&ap->pdev->dev, size,\r
944                         &ap->rxbd_dma,\r
945                         GFP_KERNEL);\r
946         if (ap->rxbd == NULL)\r
947                 goto err_out;\r
948 \r
949         /* allocate DMA transmit descriptors */\r
950         size = sizeof(*ap->txbd) * ap->tx_ring.size;\r
951         ap->txbd = dma_alloc_coherent(&ap->pdev->dev, size,\r
952                         &ap->txbd_dma,\r
953                         GFP_KERNEL);\r
954         if (ap->txbd == NULL)\r
955                 goto err_free_rxbd;\r
956 \r
957         /* ensure 8-byte aligned */\r
958         WARN_ON(((int)ap->txbd & 0x7) || ((int)ap->rxbd & 0x7));\r
959 \r
960         memset(ap->txbd, 0, sizeof(*ap->txbd) * ap->tx_ring.size);\r
961         memset(ap->rxbd, 0, sizeof(*ap->rxbd) * ap->rx_ring.size);\r
962 \r
963         /* allocate rx skb */\r
964         err = vmac_rx_refill(dev);\r
965         if (err)\r
966                 goto err_free_txbd;\r
967 \r
968         return 0;\r
969 \r
970 err_free_txbd:\r
971         dma_free_coherent(&ap->pdev->dev, sizeof(*ap->txbd) * ap->tx_ring.size,\r
972                         ap->txbd, ap->txbd_dma);\r
973 err_free_rxbd:\r
974         dma_free_coherent(&ap->pdev->dev, sizeof(*ap->rxbd) * ap->rx_ring.size,\r
975                         ap->rxbd, ap->rxbd_dma);\r
976 err_out:\r
977         return err;\r
978 }\r
979 \r
980 static int free_buffers(struct net_device *dev)\r
981 {\r
982         struct vmac_priv *ap = netdev_priv(dev);\r
983 \r
984         /* free skbuff */\r
985         vmac_tx_reclaim(dev, 1);\r
986         vmac_rx_reclaim_force(dev);\r
987 \r
988         /* free DMA ring */\r
989         dma_free_coherent(&ap->pdev->dev, sizeof(ap->txbd) * ap->tx_ring.size,\r
990                         ap->txbd, ap->txbd_dma);\r
991         dma_free_coherent(&ap->pdev->dev, sizeof(ap->rxbd) * ap->rx_ring.size,\r
992                         ap->rxbd, ap->rxbd_dma);\r
993 \r
994         return 0;\r
995 }\r
996 \r
997 static int vmac_hw_init(struct net_device *dev)\r
998 {\r
999         struct vmac_priv *priv = netdev_priv(dev);\r
1000 \r
1001         /* clear IRQ mask */\r
1002         vmac_writel(priv, 0, ENABLE);\r
1003 \r
1004         /* clear pending IRQ */\r
1005         vmac_writel(priv, 0xffffffff, STAT);\r
1006 \r
1007         /* Initialize logical address filter */\r
1008         vmac_writel(priv, 0x0, LAFL);\r
1009         vmac_writel(priv, 0x0, LAFH);\r
1010 \r
1011         return 0;\r
1012 }\r
1013 \r
1014 #ifdef DEBUG\r
1015 static int vmac_register_print(struct net_device *dev)\r
1016 {\r
1017         struct vmac_priv *ap = netdev_priv(dev);\r
1018 \r
1019         printk("func::%s vmac register %s value = 0x%x\n", __func__, "ID", vmac_readl(ap, ID));\r
1020         printk("func::%s vmac register %s value = 0x%x\n", __func__, "STAT", vmac_readl(ap, STAT));\r
1021         printk("func::%s vmac register %s value = 0x%x\n", __func__, "ENABLE", vmac_readl(ap, ENABLE));\r
1022         printk("func::%s vmac register %s value = 0x%x\n", __func__, "CONTROL", vmac_readl(ap, CONTROL));\r
1023         printk("func::%s vmac register %s value = 0x%x\n", __func__, "ADDRL", vmac_readl(ap, ADDRL));\r
1024         printk("func::%s vmac register %s value = 0x%x\n", __func__, "ADDRH", vmac_readl(ap, ADDRH));\r
1025         \r
1026         return 0;\r
1027 }\r
1028 #endif\r
1029 \r
1030 int vmac_open(struct net_device *dev)\r
1031 {\r
1032         struct vmac_priv *ap = netdev_priv(dev);\r
1033         struct phy_device *phydev;\r
1034         unsigned int temp;\r
1035         int err = 0;\r
1036         struct clk *mac_clk = NULL;\r
1037         struct clk *mac_parent = NULL;\r
1038         struct clk *arm_clk = NULL;\r
1039         struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
1040 \r
1041         printk("enter func %s...\n", __func__);\r
1042 \r
1043         if (ap == NULL)\r
1044                 return -ENODEV;\r
1045 \r
1046         wake_lock_timeout(&ap->resume_lock, 5*HZ);\r
1047 \r
1048         ap->shutdown = 0;\r
1049                 \r
1050         //set rmii ref clock 50MHz\r
1051         mac_clk = clk_get(NULL, "mac_ref_div");\r
1052         if (IS_ERR(mac_clk))\r
1053                 mac_clk = NULL;\r
1054         arm_clk = clk_get(NULL, "arm_pll");\r
1055         if (IS_ERR(arm_clk))\r
1056                 arm_clk = NULL;\r
1057         if (mac_clk) {\r
1058                 mac_parent = clk_get_parent(mac_clk);\r
1059                 if (IS_ERR(mac_parent))\r
1060                         mac_parent = NULL;\r
1061         }\r
1062         if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
1063                 wake_lock(&idlelock);\r
1064         \r
1065         clk_set_rate(mac_clk, 50000000);\r
1066         clk_enable(mac_clk);\r
1067         clk_enable(clk_get(NULL,"mii_rx"));\r
1068         clk_enable(clk_get(NULL,"mii_tx"));\r
1069         clk_enable(clk_get(NULL,"hclk_mac"));\r
1070         clk_enable(clk_get(NULL,"mac_ref"));\r
1071 \r
1072         //phy power on\r
1073         if (pdata && pdata->rmii_power_control)\r
1074                 pdata->rmii_power_control(1);\r
1075 \r
1076         msleep(1000);\r
1077 \r
1078         vmac_hw_init(dev);\r
1079 \r
1080         /* mac address changed? */\r
1081         write_mac_reg(dev, dev->dev_addr);\r
1082 \r
1083         err = alloc_buffers(dev);\r
1084         if (err)\r
1085                 goto err_out;\r
1086 \r
1087         err = request_irq(dev->irq, &vmac_intr, 0, dev->name, dev);\r
1088         if (err) {\r
1089                 dev_err(&ap->pdev->dev, "Unable to request IRQ %d (error %d)\n",\r
1090                                 dev->irq, err);\r
1091                 goto err_free_buffers;\r
1092         }\r
1093 \r
1094         /* install DMA ring pointers */\r
1095         vmac_writel(ap, ap->rxbd_dma, RXRINGPTR);\r
1096         vmac_writel(ap, ap->txbd_dma, TXRINGPTR);\r
1097 \r
1098         /* set poll rate to 1 ms */\r
1099         vmac_writel(ap, POLLRATE_TIME, POLLRATE);\r
1100 \r
1101         /* make sure we enable napi before rx interrupt  */\r
1102         napi_enable(&ap->napi);\r
1103 \r
1104         /* IRQ mask */\r
1105         temp = RXINT_MASK | ERR_MASK | TXCH_MASK | MDIO_MASK;\r
1106         vmac_writel(ap, temp, ENABLE);\r
1107 \r
1108         /* Set control */\r
1109         temp = (RX_BDT_LEN << 24) | (TX_BDT_LEN << 16) | TXRN_MASK | RXRN_MASK;\r
1110         vmac_writel(ap, temp, CONTROL);\r
1111 \r
1112         /* enable, after all other bits are set */\r
1113         vmac_writel(ap, temp | EN_MASK, CONTROL);\r
1114         \r
1115         netif_start_queue(dev);\r
1116         netif_carrier_off(dev);\r
1117 \r
1118 #ifdef DEBUG\r
1119         vmac_register_print(dev);\r
1120 #endif\r
1121 \r
1122         /* register the PHY board fixup, if needed */\r
1123         err = vmac_mii_init(ap);\r
1124         if (err)\r
1125                 goto err_free_irq;\r
1126 \r
1127         /* schedule a link state check */\r
1128         phy_start(ap->phy_dev);\r
1129 \r
1130         phydev = ap->phy_dev;\r
1131         dev_info(&ap->pdev->dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",\r
1132                phydev->drv->name, dev_name(&phydev->dev), phydev->irq);\r
1133 \r
1134         ap->suspending = 0;\r
1135         ap->open_flag = 1;\r
1136 \r
1137         return 0;\r
1138 \r
1139 err_free_irq:\r
1140         free_irq(dev->irq, dev);\r
1141 err_free_buffers:\r
1142         free_buffers(dev);\r
1143 err_out:        \r
1144         if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
1145                 wake_unlock(&idlelock);\r
1146 \r
1147         return err;\r
1148 }\r
1149 \r
1150 int vmac_close(struct net_device *dev)\r
1151 {\r
1152         struct vmac_priv *ap = netdev_priv(dev);\r
1153         unsigned int temp;\r
1154         struct clk *mac_clk = NULL;\r
1155         struct clk *arm_clk = NULL;\r
1156         struct clk *mac_parent = NULL;\r
1157         struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
1158 \r
1159         printk("enter func %s...\n", __func__);\r
1160         \r
1161         if (ap->suspending == 1) \r
1162                 return 0;\r
1163 \r
1164         ap->open_flag = 0;\r
1165 \r
1166         netif_stop_queue(dev);\r
1167         napi_disable(&ap->napi);\r
1168 \r
1169         /* stop running transfers */\r
1170         temp = vmac_readl(ap, CONTROL);\r
1171         temp &= ~(TXRN_MASK | RXRN_MASK);\r
1172         vmac_writel(ap, temp, CONTROL);\r
1173 \r
1174         del_timer_sync(&ap->rx_timeout);\r
1175 \r
1176         /* disable phy */\r
1177         phy_stop(ap->phy_dev);\r
1178         vmac_mii_exit(dev);\r
1179         netif_carrier_off(dev);\r
1180 \r
1181         /* disable interrupts */\r
1182         vmac_writel(ap, 0, ENABLE);\r
1183         free_irq(dev->irq, dev);\r
1184 \r
1185         /* turn off vmac */\r
1186         vmac_writel(ap, 0, CONTROL);\r
1187         /* vmac_reset_hw(vmac) */\r
1188 \r
1189         ap->shutdown = 1;\r
1190         wmb();\r
1191 \r
1192         free_buffers(dev);\r
1193 \r
1194         //phy power off\r
1195         if (pdata && pdata->rmii_power_control)\r
1196                 pdata->rmii_power_control(0);\r
1197 \r
1198         //clock close\r
1199         mac_clk = clk_get(NULL, "mac_ref_div");\r
1200         if (IS_ERR(mac_clk))\r
1201                 mac_clk = NULL;\r
1202         if (mac_clk) {\r
1203                 mac_parent = clk_get_parent(mac_clk);\r
1204                 if (IS_ERR(mac_parent))\r
1205                         mac_parent = NULL;\r
1206         }\r
1207         arm_clk = clk_get(NULL, "arm_pll");\r
1208         if (IS_ERR(arm_clk))\r
1209                 arm_clk = NULL;\r
1210 \r
1211         if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
1212                 wake_unlock(&idlelock);\r
1213         \r
1214         clk_disable(mac_clk);\r
1215         clk_disable(clk_get(NULL,"mii_rx"));\r
1216         clk_disable(clk_get(NULL,"mii_tx"));\r
1217         clk_disable(clk_get(NULL,"hclk_mac"));\r
1218         clk_disable(clk_get(NULL,"mac_ref"));\r
1219 \r
1220         return 0;\r
1221 }\r
1222 \r
1223 int vmac_shutdown(struct net_device *dev)\r
1224 {\r
1225         struct vmac_priv *ap = netdev_priv(dev);\r
1226         unsigned int temp;\r
1227         \r
1228         printk("enter func %s...\n", __func__);\r
1229 \r
1230         netif_stop_queue(dev);\r
1231         napi_disable(&ap->napi);\r
1232 \r
1233         /* stop running transfers */\r
1234         temp = vmac_readl(ap, CONTROL);\r
1235         temp &= ~(TXRN_MASK | RXRN_MASK);\r
1236         vmac_writel(ap, temp, CONTROL);\r
1237 \r
1238         del_timer_sync(&ap->rx_timeout);\r
1239 \r
1240         /* disable phy */\r
1241         phy_stop(ap->phy_dev);\r
1242         vmac_mii_exit(dev);\r
1243         netif_carrier_off(dev);\r
1244 \r
1245         /* disable interrupts */\r
1246         vmac_writel(ap, 0, ENABLE);\r
1247         free_irq(dev->irq, dev);\r
1248 \r
1249         /* turn off vmac */\r
1250         vmac_writel(ap, 0, CONTROL);\r
1251         /* vmac_reset_hw(vmac) */\r
1252 \r
1253         ap->shutdown = 1;\r
1254         wmb();\r
1255 \r
1256         free_buffers(dev);\r
1257 \r
1258         return 0;\r
1259 }\r
1260 \r
1261 void vmac_update_stats(struct vmac_priv *ap)\r
1262 {\r
1263         struct net_device_stats *_stats = &ap->stats;\r
1264         unsigned long miss, rxerr;\r
1265         unsigned long rxfram, rxcrc, rxoflow;\r
1266 \r
1267         /* compare with /proc/net/dev,\r
1268          * see net/core/dev.c:dev_seq_printf_stats */\r
1269 \r
1270         /* rx stats */\r
1271         rxerr = vmac_readl(ap, RXERR);\r
1272         miss = vmac_readl(ap, MISS);\r
1273 \r
1274         rxcrc = (rxerr & RXERR_CRC);\r
1275         rxfram = (rxerr & RXERR_FRM) >> 8;\r
1276         rxoflow = (rxerr & RXERR_OFLO) >> 16;\r
1277 \r
1278         _stats->rx_length_errors = 0;\r
1279         _stats->rx_over_errors += miss;\r
1280         _stats->rx_crc_errors += rxcrc;\r
1281         _stats->rx_frame_errors += rxfram;\r
1282         _stats->rx_fifo_errors += rxoflow;\r
1283         _stats->rx_missed_errors = 0;\r
1284 \r
1285         /* TODO check rx_dropped/rx_errors/tx_dropped/tx_errors have not\r
1286          * been updated elsewhere */\r
1287         _stats->rx_dropped = _stats->rx_over_errors +\r
1288                 _stats->rx_fifo_errors +\r
1289                 ap->rx_merge_error;\r
1290 \r
1291         _stats->rx_errors = _stats->rx_length_errors + _stats->rx_crc_errors +\r
1292                 _stats->rx_frame_errors +\r
1293                 _stats->rx_missed_errors +\r
1294                 _stats->rx_dropped;\r
1295 \r
1296         /* tx stats */\r
1297         _stats->tx_dropped = 0; /* otherwise queue stopped */\r
1298 \r
1299         _stats->tx_errors = _stats->tx_aborted_errors +\r
1300                 _stats->tx_carrier_errors +\r
1301                 _stats->tx_fifo_errors +\r
1302                 _stats->tx_heartbeat_errors +\r
1303                 _stats->tx_window_errors +\r
1304                 _stats->tx_dropped +\r
1305                 ap->tx_timeout_error;\r
1306 }\r
1307 \r
1308 struct net_device_stats *vmac_stats(struct net_device *dev)\r
1309 {\r
1310         struct vmac_priv *ap = netdev_priv(dev);\r
1311         unsigned long flags;\r
1312 \r
1313         spin_lock_irqsave(&ap->lock, flags);\r
1314         vmac_update_stats(ap);\r
1315         spin_unlock_irqrestore(&ap->lock, flags);\r
1316 \r
1317         return &ap->stats;\r
1318 }\r
1319 \r
1320 void vmac_tx_timeout(struct net_device *dev)\r
1321 {\r
1322         struct vmac_priv *ap = netdev_priv(dev);\r
1323         unsigned int status;\r
1324         unsigned long flags;\r
1325 \r
1326         spin_lock_irqsave(&ap->lock, flags);\r
1327 \r
1328         /* queue did not progress for timeo jiffies */\r
1329         WARN_ON(!netif_queue_stopped(dev));\r
1330         WARN_ON(!fifo_full(&ap->tx_ring));\r
1331 \r
1332         /* TX IRQ lost? */\r
1333         status = vmac_readl(ap, STAT);\r
1334         if (status & TXINT_MASK) {\r
1335                 dev_err(&ap->pdev->dev, "lost tx interrupt, IRQ mask %x\n",\r
1336                                 vmac_readl(ap, ENABLE));\r
1337                 vmac_writel(ap, TXINT_MASK, STAT);\r
1338         }\r
1339 \r
1340         /* TODO RX/MDIO/ERR as well? */\r
1341 \r
1342         vmac_tx_reclaim(dev, 0);\r
1343         if (fifo_full(&ap->tx_ring))\r
1344                 dev_err(&ap->pdev->dev, "DMA state machine not active\n");\r
1345 \r
1346         /* We can accept TX packets again */\r
1347         ap->tx_timeout_error++;\r
1348         dev->trans_start = jiffies;\r
1349         netif_wake_queue(dev);\r
1350 \r
1351         spin_unlock_irqrestore(&ap->lock, flags);\r
1352 }\r
1353 \r
1354 static void create_multicast_filter(struct net_device *dev,\r
1355         unsigned long *bitmask)\r
1356 {\r
1357 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))\r
1358         struct netdev_hw_addr *ha;\r
1359         unsigned long crc;\r
1360         char *addrs;\r
1361         struct netdev_hw_addr_list *list = &dev->dev_addrs;\r
1362         \r
1363         //printk("-----------------func %s-------------------\n", __func__);\r
1364 \r
1365         WARN_ON(dev->mc_count == 0);\r
1366         WARN_ON(dev->flags & IFF_ALLMULTI);\r
1367 \r
1368         bitmask[0] = bitmask[1] = 0;\r
1369 \r
1370         list_for_each_entry(ha, &list->list, list) {\r
1371                 addrs = ha->addr;\r
1372 \r
1373                 /* skip non-multicast addresses */\r
1374                 if (!(*addrs & 1))\r
1375                         continue;\r
1376 \r
1377                 crc = ether_crc_le(ETH_ALEN, addrs);\r
1378                 set_bit(crc >> 26, bitmask);\r
1379                 \r
1380         }\r
1381 #else\r
1382         struct netdev_hw_addr *ha;\r
1383         unsigned long crc;\r
1384         char *addrs;\r
1385 \r
1386         WARN_ON(netdev_mc_count(dev) == 0);\r
1387         WARN_ON(dev->flags & IFF_ALLMULTI);\r
1388 \r
1389         bitmask[0] = bitmask[1] = 0;\r
1390 \r
1391         netdev_for_each_mc_addr(ha, dev) {\r
1392                 addrs = ha->addr;\r
1393 \r
1394                 /* skip non-multicast addresses */\r
1395                 if (!(*addrs & 1))\r
1396                         continue;\r
1397 \r
1398                 crc = ether_crc_le(ETH_ALEN, addrs);\r
1399                 set_bit(crc >> 26, bitmask);\r
1400         }\r
1401 #endif\r
1402 }\r
1403 static void vmac_set_multicast_list(struct net_device *dev)\r
1404 {\r
1405 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))\r
1406         struct vmac_priv *ap = netdev_priv(dev);\r
1407         unsigned long flags, bitmask[2];\r
1408         int promisc, reg;\r
1409 \r
1410         //printk("-----------------func %s-------------------\n", __func__);\r
1411 \r
1412         spin_lock_irqsave(&ap->lock, flags);\r
1413 \r
1414         promisc = !!(dev->flags & IFF_PROMISC);\r
1415         reg = vmac_readl(ap, CONTROL);\r
1416         if (promisc != !!(reg & PROM_MASK)) {\r
1417                 reg ^= PROM_MASK;\r
1418                 vmac_writel(ap, reg, CONTROL);\r
1419         }\r
1420 \r
1421         if (dev->flags & IFF_ALLMULTI)\r
1422                 memset(bitmask, 1, sizeof(bitmask));\r
1423         else if (dev->mc_count == 0)\r
1424                 memset(bitmask, 0, sizeof(bitmask));\r
1425         else\r
1426                 create_multicast_filter(dev, bitmask);\r
1427 \r
1428         vmac_writel(ap, bitmask[0], LAFL);\r
1429         vmac_writel(ap, bitmask[1], LAFH);\r
1430 \r
1431         spin_unlock_irqrestore(&ap->lock, flags);\r
1432 #else\r
1433         struct vmac_priv *ap = netdev_priv(dev);\r
1434         unsigned long flags, bitmask[2];\r
1435         int promisc, reg;\r
1436 \r
1437         spin_lock_irqsave(&ap->lock, flags);\r
1438 \r
1439         promisc = !!(dev->flags & IFF_PROMISC);\r
1440         reg = vmac_readl(ap, CONTROL);\r
1441         if (promisc != !!(reg & PROM_MASK)) {\r
1442                 reg ^= PROM_MASK;\r
1443                 vmac_writel(ap, reg, CONTROL);\r
1444         }\r
1445 \r
1446         if (dev->flags & IFF_ALLMULTI)\r
1447                 memset(bitmask, 1, sizeof(bitmask));\r
1448         else if (netdev_mc_count(dev) == 0)\r
1449                 memset(bitmask, 0, sizeof(bitmask));\r
1450         else\r
1451                 create_multicast_filter(dev, bitmask);\r
1452 \r
1453         vmac_writel(ap, bitmask[0], LAFL);\r
1454         vmac_writel(ap, bitmask[1], LAFH);\r
1455 \r
1456         spin_unlock_irqrestore(&ap->lock, flags);\r
1457 #endif\r
1458 }\r
1459 \r
1460 static struct ethtool_ops vmac_ethtool_ops = {\r
1461         .get_settings           = vmacether_get_settings,\r
1462         .set_settings           = vmacether_set_settings,\r
1463         .get_drvinfo            = vmacether_get_drvinfo,\r
1464         .get_link               = ethtool_op_get_link,\r
1465 };\r
1466 \r
1467 static const struct net_device_ops vmac_netdev_ops = {\r
1468         .ndo_open               = vmac_open,\r
1469         .ndo_stop               = vmac_close,\r
1470         .ndo_get_stats          = vmac_stats,\r
1471         .ndo_start_xmit         = vmac_start_xmit,\r
1472         .ndo_do_ioctl           = vmac_ioctl,\r
1473         .ndo_set_mac_address    = eth_mac_addr,\r
1474         .ndo_tx_timeout         = vmac_tx_timeout,\r
1475         .ndo_set_multicast_list = vmac_set_multicast_list,\r
1476         .ndo_validate_addr      = eth_validate_addr,\r
1477         .ndo_change_mtu         = eth_change_mtu,\r
1478 };\r
1479 \r
1480 static int __devinit vmac_probe(struct platform_device *pdev)\r
1481 {\r
1482         struct net_device *dev;\r
1483         struct vmac_priv *ap;\r
1484         struct resource *res;\r
1485         unsigned int mem_base, mem_size, irq;\r
1486         int err;\r
1487         struct rk29_vmac_platform_data *pdata = pdev->dev.platform_data;\r
1488 \r
1489         dev = alloc_etherdev(sizeof(*ap));\r
1490         if (!dev) {\r
1491                 dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n");\r
1492                 return -ENOMEM;\r
1493         }\r
1494 \r
1495         ap = netdev_priv(dev);\r
1496 \r
1497         err = -ENODEV;\r
1498         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
1499         if (!res) {\r
1500                 dev_err(&pdev->dev, "no mmio resource defined\n");\r
1501                 goto err_out;\r
1502         }\r
1503         mem_base = res->start;\r
1504         mem_size = resource_size(res);\r
1505         irq = platform_get_irq(pdev, 0);\r
1506 \r
1507         err = -EBUSY;\r
1508         if (!request_mem_region(mem_base, mem_size, VMAC_NAME)) {\r
1509                 dev_err(&pdev->dev, "no memory region available\n");\r
1510                 goto err_out;\r
1511         }\r
1512 \r
1513         err = -ENOMEM;\r
1514         ap->regs = ioremap(mem_base, mem_size);\r
1515         if (!ap->regs) {\r
1516                 dev_err(&pdev->dev, "failed to map registers, aborting.\n");\r
1517                 goto err_out_release_mem;\r
1518         }\r
1519 \r
1520         /* no checksum support, hence no scatter/gather */\r
1521         dev->features |= NETIF_F_HIGHDMA;\r
1522 \r
1523         spin_lock_init(&ap->lock);\r
1524 \r
1525         SET_NETDEV_DEV(dev, &pdev->dev);\r
1526         ap->dev = dev;\r
1527         ap->pdev = pdev;\r
1528 \r
1529         /* init rx timeout (used for oom) */\r
1530         init_timer(&ap->rx_timeout);\r
1531         ap->rx_timeout.function = vmac_refill_rx_timer;\r
1532         ap->rx_timeout.data = (unsigned long)dev;\r
1533 \r
1534         netif_napi_add(dev, &ap->napi, vmac_poll, 2);\r
1535         dev->netdev_ops = &vmac_netdev_ops;\r
1536         dev->ethtool_ops = &vmac_ethtool_ops;\r
1537         dev->irq = irq;\r
1538 \r
1539         dev->flags |= IFF_MULTICAST;////////////////////\r
1540 \r
1541         dev->base_addr = (unsigned long)ap->regs;\r
1542         ap->mem_base = mem_base;\r
1543 \r
1544         /* prevent buffer chaining, favor speed over space */\r
1545         ap->rx_skb_size = ETH_FRAME_LEN + VMAC_BUFFER_PAD;\r
1546 \r
1547         /* private struct functional */\r
1548 \r
1549         /* mac address intialize, set vmac_open  */\r
1550         read_mac_reg(dev, dev->dev_addr);\r
1551 \r
1552         if (!is_valid_ether_addr(dev->dev_addr)) {\r
1553         //add by cx@rock-chips.com\r
1554         \r
1555         #ifdef CONFIG_ETH_MAC_FROM_EEPROM\r
1556                 ret = eeprom_read_data(0,dev->dev_addr,6);\r
1557                 if (ret != 6){\r
1558                         printk("read mac from Eeprom fail.\n");\r
1559                 }else {\r
1560                         if (is_valid_ether_addr(dev->dev_addr)){\r
1561                                 printk("eth_mac_from_eeprom***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
1562                                                         dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
1563                                                         dev->dev_addr[4],dev->dev_addr[5] );\r
1564                         }\r
1565                 }\r
1566         #endif\r
1567         \r
1568         #ifdef CONFIG_ETH_MAC_FROM_IDB\r
1569                 err = eth_mac_idb(dev->dev_addr);\r
1570                 if (err) {\r
1571                         printk("read mac from IDB fail.\n");\r
1572                 } else {\r
1573                         if (is_valid_ether_addr(dev->dev_addr)) {\r
1574                                 printk("eth_mac_from_idb***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
1575                                                         dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
1576                                                         dev->dev_addr[4],dev->dev_addr[5] );\r
1577                         }\r
1578                 }\r
1579         #endif\r
1580         \r
1581         /*#ifdef CONFIG_ETH_MAC_FROM_WIFI_MAC\r
1582                 err = eth_mac_wifi(dev->dev_addr);\r
1583                 if (err) {\r
1584                         printk("read mac from Wifi  fail.\n");\r
1585                 } else {\r
1586                         if (is_valid_ether_addr(dev->dev_addr)) {\r
1587                                 printk("eth_mac_from_wifi_mac***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
1588                                                         dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
1589                                                         dev->dev_addr[4],dev->dev_addr[5] );\r
1590                         }\r
1591                 }\r
1592         #endif*/\r
1593         \r
1594         #ifdef CONFIG_ETH_MAC_FROM_RANDOM\r
1595             random_ether_addr(dev->dev_addr);\r
1596         printk("random_ether_addr***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
1597                                   dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
1598                                   dev->dev_addr[4],dev->dev_addr[5] );  \r
1599         #endif\r
1600         //add end       \r
1601         }\r
1602 \r
1603         err = register_netdev(dev);\r
1604         if (err) {\r
1605                 dev_err(&pdev->dev, "Cannot register net device, aborting.\n");\r
1606                 goto err_out_iounmap;\r
1607         }\r
1608 \r
1609         dev_info(&pdev->dev, "ARC VMAC at 0x%08x irq %d %pM\n", mem_base,\r
1610             dev->irq, dev->dev_addr);\r
1611         platform_set_drvdata(pdev, dev);\r
1612 \r
1613         ap->suspending = 0;\r
1614         ap->open_flag = 0;\r
1615         wake_lock_init(&idlelock, WAKE_LOCK_IDLE, "vmac");\r
1616         wake_lock_init(&ap->resume_lock, WAKE_LOCK_SUSPEND, "vmac_resume");\r
1617 \r
1618         //config rk29 vmac as rmii, 100MHz \r
1619         if (pdata && pdata->vmac_register_set)\r
1620                 pdata->vmac_register_set();\r
1621 \r
1622         //power gpio init, phy power off default for power reduce\r
1623         if (pdata && pdata->rmii_io_init)\r
1624                 pdata->rmii_io_init();\r
1625 \r
1626         return 0;\r
1627 \r
1628 err_out_iounmap:\r
1629         iounmap(ap->regs);\r
1630 err_out_release_mem:\r
1631         release_mem_region(mem_base, mem_size);\r
1632 err_out:\r
1633         free_netdev(dev);\r
1634         return err;\r
1635 }\r
1636 \r
1637 static int __devexit vmac_remove(struct platform_device *pdev)\r
1638 {\r
1639         struct net_device *dev;\r
1640         struct vmac_priv *ap;\r
1641         struct resource *res;\r
1642         struct rk29_vmac_platform_data *pdata = pdev->dev.platform_data;\r
1643 \r
1644         wake_lock_destroy(&idlelock);\r
1645 \r
1646         //power gpio deinit, phy power off\r
1647         if (pdata && pdata->rmii_io_deinit)\r
1648                 pdata->rmii_io_deinit();\r
1649 \r
1650         dev = platform_get_drvdata(pdev);\r
1651         if (!dev) {\r
1652                 dev_err(&pdev->dev, "%s no valid dev found\n", __func__);\r
1653                 return 0;\r
1654         }\r
1655 \r
1656         ap = netdev_priv(dev);\r
1657 \r
1658         /* MAC */\r
1659         unregister_netdev(dev);\r
1660         iounmap(ap->regs);\r
1661 \r
1662         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
1663         release_mem_region(res->start, resource_size(res));\r
1664 \r
1665         platform_set_drvdata(pdev, NULL);\r
1666         free_netdev(dev);\r
1667         return 0;\r
1668 }\r
1669 \r
1670 static void rk29_vmac_power_off(struct net_device *dev)\r
1671 {\r
1672         struct vmac_priv *ap = netdev_priv(dev);\r
1673         struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
1674 \r
1675         printk("enter func %s...\n", __func__);\r
1676 \r
1677         //phy power off\r
1678         if (pdata && pdata->rmii_power_control)\r
1679                 pdata->rmii_power_control(0);\r
1680 \r
1681         //clock close\r
1682         clk_disable(clk_get(NULL, "mac_ref_div"));\r
1683         clk_disable(clk_get(NULL,"mii_rx"));\r
1684         clk_disable(clk_get(NULL,"mii_tx"));\r
1685         clk_disable(clk_get(NULL,"hclk_mac"));\r
1686         clk_disable(clk_get(NULL,"mac_ref"));\r
1687 \r
1688 }\r
1689 \r
1690 static int\r
1691 rk29_vmac_suspend(struct device *dev)\r
1692 {\r
1693         struct platform_device *pdev = to_platform_device(dev);\r
1694         struct net_device *ndev = platform_get_drvdata(pdev);\r
1695         struct vmac_priv *ap = netdev_priv(ndev);\r
1696         \r
1697         if (ndev) {\r
1698                 if (ap->open_flag == 1) {\r
1699                         netif_stop_queue(ndev);\r
1700                         netif_device_detach(ndev);\r
1701                         if (ap->suspending == 0) {\r
1702                                 vmac_shutdown(ndev);\r
1703                                 rk29_vmac_power_off(ndev);\r
1704                                 ap->suspending = 1;\r
1705                         }\r
1706                 }\r
1707         }\r
1708         return 0;\r
1709 }\r
1710 \r
1711 static int\r
1712 rk29_vmac_resume(struct device *dev)\r
1713 {\r
1714         struct platform_device *pdev = to_platform_device(dev);\r
1715         struct net_device *ndev = platform_get_drvdata(pdev);\r
1716         struct vmac_priv *ap = netdev_priv(ndev);\r
1717         \r
1718         if (ndev) {\r
1719                 if (ap->open_flag == 1) {\r
1720                         netif_device_attach(ndev);\r
1721                         netif_start_queue(ndev);\r
1722                 }\r
1723         }\r
1724         return 0;\r
1725 }\r
1726 \r
1727 static struct dev_pm_ops rk29_vmac_pm_ops = {\r
1728         .suspend        = rk29_vmac_suspend,\r
1729         .resume         = rk29_vmac_resume,\r
1730 };\r
1731 \r
1732 \r
1733 static struct platform_driver rk29_vmac_driver = {\r
1734         .probe          = vmac_probe,\r
1735         .remove         = __devexit_p(vmac_remove),\r
1736         .driver         = {\r
1737                 .name           = "rk29 vmac",\r
1738                 .owner   = THIS_MODULE,\r
1739                 .pm  = &rk29_vmac_pm_ops,\r
1740         },\r
1741 };\r
1742 \r
1743 static int __init vmac_init(void)\r
1744 {\r
1745         return platform_driver_register(&rk29_vmac_driver);\r
1746 }\r
1747 \r
1748 static void __exit vmac_exit(void)\r
1749 {\r
1750         platform_driver_unregister(&rk29_vmac_driver);\r
1751 }\r
1752 \r
1753 module_init(vmac_init);\r
1754 module_exit(vmac_exit);\r
1755 \r
1756 MODULE_LICENSE("GPL");\r
1757 MODULE_DESCRIPTION("RK29 VMAC Ethernet driver");\r
1758 MODULE_AUTHOR("amit.bhor@celunite.com, sameer.dhavale@celunite.com, andreas.fenkart@streamunlimited.com");\r