Commit a6f51f2e authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by David S. Miller

ravb: Add support for explicit internal clock delay configuration

Some EtherAVB variants support internal clock delay configuration, which
can add larger delays than the delays that are typically supported by
the PHY (using an "rgmii-*id" PHY mode, and/or "[rt]xc-skew-ps"
properties).

Historically, the EtherAVB driver configured these delays based on the
"rgmii-*id" PHY mode.  This caused issues with PHY drivers that
implement PHY internal delays properly[1].  Hence a backwards-compatible
workaround was added by masking the PHY mode[2].

Add proper support for explicit configuration of the MAC internal clock
delays using the new "[rt]x-internal-delay-ps" properties.
Fall back to the old handling if none of these properties is present.

[1] Commit bcf3440c ("net: phy: micrel: add phy-mode support for
    the KSZ9031 PHY")
[2] Commit 9b23203c ("ravb: Mask PHY mode to avoid inserting
    delays twice").
Signed-off-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: default avatarSergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ce19a9eb
...@@ -1038,6 +1038,7 @@ struct ravb_private { ...@@ -1038,6 +1038,7 @@ struct ravb_private {
unsigned wol_enabled:1; unsigned wol_enabled:1;
unsigned rxcidm:1; /* RX Clock Internal Delay Mode */ unsigned rxcidm:1; /* RX Clock Internal Delay Mode */
unsigned txcidm:1; /* TX Clock Internal Delay Mode */ unsigned txcidm:1; /* TX Clock Internal Delay Mode */
unsigned rgmii_override:1; /* Deprecated rgmii-*id behavior */
int num_tx_desc; /* TX descriptors per packet */ int num_tx_desc; /* TX descriptors per packet */
}; };
......
...@@ -1034,11 +1034,8 @@ static int ravb_phy_init(struct net_device *ndev) ...@@ -1034,11 +1034,8 @@ static int ravb_phy_init(struct net_device *ndev)
pn = of_node_get(np); pn = of_node_get(np);
} }
iface = priv->phy_interface; iface = priv->rgmii_override ? PHY_INTERFACE_MODE_RGMII
if (priv->chip_id != RCAR_GEN2 && phy_interface_mode_is_rgmii(iface)) { : priv->phy_interface;
/* ravb_set_delay_mode() takes care of internal delay mode */
iface = PHY_INTERFACE_MODE_RGMII;
}
phydev = of_phy_connect(ndev, pn, ravb_adjust_link, 0, iface); phydev = of_phy_connect(ndev, pn, ravb_adjust_link, 0, iface);
of_node_put(pn); of_node_put(pn);
if (!phydev) { if (!phydev) {
...@@ -1999,20 +1996,41 @@ static const struct soc_device_attribute ravb_delay_mode_quirk_match[] = { ...@@ -1999,20 +1996,41 @@ static const struct soc_device_attribute ravb_delay_mode_quirk_match[] = {
}; };
/* Set tx and rx clock internal delay modes */ /* Set tx and rx clock internal delay modes */
static void ravb_parse_delay_mode(struct net_device *ndev) static void ravb_parse_delay_mode(struct device_node *np, struct net_device *ndev)
{ {
struct ravb_private *priv = netdev_priv(ndev); struct ravb_private *priv = netdev_priv(ndev);
bool explicit_delay = false;
u32 delay;
if (!of_property_read_u32(np, "rx-internal-delay-ps", &delay)) {
/* Valid values are 0 and 1800, according to DT bindings */
priv->rxcidm = !!delay;
explicit_delay = true;
}
if (!of_property_read_u32(np, "tx-internal-delay-ps", &delay)) {
/* Valid values are 0 and 2000, according to DT bindings */
priv->txcidm = !!delay;
explicit_delay = true;
}
if (explicit_delay)
return;
/* Fall back to legacy rgmii-*id behavior */
if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID ||
priv->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) priv->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) {
priv->rxcidm = 1; priv->rxcidm = 1;
priv->rgmii_override = 1;
}
if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID ||
priv->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) { priv->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) {
if (!WARN(soc_device_match(ravb_delay_mode_quirk_match), if (!WARN(soc_device_match(ravb_delay_mode_quirk_match),
"phy-mode %s requires TX clock internal delay mode which is not supported by this hardware revision. Please update device tree", "phy-mode %s requires TX clock internal delay mode which is not supported by this hardware revision. Please update device tree",
phy_modes(priv->phy_interface))) phy_modes(priv->phy_interface))) {
priv->txcidm = 1; priv->txcidm = 1;
priv->rgmii_override = 1;
}
} }
} }
...@@ -2158,7 +2176,7 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2158,7 +2176,7 @@ static int ravb_probe(struct platform_device *pdev)
ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI); ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
if (priv->chip_id != RCAR_GEN2) { if (priv->chip_id != RCAR_GEN2) {
ravb_parse_delay_mode(ndev); ravb_parse_delay_mode(np, ndev);
ravb_set_delay_mode(ndev); ravb_set_delay_mode(ndev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment