diff options
author | Andy Fleming <afleming@freescale.com> | 2005-09-23 22:54:21 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-23 22:54:21 -0400 |
commit | bb40dcbb0fcebe1df08ba261483fcc38b307d063 (patch) | |
tree | aefeb8db397de215cf1ff1c5ff7a581cee2b2b4b | |
parent | acc4b985a6f8f22a0e826692894a4af234764001 (diff) |
[netdrvr gianfar] use new phy layer
Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r-- | drivers/net/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/gianfar.c | 412 | ||||
-rw-r--r-- | drivers/net/gianfar.h | 30 | ||||
-rw-r--r-- | drivers/net/gianfar_ethtool.c | 100 | ||||
-rw-r--r-- | drivers/net/gianfar_mii.c | 219 | ||||
-rw-r--r-- | drivers/net/gianfar_mii.h | 45 | ||||
-rw-r--r-- | drivers/net/gianfar_phy.c | 661 | ||||
-rw-r--r-- | drivers/net/gianfar_phy.h | 213 |
9 files changed, 433 insertions, 1251 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ff3fccd7513b..4739a63601eb 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -2075,6 +2075,8 @@ config SPIDER_NET | |||
2075 | config GIANFAR | 2075 | config GIANFAR |
2076 | tristate "Gianfar Ethernet" | 2076 | tristate "Gianfar Ethernet" |
2077 | depends on 85xx || 83xx | 2077 | depends on 85xx || 83xx |
2078 | select PHYLIB | ||
2079 | select PHYCONTROL | ||
2078 | help | 2080 | help |
2079 | This driver supports the Gigabit TSEC on the MPC85xx | 2081 | This driver supports the Gigabit TSEC on the MPC85xx |
2080 | family of chips, and the FEC on the 8540 | 2082 | family of chips, and the FEC on the 8540 |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index e6acba68923a..39b17cb4f86e 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -13,7 +13,7 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/ | |||
13 | obj-$(CONFIG_BONDING) += bonding/ | 13 | obj-$(CONFIG_BONDING) += bonding/ |
14 | obj-$(CONFIG_GIANFAR) += gianfar_driver.o | 14 | obj-$(CONFIG_GIANFAR) += gianfar_driver.o |
15 | 15 | ||
16 | gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o | 16 | gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o |
17 | 17 | ||
18 | # | 18 | # |
19 | # link order important here | 19 | # link order important here |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 6518334b9280..ae5a2ed3b264 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -29,12 +29,7 @@ | |||
29 | * define the configuration needed by the board are defined in a | 29 | * define the configuration needed by the board are defined in a |
30 | * board structure in arch/ppc/platforms (though I do not | 30 | * board structure in arch/ppc/platforms (though I do not |
31 | * discount the possibility that other architectures could one | 31 | * discount the possibility that other architectures could one |
32 | * day be supported. One assumption the driver currently makes | 32 | * day be supported. |
33 | * is that the PHY is configured in such a way to advertise all | ||
34 | * capabilities. This is a sensible default, and on certain | ||
35 | * PHYs, changing this default encounters substantial errata | ||
36 | * issues. Future versions may remove this requirement, but for | ||
37 | * now, it is best for the firmware to ensure this is the case. | ||
38 | * | 33 | * |
39 | * The Gianfar Ethernet Controller uses a ring of buffer | 34 | * The Gianfar Ethernet Controller uses a ring of buffer |
40 | * descriptors. The beginning is indicated by a register | 35 | * descriptors. The beginning is indicated by a register |
@@ -47,7 +42,7 @@ | |||
47 | * corresponding bit in the IMASK register is also set (if | 42 | * corresponding bit in the IMASK register is also set (if |
48 | * interrupt coalescing is active, then the interrupt may not | 43 | * interrupt coalescing is active, then the interrupt may not |
49 | * happen immediately, but will wait until either a set number | 44 | * happen immediately, but will wait until either a set number |
50 | * of frames or amount of time have passed.). In NAPI, the | 45 | * of frames or amount of time have passed). In NAPI, the |
51 | * interrupt handler will signal there is work to be done, and | 46 | * interrupt handler will signal there is work to be done, and |
52 | * exit. Without NAPI, the packet(s) will be handled | 47 | * exit. Without NAPI, the packet(s) will be handled |
53 | * immediately. Both methods will start at the last known empty | 48 | * immediately. Both methods will start at the last known empty |
@@ -75,6 +70,7 @@ | |||
75 | #include <linux/sched.h> | 70 | #include <linux/sched.h> |
76 | #include <linux/string.h> | 71 | #include <linux/string.h> |
77 | #include <linux/errno.h> | 72 | #include <linux/errno.h> |
73 | #include <linux/unistd.h> | ||
78 | #include <linux/slab.h> | 74 | #include <linux/slab.h> |
79 | #include <linux/interrupt.h> | 75 | #include <linux/interrupt.h> |
80 | #include <linux/init.h> | 76 | #include <linux/init.h> |
@@ -97,9 +93,11 @@ | |||
97 | #include <linux/version.h> | 93 | #include <linux/version.h> |
98 | #include <linux/dma-mapping.h> | 94 | #include <linux/dma-mapping.h> |
99 | #include <linux/crc32.h> | 95 | #include <linux/crc32.h> |
96 | #include <linux/mii.h> | ||
97 | #include <linux/phy.h> | ||
100 | 98 | ||
101 | #include "gianfar.h" | 99 | #include "gianfar.h" |
102 | #include "gianfar_phy.h" | 100 | #include "gianfar_mii.h" |
103 | 101 | ||
104 | #define TX_TIMEOUT (1*HZ) | 102 | #define TX_TIMEOUT (1*HZ) |
105 | #define SKB_ALLOC_TIMEOUT 1000000 | 103 | #define SKB_ALLOC_TIMEOUT 1000000 |
@@ -113,9 +111,8 @@ | |||
113 | #endif | 111 | #endif |
114 | 112 | ||
115 | const char gfar_driver_name[] = "Gianfar Ethernet"; | 113 | const char gfar_driver_name[] = "Gianfar Ethernet"; |
116 | const char gfar_driver_version[] = "1.1"; | 114 | const char gfar_driver_version[] = "1.2"; |
117 | 115 | ||
118 | int startup_gfar(struct net_device *dev); | ||
119 | static int gfar_enet_open(struct net_device *dev); | 116 | static int gfar_enet_open(struct net_device *dev); |
120 | static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); | 117 | static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); |
121 | static void gfar_timeout(struct net_device *dev); | 118 | static void gfar_timeout(struct net_device *dev); |
@@ -126,17 +123,13 @@ static int gfar_set_mac_address(struct net_device *dev); | |||
126 | static int gfar_change_mtu(struct net_device *dev, int new_mtu); | 123 | static int gfar_change_mtu(struct net_device *dev, int new_mtu); |
127 | static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs); | 124 | static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs); |
128 | static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs); | 125 | static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs); |
129 | static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs); | ||
130 | static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 126 | static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
131 | static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs); | ||
132 | static void gfar_phy_change(void *data); | ||
133 | static void gfar_phy_timer(unsigned long data); | ||
134 | static void adjust_link(struct net_device *dev); | 127 | static void adjust_link(struct net_device *dev); |
135 | static void init_registers(struct net_device *dev); | 128 | static void init_registers(struct net_device *dev); |
136 | static int init_phy(struct net_device *dev); | 129 | static int init_phy(struct net_device *dev); |
137 | static int gfar_probe(struct device *device); | 130 | static int gfar_probe(struct device *device); |
138 | static int gfar_remove(struct device *device); | 131 | static int gfar_remove(struct device *device); |
139 | void free_skb_resources(struct gfar_private *priv); | 132 | static void free_skb_resources(struct gfar_private *priv); |
140 | static void gfar_set_multi(struct net_device *dev); | 133 | static void gfar_set_multi(struct net_device *dev); |
141 | static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); | 134 | static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); |
142 | #ifdef CONFIG_GFAR_NAPI | 135 | #ifdef CONFIG_GFAR_NAPI |
@@ -144,7 +137,6 @@ static int gfar_poll(struct net_device *dev, int *budget); | |||
144 | #endif | 137 | #endif |
145 | int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); | 138 | int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); |
146 | static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length); | 139 | static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length); |
147 | static void gfar_phy_startup_timer(unsigned long data); | ||
148 | static void gfar_vlan_rx_register(struct net_device *netdev, | 140 | static void gfar_vlan_rx_register(struct net_device *netdev, |
149 | struct vlan_group *grp); | 141 | struct vlan_group *grp); |
150 | static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); | 142 | static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); |
@@ -162,6 +154,9 @@ int gfar_uses_fcb(struct gfar_private *priv) | |||
162 | else | 154 | else |
163 | return 0; | 155 | return 0; |
164 | } | 156 | } |
157 | |||
158 | /* Set up the ethernet device structure, private data, | ||
159 | * and anything else we need before we start */ | ||
165 | static int gfar_probe(struct device *device) | 160 | static int gfar_probe(struct device *device) |
166 | { | 161 | { |
167 | u32 tempval; | 162 | u32 tempval; |
@@ -175,7 +170,7 @@ static int gfar_probe(struct device *device) | |||
175 | 170 | ||
176 | einfo = (struct gianfar_platform_data *) pdev->dev.platform_data; | 171 | einfo = (struct gianfar_platform_data *) pdev->dev.platform_data; |
177 | 172 | ||
178 | if (einfo == NULL) { | 173 | if (NULL == einfo) { |
179 | printk(KERN_ERR "gfar %d: Missing additional data!\n", | 174 | printk(KERN_ERR "gfar %d: Missing additional data!\n", |
180 | pdev->id); | 175 | pdev->id); |
181 | 176 | ||
@@ -185,7 +180,7 @@ static int gfar_probe(struct device *device) | |||
185 | /* Create an ethernet device instance */ | 180 | /* Create an ethernet device instance */ |
186 | dev = alloc_etherdev(sizeof (*priv)); | 181 | dev = alloc_etherdev(sizeof (*priv)); |
187 | 182 | ||
188 | if (dev == NULL) | 183 | if (NULL == dev) |
189 | return -ENOMEM; | 184 | return -ENOMEM; |
190 | 185 | ||
191 | priv = netdev_priv(dev); | 186 | priv = netdev_priv(dev); |
@@ -207,20 +202,11 @@ static int gfar_probe(struct device *device) | |||
207 | priv->regs = (struct gfar *) | 202 | priv->regs = (struct gfar *) |
208 | ioremap(r->start, sizeof (struct gfar)); | 203 | ioremap(r->start, sizeof (struct gfar)); |
209 | 204 | ||
210 | if (priv->regs == NULL) { | 205 | if (NULL == priv->regs) { |
211 | err = -ENOMEM; | 206 | err = -ENOMEM; |
212 | goto regs_fail; | 207 | goto regs_fail; |
213 | } | 208 | } |
214 | 209 | ||
215 | /* Set the PHY base address */ | ||
216 | priv->phyregs = (struct gfar *) | ||
217 | ioremap(einfo->phy_reg_addr, sizeof (struct gfar)); | ||
218 | |||
219 | if (priv->phyregs == NULL) { | ||
220 | err = -ENOMEM; | ||
221 | goto phy_regs_fail; | ||
222 | } | ||
223 | |||
224 | spin_lock_init(&priv->lock); | 210 | spin_lock_init(&priv->lock); |
225 | 211 | ||
226 | dev_set_drvdata(device, dev); | 212 | dev_set_drvdata(device, dev); |
@@ -386,12 +372,10 @@ static int gfar_probe(struct device *device) | |||
386 | return 0; | 372 | return 0; |
387 | 373 | ||
388 | register_fail: | 374 | register_fail: |
389 | iounmap((void *) priv->phyregs); | ||
390 | phy_regs_fail: | ||
391 | iounmap((void *) priv->regs); | 375 | iounmap((void *) priv->regs); |
392 | regs_fail: | 376 | regs_fail: |
393 | free_netdev(dev); | 377 | free_netdev(dev); |
394 | return -ENOMEM; | 378 | return err; |
395 | } | 379 | } |
396 | 380 | ||
397 | static int gfar_remove(struct device *device) | 381 | static int gfar_remove(struct device *device) |
@@ -402,108 +386,41 @@ static int gfar_remove(struct device *device) | |||
402 | dev_set_drvdata(device, NULL); | 386 | dev_set_drvdata(device, NULL); |
403 | 387 | ||
404 | iounmap((void *) priv->regs); | 388 | iounmap((void *) priv->regs); |
405 | iounmap((void *) priv->phyregs); | ||
406 | free_netdev(dev); | 389 | free_netdev(dev); |
407 | 390 | ||
408 | return 0; | 391 | return 0; |
409 | } | 392 | } |
410 | 393 | ||
411 | 394 | ||
412 | /* Configure the PHY for dev. | 395 | /* Initializes driver's PHY state, and attaches to the PHY. |
413 | * returns 0 if success. -1 if failure | 396 | * Returns 0 on success. |
414 | */ | 397 | */ |
415 | static int init_phy(struct net_device *dev) | 398 | static int init_phy(struct net_device *dev) |
416 | { | 399 | { |
417 | struct gfar_private *priv = netdev_priv(dev); | 400 | struct gfar_private *priv = netdev_priv(dev); |
418 | struct phy_info *curphy; | 401 | uint gigabit_support = |
419 | unsigned int timeout = PHY_INIT_TIMEOUT; | 402 | priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? |
420 | struct gfar *phyregs = priv->phyregs; | 403 | SUPPORTED_1000baseT_Full : 0; |
421 | struct gfar_mii_info *mii_info; | 404 | struct phy_device *phydev; |
422 | int err; | ||
423 | 405 | ||
424 | priv->oldlink = 0; | 406 | priv->oldlink = 0; |
425 | priv->oldspeed = 0; | 407 | priv->oldspeed = 0; |
426 | priv->oldduplex = -1; | 408 | priv->oldduplex = -1; |
427 | 409 | ||
428 | mii_info = kmalloc(sizeof(struct gfar_mii_info), | 410 | phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0); |
429 | GFP_KERNEL); | ||
430 | |||
431 | if(NULL == mii_info) { | ||
432 | if (netif_msg_ifup(priv)) | ||
433 | printk(KERN_ERR "%s: Could not allocate mii_info\n", | ||
434 | dev->name); | ||
435 | return -ENOMEM; | ||
436 | } | ||
437 | |||
438 | mii_info->speed = SPEED_1000; | ||
439 | mii_info->duplex = DUPLEX_FULL; | ||
440 | mii_info->pause = 0; | ||
441 | mii_info->link = 1; | ||
442 | |||
443 | mii_info->advertising = (ADVERTISED_10baseT_Half | | ||
444 | ADVERTISED_10baseT_Full | | ||
445 | ADVERTISED_100baseT_Half | | ||
446 | ADVERTISED_100baseT_Full | | ||
447 | ADVERTISED_1000baseT_Full); | ||
448 | mii_info->autoneg = 1; | ||
449 | 411 | ||
450 | spin_lock_init(&mii_info->mdio_lock); | 412 | if (IS_ERR(phydev)) { |
451 | 413 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); | |
452 | mii_info->mii_id = priv->einfo->phyid; | 414 | return PTR_ERR(phydev); |
453 | |||
454 | mii_info->dev = dev; | ||
455 | |||
456 | mii_info->mdio_read = &read_phy_reg; | ||
457 | mii_info->mdio_write = &write_phy_reg; | ||
458 | |||
459 | priv->mii_info = mii_info; | ||
460 | |||
461 | /* Reset the management interface */ | ||
462 | gfar_write(&phyregs->miimcfg, MIIMCFG_RESET); | ||
463 | |||
464 | /* Setup the MII Mgmt clock speed */ | ||
465 | gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE); | ||
466 | |||
467 | /* Wait until the bus is free */ | ||
468 | while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) && | ||
469 | timeout--) | ||
470 | cpu_relax(); | ||
471 | |||
472 | if(timeout <= 0) { | ||
473 | printk(KERN_ERR "%s: The MII Bus is stuck!\n", | ||
474 | dev->name); | ||
475 | err = -1; | ||
476 | goto bus_fail; | ||
477 | } | ||
478 | |||
479 | /* get info for this PHY */ | ||
480 | curphy = get_phy_info(priv->mii_info); | ||
481 | |||
482 | if (curphy == NULL) { | ||
483 | if (netif_msg_ifup(priv)) | ||
484 | printk(KERN_ERR "%s: No PHY found\n", dev->name); | ||
485 | err = -1; | ||
486 | goto no_phy; | ||
487 | } | 415 | } |
488 | 416 | ||
489 | mii_info->phyinfo = curphy; | 417 | /* Remove any features not supported by the controller */ |
418 | phydev->supported &= (GFAR_SUPPORTED | gigabit_support); | ||
419 | phydev->advertising = phydev->supported; | ||
490 | 420 | ||
491 | /* Run the commands which initialize the PHY */ | 421 | priv->phydev = phydev; |
492 | if(curphy->init) { | ||
493 | err = curphy->init(priv->mii_info); | ||
494 | |||
495 | if (err) | ||
496 | goto phy_init_fail; | ||
497 | } | ||
498 | 422 | ||
499 | return 0; | 423 | return 0; |
500 | |||
501 | phy_init_fail: | ||
502 | no_phy: | ||
503 | bus_fail: | ||
504 | kfree(mii_info); | ||
505 | |||
506 | return err; | ||
507 | } | 424 | } |
508 | 425 | ||
509 | static void init_registers(struct net_device *dev) | 426 | static void init_registers(struct net_device *dev) |
@@ -603,24 +520,13 @@ void stop_gfar(struct net_device *dev) | |||
603 | struct gfar *regs = priv->regs; | 520 | struct gfar *regs = priv->regs; |
604 | unsigned long flags; | 521 | unsigned long flags; |
605 | 522 | ||
523 | phy_stop(priv->phydev); | ||
524 | |||
606 | /* Lock it down */ | 525 | /* Lock it down */ |
607 | spin_lock_irqsave(&priv->lock, flags); | 526 | spin_lock_irqsave(&priv->lock, flags); |
608 | 527 | ||
609 | /* Tell the kernel the link is down */ | ||
610 | priv->mii_info->link = 0; | ||
611 | adjust_link(dev); | ||
612 | |||
613 | gfar_halt(dev); | 528 | gfar_halt(dev); |
614 | 529 | ||
615 | if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { | ||
616 | /* Clear any pending interrupts */ | ||
617 | mii_clear_phy_interrupt(priv->mii_info); | ||
618 | |||
619 | /* Disable PHY Interrupts */ | ||
620 | mii_configure_phy_interrupt(priv->mii_info, | ||
621 | MII_INTERRUPT_DISABLED); | ||
622 | } | ||
623 | |||
624 | spin_unlock_irqrestore(&priv->lock, flags); | 530 | spin_unlock_irqrestore(&priv->lock, flags); |
625 | 531 | ||
626 | /* Free the IRQs */ | 532 | /* Free the IRQs */ |
@@ -629,13 +535,7 @@ void stop_gfar(struct net_device *dev) | |||
629 | free_irq(priv->interruptTransmit, dev); | 535 | free_irq(priv->interruptTransmit, dev); |
630 | free_irq(priv->interruptReceive, dev); | 536 | free_irq(priv->interruptReceive, dev); |
631 | } else { | 537 | } else { |
632 | free_irq(priv->interruptTransmit, dev); | 538 | free_irq(priv->interruptTransmit, dev); |
633 | } | ||
634 | |||
635 | if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { | ||
636 | free_irq(priv->einfo->interruptPHY, dev); | ||
637 | } else { | ||
638 | del_timer_sync(&priv->phy_info_timer); | ||
639 | } | 539 | } |
640 | 540 | ||
641 | free_skb_resources(priv); | 541 | free_skb_resources(priv); |
@@ -649,7 +549,7 @@ void stop_gfar(struct net_device *dev) | |||
649 | 549 | ||
650 | /* If there are any tx skbs or rx skbs still around, free them. | 550 | /* If there are any tx skbs or rx skbs still around, free them. |
651 | * Then free tx_skbuff and rx_skbuff */ | 551 | * Then free tx_skbuff and rx_skbuff */ |
652 | void free_skb_resources(struct gfar_private *priv) | 552 | static void free_skb_resources(struct gfar_private *priv) |
653 | { | 553 | { |
654 | struct rxbd8 *rxbdp; | 554 | struct rxbd8 *rxbdp; |
655 | struct txbd8 *txbdp; | 555 | struct txbd8 *txbdp; |
@@ -770,7 +670,7 @@ int startup_gfar(struct net_device *dev) | |||
770 | (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) * | 670 | (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) * |
771 | priv->tx_ring_size, GFP_KERNEL); | 671 | priv->tx_ring_size, GFP_KERNEL); |
772 | 672 | ||
773 | if (priv->tx_skbuff == NULL) { | 673 | if (NULL == priv->tx_skbuff) { |
774 | if (netif_msg_ifup(priv)) | 674 | if (netif_msg_ifup(priv)) |
775 | printk(KERN_ERR "%s: Could not allocate tx_skbuff\n", | 675 | printk(KERN_ERR "%s: Could not allocate tx_skbuff\n", |
776 | dev->name); | 676 | dev->name); |
@@ -785,7 +685,7 @@ int startup_gfar(struct net_device *dev) | |||
785 | (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) * | 685 | (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) * |
786 | priv->rx_ring_size, GFP_KERNEL); | 686 | priv->rx_ring_size, GFP_KERNEL); |
787 | 687 | ||
788 | if (priv->rx_skbuff == NULL) { | 688 | if (NULL == priv->rx_skbuff) { |
789 | if (netif_msg_ifup(priv)) | 689 | if (netif_msg_ifup(priv)) |
790 | printk(KERN_ERR "%s: Could not allocate rx_skbuff\n", | 690 | printk(KERN_ERR "%s: Could not allocate rx_skbuff\n", |
791 | dev->name); | 691 | dev->name); |
@@ -879,13 +779,7 @@ int startup_gfar(struct net_device *dev) | |||
879 | } | 779 | } |
880 | } | 780 | } |
881 | 781 | ||
882 | /* Set up the PHY change work queue */ | 782 | phy_start(priv->phydev); |
883 | INIT_WORK(&priv->tq, gfar_phy_change, dev); | ||
884 | |||
885 | init_timer(&priv->phy_info_timer); | ||
886 | priv->phy_info_timer.function = &gfar_phy_startup_timer; | ||
887 | priv->phy_info_timer.data = (unsigned long) priv->mii_info; | ||
888 | mod_timer(&priv->phy_info_timer, jiffies + HZ); | ||
889 | 783 | ||
890 | /* Configure the coalescing support */ | 784 | /* Configure the coalescing support */ |
891 | if (priv->txcoalescing) | 785 | if (priv->txcoalescing) |
@@ -933,11 +827,6 @@ tx_skb_fail: | |||
933 | priv->tx_bd_base, | 827 | priv->tx_bd_base, |
934 | gfar_read(®s->tbase0)); | 828 | gfar_read(®s->tbase0)); |
935 | 829 | ||
936 | if (priv->mii_info->phyinfo->close) | ||
937 | priv->mii_info->phyinfo->close(priv->mii_info); | ||
938 | |||
939 | kfree(priv->mii_info); | ||
940 | |||
941 | return err; | 830 | return err; |
942 | } | 831 | } |
943 | 832 | ||
@@ -1035,7 +924,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1035 | txbdp->status &= TXBD_WRAP; | 924 | txbdp->status &= TXBD_WRAP; |
1036 | 925 | ||
1037 | /* Set up checksumming */ | 926 | /* Set up checksumming */ |
1038 | if ((dev->features & NETIF_F_IP_CSUM) | 927 | if ((dev->features & NETIF_F_IP_CSUM) |
1039 | && (CHECKSUM_HW == skb->ip_summed)) { | 928 | && (CHECKSUM_HW == skb->ip_summed)) { |
1040 | fcb = gfar_add_fcb(skb, txbdp); | 929 | fcb = gfar_add_fcb(skb, txbdp); |
1041 | gfar_tx_checksum(skb, fcb); | 930 | gfar_tx_checksum(skb, fcb); |
@@ -1103,11 +992,9 @@ static int gfar_close(struct net_device *dev) | |||
1103 | struct gfar_private *priv = netdev_priv(dev); | 992 | struct gfar_private *priv = netdev_priv(dev); |
1104 | stop_gfar(dev); | 993 | stop_gfar(dev); |
1105 | 994 | ||
1106 | /* Shutdown the PHY */ | 995 | /* Disconnect from the PHY */ |
1107 | if (priv->mii_info->phyinfo->close) | 996 | phy_disconnect(priv->phydev); |
1108 | priv->mii_info->phyinfo->close(priv->mii_info); | 997 | priv->phydev = NULL; |
1109 | |||
1110 | kfree(priv->mii_info); | ||
1111 | 998 | ||
1112 | netif_stop_queue(dev); | 999 | netif_stop_queue(dev); |
1113 | 1000 | ||
@@ -1343,7 +1230,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) | |||
1343 | while ((!skb) && timeout--) | 1230 | while ((!skb) && timeout--) |
1344 | skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT); | 1231 | skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT); |
1345 | 1232 | ||
1346 | if (skb == NULL) | 1233 | if (NULL == skb) |
1347 | return NULL; | 1234 | return NULL; |
1348 | 1235 | ||
1349 | /* We need the data buffer to be aligned properly. We will reserve | 1236 | /* We need the data buffer to be aligned properly. We will reserve |
@@ -1490,7 +1377,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, | |||
1490 | struct gfar_private *priv = netdev_priv(dev); | 1377 | struct gfar_private *priv = netdev_priv(dev); |
1491 | struct rxfcb *fcb = NULL; | 1378 | struct rxfcb *fcb = NULL; |
1492 | 1379 | ||
1493 | if (skb == NULL) { | 1380 | if (NULL == skb) { |
1494 | if (netif_msg_rx_err(priv)) | 1381 | if (netif_msg_rx_err(priv)) |
1495 | printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name); | 1382 | printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name); |
1496 | priv->stats.rx_dropped++; | 1383 | priv->stats.rx_dropped++; |
@@ -1718,131 +1605,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1718 | return IRQ_HANDLED; | 1605 | return IRQ_HANDLED; |
1719 | } | 1606 | } |
1720 | 1607 | ||
1721 | static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
1722 | { | ||
1723 | struct net_device *dev = (struct net_device *) dev_id; | ||
1724 | struct gfar_private *priv = netdev_priv(dev); | ||
1725 | |||
1726 | /* Clear the interrupt */ | ||
1727 | mii_clear_phy_interrupt(priv->mii_info); | ||
1728 | |||
1729 | /* Disable PHY interrupts */ | ||
1730 | mii_configure_phy_interrupt(priv->mii_info, | ||
1731 | MII_INTERRUPT_DISABLED); | ||
1732 | |||
1733 | /* Schedule the phy change */ | ||
1734 | schedule_work(&priv->tq); | ||
1735 | |||
1736 | return IRQ_HANDLED; | ||
1737 | } | ||
1738 | |||
1739 | /* Scheduled by the phy_interrupt/timer to handle PHY changes */ | ||
1740 | static void gfar_phy_change(void *data) | ||
1741 | { | ||
1742 | struct net_device *dev = (struct net_device *) data; | ||
1743 | struct gfar_private *priv = netdev_priv(dev); | ||
1744 | int result = 0; | ||
1745 | |||
1746 | /* Delay to give the PHY a chance to change the | ||
1747 | * register state */ | ||
1748 | msleep(1); | ||
1749 | |||
1750 | /* Update the link, speed, duplex */ | ||
1751 | result = priv->mii_info->phyinfo->read_status(priv->mii_info); | ||
1752 | |||
1753 | /* Adjust the known status as long as the link | ||
1754 | * isn't still coming up */ | ||
1755 | if((0 == result) || (priv->mii_info->link == 0)) | ||
1756 | adjust_link(dev); | ||
1757 | |||
1758 | /* Reenable interrupts, if needed */ | ||
1759 | if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) | ||
1760 | mii_configure_phy_interrupt(priv->mii_info, | ||
1761 | MII_INTERRUPT_ENABLED); | ||
1762 | } | ||
1763 | |||
1764 | /* Called every so often on systems that don't interrupt | ||
1765 | * the core for PHY changes */ | ||
1766 | static void gfar_phy_timer(unsigned long data) | ||
1767 | { | ||
1768 | struct net_device *dev = (struct net_device *) data; | ||
1769 | struct gfar_private *priv = netdev_priv(dev); | ||
1770 | |||
1771 | schedule_work(&priv->tq); | ||
1772 | |||
1773 | mod_timer(&priv->phy_info_timer, jiffies + | ||
1774 | GFAR_PHY_CHANGE_TIME * HZ); | ||
1775 | } | ||
1776 | |||
1777 | /* Keep trying aneg for some time | ||
1778 | * If, after GFAR_AN_TIMEOUT seconds, it has not | ||
1779 | * finished, we switch to forced. | ||
1780 | * Either way, once the process has completed, we either | ||
1781 | * request the interrupt, or switch the timer over to | ||
1782 | * using gfar_phy_timer to check status */ | ||
1783 | static void gfar_phy_startup_timer(unsigned long data) | ||
1784 | { | ||
1785 | int result; | ||
1786 | static int secondary = GFAR_AN_TIMEOUT; | ||
1787 | struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data; | ||
1788 | struct gfar_private *priv = netdev_priv(mii_info->dev); | ||
1789 | |||
1790 | /* Configure the Auto-negotiation */ | ||
1791 | result = mii_info->phyinfo->config_aneg(mii_info); | ||
1792 | |||
1793 | /* If autonegotiation failed to start, and | ||
1794 | * we haven't timed out, reset the timer, and return */ | ||
1795 | if (result && secondary--) { | ||
1796 | mod_timer(&priv->phy_info_timer, jiffies + HZ); | ||
1797 | return; | ||
1798 | } else if (result) { | ||
1799 | /* Couldn't start autonegotiation. | ||
1800 | * Try switching to forced */ | ||
1801 | mii_info->autoneg = 0; | ||
1802 | result = mii_info->phyinfo->config_aneg(mii_info); | ||
1803 | |||
1804 | /* Forcing failed! Give up */ | ||
1805 | if(result) { | ||
1806 | if (netif_msg_link(priv)) | ||
1807 | printk(KERN_ERR "%s: Forcing failed!\n", | ||
1808 | mii_info->dev->name); | ||
1809 | return; | ||
1810 | } | ||
1811 | } | ||
1812 | |||
1813 | /* Kill the timer so it can be restarted */ | ||
1814 | del_timer_sync(&priv->phy_info_timer); | ||
1815 | |||
1816 | /* Grab the PHY interrupt, if necessary/possible */ | ||
1817 | if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { | ||
1818 | if (request_irq(priv->einfo->interruptPHY, | ||
1819 | phy_interrupt, | ||
1820 | SA_SHIRQ, | ||
1821 | "phy_interrupt", | ||
1822 | mii_info->dev) < 0) { | ||
1823 | if (netif_msg_intr(priv)) | ||
1824 | printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n", | ||
1825 | mii_info->dev->name, | ||
1826 | priv->einfo->interruptPHY); | ||
1827 | } else { | ||
1828 | mii_configure_phy_interrupt(priv->mii_info, | ||
1829 | MII_INTERRUPT_ENABLED); | ||
1830 | return; | ||
1831 | } | ||
1832 | } | ||
1833 | |||
1834 | /* Start the timer again, this time in order to | ||
1835 | * handle a change in status */ | ||
1836 | init_timer(&priv->phy_info_timer); | ||
1837 | priv->phy_info_timer.function = &gfar_phy_timer; | ||
1838 | priv->phy_info_timer.data = (unsigned long) mii_info->dev; | ||
1839 | mod_timer(&priv->phy_info_timer, jiffies + | ||
1840 | GFAR_PHY_CHANGE_TIME * HZ); | ||
1841 | } | ||
1842 | |||
1843 | /* Called every time the controller might need to be made | 1608 | /* Called every time the controller might need to be made |
1844 | * aware of new link state. The PHY code conveys this | 1609 | * aware of new link state. The PHY code conveys this |
1845 | * information through variables in the priv structure, and this | 1610 | * information through variables in the phydev structure, and this |
1846 | * function converts those variables into the appropriate | 1611 | * function converts those variables into the appropriate |
1847 | * register values, and can bring down the device if needed. | 1612 | * register values, and can bring down the device if needed. |
1848 | */ | 1613 | */ |
@@ -1850,84 +1615,68 @@ static void adjust_link(struct net_device *dev) | |||
1850 | { | 1615 | { |
1851 | struct gfar_private *priv = netdev_priv(dev); | 1616 | struct gfar_private *priv = netdev_priv(dev); |
1852 | struct gfar *regs = priv->regs; | 1617 | struct gfar *regs = priv->regs; |
1853 | u32 tempval; | 1618 | unsigned long flags; |
1854 | struct gfar_mii_info *mii_info = priv->mii_info; | 1619 | struct phy_device *phydev = priv->phydev; |
1620 | int new_state = 0; | ||
1621 | |||
1622 | spin_lock_irqsave(&priv->lock, flags); | ||
1623 | if (phydev->link) { | ||
1624 | u32 tempval = gfar_read(®s->maccfg2); | ||
1855 | 1625 | ||
1856 | if (mii_info->link) { | ||
1857 | /* Now we make sure that we can be in full duplex mode. | 1626 | /* Now we make sure that we can be in full duplex mode. |
1858 | * If not, we operate in half-duplex mode. */ | 1627 | * If not, we operate in half-duplex mode. */ |
1859 | if (mii_info->duplex != priv->oldduplex) { | 1628 | if (phydev->duplex != priv->oldduplex) { |
1860 | if (!(mii_info->duplex)) { | 1629 | new_state = 1; |
1861 | tempval = gfar_read(®s->maccfg2); | 1630 | if (!(phydev->duplex)) |
1862 | tempval &= ~(MACCFG2_FULL_DUPLEX); | 1631 | tempval &= ~(MACCFG2_FULL_DUPLEX); |
1863 | gfar_write(®s->maccfg2, tempval); | 1632 | else |
1864 | |||
1865 | if (netif_msg_link(priv)) | ||
1866 | printk(KERN_INFO "%s: Half Duplex\n", | ||
1867 | dev->name); | ||
1868 | } else { | ||
1869 | tempval = gfar_read(®s->maccfg2); | ||
1870 | tempval |= MACCFG2_FULL_DUPLEX; | 1633 | tempval |= MACCFG2_FULL_DUPLEX; |
1871 | gfar_write(®s->maccfg2, tempval); | ||
1872 | 1634 | ||
1873 | if (netif_msg_link(priv)) | 1635 | priv->oldduplex = phydev->duplex; |
1874 | printk(KERN_INFO "%s: Full Duplex\n", | ||
1875 | dev->name); | ||
1876 | } | ||
1877 | |||
1878 | priv->oldduplex = mii_info->duplex; | ||
1879 | } | 1636 | } |
1880 | 1637 | ||
1881 | if (mii_info->speed != priv->oldspeed) { | 1638 | if (phydev->speed != priv->oldspeed) { |
1882 | switch (mii_info->speed) { | 1639 | new_state = 1; |
1640 | switch (phydev->speed) { | ||
1883 | case 1000: | 1641 | case 1000: |
1884 | tempval = gfar_read(®s->maccfg2); | ||
1885 | tempval = | 1642 | tempval = |
1886 | ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII); | 1643 | ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII); |
1887 | gfar_write(®s->maccfg2, tempval); | ||
1888 | break; | 1644 | break; |
1889 | case 100: | 1645 | case 100: |
1890 | case 10: | 1646 | case 10: |
1891 | tempval = gfar_read(®s->maccfg2); | ||
1892 | tempval = | 1647 | tempval = |
1893 | ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); | 1648 | ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); |
1894 | gfar_write(®s->maccfg2, tempval); | ||
1895 | break; | 1649 | break; |
1896 | default: | 1650 | default: |
1897 | if (netif_msg_link(priv)) | 1651 | if (netif_msg_link(priv)) |
1898 | printk(KERN_WARNING | 1652 | printk(KERN_WARNING |
1899 | "%s: Ack! Speed (%d) is not 10/100/1000!\n", | 1653 | "%s: Ack! Speed (%d) is not 10/100/1000!\n", |
1900 | dev->name, mii_info->speed); | 1654 | dev->name, phydev->speed); |
1901 | break; | 1655 | break; |
1902 | } | 1656 | } |
1903 | 1657 | ||
1904 | if (netif_msg_link(priv)) | 1658 | priv->oldspeed = phydev->speed; |
1905 | printk(KERN_INFO "%s: Speed %dBT\n", dev->name, | ||
1906 | mii_info->speed); | ||
1907 | |||
1908 | priv->oldspeed = mii_info->speed; | ||
1909 | } | 1659 | } |
1910 | 1660 | ||
1661 | gfar_write(®s->maccfg2, tempval); | ||
1662 | |||
1911 | if (!priv->oldlink) { | 1663 | if (!priv->oldlink) { |
1912 | if (netif_msg_link(priv)) | 1664 | new_state = 1; |
1913 | printk(KERN_INFO "%s: Link is up\n", dev->name); | ||
1914 | priv->oldlink = 1; | 1665 | priv->oldlink = 1; |
1915 | netif_carrier_on(dev); | ||
1916 | netif_schedule(dev); | 1666 | netif_schedule(dev); |
1917 | } | 1667 | } |
1918 | } else { | 1668 | } else if (priv->oldlink) { |
1919 | if (priv->oldlink) { | 1669 | new_state = 1; |
1920 | if (netif_msg_link(priv)) | 1670 | priv->oldlink = 0; |
1921 | printk(KERN_INFO "%s: Link is down\n", | 1671 | priv->oldspeed = 0; |
1922 | dev->name); | 1672 | priv->oldduplex = -1; |
1923 | priv->oldlink = 0; | ||
1924 | priv->oldspeed = 0; | ||
1925 | priv->oldduplex = -1; | ||
1926 | netif_carrier_off(dev); | ||
1927 | } | ||
1928 | } | 1673 | } |
1929 | } | ||
1930 | 1674 | ||
1675 | if (new_state && netif_msg_link(priv)) | ||
1676 | phy_print_status(phydev); | ||
1677 | |||
1678 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1679 | } | ||
1931 | 1680 | ||
1932 | /* Update the hash table based on the current list of multicast | 1681 | /* Update the hash table based on the current list of multicast |
1933 | * addresses we subscribe to. Also, change the promiscuity of | 1682 | * addresses we subscribe to. Also, change the promiscuity of |
@@ -2122,12 +1871,23 @@ static struct device_driver gfar_driver = { | |||
2122 | 1871 | ||
2123 | static int __init gfar_init(void) | 1872 | static int __init gfar_init(void) |
2124 | { | 1873 | { |
2125 | return driver_register(&gfar_driver); | 1874 | int err = gfar_mdio_init(); |
1875 | |||
1876 | if (err) | ||
1877 | return err; | ||
1878 | |||
1879 | err = driver_register(&gfar_driver); | ||
1880 | |||
1881 | if (err) | ||
1882 | gfar_mdio_exit(); | ||
1883 | |||
1884 | return err; | ||
2126 | } | 1885 | } |
2127 | 1886 | ||
2128 | static void __exit gfar_exit(void) | 1887 | static void __exit gfar_exit(void) |
2129 | { | 1888 | { |
2130 | driver_unregister(&gfar_driver); | 1889 | driver_unregister(&gfar_driver); |
1890 | gfar_mdio_exit(); | ||
2131 | } | 1891 | } |
2132 | 1892 | ||
2133 | module_init(gfar_init); | 1893 | module_init(gfar_init); |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 28af087d9fbb..c77ca6c0d04a 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -17,7 +17,6 @@ | |||
17 | * | 17 | * |
18 | * Still left to do: | 18 | * Still left to do: |
19 | * -Add support for module parameters | 19 | * -Add support for module parameters |
20 | * -Add support for ethtool -s | ||
21 | * -Add patch for ethtool phys id | 20 | * -Add patch for ethtool phys id |
22 | */ | 21 | */ |
23 | #ifndef __GIANFAR_H | 22 | #ifndef __GIANFAR_H |
@@ -37,7 +36,8 @@ | |||
37 | #include <linux/skbuff.h> | 36 | #include <linux/skbuff.h> |
38 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
39 | #include <linux/mm.h> | 38 | #include <linux/mm.h> |
40 | #include <linux/fsl_devices.h> | 39 | #include <linux/mii.h> |
40 | #include <linux/phy.h> | ||
41 | 41 | ||
42 | #include <asm/io.h> | 42 | #include <asm/io.h> |
43 | #include <asm/irq.h> | 43 | #include <asm/irq.h> |
@@ -48,7 +48,8 @@ | |||
48 | #include <linux/workqueue.h> | 48 | #include <linux/workqueue.h> |
49 | #include <linux/ethtool.h> | 49 | #include <linux/ethtool.h> |
50 | #include <linux/netdevice.h> | 50 | #include <linux/netdevice.h> |
51 | #include "gianfar_phy.h" | 51 | #include <linux/fsl_devices.h> |
52 | #include "gianfar_mii.h" | ||
52 | 53 | ||
53 | /* The maximum number of packets to be handled in one call of gfar_poll */ | 54 | /* The maximum number of packets to be handled in one call of gfar_poll */ |
54 | #define GFAR_DEV_WEIGHT 64 | 55 | #define GFAR_DEV_WEIGHT 64 |
@@ -73,7 +74,7 @@ | |||
73 | #define PHY_INIT_TIMEOUT 100000 | 74 | #define PHY_INIT_TIMEOUT 100000 |
74 | #define GFAR_PHY_CHANGE_TIME 2 | 75 | #define GFAR_PHY_CHANGE_TIME 2 |
75 | 76 | ||
76 | #define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, " | 77 | #define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.2, " |
77 | #define DRV_NAME "gfar-enet" | 78 | #define DRV_NAME "gfar-enet" |
78 | extern const char gfar_driver_name[]; | 79 | extern const char gfar_driver_name[]; |
79 | extern const char gfar_driver_version[]; | 80 | extern const char gfar_driver_version[]; |
@@ -578,12 +579,7 @@ struct gfar { | |||
578 | u32 hafdup; /* 0x.50c - Half Duplex Register */ | 579 | u32 hafdup; /* 0x.50c - Half Duplex Register */ |
579 | u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */ | 580 | u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */ |
580 | u8 res18[12]; | 581 | u8 res18[12]; |
581 | u32 miimcfg; /* 0x.520 - MII Management Configuration Register */ | 582 | u8 gfar_mii_regs[24]; /* See gianfar_phy.h */ |
582 | u32 miimcom; /* 0x.524 - MII Management Command Register */ | ||
583 | u32 miimadd; /* 0x.528 - MII Management Address Register */ | ||
584 | u32 miimcon; /* 0x.52c - MII Management Control Register */ | ||
585 | u32 miimstat; /* 0x.530 - MII Management Status Register */ | ||
586 | u32 miimind; /* 0x.534 - MII Management Indicator Register */ | ||
587 | u8 res19[4]; | 583 | u8 res19[4]; |
588 | u32 ifstat; /* 0x.53c - Interface Status Register */ | 584 | u32 ifstat; /* 0x.53c - Interface Status Register */ |
589 | u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */ | 585 | u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */ |
@@ -688,9 +684,6 @@ struct gfar_private { | |||
688 | struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */ | 684 | struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */ |
689 | u32 *hash_regs[16]; | 685 | u32 *hash_regs[16]; |
690 | int hash_width; | 686 | int hash_width; |
691 | struct gfar *phyregs; | ||
692 | struct work_struct tq; | ||
693 | struct timer_list phy_info_timer; | ||
694 | struct net_device_stats stats; /* linux network statistics */ | 687 | struct net_device_stats stats; /* linux network statistics */ |
695 | struct gfar_extra_stats extra_stats; | 688 | struct gfar_extra_stats extra_stats; |
696 | spinlock_t lock; | 689 | spinlock_t lock; |
@@ -710,7 +703,8 @@ struct gfar_private { | |||
710 | unsigned int interruptError; | 703 | unsigned int interruptError; |
711 | struct gianfar_platform_data *einfo; | 704 | struct gianfar_platform_data *einfo; |
712 | 705 | ||
713 | struct gfar_mii_info *mii_info; | 706 | struct phy_device *phydev; |
707 | struct mii_bus *mii_bus; | ||
714 | int oldspeed; | 708 | int oldspeed; |
715 | int oldduplex; | 709 | int oldduplex; |
716 | int oldlink; | 710 | int oldlink; |
@@ -732,4 +726,12 @@ extern inline void gfar_write(volatile unsigned *addr, u32 val) | |||
732 | 726 | ||
733 | extern struct ethtool_ops *gfar_op_array[]; | 727 | extern struct ethtool_ops *gfar_op_array[]; |
734 | 728 | ||
729 | extern irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs); | ||
730 | extern int startup_gfar(struct net_device *dev); | ||
731 | extern void stop_gfar(struct net_device *dev); | ||
732 | extern void gfar_halt(struct net_device *dev); | ||
733 | extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, | ||
734 | int enable, u32 regnum, u32 read); | ||
735 | void gfar_setup_stashing(struct net_device *dev); | ||
736 | |||
735 | #endif /* __GIANFAR_H */ | 737 | #endif /* __GIANFAR_H */ |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index a451de629197..68e3578e7613 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -39,17 +39,18 @@ | |||
39 | #include <asm/types.h> | 39 | #include <asm/types.h> |
40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
41 | #include <linux/ethtool.h> | 41 | #include <linux/ethtool.h> |
42 | #include <linux/mii.h> | ||
43 | #include <linux/phy.h> | ||
42 | 44 | ||
43 | #include "gianfar.h" | 45 | #include "gianfar.h" |
44 | 46 | ||
45 | #define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) | 47 | #define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) |
46 | 48 | ||
47 | extern int startup_gfar(struct net_device *dev); | ||
48 | extern void stop_gfar(struct net_device *dev); | ||
49 | extern void gfar_halt(struct net_device *dev); | ||
50 | extern void gfar_start(struct net_device *dev); | 49 | extern void gfar_start(struct net_device *dev); |
51 | extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); | 50 | extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); |
52 | 51 | ||
52 | #define GFAR_MAX_COAL_USECS 0xffff | ||
53 | #define GFAR_MAX_COAL_FRAMES 0xff | ||
53 | static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, | 54 | static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, |
54 | u64 * buf); | 55 | u64 * buf); |
55 | static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); | 56 | static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); |
@@ -182,38 +183,32 @@ static void gfar_gdrvinfo(struct net_device *dev, struct | |||
182 | drvinfo->eedump_len = 0; | 183 | drvinfo->eedump_len = 0; |
183 | } | 184 | } |
184 | 185 | ||
186 | |||
187 | static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
188 | { | ||
189 | struct gfar_private *priv = netdev_priv(dev); | ||
190 | struct phy_device *phydev = priv->phydev; | ||
191 | |||
192 | if (NULL == phydev) | ||
193 | return -ENODEV; | ||
194 | |||
195 | return phy_ethtool_sset(phydev, cmd); | ||
196 | } | ||
197 | |||
198 | |||
185 | /* Return the current settings in the ethtool_cmd structure */ | 199 | /* Return the current settings in the ethtool_cmd structure */ |
186 | static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) | 200 | static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) |
187 | { | 201 | { |
188 | struct gfar_private *priv = netdev_priv(dev); | 202 | struct gfar_private *priv = netdev_priv(dev); |
189 | uint gigabit_support = | 203 | struct phy_device *phydev = priv->phydev; |
190 | priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? | 204 | |
191 | SUPPORTED_1000baseT_Full : 0; | 205 | if (NULL == phydev) |
192 | uint gigabit_advert = | 206 | return -ENODEV; |
193 | priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? | 207 | |
194 | ADVERTISED_1000baseT_Full: 0; | ||
195 | |||
196 | cmd->supported = (SUPPORTED_10baseT_Half | ||
197 | | SUPPORTED_100baseT_Half | ||
198 | | SUPPORTED_100baseT_Full | ||
199 | | gigabit_support | SUPPORTED_Autoneg); | ||
200 | |||
201 | /* For now, we always advertise everything */ | ||
202 | cmd->advertising = (ADVERTISED_10baseT_Half | ||
203 | | ADVERTISED_100baseT_Half | ||
204 | | ADVERTISED_100baseT_Full | ||
205 | | gigabit_advert | ADVERTISED_Autoneg); | ||
206 | |||
207 | cmd->speed = priv->mii_info->speed; | ||
208 | cmd->duplex = priv->mii_info->duplex; | ||
209 | cmd->port = PORT_MII; | ||
210 | cmd->phy_address = priv->mii_info->mii_id; | ||
211 | cmd->transceiver = XCVR_EXTERNAL; | ||
212 | cmd->autoneg = AUTONEG_ENABLE; | ||
213 | cmd->maxtxpkt = priv->txcount; | 208 | cmd->maxtxpkt = priv->txcount; |
214 | cmd->maxrxpkt = priv->rxcount; | 209 | cmd->maxrxpkt = priv->rxcount; |
215 | 210 | ||
216 | return 0; | 211 | return phy_ethtool_gset(phydev, cmd); |
217 | } | 212 | } |
218 | 213 | ||
219 | /* Return the length of the register structure */ | 214 | /* Return the length of the register structure */ |
@@ -241,14 +236,14 @@ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int use | |||
241 | unsigned int count; | 236 | unsigned int count; |
242 | 237 | ||
243 | /* The timer is different, depending on the interface speed */ | 238 | /* The timer is different, depending on the interface speed */ |
244 | switch (priv->mii_info->speed) { | 239 | switch (priv->phydev->speed) { |
245 | case 1000: | 240 | case SPEED_1000: |
246 | count = GFAR_GBIT_TIME; | 241 | count = GFAR_GBIT_TIME; |
247 | break; | 242 | break; |
248 | case 100: | 243 | case SPEED_100: |
249 | count = GFAR_100_TIME; | 244 | count = GFAR_100_TIME; |
250 | break; | 245 | break; |
251 | case 10: | 246 | case SPEED_10: |
252 | default: | 247 | default: |
253 | count = GFAR_10_TIME; | 248 | count = GFAR_10_TIME; |
254 | break; | 249 | break; |
@@ -265,14 +260,14 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic | |||
265 | unsigned int count; | 260 | unsigned int count; |
266 | 261 | ||
267 | /* The timer is different, depending on the interface speed */ | 262 | /* The timer is different, depending on the interface speed */ |
268 | switch (priv->mii_info->speed) { | 263 | switch (priv->phydev->speed) { |
269 | case 1000: | 264 | case SPEED_1000: |
270 | count = GFAR_GBIT_TIME; | 265 | count = GFAR_GBIT_TIME; |
271 | break; | 266 | break; |
272 | case 100: | 267 | case SPEED_100: |
273 | count = GFAR_100_TIME; | 268 | count = GFAR_100_TIME; |
274 | break; | 269 | break; |
275 | case 10: | 270 | case SPEED_10: |
276 | default: | 271 | default: |
277 | count = GFAR_10_TIME; | 272 | count = GFAR_10_TIME; |
278 | break; | 273 | break; |
@@ -292,6 +287,9 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals | |||
292 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) | 287 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) |
293 | return -EOPNOTSUPP; | 288 | return -EOPNOTSUPP; |
294 | 289 | ||
290 | if (NULL == priv->phydev) | ||
291 | return -ENODEV; | ||
292 | |||
295 | cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime); | 293 | cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime); |
296 | cvals->rx_max_coalesced_frames = priv->rxcount; | 294 | cvals->rx_max_coalesced_frames = priv->rxcount; |
297 | 295 | ||
@@ -348,6 +346,22 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals | |||
348 | else | 346 | else |
349 | priv->rxcoalescing = 1; | 347 | priv->rxcoalescing = 1; |
350 | 348 | ||
349 | if (NULL == priv->phydev) | ||
350 | return -ENODEV; | ||
351 | |||
352 | /* Check the bounds of the values */ | ||
353 | if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) { | ||
354 | pr_info("Coalescing is limited to %d microseconds\n", | ||
355 | GFAR_MAX_COAL_USECS); | ||
356 | return -EINVAL; | ||
357 | } | ||
358 | |||
359 | if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) { | ||
360 | pr_info("Coalescing is limited to %d frames\n", | ||
361 | GFAR_MAX_COAL_FRAMES); | ||
362 | return -EINVAL; | ||
363 | } | ||
364 | |||
351 | priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs); | 365 | priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs); |
352 | priv->rxcount = cvals->rx_max_coalesced_frames; | 366 | priv->rxcount = cvals->rx_max_coalesced_frames; |
353 | 367 | ||
@@ -358,6 +372,19 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals | |||
358 | else | 372 | else |
359 | priv->txcoalescing = 1; | 373 | priv->txcoalescing = 1; |
360 | 374 | ||
375 | /* Check the bounds of the values */ | ||
376 | if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) { | ||
377 | pr_info("Coalescing is limited to %d microseconds\n", | ||
378 | GFAR_MAX_COAL_USECS); | ||
379 | return -EINVAL; | ||
380 | } | ||
381 | |||
382 | if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) { | ||
383 | pr_info("Coalescing is limited to %d frames\n", | ||
384 | GFAR_MAX_COAL_FRAMES); | ||
385 | return -EINVAL; | ||
386 | } | ||
387 | |||
361 | priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs); | 388 | priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs); |
362 | priv->txcount = cvals->tx_max_coalesced_frames; | 389 | priv->txcount = cvals->tx_max_coalesced_frames; |
363 | 390 | ||
@@ -536,6 +563,7 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data) | |||
536 | 563 | ||
537 | struct ethtool_ops gfar_ethtool_ops = { | 564 | struct ethtool_ops gfar_ethtool_ops = { |
538 | .get_settings = gfar_gsettings, | 565 | .get_settings = gfar_gsettings, |
566 | .set_settings = gfar_ssettings, | ||
539 | .get_drvinfo = gfar_gdrvinfo, | 567 | .get_drvinfo = gfar_gdrvinfo, |
540 | .get_regs_len = gfar_reglen, | 568 | .get_regs_len = gfar_reglen, |
541 | .get_regs = gfar_get_regs, | 569 | .get_regs = gfar_get_regs, |
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c new file mode 100644 index 000000000000..1eca1dbca7f1 --- /dev/null +++ b/drivers/net/gianfar_mii.c | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | * drivers/net/gianfar_mii.c | ||
3 | * | ||
4 | * Gianfar Ethernet Driver -- MIIM bus implementation | ||
5 | * Provides Bus interface for MIIM regs | ||
6 | * | ||
7 | * Author: Andy Fleming | ||
8 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | ||
9 | * | ||
10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/config.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/unistd.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/netdevice.h> | ||
30 | #include <linux/etherdevice.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | #include <linux/mm.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/version.h> | ||
36 | #include <asm/ocp.h> | ||
37 | #include <linux/crc32.h> | ||
38 | #include <linux/mii.h> | ||
39 | #include <linux/phy.h> | ||
40 | |||
41 | #include <asm/io.h> | ||
42 | #include <asm/irq.h> | ||
43 | #include <asm/uaccess.h> | ||
44 | |||
45 | #include "gianfar.h" | ||
46 | #include "gianfar_mii.h" | ||
47 | |||
48 | /* Write value to the PHY at mii_id at register regnum, | ||
49 | * on the bus, waiting until the write is done before returning. | ||
50 | * All PHY configuration is done through the TSEC1 MIIM regs */ | ||
51 | int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) | ||
52 | { | ||
53 | struct gfar_mii *regs = bus->priv; | ||
54 | |||
55 | /* Set the PHY address and the register address we want to write */ | ||
56 | gfar_write(®s->miimadd, (mii_id << 8) | regnum); | ||
57 | |||
58 | /* Write out the value we want */ | ||
59 | gfar_write(®s->miimcon, value); | ||
60 | |||
61 | /* Wait for the transaction to finish */ | ||
62 | while (gfar_read(®s->miimind) & MIIMIND_BUSY) | ||
63 | cpu_relax(); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | /* Read the bus for PHY at addr mii_id, register regnum, and | ||
69 | * return the value. Clears miimcom first. All PHY | ||
70 | * configuration has to be done through the TSEC1 MIIM regs */ | ||
71 | int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | ||
72 | { | ||
73 | struct gfar_mii *regs = bus->priv; | ||
74 | u16 value; | ||
75 | |||
76 | /* Set the PHY address and the register address we want to read */ | ||
77 | gfar_write(®s->miimadd, (mii_id << 8) | regnum); | ||
78 | |||
79 | /* Clear miimcom, and then initiate a read */ | ||
80 | gfar_write(®s->miimcom, 0); | ||
81 | gfar_write(®s->miimcom, MII_READ_COMMAND); | ||
82 | |||
83 | /* Wait for the transaction to finish */ | ||
84 | while (gfar_read(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) | ||
85 | cpu_relax(); | ||
86 | |||
87 | /* Grab the value of the register from miimstat */ | ||
88 | value = gfar_read(®s->miimstat); | ||
89 | |||
90 | return value; | ||
91 | } | ||
92 | |||
93 | |||
94 | /* Reset the MIIM registers, and wait for the bus to free */ | ||
95 | int gfar_mdio_reset(struct mii_bus *bus) | ||
96 | { | ||
97 | struct gfar_mii *regs = bus->priv; | ||
98 | unsigned int timeout = PHY_INIT_TIMEOUT; | ||
99 | |||
100 | spin_lock_bh(&bus->mdio_lock); | ||
101 | |||
102 | /* Reset the management interface */ | ||
103 | gfar_write(®s->miimcfg, MIIMCFG_RESET); | ||
104 | |||
105 | /* Setup the MII Mgmt clock speed */ | ||
106 | gfar_write(®s->miimcfg, MIIMCFG_INIT_VALUE); | ||
107 | |||
108 | /* Wait until the bus is free */ | ||
109 | while ((gfar_read(®s->miimind) & MIIMIND_BUSY) && | ||
110 | timeout--) | ||
111 | cpu_relax(); | ||
112 | |||
113 | spin_unlock_bh(&bus->mdio_lock); | ||
114 | |||
115 | if(timeout <= 0) { | ||
116 | printk(KERN_ERR "%s: The MII Bus is stuck!\n", | ||
117 | bus->name); | ||
118 | return -EBUSY; | ||
119 | } | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | |||
125 | int gfar_mdio_probe(struct device *dev) | ||
126 | { | ||
127 | struct platform_device *pdev = to_platform_device(dev); | ||
128 | struct gianfar_mdio_data *pdata; | ||
129 | struct gfar_mii *regs; | ||
130 | struct mii_bus *new_bus; | ||
131 | int err = 0; | ||
132 | |||
133 | if (NULL == dev) | ||
134 | return -EINVAL; | ||
135 | |||
136 | new_bus = kmalloc(sizeof(struct mii_bus), GFP_KERNEL); | ||
137 | |||
138 | if (NULL == new_bus) | ||
139 | return -ENOMEM; | ||
140 | |||
141 | new_bus->name = "Gianfar MII Bus", | ||
142 | new_bus->read = &gfar_mdio_read, | ||
143 | new_bus->write = &gfar_mdio_write, | ||
144 | new_bus->reset = &gfar_mdio_reset, | ||
145 | new_bus->id = pdev->id; | ||
146 | |||
147 | pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data; | ||
148 | |||
149 | if (NULL == pdata) { | ||
150 | printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id); | ||
151 | return -ENODEV; | ||
152 | } | ||
153 | |||
154 | /* Set the PHY base address */ | ||
155 | regs = (struct gfar_mii *) ioremap(pdata->paddr, | ||
156 | sizeof (struct gfar_mii)); | ||
157 | |||
158 | if (NULL == regs) { | ||
159 | err = -ENOMEM; | ||
160 | goto reg_map_fail; | ||
161 | } | ||
162 | |||
163 | new_bus->priv = regs; | ||
164 | |||
165 | new_bus->irq = pdata->irq; | ||
166 | |||
167 | new_bus->dev = dev; | ||
168 | dev_set_drvdata(dev, new_bus); | ||
169 | |||
170 | err = mdiobus_register(new_bus); | ||
171 | |||
172 | if (0 != err) { | ||
173 | printk (KERN_ERR "%s: Cannot register as MDIO bus\n", | ||
174 | new_bus->name); | ||
175 | goto bus_register_fail; | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | |||
180 | bus_register_fail: | ||
181 | iounmap((void *) regs); | ||
182 | reg_map_fail: | ||
183 | kfree(new_bus); | ||
184 | |||
185 | return err; | ||
186 | } | ||
187 | |||
188 | |||
189 | int gfar_mdio_remove(struct device *dev) | ||
190 | { | ||
191 | struct mii_bus *bus = dev_get_drvdata(dev); | ||
192 | |||
193 | mdiobus_unregister(bus); | ||
194 | |||
195 | dev_set_drvdata(dev, NULL); | ||
196 | |||
197 | iounmap((void *) (&bus->priv)); | ||
198 | bus->priv = NULL; | ||
199 | kfree(bus); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static struct device_driver gianfar_mdio_driver = { | ||
205 | .name = "fsl-gianfar_mdio", | ||
206 | .bus = &platform_bus_type, | ||
207 | .probe = gfar_mdio_probe, | ||
208 | .remove = gfar_mdio_remove, | ||
209 | }; | ||
210 | |||
211 | int __init gfar_mdio_init(void) | ||
212 | { | ||
213 | return driver_register(&gianfar_mdio_driver); | ||
214 | } | ||
215 | |||
216 | void __exit gfar_mdio_exit(void) | ||
217 | { | ||
218 | driver_unregister(&gianfar_mdio_driver); | ||
219 | } | ||
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h new file mode 100644 index 000000000000..56e5665d5c9b --- /dev/null +++ b/drivers/net/gianfar_mii.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * drivers/net/gianfar_mii.h | ||
3 | * | ||
4 | * Gianfar Ethernet Driver -- MII Management Bus Implementation | ||
5 | * Driver for the MDIO bus controller in the Gianfar register space | ||
6 | * | ||
7 | * Author: Andy Fleming | ||
8 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | ||
9 | * | ||
10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | #ifndef __GIANFAR_MII_H | ||
19 | #define __GIANFAR_MII_H | ||
20 | |||
21 | #define MIIMIND_BUSY 0x00000001 | ||
22 | #define MIIMIND_NOTVALID 0x00000004 | ||
23 | |||
24 | #define MII_READ_COMMAND 0x00000001 | ||
25 | |||
26 | #define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \ | ||
27 | | SUPPORTED_100baseT_Half \ | ||
28 | | SUPPORTED_100baseT_Full \ | ||
29 | | SUPPORTED_Autoneg \ | ||
30 | | SUPPORTED_MII) | ||
31 | |||
32 | struct gfar_mii { | ||
33 | u32 miimcfg; /* 0x.520 - MII Management Config Register */ | ||
34 | u32 miimcom; /* 0x.524 - MII Management Command Register */ | ||
35 | u32 miimadd; /* 0x.528 - MII Management Address Register */ | ||
36 | u32 miimcon; /* 0x.52c - MII Management Control Register */ | ||
37 | u32 miimstat; /* 0x.530 - MII Management Status Register */ | ||
38 | u32 miimind; /* 0x.534 - MII Management Indicator Register */ | ||
39 | }; | ||
40 | |||
41 | int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum); | ||
42 | int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); | ||
43 | int __init gfar_mdio_init(void); | ||
44 | void __exit gfar_mdio_exit(void); | ||
45 | #endif /* GIANFAR_PHY_H */ | ||
diff --git a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c deleted file mode 100644 index 7c965f268a82..000000000000 --- a/drivers/net/gianfar_phy.c +++ /dev/null | |||
@@ -1,661 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/net/gianfar_phy.c | ||
3 | * | ||
4 | * Gianfar Ethernet Driver -- PHY handling | ||
5 | * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560 | ||
6 | * Based on 8260_io/fcc_enet.c | ||
7 | * | ||
8 | * Author: Andy Fleming | ||
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | ||
10 | * | ||
11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/netdevice.h> | ||
30 | #include <linux/etherdevice.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | #include <linux/mm.h> | ||
34 | |||
35 | #include <asm/io.h> | ||
36 | #include <asm/irq.h> | ||
37 | #include <asm/uaccess.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/version.h> | ||
40 | #include <linux/crc32.h> | ||
41 | #include <linux/mii.h> | ||
42 | |||
43 | #include "gianfar.h" | ||
44 | #include "gianfar_phy.h" | ||
45 | |||
46 | static void config_genmii_advert(struct gfar_mii_info *mii_info); | ||
47 | static void genmii_setup_forced(struct gfar_mii_info *mii_info); | ||
48 | static void genmii_restart_aneg(struct gfar_mii_info *mii_info); | ||
49 | static int gbit_config_aneg(struct gfar_mii_info *mii_info); | ||
50 | static int genmii_config_aneg(struct gfar_mii_info *mii_info); | ||
51 | static int genmii_update_link(struct gfar_mii_info *mii_info); | ||
52 | static int genmii_read_status(struct gfar_mii_info *mii_info); | ||
53 | u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum); | ||
54 | void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val); | ||
55 | |||
56 | /* Write value to the PHY for this device to the register at regnum, */ | ||
57 | /* waiting until the write is done before it returns. All PHY */ | ||
58 | /* configuration has to be done through the TSEC1 MIIM regs */ | ||
59 | void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value) | ||
60 | { | ||
61 | struct gfar_private *priv = netdev_priv(dev); | ||
62 | struct gfar *regbase = priv->phyregs; | ||
63 | |||
64 | /* Set the PHY address and the register address we want to write */ | ||
65 | gfar_write(®base->miimadd, (mii_id << 8) | regnum); | ||
66 | |||
67 | /* Write out the value we want */ | ||
68 | gfar_write(®base->miimcon, value); | ||
69 | |||
70 | /* Wait for the transaction to finish */ | ||
71 | while (gfar_read(®base->miimind) & MIIMIND_BUSY) | ||
72 | cpu_relax(); | ||
73 | } | ||
74 | |||
75 | /* Reads from register regnum in the PHY for device dev, */ | ||
76 | /* returning the value. Clears miimcom first. All PHY */ | ||
77 | /* configuration has to be done through the TSEC1 MIIM regs */ | ||
78 | int read_phy_reg(struct net_device *dev, int mii_id, int regnum) | ||
79 | { | ||
80 | struct gfar_private *priv = netdev_priv(dev); | ||
81 | struct gfar *regbase = priv->phyregs; | ||
82 | u16 value; | ||
83 | |||
84 | /* Set the PHY address and the register address we want to read */ | ||
85 | gfar_write(®base->miimadd, (mii_id << 8) | regnum); | ||
86 | |||
87 | /* Clear miimcom, and then initiate a read */ | ||
88 | gfar_write(®base->miimcom, 0); | ||
89 | gfar_write(®base->miimcom, MII_READ_COMMAND); | ||
90 | |||
91 | /* Wait for the transaction to finish */ | ||
92 | while (gfar_read(®base->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) | ||
93 | cpu_relax(); | ||
94 | |||
95 | /* Grab the value of the register from miimstat */ | ||
96 | value = gfar_read(®base->miimstat); | ||
97 | |||
98 | return value; | ||
99 | } | ||
100 | |||
101 | void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info) | ||
102 | { | ||
103 | if(mii_info->phyinfo->ack_interrupt) | ||
104 | mii_info->phyinfo->ack_interrupt(mii_info); | ||
105 | } | ||
106 | |||
107 | |||
108 | void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts) | ||
109 | { | ||
110 | mii_info->interrupts = interrupts; | ||
111 | if(mii_info->phyinfo->config_intr) | ||
112 | mii_info->phyinfo->config_intr(mii_info); | ||
113 | } | ||
114 | |||
115 | |||
116 | /* Writes MII_ADVERTISE with the appropriate values, after | ||
117 | * sanitizing advertise to make sure only supported features | ||
118 | * are advertised | ||
119 | */ | ||
120 | static void config_genmii_advert(struct gfar_mii_info *mii_info) | ||
121 | { | ||
122 | u32 advertise; | ||
123 | u16 adv; | ||
124 | |||
125 | /* Only allow advertising what this PHY supports */ | ||
126 | mii_info->advertising &= mii_info->phyinfo->features; | ||
127 | advertise = mii_info->advertising; | ||
128 | |||
129 | /* Setup standard advertisement */ | ||
130 | adv = phy_read(mii_info, MII_ADVERTISE); | ||
131 | adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); | ||
132 | if (advertise & ADVERTISED_10baseT_Half) | ||
133 | adv |= ADVERTISE_10HALF; | ||
134 | if (advertise & ADVERTISED_10baseT_Full) | ||
135 | adv |= ADVERTISE_10FULL; | ||
136 | if (advertise & ADVERTISED_100baseT_Half) | ||
137 | adv |= ADVERTISE_100HALF; | ||
138 | if (advertise & ADVERTISED_100baseT_Full) | ||
139 | adv |= ADVERTISE_100FULL; | ||
140 | phy_write(mii_info, MII_ADVERTISE, adv); | ||
141 | } | ||
142 | |||
143 | static void genmii_setup_forced(struct gfar_mii_info *mii_info) | ||
144 | { | ||
145 | u16 ctrl; | ||
146 | u32 features = mii_info->phyinfo->features; | ||
147 | |||
148 | ctrl = phy_read(mii_info, MII_BMCR); | ||
149 | |||
150 | ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE); | ||
151 | ctrl |= BMCR_RESET; | ||
152 | |||
153 | switch(mii_info->speed) { | ||
154 | case SPEED_1000: | ||
155 | if(features & (SUPPORTED_1000baseT_Half | ||
156 | | SUPPORTED_1000baseT_Full)) { | ||
157 | ctrl |= BMCR_SPEED1000; | ||
158 | break; | ||
159 | } | ||
160 | mii_info->speed = SPEED_100; | ||
161 | case SPEED_100: | ||
162 | if (features & (SUPPORTED_100baseT_Half | ||
163 | | SUPPORTED_100baseT_Full)) { | ||
164 | ctrl |= BMCR_SPEED100; | ||
165 | break; | ||
166 | } | ||
167 | mii_info->speed = SPEED_10; | ||
168 | case SPEED_10: | ||
169 | if (features & (SUPPORTED_10baseT_Half | ||
170 | | SUPPORTED_10baseT_Full)) | ||
171 | break; | ||
172 | default: /* Unsupported speed! */ | ||
173 | printk(KERN_ERR "%s: Bad speed!\n", | ||
174 | mii_info->dev->name); | ||
175 | break; | ||
176 | } | ||
177 | |||
178 | phy_write(mii_info, MII_BMCR, ctrl); | ||
179 | } | ||
180 | |||
181 | |||
182 | /* Enable and Restart Autonegotiation */ | ||
183 | static void genmii_restart_aneg(struct gfar_mii_info *mii_info) | ||
184 | { | ||
185 | u16 ctl; | ||
186 | |||
187 | ctl = phy_read(mii_info, MII_BMCR); | ||
188 | ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); | ||
189 | phy_write(mii_info, MII_BMCR, ctl); | ||
190 | } | ||
191 | |||
192 | |||
193 | static int gbit_config_aneg(struct gfar_mii_info *mii_info) | ||
194 | { | ||
195 | u16 adv; | ||
196 | u32 advertise; | ||
197 | |||
198 | if(mii_info->autoneg) { | ||
199 | /* Configure the ADVERTISE register */ | ||
200 | config_genmii_advert(mii_info); | ||
201 | advertise = mii_info->advertising; | ||
202 | |||
203 | adv = phy_read(mii_info, MII_1000BASETCONTROL); | ||
204 | adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP | | ||
205 | MII_1000BASETCONTROL_HALFDUPLEXCAP); | ||
206 | if (advertise & SUPPORTED_1000baseT_Half) | ||
207 | adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP; | ||
208 | if (advertise & SUPPORTED_1000baseT_Full) | ||
209 | adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP; | ||
210 | phy_write(mii_info, MII_1000BASETCONTROL, adv); | ||
211 | |||
212 | /* Start/Restart aneg */ | ||
213 | genmii_restart_aneg(mii_info); | ||
214 | } else | ||
215 | genmii_setup_forced(mii_info); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int marvell_config_aneg(struct gfar_mii_info *mii_info) | ||
221 | { | ||
222 | /* The Marvell PHY has an errata which requires | ||
223 | * that certain registers get written in order | ||
224 | * to restart autonegotiation */ | ||
225 | phy_write(mii_info, MII_BMCR, BMCR_RESET); | ||
226 | |||
227 | phy_write(mii_info, 0x1d, 0x1f); | ||
228 | phy_write(mii_info, 0x1e, 0x200c); | ||
229 | phy_write(mii_info, 0x1d, 0x5); | ||
230 | phy_write(mii_info, 0x1e, 0); | ||
231 | phy_write(mii_info, 0x1e, 0x100); | ||
232 | |||
233 | gbit_config_aneg(mii_info); | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | static int genmii_config_aneg(struct gfar_mii_info *mii_info) | ||
238 | { | ||
239 | if (mii_info->autoneg) { | ||
240 | config_genmii_advert(mii_info); | ||
241 | genmii_restart_aneg(mii_info); | ||
242 | } else | ||
243 | genmii_setup_forced(mii_info); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | |||
249 | static int genmii_update_link(struct gfar_mii_info *mii_info) | ||
250 | { | ||
251 | u16 status; | ||
252 | |||
253 | /* Do a fake read */ | ||
254 | phy_read(mii_info, MII_BMSR); | ||
255 | |||
256 | /* Read link and autonegotiation status */ | ||
257 | status = phy_read(mii_info, MII_BMSR); | ||
258 | if ((status & BMSR_LSTATUS) == 0) | ||
259 | mii_info->link = 0; | ||
260 | else | ||
261 | mii_info->link = 1; | ||
262 | |||
263 | /* If we are autonegotiating, and not done, | ||
264 | * return an error */ | ||
265 | if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE)) | ||
266 | return -EAGAIN; | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int genmii_read_status(struct gfar_mii_info *mii_info) | ||
272 | { | ||
273 | u16 status; | ||
274 | int err; | ||
275 | |||
276 | /* Update the link, but return if there | ||
277 | * was an error */ | ||
278 | err = genmii_update_link(mii_info); | ||
279 | if (err) | ||
280 | return err; | ||
281 | |||
282 | if (mii_info->autoneg) { | ||
283 | status = phy_read(mii_info, MII_LPA); | ||
284 | |||
285 | if (status & (LPA_10FULL | LPA_100FULL)) | ||
286 | mii_info->duplex = DUPLEX_FULL; | ||
287 | else | ||
288 | mii_info->duplex = DUPLEX_HALF; | ||
289 | if (status & (LPA_100FULL | LPA_100HALF)) | ||
290 | mii_info->speed = SPEED_100; | ||
291 | else | ||
292 | mii_info->speed = SPEED_10; | ||
293 | mii_info->pause = 0; | ||
294 | } | ||
295 | /* On non-aneg, we assume what we put in BMCR is the speed, | ||
296 | * though magic-aneg shouldn't prevent this case from occurring | ||
297 | */ | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | static int marvell_read_status(struct gfar_mii_info *mii_info) | ||
302 | { | ||
303 | u16 status; | ||
304 | int err; | ||
305 | |||
306 | /* Update the link, but return if there | ||
307 | * was an error */ | ||
308 | err = genmii_update_link(mii_info); | ||
309 | if (err) | ||
310 | return err; | ||
311 | |||
312 | /* If the link is up, read the speed and duplex */ | ||
313 | /* If we aren't autonegotiating, assume speeds | ||
314 | * are as set */ | ||
315 | if (mii_info->autoneg && mii_info->link) { | ||
316 | int speed; | ||
317 | status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS); | ||
318 | |||
319 | #if 0 | ||
320 | /* If speed and duplex aren't resolved, | ||
321 | * return an error. Isn't this handled | ||
322 | * by checking aneg? | ||
323 | */ | ||
324 | if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0) | ||
325 | return -EAGAIN; | ||
326 | #endif | ||
327 | |||
328 | /* Get the duplexity */ | ||
329 | if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX) | ||
330 | mii_info->duplex = DUPLEX_FULL; | ||
331 | else | ||
332 | mii_info->duplex = DUPLEX_HALF; | ||
333 | |||
334 | /* Get the speed */ | ||
335 | speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK; | ||
336 | switch(speed) { | ||
337 | case MII_M1011_PHY_SPEC_STATUS_1000: | ||
338 | mii_info->speed = SPEED_1000; | ||
339 | break; | ||
340 | case MII_M1011_PHY_SPEC_STATUS_100: | ||
341 | mii_info->speed = SPEED_100; | ||
342 | break; | ||
343 | default: | ||
344 | mii_info->speed = SPEED_10; | ||
345 | break; | ||
346 | } | ||
347 | mii_info->pause = 0; | ||
348 | } | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | |||
354 | static int cis820x_read_status(struct gfar_mii_info *mii_info) | ||
355 | { | ||
356 | u16 status; | ||
357 | int err; | ||
358 | |||
359 | /* Update the link, but return if there | ||
360 | * was an error */ | ||
361 | err = genmii_update_link(mii_info); | ||
362 | if (err) | ||
363 | return err; | ||
364 | |||
365 | /* If the link is up, read the speed and duplex */ | ||
366 | /* If we aren't autonegotiating, assume speeds | ||
367 | * are as set */ | ||
368 | if (mii_info->autoneg && mii_info->link) { | ||
369 | int speed; | ||
370 | |||
371 | status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT); | ||
372 | if (status & MII_CIS8201_AUXCONSTAT_DUPLEX) | ||
373 | mii_info->duplex = DUPLEX_FULL; | ||
374 | else | ||
375 | mii_info->duplex = DUPLEX_HALF; | ||
376 | |||
377 | speed = status & MII_CIS8201_AUXCONSTAT_SPEED; | ||
378 | |||
379 | switch (speed) { | ||
380 | case MII_CIS8201_AUXCONSTAT_GBIT: | ||
381 | mii_info->speed = SPEED_1000; | ||
382 | break; | ||
383 | case MII_CIS8201_AUXCONSTAT_100: | ||
384 | mii_info->speed = SPEED_100; | ||
385 | break; | ||
386 | default: | ||
387 | mii_info->speed = SPEED_10; | ||
388 | break; | ||
389 | } | ||
390 | } | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static int marvell_ack_interrupt(struct gfar_mii_info *mii_info) | ||
396 | { | ||
397 | /* Clear the interrupts by reading the reg */ | ||
398 | phy_read(mii_info, MII_M1011_IEVENT); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int marvell_config_intr(struct gfar_mii_info *mii_info) | ||
404 | { | ||
405 | if(mii_info->interrupts == MII_INTERRUPT_ENABLED) | ||
406 | phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT); | ||
407 | else | ||
408 | phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int cis820x_init(struct gfar_mii_info *mii_info) | ||
414 | { | ||
415 | phy_write(mii_info, MII_CIS8201_AUX_CONSTAT, | ||
416 | MII_CIS8201_AUXCONSTAT_INIT); | ||
417 | phy_write(mii_info, MII_CIS8201_EXT_CON1, | ||
418 | MII_CIS8201_EXTCON1_INIT); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info) | ||
424 | { | ||
425 | phy_read(mii_info, MII_CIS8201_ISTAT); | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int cis820x_config_intr(struct gfar_mii_info *mii_info) | ||
431 | { | ||
432 | if(mii_info->interrupts == MII_INTERRUPT_ENABLED) | ||
433 | phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK); | ||
434 | else | ||
435 | phy_write(mii_info, MII_CIS8201_IMASK, 0); | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | #define DM9161_DELAY 10 | ||
441 | |||
442 | static int dm9161_read_status(struct gfar_mii_info *mii_info) | ||
443 | { | ||
444 | u16 status; | ||
445 | int err; | ||
446 | |||
447 | /* Update the link, but return if there | ||
448 | * was an error */ | ||
449 | err = genmii_update_link(mii_info); | ||
450 | if (err) | ||
451 | return err; | ||
452 | |||
453 | /* If the link is up, read the speed and duplex */ | ||
454 | /* If we aren't autonegotiating, assume speeds | ||
455 | * are as set */ | ||
456 | if (mii_info->autoneg && mii_info->link) { | ||
457 | status = phy_read(mii_info, MII_DM9161_SCSR); | ||
458 | if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H)) | ||
459 | mii_info->speed = SPEED_100; | ||
460 | else | ||
461 | mii_info->speed = SPEED_10; | ||
462 | |||
463 | if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F)) | ||
464 | mii_info->duplex = DUPLEX_FULL; | ||
465 | else | ||
466 | mii_info->duplex = DUPLEX_HALF; | ||
467 | } | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | |||
473 | static int dm9161_config_aneg(struct gfar_mii_info *mii_info) | ||
474 | { | ||
475 | struct dm9161_private *priv = mii_info->priv; | ||
476 | |||
477 | if(0 == priv->resetdone) | ||
478 | return -EAGAIN; | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static void dm9161_timer(unsigned long data) | ||
484 | { | ||
485 | struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data; | ||
486 | struct dm9161_private *priv = mii_info->priv; | ||
487 | u16 status = phy_read(mii_info, MII_BMSR); | ||
488 | |||
489 | if (status & BMSR_ANEGCOMPLETE) { | ||
490 | priv->resetdone = 1; | ||
491 | } else | ||
492 | mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ); | ||
493 | } | ||
494 | |||
495 | static int dm9161_init(struct gfar_mii_info *mii_info) | ||
496 | { | ||
497 | struct dm9161_private *priv; | ||
498 | |||
499 | /* Allocate the private data structure */ | ||
500 | priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL); | ||
501 | |||
502 | if (NULL == priv) | ||
503 | return -ENOMEM; | ||
504 | |||
505 | mii_info->priv = priv; | ||
506 | |||
507 | /* Reset is not done yet */ | ||
508 | priv->resetdone = 0; | ||
509 | |||
510 | /* Isolate the PHY */ | ||
511 | phy_write(mii_info, MII_BMCR, BMCR_ISOLATE); | ||
512 | |||
513 | /* Do not bypass the scrambler/descrambler */ | ||
514 | phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT); | ||
515 | |||
516 | /* Clear 10BTCSR to default */ | ||
517 | phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT); | ||
518 | |||
519 | /* Reconnect the PHY, and enable Autonegotiation */ | ||
520 | phy_write(mii_info, MII_BMCR, BMCR_ANENABLE); | ||
521 | |||
522 | /* Start a timer for DM9161_DELAY seconds to wait | ||
523 | * for the PHY to be ready */ | ||
524 | init_timer(&priv->timer); | ||
525 | priv->timer.function = &dm9161_timer; | ||
526 | priv->timer.data = (unsigned long) mii_info; | ||
527 | mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ); | ||
528 | |||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | static void dm9161_close(struct gfar_mii_info *mii_info) | ||
533 | { | ||
534 | struct dm9161_private *priv = mii_info->priv; | ||
535 | |||
536 | del_timer_sync(&priv->timer); | ||
537 | kfree(priv); | ||
538 | } | ||
539 | |||
540 | #if 0 | ||
541 | static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info) | ||
542 | { | ||
543 | phy_read(mii_info, MII_DM9161_INTR); | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | #endif | ||
548 | |||
549 | /* Cicada 820x */ | ||
550 | static struct phy_info phy_info_cis820x = { | ||
551 | 0x000fc440, | ||
552 | "Cicada Cis8204", | ||
553 | 0x000fffc0, | ||
554 | .features = MII_GBIT_FEATURES, | ||
555 | .init = &cis820x_init, | ||
556 | .config_aneg = &gbit_config_aneg, | ||
557 | .read_status = &cis820x_read_status, | ||
558 | .ack_interrupt = &cis820x_ack_interrupt, | ||
559 | .config_intr = &cis820x_config_intr, | ||
560 | }; | ||
561 | |||
562 | static struct phy_info phy_info_dm9161 = { | ||
563 | .phy_id = 0x0181b880, | ||
564 | .name = "Davicom DM9161E", | ||
565 | .phy_id_mask = 0x0ffffff0, | ||
566 | .init = dm9161_init, | ||
567 | .config_aneg = dm9161_config_aneg, | ||
568 | .read_status = dm9161_read_status, | ||
569 | .close = dm9161_close, | ||
570 | }; | ||
571 | |||
572 | static struct phy_info phy_info_marvell = { | ||
573 | .phy_id = 0x01410c00, | ||
574 | .phy_id_mask = 0xffffff00, | ||
575 | .name = "Marvell 88E1101/88E1111", | ||
576 | .features = MII_GBIT_FEATURES, | ||
577 | .config_aneg = &marvell_config_aneg, | ||
578 | .read_status = &marvell_read_status, | ||
579 | .ack_interrupt = &marvell_ack_interrupt, | ||
580 | .config_intr = &marvell_config_intr, | ||
581 | }; | ||
582 | |||
583 | static struct phy_info phy_info_genmii= { | ||
584 | .phy_id = 0x00000000, | ||
585 | .phy_id_mask = 0x00000000, | ||
586 | .name = "Generic MII", | ||
587 | .features = MII_BASIC_FEATURES, | ||
588 | .config_aneg = genmii_config_aneg, | ||
589 | .read_status = genmii_read_status, | ||
590 | }; | ||
591 | |||
592 | static struct phy_info *phy_info[] = { | ||
593 | &phy_info_cis820x, | ||
594 | &phy_info_marvell, | ||
595 | &phy_info_dm9161, | ||
596 | &phy_info_genmii, | ||
597 | NULL | ||
598 | }; | ||
599 | |||
600 | u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum) | ||
601 | { | ||
602 | u16 retval; | ||
603 | unsigned long flags; | ||
604 | |||
605 | spin_lock_irqsave(&mii_info->mdio_lock, flags); | ||
606 | retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum); | ||
607 | spin_unlock_irqrestore(&mii_info->mdio_lock, flags); | ||
608 | |||
609 | return retval; | ||
610 | } | ||
611 | |||
612 | void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val) | ||
613 | { | ||
614 | unsigned long flags; | ||
615 | |||
616 | spin_lock_irqsave(&mii_info->mdio_lock, flags); | ||
617 | mii_info->mdio_write(mii_info->dev, | ||
618 | mii_info->mii_id, | ||
619 | regnum, val); | ||
620 | spin_unlock_irqrestore(&mii_info->mdio_lock, flags); | ||
621 | } | ||
622 | |||
623 | /* Use the PHY ID registers to determine what type of PHY is attached | ||
624 | * to device dev. return a struct phy_info structure describing that PHY | ||
625 | */ | ||
626 | struct phy_info * get_phy_info(struct gfar_mii_info *mii_info) | ||
627 | { | ||
628 | u16 phy_reg; | ||
629 | u32 phy_ID; | ||
630 | int i; | ||
631 | struct phy_info *theInfo = NULL; | ||
632 | struct net_device *dev = mii_info->dev; | ||
633 | |||
634 | /* Grab the bits from PHYIR1, and put them in the upper half */ | ||
635 | phy_reg = phy_read(mii_info, MII_PHYSID1); | ||
636 | phy_ID = (phy_reg & 0xffff) << 16; | ||
637 | |||
638 | /* Grab the bits from PHYIR2, and put them in the lower half */ | ||
639 | phy_reg = phy_read(mii_info, MII_PHYSID2); | ||
640 | phy_ID |= (phy_reg & 0xffff); | ||
641 | |||
642 | /* loop through all the known PHY types, and find one that */ | ||
643 | /* matches the ID we read from the PHY. */ | ||
644 | for (i = 0; phy_info[i]; i++) | ||
645 | if (phy_info[i]->phy_id == | ||
646 | (phy_ID & phy_info[i]->phy_id_mask)) { | ||
647 | theInfo = phy_info[i]; | ||
648 | break; | ||
649 | } | ||
650 | |||
651 | /* This shouldn't happen, as we have generic PHY support */ | ||
652 | if (theInfo == NULL) { | ||
653 | printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID); | ||
654 | return NULL; | ||
655 | } else { | ||
656 | printk("%s: PHY is %s (%x)\n", dev->name, theInfo->name, | ||
657 | phy_ID); | ||
658 | } | ||
659 | |||
660 | return theInfo; | ||
661 | } | ||
diff --git a/drivers/net/gianfar_phy.h b/drivers/net/gianfar_phy.h deleted file mode 100644 index 1e9b3abf1e6d..000000000000 --- a/drivers/net/gianfar_phy.h +++ /dev/null | |||
@@ -1,213 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/net/gianfar_phy.h | ||
3 | * | ||
4 | * Gianfar Ethernet Driver -- PHY handling | ||
5 | * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560 | ||
6 | * Based on 8260_io/fcc_enet.c | ||
7 | * | ||
8 | * Author: Andy Fleming | ||
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | ||
10 | * | ||
11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | * | ||
18 | */ | ||
19 | #ifndef __GIANFAR_PHY_H | ||
20 | #define __GIANFAR_PHY_H | ||
21 | |||
22 | #define MII_end ((u32)-2) | ||
23 | #define MII_read ((u32)-1) | ||
24 | |||
25 | #define MIIMIND_BUSY 0x00000001 | ||
26 | #define MIIMIND_NOTVALID 0x00000004 | ||
27 | |||
28 | #define GFAR_AN_TIMEOUT 2000 | ||
29 | |||
30 | /* 1000BT control (Marvell & BCM54xx at least) */ | ||
31 | #define MII_1000BASETCONTROL 0x09 | ||
32 | #define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200 | ||
33 | #define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100 | ||
34 | |||
35 | /* Cicada Extended Control Register 1 */ | ||
36 | #define MII_CIS8201_EXT_CON1 0x17 | ||
37 | #define MII_CIS8201_EXTCON1_INIT 0x0000 | ||
38 | |||
39 | /* Cicada Interrupt Mask Register */ | ||
40 | #define MII_CIS8201_IMASK 0x19 | ||
41 | #define MII_CIS8201_IMASK_IEN 0x8000 | ||
42 | #define MII_CIS8201_IMASK_SPEED 0x4000 | ||
43 | #define MII_CIS8201_IMASK_LINK 0x2000 | ||
44 | #define MII_CIS8201_IMASK_DUPLEX 0x1000 | ||
45 | #define MII_CIS8201_IMASK_MASK 0xf000 | ||
46 | |||
47 | /* Cicada Interrupt Status Register */ | ||
48 | #define MII_CIS8201_ISTAT 0x1a | ||
49 | #define MII_CIS8201_ISTAT_STATUS 0x8000 | ||
50 | #define MII_CIS8201_ISTAT_SPEED 0x4000 | ||
51 | #define MII_CIS8201_ISTAT_LINK 0x2000 | ||
52 | #define MII_CIS8201_ISTAT_DUPLEX 0x1000 | ||
53 | |||
54 | /* Cicada Auxiliary Control/Status Register */ | ||
55 | #define MII_CIS8201_AUX_CONSTAT 0x1c | ||
56 | #define MII_CIS8201_AUXCONSTAT_INIT 0x0004 | ||
57 | #define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020 | ||
58 | #define MII_CIS8201_AUXCONSTAT_SPEED 0x0018 | ||
59 | #define MII_CIS8201_AUXCONSTAT_GBIT 0x0010 | ||
60 | #define MII_CIS8201_AUXCONSTAT_100 0x0008 | ||
61 | |||
62 | /* 88E1011 PHY Status Register */ | ||
63 | #define MII_M1011_PHY_SPEC_STATUS 0x11 | ||
64 | #define MII_M1011_PHY_SPEC_STATUS_1000 0x8000 | ||
65 | #define MII_M1011_PHY_SPEC_STATUS_100 0x4000 | ||
66 | #define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000 | ||
67 | #define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000 | ||
68 | #define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800 | ||
69 | #define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400 | ||
70 | |||
71 | #define MII_M1011_IEVENT 0x13 | ||
72 | #define MII_M1011_IEVENT_CLEAR 0x0000 | ||
73 | |||
74 | #define MII_M1011_IMASK 0x12 | ||
75 | #define MII_M1011_IMASK_INIT 0x6400 | ||
76 | #define MII_M1011_IMASK_CLEAR 0x0000 | ||
77 | |||
78 | #define MII_DM9161_SCR 0x10 | ||
79 | #define MII_DM9161_SCR_INIT 0x0610 | ||
80 | |||
81 | /* DM9161 Specified Configuration and Status Register */ | ||
82 | #define MII_DM9161_SCSR 0x11 | ||
83 | #define MII_DM9161_SCSR_100F 0x8000 | ||
84 | #define MII_DM9161_SCSR_100H 0x4000 | ||
85 | #define MII_DM9161_SCSR_10F 0x2000 | ||
86 | #define MII_DM9161_SCSR_10H 0x1000 | ||
87 | |||
88 | /* DM9161 Interrupt Register */ | ||
89 | #define MII_DM9161_INTR 0x15 | ||
90 | #define MII_DM9161_INTR_PEND 0x8000 | ||
91 | #define MII_DM9161_INTR_DPLX_MASK 0x0800 | ||
92 | #define MII_DM9161_INTR_SPD_MASK 0x0400 | ||
93 | #define MII_DM9161_INTR_LINK_MASK 0x0200 | ||
94 | #define MII_DM9161_INTR_MASK 0x0100 | ||
95 | #define MII_DM9161_INTR_DPLX_CHANGE 0x0010 | ||
96 | #define MII_DM9161_INTR_SPD_CHANGE 0x0008 | ||
97 | #define MII_DM9161_INTR_LINK_CHANGE 0x0004 | ||
98 | #define MII_DM9161_INTR_INIT 0x0000 | ||
99 | #define MII_DM9161_INTR_STOP \ | ||
100 | (MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \ | ||
101 | | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK) | ||
102 | |||
103 | /* DM9161 10BT Configuration/Status */ | ||
104 | #define MII_DM9161_10BTCSR 0x12 | ||
105 | #define MII_DM9161_10BTCSR_INIT 0x7800 | ||
106 | |||
107 | #define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \ | ||
108 | SUPPORTED_10baseT_Full | \ | ||
109 | SUPPORTED_100baseT_Half | \ | ||
110 | SUPPORTED_100baseT_Full | \ | ||
111 | SUPPORTED_Autoneg | \ | ||
112 | SUPPORTED_TP | \ | ||
113 | SUPPORTED_MII) | ||
114 | |||
115 | #define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \ | ||
116 | SUPPORTED_1000baseT_Half | \ | ||
117 | SUPPORTED_1000baseT_Full) | ||
118 | |||
119 | #define MII_READ_COMMAND 0x00000001 | ||
120 | |||
121 | #define MII_INTERRUPT_DISABLED 0x0 | ||
122 | #define MII_INTERRUPT_ENABLED 0x1 | ||
123 | /* Taken from mii_if_info and sungem_phy.h */ | ||
124 | struct gfar_mii_info { | ||
125 | /* Information about the PHY type */ | ||
126 | /* And management functions */ | ||
127 | struct phy_info *phyinfo; | ||
128 | |||
129 | /* forced speed & duplex (no autoneg) | ||
130 | * partner speed & duplex & pause (autoneg) | ||
131 | */ | ||
132 | int speed; | ||
133 | int duplex; | ||
134 | int pause; | ||
135 | |||
136 | /* The most recently read link state */ | ||
137 | int link; | ||
138 | |||
139 | /* Enabled Interrupts */ | ||
140 | u32 interrupts; | ||
141 | |||
142 | u32 advertising; | ||
143 | int autoneg; | ||
144 | int mii_id; | ||
145 | |||
146 | /* private data pointer */ | ||
147 | /* For use by PHYs to maintain extra state */ | ||
148 | void *priv; | ||
149 | |||
150 | /* Provided by host chip */ | ||
151 | struct net_device *dev; | ||
152 | |||
153 | /* A lock to ensure that only one thing can read/write | ||
154 | * the MDIO bus at a time */ | ||
155 | spinlock_t mdio_lock; | ||
156 | |||
157 | /* Provided by ethernet driver */ | ||
158 | int (*mdio_read) (struct net_device *dev, int mii_id, int reg); | ||
159 | void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val); | ||
160 | }; | ||
161 | |||
162 | /* struct phy_info: a structure which defines attributes for a PHY | ||
163 | * | ||
164 | * id will contain a number which represents the PHY. During | ||
165 | * startup, the driver will poll the PHY to find out what its | ||
166 | * UID--as defined by registers 2 and 3--is. The 32-bit result | ||
167 | * gotten from the PHY will be ANDed with phy_id_mask to | ||
168 | * discard any bits which may change based on revision numbers | ||
169 | * unimportant to functionality | ||
170 | * | ||
171 | * There are 6 commands which take a gfar_mii_info structure. | ||
172 | * Each PHY must declare config_aneg, and read_status. | ||
173 | */ | ||
174 | struct phy_info { | ||
175 | u32 phy_id; | ||
176 | char *name; | ||
177 | unsigned int phy_id_mask; | ||
178 | u32 features; | ||
179 | |||
180 | /* Called to initialize the PHY */ | ||
181 | int (*init)(struct gfar_mii_info *mii_info); | ||
182 | |||
183 | /* Called to suspend the PHY for power */ | ||
184 | int (*suspend)(struct gfar_mii_info *mii_info); | ||
185 | |||
186 | /* Reconfigures autonegotiation (or disables it) */ | ||
187 | int (*config_aneg)(struct gfar_mii_info *mii_info); | ||
188 | |||
189 | /* Determines the negotiated speed and duplex */ | ||
190 | int (*read_status)(struct gfar_mii_info *mii_info); | ||
191 | |||
192 | /* Clears any pending interrupts */ | ||
193 | int (*ack_interrupt)(struct gfar_mii_info *mii_info); | ||
194 | |||
195 | /* Enables or disables interrupts */ | ||
196 | int (*config_intr)(struct gfar_mii_info *mii_info); | ||
197 | |||
198 | /* Clears up any memory if needed */ | ||
199 | void (*close)(struct gfar_mii_info *mii_info); | ||
200 | }; | ||
201 | |||
202 | struct phy_info *get_phy_info(struct gfar_mii_info *mii_info); | ||
203 | int read_phy_reg(struct net_device *dev, int mii_id, int regnum); | ||
204 | void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value); | ||
205 | void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info); | ||
206 | void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts); | ||
207 | |||
208 | struct dm9161_private { | ||
209 | struct timer_list timer; | ||
210 | int resetdone; | ||
211 | }; | ||
212 | |||
213 | #endif /* GIANFAR_PHY_H */ | ||