Root/target/linux/coldfire/patches/006-Add-FEC-driver-support-for-MCF5445x-MCF5441x-MCF547x.patch

1From 9be336132025e7670790cdc9c24a81c23e893484 Mon Sep 17 00:00:00 2001
2From: Alison Wang <b18965@freescale.com>
3Date: Thu, 4 Aug 2011 09:59:40 +0800
4Subject: [PATCH 06/52] Add FEC driver support for MCF5445x/MCF5441x/MCF547x/MCF548x
5
6Add FEC driver support for MCF5445x/MCF5441x/MCF547x/MCF548x.
7
8Signed-off-by: Alison Wang <b18965@freescale.com>
9---
10 arch/m68k/coldfire/m5441x/fec.c | 172 +++++
11 arch/m68k/coldfire/m5445x/fec.c | 143 ++++
12 drivers/net/Kconfig | 33 +-
13 drivers/net/Makefile | 1 +
14 drivers/net/fec.c | 27 +-
15 drivers/net/fec.h | 7 +-
16 drivers/net/fec_m547x.c | 1551 +++++++++++++++++++++++++++++++++++++++
17 drivers/net/fec_m547x.h | 241 ++++++
18 drivers/net/phy/Kconfig | 15 +
19 drivers/net/phy/Makefile | 3 +
20 drivers/net/phy/broadcom522x.c | 170 +++++
21 drivers/net/phy/national836x.c | 104 +++
22 drivers/net/phy/national8384x.c | 110 +++
23 13 files changed, 2566 insertions(+), 11 deletions(-)
24 create mode 100644 arch/m68k/coldfire/m5441x/fec.c
25 create mode 100644 arch/m68k/coldfire/m5445x/fec.c
26 create mode 100644 drivers/net/fec_m547x.c
27 create mode 100644 drivers/net/fec_m547x.h
28 create mode 100644 drivers/net/phy/broadcom522x.c
29 create mode 100644 drivers/net/phy/national836x.c
30 create mode 100644 drivers/net/phy/national8384x.c
31
32--- /dev/null
33+++ b/arch/m68k/coldfire/m5441x/fec.c
34@@ -0,0 +1,172 @@
35+/*
36+ * fec.c on m5441x platform
37+ *
38+ * Sub-architcture dependant initialization code for the Freescale
39+ * 5441X FEC module.
40+ *
41+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
42+ * ShrekWu B16972@freescale.com
43+ * Alison Wang b18965@freescale.com
44+ *
45+ *
46+ * This program is free software; you can redistribute it and/or modify it
47+ * under the terms of the GNU General Public License as published by the
48+ * Free Software Foundation; either version 2 of the License, or (at your
49+ * option) any later version.
50+ *
51+ * This program is distributed in the hope that it will be useful,
52+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
53+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54+ * GNU General Public License for more details.
55+ *
56+ * You should have received a copy of the GNU General Public License
57+ * along with this program; if not, write to the Free Software
58+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
59+ */
60+#include <linux/kernel.h>
61+#include <linux/sched.h>
62+#include <linux/param.h>
63+#include <linux/init.h>
64+#include <linux/interrupt.h>
65+#include <linux/device.h>
66+#include <linux/netdevice.h>
67+#include <linux/etherdevice.h>
68+#include <linux/skbuff.h>
69+#include <linux/spinlock.h>
70+#include <linux/workqueue.h>
71+#include <linux/platform_device.h>
72+#include <linux/fec.h>
73+#include <linux/io.h>
74+
75+#include <asm/pgtable.h>
76+#include <asm/traps.h>
77+#include <asm/machdep.h>
78+#include <asm/coldfire.h>
79+#include <asm/mcfsim.h>
80+#include <asm/mcf5441x_dtim.h>
81+
82+static struct resource fec0_resources[] = {
83+ [0] = {
84+ .start = MCF_MBAR + 0xfc0d4000,
85+ .end = MCF_MBAR + 0xfc0d42ff,
86+ .flags = IORESOURCE_MEM,
87+ },
88+ [1] = {
89+ .start = (64 + 36),
90+ .end = (64 + 36),
91+ .flags = IORESOURCE_IRQ,
92+ },
93+ [2] = {
94+ .start = (64 + 40),
95+ .end = (64 + 40),
96+ .flags = IORESOURCE_IRQ,
97+ },
98+ [3] = {
99+ .start = (64 + 42),
100+ .end = (64 + 42),
101+ .flags = IORESOURCE_IRQ,
102+ },
103+};
104+
105+#if defined(CONFIG_FEC2)
106+static struct resource fec1_resources[] = {
107+ [0] = {
108+ .start = MCF_MBAR + 0xfc0d8000,
109+ .end = MCF_MBAR + 0xfc0d82ff,
110+ .flags = IORESOURCE_MEM,
111+ },
112+ [1] = {
113+ .start = (64 + 13 + 36),
114+ .end = (64 + 13 + 36),
115+ .flags = IORESOURCE_IRQ,
116+ },
117+ [2] = {
118+ .start = (64 + 13 + 40),
119+ .end = (64 + 13 + 40),
120+ .flags = IORESOURCE_IRQ,
121+ },
122+ [3] = {
123+ .start = (64 + 13 + 42),
124+ .end = (64 + 13 + 42),
125+ .flags = IORESOURCE_IRQ,
126+ },
127+};
128+#endif
129+
130+static struct fec_platform_data m54418_fec_pdata = {
131+ .phy = PHY_INTERFACE_MODE_RMII,
132+};
133+
134+static struct platform_device fec0_coldfire_device = {
135+ .name = "m54418-fec",
136+ .id = 0,
137+ .resource = fec0_resources,
138+ .num_resources = ARRAY_SIZE(fec0_resources),
139+ .dev = {
140+ .platform_data = &m54418_fec_pdata,
141+ }
142+};
143+
144+#if defined(CONFIG_FEC2)
145+static struct platform_device fec1_coldfire_device = {
146+ .name = "m54418-fec",
147+ .id = 1,
148+ .resource = fec1_resources,
149+ .num_resources = ARRAY_SIZE(fec1_resources),
150+ .dev = {
151+ .platform_data = &m54418_fec_pdata,
152+ }
153+};
154+#endif
155+
156+static struct platform_device *fec_device[] = {
157+ &fec0_coldfire_device,
158+#if defined(CONFIG_FEC2)
159+ &fec1_coldfire_device,
160+#endif
161+};
162+
163+static int __init mcf5441x_fec_dev_init(void)
164+{
165+ int retval = 0;
166+
167+ MCF_GPIO_PAR_FEC =
168+ (MCF_GPIO_PAR_FEC &
169+ MCF_GPIO_PAR_FEC_FEC_MASK) |
170+ MCF_GPIO_PAR_FEC_FEC_RMII0FUL_ULPI;
171+
172+ MCF_GPIO_SRCR_FEC = 0x0C;
173+
174+#if defined(CONFIG_FEC2)
175+ MCF_GPIO_PAR_FEC =
176+ (MCF_GPIO_PAR_FEC &
177+ MCF_GPIO_PAR_FEC_FEC_MASK) |
178+ MCF_GPIO_PAR_FEC_FEC_RMII0FUL_1FUL;
179+
180+ MCF_GPIO_SRCR_FEC |= 0x03;
181+
182+ MCF_GPIO_PAR_SIMP0H =
183+ (MCF_GPIO_PAR_SIMP0H &
184+ MCF_GPIO_PAR_SIMP0H_DAT_MASK) |
185+ MCF_GPIO_PAR_SIMP0H_DAT_GPIO;
186+
187+ MCF_GPIO_PDDR_G =
188+ (MCF_GPIO_PDDR_G &
189+ MCF_GPIO_PDDR_G4_MASK) |
190+ MCF_GPIO_PDDR_G4_OUTPUT;
191+
192+ MCF_GPIO_PODR_G =
193+ (MCF_GPIO_PODR_G &
194+ MCF_GPIO_PODR_G4_MASK);
195+#endif
196+
197+ retval = platform_add_devices(fec_device, ARRAY_SIZE(fec_device));
198+ if (retval < 0) {
199+ printk(KERN_ERR "MCF5441x FEC: platform_device_register failed"
200+ "with code=%d\n", retval);
201+ }
202+
203+ return retval;
204+}
205+
206+arch_initcall(mcf5441x_fec_dev_init);
207--- /dev/null
208+++ b/arch/m68k/coldfire/m5445x/fec.c
209@@ -0,0 +1,143 @@
210+/*
211+ * fec-mcf5445x.c
212+ *
213+ * Sub-architcture dependant initialization code for the Freescale
214+ * 5445X FEC module.
215+ *
216+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
217+ * Shrek Wu B16972@freescale.com
218+ *
219+ * This program is free software; you can redistribute it and/or modify it
220+ * under the terms of the GNU General Public License as published by the
221+ * Free Software Foundation; either version 2 of the License, or (at your
222+ * option) any later version.
223+ *
224+ * This program is distributed in the hope that it will be useful,
225+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
226+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
227+ * GNU General Public License for more details.
228+ *
229+ * You should have received a copy of the GNU General Public License
230+ * along with this program; if not, write to the Free Software
231+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
232+ */
233+#include <linux/kernel.h>
234+#include <linux/sched.h>
235+#include <linux/param.h>
236+#include <linux/init.h>
237+#include <linux/interrupt.h>
238+#include <linux/device.h>
239+#include <linux/platform_device.h>
240+#include <linux/fsl_devices.h>
241+#include <linux/netdevice.h>
242+#include <linux/etherdevice.h>
243+#include <linux/skbuff.h>
244+#include <linux/spinlock.h>
245+#include <linux/workqueue.h>
246+#include <asm/pgtable.h>
247+
248+#include <asm/traps.h>
249+#include <asm/machdep.h>
250+#include <asm/coldfire.h>
251+#include <asm/mcfsim.h>
252+
253+static struct resource fec0_resources[] = {
254+ [0] = {
255+ .start = MCF_MBAR + 0xfc030000,
256+ .end = MCF_MBAR + 0xfc0302ff,
257+ .flags = IORESOURCE_MEM,
258+ },
259+ [1] = {
260+ .start = (64 + 36),
261+ .end = (64 + 36),
262+ .flags = IORESOURCE_IRQ,
263+ },
264+ [2] = {
265+ .start = (64 + 40),
266+ .end = (64 + 40),
267+ .flags = IORESOURCE_IRQ,
268+ },
269+ [3] = {
270+ .start = (64 + 42),
271+ .end = (64 + 42),
272+ .flags = IORESOURCE_IRQ,
273+ },
274+};
275+
276+#if defined(CONFIG_FEC2)
277+static struct resource fec1_resources[] = {
278+ [0] = {
279+ .start = MCF_MBAR + 0xfc034000,
280+ .end = MCF_MBAR + 0xfc0342ff,
281+ .flags = IORESOURCE_MEM,
282+ },
283+ [1] = {
284+ .start = (64 + 13 + 36),
285+ .end = (64 + 13 + 36),
286+ .flags = IORESOURCE_IRQ,
287+ },
288+ [2] = {
289+ .start = (64 + 13 + 40),
290+ .end = (64 + 13 + 40),
291+ .flags = IORESOURCE_IRQ,
292+ },
293+ [3] = {
294+ .start = (64 + 13 + 42),
295+ .end = (64 + 13 + 42),
296+ .flags = IORESOURCE_IRQ,
297+ },
298+};
299+#endif
300+
301+static struct platform_device fec0_coldfire_device = {
302+ .name = "fec",
303+ .id = 0,
304+ .resource = fec0_resources,
305+ .num_resources = ARRAY_SIZE(fec0_resources),
306+};
307+
308+#if defined(CONFIG_FEC2)
309+static struct platform_device fec1_coldfire_device = {
310+ .name = "fec",
311+ .id = 1,
312+ .resource = fec1_resources,
313+ .num_resources = ARRAY_SIZE(fec1_resources),
314+};
315+#endif
316+
317+static struct platform_device *fec_device[] = {
318+ &fec0_coldfire_device,
319+#if defined(CONFIG_FEC2)
320+ &fec1_coldfire_device,
321+#endif
322+};
323+
324+static int __init mcf5445x_fec_dev_init(void)
325+{
326+ int retval = 0;
327+
328+ MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
329+ MCF_GPIO_PAR_FEC_FEC0_MASK) |
330+ MCF_GPIO_PAR_FEC_FEC0_RMII_GPIO;
331+
332+ MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
333+ MCF_GPIO_PAR_FEC_FEC1_MASK) |
334+ MCF_GPIO_PAR_FEC_FEC1_RMII_GPIO;
335+
336+ MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_MDIO0_MDIO0 |
337+ MCF_GPIO_PAR_FECI2C_MDC0_MDC0);
338+
339+ MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_MDIO1_MDIO1 |
340+ MCF_GPIO_PAR_FECI2C_MDC1_MDC1);
341+
342+ retval = platform_add_devices(fec_device, ARRAY_SIZE(fec_device));
343+ if (retval < 0) {
344+ printk(KERN_ERR "MCF5445x FEC: platform_device_register failed"
345+ "with code=%d\n",
346+ retval);
347+ }
348+
349+ return retval;
350+}
351+
352+arch_initcall(mcf5445x_fec_dev_init);
353--- a/drivers/net/Kconfig
354+++ b/drivers/net/Kconfig
355@@ -1943,13 +1943,44 @@ config 68360_ENET
356 
357 config FEC
358     bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
359- depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
360+ depends on M523x || M527x || M5272 || M528x || M520x || M532x || M5445X || M5441X || \
361         MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 || SOC_IMX28
362     select PHYLIB
363     help
364       Say Y here if you want to use the built-in 10/100 Fast ethernet
365       controller on some Motorola ColdFire and Freescale i.MX processors.
366 
367+
368+config FEC2
369+ bool "Second FEC ethernet controller (on some ColdFire CPUs)"
370+ depends on FEC && (M54455 || M5441X)
371+ help
372+ Say Y here if you want to use the second built-in 10/100 Fast
373+ ethernet controller on some Motorola ColdFire processors.
374+
375+config FEC_548x
376+ tristate "MCF547x/MCF548x Fast Ethernet Controller support"
377+ depends on M547X_8X
378+ help
379+ The MCF547x and MCF548x have a built-in Fast Ethernet Controller.
380+ Saying Y here will include support for this device in the kernel.
381+
382+ To compile this driver as a module, choose M here: the module
383+ will be called fecm.
384+
385+config FEC_548x_ENABLE_FEC2
386+ bool "Enable the second FEC"
387+ depends on FEC_548x
388+ help
389+ This enables the second FEC on the 547x/548x. If you want to use
390+ it, say Y.
391+
392+config FEC_548x_SHARED_PHY
393+ bool "Shared PHY interface(on some ColdFire designs)"
394+ depends on FEC_548x_ENABLE_FEC2
395+ help
396+ Say Y here if both PHYs are controlled via a single channel.
397+
398 config FEC_MPC52xx
399     tristate "MPC52xx FEC driver"
400     depends on PPC_MPC52xx && PPC_BESTCOMM
401--- a/drivers/net/Makefile
402+++ b/drivers/net/Makefile
403@@ -123,6 +123,7 @@ obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
404 obj-$(CONFIG_HP100) += hp100.o
405 obj-$(CONFIG_SMC9194) += smc9194.o
406 obj-$(CONFIG_FEC) += fec.o
407+obj-$(CONFIG_FEC_548x) += fec_m547x.o
408 obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
409 ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
410     obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
411--- a/drivers/net/fec.c
412+++ b/drivers/net/fec.c
413@@ -18,7 +18,7 @@
414  * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
415  * Copyright (c) 2004-2006 Macq Electronique SA.
416  *
417- * Copyright (C) 2010 Freescale Semiconductor, Inc.
418+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
419  */
420 
421 #include <linux/module.h>
422@@ -74,6 +74,9 @@ static struct platform_device_id fec_dev
423     }, {
424         .name = "imx28-fec",
425         .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
426+ }, {
427+ .name = "m54418-fec",
428+ .driver_data = FEC_QUIRK_ENET_MAC,
429     },
430     { }
431 };
432@@ -148,8 +151,9 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet
433  * account when setting it.
434  */
435 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
436- defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
437- defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
438+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
439+ defined(CONFIG_M5445X) || defined(CONFIG_M5441X) || \
440+ defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
441 #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
442 #else
443 #define OPT_FRAME_SIZE 0
444@@ -400,7 +404,8 @@ fec_enet_tx(struct net_device *dev)
445         if (bdp == fep->cur_tx && fep->tx_full == 0)
446             break;
447 
448- dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
449+/* dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, \
450+ FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);*/
451         bdp->cbd_bufaddr = 0;
452 
453         skb = fep->tx_skbuff[fep->skb_dirty];
454@@ -527,8 +532,8 @@ fec_enet_rx(struct net_device *dev)
455         dev->stats.rx_bytes += pkt_len;
456         data = (__u8*)__va(bdp->cbd_bufaddr);
457 
458- dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
459- DMA_FROM_DEVICE);
460+/* dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
461+ DMA_FROM_DEVICE);*/
462 
463         if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
464             swap_buffer(data, pkt_len);
465@@ -552,8 +557,8 @@ fec_enet_rx(struct net_device *dev)
466             netif_rx(skb);
467         }
468 
469- bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen,
470- DMA_FROM_DEVICE);
471+/* bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen,
472+ DMA_FROM_DEVICE);*/
473 rx_processing_done:
474         /* Clear the status flags for this buffer */
475         status &= ~BD_ENET_RX_STATS;
476@@ -632,6 +637,8 @@ static void __inline__ fec_get_mac(struc
477 static void fec_enet_adjust_link(struct net_device *dev)
478 {
479     struct fec_enet_private *fep = netdev_priv(dev);
480+ const struct platform_device_id *id_entry =
481+ platform_get_device_id(fep->pdev);
482     struct phy_device *phy_dev = fep->phy_dev;
483     unsigned long flags;
484 
485@@ -660,6 +667,10 @@ static void fec_enet_adjust_link(struct
486             fec_restart(dev, phy_dev->duplex);
487         else
488             fec_stop(dev);
489+
490+ if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
491+ writel(2, fep->hwp + FEC_ECNTRL);
492+
493         status_change = 1;
494     }
495 
496--- a/drivers/net/fec.h
497+++ b/drivers/net/fec.h
498@@ -4,6 +4,7 @@
499  * fec.h -- Fast Ethernet Controller for Motorola ColdFire SoC
500  * processors.
501  *
502+ * Copyright (C) 2011 Freescale Semiconductor,Inc. All Rights Reserved.
503  * (C) Copyright 2000-2005, Greg Ungerer (gerg@snapgear.com)
504  * (C) Copyright 2000-2001, Lineo (www.lineo.com)
505  */
506@@ -14,8 +15,10 @@
507 /****************************************************************************/
508 
509 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
510- defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
511- defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
512+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
513+ defined(CONFIG_M537x) || defined(CONFIG_M5301x) || \
514+ defined(CONFIG_M5445X) || defined(CONFIG_M5441X) || \
515+ defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
516 /*
517  * Just figures, Motorola would have to change the offsets for
518  * registers in the same peripheral device on different models
519--- /dev/null
520+++ b/drivers/net/fec_m547x.c
521@@ -0,0 +1,1551 @@
522+/*
523+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
524+ * Author: Kurt Mahan, kmahan@freescale.com
525+ *
526+ * This program is free software; you can redistribute it and/or modify
527+ * it under the terms of the GNU General Public License as published by
528+ * the Free Software Foundation; either version 2 of the License, or
529+ * (at your option) any later version.
530+ */
531+#include <linux/module.h>
532+#include <linux/kernel.h>
533+#include <linux/string.h>
534+#include <linux/ptrace.h>
535+#include <linux/errno.h>
536+#include <linux/ioport.h>
537+#include <linux/slab.h>
538+#include <linux/interrupt.h>
539+#include <linux/pci.h>
540+#include <linux/init.h>
541+#include <linux/phy.h>
542+#include <linux/delay.h>
543+#include <linux/netdevice.h>
544+#include <linux/etherdevice.h>
545+#include <linux/skbuff.h>
546+#include <linux/spinlock.h>
547+#include <linux/workqueue.h>
548+#include <linux/bitops.h>
549+
550+#include <asm/coldfire.h>
551+#include <asm/mcfsim.h>
552+
553+#include <asm/dma.h>
554+#include <asm/MCD_dma.h>
555+#include <asm/m5485sram.h>
556+#include <asm/virtconvert.h>
557+#include <asm/irq.h>
558+
559+#include "fec_m547x.h"
560+
561+#ifdef CONFIG_FEC_548x_ENABLE_FEC2
562+#define FEC_MAX_PORTS 2
563+#define FEC_2
564+#else
565+#define FEC_MAX_PORTS 1
566+#undef FEC_2
567+#endif
568+
569+#define VERSION "0.20"
570+MODULE_DESCRIPTION("DMA Fast Ethernet Controller driver ver " VERSION);
571+
572+/* fec private */
573+struct fec_priv {
574+ struct net_device *netdev; /* owning net device */
575+ void *fecpriv_txbuf[FEC_TX_BUF_NUMBER]; /* tx buffer ptrs */
576+ MCD_bufDescFec *fecpriv_txdesc; /* tx descriptor ptrs */
577+ volatile unsigned int fecpriv_current_tx; /* current tx desc index */
578+ volatile unsigned int fecpriv_next_tx; /* next tx desc index */
579+ unsigned int fecpriv_current_rx; /* current rx desc index */
580+ MCD_bufDescFec *fecpriv_rxdesc; /* rx descriptor ptrs */
581+ struct sk_buff *askb_rx[FEC_RX_BUF_NUMBER]; /* rx SKB ptrs */
582+ unsigned int fecpriv_initiator_rx; /* rx dma initiator */
583+ unsigned int fecpriv_initiator_tx; /* tx dma initiator */
584+ int fecpriv_fec_rx_channel; /* rx dma channel */
585+ int fecpriv_fec_tx_channel; /* tx dma channel */
586+ int fecpriv_rx_requestor; /* rx dma requestor */
587+ int fecpriv_tx_requestor; /* tx dma requestor */
588+ void *fecpriv_interrupt_fec_rx_handler; /* dma rx handler */
589+ void *fecpriv_interrupt_fec_tx_handler; /* dma tx handler */
590+ unsigned char *fecpriv_mac_addr; /* private fec mac addr */
591+ struct net_device_stats fecpriv_stat; /* stats ptr */
592+ spinlock_t fecpriv_lock;
593+ int fecpriv_rxflag;
594+ struct tasklet_struct fecpriv_tasklet_reinit;
595+ int index; /* fec hw number */
596+ struct phy_device *phydev;
597+ struct mii_bus *mdio_bus;
598+ int duplex;
599+ int link;
600+ int speed;
601+};
602+
603+struct net_device *fec_dev[FEC_MAX_PORTS];
604+
605+/* FEC functions */
606+static int __init fec_init(void);
607+/*
608+static struct net_device_stats *fec_get_stat(struct net_device *dev);
609+static int fec_open(struct net_device *dev);
610+static int fec_close(struct net_device *nd);
611+static int fec_tx(struct sk_buff *skb, struct net_device *dev);
612+static void fec_set_multicast_list(struct net_device *nd);
613+static int fec_set_mac_address(struct net_device *dev, void *p);
614+static void fec_tx_timeout(struct net_device *dev);
615+*/
616+static void fec_interrupt_fec_tx_handler(struct net_device *dev);
617+static void fec_interrupt_fec_rx_handler(struct net_device *dev);
618+static irqreturn_t fec_interrupt_handler(int irq, void *dev_id);
619+static void fec_interrupt_fec_tx_handler_fec0(void);
620+static void fec_interrupt_fec_rx_handler_fec0(void);
621+static void fec_interrupt_fec_reinit(unsigned long data);
622+
623+/* default fec0 address */
624+unsigned char fec_mac_addr_fec0[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x50 };
625+
626+#ifdef FEC_2
627+/* default fec1 address */
628+unsigned char fec_mac_addr_fec1[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x51 };
629+#endif
630+
631+extern unsigned char uboot_enet0[];
632+extern unsigned char uboot_enet1[];
633+
634+#ifndef MODULE
635+int fec_str_to_mac(char *str_mac, unsigned char* addr);
636+int __init fec_mac_setup0(char *s);
637+#endif
638+
639+
640+#ifdef FEC_2
641+void fec_interrupt_fec_tx_handler_fec1(void);
642+void fec_interrupt_fec_rx_handler_fec1(void);
643+#endif
644+
645+#ifndef MODULE
646+int __init fec_mac_setup1(char *s);
647+#endif
648+
649+module_init(fec_init);
650+/* module_exit(fec_cleanup); */
651+
652+__setup("mac0=", fec_mac_setup0);
653+
654+#ifdef FEC_2
655+__setup("mac1=", fec_mac_setup1);
656+#endif
657+
658+#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
659+#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \
660+ (VAL & 0xffff))
661+/* ----------------------------------------------------------- */
662+static int coldfire_fec_mdio_read(struct mii_bus *bus,
663+ int phy_id, int reg)
664+{
665+ int ret;
666+#ifdef CONFIG_FEC_548x_SHARED_PHY
667+ unsigned long base_addr = (unsigned long)FEC_BASE_ADDR_FEC0;
668+#else
669+ unsigned long base_addr = (unsigned long) dev->base_addr;
670+#endif
671+ int tries = 100;
672+
673+ /* Clear the MII interrupt bit */
674+ FEC_EIR(base_addr) = FEC_EIR_MII;
675+
676+ /* Write to the MII management frame register */
677+ FEC_MMFR(base_addr) = mk_mii_read(reg) | (phy_id << 23);
678+
679+ /* Wait for the reading */
680+ while (!(FEC_EIR(base_addr) & FEC_EIR_MII)) {
681+ udelay(10);
682+
683+ if (!tries) {
684+ printk(KERN_ERR "%s timeout\n", __func__);
685+ return -ETIMEDOUT;
686+ }
687+ tries--;
688+ }
689+
690+ /* Clear the MII interrupt bit */
691+ FEC_EIR(base_addr) = FEC_EIR_MII;
692+ ret = FEC_MMFR(base_addr) & 0x0000FFFF;
693+ return ret;
694+}
695+
696+static int coldfire_fec_mdio_write(struct mii_bus *bus,
697+ int phy_id, int reg, u16 data)
698+{
699+ int ret;
700+#ifdef CONFIG_FEC_548x_SHARED_PHY
701+ unsigned long base_addr = (unsigned long)FEC_BASE_ADDR_FEC0;
702+#else
703+ unsigned long base_addr = (unsigned long) dev->base_addr;
704+#endif
705+ int tries = 100;
706+
707+ printk(KERN_ERR "%s base_addr %lx, phy_id %x, reg %x, data %x\n",
708+ __func__, base_addr, phy_id, reg, data);
709+ /* Clear the MII interrupt bit */
710+ FEC_EIR(base_addr) = FEC_EIR_MII;
711+
712+ /* Write to the MII management frame register */
713+ FEC_MMFR(base_addr) = mk_mii_write(reg, data) | (phy_id << 23);
714+
715+ /* Wait for the writing */
716+ while (!(FEC_EIR(base_addr) & FEC_EIR_MII)) {
717+ udelay(10);
718+ if (!tries) {
719+ printk(KERN_ERR "%s timeout\n", __func__);
720+ return -ETIMEDOUT;
721+ }
722+ tries--;
723+ }
724+ /* Clear the MII interrupt bit */
725+ FEC_EIR(base_addr) = FEC_EIR_MII;
726+ ret = FEC_MMFR(base_addr) & 0x0000FFFF;
727+
728+ return ret;
729+}
730+
731+static void fec_adjust_link(struct net_device *dev)
732+{
733+ struct fec_priv *priv = netdev_priv(dev);
734+ struct phy_device *phydev = priv->phydev;
735+ int new_state = 0;
736+
737+ if (phydev->link != PHY_DOWN) {
738+ if (phydev->duplex != priv->duplex) {
739+ new_state = 1;
740+ priv->duplex = phydev->duplex;
741+ }
742+
743+ if (phydev->speed != priv->speed) {
744+ new_state = 1;
745+ priv->speed = phydev->speed;
746+ }
747+
748+ if (priv->link == PHY_DOWN) {
749+ new_state = 1;
750+ priv->link = phydev->link;
751+ }
752+ } else if (priv->link) {
753+ new_state = 1;
754+ priv->link = PHY_DOWN;
755+ priv->speed = 0;
756+ priv->duplex = -1;
757+ }
758+
759+ if (new_state)
760+ phy_print_status(phydev);
761+}
762+
763+static int coldfire_fec_init_phy(struct net_device *dev)
764+{
765+ struct fec_priv *priv = netdev_priv(dev);
766+ struct phy_device *phydev = NULL;
767+ int i;
768+ int startnode;
769+
770+#ifdef CONFIG_FEC_548x_SHARED_PHY
771+ if (priv->index == 0)
772+ startnode = 0;
773+ else if (priv->index == 1) {
774+ struct fec_priv *priv0 = netdev_priv(fec_dev[0]);
775+ startnode = priv0->phydev->addr + 1;
776+ } else
777+ startnode = 0;
778+#else
779+ startnode = 0;
780+#endif
781+#ifdef FEC_DEBUG
782+ printk(KERN_ERR "%s priv->index %x, startnode %x\n",
783+ __func__, priv->index, startnode);
784+#endif
785+ /* search for connect PHY device */
786+ for (i = startnode; i < PHY_MAX_ADDR; i++) {
787+ struct phy_device *const tmp_phydev =
788+ priv->mdio_bus->phy_map[i];
789+
790+ if (!tmp_phydev) {
791+#ifdef FEC_DEBUG
792+ printk(KERN_INFO "%s no PHY here at"
793+ "mii_bus->phy_map[%d]\n",
794+ __func__, i);
795+#endif
796+ continue; /* no PHY here... */
797+ }
798+ phydev = tmp_phydev;
799+#ifdef FEC_DEBUG
800+ printk(KERN_INFO "%s find PHY here at"
801+ "mii_bus->phy_map[%d]\n",
802+ __func__, i);
803+#endif
804+ break; /* found it */
805+ }
806+
807+ /* now we are supposed to have a proper phydev, to attach to... */
808+ if (!phydev) {
809+ printk(KERN_INFO "%s: Don't found any phy device at all\n",
810+ dev->name);
811+ return -ENODEV;
812+ }
813+
814+ priv->link = 0;
815+ priv->speed = 0;
816+ priv->duplex = 0;
817+#ifdef FEC_DEBUG
818+ printk(KERN_INFO "%s phydev_busid %s\n", __func__, phydev->dev.bus_id);
819+#endif
820+ phydev = phy_connect(dev, dev_name(&phydev->dev),
821+ &fec_adjust_link, 0, PHY_INTERFACE_MODE_MII);
822+ if (IS_ERR(phydev)) {
823+ printk(KERN_ERR " %s phy_connect failed\n", __func__);
824+ return PTR_ERR(phydev);
825+ }
826+
827+ printk(KERN_INFO "attached phy %i to driver %s\n",
828+ phydev->addr, phydev->drv->name);
829+ priv->phydev = phydev;
830+ return 0;
831+}
832+
833+static int fec_mdio_register(struct net_device *dev,
834+ int slot)
835+{
836+ int err = 0;
837+ struct fec_priv *fp = netdev_priv(dev);
838+
839+ fp->mdio_bus = mdiobus_alloc();
840+ if (!fp->mdio_bus) {
841+ printk(KERN_ERR "ethernet mdiobus_alloc fail\n");
842+ return -ENOMEM;
843+ }
844+
845+ if (slot == 0) {
846+ fp->mdio_bus->name = "Coldfire FEC MII 0 Bus";
847+ strcpy(fp->mdio_bus->id, "0");
848+ } else if (slot == 1) {
849+ fp->mdio_bus->name = "Coldfire FEC MII 1 Bus";
850+ strcpy(fp->mdio_bus->id, "1");
851+ } else {
852+ printk(KERN_ERR "Now coldfire can not"
853+ "support more than 2 mii bus\n");
854+ }
855+
856+ fp->mdio_bus->read = &coldfire_fec_mdio_read;
857+ fp->mdio_bus->write = &coldfire_fec_mdio_write;
858+ fp->mdio_bus->priv = dev;
859+ err = mdiobus_register(fp->mdio_bus);
860+ if (err) {
861+ mdiobus_free(fp->mdio_bus);
862+ printk(KERN_ERR "%s: ethernet mdiobus_register fail %d\n",
863+ dev->name, err);
864+ return -EIO;
865+ }
866+
867+ printk(KERN_INFO "mdiobus_register %s ok\n",
868+ fp->mdio_bus->name);
869+ return err;
870+}
871+
872+/************************************************************************
873+* NAME: mcf547x_fec_open
874+*
875+* DESCRIPTION: This function performs the initialization of
876+* of FEC and corresponding KS8721 transiver
877+*
878+* RETURNS: If no error occurs, this function returns zero.
879+*************************************************************************/
880+static int mcf547x_fec_open(struct net_device *dev)
881+{
882+ struct fec_priv *fp = netdev_priv(dev);
883+ unsigned long base_addr = (unsigned long) dev->base_addr;
884+ int fduplex;
885+ int i;
886+ int channel;
887+ int error_code = -EBUSY;
888+
889+ fp->link = 0;
890+ fp->duplex = 0;
891+ fp->speed = 0;
892+ coldfire_fec_init_phy(dev);
893+ phy_start(fp->phydev);
894+
895+ /* Receive the DMA channels */
896+ channel = dma_set_channel_fec(fp->fecpriv_rx_requestor);
897+
898+ if (channel == -1) {
899+ printk(KERN_ERR "Dma channel cannot be reserved\n");
900+ goto ERRORS;
901+ }
902+
903+ fp->fecpriv_fec_rx_channel = channel;
904+
905+ dma_connect(channel, (int) fp->fecpriv_interrupt_fec_rx_handler);
906+
907+ channel = dma_set_channel_fec(fp->fecpriv_tx_requestor);
908+
909+ if (channel == -1) {
910+ printk(KERN_ERR "Dma channel cannot be reserved\n");
911+ goto ERRORS;
912+ }
913+
914+ fp->fecpriv_fec_tx_channel = channel;
915+
916+ dma_connect(channel, (int) fp->fecpriv_interrupt_fec_tx_handler);
917+
918+ /* init tasklet for controller reinitialization */
919+ tasklet_init(&fp->fecpriv_tasklet_reinit,
920+ fec_interrupt_fec_reinit, (unsigned long) dev);
921+
922+ /* Reset FIFOs */
923+ FEC_FECFRST(base_addr) |= FEC_SW_RST | FEC_RST_CTL;
924+ FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
925+
926+ /* Reset and disable FEC */
927+ FEC_ECR(base_addr) = FEC_ECR_RESET;
928+
929+ udelay(10);
930+
931+ /* Clear all events */
932+ FEC_EIR(base_addr) = FEC_EIR_CLEAR;
933+
934+ /* Reset FIFO status */
935+ FEC_FECTFSR(base_addr) = FEC_FECTFSR_MSK;
936+ FEC_FECRFSR(base_addr) = FEC_FECRFSR_MSK;
937+
938+ /* Set the default address */
939+ FEC_PALR(base_addr) = (fp->fecpriv_mac_addr[0] << 24) |
940+ (fp->fecpriv_mac_addr[1] << 16) |
941+ (fp->fecpriv_mac_addr[2] << 8) |
942+ fp->fecpriv_mac_addr[3];
943+ FEC_PAUR(base_addr) = (fp->fecpriv_mac_addr[4] << 24) |
944+ (fp->fecpriv_mac_addr[5] << 16) | 0x8808;
945+
946+ /* Reset the group address descriptor */
947+ FEC_GALR(base_addr) = 0x00000000;
948+ FEC_GAUR(base_addr) = 0x00000000;
949+
950+ /* Reset the individual address descriptor */
951+ FEC_IALR(base_addr) = 0x00000000;
952+ FEC_IAUR(base_addr) = 0x00000000;
953+
954+ /* Set the receive control register */
955+ FEC_RCR(base_addr) = FEC_RCR_MAX_FRM_SIZE | FEC_RCR_MII;
956+
957+ /* Set the receive FIFO control register */
958+ /*FEC_FECRFCR(base_addr) =
959+ * FEC_FECRFCR_FRM | FEC_FECRFCR_GR | FEC_FECRFCR_MSK;*/
960+ FEC_FECRFCR(base_addr) = FEC_FECRFCR_FRM | FEC_FECRFCR_GR
961+ | (FEC_FECRFCR_MSK
962+ /* disable all but ...*/
963+ & ~FEC_FECRFCR_FAE
964+ /* enable frame accept error*/
965+ & ~FEC_FECRFCR_RXW
966+ /* enable receive wait condition*/
967+ /*& ~FEC_FECRFCR_UF*/
968+ /* enable FIFO underflow*/
969+ );
970+
971+ /* Set the receive FIFO alarm register */
972+ FEC_FECRFAR(base_addr) = FEC_FECRFAR_ALARM;
973+
974+ /* Set the transmit FIFO control register */
975+ /*FEC_FECTFCR(base_addr) =
976+ FEC_FECTFCR_FRM | FEC_FECTFCR_GR | FEC_FECTFCR_MSK;*/
977+ FEC_FECTFCR(base_addr) = FEC_FECTFCR_FRM | FEC_FECTFCR_GR
978+ | (FEC_FECTFCR_MSK
979+ /* disable all but ... */
980+ & ~FEC_FECTFCR_FAE
981+ /* enable frame accept error */
982+ /* & ~FEC_FECTFCR_TXW */
983+ /*enable transmit wait condition*/
984+ /*& ~FEC_FECTFCR_UF*/
985+ /*enable FIFO underflow*/
986+ & ~FEC_FECTFCR_OF);
987+ /* enable FIFO overflow */
988+
989+ /* Set the transmit FIFO alarm register */
990+ FEC_FECTFAR(base_addr) = FEC_FECTFAR_ALARM;
991+
992+ /* Set the Tx FIFO watermark */
993+ FEC_FECTFWR(base_addr) = FEC_FECTFWR_XWMRK;
994+
995+ /* Enable the transmitter to append the CRC */
996+ FEC_CTCWR(base_addr) = FEC_CTCWR_TFCW_CRC;
997+
998+ /* Enable the ethernet interrupts */
999+ /*FEC_EIMR(base_addr) = FEC_EIMR_MASK;*/
1000+ FEC_EIMR(base_addr) = FEC_EIMR_DISABLE
1001+ | FEC_EIR_LC
1002+ | FEC_EIR_RL
1003+ | FEC_EIR_HBERR
1004+ | FEC_EIR_XFUN
1005+ | FEC_EIR_XFERR
1006+ | FEC_EIR_RFERR;
1007+
1008+#if 0
1009+ error_code = init_transceiver(base_addr, &fduplex);
1010+ if (error_code != 0) {
1011+ printk(KERN_ERR "Initialization of the "
1012+ "transceiver is failed\n");
1013+ goto ERRORS;
1014+ }
1015+#else
1016+ fduplex = 1;
1017+#endif
1018+ if (fduplex)
1019+ /* Enable the full duplex mode */
1020+ FEC_TCR(base_addr) = FEC_TCR_FDEN | FEC_TCR_HBC;
1021+ else
1022+ /* Disable reception of frames while transmitting */
1023+ FEC_RCR(base_addr) |= FEC_RCR_DRT;
1024+
1025+ /* Enable MIB */
1026+ FEC_MIBC(base_addr) = FEC_MIBC_ENABLE;
1027+
1028+ /* Enable FEC */
1029+ FEC_ECR(base_addr) |= FEC_ECR_ETHEREN;
1030+ FEC_MSCR(dev->base_addr) = FEC_MII_SPEED;
1031+ /* Initialize tx descriptors and start DMA for the transmission */
1032+ for (i = 0; i < FEC_TX_BUF_NUMBER; i++)
1033+ fp->fecpriv_txdesc[i].statCtrl = MCD_FEC_INTERRUPT;
1034+
1035+ fp->fecpriv_txdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
1036+
1037+ fp->fecpriv_current_tx = fp->fecpriv_next_tx = 0;
1038+
1039+ MCD_startDma(fp->fecpriv_fec_tx_channel, (char *) fp->fecpriv_txdesc, 0,
1040+ (unsigned char *) &(FEC_FECTFDR(base_addr)), 0,
1041+ FEC_MAX_FRM_SIZE, 0, fp->fecpriv_initiator_tx,
1042+ FEC_TX_DMA_PRI, MCD_FECTX_DMA | MCD_INTERRUPT,
1043+ MCD_NO_CSUM | MCD_NO_BYTE_SWAP);
1044+
1045+ /* Initialize rx descriptors and start DMA for the reception */
1046+ for (i = 0; i < FEC_RX_BUF_NUMBER; i++) {
1047+ fp->askb_rx[i] = alloc_skb(FEC_MAXBUF_SIZE + 16, GFP_DMA);
1048+ if (!fp->askb_rx[i]) {
1049+ fp->fecpriv_rxdesc[i].dataPointer = 0;
1050+ fp->fecpriv_rxdesc[i].statCtrl = 0;
1051+ fp->fecpriv_rxdesc[i].length = 0;
1052+ } else {
1053+ skb_reserve(fp->askb_rx[i], 16);
1054+ fp->askb_rx[i]->dev = dev;
1055+ fp->fecpriv_rxdesc[i].dataPointer =
1056+ (unsigned int)virt_to_phys(fp->askb_rx[i]->tail);
1057+ fp->fecpriv_rxdesc[i].statCtrl =
1058+ MCD_FEC_BUF_READY | MCD_FEC_INTERRUPT;
1059+ fp->fecpriv_rxdesc[i].length = FEC_MAXBUF_SIZE;
1060+ }
1061+ }
1062+
1063+ fp->fecpriv_rxdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
1064+ fp->fecpriv_current_rx = 0;
1065+
1066+ MCD_startDma(fp->fecpriv_fec_rx_channel, (char *) fp->fecpriv_rxdesc, 0,
1067+ (unsigned char *) &(FEC_FECRFDR(base_addr)), 0,
1068+ FEC_MAX_FRM_SIZE, 0, fp->fecpriv_initiator_rx,
1069+ FEC_RX_DMA_PRI, MCD_FECRX_DMA | MCD_INTERRUPT,
1070+ MCD_NO_CSUM | MCD_NO_BYTE_SWAP);
1071+
1072+ netif_start_queue(dev);
1073+ return 0;
1074+
1075+ERRORS:
1076+
1077+ /* Remove the channels and return with the error code */
1078+ if (fp->fecpriv_fec_rx_channel != -1) {
1079+ dma_disconnect(fp->fecpriv_fec_rx_channel);
1080+ dma_remove_channel_by_number(fp->fecpriv_fec_rx_channel);
1081+ fp->fecpriv_fec_rx_channel = -1;
1082+ }
1083+
1084+ if (fp->fecpriv_fec_tx_channel != -1) {
1085+ dma_disconnect(fp->fecpriv_fec_tx_channel);
1086+ dma_remove_channel_by_number(fp->fecpriv_fec_tx_channel);
1087+ fp->fecpriv_fec_tx_channel = -1;
1088+ }
1089+
1090+ return error_code;
1091+}
1092+
1093+/************************************************************************
1094+* NAME: mcf547x_fec_close
1095+*
1096+* DESCRIPTION: This function performs the graceful stop of the
1097+* transmission and disables FEC
1098+*
1099+* RETURNS: This function always returns zero.
1100+*************************************************************************/
1101+static int mcf547x_fec_close(struct net_device *dev)
1102+{
1103+ struct fec_priv *fp = netdev_priv(dev);
1104+ unsigned long base_addr = (unsigned long) dev->base_addr;
1105+ unsigned long time;
1106+ int i;
1107+
1108+ netif_stop_queue(dev);
1109+ phy_disconnect(fp->phydev);
1110+ phy_stop(fp->phydev);
1111+ /* Perform the graceful stop */
1112+ FEC_TCR(base_addr) |= FEC_TCR_GTS;
1113+
1114+ time = jiffies;
1115+
1116+ /* Wait for the graceful stop */
1117+ while (!(FEC_EIR(base_addr) & FEC_EIR_GRA) && jiffies - time <
1118+ (FEC_GR_TIMEOUT * HZ))
1119+ schedule();
1120+
1121+ /* Disable FEC */
1122+ FEC_ECR(base_addr) = FEC_ECR_DISABLE;
1123+
1124+ /* Reset the DMA channels */
1125+ spin_lock_irq(&fp->fecpriv_lock);
1126+ MCD_killDma(fp->fecpriv_fec_tx_channel);
1127+ spin_unlock_irq(&fp->fecpriv_lock);
1128+ dma_remove_channel_by_number(fp->fecpriv_fec_tx_channel);
1129+ dma_disconnect(fp->fecpriv_fec_tx_channel);
1130+ fp->fecpriv_fec_tx_channel = -1;
1131+
1132+ for (i = 0; i < FEC_TX_BUF_NUMBER; i++) {
1133+ kfree(fp->fecpriv_txbuf[i]);
1134+ fp->fecpriv_txbuf[i] = NULL;
1135+ }
1136+
1137+ spin_lock_irq(&fp->fecpriv_lock);
1138+ MCD_killDma(fp->fecpriv_fec_rx_channel);
1139+ spin_unlock_irq(&fp->fecpriv_lock);
1140+
1141+ dma_remove_channel_by_number(fp->fecpriv_fec_rx_channel);
1142+ dma_disconnect(fp->fecpriv_fec_rx_channel);
1143+ fp->fecpriv_fec_rx_channel = -1;
1144+
1145+ for (i = 0; i < FEC_RX_BUF_NUMBER; i++) {
1146+ if (fp->askb_rx[i]) {
1147+ kfree_skb(fp->askb_rx[i]);
1148+ fp->askb_rx[i] = NULL;
1149+ }
1150+ }
1151+
1152+ return 0;
1153+}
1154+
1155+/************************************************************************
1156+* +NAME: mcf547x_fec_get_stat
1157+*
1158+* RETURNS: This function returns the statistical information.
1159+*************************************************************************/
1160+static struct net_device_stats *mcf547x_fec_get_stats(struct net_device *dev)
1161+{
1162+ struct fec_priv *fp = netdev_priv(dev);
1163+ unsigned long base_addr = dev->base_addr;
1164+
1165+ /* Receive the statistical information */
1166+ fp->fecpriv_stat.rx_packets = FECSTAT_RMON_R_PACKETS(base_addr);
1167+ fp->fecpriv_stat.tx_packets = FECSTAT_RMON_T_PACKETS(base_addr);
1168+ fp->fecpriv_stat.rx_bytes = FECSTAT_RMON_R_OCTETS(base_addr);
1169+ fp->fecpriv_stat.tx_bytes = FECSTAT_RMON_T_OCTETS(base_addr);
1170+
1171+ fp->fecpriv_stat.multicast = FECSTAT_RMON_R_MC_PKT(base_addr);
1172+ fp->fecpriv_stat.collisions = FECSTAT_RMON_T_COL(base_addr);
1173+
1174+ fp->fecpriv_stat.rx_length_errors =
1175+ FECSTAT_RMON_R_UNDERSIZE(base_addr) +
1176+ FECSTAT_RMON_R_OVERSIZE(base_addr) +
1177+ FECSTAT_RMON_R_FRAG(base_addr) +
1178+ FECSTAT_RMON_R_JAB(base_addr);
1179+ fp->fecpriv_stat.rx_crc_errors = FECSTAT_IEEE_R_CRC(base_addr);
1180+ fp->fecpriv_stat.rx_frame_errors = FECSTAT_IEEE_R_ALIGN(base_addr);
1181+ fp->fecpriv_stat.rx_over_errors = FECSTAT_IEEE_R_MACERR(base_addr);
1182+
1183+ fp->fecpriv_stat.tx_carrier_errors = FECSTAT_IEEE_T_CSERR(base_addr);
1184+ fp->fecpriv_stat.tx_fifo_errors = FECSTAT_IEEE_T_MACERR(base_addr);
1185+ fp->fecpriv_stat.tx_window_errors = FECSTAT_IEEE_T_LCOL(base_addr);
1186+
1187+ /* I hope that one frame doesn't have more than one error */
1188+ fp->fecpriv_stat.rx_errors = fp->fecpriv_stat.rx_length_errors +
1189+ fp->fecpriv_stat.rx_crc_errors +
1190+ fp->fecpriv_stat.rx_frame_errors +
1191+ fp->fecpriv_stat.rx_over_errors +
1192+ fp->fecpriv_stat.rx_dropped;
1193+ fp->fecpriv_stat.tx_errors = fp->fecpriv_stat.tx_carrier_errors +
1194+ fp->fecpriv_stat.tx_fifo_errors +
1195+ fp->fecpriv_stat.tx_window_errors +
1196+ fp->fecpriv_stat.tx_aborted_errors +
1197+ fp->fecpriv_stat.tx_heartbeat_errors +
1198+ fp->fecpriv_stat.tx_dropped;
1199+
1200+ return &fp->fecpriv_stat;
1201+}
1202+
1203+/************************************************************************
1204+* NAME: mcf547x_fec_set_multicast_list
1205+*
1206+* DESCRIPTION: This function sets the frame filtering parameters
1207+*************************************************************************/
1208+static void mcf547x_fec_set_multicast_list(struct net_device *dev)
1209+{
1210+ unsigned int crc, data;
1211+ int j, k;
1212+ unsigned long base_addr = (unsigned long) dev->base_addr;
1213+ struct netdev_hw_addr *ha;
1214+
1215+ if (dev->flags & IFF_PROMISC || dev->flags & IFF_ALLMULTI) {
1216+ /* Allow all incoming frames */
1217+ FEC_GALR(base_addr) = 0xFFFFFFFF;
1218+ FEC_GAUR(base_addr) = 0xFFFFFFFF;
1219+ return;
1220+ }
1221+
1222+ /* Reset the group address register */
1223+ FEC_GALR(base_addr) = 0x00000000;
1224+ FEC_GAUR(base_addr) = 0x00000000;
1225+
1226+ /* Process all addresses */
1227+ netdev_for_each_mc_addr(ha, dev) {
1228+ /* Processing must be only for the group addresses */
1229+ if (!(ha->addr[0] & 1))
1230+ continue;
1231+
1232+ /* Calculate crc value for the current address */
1233+ crc = 0xFFFFFFFF;
1234+ for (j = 0; j < dev->addr_len; j++) {
1235+ data = ha->addr[j];
1236+ for (k = 0; k < 8; k++, data >>= 1) {
1237+ if ((crc ^ data) & 1)
1238+ crc = (crc >> 1) ^ FEC_CRCPOL;
1239+ else
1240+ crc >>= 1;
1241+ }
1242+ }
1243+
1244+ /* Add this value */
1245+ crc >>= 26;
1246+ crc &= 0x3F;
1247+ if (crc > 31)
1248+ FEC_GAUR(base_addr) |= 0x1 << (crc - 32);
1249+ else
1250+ FEC_GALR(base_addr) |= 0x1 << crc;
1251+ }
1252+}
1253+
1254+/************************************************************************
1255+* NAME: mcf547x_fec_set_mac_address
1256+*
1257+* DESCRIPTION: This function sets the MAC address
1258+*************************************************************************/
1259+static int mcf547x_fec_set_mac_address(struct net_device *dev, void *p)
1260+{
1261+ struct fec_priv *fp = netdev_priv(dev);
1262+ unsigned long base_addr = (unsigned long) dev->base_addr;
1263+ struct sockaddr *addr = p;
1264+
1265+ if (netif_running(dev))
1266+ return -EBUSY;
1267+
1268+ /* Copy a new address to the device structure */
1269+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
1270+
1271+ /* Copy a new address to the private structure */
1272+ memcpy(fp->fecpriv_mac_addr, addr->sa_data, 6);
1273+
1274+ /* Set the address to the registers */
1275+ FEC_PALR(base_addr) = (fp->fecpriv_mac_addr[0] << 24) |
1276+ (fp->fecpriv_mac_addr[1] << 16) |
1277+ (fp->fecpriv_mac_addr[2] << 8) |
1278+ fp->fecpriv_mac_addr[3];
1279+ FEC_PAUR(base_addr) = (fp->fecpriv_mac_addr[4] << 24) |
1280+ (fp->fecpriv_mac_addr[5] << 16) |
1281+ 0x8808;
1282+
1283+ return 0;
1284+}
1285+
1286+/************************************************************************
1287+* NAME: mcf547x_fec_start_xmit
1288+*
1289+* DESCRIPTION: This function starts transmission of the frame using DMA
1290+*
1291+* RETURNS: This function always returns zero.
1292+*************************************************************************/
1293+static int mcf547x_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
1294+{
1295+ struct fec_priv *fp = netdev_priv(dev);
1296+ void *data, *data_aligned;
1297+ int offset;
1298+
1299+ data = kmalloc(skb->len + 15, GFP_DMA | GFP_ATOMIC);
1300+
1301+ if (!data) {
1302+ fp->fecpriv_stat.tx_dropped++;
1303+ dev_kfree_skb(skb);
1304+ return 0;
1305+ }
1306+
1307+ offset = (((unsigned long)virt_to_phys(data) + 15) & 0xFFFFFFF0) -
1308+ (unsigned long)virt_to_phys(data);
1309+ data_aligned = (void *)((unsigned long)data + offset);
1310+ memcpy(data_aligned, skb->data, skb->len);
1311+
1312+ /* flush data cache before initializing
1313+ * the descriptor and starting DMA */
1314+
1315+ spin_lock_irq(&fp->fecpriv_lock);
1316+
1317+ /* Initialize the descriptor */
1318+ fp->fecpriv_txbuf[fp->fecpriv_next_tx] = data;
1319+ fp->fecpriv_txdesc[fp->fecpriv_next_tx].dataPointer
1320+ = (unsigned int) virt_to_phys(data_aligned);
1321+ fp->fecpriv_txdesc[fp->fecpriv_next_tx].length = skb->len;
1322+ fp->fecpriv_txdesc[fp->fecpriv_next_tx].statCtrl
1323+ |= (MCD_FEC_END_FRAME | MCD_FEC_BUF_READY);
1324+ fp->fecpriv_next_tx = (fp->fecpriv_next_tx + 1) & FEC_TX_INDEX_MASK;
1325+
1326+ if (fp->fecpriv_txbuf[fp->fecpriv_current_tx]
1327+ && fp->fecpriv_current_tx == fp->fecpriv_next_tx)
1328+ netif_stop_queue(dev);
1329+
1330+ spin_unlock_irq(&fp->fecpriv_lock);
1331+
1332+ /* Tell the DMA to continue the transmission */
1333+ MCD_continDma(fp->fecpriv_fec_tx_channel);
1334+
1335+ dev_kfree_skb(skb);
1336+
1337+ dev->trans_start = jiffies;
1338+
1339+ return 0;
1340+}
1341+
1342+/************************************************************************
1343+* NAME: mcf547x_fec_tx_timeout
1344+*
1345+* DESCRIPTION: If the interrupt processing of received frames was lost
1346+* and DMA stopped the reception, this function clears
1347+* the transmission descriptors and starts DMA
1348+*
1349+*************************************************************************/
1350+static void mcf547x_fec_tx_timeout(struct net_device *dev)
1351+{
1352+ int i;
1353+ struct fec_priv *fp = netdev_priv(dev);
1354+ unsigned long base_addr = (unsigned long) dev->base_addr;
1355+
1356+ spin_lock_irq(&fp->fecpriv_lock);
1357+ MCD_killDma(fp->fecpriv_fec_tx_channel);
1358+ for (i = 0; i < FEC_TX_BUF_NUMBER; i++) {
1359+ kfree(fp->fecpriv_txbuf[i]);
1360+ fp->fecpriv_txbuf[i] = NULL;
1361+ fp->fecpriv_txdesc[i].statCtrl = MCD_FEC_INTERRUPT;
1362+ }
1363+ fp->fecpriv_txdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
1364+
1365+ fp->fecpriv_current_tx = fp->fecpriv_next_tx = 0;
1366+
1367+ /* Reset FIFOs */
1368+ FEC_FECFRST(base_addr) |= FEC_SW_RST;
1369+ FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
1370+
1371+ /* Reset and disable FEC */
1372+ /* FEC_ECR(base_addr) = FEC_ECR_RESET; */
1373+
1374+ /* Enable FEC */
1375+ FEC_ECR(base_addr) |= FEC_ECR_ETHEREN;
1376+
1377+ MCD_startDma(fp->fecpriv_fec_tx_channel, (char *) fp->fecpriv_txdesc, 0,
1378+ (unsigned char *) &(FEC_FECTFDR(base_addr)), 0,
1379+ FEC_MAX_FRM_SIZE, 0, fp->fecpriv_initiator_tx,
1380+ FEC_TX_DMA_PRI, MCD_FECTX_DMA | MCD_INTERRUPT,
1381+ MCD_NO_CSUM | MCD_NO_BYTE_SWAP);
1382+
1383+ spin_unlock_irq(&fp->fecpriv_lock);
1384+
1385+ netif_wake_queue(dev);
1386+
1387+}
1388+
1389+static const struct net_device_ops mcf547x_fec_netdev_ops = {
1390+ .ndo_open = mcf547x_fec_open,
1391+ .ndo_stop = mcf547x_fec_close,
1392+ .ndo_start_xmit = mcf547x_fec_start_xmit,
1393+ .ndo_set_multicast_list = mcf547x_fec_set_multicast_list,
1394+ .ndo_set_mac_address = mcf547x_fec_set_mac_address,
1395+ .ndo_tx_timeout = mcf547x_fec_tx_timeout,
1396+ .ndo_get_stats = mcf547x_fec_get_stats,
1397+};
1398+
1399+/*
1400+ * Initialize a FEC device
1401+ */
1402+int fec_enet_init(struct net_device *dev, int slot)
1403+{
1404+ struct fec_priv *fp = netdev_priv(dev);
1405+ int i;
1406+
1407+ fp->index = slot;
1408+ fp->netdev = dev;
1409+ fec_dev[slot] = dev;
1410+
1411+ if (slot == 0) {
1412+ /* disable fec0 */
1413+ FEC_ECR(FEC_BASE_ADDR_FEC0) = FEC_ECR_DISABLE;
1414+
1415+ /* setup the interrupt handler */
1416+ dev->irq = 64 + ISC_FEC0;
1417+
1418+ if (request_irq(dev->irq, fec_interrupt_handler,
1419+ IRQF_DISABLED, "ColdFire FEC 0", dev)) {
1420+ dev->irq = 0;
1421+ printk(KERN_ERR "Cannot allocate FEC0 IRQ\n");
1422+ } else {
1423+ /* interrupt priority and level */
1424+ MCF_ICR(ISC_FEC0) = ILP_FEC0;
1425+ }
1426+
1427+ /* fec base address */
1428+ dev->base_addr = FEC_BASE_ADDR_FEC0;
1429+
1430+ /* requestor numbers */
1431+ fp->fecpriv_rx_requestor = DMA_FEC0_RX;
1432+ fp->fecpriv_tx_requestor = DMA_FEC0_TX;
1433+
1434+ /* fec0 handlers */
1435+ fp->fecpriv_interrupt_fec_rx_handler =
1436+ fec_interrupt_fec_rx_handler_fec0;
1437+ fp->fecpriv_interrupt_fec_tx_handler =
1438+ fec_interrupt_fec_tx_handler_fec0;
1439+
1440+ /* tx descriptors */
1441+ fp->fecpriv_txdesc = (void *)FEC_TX_DESC_FEC0;
1442+
1443+ /* rx descriptors */
1444+ fp->fecpriv_rxdesc = (void *)FEC_RX_DESC_FEC0;
1445+
1446+ /* mac addr
1447+ if (uboot_enet0[0] || uboot_enet0[1] || uboot_enet0[2] ||
1448+ uboot_enet0[3] || uboot_enet0[4] || uboot_enet0[5]) {
1449+ use uboot enet 0 addr
1450+ memcpy(fec_mac_addr_fec0, uboot_enet0, 6);
1451+ }*/
1452+ fec_mac_addr_fec0[0] =
1453+ (FEC_PALR(FEC_BASE_ADDR_FEC0) >> 24) & 0xFF;
1454+ fec_mac_addr_fec0[1] =
1455+ (FEC_PALR(FEC_BASE_ADDR_FEC0) >> 16) & 0xFF;
1456+ fec_mac_addr_fec0[2] =
1457+ (FEC_PALR(FEC_BASE_ADDR_FEC0) >> 8) & 0xFF;
1458+ fec_mac_addr_fec0[3] =
1459+ (FEC_PALR(FEC_BASE_ADDR_FEC0)) & 0xFF;
1460+ fec_mac_addr_fec0[4] =
1461+ (FEC_PAUR(FEC_BASE_ADDR_FEC0) >> 24) & 0xFF;
1462+ fec_mac_addr_fec0[5] =
1463+ (FEC_PAUR(FEC_BASE_ADDR_FEC0) >> 16) & 0xFF;
1464+
1465+ fp->fecpriv_mac_addr = fec_mac_addr_fec0;
1466+ } else {
1467+ /* disable fec1 */
1468+ FEC_ECR(FEC_BASE_ADDR_FEC1) = FEC_ECR_DISABLE;
1469+#ifdef FEC_2
1470+ /* setup the interrupt handler */
1471+ dev->irq = 64 + ISC_FEC1;
1472+
1473+ if (request_irq(dev->irq, fec_interrupt_handler,
1474+ IRQF_DISABLED, "ColdFire FEC 1", dev)) {
1475+ dev->irq = 0;
1476+ printk(KERN_ERR "Cannot allocate FEC1 IRQ\n");
1477+ } else {
1478+ /* interrupt priority and level */
1479+ MCF_ICR(ISC_FEC1) = ILP_FEC1;
1480+ }
1481+
1482+ /* fec base address */
1483+ dev->base_addr = FEC_BASE_ADDR_FEC1;
1484+
1485+ /* requestor numbers */
1486+ fp->fecpriv_rx_requestor = DMA_FEC1_RX;
1487+ fp->fecpriv_tx_requestor = DMA_FEC1_TX;
1488+
1489+ /* fec1 handlers */
1490+ fp->fecpriv_interrupt_fec_rx_handler =
1491+ fec_interrupt_fec_rx_handler_fec1;
1492+ fp->fecpriv_interrupt_fec_tx_handler =
1493+ fec_interrupt_fec_tx_handler_fec1;
1494+
1495+ /* tx descriptors */
1496+ fp->fecpriv_txdesc = (void *)FEC_TX_DESC_FEC1;
1497+
1498+ /* rx descriptors */
1499+ fp->fecpriv_rxdesc = (void *)FEC_RX_DESC_FEC1;
1500+
1501+ /* mac addr
1502+ if (uboot_enet1[0] || uboot_enet1[1] || uboot_enet1[2] ||
1503+ uboot_enet1[3] || uboot_enet1[4] || uboot_enet1[5]) {
1504+ use uboot enet 1 addr
1505+ memcpy(fec_mac_addr_fec1, uboot_enet1, 6);
1506+ }*/
1507+ fec_mac_addr_fec1[0] =
1508+ (FEC_PALR(FEC_BASE_ADDR_FEC1) >> 24) & 0xFF;
1509+ fec_mac_addr_fec1[1] =
1510+ (FEC_PALR(FEC_BASE_ADDR_FEC1) >> 16) & 0xFF;
1511+ fec_mac_addr_fec1[2] =
1512+ (FEC_PALR(FEC_BASE_ADDR_FEC1) >> 8) & 0xFF;
1513+ fec_mac_addr_fec1[3] =
1514+ (FEC_PALR(FEC_BASE_ADDR_FEC1)) & 0xFF;
1515+ fec_mac_addr_fec1[4] =
1516+ (FEC_PAUR(FEC_BASE_ADDR_FEC1) >> 24) & 0xFF;
1517+ fec_mac_addr_fec1[5] =
1518+ (FEC_PAUR(FEC_BASE_ADDR_FEC1) >> 16) & 0xFF;
1519+
1520+ fp->fecpriv_mac_addr = fec_mac_addr_fec1;
1521+#endif
1522+ }
1523+
1524+ /* clear MIB */
1525+ memset((void *) (dev->base_addr + 0x200), 0, FEC_MIB_LEN);
1526+
1527+ /* clear the statistics structure */
1528+ memset((void *) &(fp->fecpriv_stat), 0,
1529+ sizeof(struct net_device_stats));
1530+
1531+ /* grab the FEC initiators */
1532+ dma_set_initiator(fp->fecpriv_tx_requestor);
1533+ fp->fecpriv_initiator_tx = dma_get_initiator(fp->fecpriv_tx_requestor);
1534+ dma_set_initiator(fp->fecpriv_rx_requestor);
1535+ fp->fecpriv_initiator_rx = dma_get_initiator(fp->fecpriv_rx_requestor);
1536+
1537+ /* reset the DMA channels */
1538+ fp->fecpriv_fec_rx_channel = -1;
1539+ fp->fecpriv_fec_tx_channel = -1;
1540+
1541+ for (i = 0; i < FEC_RX_BUF_NUMBER; i++)
1542+ fp->askb_rx[i] = NULL;
1543+
1544+ /* initialize the pointers to the socket buffers */
1545+ for (i = 0; i < FEC_TX_BUF_NUMBER; i++)
1546+ fp->fecpriv_txbuf[i] = NULL;
1547+
1548+ ether_setup(dev);
1549+
1550+ dev->netdev_ops = &mcf547x_fec_netdev_ops;
1551+ dev->watchdog_timeo = FEC_TX_TIMEOUT * HZ;
1552+
1553+ memcpy(dev->dev_addr, fp->fecpriv_mac_addr, ETH_ALEN);
1554+
1555+ spin_lock_init(&fp->fecpriv_lock);
1556+
1557+ /* Initialize FEC/I2C/IRQ Pin Assignment Register*/
1558+ FEC_GPIO_PAR_FECI2CIRQ &= 0xF;
1559+ FEC_GPIO_PAR_FECI2CIRQ |= FEC_FECI2CIRQ;
1560+
1561+ return 0;
1562+}
1563+
1564+/*
1565+ * Module Initialization
1566+ */
1567+int __init fec_init(void)
1568+{
1569+ struct net_device *dev;
1570+ int i;
1571+ int err;
1572+ struct fec_priv *fep;
1573+
1574+ printk(KERN_INFO "FEC ENET (DMA) Version %s\n", VERSION);
1575+
1576+ for (i = 0; i < FEC_MAX_PORTS; i++) {
1577+ dev = alloc_etherdev(sizeof(struct fec_priv));
1578+ if (!dev)
1579+ return -ENOMEM;
1580+ err = fec_enet_init(dev, i);
1581+ if (err) {
1582+ free_netdev(dev);
1583+ continue;
1584+ }
1585+
1586+ fep = netdev_priv(dev);
1587+ FEC_MSCR(dev->base_addr) = FEC_MII_SPEED;
1588+#ifdef CONFIG_FEC_548x_SHARED_PHY
1589+ if (i == 0)
1590+ err = fec_mdio_register(dev, i);
1591+ else {
1592+ struct fec_priv *priv0 = netdev_priv(fec_dev[0]);
1593+ fep->mdio_bus = priv0->mdio_bus;
1594+ printk(KERN_INFO "FEC%d SHARED the %s ok\n",
1595+ i, fep->mdio_bus->name);
1596+ }
1597+#else
1598+ err = fec_mdio_register(dev, i);
1599+#endif
1600+ if (err) {
1601+ printk(KERN_ERR "%s: ethernet fec_mdio_register\n",
1602+ dev->name);
1603+ free_netdev(dev);
1604+ return -ENOMEM;
1605+ }
1606+
1607+ if (register_netdev(dev) != 0) {
1608+ free_netdev(dev);
1609+ return -EIO;
1610+ }
1611+
1612+ printk(KERN_INFO "%s: ethernet %s\n",
1613+ dev->name, dev->dev_addr);
1614+ }
1615+ return 0;
1616+}
1617+
1618+/*
1619+ * Stop a device
1620+ */
1621+void fec_stop(struct net_device *dev)
1622+{
1623+ struct fec_priv *fp = netdev_priv(dev);
1624+
1625+ dma_remove_initiator(fp->fecpriv_initiator_tx);
1626+ dma_remove_initiator(fp->fecpriv_initiator_rx);
1627+
1628+ if (dev->irq)
1629+ free_irq(dev->irq, dev);
1630+}
1631+
1632+/************************************************************************
1633+* NAME: fec_interrupt_tx_handler
1634+*
1635+* DESCRIPTION: This function is called when the data
1636+* transmission from the buffer to the FEC is completed.
1637+*
1638+*************************************************************************/
1639+void fec_interrupt_fec_tx_handler(struct net_device *dev)
1640+{
1641+ struct fec_priv *fp = netdev_priv(dev);
1642+
1643+ /* Release the socket buffer */
1644+ kfree(fp->fecpriv_txbuf[fp->fecpriv_current_tx]);
1645+ fp->fecpriv_txbuf[fp->fecpriv_current_tx] = NULL;
1646+
1647+ fp->fecpriv_current_tx =
1648+ (fp->fecpriv_current_tx + 1) & FEC_TX_INDEX_MASK;
1649+
1650+ if (MCD_dmaStatus(fp->fecpriv_fec_tx_channel) == MCD_DONE) {
1651+ for (; fp->fecpriv_current_tx != fp->fecpriv_next_tx;
1652+ fp->fecpriv_current_tx =
1653+ (fp->fecpriv_current_tx + 1)
1654+ & FEC_TX_INDEX_MASK) {
1655+ if (fp->fecpriv_txbuf[fp->fecpriv_current_tx]) {
1656+ kfree(fp->fecpriv_txbuf[
1657+ fp->fecpriv_current_tx]);
1658+ fp->fecpriv_txbuf[fp->fecpriv_current_tx]
1659+ = NULL;
1660+ }
1661+ }
1662+ }
1663+
1664+ if (netif_queue_stopped(dev))
1665+ netif_wake_queue(dev);
1666+}
1667+
1668+/************************************************************************
1669+* NAME: fec_interrupt_rx_handler
1670+*
1671+* DESCRIPTION: This function is called when the data
1672+* reception from the FEC to the reception buffer is completed.
1673+*
1674+*************************************************************************/
1675+void fec_interrupt_fec_rx_handler(struct net_device *dev)
1676+{
1677+ struct fec_priv *fp = netdev_priv(dev);
1678+ struct sk_buff *skb;
1679+ int i;
1680+
1681+ fp->fecpriv_rxflag = 1;
1682+ /* Some buffers can be missed */
1683+ if (!(fp->fecpriv_rxdesc[fp->fecpriv_current_rx].statCtrl
1684+ & MCD_FEC_END_FRAME)) {
1685+ /* Find a valid index */
1686+ for (i = 0; ((i < FEC_RX_BUF_NUMBER) &&
1687+ !(fp->fecpriv_rxdesc[
1688+ fp->fecpriv_current_rx].statCtrl
1689+ & MCD_FEC_END_FRAME)); i++,
1690+ (fp->fecpriv_current_rx =
1691+ (fp->fecpriv_current_rx + 1)
1692+ & FEC_RX_INDEX_MASK))
1693+ ;
1694+
1695+ if (i == FEC_RX_BUF_NUMBER) {
1696+ /* There are no data to process */
1697+ /* Tell the DMA to continue the reception */
1698+ MCD_continDma(fp->fecpriv_fec_rx_channel);
1699+
1700+ fp->fecpriv_rxflag = 0;
1701+
1702+ return;
1703+ }
1704+ }
1705+
1706+ for (; fp->fecpriv_rxdesc[fp->fecpriv_current_rx].statCtrl
1707+ & MCD_FEC_END_FRAME;
1708+ fp->fecpriv_current_rx = (fp->fecpriv_current_rx + 1)
1709+ & FEC_RX_INDEX_MASK) {
1710+ if ((fp->fecpriv_rxdesc[fp->fecpriv_current_rx].length
1711+ <= FEC_MAXBUF_SIZE) &&
1712+ (fp->fecpriv_rxdesc[fp->fecpriv_current_rx].length
1713+ > 4)) {
1714+ /* --tym-- */
1715+ skb = fp->askb_rx[fp->fecpriv_current_rx];
1716+ if (!skb)
1717+ fp->fecpriv_stat.rx_dropped++;
1718+ else {
1719+ /*
1720+ * flush data cache before initializing
1721+ * the descriptor and starting DMA
1722+ */
1723+ skb_put(skb,
1724+ (fp->fecpriv_rxdesc[
1725+ fp->fecpriv_current_rx].length - 4));
1726+ skb->protocol = eth_type_trans(skb, dev);
1727+ netif_rx(skb);
1728+ }
1729+ fp->fecpriv_rxdesc[fp->fecpriv_current_rx].statCtrl &=
1730+ ~MCD_FEC_END_FRAME;
1731+ /* allocate new skbuff */
1732+ fp->askb_rx[fp->fecpriv_current_rx] =
1733+ alloc_skb(FEC_MAXBUF_SIZE + 16,
1734+ /*GFP_ATOMIC |*/ GFP_DMA);
1735+ if (!fp->askb_rx[fp->fecpriv_current_rx]) {
1736+ fp->fecpriv_rxdesc[
1737+ fp->fecpriv_current_rx].dataPointer
1738+ = 0;
1739+ fp->fecpriv_rxdesc[
1740+ fp->fecpriv_current_rx].length = 0;
1741+ fp->fecpriv_stat.rx_dropped++;
1742+ } else {
1743+ skb_reserve(
1744+ fp->askb_rx[fp->fecpriv_current_rx], 16);
1745+ fp->askb_rx[fp->fecpriv_current_rx]->dev = dev;
1746+
1747+ /*
1748+ * flush data cache before initializing
1749+ * the descriptor and starting DMA
1750+ */
1751+
1752+ fp->fecpriv_rxdesc[
1753+ fp->fecpriv_current_rx].dataPointer =
1754+ (unsigned int) virt_to_phys(
1755+ fp->askb_rx[
1756+ fp->fecpriv_current_rx]->tail);
1757+ fp->fecpriv_rxdesc[
1758+ fp->fecpriv_current_rx].length =
1759+ FEC_MAXBUF_SIZE;
1760+ fp->fecpriv_rxdesc[
1761+ fp->fecpriv_current_rx].statCtrl |=
1762+ MCD_FEC_BUF_READY;
1763+
1764+ /*
1765+ * flush data cache before initializing
1766+ * the descriptor and starting DMA
1767+ */
1768+ }
1769+ }
1770+
1771+ }
1772+
1773+ /* Tell the DMA to continue the reception */
1774+ MCD_continDma(fp->fecpriv_fec_rx_channel);
1775+
1776+ fp->fecpriv_rxflag = 0;
1777+}
1778+
1779+/************************************************************************
1780+* NAME: fec_interrupt_handler
1781+*
1782+* DESCRIPTION: This function is called when some special errors occur
1783+*
1784+*************************************************************************/
1785+irqreturn_t fec_interrupt_handler(int irq, void *dev_id)
1786+{
1787+
1788+ struct net_device *dev = (struct net_device *)dev_id;
1789+ struct fec_priv *fp = netdev_priv(dev);
1790+ unsigned long base_addr = (unsigned long) dev->base_addr;
1791+ unsigned long events;
1792+
1793+ /* Read and clear the events */
1794+ events = FEC_EIR(base_addr) & FEC_EIMR(base_addr);
1795+
1796+ if (events & FEC_EIR_HBERR) {
1797+ fp->fecpriv_stat.tx_heartbeat_errors++;
1798+ FEC_EIR(base_addr) = FEC_EIR_HBERR;
1799+ }
1800+
1801+ /* receive/transmit FIFO error */
1802+ if (((events & FEC_EIR_RFERR) != 0)
1803+ || ((events & FEC_EIR_XFERR) != 0)) {
1804+ /* kill DMA receive channel */
1805+ MCD_killDma(fp->fecpriv_fec_rx_channel);
1806+
1807+ /* kill running transmission by DMA */
1808+ MCD_killDma(fp->fecpriv_fec_tx_channel);
1809+
1810+ /* Reset FIFOs */
1811+ FEC_FECFRST(base_addr) |= FEC_SW_RST;
1812+ FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
1813+
1814+ /* reset receive FIFO status register */
1815+ FEC_FECRFSR(base_addr) = FEC_FECRFSR_FAE |
1816+ FEC_FECRFSR_RXW |
1817+ FEC_FECRFSR_UF;
1818+
1819+ /* reset transmit FIFO status register */
1820+ FEC_FECTFSR(base_addr) = FEC_FECTFSR_FAE |
1821+ FEC_FECTFSR_TXW |
1822+ FEC_FECTFSR_UF |
1823+ FEC_FECTFSR_OF;
1824+
1825+ /* reset RFERR and XFERR event */
1826+ FEC_EIR(base_addr) = FEC_EIR_RFERR | FEC_EIR_XFERR;
1827+
1828+ /* stop queue */
1829+ netif_stop_queue(dev);
1830+
1831+ /* execute reinitialization as tasklet */
1832+ tasklet_schedule(&fp->fecpriv_tasklet_reinit);
1833+
1834+ fp->fecpriv_stat.rx_dropped++;
1835+ }
1836+
1837+ /* transmit FIFO underrun */
1838+ if ((events & FEC_EIR_XFUN) != 0) {
1839+ /* reset XFUN event */
1840+ FEC_EIR(base_addr) = FEC_EIR_XFUN;
1841+ fp->fecpriv_stat.tx_aborted_errors++;
1842+ }
1843+
1844+ /* late collision */
1845+ if ((events & FEC_EIR_LC) != 0) {
1846+ /* reset LC event */
1847+ FEC_EIR(base_addr) = FEC_EIR_LC;
1848+ fp->fecpriv_stat.tx_aborted_errors++;
1849+ }
1850+
1851+ /* collision retry limit */
1852+ if ((events & FEC_EIR_RL) != 0) {
1853+ /* reset RL event */
1854+ FEC_EIR(base_addr) = FEC_EIR_RL;
1855+ fp->fecpriv_stat.tx_aborted_errors++;
1856+ }
1857+ return 0;
1858+}
1859+
1860+/************************************************************************
1861+* NAME: fec_interrupt_reinit
1862+*
1863+* DESCRIPTION: This function is called from interrupt handler
1864+* when controller must be reinitialized.
1865+*
1866+*************************************************************************/
1867+void fec_interrupt_fec_reinit(unsigned long data)
1868+{
1869+ int i;
1870+ struct net_device *dev = (struct net_device *)data;
1871+ struct fec_priv *fp = netdev_priv(dev);
1872+ unsigned long base_addr = (unsigned long) dev->base_addr;
1873+
1874+ /* Initialize reception descriptors and start DMA for the reception */
1875+ for (i = 0; i < FEC_RX_BUF_NUMBER; i++) {
1876+ if (!fp->askb_rx[i]) {
1877+ fp->askb_rx[i] = alloc_skb(FEC_MAXBUF_SIZE + 16,
1878+ GFP_ATOMIC | GFP_DMA);
1879+ if (!fp->askb_rx[i]) {
1880+ fp->fecpriv_rxdesc[i].dataPointer = 0;
1881+ fp->fecpriv_rxdesc[i].statCtrl = 0;
1882+ fp->fecpriv_rxdesc[i].length = 0;
1883+ continue;
1884+ }
1885+ fp->askb_rx[i]->dev = dev;
1886+ skb_reserve(fp->askb_rx[i], 16);
1887+ }
1888+ fp->fecpriv_rxdesc[i].dataPointer =
1889+ (unsigned int) virt_to_phys(fp->askb_rx[i]->tail);
1890+ fp->fecpriv_rxdesc[i].statCtrl =
1891+ MCD_FEC_BUF_READY | MCD_FEC_INTERRUPT;
1892+ fp->fecpriv_rxdesc[i].length = FEC_MAXBUF_SIZE;
1893+ }
1894+
1895+ fp->fecpriv_rxdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
1896+ fp->fecpriv_current_rx = 0;
1897+
1898+ /* restart frame transmission */
1899+ for (i = 0; i < FEC_TX_BUF_NUMBER; i++) {
1900+ kfree(fp->fecpriv_txbuf[i]);
1901+ fp->fecpriv_txbuf[i] = NULL;
1902+ fp->fecpriv_stat.tx_dropped++;
1903+ fp->fecpriv_txdesc[i].statCtrl = MCD_FEC_INTERRUPT;
1904+ }
1905+ fp->fecpriv_txdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
1906+ fp->fecpriv_current_tx = fp->fecpriv_next_tx = 0;
1907+
1908+ /* flush entire data cache before restarting the DMA */
1909+
1910+ /* restart DMA from beginning */
1911+ MCD_startDma(fp->fecpriv_fec_rx_channel,
1912+ (char *) fp->fecpriv_rxdesc, 0,
1913+ (unsigned char *) &(FEC_FECRFDR(base_addr)), 0,
1914+ FEC_MAX_FRM_SIZE, 0, fp->fecpriv_initiator_rx,
1915+ FEC_RX_DMA_PRI, MCD_FECRX_DMA | MCD_INTERRUPT,
1916+ MCD_NO_CSUM | MCD_NO_BYTE_SWAP);
1917+
1918+ MCD_startDma(fp->fecpriv_fec_tx_channel, (char *) fp->fecpriv_txdesc, 0,
1919+ (unsigned char *) &(FEC_FECTFDR(base_addr)), 0,
1920+ FEC_MAX_FRM_SIZE, 0, fp->fecpriv_initiator_tx,
1921+ FEC_TX_DMA_PRI, MCD_FECTX_DMA | MCD_INTERRUPT,
1922+ MCD_NO_CSUM | MCD_NO_BYTE_SWAP);
1923+
1924+ /* Enable FEC */
1925+ FEC_ECR(base_addr) |= FEC_ECR_ETHEREN;
1926+
1927+ netif_wake_queue(dev);
1928+}
1929+
1930+/************************************************************************
1931+* NAME: fec_interrupt_tx_handler_fec0
1932+*
1933+* DESCRIPTION: This is the DMA interrupt handler using for FEC0
1934+* transmission.
1935+*
1936+*************************************************************************/
1937+void fec_interrupt_fec_tx_handler_fec0(void)
1938+{
1939+ fec_interrupt_fec_tx_handler(fec_dev[0]);
1940+}
1941+
1942+#ifdef FEC_2
1943+/************************************************************************
1944+* NAME: fec_interrupt_tx_handler_fec1
1945+*
1946+* DESCRIPTION: This is the DMA interrupt handler using for the FEC1
1947+* transmission.
1948+*
1949+*************************************************************************/
1950+void fec_interrupt_fec_tx_handler_fec1(void)
1951+{
1952+ fec_interrupt_fec_tx_handler(fec_dev[1]);
1953+}
1954+#endif
1955+
1956+/************************************************************************
1957+* NAME: fec_interrupt_rx_handler_fec0
1958+*
1959+* DESCRIPTION: This is the DMA interrupt handler using for the FEC0
1960+* reception.
1961+*
1962+*************************************************************************/
1963+void fec_interrupt_fec_rx_handler_fec0(void)
1964+{
1965+ fec_interrupt_fec_rx_handler(fec_dev[0]);
1966+}
1967+
1968+#ifdef FEC_2
1969+/************************************************************************
1970+* NAME: fec_interrupt_rx_handler_fec1
1971+*
1972+* DESCRIPTION: This is the DMA interrupt handler using for the FEC1
1973+* reception.
1974+*
1975+*************************************************************************/
1976+void fec_interrupt_fec_rx_handler_fec1(void)
1977+{
1978+ fec_interrupt_fec_rx_handler(fec_dev[1]);
1979+}
1980+
1981+#endif
1982+
1983+#ifndef MODULE
1984+/************************************************************************
1985+* NAME: fec_mac_setup0
1986+*
1987+* DESCRIPTION: This function sets the MAC address of FEC0 from command line
1988+*
1989+*************************************************************************/
1990+int __init fec_mac_setup0(char *s)
1991+{
1992+ if (!s || !*s)
1993+ return 1;
1994+
1995+ if (fec_str_to_mac(s, fec_mac_addr_fec0))
1996+ printk(KERN_ERR "The MAC address of FEC0 "
1997+ "cannot be set from command line");
1998+ return 1;
1999+}
2000+
2001+#ifdef FEC_2
2002+
2003+/************************************************************************
2004+* NAME: fec_mac_setup1
2005+*
2006+* DESCRIPTION: This function sets the MAC address of FEC1 from command line
2007+*
2008+*************************************************************************/
2009+int __init fec_mac_setup1(char *s)
2010+{
2011+ if (!s || !*s)
2012+ return 1;
2013+
2014+ if (fec_str_to_mac(s, fec_mac_addr_fec1))
2015+ printk(KERN_ERR "The MAC address of FEC1 "
2016+ "cannot be set from command line\n");
2017+ return 1;
2018+}
2019+#endif
2020+
2021+/************************************************************************
2022+* NAME: fec_str_to_mac
2023+*
2024+* DESCRIPTION: This function interprets the character string into MAC addr
2025+*
2026+*************************************************************************/
2027+int fec_str_to_mac(char *str_mac, unsigned char* addr)
2028+{
2029+ unsigned long val;
2030+ char c;
2031+ unsigned long octet[6], *octetptr = octet;
2032+ int i;
2033+
2034+again:
2035+ val = 0;
2036+ while ((c = *str_mac) != '\0') {
2037+ if ((c >= '0') && (c <= '9')) {
2038+ val = (val * 16) + (c - '0');
2039+ str_mac++;
2040+ continue;
2041+ } else if (((c >= 'a') && (c <= 'f'))
2042+ || ((c >= 'A') && (c <= 'F'))) {
2043+ val = (val << 4) +
2044+ (c + 10 -
2045+ (((c >= 'a') && (c <= 'f')) ? 'a' : 'A'));
2046+ str_mac++;
2047+ continue;
2048+ }
2049+ break;
2050+ }
2051+ if (*str_mac == ':') {
2052+ *octetptr++ = val, str_mac++;
2053+ if (octetptr >= octet + 6)
2054+ return 1;
2055+ goto again;
2056+ }
2057+
2058+ /* Check for trailing characters */
2059+ if (*str_mac && !(*str_mac == ' '))
2060+ return 1;
2061+
2062+ *octetptr++ = val;
2063+
2064+ if ((octetptr - octet) == 6) {
2065+ for (i = 0; i <= 6; i++)
2066+ addr[i] = octet[i];
2067+ } else
2068+ return 1;
2069+
2070+ return 0;
2071+}
2072+#endif
2073--- /dev/null
2074+++ b/drivers/net/fec_m547x.h
2075@@ -0,0 +1,241 @@
2076+#ifndef FEC_M547X_H
2077+#define FEC_M547X_H
2078+/*
2079+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
2080+ *
2081+ * This program is free software; you can redistribute it and/or modify
2082+ * it under the terms of the GNU General Public License as published by
2083+ * the Free Software Foundation; either version 2 of the License, or
2084+ * (at your option) any later version.
2085+ */
2086+
2087+#define FEC_BASE_ADDR_FEC0 ((unsigned int)MCF_MBAR + 0x9000)
2088+#define FEC_BASE_ADDR_FEC1 ((unsigned int)MCF_MBAR + 0x9800)
2089+
2090+#define FEC_FECI2CIRQ (0xFFC0)
2091+#define FEC_GPIO_PAR_FECI2CIRQ \
2092+ (*(volatile unsigned short *)((unsigned int)MCF_MBAR + 0xA44))
2093+
2094+#define FEC_ECR_DISABLE (0x00000000)
2095+
2096+#define FEC_ECR(x) \
2097+ (*(volatile unsigned int *)(x + 0x024))
2098+#define FEC_EIR(x) \
2099+ (*(volatile unsigned int *)(x + 0x004))
2100+#define FEC_PALR(x) \
2101+ (*(volatile unsigned int *)(x + 0x0E4))
2102+#define FEC_PAUR(x) \
2103+ (*(volatile unsigned int *)(x + 0x0E8))
2104+#define FEC_IALR(x) \
2105+ (*(volatile unsigned int *)(x + 0x11C))
2106+#define FEC_IAUR(x) \
2107+ (*(volatile unsigned int *)(x + 0x118))
2108+#define FEC_GALR(x) \
2109+ (*(volatile unsigned int *)(x + 0x124))
2110+#define FEC_GAUR(x) \
2111+ (*(volatile unsigned int *)(x + 0x120))
2112+#define FEC_RCR(x) \
2113+ (*(volatile unsigned int *)(x + 0x084))
2114+#define FEC_FECRFCR(x) \
2115+ (*(volatile unsigned int *)(x + 0x18C))
2116+#define FEC_FECRFAR(x) \
2117+ (*(volatile unsigned int *)(x + 0x198))
2118+#define FEC_FECTFCR(x) \
2119+ (*(volatile unsigned int *)(x + 0x1AC))
2120+#define FEC_FECTFAR(x) \
2121+ (*(volatile unsigned int *)(x + 0x1B8))
2122+#define FEC_FECTFWR(x) \
2123+ (*(volatile unsigned int *)(x + 0x144))
2124+#define FEC_CTCWR(x) \
2125+ (*(volatile unsigned int *)(x + 0x1C8))
2126+#define FEC_EIMR(x) \
2127+ (*(volatile unsigned int *)(x + 0x008))
2128+#define FEC_TCR(x) \
2129+ (*(volatile unsigned int *)(x + 0x0C4))
2130+#define FEC_MIBC(x) \
2131+ (*(volatile unsigned int *)(x + 0x064))
2132+#define FEC_MSCR(x) \
2133+ (*(volatile unsigned int *)(x + 0x044))
2134+#define FEC_FECTFDR(x) \
2135+ (*(volatile unsigned int *)(x + 0x1A4))
2136+#define FEC_FECRFDR(x) \
2137+ (*(volatile unsigned int *)(x + 0x184))
2138+#define FEC_FECTFSR(x) \
2139+ (*(volatile unsigned int *)(x + 0x1A8))
2140+#define FEC_FECRFSR(x) \
2141+ (*(volatile unsigned int *)(x + 0x188))
2142+#define FECSTAT_RMON_R_PACKETS(x) \
2143+ (*(volatile unsigned int *)(x + 0x284))
2144+#define FECSTAT_RMON_T_PACKETS(x) \
2145+ (*(volatile unsigned int *)(x + 0x204))
2146+#define FECSTAT_RMON_R_OCTETS(x) \
2147+ (*(volatile unsigned int *)(x + 0x2C4))
2148+#define FECSTAT_RMON_T_OCTETS(x) \
2149+ (*(volatile unsigned int *)(x + 0x244))
2150+#define FECSTAT_RMON_R_UNDERSIZE(x) \
2151+ (*(volatile unsigned int *)(x + 0x294))
2152+#define FECSTAT_RMON_R_OVERSIZE(x) \
2153+ (*(volatile unsigned int *)(x + 0x298))
2154+#define FECSTAT_RMON_R_FRAG(x) \
2155+ (*(volatile unsigned int *)(x + 0x29C))
2156+#define FECSTAT_RMON_R_JAB(x) \
2157+ (*(volatile unsigned int *)(x + 0x2A0))
2158+#define FECSTAT_RMON_R_MC_PKT(x) \
2159+ (*(volatile unsigned int *)(x + 0x28C))
2160+#define FECSTAT_RMON_T_COL(x) \
2161+ (*(volatile unsigned int *)(x + 0x224))
2162+#define FECSTAT_IEEE_R_ALIGN(x) \
2163+ (*(volatile unsigned int *)(x + 0x2D4))
2164+#define FECSTAT_IEEE_R_CRC(x) \
2165+ (*(volatile unsigned int *)(x + 0x2D0))
2166+#define FECSTAT_IEEE_R_MACERR(x) \
2167+ (*(volatile unsigned int *)(x + 0x2D8))
2168+#define FECSTAT_IEEE_T_CSERR(x) \
2169+ (*(volatile unsigned int *)(x + 0x268))
2170+#define FECSTAT_IEEE_T_MACERR(x) \
2171+ (*(volatile unsigned int *)(x + 0x264))
2172+#define FECSTAT_IEEE_T_LCOL(x) \
2173+ (*(volatile unsigned int *)(x + 0x25C))
2174+#define FECSTAT_IEEE_R_OCTETS_OK(x) \
2175+ (*(volatile unsigned int *)(x + 0x2E0))
2176+#define FECSTAT_IEEE_T_OCTETS_OK(x) \
2177+ (*(volatile unsigned int *)(x + 0x274))
2178+#define FECSTAT_IEEE_R_DROP(x) \
2179+ (*(volatile unsigned int *)(x + 0x2C8))
2180+#define FECSTAT_IEEE_T_DROP(x) \
2181+ (*(volatile unsigned int *)(x + 0x248))
2182+#define FECSTAT_IEEE_R_FRAME_OK(x) \
2183+ (*(volatile unsigned int *)(x + 0x2CC))
2184+#define FECSTAT_IEEE_T_FRAME_OK(x) \
2185+ (*(volatile unsigned int *)(x + 0x24C))
2186+#define FEC_MMFR(x) \
2187+ (*(volatile unsigned int *)(x + 0x040))
2188+#define FEC_FECFRST(x) \
2189+ (*(volatile unsigned int *)(x + 0x1C4))
2190+
2191+#define FEC_MAX_FRM_SIZE (1518)
2192+#define FEC_MAXBUF_SIZE (1520)
2193+
2194+/* Register values */
2195+#define FEC_ECR_RESET (0x00000001)
2196+#define FEC_EIR_CLEAR (0xFFFFFFFF)
2197+#define FEC_EIR_RL (0x00100000)
2198+#define FEC_EIR_HBERR (0x80000000)
2199+#define FEC_EIR_BABR (0x40000000)
2200+/* babbling receive error */
2201+#define FEC_EIR_BABT (0x20000000)
2202+/* babbling transmit error */
2203+#define FEC_EIR_TXF (0x08000000)
2204+/* transmit frame interrupt */
2205+#define FEC_EIR_MII (0x00800000)
2206+/* MII interrupt */
2207+#define FEC_EIR_LC (0x00200000)
2208+/* late collision */
2209+#define FEC_EIR_XFUN (0x00080000)
2210+/* transmit FIFO underrun */
2211+#define FEC_EIR_XFERR (0x00040000)
2212+/* transmit FIFO error */
2213+#define FEC_EIR_RFERR (0x00020000)
2214+/* receive FIFO error */
2215+#define FEC_RCR_MAX_FRM_SIZE (FEC_MAX_FRM_SIZE << 16)
2216+#define FEC_RCR_MII (0x00000004)
2217+#define FEC_FECRFCR_FAE (0x00400000)
2218+/* frame accept error */
2219+#define FEC_FECRFCR_RXW (0x00200000)
2220+/* receive wait condition */
2221+#define FEC_FECRFCR_UF (0x00100000)
2222+/* receive FIFO underflow */
2223+#define FEC_FECRFCR_FRM (0x08000000)
2224+#define FEC_FECRFCR_GR (0x7 << 24)
2225+
2226+#define FEC_EIMR_DISABLE (0x00000000)
2227+
2228+#define FEC_FECRFAR_ALARM (0x300)
2229+#define FEC_FECTFCR_FRM (0x08000000)
2230+#define FEC_FECTFCR_GR (0x7 << 24)
2231+#define FEC_FECTFCR_FAE (0x00400000)
2232+/* frame accept error */
2233+#define FEC_FECTFCR_TXW (0x00040000)
2234+/* transmit wait condition */
2235+#define FEC_FECTFCR_UF (0x00100000)
2236+/* transmit FIFO underflow */
2237+#define FEC_FECTFCR_OF (0x00080000)
2238+/* transmit FIFO overflow */
2239+
2240+#define FEC_FECTFAR_ALARM (0x100)
2241+#define FEC_FECTFWR_XWMRK (0x00000000)
2242+
2243+#define FEC_FECTFSR_MSK (0xC0B00000)
2244+#define FEC_FECTFSR_TXW (0x40000000)
2245+/* transmit wait condition */
2246+#define FEC_FECTFSR_FAE (0x00800000)
2247+/* frame accept error */
2248+#define FEC_FECTFSR_UF (0x00200000)
2249+/* transmit FIFO underflow */
2250+#define FEC_FECTFSR_OF (0x00100000)
2251+/* transmit FIFO overflow */
2252+
2253+#define FEC_FECRFSR_MSK (0x80F00000)
2254+#define FEC_FECRFSR_FAE (0x00800000)
2255+/* frame accept error */
2256+#define FEC_FECRFSR_RXW (0x00400000)
2257+/* receive wait condition */
2258+#define FEC_FECRFSR_UF (0x00200000)
2259+/* receive FIFO underflow */
2260+
2261+#define FEC_CTCWR_TFCW_CRC (0x03000000)
2262+#define FEC_TCR_FDEN (0x00000004)
2263+#define FEC_TCR_HBC (0x00000002)
2264+#define FEC_RCR_DRT (0x00000002)
2265+#define FEC_EIMR_MASK (FEC_EIR_RL | FEC_EIR_HBERR)
2266+#define FEC_ECR_ETHEREN (0x00000002)
2267+#define FEC_FECTFCR_MSK (0x00FC0000)
2268+#define FEC_FECRFCR_MSK (0x00F80000)
2269+#define FEC_EIR_GRA (0x10000000)
2270+#define FEC_TCR_GTS (0x00000001)
2271+#define FEC_MIBC_ENABLE (0x00000000)
2272+#define FEC_MIB_LEN (228)
2273+#define FEC_PHY_ADDR (0x01)
2274+
2275+#define FEC_RX_DMA_PRI (6)
2276+#define FEC_TX_DMA_PRI (6)
2277+
2278+#define FEC_TX_BUF_NUMBER (8)
2279+#define FEC_RX_BUF_NUMBER (64)
2280+
2281+#define FEC_TX_INDEX_MASK (0x7)
2282+#define FEC_RX_INDEX_MASK (0x3f)
2283+
2284+#define FEC_RX_DESC_FEC0 SYS_SRAM_FEC_START
2285+#define FEC_TX_DESC_FEC0 \
2286+ (FEC_RX_DESC_FEC0 + FEC_RX_BUF_NUMBER * sizeof(MCD_bufDescFec))
2287+
2288+#define FEC_RX_DESC_FEC1 \
2289+ (SYS_SRAM_FEC_START + SYS_SRAM_FEC_SIZE/2)
2290+#define FEC_TX_DESC_FEC1 \
2291+ (FEC_RX_DESC_FEC1 + FEC_RX_BUF_NUMBER * sizeof(MCD_bufDescFec))
2292+
2293+#define FEC_EIR_MII (0x00800000)
2294+#define FEC_MMFR_READ (0x60020000)
2295+#define FEC_MMFR_WRITE (0x50020000)
2296+
2297+#define FEC_FLAGS_RX (0x00000001)
2298+
2299+#define FEC_CRCPOL (0xEDB88320)
2300+
2301+#define FEC_MII_TIMEOUT (2)
2302+#define FEC_GR_TIMEOUT (1)
2303+#define FEC_TX_TIMEOUT (1)
2304+#define FEC_RX_TIMEOUT (1)
2305+
2306+#define FEC_SW_RST 0x2000000
2307+#define FEC_RST_CTL 0x1000000
2308+
2309+int fec_read_mii(unsigned int base_addr, unsigned int pa, unsigned int ra,
2310+ unsigned int *data);
2311+int fec_write_mii(unsigned int base_addr, unsigned int pa, unsigned int ra,
2312+ unsigned int data);
2313+
2314+#define FEC_MII_SPEED \
2315+ ((MCF_CLK / 2) / ((2500000 / 2) * 2))
2316+#endif
2317--- a/drivers/net/phy/Kconfig
2318+++ b/drivers/net/phy/Kconfig
2319@@ -62,6 +62,11 @@ config BROADCOM_PHY
2320       Currently supports the BCM5411, BCM5421, BCM5461, BCM5464, BCM5481
2321       and BCM5482 PHYs.
2322 
2323+config BROADCOM5222_PHY
2324+ tristate "Drivers for Broadcom5222 PHY"
2325+ ---help---
2326+ Currently supports the BCM5222 PHYs.
2327+
2328 config BCM63XX_PHY
2329     tristate "Drivers for Broadcom 63xx SOCs internal PHY"
2330     ---help---
2331@@ -82,6 +87,16 @@ config NATIONAL_PHY
2332     ---help---
2333       Currently supports the DP83865 PHY.
2334 
2335+config NATIONAL8364x_PHY
2336+ tristate "Drivers for National Semiconductor dp83640 PHYs"
2337+ ---help---
2338+ Currently supports the DP83640 PHY.
2339+
2340+config NATIONAL8384x_PHY
2341+ tristate "Drivers for National Semiconductor dp83848 dp83849 PHYs"
2342+ ---help---
2343+ Currently supports the DP83848 PHY.
2344+
2345 config STE10XP
2346     depends on PHYLIB
2347     tristate "Driver for STMicroelectronics STe10Xp PHYs"
2348--- a/drivers/net/phy/Makefile
2349+++ b/drivers/net/phy/Makefile
2350@@ -12,6 +12,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
2351 obj-$(CONFIG_SMSC_PHY) += smsc.o
2352 obj-$(CONFIG_VITESSE_PHY) += vitesse.o
2353 obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
2354+obj-$(CONFIG_BROADCOM5222_PHY) += broadcom522x.o
2355 obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
2356 obj-$(CONFIG_ICPLUS_PHY) += icplus.o
2357 obj-$(CONFIG_ADM6996_PHY) += adm6996.o
2358@@ -28,6 +29,8 @@ obj-$(CONFIG_FIXED_PHY) += fixed.o
2359 obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
2360 obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
2361 obj-$(CONFIG_NATIONAL_PHY) += national.o
2362+obj-$(CONFIG_NATIONAL8364x_PHY) +=national836x.o
2363+obj-$(CONFIG_NATIONAL8384x_PHY) +=national8384x.o
2364 obj-$(CONFIG_STE10XP) += ste10Xp.o
2365 obj-$(CONFIG_MICREL_PHY) += micrel.o
2366 obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
2367--- /dev/null
2368+++ b/drivers/net/phy/broadcom522x.c
2369@@ -0,0 +1,170 @@
2370+/*
2371+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
2372+ * Chenghu Wu <b16972@freescale.com>
2373+ *
2374+ * Driver for broadcom PHYs 522x
2375+ *
2376+ * This program is free software; you can redistribute it and/or modify it
2377+ * under the terms of the GNU General Public License as published by the
2378+ * Free Software Foundation; either version 2 of the License, or (at your
2379+ * option) any later version.
2380+ *
2381+ */
2382+
2383+#include <linux/kernel.h>
2384+#include <linux/module.h>
2385+#include <linux/mii.h>
2386+#include <linux/ethtool.h>
2387+#include <linux/phy.h>
2388+#include <linux/netdevice.h>
2389+
2390+/* DP83865 phy identifier values */
2391+#define BCM5222_PHY_ID 0x00406320
2392+
2393+/* PHY Register */
2394+#define BCM5222_TIMEOUT 0x100
2395+
2396+/* MII Registers */
2397+#define BCM5222_CTRL 0x00
2398+#define BCM5222_STATUS 0x01
2399+#define BCM5222_ID_HIGH 0x02
2400+#define BCM5222_ID_LOW 0x03
2401+#define BCM5222_AN_ADV 0x04
2402+#define BCM5222_AN_LP 0x05
2403+#define BCM5222_AN_EXP 0x06
2404+#define BCM5222_AN_NEXTPG 0x07
2405+#define BCM5222_AN_LP_NPTX 0x08
2406+#define BCM5222_AUX_CS 0x18
2407+#define BCM5222_AUX_STATUS 0x19
2408+
2409+/* CONTROL Bits */
2410+#define BCM5222_CTRL_RESET 0x8000
2411+#define BCM5222_CTRL_LOOPBACK 0x4000
2412+#define BCM5222_CTRL_FORCE 0x2000
2413+#define BCM5222_CTRL_AUTOEN 0x1000
2414+#define BCM5222_CTRL_PWRDN 0x0800
2415+#define BCM5222_CTRL_ISOLATE 0x0400
2416+#define BCM5222_CTRL_RESTART 0x0200
2417+#define BCM5222_CTRL_DUPLEX 0x0100
2418+#define BCM5222_CTRL_COLLEN 0x0080
2419+
2420+/* STATUS Bits */
2421+#define BCM5222_STATUS_100T4 0x8000
2422+#define BCM5222_STATUS_100TXFDX 0x4000
2423+#define BCM5222_STATUS_100TX 0x2000
2424+#define BCM5222_STATUS_10FDX 0x1000
2425+#define BCM5222_STATUS_10 0x0800
2426+#define BCM5222_STATUS_MF_PREAMBLE 0x0040
2427+#define BCM5222_STATUS_AN_COMPLETE 0x0020
2428+#define BCM5222_STATUS_REMOTE_FAULT 0x0010
2429+#define BCM5222_STATUS_AN_CAPABLE 0x0008
2430+#define BCM5222_STATUS_LINK 0x0004
2431+#define BCM5222_STATUS_JABBER 0x0002
2432+#define BCM5222_STATUS_EXT_CAP 0x0001
2433+
2434+/* ID Values */
2435+#define BCM5222_ID_HIGH_VAL 0x0040
2436+#define BCM5222_ID_LOW_VAL 0x6320
2437+
2438+/* Advertise Bits */
2439+#define BCM5222_AN_ADV_NEXTPG 0x8000
2440+#define BCM5222_AN_ADV_REMOTE_FAULT 0x2000
2441+#define BCM5222_AN_ADV_PAUSE 0x0400
2442+#define BCM5222_AN_ADV_100T4 0x0200
2443+#define BCM5222_AN_ADV_100TXFDX 0x0100
2444+#define BCM5222_AN_ADV_100TX 0x0080
2445+#define BCM5222_AN_ADV_10FDX 0x0040
2446+#define BCM5222_AN_ADV_10 0x0020
2447+#define BCM5222_AN_ADV_8023 0x0001
2448+#define BCM5222_AN_ADV_ALL \
2449+ (BCM5222_AN_ADV_100TXFDX | \
2450+ BCM5222_AN_ADV_100TXFDX | \
2451+ BCM5222_AN_ADV_100TX | \
2452+ BCM5222_AN_ADV_10FDX | \
2453+ BCM5222_AN_ADV_10 | \
2454+ BCM5222_AN_ADV_8023)
2455+
2456+/* AUX CTRL/STATUS Bits */
2457+#define BCM5222_AUX_CS_JABBER_DIS 0x8000
2458+#define BCM5222_AUX_CS_FORCE_LINK 0x4000
2459+#define BCM5222_AUX_CS_10M_TX_PWR 0x0100
2460+#define BCM5222_AUX_CS_HSQ_LSQ_MASK 0x00c0
2461+#define BCM5222_AUX_CS_EDGE_RATE_MASK 0x0030
2462+#define BCM5222_AUX_CS_AN_IND 0x0008
2463+#define BCM5222_AUX_CS_SPEED_FORCE 0x0004
2464+#define BCM5222_AUX_CS_SPEED 0x0002
2465+#define BCM5222_AUX_CS_DUPLEX 0x0001
2466+
2467+/* AUX STATUS Bits */
2468+#define BCM5222_AUX_STATUS_AN_COMP 0x8000
2469+#define BCM5222_AUX_STATUS_AN_COMPACK 0x4000
2470+#define BCM5222_AUX_STATUS_AN_ACKDET 0x2000
2471+#define BCM5222_AUX_STATUS_AN_ABDET 0x1000
2472+#define BCM5222_AUX_STATUS_AN_PAUSE 0x0800
2473+#define BCM5222_AUX_STATUS_AN_HCDMASK 0x0700
2474+#define BCM5222_AUX_STATUS_AN_PDFAULT 0x0080
2475+#define BCM5222_AUX_STATUS_LP_RMTFAULT 0x0040
2476+#define BCM5222_AUX_STATUS_LP_PGRX 0x0020
2477+#define BCM5222_AUX_STATUS_LP_NEGABLE 0x0010
2478+#define BCM5222_AUX_STATUS_SPEED 0x0008
2479+#define BCM5222_AUX_STATUS_LINK 0x0004
2480+#define BCM5222_AUX_STATUS_AN_EN 0x0002
2481+#define BCM5222_AUX_STATUS_JABBER 0x0001
2482+
2483+static int bcm5222_config_intr(struct phy_device *phydev)
2484+{
2485+ int err = 0;
2486+ printk(KERN_INFO "%s PHY_INTERRUPT %x\n",
2487+ __func__, phydev->interrupts);
2488+
2489+ return err;
2490+}
2491+
2492+static int bcm5222_ack_interrupt(struct phy_device *phydev)
2493+{
2494+ return 0;
2495+}
2496+
2497+static int bcm5222_config_init(struct phy_device *phydev)
2498+{
2499+ return bcm5222_ack_interrupt(phydev);
2500+}
2501+
2502+static struct phy_driver bcm5222_driver = {
2503+ .phy_id = BCM5222_PHY_ID,
2504+ .phy_id_mask = 0xfffffff0,
2505+ .name = "Broadcom BCM5222",
2506+ .features = PHY_BASIC_FEATURES,
2507+ .flags = PHY_HAS_INTERRUPT,
2508+ .config_init = bcm5222_config_init,
2509+ .config_aneg = genphy_config_aneg,
2510+ .read_status = genphy_read_status,
2511+ .ack_interrupt = bcm5222_ack_interrupt,
2512+ .config_intr = bcm5222_config_intr,
2513+ .driver = {.owner = THIS_MODULE,}
2514+};
2515+
2516+static int __init bcm5222_init(void)
2517+{
2518+ int ret;
2519+
2520+ ret = phy_driver_register(&bcm5222_driver);
2521+ if (ret)
2522+ goto err1;
2523+
2524+ return 0;
2525+err1:
2526+ printk(KERN_INFO "register bcm5222 PHY driver fail\n");
2527+ return ret;
2528+}
2529+
2530+static void __exit bcm5222_exit(void)
2531+{
2532+ phy_driver_unregister(&bcm5222_driver);
2533+}
2534+
2535+MODULE_DESCRIPTION("Broadcom PHY driver");
2536+MODULE_LICENSE("GPL v2");
2537+
2538+module_init(bcm5222_init);
2539+module_exit(bcm5222_exit);
2540--- /dev/null
2541+++ b/drivers/net/phy/national836x.c
2542@@ -0,0 +1,104 @@
2543+/*
2544+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
2545+ * Chenghu Wu <b16972@freescale.com>
2546+ *
2547+ * Driver for National Semiconductor PHYs 83640
2548+ *
2549+ * This program is free software; you can redistribute it and/or modify it
2550+ * under the terms of the GNU General Public License as published by the
2551+ * Free Software Foundation; either version 2 of the License, or (at your
2552+ * option) any later version.
2553+ *
2554+ */
2555+
2556+#include <linux/kernel.h>
2557+#include <linux/module.h>
2558+#include <linux/mii.h>
2559+#include <linux/ethtool.h>
2560+#include <linux/phy.h>
2561+#include <linux/netdevice.h>
2562+
2563+/* DP83640 phy identifier values */
2564+#define DP83640_PHY_ID 0x20005ce0
2565+
2566+/* PHY Status Register */
2567+#define MII_DP83640_PHYSTST 16
2568+/* Interrupt Control Register */
2569+#define MII_DP83640_ICR 17
2570+/* Interrupt Status and Interrupt EVEN Enable Register */
2571+#define MII_DP83640_ISR 18
2572+
2573+#define MII_DP83640_ICR_IRQEVEN_EN 0x0001
2574+#define MII_DP83640_ICR_IRQOUTPUT_EN 0x0002
2575+#define MII_DP83640_ISR_ENERGY_EVEN 0x0040
2576+#define MII_DP83640_ISR_LINKSTATUS_EVEN 0x0020
2577+
2578+static int ns_config_intr(struct phy_device *phydev)
2579+{
2580+ int err;
2581+
2582+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
2583+ err = phy_write(phydev, MII_DP83640_ICR,
2584+ MII_DP83640_ICR_IRQEVEN_EN |
2585+ MII_DP83640_ICR_IRQOUTPUT_EN);
2586+ err = phy_write(phydev, MII_DP83640_ICR,
2587+ MII_DP83640_ISR_ENERGY_EVEN |
2588+ MII_DP83640_ISR_LINKSTATUS_EVEN);
2589+ } else {
2590+ err = phy_write(phydev, MII_DP83640_ICR, 0);
2591+ }
2592+ return err;
2593+}
2594+
2595+static int ns83640_ack_interrupt(struct phy_device *phydev)
2596+{
2597+ int ret = phy_read(phydev, MII_DP83640_ISR);
2598+ if (ret < 0) {
2599+ printk(KERN_INFO "%s MII_DP83640_ISR %x\n",
2600+ __func__, ret);
2601+ return ret;
2602+ }
2603+ return 0;
2604+}
2605+
2606+static int ns83640_config_init(struct phy_device *phydev)
2607+{
2608+ int ret = phy_read(phydev, MII_DP83640_PHYSTST);
2609+ if (ret < 0) {
2610+ printk(KERN_INFO "%s MII_DP83640_ISR %x\n",
2611+ __func__, ret);
2612+ }
2613+
2614+ return ns83640_ack_interrupt(phydev);
2615+}
2616+
2617+static struct phy_driver dp83640_driver = {
2618+ .phy_id = DP83640_PHY_ID,
2619+ .phy_id_mask = 0xfffffff0,
2620+ .name = "NatSemi DP83640",
2621+ .features = PHY_BASIC_FEATURES,
2622+ .flags = PHY_HAS_INTERRUPT,
2623+ .config_init = ns83640_config_init,
2624+ .config_aneg = genphy_config_aneg,
2625+ .read_status = genphy_read_status,
2626+ .ack_interrupt = ns83640_ack_interrupt,
2627+ .config_intr = ns_config_intr,
2628+ .driver = {.owner = THIS_MODULE,}
2629+};
2630+
2631+static int __init ns83640_init(void)
2632+{
2633+ return phy_driver_register(&dp83640_driver);
2634+}
2635+
2636+static void __exit ns83640_exit(void)
2637+{
2638+ phy_driver_unregister(&dp83640_driver);
2639+}
2640+
2641+MODULE_DESCRIPTION("NatSemi PHY driver");
2642+MODULE_AUTHOR("Chenghu Wu <b16972@freescale.com>");
2643+MODULE_LICENSE("GPL v2");
2644+
2645+module_init(ns83640_init);
2646+module_exit(ns83640_exit);
2647--- /dev/null
2648+++ b/drivers/net/phy/national8384x.c
2649@@ -0,0 +1,110 @@
2650+/*
2651+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
2652+ * Chenghu Wu <b16972@freescale.com>
2653+ *
2654+ * Driver for National Semiconductor PHYs 8384x
2655+ *
2656+ * This program is free software; you can redistribute it and/or modify it
2657+ * under the terms of the GNU General Public License as published by the
2658+ * Free Software Foundation; either version 2 of the License, or (at your
2659+ * option) any later version.
2660+ *
2661+ */
2662+
2663+#include <linux/kernel.h>
2664+#include <linux/module.h>
2665+#include <linux/mii.h>
2666+#include <linux/ethtool.h>
2667+#include <linux/phy.h>
2668+#include <linux/netdevice.h>
2669+
2670+/* DP8384x phy identifier values */
2671+#define DP83848_PHY_ID 0x20005c90
2672+#define DP83849_PHY_ID 0x20005ca0
2673+/* PHY Status Register */
2674+#define MII_DP8384X_PHYSTST 16
2675+
2676+static int ns8384x_config_intr(struct phy_device *phydev)
2677+{
2678+ int err = 0;
2679+
2680+ return err;
2681+}
2682+
2683+static int ns8384x_ack_interrupt(struct phy_device *phydev)
2684+{
2685+ return 0;
2686+}
2687+
2688+static int ns8384x_config_init(struct phy_device *phydev)
2689+{
2690+ int ret = phy_read(phydev, MII_DP8384X_PHYSTST);
2691+ if (ret < 0) {
2692+ printk(KERN_INFO "%s MII_DP83640_ISR %x\n",
2693+ __func__, ret);
2694+ }
2695+
2696+ return ns8384x_ack_interrupt(phydev);
2697+}
2698+
2699+static struct phy_driver dp83848_driver = {
2700+ .phy_id = DP83848_PHY_ID,
2701+ .phy_id_mask = 0xfffffff0,
2702+ .name = "NatSemi DP83848",
2703+ .features = PHY_BASIC_FEATURES,
2704+ .flags = PHY_HAS_INTERRUPT,
2705+ .config_init = ns8384x_config_init,
2706+ .config_aneg = genphy_config_aneg,
2707+ .read_status = genphy_read_status,
2708+ .ack_interrupt = ns8384x_ack_interrupt,
2709+ .config_intr = ns8384x_config_intr,
2710+ .driver = {.owner = THIS_MODULE,}
2711+};
2712+
2713+static struct phy_driver dp83849_driver = {
2714+ .phy_id = DP83849_PHY_ID,
2715+ .phy_id_mask = 0xfffffff0,
2716+ .name = "NatSemi DP83849",
2717+ .features = PHY_BASIC_FEATURES,
2718+ .flags = PHY_HAS_INTERRUPT,
2719+ .config_init = ns8384x_config_init,
2720+ .config_aneg = genphy_config_aneg,
2721+ .read_status = genphy_read_status,
2722+ .ack_interrupt = ns8384x_ack_interrupt,
2723+ .config_intr = ns8384x_config_intr,
2724+ .driver = {.owner = THIS_MODULE,}
2725+};
2726+
2727+static int __init ns8384x_init(void)
2728+{
2729+ int ret;
2730+
2731+ ret = phy_driver_register(&dp83848_driver);
2732+ if (ret)
2733+ goto err1;
2734+
2735+ ret = phy_driver_register(&dp83849_driver);
2736+ if (ret)
2737+ goto err2;
2738+
2739+ return 0;
2740+err2:
2741+ printk(KERN_INFO "register dp83849 PHY driver fail\n");
2742+ phy_driver_unregister(&dp83848_driver);
2743+err1:
2744+ printk(KERN_INFO "register dp83848 PHY driver fail\n");
2745+ return ret;
2746+}
2747+
2748+static void __exit ns8384x_exit(void)
2749+{
2750+ phy_driver_unregister(&dp83848_driver);
2751+ phy_driver_unregister(&dp83849_driver);
2752+}
2753+
2754+MODULE_DESCRIPTION("NatSemi PHY driver");
2755+MODULE_AUTHOR("Chenghu Wu <b16972@freescale.com>");
2756+MODULE_LICENSE("GPL v2");
2757+
2758+module_init(ns8384x_init);
2759+module_exit(ns8384x_exit);
2760

Archive Download this file



interactive