* [RFC net-next PATCH 00/13] Add PCS core support
@ 2025-04-03 18:18 Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 01/13] dt-bindings: net: Add binding for Xilinx PCS Sean Anderson
` (13 more replies)
0 siblings, 14 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:18 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit,
Sean Anderson, Alexandre Belloni, Alexandre Torgue,
Christophe Leroy, Clark Wang, Claudiu Beznea, Claudiu Manoil,
Conor Dooley, Ioana Ciornei, Jonathan Corbet, Joyce Ooi,
Krzysztof Kozlowski, Krzysztof Kozlowski, Li Yang, Madalin Bucur,
Madhavan Srinivasan, Maxime Coquelin, Michael Ellerman,
Michal Simek, Naveen N Rao, Nicholas Piggin, Nicolas Ferre,
Radhey Shyam Pandey, Rob Herring, Rob Herring, Robert Hancock,
Saravana Kannan, Shawn Guo, UNGLinuxDriver, Vladimir Oltean,
Wei Fang, devicetree, imx, linux-arm-kernel, linux-doc,
linux-stm32, linuxppc-dev
This series adds support for creating PCSs as devices on a bus with a
driver (patch 3). As initial users,
- The Lynx PCS (and all of its users) is converted to this system (patch 5)
- The Xilinx PCS is broken out from the AXI Ethernet driver (patches 6-8)
- The Cadence MACB driver is converted to support external PCSs (namely
the Xilinx PCS) (patches 9-10).
The last few patches add device links for pcs-handle to improve boot times,
and add compatibles for all Lynx PCSs.
Care has been taken to ensure backwards-compatibility. The main source
of this is that many PCS devices lack compatibles and get detected as
PHYs. To address this, pcs_get_by_fwnode_compat allows drivers to edit
the devicetree to add appropriate compatibles.
This is technically a v3 (with [1,2] being v1 and v2, respectively), but
there have been so many architectural changes that I didn't bother
maintaining the series changelog. I think it is best to review this
series independently of its past iterations. I submitted this as an RFC
since net-next is closed, but I believe this series is fully tested and
ready to be applied.
[1] https://lore.kernel.org/netdev/20211004191527.1610759-1-sean.anderson@seco.com/
[2] https://lore.kernel.org/netdev/20221103210650.2325784-1-sean.anderson@seco.com/
Sean Anderson (12):
dt-bindings: net: Add binding for Xilinx PCS
net: phylink: Support setting PCS link change callbacks
net: pcs: Add subsystem
net: pcs: lynx: Convert to an MDIO driver
net: phy: Export some functions
net: pcs: Add Xilinx PCS driver
net: axienet: Convert to use PCS subsystem
net: macb: Move most of mac_config to mac_prepare
net: macb: Support external PCSs
of: property: Add device link support for PCS
arm64: dts: Add compatible strings for Lynx PCSs
powerpc: dts: Add compatible strings for Lynx PCSs
Vladimir Oltean (1):
net: dsa: ocelot: suppress PHY device scanning on the internal MDIO
bus
.../devicetree/bindings/net/xilinx,pcs.yaml | 129 ++++
Documentation/networking/index.rst | 1 +
Documentation/networking/kapi.rst | 4 +
Documentation/networking/pcs.rst | 99 +++
MAINTAINERS | 8 +
.../arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 48 +-
.../arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 54 +-
.../dts/freescale/qoriq-fman3-0-10g-0.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-10g-1.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-0.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-1.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-2.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-3.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-4.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-5.dtsi | 3 +-
.../fsl/qoriq-fman3-0-10g-0-best-effort.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi | 3 +-
.../fsl/qoriq-fman3-0-10g-1-best-effort.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi | 3 +-
.../boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi | 3 +-
drivers/net/dsa/ocelot/Kconfig | 4 +
drivers/net/dsa/ocelot/felix_vsc9959.c | 15 +-
drivers/net/dsa/ocelot/seville_vsc9953.c | 16 +-
drivers/net/ethernet/altera/Kconfig | 2 +
drivers/net/ethernet/altera/altera_tse_main.c | 7 +-
drivers/net/ethernet/cadence/macb.h | 1 +
drivers/net/ethernet/cadence/macb_main.c | 229 ++++--
drivers/net/ethernet/freescale/dpaa/Kconfig | 2 +-
drivers/net/ethernet/freescale/dpaa2/Kconfig | 3 +
.../net/ethernet/freescale/dpaa2/dpaa2-mac.c | 11 +-
drivers/net/ethernet/freescale/enetc/Kconfig | 2 +
.../net/ethernet/freescale/enetc/enetc_pf.c | 8 +-
.../net/ethernet/freescale/enetc/enetc_pf.h | 1 -
.../freescale/enetc/enetc_pf_common.c | 4 +-
drivers/net/ethernet/freescale/fman/Kconfig | 4 +-
.../net/ethernet/freescale/fman/fman_memac.c | 27 +-
drivers/net/ethernet/stmicro/stmmac/Kconfig | 3 +
.../ethernet/stmicro/stmmac/dwmac-socfpga.c | 6 +-
drivers/net/ethernet/xilinx/Kconfig | 1 +
drivers/net/ethernet/xilinx/xilinx_axienet.h | 4 +-
.../net/ethernet/xilinx/xilinx_axienet_main.c | 104 +--
drivers/net/pcs/Kconfig | 51 +-
drivers/net/pcs/Makefile | 4 +
drivers/net/pcs/core.c | 701 ++++++++++++++++++
drivers/net/pcs/pcs-lynx.c | 115 +--
drivers/net/pcs/pcs-xilinx.c | 481 ++++++++++++
drivers/net/phy/mdio_device.c | 1 +
drivers/net/phy/phy_device.c | 3 +-
drivers/net/phy/phylink.c | 24 +-
drivers/of/property.c | 2 +
include/linux/pcs-lynx.h | 13 +-
include/linux/pcs-xilinx.h | 36 +
include/linux/pcs.h | 122 +++
include/linux/phy.h | 1 +
include/linux/phylink.h | 27 +-
70 files changed, 2104 insertions(+), 358 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/xilinx,pcs.yaml
create mode 100644 Documentation/networking/pcs.rst
create mode 100644 drivers/net/pcs/core.c
create mode 100644 drivers/net/pcs/pcs-xilinx.c
create mode 100644 include/linux/pcs-xilinx.h
create mode 100644 include/linux/pcs.h
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 01/13] dt-bindings: net: Add binding for Xilinx PCS
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
@ 2025-04-03 18:18 ` Sean Anderson
2025-04-04 10:37 ` Krzysztof Kozlowski
2025-04-03 18:18 ` [RFC net-next PATCH 02/13] net: phylink: Support setting PCS link change callbacks Sean Anderson
` (12 subsequent siblings)
13 siblings, 1 reply; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:18 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit,
Sean Anderson, Conor Dooley, Krzysztof Kozlowski, Michal Simek,
Radhey Shyam Pandey, Rob Herring, Robert Hancock, devicetree
This adds a binding for the Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII
LogiCORE IP. This device is a soft device typically used to adapt
between GMII and SGMII or 1000BASE-X (possbilty in combination with a
serdes). pcs-modes reflects the modes available with the as configured
when the device is synthesized. Multiple modes may be specified if
dynamic reconfiguration is supported.
One PCS may contain "shared logic in core" which can be connected to
other PCSs with "shared logic in example design." This primarily refers
to clocking resources, allowing a reference clock to be shared by a bank
of PCSs. To support this, if #clock-cells is defined then the PCS will
register itself as a clock provider for other PCSs.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
.../devicetree/bindings/net/xilinx,pcs.yaml | 129 ++++++++++++++++++
1 file changed, 129 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/xilinx,pcs.yaml
diff --git a/Documentation/devicetree/bindings/net/xilinx,pcs.yaml b/Documentation/devicetree/bindings/net/xilinx,pcs.yaml
new file mode 100644
index 000000000000..56a3ce0c4ef0
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/xilinx,pcs.yaml
@@ -0,0 +1,129 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/xilinx,pcs.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII LogiCORE IP
+
+maintainers:
+ - Sean Anderson <sean.anderson@seco.com>
+
+description:
+ This is a soft device which implements the PCS and (depending on
+ configuration) PMA layers of an IEEE Ethernet PHY. On the MAC side, it
+ implements GMII. It may have an attached SERDES (internal or external), or
+ may directly use LVDS IO resources. Depending on the configuration, it may
+ implement 1000BASE-X, SGMII, 2500BASE-X, or 2.5G SGMII.
+
+ This device has a notion of "shared logic" such as reset and clocking
+ resources which must be shared between multiple PCSs using the same I/O
+ banks. Each PCS can be configured to have the shared logic in the "core"
+ (instantiated internally and made available to other PCSs) or in the "example
+ design" (provided by another PCS). PCSs with shared logic in the core are
+ reset controllers, and generally provide several resets for other PCSs in the
+ same bank.
+
+allOf:
+ - $ref: ethernet-controller.yaml#
+
+properties:
+ compatible:
+ contains:
+ const: xilinx,pcs-16.2
+
+ reg:
+ maxItems: 1
+
+ "#clock-cells":
+ const: 0
+ description:
+ Register a clock representing the clocking resources shared with other
+ PCSs.
+
+ clocks:
+ items:
+ - description:
+ The reference clock for the PCS. Depending on your setup, this may be
+ the gtrefclk, refclk, clk125m signal, or clocks from another PCS.
+
+ clock-names:
+ const: refclk
+
+ done-gpios:
+ maxItems: 1
+ description:
+ GPIO connected to the reset-done output, if present.
+
+ interrupts:
+ items:
+ - description:
+ The an_interrupt autonegotiation-complete interrupt.
+
+ interrupt-names:
+ const: an
+
+ pcs-modes:
+ description:
+ The interfaces that the PCS supports.
+ oneOf:
+ - const: sgmii
+ - const: 1000base-x
+ - const: 2500base-x
+ - items:
+ - const: sgmii
+ - const: 1000base-x
+
+ reset-gpios:
+ maxItems: 1
+ description:
+ GPIO connected to the reset input.
+
+required:
+ - compatible
+ - reg
+ - pcs-modes
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pcs0: ethernet-pcs@0 {
+ #clock-cells = <0>;
+ compatible = "xlnx,pcs-16.2";
+ reg = <0>;
+ clocks = <&si570>;
+ clock-names = "refclk";
+ interrupts-extended = <&gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "an";
+ reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+ done-gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
+ pcs-modes = "sgmii", "1000base-x";
+ };
+
+ pcs1: ethernet-pcs@1 {
+ compatible = "xlnx,pcs-16.2";
+ reg = <1>;
+ clocks = <&pcs0>;
+ clock-names = "refclk";
+ interrupts-extended = <&gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "an";
+ reset-gpios = <&gpio 7 GPIO_ACTIVE_HIGH>;
+ done-gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
+ pcs-modes = "sgmii", "1000base-x";
+ };
+
+ pcs2: ethernet-pcs@2 {
+ compatible = "xlnx,pcs-16.2";
+ reg = <2>;
+ pcs-modes = "sgmii";
+ };
+ };
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 02/13] net: phylink: Support setting PCS link change callbacks
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 01/13] dt-bindings: net: Add binding for Xilinx PCS Sean Anderson
@ 2025-04-03 18:18 ` Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 03/13] net: pcs: Add subsystem Sean Anderson
` (11 subsequent siblings)
13 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:18 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit,
Sean Anderson
Support changing the link change callback, similar to how PHYs do it.
This will allow the PCS wrapper to forward link changes to the wrapped
PCS.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
drivers/net/phy/phylink.c | 24 +++++++-----------------
include/linux/phylink.h | 27 ++++++++++++++++++++++-----
2 files changed, 29 insertions(+), 22 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 69ca765485db..76ce96315c0c 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1205,6 +1205,8 @@ static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
pl->act_link_an_mode = mode;
}
+static void pcs_change_callback(void *priv, bool up);
+
static void phylink_major_config(struct phylink *pl, bool restart,
const struct phylink_link_state *state)
{
@@ -1260,10 +1262,10 @@ static void phylink_major_config(struct phylink *pl, bool restart,
phylink_pcs_disable(pl->pcs);
if (pl->pcs)
- pl->pcs->phylink = NULL;
-
- pcs->phylink = pl;
+ pl->pcs->link_change_priv = NULL;
+ pcs->link_change = pcs_change_callback;
+ pcs->link_change_priv = pl;
pl->pcs = pcs;
}
@@ -2333,25 +2335,13 @@ void phylink_mac_change(struct phylink *pl, bool up)
}
EXPORT_SYMBOL_GPL(phylink_mac_change);
-/**
- * phylink_pcs_change() - notify phylink of a change to PCS link state
- * @pcs: pointer to &struct phylink_pcs
- * @up: indicates whether the link is currently up.
- *
- * The PCS driver should call this when the state of its link changes
- * (e.g. link failure, new negotiation results, etc.) Note: it should
- * not determine "up" by reading the BMSR. If in doubt about the link
- * state at interrupt time, then pass true if pcs_get_state() returns
- * the latched link-down state, otherwise pass false.
- */
-void phylink_pcs_change(struct phylink_pcs *pcs, bool up)
+static void pcs_change_callback(void *priv, bool up)
{
- struct phylink *pl = pcs->phylink;
+ struct phylink *pl = priv;
if (pl)
phylink_link_changed(pl, up, "pcs");
}
-EXPORT_SYMBOL_GPL(phylink_pcs_change);
static irqreturn_t phylink_link_handler(int irq, void *data)
{
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 1f5773ab5660..a16282ae746d 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -441,7 +441,8 @@ struct phylink_pcs_ops;
* @supported_interfaces: describing which PHY_INTERFACE_MODE_xxx
* are supported by this PCS.
* @ops: a pointer to the &struct phylink_pcs_ops structure
- * @phylink: pointer to &struct phylink_config
+ * @link_change: callback for when the link changes
+ * @link_change_priv: first argument to @link_change
* @poll: poll the PCS for link changes
* @rxc_always_on: The MAC driver requires the reference clock
* to always be on. Standalone PCS drivers which
@@ -451,13 +452,14 @@ struct phylink_pcs_ops;
* This structure is designed to be embedded within the PCS private data,
* and will be passed between phylink and the PCS.
*
- * The @phylink member is private to phylink and must not be touched by
- * the PCS driver.
+ * @link_change, @link_change_priv, and @rxc_always_on will be filled in by
+ * phylink.
*/
struct phylink_pcs {
DECLARE_PHY_INTERFACE_MASK(supported_interfaces);
const struct phylink_pcs_ops *ops;
- struct phylink *phylink;
+ void (*link_change)(void *priv, bool up);
+ void *link_change_priv;
bool poll;
bool rxc_always_on;
};
@@ -699,7 +701,22 @@ int phylink_set_fixed_link(struct phylink *,
const struct phylink_link_state *);
void phylink_mac_change(struct phylink *, bool up);
-void phylink_pcs_change(struct phylink_pcs *, bool up);
+/**
+ * phylink_pcs_change() - notify phylink of a change to PCS link state
+ * @pcs: pointer to &struct phylink_pcs
+ * @up: indicates whether the link is currently up.
+ *
+ * The PCS driver should call this when the state of its link changes
+ * (e.g. link failure, new negotiation results, etc.) Note: it should
+ * not determine "up" by reading the BMSR. If in doubt about the link
+ * state at interrupt time, then pass true if pcs_get_state() returns
+ * the latched link-down state, otherwise pass false.
+ */
+static inline void phylink_pcs_change(struct phylink_pcs *pcs, bool up)
+{
+ if (pcs->link_change)
+ pcs->link_change(pcs->link_change_priv, up);
+}
int phylink_pcs_pre_init(struct phylink *pl, struct phylink_pcs *pcs);
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 03/13] net: pcs: Add subsystem
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 01/13] dt-bindings: net: Add binding for Xilinx PCS Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 02/13] net: phylink: Support setting PCS link change callbacks Sean Anderson
@ 2025-04-03 18:18 ` Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 04/13] net: dsa: ocelot: suppress PHY device scanning on the internal MDIO bus Sean Anderson
` (10 subsequent siblings)
13 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:18 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit,
Sean Anderson, Jonathan Corbet, linux-doc
This adds support for getting PCS devices from the device tree. PCS
drivers must first register with phylink_register_pcs. After that, MAC
drivers may look up their PCS using phylink_get_pcs.
We wrap registered PCSs in another PCS. This wrapper PCS is refcounted
and can outlive the wrapped PCS (such as if the wrapped PCS's driver is
unbound). The wrapper forwards all PCS callbacks to the wrapped PCS,
first checking to make sure the wrapped PCS still exists. This design
was inspired by Bartosz Golaszewsk's talk at LPC [1].
pcs_get_by_fwnode_compat is a bit hairy, but it's necessary for
compatibility with existing drivers, which often attach to (devicetree)
nodes directly. We use the devicetree changeset system instead of
adding a (secondary) software node because mdio_bus_match calls
of_driver_match_device to match devices, and that function only works on
devicetree nodes.
[1] https://lpc.events/event/17/contributions/1627/
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
Documentation/networking/index.rst | 1 +
Documentation/networking/kapi.rst | 4 +
Documentation/networking/pcs.rst | 99 ++++
MAINTAINERS | 2 +
drivers/net/pcs/Kconfig | 12 +
drivers/net/pcs/Makefile | 2 +
drivers/net/pcs/core.c | 701 +++++++++++++++++++++++++++++
include/linux/pcs.h | 122 +++++
8 files changed, 943 insertions(+)
create mode 100644 Documentation/networking/pcs.rst
create mode 100644 drivers/net/pcs/core.c
create mode 100644 include/linux/pcs.h
diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst
index 058193ed2eeb..96a2cf71057d 100644
--- a/Documentation/networking/index.rst
+++ b/Documentation/networking/index.rst
@@ -30,6 +30,7 @@ Contents:
page_pool
phy
sfp-phylink
+ pcs
alias
bridge
snmp_counter
diff --git a/Documentation/networking/kapi.rst b/Documentation/networking/kapi.rst
index 98682b9a13ee..7a48178649de 100644
--- a/Documentation/networking/kapi.rst
+++ b/Documentation/networking/kapi.rst
@@ -146,6 +146,10 @@ PHYLINK
.. kernel-doc:: include/linux/phylink.h
:internal:
+ :no-identifiers: phylink_pcs phylink_pcs_ops pcs_validate pcs_inband_caps
+ pcs_enable pcs_disable pcs_pre_config pcs_post_config pcs_get_state
+ pcs_config pcs_an_restart pcs_link_up pcs_disable_eee pcs_enable_eee
+ pcs_pre_init
.. kernel-doc:: drivers/net/phy/phylink.c
diff --git a/Documentation/networking/pcs.rst b/Documentation/networking/pcs.rst
new file mode 100644
index 000000000000..3677527e5e2b
--- /dev/null
+++ b/Documentation/networking/pcs.rst
@@ -0,0 +1,99 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============
+PCS Subsystem
+=============
+
+The PCS (Physical Coding Sublayer) subsystem handles the registration and lookup
+of PCS devices. These devices contain the upper sublayers of the Ethernet
+physical layer, generally handling framing, scrambling, and encoding tasks. PCS
+devices may also include PMA (Physical Medium Attachment) components. PCS
+devices transfer data between the Link-layer MAC device, and the rest of the
+physical layer, typically via a serdes. The output of the serdes may be
+connected more-or-less directly to the medium when using fiber-optic or
+backplane connections (1000BASE-SX, 1000BASE-KX, etc). It may also communicate
+with a separate PHY (such as over SGMII) which handles the connection to the
+medium (such as 1000BASE-T).
+
+Looking up PCS Devices
+----------------------
+
+There are generally two ways to look up a PCS device. If the PCS device is
+internal to a larger device (such as a MAC or switch), and it does not share an
+implementation with an existing PCS, then it does not need to be registered with
+the PCS subsystem. Instead, you can populate a :c:type:`phylink_pcs`
+in your probe function. Otherwise, you must look up the PCS.
+
+If your device has a :c:type:`fwnode_handle`, you can add a PCS using the
+``pcs-handle`` property::
+
+ ethernet-controller {
+ // ...
+ pcs-handle = <&pcs>;
+ pcs-handle-names = "internal";
+ };
+
+Then, during your probe function, you can get the PCS using :c:func:`pcs_get`::
+
+ mac->pcs = pcs_get(dev, "internal");
+ if (IS_ERR(mac->pcs)) {
+ err = PTR_ERR(mac->pcs);
+ return dev_err_probe(dev, "Could not get PCS\n");
+ }
+
+If your device doesn't have a :c:type:`fwnode_handle`, you can get the PCS
+based on the providing device using :c:func:`pcs_get_by_dev`. Typically, you
+will create the device and bind your PCS driver to it before calling this
+function. This allows reuse of an existing PCS driver.
+
+Once you are done using the PCS, you must call :c:func:`pcs_put`.
+
+Using PCS Devices
+-----------------
+
+To select the PCS from a MAC driver, implement the ``mac_select_pcs`` callback
+of :c:type:`phylink_mac_ops`. In this example, the PCS is selected for SGMII
+and 1000BASE-X, and deselected for other interfaces::
+
+ static struct phylink_pcs *mac_select_pcs(struct phylink_config *config,
+ phy_interface_t iface)
+ {
+ struct mac *mac = config_to_mac(config);
+
+ switch (iface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ return mac->pcs;
+ default:
+ return NULL;
+ }
+ }
+
+To do the same from a DSA driver, implement the ``phylink_mac_select_pcs``
+callback of :c:type:`dsa_switch_ops`.
+
+Writing PCS Drivers
+-------------------
+
+To write a PCS driver, first implement :c:type:`phylink_pcs_ops`. Then,
+register your PCS in your probe function using :c:func:`pcs_register`. You must
+call :c:func:`pcs_unregister` from your remove function. You can avoid this step
+by registering with :c:func:`devm_pcs_unregister`.
+
+API Reference
+-------------
+
+.. kernel-doc:: include/linux/phylink.h
+ :identifiers: phylink_pcs phylink_pcs_ops pcs_validate pcs_inband_caps
+ pcs_enable pcs_disable pcs_pre_config pcs_post_config pcs_get_state
+ pcs_config pcs_an_restart pcs_link_up pcs_disable_eee pcs_enable_eee
+ pcs_pre_init
+
+.. kernel-doc:: include/linux/pcs.h
+ :internal:
+
+.. kernel-doc:: drivers/net/pcs/core.c
+ :export:
+
+.. kernel-doc:: drivers/net/pcs/core.c
+ :internal:
diff --git a/MAINTAINERS b/MAINTAINERS
index 1cd25139cc58..9d3b3788a005 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8644,6 +8644,7 @@ F: Documentation/ABI/testing/sysfs-class-net-phydev
F: Documentation/devicetree/bindings/net/ethernet-phy.yaml
F: Documentation/devicetree/bindings/net/mdio*
F: Documentation/devicetree/bindings/net/qca,ar803x.yaml
+F: Documentation/networking/pcs.rst
F: Documentation/networking/phy.rst
F: drivers/net/mdio/
F: drivers/net/mdio/acpi_mdio.c
@@ -8657,6 +8658,7 @@ F: include/linux/linkmode.h
F: include/linux/mdio/*.h
F: include/linux/mii.h
F: include/linux/of_net.h
+F: include/linux/pcs.h
F: include/linux/phy.h
F: include/linux/phy_fixed.h
F: include/linux/phy_link_topology.h
diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig
index f6aa437473de..b764770063cc 100644
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -5,6 +5,18 @@
menu "PCS device drivers"
+config PCS
+ bool "PCS subsystem"
+ help
+ This provides common helper functions for registering and looking up
+ Physical Coding Sublayer (PCS) devices. PCS devices translate between
+ different interface types. In some use cases, they may either
+ translate between different types of Medium-Independent Interfaces
+ (MIIs), such as translating GMII to SGMII. This allows using a fast
+ serial interface to talk to the phy which translates the MII to the
+ Medium-Dependent Interface. Alternatively, they may translate a MII
+ directly to an MDI, such as translating GMII to 1000Base-X.
+
config PCS_XPCS
tristate "Synopsys DesignWare Ethernet XPCS"
select PHYLINK
diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile
index 4f7920618b90..35e3324fc26e 100644
--- a/drivers/net/pcs/Makefile
+++ b/drivers/net/pcs/Makefile
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for Linux PCS drivers
+obj-$(CONFIG_PCS) += core.o
+
pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.o pcs-xpcs-plat.o \
pcs-xpcs-nxp.o pcs-xpcs-wx.o
diff --git a/drivers/net/pcs/core.c b/drivers/net/pcs/core.c
new file mode 100644
index 000000000000..de3f9e418cf2
--- /dev/null
+++ b/drivers/net/pcs/core.c
@@ -0,0 +1,701 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022, 2025 Sean Anderson <sean.anderson@seco.com>
+ */
+
+#define pr_fmt(fmt) "pcs-core: " fmt
+
+#include <linux/fwnode.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/pcs.h>
+#include <linux/phylink.h>
+#include <linux/property.h>
+#include <linux/rcupdate.h>
+
+static LIST_HEAD(pcs_wrappers);
+static DEFINE_MUTEX(pcs_mutex);
+
+/**
+ * struct pcs_wrapper - Wrapper for a registered PCS
+ * @pcs: the wrapping PCS
+ * @ssp: SRCU protecting @wrapped
+ * @refcnt: refcount for the wrapper
+ * @list: list head for pcs_wrappers
+ * @dev: the device associated with this PCS
+ * @wrapped: the backing PCS
+ */
+struct pcs_wrapper {
+ struct phylink_pcs pcs;
+ struct srcu_struct ssp;
+ refcount_t refcnt;
+ struct list_head list;
+ struct device *dev;
+ struct phylink_pcs *wrapped;
+};
+
+static const struct phylink_pcs_ops pcs_ops;
+
+static struct pcs_wrapper *pcs_to_wrapper(struct phylink_pcs *pcs)
+{
+ WARN_ON(pcs->ops != &pcs_ops);
+ return container_of(pcs, struct pcs_wrapper, pcs);
+}
+
+static int pcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
+ const struct phylink_link_state *state)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int ret, idx;
+
+ if (!wrapper)
+ return 0;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped) {
+ if (wrapped->ops->pcs_validate)
+ ret = wrapped->ops->pcs_validate(wrapped, supported,
+ state);
+ else
+ ret = 0;
+ } else {
+ ret = -ENODEV;
+ }
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+ return ret;
+}
+
+static unsigned int pcs_inband_caps(struct phylink_pcs *pcs,
+ phy_interface_t interface)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int ret, idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped && wrapped->ops->pcs_inband_caps)
+ ret = wrapped->ops->pcs_inband_caps(wrapped, interface);
+ else
+ ret = 0;
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+ return ret;
+}
+
+static int pcs_enable(struct phylink_pcs *pcs)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int ret, idx;
+
+ if (!wrapper)
+ return 0;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped) {
+ if (wrapped->ops->pcs_enable)
+ ret = wrapped->ops->pcs_enable(wrapped);
+ else
+ ret = 0;
+ } else {
+ ret = -ENODEV;
+ }
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+ return ret;
+}
+
+static void pcs_disable(struct phylink_pcs *pcs)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped && wrapped->ops->pcs_disable)
+ wrapped->ops->pcs_disable(wrapped);
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+}
+
+static void pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
+ struct phylink_link_state *state)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped)
+ wrapped->ops->pcs_get_state(wrapped, neg_mode, state);
+ else
+ state->link = 0;
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+}
+
+static void pcs_pre_config(struct phylink_pcs *pcs,
+ phy_interface_t interface)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped && wrapped->ops->pcs_pre_config)
+ wrapped->ops->pcs_pre_config(wrapped, interface);
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+}
+
+static int pcs_post_config(struct phylink_pcs *pcs,
+ phy_interface_t interface)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int ret, idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (pcs && wrapped->ops->pcs_post_config)
+ ret = wrapped->ops->pcs_post_config(wrapped, interface);
+ else
+ ret = 0;
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+ return ret;
+}
+
+static int pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ bool permit_pause_to_mac)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int ret, idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped)
+ ret = wrapped->ops->pcs_config(wrapped, neg_mode, interface,
+ advertising, permit_pause_to_mac);
+ else
+ ret = -ENODEV;
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+ return ret;
+}
+
+static void pcs_an_restart(struct phylink_pcs *pcs)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped)
+ wrapped->ops->pcs_an_restart(wrapped);
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+}
+
+static void pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface, int speed, int duplex)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped && wrapped->ops->pcs_link_up)
+ wrapped->ops->pcs_link_up(wrapped, neg_mode, interface, speed,
+ duplex);
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+}
+
+static void pcs_disable_eee(struct phylink_pcs *pcs)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped && wrapped->ops->pcs_disable_eee)
+ wrapped->ops->pcs_disable_eee(wrapped);
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+}
+
+static void pcs_enable_eee(struct phylink_pcs *pcs)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped && wrapped->ops->pcs_enable_eee)
+ wrapped->ops->pcs_enable_eee(wrapped);
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+}
+
+static int pcs_pre_init(struct phylink_pcs *pcs)
+{
+ struct pcs_wrapper *wrapper = pcs_to_wrapper(pcs);
+ struct phylink_pcs *wrapped;
+ int ret, idx;
+
+ idx = srcu_read_lock(&wrapper->ssp);
+
+ wrapped = srcu_dereference(wrapper->wrapped, &wrapper->ssp);
+ if (wrapped) {
+ wrapped->rxc_always_on = pcs->rxc_always_on;
+ if (wrapped->ops->pcs_pre_init)
+ ret = wrapped->ops->pcs_pre_init(wrapped);
+ else
+ ret = 0;
+ } else {
+ ret = -ENODEV;
+ }
+
+ srcu_read_unlock(&wrapper->ssp, idx);
+ return ret;
+}
+
+static const struct phylink_pcs_ops pcs_ops = {
+ .pcs_validate = pcs_validate,
+ .pcs_inband_caps = pcs_inband_caps,
+ .pcs_enable = pcs_enable,
+ .pcs_disable = pcs_disable,
+ .pcs_pre_config = pcs_pre_config,
+ .pcs_post_config = pcs_post_config,
+ .pcs_get_state = pcs_get_state,
+ .pcs_config = pcs_config,
+ .pcs_an_restart = pcs_an_restart,
+ .pcs_link_up = pcs_link_up,
+ .pcs_disable_eee = pcs_disable_eee,
+ .pcs_enable_eee = pcs_enable_eee,
+ .pcs_pre_init = pcs_pre_init,
+};
+
+static void pcs_change_callback(void *priv, bool up)
+{
+ struct pcs_wrapper *wrapper = priv;
+
+ phylink_pcs_change(&wrapper->pcs, up);
+}
+
+/**
+ * pcs_register() - register a new PCS
+ * @dev: The device requesting the PCS
+ * @pcs: The PCS to register
+ *
+ * Registers a new PCS which can be attached to a phylink.
+ *
+ * Return: 0 on success, or -errno on error
+ */
+int pcs_register(struct device *dev, struct phylink_pcs *pcs)
+{
+ struct pcs_wrapper *wrapper;
+
+ if (!dev || !pcs->ops)
+ return -EINVAL;
+
+ if (!pcs->ops->pcs_an_restart || !pcs->ops->pcs_config ||
+ !pcs->ops->pcs_get_state)
+ return -EINVAL;
+
+ wrapper = kzalloc(sizeof(*wrapper), GFP_KERNEL);
+ if (!wrapper)
+ return -ENOMEM;
+
+ init_srcu_struct(&wrapper->ssp);
+ refcount_set(&wrapper->refcnt, 1);
+ INIT_LIST_HEAD(&wrapper->list);
+ wrapper->dev = dev;
+ RCU_INIT_POINTER(wrapper->wrapped, pcs);
+
+ wrapper->pcs.ops = &pcs_ops;
+ wrapper->pcs.poll = pcs->poll;
+ bitmap_copy(wrapper->pcs.supported_interfaces, pcs->supported_interfaces,
+ PHY_INTERFACE_MODE_MAX);
+
+ pcs->link_change = pcs_change_callback;
+ pcs->link_change_priv = wrapper;
+
+ mutex_lock(&pcs_mutex);
+ list_add(&wrapper->list, &pcs_wrappers);
+ mutex_unlock(&pcs_mutex);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pcs_register);
+
+static void pcs_destroy(struct pcs_wrapper *wrapper)
+{
+ cleanup_srcu_struct(&wrapper->ssp);
+ kfree(wrapper);
+}
+
+/**
+ * pcs_unregister() - unregister a PCS
+ * @pcs: a PCS previously registered with pcs_register()
+ */
+void pcs_unregister(struct phylink_pcs *pcs)
+{
+ struct pcs_wrapper *wrapper;
+ struct phylink_pcs *wrapped;
+
+ mutex_lock(&pcs_mutex);
+ list_for_each_entry(wrapper, &pcs_wrappers, list) {
+ if (wrapper->wrapped == pcs)
+ goto found;
+ }
+
+ mutex_unlock(&pcs_mutex);
+ WARN(1, "trying to unregister an already-unregistered PCS\n");
+ return;
+
+found:
+ list_del(&wrapper->list);
+ wrapped = rcu_replace_pointer(wrapper->wrapped, NULL, true);
+ mutex_unlock(&pcs_mutex);
+ synchronize_srcu(&wrapper->ssp);
+
+ if (!wrapper->pcs.poll)
+ phylink_pcs_change(&wrapper->pcs, false);
+ if (refcount_dec_and_test(&wrapper->refcnt))
+ pcs_destroy(wrapper);
+}
+EXPORT_SYMBOL_GPL(pcs_unregister);
+
+static void devm_pcs_release(struct device *dev, void *res)
+{
+ pcs_unregister(*(struct phylink_pcs **)res);
+}
+
+/**
+ * devm_pcs_register - resource managed pcs_register()
+ * @dev: device that is registering this PCS
+ * @pcs: the PCS to register
+ *
+ * Managed pcs_register(). For PCSs registered by this function,
+ * pcs_unregister() is automatically called on driver detach. See
+ * pcs_register() for more information.
+ *
+ * Return: 0 on success, or -errno on failure
+ */
+int devm_pcs_register(struct device *dev, struct phylink_pcs *pcs)
+{
+ struct phylink_pcs **pcsp;
+ int ret;
+
+ pcsp = devres_alloc(devm_pcs_release, sizeof(*pcsp),
+ GFP_KERNEL);
+ if (!pcsp)
+ return -ENOMEM;
+
+ ret = pcs_register(dev, pcs);
+ if (ret) {
+ devres_free(pcsp);
+ return ret;
+ }
+
+ *pcsp = pcs;
+ devres_add(dev, pcsp);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_pcs_register);
+
+/**
+ * _pcs_get_tail() - Look up and request a PCS
+ * @dev: The device requesting the PCS
+ * @fwnode: The PCS's fwnode
+ * @pcs_dev: The PCS's device
+ *
+ * Search PCSs registered with pcs_register() for one with a matching
+ * fwnode or device. Either @fwnode or @pcs_dev may be %NULL if matching
+ * against a fwnode or device is not desired (respectively).
+ *
+ * Once a PCS is found, perform common operations necessary when getting a PCS
+ * (increment reference counts, etc).
+ *
+ * You should probably call one of the pcs_get* functions instead of this one.
+ *
+ * Return: A PCS, or an error pointer on failure. If both @fwnode and @pcs_dev are
+ * * %NULL, returns %NULL to allow easier chaining.
+ */
+struct phylink_pcs *_pcs_get_tail(struct device *dev,
+ const struct fwnode_handle *fwnode,
+ const struct device *pcs_dev)
+{
+ struct pcs_wrapper *wrapper;
+
+ if (!fwnode && !pcs_dev)
+ return NULL;
+
+ pr_debug("looking for %pfwf or %s %s...\n", fwnode,
+ pcs_dev ? dev_driver_string(pcs_dev) : "(null)",
+ pcs_dev ? dev_name(pcs_dev) : "(null)");
+
+ /* We need to hold this until we get to device_link_add. Otherwise,
+ * someone could unbind the PCS driver.
+ */
+ mutex_lock(&pcs_mutex);
+ list_for_each_entry(wrapper, &pcs_wrappers, list) {
+ if (pcs_dev && wrapper->dev == pcs_dev)
+ goto found;
+ if (fwnode && wrapper->dev && wrapper->dev->fwnode == fwnode)
+ goto found;
+ }
+ mutex_unlock(&pcs_mutex);
+ pr_debug("...not found\n");
+ return ERR_PTR(-EPROBE_DEFER);
+
+found:
+ pr_debug("...found\n");
+
+ refcount_inc(&wrapper->refcnt);
+ get_device(wrapper->dev);
+
+ mutex_unlock(&pcs_mutex);
+ return &wrapper->pcs;
+}
+EXPORT_SYMBOL_GPL(_pcs_get_tail);
+
+/**
+ * pcs_find_fwnode() - Find a PCS's fwnode
+ * @mac_node: The fwnode referencing the PCS
+ * @id: The name of the PCS to get. May be %NULL to get the first PCS.
+ * @fallback: An optional fallback property to use if pcs-handle is absent
+ * @optional: Whether the PCS is optional
+ *
+ * Find a PCS's fwnode, as referenced by @mac_node. This fwnode can later be
+ * used with _pcs_get_tail() to get the actual PCS. ``pcs-handle-names`` is
+ * used to match @id, then the fwnode is found using ``pcs-handle``.
+ *
+ * This function is internal to the PCS subsystem from a consumer
+ * point-of-view. However, it may be used to implement fallbacks for legacy
+ * behavior in PCS providers.
+ *
+ * Return: %NULL if @optional is set and the PCS cannot be found. Otherwise,
+ * * returns a PCS if found or an error pointer on failure.
+ */
+struct fwnode_handle *pcs_find_fwnode(const struct fwnode_handle *mac_node,
+ const char *id, const char *fallback,
+ bool optional)
+{
+ int index;
+ struct fwnode_handle *pcs_fwnode;
+
+ if (!mac_node)
+ return optional ? NULL : ERR_PTR(-ENODEV);
+
+ if (id)
+ index = fwnode_property_match_string(mac_node,
+ "pcs-handle-names", id);
+ else
+ index = 0;
+
+ if (index < 0) {
+ if (optional && (index == -EINVAL || index == -ENODATA))
+ return NULL;
+ return ERR_PTR(index);
+ }
+
+ /* First try pcs-handle, and if that doesn't work try the fallback */
+ pcs_fwnode = fwnode_find_reference(mac_node, "pcs-handle", index);
+ if (PTR_ERR(pcs_fwnode) == -ENOENT && fallback)
+ pcs_fwnode = fwnode_find_reference(mac_node, fallback, index);
+ if (optional && !id && PTR_ERR(pcs_fwnode) == -ENOENT)
+ return NULL;
+ return pcs_fwnode;
+}
+EXPORT_SYMBOL_GPL(pcs_find_fwnode);
+
+/**
+ * _pcs_get() - Get a PCS from a fwnode property
+ * @dev: The device to get a PCS for
+ * @fwnode: The fwnode to find the PCS with
+ * @id: The name of the PCS to get. May be %NULL to get the first PCS.
+ * @fallback: An optional fallback property to use if pcs-handle is absent
+ * @optional: Whether the PCS is optional
+ *
+ * Find a PCS referenced by @mac_node and return a reference to it. Every call
+ * to _pcs_get_by_fwnode() must be balanced with one to pcs_put().
+ *
+ * Return: a PCS if found, %NULL if not, or an error pointer on failure
+ */
+struct phylink_pcs *_pcs_get(struct device *dev, struct fwnode_handle *fwnode,
+ const char *id, const char *fallback,
+ bool optional)
+{
+ struct fwnode_handle *pcs_fwnode;
+ struct phylink_pcs *pcs;
+
+ pcs_fwnode = pcs_find_fwnode(fwnode, id, fallback, optional);
+ if (IS_ERR(pcs_fwnode))
+ return ERR_CAST(pcs_fwnode);
+
+ pcs = _pcs_get_tail(dev, pcs_fwnode, NULL);
+ fwnode_handle_put(pcs_fwnode);
+ return pcs;
+}
+EXPORT_SYMBOL_GPL(_pcs_get);
+
+static __maybe_unused void of_changeset_cleanup(void *data)
+{
+ struct of_changeset *ocs = data;
+
+ if (WARN(of_changeset_revert(ocs),
+ "could not revert changeset; leaking memory\n"))
+ return;
+
+ of_changeset_destroy(ocs);
+ kfree(ocs);
+}
+
+/**
+ * pcs_get_by_fwnode_compat() - Get a PCS with a compatibility fallback
+ * @dev: The device requesting the PCS
+ * @fwnode: The &struct fwnode_handle of the PCS itself
+ * @fixup: Callback to fix up @fwnode for compatibility
+ * @data: Passed to @fixup
+ *
+ * This function looks up a PCS and retries on failure after fixing up @fwnode.
+ * It is intended to assist in backwards-compatible behavior for drivers that
+ * used to create a PCS directly from a &struct device_node. This function
+ * should NOT be used in new drivers.
+ *
+ * @fixup modifies a devicetree changeset to create any properties necessary to
+ * bind the PCS's &struct device_node. At the very least, it should use
+ * of_changeset_add_prop_string() to add a compatible property.
+ *
+ * Note that unlike pcs_get_by_fwnode, @fwnode is the &struct fwnode_handle of
+ * the PCS itself, and not that of the requesting device. @fwnode could be
+ * looked up with pcs_find_fwnode() or determined by some other means for
+ * compatibility.
+ *
+ * Return: A PCS on success or an error pointer on failure
+ */
+struct phylink_pcs *
+pcs_get_by_fwnode_compat(struct device *dev, struct fwnode_handle *fwnode,
+ int (*fixup)(struct of_changeset *ocs,
+ struct device_node *np, void *data),
+ void *data)
+{
+#ifdef CONFIG_OF_DYNAMIC
+ struct mdio_device *mdiodev;
+ struct of_changeset *ocs;
+ struct phylink_pcs *pcs;
+ struct device_node *np;
+ struct device *pcsdev;
+ int err;
+
+ /* First attempt */
+ pcs = _pcs_get_tail(dev, fwnode, NULL);
+ if (PTR_ERR(pcs) != -EPROBE_DEFER)
+ return pcs;
+
+ /* No luck? Maybe there's no compatible... */
+ np = to_of_node(fwnode);
+ if (!np || of_property_present(np, "compatible"))
+ return pcs;
+
+ /* OK, let's try fixing things up */
+ pr_warn("%pOF is missing a compatible\n", np);
+ ocs = kmalloc(sizeof(*ocs), GFP_KERNEL);
+ if (!ocs)
+ return ERR_PTR(-ENOMEM);
+
+ of_changeset_init(ocs);
+ err = fixup(ocs, np, data);
+ if (err)
+ goto err_ocs;
+
+ err = of_changeset_apply(ocs);
+ if (err)
+ goto err_ocs;
+
+ err = devm_add_action_or_reset(dev, of_changeset_cleanup, ocs);
+ if (err)
+ return ERR_PTR(err);
+
+ mdiodev = fwnode_mdio_find_device(fwnode);
+ if (mdiodev) {
+ /* Clear that pesky PHY flag so we can match PCS drivers */
+ device_lock(&mdiodev->dev);
+ mdiodev->flags &= ~MDIO_DEVICE_FLAG_PHY;
+ device_unlock(&mdiodev->dev);
+ pcsdev = &mdiodev->dev;
+ } else {
+ pcsdev = get_device(fwnode->dev);
+ if (!pcsdev)
+ return ERR_PTR(-EPROBE_DEFER);
+ }
+
+ err = device_reprobe(pcsdev);
+ put_device(pcsdev);
+ if (err)
+ return ERR_PTR(err);
+
+ return _pcs_get_tail(dev, fwnode, NULL);
+
+err_ocs:
+ of_changeset_destroy(ocs);
+ kfree(ocs);
+ return ERR_PTR(err);
+#else
+ return _pcs_get_tail(dev, fwnode, NULL);
+#endif
+}
+EXPORT_SYMBOL_GPL(pcs_get_by_fwnode_compat);
+
+/**
+ * pcs_put() - Release a previously-acquired PCS
+ * @dev: The device used to acquire the PCS
+ * @pcs: The PCS to put
+ *
+ * This frees resources associated with the PCS which were acquired when it was
+ * gotten.
+ */
+void pcs_put(struct device *dev, struct phylink_pcs *pcs)
+{
+ struct pcs_wrapper *wrapper;
+
+ if (!pcs)
+ return;
+
+ wrapper = pcs_to_wrapper(pcs);
+ put_device(wrapper->dev);
+ if (refcount_dec_and_test(&wrapper->refcnt))
+ pcs_destroy(wrapper);
+}
+EXPORT_SYMBOL_GPL(pcs_put);
diff --git a/include/linux/pcs.h b/include/linux/pcs.h
new file mode 100644
index 000000000000..53fbff3af9e8
--- /dev/null
+++ b/include/linux/pcs.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ */
+
+#ifndef _PCS_H
+#define _PCS_H
+
+struct device_node;
+struct of_changeset;
+struct phylink_pcs;
+
+int pcs_register(struct device *dev, struct phylink_pcs *pcs);
+void pcs_unregister(struct phylink_pcs *pcs);
+int devm_pcs_register(struct device *dev, struct phylink_pcs *pcs);
+struct phylink_pcs *_pcs_get_tail(struct device *dev,
+ const struct fwnode_handle *fwnode,
+ const struct device *pcs_dev);
+struct phylink_pcs *_pcs_get(struct device *dev, struct fwnode_handle *fwnode,
+ const char *id, const char *fallback,
+ bool optional);
+void pcs_put(struct device *dev, struct phylink_pcs *handle);
+
+/**
+ * pcs_get() - Get a PCS based on a fwnode
+ * @dev: The device requesting the PCS
+ * @id: The name of the PCS
+ *
+ * Find and get a PCS, as referenced by @dev's &struct fwnode_handle. See
+ * pcs_find_fwnode() for details. Each call to this function must be balanced
+ * with one to pcs_put().
+ *
+ * Return: A PCS on success or an error pointer on failure
+ */
+static inline struct phylink_pcs *pcs_get(struct device *dev, const char *id)
+{
+ return _pcs_get(dev, dev_fwnode(dev), id, NULL, false);
+}
+
+/**
+ * pcs_get_optional() - Optionally get a PCS based on a fwnode
+ * @dev: The device requesting the PCS
+ * @id: The name of the PCS
+ *
+ * Optionally find and get a PCS, as referenced by @dev's &struct
+ * fwnode_handle. See pcs_find_fwnode() for details. Each call to this function
+ * must be balanced with one to pcs_put().
+ *
+ * Return: A PCS on success, %NULL if none was found, or an error pointer on
+ * * failure
+ */
+static inline struct phylink_pcs *pcs_get_optional(struct device *dev,
+ const char *id)
+{
+ return _pcs_get(dev, dev_fwnode(dev), id, NULL, true);
+}
+
+/**
+ * pcs_get_by_fwnode() - Get a PCS based on a fwnode
+ * @dev: The device requesting the PCS
+ * @fwnode: The &struct fwnode_handle referencing the PCS
+ * @id: The name of the PCS
+ *
+ * Find and get a PCS, as referenced by @fwnode. See pcs_find_fwnode() for
+ * details. Each call to this function must be balanced with one to pcs_put().
+ *
+ * Return: A PCS on success or an error pointer on failure
+ */
+static inline struct phylink_pcs
+*pcs_get_by_fwnode(struct device *dev, struct fwnode_handle *fwnode,
+ const char *id)
+{
+ return _pcs_get(dev, fwnode, id, NULL, false);
+}
+
+/**
+ * pcs_get_by_fwnode_optional() - Optionally get a PCS based on a fwnode
+ * @dev: The device requesting the PCS
+ * @fwnode: The &struct fwnode_handle referencing the PCS
+ * @id: The name of the PCS
+ *
+ * Optionally find and get a PCS, as referenced by @fwnode. See
+ * pcs_find_fwnode() for details. Each call to this function must be balanced
+ * with one to pcs_put().
+ *
+ * Return: A PCS on success, %NULL if none was found, or an error pointer on
+ * * failure
+ */
+static inline struct phylink_pcs
+*pcs_get_by_fwnode_optional(struct device *dev, struct fwnode_handle *fwnode,
+ const char *id)
+{
+ return _pcs_get(dev, fwnode, id, NULL, true);
+}
+
+/**
+ * pcs_get_by_dev() - Get a PCS from its providing device
+ * @dev: The device requesting the PCS
+ * @pcs_dev: The device providing the PCS
+ *
+ * Get the first PCS registered by @pcs_dev. Each call to this function must be
+ * balanced with one to pcs_put().
+ *
+ * Return: A PCS on success or an error pointer on failure
+ */
+static inline struct phylink_pcs *pcs_get_by_dev(struct device *dev,
+ const struct device *pcs_dev)
+{
+ return _pcs_get_tail(dev, NULL, pcs_dev);
+}
+
+struct fwnode_handle *pcs_find_fwnode(const struct fwnode_handle *mac_node,
+ const char *id, const char *fallback,
+ bool optional);
+
+struct phylink_pcs *
+pcs_get_by_fwnode_compat(struct device *dev, struct fwnode_handle *fwnode,
+ int (*fixup)(struct of_changeset *ocs, struct device_node *np,
+ void *data),
+ void *data);
+
+#endif /* PCS_H */
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 04/13] net: dsa: ocelot: suppress PHY device scanning on the internal MDIO bus
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (2 preceding siblings ...)
2025-04-03 18:18 ` [RFC net-next PATCH 03/13] net: pcs: Add subsystem Sean Anderson
@ 2025-04-03 18:18 ` Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 05/13] net: pcs: lynx: Convert to an MDIO driver Sean Anderson
` (9 subsequent siblings)
13 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:18 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit,
Vladimir Oltean, Sean Anderson, Alexandre Belloni, Claudiu Manoil,
UNGLinuxDriver
From: Vladimir Oltean <vladimir.oltean@nxp.com>
This bus contains Lynx PCS devices, and if the lynx-pcs driver ever
decided to call mdio_device_register(), it would fail due to
mdiobus_scan() having created a dummy phydev for the same address
(the PCS responds to standard clause 22 PHY ID registers and can
therefore by autodetected by phylib which thinks it's a PHY).
On the Seville driver, things are a bit more complicated, since bus
creation is handled by mscc_miim_setup() and that is shared with the
dedicated mscc-miim driver. Suppress PHY scanning only for the Seville
internal MDIO bus rather than for the whole mscc-miim driver, since we
know that on NXP T1040, this bus only contains Lynx PCS devices.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
drivers/net/dsa/ocelot/felix_vsc9959.c | 4 ++++
drivers/net/dsa/ocelot/seville_vsc9953.c | 5 +++++
2 files changed, 9 insertions(+)
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 940f1b71226d..2de12611ab57 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1001,6 +1001,10 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
bus->read_c45 = enetc_mdio_read_c45;
bus->write_c45 = enetc_mdio_write_c45;
bus->parent = dev;
+ /* Suppress PHY device creation in mdiobus_scan(),
+ * we have Lynx PCSs
+ */
+ bus->phy_mask = ~0;
mdio_priv = bus->priv;
mdio_priv->hw = hw;
/* This gets added to imdio_regs, which already maps addresses
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index eb3944ba2a72..28bcdef34a6c 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -901,6 +901,11 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
return rc;
}
+ /* Suppress PHY device creation in mdiobus_scan(),
+ * we have Lynx PCSs
+ */
+ bus->phy_mask = ~0;
+
/* Needed in order to initialize the bus mutex lock */
rc = devm_of_mdiobus_register(dev, bus, NULL);
if (rc < 0) {
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 05/13] net: pcs: lynx: Convert to an MDIO driver
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (3 preceding siblings ...)
2025-04-03 18:18 ` [RFC net-next PATCH 04/13] net: dsa: ocelot: suppress PHY device scanning on the internal MDIO bus Sean Anderson
@ 2025-04-03 18:18 ` Sean Anderson
2025-04-03 18:19 ` [RFC net-next PATCH 06/13] net: phy: Export some functions Sean Anderson
` (8 subsequent siblings)
13 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:18 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit,
Sean Anderson, Alexandre Belloni, Alexandre Torgue, Clark Wang,
Claudiu Manoil, Ioana Ciornei, Joyce Ooi, Madalin Bucur,
Maxime Coquelin, UNGLinuxDriver, Vladimir Oltean, Wei Fang, imx,
linux-stm32
This converts the lynx PCS driver to a proper MDIO driver.
This allows using a more conventional driver lifecycle (e.g. with a
probe and remove). It will also make it easier to add interrupt support.
The existing helpers are converted to bind the MDIO driver instead of
creating the PCS directly. As lynx_pcs_create_mdiodev creates the PCS
device, we can just set the modalias. For lynx_pcs_create_fwnode, we try
to get the PCS the usual way, and if that fails we edit the devicetree
to add a compatible and reprobe the device.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
drivers/net/dsa/ocelot/Kconfig | 4 +
drivers/net/dsa/ocelot/felix_vsc9959.c | 11 +-
drivers/net/dsa/ocelot/seville_vsc9953.c | 11 +-
drivers/net/ethernet/altera/Kconfig | 2 +
drivers/net/ethernet/altera/altera_tse_main.c | 7 +-
drivers/net/ethernet/freescale/dpaa/Kconfig | 2 +-
drivers/net/ethernet/freescale/dpaa2/Kconfig | 3 +
.../net/ethernet/freescale/dpaa2/dpaa2-mac.c | 11 +-
drivers/net/ethernet/freescale/enetc/Kconfig | 2 +
.../net/ethernet/freescale/enetc/enetc_pf.c | 8 +-
.../net/ethernet/freescale/enetc/enetc_pf.h | 1 -
.../freescale/enetc/enetc_pf_common.c | 4 +-
drivers/net/ethernet/freescale/fman/Kconfig | 4 +-
.../net/ethernet/freescale/fman/fman_memac.c | 27 ++--
drivers/net/ethernet/stmicro/stmmac/Kconfig | 3 +
.../ethernet/stmicro/stmmac/dwmac-socfpga.c | 6 +-
drivers/net/pcs/Kconfig | 11 +-
drivers/net/pcs/pcs-lynx.c | 115 ++++++++++--------
include/linux/pcs-lynx.h | 13 +-
19 files changed, 135 insertions(+), 110 deletions(-)
diff --git a/drivers/net/dsa/ocelot/Kconfig b/drivers/net/dsa/ocelot/Kconfig
index 081e7a88ea02..e879f82537db 100644
--- a/drivers/net/dsa/ocelot/Kconfig
+++ b/drivers/net/dsa/ocelot/Kconfig
@@ -42,7 +42,9 @@ config NET_DSA_MSCC_FELIX
select NET_DSA_TAG_OCELOT_8021Q
select NET_DSA_TAG_OCELOT
select FSL_ENETC_MDIO
+ select PCS
select PCS_LYNX
+ select MDIO_DEVICE
help
This driver supports the VSC9959 (Felix) switch, which is embedded as
a PCIe function of the NXP LS1028A ENETC RCiEP.
@@ -58,7 +60,9 @@ config NET_DSA_MSCC_SEVILLE
select NET_DSA_MSCC_FELIX_DSA_LIB
select NET_DSA_TAG_OCELOT_8021Q
select NET_DSA_TAG_OCELOT
+ select PCS
select PCS_LYNX
+ select MDIO_DEVICE
help
This driver supports the VSC9953 (Seville) switch, which is embedded
as a platform device on the NXP T1040 SoC.
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 2de12611ab57..a67fc2f8528c 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -12,6 +12,7 @@
#include <net/tc_act/tc_gate.h>
#include <soc/mscc/ocelot.h>
#include <linux/dsa/ocelot.h>
+#include <linux/pcs.h>
#include <linux/pcs-lynx.h>
#include <net/pkt_sched.h>
#include <linux/iopoll.h>
@@ -1033,7 +1034,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL)
continue;
- phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, port);
+ phylink_pcs = lynx_pcs_create_mdiodev(dev, felix->imdio, port);
if (IS_ERR(phylink_pcs))
continue;
@@ -1050,12 +1051,8 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
struct felix *felix = ocelot_to_felix(ocelot);
int port;
- for (port = 0; port < ocelot->num_phys_ports; port++) {
- struct phylink_pcs *phylink_pcs = felix->pcs[port];
-
- if (phylink_pcs)
- lynx_pcs_destroy(phylink_pcs);
- }
+ for (port = 0; port < ocelot->num_phys_ports; port++)
+ pcs_put(ocelot->dev, felix->pcs[port]);
mdiobus_unregister(felix->imdio);
mdiobus_free(felix->imdio);
}
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index 28bcdef34a6c..0e61bd8bc7cd 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -10,6 +10,7 @@
#include <linux/mdio/mdio-mscc-miim.h>
#include <linux/mod_devicetable.h>
#include <linux/of_mdio.h>
+#include <linux/pcs.h>
#include <linux/pcs-lynx.h>
#include <linux/dsa/ocelot.h>
#include <linux/iopoll.h>
@@ -926,7 +927,7 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL)
continue;
- phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, addr);
+ phylink_pcs = lynx_pcs_create_mdiodev(dev, felix->imdio, addr);
if (IS_ERR(phylink_pcs))
continue;
@@ -943,12 +944,8 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot)
struct felix *felix = ocelot_to_felix(ocelot);
int port;
- for (port = 0; port < ocelot->num_phys_ports; port++) {
- struct phylink_pcs *phylink_pcs = felix->pcs[port];
-
- if (phylink_pcs)
- lynx_pcs_destroy(phylink_pcs);
- }
+ for (port = 0; port < ocelot->num_phys_ports; port++)
+ pcs_put(ocelot->dev, felix->pcs[port]);
/* mdiobus_unregister and mdiobus_free handled by devres */
}
diff --git a/drivers/net/ethernet/altera/Kconfig b/drivers/net/ethernet/altera/Kconfig
index 4ef819a9a1ad..daf508a195a5 100644
--- a/drivers/net/ethernet/altera/Kconfig
+++ b/drivers/net/ethernet/altera/Kconfig
@@ -5,7 +5,9 @@ config ALTERA_TSE
depends on HAS_IOMEM
select PHYLIB
select PHYLINK
+ select PCS
select PCS_LYNX
+ select MDIO_DEVICE
select MDIO_REGMAP
select REGMAP_MMIO
help
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 3f6204de9e6b..7b34b6dc521e 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -32,6 +32,7 @@
#include <linux/of.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
+#include <linux/pcs.h>
#include <linux/pcs-lynx.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
@@ -1412,7 +1413,7 @@ static int altera_tse_probe(struct platform_device *pdev)
goto err_init_pcs;
}
- priv->pcs = lynx_pcs_create_mdiodev(pcs_bus, 0);
+ priv->pcs = lynx_pcs_create_mdiodev(&pdev->dev, pcs_bus, 0);
if (IS_ERR(priv->pcs)) {
ret = PTR_ERR(priv->pcs);
goto err_init_pcs;
@@ -1444,7 +1445,7 @@ static int altera_tse_probe(struct platform_device *pdev)
return 0;
err_init_phylink:
- lynx_pcs_destroy(priv->pcs);
+ pcs_put(&pdev->dev, priv->pcs);
err_init_pcs:
unregister_netdev(ndev);
err_register_netdev:
@@ -1466,7 +1467,7 @@ static void altera_tse_remove(struct platform_device *pdev)
altera_tse_mdio_destroy(ndev);
unregister_netdev(ndev);
phylink_destroy(priv->phylink);
- lynx_pcs_destroy(priv->pcs);
+ pcs_put(&pdev->dev, priv->pcs);
free_netdev(ndev);
}
diff --git a/drivers/net/ethernet/freescale/dpaa/Kconfig b/drivers/net/ethernet/freescale/dpaa/Kconfig
index 2b560661c82a..3129f029445b 100644
--- a/drivers/net/ethernet/freescale/dpaa/Kconfig
+++ b/drivers/net/ethernet/freescale/dpaa/Kconfig
@@ -3,7 +3,7 @@ menuconfig FSL_DPAA_ETH
tristate "DPAA Ethernet"
depends on FSL_DPAA && FSL_FMAN
select PHYLINK
- select PCS_LYNX
+ select MDIO_DEVICE
help
Data Path Acceleration Architecture Ethernet driver,
supporting the Freescale QorIQ chips.
diff --git a/drivers/net/ethernet/freescale/dpaa2/Kconfig b/drivers/net/ethernet/freescale/dpaa2/Kconfig
index d029b69c3f18..28e63dc4acbf 100644
--- a/drivers/net/ethernet/freescale/dpaa2/Kconfig
+++ b/drivers/net/ethernet/freescale/dpaa2/Kconfig
@@ -2,8 +2,11 @@
config FSL_DPAA2_ETH
tristate "Freescale DPAA2 Ethernet"
depends on FSL_MC_BUS && FSL_MC_DPIO
+ select OF_DYNAMIC
select PHYLINK
+ select PCS
select PCS_LYNX
+ select MDIO_DEVICE
select FSL_XGMAC_MDIO
select NET_DEVLINK
help
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index 422ce13a7c94..26accbe7e736 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -2,6 +2,7 @@
/* Copyright 2019 NXP */
#include <linux/acpi.h>
+#include <linux/pcs.h>
#include <linux/pcs-lynx.h>
#include <linux/phy/phy.h>
#include <linux/property.h>
@@ -262,7 +263,7 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
return 0;
}
- pcs = lynx_pcs_create_fwnode(node);
+ pcs = lynx_pcs_create_fwnode(&mac->mc_dev->dev, node);
fwnode_handle_put(node);
if (pcs == ERR_PTR(-EPROBE_DEFER)) {
@@ -288,12 +289,8 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
{
- struct phylink_pcs *phylink_pcs = mac->pcs;
-
- if (phylink_pcs) {
- lynx_pcs_destroy(phylink_pcs);
- mac->pcs = NULL;
- }
+ pcs_put(&mac->mc_dev->dev, mac->pcs);
+ mac->pcs = NULL;
}
static void dpaa2_mac_set_supported_interfaces(struct dpaa2_mac *mac)
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index 6c2779047dcd..6a58254b9a5f 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -24,7 +24,9 @@ config FSL_ENETC
select FSL_ENETC_MDIO
select NXP_ENETC_PF_COMMON
select PHYLINK
+ select PCS
select PCS_LYNX
+ select MDIO_DEVICE
select DIMLIB
help
This driver supports NXP ENETC gigabit ethernet controller PCIe
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 203862ec1114..737797b541a0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -34,12 +34,7 @@ static void enetc_pf_set_primary_mac_addr(struct enetc_hw *hw, int si,
static struct phylink_pcs *enetc_pf_create_pcs(struct enetc_pf *pf,
struct mii_bus *bus)
{
- return lynx_pcs_create_mdiodev(bus, 0);
-}
-
-static void enetc_pf_destroy_pcs(struct phylink_pcs *pcs)
-{
- lynx_pcs_destroy(pcs);
+ return lynx_pcs_create_mdiodev(&pf->si->pdev->dev, bus, 0);
}
static void enetc_set_vlan_promisc(struct enetc_hw *hw, char si_map)
@@ -1003,7 +998,6 @@ static const struct enetc_pf_ops enetc_pf_ops = {
.set_si_primary_mac = enetc_pf_set_primary_mac_addr,
.get_si_primary_mac = enetc_pf_get_primary_mac_addr,
.create_pcs = enetc_pf_create_pcs,
- .destroy_pcs = enetc_pf_destroy_pcs,
.enable_psfp = enetc_psfp_enable,
};
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index a26a12863855..d5e02d02c7a8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -42,7 +42,6 @@ struct enetc_pf_ops {
void (*set_si_primary_mac)(struct enetc_hw *hw, int si, const u8 *addr);
void (*get_si_primary_mac)(struct enetc_hw *hw, int si, u8 *addr);
struct phylink_pcs *(*create_pcs)(struct enetc_pf *pf, struct mii_bus *bus);
- void (*destroy_pcs)(struct phylink_pcs *pcs);
int (*enable_psfp)(struct enetc_ndev_priv *priv);
};
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 3fd9b0727875..f5b75d40f7c5 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -4,6 +4,7 @@
#include <linux/fsl/enetc_mdio.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
+#include <linux/pcs.h>
#include "enetc_pf_common.h"
@@ -248,8 +249,7 @@ static int enetc_imdio_create(struct enetc_pf *pf)
static void enetc_imdio_remove(struct enetc_pf *pf)
{
- if (pf->pcs && pf->ops->destroy_pcs)
- pf->ops->destroy_pcs(pf->pcs);
+ pcs_put(&pf->si->pdev->dev, pf->pcs);
if (pf->imdio) {
mdiobus_unregister(pf->imdio);
diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
index a55542c1ad65..b87b22220972 100644
--- a/drivers/net/ethernet/freescale/fman/Kconfig
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -3,10 +3,12 @@ config FSL_FMAN
tristate "FMan support"
depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST
select GENERIC_ALLOCATOR
+ select OF_DYNAMIC
+ select MDIO_DEVICE
select PHYLINK
+ select PCS
select PCS_LYNX
select CRC32
- default n
help
Freescale Data-Path Acceleration Architecture Frame Manager
(FMan) support
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 3925441143fa..fc12f3e44824 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/pcs.h>
#include <linux/pcs-lynx.h>
#include <linux/phy.h>
#include <linux/phy_fixed.h>
@@ -972,21 +973,23 @@ static int memac_init(struct fman_mac *memac)
return 0;
}
-static void pcs_put(struct phylink_pcs *pcs)
+static void memac_pcs_put(struct device *dev, struct phylink_pcs *pcs)
{
if (IS_ERR_OR_NULL(pcs))
return;
- lynx_pcs_destroy(pcs);
+ pcs_put(dev, pcs);
}
static int memac_free(struct fman_mac *memac)
{
+ struct device *dev = memac->dev_id->dev;
+
free_init_resources(memac);
- pcs_put(memac->sgmii_pcs);
- pcs_put(memac->qsgmii_pcs);
- pcs_put(memac->xfi_pcs);
+ memac_pcs_put(dev, memac->sgmii_pcs);
+ memac_pcs_put(dev, memac->qsgmii_pcs);
+ memac_pcs_put(dev, memac->xfi_pcs);
kfree(memac->memac_drv_param);
kfree(memac);
@@ -1033,7 +1036,8 @@ static struct fman_mac *memac_config(struct mac_device *mac_dev,
return memac;
}
-static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node,
+static struct phylink_pcs *memac_pcs_create(struct device *dev,
+ struct device_node *mac_node,
int index)
{
struct device_node *node;
@@ -1043,7 +1047,7 @@ static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node,
if (!node)
return ERR_PTR(-ENODEV);
- pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node));
+ pcs = lynx_pcs_create_fwnode(dev, of_fwnode_handle(node));
of_node_put(node);
return pcs;
@@ -1100,7 +1104,7 @@ int memac_initialization(struct mac_device *mac_dev,
err = of_property_match_string(mac_node, "pcs-handle-names", "xfi");
if (err >= 0) {
- memac->xfi_pcs = memac_pcs_create(mac_node, err);
+ memac->xfi_pcs = memac_pcs_create(mac_dev->dev, mac_node, err);
if (IS_ERR(memac->xfi_pcs)) {
err = PTR_ERR(memac->xfi_pcs);
dev_err_probe(mac_dev->dev, err, "missing xfi pcs\n");
@@ -1112,7 +1116,8 @@ int memac_initialization(struct mac_device *mac_dev,
err = of_property_match_string(mac_node, "pcs-handle-names", "qsgmii");
if (err >= 0) {
- memac->qsgmii_pcs = memac_pcs_create(mac_node, err);
+ memac->qsgmii_pcs = memac_pcs_create(mac_dev->dev, mac_node,
+ err);
if (IS_ERR(memac->qsgmii_pcs)) {
err = PTR_ERR(memac->qsgmii_pcs);
dev_err_probe(mac_dev->dev, err,
@@ -1128,11 +1133,11 @@ int memac_initialization(struct mac_device *mac_dev,
*/
err = of_property_match_string(mac_node, "pcs-handle-names", "sgmii");
if (err == -EINVAL || err == -ENODATA)
- pcs = memac_pcs_create(mac_node, 0);
+ pcs = memac_pcs_create(mac_dev->dev, mac_node, 0);
else if (err < 0)
goto _return_fm_mac_free;
else
- pcs = memac_pcs_create(mac_node, err);
+ pcs = memac_pcs_create(mac_dev->dev, mac_node, err);
if (IS_ERR(pcs)) {
err = PTR_ERR(pcs);
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 3c820ef56775..3df23331c726 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -170,9 +170,12 @@ config DWMAC_SOCFPGA
tristate "SOCFPGA dwmac support"
default ARCH_INTEL_SOCFPGA
depends on OF && (ARCH_INTEL_SOCFPGA || COMPILE_TEST)
+ select OF_DYNAMIC
select MFD_SYSCON
+ select MDIO_DEVICE
select MDIO_REGMAP
select REGMAP_MMIO
+ select PCS
select PCS_LYNX
help
Support for ethernet controller on Altera SOCFPGA
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index 116855658559..2c2fb820752b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -8,6 +8,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_net.h>
+#include <linux/pcs.h>
#include <linux/phy.h>
#include <linux/regmap.h>
#include <linux/mdio/mdio-regmap.h>
@@ -415,7 +416,7 @@ static int socfpga_dwmac_pcs_init(struct stmmac_priv *priv)
if (IS_ERR(pcs_bus))
return PTR_ERR(pcs_bus);
- pcs = lynx_pcs_create_mdiodev(pcs_bus, 0);
+ pcs = lynx_pcs_create_mdiodev(priv->device, pcs_bus, 0);
if (IS_ERR(pcs))
return PTR_ERR(pcs);
@@ -425,8 +426,7 @@ static int socfpga_dwmac_pcs_init(struct stmmac_priv *priv)
static void socfpga_dwmac_pcs_exit(struct stmmac_priv *priv)
{
- if (priv->hw->phylink_pcs)
- lynx_pcs_destroy(priv->hw->phylink_pcs);
+ pcs_put(priv->device, priv->hw->phylink_pcs);
}
static struct phylink_pcs *socfpga_dwmac_select_pcs(struct stmmac_priv *priv,
diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig
index b764770063cc..91ff59899aaf 100644
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -25,10 +25,15 @@ config PCS_XPCS
DesignWare XPCS controllers.
config PCS_LYNX
- tristate
+ tristate "NXP Lynx PCS driver"
+ depends on PCS && MDIO_DEVICE
help
- This module provides helpers to phylink for managing the Lynx PCS
- which is part of the Layerscape and QorIQ Ethernet SERDES.
+ This module provides driver support for the PCSs in Lynx 10g and 28g
+ SerDes devices. These devices are present in NXP QorIQ SoCs,
+ including the Layerscape series.
+
+ If you want to use Ethernet on a QorIQ SoC, say "Y". If compiled as a
+ module, it will be called "pcs-lynx".
config PCS_MTK_LYNXI
tristate
diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c
index 23b40e9eacbb..4a6bd5248efa 100644
--- a/drivers/net/pcs/pcs-lynx.c
+++ b/drivers/net/pcs/pcs-lynx.c
@@ -1,11 +1,15 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-/* Copyright 2020 NXP
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2022 Sean Anderson <seanga2@gmail.com>
+ * Copyright 2020 NXP
* Lynx PCS MDIO helpers
*/
#include <linux/mdio.h>
#include <linux/phylink.h>
+#include <linux/of.h>
+#include <linux/pcs.h>
#include <linux/pcs-lynx.h>
+#include <linux/phylink.h>
#include <linux/property.h>
#define SGMII_CLOCK_PERIOD_NS 8 /* PCS is clocked at 125 MHz */
@@ -343,16 +347,16 @@ static const phy_interface_t lynx_interfaces[] = {
PHY_INTERFACE_MODE_USXGMII,
};
-static struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
+static int lynx_pcs_probe(struct mdio_device *mdio)
{
+ struct device *dev = &mdio->dev;
struct lynx_pcs *lynx;
- int i;
+ int i, ret;
- lynx = kzalloc(sizeof(*lynx), GFP_KERNEL);
+ lynx = devm_kzalloc(dev, sizeof(*lynx), GFP_KERNEL);
if (!lynx)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
- mdio_device_get(mdio);
lynx->mdio = mdio;
lynx->pcs.ops = &lynx_pcs_phylink_ops;
lynx->pcs.poll = true;
@@ -360,32 +364,69 @@ static struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
for (i = 0; i < ARRAY_SIZE(lynx_interfaces); i++)
__set_bit(lynx_interfaces[i], lynx->pcs.supported_interfaces);
- return lynx_to_phylink_pcs(lynx);
+ ret = devm_pcs_register(dev, &lynx->pcs);
+ if (ret)
+ return dev_err_probe(dev, ret, "could not register PCS\n");
+ dev_info(dev, "probed\n");
+ return 0;
}
-struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr)
+static const struct of_device_id lynx_pcs_of_match[] = {
+ { .compatible = "fsl,lynx-pcs" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, lynx_pcs_of_match);
+
+static struct mdio_driver lynx_pcs_driver = {
+ .probe = lynx_pcs_probe,
+ .mdiodrv.driver = {
+ .name = "lynx-pcs",
+ .of_match_table = of_match_ptr(lynx_pcs_of_match),
+ },
+};
+mdio_module_driver(lynx_pcs_driver);
+
+struct phylink_pcs *lynx_pcs_create_mdiodev(struct device *dev,
+ struct mii_bus *bus, int addr)
{
struct mdio_device *mdio;
struct phylink_pcs *pcs;
+ int err;
mdio = mdio_device_create(bus, addr);
if (IS_ERR(mdio))
return ERR_CAST(mdio);
- pcs = lynx_pcs_create(mdio);
-
- /* lynx_create() has taken a refcount on the mdiodev if it was
- * successful. If lynx_create() fails, this will free the mdio
- * device here. In any case, we don't need to hold our reference
- * anymore, and putting it here will allow mdio_device_put() in
- * lynx_destroy() to automatically free the mdio device.
- */
- mdio_device_put(mdio);
+ mdio->bus_match = mdio_device_bus_match;
+ strscpy(mdio->modalias, "lynx-pcs");
+ err = mdio_device_register(mdio);
+ if (err) {
+ mdio_device_free(mdio);
+ return ERR_PTR(err);
+ }
+ pcs = pcs_get_by_dev(dev, &mdio->dev);
+ mdio_device_free(mdio);
return pcs;
}
EXPORT_SYMBOL(lynx_pcs_create_mdiodev);
+static const struct property_entry lynx_properties[] = {
+ PROPERTY_ENTRY_STRING("compatible", "fsl,lynx-pcs"),
+ { },
+};
+
+static int lynx_pcs_fixup(struct of_changeset *ocs,
+ struct device_node *np, void *data)
+{
+#ifdef CONFIG_OF_DYNAMIC
+ return of_changeset_add_prop_string(ocs, np, "compatible",
+ "fsl,lynx-pcs");
+#else
+ return -ENODEV;
+#endif
+}
+
/*
* lynx_pcs_create_fwnode() creates a lynx PCS instance from the fwnode
* device indicated by node.
@@ -396,40 +437,12 @@ EXPORT_SYMBOL(lynx_pcs_create_mdiodev);
* -ENOMEM if we fail to allocate memory
* pointer to a phylink_pcs on success
*/
-struct phylink_pcs *lynx_pcs_create_fwnode(struct fwnode_handle *node)
+struct phylink_pcs *lynx_pcs_create_fwnode(struct device *dev,
+ struct fwnode_handle *node)
{
- struct mdio_device *mdio;
- struct phylink_pcs *pcs;
-
- if (!fwnode_device_is_available(node))
- return ERR_PTR(-ENODEV);
-
- mdio = fwnode_mdio_find_device(node);
- if (!mdio)
- return ERR_PTR(-EPROBE_DEFER);
-
- pcs = lynx_pcs_create(mdio);
-
- /* lynx_create() has taken a refcount on the mdiodev if it was
- * successful. If lynx_create() fails, this will free the mdio
- * device here. In any case, we don't need to hold our reference
- * anymore, and putting it here will allow mdio_device_put() in
- * lynx_destroy() to automatically free the mdio device.
- */
- mdio_device_put(mdio);
-
- return pcs;
+ return pcs_get_by_fwnode_compat(dev, node, lynx_pcs_fixup, NULL);
}
EXPORT_SYMBOL_GPL(lynx_pcs_create_fwnode);
-void lynx_pcs_destroy(struct phylink_pcs *pcs)
-{
- struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
-
- mdio_device_put(lynx->mdio);
- kfree(lynx);
-}
-EXPORT_SYMBOL(lynx_pcs_destroy);
-
-MODULE_DESCRIPTION("NXP Lynx PCS phylink library");
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("NXP Lynx PCS phylink driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/pcs-lynx.h b/include/linux/pcs-lynx.h
index 7958cccd16f2..a95801337205 100644
--- a/include/linux/pcs-lynx.h
+++ b/include/linux/pcs-lynx.h
@@ -6,12 +6,13 @@
#ifndef __LINUX_PCS_LYNX_H
#define __LINUX_PCS_LYNX_H
-#include <linux/mdio.h>
-#include <linux/phylink.h>
+struct device;
+struct mii_bus;
+struct phylink_pcs;
-struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr);
-struct phylink_pcs *lynx_pcs_create_fwnode(struct fwnode_handle *node);
-
-void lynx_pcs_destroy(struct phylink_pcs *pcs);
+struct phylink_pcs *lynx_pcs_create_mdiodev(struct device *dev,
+ struct mii_bus *bus, int addr);
+struct phylink_pcs *lynx_pcs_create_fwnode(struct device *dev,
+ struct fwnode_handle *node);
#endif /* __LINUX_PCS_LYNX_H */
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 06/13] net: phy: Export some functions
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (4 preceding siblings ...)
2025-04-03 18:18 ` [RFC net-next PATCH 05/13] net: pcs: lynx: Convert to an MDIO driver Sean Anderson
@ 2025-04-03 18:19 ` Sean Anderson
2025-04-03 18:37 ` Florian Fainelli
2025-04-03 18:19 ` [RFC net-next PATCH 07/13] net: pcs: Add Xilinx PCS driver Sean Anderson
` (7 subsequent siblings)
13 siblings, 1 reply; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:19 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit,
Sean Anderson
Export a few functions so they can be used outside the phy subsystem:
get_phy_c22_id is useful when probing MDIO devices which present a
phy-like interface despite not using the Linux ethernet phy subsystem.
mdio_device_bus_match is useful when creating MDIO devices manually
(e.g. on non-devicetree platforms).
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
drivers/net/phy/mdio_device.c | 1 +
drivers/net/phy/phy_device.c | 3 ++-
include/linux/phy.h | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
index e747ee63c665..cce3f405d1a4 100644
--- a/drivers/net/phy/mdio_device.c
+++ b/drivers/net/phy/mdio_device.c
@@ -45,6 +45,7 @@ int mdio_device_bus_match(struct device *dev, const struct device_driver *drv)
return strcmp(mdiodev->modalias, drv->name) == 0;
}
+EXPORT_SYMBOL_GPL(mdio_device_bus_match);
struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr)
{
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 675fbd225378..45d8bc13eb64 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -859,7 +859,7 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr,
* valid, %-EIO on bus access error, or %-ENODEV if no device responds
* or invalid ID.
*/
-static int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
+int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
{
int phy_reg;
@@ -887,6 +887,7 @@ static int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
return 0;
}
+EXPORT_SYMBOL_GPL(get_phy_c22_id);
/* Extract the phy ID from the compatible string of the form
* ethernet-phy-idAAAA.BBBB.
diff --git a/include/linux/phy.h b/include/linux/phy.h
index a2bfae80c449..c648f1699c5c 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1754,6 +1754,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
bool is_c45,
struct phy_c45_device_ids *c45_ids);
#if IS_ENABLED(CONFIG_PHYLIB)
+int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id);
int fwnode_get_phy_id(struct fwnode_handle *fwnode, u32 *phy_id);
struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode);
struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode);
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 07/13] net: pcs: Add Xilinx PCS driver
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (5 preceding siblings ...)
2025-04-03 18:19 ` [RFC net-next PATCH 06/13] net: phy: Export some functions Sean Anderson
@ 2025-04-03 18:19 ` Sean Anderson
2025-04-03 20:27 ` Russell King (Oracle)
2025-04-03 18:19 ` [RFC net-next PATCH 08/13] net: axienet: Convert to use PCS subsystem Sean Anderson
` (6 subsequent siblings)
13 siblings, 1 reply; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:19 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit,
Sean Anderson, Michal Simek, Radhey Shyam Pandey, Robert Hancock,
linux-arm-kernel
This adds support for the Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII device.
This is a soft device which converts between GMII and either SGMII,
1000Base-X, or 2500Base-X. If configured correctly, it can also switch
between SGMII and 1000BASE-X at runtime. Thoretically this is also possible
for 2500Base-X, but that requires reconfiguring the serdes. The exact
capabilities depend on synthesis parameters, so they are read from the
devicetree.
This device has a c22-compliant PHY interface, so for the most part we can
just use the phylink helpers. This device supports an interrupt which is
triggered on autonegotiation completion. I'm not sure how useful this is,
since we can never detect a link down (in the PCS).
This device supports sharing some logic between different implementations
of the device. In this case, one device contains the "shared logic" and the
clocks are connected to other devices. To coordinate this, one device
registers a clock that the other devices can request. The clock is enabled
in the probe function by releasing the device from reset. There are no othe
software controls, so the clock ops are empty.
Later in this series, we will convert the Xilinx AXI Ethernet driver to use
this PCS. To help out, we provide a compatibility function to bind this
driver in the event the MDIO device has no compatible.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
MAINTAINERS | 6 +
drivers/net/pcs/Kconfig | 28 ++
drivers/net/pcs/Makefile | 2 +
drivers/net/pcs/pcs-xilinx.c | 481 +++++++++++++++++++++++++++++++++++
include/linux/pcs-xilinx.h | 36 +++
5 files changed, 553 insertions(+)
create mode 100644 drivers/net/pcs/pcs-xilinx.c
create mode 100644 include/linux/pcs-xilinx.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 9d3b3788a005..452096e6b04f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26160,6 +26160,12 @@ L: netdev@vger.kernel.org
S: Orphan
F: drivers/net/ethernet/xilinx/ll_temac*
+XILINX PCS DRIVER
+M: Sean Anderson <sean.anderson@linux.dev>
+S: Maintained
+F: Documentation/devicetree/bindings/net/xilinx,pcs.yaml
+F: drivers/net/pcs/pcs-xilinx.c
+
XILINX PWM DRIVER
M: Sean Anderson <sean.anderson@seco.com>
S: Maintained
diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig
index 91ff59899aaf..c28b4630492a 100644
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -50,4 +50,32 @@ config PCS_RZN1_MIIC
on RZ/N1 SoCs. This PCS converts MII to RMII/RGMII or can be set in
pass-through mode for MII.
+config PCS_ALTERA_TSE
+ tristate
+ help
+ This module provides helper functions for the Altera Triple Speed
+ Ethernet SGMII PCS, that can be found on the Intel Socfpga family.
+
+config PCS_XILINX
+ depends on OF
+ depends on GPIOLIB
+ depends on COMMON_CLK
+ depends on PCS
+ select MDIO_DEVICE
+ select PHYLINK
+ default XILINX_AXI_EMAC
+ tristate "Xilinx PCS driver"
+ help
+ PCS driver for the Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII device.
+ This device can either act as a PCS+PMA for 1000BASE-X or 2500BASE-X,
+ or as a GMII-to-SGMII bridge. It can also switch between 1000BASE-X
+ and SGMII dynamically if configured correctly when synthesized.
+ Typical applications use this device on an FPGA connected to a GEM or
+ TEMAC on the GMII side. The other side is typically connected to
+ on-device gigabit transceivers, off-device SERDES devices using TBI,
+ or LVDS IO resources directly.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pcs-xilinx.
+
endmenu
diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile
index 35e3324fc26e..347afd91f034 100644
--- a/drivers/net/pcs/Makefile
+++ b/drivers/net/pcs/Makefile
@@ -10,3 +10,5 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o
obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o
obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o
obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o
+obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o
+obj-$(CONFIG_PCS_XILINX) += pcs-xilinx.o
diff --git a/drivers/net/pcs/pcs-xilinx.c b/drivers/net/pcs/pcs-xilinx.c
new file mode 100644
index 000000000000..a278f86513c2
--- /dev/null
+++ b/drivers/net/pcs/pcs-xilinx.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021-25 Sean Anderson <sean.anderson@seco.com>
+ *
+ * This is the driver for the Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII LogiCORE
+ * IP. A typical setup will look something like
+ *
+ * MAC <--GMII--> PCS/PMA <--1000BASE-X--> SFP module (PMD)
+ *
+ * The IEEE model mostly describes this device, but the PCS layer has a
+ * separate sublayer for 8b/10b en/decoding:
+ *
+ * - When using a device-specific transceiver (serdes), the serdes handles 8b/10b
+ * en/decoding and PMA functions. The IP implements other PCS functions.
+ * - When using LVDS IO resources, the IP implements PCS and PMA functions,
+ * including 8b/10b en/decoding and (de)serialization.
+ * - When using an external serdes (accessed via TBI), the IP implements all
+ * PCS functions, including 8b/10b en/decoding.
+ *
+ * The link to the PMD is not modeled by this driver, except for refclk. It is
+ * assumed that the serdes (if present) needs no configuration, though it
+ * should be fairly easy to add support. It is also possible to go from SGMII
+ * to GMII (PHY mode), but this is not supported.
+ *
+ * This driver was written with reference to PG047:
+ * https://docs.amd.com/r/en-US/pg047-gig-eth-pcs-pma
+ */
+
+#include <linux/bitmap.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iopoll.h>
+#include <linux/mdio.h>
+#include <linux/of.h>
+#include <linux/pcs.h>
+#include <linux/pcs-xilinx.h>
+#include <linux/phylink.h>
+#include <linux/property.h>
+
+/* Vendor-specific MDIO registers */
+#define XILINX_PCS_ANICR 16 /* Auto-Negotiation Interrupt Control Register */
+#define XILINX_PCS_SSR 17 /* Standard Selection Register */
+
+#define XILINX_PCS_ANICR_IE BIT(0) /* Interrupt Enable */
+#define XILINX_PCS_ANICR_IS BIT(1) /* Interrupt Status */
+
+#define XILINX_PCS_SSR_SGMII BIT(0) /* Select SGMII standard */
+
+/**
+ * struct xilinx_pcs - Private data for Xilinx PCS devices
+ * @pcs: The phylink PCS
+ * @mdiodev: The mdiodevice used to access the PCS
+ * @refclk: The reference clock for the PMD
+ * @refclk_out: Optional reference clock for other PCSs using this PCS's shared
+ * logic
+ * @reset: The reset line for the PCS
+ * @done: Optional GPIO for reset_done
+ * @irq: IRQ, or -EINVAL if polling
+ * @enabled: Set if @pcs.link_change is valid and we can call phylink_pcs_change()
+ */
+struct xilinx_pcs {
+ struct phylink_pcs pcs;
+ struct clk_hw refclk_out;
+ struct clk *refclk;
+ struct gpio_desc *reset, *done;
+ struct mdio_device *mdiodev;
+ int irq;
+ bool enabled;
+};
+
+static inline struct xilinx_pcs *pcs_to_xilinx(struct phylink_pcs *pcs)
+{
+ return container_of(pcs, struct xilinx_pcs, pcs);
+}
+
+static irqreturn_t xilinx_pcs_an_irq(int irq, void *dev_id)
+{
+ struct xilinx_pcs *xp = dev_id;
+
+ if (mdiodev_modify_changed(xp->mdiodev, XILINX_PCS_ANICR,
+ XILINX_PCS_ANICR_IS, 0) <= 0)
+ return IRQ_NONE;
+
+ /* paired with xilinx_pcs_enable/disable; protects xp->pcs->link_change */
+ if (smp_load_acquire(&xp->enabled))
+ phylink_pcs_change(&xp->pcs, true);
+ return IRQ_HANDLED;
+}
+
+static int xilinx_pcs_enable(struct phylink_pcs *pcs)
+{
+ struct xilinx_pcs *xp = pcs_to_xilinx(pcs);
+ struct device *dev = &xp->mdiodev->dev;
+ int ret;
+
+ if (xp->irq < 0)
+ return 0;
+
+ ret = mdiodev_modify(xp->mdiodev, XILINX_PCS_ANICR, 0,
+ XILINX_PCS_ANICR_IE);
+ if (ret)
+ dev_err(dev, "could not clear IRQ enable: %d\n", ret);
+ else
+ /* paired with xilinx_pcs_an_irq */
+ smp_store_release(&xp->enabled, true);
+ return ret;
+}
+
+static void xilinx_pcs_disable(struct phylink_pcs *pcs)
+{
+ struct xilinx_pcs *xp = pcs_to_xilinx(pcs);
+ struct device *dev = &xp->mdiodev->dev;
+ int err;
+
+ if (xp->irq < 0)
+ return;
+
+ WRITE_ONCE(xp->enabled, false);
+ /* paired with xilinx_pcs_an_irq */
+ smp_wmb();
+
+ err = mdiodev_modify(xp->mdiodev, XILINX_PCS_ANICR,
+ XILINX_PCS_ANICR_IE, 0);
+ if (err)
+ dev_err(dev, "could not clear IRQ enable: %d\n", err);
+}
+
+static int xilinx_pcs_validate(struct phylink_pcs *pcs,
+ unsigned long *supported,
+ const struct phylink_link_state *state)
+{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(xilinx_supported) = { 0 };
+
+ phylink_set_port_modes(xilinx_supported);
+ phylink_set(xilinx_supported, Autoneg);
+ phylink_set(xilinx_supported, Pause);
+ phylink_set(xilinx_supported, Asym_Pause);
+ switch (state->interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ /* Half duplex not supported */
+ phylink_set(xilinx_supported, 10baseT_Full);
+ phylink_set(xilinx_supported, 100baseT_Full);
+ phylink_set(xilinx_supported, 1000baseT_Full);
+ break;
+ case PHY_INTERFACE_MODE_1000BASEX:
+ phylink_set(xilinx_supported, 1000baseX_Full);
+ break;
+ case PHY_INTERFACE_MODE_2500BASEX:
+ phylink_set(xilinx_supported, 2500baseX_Full);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ linkmode_and(supported, supported, xilinx_supported);
+ return 0;
+}
+
+static void xilinx_pcs_get_state(struct phylink_pcs *pcs,
+ unsigned int neg_mode,
+ struct phylink_link_state *state)
+{
+ struct xilinx_pcs *xp = pcs_to_xilinx(pcs);
+
+ phylink_mii_c22_pcs_get_state(xp->mdiodev, neg_mode, state);
+}
+
+static int xilinx_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ bool permit_pause_to_mac)
+{
+ int ret, changed = 0;
+ struct xilinx_pcs *xp = pcs_to_xilinx(pcs);
+
+ if (test_bit(PHY_INTERFACE_MODE_SGMII, pcs->supported_interfaces) &&
+ test_bit(PHY_INTERFACE_MODE_1000BASEX, pcs->supported_interfaces)) {
+ u16 ssr;
+
+ if (interface == PHY_INTERFACE_MODE_SGMII)
+ ssr = XILINX_PCS_SSR_SGMII;
+ else
+ ssr = 0;
+
+ changed = mdiodev_modify_changed(xp->mdiodev, XILINX_PCS_SSR,
+ XILINX_PCS_SSR_SGMII, ssr);
+ if (changed < 0)
+ return changed;
+ }
+
+ ret = phylink_mii_c22_pcs_config(xp->mdiodev, interface, advertising,
+ neg_mode);
+ return ret ?: changed;
+}
+
+static void xilinx_pcs_an_restart(struct phylink_pcs *pcs)
+{
+ struct xilinx_pcs *xp = pcs_to_xilinx(pcs);
+
+ phylink_mii_c22_pcs_an_restart(xp->mdiodev);
+}
+
+static void xilinx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
+ phy_interface_t interface, int speed, int duplex)
+{
+ int bmcr;
+ struct xilinx_pcs *xp = pcs_to_xilinx(pcs);
+
+ if (phylink_autoneg_inband(mode))
+ return;
+
+ bmcr = mdiodev_read(xp->mdiodev, MII_BMCR);
+ if (bmcr < 0) {
+ dev_err(&xp->mdiodev->dev, "could not read BMCR (err=%d)\n",
+ bmcr);
+ return;
+ }
+
+ bmcr &= ~(BMCR_SPEED1000 | BMCR_SPEED100);
+ switch (speed) {
+ case SPEED_2500:
+ case SPEED_1000:
+ bmcr |= BMCR_SPEED1000;
+ break;
+ case SPEED_100:
+ bmcr |= BMCR_SPEED100;
+ break;
+ case SPEED_10:
+ bmcr |= BMCR_SPEED10;
+ break;
+ default:
+ dev_err(&xp->mdiodev->dev, "invalid speed %d\n", speed);
+ }
+
+ bmcr = mdiodev_write(xp->mdiodev, MII_BMCR, bmcr);
+ if (bmcr < 0)
+ dev_err(&xp->mdiodev->dev, "could not write BMCR (err=%d)\n",
+ bmcr);
+}
+
+static const struct phylink_pcs_ops xilinx_pcs_ops = {
+ .pcs_validate = xilinx_pcs_validate,
+ .pcs_enable = xilinx_pcs_enable,
+ .pcs_disable = xilinx_pcs_disable,
+ .pcs_get_state = xilinx_pcs_get_state,
+ .pcs_config = xilinx_pcs_config,
+ .pcs_an_restart = xilinx_pcs_an_restart,
+ .pcs_link_up = xilinx_pcs_link_up,
+};
+
+static const struct clk_ops xilinx_pcs_clk_ops = { };
+
+static const phy_interface_t xilinx_pcs_interfaces[] = {
+ PHY_INTERFACE_MODE_SGMII,
+ PHY_INTERFACE_MODE_1000BASEX,
+ PHY_INTERFACE_MODE_2500BASEX,
+};
+
+static int xilinx_pcs_probe(struct mdio_device *mdiodev)
+{
+ struct device *dev = &mdiodev->dev;
+ struct fwnode_handle *fwnode = dev->fwnode;
+ int ret, i, j, mode_count;
+ struct xilinx_pcs *xp;
+ const char **modes;
+ u32 phy_id;
+
+ xp = devm_kzalloc(dev, sizeof(*xp), GFP_KERNEL);
+ if (!xp)
+ return -ENOMEM;
+ xp->mdiodev = mdiodev;
+ dev_set_drvdata(dev, xp);
+
+ xp->irq = fwnode_irq_get_byname(fwnode, "an");
+ /* There's no _optional variant, so this is the best we've got */
+ if (xp->irq < 0 && xp->irq != -EINVAL)
+ return dev_err_probe(dev, xp->irq, "could not get IRQ\n");
+
+ mode_count = fwnode_property_string_array_count(fwnode, "pcs-modes");
+ if (!mode_count)
+ mode_count = -ENODATA;
+ if (mode_count < 0) {
+ dev_err(dev, "could not read pcs-modes: %d", mode_count);
+ return mode_count;
+ }
+
+ modes = kcalloc(mode_count, sizeof(*modes), GFP_KERNEL);
+ if (!modes)
+ return -ENOMEM;
+
+ ret = fwnode_property_read_string_array(fwnode, "pcs-modes",
+ modes, mode_count);
+ if (ret < 0) {
+ dev_err(dev, "could not read pcs-modes: %d\n", ret);
+ kfree(modes);
+ return ret;
+ }
+
+ for (i = 0; i < mode_count; i++) {
+ for (j = 0; j < ARRAY_SIZE(xilinx_pcs_interfaces); j++) {
+ if (!strcmp(phy_modes(xilinx_pcs_interfaces[j]), modes[i])) {
+ __set_bit(xilinx_pcs_interfaces[j],
+ xp->pcs.supported_interfaces);
+ goto next;
+ }
+ }
+
+ dev_err(dev, "invalid pcs-mode \"%s\"\n", modes[i]);
+ kfree(modes);
+ return -EINVAL;
+next:
+ }
+
+ kfree(modes);
+ if ((test_bit(PHY_INTERFACE_MODE_SGMII, xp->pcs.supported_interfaces) ||
+ test_bit(PHY_INTERFACE_MODE_1000BASEX, xp->pcs.supported_interfaces)) &&
+ test_bit(PHY_INTERFACE_MODE_2500BASEX, xp->pcs.supported_interfaces)) {
+ dev_err(dev,
+ "Switching from SGMII or 1000Base-X to 2500Base-X not supported\n");
+ return -EINVAL;
+ }
+
+ xp->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(xp->reset))
+ return dev_err_probe(dev, PTR_ERR(xp->reset),
+ "could not get reset gpio\n");
+
+ xp->done = devm_gpiod_get_optional(dev, "done", GPIOD_IN);
+ if (IS_ERR(xp->done))
+ return dev_err_probe(dev, PTR_ERR(xp->done),
+ "could not get done gpio\n");
+
+ xp->refclk = devm_clk_get_optional_enabled(dev, "refclk");
+ if (IS_ERR(xp->refclk))
+ return dev_err_probe(dev, PTR_ERR(xp->refclk),
+ "could not get/enable reference clock\n");
+
+ gpiod_set_value_cansleep(xp->reset, 0);
+ if (xp->done) {
+ if (read_poll_timeout(gpiod_get_value_cansleep, ret, ret, 1000,
+ 100000, true, xp->done))
+ return dev_err_probe(dev, -ETIMEDOUT,
+ "timed out waiting for reset\n");
+ } else {
+ /* Just wait for a while and hope we're done */
+ usleep_range(50000, 100000);
+ }
+
+ if (fwnode_property_present(fwnode, "#clock-cells")) {
+ const char *parent = "refclk";
+ struct clk_init_data init = {
+ .name = fwnode_get_name(fwnode),
+ .ops = &xilinx_pcs_clk_ops,
+ .parent_names = &parent,
+ .num_parents = 1,
+ .flags = 0,
+ };
+
+ xp->refclk_out.init = &init;
+ ret = devm_clk_hw_register(dev, &xp->refclk_out);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "could not register refclk\n");
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+ &xp->refclk_out);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "could not register refclk\n");
+ }
+
+ /* Sanity check */
+ ret = get_phy_c22_id(mdiodev->bus, mdiodev->addr, &phy_id);
+ if (ret) {
+ dev_err_probe(dev, ret, "could not read id\n");
+ return ret;
+ }
+ if ((phy_id & 0xfffffff0) != 0x01740c00)
+ dev_warn(dev, "unknown phy id %x\n", phy_id);
+
+ if (xp->irq < 0) {
+ xp->pcs.poll = true;
+ } else {
+ /* The IRQ is enabled by default; turn it off */
+ ret = mdiodev_write(xp->mdiodev, XILINX_PCS_ANICR, 0);
+ if (ret) {
+ dev_err(dev, "could not disable IRQ: %d\n", ret);
+ return ret;
+ }
+
+ /* Some PCSs have a bad habit of re-enabling their IRQ!
+ * Request the IRQ in probe so we don't end up triggering the
+ * spurious IRQ logic.
+ */
+ ret = devm_request_threaded_irq(dev, xp->irq, NULL, xilinx_pcs_an_irq,
+ IRQF_SHARED | IRQF_ONESHOT,
+ dev_name(dev), xp);
+ if (ret) {
+ dev_err(dev, "could not request IRQ: %d\n", ret);
+ return ret;
+ }
+ }
+
+ xp->pcs.ops = &xilinx_pcs_ops;
+ ret = devm_pcs_register(dev, &xp->pcs);
+ if (ret)
+ return dev_err_probe(dev, ret, "could not register PCS\n");
+
+ if (xp->irq < 0)
+ dev_info(dev, "probed with irq=poll\n");
+ else
+ dev_info(dev, "probed with irq=%d\n", xp->irq);
+ return 0;
+}
+
+static const struct of_device_id xilinx_pcs_of_match[] = {
+ { .compatible = "xlnx,pcs-16.2", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, xilinx_timer_of_match);
+
+static struct mdio_driver xilinx_pcs_driver = {
+ .probe = xilinx_pcs_probe,
+ .mdiodrv.driver = {
+ .name = "xilinx-pcs",
+ .of_match_table = of_match_ptr(xilinx_pcs_of_match),
+ .suppress_bind_attrs = true,
+ },
+};
+mdio_module_driver(xilinx_pcs_driver);
+
+static int axienet_xilinx_pcs_fixup(struct of_changeset *ocs,
+ struct device_node *np, void *data)
+{
+#ifdef CONFIG_OF_DYNAMIC
+ unsigned int interface, mode_count, mode = 0;
+ const unsigned long *interfaces = data;
+ const char **modes;
+ int ret;
+
+ mode_count = bitmap_weight(interfaces, PHY_INTERFACE_MODE_MAX);
+ WARN_ON_ONCE(!mode_count);
+ modes = kcalloc(mode_count, sizeof(*modes), GFP_KERNEL);
+ if (!modes)
+ return -ENOMEM;
+
+ for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX)
+ modes[mode++] = phy_modes(interface);
+ ret = of_changeset_add_prop_string_array(ocs, np, "pcs-modes", modes,
+ mode_count);
+ kfree(modes);
+ if (ret)
+ return ret;
+
+ return of_changeset_add_prop_string(ocs, np, "compatible",
+ "xlnx,pcs-16.2");
+#else
+ return -ENODEV;
+#endif
+}
+
+struct phylink_pcs *axienet_xilinx_pcs_get(struct device *dev,
+ const unsigned long *interfaces)
+{
+ struct fwnode_handle *fwnode;
+ struct phylink_pcs *pcs;
+
+ fwnode = pcs_find_fwnode(dev_fwnode(dev), NULL, "phy-handle", false);
+ if (IS_ERR(fwnode))
+ return ERR_CAST(fwnode);
+
+ pcs = pcs_get_by_fwnode_compat(dev, fwnode, axienet_xilinx_pcs_fixup,
+ (void *)interfaces);
+ fwnode_handle_put(fwnode);
+ return pcs;
+}
+
+MODULE_ALIAS("platform:xilinx-pcs");
+MODULE_DESCRIPTION("Xilinx PCS driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/pcs-xilinx.h b/include/linux/pcs-xilinx.h
new file mode 100644
index 000000000000..409057fbdf34
--- /dev/null
+++ b/include/linux/pcs-xilinx.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2024 Sean Anderson <sean.anderson@seco.com>
+ */
+
+#ifndef PCS_XILINX_H
+#define PCS_XILINX_H
+
+#include <linux/err.h>
+
+struct device;
+struct phylink_pcs;
+
+#ifdef CONFIG_PCS_XILINX
+/**
+ * axienet_xilinx_pcs_get() - Compatibility function for the AXI Ethernet driver
+ * @dev: The MAC device
+ * @interfaces: The interfaces to use as a fallback
+ *
+ * This is a helper function for the AXI Ethernet driver to ensure backwards
+ * compatibility with device trees which do not include compatible strings for
+ * the PCS. It should not be used by new code.
+ *
+ * Return: a PCS, or an error pointer
+ */
+struct phylink_pcs *axienet_xilinx_pcs_get(struct device *dev,
+ const unsigned long *interfaces);
+#else
+static inline struct phylink_pcs *
+axienet_xilinx_pcs_get(struct device *dev, const unsigned long *interfaces)
+{
+ return ERR_PTR(-ENODEV);
+}
+#endif
+
+#endif /* PCS_XILINX_H */
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 08/13] net: axienet: Convert to use PCS subsystem
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (6 preceding siblings ...)
2025-04-03 18:19 ` [RFC net-next PATCH 07/13] net: pcs: Add Xilinx PCS driver Sean Anderson
@ 2025-04-03 18:19 ` Sean Anderson
2025-04-03 18:19 ` [RFC net-next PATCH 09/13] net: macb: Move most of mac_config to mac_prepare Sean Anderson
` (5 subsequent siblings)
13 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:19 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit,
Sean Anderson, Michal Simek, Radhey Shyam Pandey, Robert Hancock,
linux-arm-kernel
Convert the AXI Ethernet driver to use the PCS subsystem, including the
new Xilinx PCA/PMA driver. Unfortunately, we must use a helper to work
with bare MDIO nodes without a compatible.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
drivers/net/ethernet/xilinx/Kconfig | 1 +
drivers/net/ethernet/xilinx/xilinx_axienet.h | 4 +-
.../net/ethernet/xilinx/xilinx_axienet_main.c | 104 ++++--------------
drivers/net/pcs/Kconfig | 1 -
4 files changed, 22 insertions(+), 88 deletions(-)
diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig
index 7502214cc7d5..2eab64cf1646 100644
--- a/drivers/net/ethernet/xilinx/Kconfig
+++ b/drivers/net/ethernet/xilinx/Kconfig
@@ -27,6 +27,7 @@ config XILINX_AXI_EMAC
tristate "Xilinx 10/100/1000 AXI Ethernet support"
depends on HAS_IOMEM
depends on XILINX_DMA
+ select OF_DYNAMIC if PCS_XILINX
select PHYLINK
select DIMLIB
help
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
index 5ff742103beb..f46e862245eb 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -473,7 +473,6 @@ struct skbuf_dma_descriptor {
* @dev: Pointer to device structure
* @phylink: Pointer to phylink instance
* @phylink_config: phylink configuration settings
- * @pcs_phy: Reference to PCS/PMA PHY if used
* @pcs: phylink pcs structure for PCS PHY
* @switch_x_sgmii: Whether switchable 1000BaseX/SGMII mode is enabled in the core
* @axi_clk: AXI4-Lite bus clock
@@ -553,8 +552,7 @@ struct axienet_local {
struct phylink *phylink;
struct phylink_config phylink_config;
- struct mdio_device *pcs_phy;
- struct phylink_pcs pcs;
+ struct phylink_pcs *pcs;
bool switch_x_sgmii;
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 054abf283ab3..07487c4b2141 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -35,6 +35,8 @@
#include <linux/platform_device.h>
#include <linux/skbuff.h>
#include <linux/math64.h>
+#include <linux/pcs.h>
+#include <linux/pcs-xilinx.h>
#include <linux/phy.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
@@ -2519,63 +2521,6 @@ static const struct ethtool_ops axienet_ethtool_ops = {
.get_rmon_stats = axienet_ethtool_get_rmon_stats,
};
-static struct axienet_local *pcs_to_axienet_local(struct phylink_pcs *pcs)
-{
- return container_of(pcs, struct axienet_local, pcs);
-}
-
-static void axienet_pcs_get_state(struct phylink_pcs *pcs,
- unsigned int neg_mode,
- struct phylink_link_state *state)
-{
- struct mdio_device *pcs_phy = pcs_to_axienet_local(pcs)->pcs_phy;
-
- phylink_mii_c22_pcs_get_state(pcs_phy, neg_mode, state);
-}
-
-static void axienet_pcs_an_restart(struct phylink_pcs *pcs)
-{
- struct mdio_device *pcs_phy = pcs_to_axienet_local(pcs)->pcs_phy;
-
- phylink_mii_c22_pcs_an_restart(pcs_phy);
-}
-
-static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
- phy_interface_t interface,
- const unsigned long *advertising,
- bool permit_pause_to_mac)
-{
- struct mdio_device *pcs_phy = pcs_to_axienet_local(pcs)->pcs_phy;
- struct net_device *ndev = pcs_to_axienet_local(pcs)->ndev;
- struct axienet_local *lp = netdev_priv(ndev);
- int ret;
-
- if (lp->switch_x_sgmii) {
- ret = mdiodev_write(pcs_phy, XLNX_MII_STD_SELECT_REG,
- interface == PHY_INTERFACE_MODE_SGMII ?
- XLNX_MII_STD_SELECT_SGMII : 0);
- if (ret < 0) {
- netdev_warn(ndev,
- "Failed to switch PHY interface: %d\n",
- ret);
- return ret;
- }
- }
-
- ret = phylink_mii_c22_pcs_config(pcs_phy, interface, advertising,
- neg_mode);
- if (ret < 0)
- netdev_warn(ndev, "Failed to configure PCS: %d\n", ret);
-
- return ret;
-}
-
-static const struct phylink_pcs_ops axienet_pcs_ops = {
- .pcs_get_state = axienet_pcs_get_state,
- .pcs_config = axienet_pcs_config,
- .pcs_an_restart = axienet_pcs_an_restart,
-};
-
static struct phylink_pcs *axienet_mac_select_pcs(struct phylink_config *config,
phy_interface_t interface)
{
@@ -2583,8 +2528,8 @@ static struct phylink_pcs *axienet_mac_select_pcs(struct phylink_config *config,
struct axienet_local *lp = netdev_priv(ndev);
if (interface == PHY_INTERFACE_MODE_1000BASEX ||
- interface == PHY_INTERFACE_MODE_SGMII)
- return &lp->pcs;
+ interface == PHY_INTERFACE_MODE_SGMII)
+ return lp->pcs;
return NULL;
}
@@ -3056,28 +3001,23 @@ static int axienet_probe(struct platform_device *pdev)
if (lp->phy_mode == PHY_INTERFACE_MODE_SGMII ||
lp->phy_mode == PHY_INTERFACE_MODE_1000BASEX) {
- np = of_parse_phandle(pdev->dev.of_node, "pcs-handle", 0);
- if (!np) {
- /* Deprecated: Always use "pcs-handle" for pcs_phy.
- * Falling back to "phy-handle" here is only for
- * backward compatibility with old device trees.
- */
- np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
- }
- if (!np) {
- dev_err(&pdev->dev, "pcs-handle (preferred) or phy-handle required for 1000BaseX/SGMII\n");
- ret = -EINVAL;
- goto cleanup_mdio;
- }
- lp->pcs_phy = of_mdio_find_device(np);
- if (!lp->pcs_phy) {
- ret = -EPROBE_DEFER;
- of_node_put(np);
+ DECLARE_PHY_INTERFACE_MASK(interfaces);
+
+ phy_interface_zero(interfaces);
+ if (lp->switch_x_sgmii ||
+ lp->phy_mode == PHY_INTERFACE_MODE_SGMII)
+ __set_bit(PHY_INTERFACE_MODE_SGMII, interfaces);
+ if (lp->switch_x_sgmii ||
+ lp->phy_mode == PHY_INTERFACE_MODE_1000BASEX)
+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces);
+
+ lp->pcs = axienet_xilinx_pcs_get(&pdev->dev, interfaces);
+ if (IS_ERR(lp->pcs)) {
+ ret = PTR_ERR(lp->pcs);
+ dev_err_probe(&pdev->dev, ret,
+ "could not get PCS for 1000BASE-X/SGMII\n");
goto cleanup_mdio;
}
- of_node_put(np);
- lp->pcs.ops = &axienet_pcs_ops;
- lp->pcs.poll = true;
}
lp->phylink_config.dev = &ndev->dev;
@@ -3115,8 +3055,6 @@ static int axienet_probe(struct platform_device *pdev)
phylink_destroy(lp->phylink);
cleanup_mdio:
- if (lp->pcs_phy)
- put_device(&lp->pcs_phy->dev);
if (lp->mii_bus)
axienet_mdio_teardown(lp);
cleanup_clk:
@@ -3139,9 +3077,7 @@ static void axienet_remove(struct platform_device *pdev)
if (lp->phylink)
phylink_destroy(lp->phylink);
- if (lp->pcs_phy)
- put_device(&lp->pcs_phy->dev);
-
+ pcs_put(&pdev->dev, lp->pcs);
axienet_mdio_teardown(lp);
clk_bulk_disable_unprepare(XAE_NUM_MISC_CLOCKS, lp->misc_clks);
diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig
index c28b4630492a..d9369a525498 100644
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -63,7 +63,6 @@ config PCS_XILINX
depends on PCS
select MDIO_DEVICE
select PHYLINK
- default XILINX_AXI_EMAC
tristate "Xilinx PCS driver"
help
PCS driver for the Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII device.
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 09/13] net: macb: Move most of mac_config to mac_prepare
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (7 preceding siblings ...)
2025-04-03 18:19 ` [RFC net-next PATCH 08/13] net: axienet: Convert to use PCS subsystem Sean Anderson
@ 2025-04-03 18:19 ` Sean Anderson
2025-04-03 18:27 ` [RFC net-next PATCH 10/13] net: macb: Support external PCSs Sean Anderson
` (4 subsequent siblings)
13 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:19 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit,
Sean Anderson, Claudiu Beznea, Nicolas Ferre
mac_prepare is called every time the interface is changed, so we can do
all of our configuration there, instead of in mac_config. This will be
useful for the next patch where we will set the PCS bit based on whether
we are using our internal PCS. No functional change intended.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
drivers/net/ethernet/cadence/macb_main.c | 209 ++++++++++++++---------
drivers/net/pcs/Kconfig | 1 +
2 files changed, 133 insertions(+), 77 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 1fe8ec37491b..665fc3c4d39a 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -549,19 +549,91 @@ static void macb_set_tx_clk(struct macb *bp, int speed)
netdev_err(bp->dev, "adjusting tx_clk failed.\n");
}
-static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
- phy_interface_t interface, int speed,
- int duplex)
-{
- struct macb *bp = container_of(pcs, struct macb, phylink_usx_pcs);
- u32 config;
-
- config = gem_readl(bp, USX_CONTROL);
- config = GEM_BFINS(SERDES_RATE, MACB_SERDES_RATE_10G, config);
- config = GEM_BFINS(USX_CTRL_SPEED, HS_SPEED_10000M, config);
- config &= ~(GEM_BIT(TX_SCR_BYPASS) | GEM_BIT(RX_SCR_BYPASS));
- config |= GEM_BIT(TX_EN);
- gem_writel(bp, USX_CONTROL, config);
+static void macb_pcs_get_state(struct phylink_pcs *pcs,
+ struct phylink_link_state *state)
+{
+ struct macb *bp = container_of(pcs, struct macb, phylink_sgmii_pcs);
+
+ phylink_mii_c22_pcs_decode_state(state, gem_readl(bp, PCSSTS),
+ gem_readl(bp, PCSANLPBASE));
+}
+
+/**
+ * macb_pcs_config_an() - Configure autonegotiation settings for PCSs
+ * @bp - The macb to operate on
+ * @neg_mode - The autonegotiation mode
+ * @interface - The interface to use
+ * @advertising - The advertisement mask
+ *
+ * This provides common configuration for PCS autonegotiation.
+ *
+ * Context: Call with @bp->lock held.
+ * Return: 1 if any registers were changed; 0 otherwise
+ */
+static int macb_pcs_config_an(struct macb *bp, unsigned int neg_mode,
+ phy_interface_t interface,
+ const unsigned long *advertising)
+{
+ bool changed = false;
+ int old, new;
+
+ old = gem_readl(bp, PCSANADV);
+ new = phylink_mii_c22_pcs_encode_advertisement(interface, advertising);
+ if (new != -EINVAL && old != new) {
+ changed = true;
+ gem_writel(bp, PCSANADV, new);
+ }
+
+ old = new = gem_readl(bp, PCSCNTRL);
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
+ new |= BMCR_ANENABLE;
+ else
+ new &= ~BMCR_ANENABLE;
+ if (old != new) {
+ changed = true;
+ gem_writel(bp, PCSCNTRL, new);
+ }
+ return changed;
+}
+
+static int macb_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ bool permit_pause_to_mac)
+{
+ struct macb *bp = container_of(pcs, struct macb, phylink_sgmii_pcs);
+ bool changed = false;
+ unsigned long flags;
+ u32 old, new;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ old = new = gem_readl(bp, NCFGR);
+ new |= GEM_BIT(SGMIIEN);
+ if (old != new) {
+ changed = true;
+ gem_writel(bp, NCFGR, new);
+ }
+
+ if (macb_pcs_config_an(bp, mode, interface, advertising))
+ changed = true;
+
+ spin_unlock_irqrestore(&bp->lock, flags);
+ return changed;
+}
+
+static void macb_pcs_an_restart(struct phylink_pcs *pcs)
+{
+ struct macb *bp = container_of(pcs, struct macb, phylink_sgmii_pcs);
+ u32 bmcr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->lock, flags);
+
+ bmcr = gem_readl(bp, PCSCNTRL);
+ bmcr |= BMCR_ANENABLE;
+ gem_writel(bp, PCSCNTRL, bmcr);
+
+ spin_lock_irqsave(&bp->lock, flags);
}
static void macb_usx_pcs_get_state(struct phylink_pcs *pcs,
@@ -589,45 +661,60 @@ static int macb_usx_pcs_config(struct phylink_pcs *pcs,
bool permit_pause_to_mac)
{
struct macb *bp = container_of(pcs, struct macb, phylink_usx_pcs);
+ unsigned long flags;
+ bool changed;
+ u16 old, new;
- gem_writel(bp, USX_CONTROL, gem_readl(bp, USX_CONTROL) |
- GEM_BIT(SIGNAL_OK));
+ spin_lock_irqsave(&bp->lock, flags);
+ if (macb_pcs_config_an(bp, neg_mode, interface, advertising))
+ changed = true;
- return 0;
-}
+ old = new = gem_readl(bp, USX_CONTROL);
+ new |= GEM_BIT(SIGNAL_OK);
+ if (old != new) {
+ changed = true;
+ gem_writel(bp, USX_CONTROL, new);
+ }
-static void macb_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
- struct phylink_link_state *state)
-{
- state->link = 0;
-}
+ old = new = gem_readl(bp, USX_CONTROL);
+ new = GEM_BFINS(SERDES_RATE, MACB_SERDES_RATE_10G, new);
+ new = GEM_BFINS(USX_CTRL_SPEED, HS_SPEED_10000M, new);
+ new &= ~(GEM_BIT(TX_SCR_BYPASS) | GEM_BIT(RX_SCR_BYPASS));
+ new |= GEM_BIT(TX_EN);
+ if (old != new) {
+ changed = true;
+ gem_writel(bp, USX_CONTROL, new);
+ }
-static void macb_pcs_an_restart(struct phylink_pcs *pcs)
-{
- /* Not supported */
-}
-
-static int macb_pcs_config(struct phylink_pcs *pcs,
- unsigned int neg_mode,
- phy_interface_t interface,
- const unsigned long *advertising,
- bool permit_pause_to_mac)
-{
- return 0;
+ spin_unlock_irqrestore(&bp->lock, flags);
+ return changed;
}
static const struct phylink_pcs_ops macb_phylink_usx_pcs_ops = {
.pcs_get_state = macb_usx_pcs_get_state,
.pcs_config = macb_usx_pcs_config,
- .pcs_link_up = macb_usx_pcs_link_up,
};
static const struct phylink_pcs_ops macb_phylink_pcs_ops = {
.pcs_get_state = macb_pcs_get_state,
- .pcs_an_restart = macb_pcs_an_restart,
.pcs_config = macb_pcs_config,
+ .pcs_an_restart = macb_pcs_an_restart,
};
+static struct phylink_pcs *macb_mac_select_pcs(struct phylink_config *config,
+ phy_interface_t interface)
+{
+ struct net_device *ndev = to_net_dev(config->dev);
+ struct macb *bp = netdev_priv(ndev);
+
+ if (interface == PHY_INTERFACE_MODE_10GBASER)
+ return &bp->phylink_usx_pcs;
+ else if (interface == PHY_INTERFACE_MODE_SGMII)
+ return &bp->phylink_sgmii_pcs;
+ else
+ return NULL;
+}
+
static void macb_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
@@ -646,18 +733,14 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
if (state->interface == PHY_INTERFACE_MODE_RMII)
ctrl |= MACB_BIT(RM9200_RMII);
} else if (macb_is_gem(bp)) {
- ctrl &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
- ncr &= ~GEM_BIT(ENABLE_HS_MAC);
-
- if (state->interface == PHY_INTERFACE_MODE_SGMII) {
- ctrl |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
- } else if (state->interface == PHY_INTERFACE_MODE_10GBASER) {
+ if (macb_mac_select_pcs(config, state->interface))
ctrl |= GEM_BIT(PCSSEL);
- ncr |= GEM_BIT(ENABLE_HS_MAC);
- } else if (bp->caps & MACB_CAPS_MIIONRGMII &&
- bp->phy_interface == PHY_INTERFACE_MODE_MII) {
+ else
+ ctrl &= ~GEM_BIT(PCSSEL);
+
+ if (bp->caps & MACB_CAPS_MIIONRGMII &&
+ bp->phy_interface == PHY_INTERFACE_MODE_MII)
ncr |= MACB_BIT(MIIONRGMII);
- }
}
/* Apply the new configuration, if any */
@@ -667,22 +750,6 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
if (old_ncr ^ ncr)
macb_or_gem_writel(bp, NCR, ncr);
- /* Disable AN for SGMII fixed link configuration, enable otherwise.
- * Must be written after PCSSEL is set in NCFGR,
- * otherwise writes will not take effect.
- */
- if (macb_is_gem(bp) && state->interface == PHY_INTERFACE_MODE_SGMII) {
- u32 pcsctrl, old_pcsctrl;
-
- old_pcsctrl = gem_readl(bp, PCSCNTRL);
- if (mode == MLO_AN_FIXED)
- pcsctrl = old_pcsctrl & ~GEM_BIT(PCSAUTONEG);
- else
- pcsctrl = old_pcsctrl | GEM_BIT(PCSAUTONEG);
- if (old_pcsctrl != pcsctrl)
- gem_writel(bp, PCSCNTRL, pcsctrl);
- }
-
spin_unlock_irqrestore(&bp->lock, flags);
}
@@ -735,10 +802,12 @@ static void macb_mac_link_up(struct phylink_config *config,
if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) {
ctrl &= ~MACB_BIT(PAE);
if (macb_is_gem(bp)) {
- ctrl &= ~GEM_BIT(GBE);
+ ctrl &= ~(GEM_BIT(GBE) | GEM_BIT(ENABLE_HS_MAC));
if (speed == SPEED_1000)
ctrl |= GEM_BIT(GBE);
+ else if (speed == SPEED_10000)
+ ctrl |= GEM_BIT(ENABLE_HS_MAC);
}
if (rx_pause)
@@ -776,20 +845,6 @@ static void macb_mac_link_up(struct phylink_config *config,
netif_tx_wake_all_queues(ndev);
}
-static struct phylink_pcs *macb_mac_select_pcs(struct phylink_config *config,
- phy_interface_t interface)
-{
- struct net_device *ndev = to_net_dev(config->dev);
- struct macb *bp = netdev_priv(ndev);
-
- if (interface == PHY_INTERFACE_MODE_10GBASER)
- return &bp->phylink_usx_pcs;
- else if (interface == PHY_INTERFACE_MODE_SGMII)
- return &bp->phylink_sgmii_pcs;
- else
- return NULL;
-}
-
static const struct phylink_mac_ops macb_phylink_ops = {
.mac_select_pcs = macb_mac_select_pcs,
.mac_config = macb_mac_config,
diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig
index d9369a525498..c28b4630492a 100644
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -63,6 +63,7 @@ config PCS_XILINX
depends on PCS
select MDIO_DEVICE
select PHYLINK
+ default XILINX_AXI_EMAC
tristate "Xilinx PCS driver"
help
PCS driver for the Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII device.
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 10/13] net: macb: Support external PCSs
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (8 preceding siblings ...)
2025-04-03 18:19 ` [RFC net-next PATCH 09/13] net: macb: Move most of mac_config to mac_prepare Sean Anderson
@ 2025-04-03 18:27 ` Sean Anderson
2025-04-03 20:31 ` Russell King (Oracle)
2025-04-03 18:27 ` [RFC net-next PATCH 11/13] of: property: Add device link support for PCS Sean Anderson
` (3 subsequent siblings)
13 siblings, 1 reply; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:27 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: Christian Marangi, Heiner Kallweit, linux-kernel, upstream,
Claudiu Beznea, Nicolas Ferre, Sean Anderson
This adds support for external PCSs. For example, the Xilinx UltraScale+
processor exposes its GMII interface to the FPGA fabric. This fabric may
implement PCS to convert GMII to a serial interface such as SGMII or
1000BASE-X. When present, the external PCS takes precedence over the
internal PCSs.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
drivers/net/ethernet/cadence/macb.h | 1 +
drivers/net/ethernet/cadence/macb_main.c | 30 ++++++++++++++++++++----
2 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index c9a5c8beb2fa..9d310814f052 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -1291,6 +1291,7 @@ struct macb {
struct phylink_config phylink_config;
struct phylink_pcs phylink_usx_pcs;
struct phylink_pcs phylink_sgmii_pcs;
+ struct phylink_pcs *phylink_ext_pcs;
u32 caps;
unsigned int dma_burst_length;
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 665fc3c4d39a..65cdf3b478fc 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -21,6 +21,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/dma-mapping.h>
+#include <linux/pcs.h>
#include <linux/platform_device.h>
#include <linux/phylink.h>
#include <linux/of.h>
@@ -549,12 +550,12 @@ static void macb_set_tx_clk(struct macb *bp, int speed)
netdev_err(bp->dev, "adjusting tx_clk failed.\n");
}
-static void macb_pcs_get_state(struct phylink_pcs *pcs,
+static void macb_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
struct phylink_link_state *state)
{
struct macb *bp = container_of(pcs, struct macb, phylink_sgmii_pcs);
- phylink_mii_c22_pcs_decode_state(state, gem_readl(bp, PCSSTS),
+ phylink_mii_c22_pcs_decode_state(state, neg_mode, gem_readl(bp, PCSSTS),
gem_readl(bp, PCSANLPBASE));
}
@@ -707,7 +708,10 @@ static struct phylink_pcs *macb_mac_select_pcs(struct phylink_config *config,
struct net_device *ndev = to_net_dev(config->dev);
struct macb *bp = netdev_priv(ndev);
- if (interface == PHY_INTERFACE_MODE_10GBASER)
+ if (bp->phylink_ext_pcs &&
+ test_bit(interface, bp->phylink_ext_pcs->supported_interfaces))
+ return bp->phylink_ext_pcs;
+ else if (interface == PHY_INTERFACE_MODE_10GBASER)
return &bp->phylink_usx_pcs;
else if (interface == PHY_INTERFACE_MODE_SGMII)
return &bp->phylink_sgmii_pcs;
@@ -733,7 +737,10 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
if (state->interface == PHY_INTERFACE_MODE_RMII)
ctrl |= MACB_BIT(RM9200_RMII);
} else if (macb_is_gem(bp)) {
- if (macb_mac_select_pcs(config, state->interface))
+ struct phylink_pcs *pcs = macb_mac_select_pcs(config,
+ state->interface);
+
+ if (pcs && pcs != bp->phylink_ext_pcs)
ctrl |= GEM_BIT(PCSSEL);
else
ctrl &= ~GEM_BIT(PCSSEL);
@@ -907,6 +914,14 @@ static int macb_mii_probe(struct net_device *dev)
bp->phylink_sgmii_pcs.ops = &macb_phylink_pcs_ops;
bp->phylink_usx_pcs.ops = &macb_phylink_usx_pcs_ops;
+ bp->phylink_ext_pcs = pcs_get_by_fwnode_optional(&bp->pdev->dev,
+ bp->pdev->dev.fwnode,
+ NULL);
+ if (IS_ERR(bp->phylink_ext_pcs))
+ return dev_err_probe(&bp->pdev->dev,
+ PTR_ERR(bp->phylink_ext_pcs),
+ "Could not get external PCS\n");
+
bp->phylink_config.dev = &dev->dev;
bp->phylink_config.type = PHYLINK_NETDEV;
bp->phylink_config.mac_managed_pm = true;
@@ -924,6 +939,11 @@ static int macb_mii_probe(struct net_device *dev)
__set_bit(PHY_INTERFACE_MODE_RMII,
bp->phylink_config.supported_interfaces);
+ if (bp->phylink_ext_pcs)
+ phy_interface_or(bp->phylink_config.supported_interfaces,
+ bp->phylink_config.supported_interfaces,
+ bp->phylink_ext_pcs->supported_interfaces);
+
/* Determine what modes are supported */
if (macb_is_gem(bp) && (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)) {
bp->phylink_config.mac_capabilities |= MAC_1000FD;
@@ -950,6 +970,7 @@ static int macb_mii_probe(struct net_device *dev)
if (IS_ERR(bp->phylink)) {
netdev_err(dev, "Could not create a phylink instance (%ld)\n",
PTR_ERR(bp->phylink));
+ pcs_put(&bp->pdev->dev, bp->phylink_ext_pcs);
return PTR_ERR(bp->phylink);
}
@@ -5462,6 +5483,7 @@ static void macb_remove(struct platform_device *pdev)
bp->rx_clk, bp->tsu_clk);
pm_runtime_set_suspended(&pdev->dev);
}
+ pcs_put(&pdev->dev, bp->phylink_ext_pcs);
phylink_destroy(bp->phylink);
free_netdev(dev);
}
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 11/13] of: property: Add device link support for PCS
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (9 preceding siblings ...)
2025-04-03 18:27 ` [RFC net-next PATCH 10/13] net: macb: Support external PCSs Sean Anderson
@ 2025-04-03 18:27 ` Sean Anderson
2025-04-03 18:32 ` Saravana Kannan
2025-04-03 18:28 ` [RFC net-next PATCH 12/13] arm64: dts: Add compatible strings for Lynx PCSs Sean Anderson
` (2 subsequent siblings)
13 siblings, 1 reply; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:27 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: Christian Marangi, Heiner Kallweit, linux-kernel, upstream,
Rob Herring, Saravana Kannan, devicetree, Sean Anderson
This adds device link support for PCS devices, providing
better probe ordering.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
drivers/of/property.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/of/property.c b/drivers/of/property.c
index c1feb631e383..f3e0c390ddba 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -1379,6 +1379,7 @@ DEFINE_SIMPLE_PROP(pses, "pses", "#pse-cells")
DEFINE_SIMPLE_PROP(power_supplies, "power-supplies", NULL)
DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
+DEFINE_SIMPLE_PROP(pcs_handle, "pcs-handle", NULL)
static struct device_node *parse_gpios(struct device_node *np,
const char *prop_name, int index)
@@ -1535,6 +1536,7 @@ static const struct supplier_bindings of_supplier_bindings[] = {
.parse_prop = parse_post_init_providers,
.fwlink_flags = FWLINK_FLAG_IGNORE,
},
+ { .parse_prop = parse_pcs_handle, },
{}
};
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 12/13] arm64: dts: Add compatible strings for Lynx PCSs
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (10 preceding siblings ...)
2025-04-03 18:27 ` [RFC net-next PATCH 11/13] of: property: Add device link support for PCS Sean Anderson
@ 2025-04-03 18:28 ` Sean Anderson
2025-04-03 18:30 ` [RFC net-next PATCH 13/13] powerpc: " Sean Anderson
2025-04-07 16:27 ` [RFC net-next PATCH 00/13] Add PCS core support Kory Maincent
13 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:28 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: Christian Marangi, Heiner Kallweit, linux-kernel, upstream,
Conor Dooley, Krzysztof Kozlowski, Rob Herring, Shawn Guo,
devicetree, linux-arm-kernel, Sean Anderson
This adds appropriate compatible strings for Lynx PCSs on arm64 QorIQ
platforms. This also changes the node name to avoid warnings from
ethernet-phy.yaml.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
.../arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 48 +++++++++++------
.../arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 54 ++++++++++++-------
.../dts/freescale/qoriq-fman3-0-10g-0.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-10g-1.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-0.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-1.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-2.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-3.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-4.dtsi | 3 +-
.../dts/freescale/qoriq-fman3-0-1g-5.dtsi | 3 +-
10 files changed, 84 insertions(+), 42 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
index 9421fdd7e30e..90c1631c958e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
@@ -554,7 +554,8 @@ pcs_mdio1: mdio@8c07000 {
#size-cells = <0>;
status = "disabled";
- pcs1: ethernet-phy@0 {
+ pcs1: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -567,7 +568,8 @@ pcs_mdio2: mdio@8c0b000 {
#size-cells = <0>;
status = "disabled";
- pcs2: ethernet-phy@0 {
+ pcs2: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -580,7 +582,8 @@ pcs_mdio3: mdio@8c0f000 {
#size-cells = <0>;
status = "disabled";
- pcs3: ethernet-phy@0 {
+ pcs3: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -593,7 +596,8 @@ pcs_mdio4: mdio@8c13000 {
#size-cells = <0>;
status = "disabled";
- pcs4: ethernet-phy@0 {
+ pcs4: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -606,7 +610,8 @@ pcs_mdio5: mdio@8c17000 {
#size-cells = <0>;
status = "disabled";
- pcs5: ethernet-phy@0 {
+ pcs5: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -619,7 +624,8 @@ pcs_mdio6: mdio@8c1b000 {
#size-cells = <0>;
status = "disabled";
- pcs6: ethernet-phy@0 {
+ pcs6: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -632,7 +638,8 @@ pcs_mdio7: mdio@8c1f000 {
#size-cells = <0>;
status = "disabled";
- pcs7: ethernet-phy@0 {
+ pcs7: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -645,7 +652,8 @@ pcs_mdio8: mdio@8c23000 {
#size-cells = <0>;
status = "disabled";
- pcs8: ethernet-phy@0 {
+ pcs8: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -658,7 +666,8 @@ pcs_mdio9: mdio@8c27000 {
#size-cells = <0>;
status = "disabled";
- pcs9: ethernet-phy@0 {
+ pcs9: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -671,7 +680,8 @@ pcs_mdio10: mdio@8c2b000 {
#size-cells = <0>;
status = "disabled";
- pcs10: ethernet-phy@0 {
+ pcs10: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -684,7 +694,8 @@ pcs_mdio11: mdio@8c2f000 {
#size-cells = <0>;
status = "disabled";
- pcs11: ethernet-phy@0 {
+ pcs11: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -697,7 +708,8 @@ pcs_mdio12: mdio@8c33000 {
#size-cells = <0>;
status = "disabled";
- pcs12: ethernet-phy@0 {
+ pcs12: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -710,7 +722,8 @@ pcs_mdio13: mdio@8c37000 {
#size-cells = <0>;
status = "disabled";
- pcs13: ethernet-phy@0 {
+ pcs13: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -723,7 +736,8 @@ pcs_mdio14: mdio@8c3b000 {
#size-cells = <0>;
status = "disabled";
- pcs14: ethernet-phy@0 {
+ pcs14: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -736,7 +750,8 @@ pcs_mdio15: mdio@8c3f000 {
#size-cells = <0>;
status = "disabled";
- pcs15: ethernet-phy@0 {
+ pcs15: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -749,7 +764,8 @@ pcs_mdio16: mdio@8c43000 {
#size-cells = <0>;
status = "disabled";
- pcs16: ethernet-phy@0 {
+ pcs16: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
index c9541403bcd8..f35da67b6e61 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
@@ -1474,7 +1474,8 @@ pcs_mdio1: mdio@8c07000 {
#size-cells = <0>;
status = "disabled";
- pcs1: ethernet-phy@0 {
+ pcs1: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1487,7 +1488,8 @@ pcs_mdio2: mdio@8c0b000 {
#size-cells = <0>;
status = "disabled";
- pcs2: ethernet-phy@0 {
+ pcs2: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1500,7 +1502,8 @@ pcs_mdio3: mdio@8c0f000 {
#size-cells = <0>;
status = "disabled";
- pcs3: ethernet-phy@0 {
+ pcs3: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1513,7 +1516,8 @@ pcs_mdio4: mdio@8c13000 {
#size-cells = <0>;
status = "disabled";
- pcs4: ethernet-phy@0 {
+ pcs4: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1526,7 +1530,8 @@ pcs_mdio5: mdio@8c17000 {
#size-cells = <0>;
status = "disabled";
- pcs5: ethernet-phy@0 {
+ pcs5: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1539,7 +1544,8 @@ pcs_mdio6: mdio@8c1b000 {
#size-cells = <0>;
status = "disabled";
- pcs6: ethernet-phy@0 {
+ pcs6: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1552,7 +1558,8 @@ pcs_mdio7: mdio@8c1f000 {
#size-cells = <0>;
status = "disabled";
- pcs7: ethernet-phy@0 {
+ pcs7: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1565,7 +1572,8 @@ pcs_mdio8: mdio@8c23000 {
#size-cells = <0>;
status = "disabled";
- pcs8: ethernet-phy@0 {
+ pcs8: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1578,7 +1586,8 @@ pcs_mdio9: mdio@8c27000 {
#size-cells = <0>;
status = "disabled";
- pcs9: ethernet-phy@0 {
+ pcs9: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1591,7 +1600,8 @@ pcs_mdio10: mdio@8c2b000 {
#size-cells = <0>;
status = "disabled";
- pcs10: ethernet-phy@0 {
+ pcs10: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1604,7 +1614,8 @@ pcs_mdio11: mdio@8c2f000 {
#size-cells = <0>;
status = "disabled";
- pcs11: ethernet-phy@0 {
+ pcs11: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1617,7 +1628,8 @@ pcs_mdio12: mdio@8c33000 {
#size-cells = <0>;
status = "disabled";
- pcs12: ethernet-phy@0 {
+ pcs12: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1630,7 +1642,8 @@ pcs_mdio13: mdio@8c37000 {
#size-cells = <0>;
status = "disabled";
- pcs13: ethernet-phy@0 {
+ pcs13: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1643,7 +1656,8 @@ pcs_mdio14: mdio@8c3b000 {
#size-cells = <0>;
status = "disabled";
- pcs14: ethernet-phy@0 {
+ pcs14: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1656,7 +1670,8 @@ pcs_mdio15: mdio@8c3f000 {
#size-cells = <0>;
status = "disabled";
- pcs15: ethernet-phy@0 {
+ pcs15: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1669,7 +1684,8 @@ pcs_mdio16: mdio@8c43000 {
#size-cells = <0>;
status = "disabled";
- pcs16: ethernet-phy@0 {
+ pcs16: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1682,7 +1698,8 @@ pcs_mdio17: mdio@8c47000 {
#size-cells = <0>;
status = "disabled";
- pcs17: ethernet-phy@0 {
+ pcs17: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
@@ -1695,7 +1712,8 @@ pcs_mdio18: mdio@8c4b000 {
#size-cells = <0>;
status = "disabled";
- pcs18: ethernet-phy@0 {
+ pcs18: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi
index 1b2b20c6126d..e11c6ddab457 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi
@@ -36,7 +36,8 @@ mdio@f1000 {
compatible = "fsl,fman-memac-mdio";
reg = <0xf1000 0x1000>;
- pcsphy6: ethernet-phy@0 {
+ pcsphy6: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi
index 55d78f6f7c6c..c8b7f2c61a8f 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi
@@ -36,7 +36,8 @@ mdio@f3000 {
compatible = "fsl,fman-memac-mdio";
reg = <0xf3000 0x1000>;
- pcsphy7: ethernet-phy@0 {
+ pcsphy7: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi
index 18916a860c2e..1a4bcb38646e 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi
@@ -35,7 +35,8 @@ mdio@e1000 {
compatible = "fsl,fman-memac-mdio";
reg = <0xe1000 0x1000>;
- pcsphy0: ethernet-phy@0 {
+ pcsphy0: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi
index e90af445a293..6a4d55f9d045 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi
@@ -35,7 +35,8 @@ mdio@e3000 {
compatible = "fsl,fman-memac-mdio";
reg = <0xe3000 0x1000>;
- pcsphy1: ethernet-phy@0 {
+ pcsphy1: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi
index fec93905bc81..0de30065aa3b 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi
@@ -35,7 +35,8 @@ mdio@e5000 {
compatible = "fsl,fman-memac-mdio";
reg = <0xe5000 0x1000>;
- pcsphy2: ethernet-phy@0 {
+ pcsphy2: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi
index 2aa953faa62b..2f8064b1039f 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi
@@ -35,7 +35,8 @@ mdio@e7000 {
compatible = "fsl,fman-memac-mdio";
reg = <0xe7000 0x1000>;
- pcsphy3: ethernet-phy@0 {
+ pcsphy3: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi
index 948e39411415..6246f1fdac2d 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi
@@ -35,7 +35,8 @@ mdio@e9000 {
compatible = "fsl,fman-memac-mdio";
reg = <0xe9000 0x1000>;
- pcsphy4: ethernet-phy@0 {
+ pcsphy4: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi
index 01b78c0463a7..c205e1e8bfc8 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi
@@ -34,7 +34,8 @@ mdio@eb000 {
compatible = "fsl,fman-memac-mdio";
reg = <0xeb000 0x1000>;
- pcsphy5: ethernet-phy@0 {
+ pcsphy5: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [RFC net-next PATCH 13/13] powerpc: dts: Add compatible strings for Lynx PCSs
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (11 preceding siblings ...)
2025-04-03 18:28 ` [RFC net-next PATCH 12/13] arm64: dts: Add compatible strings for Lynx PCSs Sean Anderson
@ 2025-04-03 18:30 ` Sean Anderson
2025-04-07 16:27 ` [RFC net-next PATCH 00/13] Add PCS core support Kory Maincent
13 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 18:30 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King
Cc: Christian Marangi, Heiner Kallweit, linux-kernel, upstream,
Conor Dooley, Krzysztof Kozlowski, Rob Herring, devicetree,
Christophe Leroy, Madhavan Srinivasan, Michael Ellerman,
Naveen N Rao, Nicholas Piggin, linuxppc-dev, Sean Anderson
This adds appropriate compatible strings for Lynx PCSs on PowerPC QorIQ
platforms. This also changes the node name to avoid warnings from
ethernet-phy.yaml.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi | 3 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi | 3 ++-
20 files changed, 40 insertions(+), 20 deletions(-)
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi
index 7e70977f282a..61d52044e7b4 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi
@@ -66,7 +66,8 @@ mdio@e1000 {
reg = <0xe1000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy0: ethernet-phy@0 {
+ pcsphy0: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi
index 5f89f7c1761f..78d6e49655f4 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi
@@ -70,7 +70,8 @@ mdio@f1000 {
reg = <0xf1000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy6: ethernet-phy@0 {
+ pcsphy6: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi
index 71eb75e82c2e..5ffd1c2efaee 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi
@@ -73,7 +73,8 @@ mdio@e3000 {
reg = <0xe3000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy1: ethernet-phy@0 {
+ pcsphy1: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi
index fb7032ddb7fc..e0325f09ce5f 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi
@@ -70,7 +70,8 @@ mdio@f3000 {
reg = <0xf3000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy7: ethernet-phy@0 {
+ pcsphy7: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi
index 6b3609574b0f..8e6f6c5f0f2e 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi
@@ -38,7 +38,8 @@ mdio@e1000 {
reg = <0xe1000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy0: ethernet-phy@0 {
+ pcsphy0: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi
index 28ed1a85a436..2cd3f0688cb1 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi
@@ -38,7 +38,8 @@ mdio@e3000 {
reg = <0xe3000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy1: ethernet-phy@0 {
+ pcsphy1: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi
index 1089d6861bfb..9f8c38a629cb 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi
@@ -62,7 +62,8 @@ mdio@e1000 {
reg = <0xe1000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy0: ethernet-phy@0 {
+ pcsphy0: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi
index a95bbb4fc827..248a57129d40 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi
@@ -69,7 +69,8 @@ mdio@e3000 {
reg = <0xe3000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy1: ethernet-phy@0 {
+ pcsphy1: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi
index 7d5af0147a25..73cef28db890 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi
@@ -69,7 +69,8 @@ mdio@e5000 {
reg = <0xe5000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy2: ethernet-phy@0 {
+ pcsphy2: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi
index 61e5466ec854..4657b6a8fb78 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi
@@ -69,7 +69,8 @@ mdio@e7000 {
reg = <0xe7000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy3: ethernet-phy@0 {
+ pcsphy3: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi
index 3ba0cdafc069..ac322e5803c2 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi
@@ -62,7 +62,8 @@ mdio@e9000 {
reg = <0xe9000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy4: ethernet-phy@0 {
+ pcsphy4: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi
index 51748de0a289..68ffa2c65e03 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi
@@ -69,7 +69,8 @@ mdio@eb000 {
reg = <0xeb000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy5: ethernet-phy@0 {
+ pcsphy5: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi
index ee4f5170f632..caf28fcbd55c 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi
@@ -70,7 +70,8 @@ mdio@f1000 {
reg = <0xf1000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy14: ethernet-phy@0 {
+ pcsphy14: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi
index 83d2e0ce8f7b..6128b9fb5381 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi
@@ -70,7 +70,8 @@ mdio@f3000 {
reg = <0xf3000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy15: ethernet-phy@0 {
+ pcsphy15: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi
index 3132fc73f133..a7dffe6bbe5b 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi
@@ -62,7 +62,8 @@ mdio@e1000 {
reg = <0xe1000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy8: ethernet-phy@0 {
+ pcsphy8: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi
index 75e904d96602..d0ad92f2ca2d 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi
@@ -69,7 +69,8 @@ mdio@e3000 {
reg = <0xe3000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy9: ethernet-phy@0 {
+ pcsphy9: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi
index 69f2cc7b8f19..b4b893eead2a 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi
@@ -69,7 +69,8 @@ mdio@e5000 {
reg = <0xe5000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy10: ethernet-phy@0 {
+ pcsphy10: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi
index b3aaf01d7da0..6c15a6ff0926 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi
@@ -69,7 +69,8 @@ mdio@e7000 {
reg = <0xe7000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy11: ethernet-phy@0 {
+ pcsphy11: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi
index 18e020432807..14fa4d067ffd 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi
@@ -62,7 +62,8 @@ mdio@e9000 {
reg = <0xe9000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy12: ethernet-phy@0 {
+ pcsphy12: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi
index 55f329d13f19..64737187a577 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi
@@ -69,7 +69,8 @@ mdio@eb000 {
reg = <0xeb000 0x1000>;
fsl,erratum-a011043; /* must ignore read errors */
- pcsphy13: ethernet-phy@0 {
+ pcsphy13: ethernet-pcs@0 {
+ compatible = "fsl,lynx-pcs";
reg = <0x0>;
};
};
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 11/13] of: property: Add device link support for PCS
2025-04-03 18:27 ` [RFC net-next PATCH 11/13] of: property: Add device link support for PCS Sean Anderson
@ 2025-04-03 18:32 ` Saravana Kannan
2025-04-03 19:04 ` Sean Anderson
0 siblings, 1 reply; 35+ messages in thread
From: Saravana Kannan @ 2025-04-03 18:32 UTC (permalink / raw)
To: Sean Anderson
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, Christian Marangi,
Heiner Kallweit, linux-kernel, upstream, Rob Herring, devicetree
On Thu, Apr 3, 2025 at 11:28 AM Sean Anderson <sean.anderson@linux.dev> wrote:
>
> This adds device link support for PCS devices, providing
> better probe ordering.
>
> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
> ---
>
> drivers/of/property.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/of/property.c b/drivers/of/property.c
> index c1feb631e383..f3e0c390ddba 100644
> --- a/drivers/of/property.c
> +++ b/drivers/of/property.c
> @@ -1379,6 +1379,7 @@ DEFINE_SIMPLE_PROP(pses, "pses", "#pse-cells")
> DEFINE_SIMPLE_PROP(power_supplies, "power-supplies", NULL)
> DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
> DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> +DEFINE_SIMPLE_PROP(pcs_handle, "pcs-handle", NULL)
>
> static struct device_node *parse_gpios(struct device_node *np,
> const char *prop_name, int index)
> @@ -1535,6 +1536,7 @@ static const struct supplier_bindings of_supplier_bindings[] = {
> .parse_prop = parse_post_init_providers,
> .fwlink_flags = FWLINK_FLAG_IGNORE,
> },
> + { .parse_prop = parse_pcs_handle, },
Can you add this in the right order please? All the simple ones come
before the SUFFIX ones so that it's less expensive/fewer comparisons
before you parse the simple properties.
-Saravana
> {}
> };
>
> --
> 2.35.1.1320.gc452695387.dirty
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 06/13] net: phy: Export some functions
2025-04-03 18:19 ` [RFC net-next PATCH 06/13] net: phy: Export some functions Sean Anderson
@ 2025-04-03 18:37 ` Florian Fainelli
2025-04-03 19:08 ` Sean Anderson
0 siblings, 1 reply; 35+ messages in thread
From: Florian Fainelli @ 2025-04-03 18:37 UTC (permalink / raw)
To: Sean Anderson, netdev, Andrew Lunn, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit
On 4/3/25 11:19, Sean Anderson wrote:
> Export a few functions so they can be used outside the phy subsystem:
>
> get_phy_c22_id is useful when probing MDIO devices which present a
> phy-like interface despite not using the Linux ethernet phy subsystem.
>
> mdio_device_bus_match is useful when creating MDIO devices manually
> (e.g. on non-devicetree platforms).
>
> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
> ---
>
> drivers/net/phy/mdio_device.c | 1 +
> drivers/net/phy/phy_device.c | 3 ++-
> include/linux/phy.h | 1 +
> 3 files changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
> index e747ee63c665..cce3f405d1a4 100644
> --- a/drivers/net/phy/mdio_device.c
> +++ b/drivers/net/phy/mdio_device.c
> @@ -45,6 +45,7 @@ int mdio_device_bus_match(struct device *dev, const struct device_driver *drv)
>
> return strcmp(mdiodev->modalias, drv->name) == 0;
> }
> +EXPORT_SYMBOL_GPL(mdio_device_bus_match);
>
> struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr)
> {
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index 675fbd225378..45d8bc13eb64 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
> @@ -859,7 +859,7 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr,
> * valid, %-EIO on bus access error, or %-ENODEV if no device responds
> * or invalid ID.
> */
> -static int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
> +int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
> {
> int phy_reg;
>
> @@ -887,6 +887,7 @@ static int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
>
> return 0;
> }
> +EXPORT_SYMBOL_GPL(get_phy_c22_id);
>
> /* Extract the phy ID from the compatible string of the form
> * ethernet-phy-idAAAA.BBBB.
> diff --git a/include/linux/phy.h b/include/linux/phy.h
> index a2bfae80c449..c648f1699c5c 100644
> --- a/include/linux/phy.h
> +++ b/include/linux/phy.h
> @@ -1754,6 +1754,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
> bool is_c45,
> struct phy_c45_device_ids *c45_ids);
> #if IS_ENABLED(CONFIG_PHYLIB)
> +int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id);
Seems like you will need to provide an empty inline stub for when
CONFIG_PHYLIB=n?
--
Florian
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 11/13] of: property: Add device link support for PCS
2025-04-03 18:32 ` Saravana Kannan
@ 2025-04-03 19:04 ` Sean Anderson
0 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 19:04 UTC (permalink / raw)
To: Saravana Kannan
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, Christian Marangi,
Heiner Kallweit, linux-kernel, upstream, Rob Herring, devicetree
On 4/3/25 14:32, Saravana Kannan wrote:
> On Thu, Apr 3, 2025 at 11:28 AM Sean Anderson <sean.anderson@linux.dev> wrote:
>>
>> This adds device link support for PCS devices, providing
>> better probe ordering.
>>
>> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
>> ---
>>
>> drivers/of/property.c | 2 ++
>> 1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/of/property.c b/drivers/of/property.c
>> index c1feb631e383..f3e0c390ddba 100644
>> --- a/drivers/of/property.c
>> +++ b/drivers/of/property.c
>> @@ -1379,6 +1379,7 @@ DEFINE_SIMPLE_PROP(pses, "pses", "#pse-cells")
>> DEFINE_SIMPLE_PROP(power_supplies, "power-supplies", NULL)
>> DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
>> DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
>> +DEFINE_SIMPLE_PROP(pcs_handle, "pcs-handle", NULL)
>>
>> static struct device_node *parse_gpios(struct device_node *np,
>> const char *prop_name, int index)
>> @@ -1535,6 +1536,7 @@ static const struct supplier_bindings of_supplier_bindings[] = {
>> .parse_prop = parse_post_init_providers,
>> .fwlink_flags = FWLINK_FLAG_IGNORE,
>> },
>> + { .parse_prop = parse_pcs_handle, },
>
> Can you add this in the right order please? All the simple ones come
> before the SUFFIX ones so that it's less expensive/fewer comparisons
> before you parse the simple properties.
Ah, I couldn't figure out what the intended order was so I just stuck
it at the end.
--Sean
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 06/13] net: phy: Export some functions
2025-04-03 18:37 ` Florian Fainelli
@ 2025-04-03 19:08 ` Sean Anderson
0 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 19:08 UTC (permalink / raw)
To: Florian Fainelli, netdev, Andrew Lunn, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King
Cc: linux-kernel, Christian Marangi, upstream, Heiner Kallweit
On 4/3/25 14:37, Florian Fainelli wrote:
> On 4/3/25 11:19, Sean Anderson wrote:
>> Export a few functions so they can be used outside the phy subsystem:
>>
>> get_phy_c22_id is useful when probing MDIO devices which present a
>> phy-like interface despite not using the Linux ethernet phy subsystem.
>>
>> mdio_device_bus_match is useful when creating MDIO devices manually
>> (e.g. on non-devicetree platforms).
>>
>> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
>> ---
>>
>> drivers/net/phy/mdio_device.c | 1 +
>> drivers/net/phy/phy_device.c | 3 ++-
>> include/linux/phy.h | 1 +
>> 3 files changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
>> index e747ee63c665..cce3f405d1a4 100644
>> --- a/drivers/net/phy/mdio_device.c
>> +++ b/drivers/net/phy/mdio_device.c
>> @@ -45,6 +45,7 @@ int mdio_device_bus_match(struct device *dev, const struct device_driver *drv)
>> return strcmp(mdiodev->modalias, drv->name) == 0;
>> }
>> +EXPORT_SYMBOL_GPL(mdio_device_bus_match);
>> struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr)
>> {
>> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
>> index 675fbd225378..45d8bc13eb64 100644
>> --- a/drivers/net/phy/phy_device.c
>> +++ b/drivers/net/phy/phy_device.c
>> @@ -859,7 +859,7 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr,
>> * valid, %-EIO on bus access error, or %-ENODEV if no device responds
>> * or invalid ID.
>> */
>> -static int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
>> +int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
>> {
>> int phy_reg;
>> @@ -887,6 +887,7 @@ static int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
>> return 0;
>> }
>> +EXPORT_SYMBOL_GPL(get_phy_c22_id);
>> /* Extract the phy ID from the compatible string of the form
>> * ethernet-phy-idAAAA.BBBB.
>> diff --git a/include/linux/phy.h b/include/linux/phy.h
>> index a2bfae80c449..c648f1699c5c 100644
>> --- a/include/linux/phy.h
>> +++ b/include/linux/phy.h
>> @@ -1754,6 +1754,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
>> bool is_c45,
>> struct phy_c45_device_ids *c45_ids);
>> #if IS_ENABLED(CONFIG_PHYLIB)
>> +int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id);
>
> Seems like you will need to provide an empty inline stub for when CONFIG_PHYLIB=n?
The only user (CONFIG_PCS_XILINX) selects CONFIG_PHYLINK which selects
CONFIG_PHYLIB. So I don't think this can occur yet.
--Sean
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 07/13] net: pcs: Add Xilinx PCS driver
2025-04-03 18:19 ` [RFC net-next PATCH 07/13] net: pcs: Add Xilinx PCS driver Sean Anderson
@ 2025-04-03 20:27 ` Russell King (Oracle)
2025-04-03 20:51 ` Sean Anderson
0 siblings, 1 reply; 35+ messages in thread
From: Russell King (Oracle) @ 2025-04-03 20:27 UTC (permalink / raw)
To: Sean Anderson
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, linux-kernel, Christian Marangi,
upstream, Heiner Kallweit, Michal Simek, Radhey Shyam Pandey,
Robert Hancock, linux-arm-kernel
On Thu, Apr 03, 2025 at 02:19:01PM -0400, Sean Anderson wrote:
> +static int xilinx_pcs_validate(struct phylink_pcs *pcs,
> + unsigned long *supported,
> + const struct phylink_link_state *state)
> +{
> + __ETHTOOL_DECLARE_LINK_MODE_MASK(xilinx_supported) = { 0 };
> +
> + phylink_set_port_modes(xilinx_supported);
> + phylink_set(xilinx_supported, Autoneg);
> + phylink_set(xilinx_supported, Pause);
> + phylink_set(xilinx_supported, Asym_Pause);
> + switch (state->interface) {
> + case PHY_INTERFACE_MODE_SGMII:
> + /* Half duplex not supported */
> + phylink_set(xilinx_supported, 10baseT_Full);
> + phylink_set(xilinx_supported, 100baseT_Full);
> + phylink_set(xilinx_supported, 1000baseT_Full);
> + break;
> + case PHY_INTERFACE_MODE_1000BASEX:
> + phylink_set(xilinx_supported, 1000baseX_Full);
> + break;
> + case PHY_INTERFACE_MODE_2500BASEX:
> + phylink_set(xilinx_supported, 2500baseX_Full);
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + linkmode_and(supported, supported, xilinx_supported);
> + return 0;
You can not assume that an interface mode implies any particular media.
For example, you can not assume that just because you have SGMII, that
the only supported media is BaseT. This has been a fundamental principle
in phylink's validation since day one.
Phylink documentation for the pcs_validate() callback states:
* Validate the interface mode, and advertising's autoneg bit, removing any
* media ethtool link modes that would not be supportable from the supported
* mask. Phylink will propagate the changes to the advertising mask. See the
* &struct phylink_mac_ops validate() method.
and if we look at the MAC ops validate (before it was removed):
- * Clear bits in the @supported and @state->advertising masks that
- * are not supportable by the MAC.
- *
- * Note that the PHY may be able to transform from one connection
- * technology to another, so, eg, don't clear 1000BaseX just
- * because the MAC is unable to BaseX mode. This is more about
- * clearing unsupported speeds and duplex settings. The port modes
- * should not be cleared; phylink_set_port_modes() will help with this.
PHYs can and do take SGMII and provide both BaseT and BaseX or BaseR
connections. A PCS that is not directly media facing can not dictate
the link modes.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 10/13] net: macb: Support external PCSs
2025-04-03 18:27 ` [RFC net-next PATCH 10/13] net: macb: Support external PCSs Sean Anderson
@ 2025-04-03 20:31 ` Russell King (Oracle)
0 siblings, 0 replies; 35+ messages in thread
From: Russell King (Oracle) @ 2025-04-03 20:31 UTC (permalink / raw)
To: Sean Anderson
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Christian Marangi, Heiner Kallweit,
linux-kernel, upstream, Claudiu Beznea, Nicolas Ferre
On Thu, Apr 03, 2025 at 02:27:06PM -0400, Sean Anderson wrote:
> -static void macb_pcs_get_state(struct phylink_pcs *pcs,
> +static void macb_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
> struct phylink_link_state *state)
> {
> struct macb *bp = container_of(pcs, struct macb, phylink_sgmii_pcs);
>
> - phylink_mii_c22_pcs_decode_state(state, gem_readl(bp, PCSSTS),
> + phylink_mii_c22_pcs_decode_state(state, neg_mode, gem_readl(bp, PCSSTS),
> gem_readl(bp, PCSANLPBASE));
Looks like this should be in the previous patch.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 07/13] net: pcs: Add Xilinx PCS driver
2025-04-03 20:27 ` Russell King (Oracle)
@ 2025-04-03 20:51 ` Sean Anderson
0 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-03 20:51 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, linux-kernel, Christian Marangi,
upstream, Heiner Kallweit, Michal Simek, Radhey Shyam Pandey,
Robert Hancock, linux-arm-kernel
On 4/3/25 16:27, Russell King (Oracle) wrote:
> On Thu, Apr 03, 2025 at 02:19:01PM -0400, Sean Anderson wrote:
>> +static int xilinx_pcs_validate(struct phylink_pcs *pcs,
>> + unsigned long *supported,
>> + const struct phylink_link_state *state)
>> +{
>> + __ETHTOOL_DECLARE_LINK_MODE_MASK(xilinx_supported) = { 0 };
>> +
>> + phylink_set_port_modes(xilinx_supported);
>> + phylink_set(xilinx_supported, Autoneg);
>> + phylink_set(xilinx_supported, Pause);
>> + phylink_set(xilinx_supported, Asym_Pause);
>> + switch (state->interface) {
>> + case PHY_INTERFACE_MODE_SGMII:
>> + /* Half duplex not supported */
>> + phylink_set(xilinx_supported, 10baseT_Full);
>> + phylink_set(xilinx_supported, 100baseT_Full);
>> + phylink_set(xilinx_supported, 1000baseT_Full);
>> + break;
>> + case PHY_INTERFACE_MODE_1000BASEX:
>> + phylink_set(xilinx_supported, 1000baseX_Full);
>> + break;
>> + case PHY_INTERFACE_MODE_2500BASEX:
>> + phylink_set(xilinx_supported, 2500baseX_Full);
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + linkmode_and(supported, supported, xilinx_supported);
>> + return 0;
>
> You can not assume that an interface mode implies any particular media.
> For example, you can not assume that just because you have SGMII, that
> the only supported media is BaseT. This has been a fundamental principle
> in phylink's validation since day one.
>
> Phylink documentation for the pcs_validate() callback states:
>
> * Validate the interface mode, and advertising's autoneg bit, removing any
> * media ethtool link modes that would not be supportable from the supported
> * mask. Phylink will propagate the changes to the advertising mask. See the
> * &struct phylink_mac_ops validate() method.
>
> and if we look at the MAC ops validate (before it was removed):
>
> - * Clear bits in the @supported and @state->advertising masks that
> - * are not supportable by the MAC.
> - *
> - * Note that the PHY may be able to transform from one connection
> - * technology to another, so, eg, don't clear 1000BaseX just
> - * because the MAC is unable to BaseX mode. This is more about
> - * clearing unsupported speeds and duplex settings. The port modes
> - * should not be cleared; phylink_set_port_modes() will help with this.
>
> PHYs can and do take SGMII and provide both BaseT and BaseX or BaseR
> connections. A PCS that is not directly media facing can not dictate
> the link modes.
>
OK, how about this:
static int xilinx_pcs_validate(struct phylink_pcs *pcs,
unsigned long *supported,
const struct phylink_link_state *state)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(xilinx_supported) = { 0 };
unsigned long caps = phy_caps_from_interface(state->interface);
phylink_set_port_modes(xilinx_supported);
phylink_set(xilinx_supported, Autoneg);
phylink_set(xilinx_supported, Pause);
phylink_set(xilinx_supported, Asym_Pause);
/* Half duplex not supported */
caps &= ~(LINK_CAPA_10HD | LINK_CAPA_100HD | LINK_CAPA_1000HD);
phy_caps_linkmodes(caps, xilinx_supported);
linkmode_and(supported, supported, xilinx_supported);
return 0;
}
--Sean
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 01/13] dt-bindings: net: Add binding for Xilinx PCS
2025-04-03 18:18 ` [RFC net-next PATCH 01/13] dt-bindings: net: Add binding for Xilinx PCS Sean Anderson
@ 2025-04-04 10:37 ` Krzysztof Kozlowski
2025-04-04 10:39 ` Krzysztof Kozlowski
2025-04-04 15:19 ` Sean Anderson
0 siblings, 2 replies; 35+ messages in thread
From: Krzysztof Kozlowski @ 2025-04-04 10:37 UTC (permalink / raw)
To: Sean Anderson
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, linux-kernel,
Christian Marangi, upstream, Heiner Kallweit, Conor Dooley,
Krzysztof Kozlowski, Michal Simek, Radhey Shyam Pandey,
Rob Herring, Robert Hancock, devicetree
On Thu, Apr 03, 2025 at 02:18:55PM GMT, Sean Anderson wrote:
> This adds a binding for the Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII
Incomplete review, since this is an RFC.
Please do not use "This commit/patch/change", but imperative mood. See
longer explanation here:
https://elixir.bootlin.com/linux/v5.17.1/source/Documentation/process/submitting-patches.rst#L95
A nit, subject: drop second/last, redundant "binding for". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v6.7-rc8/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
> LogiCORE IP. This device is a soft device typically used to adapt
> between GMII and SGMII or 1000BASE-X (possbilty in combination with a
> serdes). pcs-modes reflects the modes available with the as configured
> when the device is synthesized. Multiple modes may be specified if
> dynamic reconfiguration is supported.
>
> One PCS may contain "shared logic in core" which can be connected to
> other PCSs with "shared logic in example design." This primarily refers
> to clocking resources, allowing a reference clock to be shared by a bank
> of PCSs. To support this, if #clock-cells is defined then the PCS will
> register itself as a clock provider for other PCSs.
>
> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
> ---
>
> .../devicetree/bindings/net/xilinx,pcs.yaml | 129 ++++++++++++++++++
> 1 file changed, 129 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/xilinx,pcs.yaml
>
> diff --git a/Documentation/devicetree/bindings/net/xilinx,pcs.yaml b/Documentation/devicetree/bindings/net/xilinx,pcs.yaml
> new file mode 100644
> index 000000000000..56a3ce0c4ef0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/xilinx,pcs.yaml
> @@ -0,0 +1,129 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/xilinx,pcs.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII LogiCORE IP
> +
> +maintainers:
> + - Sean Anderson <sean.anderson@seco.com>
> +
> +description:
> + This is a soft device which implements the PCS and (depending on
> + configuration) PMA layers of an IEEE Ethernet PHY. On the MAC side, it
> + implements GMII. It may have an attached SERDES (internal or external), or
> + may directly use LVDS IO resources. Depending on the configuration, it may
> + implement 1000BASE-X, SGMII, 2500BASE-X, or 2.5G SGMII.
> +
> + This device has a notion of "shared logic" such as reset and clocking
> + resources which must be shared between multiple PCSs using the same I/O
> + banks. Each PCS can be configured to have the shared logic in the "core"
> + (instantiated internally and made available to other PCSs) or in the "example
> + design" (provided by another PCS). PCSs with shared logic in the core are
> + reset controllers, and generally provide several resets for other PCSs in the
> + same bank.
> +
> +allOf:
> + - $ref: ethernet-controller.yaml#
> +
> +properties:
> + compatible:
> + contains:
From where did you get such syntax? What do you want to express?
> + const: xilinx,pcs-16.2
What does the number mean?
> +
> + reg:
> + maxItems: 1
> +
> + "#clock-cells":
> + const: 0
> + description:
> + Register a clock representing the clocking resources shared with other
> + PCSs.
Drop description, redundant.
> +
> + clocks:
> + items:
> + - description:
> + The reference clock for the PCS. Depending on your setup, this may be
> + the gtrefclk, refclk, clk125m signal, or clocks from another PCS.
> +
> + clock-names:
> + const: refclk
> +
> + done-gpios:
> + maxItems: 1
> + description:
> + GPIO connected to the reset-done output, if present.
> +
> + interrupts:
> + items:
> + - description:
> + The an_interrupt autonegotiation-complete interrupt.
> +
> + interrupt-names:
> + const: an
> +
> + pcs-modes:
> + description:
> + The interfaces that the PCS supports.
> + oneOf:
> + - const: sgmii
> + - const: 1000base-x
> + - const: 2500base-x
> + - items:
> + - const: sgmii
> + - const: 1000base-x
This is confusing. Why fallbacks? Shouldn't this be just enum? And
where is the type or constraints about number of items?
> +
> + reset-gpios:
> + maxItems: 1
> + description:
> + GPIO connected to the reset input.
> +
> +required:
> + - compatible
> + - reg
> + - pcs-modes
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/gpio/gpio.h>
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/interrupt-controller/irq.h>
> +
> + mdio {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + pcs0: ethernet-pcs@0 {
> + #clock-cells = <0>;
Follow DTS coding style. clock-cells are never the first property.
> + compatible = "xlnx,pcs-16.2";
> + reg = <0>;
> + clocks = <&si570>;
> + clock-names = "refclk";
> + interrupts-extended = <&gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-names = "an";
> + reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
> + done-gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
> + pcs-modes = "sgmii", "1000base-x";
> + };
> +
> + pcs1: ethernet-pcs@1 {
> + compatible = "xlnx,pcs-16.2";
> + reg = <1>;
> + clocks = <&pcs0>;
> + clock-names = "refclk";
> + interrupts-extended = <&gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-names = "an";
> + reset-gpios = <&gpio 7 GPIO_ACTIVE_HIGH>;
> + done-gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
> + pcs-modes = "sgmii", "1000base-x";
Drop example, basically the same as previous.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 01/13] dt-bindings: net: Add binding for Xilinx PCS
2025-04-04 10:37 ` Krzysztof Kozlowski
@ 2025-04-04 10:39 ` Krzysztof Kozlowski
2025-04-04 15:12 ` Sean Anderson
2025-04-04 15:19 ` Sean Anderson
1 sibling, 1 reply; 35+ messages in thread
From: Krzysztof Kozlowski @ 2025-04-04 10:39 UTC (permalink / raw)
To: Sean Anderson
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, linux-kernel,
Christian Marangi, upstream, Heiner Kallweit, Conor Dooley,
Krzysztof Kozlowski, Michal Simek, Radhey Shyam Pandey,
Rob Herring, Robert Hancock, devicetree
On 04/04/2025 12:37, Krzysztof Kozlowski wrote:
>> + pcs-modes:
>> + description:
>> + The interfaces that the PCS supports.
>> + oneOf:
>> + - const: sgmii
>> + - const: 1000base-x
>> + - const: 2500base-x
>> + - items:
>> + - const: sgmii
>> + - const: 1000base-x
>
> This is confusing. Why fallbacks? Shouldn't this be just enum? And
> where is the type or constraints about number of items?
>
I just double checked now in dtschema and latest next - there is no such
property.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 01/13] dt-bindings: net: Add binding for Xilinx PCS
2025-04-04 10:39 ` Krzysztof Kozlowski
@ 2025-04-04 15:12 ` Sean Anderson
0 siblings, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-04 15:12 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, linux-kernel,
Christian Marangi, upstream, Heiner Kallweit, Conor Dooley,
Krzysztof Kozlowski, Michal Simek, Radhey Shyam Pandey,
Rob Herring, Robert Hancock, devicetree
On 4/4/25 06:39, Krzysztof Kozlowski wrote:
> On 04/04/2025 12:37, Krzysztof Kozlowski wrote:
>>> + pcs-modes:
>>> + description:
>>> + The interfaces that the PCS supports.
>>> + oneOf:
>>> + - const: sgmii
>>> + - const: 1000base-x
>>> + - const: 2500base-x
>>> + - items:
>>> + - const: sgmii
>>> + - const: 1000base-x
>>
>> This is confusing. Why fallbacks? Shouldn't this be just enum? And
>> where is the type or constraints about number of items?
>>
> I just double checked now in dtschema and latest next - there is no such
> property.
OK, so you would prefer xlnx,pcs-modes?
--Sean
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 01/13] dt-bindings: net: Add binding for Xilinx PCS
2025-04-04 10:37 ` Krzysztof Kozlowski
2025-04-04 10:39 ` Krzysztof Kozlowski
@ 2025-04-04 15:19 ` Sean Anderson
1 sibling, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-04 15:19 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, linux-kernel,
Christian Marangi, upstream, Heiner Kallweit, Conor Dooley,
Krzysztof Kozlowski, Michal Simek, Radhey Shyam Pandey,
Rob Herring, Robert Hancock, devicetree
On 4/4/25 06:37, Krzysztof Kozlowski wrote:
> On Thu, Apr 03, 2025 at 02:18:55PM GMT, Sean Anderson wrote:
>> This adds a binding for the Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII
>
> Incomplete review, since this is an RFC.
Only an RFC due to netdev's rules. I consider this patchset complete.
> Please do not use "This commit/patch/change", but imperative mood. See
> longer explanation here:
> https://elixir.bootlin.com/linux/v5.17.1/source/Documentation/process/submitting-patches.rst#L95
>
> A nit, subject: drop second/last, redundant "binding for". The
> "dt-bindings" prefix is already stating that these are bindings.
> See also:
> https://elixir.bootlin.com/linux/v6.7-rc8/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
>
>> LogiCORE IP. This device is a soft device typically used to adapt
>> between GMII and SGMII or 1000BASE-X (possbilty in combination with a
>> serdes). pcs-modes reflects the modes available with the as configured
>> when the device is synthesized. Multiple modes may be specified if
>> dynamic reconfiguration is supported.
>>
>> One PCS may contain "shared logic in core" which can be connected to
>> other PCSs with "shared logic in example design." This primarily refers
>> to clocking resources, allowing a reference clock to be shared by a bank
>> of PCSs. To support this, if #clock-cells is defined then the PCS will
>> register itself as a clock provider for other PCSs.
>>
>> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
>> ---
>>
>> .../devicetree/bindings/net/xilinx,pcs.yaml | 129 ++++++++++++++++++
>> 1 file changed, 129 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/net/xilinx,pcs.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/net/xilinx,pcs.yaml b/Documentation/devicetree/bindings/net/xilinx,pcs.yaml
>> new file mode 100644
>> index 000000000000..56a3ce0c4ef0
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/net/xilinx,pcs.yaml
>> @@ -0,0 +1,129 @@
>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/net/xilinx,pcs.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Xilinx 1G/2.5G Ethernet PCS/PMA or SGMII LogiCORE IP
>> +
>> +maintainers:
>> + - Sean Anderson <sean.anderson@seco.com>
>> +
>> +description:
>> + This is a soft device which implements the PCS and (depending on
>> + configuration) PMA layers of an IEEE Ethernet PHY. On the MAC side, it
>> + implements GMII. It may have an attached SERDES (internal or external), or
>> + may directly use LVDS IO resources. Depending on the configuration, it may
>> + implement 1000BASE-X, SGMII, 2500BASE-X, or 2.5G SGMII.
>> +
>> + This device has a notion of "shared logic" such as reset and clocking
>> + resources which must be shared between multiple PCSs using the same I/O
>> + banks. Each PCS can be configured to have the shared logic in the "core"
>> + (instantiated internally and made available to other PCSs) or in the "example
>> + design" (provided by another PCS). PCSs with shared logic in the core are
>> + reset controllers, and generally provide several resets for other PCSs in the
>> + same bank.
>> +
>> +allOf:
>> + - $ref: ethernet-controller.yaml#
>> +
>> +properties:
>> + compatible:
>> + contains:
>
> From where did you get such syntax? What do you want to express?
The compatible should contain this value, but we don't really care what else it
contains. This aligns with how the kernel matches drivers to devices.
>> + const: xilinx,pcs-16.2
>
> What does the number mean?
It's the version of the IP.
>> +
>> + reg:
>> + maxItems: 1
>> +
>> + "#clock-cells":
>> + const: 0
>> + description:
>> + Register a clock representing the clocking resources shared with other
>> + PCSs.
>
> Drop description, redundant.
>
>> +
>> + clocks:
>> + items:
>> + - description:
>> + The reference clock for the PCS. Depending on your setup, this may be
>> + the gtrefclk, refclk, clk125m signal, or clocks from another PCS.
>> +
>> + clock-names:
>> + const: refclk
>> +
>> + done-gpios:
>> + maxItems: 1
>> + description:
>> + GPIO connected to the reset-done output, if present.
>> +
>> + interrupts:
>> + items:
>> + - description:
>> + The an_interrupt autonegotiation-complete interrupt.
>> +
>> + interrupt-names:
>> + const: an
>> +
>> + pcs-modes:
>> + description:
>> + The interfaces that the PCS supports.
>> + oneOf:
>> + - const: sgmii
>> + - const: 1000base-x
>> + - const: 2500base-x
>> + - items:
>> + - const: sgmii
>> + - const: 1000base-x
>
> This is confusing. Why fallbacks? Shouldn't this be just enum? And
> where is the type or constraints about number of items?
As stated in the commit message, multiple modes may be specified if
dynamic reconfiguration is supported. So I want to allow
pcs-modes = "sgmii"
pcs-modes = "1000base-x"
pcs-modes = "2500base-x"
pcs-modes = "sgmii", "1000base-x"
>> +
>> + reset-gpios:
>> + maxItems: 1
>> + description:
>> + GPIO connected to the reset input.
>> +
>> +required:
>> + - compatible
>> + - reg
>> + - pcs-modes
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> + - |
>> + #include <dt-bindings/gpio/gpio.h>
>> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>> + #include <dt-bindings/interrupt-controller/irq.h>
>> +
>> + mdio {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> +
>> + pcs0: ethernet-pcs@0 {
>> + #clock-cells = <0>;
>
> Follow DTS coding style. clock-cells are never the first property.
Where is this documented?
>> + compatible = "xlnx,pcs-16.2";
>> + reg = <0>;
>> + clocks = <&si570>;
>> + clock-names = "refclk";
>> + interrupts-extended = <&gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
>> + interrupt-names = "an";
>> + reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
>> + done-gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
>> + pcs-modes = "sgmii", "1000base-x";
>> + };
>> +
>> + pcs1: ethernet-pcs@1 {
>> + compatible = "xlnx,pcs-16.2";
>> + reg = <1>;
>> + clocks = <&pcs0>;
>> + clock-names = "refclk";
>> + interrupts-extended = <&gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
>> + interrupt-names = "an";
>> + reset-gpios = <&gpio 7 GPIO_ACTIVE_HIGH>;
>> + done-gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
>> + pcs-modes = "sgmii", "1000base-x";
>
> Drop example, basically the same as previous.
>
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 00/13] Add PCS core support
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
` (12 preceding siblings ...)
2025-04-03 18:30 ` [RFC net-next PATCH 13/13] powerpc: " Sean Anderson
@ 2025-04-07 16:27 ` Kory Maincent
2025-04-07 16:33 ` Sean Anderson
13 siblings, 1 reply; 35+ messages in thread
From: Kory Maincent @ 2025-04-07 16:27 UTC (permalink / raw)
To: Sean Anderson
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, linux-kernel,
Christian Marangi, upstream, Heiner Kallweit, Alexandre Belloni,
Alexandre Torgue, Christophe Leroy, Clark Wang, Claudiu Beznea,
Claudiu Manoil, Conor Dooley, Ioana Ciornei, Jonathan Corbet,
Joyce Ooi, Krzysztof Kozlowski, Krzysztof Kozlowski, Li Yang,
Madalin Bucur, Madhavan Srinivasan, Maxime Coquelin,
Michael Ellerman, Michal Simek, Naveen N Rao, Nicholas Piggin,
Nicolas Ferre, Radhey Shyam Pandey, Rob Herring, Rob Herring,
Robert Hancock, Saravana Kannan, Shawn Guo, UNGLinuxDriver,
Vladimir Oltean, Wei Fang, devicetree, imx, linux-arm-kernel,
linux-doc, linux-stm32, linuxppc-dev
On Thu, 3 Apr 2025 14:18:54 -0400
Sean Anderson <sean.anderson@linux.dev> wrote:
> This series adds support for creating PCSs as devices on a bus with a
> driver (patch 3). As initial users,
>
> - The Lynx PCS (and all of its users) is converted to this system (patch 5)
> - The Xilinx PCS is broken out from the AXI Ethernet driver (patches 6-8)
> - The Cadence MACB driver is converted to support external PCSs (namely
> the Xilinx PCS) (patches 9-10).
>
> The last few patches add device links for pcs-handle to improve boot times,
> and add compatibles for all Lynx PCSs.
>
> Care has been taken to ensure backwards-compatibility. The main source
> of this is that many PCS devices lack compatibles and get detected as
> PHYs. To address this, pcs_get_by_fwnode_compat allows drivers to edit
> the devicetree to add appropriate compatibles.
I don't dive into your patch series and I don't know if you have heard about it
but Christian Marangi is currently working on fwnode for PCS:
https://lore.kernel.org/netdev/20250406221423.9723-1-ansuelsmth@gmail.com
Maybe you should sync with him!
Regards,
--
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 00/13] Add PCS core support
2025-04-07 16:27 ` [RFC net-next PATCH 00/13] Add PCS core support Kory Maincent
@ 2025-04-07 16:33 ` Sean Anderson
2025-04-07 16:46 ` Christian Marangi (Ansuel)
2025-04-07 16:51 ` Kory Maincent
0 siblings, 2 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-07 16:33 UTC (permalink / raw)
To: Kory Maincent
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, linux-kernel,
Christian Marangi, upstream, Heiner Kallweit, Alexandre Belloni,
Alexandre Torgue, Christophe Leroy, Clark Wang, Claudiu Beznea,
Claudiu Manoil, Conor Dooley, Ioana Ciornei, Jonathan Corbet,
Joyce Ooi, Krzysztof Kozlowski, Krzysztof Kozlowski, Li Yang,
Madalin Bucur, Madhavan Srinivasan, Maxime Coquelin,
Michael Ellerman, Michal Simek, Naveen N Rao, Nicholas Piggin,
Nicolas Ferre, Radhey Shyam Pandey, Rob Herring, Rob Herring,
Robert Hancock, Saravana Kannan, Shawn Guo, UNGLinuxDriver,
Vladimir Oltean, Wei Fang, devicetree, imx, linux-arm-kernel,
linux-doc, linux-stm32, linuxppc-dev
On 4/7/25 12:27, Kory Maincent wrote:
> On Thu, 3 Apr 2025 14:18:54 -0400
> Sean Anderson <sean.anderson@linux.dev> wrote:
>
>> This series adds support for creating PCSs as devices on a bus with a
>> driver (patch 3). As initial users,
>>
>> - The Lynx PCS (and all of its users) is converted to this system (patch 5)
>> - The Xilinx PCS is broken out from the AXI Ethernet driver (patches 6-8)
>> - The Cadence MACB driver is converted to support external PCSs (namely
>> the Xilinx PCS) (patches 9-10).
>>
>> The last few patches add device links for pcs-handle to improve boot times,
>> and add compatibles for all Lynx PCSs.
>>
>> Care has been taken to ensure backwards-compatibility. The main source
>> of this is that many PCS devices lack compatibles and get detected as
>> PHYs. To address this, pcs_get_by_fwnode_compat allows drivers to edit
>> the devicetree to add appropriate compatibles.
>
> I don't dive into your patch series and I don't know if you have heard about it
> but Christian Marangi is currently working on fwnode for PCS:
> https://lore.kernel.org/netdev/20250406221423.9723-1-ansuelsmth@gmail.com
>
> Maybe you should sync with him!
I saw that series and made some comments. He is CC'd on this one.
I think this approach has two advantages:
- It completely solves the problem of the PCS being unregistered while the netdev
(or whatever) is up
- I have designed the interface to make it easy to convert existing
drivers that may not be able to use the "standard" probing process
(because they have to support other devicetree structures for
backwards-compatibility).
--Sean
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 00/13] Add PCS core support
2025-04-07 16:33 ` Sean Anderson
@ 2025-04-07 16:46 ` Christian Marangi (Ansuel)
2025-04-07 17:00 ` Sean Anderson
2025-04-07 16:51 ` Kory Maincent
1 sibling, 1 reply; 35+ messages in thread
From: Christian Marangi (Ansuel) @ 2025-04-07 16:46 UTC (permalink / raw)
To: Sean Anderson
Cc: Kory Maincent, netdev, Andrew Lunn, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel, upstream, Heiner Kallweit, Alexandre Belloni,
Alexandre Torgue, Christophe Leroy, Clark Wang, Claudiu Beznea,
Claudiu Manoil, Conor Dooley, Ioana Ciornei, Jonathan Corbet,
Joyce Ooi, Krzysztof Kozlowski, Krzysztof Kozlowski, Li Yang,
Madalin Bucur, Madhavan Srinivasan, Maxime Coquelin,
Michael Ellerman, Michal Simek, Naveen N Rao, Nicholas Piggin,
Nicolas Ferre, Radhey Shyam Pandey, Rob Herring, Rob Herring,
Robert Hancock, Saravana Kannan, Shawn Guo, UNGLinuxDriver,
Vladimir Oltean, Wei Fang, devicetree, imx, linux-arm-kernel,
linux-doc, linux-stm32, linuxppc-dev
Il giorno lun 7 apr 2025 alle ore 18:33 Sean Anderson
<sean.anderson@linux.dev> ha scritto:
>
> On 4/7/25 12:27, Kory Maincent wrote:
> > On Thu, 3 Apr 2025 14:18:54 -0400
> > Sean Anderson <sean.anderson@linux.dev> wrote:
> >
> >> This series adds support for creating PCSs as devices on a bus with a
> >> driver (patch 3). As initial users,
> >>
> >> - The Lynx PCS (and all of its users) is converted to this system (patch 5)
> >> - The Xilinx PCS is broken out from the AXI Ethernet driver (patches 6-8)
> >> - The Cadence MACB driver is converted to support external PCSs (namely
> >> the Xilinx PCS) (patches 9-10).
> >>
> >> The last few patches add device links for pcs-handle to improve boot times,
> >> and add compatibles for all Lynx PCSs.
> >>
> >> Care has been taken to ensure backwards-compatibility. The main source
> >> of this is that many PCS devices lack compatibles and get detected as
> >> PHYs. To address this, pcs_get_by_fwnode_compat allows drivers to edit
> >> the devicetree to add appropriate compatibles.
> >
> > I don't dive into your patch series and I don't know if you have heard about it
> > but Christian Marangi is currently working on fwnode for PCS:
> > https://lore.kernel.org/netdev/20250406221423.9723-1-ansuelsmth@gmail.com
> >
> > Maybe you should sync with him!
>
> I saw that series and made some comments. He is CC'd on this one.
>
> I think this approach has two advantages:
>
> - It completely solves the problem of the PCS being unregistered while the netdev
> (or whatever) is up
> - I have designed the interface to make it easy to convert existing
> drivers that may not be able to use the "standard" probing process
> (because they have to support other devicetree structures for
> backwards-compatibility).
>
I notice this and it's my fault for taking too long to post v2 of the PCS patch.
There was also this idea of entering the wrapper hell but I scrapped that early
as I really feel it's a workaround to the current problem present for
PCS handling.
And the real problem IMHO is that currently PCS handling is fragile and with too
many assumptions. With Daniel we also discussed backwards-compatibility.
(mainly needed for mt7621 and mt7986 (for mediatek side those are the 2
that slipped in before it was correctly complained that things were
taking a bad path)
We feel v2 permits correct support of old implementations.
The ""legacy"" implementation pose the assumption that PCS is never removed
(unless the MAC driver is removed)
That fits v2 where a MAC has to initially provide a list of PCS to
phylink instance.
With this implementation, a MAC can manually parse whatever PCS node structure
is in place and fill the PCS.
As really the "late" removal/addition of a PCS can only be supported with fwnode
implementation as dedicated PCS driver will make use of that.
I honestly hope we can skip having to enter the wrapper hell.
Anyway I also see you made REALLY GOOD documentation. Would be ideal to
collaborate for that. Anyway it's up to net maintainers on what path to follow.
Just my 2 cent on the PCS topic.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 00/13] Add PCS core support
2025-04-07 16:33 ` Sean Anderson
2025-04-07 16:46 ` Christian Marangi (Ansuel)
@ 2025-04-07 16:51 ` Kory Maincent
1 sibling, 0 replies; 35+ messages in thread
From: Kory Maincent @ 2025-04-07 16:51 UTC (permalink / raw)
To: Sean Anderson
Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, linux-kernel,
Christian Marangi, upstream, Heiner Kallweit, Alexandre Belloni,
Alexandre Torgue, Christophe Leroy, Clark Wang, Claudiu Beznea,
Claudiu Manoil, Conor Dooley, Ioana Ciornei, Jonathan Corbet,
Joyce Ooi, Krzysztof Kozlowski, Krzysztof Kozlowski, Li Yang,
Madalin Bucur, Madhavan Srinivasan, Maxime Coquelin,
Michael Ellerman, Michal Simek, Naveen N Rao, Nicholas Piggin,
Nicolas Ferre, Radhey Shyam Pandey, Rob Herring, Rob Herring,
Robert Hancock, Saravana Kannan, Shawn Guo, UNGLinuxDriver,
Vladimir Oltean, Wei Fang, devicetree, imx, linux-arm-kernel,
linux-doc, linux-stm32, linuxppc-dev
On Mon, 7 Apr 2025 12:33:28 -0400
Sean Anderson <sean.anderson@linux.dev> wrote:
> On 4/7/25 12:27, Kory Maincent wrote:
> > On Thu, 3 Apr 2025 14:18:54 -0400
> > Sean Anderson <sean.anderson@linux.dev> wrote:
> >
> >> This series adds support for creating PCSs as devices on a bus with a
> >> driver (patch 3). As initial users,
> >>
> >> - The Lynx PCS (and all of its users) is converted to this system (patch 5)
> >> - The Xilinx PCS is broken out from the AXI Ethernet driver (patches 6-8)
> >> - The Cadence MACB driver is converted to support external PCSs (namely
> >> the Xilinx PCS) (patches 9-10).
> >>
> >> The last few patches add device links for pcs-handle to improve boot times,
> >> and add compatibles for all Lynx PCSs.
> >>
> >> Care has been taken to ensure backwards-compatibility. The main source
> >> of this is that many PCS devices lack compatibles and get detected as
> >> PHYs. To address this, pcs_get_by_fwnode_compat allows drivers to edit
> >> the devicetree to add appropriate compatibles.
> >
> > I don't dive into your patch series and I don't know if you have heard
> > about it but Christian Marangi is currently working on fwnode for PCS:
> > https://lore.kernel.org/netdev/20250406221423.9723-1-ansuelsmth@gmail.com
> >
> > Maybe you should sync with him!
>
> I saw that series and made some comments. He is CC'd on this one.
Oh indeed, you have replied on his v1, sorry I missed it.
It seems he forgot to add you in CC in the v2.
> I think this approach has two advantages:
>
> - It completely solves the problem of the PCS being unregistered while the
> netdev (or whatever) is up
> - I have designed the interface to make it easy to convert existing
> drivers that may not be able to use the "standard" probing process
> (because they have to support other devicetree structures for
> backwards-compatibility).
Ok, thanks for the clarification!
I was working on the axienet driver to add support for the 10G version that's
why I discovered your series.
Regards,
--
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 00/13] Add PCS core support
2025-04-07 16:46 ` Christian Marangi (Ansuel)
@ 2025-04-07 17:00 ` Sean Anderson
2025-04-07 17:21 ` Christian Marangi (Ansuel)
0 siblings, 1 reply; 35+ messages in thread
From: Sean Anderson @ 2025-04-07 17:00 UTC (permalink / raw)
To: Christian Marangi (Ansuel)
Cc: Kory Maincent, netdev, Andrew Lunn, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel, upstream, Heiner Kallweit, Alexandre Belloni,
Alexandre Torgue, Christophe Leroy, Clark Wang, Claudiu Beznea,
Claudiu Manoil, Conor Dooley, Ioana Ciornei, Jonathan Corbet,
Joyce Ooi, Krzysztof Kozlowski, Krzysztof Kozlowski, Li Yang,
Madalin Bucur, Madhavan Srinivasan, Maxime Coquelin,
Michael Ellerman, Michal Simek, Naveen N Rao, Nicholas Piggin,
Nicolas Ferre, Radhey Shyam Pandey, Rob Herring, Rob Herring,
Robert Hancock, Saravana Kannan, Shawn Guo, UNGLinuxDriver,
Vladimir Oltean, Wei Fang, devicetree, imx, linux-arm-kernel,
linux-doc, linux-stm32, linuxppc-dev
On 4/7/25 12:46, Christian Marangi (Ansuel) wrote:
> Il giorno lun 7 apr 2025 alle ore 18:33 Sean Anderson
> <sean.anderson@linux.dev> ha scritto:
>>
>> On 4/7/25 12:27, Kory Maincent wrote:
>> > On Thu, 3 Apr 2025 14:18:54 -0400
>> > Sean Anderson <sean.anderson@linux.dev> wrote:
>> >
>> >> This series adds support for creating PCSs as devices on a bus with a
>> >> driver (patch 3). As initial users,
>> >>
>> >> - The Lynx PCS (and all of its users) is converted to this system (patch 5)
>> >> - The Xilinx PCS is broken out from the AXI Ethernet driver (patches 6-8)
>> >> - The Cadence MACB driver is converted to support external PCSs (namely
>> >> the Xilinx PCS) (patches 9-10).
>> >>
>> >> The last few patches add device links for pcs-handle to improve boot times,
>> >> and add compatibles for all Lynx PCSs.
>> >>
>> >> Care has been taken to ensure backwards-compatibility. The main source
>> >> of this is that many PCS devices lack compatibles and get detected as
>> >> PHYs. To address this, pcs_get_by_fwnode_compat allows drivers to edit
>> >> the devicetree to add appropriate compatibles.
>> >
>> > I don't dive into your patch series and I don't know if you have heard about it
>> > but Christian Marangi is currently working on fwnode for PCS:
>> > https://lore.kernel.org/netdev/20250406221423.9723-1-ansuelsmth@gmail.com
>> >
>> > Maybe you should sync with him!
>>
>> I saw that series and made some comments. He is CC'd on this one.
>>
>> I think this approach has two advantages:
>>
>> - It completely solves the problem of the PCS being unregistered while the netdev
>> (or whatever) is up
>> - I have designed the interface to make it easy to convert existing
>> drivers that may not be able to use the "standard" probing process
>> (because they have to support other devicetree structures for
>> backwards-compatibility).
>>
>
> I notice this and it's my fault for taking too long to post v2 of the PCS patch.
> There was also this idea of entering the wrapper hell but I scrapped that early
> as I really feel it's a workaround to the current problem present for
> PCS handling.
It's no workaround. The fundamental problem is that drivers can become
unbound at any time, and we cannot make consumers drop their references.
Every subsystem must deal with this reality, or suffer from
user-after-free bugs. See [1-3] for discussion of this problem in
relation to PCSs and PHYs, and [4] for more discussion of my approach.
[1] https://lore.kernel.org/netdev/YV7Kp2k8VvN7J0fY@shell.armlinux.org.uk/
[2] https://lore.kernel.org/netdev/20220816163701.1578850-1-sean.anderson@seco.com/
[3] https://lore.kernel.org/netdev/9747f8ef-66b3-0870-cbc0-c1783896b30d@seco.com/
[3] https://lpc.events/event/17/contributions/1627/
> And the real problem IMHO is that currently PCS handling is fragile and with too
> many assumptions. With Daniel we also discussed backwards-compatibility.
> (mainly needed for mt7621 and mt7986 (for mediatek side those are the 2
> that slipped in before it was correctly complained that things were
> taking a bad path)
>
> We feel v2 permits correct support of old implementations.
> The ""legacy"" implementation pose the assumption that PCS is never removed
> (unless the MAC driver is removed)
> That fits v2 where a MAC has to initially provide a list of PCS to
> phylink instance.
And what happens when the driver is unbound from the device and suddenly
a PCS on that list is free'd memory but is in active use by a netdev?
> With this implementation, a MAC can manually parse whatever PCS node structure
> is in place and fill the PCS.
>
> As really the "late" removal/addition of a PCS can only be supported with fwnode
> implementation as dedicated PCS driver will make use of that.
I agree that a "cells" approach would require this, but
- There are no in-tree examples of where this is necessary
- I think this would be easy to add when necessary
> I honestly hope we can skip having to enter the wrapper hell.
Unfortunately, this is required by the kernel driver model :l
> Anyway I also see you made REALLY GOOD documentation.
Thanks. One of my peeves is subsystems that have zero docs...
> Would be ideal to
> collaborate for that. Anyway it's up to net maintainers on what path to follow.
>
> Just my 2 cent on the PCS topic.
--Sean
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 00/13] Add PCS core support
2025-04-07 17:00 ` Sean Anderson
@ 2025-04-07 17:21 ` Christian Marangi (Ansuel)
2025-04-07 17:25 ` Daniel Golle
2025-04-07 18:06 ` Sean Anderson
0 siblings, 2 replies; 35+ messages in thread
From: Christian Marangi (Ansuel) @ 2025-04-07 17:21 UTC (permalink / raw)
To: Sean Anderson
Cc: Kory Maincent, netdev, Andrew Lunn, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel, upstream, Heiner Kallweit, Alexandre Belloni,
Alexandre Torgue, Christophe Leroy, Clark Wang, Claudiu Beznea,
Claudiu Manoil, Conor Dooley, Ioana Ciornei, Jonathan Corbet,
Joyce Ooi, Krzysztof Kozlowski, Krzysztof Kozlowski, Li Yang,
Madalin Bucur, Madhavan Srinivasan, Maxime Coquelin,
Michael Ellerman, Michal Simek, Naveen N Rao, Nicholas Piggin,
Nicolas Ferre, Radhey Shyam Pandey, Rob Herring, Rob Herring,
Robert Hancock, Saravana Kannan, Shawn Guo, UNGLinuxDriver,
Vladimir Oltean, Wei Fang, devicetree, imx, linux-arm-kernel,
linux-doc, linux-stm32, linuxppc-dev
Il giorno lun 7 apr 2025 alle ore 19:00 Sean Anderson
<sean.anderson@linux.dev> ha scritto:
>
> On 4/7/25 12:46, Christian Marangi (Ansuel) wrote:
> > Il giorno lun 7 apr 2025 alle ore 18:33 Sean Anderson
> > <sean.anderson@linux.dev> ha scritto:
> >>
> >> On 4/7/25 12:27, Kory Maincent wrote:
> >> > On Thu, 3 Apr 2025 14:18:54 -0400
> >> > Sean Anderson <sean.anderson@linux.dev> wrote:
> >> >
> >> >> This series adds support for creating PCSs as devices on a bus with a
> >> >> driver (patch 3). As initial users,
> >> >>
> >> >> - The Lynx PCS (and all of its users) is converted to this system (patch 5)
> >> >> - The Xilinx PCS is broken out from the AXI Ethernet driver (patches 6-8)
> >> >> - The Cadence MACB driver is converted to support external PCSs (namely
> >> >> the Xilinx PCS) (patches 9-10).
> >> >>
> >> >> The last few patches add device links for pcs-handle to improve boot times,
> >> >> and add compatibles for all Lynx PCSs.
> >> >>
> >> >> Care has been taken to ensure backwards-compatibility. The main source
> >> >> of this is that many PCS devices lack compatibles and get detected as
> >> >> PHYs. To address this, pcs_get_by_fwnode_compat allows drivers to edit
> >> >> the devicetree to add appropriate compatibles.
> >> >
> >> > I don't dive into your patch series and I don't know if you have heard about it
> >> > but Christian Marangi is currently working on fwnode for PCS:
> >> > https://lore.kernel.org/netdev/20250406221423.9723-1-ansuelsmth@gmail.com
> >> >
> >> > Maybe you should sync with him!
> >>
> >> I saw that series and made some comments. He is CC'd on this one.
> >>
> >> I think this approach has two advantages:
> >>
> >> - It completely solves the problem of the PCS being unregistered while the netdev
> >> (or whatever) is up
> >> - I have designed the interface to make it easy to convert existing
> >> drivers that may not be able to use the "standard" probing process
> >> (because they have to support other devicetree structures for
> >> backwards-compatibility).
> >>
> >
> > I notice this and it's my fault for taking too long to post v2 of the PCS patch.
> > There was also this idea of entering the wrapper hell but I scrapped that early
> > as I really feel it's a workaround to the current problem present for
> > PCS handling.
>
> It's no workaround. The fundamental problem is that drivers can become
> unbound at any time, and we cannot make consumers drop their references.
> Every subsystem must deal with this reality, or suffer from
> user-after-free bugs. See [1-3] for discussion of this problem in
> relation to PCSs and PHYs, and [4] for more discussion of my approach.
>
> [1] https://lore.kernel.org/netdev/YV7Kp2k8VvN7J0fY@shell.armlinux.org.uk/
> [2] https://lore.kernel.org/netdev/20220816163701.1578850-1-sean.anderson@seco.com/
> [3] https://lore.kernel.org/netdev/9747f8ef-66b3-0870-cbc0-c1783896b30d@seco.com/
> [3] https://lpc.events/event/17/contributions/1627/
>
> > And the real problem IMHO is that currently PCS handling is fragile and with too
> > many assumptions. With Daniel we also discussed backwards-compatibility.
> > (mainly needed for mt7621 and mt7986 (for mediatek side those are the 2
> > that slipped in before it was correctly complained that things were
> > taking a bad path)
> >
> > We feel v2 permits correct support of old implementations.
> > The ""legacy"" implementation pose the assumption that PCS is never removed
> > (unless the MAC driver is removed)
> > That fits v2 where a MAC has to initially provide a list of PCS to
> > phylink instance.
>
> And what happens when the driver is unbound from the device and suddenly
> a PCS on that list is free'd memory but is in active use by a netdev?
>
driver bug for not correctly implementing the removal task.
The approach is remove as provider and call phylink removal phase
under rtnl lock.
We tested this with unbind, that is actually the main problem we are
trying to address
and works correctly.
> > With this implementation, a MAC can manually parse whatever PCS node structure
> > is in place and fill the PCS.
> >
> > As really the "late" removal/addition of a PCS can only be supported with fwnode
> > implementation as dedicated PCS driver will make use of that.
>
> I agree that a "cells" approach would require this, but
>
> - There are no in-tree examples of where this is necessary
> - I think this would be easy to add when necessary
>
There are no in-tree cause only now we are starting to support
complex configuration with multiple PCS placed outside the MAC.
I feel it's better to define a standard API for them now before
we permit even more MAC driver to implement custom property
and have to address tons of workaround for compatibility.
> > I honestly hope we can skip having to enter the wrapper hell.
>
> Unfortunately, this is required by the kernel driver model :l
>
> > Anyway I also see you made REALLY GOOD documentation.
>
> Thanks. One of my peeves is subsystems that have zero docs...
>
> > Would be ideal to
> > collaborate for that. Anyway it's up to net maintainers on what path to follow.
> >
> > Just my 2 cent on the PCS topic.
>
> --Sean
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 00/13] Add PCS core support
2025-04-07 17:21 ` Christian Marangi (Ansuel)
@ 2025-04-07 17:25 ` Daniel Golle
2025-04-07 17:40 ` Sean Anderson
2025-04-08 15:17 ` Sean Anderson
2025-04-07 18:06 ` Sean Anderson
1 sibling, 2 replies; 35+ messages in thread
From: Daniel Golle @ 2025-04-07 17:25 UTC (permalink / raw)
To: Christian Marangi (Ansuel)
Cc: Sean Anderson, Kory Maincent, netdev, Andrew Lunn,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King, linux-kernel, upstream, Heiner Kallweit,
Alexandre Belloni, Alexandre Torgue, Christophe Leroy, Clark Wang,
Claudiu Beznea, Claudiu Manoil, Conor Dooley, Ioana Ciornei,
Jonathan Corbet, Joyce Ooi, Krzysztof Kozlowski,
Krzysztof Kozlowski, Li Yang, Madalin Bucur, Madhavan Srinivasan,
Maxime Coquelin, Michael Ellerman, Michal Simek, Naveen N Rao,
Nicholas Piggin, Nicolas Ferre, Radhey Shyam Pandey, Rob Herring,
Rob Herring, Robert Hancock, Saravana Kannan, Shawn Guo,
UNGLinuxDriver, Vladimir Oltean, Wei Fang, devicetree, imx,
linux-arm-kernel, linux-doc, linux-stm32, linuxppc-dev
On Mon, Apr 07, 2025 at 07:21:38PM +0200, Christian Marangi (Ansuel) wrote:
> Il giorno lun 7 apr 2025 alle ore 19:00 Sean Anderson
> > I agree that a "cells" approach would require this, but
> >
> > - There are no in-tree examples of where this is necessary
> > - I think this would be easy to add when necessary
> >
>
> There are no in-tree cause only now we are starting to support
> complex configuration with multiple PCS placed outside the MAC.
>
> I feel it's better to define a standard API for them now before
> we permit even more MAC driver to implement custom property
> and have to address tons of workaround for compatibility.
Qualcomm's PCS driver will require offering multiple phylink_pcs by a
single device/of_node. So while it's true that there is currently no
in-tree user for that, that very user is already knocking on our doors.
See
https://patchwork.kernel.org/project/netdevbpf/list/?series=931658&state=*
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 00/13] Add PCS core support
2025-04-07 17:25 ` Daniel Golle
@ 2025-04-07 17:40 ` Sean Anderson
2025-04-08 15:17 ` Sean Anderson
1 sibling, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-07 17:40 UTC (permalink / raw)
To: Daniel Golle, Christian Marangi (Ansuel)
Cc: Kory Maincent, netdev, Andrew Lunn, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel, upstream, Heiner Kallweit, Alexandre Belloni,
Alexandre Torgue, Christophe Leroy, Clark Wang, Claudiu Beznea,
Claudiu Manoil, Conor Dooley, Ioana Ciornei, Jonathan Corbet,
Joyce Ooi, Krzysztof Kozlowski, Krzysztof Kozlowski, Li Yang,
Madalin Bucur, Madhavan Srinivasan, Maxime Coquelin,
Michael Ellerman, Michal Simek, Naveen N Rao, Nicholas Piggin,
Nicolas Ferre, Radhey Shyam Pandey, Rob Herring, Rob Herring,
Robert Hancock, Saravana Kannan, Shawn Guo, UNGLinuxDriver,
Vladimir Oltean, Wei Fang, devicetree, imx, linux-arm-kernel,
linux-doc, linux-stm32, linuxppc-dev
On 4/7/25 13:25, Daniel Golle wrote:
> On Mon, Apr 07, 2025 at 07:21:38PM +0200, Christian Marangi (Ansuel) wrote:
>> Il giorno lun 7 apr 2025 alle ore 19:00 Sean Anderson
>> > I agree that a "cells" approach would require this, but
>> >
>> > - There are no in-tree examples of where this is necessary
>> > - I think this would be easy to add when necessary
>> >
>>
>> There are no in-tree cause only now we are starting to support
>> complex configuration with multiple PCS placed outside the MAC.
>>
>> I feel it's better to define a standard API for them now before
>> we permit even more MAC driver to implement custom property
>> and have to address tons of workaround for compatibility.
>
> Qualcomm's PCS driver will require offering multiple phylink_pcs by a
> single device/of_node. So while it's true that there is currently no
> in-tree user for that, that very user is already knocking on our doors.
>
> See
> https://patchwork.kernel.org/project/netdevbpf/list/?series=931658&state=*
OK, but I still think this is quite easy to add.
--Sean
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 00/13] Add PCS core support
2025-04-07 17:21 ` Christian Marangi (Ansuel)
2025-04-07 17:25 ` Daniel Golle
@ 2025-04-07 18:06 ` Sean Anderson
1 sibling, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-07 18:06 UTC (permalink / raw)
To: Christian Marangi (Ansuel)
Cc: Kory Maincent, netdev, Andrew Lunn, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel, upstream, Heiner Kallweit, Alexandre Belloni,
Alexandre Torgue, Christophe Leroy, Clark Wang, Claudiu Beznea,
Claudiu Manoil, Conor Dooley, Ioana Ciornei, Jonathan Corbet,
Joyce Ooi, Krzysztof Kozlowski, Krzysztof Kozlowski, Li Yang,
Madalin Bucur, Madhavan Srinivasan, Maxime Coquelin,
Michael Ellerman, Michal Simek, Naveen N Rao, Nicholas Piggin,
Nicolas Ferre, Radhey Shyam Pandey, Rob Herring, Rob Herring,
Robert Hancock, Saravana Kannan, Shawn Guo, UNGLinuxDriver,
Vladimir Oltean, Wei Fang, devicetree, imx, linux-arm-kernel,
linux-doc, linux-stm32, linuxppc-dev
On 4/7/25 13:21, Christian Marangi (Ansuel) wrote:
> Il giorno lun 7 apr 2025 alle ore 19:00 Sean Anderson
> <sean.anderson@linux.dev> ha scritto:
>>
>> On 4/7/25 12:46, Christian Marangi (Ansuel) wrote:
>> > Il giorno lun 7 apr 2025 alle ore 18:33 Sean Anderson
>> > <sean.anderson@linux.dev> ha scritto:
>> >>
>> >> On 4/7/25 12:27, Kory Maincent wrote:
>> >> > On Thu, 3 Apr 2025 14:18:54 -0400
>> >> > Sean Anderson <sean.anderson@linux.dev> wrote:
>> >> >
>> >> >> This series adds support for creating PCSs as devices on a bus with a
>> >> >> driver (patch 3). As initial users,
>> >> >>
>> >> >> - The Lynx PCS (and all of its users) is converted to this system (patch 5)
>> >> >> - The Xilinx PCS is broken out from the AXI Ethernet driver (patches 6-8)
>> >> >> - The Cadence MACB driver is converted to support external PCSs (namely
>> >> >> the Xilinx PCS) (patches 9-10).
>> >> >>
>> >> >> The last few patches add device links for pcs-handle to improve boot times,
>> >> >> and add compatibles for all Lynx PCSs.
>> >> >>
>> >> >> Care has been taken to ensure backwards-compatibility. The main source
>> >> >> of this is that many PCS devices lack compatibles and get detected as
>> >> >> PHYs. To address this, pcs_get_by_fwnode_compat allows drivers to edit
>> >> >> the devicetree to add appropriate compatibles.
>> >> >
>> >> > I don't dive into your patch series and I don't know if you have heard about it
>> >> > but Christian Marangi is currently working on fwnode for PCS:
>> >> > https://lore.kernel.org/netdev/20250406221423.9723-1-ansuelsmth@gmail.com
>> >> >
>> >> > Maybe you should sync with him!
>> >>
>> >> I saw that series and made some comments. He is CC'd on this one.
>> >>
>> >> I think this approach has two advantages:
>> >>
>> >> - It completely solves the problem of the PCS being unregistered while the netdev
>> >> (or whatever) is up
>> >> - I have designed the interface to make it easy to convert existing
>> >> drivers that may not be able to use the "standard" probing process
>> >> (because they have to support other devicetree structures for
>> >> backwards-compatibility).
>> >>
>> >
>> > I notice this and it's my fault for taking too long to post v2 of the PCS patch.
>> > There was also this idea of entering the wrapper hell but I scrapped that early
>> > as I really feel it's a workaround to the current problem present for
>> > PCS handling.
>>
>> It's no workaround. The fundamental problem is that drivers can become
>> unbound at any time, and we cannot make consumers drop their references.
>> Every subsystem must deal with this reality, or suffer from
>> user-after-free bugs. See [1-3] for discussion of this problem in
>> relation to PCSs and PHYs, and [4] for more discussion of my approach.
>>
>> [1] https://lore.kernel.org/netdev/YV7Kp2k8VvN7J0fY@shell.armlinux.org.uk/
>> [2] https://lore.kernel.org/netdev/20220816163701.1578850-1-sean.anderson@seco.com/
>> [3] https://lore.kernel.org/netdev/9747f8ef-66b3-0870-cbc0-c1783896b30d@seco.com/
>> [3] https://lpc.events/event/17/contributions/1627/
>>
>> > And the real problem IMHO is that currently PCS handling is fragile and with too
>> > many assumptions. With Daniel we also discussed backwards-compatibility.
>> > (mainly needed for mt7621 and mt7986 (for mediatek side those are the 2
>> > that slipped in before it was correctly complained that things were
>> > taking a bad path)
>> >
>> > We feel v2 permits correct support of old implementations.
>> > The ""legacy"" implementation pose the assumption that PCS is never removed
>> > (unless the MAC driver is removed)
>> > That fits v2 where a MAC has to initially provide a list of PCS to
>> > phylink instance.
>>
>> And what happens when the driver is unbound from the device and suddenly
>> a PCS on that list is free'd memory but is in active use by a netdev?
>>
>
> driver bug for not correctly implementing the removal task.
>
> The approach is remove as provider and call phylink removal phase
> under rtnl lock.
> We tested this with unbind, that is actually the main problem we are
> trying to address
> and works correctly.
OK, so this is a different approach since your last submission. Please
CC me on your series.
- Fundamentally this is going to make backwards compatibility very
difficult, since your approach cannot work with mac_select_pcs. How
are you going to handle the case of MAC-internal PCSs? Are you going
to make them create a swnode and bind to it just to create a PCS for
e.g. MMIO registers? And how is the MAC supposed to know how to select
the PCS? From what I can tell you don't even notify the MAC about
which PCS it's using.
I considered an approach like this, where the phylink would be in the
driver's seat (so to speak), but I decided not to persue it due to
the problems listed above. A lot of PCSs are tightly-integrated with
their MACs, so it does not make sense to introduce this little
coupling. I think it is better to let the MAC select the PCS e.g.
based on the phy interface. This tends to be a few lines of code for
the MAC and saves so much complexity in phylink.
I think you should try doing the macb and lynx conversions for your
approach. It will make the above problems obvious.
- Your approach is very intrusive. There are lots of changes all over
phylink across several patches and it is hard to verify all the
assumptions. Whereas a wrapper keeps everything contained to one file,
and most of the functions can be evaluated independently.
--Sean
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [RFC net-next PATCH 00/13] Add PCS core support
2025-04-07 17:25 ` Daniel Golle
2025-04-07 17:40 ` Sean Anderson
@ 2025-04-08 15:17 ` Sean Anderson
1 sibling, 0 replies; 35+ messages in thread
From: Sean Anderson @ 2025-04-08 15:17 UTC (permalink / raw)
To: Daniel Golle, Christian Marangi (Ansuel)
Cc: Kory Maincent, netdev, Andrew Lunn, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel, upstream, Heiner Kallweit, Alexandre Belloni,
Alexandre Torgue, Christophe Leroy, Clark Wang, Claudiu Beznea,
Claudiu Manoil, Conor Dooley, Ioana Ciornei, Jonathan Corbet,
Joyce Ooi, Krzysztof Kozlowski, Krzysztof Kozlowski, Li Yang,
Madalin Bucur, Madhavan Srinivasan, Maxime Coquelin,
Michael Ellerman, Michal Simek, Naveen N Rao, Nicholas Piggin,
Nicolas Ferre, Radhey Shyam Pandey, Rob Herring, Rob Herring,
Robert Hancock, Saravana Kannan, Shawn Guo, UNGLinuxDriver,
Vladimir Oltean, Wei Fang, devicetree, imx, linux-arm-kernel,
linux-doc, linux-stm32, linuxppc-dev
On 4/7/25 13:25, Daniel Golle wrote:
> On Mon, Apr 07, 2025 at 07:21:38PM +0200, Christian Marangi (Ansuel) wrote:
>> Il giorno lun 7 apr 2025 alle ore 19:00 Sean Anderson
>> > I agree that a "cells" approach would require this, but
>> >
>> > - There are no in-tree examples of where this is necessary
>> > - I think this would be easy to add when necessary
>> >
>>
>> There are no in-tree cause only now we are starting to support
>> complex configuration with multiple PCS placed outside the MAC.
>>
>> I feel it's better to define a standard API for them now before
>> we permit even more MAC driver to implement custom property
>> and have to address tons of workaround for compatibility.
>
> Qualcomm's PCS driver will require offering multiple phylink_pcs by a
> single device/of_node. So while it's true that there is currently no
> in-tree user for that, that very user is already knocking on our doors.
>
> See
> https://patchwork.kernel.org/project/netdevbpf/list/?series=931658&state=*
OK, but you have separate nodes for each PCS? So maybe the best thing is to
allow customizing the fwnode? E.g. something like
pcs_register_fwnode(struct device *dev, struct phylink_pcs *pcs, struct fwnode_handle *fwnode)
--Sean
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2025-04-08 15:18 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-03 18:18 [RFC net-next PATCH 00/13] Add PCS core support Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 01/13] dt-bindings: net: Add binding for Xilinx PCS Sean Anderson
2025-04-04 10:37 ` Krzysztof Kozlowski
2025-04-04 10:39 ` Krzysztof Kozlowski
2025-04-04 15:12 ` Sean Anderson
2025-04-04 15:19 ` Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 02/13] net: phylink: Support setting PCS link change callbacks Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 03/13] net: pcs: Add subsystem Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 04/13] net: dsa: ocelot: suppress PHY device scanning on the internal MDIO bus Sean Anderson
2025-04-03 18:18 ` [RFC net-next PATCH 05/13] net: pcs: lynx: Convert to an MDIO driver Sean Anderson
2025-04-03 18:19 ` [RFC net-next PATCH 06/13] net: phy: Export some functions Sean Anderson
2025-04-03 18:37 ` Florian Fainelli
2025-04-03 19:08 ` Sean Anderson
2025-04-03 18:19 ` [RFC net-next PATCH 07/13] net: pcs: Add Xilinx PCS driver Sean Anderson
2025-04-03 20:27 ` Russell King (Oracle)
2025-04-03 20:51 ` Sean Anderson
2025-04-03 18:19 ` [RFC net-next PATCH 08/13] net: axienet: Convert to use PCS subsystem Sean Anderson
2025-04-03 18:19 ` [RFC net-next PATCH 09/13] net: macb: Move most of mac_config to mac_prepare Sean Anderson
2025-04-03 18:27 ` [RFC net-next PATCH 10/13] net: macb: Support external PCSs Sean Anderson
2025-04-03 20:31 ` Russell King (Oracle)
2025-04-03 18:27 ` [RFC net-next PATCH 11/13] of: property: Add device link support for PCS Sean Anderson
2025-04-03 18:32 ` Saravana Kannan
2025-04-03 19:04 ` Sean Anderson
2025-04-03 18:28 ` [RFC net-next PATCH 12/13] arm64: dts: Add compatible strings for Lynx PCSs Sean Anderson
2025-04-03 18:30 ` [RFC net-next PATCH 13/13] powerpc: " Sean Anderson
2025-04-07 16:27 ` [RFC net-next PATCH 00/13] Add PCS core support Kory Maincent
2025-04-07 16:33 ` Sean Anderson
2025-04-07 16:46 ` Christian Marangi (Ansuel)
2025-04-07 17:00 ` Sean Anderson
2025-04-07 17:21 ` Christian Marangi (Ansuel)
2025-04-07 17:25 ` Daniel Golle
2025-04-07 17:40 ` Sean Anderson
2025-04-08 15:17 ` Sean Anderson
2025-04-07 18:06 ` Sean Anderson
2025-04-07 16:51 ` Kory Maincent
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).