diff options
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/common.h | 21 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 34 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 64 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 94 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 58 |
6 files changed, 257 insertions, 15 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 479f47914035..942fdce3ab93 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h | |||
@@ -144,6 +144,9 @@ struct stmmac_extra_stats { | |||
144 | unsigned long irq_pcs_ane_n; | 144 | unsigned long irq_pcs_ane_n; |
145 | unsigned long irq_pcs_link_n; | 145 | unsigned long irq_pcs_link_n; |
146 | unsigned long irq_rgmii_n; | 146 | unsigned long irq_rgmii_n; |
147 | unsigned long pcs_link; | ||
148 | unsigned long pcs_duplex; | ||
149 | unsigned long pcs_speed; | ||
147 | }; | 150 | }; |
148 | 151 | ||
149 | /* CSR Frequency Access Defines*/ | 152 | /* CSR Frequency Access Defines*/ |
@@ -165,6 +168,12 @@ struct stmmac_extra_stats { | |||
165 | #define FLOW_TX 2 | 168 | #define FLOW_TX 2 |
166 | #define FLOW_AUTO (FLOW_TX | FLOW_RX) | 169 | #define FLOW_AUTO (FLOW_TX | FLOW_RX) |
167 | 170 | ||
171 | /* PCS defines */ | ||
172 | #define STMMAC_PCS_RGMII (1 << 0) | ||
173 | #define STMMAC_PCS_SGMII (1 << 1) | ||
174 | #define STMMAC_PCS_TBI (1 << 2) | ||
175 | #define STMMAC_PCS_RTBI (1 << 3) | ||
176 | |||
168 | #define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */ | 177 | #define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */ |
169 | 178 | ||
170 | /* DAM HW feature register fields */ | 179 | /* DAM HW feature register fields */ |
@@ -230,6 +239,16 @@ enum dma_irq_status { | |||
230 | #define CORE_PCS_LINK_STATUS (1 << 6) | 239 | #define CORE_PCS_LINK_STATUS (1 << 6) |
231 | #define CORE_RGMII_IRQ (1 << 7) | 240 | #define CORE_RGMII_IRQ (1 << 7) |
232 | 241 | ||
242 | struct rgmii_adv { | ||
243 | unsigned int pause; | ||
244 | unsigned int duplex; | ||
245 | unsigned int lp_pause; | ||
246 | unsigned int lp_duplex; | ||
247 | }; | ||
248 | |||
249 | #define STMMAC_PCS_PAUSE 1 | ||
250 | #define STMMAC_PCS_ASYM_PAUSE 2 | ||
251 | |||
233 | /* DMA HW capabilities */ | 252 | /* DMA HW capabilities */ |
234 | struct dma_features { | 253 | struct dma_features { |
235 | unsigned int mbps_10_100; | 254 | unsigned int mbps_10_100; |
@@ -375,6 +394,8 @@ struct stmmac_ops { | |||
375 | void (*reset_eee_mode) (void __iomem *ioaddr); | 394 | void (*reset_eee_mode) (void __iomem *ioaddr); |
376 | void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw); | 395 | void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw); |
377 | void (*set_eee_pls) (void __iomem *ioaddr, int link); | 396 | void (*set_eee_pls) (void __iomem *ioaddr, int link); |
397 | void (*ctrl_ane) (void __iomem *ioaddr, bool restart); | ||
398 | void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv); | ||
378 | }; | 399 | }; |
379 | 400 | ||
380 | struct mac_link { | 401 | struct mac_link { |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h index 6dd689e19f0a..57f4e8f607e9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | |||
@@ -98,6 +98,38 @@ enum power_event { | |||
98 | #define GMAC_TBI 0x000000d4 /* TBI extend status */ | 98 | #define GMAC_TBI 0x000000d4 /* TBI extend status */ |
99 | #define GMAC_S_R_GMII 0x000000d8 /* SGMII RGMII status */ | 99 | #define GMAC_S_R_GMII 0x000000d8 /* SGMII RGMII status */ |
100 | 100 | ||
101 | /* AN Configuration defines */ | ||
102 | #define GMAC_AN_CTRL_RAN 0x00000200 /* Restart Auto-Negotiation */ | ||
103 | #define GMAC_AN_CTRL_ANE 0x00001000 /* Auto-Negotiation Enable */ | ||
104 | #define GMAC_AN_CTRL_ELE 0x00004000 /* External Loopback Enable */ | ||
105 | #define GMAC_AN_CTRL_ECD 0x00010000 /* Enable Comma Detect */ | ||
106 | #define GMAC_AN_CTRL_LR 0x00020000 /* Lock to Reference */ | ||
107 | #define GMAC_AN_CTRL_SGMRAL 0x00040000 /* SGMII RAL Control */ | ||
108 | |||
109 | /* AN Status defines */ | ||
110 | #define GMAC_AN_STATUS_LS 0x00000004 /* Link Status 0:down 1:up */ | ||
111 | #define GMAC_AN_STATUS_ANA 0x00000008 /* Auto-Negotiation Ability */ | ||
112 | #define GMAC_AN_STATUS_ANC 0x00000020 /* Auto-Negotiation Complete */ | ||
113 | #define GMAC_AN_STATUS_ES 0x00000100 /* Extended Status */ | ||
114 | |||
115 | /* Register 54 (SGMII/RGMII status register) */ | ||
116 | #define GMAC_S_R_GMII_LINK 0x8 | ||
117 | #define GMAC_S_R_GMII_SPEED 0x5 | ||
118 | #define GMAC_S_R_GMII_SPEED_SHIFT 0x1 | ||
119 | #define GMAC_S_R_GMII_MODE 0x1 | ||
120 | #define GMAC_S_R_GMII_SPEED_125 2 | ||
121 | #define GMAC_S_R_GMII_SPEED_25 1 | ||
122 | |||
123 | /* Common ADV and LPA defines */ | ||
124 | #define GMAC_ANE_FD (1 << 5) | ||
125 | #define GMAC_ANE_HD (1 << 6) | ||
126 | #define GMAC_ANE_PSE (3 << 7) | ||
127 | #define GMAC_ANE_PSE_SHIFT 7 | ||
128 | |||
129 | /* GMAC Configuration defines */ | ||
130 | #define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */ | ||
131 | #define GMAC_CONTROL_WD 0x00800000 /* Disable Watchdog on receive */ | ||
132 | |||
101 | /* GMAC Configuration defines */ | 133 | /* GMAC Configuration defines */ |
102 | #define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */ | 134 | #define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */ |
103 | #define GMAC_CONTROL_WD 0x00800000 /* Disable Watchdog on receive */ | 135 | #define GMAC_CONTROL_WD 0x00800000 /* Disable Watchdog on receive */ |
@@ -232,5 +264,7 @@ enum rtc_control { | |||
232 | #define GMAC_MMC_TX_INTR 0x108 | 264 | #define GMAC_MMC_TX_INTR 0x108 |
233 | #define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 | 265 | #define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 |
234 | 266 | ||
267 | |||
268 | |||
235 | extern const struct stmmac_dma_ops dwmac1000_dma_ops; | 269 | extern const struct stmmac_dma_ops dwmac1000_dma_ops; |
236 | #endif /* __DWMAC1000_H__ */ | 270 | #endif /* __DWMAC1000_H__ */ |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index ff4c79e690f1..29138da19db0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | |||
@@ -28,6 +28,7 @@ | |||
28 | 28 | ||
29 | #include <linux/crc32.h> | 29 | #include <linux/crc32.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/ethtool.h> | ||
31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
32 | #include "dwmac1000.h" | 33 | #include "dwmac1000.h" |
33 | 34 | ||
@@ -193,7 +194,6 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode) | |||
193 | writel(pmt, ioaddr + GMAC_PMT); | 194 | writel(pmt, ioaddr + GMAC_PMT); |
194 | } | 195 | } |
195 | 196 | ||
196 | |||
197 | static int dwmac1000_irq_status(void __iomem *ioaddr, | 197 | static int dwmac1000_irq_status(void __iomem *ioaddr, |
198 | struct stmmac_extra_stats *x) | 198 | struct stmmac_extra_stats *x) |
199 | { | 199 | { |
@@ -252,9 +252,30 @@ static int dwmac1000_irq_status(void __iomem *ioaddr, | |||
252 | x->irq_pcs_ane_n++; | 252 | x->irq_pcs_ane_n++; |
253 | } | 253 | } |
254 | if (intr_status & rgmii_irq) { | 254 | if (intr_status & rgmii_irq) { |
255 | CHIP_DBG(KERN_INFO "GMAC RGMII IRQ status\n"); | 255 | u32 status = readl(ioaddr + GMAC_S_R_GMII); |
256 | readl(ioaddr + GMAC_S_R_GMII); | 256 | CHIP_DBG(KERN_INFO "GMAC RGMII/SGMII interrupt\n"); |
257 | x->irq_rgmii_n++; | 257 | x->irq_rgmii_n++; |
258 | |||
259 | /* Save and dump the link status. */ | ||
260 | if (status & GMAC_S_R_GMII_LINK) { | ||
261 | int speed_value = (status & GMAC_S_R_GMII_SPEED) >> | ||
262 | GMAC_S_R_GMII_SPEED_SHIFT; | ||
263 | x->pcs_duplex = (status & GMAC_S_R_GMII_MODE); | ||
264 | |||
265 | if (speed_value == GMAC_S_R_GMII_SPEED_125) | ||
266 | x->pcs_speed = SPEED_1000; | ||
267 | else if (speed_value == GMAC_S_R_GMII_SPEED_25) | ||
268 | x->pcs_speed = SPEED_100; | ||
269 | else | ||
270 | x->pcs_speed = SPEED_10; | ||
271 | |||
272 | x->pcs_link = 1; | ||
273 | pr_debug("Link is Up - %d/%s\n", (int) x->pcs_speed, | ||
274 | x->pcs_duplex ? "Full" : "Half"); | ||
275 | } else { | ||
276 | x->pcs_link = 0; | ||
277 | pr_debug("Link is Down\n"); | ||
278 | } | ||
258 | } | 279 | } |
259 | 280 | ||
260 | return ret; | 281 | return ret; |
@@ -309,6 +330,41 @@ static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw) | |||
309 | writel(value, ioaddr + LPI_TIMER_CTRL); | 330 | writel(value, ioaddr + LPI_TIMER_CTRL); |
310 | } | 331 | } |
311 | 332 | ||
333 | static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool restart) | ||
334 | { | ||
335 | u32 value; | ||
336 | |||
337 | value = readl(ioaddr + GMAC_AN_CTRL); | ||
338 | /* auto negotiation enable and External Loopback enable */ | ||
339 | value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE; | ||
340 | |||
341 | if (restart) | ||
342 | value |= GMAC_AN_CTRL_RAN; | ||
343 | |||
344 | writel(value, ioaddr + GMAC_AN_CTRL); | ||
345 | } | ||
346 | |||
347 | static void dwmac1000_get_adv(void __iomem *ioaddr, struct rgmii_adv *adv) | ||
348 | { | ||
349 | u32 value = readl(ioaddr + GMAC_ANE_ADV); | ||
350 | |||
351 | if (value & GMAC_ANE_FD) | ||
352 | adv->duplex = DUPLEX_FULL; | ||
353 | if (value & GMAC_ANE_HD) | ||
354 | adv->duplex |= DUPLEX_HALF; | ||
355 | |||
356 | adv->pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; | ||
357 | |||
358 | value = readl(ioaddr + GMAC_ANE_LPA); | ||
359 | |||
360 | if (value & GMAC_ANE_FD) | ||
361 | adv->lp_duplex = DUPLEX_FULL; | ||
362 | if (value & GMAC_ANE_HD) | ||
363 | adv->lp_duplex = DUPLEX_HALF; | ||
364 | |||
365 | adv->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; | ||
366 | } | ||
367 | |||
312 | static const struct stmmac_ops dwmac1000_ops = { | 368 | static const struct stmmac_ops dwmac1000_ops = { |
313 | .core_init = dwmac1000_core_init, | 369 | .core_init = dwmac1000_core_init, |
314 | .rx_ipc = dwmac1000_rx_ipc_enable, | 370 | .rx_ipc = dwmac1000_rx_ipc_enable, |
@@ -323,6 +379,8 @@ static const struct stmmac_ops dwmac1000_ops = { | |||
323 | .reset_eee_mode = dwmac1000_reset_eee_mode, | 379 | .reset_eee_mode = dwmac1000_reset_eee_mode, |
324 | .set_eee_timer = dwmac1000_set_eee_timer, | 380 | .set_eee_timer = dwmac1000_set_eee_timer, |
325 | .set_eee_pls = dwmac1000_set_eee_pls, | 381 | .set_eee_pls = dwmac1000_set_eee_pls, |
382 | .ctrl_ane = dwmac1000_ctrl_ane, | ||
383 | .get_adv = dwmac1000_get_adv, | ||
326 | }; | 384 | }; |
327 | 385 | ||
328 | struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr) | 386 | struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr) |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 9637d3e86af9..182a83802aa2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h | |||
@@ -97,6 +97,7 @@ struct stmmac_priv { | |||
97 | u32 rx_riwt; | 97 | u32 rx_riwt; |
98 | unsigned int mode; | 98 | unsigned int mode; |
99 | int extend_desc; | 99 | int extend_desc; |
100 | int pcs; | ||
100 | }; | 101 | }; |
101 | 102 | ||
102 | extern int phyaddr; | 103 | extern int phyaddr; |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 179362857096..54e15db516fe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | |||
@@ -246,6 +246,70 @@ static int stmmac_ethtool_getsettings(struct net_device *dev, | |||
246 | struct stmmac_priv *priv = netdev_priv(dev); | 246 | struct stmmac_priv *priv = netdev_priv(dev); |
247 | struct phy_device *phy = priv->phydev; | 247 | struct phy_device *phy = priv->phydev; |
248 | int rc; | 248 | int rc; |
249 | |||
250 | if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) { | ||
251 | struct rgmii_adv adv; | ||
252 | |||
253 | if (!priv->xstats.pcs_link) { | ||
254 | ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); | ||
255 | cmd->duplex = DUPLEX_UNKNOWN; | ||
256 | return 0; | ||
257 | } | ||
258 | cmd->duplex = priv->xstats.pcs_duplex; | ||
259 | |||
260 | ethtool_cmd_speed_set(cmd, priv->xstats.pcs_speed); | ||
261 | |||
262 | /* Get and convert ADV/LP_ADV from the HW AN registers */ | ||
263 | if (priv->hw->mac->get_adv) | ||
264 | priv->hw->mac->get_adv(priv->ioaddr, &adv); | ||
265 | else | ||
266 | return -EOPNOTSUPP; /* should never happen indeed */ | ||
267 | |||
268 | /* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */ | ||
269 | |||
270 | if (adv.pause & STMMAC_PCS_PAUSE) | ||
271 | cmd->advertising |= ADVERTISED_Pause; | ||
272 | if (adv.pause & STMMAC_PCS_ASYM_PAUSE) | ||
273 | cmd->advertising |= ADVERTISED_Asym_Pause; | ||
274 | if (adv.lp_pause & STMMAC_PCS_PAUSE) | ||
275 | cmd->lp_advertising |= ADVERTISED_Pause; | ||
276 | if (adv.lp_pause & STMMAC_PCS_ASYM_PAUSE) | ||
277 | cmd->lp_advertising |= ADVERTISED_Asym_Pause; | ||
278 | |||
279 | /* Reg49[3] always set because ANE is always supported */ | ||
280 | cmd->autoneg = ADVERTISED_Autoneg; | ||
281 | cmd->supported |= SUPPORTED_Autoneg; | ||
282 | cmd->advertising |= ADVERTISED_Autoneg; | ||
283 | cmd->lp_advertising |= ADVERTISED_Autoneg; | ||
284 | |||
285 | if (adv.duplex) { | ||
286 | cmd->supported |= (SUPPORTED_1000baseT_Full | | ||
287 | SUPPORTED_100baseT_Full | | ||
288 | SUPPORTED_10baseT_Full); | ||
289 | cmd->advertising |= (ADVERTISED_1000baseT_Full | | ||
290 | ADVERTISED_100baseT_Full | | ||
291 | ADVERTISED_10baseT_Full); | ||
292 | } else { | ||
293 | cmd->supported |= (SUPPORTED_1000baseT_Half | | ||
294 | SUPPORTED_100baseT_Half | | ||
295 | SUPPORTED_10baseT_Half); | ||
296 | cmd->advertising |= (ADVERTISED_1000baseT_Half | | ||
297 | ADVERTISED_100baseT_Half | | ||
298 | ADVERTISED_10baseT_Half); | ||
299 | } | ||
300 | if (adv.lp_duplex) | ||
301 | cmd->lp_advertising |= (ADVERTISED_1000baseT_Full | | ||
302 | ADVERTISED_100baseT_Full | | ||
303 | ADVERTISED_10baseT_Full); | ||
304 | else | ||
305 | cmd->lp_advertising |= (ADVERTISED_1000baseT_Half | | ||
306 | ADVERTISED_100baseT_Half | | ||
307 | ADVERTISED_10baseT_Half); | ||
308 | cmd->port = PORT_OTHER; | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
249 | if (phy == NULL) { | 313 | if (phy == NULL) { |
250 | pr_err("%s: %s: PHY is not registered\n", | 314 | pr_err("%s: %s: PHY is not registered\n", |
251 | __func__, dev->name); | 315 | __func__, dev->name); |
@@ -270,6 +334,30 @@ static int stmmac_ethtool_setsettings(struct net_device *dev, | |||
270 | struct phy_device *phy = priv->phydev; | 334 | struct phy_device *phy = priv->phydev; |
271 | int rc; | 335 | int rc; |
272 | 336 | ||
337 | if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) { | ||
338 | u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause; | ||
339 | |||
340 | /* Only support ANE */ | ||
341 | if (cmd->autoneg != AUTONEG_ENABLE) | ||
342 | return -EINVAL; | ||
343 | |||
344 | if (cmd->autoneg == AUTONEG_ENABLE) { | ||
345 | mask &= (ADVERTISED_1000baseT_Half | | ||
346 | ADVERTISED_1000baseT_Full | | ||
347 | ADVERTISED_100baseT_Half | | ||
348 | ADVERTISED_100baseT_Full | | ||
349 | ADVERTISED_10baseT_Half | | ||
350 | ADVERTISED_10baseT_Full); | ||
351 | |||
352 | spin_lock(&priv->lock); | ||
353 | if (priv->hw->mac->ctrl_ane) | ||
354 | priv->hw->mac->ctrl_ane(priv->ioaddr, 1); | ||
355 | spin_unlock(&priv->lock); | ||
356 | } | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
273 | spin_lock(&priv->lock); | 361 | spin_lock(&priv->lock); |
274 | rc = phy_ethtool_sset(phy, cmd); | 362 | rc = phy_ethtool_sset(phy, cmd); |
275 | spin_unlock(&priv->lock); | 363 | spin_unlock(&priv->lock); |
@@ -339,6 +427,9 @@ stmmac_get_pauseparam(struct net_device *netdev, | |||
339 | { | 427 | { |
340 | struct stmmac_priv *priv = netdev_priv(netdev); | 428 | struct stmmac_priv *priv = netdev_priv(netdev); |
341 | 429 | ||
430 | if (priv->pcs) /* FIXME */ | ||
431 | return; | ||
432 | |||
342 | spin_lock(&priv->lock); | 433 | spin_lock(&priv->lock); |
343 | 434 | ||
344 | pause->rx_pause = 0; | 435 | pause->rx_pause = 0; |
@@ -362,6 +453,9 @@ stmmac_set_pauseparam(struct net_device *netdev, | |||
362 | int new_pause = FLOW_OFF; | 453 | int new_pause = FLOW_OFF; |
363 | int ret = 0; | 454 | int ret = 0; |
364 | 455 | ||
456 | if (priv->pcs) /* FIXME */ | ||
457 | return -EOPNOTSUPP; | ||
458 | |||
365 | spin_lock(&priv->lock); | 459 | spin_lock(&priv->lock); |
366 | 460 | ||
367 | if (pause->rx_pause) | 461 | if (pause->rx_pause) |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index ca3e95a4b16f..ac166be325ed 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | |||
@@ -405,6 +405,24 @@ static void stmmac_adjust_link(struct net_device *dev) | |||
405 | DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n"); | 405 | DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n"); |
406 | } | 406 | } |
407 | 407 | ||
408 | static void stmmac_check_pcs_mode(struct stmmac_priv *priv) | ||
409 | { | ||
410 | int interface = priv->plat->interface; | ||
411 | |||
412 | if (priv->dma_cap.pcs) { | ||
413 | if ((interface & PHY_INTERFACE_MODE_RGMII) || | ||
414 | (interface & PHY_INTERFACE_MODE_RGMII_ID) || | ||
415 | (interface & PHY_INTERFACE_MODE_RGMII_RXID) || | ||
416 | (interface & PHY_INTERFACE_MODE_RGMII_TXID)) { | ||
417 | pr_debug("STMMAC: PCS RGMII support enable\n"); | ||
418 | priv->pcs = STMMAC_PCS_RGMII; | ||
419 | } else if (interface & PHY_INTERFACE_MODE_SGMII) { | ||
420 | pr_debug("STMMAC: PCS SGMII support enable\n"); | ||
421 | priv->pcs = STMMAC_PCS_SGMII; | ||
422 | } | ||
423 | } | ||
424 | } | ||
425 | |||
408 | /** | 426 | /** |
409 | * stmmac_init_phy - PHY initialization | 427 | * stmmac_init_phy - PHY initialization |
410 | * @dev: net device structure | 428 | * @dev: net device structure |
@@ -1141,10 +1159,13 @@ static int stmmac_open(struct net_device *dev) | |||
1141 | 1159 | ||
1142 | stmmac_check_ether_addr(priv); | 1160 | stmmac_check_ether_addr(priv); |
1143 | 1161 | ||
1144 | ret = stmmac_init_phy(dev); | 1162 | if (!priv->pcs) { |
1145 | if (unlikely(ret)) { | 1163 | ret = stmmac_init_phy(dev); |
1146 | pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret); | 1164 | if (ret) { |
1147 | goto open_error; | 1165 | pr_err("%s: Cannot attach to PHY (error: %d)\n", |
1166 | __func__, ret); | ||
1167 | goto open_error; | ||
1168 | } | ||
1148 | } | 1169 | } |
1149 | 1170 | ||
1150 | /* Create and initialize the TX/RX descriptors chains. */ | 1171 | /* Create and initialize the TX/RX descriptors chains. */ |
@@ -1233,7 +1254,12 @@ static int stmmac_open(struct net_device *dev) | |||
1233 | phy_start(priv->phydev); | 1254 | phy_start(priv->phydev); |
1234 | 1255 | ||
1235 | priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER; | 1256 | priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER; |
1236 | priv->eee_enabled = stmmac_eee_init(priv); | 1257 | |
1258 | /* Using PCS we cannot dial with the phy registers at this stage | ||
1259 | * so we do not support extra feature like EEE. | ||
1260 | */ | ||
1261 | if (!priv->pcs) | ||
1262 | priv->eee_enabled = stmmac_eee_init(priv); | ||
1237 | 1263 | ||
1238 | stmmac_init_tx_coalesce(priv); | 1264 | stmmac_init_tx_coalesce(priv); |
1239 | 1265 | ||
@@ -1242,6 +1268,9 @@ static int stmmac_open(struct net_device *dev) | |||
1242 | priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); | 1268 | priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); |
1243 | } | 1269 | } |
1244 | 1270 | ||
1271 | if (priv->pcs && priv->hw->mac->ctrl_ane) | ||
1272 | priv->hw->mac->ctrl_ane(priv->ioaddr, 0); | ||
1273 | |||
1245 | napi_enable(&priv->napi); | 1274 | napi_enable(&priv->napi); |
1246 | netif_start_queue(dev); | 1275 | netif_start_queue(dev); |
1247 | 1276 | ||
@@ -2225,12 +2254,16 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, | |||
2225 | else | 2254 | else |
2226 | priv->clk_csr = priv->plat->clk_csr; | 2255 | priv->clk_csr = priv->plat->clk_csr; |
2227 | 2256 | ||
2228 | /* MDIO bus Registration */ | 2257 | stmmac_check_pcs_mode(priv); |
2229 | ret = stmmac_mdio_register(ndev); | 2258 | |
2230 | if (ret < 0) { | 2259 | if (!priv->pcs) { |
2231 | pr_debug("%s: MDIO bus (id: %d) registration failed", | 2260 | /* MDIO bus Registration */ |
2232 | __func__, priv->plat->bus_id); | 2261 | ret = stmmac_mdio_register(ndev); |
2233 | goto error_mdio_register; | 2262 | if (ret < 0) { |
2263 | pr_debug("%s: MDIO bus (id: %d) registration failed", | ||
2264 | __func__, priv->plat->bus_id); | ||
2265 | goto error_mdio_register; | ||
2266 | } | ||
2234 | } | 2267 | } |
2235 | 2268 | ||
2236 | return priv; | 2269 | return priv; |
@@ -2263,7 +2296,8 @@ int stmmac_dvr_remove(struct net_device *ndev) | |||
2263 | priv->hw->dma->stop_tx(priv->ioaddr); | 2296 | priv->hw->dma->stop_tx(priv->ioaddr); |
2264 | 2297 | ||
2265 | stmmac_set_mac(priv->ioaddr, false); | 2298 | stmmac_set_mac(priv->ioaddr, false); |
2266 | stmmac_mdio_unregister(ndev); | 2299 | if (!priv->pcs) |
2300 | stmmac_mdio_unregister(ndev); | ||
2267 | netif_carrier_off(ndev); | 2301 | netif_carrier_off(ndev); |
2268 | unregister_netdev(ndev); | 2302 | unregister_netdev(ndev); |
2269 | free_netdev(ndev); | 2303 | free_netdev(ndev); |