[RFC PATCH net-next 4/9] net: pcs: lynx: Convert to an mdio driver
From: Sean Anderson <hidden>
Date: 2022-07-11 16:06:26
Also in:
lkml
Subsystem:
dpaa2 ethernet driver, ethernet phy library, freescale enetc ethernet drivers, lynx pcs module, networking drivers, networking [dsa], ocelot ethernet switch driver, the rest · Maintainers:
Ioana Ciornei, Andrew Lunn, Heiner Kallweit, Claudiu Manoil, Vladimir Oltean, Wei Fang, Clark Wang, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
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). For compatibility with existing device trees lacking a compatible property, we bind the driver in lynx_pcs_create. This is intended only as a transitional method. After compatible properties are added to all existing device trees (and a reasonable amount of time has passed), then lynx_pcs_create can be removed, and users can be converted to pcs_get_fwnode. Signed-off-by: Sean Anderson <redacted> --- drivers/net/dsa/ocelot/Kconfig | 2 + drivers/net/dsa/ocelot/felix_vsc9959.c | 2 +- drivers/net/dsa/ocelot/seville_vsc9953.c | 2 +- drivers/net/ethernet/freescale/dpaa2/Kconfig | 1 + .../net/ethernet/freescale/dpaa2/dpaa2-mac.c | 4 +- drivers/net/ethernet/freescale/enetc/Kconfig | 1 + .../net/ethernet/freescale/enetc/enetc_pf.c | 4 +- drivers/net/pcs/Kconfig | 11 +++- drivers/net/pcs/pcs-lynx.c | 65 +++++++++++++++---- 9 files changed, 72 insertions(+), 20 deletions(-)
diff --git a/drivers/net/dsa/ocelot/Kconfig b/drivers/net/dsa/ocelot/Kconfig
index 220b0b027b55..cbb0ced3f37d 100644
--- a/drivers/net/dsa/ocelot/Kconfig
+++ b/drivers/net/dsa/ocelot/Kconfig@@ -10,6 +10,7 @@ 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 help This driver supports the VSC9959 (Felix) switch, which is embedded as
@@ -25,6 +26,7 @@ config NET_DSA_MSCC_SEVILLE select MSCC_OCELOT_SWITCH_LIB select NET_DSA_TAG_OCELOT_8021Q select NET_DSA_TAG_OCELOT + select PCS select PCS_LYNX help This driver supports the VSC9953 (Seville) switch, which is embedded
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 570d0204b7be..57634e2296c0 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c@@ -1094,7 +1094,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) continue; phylink_pcs = lynx_pcs_create(mdio_device); - if (!phylink_pcs) { + if (IS_ERR(phylink_pcs)) { mdio_device_free(mdio_device); continue; }
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index ea0649211356..8c52de5d0b02 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c@@ -1049,7 +1049,7 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot) continue; phylink_pcs = lynx_pcs_create(mdio_device); - if (!phylink_pcs) { + if (IS_ERR(phylink_pcs)) { mdio_device_free(mdio_device); continue; }
diff --git a/drivers/net/ethernet/freescale/dpaa2/Kconfig b/drivers/net/ethernet/freescale/dpaa2/Kconfig
index d029b69c3f18..2648e9fb6e13 100644
--- a/drivers/net/ethernet/freescale/dpaa2/Kconfig
+++ b/drivers/net/ethernet/freescale/dpaa2/Kconfig@@ -3,6 +3,7 @@ config FSL_DPAA2_ETH tristate "Freescale DPAA2 Ethernet" depends on FSL_MC_BUS && FSL_MC_DPIO select PHYLINK + select PCS select PCS_LYNX select FSL_XGMAC_MDIO select NET_DEVLINK
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index c9bee9a0c9b2..e82c0d23eeb5 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c@@ -268,10 +268,10 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac, return -EPROBE_DEFER; mac->pcs = lynx_pcs_create(mdiodev); - if (!mac->pcs) { + if (IS_ERR(mac->pcs)) { netdev_err(mac->net_dev, "lynx_pcs_create() failed\n"); put_device(&mdiodev->dev); - return -ENOMEM; + return PTR_ERR(mac->pcs); } return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index cdc0ff89388a..c7dcdeb9a333 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig@@ -5,6 +5,7 @@ config FSL_ENETC select FSL_ENETC_IERB select FSL_ENETC_MDIO select PHYLINK + select PCS select PCS_LYNX select DIMLIB help
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index c4a0e836d4f0..8c923a93da88 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c@@ -859,9 +859,9 @@ static int enetc_imdio_create(struct enetc_pf *pf) } phylink_pcs = lynx_pcs_create(mdio_device); - if (!phylink_pcs) { + if (IS_ERR(phylink_pcs)) { mdio_device_free(mdio_device); - err = -ENOMEM; + err = PTR_ERR(phylink_pcs); dev_err(dev, "cannot create lynx pcs (%d)\n", err); goto unregister_mdiobus; }
diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig
index fed6264fdf33..a225176f92e8 100644
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig@@ -25,9 +25,14 @@ config PCS_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". endmenu
diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c
index fd3445374955..8272072698e4 100644
--- a/drivers/net/pcs/pcs-lynx.c
+++ b/drivers/net/pcs/pcs-lynx.c@@ -1,11 +1,14 @@ -// 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> #define SGMII_CLOCK_PERIOD_NS 8 /* PCS is clocked at 125 MHz */ #define LINK_TIMER_VAL(ns) ((u32)((ns) / SGMII_CLOCK_PERIOD_NS))
@@ -337,34 +340,74 @@ static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, } static const struct phylink_pcs_ops lynx_pcs_phylink_ops = { + .owner = THIS_MODULE, .pcs_get_state = lynx_pcs_get_state, .pcs_config = lynx_pcs_config, .pcs_an_restart = lynx_pcs_an_restart, .pcs_link_up = lynx_pcs_link_up, }; -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 ret; - lynx = kzalloc(sizeof(*lynx), GFP_KERNEL); + lynx = devm_kzalloc(dev, sizeof(*lynx), GFP_KERNEL); if (!lynx) - return NULL; + return -ENOMEM; lynx->mdio = mdio; + lynx->pcs.dev = dev; lynx->pcs.ops = &lynx_pcs_phylink_ops; lynx->pcs.poll = true; - 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; +} + +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(struct mdio_device *mdio) +{ + struct device *dev = &mdio->dev; + int err; + + /* For compatibility with device trees lacking compatible strings, we + * bind the device manually here. + */ + err = device_driver_attach(&lynx_pcs_driver.mdiodrv.driver, dev); + if (err && err != -EBUSY) { + if (err == -EAGAIN) + err = -EPROBE_DEFER; + return ERR_PTR(err); + } + + return pcs_get_by_provider(&mdio->dev); } EXPORT_SYMBOL(lynx_pcs_create); void lynx_pcs_destroy(struct phylink_pcs *pcs) { - struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); - - kfree(lynx); + pcs_put(pcs); } EXPORT_SYMBOL(lynx_pcs_destroy); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("NXP Lynx 10G/28G PCS driver"); +MODULE_LICENSE("GPL");
--
2.35.1.1320.gc452695387.dirty