Commit 5d645df9 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: sja1105: determine PHY/MAC role from PHY interface type

Now that both RevMII as well as RevRMII exist, we can deprecate the
sja1105,role-mac and sja1105,role-phy properties and simply let the user
select that a port operates in MII PHY role by using
	phy-mode = "rev-mii";
or in RMII PHY role by using
	phy-mode = "rev-rmii";

There are no fixed-link MII or RMII properties in mainline device trees,
and the setup itself is fairly uncommon, so there shouldn't be risks of
breaking compatibility.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 29afb83a
...@@ -19,37 +19,6 @@ Required properties: ...@@ -19,37 +19,6 @@ Required properties:
of support for RGMII internal delays (supported on P/Q/R/S, but not on of support for RGMII internal delays (supported on P/Q/R/S, but not on
E/T). E/T).
Optional properties:
- sja1105,role-mac:
- sja1105,role-phy:
Boolean properties that can be assigned under each port node. By
default (unless otherwise specified) a port is configured as MAC if it
is driving a PHY (phy-handle is present) or as PHY if it is PHY-less
(fixed-link specified, presumably because it is connected to a MAC).
The effect of this property (in either its implicit or explicit form)
is:
- In the case of MII or RMII it specifies whether the SJA1105 port is a
clock source or sink for this interface (not applicable for RGMII
where there is a Tx and an Rx clock).
- In the case of RGMII it affects the behavior regarding internal
delays:
1. If sja1105,role-mac is specified, and the phy-mode property is one
of "rgmii-id", "rgmii-txid" or "rgmii-rxid", then the entity
designated to apply the delay/clock skew necessary for RGMII
is the PHY. The SJA1105 MAC does not apply any internal delays.
2. If sja1105,role-phy is specified, and the phy-mode property is one
of the above, the designated entity to apply the internal delays
is the SJA1105 MAC (if hardware-supported). This is only supported
by the second-generation (P/Q/R/S) hardware. On a first-generation
E or T device, it is an error to specify an RGMII phy-mode other
than "rgmii" for a port that is in fixed-link mode. In that case,
the clock skew must either be added by the MAC at the other end of
the fixed-link, or by PCB serpentine traces on the board.
These properties are required, for example, in the case where SJA1105
ports are at both ends of a MII/RMII PHY-less setup. One end would need
to have sja1105,role-mac, while the other sja1105,role-phy.
See Documentation/devicetree/bindings/net/dsa/dsa.txt for the list of standard See Documentation/devicetree/bindings/net/dsa/dsa.txt for the list of standard
DSA required and optional properties. DSA required and optional properties.
...@@ -87,7 +56,6 @@ arch/arm/boot/dts/ls1021a-tsn.dts: ...@@ -87,7 +56,6 @@ arch/arm/boot/dts/ls1021a-tsn.dts:
phy-handle = <&rgmii_phy6>; phy-handle = <&rgmii_phy6>;
phy-mode = "rgmii-id"; phy-mode = "rgmii-id";
reg = <0>; reg = <0>;
/* Implicit "sja1105,role-mac;" */
}; };
port@1 { port@1 {
/* ETH2 written on chassis */ /* ETH2 written on chassis */
...@@ -95,7 +63,6 @@ arch/arm/boot/dts/ls1021a-tsn.dts: ...@@ -95,7 +63,6 @@ arch/arm/boot/dts/ls1021a-tsn.dts:
phy-handle = <&rgmii_phy3>; phy-handle = <&rgmii_phy3>;
phy-mode = "rgmii-id"; phy-mode = "rgmii-id";
reg = <1>; reg = <1>;
/* Implicit "sja1105,role-mac;" */
}; };
port@2 { port@2 {
/* ETH3 written on chassis */ /* ETH3 written on chassis */
...@@ -103,7 +70,6 @@ arch/arm/boot/dts/ls1021a-tsn.dts: ...@@ -103,7 +70,6 @@ arch/arm/boot/dts/ls1021a-tsn.dts:
phy-handle = <&rgmii_phy4>; phy-handle = <&rgmii_phy4>;
phy-mode = "rgmii-id"; phy-mode = "rgmii-id";
reg = <2>; reg = <2>;
/* Implicit "sja1105,role-mac;" */
}; };
port@3 { port@3 {
/* ETH4 written on chassis */ /* ETH4 written on chassis */
...@@ -111,14 +77,13 @@ arch/arm/boot/dts/ls1021a-tsn.dts: ...@@ -111,14 +77,13 @@ arch/arm/boot/dts/ls1021a-tsn.dts:
label = "swp4"; label = "swp4";
phy-mode = "rgmii-id"; phy-mode = "rgmii-id";
reg = <3>; reg = <3>;
/* Implicit "sja1105,role-mac;" */
}; };
port@4 { port@4 {
/* Internal port connected to eth2 */ /* Internal port connected to eth2 */
ethernet = <&enet2>; ethernet = <&enet2>;
phy-mode = "rgmii"; phy-mode = "rgmii";
reg = <4>; reg = <4>;
/* Implicit "sja1105,role-phy;" */
fixed-link { fixed-link {
speed = <1000>; speed = <1000>;
full-duplex; full-duplex;
......
...@@ -57,14 +57,6 @@ static bool sja1105_can_forward(struct sja1105_l2_forwarding_entry *l2_fwd, ...@@ -57,14 +57,6 @@ static bool sja1105_can_forward(struct sja1105_l2_forwarding_entry *l2_fwd,
return !!(l2_fwd[from].reach_port & BIT(to)); return !!(l2_fwd[from].reach_port & BIT(to));
} }
/* Structure used to temporarily transport device tree
* settings into sja1105_setup
*/
struct sja1105_dt_port {
phy_interface_t phy_mode;
sja1105_mii_role_t role;
};
static int sja1105_init_mac_settings(struct sja1105_private *priv) static int sja1105_init_mac_settings(struct sja1105_private *priv)
{ {
struct sja1105_mac_config_entry default_mac = { struct sja1105_mac_config_entry default_mac = {
...@@ -143,8 +135,7 @@ static int sja1105_init_mac_settings(struct sja1105_private *priv) ...@@ -143,8 +135,7 @@ static int sja1105_init_mac_settings(struct sja1105_private *priv)
return 0; return 0;
} }
static int sja1105_init_mii_settings(struct sja1105_private *priv, static int sja1105_init_mii_settings(struct sja1105_private *priv)
struct sja1105_dt_port *ports)
{ {
struct device *dev = &priv->spidev->dev; struct device *dev = &priv->spidev->dev;
struct sja1105_xmii_params_entry *mii; struct sja1105_xmii_params_entry *mii;
...@@ -171,16 +162,24 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv, ...@@ -171,16 +162,24 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv,
mii = table->entries; mii = table->entries;
for (i = 0; i < ds->num_ports; i++) { for (i = 0; i < ds->num_ports; i++) {
sja1105_mii_role_t role = XMII_MAC;
if (dsa_is_unused_port(priv->ds, i)) if (dsa_is_unused_port(priv->ds, i))
continue; continue;
switch (ports[i].phy_mode) { switch (priv->phy_mode[i]) {
case PHY_INTERFACE_MODE_REVMII:
role = XMII_PHY;
fallthrough;
case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_MII:
if (!priv->info->supports_mii[i]) if (!priv->info->supports_mii[i])
goto unsupported; goto unsupported;
mii->xmii_mode[i] = XMII_MODE_MII; mii->xmii_mode[i] = XMII_MODE_MII;
break; break;
case PHY_INTERFACE_MODE_REVRMII:
role = XMII_PHY;
fallthrough;
case PHY_INTERFACE_MODE_RMII: case PHY_INTERFACE_MODE_RMII:
if (!priv->info->supports_rmii[i]) if (!priv->info->supports_rmii[i])
goto unsupported; goto unsupported;
...@@ -211,24 +210,11 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv, ...@@ -211,24 +210,11 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv,
unsupported: unsupported:
default: default:
dev_err(dev, "Unsupported PHY mode %s on port %d!\n", dev_err(dev, "Unsupported PHY mode %s on port %d!\n",
phy_modes(ports[i].phy_mode), i); phy_modes(priv->phy_mode[i]), i);
return -EINVAL; return -EINVAL;
} }
/* Even though the SerDes port is able to drive SGMII autoneg mii->phy_mac[i] = role;
* like a PHY would, from the perspective of the XMII tables,
* the SGMII port should always be put in MAC mode.
* Similarly, RGMII is a symmetric protocol electrically
* speaking, and the 'RGMII PHY' role does not mean anything to
* hardware. Just keep the 'PHY role' notation relevant to the
* driver to mean 'the switch port should apply RGMII delays',
* but unconditionally put the port in the MAC role.
*/
if (ports[i].phy_mode == PHY_INTERFACE_MODE_SGMII ||
phy_interface_mode_is_rgmii(ports[i].phy_mode))
mii->phy_mac[i] = XMII_MAC;
else
mii->phy_mac[i] = ports[i].role;
} }
return 0; return 0;
} }
...@@ -751,8 +737,7 @@ static int sja1105_init_l2_policing(struct sja1105_private *priv) ...@@ -751,8 +737,7 @@ static int sja1105_init_l2_policing(struct sja1105_private *priv)
return 0; return 0;
} }
static int sja1105_static_config_load(struct sja1105_private *priv, static int sja1105_static_config_load(struct sja1105_private *priv)
struct sja1105_dt_port *ports)
{ {
int rc; int rc;
...@@ -767,7 +752,7 @@ static int sja1105_static_config_load(struct sja1105_private *priv, ...@@ -767,7 +752,7 @@ static int sja1105_static_config_load(struct sja1105_private *priv,
rc = sja1105_init_mac_settings(priv); rc = sja1105_init_mac_settings(priv);
if (rc < 0) if (rc < 0)
return rc; return rc;
rc = sja1105_init_mii_settings(priv, ports); rc = sja1105_init_mii_settings(priv);
if (rc < 0) if (rc < 0)
return rc; return rc;
rc = sja1105_init_static_fdb(priv); rc = sja1105_init_static_fdb(priv);
...@@ -824,7 +809,6 @@ static int sja1105_parse_rgmii_delays(struct sja1105_private *priv) ...@@ -824,7 +809,6 @@ static int sja1105_parse_rgmii_delays(struct sja1105_private *priv)
} }
static int sja1105_parse_ports_node(struct sja1105_private *priv, static int sja1105_parse_ports_node(struct sja1105_private *priv,
struct sja1105_dt_port *ports,
struct device_node *ports_node) struct device_node *ports_node)
{ {
struct device *dev = &priv->spidev->dev; struct device *dev = &priv->spidev->dev;
...@@ -853,7 +837,6 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv, ...@@ -853,7 +837,6 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
of_node_put(child); of_node_put(child);
return -ENODEV; return -ENODEV;
} }
ports[index].phy_mode = phy_mode;
phy_node = of_parse_phandle(child, "phy-handle", 0); phy_node = of_parse_phandle(child, "phy-handle", 0);
if (!phy_node) { if (!phy_node) {
...@@ -867,27 +850,17 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv, ...@@ -867,27 +850,17 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
* So it's a fixed link. Default to PHY role. * So it's a fixed link. Default to PHY role.
*/ */
priv->fixed_link[index] = true; priv->fixed_link[index] = true;
ports[index].role = XMII_PHY;
} else { } else {
/* phy-handle present => put port in MAC role */
ports[index].role = XMII_MAC;
of_node_put(phy_node); of_node_put(phy_node);
} }
/* The MAC/PHY role can be overridden with explicit bindings */
if (of_property_read_bool(child, "sja1105,role-mac"))
ports[index].role = XMII_MAC;
else if (of_property_read_bool(child, "sja1105,role-phy"))
ports[index].role = XMII_PHY;
priv->phy_mode[index] = phy_mode; priv->phy_mode[index] = phy_mode;
} }
return 0; return 0;
} }
static int sja1105_parse_dt(struct sja1105_private *priv, static int sja1105_parse_dt(struct sja1105_private *priv)
struct sja1105_dt_port *ports)
{ {
struct device *dev = &priv->spidev->dev; struct device *dev = &priv->spidev->dev;
struct device_node *switch_node = dev->of_node; struct device_node *switch_node = dev->of_node;
...@@ -902,7 +875,7 @@ static int sja1105_parse_dt(struct sja1105_private *priv, ...@@ -902,7 +875,7 @@ static int sja1105_parse_dt(struct sja1105_private *priv,
return -ENODEV; return -ENODEV;
} }
rc = sja1105_parse_ports_node(priv, ports, ports_node); rc = sja1105_parse_ports_node(priv, ports_node);
of_node_put(ports_node); of_node_put(ports_node);
return rc; return rc;
...@@ -3008,11 +2981,10 @@ static const struct dsa_8021q_ops sja1105_dsa_8021q_ops = { ...@@ -3008,11 +2981,10 @@ static const struct dsa_8021q_ops sja1105_dsa_8021q_ops = {
*/ */
static int sja1105_setup(struct dsa_switch *ds) static int sja1105_setup(struct dsa_switch *ds)
{ {
struct sja1105_dt_port ports[SJA1105_MAX_NUM_PORTS];
struct sja1105_private *priv = ds->priv; struct sja1105_private *priv = ds->priv;
int rc; int rc;
rc = sja1105_parse_dt(priv, ports); rc = sja1105_parse_dt(priv);
if (rc < 0) { if (rc < 0) {
dev_err(ds->dev, "Failed to parse DT: %d\n", rc); dev_err(ds->dev, "Failed to parse DT: %d\n", rc);
return rc; return rc;
...@@ -3033,7 +3005,7 @@ static int sja1105_setup(struct dsa_switch *ds) ...@@ -3033,7 +3005,7 @@ static int sja1105_setup(struct dsa_switch *ds)
return rc; return rc;
} }
/* Create and send configuration down to device */ /* Create and send configuration down to device */
rc = sja1105_static_config_load(priv, ports); rc = sja1105_static_config_load(priv);
if (rc < 0) { if (rc < 0) {
dev_err(ds->dev, "Failed to load static config: %d\n", rc); dev_err(ds->dev, "Failed to load static config: %d\n", rc);
goto out_ptp_clock_unregister; goto out_ptp_clock_unregister;
......
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