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

Configure Feed

Select the types of activity you want to include in your feed.

phy: Add RGMII support on lan966x

The serdes driver contains also a mux to decide which interface type to
use. Currently the driver supports GMII/SGMII/QSGMII and partially RGMII.
As it doesn't support all the other RGMII interfaces like
RGMII_TXID/RXID/ID and it could run only at 1G.
Therefore extend this for all the other speeds(10/100) and also allow
the other interfaces.

Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Link: https://lore.kernel.org/r/20220901121455.245103-1-horatiu.vultur@microchip.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Horatiu Vultur and committed by
Vinod Koul
b0131107 f340ed86

+129 -12
+87 -12
drivers/phy/microchip/lan966x_serdes.c
··· 42 42 #define SERDES_MUX_QSGMII(i, p, m, c) \ 43 43 SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_QSGMII, m, c) 44 44 #define SERDES_MUX_RGMII(i, p, m, c) \ 45 - SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII, m, c) 45 + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII, m, c), \ 46 + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_TXID, m, c), \ 47 + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_RXID, m, c), \ 48 + SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_ID, m, c) 46 49 47 50 static void lan_rmw_(u32 val, u32 mask, void __iomem *mem, u32 offset) 48 51 { ··· 97 94 HSIO_HW_CFG_SD6G_1_CFG_SET(1)), 98 95 99 96 SERDES_MUX_RGMII(RGMII(0), 2, HSIO_HW_CFG_RGMII_0_CFG | 100 - HSIO_HW_CFG_RGMII_ENA, 101 - HSIO_HW_CFG_RGMII_0_CFG_SET(BIT(0)) | 102 - HSIO_HW_CFG_RGMII_ENA_SET(BIT(0))), 97 + HSIO_HW_CFG_RGMII_ENA | 98 + HSIO_HW_CFG_GMII_ENA, 99 + HSIO_HW_CFG_RGMII_0_CFG_SET(0) | 100 + HSIO_HW_CFG_RGMII_ENA_SET(BIT(0)) | 101 + HSIO_HW_CFG_GMII_ENA_SET(BIT(2))), 103 102 SERDES_MUX_RGMII(RGMII(1), 3, HSIO_HW_CFG_RGMII_1_CFG | 104 - HSIO_HW_CFG_RGMII_ENA, 105 - HSIO_HW_CFG_RGMII_1_CFG_SET(BIT(0)) | 106 - HSIO_HW_CFG_RGMII_ENA_SET(BIT(1))), 103 + HSIO_HW_CFG_RGMII_ENA | 104 + HSIO_HW_CFG_GMII_ENA, 105 + HSIO_HW_CFG_RGMII_1_CFG_SET(0) | 106 + HSIO_HW_CFG_RGMII_ENA_SET(BIT(1)) | 107 + HSIO_HW_CFG_GMII_ENA_SET(BIT(3))), 107 108 SERDES_MUX_RGMII(RGMII(0), 5, HSIO_HW_CFG_RGMII_0_CFG | 108 - HSIO_HW_CFG_RGMII_ENA, 109 + HSIO_HW_CFG_RGMII_ENA | 110 + HSIO_HW_CFG_GMII_ENA, 109 111 HSIO_HW_CFG_RGMII_0_CFG_SET(BIT(0)) | 110 - HSIO_HW_CFG_RGMII_ENA_SET(BIT(0))), 112 + HSIO_HW_CFG_RGMII_ENA_SET(BIT(0)) | 113 + HSIO_HW_CFG_GMII_ENA_SET(BIT(5))), 111 114 SERDES_MUX_RGMII(RGMII(1), 6, HSIO_HW_CFG_RGMII_1_CFG | 112 - HSIO_HW_CFG_RGMII_ENA, 115 + HSIO_HW_CFG_RGMII_ENA | 116 + HSIO_HW_CFG_GMII_ENA, 113 117 HSIO_HW_CFG_RGMII_1_CFG_SET(BIT(0)) | 114 - HSIO_HW_CFG_RGMII_ENA_SET(BIT(1))), 118 + HSIO_HW_CFG_RGMII_ENA_SET(BIT(1)) | 119 + HSIO_HW_CFG_GMII_ENA_SET(BIT(6))), 115 120 }; 116 121 117 122 struct serdes_ctrl { ··· 393 382 return lan966x_sd6g40_setup_lane(macro, conf, idx); 394 383 } 395 384 385 + static int lan966x_rgmii_setup(struct serdes_macro *macro, u32 idx, int mode) 386 + { 387 + bool tx_delay = false; 388 + bool rx_delay = false; 389 + 390 + /* Configure RGMII */ 391 + lan_rmw(HSIO_RGMII_CFG_RGMII_RX_RST_SET(0) | 392 + HSIO_RGMII_CFG_RGMII_TX_RST_SET(0) | 393 + HSIO_RGMII_CFG_TX_CLK_CFG_SET(macro->speed == SPEED_1000 ? 1 : 394 + macro->speed == SPEED_100 ? 2 : 395 + macro->speed == SPEED_10 ? 3 : 0), 396 + HSIO_RGMII_CFG_RGMII_RX_RST | 397 + HSIO_RGMII_CFG_RGMII_TX_RST | 398 + HSIO_RGMII_CFG_TX_CLK_CFG, 399 + macro->ctrl->regs, HSIO_RGMII_CFG(idx)); 400 + 401 + if (mode == PHY_INTERFACE_MODE_RGMII || 402 + mode == PHY_INTERFACE_MODE_RGMII_TXID) 403 + rx_delay = true; 404 + 405 + if (mode == PHY_INTERFACE_MODE_RGMII || 406 + mode == PHY_INTERFACE_MODE_RGMII_RXID) 407 + tx_delay = true; 408 + 409 + /* Setup DLL configuration */ 410 + lan_rmw(HSIO_DLL_CFG_DLL_RST_SET(0) | 411 + HSIO_DLL_CFG_DLL_ENA_SET(rx_delay), 412 + HSIO_DLL_CFG_DLL_RST | 413 + HSIO_DLL_CFG_DLL_ENA, 414 + macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2)); 415 + 416 + lan_rmw(HSIO_DLL_CFG_DELAY_ENA_SET(rx_delay), 417 + HSIO_DLL_CFG_DELAY_ENA, 418 + macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2)); 419 + 420 + lan_rmw(HSIO_DLL_CFG_DLL_RST_SET(0) | 421 + HSIO_DLL_CFG_DLL_ENA_SET(tx_delay), 422 + HSIO_DLL_CFG_DLL_RST | 423 + HSIO_DLL_CFG_DLL_ENA, 424 + macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3)); 425 + 426 + lan_rmw(HSIO_DLL_CFG_DELAY_ENA_SET(tx_delay), 427 + HSIO_DLL_CFG_DELAY_ENA, 428 + macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3)); 429 + 430 + return 0; 431 + } 432 + 433 + static int serdes_set_speed(struct phy *phy, int speed) 434 + { 435 + struct serdes_macro *macro = phy_get_drvdata(phy); 436 + 437 + if (!phy_interface_mode_is_rgmii(macro->mode)) 438 + return 0; 439 + 440 + macro->speed = speed; 441 + lan966x_rgmii_setup(macro, macro->idx - (SERDES6G_MAX + 1), macro->mode); 442 + 443 + return 0; 444 + } 445 + 396 446 static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode) 397 447 { 398 448 struct serdes_macro *macro = phy_get_drvdata(phy); ··· 496 424 macro->mode); 497 425 498 426 if (macro->idx < RGMII_MAX) 499 - return 0; 427 + return lan966x_rgmii_setup(macro, 428 + macro->idx - (SERDES6G_MAX + 1), 429 + macro->mode); 500 430 501 431 return -EOPNOTSUPP; 502 432 } ··· 508 434 509 435 static const struct phy_ops serdes_ops = { 510 436 .set_mode = serdes_set_mode, 437 + .set_speed = serdes_set_speed, 511 438 .owner = THIS_MODULE, 512 439 }; 513 440
+42
drivers/phy/microchip/lan966x_serdes_regs.h
··· 206 206 #define HSIO_HW_CFG_QSGMII_ENA_GET(x)\ 207 207 FIELD_GET(HSIO_HW_CFG_QSGMII_ENA, x) 208 208 209 + /* HSIO:HW_CFGSTAT:RGMII_CFG */ 210 + #define HSIO_RGMII_CFG(r) __REG(TARGET_HSIO, 0, 1, 104, 0, 1, 52, 20, r, 2, 4) 211 + 212 + #define HSIO_RGMII_CFG_TX_CLK_CFG GENMASK(4, 2) 213 + #define HSIO_RGMII_CFG_TX_CLK_CFG_SET(x)\ 214 + FIELD_PREP(HSIO_RGMII_CFG_TX_CLK_CFG, x) 215 + #define HSIO_RGMII_CFG_TX_CLK_CFG_GET(x)\ 216 + FIELD_GET(HSIO_RGMII_CFG_TX_CLK_CFG, x) 217 + 218 + #define HSIO_RGMII_CFG_RGMII_TX_RST BIT(1) 219 + #define HSIO_RGMII_CFG_RGMII_TX_RST_SET(x)\ 220 + FIELD_PREP(HSIO_RGMII_CFG_RGMII_TX_RST, x) 221 + #define HSIO_RGMII_CFG_RGMII_TX_RST_GET(x)\ 222 + FIELD_GET(HSIO_RGMII_CFG_RGMII_TX_RST, x) 223 + 224 + #define HSIO_RGMII_CFG_RGMII_RX_RST BIT(0) 225 + #define HSIO_RGMII_CFG_RGMII_RX_RST_SET(x)\ 226 + FIELD_PREP(HSIO_RGMII_CFG_RGMII_RX_RST, x) 227 + #define HSIO_RGMII_CFG_RGMII_RX_RST_GET(x)\ 228 + FIELD_GET(HSIO_RGMII_CFG_RGMII_RX_RST, x) 229 + 230 + /* HSIO:HW_CFGSTAT:DLL_CFG */ 231 + #define HSIO_DLL_CFG(r) __REG(TARGET_HSIO, 0, 1, 104, 0, 1, 52, 36, r, 4, 4) 232 + 233 + #define HSIO_DLL_CFG_DELAY_ENA BIT(2) 234 + #define HSIO_DLL_CFG_DELAY_ENA_SET(x)\ 235 + FIELD_PREP(HSIO_DLL_CFG_DELAY_ENA, x) 236 + #define HSIO_DLL_CFG_DELAY_ENA_GET(x)\ 237 + FIELD_GET(HSIO_DLL_CFG_DELAY_ENA, x) 238 + 239 + #define HSIO_DLL_CFG_DLL_ENA BIT(1) 240 + #define HSIO_DLL_CFG_DLL_ENA_SET(x)\ 241 + FIELD_PREP(HSIO_DLL_CFG_DLL_ENA, x) 242 + #define HSIO_DLL_CFG_DLL_ENA_GET(x)\ 243 + FIELD_GET(HSIO_DLL_CFG_DLL_ENA, x) 244 + 245 + #define HSIO_DLL_CFG_DLL_RST BIT(0) 246 + #define HSIO_DLL_CFG_DLL_RST_SET(x)\ 247 + FIELD_PREP(HSIO_DLL_CFG_DLL_RST, x) 248 + #define HSIO_DLL_CFG_DLL_RST_GET(x)\ 249 + FIELD_GET(HSIO_DLL_CFG_DLL_RST, x) 250 + 209 251 #endif /* _LAN966X_HSIO_REGS_H_ */