For EHL & TGL Ethernet PCS, the mdio bus address is the same across all TSN controller instances. External PHY is using default mdio bus address of 0x0. As Ethernet DW PCS is only applicable for SGMII interface, we only register setup_intel_mgbe_phy_conv() for all TSN controller with SGMII interface only.
Also introduce callback for remove mdio_device for unloading driver. Signed-off-by: Ong Boon Leong <boon.leong....@intel.com> --- drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 25 +++++++++++ .../net/ethernet/stmicro/stmmac/stmmac_pci.c | 45 ++++++++++++++++++- include/linux/stmmac.h | 3 ++ 5 files changed, 75 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 2325b40dff6e..db4332863611 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -200,6 +200,7 @@ endif config STMMAC_PCI tristate "STMMAC PCI bus support" depends on STMMAC_ETH && PCI + select DWXPCS ---help--- This selects the platform specific bus support for the stmmac driver. This driver was tested on XLINX XC2V3000 FF1152AMT0221 diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index dcb2e29a5717..d4e232223941 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -29,6 +29,7 @@ struct stmmac_resources { int wol_irq; int lpi_irq; int irq; + int phy_conv_irq; }; struct stmmac_tx_info { @@ -203,6 +204,7 @@ struct stmmac_priv { void __iomem *mmcaddr; void __iomem *ptpaddr; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; + int phy_conv_irq; #ifdef CONFIG_DEBUG_FS struct dentry *dbgfs_dir; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 06ccd216ae90..43e3d3799581 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2726,11 +2726,23 @@ static int stmmac_open(struct net_device *dev) } } + /* Start phy converter after MDIO bus IRQ handling is up */ + if (priv->plat->setup_phy_conv) { + ret = priv->plat->setup_phy_conv(priv->mii, priv->phy_conv_irq); + if (ret < 0) { + netdev_err(priv->dev, + "%s: ERROR: setup phy conv (error: %d)\n", + __func__, ret); + goto phy_conv_error; + } + } + stmmac_enable_all_queues(priv); stmmac_start_all_queues(priv); return 0; +phy_conv_error: lpiirq_error: if (priv->wol_irq != dev->irq) free_irq(priv->wol_irq, dev); @@ -2760,6 +2772,7 @@ static int stmmac_release(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); u32 chan; + int ret; if (priv->eee_enabled) del_timer_sync(&priv->eee_ctrl_timer); @@ -2782,6 +2795,17 @@ static int stmmac_release(struct net_device *dev) if (priv->lpi_irq > 0) free_irq(priv->lpi_irq, dev); + /* Start phy converter after MDIO bus IRQ handling is up */ + if (priv->plat->remove_phy_conv) { + ret = priv->plat->remove_phy_conv(priv->mii); + if (ret < 0) { + netdev_err(priv->dev, + "%s: ERROR: remove phy conv (error: %d)\n", + __func__, ret); + return 0; + } + } + /* Stop TX/RX DMA and clear the descriptors */ stmmac_stop_all_dma(priv); @@ -4424,6 +4448,7 @@ int stmmac_dvr_probe(struct device *device, priv->dev->irq = res->irq; priv->wol_irq = res->wol_irq; priv->lpi_irq = res->lpi_irq; + priv->phy_conv_irq = res->phy_conv_irq; if (!IS_ERR_OR_NULL(res->mac)) memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 20906287b6d4..c3dfb0e9b025 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -10,9 +10,10 @@ *******************************************************************************/ #include <linux/clk-provider.h> +#include <linux/phy.h> #include <linux/pci.h> #include <linux/dmi.h> - +#include <linux/dwxpcs.h> #include "stmmac.h" /* @@ -109,6 +110,42 @@ static const struct stmmac_pci_info stmmac_pci_info = { .setup = stmmac_default_data, }; +static struct dwxpcs_platform_data intel_mgbe_pdata = { + .mode = DWXPCS_MODE_SGMII_AN, + .ext_phy_addr = 0x0, +}; + +static struct mdio_board_info intel_mgbe_bdinfo = { + .bus_id = "stmmac-1", + .modalias = "dwxpcs", + .mdio_addr = 0x16, + .platform_data = &intel_mgbe_pdata, +}; + +static int setup_intel_mgbe_phy_conv(struct mii_bus *bus, int irq) +{ + struct dwxpcs_platform_data *pdata = &intel_mgbe_pdata; + + pdata->irq = irq; + + return mdiobus_create_device(bus, &intel_mgbe_bdinfo); +} + +static int remove_intel_mgbe_phy_conv(struct mii_bus *bus) +{ + struct mdio_board_info *bdinfo = &intel_mgbe_bdinfo; + struct mdio_device *mdiodev; + + mdiodev = mdiobus_get_mdio_device(bus, bdinfo->mdio_addr); + + if (!mdiodev) + return -1; + + mdio_device_remove(mdiodev); + + return 0; +} + static int intel_mgbe_common_data(struct pci_dev *pdev, struct plat_stmmacenet_data *plat) { @@ -197,6 +234,11 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, /* Set the maxmtu to a default of JUMBO_LEN */ plat->maxmtu = JUMBO_LEN; + if (plat->interface == PHY_INTERFACE_MODE_SGMII) { + plat->setup_phy_conv = setup_intel_mgbe_phy_conv; + plat->remove_phy_conv = remove_intel_mgbe_phy_conv; + } + return 0; } @@ -441,6 +483,7 @@ static int stmmac_pci_probe(struct pci_dev *pdev, res.addr = pcim_iomap_table(pdev)[i]; res.wol_irq = pdev->irq; res.irq = pdev->irq; + res.phy_conv_irq = res.irq; return stmmac_dvr_probe(&pdev->dev, plat, &res); } diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 7ad7ae35cf88..9ffd0e9c21b1 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -12,6 +12,7 @@ #ifndef __STMMAC_PLATFORM_DATA #define __STMMAC_PLATFORM_DATA +#include <linux/phy.h> #include <linux/platform_device.h> #define MTL_MAX_RX_QUEUES 8 @@ -162,6 +163,8 @@ struct plat_stmmacenet_data { int (*init)(struct platform_device *pdev, void *priv); void (*exit)(struct platform_device *pdev, void *priv); struct mac_device_info *(*setup)(void *priv); + int (*setup_phy_conv)(struct mii_bus *bus, int irq); + int (*remove_phy_conv)(struct mii_bus *bus); void *bsp_priv; struct clk *stmmac_clk; struct clk *pclk; -- 2.17.0