diff options
| author | Patrick McHardy <kaber@trash.net> | 2010-04-20 10:02:01 -0400 | 
|---|---|---|
| committer | Patrick McHardy <kaber@trash.net> | 2010-04-20 10:02:01 -0400 | 
| commit | 62910554656cdcd6b6f84a5154c4155aae4ca231 (patch) | |
| tree | dcf14004f6fd2ef7154362ff948bfeba0f3ea92d /drivers/net/fec.c | |
| parent | 22265a5c3c103cf8c50be62e6c90d045eb649e6d (diff) | |
| parent | ab9304717f7624c41927f442e6b6d418b2d8b3e4 (diff) | |
Merge branch 'master' of /repos/git/net-next-2.6
Conflicts:
	Documentation/feature-removal-schedule.txt
	net/ipv6/netfilter/ip6t_REJECT.c
	net/netfilter/xt_limit.c
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'drivers/net/fec.c')
| -rw-r--r-- | drivers/net/fec.c | 1138 | 
1 files changed, 256 insertions, 882 deletions
| diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 9f98c1c4a344..2b1651aee13f 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/irq.h> | 40 | #include <linux/irq.h> | 
| 41 | #include <linux/clk.h> | 41 | #include <linux/clk.h> | 
| 42 | #include <linux/platform_device.h> | 42 | #include <linux/platform_device.h> | 
| 43 | #include <linux/phy.h> | ||
| 43 | 44 | ||
| 44 | #include <asm/cacheflush.h> | 45 | #include <asm/cacheflush.h> | 
| 45 | 46 | ||
| @@ -61,7 +62,6 @@ | |||
| 61 | * Define the fixed address of the FEC hardware. | 62 | * Define the fixed address of the FEC hardware. | 
| 62 | */ | 63 | */ | 
| 63 | #if defined(CONFIG_M5272) | 64 | #if defined(CONFIG_M5272) | 
| 64 | #define HAVE_mii_link_interrupt | ||
| 65 | 65 | ||
| 66 | static unsigned char fec_mac_default[] = { | 66 | static unsigned char fec_mac_default[] = { | 
| 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
| @@ -86,23 +86,6 @@ static unsigned char fec_mac_default[] = { | |||
| 86 | #endif | 86 | #endif | 
| 87 | #endif /* CONFIG_M5272 */ | 87 | #endif /* CONFIG_M5272 */ | 
| 88 | 88 | ||
| 89 | /* Forward declarations of some structures to support different PHYs */ | ||
| 90 | |||
| 91 | typedef struct { | ||
| 92 | uint mii_data; | ||
| 93 | void (*funct)(uint mii_reg, struct net_device *dev); | ||
| 94 | } phy_cmd_t; | ||
| 95 | |||
| 96 | typedef struct { | ||
| 97 | uint id; | ||
| 98 | char *name; | ||
| 99 | |||
| 100 | const phy_cmd_t *config; | ||
| 101 | const phy_cmd_t *startup; | ||
| 102 | const phy_cmd_t *ack_int; | ||
| 103 | const phy_cmd_t *shutdown; | ||
| 104 | } phy_info_t; | ||
| 105 | |||
| 106 | /* The number of Tx and Rx buffers. These are allocated from the page | 89 | /* The number of Tx and Rx buffers. These are allocated from the page | 
| 107 | * pool. The code may assume these are power of two, so it it best | 90 | * pool. The code may assume these are power of two, so it it best | 
| 108 | * to keep them that size. | 91 | * to keep them that size. | 
| @@ -189,29 +172,21 @@ struct fec_enet_private { | |||
| 189 | uint tx_full; | 172 | uint tx_full; | 
| 190 | /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ | 173 | /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ | 
| 191 | spinlock_t hw_lock; | 174 | spinlock_t hw_lock; | 
| 192 | /* hold while accessing the mii_list_t() elements */ | ||
| 193 | spinlock_t mii_lock; | ||
| 194 | |||
| 195 | uint phy_id; | ||
| 196 | uint phy_id_done; | ||
| 197 | uint phy_status; | ||
| 198 | uint phy_speed; | ||
| 199 | phy_info_t const *phy; | ||
| 200 | struct work_struct phy_task; | ||
| 201 | 175 | ||
| 202 | uint sequence_done; | 176 | struct platform_device *pdev; | 
| 203 | uint mii_phy_task_queued; | ||
| 204 | 177 | ||
| 205 | uint phy_addr; | 178 | int opened; | 
| 206 | 179 | ||
| 180 | /* Phylib and MDIO interface */ | ||
| 181 | struct mii_bus *mii_bus; | ||
| 182 | struct phy_device *phy_dev; | ||
| 183 | int mii_timeout; | ||
| 184 | uint phy_speed; | ||
| 207 | int index; | 185 | int index; | 
| 208 | int opened; | ||
| 209 | int link; | 186 | int link; | 
| 210 | int old_link; | ||
| 211 | int full_duplex; | 187 | int full_duplex; | 
| 212 | }; | 188 | }; | 
| 213 | 189 | ||
| 214 | static void fec_enet_mii(struct net_device *dev); | ||
| 215 | static irqreturn_t fec_enet_interrupt(int irq, void * dev_id); | 190 | static irqreturn_t fec_enet_interrupt(int irq, void * dev_id); | 
| 216 | static void fec_enet_tx(struct net_device *dev); | 191 | static void fec_enet_tx(struct net_device *dev); | 
| 217 | static void fec_enet_rx(struct net_device *dev); | 192 | static void fec_enet_rx(struct net_device *dev); | 
| @@ -219,67 +194,20 @@ static int fec_enet_close(struct net_device *dev); | |||
| 219 | static void fec_restart(struct net_device *dev, int duplex); | 194 | static void fec_restart(struct net_device *dev, int duplex); | 
| 220 | static void fec_stop(struct net_device *dev); | 195 | static void fec_stop(struct net_device *dev); | 
| 221 | 196 | ||
| 197 | /* FEC MII MMFR bits definition */ | ||
| 198 | #define FEC_MMFR_ST (1 << 30) | ||
| 199 | #define FEC_MMFR_OP_READ (2 << 28) | ||
| 200 | #define FEC_MMFR_OP_WRITE (1 << 28) | ||
| 201 | #define FEC_MMFR_PA(v) ((v & 0x1f) << 23) | ||
| 202 | #define FEC_MMFR_RA(v) ((v & 0x1f) << 18) | ||
| 203 | #define FEC_MMFR_TA (2 << 16) | ||
| 204 | #define FEC_MMFR_DATA(v) (v & 0xffff) | ||
| 222 | 205 | ||
| 223 | /* MII processing. We keep this as simple as possible. Requests are | 206 | #define FEC_MII_TIMEOUT 10000 | 
| 224 | * placed on the list (if there is room). When the request is finished | ||
| 225 | * by the MII, an optional function may be called. | ||
| 226 | */ | ||
| 227 | typedef struct mii_list { | ||
| 228 | uint mii_regval; | ||
| 229 | void (*mii_func)(uint val, struct net_device *dev); | ||
| 230 | struct mii_list *mii_next; | ||
| 231 | } mii_list_t; | ||
| 232 | |||
| 233 | #define NMII 20 | ||
| 234 | static mii_list_t mii_cmds[NMII]; | ||
| 235 | static mii_list_t *mii_free; | ||
| 236 | static mii_list_t *mii_head; | ||
| 237 | static mii_list_t *mii_tail; | ||
| 238 | |||
| 239 | static int mii_queue(struct net_device *dev, int request, | ||
| 240 | void (*func)(uint, struct net_device *)); | ||
| 241 | |||
| 242 | /* Make MII read/write commands for the FEC */ | ||
| 243 | #define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) | ||
| 244 | #define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \ | ||
| 245 | (VAL & 0xffff)) | ||
| 246 | #define mk_mii_end 0 | ||
| 247 | 207 | ||
| 248 | /* Transmitter timeout */ | 208 | /* Transmitter timeout */ | 
| 249 | #define TX_TIMEOUT (2 * HZ) | 209 | #define TX_TIMEOUT (2 * HZ) | 
| 250 | 210 | ||
| 251 | /* Register definitions for the PHY */ | ||
| 252 | |||
| 253 | #define MII_REG_CR 0 /* Control Register */ | ||
| 254 | #define MII_REG_SR 1 /* Status Register */ | ||
| 255 | #define MII_REG_PHYIR1 2 /* PHY Identification Register 1 */ | ||
| 256 | #define MII_REG_PHYIR2 3 /* PHY Identification Register 2 */ | ||
| 257 | #define MII_REG_ANAR 4 /* A-N Advertisement Register */ | ||
| 258 | #define MII_REG_ANLPAR 5 /* A-N Link Partner Ability Register */ | ||
| 259 | #define MII_REG_ANER 6 /* A-N Expansion Register */ | ||
| 260 | #define MII_REG_ANNPTR 7 /* A-N Next Page Transmit Register */ | ||
| 261 | #define MII_REG_ANLPRNPR 8 /* A-N Link Partner Received Next Page Reg. */ | ||
| 262 | |||
| 263 | /* values for phy_status */ | ||
| 264 | |||
| 265 | #define PHY_CONF_ANE 0x0001 /* 1 auto-negotiation enabled */ | ||
| 266 | #define PHY_CONF_LOOP 0x0002 /* 1 loopback mode enabled */ | ||
| 267 | #define PHY_CONF_SPMASK 0x00f0 /* mask for speed */ | ||
| 268 | #define PHY_CONF_10HDX 0x0010 /* 10 Mbit half duplex supported */ | ||
| 269 | #define PHY_CONF_10FDX 0x0020 /* 10 Mbit full duplex supported */ | ||
| 270 | #define PHY_CONF_100HDX 0x0040 /* 100 Mbit half duplex supported */ | ||
| 271 | #define PHY_CONF_100FDX 0x0080 /* 100 Mbit full duplex supported */ | ||
| 272 | |||
| 273 | #define PHY_STAT_LINK 0x0100 /* 1 up - 0 down */ | ||
| 274 | #define PHY_STAT_FAULT 0x0200 /* 1 remote fault */ | ||
| 275 | #define PHY_STAT_ANC 0x0400 /* 1 auto-negotiation complete */ | ||
| 276 | #define PHY_STAT_SPMASK 0xf000 /* mask for speed */ | ||
| 277 | #define PHY_STAT_10HDX 0x1000 /* 10 Mbit half duplex selected */ | ||
| 278 | #define PHY_STAT_10FDX 0x2000 /* 10 Mbit full duplex selected */ | ||
| 279 | #define PHY_STAT_100HDX 0x4000 /* 100 Mbit half duplex selected */ | ||
| 280 | #define PHY_STAT_100FDX 0x8000 /* 100 Mbit full duplex selected */ | ||
| 281 | |||
| 282 | |||
| 283 | static int | 211 | static int | 
| 284 | fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | 212 | fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | 
| 285 | { | 213 | { | 
| @@ -406,12 +334,6 @@ fec_enet_interrupt(int irq, void * dev_id) | |||
| 406 | ret = IRQ_HANDLED; | 334 | ret = IRQ_HANDLED; | 
| 407 | fec_enet_tx(dev); | 335 | fec_enet_tx(dev); | 
| 408 | } | 336 | } | 
| 409 | |||
| 410 | if (int_events & FEC_ENET_MII) { | ||
| 411 | ret = IRQ_HANDLED; | ||
| 412 | fec_enet_mii(dev); | ||
| 413 | } | ||
| 414 | |||
| 415 | } while (int_events); | 337 | } while (int_events); | 
| 416 | 338 | ||
| 417 | return ret; | 339 | return ret; | 
| @@ -607,827 +529,311 @@ rx_processing_done: | |||
| 607 | spin_unlock(&fep->hw_lock); | 529 | spin_unlock(&fep->hw_lock); | 
| 608 | } | 530 | } | 
| 609 | 531 | ||
| 610 | /* called from interrupt context */ | 532 | /* ------------------------------------------------------------------------- */ | 
| 611 | static void | 533 | #ifdef CONFIG_M5272 | 
| 612 | fec_enet_mii(struct net_device *dev) | 534 | static void __inline__ fec_get_mac(struct net_device *dev) | 
| 613 | { | ||
| 614 | struct fec_enet_private *fep; | ||
| 615 | mii_list_t *mip; | ||
| 616 | |||
| 617 | fep = netdev_priv(dev); | ||
| 618 | spin_lock(&fep->mii_lock); | ||
| 619 | |||
| 620 | if ((mip = mii_head) == NULL) { | ||
| 621 | printk("MII and no head!\n"); | ||
| 622 | goto unlock; | ||
| 623 | } | ||
| 624 | |||
| 625 | if (mip->mii_func != NULL) | ||
| 626 | (*(mip->mii_func))(readl(fep->hwp + FEC_MII_DATA), dev); | ||
| 627 | |||
| 628 | mii_head = mip->mii_next; | ||
| 629 | mip->mii_next = mii_free; | ||
| 630 | mii_free = mip; | ||
| 631 | |||
| 632 | if ((mip = mii_head) != NULL) | ||
| 633 | writel(mip->mii_regval, fep->hwp + FEC_MII_DATA); | ||
| 634 | |||
| 635 | unlock: | ||
| 636 | spin_unlock(&fep->mii_lock); | ||
| 637 | } | ||
| 638 | |||
| 639 | static int | ||
| 640 | mii_queue_unlocked(struct net_device *dev, int regval, | ||
| 641 | void (*func)(uint, struct net_device *)) | ||
| 642 | { | 535 | { | 
| 643 | struct fec_enet_private *fep; | 536 | struct fec_enet_private *fep = netdev_priv(dev); | 
| 644 | mii_list_t *mip; | 537 | unsigned char *iap, tmpaddr[ETH_ALEN]; | 
| 645 | int retval; | ||
| 646 | |||
| 647 | /* Add PHY address to register command */ | ||
| 648 | fep = netdev_priv(dev); | ||
| 649 | 538 | ||
| 650 | regval |= fep->phy_addr << 23; | 539 | if (FEC_FLASHMAC) { | 
| 651 | retval = 0; | 540 | /* | 
| 652 | 541 | * Get MAC address from FLASH. | |
| 653 | if ((mip = mii_free) != NULL) { | 542 | * If it is all 1's or 0's, use the default. | 
| 654 | mii_free = mip->mii_next; | 543 | */ | 
| 655 | mip->mii_regval = regval; | 544 | iap = (unsigned char *)FEC_FLASHMAC; | 
| 656 | mip->mii_func = func; | 545 | if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && | 
| 657 | mip->mii_next = NULL; | 546 | (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) | 
| 658 | if (mii_head) { | 547 | iap = fec_mac_default; | 
| 659 | mii_tail->mii_next = mip; | 548 | if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && | 
| 660 | mii_tail = mip; | 549 | (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) | 
| 661 | } else { | 550 | iap = fec_mac_default; | 
| 662 | mii_head = mii_tail = mip; | ||
| 663 | writel(regval, fep->hwp + FEC_MII_DATA); | ||
| 664 | } | ||
| 665 | } else { | 551 | } else { | 
| 666 | retval = 1; | 552 | *((unsigned long *) &tmpaddr[0]) = readl(fep->hwp + FEC_ADDR_LOW); | 
| 553 | *((unsigned short *) &tmpaddr[4]) = (readl(fep->hwp + FEC_ADDR_HIGH) >> 16); | ||
| 554 | iap = &tmpaddr[0]; | ||
| 667 | } | 555 | } | 
| 668 | 556 | ||
| 669 | return retval; | 557 | memcpy(dev->dev_addr, iap, ETH_ALEN); | 
| 670 | } | ||
| 671 | |||
| 672 | static int | ||
| 673 | mii_queue(struct net_device *dev, int regval, | ||
| 674 | void (*func)(uint, struct net_device *)) | ||
| 675 | { | ||
| 676 | struct fec_enet_private *fep; | ||
| 677 | unsigned long flags; | ||
| 678 | int retval; | ||
| 679 | fep = netdev_priv(dev); | ||
| 680 | spin_lock_irqsave(&fep->mii_lock, flags); | ||
| 681 | retval = mii_queue_unlocked(dev, regval, func); | ||
| 682 | spin_unlock_irqrestore(&fep->mii_lock, flags); | ||
| 683 | return retval; | ||
| 684 | } | ||
| 685 | |||
| 686 | static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c) | ||
| 687 | { | ||
| 688 | if(!c) | ||
| 689 | return; | ||
| 690 | 558 | ||
| 691 | for (; c->mii_data != mk_mii_end; c++) | 559 | /* Adjust MAC if using default MAC address */ | 
| 692 | mii_queue(dev, c->mii_data, c->funct); | 560 | if (iap == fec_mac_default) | 
| 561 | dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; | ||
| 693 | } | 562 | } | 
| 563 | #endif | ||
| 694 | 564 | ||
| 695 | static void mii_parse_sr(uint mii_reg, struct net_device *dev) | 565 | /* ------------------------------------------------------------------------- */ | 
| 696 | { | ||
| 697 | struct fec_enet_private *fep = netdev_priv(dev); | ||
| 698 | volatile uint *s = &(fep->phy_status); | ||
| 699 | uint status; | ||
| 700 | |||
| 701 | status = *s & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC); | ||
| 702 | |||
| 703 | if (mii_reg & 0x0004) | ||
| 704 | status |= PHY_STAT_LINK; | ||
| 705 | if (mii_reg & 0x0010) | ||
| 706 | status |= PHY_STAT_FAULT; | ||
| 707 | if (mii_reg & 0x0020) | ||
| 708 | status |= PHY_STAT_ANC; | ||
| 709 | *s = status; | ||
| 710 | } | ||
| 711 | 566 | ||
| 712 | static void mii_parse_cr(uint mii_reg, struct net_device *dev) | 567 | /* | 
| 568 | * Phy section | ||
| 569 | */ | ||
| 570 | static void fec_enet_adjust_link(struct net_device *dev) | ||
| 713 | { | 571 | { | 
| 714 | struct fec_enet_private *fep = netdev_priv(dev); | 572 | struct fec_enet_private *fep = netdev_priv(dev); | 
| 715 | volatile uint *s = &(fep->phy_status); | 573 | struct phy_device *phy_dev = fep->phy_dev; | 
| 716 | uint status; | 574 | unsigned long flags; | 
| 717 | |||
| 718 | status = *s & ~(PHY_CONF_ANE | PHY_CONF_LOOP); | ||
| 719 | |||
| 720 | if (mii_reg & 0x1000) | ||
| 721 | status |= PHY_CONF_ANE; | ||
| 722 | if (mii_reg & 0x4000) | ||
| 723 | status |= PHY_CONF_LOOP; | ||
| 724 | *s = status; | ||
| 725 | } | ||
| 726 | 575 | ||
| 727 | static void mii_parse_anar(uint mii_reg, struct net_device *dev) | 576 | int status_change = 0; | 
| 728 | { | ||
| 729 | struct fec_enet_private *fep = netdev_priv(dev); | ||
| 730 | volatile uint *s = &(fep->phy_status); | ||
| 731 | uint status; | ||
| 732 | |||
| 733 | status = *s & ~(PHY_CONF_SPMASK); | ||
| 734 | |||
| 735 | if (mii_reg & 0x0020) | ||
| 736 | status |= PHY_CONF_10HDX; | ||
| 737 | if (mii_reg & 0x0040) | ||
| 738 | status |= PHY_CONF_10FDX; | ||
| 739 | if (mii_reg & 0x0080) | ||
| 740 | status |= PHY_CONF_100HDX; | ||
| 741 | if (mii_reg & 0x00100) | ||
| 742 | status |= PHY_CONF_100FDX; | ||
| 743 | *s = status; | ||
| 744 | } | ||
| 745 | 577 | ||
| 746 | /* ------------------------------------------------------------------------- */ | 578 | spin_lock_irqsave(&fep->hw_lock, flags); | 
| 747 | /* The Level one LXT970 is used by many boards */ | ||
| 748 | 579 | ||
| 749 | #define MII_LXT970_MIRROR 16 /* Mirror register */ | 580 | /* Prevent a state halted on mii error */ | 
| 750 | #define MII_LXT970_IER 17 /* Interrupt Enable Register */ | 581 | if (fep->mii_timeout && phy_dev->state == PHY_HALTED) { | 
| 751 | #define MII_LXT970_ISR 18 /* Interrupt Status Register */ | 582 | phy_dev->state = PHY_RESUMING; | 
| 752 | #define MII_LXT970_CONFIG 19 /* Configuration Register */ | 583 | goto spin_unlock; | 
| 753 | #define MII_LXT970_CSR 20 /* Chip Status Register */ | 584 | } | 
| 754 | 585 | ||
| 755 | static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev) | 586 | /* Duplex link change */ | 
| 756 | { | 587 | if (phy_dev->link) { | 
| 757 | struct fec_enet_private *fep = netdev_priv(dev); | 588 | if (fep->full_duplex != phy_dev->duplex) { | 
| 758 | volatile uint *s = &(fep->phy_status); | 589 | fec_restart(dev, phy_dev->duplex); | 
| 759 | uint status; | 590 | status_change = 1; | 
| 591 | } | ||
| 592 | } | ||
| 760 | 593 | ||
| 761 | status = *s & ~(PHY_STAT_SPMASK); | 594 | /* Link on or off change */ | 
| 762 | if (mii_reg & 0x0800) { | 595 | if (phy_dev->link != fep->link) { | 
| 763 | if (mii_reg & 0x1000) | 596 | fep->link = phy_dev->link; | 
| 764 | status |= PHY_STAT_100FDX; | 597 | if (phy_dev->link) | 
| 598 | fec_restart(dev, phy_dev->duplex); | ||
| 765 | else | 599 | else | 
| 766 | status |= PHY_STAT_100HDX; | 600 | fec_stop(dev); | 
| 767 | } else { | 601 | status_change = 1; | 
| 768 | if (mii_reg & 0x1000) | ||
| 769 | status |= PHY_STAT_10FDX; | ||
| 770 | else | ||
| 771 | status |= PHY_STAT_10HDX; | ||
| 772 | } | 602 | } | 
| 773 | *s = status; | ||
| 774 | } | ||
| 775 | |||
| 776 | static phy_cmd_t const phy_cmd_lxt970_config[] = { | ||
| 777 | { mk_mii_read(MII_REG_CR), mii_parse_cr }, | ||
| 778 | { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, | ||
| 779 | { mk_mii_end, } | ||
| 780 | }; | ||
| 781 | static phy_cmd_t const phy_cmd_lxt970_startup[] = { /* enable interrupts */ | ||
| 782 | { mk_mii_write(MII_LXT970_IER, 0x0002), NULL }, | ||
| 783 | { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ | ||
| 784 | { mk_mii_end, } | ||
| 785 | }; | ||
| 786 | static phy_cmd_t const phy_cmd_lxt970_ack_int[] = { | ||
| 787 | /* read SR and ISR to acknowledge */ | ||
| 788 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 789 | { mk_mii_read(MII_LXT970_ISR), NULL }, | ||
| 790 | |||
| 791 | /* find out the current status */ | ||
| 792 | { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr }, | ||
| 793 | { mk_mii_end, } | ||
| 794 | }; | ||
| 795 | static phy_cmd_t const phy_cmd_lxt970_shutdown[] = { /* disable interrupts */ | ||
| 796 | { mk_mii_write(MII_LXT970_IER, 0x0000), NULL }, | ||
| 797 | { mk_mii_end, } | ||
| 798 | }; | ||
| 799 | static phy_info_t const phy_info_lxt970 = { | ||
| 800 | .id = 0x07810000, | ||
| 801 | .name = "LXT970", | ||
| 802 | .config = phy_cmd_lxt970_config, | ||
| 803 | .startup = phy_cmd_lxt970_startup, | ||
| 804 | .ack_int = phy_cmd_lxt970_ack_int, | ||
| 805 | .shutdown = phy_cmd_lxt970_shutdown | ||
| 806 | }; | ||
| 807 | 603 | ||
| 808 | /* ------------------------------------------------------------------------- */ | 604 | spin_unlock: | 
| 809 | /* The Level one LXT971 is used on some of my custom boards */ | 605 | spin_unlock_irqrestore(&fep->hw_lock, flags); | 
| 810 | |||
| 811 | /* register definitions for the 971 */ | ||
| 812 | 606 | ||
| 813 | #define MII_LXT971_PCR 16 /* Port Control Register */ | 607 | if (status_change) | 
| 814 | #define MII_LXT971_SR2 17 /* Status Register 2 */ | 608 | phy_print_status(phy_dev); | 
| 815 | #define MII_LXT971_IER 18 /* Interrupt Enable Register */ | 609 | } | 
| 816 | #define MII_LXT971_ISR 19 /* Interrupt Status Register */ | ||
| 817 | #define MII_LXT971_LCR 20 /* LED Control Register */ | ||
| 818 | #define MII_LXT971_TCR 30 /* Transmit Control Register */ | ||
| 819 | 610 | ||
| 820 | /* | 611 | /* | 
| 821 | * I had some nice ideas of running the MDIO faster... | 612 | * NOTE: a MII transaction is during around 25 us, so polling it... | 
| 822 | * The 971 should support 8MHz and I tried it, but things acted really | ||
| 823 | * weird, so 2.5 MHz ought to be enough for anyone... | ||
| 824 | */ | 613 | */ | 
| 825 | 614 | static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | |
| 826 | static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev) | ||
| 827 | { | 615 | { | 
| 828 | struct fec_enet_private *fep = netdev_priv(dev); | 616 | struct fec_enet_private *fep = bus->priv; | 
| 829 | volatile uint *s = &(fep->phy_status); | 617 | int timeout = FEC_MII_TIMEOUT; | 
| 830 | uint status; | ||
| 831 | 618 | ||
| 832 | status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC); | 619 | fep->mii_timeout = 0; | 
| 833 | 620 | ||
| 834 | if (mii_reg & 0x0400) { | 621 | /* clear MII end of transfer bit*/ | 
| 835 | fep->link = 1; | 622 | writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); | 
| 836 | status |= PHY_STAT_LINK; | 623 | |
| 837 | } else { | 624 | /* start a read op */ | 
| 838 | fep->link = 0; | 625 | writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | | 
| 839 | } | 626 | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | | 
| 840 | if (mii_reg & 0x0080) | 627 | FEC_MMFR_TA, fep->hwp + FEC_MII_DATA); | 
| 841 | status |= PHY_STAT_ANC; | 628 | |
| 842 | if (mii_reg & 0x4000) { | 629 | /* wait for end of transfer */ | 
| 843 | if (mii_reg & 0x0200) | 630 | while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) { | 
| 844 | status |= PHY_STAT_100FDX; | 631 | cpu_relax(); | 
| 845 | else | 632 | if (timeout-- < 0) { | 
| 846 | status |= PHY_STAT_100HDX; | 633 | fep->mii_timeout = 1; | 
| 847 | } else { | 634 | printk(KERN_ERR "FEC: MDIO read timeout\n"); | 
| 848 | if (mii_reg & 0x0200) | 635 | return -ETIMEDOUT; | 
| 849 | status |= PHY_STAT_10FDX; | 636 | } | 
| 850 | else | ||
| 851 | status |= PHY_STAT_10HDX; | ||
| 852 | } | 637 | } | 
| 853 | if (mii_reg & 0x0008) | ||
| 854 | status |= PHY_STAT_FAULT; | ||
| 855 | 638 | ||
| 856 | *s = status; | 639 | /* return value */ | 
| 640 | return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); | ||
| 857 | } | 641 | } | 
| 858 | 642 | ||
| 859 | static phy_cmd_t const phy_cmd_lxt971_config[] = { | 643 | static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, | 
| 860 | /* limit to 10MBit because my prototype board | 644 | u16 value) | 
| 861 | * doesn't work with 100. */ | ||
| 862 | { mk_mii_read(MII_REG_CR), mii_parse_cr }, | ||
| 863 | { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, | ||
| 864 | { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 }, | ||
| 865 | { mk_mii_end, } | ||
| 866 | }; | ||
| 867 | static phy_cmd_t const phy_cmd_lxt971_startup[] = { /* enable interrupts */ | ||
| 868 | { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL }, | ||
| 869 | { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ | ||
| 870 | { mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */ | ||
| 871 | /* Somehow does the 971 tell me that the link is down | ||
| 872 | * the first read after power-up. | ||
| 873 | * read here to get a valid value in ack_int */ | ||
| 874 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 875 | { mk_mii_end, } | ||
| 876 | }; | ||
| 877 | static phy_cmd_t const phy_cmd_lxt971_ack_int[] = { | ||
| 878 | /* acknowledge the int before reading status ! */ | ||
| 879 | { mk_mii_read(MII_LXT971_ISR), NULL }, | ||
| 880 | /* find out the current status */ | ||
| 881 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 882 | { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 }, | ||
| 883 | { mk_mii_end, } | ||
| 884 | }; | ||
| 885 | static phy_cmd_t const phy_cmd_lxt971_shutdown[] = { /* disable interrupts */ | ||
| 886 | { mk_mii_write(MII_LXT971_IER, 0x0000), NULL }, | ||
| 887 | { mk_mii_end, } | ||
| 888 | }; | ||
| 889 | static phy_info_t const phy_info_lxt971 = { | ||
| 890 | .id = 0x0001378e, | ||
| 891 | .name = "LXT971", | ||
| 892 | .config = phy_cmd_lxt971_config, | ||
| 893 | .startup = phy_cmd_lxt971_startup, | ||
| 894 | .ack_int = phy_cmd_lxt971_ack_int, | ||
| 895 | .shutdown = phy_cmd_lxt971_shutdown | ||
| 896 | }; | ||
| 897 | |||
| 898 | /* ------------------------------------------------------------------------- */ | ||
| 899 | /* The Quality Semiconductor QS6612 is used on the RPX CLLF */ | ||
| 900 | |||
| 901 | /* register definitions */ | ||
| 902 | |||
| 903 | #define MII_QS6612_MCR 17 /* Mode Control Register */ | ||
| 904 | #define MII_QS6612_FTR 27 /* Factory Test Register */ | ||
| 905 | #define MII_QS6612_MCO 28 /* Misc. Control Register */ | ||
| 906 | #define MII_QS6612_ISR 29 /* Interrupt Source Register */ | ||
| 907 | #define MII_QS6612_IMR 30 /* Interrupt Mask Register */ | ||
| 908 | #define MII_QS6612_PCR 31 /* 100BaseTx PHY Control Reg. */ | ||
| 909 | |||
| 910 | static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev) | ||
| 911 | { | 645 | { | 
| 912 | struct fec_enet_private *fep = netdev_priv(dev); | 646 | struct fec_enet_private *fep = bus->priv; | 
| 913 | volatile uint *s = &(fep->phy_status); | 647 | int timeout = FEC_MII_TIMEOUT; | 
| 914 | uint status; | ||
| 915 | 648 | ||
| 916 | status = *s & ~(PHY_STAT_SPMASK); | 649 | fep->mii_timeout = 0; | 
| 917 | 650 | ||
| 918 | switch((mii_reg >> 2) & 7) { | 651 | /* clear MII end of transfer bit*/ | 
| 919 | case 1: status |= PHY_STAT_10HDX; break; | 652 | writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); | 
| 920 | case 2: status |= PHY_STAT_100HDX; break; | ||
| 921 | case 5: status |= PHY_STAT_10FDX; break; | ||
| 922 | case 6: status |= PHY_STAT_100FDX; break; | ||
| 923 | } | ||
| 924 | |||
| 925 | *s = status; | ||
| 926 | } | ||
| 927 | |||
| 928 | static phy_cmd_t const phy_cmd_qs6612_config[] = { | ||
| 929 | /* The PHY powers up isolated on the RPX, | ||
| 930 | * so send a command to allow operation. | ||
| 931 | */ | ||
| 932 | { mk_mii_write(MII_QS6612_PCR, 0x0dc0), NULL }, | ||
| 933 | |||
| 934 | /* parse cr and anar to get some info */ | ||
| 935 | { mk_mii_read(MII_REG_CR), mii_parse_cr }, | ||
| 936 | { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, | ||
| 937 | { mk_mii_end, } | ||
| 938 | }; | ||
| 939 | static phy_cmd_t const phy_cmd_qs6612_startup[] = { /* enable interrupts */ | ||
| 940 | { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL }, | ||
| 941 | { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ | ||
| 942 | { mk_mii_end, } | ||
| 943 | }; | ||
| 944 | static phy_cmd_t const phy_cmd_qs6612_ack_int[] = { | ||
| 945 | /* we need to read ISR, SR and ANER to acknowledge */ | ||
| 946 | { mk_mii_read(MII_QS6612_ISR), NULL }, | ||
| 947 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 948 | { mk_mii_read(MII_REG_ANER), NULL }, | ||
| 949 | |||
| 950 | /* read pcr to get info */ | ||
| 951 | { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr }, | ||
| 952 | { mk_mii_end, } | ||
| 953 | }; | ||
| 954 | static phy_cmd_t const phy_cmd_qs6612_shutdown[] = { /* disable interrupts */ | ||
| 955 | { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL }, | ||
| 956 | { mk_mii_end, } | ||
| 957 | }; | ||
| 958 | static phy_info_t const phy_info_qs6612 = { | ||
| 959 | .id = 0x00181440, | ||
| 960 | .name = "QS6612", | ||
| 961 | .config = phy_cmd_qs6612_config, | ||
| 962 | .startup = phy_cmd_qs6612_startup, | ||
| 963 | .ack_int = phy_cmd_qs6612_ack_int, | ||
| 964 | .shutdown = phy_cmd_qs6612_shutdown | ||
| 965 | }; | ||
| 966 | |||
| 967 | /* ------------------------------------------------------------------------- */ | ||
| 968 | /* AMD AM79C874 phy */ | ||
| 969 | 653 | ||
| 970 | /* register definitions for the 874 */ | 654 | /* start a read op */ | 
| 655 | writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | | ||
| 656 | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | | ||
| 657 | FEC_MMFR_TA | FEC_MMFR_DATA(value), | ||
| 658 | fep->hwp + FEC_MII_DATA); | ||
| 659 | |||
| 660 | /* wait for end of transfer */ | ||
| 661 | while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) { | ||
| 662 | cpu_relax(); | ||
| 663 | if (timeout-- < 0) { | ||
| 664 | fep->mii_timeout = 1; | ||
| 665 | printk(KERN_ERR "FEC: MDIO write timeout\n"); | ||
| 666 | return -ETIMEDOUT; | ||
| 667 | } | ||
| 668 | } | ||
| 971 | 669 | ||
| 972 | #define MII_AM79C874_MFR 16 /* Miscellaneous Feature Register */ | 670 | return 0; | 
| 973 | #define MII_AM79C874_ICSR 17 /* Interrupt/Status Register */ | 671 | } | 
| 974 | #define MII_AM79C874_DR 18 /* Diagnostic Register */ | ||
| 975 | #define MII_AM79C874_PMLR 19 /* Power and Loopback Register */ | ||
| 976 | #define MII_AM79C874_MCR 21 /* ModeControl Register */ | ||
| 977 | #define MII_AM79C874_DC 23 /* Disconnect Counter */ | ||
| 978 | #define MII_AM79C874_REC 24 /* Recieve Error Counter */ | ||
| 979 | 672 | ||
| 980 | static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev) | 673 | static int fec_enet_mdio_reset(struct mii_bus *bus) | 
| 981 | { | 674 | { | 
| 982 | struct fec_enet_private *fep = netdev_priv(dev); | 675 | return 0; | 
| 983 | volatile uint *s = &(fep->phy_status); | ||
| 984 | uint status; | ||
| 985 | |||
| 986 | status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_ANC); | ||
| 987 | |||
| 988 | if (mii_reg & 0x0080) | ||
| 989 | status |= PHY_STAT_ANC; | ||
| 990 | if (mii_reg & 0x0400) | ||
| 991 | status |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX); | ||
| 992 | else | ||
| 993 | status |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX); | ||
| 994 | |||
| 995 | *s = status; | ||
| 996 | } | 676 | } | 
| 997 | 677 | ||
| 998 | static phy_cmd_t const phy_cmd_am79c874_config[] = { | 678 | static int fec_enet_mii_probe(struct net_device *dev) | 
| 999 | { mk_mii_read(MII_REG_CR), mii_parse_cr }, | ||
| 1000 | { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, | ||
| 1001 | { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr }, | ||
| 1002 | { mk_mii_end, } | ||
| 1003 | }; | ||
| 1004 | static phy_cmd_t const phy_cmd_am79c874_startup[] = { /* enable interrupts */ | ||
| 1005 | { mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL }, | ||
| 1006 | { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ | ||
| 1007 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 1008 | { mk_mii_end, } | ||
| 1009 | }; | ||
| 1010 | static phy_cmd_t const phy_cmd_am79c874_ack_int[] = { | ||
| 1011 | /* find out the current status */ | ||
| 1012 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 1013 | { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr }, | ||
| 1014 | /* we only need to read ISR to acknowledge */ | ||
| 1015 | { mk_mii_read(MII_AM79C874_ICSR), NULL }, | ||
| 1016 | { mk_mii_end, } | ||
| 1017 | }; | ||
| 1018 | static phy_cmd_t const phy_cmd_am79c874_shutdown[] = { /* disable interrupts */ | ||
| 1019 | { mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL }, | ||
| 1020 | { mk_mii_end, } | ||
| 1021 | }; | ||
| 1022 | static phy_info_t const phy_info_am79c874 = { | ||
| 1023 | .id = 0x00022561, | ||
| 1024 | .name = "AM79C874", | ||
| 1025 | .config = phy_cmd_am79c874_config, | ||
| 1026 | .startup = phy_cmd_am79c874_startup, | ||
| 1027 | .ack_int = phy_cmd_am79c874_ack_int, | ||
| 1028 | .shutdown = phy_cmd_am79c874_shutdown | ||
| 1029 | }; | ||
| 1030 | |||
| 1031 | |||
| 1032 | /* ------------------------------------------------------------------------- */ | ||
| 1033 | /* Kendin KS8721BL phy */ | ||
| 1034 | |||
| 1035 | /* register definitions for the 8721 */ | ||
| 1036 | |||
| 1037 | #define MII_KS8721BL_RXERCR 21 | ||
| 1038 | #define MII_KS8721BL_ICSR 27 | ||
| 1039 | #define MII_KS8721BL_PHYCR 31 | ||
| 1040 | |||
| 1041 | static phy_cmd_t const phy_cmd_ks8721bl_config[] = { | ||
| 1042 | { mk_mii_read(MII_REG_CR), mii_parse_cr }, | ||
| 1043 | { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, | ||
| 1044 | { mk_mii_end, } | ||
| 1045 | }; | ||
| 1046 | static phy_cmd_t const phy_cmd_ks8721bl_startup[] = { /* enable interrupts */ | ||
| 1047 | { mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL }, | ||
| 1048 | { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ | ||
| 1049 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 1050 | { mk_mii_end, } | ||
| 1051 | }; | ||
| 1052 | static phy_cmd_t const phy_cmd_ks8721bl_ack_int[] = { | ||
| 1053 | /* find out the current status */ | ||
| 1054 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 1055 | /* we only need to read ISR to acknowledge */ | ||
| 1056 | { mk_mii_read(MII_KS8721BL_ICSR), NULL }, | ||
| 1057 | { mk_mii_end, } | ||
| 1058 | }; | ||
| 1059 | static phy_cmd_t const phy_cmd_ks8721bl_shutdown[] = { /* disable interrupts */ | ||
| 1060 | { mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL }, | ||
| 1061 | { mk_mii_end, } | ||
| 1062 | }; | ||
| 1063 | static phy_info_t const phy_info_ks8721bl = { | ||
| 1064 | .id = 0x00022161, | ||
| 1065 | .name = "KS8721BL", | ||
| 1066 | .config = phy_cmd_ks8721bl_config, | ||
| 1067 | .startup = phy_cmd_ks8721bl_startup, | ||
| 1068 | .ack_int = phy_cmd_ks8721bl_ack_int, | ||
| 1069 | .shutdown = phy_cmd_ks8721bl_shutdown | ||
| 1070 | }; | ||
| 1071 | |||
| 1072 | /* ------------------------------------------------------------------------- */ | ||
| 1073 | /* register definitions for the DP83848 */ | ||
| 1074 | |||
| 1075 | #define MII_DP8384X_PHYSTST 16 /* PHY Status Register */ | ||
| 1076 | |||
| 1077 | static void mii_parse_dp8384x_sr2(uint mii_reg, struct net_device *dev) | ||
| 1078 | { | 679 | { | 
| 1079 | struct fec_enet_private *fep = netdev_priv(dev); | 680 | struct fec_enet_private *fep = netdev_priv(dev); | 
| 1080 | volatile uint *s = &(fep->phy_status); | 681 | struct phy_device *phy_dev = NULL; | 
| 1081 | 682 | int phy_addr; | |
| 1082 | *s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC); | ||
| 1083 | |||
| 1084 | /* Link up */ | ||
| 1085 | if (mii_reg & 0x0001) { | ||
| 1086 | fep->link = 1; | ||
| 1087 | *s |= PHY_STAT_LINK; | ||
| 1088 | } else | ||
| 1089 | fep->link = 0; | ||
| 1090 | /* Status of link */ | ||
| 1091 | if (mii_reg & 0x0010) /* Autonegotioation complete */ | ||
| 1092 | *s |= PHY_STAT_ANC; | ||
| 1093 | if (mii_reg & 0x0002) { /* 10MBps? */ | ||
| 1094 | if (mii_reg & 0x0004) /* Full Duplex? */ | ||
| 1095 | *s |= PHY_STAT_10FDX; | ||
| 1096 | else | ||
| 1097 | *s |= PHY_STAT_10HDX; | ||
| 1098 | } else { /* 100 Mbps? */ | ||
| 1099 | if (mii_reg & 0x0004) /* Full Duplex? */ | ||
| 1100 | *s |= PHY_STAT_100FDX; | ||
| 1101 | else | ||
| 1102 | *s |= PHY_STAT_100HDX; | ||
| 1103 | } | ||
| 1104 | if (mii_reg & 0x0008) | ||
| 1105 | *s |= PHY_STAT_FAULT; | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | static phy_info_t phy_info_dp83848= { | ||
| 1109 | 0x020005c9, | ||
| 1110 | "DP83848", | ||
| 1111 | 683 | ||
| 1112 | (const phy_cmd_t []) { /* config */ | 684 | /* find the first phy */ | 
| 1113 | { mk_mii_read(MII_REG_CR), mii_parse_cr }, | 685 | for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { | 
| 1114 | { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, | 686 | if (fep->mii_bus->phy_map[phy_addr]) { | 
| 1115 | { mk_mii_read(MII_DP8384X_PHYSTST), mii_parse_dp8384x_sr2 }, | 687 | phy_dev = fep->mii_bus->phy_map[phy_addr]; | 
| 1116 | { mk_mii_end, } | 688 | break; | 
| 1117 | }, | 689 | } | 
| 1118 | (const phy_cmd_t []) { /* startup - enable interrupts */ | 690 | } | 
| 1119 | { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ | ||
| 1120 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 1121 | { mk_mii_end, } | ||
| 1122 | }, | ||
| 1123 | (const phy_cmd_t []) { /* ack_int - never happens, no interrupt */ | ||
| 1124 | { mk_mii_end, } | ||
| 1125 | }, | ||
| 1126 | (const phy_cmd_t []) { /* shutdown */ | ||
| 1127 | { mk_mii_end, } | ||
| 1128 | }, | ||
| 1129 | }; | ||
| 1130 | 691 | ||
| 1131 | static phy_info_t phy_info_lan8700 = { | 692 | if (!phy_dev) { | 
| 1132 | 0x0007C0C, | 693 | printk(KERN_ERR "%s: no PHY found\n", dev->name); | 
| 1133 | "LAN8700", | 694 | return -ENODEV; | 
| 1134 | (const phy_cmd_t []) { /* config */ | 695 | } | 
| 1135 | { mk_mii_read(MII_REG_CR), mii_parse_cr }, | ||
| 1136 | { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, | ||
| 1137 | { mk_mii_end, } | ||
| 1138 | }, | ||
| 1139 | (const phy_cmd_t []) { /* startup */ | ||
| 1140 | { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ | ||
| 1141 | { mk_mii_read(MII_REG_SR), mii_parse_sr }, | ||
| 1142 | { mk_mii_end, } | ||
| 1143 | }, | ||
| 1144 | (const phy_cmd_t []) { /* act_int */ | ||
| 1145 | { mk_mii_end, } | ||
| 1146 | }, | ||
| 1147 | (const phy_cmd_t []) { /* shutdown */ | ||
| 1148 | { mk_mii_end, } | ||
| 1149 | }, | ||
| 1150 | }; | ||
| 1151 | /* ------------------------------------------------------------------------- */ | ||
| 1152 | 696 | ||
| 1153 | static phy_info_t const * const phy_info[] = { | 697 | /* attach the mac to the phy */ | 
| 1154 | &phy_info_lxt970, | 698 | phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), | 
| 1155 | &phy_info_lxt971, | 699 | &fec_enet_adjust_link, 0, | 
| 1156 | &phy_info_qs6612, | 700 | PHY_INTERFACE_MODE_MII); | 
| 1157 | &phy_info_am79c874, | 701 | if (IS_ERR(phy_dev)) { | 
| 1158 | &phy_info_ks8721bl, | 702 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); | 
| 1159 | &phy_info_dp83848, | 703 | return PTR_ERR(phy_dev); | 
| 1160 | &phy_info_lan8700, | 704 | } | 
| 1161 | NULL | ||
| 1162 | }; | ||
| 1163 | 705 | ||
| 1164 | /* ------------------------------------------------------------------------- */ | 706 | /* mask with MAC supported features */ | 
| 1165 | #ifdef HAVE_mii_link_interrupt | 707 | phy_dev->supported &= PHY_BASIC_FEATURES; | 
| 1166 | static irqreturn_t | 708 | phy_dev->advertising = phy_dev->supported; | 
| 1167 | mii_link_interrupt(int irq, void * dev_id); | ||
| 1168 | 709 | ||
| 1169 | /* | 710 | fep->phy_dev = phy_dev; | 
| 1170 | * This is specific to the MII interrupt setup of the M5272EVB. | 711 | fep->link = 0; | 
| 1171 | */ | 712 | fep->full_duplex = 0; | 
| 1172 | static void __inline__ fec_request_mii_intr(struct net_device *dev) | ||
| 1173 | { | ||
| 1174 | if (request_irq(66, mii_link_interrupt, IRQF_DISABLED, "fec(MII)", dev) != 0) | ||
| 1175 | printk("FEC: Could not allocate fec(MII) IRQ(66)!\n"); | ||
| 1176 | } | ||
| 1177 | 713 | ||
| 1178 | static void __inline__ fec_disable_phy_intr(struct net_device *dev) | 714 | return 0; | 
| 1179 | { | ||
| 1180 | free_irq(66, dev); | ||
| 1181 | } | 715 | } | 
| 1182 | #endif | ||
| 1183 | 716 | ||
| 1184 | #ifdef CONFIG_M5272 | 717 | static int fec_enet_mii_init(struct platform_device *pdev) | 
| 1185 | static void __inline__ fec_get_mac(struct net_device *dev) | ||
| 1186 | { | 718 | { | 
| 719 | struct net_device *dev = platform_get_drvdata(pdev); | ||
| 1187 | struct fec_enet_private *fep = netdev_priv(dev); | 720 | struct fec_enet_private *fep = netdev_priv(dev); | 
| 1188 | unsigned char *iap, tmpaddr[ETH_ALEN]; | 721 | int err = -ENXIO, i; | 
| 1189 | 722 | ||
| 1190 | if (FEC_FLASHMAC) { | 723 | fep->mii_timeout = 0; | 
| 1191 | /* | ||
| 1192 | * Get MAC address from FLASH. | ||
| 1193 | * If it is all 1's or 0's, use the default. | ||
| 1194 | */ | ||
| 1195 | iap = (unsigned char *)FEC_FLASHMAC; | ||
| 1196 | if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && | ||
| 1197 | (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) | ||
| 1198 | iap = fec_mac_default; | ||
| 1199 | if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && | ||
| 1200 | (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) | ||
| 1201 | iap = fec_mac_default; | ||
| 1202 | } else { | ||
| 1203 | *((unsigned long *) &tmpaddr[0]) = readl(fep->hwp + FEC_ADDR_LOW); | ||
| 1204 | *((unsigned short *) &tmpaddr[4]) = (readl(fep->hwp + FEC_ADDR_HIGH) >> 16); | ||
| 1205 | iap = &tmpaddr[0]; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | memcpy(dev->dev_addr, iap, ETH_ALEN); | ||
| 1209 | |||
| 1210 | /* Adjust MAC if using default MAC address */ | ||
| 1211 | if (iap == fec_mac_default) | ||
| 1212 | dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; | ||
| 1213 | } | ||
| 1214 | #endif | ||
| 1215 | 724 | ||
| 1216 | /* ------------------------------------------------------------------------- */ | 725 | /* | 
| 1217 | 726 | * Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed) | |
| 1218 | static void mii_display_status(struct net_device *dev) | 727 | */ | 
| 1219 | { | 728 | fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000) << 1; | 
| 1220 | struct fec_enet_private *fep = netdev_priv(dev); | 729 | writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); | 
| 1221 | volatile uint *s = &(fep->phy_status); | ||
| 1222 | 730 | ||
| 1223 | if (!fep->link && !fep->old_link) { | 731 | fep->mii_bus = mdiobus_alloc(); | 
| 1224 | /* Link is still down - don't print anything */ | 732 | if (fep->mii_bus == NULL) { | 
| 1225 | return; | 733 | err = -ENOMEM; | 
| 734 | goto err_out; | ||
| 1226 | } | 735 | } | 
| 1227 | 736 | ||
| 1228 | printk("%s: status: ", dev->name); | 737 | fep->mii_bus->name = "fec_enet_mii_bus"; | 
| 1229 | 738 | fep->mii_bus->read = fec_enet_mdio_read; | |
| 1230 | if (!fep->link) { | 739 | fep->mii_bus->write = fec_enet_mdio_write; | 
| 1231 | printk("link down"); | 740 | fep->mii_bus->reset = fec_enet_mdio_reset; | 
| 1232 | } else { | 741 | snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); | 
| 1233 | printk("link up"); | 742 | fep->mii_bus->priv = fep; | 
| 1234 | 743 | fep->mii_bus->parent = &pdev->dev; | |
| 1235 | switch(*s & PHY_STAT_SPMASK) { | 744 | |
| 1236 | case PHY_STAT_100FDX: printk(", 100MBit Full Duplex"); break; | 745 | fep->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); | 
| 1237 | case PHY_STAT_100HDX: printk(", 100MBit Half Duplex"); break; | 746 | if (!fep->mii_bus->irq) { | 
| 1238 | case PHY_STAT_10FDX: printk(", 10MBit Full Duplex"); break; | 747 | err = -ENOMEM; | 
| 1239 | case PHY_STAT_10HDX: printk(", 10MBit Half Duplex"); break; | 748 | goto err_out_free_mdiobus; | 
| 1240 | default: | ||
| 1241 | printk(", Unknown speed/duplex"); | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | if (*s & PHY_STAT_ANC) | ||
| 1245 | printk(", auto-negotiation complete"); | ||
| 1246 | } | 749 | } | 
| 1247 | 750 | ||
| 1248 | if (*s & PHY_STAT_FAULT) | 751 | for (i = 0; i < PHY_MAX_ADDR; i++) | 
| 1249 | printk(", remote fault"); | 752 | fep->mii_bus->irq[i] = PHY_POLL; | 
| 1250 | |||
| 1251 | printk(".\n"); | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | static void mii_display_config(struct work_struct *work) | ||
| 1255 | { | ||
| 1256 | struct fec_enet_private *fep = container_of(work, struct fec_enet_private, phy_task); | ||
| 1257 | struct net_device *dev = fep->netdev; | ||
| 1258 | uint status = fep->phy_status; | ||
| 1259 | 753 | ||
| 1260 | /* | 754 | platform_set_drvdata(dev, fep->mii_bus); | 
| 1261 | ** When we get here, phy_task is already removed from | ||
| 1262 | ** the workqueue. It is thus safe to allow to reuse it. | ||
| 1263 | */ | ||
| 1264 | fep->mii_phy_task_queued = 0; | ||
| 1265 | printk("%s: config: auto-negotiation ", dev->name); | ||
| 1266 | |||
| 1267 | if (status & PHY_CONF_ANE) | ||
| 1268 | printk("on"); | ||
| 1269 | else | ||
| 1270 | printk("off"); | ||
| 1271 | 755 | ||
| 1272 | if (status & PHY_CONF_100FDX) | 756 | if (mdiobus_register(fep->mii_bus)) | 
| 1273 | printk(", 100FDX"); | 757 | goto err_out_free_mdio_irq; | 
| 1274 | if (status & PHY_CONF_100HDX) | ||
| 1275 | printk(", 100HDX"); | ||
| 1276 | if (status & PHY_CONF_10FDX) | ||
| 1277 | printk(", 10FDX"); | ||
| 1278 | if (status & PHY_CONF_10HDX) | ||
| 1279 | printk(", 10HDX"); | ||
| 1280 | if (!(status & PHY_CONF_SPMASK)) | ||
| 1281 | printk(", No speed/duplex selected?"); | ||
| 1282 | 758 | ||
| 1283 | if (status & PHY_CONF_LOOP) | 759 | if (fec_enet_mii_probe(dev) != 0) | 
| 1284 | printk(", loopback enabled"); | 760 | goto err_out_unregister_bus; | 
| 1285 | 761 | ||
| 1286 | printk(".\n"); | 762 | return 0; | 
| 1287 | 763 | ||
| 1288 | fep->sequence_done = 1; | 764 | err_out_unregister_bus: | 
| 765 | mdiobus_unregister(fep->mii_bus); | ||
| 766 | err_out_free_mdio_irq: | ||
| 767 | kfree(fep->mii_bus->irq); | ||
| 768 | err_out_free_mdiobus: | ||
| 769 | mdiobus_free(fep->mii_bus); | ||
| 770 | err_out: | ||
| 771 | return err; | ||
| 1289 | } | 772 | } | 
| 1290 | 773 | ||
| 1291 | static void mii_relink(struct work_struct *work) | 774 | static void fec_enet_mii_remove(struct fec_enet_private *fep) | 
| 1292 | { | 775 | { | 
| 1293 | struct fec_enet_private *fep = container_of(work, struct fec_enet_private, phy_task); | 776 | if (fep->phy_dev) | 
| 1294 | struct net_device *dev = fep->netdev; | 777 | phy_disconnect(fep->phy_dev); | 
| 1295 | int duplex; | 778 | mdiobus_unregister(fep->mii_bus); | 
| 1296 | 779 | kfree(fep->mii_bus->irq); | |
| 1297 | /* | 780 | mdiobus_free(fep->mii_bus); | 
| 1298 | ** When we get here, phy_task is already removed from | ||
| 1299 | ** the workqueue. It is thus safe to allow to reuse it. | ||
| 1300 | */ | ||
| 1301 | fep->mii_phy_task_queued = 0; | ||
| 1302 | fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0; | ||
| 1303 | mii_display_status(dev); | ||
| 1304 | fep->old_link = fep->link; | ||
| 1305 | |||
| 1306 | if (fep->link) { | ||
| 1307 | duplex = 0; | ||
| 1308 | if (fep->phy_status | ||
| 1309 | & (PHY_STAT_100FDX | PHY_STAT_10FDX)) | ||
| 1310 | duplex = 1; | ||
| 1311 | fec_restart(dev, duplex); | ||
| 1312 | } else | ||
| 1313 | fec_stop(dev); | ||
| 1314 | } | 781 | } | 
| 1315 | 782 | ||
| 1316 | /* mii_queue_relink is called in interrupt context from mii_link_interrupt */ | 783 | static int fec_enet_get_settings(struct net_device *dev, | 
| 1317 | static void mii_queue_relink(uint mii_reg, struct net_device *dev) | 784 | struct ethtool_cmd *cmd) | 
| 1318 | { | 785 | { | 
| 1319 | struct fec_enet_private *fep = netdev_priv(dev); | 786 | struct fec_enet_private *fep = netdev_priv(dev); | 
| 787 | struct phy_device *phydev = fep->phy_dev; | ||
| 1320 | 788 | ||
| 1321 | /* | 789 | if (!phydev) | 
| 1322 | * We cannot queue phy_task twice in the workqueue. It | 790 | return -ENODEV; | 
| 1323 | * would cause an endless loop in the workqueue. | ||
| 1324 | * Fortunately, if the last mii_relink entry has not yet been | ||
| 1325 | * executed now, it will do the job for the current interrupt, | ||
| 1326 | * which is just what we want. | ||
| 1327 | */ | ||
| 1328 | if (fep->mii_phy_task_queued) | ||
| 1329 | return; | ||
| 1330 | 791 | ||
| 1331 | fep->mii_phy_task_queued = 1; | 792 | return phy_ethtool_gset(phydev, cmd); | 
| 1332 | INIT_WORK(&fep->phy_task, mii_relink); | ||
| 1333 | schedule_work(&fep->phy_task); | ||
| 1334 | } | 793 | } | 
| 1335 | 794 | ||
| 1336 | /* mii_queue_config is called in interrupt context from fec_enet_mii */ | 795 | static int fec_enet_set_settings(struct net_device *dev, | 
| 1337 | static void mii_queue_config(uint mii_reg, struct net_device *dev) | 796 | struct ethtool_cmd *cmd) | 
| 1338 | { | 797 | { | 
| 1339 | struct fec_enet_private *fep = netdev_priv(dev); | 798 | struct fec_enet_private *fep = netdev_priv(dev); | 
| 799 | struct phy_device *phydev = fep->phy_dev; | ||
| 1340 | 800 | ||
| 1341 | if (fep->mii_phy_task_queued) | 801 | if (!phydev) | 
| 1342 | return; | 802 | return -ENODEV; | 
| 1343 | 803 | ||
| 1344 | fep->mii_phy_task_queued = 1; | 804 | return phy_ethtool_sset(phydev, cmd); | 
| 1345 | INIT_WORK(&fep->phy_task, mii_display_config); | ||
| 1346 | schedule_work(&fep->phy_task); | ||
| 1347 | } | 805 | } | 
| 1348 | 806 | ||
| 1349 | phy_cmd_t const phy_cmd_relink[] = { | 807 | static void fec_enet_get_drvinfo(struct net_device *dev, | 
| 1350 | { mk_mii_read(MII_REG_CR), mii_queue_relink }, | 808 | struct ethtool_drvinfo *info) | 
| 1351 | { mk_mii_end, } | ||
| 1352 | }; | ||
| 1353 | phy_cmd_t const phy_cmd_config[] = { | ||
| 1354 | { mk_mii_read(MII_REG_CR), mii_queue_config }, | ||
| 1355 | { mk_mii_end, } | ||
| 1356 | }; | ||
| 1357 | |||
| 1358 | /* Read remainder of PHY ID. */ | ||
| 1359 | static void | ||
| 1360 | mii_discover_phy3(uint mii_reg, struct net_device *dev) | ||
| 1361 | { | 809 | { | 
| 1362 | struct fec_enet_private *fep; | 810 | struct fec_enet_private *fep = netdev_priv(dev); | 
| 1363 | int i; | ||
| 1364 | |||
| 1365 | fep = netdev_priv(dev); | ||
| 1366 | fep->phy_id |= (mii_reg & 0xffff); | ||
| 1367 | printk("fec: PHY @ 0x%x, ID 0x%08x", fep->phy_addr, fep->phy_id); | ||
| 1368 | |||
| 1369 | for(i = 0; phy_info[i]; i++) { | ||
| 1370 | if(phy_info[i]->id == (fep->phy_id >> 4)) | ||
| 1371 | break; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | if (phy_info[i]) | ||
| 1375 | printk(" -- %s\n", phy_info[i]->name); | ||
| 1376 | else | ||
| 1377 | printk(" -- unknown PHY!\n"); | ||
| 1378 | 811 | ||
| 1379 | fep->phy = phy_info[i]; | 812 | strcpy(info->driver, fep->pdev->dev.driver->name); | 
| 1380 | fep->phy_id_done = 1; | 813 | strcpy(info->version, "Revision: 1.0"); | 
| 814 | strcpy(info->bus_info, dev_name(&dev->dev)); | ||
| 1381 | } | 815 | } | 
| 1382 | 816 | ||
| 1383 | /* Scan all of the MII PHY addresses looking for someone to respond | 817 | static struct ethtool_ops fec_enet_ethtool_ops = { | 
| 1384 | * with a valid ID. This usually happens quickly. | 818 | .get_settings = fec_enet_get_settings, | 
| 1385 | */ | 819 | .set_settings = fec_enet_set_settings, | 
| 1386 | static void | 820 | .get_drvinfo = fec_enet_get_drvinfo, | 
| 1387 | mii_discover_phy(uint mii_reg, struct net_device *dev) | 821 | .get_link = ethtool_op_get_link, | 
| 1388 | { | 822 | }; | 
| 1389 | struct fec_enet_private *fep; | ||
| 1390 | uint phytype; | ||
| 1391 | |||
| 1392 | fep = netdev_priv(dev); | ||
| 1393 | |||
| 1394 | if (fep->phy_addr < 32) { | ||
| 1395 | if ((phytype = (mii_reg & 0xffff)) != 0xffff && phytype != 0) { | ||
| 1396 | |||
| 1397 | /* Got first part of ID, now get remainder */ | ||
| 1398 | fep->phy_id = phytype << 16; | ||
| 1399 | mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR2), | ||
| 1400 | mii_discover_phy3); | ||
| 1401 | } else { | ||
| 1402 | fep->phy_addr++; | ||
| 1403 | mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR1), | ||
| 1404 | mii_discover_phy); | ||
| 1405 | } | ||
| 1406 | } else { | ||
| 1407 | printk("FEC: No PHY device found.\n"); | ||
| 1408 | /* Disable external MII interface */ | ||
| 1409 | writel(0, fep->hwp + FEC_MII_SPEED); | ||
| 1410 | fep->phy_speed = 0; | ||
| 1411 | #ifdef HAVE_mii_link_interrupt | ||
| 1412 | fec_disable_phy_intr(dev); | ||
| 1413 | #endif | ||
| 1414 | } | ||
| 1415 | } | ||
| 1416 | 823 | ||
| 1417 | /* This interrupt occurs when the PHY detects a link change */ | 824 | static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 
| 1418 | #ifdef HAVE_mii_link_interrupt | ||
| 1419 | static irqreturn_t | ||
| 1420 | mii_link_interrupt(int irq, void * dev_id) | ||
| 1421 | { | 825 | { | 
| 1422 | struct net_device *dev = dev_id; | ||
| 1423 | struct fec_enet_private *fep = netdev_priv(dev); | 826 | struct fec_enet_private *fep = netdev_priv(dev); | 
| 827 | struct phy_device *phydev = fep->phy_dev; | ||
| 828 | |||
| 829 | if (!netif_running(dev)) | ||
| 830 | return -EINVAL; | ||
| 1424 | 831 | ||
| 1425 | mii_do_cmd(dev, fep->phy->ack_int); | 832 | if (!phydev) | 
| 1426 | mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */ | 833 | return -ENODEV; | 
| 1427 | 834 | ||
| 1428 | return IRQ_HANDLED; | 835 | return phy_mii_ioctl(phydev, if_mii(rq), cmd); | 
| 1429 | } | 836 | } | 
| 1430 | #endif | ||
| 1431 | 837 | ||
| 1432 | static void fec_enet_free_buffers(struct net_device *dev) | 838 | static void fec_enet_free_buffers(struct net_device *dev) | 
| 1433 | { | 839 | { | 
| @@ -1509,35 +915,8 @@ fec_enet_open(struct net_device *dev) | |||
| 1509 | if (ret) | 915 | if (ret) | 
| 1510 | return ret; | 916 | return ret; | 
| 1511 | 917 | ||
| 1512 | fep->sequence_done = 0; | 918 | /* schedule a link state check */ | 
| 1513 | fep->link = 0; | 919 | phy_start(fep->phy_dev); | 
| 1514 | |||
| 1515 | fec_restart(dev, 1); | ||
| 1516 | |||
| 1517 | if (fep->phy) { | ||
| 1518 | mii_do_cmd(dev, fep->phy->ack_int); | ||
| 1519 | mii_do_cmd(dev, fep->phy->config); | ||
| 1520 | mii_do_cmd(dev, phy_cmd_config); /* display configuration */ | ||
| 1521 | |||
| 1522 | /* Poll until the PHY tells us its configuration | ||
| 1523 | * (not link state). | ||
| 1524 | * Request is initiated by mii_do_cmd above, but answer | ||
| 1525 | * comes by interrupt. | ||
| 1526 | * This should take about 25 usec per register at 2.5 MHz, | ||
| 1527 | * and we read approximately 5 registers. | ||
| 1528 | */ | ||
| 1529 | while(!fep->sequence_done) | ||
| 1530 | schedule(); | ||
| 1531 | |||
| 1532 | mii_do_cmd(dev, fep->phy->startup); | ||
| 1533 | } | ||
| 1534 | |||
| 1535 | /* Set the initial link state to true. A lot of hardware | ||
| 1536 | * based on this device does not implement a PHY interrupt, | ||
| 1537 | * so we are never notified of link change. | ||
| 1538 | */ | ||
| 1539 | fep->link = 1; | ||
| 1540 | |||
| 1541 | netif_start_queue(dev); | 920 | netif_start_queue(dev); | 
| 1542 | fep->opened = 1; | 921 | fep->opened = 1; | 
| 1543 | return 0; | 922 | return 0; | 
| @@ -1550,6 +929,7 @@ fec_enet_close(struct net_device *dev) | |||
| 1550 | 929 | ||
| 1551 | /* Don't know what to do yet. */ | 930 | /* Don't know what to do yet. */ | 
| 1552 | fep->opened = 0; | 931 | fep->opened = 0; | 
| 932 | phy_stop(fep->phy_dev); | ||
| 1553 | netif_stop_queue(dev); | 933 | netif_stop_queue(dev); | 
| 1554 | fec_stop(dev); | 934 | fec_stop(dev); | 
| 1555 | 935 | ||
| @@ -1574,7 +954,7 @@ fec_enet_close(struct net_device *dev) | |||
| 1574 | static void set_multicast_list(struct net_device *dev) | 954 | static void set_multicast_list(struct net_device *dev) | 
| 1575 | { | 955 | { | 
| 1576 | struct fec_enet_private *fep = netdev_priv(dev); | 956 | struct fec_enet_private *fep = netdev_priv(dev); | 
| 1577 | struct dev_mc_list *dmi; | 957 | struct netdev_hw_addr *ha; | 
| 1578 | unsigned int i, bit, data, crc, tmp; | 958 | unsigned int i, bit, data, crc, tmp; | 
| 1579 | unsigned char hash; | 959 | unsigned char hash; | 
| 1580 | 960 | ||
| @@ -1604,16 +984,16 @@ static void set_multicast_list(struct net_device *dev) | |||
| 1604 | writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); | 984 | writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); | 
| 1605 | writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); | 985 | writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); | 
| 1606 | 986 | ||
| 1607 | netdev_for_each_mc_addr(dmi, dev) { | 987 | netdev_for_each_mc_addr(ha, dev) { | 
| 1608 | /* Only support group multicast for now */ | 988 | /* Only support group multicast for now */ | 
| 1609 | if (!(dmi->dmi_addr[0] & 1)) | 989 | if (!(ha->addr[0] & 1)) | 
| 1610 | continue; | 990 | continue; | 
| 1611 | 991 | ||
| 1612 | /* calculate crc32 value of mac address */ | 992 | /* calculate crc32 value of mac address */ | 
| 1613 | crc = 0xffffffff; | 993 | crc = 0xffffffff; | 
| 1614 | 994 | ||
| 1615 | for (i = 0; i < dmi->dmi_addrlen; i++) { | 995 | for (i = 0; i < dev->addr_len; i++) { | 
| 1616 | data = dmi->dmi_addr[i]; | 996 | data = ha->addr[i]; | 
| 1617 | for (bit = 0; bit < 8; bit++, data >>= 1) { | 997 | for (bit = 0; bit < 8; bit++, data >>= 1) { | 
| 1618 | crc = (crc >> 1) ^ | 998 | crc = (crc >> 1) ^ | 
| 1619 | (((crc ^ data) & 1) ? CRC32_POLY : 0); | 999 | (((crc ^ data) & 1) ? CRC32_POLY : 0); | 
| @@ -1666,6 +1046,7 @@ static const struct net_device_ops fec_netdev_ops = { | |||
| 1666 | .ndo_validate_addr = eth_validate_addr, | 1046 | .ndo_validate_addr = eth_validate_addr, | 
| 1667 | .ndo_tx_timeout = fec_timeout, | 1047 | .ndo_tx_timeout = fec_timeout, | 
| 1668 | .ndo_set_mac_address = fec_set_mac_address, | 1048 | .ndo_set_mac_address = fec_set_mac_address, | 
| 1049 | .ndo_do_ioctl = fec_enet_ioctl, | ||
| 1669 | }; | 1050 | }; | 
| 1670 | 1051 | ||
| 1671 | /* | 1052 | /* | 
| @@ -1689,7 +1070,6 @@ static int fec_enet_init(struct net_device *dev, int index) | |||
| 1689 | } | 1070 | } | 
| 1690 | 1071 | ||
| 1691 | spin_lock_init(&fep->hw_lock); | 1072 | spin_lock_init(&fep->hw_lock); | 
| 1692 | spin_lock_init(&fep->mii_lock); | ||
| 1693 | 1073 | ||
| 1694 | fep->index = index; | 1074 | fep->index = index; | 
| 1695 | fep->hwp = (void __iomem *)dev->base_addr; | 1075 | fep->hwp = (void __iomem *)dev->base_addr; | 
| @@ -1716,20 +1096,10 @@ static int fec_enet_init(struct net_device *dev, int index) | |||
| 1716 | fep->rx_bd_base = cbd_base; | 1096 | fep->rx_bd_base = cbd_base; | 
| 1717 | fep->tx_bd_base = cbd_base + RX_RING_SIZE; | 1097 | fep->tx_bd_base = cbd_base + RX_RING_SIZE; | 
| 1718 | 1098 | ||
| 1719 | #ifdef HAVE_mii_link_interrupt | ||
| 1720 | fec_request_mii_intr(dev); | ||
| 1721 | #endif | ||
| 1722 | /* The FEC Ethernet specific entries in the device structure */ | 1099 | /* The FEC Ethernet specific entries in the device structure */ | 
| 1723 | dev->watchdog_timeo = TX_TIMEOUT; | 1100 | dev->watchdog_timeo = TX_TIMEOUT; | 
| 1724 | dev->netdev_ops = &fec_netdev_ops; | 1101 | dev->netdev_ops = &fec_netdev_ops; | 
| 1725 | 1102 | dev->ethtool_ops = &fec_enet_ethtool_ops; | |
| 1726 | for (i=0; i<NMII-1; i++) | ||
| 1727 | mii_cmds[i].mii_next = &mii_cmds[i+1]; | ||
| 1728 | mii_free = mii_cmds; | ||
| 1729 | |||
| 1730 | /* Set MII speed to 2.5 MHz */ | ||
| 1731 | fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) | ||
| 1732 | / 2500000) / 2) & 0x3F) << 1; | ||
| 1733 | 1103 | ||
| 1734 | /* Initialize the receive buffer descriptors. */ | 1104 | /* Initialize the receive buffer descriptors. */ | 
| 1735 | bdp = fep->rx_bd_base; | 1105 | bdp = fep->rx_bd_base; | 
| @@ -1760,13 +1130,6 @@ static int fec_enet_init(struct net_device *dev, int index) | |||
| 1760 | 1130 | ||
| 1761 | fec_restart(dev, 0); | 1131 | fec_restart(dev, 0); | 
| 1762 | 1132 | ||
| 1763 | /* Queue up command to detect the PHY and initialize the | ||
| 1764 | * remainder of the interface. | ||
| 1765 | */ | ||
| 1766 | fep->phy_id_done = 0; | ||
| 1767 | fep->phy_addr = 0; | ||
| 1768 | mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy); | ||
| 1769 | |||
| 1770 | return 0; | 1133 | return 0; | 
| 1771 | } | 1134 | } | 
| 1772 | 1135 | ||
| @@ -1835,8 +1198,7 @@ fec_restart(struct net_device *dev, int duplex) | |||
| 1835 | writel(0, fep->hwp + FEC_R_DES_ACTIVE); | 1198 | writel(0, fep->hwp + FEC_R_DES_ACTIVE); | 
| 1836 | 1199 | ||
| 1837 | /* Enable interrupts we wish to service */ | 1200 | /* Enable interrupts we wish to service */ | 
| 1838 | writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII, | 1201 | writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->hwp + FEC_IMASK); | 
| 1839 | fep->hwp + FEC_IMASK); | ||
| 1840 | } | 1202 | } | 
| 1841 | 1203 | ||
| 1842 | static void | 1204 | static void | 
| @@ -1859,7 +1221,6 @@ fec_stop(struct net_device *dev) | |||
| 1859 | /* Clear outstanding MII command interrupts. */ | 1221 | /* Clear outstanding MII command interrupts. */ | 
| 1860 | writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); | 1222 | writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); | 
| 1861 | 1223 | ||
| 1862 | writel(FEC_ENET_MII, fep->hwp + FEC_IMASK); | ||
| 1863 | writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); | 1224 | writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); | 
| 1864 | } | 1225 | } | 
| 1865 | 1226 | ||
| @@ -1891,6 +1252,7 @@ fec_probe(struct platform_device *pdev) | |||
| 1891 | memset(fep, 0, sizeof(*fep)); | 1252 | memset(fep, 0, sizeof(*fep)); | 
| 1892 | 1253 | ||
| 1893 | ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); | 1254 | ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); | 
| 1255 | fep->pdev = pdev; | ||
| 1894 | 1256 | ||
| 1895 | if (!ndev->base_addr) { | 1257 | if (!ndev->base_addr) { | 
| 1896 | ret = -ENOMEM; | 1258 | ret = -ENOMEM; | 
| @@ -1926,13 +1288,24 @@ fec_probe(struct platform_device *pdev) | |||
| 1926 | if (ret) | 1288 | if (ret) | 
| 1927 | goto failed_init; | 1289 | goto failed_init; | 
| 1928 | 1290 | ||
| 1291 | ret = fec_enet_mii_init(pdev); | ||
| 1292 | if (ret) | ||
| 1293 | goto failed_mii_init; | ||
| 1294 | |||
| 1929 | ret = register_netdev(ndev); | 1295 | ret = register_netdev(ndev); | 
| 1930 | if (ret) | 1296 | if (ret) | 
| 1931 | goto failed_register; | 1297 | goto failed_register; | 
| 1932 | 1298 | ||
| 1299 | printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] " | ||
| 1300 | "(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name, | ||
| 1301 | fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev), | ||
| 1302 | fep->phy_dev->irq); | ||
| 1303 | |||
| 1933 | return 0; | 1304 | return 0; | 
| 1934 | 1305 | ||
| 1935 | failed_register: | 1306 | failed_register: | 
| 1307 | fec_enet_mii_remove(fep); | ||
| 1308 | failed_mii_init: | ||
| 1936 | failed_init: | 1309 | failed_init: | 
| 1937 | clk_disable(fep->clk); | 1310 | clk_disable(fep->clk); | 
| 1938 | clk_put(fep->clk); | 1311 | clk_put(fep->clk); | 
| @@ -1959,6 +1332,7 @@ fec_drv_remove(struct platform_device *pdev) | |||
| 1959 | platform_set_drvdata(pdev, NULL); | 1332 | platform_set_drvdata(pdev, NULL); | 
| 1960 | 1333 | ||
| 1961 | fec_stop(ndev); | 1334 | fec_stop(ndev); | 
| 1335 | fec_enet_mii_remove(fep); | ||
| 1962 | clk_disable(fep->clk); | 1336 | clk_disable(fep->clk); | 
| 1963 | clk_put(fep->clk); | 1337 | clk_put(fep->clk); | 
| 1964 | iounmap((void __iomem *)ndev->base_addr); | 1338 | iounmap((void __iomem *)ndev->base_addr); | 
