diff options
author | Huang, Xiong <xiong@qca.qualcomm.com> | 2012-04-30 11:38:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-30 21:44:13 -0400 |
commit | 903d7ce0cc9a45dd29d6f7690b2e3534c61ef326 (patch) | |
tree | e4cb30182db76bdcfe5453f2dbafa3a6332f0e2b /drivers/net | |
parent | 7cb6a291ef3b159e8ade6b113171c089d38e944c (diff) |
atl1c: add PHY link event(up/down) patch
On some platforms the PHY settings need to change depending on the
cable link status to get better stability.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_hw.c | 37 | ||||
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 53 |
4 files changed, 92 insertions, 0 deletions
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h index acc2956df907..b2bf324631dc 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c.h +++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h | |||
@@ -436,6 +436,7 @@ struct atl1c_hw { | |||
436 | bool phy_configured; | 436 | bool phy_configured; |
437 | bool re_autoneg; | 437 | bool re_autoneg; |
438 | bool emi_ca; | 438 | bool emi_ca; |
439 | bool msi_lnkpatch; /* link patch for specific platforms */ | ||
439 | }; | 440 | }; |
440 | 441 | ||
441 | /* | 442 | /* |
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c index 07f017f59b39..209c1791531c 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c | |||
@@ -848,3 +848,40 @@ int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc) | |||
848 | 848 | ||
849 | return 0; | 849 | return 0; |
850 | } | 850 | } |
851 | |||
852 | |||
853 | /* configure phy after Link change Event */ | ||
854 | void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed) | ||
855 | { | ||
856 | u16 phy_val; | ||
857 | bool adj_thresh = false; | ||
858 | |||
859 | if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 || | ||
860 | hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2) | ||
861 | adj_thresh = true; | ||
862 | |||
863 | if (link_speed != SPEED_0) { /* link up */ | ||
864 | /* az with brcm, half-amp */ | ||
865 | if (hw->nic_type == athr_l1d_2) { | ||
866 | atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6, | ||
867 | &phy_val); | ||
868 | phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN); | ||
869 | phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ? | ||
870 | AZ_ANADECT_LONG : AZ_ANADECT_DEF; | ||
871 | atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val); | ||
872 | } | ||
873 | /* threshold adjust */ | ||
874 | if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) { | ||
875 | atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP); | ||
876 | atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, | ||
877 | L1D_SYSMODCTRL_IECHOADJ_DEF); | ||
878 | } | ||
879 | } else { /* link down */ | ||
880 | if (adj_thresh && hw->msi_lnkpatch) { | ||
881 | atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, | ||
882 | SYSMODCTRL_IECHOADJ_DEF); | ||
883 | atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, | ||
884 | L1D_MSE16DB_DOWN); | ||
885 | } | ||
886 | } | ||
887 | } | ||
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h index 0adb34131332..ea3f5201a8ff 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | |||
@@ -63,6 +63,7 @@ int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, | |||
63 | u16 reg_addr, u16 phy_data); | 63 | u16 reg_addr, u16 phy_data); |
64 | int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); | 64 | int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); |
65 | int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data); | 65 | int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data); |
66 | void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed); | ||
66 | 67 | ||
67 | /* hw-ids */ | 68 | /* hw-ids */ |
68 | #define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 | 69 | #define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 |
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 25b7b0098496..6d5b37479ec4 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c | |||
@@ -258,6 +258,7 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) | |||
258 | if (netif_msg_hw(adapter)) | 258 | if (netif_msg_hw(adapter)) |
259 | dev_warn(&pdev->dev, "stop mac failed\n"); | 259 | dev_warn(&pdev->dev, "stop mac failed\n"); |
260 | atl1c_set_aspm(hw, SPEED_0); | 260 | atl1c_set_aspm(hw, SPEED_0); |
261 | atl1c_post_phy_linkchg(hw, SPEED_0); | ||
261 | netif_carrier_off(netdev); | 262 | netif_carrier_off(netdev); |
262 | netif_stop_queue(netdev); | 263 | netif_stop_queue(netdev); |
263 | } else { | 264 | } else { |
@@ -274,6 +275,7 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) | |||
274 | adapter->link_speed = speed; | 275 | adapter->link_speed = speed; |
275 | adapter->link_duplex = duplex; | 276 | adapter->link_duplex = duplex; |
276 | atl1c_set_aspm(hw, speed); | 277 | atl1c_set_aspm(hw, speed); |
278 | atl1c_post_phy_linkchg(hw, speed); | ||
277 | atl1c_start_mac(adapter); | 279 | atl1c_start_mac(adapter); |
278 | if (netif_msg_link(adapter)) | 280 | if (netif_msg_link(adapter)) |
279 | dev_info(&pdev->dev, | 281 | dev_info(&pdev->dev, |
@@ -697,6 +699,55 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) | |||
697 | hw->link_cap_flags |= ATL1C_LINK_CAP_1000M; | 699 | hw->link_cap_flags |= ATL1C_LINK_CAP_1000M; |
698 | return 0; | 700 | return 0; |
699 | } | 701 | } |
702 | |||
703 | struct atl1c_platform_patch { | ||
704 | u16 pci_did; | ||
705 | u8 pci_revid; | ||
706 | u16 subsystem_vid; | ||
707 | u16 subsystem_did; | ||
708 | u32 patch_flag; | ||
709 | #define ATL1C_LINK_PATCH 0x1 | ||
710 | }; | ||
711 | static const struct atl1c_platform_patch plats[] __devinitdata = { | ||
712 | {0x2060, 0xC1, 0x1019, 0x8152, 0x1}, | ||
713 | {0x2060, 0xC1, 0x1019, 0x2060, 0x1}, | ||
714 | {0x2060, 0xC1, 0x1019, 0xE000, 0x1}, | ||
715 | {0x2062, 0xC0, 0x1019, 0x8152, 0x1}, | ||
716 | {0x2062, 0xC0, 0x1019, 0x2062, 0x1}, | ||
717 | {0x2062, 0xC0, 0x1458, 0xE000, 0x1}, | ||
718 | {0x2062, 0xC1, 0x1019, 0x8152, 0x1}, | ||
719 | {0x2062, 0xC1, 0x1019, 0x2062, 0x1}, | ||
720 | {0x2062, 0xC1, 0x1458, 0xE000, 0x1}, | ||
721 | {0x2062, 0xC1, 0x1565, 0x2802, 0x1}, | ||
722 | {0x2062, 0xC1, 0x1565, 0x2801, 0x1}, | ||
723 | {0x1073, 0xC0, 0x1019, 0x8151, 0x1}, | ||
724 | {0x1073, 0xC0, 0x1019, 0x1073, 0x1}, | ||
725 | {0x1073, 0xC0, 0x1458, 0xE000, 0x1}, | ||
726 | {0x1083, 0xC0, 0x1458, 0xE000, 0x1}, | ||
727 | {0x1083, 0xC0, 0x1019, 0x8151, 0x1}, | ||
728 | {0x1083, 0xC0, 0x1019, 0x1083, 0x1}, | ||
729 | {0x1083, 0xC0, 0x1462, 0x7680, 0x1}, | ||
730 | {0x1083, 0xC0, 0x1565, 0x2803, 0x1}, | ||
731 | {0}, | ||
732 | }; | ||
733 | |||
734 | static void __devinit atl1c_patch_assign(struct atl1c_hw *hw) | ||
735 | { | ||
736 | int i = 0; | ||
737 | |||
738 | hw->msi_lnkpatch = false; | ||
739 | |||
740 | while (plats[i].pci_did != 0) { | ||
741 | if (plats[i].pci_did == hw->device_id && | ||
742 | plats[i].pci_revid == hw->revision_id && | ||
743 | plats[i].subsystem_vid == hw->subsystem_vendor_id && | ||
744 | plats[i].subsystem_did == hw->subsystem_id) { | ||
745 | if (plats[i].patch_flag & ATL1C_LINK_PATCH) | ||
746 | hw->msi_lnkpatch = true; | ||
747 | } | ||
748 | i++; | ||
749 | } | ||
750 | } | ||
700 | /* | 751 | /* |
701 | * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) | 752 | * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) |
702 | * @adapter: board private structure to initialize | 753 | * @adapter: board private structure to initialize |
@@ -732,6 +783,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) | |||
732 | dev_err(&pdev->dev, "set mac function pointers failed\n"); | 783 | dev_err(&pdev->dev, "set mac function pointers failed\n"); |
733 | return -1; | 784 | return -1; |
734 | } | 785 | } |
786 | atl1c_patch_assign(hw); | ||
787 | |||
735 | hw->intr_mask = IMR_NORMAL_MASK; | 788 | hw->intr_mask = IMR_NORMAL_MASK; |
736 | hw->phy_configured = false; | 789 | hw->phy_configured = false; |
737 | hw->preamble_len = 7; | 790 | hw->preamble_len = 7; |