diff options
Diffstat (limited to 'drivers/net/ethernet/mediatek/mtk_eth_soc.c')
-rw-r--r-- | drivers/net/ethernet/mediatek/mtk_eth_soc.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index c984462fad2a..4763252bbf85 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c | |||
@@ -133,6 +133,8 @@ static int mtk_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg) | |||
133 | static void mtk_phy_link_adjust(struct net_device *dev) | 133 | static void mtk_phy_link_adjust(struct net_device *dev) |
134 | { | 134 | { |
135 | struct mtk_mac *mac = netdev_priv(dev); | 135 | struct mtk_mac *mac = netdev_priv(dev); |
136 | u16 lcl_adv = 0, rmt_adv = 0; | ||
137 | u8 flowctrl; | ||
136 | u32 mcr = MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | | 138 | u32 mcr = MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | |
137 | MAC_MCR_FORCE_MODE | MAC_MCR_TX_EN | | 139 | MAC_MCR_FORCE_MODE | MAC_MCR_TX_EN | |
138 | MAC_MCR_RX_EN | MAC_MCR_BACKOFF_EN | | 140 | MAC_MCR_RX_EN | MAC_MCR_BACKOFF_EN | |
@@ -150,11 +152,30 @@ static void mtk_phy_link_adjust(struct net_device *dev) | |||
150 | if (mac->phy_dev->link) | 152 | if (mac->phy_dev->link) |
151 | mcr |= MAC_MCR_FORCE_LINK; | 153 | mcr |= MAC_MCR_FORCE_LINK; |
152 | 154 | ||
153 | if (mac->phy_dev->duplex) | 155 | if (mac->phy_dev->duplex) { |
154 | mcr |= MAC_MCR_FORCE_DPX; | 156 | mcr |= MAC_MCR_FORCE_DPX; |
155 | 157 | ||
156 | if (mac->phy_dev->pause) | 158 | if (mac->phy_dev->pause) |
157 | mcr |= MAC_MCR_FORCE_RX_FC | MAC_MCR_FORCE_TX_FC; | 159 | rmt_adv = LPA_PAUSE_CAP; |
160 | if (mac->phy_dev->asym_pause) | ||
161 | rmt_adv |= LPA_PAUSE_ASYM; | ||
162 | |||
163 | if (mac->phy_dev->advertising & ADVERTISED_Pause) | ||
164 | lcl_adv |= ADVERTISE_PAUSE_CAP; | ||
165 | if (mac->phy_dev->advertising & ADVERTISED_Asym_Pause) | ||
166 | lcl_adv |= ADVERTISE_PAUSE_ASYM; | ||
167 | |||
168 | flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); | ||
169 | |||
170 | if (flowctrl & FLOW_CTRL_TX) | ||
171 | mcr |= MAC_MCR_FORCE_TX_FC; | ||
172 | if (flowctrl & FLOW_CTRL_RX) | ||
173 | mcr |= MAC_MCR_FORCE_RX_FC; | ||
174 | |||
175 | netif_dbg(mac->hw, link, dev, "rx pause %s, tx pause %s\n", | ||
176 | flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled", | ||
177 | flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled"); | ||
178 | } | ||
158 | 179 | ||
159 | mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); | 180 | mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); |
160 | 181 | ||
@@ -208,10 +229,16 @@ static int mtk_phy_connect(struct mtk_mac *mac) | |||
208 | u32 val, ge_mode; | 229 | u32 val, ge_mode; |
209 | 230 | ||
210 | np = of_parse_phandle(mac->of_node, "phy-handle", 0); | 231 | np = of_parse_phandle(mac->of_node, "phy-handle", 0); |
232 | if (!np && of_phy_is_fixed_link(mac->of_node)) | ||
233 | if (!of_phy_register_fixed_link(mac->of_node)) | ||
234 | np = of_node_get(mac->of_node); | ||
211 | if (!np) | 235 | if (!np) |
212 | return -ENODEV; | 236 | return -ENODEV; |
213 | 237 | ||
214 | switch (of_get_phy_mode(np)) { | 238 | switch (of_get_phy_mode(np)) { |
239 | case PHY_INTERFACE_MODE_RGMII_TXID: | ||
240 | case PHY_INTERFACE_MODE_RGMII_RXID: | ||
241 | case PHY_INTERFACE_MODE_RGMII_ID: | ||
215 | case PHY_INTERFACE_MODE_RGMII: | 242 | case PHY_INTERFACE_MODE_RGMII: |
216 | ge_mode = 0; | 243 | ge_mode = 0; |
217 | break; | 244 | break; |
@@ -236,7 +263,8 @@ static int mtk_phy_connect(struct mtk_mac *mac) | |||
236 | mac->phy_dev->autoneg = AUTONEG_ENABLE; | 263 | mac->phy_dev->autoneg = AUTONEG_ENABLE; |
237 | mac->phy_dev->speed = 0; | 264 | mac->phy_dev->speed = 0; |
238 | mac->phy_dev->duplex = 0; | 265 | mac->phy_dev->duplex = 0; |
239 | mac->phy_dev->supported &= PHY_BASIC_FEATURES; | 266 | mac->phy_dev->supported &= PHY_GBIT_FEATURES | SUPPORTED_Pause | |
267 | SUPPORTED_Asym_Pause; | ||
240 | mac->phy_dev->advertising = mac->phy_dev->supported | | 268 | mac->phy_dev->advertising = mac->phy_dev->supported | |
241 | ADVERTISED_Autoneg; | 269 | ADVERTISED_Autoneg; |
242 | phy_start_aneg(mac->phy_dev); | 270 | phy_start_aneg(mac->phy_dev); |
@@ -280,7 +308,7 @@ static int mtk_mdio_init(struct mtk_eth *eth) | |||
280 | return 0; | 308 | return 0; |
281 | 309 | ||
282 | err_free_bus: | 310 | err_free_bus: |
283 | kfree(eth->mii_bus); | 311 | mdiobus_free(eth->mii_bus); |
284 | 312 | ||
285 | err_put_node: | 313 | err_put_node: |
286 | of_node_put(mii_np); | 314 | of_node_put(mii_np); |
@@ -295,7 +323,7 @@ static void mtk_mdio_cleanup(struct mtk_eth *eth) | |||
295 | 323 | ||
296 | mdiobus_unregister(eth->mii_bus); | 324 | mdiobus_unregister(eth->mii_bus); |
297 | of_node_put(eth->mii_bus->dev.of_node); | 325 | of_node_put(eth->mii_bus->dev.of_node); |
298 | kfree(eth->mii_bus); | 326 | mdiobus_free(eth->mii_bus); |
299 | } | 327 | } |
300 | 328 | ||
301 | static inline void mtk_irq_disable(struct mtk_eth *eth, u32 mask) | 329 | static inline void mtk_irq_disable(struct mtk_eth *eth, u32 mask) |