|
101 | 101 | /* RGMIIDCTL bits */
|
102 | 102 | #define DP83867_RGMII_TX_CLK_DELAY_MAX 0xf
|
103 | 103 | #define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4
|
| 104 | +#define DP83867_RGMII_TX_CLK_DELAY_INV (DP83867_RGMII_TX_CLK_DELAY_MAX + 1) |
104 | 105 | #define DP83867_RGMII_RX_CLK_DELAY_MAX 0xf
|
105 | 106 | #define DP83867_RGMII_RX_CLK_DELAY_SHIFT 0
|
| 107 | +#define DP83867_RGMII_RX_CLK_DELAY_INV (DP83867_RGMII_RX_CLK_DELAY_MAX + 1) |
| 108 | + |
106 | 109 |
|
107 | 110 | /* IO_MUX_CFG bits */
|
108 | 111 | #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MASK 0x1f
|
@@ -294,6 +297,48 @@ static int dp83867_config_port_mirroring(struct phy_device *phydev)
|
294 | 297 | return 0;
|
295 | 298 | }
|
296 | 299 |
|
| 300 | +static int dp83867_verify_rgmii_cfg(struct phy_device *phydev) |
| 301 | +{ |
| 302 | + struct dp83867_private *dp83867 = phydev->priv; |
| 303 | + |
| 304 | + /* Existing behavior was to use default pin strapping delay in rgmii |
| 305 | + * mode, but rgmii should have meant no delay. Warn existing users. |
| 306 | + */ |
| 307 | + if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { |
| 308 | + const u16 val = phy_read_mmd(phydev, DP83867_DEVADDR, |
| 309 | + DP83867_STRAP_STS2); |
| 310 | + const u16 txskew = (val & DP83867_STRAP_STS2_CLK_SKEW_TX_MASK) >> |
| 311 | + DP83867_STRAP_STS2_CLK_SKEW_TX_SHIFT; |
| 312 | + const u16 rxskew = (val & DP83867_STRAP_STS2_CLK_SKEW_RX_MASK) >> |
| 313 | + DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT; |
| 314 | + |
| 315 | + if (txskew != DP83867_STRAP_STS2_CLK_SKEW_NONE || |
| 316 | + rxskew != DP83867_STRAP_STS2_CLK_SKEW_NONE) |
| 317 | + phydev_warn(phydev, |
| 318 | + "PHY has delays via pin strapping, but phy-mode = 'rgmii'\n" |
| 319 | + "Should be 'rgmii-id' to use internal delays txskew:%x rxskew:%x\n", |
| 320 | + txskew, rxskew); |
| 321 | + } |
| 322 | + |
| 323 | + /* RX delay *must* be specified if internal delay of RX is used. */ |
| 324 | + if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || |
| 325 | + phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) && |
| 326 | + dp83867->rx_id_delay == DP83867_RGMII_RX_CLK_DELAY_INV) { |
| 327 | + phydev_err(phydev, "ti,rx-internal-delay must be specified\n"); |
| 328 | + return -EINVAL; |
| 329 | + } |
| 330 | + |
| 331 | + /* TX delay *must* be specified if internal delay of TX is used. */ |
| 332 | + if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || |
| 333 | + phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) && |
| 334 | + dp83867->tx_id_delay == DP83867_RGMII_TX_CLK_DELAY_INV) { |
| 335 | + phydev_err(phydev, "ti,tx-internal-delay must be specified\n"); |
| 336 | + return -EINVAL; |
| 337 | + } |
| 338 | + |
| 339 | + return 0; |
| 340 | +} |
| 341 | + |
297 | 342 | #ifdef CONFIG_OF_MDIO
|
298 | 343 | static int dp83867_of_init(struct phy_device *phydev)
|
299 | 344 | {
|
@@ -335,55 +380,25 @@ static int dp83867_of_init(struct phy_device *phydev)
|
335 | 380 | dp83867->sgmii_ref_clk_en = of_property_read_bool(of_node,
|
336 | 381 | "ti,sgmii-ref-clock-output-enable");
|
337 | 382 |
|
338 |
| - /* Existing behavior was to use default pin strapping delay in rgmii |
339 |
| - * mode, but rgmii should have meant no delay. Warn existing users. |
340 |
| - */ |
341 |
| - if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { |
342 |
| - const u16 val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_STRAP_STS2); |
343 |
| - const u16 txskew = (val & DP83867_STRAP_STS2_CLK_SKEW_TX_MASK) >> |
344 |
| - DP83867_STRAP_STS2_CLK_SKEW_TX_SHIFT; |
345 |
| - const u16 rxskew = (val & DP83867_STRAP_STS2_CLK_SKEW_RX_MASK) >> |
346 |
| - DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT; |
347 | 383 |
|
348 |
| - if (txskew != DP83867_STRAP_STS2_CLK_SKEW_NONE || |
349 |
| - rxskew != DP83867_STRAP_STS2_CLK_SKEW_NONE) |
350 |
| - phydev_warn(phydev, |
351 |
| - "PHY has delays via pin strapping, but phy-mode = 'rgmii'\n" |
352 |
| - "Should be 'rgmii-id' to use internal delays\n"); |
353 |
| - } |
354 |
| - |
355 |
| - /* RX delay *must* be specified if internal delay of RX is used. */ |
356 |
| - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || |
357 |
| - phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { |
358 |
| - ret = of_property_read_u32(of_node, "ti,rx-internal-delay", |
359 |
| - &dp83867->rx_id_delay); |
360 |
| - if (ret) { |
361 |
| - phydev_err(phydev, "ti,rx-internal-delay must be specified\n"); |
362 |
| - return ret; |
363 |
| - } |
364 |
| - if (dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) { |
365 |
| - phydev_err(phydev, |
366 |
| - "ti,rx-internal-delay value of %u out of range\n", |
367 |
| - dp83867->rx_id_delay); |
368 |
| - return -EINVAL; |
369 |
| - } |
| 384 | + dp83867->rx_id_delay = DP83867_RGMII_RX_CLK_DELAY_INV; |
| 385 | + ret = of_property_read_u32(of_node, "ti,rx-internal-delay", |
| 386 | + &dp83867->rx_id_delay); |
| 387 | + if (!ret && dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) { |
| 388 | + phydev_err(phydev, |
| 389 | + "ti,rx-internal-delay value of %u out of range\n", |
| 390 | + dp83867->rx_id_delay); |
| 391 | + return -EINVAL; |
370 | 392 | }
|
371 | 393 |
|
372 |
| - /* TX delay *must* be specified if internal delay of RX is used. */ |
373 |
| - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || |
374 |
| - phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { |
375 |
| - ret = of_property_read_u32(of_node, "ti,tx-internal-delay", |
376 |
| - &dp83867->tx_id_delay); |
377 |
| - if (ret) { |
378 |
| - phydev_err(phydev, "ti,tx-internal-delay must be specified\n"); |
379 |
| - return ret; |
380 |
| - } |
381 |
| - if (dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) { |
382 |
| - phydev_err(phydev, |
383 |
| - "ti,tx-internal-delay value of %u out of range\n", |
384 |
| - dp83867->tx_id_delay); |
385 |
| - return -EINVAL; |
386 |
| - } |
| 394 | + dp83867->tx_id_delay = DP83867_RGMII_TX_CLK_DELAY_INV; |
| 395 | + ret = of_property_read_u32(of_node, "ti,tx-internal-delay", |
| 396 | + &dp83867->tx_id_delay); |
| 397 | + if (!ret && dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) { |
| 398 | + phydev_err(phydev, |
| 399 | + "ti,tx-internal-delay value of %u out of range\n", |
| 400 | + dp83867->tx_id_delay); |
| 401 | + return -EINVAL; |
387 | 402 | }
|
388 | 403 |
|
389 | 404 | if (of_property_read_bool(of_node, "enet-phy-lane-swap"))
|
@@ -434,6 +449,10 @@ static int dp83867_config_init(struct phy_device *phydev)
|
434 | 449 | int ret, val, bs;
|
435 | 450 | u16 delay;
|
436 | 451 |
|
| 452 | + ret = dp83867_verify_rgmii_cfg(phydev); |
| 453 | + if (ret) |
| 454 | + return ret; |
| 455 | + |
437 | 456 | /* RX_DV/RX_CTRL strapped in mode 1 or mode 2 workaround */
|
438 | 457 | if (dp83867->rxctrl_strap_quirk)
|
439 | 458 | phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
|
@@ -485,8 +504,12 @@ static int dp83867_config_init(struct phy_device *phydev)
|
485 | 504 |
|
486 | 505 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL, val);
|
487 | 506 |
|
488 |
| - delay = (dp83867->rx_id_delay | |
489 |
| - (dp83867->tx_id_delay << DP83867_RGMII_TX_CLK_DELAY_SHIFT)); |
| 507 | + delay = 0; |
| 508 | + if (dp83867->rx_id_delay != DP83867_RGMII_RX_CLK_DELAY_INV) |
| 509 | + delay |= dp83867->rx_id_delay; |
| 510 | + if (dp83867->tx_id_delay != DP83867_RGMII_TX_CLK_DELAY_INV) |
| 511 | + delay |= dp83867->tx_id_delay << |
| 512 | + DP83867_RGMII_TX_CLK_DELAY_SHIFT; |
490 | 513 |
|
491 | 514 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIIDCTL,
|
492 | 515 | delay);
|
|
0 commit comments