[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250403181907.1947517-9-sean.anderson@linux.dev>
Date: Thu, 3 Apr 2025 14:19:02 -0400
From: Sean Anderson <sean.anderson@...ux.dev>
To: netdev@...r.kernel.org,
Andrew Lunn <andrew+netdev@...n.ch>,
"David S . Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
Russell King <linux@...linux.org.uk>
Cc: linux-kernel@...r.kernel.org,
Christian Marangi <ansuelsmth@...il.com>,
upstream@...oha.com,
Heiner Kallweit <hkallweit1@...il.com>,
Sean Anderson <sean.anderson@...ux.dev>,
Michal Simek <michal.simek@....com>,
Radhey Shyam Pandey <radhey.shyam.pandey@....com>,
Robert Hancock <robert.hancock@...ian.com>,
linux-arm-kernel@...ts.infradead.org
Subject: [RFC net-next PATCH 08/13] net: axienet: Convert to use PCS subsystem
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@...ux.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
Powered by blists - more mailing lists