Skip to content

Commit fafc5db

Browse files
grygoriySdavem330
authored andcommitted
net: phy: dp83867: fix hfs boot in rgmii mode
The commit ef87f7d ("net: phy: dp83867: move dt parsing to probe") causes regression on TI dra71x-evm and dra72x-evm, where DP83867 PHY is used in "rgmii-id" mode - the networking stops working. Unfortunately, it's not enough to just move DT parsing code to .probe() as it depends on phydev->interface value, which is set to correct value abter the .probe() is completed and before calling .config_init(). So, RGMII configuration can't be loaded from DT. To fix and issue - move RGMII validation code to .config_init() - parse RGMII parameters in dp83867_of_init(), but consider them as optional. Fixes: ef87f7d ("net: phy: dp83867: move dt parsing to probe") Signed-off-by: Grygorii Strashko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 51302f7 commit fafc5db

File tree

1 file changed

+71
-48
lines changed

1 file changed

+71
-48
lines changed

drivers/net/phy/dp83867.c

Lines changed: 71 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,11 @@
101101
/* RGMIIDCTL bits */
102102
#define DP83867_RGMII_TX_CLK_DELAY_MAX 0xf
103103
#define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4
104+
#define DP83867_RGMII_TX_CLK_DELAY_INV (DP83867_RGMII_TX_CLK_DELAY_MAX + 1)
104105
#define DP83867_RGMII_RX_CLK_DELAY_MAX 0xf
105106
#define DP83867_RGMII_RX_CLK_DELAY_SHIFT 0
107+
#define DP83867_RGMII_RX_CLK_DELAY_INV (DP83867_RGMII_RX_CLK_DELAY_MAX + 1)
108+
106109

107110
/* IO_MUX_CFG bits */
108111
#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MASK 0x1f
@@ -294,6 +297,48 @@ static int dp83867_config_port_mirroring(struct phy_device *phydev)
294297
return 0;
295298
}
296299

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+
297342
#ifdef CONFIG_OF_MDIO
298343
static int dp83867_of_init(struct phy_device *phydev)
299344
{
@@ -335,55 +380,25 @@ static int dp83867_of_init(struct phy_device *phydev)
335380
dp83867->sgmii_ref_clk_en = of_property_read_bool(of_node,
336381
"ti,sgmii-ref-clock-output-enable");
337382

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;
347383

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;
370392
}
371393

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;
387402
}
388403

389404
if (of_property_read_bool(of_node, "enet-phy-lane-swap"))
@@ -434,6 +449,10 @@ static int dp83867_config_init(struct phy_device *phydev)
434449
int ret, val, bs;
435450
u16 delay;
436451

452+
ret = dp83867_verify_rgmii_cfg(phydev);
453+
if (ret)
454+
return ret;
455+
437456
/* RX_DV/RX_CTRL strapped in mode 1 or mode 2 workaround */
438457
if (dp83867->rxctrl_strap_quirk)
439458
phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
@@ -485,8 +504,12 @@ static int dp83867_config_init(struct phy_device *phydev)
485504

486505
phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL, val);
487506

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;
490513

491514
phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIIDCTL,
492515
delay);

0 commit comments

Comments
 (0)