1 From 9be336132025e7670790cdc9c24a81c23e893484 Mon Sep 17 00:00:00 2001
2 From: Alison Wang <b18965@freescale.com>
3 Date: Thu, 4 Aug 2011 09:59:40 +0800
4 Subject: [PATCH 06/52] Add FEC driver support for MCF5445x/MCF5441x/MCF547x/MCF548x
6 Add FEC driver support for MCF5445x/MCF5441x/MCF547x/MCF548x.
8 Signed-off-by: Alison Wang <b18965@freescale.com>
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
33 +++ b/arch/m68k/coldfire/m5441x/fec.c
36 + * fec.c on m5441x platform
38 + * Sub-architcture dependant initialization code for the Freescale
41 + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
42 + * ShrekWu B16972@freescale.com
43 + * Alison Wang b18965@freescale.com
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.
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.
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
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>
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>
82 +static struct resource fec0_resources[] = {
84 + .start = MCF_MBAR + 0xfc0d4000,
85 + .end = MCF_MBAR + 0xfc0d42ff,
86 + .flags = IORESOURCE_MEM,
91 + .flags = IORESOURCE_IRQ,
96 + .flags = IORESOURCE_IRQ,
101 + .flags = IORESOURCE_IRQ,
105 +#if defined(CONFIG_FEC2)
106 +static struct resource fec1_resources[] = {
108 + .start = MCF_MBAR + 0xfc0d8000,
109 + .end = MCF_MBAR + 0xfc0d82ff,
110 + .flags = IORESOURCE_MEM,
113 + .start = (64 + 13 + 36),
114 + .end = (64 + 13 + 36),
115 + .flags = IORESOURCE_IRQ,
118 + .start = (64 + 13 + 40),
119 + .end = (64 + 13 + 40),
120 + .flags = IORESOURCE_IRQ,
123 + .start = (64 + 13 + 42),
124 + .end = (64 + 13 + 42),
125 + .flags = IORESOURCE_IRQ,
130 +static struct fec_platform_data m54418_fec_pdata = {
131 + .phy = PHY_INTERFACE_MODE_RMII,
134 +static struct platform_device fec0_coldfire_device = {
135 + .name = "m54418-fec",
137 + .resource = fec0_resources,
138 + .num_resources = ARRAY_SIZE(fec0_resources),
140 + .platform_data = &m54418_fec_pdata,
144 +#if defined(CONFIG_FEC2)
145 +static struct platform_device fec1_coldfire_device = {
146 + .name = "m54418-fec",
148 + .resource = fec1_resources,
149 + .num_resources = ARRAY_SIZE(fec1_resources),
151 + .platform_data = &m54418_fec_pdata,
156 +static struct platform_device *fec_device[] = {
157 + &fec0_coldfire_device,
158 +#if defined(CONFIG_FEC2)
159 + &fec1_coldfire_device,
163 +static int __init mcf5441x_fec_dev_init(void)
168 + (MCF_GPIO_PAR_FEC &
169 + MCF_GPIO_PAR_FEC_FEC_MASK) |
170 + MCF_GPIO_PAR_FEC_FEC_RMII0FUL_ULPI;
172 + MCF_GPIO_SRCR_FEC = 0x0C;
174 +#if defined(CONFIG_FEC2)
176 + (MCF_GPIO_PAR_FEC &
177 + MCF_GPIO_PAR_FEC_FEC_MASK) |
178 + MCF_GPIO_PAR_FEC_FEC_RMII0FUL_1FUL;
180 + MCF_GPIO_SRCR_FEC |= 0x03;
182 + MCF_GPIO_PAR_SIMP0H =
183 + (MCF_GPIO_PAR_SIMP0H &
184 + MCF_GPIO_PAR_SIMP0H_DAT_MASK) |
185 + MCF_GPIO_PAR_SIMP0H_DAT_GPIO;
189 + MCF_GPIO_PDDR_G4_MASK) |
190 + MCF_GPIO_PDDR_G4_OUTPUT;
194 + MCF_GPIO_PODR_G4_MASK);
197 + retval = platform_add_devices(fec_device, ARRAY_SIZE(fec_device));
199 + printk(KERN_ERR "MCF5441x FEC: platform_device_register failed"
200 + "with code=%d\n", retval);
206 +arch_initcall(mcf5441x_fec_dev_init);
208 +++ b/arch/m68k/coldfire/m5445x/fec.c
213 + * Sub-architcture dependant initialization code for the Freescale
214 + * 5445X FEC module.
216 + * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
217 + * Shrek Wu B16972@freescale.com
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.
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.
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
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>
248 +#include <asm/traps.h>
249 +#include <asm/machdep.h>
250 +#include <asm/coldfire.h>
251 +#include <asm/mcfsim.h>
253 +static struct resource fec0_resources[] = {
255 + .start = MCF_MBAR + 0xfc030000,
256 + .end = MCF_MBAR + 0xfc0302ff,
257 + .flags = IORESOURCE_MEM,
260 + .start = (64 + 36),
262 + .flags = IORESOURCE_IRQ,
265 + .start = (64 + 40),
267 + .flags = IORESOURCE_IRQ,
270 + .start = (64 + 42),
272 + .flags = IORESOURCE_IRQ,
276 +#if defined(CONFIG_FEC2)
277 +static struct resource fec1_resources[] = {
279 + .start = MCF_MBAR + 0xfc034000,
280 + .end = MCF_MBAR + 0xfc0342ff,
281 + .flags = IORESOURCE_MEM,
284 + .start = (64 + 13 + 36),
285 + .end = (64 + 13 + 36),
286 + .flags = IORESOURCE_IRQ,
289 + .start = (64 + 13 + 40),
290 + .end = (64 + 13 + 40),
291 + .flags = IORESOURCE_IRQ,
294 + .start = (64 + 13 + 42),
295 + .end = (64 + 13 + 42),
296 + .flags = IORESOURCE_IRQ,
301 +static struct platform_device fec0_coldfire_device = {
304 + .resource = fec0_resources,
305 + .num_resources = ARRAY_SIZE(fec0_resources),
308 +#if defined(CONFIG_FEC2)
309 +static struct platform_device fec1_coldfire_device = {
312 + .resource = fec1_resources,
313 + .num_resources = ARRAY_SIZE(fec1_resources),
317 +static struct platform_device *fec_device[] = {
318 + &fec0_coldfire_device,
319 +#if defined(CONFIG_FEC2)
320 + &fec1_coldfire_device,
324 +static int __init mcf5445x_fec_dev_init(void)
328 + MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
329 + MCF_GPIO_PAR_FEC_FEC0_MASK) |
330 + MCF_GPIO_PAR_FEC_FEC0_RMII_GPIO;
332 + MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
333 + MCF_GPIO_PAR_FEC_FEC1_MASK) |
334 + MCF_GPIO_PAR_FEC_FEC1_RMII_GPIO;
336 + MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_MDIO0_MDIO0 |
337 + MCF_GPIO_PAR_FECI2C_MDC0_MDC0);
339 + MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_MDIO1_MDIO1 |
340 + MCF_GPIO_PAR_FECI2C_MDC1_MDC1);
342 + retval = platform_add_devices(fec_device, ARRAY_SIZE(fec_device));
344 + printk(KERN_ERR "MCF5445x FEC: platform_device_register failed"
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
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
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.
369 + bool "Second FEC ethernet controller (on some ColdFire CPUs)"
370 + depends on FEC && (M54455 || M5441X)
372 + Say Y here if you want to use the second built-in 10/100 Fast
373 + ethernet controller on some Motorola ColdFire processors.
376 + tristate "MCF547x/MCF548x Fast Ethernet Controller support"
377 + depends on M547X_8X
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.
382 + To compile this driver as a module, choose M here: the module
383 + will be called fecm.
385 +config FEC_548x_ENABLE_FEC2
386 + bool "Enable the second FEC"
387 + depends on FEC_548x
389 + This enables the second FEC on the 547x/548x. If you want to use
392 +config FEC_548x_SHARED_PHY
393 + bool "Shared PHY interface(on some ColdFire designs)"
394 + depends on FEC_548x_ENABLE_FEC2
396 + Say Y here if both PHYs are controlled via a single channel.
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
414 * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
415 * Copyright (c) 2004-2006 Macq Electronique SA.
417 - * Copyright (C) 2010 Freescale Semiconductor, Inc.
418 + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
421 #include <linux/module.h>
422 @@ -74,6 +74,9 @@ static struct platform_device_id fec_dev
425 .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
427 + .name = "m54418-fec",
428 + .driver_data = FEC_QUIRK_ENET_MAC,
432 @@ -148,8 +151,9 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet
433 * account when setting it.
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)
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)
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;
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);
458 - dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
460 +/* dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
461 + DMA_FROM_DEVICE);*/
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)
469 - bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen,
471 +/* bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen,
472 + DMA_FROM_DEVICE);*/
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)
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;
485 @@ -660,6 +667,10 @@ static void fec_enet_adjust_link(struct
486 fec_restart(dev, phy_dev->duplex);
490 + if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
491 + writel(2, fep->hwp + FEC_ECNTRL);
496 --- a/drivers/net/fec.h
497 +++ b/drivers/net/fec.h
499 * fec.h -- Fast Ethernet Controller for Motorola ColdFire SoC
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)
507 /****************************************************************************/
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)
517 * Just figures, Motorola would have to change the offsets for
518 * registers in the same peripheral device on different models
520 +++ b/drivers/net/fec_m547x.c
523 + * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
524 + * Author: Kurt Mahan, kmahan@freescale.com
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.
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>
550 +#include <asm/coldfire.h>
551 +#include <asm/mcfsim.h>
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>
559 +#include "fec_m547x.h"
561 +#ifdef CONFIG_FEC_548x_ENABLE_FEC2
562 +#define FEC_MAX_PORTS 2
565 +#define FEC_MAX_PORTS 1
569 +#define VERSION "0.20"
570 +MODULE_DESCRIPTION("DMA Fast Ethernet Controller driver ver " VERSION);
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;
603 +struct net_device *fec_dev[FEC_MAX_PORTS];
606 +static int __init fec_init(void);
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);
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);
623 +/* default fec0 address */
624 +unsigned char fec_mac_addr_fec0[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x50 };
627 +/* default fec1 address */
628 +unsigned char fec_mac_addr_fec1[6] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x51 };
631 +extern unsigned char uboot_enet0[];
632 +extern unsigned char uboot_enet1[];
635 +int fec_str_to_mac(char *str_mac, unsigned char* addr);
636 +int __init fec_mac_setup0(char *s);
641 +void fec_interrupt_fec_tx_handler_fec1(void);
642 +void fec_interrupt_fec_rx_handler_fec1(void);
646 +int __init fec_mac_setup1(char *s);
649 +module_init(fec_init);
650 +/* module_exit(fec_cleanup); */
652 +__setup("mac0=", fec_mac_setup0);
655 +__setup("mac1=", fec_mac_setup1);
658 +#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
659 +#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \
661 +/* ----------------------------------------------------------- */
662 +static int coldfire_fec_mdio_read(struct mii_bus *bus,
663 + int phy_id, int reg)
666 +#ifdef CONFIG_FEC_548x_SHARED_PHY
667 + unsigned long base_addr = (unsigned long)FEC_BASE_ADDR_FEC0;
669 + unsigned long base_addr = (unsigned long) dev->base_addr;
673 + /* Clear the MII interrupt bit */
674 + FEC_EIR(base_addr) = FEC_EIR_MII;
676 + /* Write to the MII management frame register */
677 + FEC_MMFR(base_addr) = mk_mii_read(reg) | (phy_id << 23);
679 + /* Wait for the reading */
680 + while (!(FEC_EIR(base_addr) & FEC_EIR_MII)) {
684 + printk(KERN_ERR "%s timeout\n", __func__);
690 + /* Clear the MII interrupt bit */
691 + FEC_EIR(base_addr) = FEC_EIR_MII;
692 + ret = FEC_MMFR(base_addr) & 0x0000FFFF;
696 +static int coldfire_fec_mdio_write(struct mii_bus *bus,
697 + int phy_id, int reg, u16 data)
700 +#ifdef CONFIG_FEC_548x_SHARED_PHY
701 + unsigned long base_addr = (unsigned long)FEC_BASE_ADDR_FEC0;
703 + unsigned long base_addr = (unsigned long) dev->base_addr;
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;
712 + /* Write to the MII management frame register */
713 + FEC_MMFR(base_addr) = mk_mii_write(reg, data) | (phy_id << 23);
715 + /* Wait for the writing */
716 + while (!(FEC_EIR(base_addr) & FEC_EIR_MII)) {
719 + printk(KERN_ERR "%s timeout\n", __func__);
724 + /* Clear the MII interrupt bit */
725 + FEC_EIR(base_addr) = FEC_EIR_MII;
726 + ret = FEC_MMFR(base_addr) & 0x0000FFFF;
731 +static void fec_adjust_link(struct net_device *dev)
733 + struct fec_priv *priv = netdev_priv(dev);
734 + struct phy_device *phydev = priv->phydev;
737 + if (phydev->link != PHY_DOWN) {
738 + if (phydev->duplex != priv->duplex) {
740 + priv->duplex = phydev->duplex;
743 + if (phydev->speed != priv->speed) {
745 + priv->speed = phydev->speed;
748 + if (priv->link == PHY_DOWN) {
750 + priv->link = phydev->link;
752 + } else if (priv->link) {
754 + priv->link = PHY_DOWN;
760 + phy_print_status(phydev);
763 +static int coldfire_fec_init_phy(struct net_device *dev)
765 + struct fec_priv *priv = netdev_priv(dev);
766 + struct phy_device *phydev = NULL;
770 +#ifdef CONFIG_FEC_548x_SHARED_PHY
771 + if (priv->index == 0)
773 + else if (priv->index == 1) {
774 + struct fec_priv *priv0 = netdev_priv(fec_dev[0]);
775 + startnode = priv0->phydev->addr + 1;
782 + printk(KERN_ERR "%s priv->index %x, startnode %x\n",
783 + __func__, priv->index, startnode);
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];
792 + printk(KERN_INFO "%s no PHY here at"
793 + "mii_bus->phy_map[%d]\n",
796 + continue; /* no PHY here... */
798 + phydev = tmp_phydev;
800 + printk(KERN_INFO "%s find PHY here at"
801 + "mii_bus->phy_map[%d]\n",
804 + break; /* found it */
807 + /* now we are supposed to have a proper phydev, to attach to... */
809 + printk(KERN_INFO "%s: Don't found any phy device at all\n",
818 + printk(KERN_INFO "%s phydev_busid %s\n", __func__, phydev->dev.bus_id);
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);
827 + printk(KERN_INFO "attached phy %i to driver %s\n",
828 + phydev->addr, phydev->drv->name);
829 + priv->phydev = phydev;
833 +static int fec_mdio_register(struct net_device *dev,
837 + struct fec_priv *fp = netdev_priv(dev);
839 + fp->mdio_bus = mdiobus_alloc();
840 + if (!fp->mdio_bus) {
841 + printk(KERN_ERR "ethernet mdiobus_alloc fail\n");
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");
852 + printk(KERN_ERR "Now coldfire can not"
853 + "support more than 2 mii bus\n");
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);
861 + mdiobus_free(fp->mdio_bus);
862 + printk(KERN_ERR "%s: ethernet mdiobus_register fail %d\n",
867 + printk(KERN_INFO "mdiobus_register %s ok\n",
868 + fp->mdio_bus->name);
872 +/************************************************************************
873 +* NAME: mcf547x_fec_open
875 +* DESCRIPTION: This function performs the initialization of
876 +* of FEC and corresponding KS8721 transiver
878 +* RETURNS: If no error occurs, this function returns zero.
879 +*************************************************************************/
880 +static int mcf547x_fec_open(struct net_device *dev)
882 + struct fec_priv *fp = netdev_priv(dev);
883 + unsigned long base_addr = (unsigned long) dev->base_addr;
887 + int error_code = -EBUSY;
892 + coldfire_fec_init_phy(dev);
893 + phy_start(fp->phydev);
895 + /* Receive the DMA channels */
896 + channel = dma_set_channel_fec(fp->fecpriv_rx_requestor);
898 + if (channel == -1) {
899 + printk(KERN_ERR "Dma channel cannot be reserved\n");
903 + fp->fecpriv_fec_rx_channel = channel;
905 + dma_connect(channel, (int) fp->fecpriv_interrupt_fec_rx_handler);
907 + channel = dma_set_channel_fec(fp->fecpriv_tx_requestor);
909 + if (channel == -1) {
910 + printk(KERN_ERR "Dma channel cannot be reserved\n");
914 + fp->fecpriv_fec_tx_channel = channel;
916 + dma_connect(channel, (int) fp->fecpriv_interrupt_fec_tx_handler);
918 + /* init tasklet for controller reinitialization */
919 + tasklet_init(&fp->fecpriv_tasklet_reinit,
920 + fec_interrupt_fec_reinit, (unsigned long) dev);
923 + FEC_FECFRST(base_addr) |= FEC_SW_RST | FEC_RST_CTL;
924 + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
926 + /* Reset and disable FEC */
927 + FEC_ECR(base_addr) = FEC_ECR_RESET;
931 + /* Clear all events */
932 + FEC_EIR(base_addr) = FEC_EIR_CLEAR;
934 + /* Reset FIFO status */
935 + FEC_FECTFSR(base_addr) = FEC_FECTFSR_MSK;
936 + FEC_FECRFSR(base_addr) = FEC_FECRFSR_MSK;
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;
946 + /* Reset the group address descriptor */
947 + FEC_GALR(base_addr) = 0x00000000;
948 + FEC_GAUR(base_addr) = 0x00000000;
950 + /* Reset the individual address descriptor */
951 + FEC_IALR(base_addr) = 0x00000000;
952 + FEC_IAUR(base_addr) = 0x00000000;
954 + /* Set the receive control register */
955 + FEC_RCR(base_addr) = FEC_RCR_MAX_FRM_SIZE | FEC_RCR_MII;
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
962 + /* disable all but ...*/
964 + /* enable frame accept error*/
966 + /* enable receive wait condition*/
967 + /*& ~FEC_FECRFCR_UF*/
968 + /* enable FIFO underflow*/
971 + /* Set the receive FIFO alarm register */
972 + FEC_FECRFAR(base_addr) = FEC_FECRFAR_ALARM;
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
979 + /* disable all but ... */
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 */
989 + /* Set the transmit FIFO alarm register */
990 + FEC_FECTFAR(base_addr) = FEC_FECTFAR_ALARM;
992 + /* Set the Tx FIFO watermark */
993 + FEC_FECTFWR(base_addr) = FEC_FECTFWR_XWMRK;
995 + /* Enable the transmitter to append the CRC */
996 + FEC_CTCWR(base_addr) = FEC_CTCWR_TFCW_CRC;
998 + /* Enable the ethernet interrupts */
999 + /*FEC_EIMR(base_addr) = FEC_EIMR_MASK;*/
1000 + FEC_EIMR(base_addr) = FEC_EIMR_DISABLE
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");
1019 + /* Enable the full duplex mode */
1020 + FEC_TCR(base_addr) = FEC_TCR_FDEN | FEC_TCR_HBC;
1022 + /* Disable reception of frames while transmitting */
1023 + FEC_RCR(base_addr) |= FEC_RCR_DRT;
1026 + FEC_MIBC(base_addr) = FEC_MIBC_ENABLE;
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;
1035 + fp->fecpriv_txdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
1037 + fp->fecpriv_current_tx = fp->fecpriv_next_tx = 0;
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);
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;
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;
1063 + fp->fecpriv_rxdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
1064 + fp->fecpriv_current_rx = 0;
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);
1072 + netif_start_queue(dev);
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;
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;
1090 + return error_code;
1093 +/************************************************************************
1094 +* NAME: mcf547x_fec_close
1096 +* DESCRIPTION: This function performs the graceful stop of the
1097 +* transmission and disables FEC
1099 +* RETURNS: This function always returns zero.
1100 +*************************************************************************/
1101 +static int mcf547x_fec_close(struct net_device *dev)
1103 + struct fec_priv *fp = netdev_priv(dev);
1104 + unsigned long base_addr = (unsigned long) dev->base_addr;
1105 + unsigned long time;
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;
1116 + /* Wait for the graceful stop */
1117 + while (!(FEC_EIR(base_addr) & FEC_EIR_GRA) && jiffies - time <
1118 + (FEC_GR_TIMEOUT * HZ))
1122 + FEC_ECR(base_addr) = FEC_ECR_DISABLE;
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;
1132 + for (i = 0; i < FEC_TX_BUF_NUMBER; i++) {
1133 + kfree(fp->fecpriv_txbuf[i]);
1134 + fp->fecpriv_txbuf[i] = NULL;
1137 + spin_lock_irq(&fp->fecpriv_lock);
1138 + MCD_killDma(fp->fecpriv_fec_rx_channel);
1139 + spin_unlock_irq(&fp->fecpriv_lock);
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;
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;
1155 +/************************************************************************
1156 +* +NAME: mcf547x_fec_get_stat
1158 +* RETURNS: This function returns the statistical information.
1159 +*************************************************************************/
1160 +static struct net_device_stats *mcf547x_fec_get_stats(struct net_device *dev)
1162 + struct fec_priv *fp = netdev_priv(dev);
1163 + unsigned long base_addr = dev->base_addr;
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);
1171 + fp->fecpriv_stat.multicast = FECSTAT_RMON_R_MC_PKT(base_addr);
1172 + fp->fecpriv_stat.collisions = FECSTAT_RMON_T_COL(base_addr);
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);
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);
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;
1200 + return &fp->fecpriv_stat;
1203 +/************************************************************************
1204 +* NAME: mcf547x_fec_set_multicast_list
1206 +* DESCRIPTION: This function sets the frame filtering parameters
1207 +*************************************************************************/
1208 +static void mcf547x_fec_set_multicast_list(struct net_device *dev)
1210 + unsigned int crc, data;
1212 + unsigned long base_addr = (unsigned long) dev->base_addr;
1213 + struct netdev_hw_addr *ha;
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;
1222 + /* Reset the group address register */
1223 + FEC_GALR(base_addr) = 0x00000000;
1224 + FEC_GAUR(base_addr) = 0x00000000;
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))
1232 + /* Calculate crc value for the current address */
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;
1244 + /* Add this value */
1248 + FEC_GAUR(base_addr) |= 0x1 << (crc - 32);
1250 + FEC_GALR(base_addr) |= 0x1 << crc;
1254 +/************************************************************************
1255 +* NAME: mcf547x_fec_set_mac_address
1257 +* DESCRIPTION: This function sets the MAC address
1258 +*************************************************************************/
1259 +static int mcf547x_fec_set_mac_address(struct net_device *dev, void *p)
1261 + struct fec_priv *fp = netdev_priv(dev);
1262 + unsigned long base_addr = (unsigned long) dev->base_addr;
1263 + struct sockaddr *addr = p;
1265 + if (netif_running(dev))
1268 + /* Copy a new address to the device structure */
1269 + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
1271 + /* Copy a new address to the private structure */
1272 + memcpy(fp->fecpriv_mac_addr, addr->sa_data, 6);
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) |
1286 +/************************************************************************
1287 +* NAME: mcf547x_fec_start_xmit
1289 +* DESCRIPTION: This function starts transmission of the frame using DMA
1291 +* RETURNS: This function always returns zero.
1292 +*************************************************************************/
1293 +static int mcf547x_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
1295 + struct fec_priv *fp = netdev_priv(dev);
1296 + void *data, *data_aligned;
1299 + data = kmalloc(skb->len + 15, GFP_DMA | GFP_ATOMIC);
1302 + fp->fecpriv_stat.tx_dropped++;
1303 + dev_kfree_skb(skb);
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);
1312 + /* flush data cache before initializing
1313 + * the descriptor and starting DMA */
1315 + spin_lock_irq(&fp->fecpriv_lock);
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;
1326 + if (fp->fecpriv_txbuf[fp->fecpriv_current_tx]
1327 + && fp->fecpriv_current_tx == fp->fecpriv_next_tx)
1328 + netif_stop_queue(dev);
1330 + spin_unlock_irq(&fp->fecpriv_lock);
1332 + /* Tell the DMA to continue the transmission */
1333 + MCD_continDma(fp->fecpriv_fec_tx_channel);
1335 + dev_kfree_skb(skb);
1337 + dev->trans_start = jiffies;
1342 +/************************************************************************
1343 +* NAME: mcf547x_fec_tx_timeout
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
1349 +*************************************************************************/
1350 +static void mcf547x_fec_tx_timeout(struct net_device *dev)
1353 + struct fec_priv *fp = netdev_priv(dev);
1354 + unsigned long base_addr = (unsigned long) dev->base_addr;
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;
1363 + fp->fecpriv_txdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
1365 + fp->fecpriv_current_tx = fp->fecpriv_next_tx = 0;
1368 + FEC_FECFRST(base_addr) |= FEC_SW_RST;
1369 + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
1371 + /* Reset and disable FEC */
1372 + /* FEC_ECR(base_addr) = FEC_ECR_RESET; */
1375 + FEC_ECR(base_addr) |= FEC_ECR_ETHEREN;
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);
1383 + spin_unlock_irq(&fp->fecpriv_lock);
1385 + netif_wake_queue(dev);
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,
1400 + * Initialize a FEC device
1402 +int fec_enet_init(struct net_device *dev, int slot)
1404 + struct fec_priv *fp = netdev_priv(dev);
1409 + fec_dev[slot] = dev;
1412 + /* disable fec0 */
1413 + FEC_ECR(FEC_BASE_ADDR_FEC0) = FEC_ECR_DISABLE;
1415 + /* setup the interrupt handler */
1416 + dev->irq = 64 + ISC_FEC0;
1418 + if (request_irq(dev->irq, fec_interrupt_handler,
1419 + IRQF_DISABLED, "ColdFire FEC 0", dev)) {
1421 + printk(KERN_ERR "Cannot allocate FEC0 IRQ\n");
1423 + /* interrupt priority and level */
1424 + MCF_ICR(ISC_FEC0) = ILP_FEC0;
1427 + /* fec base address */
1428 + dev->base_addr = FEC_BASE_ADDR_FEC0;
1430 + /* requestor numbers */
1431 + fp->fecpriv_rx_requestor = DMA_FEC0_RX;
1432 + fp->fecpriv_tx_requestor = DMA_FEC0_TX;
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;
1440 + /* tx descriptors */
1441 + fp->fecpriv_txdesc = (void *)FEC_TX_DESC_FEC0;
1443 + /* rx descriptors */
1444 + fp->fecpriv_rxdesc = (void *)FEC_RX_DESC_FEC0;
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);
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;
1465 + fp->fecpriv_mac_addr = fec_mac_addr_fec0;
1467 + /* disable fec1 */
1468 + FEC_ECR(FEC_BASE_ADDR_FEC1) = FEC_ECR_DISABLE;
1470 + /* setup the interrupt handler */
1471 + dev->irq = 64 + ISC_FEC1;
1473 + if (request_irq(dev->irq, fec_interrupt_handler,
1474 + IRQF_DISABLED, "ColdFire FEC 1", dev)) {
1476 + printk(KERN_ERR "Cannot allocate FEC1 IRQ\n");
1478 + /* interrupt priority and level */
1479 + MCF_ICR(ISC_FEC1) = ILP_FEC1;
1482 + /* fec base address */
1483 + dev->base_addr = FEC_BASE_ADDR_FEC1;
1485 + /* requestor numbers */
1486 + fp->fecpriv_rx_requestor = DMA_FEC1_RX;
1487 + fp->fecpriv_tx_requestor = DMA_FEC1_TX;
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;
1495 + /* tx descriptors */
1496 + fp->fecpriv_txdesc = (void *)FEC_TX_DESC_FEC1;
1498 + /* rx descriptors */
1499 + fp->fecpriv_rxdesc = (void *)FEC_RX_DESC_FEC1;
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);
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;
1520 + fp->fecpriv_mac_addr = fec_mac_addr_fec1;
1525 + memset((void *) (dev->base_addr + 0x200), 0, FEC_MIB_LEN);
1527 + /* clear the statistics structure */
1528 + memset((void *) &(fp->fecpriv_stat), 0,
1529 + sizeof(struct net_device_stats));
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);
1537 + /* reset the DMA channels */
1538 + fp->fecpriv_fec_rx_channel = -1;
1539 + fp->fecpriv_fec_tx_channel = -1;
1541 + for (i = 0; i < FEC_RX_BUF_NUMBER; i++)
1542 + fp->askb_rx[i] = NULL;
1544 + /* initialize the pointers to the socket buffers */
1545 + for (i = 0; i < FEC_TX_BUF_NUMBER; i++)
1546 + fp->fecpriv_txbuf[i] = NULL;
1550 + dev->netdev_ops = &mcf547x_fec_netdev_ops;
1551 + dev->watchdog_timeo = FEC_TX_TIMEOUT * HZ;
1553 + memcpy(dev->dev_addr, fp->fecpriv_mac_addr, ETH_ALEN);
1555 + spin_lock_init(&fp->fecpriv_lock);
1557 + /* Initialize FEC/I2C/IRQ Pin Assignment Register*/
1558 + FEC_GPIO_PAR_FECI2CIRQ &= 0xF;
1559 + FEC_GPIO_PAR_FECI2CIRQ |= FEC_FECI2CIRQ;
1565 + * Module Initialization
1567 +int __init fec_init(void)
1569 + struct net_device *dev;
1572 + struct fec_priv *fep;
1574 + printk(KERN_INFO "FEC ENET (DMA) Version %s\n", VERSION);
1576 + for (i = 0; i < FEC_MAX_PORTS; i++) {
1577 + dev = alloc_etherdev(sizeof(struct fec_priv));
1580 + err = fec_enet_init(dev, i);
1586 + fep = netdev_priv(dev);
1587 + FEC_MSCR(dev->base_addr) = FEC_MII_SPEED;
1588 +#ifdef CONFIG_FEC_548x_SHARED_PHY
1590 + err = fec_mdio_register(dev, i);
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);
1598 + err = fec_mdio_register(dev, i);
1601 + printk(KERN_ERR "%s: ethernet fec_mdio_register\n",
1607 + if (register_netdev(dev) != 0) {
1612 + printk(KERN_INFO "%s: ethernet %s\n",
1613 + dev->name, dev->dev_addr);
1621 +void fec_stop(struct net_device *dev)
1623 + struct fec_priv *fp = netdev_priv(dev);
1625 + dma_remove_initiator(fp->fecpriv_initiator_tx);
1626 + dma_remove_initiator(fp->fecpriv_initiator_rx);
1629 + free_irq(dev->irq, dev);
1632 +/************************************************************************
1633 +* NAME: fec_interrupt_tx_handler
1635 +* DESCRIPTION: This function is called when the data
1636 +* transmission from the buffer to the FEC is completed.
1638 +*************************************************************************/
1639 +void fec_interrupt_fec_tx_handler(struct net_device *dev)
1641 + struct fec_priv *fp = netdev_priv(dev);
1643 + /* Release the socket buffer */
1644 + kfree(fp->fecpriv_txbuf[fp->fecpriv_current_tx]);
1645 + fp->fecpriv_txbuf[fp->fecpriv_current_tx] = NULL;
1647 + fp->fecpriv_current_tx =
1648 + (fp->fecpriv_current_tx + 1) & FEC_TX_INDEX_MASK;
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]
1664 + if (netif_queue_stopped(dev))
1665 + netif_wake_queue(dev);
1668 +/************************************************************************
1669 +* NAME: fec_interrupt_rx_handler
1671 +* DESCRIPTION: This function is called when the data
1672 +* reception from the FEC to the reception buffer is completed.
1674 +*************************************************************************/
1675 +void fec_interrupt_fec_rx_handler(struct net_device *dev)
1677 + struct fec_priv *fp = netdev_priv(dev);
1678 + struct sk_buff *skb;
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))
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);
1700 + fp->fecpriv_rxflag = 0;
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
1715 + skb = fp->askb_rx[fp->fecpriv_current_rx];
1717 + fp->fecpriv_stat.rx_dropped++;
1720 + * flush data cache before initializing
1721 + * the descriptor and starting DMA
1724 + (fp->fecpriv_rxdesc[
1725 + fp->fecpriv_current_rx].length - 4));
1726 + skb->protocol = eth_type_trans(skb, dev);
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
1739 + fp->fecpriv_rxdesc[
1740 + fp->fecpriv_current_rx].length = 0;
1741 + fp->fecpriv_stat.rx_dropped++;
1744 + fp->askb_rx[fp->fecpriv_current_rx], 16);
1745 + fp->askb_rx[fp->fecpriv_current_rx]->dev = dev;
1748 + * flush data cache before initializing
1749 + * the descriptor and starting DMA
1752 + fp->fecpriv_rxdesc[
1753 + fp->fecpriv_current_rx].dataPointer =
1754 + (unsigned int) virt_to_phys(
1756 + fp->fecpriv_current_rx]->tail);
1757 + fp->fecpriv_rxdesc[
1758 + fp->fecpriv_current_rx].length =
1760 + fp->fecpriv_rxdesc[
1761 + fp->fecpriv_current_rx].statCtrl |=
1762 + MCD_FEC_BUF_READY;
1765 + * flush data cache before initializing
1766 + * the descriptor and starting DMA
1773 + /* Tell the DMA to continue the reception */
1774 + MCD_continDma(fp->fecpriv_fec_rx_channel);
1776 + fp->fecpriv_rxflag = 0;
1779 +/************************************************************************
1780 +* NAME: fec_interrupt_handler
1782 +* DESCRIPTION: This function is called when some special errors occur
1784 +*************************************************************************/
1785 +irqreturn_t fec_interrupt_handler(int irq, void *dev_id)
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;
1793 + /* Read and clear the events */
1794 + events = FEC_EIR(base_addr) & FEC_EIMR(base_addr);
1796 + if (events & FEC_EIR_HBERR) {
1797 + fp->fecpriv_stat.tx_heartbeat_errors++;
1798 + FEC_EIR(base_addr) = FEC_EIR_HBERR;
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);
1807 + /* kill running transmission by DMA */
1808 + MCD_killDma(fp->fecpriv_fec_tx_channel);
1811 + FEC_FECFRST(base_addr) |= FEC_SW_RST;
1812 + FEC_FECFRST(base_addr) &= ~FEC_SW_RST;
1814 + /* reset receive FIFO status register */
1815 + FEC_FECRFSR(base_addr) = FEC_FECRFSR_FAE |
1819 + /* reset transmit FIFO status register */
1820 + FEC_FECTFSR(base_addr) = FEC_FECTFSR_FAE |
1825 + /* reset RFERR and XFERR event */
1826 + FEC_EIR(base_addr) = FEC_EIR_RFERR | FEC_EIR_XFERR;
1829 + netif_stop_queue(dev);
1831 + /* execute reinitialization as tasklet */
1832 + tasklet_schedule(&fp->fecpriv_tasklet_reinit);
1834 + fp->fecpriv_stat.rx_dropped++;
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++;
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++;
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++;
1860 +/************************************************************************
1861 +* NAME: fec_interrupt_reinit
1863 +* DESCRIPTION: This function is called from interrupt handler
1864 +* when controller must be reinitialized.
1866 +*************************************************************************/
1867 +void fec_interrupt_fec_reinit(unsigned long data)
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;
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;
1885 + fp->askb_rx[i]->dev = dev;
1886 + skb_reserve(fp->askb_rx[i], 16);
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;
1895 + fp->fecpriv_rxdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
1896 + fp->fecpriv_current_rx = 0;
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;
1905 + fp->fecpriv_txdesc[i - 1].statCtrl |= MCD_FEC_WRAP;
1906 + fp->fecpriv_current_tx = fp->fecpriv_next_tx = 0;
1908 + /* flush entire data cache before restarting the DMA */
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);
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);
1925 + FEC_ECR(base_addr) |= FEC_ECR_ETHEREN;
1927 + netif_wake_queue(dev);
1930 +/************************************************************************
1931 +* NAME: fec_interrupt_tx_handler_fec0
1933 +* DESCRIPTION: This is the DMA interrupt handler using for FEC0
1936 +*************************************************************************/
1937 +void fec_interrupt_fec_tx_handler_fec0(void)
1939 + fec_interrupt_fec_tx_handler(fec_dev[0]);
1943 +/************************************************************************
1944 +* NAME: fec_interrupt_tx_handler_fec1
1946 +* DESCRIPTION: This is the DMA interrupt handler using for the FEC1
1949 +*************************************************************************/
1950 +void fec_interrupt_fec_tx_handler_fec1(void)
1952 + fec_interrupt_fec_tx_handler(fec_dev[1]);
1956 +/************************************************************************
1957 +* NAME: fec_interrupt_rx_handler_fec0
1959 +* DESCRIPTION: This is the DMA interrupt handler using for the FEC0
1962 +*************************************************************************/
1963 +void fec_interrupt_fec_rx_handler_fec0(void)
1965 + fec_interrupt_fec_rx_handler(fec_dev[0]);
1969 +/************************************************************************
1970 +* NAME: fec_interrupt_rx_handler_fec1
1972 +* DESCRIPTION: This is the DMA interrupt handler using for the FEC1
1975 +*************************************************************************/
1976 +void fec_interrupt_fec_rx_handler_fec1(void)
1978 + fec_interrupt_fec_rx_handler(fec_dev[1]);
1984 +/************************************************************************
1985 +* NAME: fec_mac_setup0
1987 +* DESCRIPTION: This function sets the MAC address of FEC0 from command line
1989 +*************************************************************************/
1990 +int __init fec_mac_setup0(char *s)
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");
2003 +/************************************************************************
2004 +* NAME: fec_mac_setup1
2006 +* DESCRIPTION: This function sets the MAC address of FEC1 from command line
2008 +*************************************************************************/
2009 +int __init fec_mac_setup1(char *s)
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");
2021 +/************************************************************************
2022 +* NAME: fec_str_to_mac
2024 +* DESCRIPTION: This function interprets the character string into MAC addr
2026 +*************************************************************************/
2027 +int fec_str_to_mac(char *str_mac, unsigned char* addr)
2029 + unsigned long val;
2031 + unsigned long octet[6], *octetptr = octet;
2036 + while ((c = *str_mac) != '\0') {
2037 + if ((c >= '0') && (c <= '9')) {
2038 + val = (val * 16) + (c - '0');
2041 + } else if (((c >= 'a') && (c <= 'f'))
2042 + || ((c >= 'A') && (c <= 'F'))) {
2043 + val = (val << 4) +
2045 + (((c >= 'a') && (c <= 'f')) ? 'a' : 'A'));
2051 + if (*str_mac == ':') {
2052 + *octetptr++ = val, str_mac++;
2053 + if (octetptr >= octet + 6)
2058 + /* Check for trailing characters */
2059 + if (*str_mac && !(*str_mac == ' '))
2062 + *octetptr++ = val;
2064 + if ((octetptr - octet) == 6) {
2065 + for (i = 0; i <= 6; i++)
2066 + addr[i] = octet[i];
2074 +++ b/drivers/net/fec_m547x.h
2076 +#ifndef FEC_M547X_H
2077 +#define FEC_M547X_H
2079 + * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
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.
2087 +#define FEC_BASE_ADDR_FEC0 ((unsigned int)MCF_MBAR + 0x9000)
2088 +#define FEC_BASE_ADDR_FEC1 ((unsigned int)MCF_MBAR + 0x9800)
2090 +#define FEC_FECI2CIRQ (0xFFC0)
2091 +#define FEC_GPIO_PAR_FECI2CIRQ \
2092 + (*(volatile unsigned short *)((unsigned int)MCF_MBAR + 0xA44))
2094 +#define FEC_ECR_DISABLE (0x00000000)
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))
2191 +#define FEC_MAX_FRM_SIZE (1518)
2192 +#define FEC_MAXBUF_SIZE (1520)
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)
2226 +#define FEC_EIMR_DISABLE (0x00000000)
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 */
2240 +#define FEC_FECTFAR_ALARM (0x100)
2241 +#define FEC_FECTFWR_XWMRK (0x00000000)
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 */
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 */
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)
2275 +#define FEC_RX_DMA_PRI (6)
2276 +#define FEC_TX_DMA_PRI (6)
2278 +#define FEC_TX_BUF_NUMBER (8)
2279 +#define FEC_RX_BUF_NUMBER (64)
2281 +#define FEC_TX_INDEX_MASK (0x7)
2282 +#define FEC_RX_INDEX_MASK (0x3f)
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))
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))
2293 +#define FEC_EIR_MII (0x00800000)
2294 +#define FEC_MMFR_READ (0x60020000)
2295 +#define FEC_MMFR_WRITE (0x50020000)
2297 +#define FEC_FLAGS_RX (0x00000001)
2299 +#define FEC_CRCPOL (0xEDB88320)
2301 +#define FEC_MII_TIMEOUT (2)
2302 +#define FEC_GR_TIMEOUT (1)
2303 +#define FEC_TX_TIMEOUT (1)
2304 +#define FEC_RX_TIMEOUT (1)
2306 +#define FEC_SW_RST 0x2000000
2307 +#define FEC_RST_CTL 0x1000000
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);
2314 +#define FEC_MII_SPEED \
2315 + ((MCF_CLK / 2) / ((2500000 / 2) * 2))
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
2323 +config BROADCOM5222_PHY
2324 + tristate "Drivers for Broadcom5222 PHY"
2326 + Currently supports the BCM5222 PHYs.
2329 tristate "Drivers for Broadcom 63xx SOCs internal PHY"
2331 @@ -82,6 +87,16 @@ config NATIONAL_PHY
2333 Currently supports the DP83865 PHY.
2335 +config NATIONAL8364x_PHY
2336 + tristate "Drivers for National Semiconductor dp83640 PHYs"
2338 + Currently supports the DP83640 PHY.
2340 +config NATIONAL8384x_PHY
2341 + tristate "Drivers for National Semiconductor dp83848 dp83849 PHYs"
2343 + Currently supports the DP83848 PHY.
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
2368 +++ b/drivers/net/phy/broadcom522x.c
2371 + * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
2372 + * Chenghu Wu <b16972@freescale.com>
2374 + * Driver for broadcom PHYs 522x
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.
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>
2390 +/* DP83865 phy identifier values */
2391 +#define BCM5222_PHY_ID 0x00406320
2394 +#define BCM5222_TIMEOUT 0x100
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
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
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
2435 +#define BCM5222_ID_HIGH_VAL 0x0040
2436 +#define BCM5222_ID_LOW_VAL 0x6320
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)
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
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
2483 +static int bcm5222_config_intr(struct phy_device *phydev)
2486 + printk(KERN_INFO "%s PHY_INTERRUPT %x\n",
2487 + __func__, phydev->interrupts);
2492 +static int bcm5222_ack_interrupt(struct phy_device *phydev)
2497 +static int bcm5222_config_init(struct phy_device *phydev)
2499 + return bcm5222_ack_interrupt(phydev);
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,}
2516 +static int __init bcm5222_init(void)
2520 + ret = phy_driver_register(&bcm5222_driver);
2526 + printk(KERN_INFO "register bcm5222 PHY driver fail\n");
2530 +static void __exit bcm5222_exit(void)
2532 + phy_driver_unregister(&bcm5222_driver);
2535 +MODULE_DESCRIPTION("Broadcom PHY driver");
2536 +MODULE_LICENSE("GPL v2");
2538 +module_init(bcm5222_init);
2539 +module_exit(bcm5222_exit);
2541 +++ b/drivers/net/phy/national836x.c
2544 + * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
2545 + * Chenghu Wu <b16972@freescale.com>
2547 + * Driver for National Semiconductor PHYs 83640
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.
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>
2563 +/* DP83640 phy identifier values */
2564 +#define DP83640_PHY_ID 0x20005ce0
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
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
2578 +static int ns_config_intr(struct phy_device *phydev)
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);
2590 + err = phy_write(phydev, MII_DP83640_ICR, 0);
2595 +static int ns83640_ack_interrupt(struct phy_device *phydev)
2597 + int ret = phy_read(phydev, MII_DP83640_ISR);
2599 + printk(KERN_INFO "%s MII_DP83640_ISR %x\n",
2606 +static int ns83640_config_init(struct phy_device *phydev)
2608 + int ret = phy_read(phydev, MII_DP83640_PHYSTST);
2610 + printk(KERN_INFO "%s MII_DP83640_ISR %x\n",
2614 + return ns83640_ack_interrupt(phydev);
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,}
2631 +static int __init ns83640_init(void)
2633 + return phy_driver_register(&dp83640_driver);
2636 +static void __exit ns83640_exit(void)
2638 + phy_driver_unregister(&dp83640_driver);
2641 +MODULE_DESCRIPTION("NatSemi PHY driver");
2642 +MODULE_AUTHOR("Chenghu Wu <b16972@freescale.com>");
2643 +MODULE_LICENSE("GPL v2");
2645 +module_init(ns83640_init);
2646 +module_exit(ns83640_exit);
2648 +++ b/drivers/net/phy/national8384x.c
2651 + * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
2652 + * Chenghu Wu <b16972@freescale.com>
2654 + * Driver for National Semiconductor PHYs 8384x
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.
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>
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
2676 +static int ns8384x_config_intr(struct phy_device *phydev)
2683 +static int ns8384x_ack_interrupt(struct phy_device *phydev)
2688 +static int ns8384x_config_init(struct phy_device *phydev)
2690 + int ret = phy_read(phydev, MII_DP8384X_PHYSTST);
2692 + printk(KERN_INFO "%s MII_DP83640_ISR %x\n",
2696 + return ns8384x_ack_interrupt(phydev);
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,}
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,}
2727 +static int __init ns8384x_init(void)
2731 + ret = phy_driver_register(&dp83848_driver);
2735 + ret = phy_driver_register(&dp83849_driver);
2741 + printk(KERN_INFO "register dp83849 PHY driver fail\n");
2742 + phy_driver_unregister(&dp83848_driver);
2744 + printk(KERN_INFO "register dp83848 PHY driver fail\n");
2748 +static void __exit ns8384x_exit(void)
2750 + phy_driver_unregister(&dp83848_driver);
2751 + phy_driver_unregister(&dp83849_driver);
2754 +MODULE_DESCRIPTION("NatSemi PHY driver");
2755 +MODULE_AUTHOR("Chenghu Wu <b16972@freescale.com>");
2756 +MODULE_LICENSE("GPL v2");
2758 +module_init(ns8384x_init);
2759 +module_exit(ns8384x_exit);