Loading drivers/net/ethernet/msm/emac/emac.h +4 −1 Original line number Diff line number Diff line /* Copyright (c) 2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -193,6 +193,7 @@ struct emac_hw { /* PHY parameter */ u32 phy_addr; u16 phy_id[2]; bool autoneg; u32 autoneg_advertised; u32 link_speed; bool link_up; Loading Loading @@ -676,5 +677,7 @@ extern void emac_set_ethtool_ops(struct net_device *netdev); extern void emac_reinit_locked(struct emac_adapter *adpt); extern void emac_update_hw_stats(struct emac_adapter *adpt); extern int emac_resize_rings(struct net_device *netdev); extern int emac_up(struct emac_adapter *adpt); extern void emac_down(struct emac_adapter *adpt, u32 ctrl); #endif /* _MSM_EMAC_H_ */ drivers/net/ethernet/msm/emac/emac_ethtool.c +23 −9 Original line number Diff line number Diff line Loading @@ -89,13 +89,17 @@ static int emac_get_settings(struct net_device *netdev, SUPPORTED_TP); ecmd->advertising = ADVERTISED_TP; if (hw->autoneg) { ecmd->advertising |= ADVERTISED_Autoneg; ecmd->advertising |= hw->autoneg_advertised; ecmd->autoneg = AUTONEG_ENABLE; } else { ecmd->autoneg = AUTONEG_DISABLE; } ecmd->port = PORT_TP; ecmd->phy_address = hw->phy_addr; ecmd->transceiver = XCVR_INTERNAL; ecmd->autoneg = AUTONEG_ENABLE; if (hw->link_up) { switch (hw->link_speed) { Loading Loading @@ -176,18 +180,28 @@ static int emac_set_settings(struct net_device *netdev, } } if (hw->autoneg_advertised == advertised) { CLI_ADPT_FLAG(STATE_RESETTING); return retval; } if ((hw->autoneg == autoneg) && (hw->autoneg_advertised == advertised)) goto done; retval = emac_setup_phy_link_speed(hw, advertised, autoneg, !hw->disable_fc_autoneg); if (retval) { retval = emac_setup_phy_link_speed(hw, old, autoneg, emac_setup_phy_link_speed(hw, old, autoneg, !hw->disable_fc_autoneg); } if (netif_running(adpt->netdev)) { /* If there is no EPHY, the EMAC internal PHY may get reset in * emac_setup_phy_link_speed. Reset the MAC to avoid the memory * corruption. */ if (adpt->no_ephy) { emac_down(adpt, EMAC_HW_CTRL_RESET_MAC); emac_up(adpt); } } done: CLI_ADPT_FLAG(STATE_RESETTING); return retval; } Loading drivers/net/ethernet/msm/emac/emac_hw.c +42 −6 Original line number Diff line number Diff line /* Copyright (c) 2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -34,6 +34,9 @@ #define SGMII_TX_CLK_RATE 125000000 #define SGMII_CXO_CLK_RATE 19200000 static int emac_hw_sgmii_setup_link(struct emac_hw *hw, u32 speed, bool autoneg, bool fc); /* REG */ u32 emac_reg_r32(struct emac_hw *hw, u8 base, u32 reg) { Loading Loading @@ -280,6 +283,8 @@ int emac_hw_init_sgmii(struct emac_hw *hw) { int i; emac_hw_sgmii_setup_link(hw, hw->autoneg_advertised, hw->autoneg, !hw->disable_fc_autoneg); /* PCS programming */ emac_reg_w32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_CDR_CTRL0, SGMII_CDR_MAX_CNT); Loading Loading @@ -434,6 +439,7 @@ int emac_hw_init_phy(struct emac_hw *hw) emac_disable_mdio_autopoll(hw); } hw->autoneg = true; hw->autoneg_advertised = EMAC_LINK_SPEED_DEFAULT; if (hw->adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) Loading @@ -453,6 +459,7 @@ static int emac_hw_sgmii_setup_link(struct emac_hw *hw, u32 speed, bool autoneg, bool fc) { u32 val; u32 speed_cfg = 0; val = emac_reg_r32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_AUTONEG_CFG2); Loading @@ -463,9 +470,31 @@ static int emac_hw_sgmii_setup_link(struct emac_hw *hw, u32 speed, EMAC_SGMII_PHY_AUTONEG_CFG2, val); wmb(); } else { emac_warn(hw->adpt, hw, "No support to turn off SGMII-autoneg\n"); return -ENOTSUPP; switch (speed) { case EMAC_LINK_SPEED_10_HALF: speed_cfg = SPDMODE_10; break; case EMAC_LINK_SPEED_10_FULL: speed_cfg = SPDMODE_10 | DUPLEX_MODE; break; case EMAC_LINK_SPEED_100_HALF: speed_cfg = SPDMODE_100; break; case EMAC_LINK_SPEED_100_FULL: speed_cfg = SPDMODE_100 | DUPLEX_MODE; break; case EMAC_LINK_SPEED_1GB_FULL: speed_cfg = SPDMODE_1000 | DUPLEX_MODE; break; default: return -EINVAL; } val &= ~AN_ENABLE; emac_reg_w32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_SPEED_CFG1, speed_cfg); emac_reg_w32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_AUTONEG_CFG2, val); wmb(); } return 0; Loading Loading @@ -535,7 +564,12 @@ int emac_setup_phy_link(struct emac_hw *hw, u32 speed, bool autoneg, bool fc) if (hw->adpt->no_ephy == true) { if (hw->adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) { return emac_hw_sgmii_setup_link(hw, speed, autoneg, fc); hw->autoneg = autoneg; hw->autoneg_advertised = speed; /* The AN_ENABLE and SPEED_CFG can't change on fly. The SGMII_PHY has to be re-initialized. */ return emac_hw_reset_sgmii(hw); } else { emac_err(hw->adpt, "can't setup phy link without ephy\n"); Loading @@ -546,6 +580,8 @@ int emac_setup_phy_link(struct emac_hw *hw, u32 speed, bool autoneg, bool fc) if (emac_hw_setup_phy_link(hw, speed, autoneg, fc)) { emac_err(hw->adpt, "error when init phy speed and fc\n"); retval = -EINVAL; } else { hw->autoneg = autoneg; } return retval; Loading @@ -554,7 +590,7 @@ int emac_setup_phy_link(struct emac_hw *hw, u32 speed, bool autoneg, bool fc) int emac_setup_phy_link_speed(struct emac_hw *hw, u32 speed, bool autoneg, bool fc) { /* update autoneg_advertised based on input link speed */ /* update speed based on input link speed */ hw->autoneg_advertised = speed & EMAC_LINK_SPEED_DEFAULT; return emac_setup_phy_link(hw, hw->autoneg_advertised, autoneg, fc); } Loading drivers/net/ethernet/msm/emac/emac_main.c +2 −4 Original line number Diff line number Diff line Loading @@ -59,8 +59,6 @@ static int msm_emac_intr_ext; module_param_named(intr_ext, msm_emac_intr_ext, int, S_IRUGO | S_IWUSR | S_IWGRP); static int emac_up(struct emac_adapter *adpt); static void emac_down(struct emac_adapter *adpt, u32 ctrl); static irqreturn_t emac_interrupt(int irq, void *data); static irqreturn_t emac_sgmii_interrupt(int irq, void *data); static irqreturn_t emac_wol_interrupt(int irq, void *data); Loading Loading @@ -1451,7 +1449,7 @@ static int emac_change_mtu(struct net_device *netdev, int new_mtu) } /* Bringup the interface/HW */ static int emac_up(struct emac_adapter *adpt) int emac_up(struct emac_adapter *adpt) { struct emac_hw *hw = &adpt->hw; struct net_device *netdev = adpt->netdev; Loading Loading @@ -1520,7 +1518,7 @@ err_request_gpio: } /* Bring down the interface/HW */ static void emac_down(struct emac_adapter *adpt, u32 ctrl) void emac_down(struct emac_adapter *adpt, u32 ctrl) { struct net_device *netdev = adpt->netdev; struct emac_hw *hw = &adpt->hw; Loading Loading
drivers/net/ethernet/msm/emac/emac.h +4 −1 Original line number Diff line number Diff line /* Copyright (c) 2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -193,6 +193,7 @@ struct emac_hw { /* PHY parameter */ u32 phy_addr; u16 phy_id[2]; bool autoneg; u32 autoneg_advertised; u32 link_speed; bool link_up; Loading Loading @@ -676,5 +677,7 @@ extern void emac_set_ethtool_ops(struct net_device *netdev); extern void emac_reinit_locked(struct emac_adapter *adpt); extern void emac_update_hw_stats(struct emac_adapter *adpt); extern int emac_resize_rings(struct net_device *netdev); extern int emac_up(struct emac_adapter *adpt); extern void emac_down(struct emac_adapter *adpt, u32 ctrl); #endif /* _MSM_EMAC_H_ */
drivers/net/ethernet/msm/emac/emac_ethtool.c +23 −9 Original line number Diff line number Diff line Loading @@ -89,13 +89,17 @@ static int emac_get_settings(struct net_device *netdev, SUPPORTED_TP); ecmd->advertising = ADVERTISED_TP; if (hw->autoneg) { ecmd->advertising |= ADVERTISED_Autoneg; ecmd->advertising |= hw->autoneg_advertised; ecmd->autoneg = AUTONEG_ENABLE; } else { ecmd->autoneg = AUTONEG_DISABLE; } ecmd->port = PORT_TP; ecmd->phy_address = hw->phy_addr; ecmd->transceiver = XCVR_INTERNAL; ecmd->autoneg = AUTONEG_ENABLE; if (hw->link_up) { switch (hw->link_speed) { Loading Loading @@ -176,18 +180,28 @@ static int emac_set_settings(struct net_device *netdev, } } if (hw->autoneg_advertised == advertised) { CLI_ADPT_FLAG(STATE_RESETTING); return retval; } if ((hw->autoneg == autoneg) && (hw->autoneg_advertised == advertised)) goto done; retval = emac_setup_phy_link_speed(hw, advertised, autoneg, !hw->disable_fc_autoneg); if (retval) { retval = emac_setup_phy_link_speed(hw, old, autoneg, emac_setup_phy_link_speed(hw, old, autoneg, !hw->disable_fc_autoneg); } if (netif_running(adpt->netdev)) { /* If there is no EPHY, the EMAC internal PHY may get reset in * emac_setup_phy_link_speed. Reset the MAC to avoid the memory * corruption. */ if (adpt->no_ephy) { emac_down(adpt, EMAC_HW_CTRL_RESET_MAC); emac_up(adpt); } } done: CLI_ADPT_FLAG(STATE_RESETTING); return retval; } Loading
drivers/net/ethernet/msm/emac/emac_hw.c +42 −6 Original line number Diff line number Diff line /* Copyright (c) 2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -34,6 +34,9 @@ #define SGMII_TX_CLK_RATE 125000000 #define SGMII_CXO_CLK_RATE 19200000 static int emac_hw_sgmii_setup_link(struct emac_hw *hw, u32 speed, bool autoneg, bool fc); /* REG */ u32 emac_reg_r32(struct emac_hw *hw, u8 base, u32 reg) { Loading Loading @@ -280,6 +283,8 @@ int emac_hw_init_sgmii(struct emac_hw *hw) { int i; emac_hw_sgmii_setup_link(hw, hw->autoneg_advertised, hw->autoneg, !hw->disable_fc_autoneg); /* PCS programming */ emac_reg_w32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_CDR_CTRL0, SGMII_CDR_MAX_CNT); Loading Loading @@ -434,6 +439,7 @@ int emac_hw_init_phy(struct emac_hw *hw) emac_disable_mdio_autopoll(hw); } hw->autoneg = true; hw->autoneg_advertised = EMAC_LINK_SPEED_DEFAULT; if (hw->adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) Loading @@ -453,6 +459,7 @@ static int emac_hw_sgmii_setup_link(struct emac_hw *hw, u32 speed, bool autoneg, bool fc) { u32 val; u32 speed_cfg = 0; val = emac_reg_r32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_AUTONEG_CFG2); Loading @@ -463,9 +470,31 @@ static int emac_hw_sgmii_setup_link(struct emac_hw *hw, u32 speed, EMAC_SGMII_PHY_AUTONEG_CFG2, val); wmb(); } else { emac_warn(hw->adpt, hw, "No support to turn off SGMII-autoneg\n"); return -ENOTSUPP; switch (speed) { case EMAC_LINK_SPEED_10_HALF: speed_cfg = SPDMODE_10; break; case EMAC_LINK_SPEED_10_FULL: speed_cfg = SPDMODE_10 | DUPLEX_MODE; break; case EMAC_LINK_SPEED_100_HALF: speed_cfg = SPDMODE_100; break; case EMAC_LINK_SPEED_100_FULL: speed_cfg = SPDMODE_100 | DUPLEX_MODE; break; case EMAC_LINK_SPEED_1GB_FULL: speed_cfg = SPDMODE_1000 | DUPLEX_MODE; break; default: return -EINVAL; } val &= ~AN_ENABLE; emac_reg_w32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_SPEED_CFG1, speed_cfg); emac_reg_w32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_AUTONEG_CFG2, val); wmb(); } return 0; Loading Loading @@ -535,7 +564,12 @@ int emac_setup_phy_link(struct emac_hw *hw, u32 speed, bool autoneg, bool fc) if (hw->adpt->no_ephy == true) { if (hw->adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) { return emac_hw_sgmii_setup_link(hw, speed, autoneg, fc); hw->autoneg = autoneg; hw->autoneg_advertised = speed; /* The AN_ENABLE and SPEED_CFG can't change on fly. The SGMII_PHY has to be re-initialized. */ return emac_hw_reset_sgmii(hw); } else { emac_err(hw->adpt, "can't setup phy link without ephy\n"); Loading @@ -546,6 +580,8 @@ int emac_setup_phy_link(struct emac_hw *hw, u32 speed, bool autoneg, bool fc) if (emac_hw_setup_phy_link(hw, speed, autoneg, fc)) { emac_err(hw->adpt, "error when init phy speed and fc\n"); retval = -EINVAL; } else { hw->autoneg = autoneg; } return retval; Loading @@ -554,7 +590,7 @@ int emac_setup_phy_link(struct emac_hw *hw, u32 speed, bool autoneg, bool fc) int emac_setup_phy_link_speed(struct emac_hw *hw, u32 speed, bool autoneg, bool fc) { /* update autoneg_advertised based on input link speed */ /* update speed based on input link speed */ hw->autoneg_advertised = speed & EMAC_LINK_SPEED_DEFAULT; return emac_setup_phy_link(hw, hw->autoneg_advertised, autoneg, fc); } Loading
drivers/net/ethernet/msm/emac/emac_main.c +2 −4 Original line number Diff line number Diff line Loading @@ -59,8 +59,6 @@ static int msm_emac_intr_ext; module_param_named(intr_ext, msm_emac_intr_ext, int, S_IRUGO | S_IWUSR | S_IWGRP); static int emac_up(struct emac_adapter *adpt); static void emac_down(struct emac_adapter *adpt, u32 ctrl); static irqreturn_t emac_interrupt(int irq, void *data); static irqreturn_t emac_sgmii_interrupt(int irq, void *data); static irqreturn_t emac_wol_interrupt(int irq, void *data); Loading Loading @@ -1451,7 +1449,7 @@ static int emac_change_mtu(struct net_device *netdev, int new_mtu) } /* Bringup the interface/HW */ static int emac_up(struct emac_adapter *adpt) int emac_up(struct emac_adapter *adpt) { struct emac_hw *hw = &adpt->hw; struct net_device *netdev = adpt->netdev; Loading Loading @@ -1520,7 +1518,7 @@ err_request_gpio: } /* Bring down the interface/HW */ static void emac_down(struct emac_adapter *adpt, u32 ctrl) void emac_down(struct emac_adapter *adpt, u32 ctrl) { struct net_device *netdev = adpt->netdev; struct emac_hw *hw = &adpt->hw; Loading