diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2010-10-14 06:37:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-17 16:57:44 -0400 |
commit | 52b02d04c801fff51ca49ad033210846d1713253 (patch) | |
tree | 719c03990321d703b192caf38186e30bb999885e /drivers/net/tg3.c | |
parent | ddfc87bfd16f370904c6ff7d23738335dd68d0ce (diff) |
tg3: Add EEE support
This patch adds Energy Efficient Ethernet (EEE) support for the 5718
device ID and the 57765 B0 asic revision.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index afcc593108ce..f2d96ddd464e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -1584,6 +1584,17 @@ static void tg3_phy_fini(struct tg3 *tp) | |||
1584 | } | 1584 | } |
1585 | } | 1585 | } |
1586 | 1586 | ||
1587 | static int tg3_phydsp_read(struct tg3 *tp, u32 reg, u32 *val) | ||
1588 | { | ||
1589 | int err; | ||
1590 | |||
1591 | err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); | ||
1592 | if (!err) | ||
1593 | err = tg3_readphy(tp, MII_TG3_DSP_RW_PORT, val); | ||
1594 | |||
1595 | return err; | ||
1596 | } | ||
1597 | |||
1587 | static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) | 1598 | static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) |
1588 | { | 1599 | { |
1589 | int err; | 1600 | int err; |
@@ -1747,6 +1758,42 @@ static void tg3_phy_apply_otp(struct tg3 *tp) | |||
1747 | tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); | 1758 | tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); |
1748 | } | 1759 | } |
1749 | 1760 | ||
1761 | static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) | ||
1762 | { | ||
1763 | u32 val; | ||
1764 | |||
1765 | if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) | ||
1766 | return; | ||
1767 | |||
1768 | tp->setlpicnt = 0; | ||
1769 | |||
1770 | if (tp->link_config.autoneg == AUTONEG_ENABLE && | ||
1771 | current_link_up == 1 && | ||
1772 | (tp->link_config.active_speed == SPEED_1000 || | ||
1773 | (tp->link_config.active_speed == SPEED_100 && | ||
1774 | tp->link_config.active_duplex == DUPLEX_FULL))) { | ||
1775 | u32 eeectl; | ||
1776 | |||
1777 | if (tp->link_config.active_speed == SPEED_1000) | ||
1778 | eeectl = TG3_CPMU_EEE_CTRL_EXIT_16_5_US; | ||
1779 | else | ||
1780 | eeectl = TG3_CPMU_EEE_CTRL_EXIT_36_US; | ||
1781 | |||
1782 | tw32(TG3_CPMU_EEE_CTRL, eeectl); | ||
1783 | |||
1784 | tg3_phy_cl45_read(tp, 0x7, TG3_CL45_D7_EEERES_STAT, &val); | ||
1785 | |||
1786 | if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T || | ||
1787 | val == TG3_CL45_D7_EEERES_STAT_LP_100TX) | ||
1788 | tp->setlpicnt = 2; | ||
1789 | } | ||
1790 | |||
1791 | if (!tp->setlpicnt) { | ||
1792 | val = tr32(TG3_CPMU_EEE_MODE); | ||
1793 | tw32(TG3_CPMU_EEE_MODE, val & ~TG3_CPMU_EEEMD_LPI_ENABLE); | ||
1794 | } | ||
1795 | } | ||
1796 | |||
1750 | static int tg3_wait_macro_done(struct tg3 *tp) | 1797 | static int tg3_wait_macro_done(struct tg3 *tp) |
1751 | { | 1798 | { |
1752 | int limit = 100; | 1799 | int limit = 100; |
@@ -2921,6 +2968,44 @@ static void tg3_phy_copper_begin(struct tg3 *tp) | |||
2921 | tg3_writephy(tp, MII_TG3_CTRL, new_adv); | 2968 | tg3_writephy(tp, MII_TG3_CTRL, new_adv); |
2922 | } | 2969 | } |
2923 | 2970 | ||
2971 | if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) { | ||
2972 | u32 val = 0; | ||
2973 | |||
2974 | tw32(TG3_CPMU_EEE_MODE, | ||
2975 | tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); | ||
2976 | |||
2977 | /* Enable SM_DSP clock and tx 6dB coding. */ | ||
2978 | val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | | ||
2979 | MII_TG3_AUXCTL_ACTL_SMDSP_ENA | | ||
2980 | MII_TG3_AUXCTL_ACTL_TX_6DB; | ||
2981 | tg3_writephy(tp, MII_TG3_AUX_CTRL, val); | ||
2982 | |||
2983 | if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || | ||
2984 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && | ||
2985 | !tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val)) | ||
2986 | tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, | ||
2987 | val | MII_TG3_DSP_CH34TP2_HIBW01); | ||
2988 | |||
2989 | if (tp->link_config.autoneg == AUTONEG_ENABLE) { | ||
2990 | /* Advertise 100-BaseTX EEE ability */ | ||
2991 | if (tp->link_config.advertising & | ||
2992 | (ADVERTISED_100baseT_Half | | ||
2993 | ADVERTISED_100baseT_Full)) | ||
2994 | val |= TG3_CL45_D7_EEEADV_CAP_100TX; | ||
2995 | /* Advertise 1000-BaseT EEE ability */ | ||
2996 | if (tp->link_config.advertising & | ||
2997 | (ADVERTISED_1000baseT_Half | | ||
2998 | ADVERTISED_1000baseT_Full)) | ||
2999 | val |= TG3_CL45_D7_EEEADV_CAP_1000T; | ||
3000 | } | ||
3001 | tg3_phy_cl45_write(tp, 0x7, TG3_CL45_D7_EEEADV_CAP, val); | ||
3002 | |||
3003 | /* Turn off SM_DSP clock. */ | ||
3004 | val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | | ||
3005 | MII_TG3_AUXCTL_ACTL_TX_6DB; | ||
3006 | tg3_writephy(tp, MII_TG3_AUX_CTRL, val); | ||
3007 | } | ||
3008 | |||
2924 | if (tp->link_config.autoneg == AUTONEG_DISABLE && | 3009 | if (tp->link_config.autoneg == AUTONEG_DISABLE && |
2925 | tp->link_config.speed != SPEED_INVALID) { | 3010 | tp->link_config.speed != SPEED_INVALID) { |
2926 | u32 bmcr, orig_bmcr; | 3011 | u32 bmcr, orig_bmcr; |
@@ -3282,6 +3367,8 @@ relink: | |||
3282 | tw32_f(MAC_MODE, tp->mac_mode); | 3367 | tw32_f(MAC_MODE, tp->mac_mode); |
3283 | udelay(40); | 3368 | udelay(40); |
3284 | 3369 | ||
3370 | tg3_phy_eee_adjust(tp, current_link_up); | ||
3371 | |||
3285 | if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { | 3372 | if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { |
3286 | /* Polled via timer. */ | 3373 | /* Polled via timer. */ |
3287 | tw32_f(MAC_EVENT, 0); | 3374 | tw32_f(MAC_EVENT, 0); |
@@ -7790,6 +7877,22 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
7790 | tw32(TG3_CPMU_LSPD_10MB_CLK, val); | 7877 | tw32(TG3_CPMU_LSPD_10MB_CLK, val); |
7791 | } | 7878 | } |
7792 | 7879 | ||
7880 | /* Enable MAC control of LPI */ | ||
7881 | if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) { | ||
7882 | tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, | ||
7883 | TG3_CPMU_EEE_LNKIDL_PCIE_NL0 | | ||
7884 | TG3_CPMU_EEE_LNKIDL_UART_IDL); | ||
7885 | |||
7886 | tw32_f(TG3_CPMU_EEE_CTRL, | ||
7887 | TG3_CPMU_EEE_CTRL_EXIT_20_1_US); | ||
7888 | |||
7889 | tw32_f(TG3_CPMU_EEE_MODE, | ||
7890 | TG3_CPMU_EEEMD_ERLY_L1_XIT_DET | | ||
7891 | TG3_CPMU_EEEMD_LPI_IN_TX | | ||
7892 | TG3_CPMU_EEEMD_LPI_IN_RX | | ||
7893 | TG3_CPMU_EEEMD_EEE_ENABLE); | ||
7894 | } | ||
7895 | |||
7793 | /* This works around an issue with Athlon chipsets on | 7896 | /* This works around an issue with Athlon chipsets on |
7794 | * B3 tigon3 silicon. This bit has no effect on any | 7897 | * B3 tigon3 silicon. This bit has no effect on any |
7795 | * other revision. But do not set this on PCI Express | 7898 | * other revision. But do not set this on PCI Express |
@@ -8598,6 +8701,12 @@ static void tg3_timer(unsigned long __opaque) | |||
8598 | if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) | 8701 | if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) |
8599 | tg3_periodic_fetch_stats(tp); | 8702 | tg3_periodic_fetch_stats(tp); |
8600 | 8703 | ||
8704 | if (tp->setlpicnt && !--tp->setlpicnt) { | ||
8705 | u32 val = tr32(TG3_CPMU_EEE_MODE); | ||
8706 | tw32(TG3_CPMU_EEE_MODE, | ||
8707 | val | TG3_CPMU_EEEMD_LPI_ENABLE); | ||
8708 | } | ||
8709 | |||
8601 | if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { | 8710 | if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { |
8602 | u32 mac_stat; | 8711 | u32 mac_stat; |
8603 | int phy_event; | 8712 | int phy_event; |
@@ -12432,6 +12541,11 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) | |||
12432 | } | 12541 | } |
12433 | } | 12542 | } |
12434 | 12543 | ||
12544 | if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || | ||
12545 | (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && | ||
12546 | tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)) | ||
12547 | tp->phy_flags |= TG3_PHYFLG_EEE_CAP; | ||
12548 | |||
12435 | if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && | 12549 | if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && |
12436 | !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) && | 12550 | !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) && |
12437 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { | 12551 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { |