aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/atheros
diff options
context:
space:
mode:
authorHuang, Xiong <xiong@qca.qualcomm.com>2012-04-30 11:38:50 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-30 21:44:13 -0400
commit903d7ce0cc9a45dd29d6f7690b2e3534c61ef326 (patch)
treee4cb30182db76bdcfe5453f2dbafa3a6332f0e2b /drivers/net/ethernet/atheros
parent7cb6a291ef3b159e8ade6b113171c089d38e944c (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/ethernet/atheros')
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c.h1
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.c37
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.h1
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c53
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 */
854void 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);
64int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); 64int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
65int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data); 65int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data);
66void 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
703struct 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};
711static 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
734static 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;