summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2021-06-07 22:20:18 +0300
committerDavid S. Miller <davem@davemloft.net>2021-06-07 22:20:18 +0300
commit06d6211361ee7ae64145713ce95fa8697b37cc63 (patch)
tree9c9d19be831eb8999a48e66283414651441cd591
parent1a42624aecba438f1d114430a14b640cdfa51c87 (diff)
parent62568bdbe6f6293c955fbd98db15adf7ee6aca1c (diff)
downloadlinux-06d6211361ee7ae64145713ce95fa8697b37cc63.tar.xz
Merge branch 'sja1105-yaml'
Vladimir Oltean says: ==================== Convert NXP SJA1105 DSA driver to YAML This is an attempt to convert the SJA1105 driver to the YAML schema. The SJA1105 driver has some custom device tree properties which caused validation problems in the previous attempt: https://patchwork.kernel.org/project/netdevbpf/patch/20210531234735.1582031-1-olteanv@gmail.com/ So now we are removing them, hoping that this will make the conversion easier to accept. In order to do that, we introduce a new PHY interface type, "reverse RMII", which is like "reverse MII" (aka MII as a PHY) but for the reduced data width version of the protocol. This is a direct replacement for an rmii fixed-link. Now, rmii fixed-link interfaces behave as a MAC, and rev-rmii fixed-link interfaces behave as a PHY. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml89
-rw-r--r--Documentation/devicetree/bindings/net/dsa/sja1105.txt156
-rw-r--r--Documentation/devicetree/bindings/net/ethernet-controller.yaml1
-rw-r--r--drivers/net/dsa/sja1105/sja1105.h1
-rw-r--r--drivers/net/dsa/sja1105/sja1105_main.c92
-rw-r--r--include/linux/phy.h4
6 files changed, 127 insertions, 216 deletions
diff --git a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
new file mode 100644
index 000000000000..d6ac9a0c1b04
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/dsa/nxp,sja1105.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP SJA1105 Automotive Ethernet Switch Family Device Tree Bindings
+
+description:
+ The SJA1105 SPI interface requires a CS-to-CLK time (t2 in UM10944.pdf) of at
+ least one half of t_CLK. At an SPI frequency of 1MHz, this means a minimum
+ cs_sck_delay of 500ns. Ensuring that this SPI timing requirement is observed
+ depends on the SPI bus master driver.
+
+allOf:
+ - $ref: "dsa.yaml#"
+
+maintainers:
+ - Vladimir Oltean <vladimir.oltean@nxp.com>
+
+properties:
+ compatible:
+ enum:
+ - nxp,sja1105e
+ - nxp,sja1105t
+ - nxp,sja1105p
+ - nxp,sja1105q
+ - nxp,sja1105r
+ - nxp,sja1105s
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet-switch@1 {
+ reg = <0x1>;
+ compatible = "nxp,sja1105t";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ phy-handle = <&rgmii_phy6>;
+ phy-mode = "rgmii-id";
+ reg = <0>;
+ };
+
+ port@1 {
+ phy-handle = <&rgmii_phy3>;
+ phy-mode = "rgmii-id";
+ reg = <1>;
+ };
+
+ port@2 {
+ phy-handle = <&rgmii_phy4>;
+ phy-mode = "rgmii-id";
+ reg = <2>;
+ };
+
+ port@3 {
+ phy-mode = "rgmii-id";
+ reg = <3>;
+ };
+
+ port@4 {
+ ethernet = <&enet2>;
+ phy-mode = "rgmii";
+ reg = <4>;
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/net/dsa/sja1105.txt b/Documentation/devicetree/bindings/net/dsa/sja1105.txt
deleted file mode 100644
index 13fd21074d48..000000000000
--- a/Documentation/devicetree/bindings/net/dsa/sja1105.txt
+++ /dev/null
@@ -1,156 +0,0 @@
-NXP SJA1105 switch driver
-=========================
-
-Required properties:
-
-- compatible:
- Must be one of:
- - "nxp,sja1105e"
- - "nxp,sja1105t"
- - "nxp,sja1105p"
- - "nxp,sja1105q"
- - "nxp,sja1105r"
- - "nxp,sja1105s"
-
- Although the device ID could be detected at runtime, explicit bindings
- are required in order to be able to statically check their validity.
- For example, SGMII can only be specified on port 4 of R and S devices,
- and the non-SGMII devices, while pin-compatible, are not equal in terms
- of support for RGMII internal delays (supported on P/Q/R/S, but not on
- 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
-DSA required and optional properties.
-
-Other observations
-------------------
-
-The SJA1105 SPI interface requires a CS-to-CLK time (t2 in UM10944) of at least
-one half of t_CLK. At an SPI frequency of 1MHz, this means a minimum
-cs_sck_delay of 500ns. Ensuring that this SPI timing requirement is observed
-depends on the SPI bus master driver.
-
-Example
--------
-
-Ethernet switch connected via SPI to the host, CPU port wired to enet2:
-
-arch/arm/boot/dts/ls1021a-tsn.dts:
-
-/* SPI controller of the LS1021 */
-&dspi0 {
- sja1105@1 {
- reg = <0x1>;
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "nxp,sja1105t";
- spi-max-frequency = <4000000>;
- fsl,spi-cs-sck-delay = <1000>;
- fsl,spi-sck-cs-delay = <1000>;
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- /* ETH5 written on chassis */
- label = "swp5";
- phy-handle = <&rgmii_phy6>;
- phy-mode = "rgmii-id";
- reg = <0>;
- /* Implicit "sja1105,role-mac;" */
- };
- port@1 {
- /* ETH2 written on chassis */
- label = "swp2";
- phy-handle = <&rgmii_phy3>;
- phy-mode = "rgmii-id";
- reg = <1>;
- /* Implicit "sja1105,role-mac;" */
- };
- port@2 {
- /* ETH3 written on chassis */
- label = "swp3";
- phy-handle = <&rgmii_phy4>;
- phy-mode = "rgmii-id";
- reg = <2>;
- /* Implicit "sja1105,role-mac;" */
- };
- port@3 {
- /* ETH4 written on chassis */
- phy-handle = <&rgmii_phy5>;
- label = "swp4";
- phy-mode = "rgmii-id";
- reg = <3>;
- /* Implicit "sja1105,role-mac;" */
- };
- port@4 {
- /* Internal port connected to eth2 */
- ethernet = <&enet2>;
- phy-mode = "rgmii";
- reg = <4>;
- /* Implicit "sja1105,role-phy;" */
- fixed-link {
- speed = <1000>;
- full-duplex;
- };
- };
- };
- };
-};
-
-/* MDIO controller of the LS1021 */
-&mdio0 {
- /* BCM5464 */
- rgmii_phy3: ethernet-phy@3 {
- reg = <0x3>;
- };
- rgmii_phy4: ethernet-phy@4 {
- reg = <0x4>;
- };
- rgmii_phy5: ethernet-phy@5 {
- reg = <0x5>;
- };
- rgmii_phy6: ethernet-phy@6 {
- reg = <0x6>;
- };
-};
-
-/* Ethernet master port of the LS1021 */
-&enet2 {
- phy-connection-type = "rgmii";
- status = "ok";
- fixed-link {
- speed = <1000>;
- full-duplex;
- };
-};
diff --git a/Documentation/devicetree/bindings/net/ethernet-controller.yaml b/Documentation/devicetree/bindings/net/ethernet-controller.yaml
index e8f04687a3e0..d97b561003ed 100644
--- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml
+++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml
@@ -68,6 +68,7 @@ properties:
- tbi
- rev-mii
- rmii
+ - rev-rmii
# RX and TX delays are added by the MAC when required
- rgmii
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index 867cda832e77..3c66e5945cca 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -226,6 +226,7 @@ struct sja1105_private {
bool rgmii_rx_delay[SJA1105_MAX_NUM_PORTS];
bool rgmii_tx_delay[SJA1105_MAX_NUM_PORTS];
phy_interface_t phy_mode[SJA1105_MAX_NUM_PORTS];
+ bool fixed_link[SJA1105_MAX_NUM_PORTS];
bool best_effort_vlan_filtering;
unsigned long learn_ena;
unsigned long ucast_egress_floods;
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 84edd054781b..cbce6e90dc63 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -57,14 +57,6 @@ static bool sja1105_can_forward(struct sja1105_l2_forwarding_entry *l2_fwd,
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)
{
struct sja1105_mac_config_entry default_mac = {
@@ -143,8 +135,7 @@ static int sja1105_init_mac_settings(struct sja1105_private *priv)
return 0;
}
-static int sja1105_init_mii_settings(struct sja1105_private *priv,
- struct sja1105_dt_port *ports)
+static int sja1105_init_mii_settings(struct sja1105_private *priv)
{
struct device *dev = &priv->spidev->dev;
struct sja1105_xmii_params_entry *mii;
@@ -171,16 +162,24 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv,
mii = table->entries;
for (i = 0; i < ds->num_ports; i++) {
+ sja1105_mii_role_t role = XMII_MAC;
+
if (dsa_is_unused_port(priv->ds, i))
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:
if (!priv->info->supports_mii[i])
goto unsupported;
mii->xmii_mode[i] = XMII_MODE_MII;
break;
+ case PHY_INTERFACE_MODE_REVRMII:
+ role = XMII_PHY;
+ fallthrough;
case PHY_INTERFACE_MODE_RMII:
if (!priv->info->supports_rmii[i])
goto unsupported;
@@ -211,24 +210,11 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv,
unsupported:
default:
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;
}
- /* Even though the SerDes port is able to drive SGMII autoneg
- * 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;
+ mii->phy_mac[i] = role;
}
return 0;
}
@@ -751,8 +737,7 @@ static int sja1105_init_l2_policing(struct sja1105_private *priv)
return 0;
}
-static int sja1105_static_config_load(struct sja1105_private *priv,
- struct sja1105_dt_port *ports)
+static int sja1105_static_config_load(struct sja1105_private *priv)
{
int rc;
@@ -767,7 +752,7 @@ static int sja1105_static_config_load(struct sja1105_private *priv,
rc = sja1105_init_mac_settings(priv);
if (rc < 0)
return rc;
- rc = sja1105_init_mii_settings(priv, ports);
+ rc = sja1105_init_mii_settings(priv);
if (rc < 0)
return rc;
rc = sja1105_init_static_fdb(priv);
@@ -799,33 +784,31 @@ static int sja1105_static_config_load(struct sja1105_private *priv,
return sja1105_static_config_upload(priv);
}
-static int sja1105_parse_rgmii_delays(struct sja1105_private *priv,
- const struct sja1105_dt_port *ports)
+static int sja1105_parse_rgmii_delays(struct sja1105_private *priv)
{
struct dsa_switch *ds = priv->ds;
- int i;
+ int port;
- for (i = 0; i < ds->num_ports; i++) {
- if (ports[i].role == XMII_MAC)
+ for (port = 0; port < ds->num_ports; port++) {
+ if (!priv->fixed_link[port])
continue;
- if (ports[i].phy_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
- ports[i].phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
- priv->rgmii_rx_delay[i] = true;
+ if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_RXID ||
+ priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID)
+ priv->rgmii_rx_delay[port] = true;
- if (ports[i].phy_mode == PHY_INTERFACE_MODE_RGMII_TXID ||
- ports[i].phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
- priv->rgmii_tx_delay[i] = true;
+ if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_TXID ||
+ priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID)
+ priv->rgmii_tx_delay[port] = true;
- if ((priv->rgmii_rx_delay[i] || priv->rgmii_tx_delay[i]) &&
- !priv->info->setup_rgmii_delay)
+ if ((priv->rgmii_rx_delay[port] || priv->rgmii_tx_delay[port]) &&
+ !priv->info->setup_rgmii_delay)
return -EINVAL;
}
return 0;
}
static int sja1105_parse_ports_node(struct sja1105_private *priv,
- struct sja1105_dt_port *ports,
struct device_node *ports_node)
{
struct device *dev = &priv->spidev->dev;
@@ -854,7 +837,6 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
of_node_put(child);
return -ENODEV;
}
- ports[index].phy_mode = phy_mode;
phy_node = of_parse_phandle(child, "phy-handle", 0);
if (!phy_node) {
@@ -867,27 +849,18 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
/* phy-handle is missing, but fixed-link isn't.
* So it's a fixed link. Default to PHY role.
*/
- ports[index].role = XMII_PHY;
+ priv->fixed_link[index] = true;
} else {
- /* phy-handle present => put port in MAC role */
- ports[index].role = XMII_MAC;
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;
}
return 0;
}
-static int sja1105_parse_dt(struct sja1105_private *priv,
- struct sja1105_dt_port *ports)
+static int sja1105_parse_dt(struct sja1105_private *priv)
{
struct device *dev = &priv->spidev->dev;
struct device_node *switch_node = dev->of_node;
@@ -902,7 +875,7 @@ static int sja1105_parse_dt(struct sja1105_private *priv,
return -ENODEV;
}
- rc = sja1105_parse_ports_node(priv, ports, ports_node);
+ rc = sja1105_parse_ports_node(priv, ports_node);
of_node_put(ports_node);
return rc;
@@ -3008,11 +2981,10 @@ static const struct dsa_8021q_ops sja1105_dsa_8021q_ops = {
*/
static int sja1105_setup(struct dsa_switch *ds)
{
- struct sja1105_dt_port ports[SJA1105_MAX_NUM_PORTS];
struct sja1105_private *priv = ds->priv;
int rc;
- rc = sja1105_parse_dt(priv, ports);
+ rc = sja1105_parse_dt(priv);
if (rc < 0) {
dev_err(ds->dev, "Failed to parse DT: %d\n", rc);
return rc;
@@ -3021,7 +2993,7 @@ static int sja1105_setup(struct dsa_switch *ds)
/* Error out early if internal delays are required through DT
* and we can't apply them.
*/
- rc = sja1105_parse_rgmii_delays(priv, ports);
+ rc = sja1105_parse_rgmii_delays(priv);
if (rc < 0) {
dev_err(ds->dev, "RGMII delay not supported\n");
return rc;
@@ -3033,7 +3005,7 @@ static int sja1105_setup(struct dsa_switch *ds)
return rc;
}
/* Create and send configuration down to device */
- rc = sja1105_static_config_load(priv, ports);
+ rc = sja1105_static_config_load(priv);
if (rc < 0) {
dev_err(ds->dev, "Failed to load static config: %d\n", rc);
goto out_ptp_clock_unregister;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 852743f07e3e..ed332ac92e25 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -93,6 +93,7 @@ extern const int phy_10gbit_features_array[1];
* @PHY_INTERFACE_MODE_TBI: Ten Bit Interface
* @PHY_INTERFACE_MODE_REVMII: Reverse Media Independent Interface
* @PHY_INTERFACE_MODE_RMII: Reduced Media Independent Interface
+ * @PHY_INTERFACE_MODE_REVRMII: Reduced Media Independent Interface in PHY role
* @PHY_INTERFACE_MODE_RGMII: Reduced gigabit media-independent interface
* @PHY_INTERFACE_MODE_RGMII_ID: RGMII with Internal RX+TX delay
* @PHY_INTERFACE_MODE_RGMII_RXID: RGMII with Internal RX delay
@@ -126,6 +127,7 @@ typedef enum {
PHY_INTERFACE_MODE_TBI,
PHY_INTERFACE_MODE_REVMII,
PHY_INTERFACE_MODE_RMII,
+ PHY_INTERFACE_MODE_REVRMII,
PHY_INTERFACE_MODE_RGMII,
PHY_INTERFACE_MODE_RGMII_ID,
PHY_INTERFACE_MODE_RGMII_RXID,
@@ -185,6 +187,8 @@ static inline const char *phy_modes(phy_interface_t interface)
return "rev-mii";
case PHY_INTERFACE_MODE_RMII:
return "rmii";
+ case PHY_INTERFACE_MODE_REVRMII:
+ return "rev-rmii";
case PHY_INTERFACE_MODE_RGMII:
return "rgmii";
case PHY_INTERFACE_MODE_RGMII_ID: