aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2005-07-25 15:33:22 -0400
committerDavid S. Miller <davem@davemloft.net>2005-07-25 15:33:22 -0400
commit747e8f8bff56955374521fa4d488e702d4b0c04f (patch)
tree66ab6d67818338a0421ef1e374ff15666c85dfa6
parentef7f5ec0deb2bcdc005f30f6f75f79c65c577cf5 (diff)
[TG3]: add 5780 fiber support
Add 5780S support by adding a new tg3_setup_fiber_mii_phy() function and a timer function for parallel link detection. 5780S uses standard MII registers for 1000BaseX and runs in GMII mode as opposed to TBI mode on older serdes chips. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/tg3.c256
-rw-r--r--drivers/net/tg3.h4
2 files changed, 253 insertions, 7 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 04d8b18e2912..ffc854c4ab01 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1100,7 +1100,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
1100 tp->link_config.orig_autoneg = tp->link_config.autoneg; 1100 tp->link_config.orig_autoneg = tp->link_config.autoneg;
1101 } 1101 }
1102 1102
1103 if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { 1103 if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) {
1104 tp->link_config.speed = SPEED_10; 1104 tp->link_config.speed = SPEED_10;
1105 tp->link_config.duplex = DUPLEX_HALF; 1105 tp->link_config.duplex = DUPLEX_HALF;
1106 tp->link_config.autoneg = AUTONEG_ENABLE; 1106 tp->link_config.autoneg = AUTONEG_ENABLE;
@@ -1247,6 +1247,25 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv
1247 u32 old_tx_mode = tp->tx_mode; 1247 u32 old_tx_mode = tp->tx_mode;
1248 1248
1249 if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) { 1249 if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
1250
1251 /* Convert 1000BaseX flow control bits to 1000BaseT
1252 * bits before resolving flow control.
1253 */
1254 if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
1255 local_adv &= ~(ADVERTISE_PAUSE_CAP |
1256 ADVERTISE_PAUSE_ASYM);
1257 remote_adv &= ~(LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
1258
1259 if (local_adv & ADVERTISE_1000XPAUSE)
1260 local_adv |= ADVERTISE_PAUSE_CAP;
1261 if (local_adv & ADVERTISE_1000XPSE_ASYM)
1262 local_adv |= ADVERTISE_PAUSE_ASYM;
1263 if (remote_adv & LPA_1000XPAUSE)
1264 remote_adv |= LPA_PAUSE_CAP;
1265 if (remote_adv & LPA_1000XPAUSE_ASYM)
1266 remote_adv |= LPA_PAUSE_ASYM;
1267 }
1268
1250 if (local_adv & ADVERTISE_PAUSE_CAP) { 1269 if (local_adv & ADVERTISE_PAUSE_CAP) {
1251 if (local_adv & ADVERTISE_PAUSE_ASYM) { 1270 if (local_adv & ADVERTISE_PAUSE_ASYM) {
1252 if (remote_adv & LPA_PAUSE_CAP) 1271 if (remote_adv & LPA_PAUSE_CAP)
@@ -2507,12 +2526,226 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
2507 return 0; 2526 return 0;
2508} 2527}
2509 2528
2529static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
2530{
2531 int current_link_up, err = 0;
2532 u32 bmsr, bmcr;
2533 u16 current_speed;
2534 u8 current_duplex;
2535
2536 tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
2537 tw32_f(MAC_MODE, tp->mac_mode);
2538 udelay(40);
2539
2540 tw32(MAC_EVENT, 0);
2541
2542 tw32_f(MAC_STATUS,
2543 (MAC_STATUS_SYNC_CHANGED |
2544 MAC_STATUS_CFG_CHANGED |
2545 MAC_STATUS_MI_COMPLETION |
2546 MAC_STATUS_LNKSTATE_CHANGED));
2547 udelay(40);
2548
2549 if (force_reset)
2550 tg3_phy_reset(tp);
2551
2552 current_link_up = 0;
2553 current_speed = SPEED_INVALID;
2554 current_duplex = DUPLEX_INVALID;
2555
2556 err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2557 err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2558
2559 err |= tg3_readphy(tp, MII_BMCR, &bmcr);
2560
2561 if ((tp->link_config.autoneg == AUTONEG_ENABLE) && !force_reset &&
2562 (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT)) {
2563 /* do nothing, just check for link up at the end */
2564 } else if (tp->link_config.autoneg == AUTONEG_ENABLE) {
2565 u32 adv, new_adv;
2566
2567 err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
2568 new_adv = adv & ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF |
2569 ADVERTISE_1000XPAUSE |
2570 ADVERTISE_1000XPSE_ASYM |
2571 ADVERTISE_SLCT);
2572
2573 /* Always advertise symmetric PAUSE just like copper */
2574 new_adv |= ADVERTISE_1000XPAUSE;
2575
2576 if (tp->link_config.advertising & ADVERTISED_1000baseT_Half)
2577 new_adv |= ADVERTISE_1000XHALF;
2578 if (tp->link_config.advertising & ADVERTISED_1000baseT_Full)
2579 new_adv |= ADVERTISE_1000XFULL;
2580
2581 if ((new_adv != adv) || !(bmcr & BMCR_ANENABLE)) {
2582 tg3_writephy(tp, MII_ADVERTISE, new_adv);
2583 bmcr |= BMCR_ANENABLE | BMCR_ANRESTART;
2584 tg3_writephy(tp, MII_BMCR, bmcr);
2585
2586 tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
2587 tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
2588 tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
2589
2590 return err;
2591 }
2592 } else {
2593 u32 new_bmcr;
2594
2595 bmcr &= ~BMCR_SPEED1000;
2596 new_bmcr = bmcr & ~(BMCR_ANENABLE | BMCR_FULLDPLX);
2597
2598 if (tp->link_config.duplex == DUPLEX_FULL)
2599 new_bmcr |= BMCR_FULLDPLX;
2600
2601 if (new_bmcr != bmcr) {
2602 /* BMCR_SPEED1000 is a reserved bit that needs
2603 * to be set on write.
2604 */
2605 new_bmcr |= BMCR_SPEED1000;
2606
2607 /* Force a linkdown */
2608 if (netif_carrier_ok(tp->dev)) {
2609 u32 adv;
2610
2611 err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
2612 adv &= ~(ADVERTISE_1000XFULL |
2613 ADVERTISE_1000XHALF |
2614 ADVERTISE_SLCT);
2615 tg3_writephy(tp, MII_ADVERTISE, adv);
2616 tg3_writephy(tp, MII_BMCR, bmcr |
2617 BMCR_ANRESTART |
2618 BMCR_ANENABLE);
2619 udelay(10);
2620 netif_carrier_off(tp->dev);
2621 }
2622 tg3_writephy(tp, MII_BMCR, new_bmcr);
2623 bmcr = new_bmcr;
2624 err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2625 err |= tg3_readphy(tp, MII_BMSR, &bmsr);
2626 tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
2627 }
2628 }
2629
2630 if (bmsr & BMSR_LSTATUS) {
2631 current_speed = SPEED_1000;
2632 current_link_up = 1;
2633 if (bmcr & BMCR_FULLDPLX)
2634 current_duplex = DUPLEX_FULL;
2635 else
2636 current_duplex = DUPLEX_HALF;
2637
2638 if (bmcr & BMCR_ANENABLE) {
2639 u32 local_adv, remote_adv, common;
2640
2641 err |= tg3_readphy(tp, MII_ADVERTISE, &local_adv);
2642 err |= tg3_readphy(tp, MII_LPA, &remote_adv);
2643 common = local_adv & remote_adv;
2644 if (common & (ADVERTISE_1000XHALF |
2645 ADVERTISE_1000XFULL)) {
2646 if (common & ADVERTISE_1000XFULL)
2647 current_duplex = DUPLEX_FULL;
2648 else
2649 current_duplex = DUPLEX_HALF;
2650
2651 tg3_setup_flow_control(tp, local_adv,
2652 remote_adv);
2653 }
2654 else
2655 current_link_up = 0;
2656 }
2657 }
2658
2659 tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
2660 if (tp->link_config.active_duplex == DUPLEX_HALF)
2661 tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
2662
2663 tw32_f(MAC_MODE, tp->mac_mode);
2664 udelay(40);
2665
2666 tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
2667
2668 tp->link_config.active_speed = current_speed;
2669 tp->link_config.active_duplex = current_duplex;
2670
2671 if (current_link_up != netif_carrier_ok(tp->dev)) {
2672 if (current_link_up)
2673 netif_carrier_on(tp->dev);
2674 else {
2675 netif_carrier_off(tp->dev);
2676 tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
2677 }
2678 tg3_link_report(tp);
2679 }
2680 return err;
2681}
2682
2683static void tg3_serdes_parallel_detect(struct tg3 *tp)
2684{
2685 if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) {
2686 /* Give autoneg time to complete. */
2687 tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
2688 return;
2689 }
2690 if (!netif_carrier_ok(tp->dev) &&
2691 (tp->link_config.autoneg == AUTONEG_ENABLE)) {
2692 u32 bmcr;
2693
2694 tg3_readphy(tp, MII_BMCR, &bmcr);
2695 if (bmcr & BMCR_ANENABLE) {
2696 u32 phy1, phy2;
2697
2698 /* Select shadow register 0x1f */
2699 tg3_writephy(tp, 0x1c, 0x7c00);
2700 tg3_readphy(tp, 0x1c, &phy1);
2701
2702 /* Select expansion interrupt status register */
2703 tg3_writephy(tp, 0x17, 0x0f01);
2704 tg3_readphy(tp, 0x15, &phy2);
2705 tg3_readphy(tp, 0x15, &phy2);
2706
2707 if ((phy1 & 0x10) && !(phy2 & 0x20)) {
2708 /* We have signal detect and not receiving
2709 * config code words, link is up by parallel
2710 * detection.
2711 */
2712
2713 bmcr &= ~BMCR_ANENABLE;
2714 bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX;
2715 tg3_writephy(tp, MII_BMCR, bmcr);
2716 tp->tg3_flags2 |= TG3_FLG2_PARALLEL_DETECT;
2717 }
2718 }
2719 }
2720 else if (netif_carrier_ok(tp->dev) &&
2721 (tp->link_config.autoneg == AUTONEG_ENABLE) &&
2722 (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT)) {
2723 u32 phy2;
2724
2725 /* Select expansion interrupt status register */
2726 tg3_writephy(tp, 0x17, 0x0f01);
2727 tg3_readphy(tp, 0x15, &phy2);
2728 if (phy2 & 0x20) {
2729 u32 bmcr;
2730
2731 /* Config code words received, turn on autoneg. */
2732 tg3_readphy(tp, MII_BMCR, &bmcr);
2733 tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANENABLE);
2734
2735 tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
2736
2737 }
2738 }
2739}
2740
2510static int tg3_setup_phy(struct tg3 *tp, int force_reset) 2741static int tg3_setup_phy(struct tg3 *tp, int force_reset)
2511{ 2742{
2512 int err; 2743 int err;
2513 2744
2514 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { 2745 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
2515 err = tg3_setup_fiber_phy(tp, force_reset); 2746 err = tg3_setup_fiber_phy(tp, force_reset);
2747 } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
2748 err = tg3_setup_fiber_mii_phy(tp, force_reset);
2516 } else { 2749 } else {
2517 err = tg3_setup_copper_phy(tp, force_reset); 2750 err = tg3_setup_copper_phy(tp, force_reset);
2518 } 2751 }
@@ -4127,6 +4360,9 @@ static int tg3_chip_reset(struct tg3 *tp)
4127 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { 4360 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
4128 tp->mac_mode = MAC_MODE_PORT_MODE_TBI; 4361 tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
4129 tw32_f(MAC_MODE, tp->mac_mode); 4362 tw32_f(MAC_MODE, tp->mac_mode);
4363 } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
4364 tp->mac_mode = MAC_MODE_PORT_MODE_GMII;
4365 tw32_f(MAC_MODE, tp->mac_mode);
4130 } else 4366 } else
4131 tw32_f(MAC_MODE, 0); 4367 tw32_f(MAC_MODE, 0);
4132 udelay(40); 4368 udelay(40);
@@ -5911,7 +6147,8 @@ static void tg3_timer(unsigned long __opaque)
5911 udelay(40); 6147 udelay(40);
5912 tg3_setup_phy(tp, 0); 6148 tg3_setup_phy(tp, 0);
5913 } 6149 }
5914 } 6150 } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
6151 tg3_serdes_parallel_detect(tp);
5915 6152
5916 tp->timer_counter = tp->timer_multiplier; 6153 tp->timer_counter = tp->timer_multiplier;
5917 } 6154 }
@@ -8615,8 +8852,12 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
8615 eeprom_phy_id = 0; 8852 eeprom_phy_id = 0;
8616 8853
8617 tp->phy_id = eeprom_phy_id; 8854 tp->phy_id = eeprom_phy_id;
8618 if (eeprom_phy_serdes) 8855 if (eeprom_phy_serdes) {
8619 tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; 8856 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
8857 tp->tg3_flags2 |= TG3_FLG2_MII_SERDES;
8858 else
8859 tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
8860 }
8620 8861
8621 if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) 8862 if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
8622 led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK | 8863 led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK |
@@ -8751,7 +8992,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
8751 } 8992 }
8752 } 8993 }
8753 8994
8754 if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && 8995 if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) &&
8755 !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { 8996 !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
8756 u32 bmsr, adv_reg, tg3_ctrl; 8997 u32 bmsr, adv_reg, tg3_ctrl;
8757 8998
@@ -8804,7 +9045,7 @@ skip_phy_reset:
8804 err = tg3_init_5401phy_dsp(tp); 9045 err = tg3_init_5401phy_dsp(tp);
8805 } 9046 }
8806 9047
8807 if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) 9048 if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
8808 tp->link_config.advertising = 9049 tp->link_config.advertising =
8809 (ADVERTISED_1000baseT_Half | 9050 (ADVERTISED_1000baseT_Half |
8810 ADVERTISED_1000baseT_Full | 9051 ADVERTISED_1000baseT_Full |
@@ -9153,7 +9394,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
9153 if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) || 9394 if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) ||
9154 ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && 9395 ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
9155 (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) && 9396 (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
9156 (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1))) 9397 (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) ||
9398 (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
9157 tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED; 9399 tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
9158 9400
9159 if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX || 9401 if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX ||
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 0a277c1e75d1..5c4433c147fa 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2161,6 +2161,10 @@ struct tg3 {
2161#define TG3_FLG2_PROTECTED_NVRAM 0x00100000 2161#define TG3_FLG2_PROTECTED_NVRAM 0x00100000
2162#define TG3_FLG2_USING_MSI 0x00200000 2162#define TG3_FLG2_USING_MSI 0x00200000
2163#define TG3_FLG2_JUMBO_CAPABLE 0x00400000 2163#define TG3_FLG2_JUMBO_CAPABLE 0x00400000
2164#define TG3_FLG2_MII_SERDES 0x00800000
2165#define TG3_FLG2_ANY_SERDES (TG3_FLG2_PHY_SERDES | \
2166 TG3_FLG2_MII_SERDES)
2167#define TG3_FLG2_PARALLEL_DETECT 0x01000000
2164 2168
2165 u32 split_mode_max_reqs; 2169 u32 split_mode_max_reqs;
2166#define SPLIT_MODE_5704_MAX_REQ 3 2170#define SPLIT_MODE_5704_MAX_REQ 3