Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers: net: stmmac: reworking the PCS code.

The 3.xx and 4.xx synopsys gmacs have a very similar
PCS embedded module and they share almost the same registers:
for example:
AN_Control, AN_Status, AN_Advertisement, AN_Link_Partner_Ability,
AN_Expansion, TBI_Extended_Status.

Just the RGMII/SMII Control/Status register differs.

So This patch aims to reorganize and enhance the PCS support.
It removes the existent support from the dwmac1000/dwmac4_core.c
moving basic PCS functions inside a new file called: stmmac_pcs.h.

The patch also reviews the available APIs to be better shared among
different hardware and easily enhanced to support new features.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Giuseppe CAVALLARO and committed by
David S. Miller
70523e63 a5e4bd99

+350 -165
+1
Documentation/networking/stmmac.txt
··· 285 285 o mmc_core.c/mmc.h: Management MAC Counters; 286 286 o stmmac_hwtstamp.c: HW timestamp support for PTP; 287 287 o stmmac_ptp.c: PTP 1588 clock; 288 + o stmmac_pcs.h: Physical Coding Sublayer common implementation; 288 289 o dwmac-<XXX>.c: these are for the platform glue-logic file; e.g. dwmac-sti.c 289 290 for STMicroelectronics SoCs. 290 291
+11 -5
drivers/net/ethernet/stmicro/stmmac/common.h
··· 232 232 #define DMA_HW_FEAT_ACTPHYIF 0x70000000 /* Active/selected PHY iface */ 233 233 #define DEFAULT_DMA_PBL 8 234 234 235 + /* PCS status and mask defines */ 236 + #define PCS_ANE_IRQ BIT(2) /* PCS Auto-Negotiation */ 237 + #define PCS_LINK_IRQ BIT(1) /* PCS Link */ 238 + #define PCS_RGSMIIIS_IRQ BIT(0) /* RGMII or SMII Interrupt */ 239 + 235 240 /* Max/Min RI Watchdog Timer count value */ 236 241 #define MAX_DMA_RIWT 0xff 237 242 #define MIN_DMA_RIWT 0x20 ··· 277 272 #define CORE_IRQ_RX_PATH_IN_LPI_MODE (1 << 2) 278 273 #define CORE_IRQ_RX_PATH_EXIT_LPI_MODE (1 << 3) 279 274 280 - #define CORE_PCS_ANE_COMPLETE (1 << 5) 281 - #define CORE_PCS_LINK_STATUS (1 << 6) 282 - #define CORE_RGMII_IRQ (1 << 7) 283 275 #define CORE_IRQ_MTL_RX_OVERFLOW BIT(8) 284 276 285 277 /* Physical Coding Sublayer */ ··· 471 469 void (*reset_eee_mode)(struct mac_device_info *hw); 472 470 void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw); 473 471 void (*set_eee_pls)(struct mac_device_info *hw, int link); 474 - void (*ctrl_ane)(struct mac_device_info *hw, bool restart); 475 - void (*get_adv)(struct mac_device_info *hw, struct rgmii_adv *adv); 476 472 void (*debug)(void __iomem *ioaddr, struct stmmac_extra_stats *x); 473 + /* PCS calls */ 474 + void (*pcs_ctrl_ane)(void __iomem *ioaddr, bool ane, bool srgmi_ral, 475 + bool loopback); 476 + void (*pcs_rane)(void __iomem *ioaddr, bool restart); 477 + void (*pcs_get_adv_lp)(void __iomem *ioaddr, struct rgmii_adv *adv); 477 478 }; 478 479 479 480 /* PTP and HW Timer helpers */ ··· 551 546 void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable); 552 547 553 548 void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr); 549 + 554 550 extern const struct stmmac_mode_ops ring_mode_ops; 555 551 extern const struct stmmac_mode_ops chain_mode_ops; 556 552 extern const struct stmmac_desc_ops dwmac4_desc_ops;
+16 -38
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
··· 46 46 mmc_rx_irq = 0x0020, 47 47 mmc_irq = 0x0010, 48 48 pmt_irq = 0x0008, 49 - pcs_ane_irq = 0x0004, 50 - pcs_link_irq = 0x0002, 51 - rgmii_irq = 0x0001, 52 49 }; 53 50 #define GMAC_INT_MASK 0x0000003c /* interrupt mask register */ 54 51 ··· 87 90 (reg * 8)) 88 91 #define GMAC_MAX_PERFECT_ADDRESSES 1 89 92 90 - /* PCS registers (AN/TBI/SGMII/RGMII) offset */ 91 - #define GMAC_AN_CTRL 0x000000c0 /* AN control */ 92 - #define GMAC_AN_STATUS 0x000000c4 /* AN status */ 93 - #define GMAC_ANE_ADV 0x000000c8 /* Auto-Neg. Advertisement */ 94 - #define GMAC_ANE_LPA 0x000000cc /* Auto-Neg. link partener ability */ 95 - #define GMAC_ANE_EXP 0x000000d0 /* ANE expansion */ 96 - #define GMAC_TBI 0x000000d4 /* TBI extend status */ 97 - #define GMAC_S_R_GMII 0x000000d8 /* SGMII RGMII status */ 93 + #define GMAC_PCS_BASE 0x000000c0 /* PCS register base */ 94 + #define GMAC_RGSMIIIS 0x000000d8 /* RGMII/SMII status */ 98 95 99 - /* AN Configuration defines */ 100 - #define GMAC_AN_CTRL_RAN 0x00000200 /* Restart Auto-Negotiation */ 101 - #define GMAC_AN_CTRL_ANE 0x00001000 /* Auto-Negotiation Enable */ 102 - #define GMAC_AN_CTRL_ELE 0x00004000 /* External Loopback Enable */ 103 - #define GMAC_AN_CTRL_ECD 0x00010000 /* Enable Comma Detect */ 104 - #define GMAC_AN_CTRL_LR 0x00020000 /* Lock to Reference */ 105 - #define GMAC_AN_CTRL_SGMRAL 0x00040000 /* SGMII RAL Control */ 106 - 107 - /* AN Status defines */ 108 - #define GMAC_AN_STATUS_LS 0x00000004 /* Link Status 0:down 1:up */ 109 - #define GMAC_AN_STATUS_ANA 0x00000008 /* Auto-Negotiation Ability */ 110 - #define GMAC_AN_STATUS_ANC 0x00000020 /* Auto-Negotiation Complete */ 111 - #define GMAC_AN_STATUS_ES 0x00000100 /* Extended Status */ 112 - 113 - /* Register 54 (SGMII/RGMII status register) */ 114 - #define GMAC_S_R_GMII_LINK 0x8 115 - #define GMAC_S_R_GMII_SPEED 0x5 116 - #define GMAC_S_R_GMII_SPEED_SHIFT 0x1 117 - #define GMAC_S_R_GMII_MODE 0x1 118 - #define GMAC_S_R_GMII_SPEED_125 2 119 - #define GMAC_S_R_GMII_SPEED_25 1 120 - 121 - /* Common ADV and LPA defines */ 122 - #define GMAC_ANE_FD (1 << 5) 123 - #define GMAC_ANE_HD (1 << 6) 124 - #define GMAC_ANE_PSE (3 << 7) 125 - #define GMAC_ANE_PSE_SHIFT 7 96 + /* SGMII/RGMII status register */ 97 + #define GMAC_RGSMIIIS_LNKMODE BIT(0) 98 + #define GMAC_RGSMIIIS_SPEED GENMASK(2, 1) 99 + #define GMAC_RGSMIIIS_SPEED_SHIFT 1 100 + #define GMAC_RGSMIIIS_LNKSTS BIT(3) 101 + #define GMAC_RGSMIIIS_JABTO BIT(4) 102 + #define GMAC_RGSMIIIS_FALSECARDET BIT(5) 103 + #define GMAC_RGSMIIIS_SMIDRXS BIT(16) 104 + /* LNKMOD */ 105 + #define GMAC_RGSMIIIS_LNKMOD_MASK 0x1 106 + /* LNKSPEED */ 107 + #define GMAC_RGSMIIIS_SPEED_125 0x2 108 + #define GMAC_RGSMIIIS_SPEED_25 0x1 109 + #define GMAC_RGSMIIIS_SPEED_2_5 0x0 126 110 127 111 /* GMAC Configuration defines */ 128 112 #define GMAC_CONTROL_2K 0x08000000 /* IEEE 802.3as 2K packets */
+50 -58
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
··· 30 30 #include <linux/slab.h> 31 31 #include <linux/ethtool.h> 32 32 #include <asm/io.h> 33 + #include "stmmac_pcs.h" 33 34 #include "dwmac1000.h" 34 35 35 36 static void dwmac1000_core_init(struct mac_device_info *hw, int mtu) ··· 242 241 writel(pmt, ioaddr + GMAC_PMT); 243 242 } 244 243 244 + /* RGMII or SMII interface */ 245 + static void dwmac1000_rgsmii(void __iomem *ioaddr, struct stmmac_extra_stats *x) 246 + { 247 + u32 status; 248 + 249 + status = readl(ioaddr + GMAC_RGSMIIIS); 250 + x->irq_rgmii_n++; 251 + 252 + /* Check the link status */ 253 + if (status & GMAC_RGSMIIIS_LNKSTS) { 254 + int speed_value; 255 + 256 + x->pcs_link = 1; 257 + 258 + speed_value = ((status & GMAC_RGSMIIIS_SPEED) >> 259 + GMAC_RGSMIIIS_SPEED_SHIFT); 260 + if (speed_value == GMAC_RGSMIIIS_SPEED_125) 261 + x->pcs_speed = SPEED_1000; 262 + else if (speed_value == GMAC_RGSMIIIS_SPEED_25) 263 + x->pcs_speed = SPEED_100; 264 + else 265 + x->pcs_speed = SPEED_10; 266 + 267 + x->pcs_duplex = (status & GMAC_RGSMIIIS_LNKMOD_MASK); 268 + 269 + pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed, 270 + x->pcs_duplex ? "Full" : "Half"); 271 + } else { 272 + x->pcs_link = 0; 273 + pr_info("Link is Down\n"); 274 + } 275 + } 276 + 245 277 static int dwmac1000_irq_status(struct mac_device_info *hw, 246 278 struct stmmac_extra_stats *x) 247 279 { ··· 294 260 readl(ioaddr + GMAC_PMT); 295 261 x->irq_receive_pmt_irq_n++; 296 262 } 263 + 297 264 /* MAC trx/rx EEE LPI entry/exit interrupts */ 298 265 if (intr_status & lpiis_irq) { 299 266 /* Clean LPI interrupt by reading the Reg 12 */ ··· 310 275 x->irq_rx_path_exit_lpi_mode_n++; 311 276 } 312 277 313 - if ((intr_status & pcs_ane_irq) || (intr_status & pcs_link_irq)) { 314 - readl(ioaddr + GMAC_AN_STATUS); 315 - x->irq_pcs_ane_n++; 316 - } 317 - if (intr_status & rgmii_irq) { 318 - u32 status = readl(ioaddr + GMAC_S_R_GMII); 319 - x->irq_rgmii_n++; 278 + dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x); 320 279 321 - /* Save and dump the link status. */ 322 - if (status & GMAC_S_R_GMII_LINK) { 323 - int speed_value = (status & GMAC_S_R_GMII_SPEED) >> 324 - GMAC_S_R_GMII_SPEED_SHIFT; 325 - x->pcs_duplex = (status & GMAC_S_R_GMII_MODE); 326 - 327 - if (speed_value == GMAC_S_R_GMII_SPEED_125) 328 - x->pcs_speed = SPEED_1000; 329 - else if (speed_value == GMAC_S_R_GMII_SPEED_25) 330 - x->pcs_speed = SPEED_100; 331 - else 332 - x->pcs_speed = SPEED_10; 333 - 334 - x->pcs_link = 1; 335 - pr_debug("%s: Link is Up - %d/%s\n", __func__, 336 - (int)x->pcs_speed, 337 - x->pcs_duplex ? "Full" : "Half"); 338 - } else { 339 - x->pcs_link = 0; 340 - pr_debug("%s: Link is Down\n", __func__); 341 - } 342 - } 280 + if (intr_status & PCS_RGSMIIIS_IRQ) 281 + dwmac1000_rgsmii(ioaddr, x); 343 282 344 283 return ret; 345 284 } ··· 372 363 writel(value, ioaddr + LPI_TIMER_CTRL); 373 364 } 374 365 375 - static void dwmac1000_ctrl_ane(struct mac_device_info *hw, bool restart) 366 + static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool ane, bool srgmi_ral, 367 + bool loopback) 376 368 { 377 - void __iomem *ioaddr = hw->pcsr; 378 - /* auto negotiation enable and External Loopback enable */ 379 - u32 value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE; 380 - 381 - if (restart) 382 - value |= GMAC_AN_CTRL_RAN; 383 - 384 - writel(value, ioaddr + GMAC_AN_CTRL); 369 + dwmac_ctrl_ane(ioaddr, GMAC_PCS_BASE, ane, srgmi_ral, loopback); 385 370 } 386 371 387 - static void dwmac1000_get_adv(struct mac_device_info *hw, struct rgmii_adv *adv) 372 + static void dwmac1000_rane(void __iomem *ioaddr, bool restart) 388 373 { 389 - void __iomem *ioaddr = hw->pcsr; 390 - u32 value = readl(ioaddr + GMAC_ANE_ADV); 374 + dwmac_rane(ioaddr, GMAC_PCS_BASE, restart); 375 + } 391 376 392 - if (value & GMAC_ANE_FD) 393 - adv->duplex = DUPLEX_FULL; 394 - if (value & GMAC_ANE_HD) 395 - adv->duplex |= DUPLEX_HALF; 396 - 397 - adv->pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; 398 - 399 - value = readl(ioaddr + GMAC_ANE_LPA); 400 - 401 - if (value & GMAC_ANE_FD) 402 - adv->lp_duplex = DUPLEX_FULL; 403 - if (value & GMAC_ANE_HD) 404 - adv->lp_duplex = DUPLEX_HALF; 405 - 406 - adv->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; 377 + static void dwmac1000_get_adv_lp(void __iomem *ioaddr, struct rgmii_adv *adv) 378 + { 379 + dwmac_get_adv_lp(ioaddr, GMAC_PCS_BASE, adv); 407 380 } 408 381 409 382 static void dwmac1000_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x) ··· 476 485 .reset_eee_mode = dwmac1000_reset_eee_mode, 477 486 .set_eee_timer = dwmac1000_set_eee_timer, 478 487 .set_eee_pls = dwmac1000_set_eee_pls, 479 - .ctrl_ane = dwmac1000_ctrl_ane, 480 - .get_adv = dwmac1000_get_adv, 481 488 .debug = dwmac1000_debug, 489 + .pcs_ctrl_ane = dwmac1000_ctrl_ane, 490 + .pcs_rane = dwmac1000_rane, 491 + .pcs_get_adv_lp = dwmac1000_get_adv_lp, 482 492 }; 483 493 484 494 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
+19 -15
drivers/net/ethernet/stmicro/stmmac/dwmac4.h
··· 24 24 #define GMAC_QX_TX_FLOW_CTRL(x) (0x70 + x * 4) 25 25 #define GMAC_INT_STATUS 0x000000b0 26 26 #define GMAC_INT_EN 0x000000b4 27 - #define GMAC_AN_CTRL 0x000000e0 28 - #define GMAC_AN_STATUS 0x000000e4 29 - #define GMAC_AN_ADV 0x000000e8 30 - #define GMAC_AN_LPA 0x000000ec 27 + #define GMAC_PCS_BASE 0x000000e0 28 + #define GMAC_PHYIF_CONTROL_STATUS 0x000000f8 31 29 #define GMAC_PMT 0x000000c0 32 30 #define GMAC_VERSION 0x00000110 33 31 #define GMAC_DEBUG 0x00000114 ··· 62 64 mmc_rx_irq = 0x00000200, 63 65 mmc_irq = 0x00000100, 64 66 pmt_irq = 0x00000010, 65 - pcs_ane_irq = 0x00000004, 66 - pcs_link_irq = 0x00000002, 67 67 }; 68 - 69 - /* MAC Auto-Neg bitmap*/ 70 - #define GMAC_AN_CTRL_RAN BIT(9) 71 - #define GMAC_AN_CTRL_ANE BIT(12) 72 - #define GMAC_AN_CTRL_ELE BIT(14) 73 - #define GMAC_AN_FD BIT(5) 74 - #define GMAC_AN_HD BIT(6) 75 - #define GMAC_AN_PSE_MASK GENMASK(8, 7) 76 - #define GMAC_AN_PSE_SHIFT 7 77 68 78 69 /* MAC PMT bitmap */ 79 70 enum power_event { ··· 236 249 #define MTL_DEBUG_RRCSTS_RSTAT 2 237 250 #define MTL_DEBUG_RRCSTS_FLUSH 3 238 251 #define MTL_DEBUG_RWCSTS BIT(0) 252 + 253 + /* SGMII/RGMII status register */ 254 + #define GMAC_PHYIF_CTRLSTATUS_TC BIT(0) 255 + #define GMAC_PHYIF_CTRLSTATUS_LUD BIT(1) 256 + #define GMAC_PHYIF_CTRLSTATUS_SMIDRXS BIT(4) 257 + #define GMAC_PHYIF_CTRLSTATUS_LNKMOD BIT(16) 258 + #define GMAC_PHYIF_CTRLSTATUS_SPEED GENMASK(18, 17) 259 + #define GMAC_PHYIF_CTRLSTATUS_SPEED_SHIFT 17 260 + #define GMAC_PHYIF_CTRLSTATUS_LNKSTS BIT(19) 261 + #define GMAC_PHYIF_CTRLSTATUS_JABTO BIT(20) 262 + #define GMAC_PHYIF_CTRLSTATUS_FALSECARDET BIT(21) 263 + /* LNKMOD */ 264 + #define GMAC_PHYIF_CTRLSTATUS_LNKMOD_MASK 0x1 265 + /* LNKSPEED */ 266 + #define GMAC_PHYIF_CTRLSTATUS_SPEED_125 0x2 267 + #define GMAC_PHYIF_CTRLSTATUS_SPEED_25 0x1 268 + #define GMAC_PHYIF_CTRLSTATUS_SPEED_2_5 0x0 239 269 240 270 extern const struct stmmac_dma_ops dwmac4_dma_ops; 241 271 extern const struct stmmac_dma_ops dwmac410_dma_ops;
+46 -31
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
··· 17 17 #include <linux/slab.h> 18 18 #include <linux/ethtool.h> 19 19 #include <linux/io.h> 20 + #include "stmmac_pcs.h" 20 21 #include "dwmac4.h" 21 22 22 23 static void dwmac4_core_init(struct mac_device_info *hw, int mtu) ··· 191 190 } 192 191 } 193 192 194 - static void dwmac4_ctrl_ane(struct mac_device_info *hw, bool restart) 193 + static void dwmac4_ctrl_ane(void __iomem *ioaddr, bool ane, bool srgmi_ral, 194 + bool loopback) 195 195 { 196 - void __iomem *ioaddr = hw->pcsr; 197 - 198 - /* auto negotiation enable and External Loopback enable */ 199 - u32 value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE; 200 - 201 - if (restart) 202 - value |= GMAC_AN_CTRL_RAN; 203 - 204 - writel(value, ioaddr + GMAC_AN_CTRL); 196 + dwmac_ctrl_ane(ioaddr, GMAC_PCS_BASE, ane, srgmi_ral, loopback); 205 197 } 206 198 207 - static void dwmac4_get_adv(struct mac_device_info *hw, struct rgmii_adv *adv) 199 + static void dwmac4_rane(void __iomem *ioaddr, bool restart) 208 200 { 209 - void __iomem *ioaddr = hw->pcsr; 210 - u32 value = readl(ioaddr + GMAC_AN_ADV); 201 + dwmac_rane(ioaddr, GMAC_PCS_BASE, restart); 202 + } 211 203 212 - if (value & GMAC_AN_FD) 213 - adv->duplex = DUPLEX_FULL; 214 - if (value & GMAC_AN_HD) 215 - adv->duplex |= DUPLEX_HALF; 204 + static void dwmac4_get_adv_lp(void __iomem *ioaddr, struct rgmii_adv *adv) 205 + { 206 + dwmac_get_adv_lp(ioaddr, GMAC_PCS_BASE, adv); 207 + } 216 208 217 - adv->pause = (value & GMAC_AN_PSE_MASK) >> GMAC_AN_PSE_SHIFT; 209 + /* RGMII or SMII interface */ 210 + static void dwmac4_phystatus(void __iomem *ioaddr, struct stmmac_extra_stats *x) 211 + { 212 + u32 status; 218 213 219 - value = readl(ioaddr + GMAC_AN_LPA); 214 + status = readl(ioaddr + GMAC_PHYIF_CONTROL_STATUS); 215 + x->irq_rgmii_n++; 220 216 221 - if (value & GMAC_AN_FD) 222 - adv->lp_duplex = DUPLEX_FULL; 223 - if (value & GMAC_AN_HD) 224 - adv->lp_duplex = DUPLEX_HALF; 217 + /* Check the link status */ 218 + if (status & GMAC_PHYIF_CTRLSTATUS_LNKSTS) { 219 + int speed_value; 225 220 226 - adv->lp_pause = (value & GMAC_AN_PSE_MASK) >> GMAC_AN_PSE_SHIFT; 221 + x->pcs_link = 1; 222 + 223 + speed_value = ((status & GMAC_PHYIF_CTRLSTATUS_SPEED) >> 224 + GMAC_PHYIF_CTRLSTATUS_SPEED_SHIFT); 225 + if (speed_value == GMAC_PHYIF_CTRLSTATUS_SPEED_125) 226 + x->pcs_speed = SPEED_1000; 227 + else if (speed_value == GMAC_PHYIF_CTRLSTATUS_SPEED_25) 228 + x->pcs_speed = SPEED_100; 229 + else 230 + x->pcs_speed = SPEED_10; 231 + 232 + x->pcs_duplex = (status & GMAC_PHYIF_CTRLSTATUS_LNKMOD_MASK); 233 + 234 + pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed, 235 + x->pcs_duplex ? "Full" : "Half"); 236 + } else { 237 + x->pcs_link = 0; 238 + pr_info("Link is Down\n"); 239 + } 227 240 } 228 241 229 242 static int dwmac4_irq_status(struct mac_device_info *hw, ··· 263 248 x->irq_receive_pmt_irq_n++; 264 249 } 265 250 266 - if ((intr_status & pcs_ane_irq) || (intr_status & pcs_link_irq)) { 267 - readl(ioaddr + GMAC_AN_STATUS); 268 - x->irq_pcs_ane_n++; 269 - } 270 - 271 251 mtl_int_qx_status = readl(ioaddr + MTL_INT_STATUS); 272 252 /* Check MTL Interrupt: Currently only one queue is used: Q0. */ 273 253 if (mtl_int_qx_status & MTL_INT_Q0) { ··· 276 266 ret = CORE_IRQ_MTL_RX_OVERFLOW; 277 267 } 278 268 } 269 + 270 + dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x); 271 + if (intr_status & PCS_RGSMIIIS_IRQ) 272 + dwmac4_phystatus(ioaddr, x); 279 273 280 274 return ret; 281 275 } ··· 377 363 .pmt = dwmac4_pmt, 378 364 .set_umac_addr = dwmac4_set_umac_addr, 379 365 .get_umac_addr = dwmac4_get_umac_addr, 380 - .ctrl_ane = dwmac4_ctrl_ane, 381 - .get_adv = dwmac4_get_adv, 366 + .pcs_ctrl_ane = dwmac4_ctrl_ane, 367 + .pcs_rane = dwmac4_rane, 368 + .pcs_get_adv_lp = dwmac4_get_adv_lp, 382 369 .debug = dwmac4_debug, 383 370 .set_filter = dwmac4_set_filter, 384 371 };
+38 -16
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
··· 289 289 ethtool_cmd_speed_set(cmd, priv->xstats.pcs_speed); 290 290 291 291 /* Get and convert ADV/LP_ADV from the HW AN registers */ 292 - if (!priv->hw->mac->get_adv) 292 + if (!priv->hw->mac->pcs_get_adv_lp) 293 293 return -EOPNOTSUPP; /* should never happen indeed */ 294 294 295 - priv->hw->mac->get_adv(priv->hw, &adv); 295 + priv->hw->mac->pcs_get_adv_lp(priv->ioaddr, &adv); 296 296 297 297 /* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */ 298 298 ··· 376 376 ADVERTISED_10baseT_Full); 377 377 378 378 spin_lock(&priv->lock); 379 - if (priv->hw->mac->ctrl_ane) 380 - priv->hw->mac->ctrl_ane(priv->hw, 1); 379 + 380 + if (priv->hw->mac->pcs_ctrl_ane) 381 + priv->hw->mac->pcs_ctrl_ane(priv->ioaddr, 1, 0, 0); 382 + 381 383 spin_unlock(&priv->lock); 382 384 383 385 return 0; ··· 454 452 { 455 453 struct stmmac_priv *priv = netdev_priv(netdev); 456 454 457 - if (priv->pcs) /* FIXME */ 458 - return; 459 - 460 455 pause->rx_pause = 0; 461 456 pause->tx_pause = 0; 457 + 458 + if (priv->pcs && priv->hw->mac->pcs_get_adv_lp) { 459 + struct rgmii_adv adv_lp; 460 + 461 + pause->autoneg = 1; 462 + priv->hw->mac->pcs_get_adv_lp(priv->ioaddr, &adv_lp); 463 + if (!adv_lp.pause) 464 + return; 465 + } else { 466 + if (!(priv->phydev->supported & SUPPORTED_Pause) || 467 + !(priv->phydev->supported & SUPPORTED_Asym_Pause)) 468 + return; 469 + } 470 + 462 471 pause->autoneg = priv->phydev->autoneg; 463 472 464 473 if (priv->flow_ctrl & FLOW_RX) ··· 486 473 struct stmmac_priv *priv = netdev_priv(netdev); 487 474 struct phy_device *phy = priv->phydev; 488 475 int new_pause = FLOW_OFF; 489 - int ret = 0; 490 476 491 - if (priv->pcs) /* FIXME */ 492 - return -EOPNOTSUPP; 477 + if (priv->pcs && priv->hw->mac->pcs_get_adv_lp) { 478 + struct rgmii_adv adv_lp; 479 + 480 + pause->autoneg = 1; 481 + priv->hw->mac->pcs_get_adv_lp(priv->ioaddr, &adv_lp); 482 + if (!adv_lp.pause) 483 + return -EOPNOTSUPP; 484 + } else { 485 + if (!(phy->supported & SUPPORTED_Pause) || 486 + !(phy->supported & SUPPORTED_Asym_Pause)) 487 + return -EOPNOTSUPP; 488 + } 493 489 494 490 if (pause->rx_pause) 495 491 new_pause |= FLOW_RX; ··· 507 485 508 486 priv->flow_ctrl = new_pause; 509 487 phy->autoneg = pause->autoneg; 510 - 511 488 if (phy->autoneg) { 512 489 if (netif_running(netdev)) 513 - ret = phy_start_aneg(phy); 514 - } else 515 - priv->hw->mac->flow_ctrl(priv->hw, phy->duplex, 516 - priv->flow_ctrl, priv->pause); 517 - return ret; 490 + return phy_start_aneg(phy); 491 + } 492 + 493 + priv->hw->mac->flow_ctrl(priv->hw, phy->duplex, priv->flow_ctrl, 494 + priv->pause); 495 + return 0; 518 496 } 519 497 520 498 static void stmmac_get_ethtool_stats(struct net_device *dev,
+10 -2
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
··· 1714 1714 priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); 1715 1715 } 1716 1716 1717 - if (priv->pcs && priv->hw->mac->ctrl_ane) 1718 - priv->hw->mac->ctrl_ane(priv->hw, 0); 1717 + if (priv->pcs && priv->hw->mac->pcs_ctrl_ane) 1718 + priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, 0, 0); 1719 1719 1720 1720 /* set TX ring length */ 1721 1721 if (priv->hw->dma->set_tx_ring_len) ··· 2808 2808 priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, 2809 2809 priv->rx_tail_addr, 2810 2810 STMMAC_CHAN0); 2811 + } 2812 + 2813 + /* PCS link status */ 2814 + if (priv->pcs) { 2815 + if (priv->xstats.pcs_link) 2816 + netif_carrier_on(dev); 2817 + else 2818 + netif_carrier_off(dev); 2811 2819 } 2812 2820 } 2813 2821
+159
drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h
··· 1 + /* 2 + * stmmac_pcs.h: Physical Coding Sublayer Header File 3 + * 4 + * Copyright (C) 2016 STMicroelectronics (R&D) Limited 5 + * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation; either version 2 of the License, or 10 + * (at your option) any later version. 11 + */ 12 + 13 + #ifndef __STMMAC_PCS_H__ 14 + #define __STMMAC_PCS_H__ 15 + 16 + #include <linux/slab.h> 17 + #include <linux/io.h> 18 + #include "common.h" 19 + 20 + /* PCS registers (AN/TBI/SGMII/RGMII) offsets */ 21 + #define GMAC_AN_CTRL(x) (x) /* AN control */ 22 + #define GMAC_AN_STATUS(x) (x + 0x4) /* AN status */ 23 + #define GMAC_ANE_ADV(x) (x + 0x8) /* ANE Advertisement */ 24 + #define GMAC_ANE_LPA(x) (x + 0xc) /* ANE link partener ability */ 25 + #define GMAC_ANE_EXP(x) (x + 0x10) /* ANE expansion */ 26 + #define GMAC_TBI(x) (x + 0x14) /* TBI extend status */ 27 + 28 + /* AN Configuration defines */ 29 + #define GMAC_AN_CTRL_RAN BIT(9) /* Restart Auto-Negotiation */ 30 + #define GMAC_AN_CTRL_ANE BIT(12) /* Auto-Negotiation Enable */ 31 + #define GMAC_AN_CTRL_ELE BIT(14) /* External Loopback Enable */ 32 + #define GMAC_AN_CTRL_ECD BIT(16) /* Enable Comma Detect */ 33 + #define GMAC_AN_CTRL_LR BIT(17) /* Lock to Reference */ 34 + #define GMAC_AN_CTRL_SGMRAL BIT(18) /* SGMII RAL Control */ 35 + 36 + /* AN Status defines */ 37 + #define GMAC_AN_STATUS_LS BIT(2) /* Link Status 0:down 1:up */ 38 + #define GMAC_AN_STATUS_ANA BIT(3) /* Auto-Negotiation Ability */ 39 + #define GMAC_AN_STATUS_ANC BIT(5) /* Auto-Negotiation Complete */ 40 + #define GMAC_AN_STATUS_ES BIT(8) /* Extended Status */ 41 + 42 + /* ADV and LPA defines */ 43 + #define GMAC_ANE_FD BIT(5) 44 + #define GMAC_ANE_HD BIT(6) 45 + #define GMAC_ANE_PSE GENMASK(8, 7) 46 + #define GMAC_ANE_PSE_SHIFT 7 47 + #define GMAC_ANE_RFE GENMASK(13, 12) 48 + #define GMAC_ANE_RFE_SHIFT 12 49 + #define GMAC_ANE_ACK BIT(14) 50 + 51 + /** 52 + * dwmac_pcs_isr - TBI, RTBI, or SGMII PHY ISR 53 + * @ioaddr: IO registers pointer 54 + * @reg: Base address of the AN Control Register. 55 + * @intr_status: GMAC core interrupt status 56 + * @x: pointer to log these events as stats 57 + * Description: it is the ISR for PCS events: Auto-Negotiation Completed and 58 + * Link status. 59 + */ 60 + static inline void dwmac_pcs_isr(void __iomem *ioaddr, u32 reg, 61 + unsigned int intr_status, 62 + struct stmmac_extra_stats *x) 63 + { 64 + u32 val = readl(ioaddr + GMAC_AN_STATUS(reg)); 65 + 66 + if (intr_status & PCS_ANE_IRQ) { 67 + x->irq_pcs_ane_n++; 68 + if (val & GMAC_AN_STATUS_ANC) 69 + pr_info("stmmac_pcs: ANE process completed\n"); 70 + } 71 + 72 + if (intr_status & PCS_LINK_IRQ) { 73 + x->irq_pcs_link_n++; 74 + if (val & GMAC_AN_STATUS_LS) 75 + pr_info("stmmac_pcs: Link Up\n"); 76 + else 77 + pr_info("stmmac_pcs: Link Down\n"); 78 + } 79 + } 80 + 81 + /** 82 + * dwmac_rane - To restart ANE 83 + * @ioaddr: IO registers pointer 84 + * @reg: Base address of the AN Control Register. 85 + * @restart: to restart ANE 86 + * Description: this is to just restart the Auto-Negotiation. 87 + */ 88 + static inline void dwmac_rane(void __iomem *ioaddr, u32 reg, bool restart) 89 + { 90 + u32 value = readl(ioaddr + GMAC_AN_CTRL(reg)); 91 + 92 + if (restart) 93 + value |= GMAC_AN_CTRL_RAN; 94 + 95 + writel(value, ioaddr + GMAC_AN_CTRL(reg)); 96 + } 97 + 98 + /** 99 + * dwmac_ctrl_ane - To program the AN Control Register. 100 + * @ioaddr: IO registers pointer 101 + * @reg: Base address of the AN Control Register. 102 + * @ane: to enable the auto-negotiation 103 + * @srgmi_ral: to manage MAC-2-MAC SGMII connections. 104 + * @loopback: to cause the PHY to loopback tx data into rx path. 105 + * Description: this is the main function to configure the AN control register 106 + * and init the ANE, select loopback (usually for debugging purpose) and 107 + * configure SGMII RAL. 108 + */ 109 + static inline void dwmac_ctrl_ane(void __iomem *ioaddr, u32 reg, bool ane, 110 + bool srgmi_ral, bool loopback) 111 + { 112 + u32 value = readl(ioaddr + GMAC_AN_CTRL(reg)); 113 + 114 + /* Enable and restart the Auto-Negotiation */ 115 + if (ane) 116 + value |= GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_RAN; 117 + 118 + /* In case of MAC-2-MAC connection, block is configured to operate 119 + * according to MAC conf register. 120 + */ 121 + if (srgmi_ral) 122 + value |= GMAC_AN_CTRL_SGMRAL; 123 + 124 + if (loopback) 125 + value |= GMAC_AN_CTRL_ELE; 126 + 127 + writel(value, ioaddr + GMAC_AN_CTRL(reg)); 128 + } 129 + 130 + /** 131 + * dwmac_get_adv_lp - Get ADV and LP cap 132 + * @ioaddr: IO registers pointer 133 + * @reg: Base address of the AN Control Register. 134 + * @adv_lp: structure to store the adv,lp status 135 + * Description: this is to expose the ANE advertisement and Link partner ability 136 + * status to ethtool support. 137 + */ 138 + static inline void dwmac_get_adv_lp(void __iomem *ioaddr, u32 reg, 139 + struct rgmii_adv *adv_lp) 140 + { 141 + u32 value = readl(ioaddr + GMAC_ANE_ADV(reg)); 142 + 143 + if (value & GMAC_ANE_FD) 144 + adv_lp->duplex = DUPLEX_FULL; 145 + if (value & GMAC_ANE_HD) 146 + adv_lp->duplex |= DUPLEX_HALF; 147 + 148 + adv_lp->pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; 149 + 150 + value = readl(ioaddr + GMAC_ANE_LPA(reg)); 151 + 152 + if (value & GMAC_ANE_FD) 153 + adv_lp->lp_duplex = DUPLEX_FULL; 154 + if (value & GMAC_ANE_HD) 155 + adv_lp->lp_duplex = DUPLEX_HALF; 156 + 157 + adv_lp->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; 158 + } 159 + #endif /* __STMMAC_PCS_H__ */