lkml.org 
[lkml]   [2012]   [Apr]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 02/10] atl1c: add PHY link event(up/down) patch
    Date
    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>
    ---
    drivers/net/ethernet/atheros/atl1c/atl1c.h | 1 +
    drivers/net/ethernet/atheros/atl1c/atl1c_hw.c | 37 ++++++++++++++++
    drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 1 +
    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 acc2956..b2bf324 100644
    --- a/drivers/net/ethernet/atheros/atl1c/atl1c.h
    +++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h
    @@ -436,6 +436,7 @@ struct atl1c_hw {
    bool phy_configured;
    bool re_autoneg;
    bool emi_ca;
    + bool msi_lnkpatch; /* link patch for specific platforms */
    };

    /*
    diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
    index 07f017f..209c179 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)

    return 0;
    }
    +
    +
    +/* configure phy after Link change Event */
    +void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed)
    +{
    + u16 phy_val;
    + bool adj_thresh = false;
    +
    + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 ||
    + hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2)
    + adj_thresh = true;
    +
    + if (link_speed != SPEED_0) { /* link up */
    + /* az with brcm, half-amp */
    + if (hw->nic_type == athr_l1d_2) {
    + atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6,
    + &phy_val);
    + phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN);
    + phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ?
    + AZ_ANADECT_LONG : AZ_ANADECT_DEF;
    + atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val);
    + }
    + /* threshold adjust */
    + if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) {
    + atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP);
    + atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,
    + L1D_SYSMODCTRL_IECHOADJ_DEF);
    + }
    + } else { /* link down */
    + if (adj_thresh && hw->msi_lnkpatch) {
    + atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,
    + SYSMODCTRL_IECHOADJ_DEF);
    + atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB,
    + L1D_MSE16DB_DOWN);
    + }
    + }
    +}
    diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
    index 0adb341..ea3f520 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,
    u16 reg_addr, u16 phy_data);
    int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
    int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data);
    +void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed);

    /* hw-ids */
    #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 25b7b00..6d5b374 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)
    if (netif_msg_hw(adapter))
    dev_warn(&pdev->dev, "stop mac failed\n");
    atl1c_set_aspm(hw, SPEED_0);
    + atl1c_post_phy_linkchg(hw, SPEED_0);
    netif_carrier_off(netdev);
    netif_stop_queue(netdev);
    } else {
    @@ -274,6 +275,7 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
    adapter->link_speed = speed;
    adapter->link_duplex = duplex;
    atl1c_set_aspm(hw, speed);
    + atl1c_post_phy_linkchg(hw, speed);
    atl1c_start_mac(adapter);
    if (netif_msg_link(adapter))
    dev_info(&pdev->dev,
    @@ -697,6 +699,55 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
    hw->link_cap_flags |= ATL1C_LINK_CAP_1000M;
    return 0;
    }
    +
    +struct atl1c_platform_patch {
    + u16 pci_did;
    + u8 pci_revid;
    + u16 subsystem_vid;
    + u16 subsystem_did;
    + u32 patch_flag;
    +#define ATL1C_LINK_PATCH 0x1
    +};
    +static const struct atl1c_platform_patch plats[] __devinitdata = {
    +{0x2060, 0xC1, 0x1019, 0x8152, 0x1},
    +{0x2060, 0xC1, 0x1019, 0x2060, 0x1},
    +{0x2060, 0xC1, 0x1019, 0xE000, 0x1},
    +{0x2062, 0xC0, 0x1019, 0x8152, 0x1},
    +{0x2062, 0xC0, 0x1019, 0x2062, 0x1},
    +{0x2062, 0xC0, 0x1458, 0xE000, 0x1},
    +{0x2062, 0xC1, 0x1019, 0x8152, 0x1},
    +{0x2062, 0xC1, 0x1019, 0x2062, 0x1},
    +{0x2062, 0xC1, 0x1458, 0xE000, 0x1},
    +{0x2062, 0xC1, 0x1565, 0x2802, 0x1},
    +{0x2062, 0xC1, 0x1565, 0x2801, 0x1},
    +{0x1073, 0xC0, 0x1019, 0x8151, 0x1},
    +{0x1073, 0xC0, 0x1019, 0x1073, 0x1},
    +{0x1073, 0xC0, 0x1458, 0xE000, 0x1},
    +{0x1083, 0xC0, 0x1458, 0xE000, 0x1},
    +{0x1083, 0xC0, 0x1019, 0x8151, 0x1},
    +{0x1083, 0xC0, 0x1019, 0x1083, 0x1},
    +{0x1083, 0xC0, 0x1462, 0x7680, 0x1},
    +{0x1083, 0xC0, 0x1565, 0x2803, 0x1},
    +{0},
    +};
    +
    +static void __devinit atl1c_patch_assign(struct atl1c_hw *hw)
    +{
    + int i = 0;
    +
    + hw->msi_lnkpatch = false;
    +
    + while (plats[i].pci_did != 0) {
    + if (plats[i].pci_did == hw->device_id &&
    + plats[i].pci_revid == hw->revision_id &&
    + plats[i].subsystem_vid == hw->subsystem_vendor_id &&
    + plats[i].subsystem_did == hw->subsystem_id) {
    + if (plats[i].patch_flag & ATL1C_LINK_PATCH)
    + hw->msi_lnkpatch = true;
    + }
    + i++;
    + }
    +}
    /*
    * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter)
    * @adapter: board private structure to initialize
    @@ -732,6 +783,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
    dev_err(&pdev->dev, "set mac function pointers failed\n");
    return -1;
    }
    + atl1c_patch_assign(hw);
    +
    hw->intr_mask = IMR_NORMAL_MASK;
    hw->phy_configured = false;
    hw->preamble_len = 7;
    --
    1.7.7


    \
     
     \ /
      Last update: 2012-05-01 04:01    [W:4.146 / U:0.288 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site