diff options
Diffstat (limited to 'drivers/net/fec.c')
-rw-r--r-- | drivers/net/fec.c | 1140 |
1 files changed, 256 insertions, 884 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 9b4e8f797a7a..42d9ac9ba395 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 | { |
@@ -347,8 +275,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
347 | | BD_ENET_TX_LAST | BD_ENET_TX_TC); | 275 | | BD_ENET_TX_LAST | BD_ENET_TX_TC); |
348 | bdp->cbd_sc = status; | 276 | bdp->cbd_sc = status; |
349 | 277 | ||
350 | dev->trans_start = jiffies; | ||
351 | |||
352 | /* Trigger transmission start */ | 278 | /* Trigger transmission start */ |
353 | writel(0, fep->hwp + FEC_X_DES_ACTIVE); | 279 | writel(0, fep->hwp + FEC_X_DES_ACTIVE); |
354 | 280 | ||
@@ -406,12 +332,6 @@ fec_enet_interrupt(int irq, void * dev_id) | |||
406 | ret = IRQ_HANDLED; | 332 | ret = IRQ_HANDLED; |
407 | fec_enet_tx(dev); | 333 | fec_enet_tx(dev); |
408 | } | 334 | } |
409 | |||
410 | if (int_events & FEC_ENET_MII) { | ||
411 | ret = IRQ_HANDLED; | ||
412 | fec_enet_mii(dev); | ||
413 | } | ||
414 | |||
415 | } while (int_events); | 335 | } while (int_events); |
416 | 336 | ||
417 | return ret; | 337 | return ret; |
@@ -607,827 +527,311 @@ rx_processing_done: | |||
607 | spin_unlock(&fep->hw_lock); | 527 | spin_unlock(&fep->hw_lock); |
608 | } | 528 | } |
609 | 529 | ||
610 | /* called from interrupt context */ | 530 | /* ------------------------------------------------------------------------- */ |
611 | static void | 531 | #ifdef CONFIG_M5272 |
612 | fec_enet_mii(struct net_device *dev) | 532 | 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 | { | 533 | { |
643 | struct fec_enet_private *fep; | 534 | struct fec_enet_private *fep = netdev_priv(dev); |
644 | mii_list_t *mip; | 535 | unsigned char *iap, tmpaddr[ETH_ALEN]; |
645 | int retval; | ||
646 | |||
647 | /* Add PHY address to register command */ | ||
648 | fep = netdev_priv(dev); | ||
649 | 536 | ||
650 | regval |= fep->phy_addr << 23; | 537 | if (FEC_FLASHMAC) { |
651 | retval = 0; | 538 | /* |
652 | 539 | * Get MAC address from FLASH. | |
653 | if ((mip = mii_free) != NULL) { | 540 | * If it is all 1's or 0's, use the default. |
654 | mii_free = mip->mii_next; | 541 | */ |
655 | mip->mii_regval = regval; | 542 | iap = (unsigned char *)FEC_FLASHMAC; |
656 | mip->mii_func = func; | 543 | if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && |
657 | mip->mii_next = NULL; | 544 | (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) |
658 | if (mii_head) { | 545 | iap = fec_mac_default; |
659 | mii_tail->mii_next = mip; | 546 | if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && |
660 | mii_tail = mip; | 547 | (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) |
661 | } else { | 548 | iap = fec_mac_default; |
662 | mii_head = mii_tail = mip; | ||
663 | writel(regval, fep->hwp + FEC_MII_DATA); | ||
664 | } | ||
665 | } else { | 549 | } else { |
666 | retval = 1; | 550 | *((unsigned long *) &tmpaddr[0]) = readl(fep->hwp + FEC_ADDR_LOW); |
551 | *((unsigned short *) &tmpaddr[4]) = (readl(fep->hwp + FEC_ADDR_HIGH) >> 16); | ||
552 | iap = &tmpaddr[0]; | ||
667 | } | 553 | } |
668 | 554 | ||
669 | return retval; | 555 | 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 | 556 | ||
691 | for (; c->mii_data != mk_mii_end; c++) | 557 | /* Adjust MAC if using default MAC address */ |
692 | mii_queue(dev, c->mii_data, c->funct); | 558 | if (iap == fec_mac_default) |
559 | dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; | ||
693 | } | 560 | } |
561 | #endif | ||
694 | 562 | ||
695 | static void mii_parse_sr(uint mii_reg, struct net_device *dev) | 563 | /* ------------------------------------------------------------------------- */ |
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 | 564 | ||
712 | static void mii_parse_cr(uint mii_reg, struct net_device *dev) | 565 | /* |
566 | * Phy section | ||
567 | */ | ||
568 | static void fec_enet_adjust_link(struct net_device *dev) | ||
713 | { | 569 | { |
714 | struct fec_enet_private *fep = netdev_priv(dev); | 570 | struct fec_enet_private *fep = netdev_priv(dev); |
715 | volatile uint *s = &(fep->phy_status); | 571 | struct phy_device *phy_dev = fep->phy_dev; |
716 | uint status; | 572 | 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 | 573 | ||
727 | static void mii_parse_anar(uint mii_reg, struct net_device *dev) | 574 | 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 | 575 | ||
746 | /* ------------------------------------------------------------------------- */ | 576 | spin_lock_irqsave(&fep->hw_lock, flags); |
747 | /* The Level one LXT970 is used by many boards */ | ||
748 | 577 | ||
749 | #define MII_LXT970_MIRROR 16 /* Mirror register */ | 578 | /* Prevent a state halted on mii error */ |
750 | #define MII_LXT970_IER 17 /* Interrupt Enable Register */ | 579 | if (fep->mii_timeout && phy_dev->state == PHY_HALTED) { |
751 | #define MII_LXT970_ISR 18 /* Interrupt Status Register */ | 580 | phy_dev->state = PHY_RESUMING; |
752 | #define MII_LXT970_CONFIG 19 /* Configuration Register */ | 581 | goto spin_unlock; |
753 | #define MII_LXT970_CSR 20 /* Chip Status Register */ | 582 | } |
754 | 583 | ||
755 | static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev) | 584 | /* Duplex link change */ |
756 | { | 585 | if (phy_dev->link) { |
757 | struct fec_enet_private *fep = netdev_priv(dev); | 586 | if (fep->full_duplex != phy_dev->duplex) { |
758 | volatile uint *s = &(fep->phy_status); | 587 | fec_restart(dev, phy_dev->duplex); |
759 | uint status; | 588 | status_change = 1; |
589 | } | ||
590 | } | ||
760 | 591 | ||
761 | status = *s & ~(PHY_STAT_SPMASK); | 592 | /* Link on or off change */ |
762 | if (mii_reg & 0x0800) { | 593 | if (phy_dev->link != fep->link) { |
763 | if (mii_reg & 0x1000) | 594 | fep->link = phy_dev->link; |
764 | status |= PHY_STAT_100FDX; | 595 | if (phy_dev->link) |
765 | else | 596 | fec_restart(dev, phy_dev->duplex); |
766 | status |= PHY_STAT_100HDX; | ||
767 | } else { | ||
768 | if (mii_reg & 0x1000) | ||
769 | status |= PHY_STAT_10FDX; | ||
770 | else | 597 | else |
771 | status |= PHY_STAT_10HDX; | 598 | fec_stop(dev); |
599 | status_change = 1; | ||
772 | } | 600 | } |
773 | *s = status; | ||
774 | } | ||
775 | 601 | ||
776 | static phy_cmd_t const phy_cmd_lxt970_config[] = { | 602 | spin_unlock: |
777 | { mk_mii_read(MII_REG_CR), mii_parse_cr }, | 603 | spin_unlock_irqrestore(&fep->hw_lock, flags); |
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 | |||
808 | /* ------------------------------------------------------------------------- */ | ||
809 | /* The Level one LXT971 is used on some of my custom boards */ | ||
810 | |||
811 | /* register definitions for the 971 */ | ||
812 | 604 | ||
813 | #define MII_LXT971_PCR 16 /* Port Control Register */ | 605 | if (status_change) |
814 | #define MII_LXT971_SR2 17 /* Status Register 2 */ | 606 | phy_print_status(phy_dev); |
815 | #define MII_LXT971_IER 18 /* Interrupt Enable Register */ | 607 | } |
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 | 608 | ||
820 | /* | 609 | /* |
821 | * I had some nice ideas of running the MDIO faster... | 610 | * 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 | */ | 611 | */ |
825 | 612 | 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 | { | 613 | { |
828 | struct fec_enet_private *fep = netdev_priv(dev); | 614 | struct fec_enet_private *fep = bus->priv; |
829 | volatile uint *s = &(fep->phy_status); | 615 | int timeout = FEC_MII_TIMEOUT; |
830 | uint status; | ||
831 | 616 | ||
832 | status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC); | 617 | fep->mii_timeout = 0; |
833 | 618 | ||
834 | if (mii_reg & 0x0400) { | 619 | /* clear MII end of transfer bit*/ |
835 | fep->link = 1; | 620 | writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); |
836 | status |= PHY_STAT_LINK; | 621 | |
837 | } else { | 622 | /* start a read op */ |
838 | fep->link = 0; | 623 | writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | |
839 | } | 624 | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | |
840 | if (mii_reg & 0x0080) | 625 | FEC_MMFR_TA, fep->hwp + FEC_MII_DATA); |
841 | status |= PHY_STAT_ANC; | 626 | |
842 | if (mii_reg & 0x4000) { | 627 | /* wait for end of transfer */ |
843 | if (mii_reg & 0x0200) | 628 | while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) { |
844 | status |= PHY_STAT_100FDX; | 629 | cpu_relax(); |
845 | else | 630 | if (timeout-- < 0) { |
846 | status |= PHY_STAT_100HDX; | 631 | fep->mii_timeout = 1; |
847 | } else { | 632 | printk(KERN_ERR "FEC: MDIO read timeout\n"); |
848 | if (mii_reg & 0x0200) | 633 | return -ETIMEDOUT; |
849 | status |= PHY_STAT_10FDX; | 634 | } |
850 | else | ||
851 | status |= PHY_STAT_10HDX; | ||
852 | } | 635 | } |
853 | if (mii_reg & 0x0008) | ||
854 | status |= PHY_STAT_FAULT; | ||
855 | 636 | ||
856 | *s = status; | 637 | /* return value */ |
638 | return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); | ||
857 | } | 639 | } |
858 | 640 | ||
859 | static phy_cmd_t const phy_cmd_lxt971_config[] = { | 641 | static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, |
860 | /* limit to 10MBit because my prototype board | 642 | 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 | { | 643 | { |
912 | struct fec_enet_private *fep = netdev_priv(dev); | 644 | struct fec_enet_private *fep = bus->priv; |
913 | volatile uint *s = &(fep->phy_status); | 645 | int timeout = FEC_MII_TIMEOUT; |
914 | uint status; | ||
915 | |||
916 | status = *s & ~(PHY_STAT_SPMASK); | ||
917 | 646 | ||
918 | switch((mii_reg >> 2) & 7) { | 647 | fep->mii_timeout = 0; |
919 | case 1: status |= PHY_STAT_10HDX; break; | ||
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 | 648 | ||
928 | static phy_cmd_t const phy_cmd_qs6612_config[] = { | 649 | /* clear MII end of transfer bit*/ |
929 | /* The PHY powers up isolated on the RPX, | 650 | writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); |
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 | 651 | ||
970 | /* register definitions for the 874 */ | 652 | /* start a read op */ |
653 | writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | | ||
654 | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | | ||
655 | FEC_MMFR_TA | FEC_MMFR_DATA(value), | ||
656 | fep->hwp + FEC_MII_DATA); | ||
657 | |||
658 | /* wait for end of transfer */ | ||
659 | while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) { | ||
660 | cpu_relax(); | ||
661 | if (timeout-- < 0) { | ||
662 | fep->mii_timeout = 1; | ||
663 | printk(KERN_ERR "FEC: MDIO write timeout\n"); | ||
664 | return -ETIMEDOUT; | ||
665 | } | ||
666 | } | ||
971 | 667 | ||
972 | #define MII_AM79C874_MFR 16 /* Miscellaneous Feature Register */ | 668 | return 0; |
973 | #define MII_AM79C874_ICSR 17 /* Interrupt/Status Register */ | 669 | } |
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 | 670 | ||
980 | static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev) | 671 | static int fec_enet_mdio_reset(struct mii_bus *bus) |
981 | { | 672 | { |
982 | struct fec_enet_private *fep = netdev_priv(dev); | 673 | 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 | } | 674 | } |
997 | 675 | ||
998 | static phy_cmd_t const phy_cmd_am79c874_config[] = { | 676 | 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 | { | 677 | { |
1079 | struct fec_enet_private *fep = netdev_priv(dev); | 678 | struct fec_enet_private *fep = netdev_priv(dev); |
1080 | volatile uint *s = &(fep->phy_status); | 679 | struct phy_device *phy_dev = NULL; |
1081 | 680 | 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 | 681 | ||
1108 | static phy_info_t phy_info_dp83848= { | 682 | /* find the first phy */ |
1109 | 0x020005c9, | 683 | for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { |
1110 | "DP83848", | 684 | if (fep->mii_bus->phy_map[phy_addr]) { |
1111 | 685 | phy_dev = fep->mii_bus->phy_map[phy_addr]; | |
1112 | (const phy_cmd_t []) { /* config */ | 686 | break; |
1113 | { mk_mii_read(MII_REG_CR), mii_parse_cr }, | 687 | } |
1114 | { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, | 688 | } |
1115 | { mk_mii_read(MII_DP8384X_PHYSTST), mii_parse_dp8384x_sr2 }, | ||
1116 | { mk_mii_end, } | ||
1117 | }, | ||
1118 | (const phy_cmd_t []) { /* startup - enable interrupts */ | ||
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 | 689 | ||
1131 | static phy_info_t phy_info_lan8700 = { | 690 | if (!phy_dev) { |
1132 | 0x0007C0C, | 691 | printk(KERN_ERR "%s: no PHY found\n", dev->name); |
1133 | "LAN8700", | 692 | return -ENODEV; |
1134 | (const phy_cmd_t []) { /* config */ | 693 | } |
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 | 694 | ||
1153 | static phy_info_t const * const phy_info[] = { | 695 | /* attach the mac to the phy */ |
1154 | &phy_info_lxt970, | 696 | phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), |
1155 | &phy_info_lxt971, | 697 | &fec_enet_adjust_link, 0, |
1156 | &phy_info_qs6612, | 698 | PHY_INTERFACE_MODE_MII); |
1157 | &phy_info_am79c874, | 699 | if (IS_ERR(phy_dev)) { |
1158 | &phy_info_ks8721bl, | 700 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); |
1159 | &phy_info_dp83848, | 701 | return PTR_ERR(phy_dev); |
1160 | &phy_info_lan8700, | 702 | } |
1161 | NULL | ||
1162 | }; | ||
1163 | 703 | ||
1164 | /* ------------------------------------------------------------------------- */ | 704 | /* mask with MAC supported features */ |
1165 | #ifdef HAVE_mii_link_interrupt | 705 | phy_dev->supported &= PHY_BASIC_FEATURES; |
1166 | static irqreturn_t | 706 | phy_dev->advertising = phy_dev->supported; |
1167 | mii_link_interrupt(int irq, void * dev_id); | ||
1168 | 707 | ||
1169 | /* | 708 | fep->phy_dev = phy_dev; |
1170 | * This is specific to the MII interrupt setup of the M5272EVB. | 709 | fep->link = 0; |
1171 | */ | 710 | 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 | 711 | ||
1178 | static void __inline__ fec_disable_phy_intr(struct net_device *dev) | 712 | return 0; |
1179 | { | ||
1180 | free_irq(66, dev); | ||
1181 | } | 713 | } |
1182 | #endif | ||
1183 | 714 | ||
1184 | #ifdef CONFIG_M5272 | 715 | static int fec_enet_mii_init(struct platform_device *pdev) |
1185 | static void __inline__ fec_get_mac(struct net_device *dev) | ||
1186 | { | 716 | { |
717 | struct net_device *dev = platform_get_drvdata(pdev); | ||
1187 | struct fec_enet_private *fep = netdev_priv(dev); | 718 | struct fec_enet_private *fep = netdev_priv(dev); |
1188 | unsigned char *iap, tmpaddr[ETH_ALEN]; | 719 | int err = -ENXIO, i; |
1189 | 720 | ||
1190 | if (FEC_FLASHMAC) { | 721 | 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 | 722 | ||
1208 | memcpy(dev->dev_addr, iap, ETH_ALEN); | 723 | /* |
1209 | 724 | * Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed) | |
1210 | /* Adjust MAC if using default MAC address */ | 725 | */ |
1211 | if (iap == fec_mac_default) | 726 | fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000) << 1; |
1212 | dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; | 727 | writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); |
1213 | } | ||
1214 | #endif | ||
1215 | |||
1216 | /* ------------------------------------------------------------------------- */ | ||
1217 | |||
1218 | static void mii_display_status(struct net_device *dev) | ||
1219 | { | ||
1220 | struct fec_enet_private *fep = netdev_priv(dev); | ||
1221 | volatile uint *s = &(fep->phy_status); | ||
1222 | 728 | ||
1223 | if (!fep->link && !fep->old_link) { | 729 | fep->mii_bus = mdiobus_alloc(); |
1224 | /* Link is still down - don't print anything */ | 730 | if (fep->mii_bus == NULL) { |
1225 | return; | 731 | err = -ENOMEM; |
732 | goto err_out; | ||
1226 | } | 733 | } |
1227 | 734 | ||
1228 | printk("%s: status: ", dev->name); | 735 | fep->mii_bus->name = "fec_enet_mii_bus"; |
1229 | 736 | fep->mii_bus->read = fec_enet_mdio_read; | |
1230 | if (!fep->link) { | 737 | fep->mii_bus->write = fec_enet_mdio_write; |
1231 | printk("link down"); | 738 | fep->mii_bus->reset = fec_enet_mdio_reset; |
1232 | } else { | 739 | snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); |
1233 | printk("link up"); | 740 | fep->mii_bus->priv = fep; |
1234 | 741 | fep->mii_bus->parent = &pdev->dev; | |
1235 | switch(*s & PHY_STAT_SPMASK) { | 742 | |
1236 | case PHY_STAT_100FDX: printk(", 100MBit Full Duplex"); break; | 743 | fep->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); |
1237 | case PHY_STAT_100HDX: printk(", 100MBit Half Duplex"); break; | 744 | if (!fep->mii_bus->irq) { |
1238 | case PHY_STAT_10FDX: printk(", 10MBit Full Duplex"); break; | 745 | err = -ENOMEM; |
1239 | case PHY_STAT_10HDX: printk(", 10MBit Half Duplex"); break; | 746 | 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 | } | 747 | } |
1247 | 748 | ||
1248 | if (*s & PHY_STAT_FAULT) | 749 | for (i = 0; i < PHY_MAX_ADDR; i++) |
1249 | printk(", remote fault"); | 750 | 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 | 751 | ||
1260 | /* | 752 | 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 | 753 | ||
1272 | if (status & PHY_CONF_100FDX) | 754 | if (mdiobus_register(fep->mii_bus)) |
1273 | printk(", 100FDX"); | 755 | 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 | 756 | ||
1283 | if (status & PHY_CONF_LOOP) | 757 | if (fec_enet_mii_probe(dev) != 0) |
1284 | printk(", loopback enabled"); | 758 | goto err_out_unregister_bus; |
1285 | 759 | ||
1286 | printk(".\n"); | 760 | return 0; |
1287 | 761 | ||
1288 | fep->sequence_done = 1; | 762 | err_out_unregister_bus: |
763 | mdiobus_unregister(fep->mii_bus); | ||
764 | err_out_free_mdio_irq: | ||
765 | kfree(fep->mii_bus->irq); | ||
766 | err_out_free_mdiobus: | ||
767 | mdiobus_free(fep->mii_bus); | ||
768 | err_out: | ||
769 | return err; | ||
1289 | } | 770 | } |
1290 | 771 | ||
1291 | static void mii_relink(struct work_struct *work) | 772 | static void fec_enet_mii_remove(struct fec_enet_private *fep) |
1292 | { | 773 | { |
1293 | struct fec_enet_private *fep = container_of(work, struct fec_enet_private, phy_task); | 774 | if (fep->phy_dev) |
1294 | struct net_device *dev = fep->netdev; | 775 | phy_disconnect(fep->phy_dev); |
1295 | int duplex; | 776 | mdiobus_unregister(fep->mii_bus); |
1296 | 777 | kfree(fep->mii_bus->irq); | |
1297 | /* | 778 | 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 | } | 779 | } |
1315 | 780 | ||
1316 | /* mii_queue_relink is called in interrupt context from mii_link_interrupt */ | 781 | static int fec_enet_get_settings(struct net_device *dev, |
1317 | static void mii_queue_relink(uint mii_reg, struct net_device *dev) | 782 | struct ethtool_cmd *cmd) |
1318 | { | 783 | { |
1319 | struct fec_enet_private *fep = netdev_priv(dev); | 784 | struct fec_enet_private *fep = netdev_priv(dev); |
785 | struct phy_device *phydev = fep->phy_dev; | ||
1320 | 786 | ||
1321 | /* | 787 | if (!phydev) |
1322 | * We cannot queue phy_task twice in the workqueue. It | 788 | 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 | 789 | ||
1331 | fep->mii_phy_task_queued = 1; | 790 | return phy_ethtool_gset(phydev, cmd); |
1332 | INIT_WORK(&fep->phy_task, mii_relink); | ||
1333 | schedule_work(&fep->phy_task); | ||
1334 | } | 791 | } |
1335 | 792 | ||
1336 | /* mii_queue_config is called in interrupt context from fec_enet_mii */ | 793 | static int fec_enet_set_settings(struct net_device *dev, |
1337 | static void mii_queue_config(uint mii_reg, struct net_device *dev) | 794 | struct ethtool_cmd *cmd) |
1338 | { | 795 | { |
1339 | struct fec_enet_private *fep = netdev_priv(dev); | 796 | struct fec_enet_private *fep = netdev_priv(dev); |
797 | struct phy_device *phydev = fep->phy_dev; | ||
1340 | 798 | ||
1341 | if (fep->mii_phy_task_queued) | 799 | if (!phydev) |
1342 | return; | 800 | return -ENODEV; |
1343 | 801 | ||
1344 | fep->mii_phy_task_queued = 1; | 802 | return phy_ethtool_sset(phydev, cmd); |
1345 | INIT_WORK(&fep->phy_task, mii_display_config); | ||
1346 | schedule_work(&fep->phy_task); | ||
1347 | } | 803 | } |
1348 | 804 | ||
1349 | phy_cmd_t const phy_cmd_relink[] = { | 805 | static void fec_enet_get_drvinfo(struct net_device *dev, |
1350 | { mk_mii_read(MII_REG_CR), mii_queue_relink }, | 806 | 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 | { | 807 | { |
1362 | struct fec_enet_private *fep; | 808 | 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 | 809 | ||
1379 | fep->phy = phy_info[i]; | 810 | strcpy(info->driver, fep->pdev->dev.driver->name); |
1380 | fep->phy_id_done = 1; | 811 | strcpy(info->version, "Revision: 1.0"); |
812 | strcpy(info->bus_info, dev_name(&dev->dev)); | ||
1381 | } | 813 | } |
1382 | 814 | ||
1383 | /* Scan all of the MII PHY addresses looking for someone to respond | 815 | static struct ethtool_ops fec_enet_ethtool_ops = { |
1384 | * with a valid ID. This usually happens quickly. | 816 | .get_settings = fec_enet_get_settings, |
1385 | */ | 817 | .set_settings = fec_enet_set_settings, |
1386 | static void | 818 | .get_drvinfo = fec_enet_get_drvinfo, |
1387 | mii_discover_phy(uint mii_reg, struct net_device *dev) | 819 | .get_link = ethtool_op_get_link, |
1388 | { | 820 | }; |
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 | 821 | ||
1417 | /* This interrupt occurs when the PHY detects a link change */ | 822 | 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 | { | 823 | { |
1422 | struct net_device *dev = dev_id; | ||
1423 | struct fec_enet_private *fep = netdev_priv(dev); | 824 | struct fec_enet_private *fep = netdev_priv(dev); |
825 | struct phy_device *phydev = fep->phy_dev; | ||
826 | |||
827 | if (!netif_running(dev)) | ||
828 | return -EINVAL; | ||
1424 | 829 | ||
1425 | mii_do_cmd(dev, fep->phy->ack_int); | 830 | if (!phydev) |
1426 | mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */ | 831 | return -ENODEV; |
1427 | 832 | ||
1428 | return IRQ_HANDLED; | 833 | return phy_mii_ioctl(phydev, if_mii(rq), cmd); |
1429 | } | 834 | } |
1430 | #endif | ||
1431 | 835 | ||
1432 | static void fec_enet_free_buffers(struct net_device *dev) | 836 | static void fec_enet_free_buffers(struct net_device *dev) |
1433 | { | 837 | { |
@@ -1509,35 +913,8 @@ fec_enet_open(struct net_device *dev) | |||
1509 | if (ret) | 913 | if (ret) |
1510 | return ret; | 914 | return ret; |
1511 | 915 | ||
1512 | fep->sequence_done = 0; | 916 | /* schedule a link state check */ |
1513 | fep->link = 0; | 917 | 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); | 918 | netif_start_queue(dev); |
1542 | fep->opened = 1; | 919 | fep->opened = 1; |
1543 | return 0; | 920 | return 0; |
@@ -1550,6 +927,7 @@ fec_enet_close(struct net_device *dev) | |||
1550 | 927 | ||
1551 | /* Don't know what to do yet. */ | 928 | /* Don't know what to do yet. */ |
1552 | fep->opened = 0; | 929 | fep->opened = 0; |
930 | phy_stop(fep->phy_dev); | ||
1553 | netif_stop_queue(dev); | 931 | netif_stop_queue(dev); |
1554 | fec_stop(dev); | 932 | fec_stop(dev); |
1555 | 933 | ||
@@ -1574,7 +952,7 @@ fec_enet_close(struct net_device *dev) | |||
1574 | static void set_multicast_list(struct net_device *dev) | 952 | static void set_multicast_list(struct net_device *dev) |
1575 | { | 953 | { |
1576 | struct fec_enet_private *fep = netdev_priv(dev); | 954 | struct fec_enet_private *fep = netdev_priv(dev); |
1577 | struct dev_mc_list *dmi; | 955 | struct netdev_hw_addr *ha; |
1578 | unsigned int i, bit, data, crc, tmp; | 956 | unsigned int i, bit, data, crc, tmp; |
1579 | unsigned char hash; | 957 | unsigned char hash; |
1580 | 958 | ||
@@ -1604,16 +982,16 @@ static void set_multicast_list(struct net_device *dev) | |||
1604 | writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); | 982 | writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); |
1605 | writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); | 983 | writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); |
1606 | 984 | ||
1607 | netdev_for_each_mc_addr(dmi, dev) { | 985 | netdev_for_each_mc_addr(ha, dev) { |
1608 | /* Only support group multicast for now */ | 986 | /* Only support group multicast for now */ |
1609 | if (!(dmi->dmi_addr[0] & 1)) | 987 | if (!(ha->addr[0] & 1)) |
1610 | continue; | 988 | continue; |
1611 | 989 | ||
1612 | /* calculate crc32 value of mac address */ | 990 | /* calculate crc32 value of mac address */ |
1613 | crc = 0xffffffff; | 991 | crc = 0xffffffff; |
1614 | 992 | ||
1615 | for (i = 0; i < dmi->dmi_addrlen; i++) { | 993 | for (i = 0; i < dev->addr_len; i++) { |
1616 | data = dmi->dmi_addr[i]; | 994 | data = ha->addr[i]; |
1617 | for (bit = 0; bit < 8; bit++, data >>= 1) { | 995 | for (bit = 0; bit < 8; bit++, data >>= 1) { |
1618 | crc = (crc >> 1) ^ | 996 | crc = (crc >> 1) ^ |
1619 | (((crc ^ data) & 1) ? CRC32_POLY : 0); | 997 | (((crc ^ data) & 1) ? CRC32_POLY : 0); |
@@ -1666,6 +1044,7 @@ static const struct net_device_ops fec_netdev_ops = { | |||
1666 | .ndo_validate_addr = eth_validate_addr, | 1044 | .ndo_validate_addr = eth_validate_addr, |
1667 | .ndo_tx_timeout = fec_timeout, | 1045 | .ndo_tx_timeout = fec_timeout, |
1668 | .ndo_set_mac_address = fec_set_mac_address, | 1046 | .ndo_set_mac_address = fec_set_mac_address, |
1047 | .ndo_do_ioctl = fec_enet_ioctl, | ||
1669 | }; | 1048 | }; |
1670 | 1049 | ||
1671 | /* | 1050 | /* |
@@ -1689,7 +1068,6 @@ static int fec_enet_init(struct net_device *dev, int index) | |||
1689 | } | 1068 | } |
1690 | 1069 | ||
1691 | spin_lock_init(&fep->hw_lock); | 1070 | spin_lock_init(&fep->hw_lock); |
1692 | spin_lock_init(&fep->mii_lock); | ||
1693 | 1071 | ||
1694 | fep->index = index; | 1072 | fep->index = index; |
1695 | fep->hwp = (void __iomem *)dev->base_addr; | 1073 | fep->hwp = (void __iomem *)dev->base_addr; |
@@ -1716,20 +1094,10 @@ static int fec_enet_init(struct net_device *dev, int index) | |||
1716 | fep->rx_bd_base = cbd_base; | 1094 | fep->rx_bd_base = cbd_base; |
1717 | fep->tx_bd_base = cbd_base + RX_RING_SIZE; | 1095 | fep->tx_bd_base = cbd_base + RX_RING_SIZE; |
1718 | 1096 | ||
1719 | #ifdef HAVE_mii_link_interrupt | ||
1720 | fec_request_mii_intr(dev); | ||
1721 | #endif | ||
1722 | /* The FEC Ethernet specific entries in the device structure */ | 1097 | /* The FEC Ethernet specific entries in the device structure */ |
1723 | dev->watchdog_timeo = TX_TIMEOUT; | 1098 | dev->watchdog_timeo = TX_TIMEOUT; |
1724 | dev->netdev_ops = &fec_netdev_ops; | 1099 | dev->netdev_ops = &fec_netdev_ops; |
1725 | 1100 | 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 | 1101 | ||
1734 | /* Initialize the receive buffer descriptors. */ | 1102 | /* Initialize the receive buffer descriptors. */ |
1735 | bdp = fep->rx_bd_base; | 1103 | bdp = fep->rx_bd_base; |
@@ -1760,13 +1128,6 @@ static int fec_enet_init(struct net_device *dev, int index) | |||
1760 | 1128 | ||
1761 | fec_restart(dev, 0); | 1129 | fec_restart(dev, 0); |
1762 | 1130 | ||
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; | 1131 | return 0; |
1771 | } | 1132 | } |
1772 | 1133 | ||
@@ -1835,8 +1196,7 @@ fec_restart(struct net_device *dev, int duplex) | |||
1835 | writel(0, fep->hwp + FEC_R_DES_ACTIVE); | 1196 | writel(0, fep->hwp + FEC_R_DES_ACTIVE); |
1836 | 1197 | ||
1837 | /* Enable interrupts we wish to service */ | 1198 | /* Enable interrupts we wish to service */ |
1838 | writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII, | 1199 | writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->hwp + FEC_IMASK); |
1839 | fep->hwp + FEC_IMASK); | ||
1840 | } | 1200 | } |
1841 | 1201 | ||
1842 | static void | 1202 | static void |
@@ -1859,7 +1219,6 @@ fec_stop(struct net_device *dev) | |||
1859 | /* Clear outstanding MII command interrupts. */ | 1219 | /* Clear outstanding MII command interrupts. */ |
1860 | writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); | 1220 | writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); |
1861 | 1221 | ||
1862 | writel(FEC_ENET_MII, fep->hwp + FEC_IMASK); | ||
1863 | writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); | 1222 | writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); |
1864 | } | 1223 | } |
1865 | 1224 | ||
@@ -1891,6 +1250,7 @@ fec_probe(struct platform_device *pdev) | |||
1891 | memset(fep, 0, sizeof(*fep)); | 1250 | memset(fep, 0, sizeof(*fep)); |
1892 | 1251 | ||
1893 | ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); | 1252 | ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); |
1253 | fep->pdev = pdev; | ||
1894 | 1254 | ||
1895 | if (!ndev->base_addr) { | 1255 | if (!ndev->base_addr) { |
1896 | ret = -ENOMEM; | 1256 | ret = -ENOMEM; |
@@ -1926,13 +1286,24 @@ fec_probe(struct platform_device *pdev) | |||
1926 | if (ret) | 1286 | if (ret) |
1927 | goto failed_init; | 1287 | goto failed_init; |
1928 | 1288 | ||
1289 | ret = fec_enet_mii_init(pdev); | ||
1290 | if (ret) | ||
1291 | goto failed_mii_init; | ||
1292 | |||
1929 | ret = register_netdev(ndev); | 1293 | ret = register_netdev(ndev); |
1930 | if (ret) | 1294 | if (ret) |
1931 | goto failed_register; | 1295 | goto failed_register; |
1932 | 1296 | ||
1297 | printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] " | ||
1298 | "(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name, | ||
1299 | fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev), | ||
1300 | fep->phy_dev->irq); | ||
1301 | |||
1933 | return 0; | 1302 | return 0; |
1934 | 1303 | ||
1935 | failed_register: | 1304 | failed_register: |
1305 | fec_enet_mii_remove(fep); | ||
1306 | failed_mii_init: | ||
1936 | failed_init: | 1307 | failed_init: |
1937 | clk_disable(fep->clk); | 1308 | clk_disable(fep->clk); |
1938 | clk_put(fep->clk); | 1309 | clk_put(fep->clk); |
@@ -1959,6 +1330,7 @@ fec_drv_remove(struct platform_device *pdev) | |||
1959 | platform_set_drvdata(pdev, NULL); | 1330 | platform_set_drvdata(pdev, NULL); |
1960 | 1331 | ||
1961 | fec_stop(ndev); | 1332 | fec_stop(ndev); |
1333 | fec_enet_mii_remove(fep); | ||
1962 | clk_disable(fep->clk); | 1334 | clk_disable(fep->clk); |
1963 | clk_put(fep->clk); | 1335 | clk_put(fep->clk); |
1964 | iounmap((void __iomem *)ndev->base_addr); | 1336 | iounmap((void __iomem *)ndev->base_addr); |