From patchwork Wed Aug 28 17:47:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ong Boon Leong X-Patchwork-Id: 1154702 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46JY9l0yGrz9sDQ for ; Thu, 29 Aug 2019 03:47:55 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726897AbfH1Rru (ORCPT ); Wed, 28 Aug 2019 13:47:50 -0400 Received: from mga02.intel.com ([134.134.136.20]:20452 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726515AbfH1Rru (ORCPT ); Wed, 28 Aug 2019 13:47:50 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Aug 2019 10:47:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,442,1559545200"; d="scan'208";a="192675244" Received: from glass.png.intel.com ([172.30.181.95]) by orsmga002.jf.intel.com with ESMTP; 28 Aug 2019 10:47:28 -0700 From: Ong Boon Leong To: davem@davemloft.net, linux@armlinux.org.uk, mcoquelin.stm32@gmail.com, joabreu@synopsys.com, f.fainelli@gmail.com, andrew@lunn.ch Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, peppe.cavallaro@st.com, alexandre.torgue@st.com, weifeng.voon@intel.com Subject: [RFC net-next v2 1/5] net: phy: make mdiobus_create_device() function callable from Eth driver Date: Thu, 29 Aug 2019 01:47:18 +0800 Message-Id: <20190828174722.6726-2-boon.leong.ong@intel.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20190828174722.6726-1-boon.leong.ong@intel.com> References: <20190828174722.6726-1-boon.leong.ong@intel.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org PHY converter and external PHY drivers depend on MDIO functions of Eth driver and such MDIO read/write completion may fire IRQ. The ISR for MDIO completion IRQ is done in the open() function of driver. For PHY converter mdio driver that registers ISR event that uses MDIO read/write function during its probe() function, the MDIO ISR should have been performed a head of time before mdio driver probe() is called. It is for reason as such, the mdio device creation and registration will need to be callable from Eth driver open() function. Why existing way to register mdio_device for PHY converter that is done via mdiobus_register_board_info() is not feasible is the mdio device creation and registration happens inside Eth driver probe() function, specifically in mdiobus_setup_mdiodevfrom_board_info() that is called by mdiobus_register(). Therefore, to fulfill the need mentioned above, we make mdiobus_create_ device() to be callable from Eth driver open(). Signed-off-by: Ong Boon Leong --- drivers/net/phy/mdio_bus.c | 5 +++-- include/linux/phy.h | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index bd04fe762056..06658d9197a1 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -338,8 +338,8 @@ static inline void of_mdiobus_link_mdiodev(struct mii_bus *mdio, * * Returns 0 on success or < 0 on error. */ -static int mdiobus_create_device(struct mii_bus *bus, - struct mdio_board_info *bi) +int mdiobus_create_device(struct mii_bus *bus, + struct mdio_board_info *bi) { struct mdio_device *mdiodev; int ret = 0; @@ -359,6 +359,7 @@ static int mdiobus_create_device(struct mii_bus *bus, return ret; } +EXPORT_SYMBOL(mdiobus_create_device); /** * __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus diff --git a/include/linux/phy.h b/include/linux/phy.h index d26779f1fb6b..4524db57fe0b 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1249,12 +1249,19 @@ struct mdio_board_info { #if IS_ENABLED(CONFIG_MDIO_DEVICE) int mdiobus_register_board_info(const struct mdio_board_info *info, unsigned int n); +int mdiobus_create_device(struct mii_bus *bus, struct mdio_board_info *bi); #else static inline int mdiobus_register_board_info(const struct mdio_board_info *i, unsigned int n) { return 0; } + +static inline int mdiobus_create_device(struct mii_bus *bus, + struct mdio_board_info *bi) +{ + return 0; +} #endif From patchwork Wed Aug 28 17:47:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ong Boon Leong X-Patchwork-Id: 1154704 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46JY9x2zZRz9sN1 for ; Thu, 29 Aug 2019 03:48:05 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726991AbfH1Rrz (ORCPT ); Wed, 28 Aug 2019 13:47:55 -0400 Received: from mga02.intel.com ([134.134.136.20]:20452 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726583AbfH1Rrw (ORCPT ); Wed, 28 Aug 2019 13:47:52 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Aug 2019 10:47:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,442,1559545200"; d="scan'208";a="192675389" Received: from glass.png.intel.com ([172.30.181.95]) by orsmga002.jf.intel.com with ESMTP; 28 Aug 2019 10:47:31 -0700 From: Ong Boon Leong To: davem@davemloft.net, linux@armlinux.org.uk, mcoquelin.stm32@gmail.com, joabreu@synopsys.com, f.fainelli@gmail.com, andrew@lunn.ch Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, peppe.cavallaro@st.com, alexandre.torgue@st.com, weifeng.voon@intel.com Subject: [RFC net-next v2 2/5] net: phy: introduce mdiobus_get_mdio_device Date: Thu, 29 Aug 2019 01:47:19 +0800 Message-Id: <20190828174722.6726-3-boon.leong.ong@intel.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20190828174722.6726-1-boon.leong.ong@intel.com> References: <20190828174722.6726-1-boon.leong.ong@intel.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add the function to get mdio_device based on the mdio addr. Signed-off-by: Ong Boon Leong --- drivers/net/phy/mdio_bus.c | 6 ++++++ include/linux/mdio.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 06658d9197a1..96ef94f87ff1 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -130,6 +130,12 @@ struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr) } EXPORT_SYMBOL(mdiobus_get_phy); +struct mdio_device *mdiobus_get_mdio_device(struct mii_bus *bus, int addr) +{ + return bus->mdio_map[addr]; +} +EXPORT_SYMBOL(mdiobus_get_mdio_device); + bool mdiobus_is_registered_device(struct mii_bus *bus, int addr) { return bus->mdio_map[addr]; diff --git a/include/linux/mdio.h b/include/linux/mdio.h index e8242ad88c81..e0ccd56a7ac0 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -315,6 +315,7 @@ int mdiobus_register_device(struct mdio_device *mdiodev); int mdiobus_unregister_device(struct mdio_device *mdiodev); bool mdiobus_is_registered_device(struct mii_bus *bus, int addr); struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr); +struct mdio_device *mdiobus_get_mdio_device(struct mii_bus *bus, int addr); /** * mdio_module_driver() - Helper macro for registering mdio drivers From patchwork Wed Aug 28 17:47:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ong Boon Leong X-Patchwork-Id: 1154705 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46JYB44B1hz9sNF for ; Thu, 29 Aug 2019 03:48:12 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726961AbfH1Rry (ORCPT ); Wed, 28 Aug 2019 13:47:54 -0400 Received: from mga02.intel.com ([134.134.136.20]:20453 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726515AbfH1Rrw (ORCPT ); Wed, 28 Aug 2019 13:47:52 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Aug 2019 10:47:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,442,1559545200"; d="scan'208";a="192675396" Received: from glass.png.intel.com ([172.30.181.95]) by orsmga002.jf.intel.com with ESMTP; 28 Aug 2019 10:47:34 -0700 From: Ong Boon Leong To: davem@davemloft.net, linux@armlinux.org.uk, mcoquelin.stm32@gmail.com, joabreu@synopsys.com, f.fainelli@gmail.com, andrew@lunn.ch Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, peppe.cavallaro@st.com, alexandre.torgue@st.com, weifeng.voon@intel.com Subject: [RFC net-next v2 3/5] net: phy: add private data to mdio_device Date: Thu, 29 Aug 2019 01:47:20 +0800 Message-Id: <20190828174722.6726-4-boon.leong.ong@intel.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20190828174722.6726-1-boon.leong.ong@intel.com> References: <20190828174722.6726-1-boon.leong.ong@intel.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org PHY converter device is represented as mdio_device and requires private data. So, we add pointer for private data to mdio_device struct. Signed-off-by: Ong Boon Leong --- include/linux/mdio.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/mdio.h b/include/linux/mdio.h index e0ccd56a7ac0..fc7dfbe75006 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -40,6 +40,8 @@ struct mdio_device { struct reset_control *reset_ctrl; unsigned int reset_assert_delay; unsigned int reset_deassert_delay; + /* Private data */ + void *priv; }; #define to_mdio_device(d) container_of(d, struct mdio_device, dev) From patchwork Wed Aug 28 17:47:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ong Boon Leong X-Patchwork-Id: 1154703 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46JY9r1xWKz9sDQ for ; Thu, 29 Aug 2019 03:48:00 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727030AbfH1Rr7 (ORCPT ); Wed, 28 Aug 2019 13:47:59 -0400 Received: from mga02.intel.com ([134.134.136.20]:20456 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726921AbfH1Rrz (ORCPT ); Wed, 28 Aug 2019 13:47:55 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Aug 2019 10:47:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,442,1559545200"; d="scan'208";a="192675399" Received: from glass.png.intel.com ([172.30.181.95]) by orsmga002.jf.intel.com with ESMTP; 28 Aug 2019 10:47:38 -0700 From: Ong Boon Leong To: davem@davemloft.net, linux@armlinux.org.uk, mcoquelin.stm32@gmail.com, joabreu@synopsys.com, f.fainelli@gmail.com, andrew@lunn.ch Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, peppe.cavallaro@st.com, alexandre.torgue@st.com, weifeng.voon@intel.com Subject: [RFC net-next v2 4/5] net: phy: introducing support for DWC xPCS logics for EHL & TGL Date: Thu, 29 Aug 2019 01:47:21 +0800 Message-Id: <20190828174722.6726-5-boon.leong.ong@intel.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20190828174722.6726-1-boon.leong.ong@intel.com> References: <20190828174722.6726-1-boon.leong.ong@intel.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org xPCS is DWC Ethernet Physical Coding Sublayer that can be integrated with Ethernet MAC controller and acts as converter between GMII and SGMII. An example is as shown below whereby DWC xPCS is integrated with DW EQoS MAC to form GbE Controller. <-----------------GbE Controller---------->|<--External PHY chip--> +----------+ +----+ +---+ +--------------+ | EQoS | <-GMII->| DW |<-->|PHY| <-- SGMII --> | External GbE | | MAC | |xPCS| |IF | | PHY Chip | +----------+ +----+ +---+ +--------------+ ^ ^ ^ | | | +---------------------MDIO-------------------------+ xPCS is a Clause-45 MDIO Manageable Device (MMD) and supports basic functionalities for initializing xPCS and configuring auto negotiation(AN), loopback, link status, AN advertisement and Link Partner ability are implemented. The implementation supports the C37 AN for 1000BASE-X and SGMII (MAC side SGMII only). Tested-by: Tan, Tee Min Reviewed-by: Voon Weifeng Reviewed-by: Kweh Hock Leong Signed-off-by: Ong Boon Leong --- drivers/net/phy/Kconfig | 9 + drivers/net/phy/Makefile | 1 + drivers/net/phy/dwxpcs.c | 417 +++++++++++++++++++++++++++++++++++++++ include/linux/dwxpcs.h | 16 ++ 4 files changed, 443 insertions(+) create mode 100644 drivers/net/phy/dwxpcs.c create mode 100644 include/linux/dwxpcs.h diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 03be30cde552..fd037f5366d8 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -364,6 +364,15 @@ config DP83867_PHY ---help--- Currently supports the DP83867 PHY. +config DWXPCS + tristate "Synopsys DesignWare PCS converter driver" + help + This driver supports DW PCS IP that provides the Serial Gigabit + Media Independent Interface(SGMII) between Ethernet physical media + devices and the Gigabit Ethernet controller. + + Currently tested with stmmac. + config FIXED_PHY tristate "MDIO Bus/PHY emulation with fixed speed/link PHYs" depends on PHYLIB diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index a03437e091f3..5def985ae3ca 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_DP83822_PHY) += dp83822.o obj-$(CONFIG_DP83TC811_PHY) += dp83tc811.o obj-$(CONFIG_DP83848_PHY) += dp83848.o obj-$(CONFIG_DP83867_PHY) += dp83867.o +obj-$(CONFIG_DWXPCS) += dwxpcs.o obj-$(CONFIG_FIXED_PHY) += fixed_phy.o obj-$(CONFIG_ICPLUS_PHY) += icplus.o obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o diff --git a/drivers/net/phy/dwxpcs.c b/drivers/net/phy/dwxpcs.c new file mode 100644 index 000000000000..f0003cec6871 --- /dev/null +++ b/drivers/net/phy/dwxpcs.c @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019, Intel Corporation. + * DWC Ethernet Physical Coding Sublayer for GMII2SGMII Converter + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* XPCS MII MMD Device Addresses */ +#define XPCS_MDIO_MII_MMD MDIO_MMD_VEND2 + +/* MII MMD registers offsets */ +#define MDIO_MII_MMD_DIGITAL_CTRL_1 0x8000 /* Digital Control 1 */ +#define MDIO_MII_MMD_AN_CTRL 0x8001 /* AN Control */ +#define MDIO_MII_MMD_AN_STAT 0x8002 /* AN Status */ + +/* MII MMD SR AN Advertisement & Link Partner Ability are slightly + * different from MII_ADVERTISEMENT & MII_LPA in below fields: + */ +#define MDIO_MII_MMD_HD BIT(6) /* Half duplex */ +#define MDIO_MII_MMD_FD BIT(5) /* Full duplex */ +#define MDIO_MII_MMD_PSE_SHIFT 7 /* Pause Ability shift */ +#define MDIO_MII_MMD_PSE GENMASK(8, 7) /* Pause Ability */ +#define MDIO_MII_MMD_PSE_NO 0x0 +#define MDIO_MII_MMD_PSE_ASYM 0x1 +#define MDIO_MII_MMD_PSE_SYM 0x2 +#define MDIO_MII_MMD_PSE_BOTH 0x3 + +/* Automatic Speed Mode Change for MAC side SGMII AN */ +#define MDIO_MII_MMD_DIGI_CTRL_1_MAC_AUTO_SW BIT(9) + +/* MII MMD AN Control defines */ +#define MDIO_MII_MMD_AN_CTRL_TX_CONFIG_SHIFT 3 /* TX Config shift */ +#define AN_CTRL_TX_CONF_PHY_SIDE_SGMII 0x1 /* PHY side SGMII mode */ +#define AN_CTRL_TX_CONF_MAC_SIDE_SGMII 0x0 /* MAC side SGMII mode */ +#define MDIO_MII_MMD_AN_CTRL_PCS_MD_SHIFT 1 /* PCS Mode shift */ +#define MDIO_MII_MMD_AN_CTRL_PCS_MD GENMASK(2, 1) /* PCS Mode */ +#define AN_CTRL_PCS_MD_C37_1000BASEX 0x0 /* C37 AN for 1000BASE-X */ +#define AN_CTRL_PCS_MD_C37_SGMII 0x2 /* C37 AN for SGMII */ +#define MDIO_MII_MMD_AN_CTRL_AN_INTR_EN BIT(0) /* AN Complete Intr Enable */ + +/* MII MMD AN Status defines for SGMII AN Status */ +#define AN_STAT_C37_AN_CMPLT BIT(0) /* AN Complete Intr */ +#define AN_STAT_SGMII_AN_FD BIT(1) /* Full Duplex */ +#define AN_STAT_SGMII_AN_SPEED_SHIFT 2 /* AN Speed shift */ +#define AN_STAT_SGMII_AN_SPEED GENMASK(3, 2) /* AN Speed */ +#define AN_STAT_SGMII_AN_10MBPS 0x0 /* 10 Mbps */ +#define AN_STAT_SGMII_AN_100MBPS 0x1 /* 100 Mbps */ +#define AN_STAT_SGMII_AN_1000MBPS 0x2 /* 1000 Mbps */ +#define AN_STAT_SGMII_AN_LNKSTS BIT(4) /* Link Status */ + +enum dwxpcs_state_t { + __DWXPCS_REMOVING, + __DWXPCS_TASK_SCHED, +}; + +struct pcs_stats { + int link; + int speed; + int duplex; +}; + +struct dwxpcs_priv { + struct phy_device *phy_dev; + struct phy_driver *phy_drv; + struct phy_device cached_phy_dev; + struct phy_driver conv_phy_drv; + struct mdio_device *mdiodev; + struct pcs_stats stats; + struct dwxpcs_platform_data *pdata; + char int_name[IFNAMSIZ]; + unsigned long state; + struct workqueue_struct *int_wq; + struct work_struct an_task; +}; + +/* DW xPCS mdiobus_read and mdiobus_write helper functions */ +#define xpcs_read(dev, reg) \ + mdiobus_read(bus, xpcs_addr, \ + MII_ADDR_C45 | (reg) | \ + ((dev) << MII_DEVADDR_C45_SHIFT)) +#define xpcs_write(dev, reg, val) \ + mdiobus_write(bus, xpcs_addr, \ + MII_ADDR_C45 | (reg) | \ + ((dev) << MII_DEVADDR_C45_SHIFT), val) + +static void dwxpcs_init(struct dwxpcs_priv *priv) +{ + struct mii_bus *bus = priv->mdiodev->bus; + int xpcs_addr = priv->mdiodev->addr; + int pcs_mode = priv->pdata->mode; + int phydata; + + if (pcs_mode == DWXPCS_MODE_SGMII_AN) { + /* For AN for SGMII mode, the settings are :- + * 1) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 10b (SGMII AN) + * 2) VR_MII_AN_CTRL Bit(3) [TX_CONFIG] = 0b (MAC side SGMII) + * DW xPCS used with DW EQoS MAC is always MAC + * side SGMII. + * 3) VR_MII_AN_CTRL Bit(0) [AN_INTR_EN] = 1b (AN Interrupt + * enabled) + * 4) VR_MII_DIG_CTRL1 Bit(9) [MAC_AUTO_SW] = 1b (Automatic + * speed/duplex mode change by HW after SGMII AN complete) + * Note: Since it is MAC side SGMII, there is no need to set + * SR_MII_AN_ADV. MAC side SGMII receives AN Tx Config + * from PHY about the link state change after C28 AN + * is completed between PHY and Link Partner. + */ + phydata = xpcs_read(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL); + phydata &= ~MDIO_MII_MMD_AN_CTRL_PCS_MD; + + phydata |= MDIO_MII_MMD_AN_CTRL_AN_INTR_EN | + (AN_CTRL_PCS_MD_C37_SGMII << + MDIO_MII_MMD_AN_CTRL_PCS_MD_SHIFT & + MDIO_MII_MMD_AN_CTRL_PCS_MD) | + (AN_CTRL_TX_CONF_MAC_SIDE_SGMII << + MDIO_MII_MMD_AN_CTRL_TX_CONFIG_SHIFT); + xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL, phydata); + + phydata = xpcs_read(XPCS_MDIO_MII_MMD, + MDIO_MII_MMD_DIGITAL_CTRL_1); + phydata |= MDIO_MII_MMD_DIGI_CTRL_1_MAC_AUTO_SW; + xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_DIGITAL_CTRL_1, + phydata); + } else { + /* For AN for 1000BASE-X mode, the settings are :- + * 1) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 00b (1000BASE-X C37) + * 2) VR_MII_AN_CTRL Bit(0) [AN_INTR_EN] = 1b (AN Interrupt + * enabled) + * 3) SR_MII_AN_ADV Bit(6)[FD] = 1b (Full Duplex) + * Note: Half Duplex is rarely used, so don't advertise. + * 4) SR_MII_AN_ADV Bit(8:7)[PSE] = 11b (Sym & Asym Pause) + */ + phydata = xpcs_read(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL); + phydata &= ~MDIO_MII_MMD_AN_CTRL_PCS_MD; + phydata |= MDIO_MII_MMD_AN_CTRL_AN_INTR_EN | + (AN_CTRL_PCS_MD_C37_1000BASEX << + MDIO_MII_MMD_AN_CTRL_PCS_MD_SHIFT & + MDIO_MII_MMD_AN_CTRL_PCS_MD); + xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_CTRL, phydata); + + phydata = xpcs_read(XPCS_MDIO_MII_MMD, MII_ADVERTISE); + phydata |= MDIO_MII_MMD_FD | + (MDIO_MII_MMD_PSE_BOTH << MDIO_MII_MMD_PSE_SHIFT); + xpcs_write(XPCS_MDIO_MII_MMD, MII_ADVERTISE, phydata); + } +} + +static int dwxpcs_read_status(struct phy_device *phydev) +{ + struct dwxpcs_priv *priv = (struct dwxpcs_priv *)phydev->priv; + struct mii_bus *bus = priv->mdiodev->bus; + int xpcs_addr = priv->mdiodev->addr; + int pcs_mode = priv->pdata->mode; + int phydata; + int err; + + if (priv->phy_drv->read_status) + err = priv->phy_drv->read_status(phydev); + else + err = genphy_read_status(phydev); + + if (err < 0) + return err; + + /* For SGMII AN, we are done as the speed/duplex are automatically + * set because we have initialized 'MAC_AUTO_SW' for MAC side SGMII. + */ + if (pcs_mode == DWXPCS_MODE_1000BASEX_AN) { + /* For 1000BASE-X AN, we need to adjust duplex mode according + * to link partner. No need to update speed as it is always + * 1000Mbps. + */ + phydata = xpcs_read(XPCS_MDIO_MII_MMD, MII_BMCR); + phydata &= ~BMCR_FULLDPLX; + phydata |= phydev->duplex ? BMCR_FULLDPLX : 0; + xpcs_write(XPCS_MDIO_MII_MMD, MII_BMCR, phydata); + } + + return 0; +} + +static void dwxpcs_get_linkstatus(struct dwxpcs_priv *priv, int an_stat) +{ + struct mii_bus *bus = priv->mdiodev->bus; + struct pcs_stats *stats = &priv->stats; + int xpcs_addr = priv->mdiodev->addr; + int pcs_mode = priv->pdata->mode; + + if (pcs_mode == DWXPCS_MODE_SGMII_AN) { + /* Check the SGMII AN link status */ + if (an_stat & AN_STAT_SGMII_AN_LNKSTS) { + int speed_value; + + stats->link = 1; + + speed_value = ((an_stat & AN_STAT_SGMII_AN_SPEED) >> + AN_STAT_SGMII_AN_SPEED_SHIFT); + if (speed_value == AN_STAT_SGMII_AN_1000MBPS) + stats->speed = SPEED_1000; + else if (speed_value == AN_STAT_SGMII_AN_100MBPS) + stats->speed = SPEED_100; + else + stats->speed = SPEED_10; + + if (an_stat & AN_STAT_SGMII_AN_FD) + stats->duplex = 1; + else + stats->duplex = 0; + } else { + stats->link = 0; + } + } else if (pcs_mode == DWXPCS_MODE_1000BASEX_AN) { + /* For 1000BASE-X AN, 1000BASE-X is always 1000Mbps. + * For duplex mode, we read from BMCR_FULLDPLX which is + * only valid if BMCR_ANENABLE is not enabeld. + */ + int phydata = xpcs_read(XPCS_MDIO_MII_MMD, MII_BMCR); + + stats->link = 1; + stats->speed = SPEED_1000; + if (!(phydata & BMCR_ANENABLE)) + stats->duplex = phydata & BMCR_FULLDPLX ? 1 : 0; + } +} + +static void dwxpcs_irq_handle(struct dwxpcs_priv *priv) +{ + struct mii_bus *bus = priv->mdiodev->bus; + struct device *dev = &priv->mdiodev->dev; + int xpcs_addr = priv->mdiodev->addr; + int an_stat; + + /* AN status */ + an_stat = xpcs_read(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_STAT); + + if (an_stat & AN_STAT_C37_AN_CMPLT) { + struct pcs_stats *stats = &priv->stats; + + dwxpcs_get_linkstatus(priv, an_stat); + + /* Clear C37 AN complete status by writing zero */ + xpcs_write(XPCS_MDIO_MII_MMD, MDIO_MII_MMD_AN_STAT, 0); + + dev_info(dev, "%s: Link = %d - %d/%s\n", + __func__, + stats->link, + stats->speed, + stats->duplex ? "Full" : "Half"); + } +} + +static void dwxpcs_an_task(struct work_struct *work) +{ + struct dwxpcs_priv *priv = container_of(work, + struct dwxpcs_priv, + an_task); + dwxpcs_irq_handle(priv); + + clear_bit(__DWXPCS_TASK_SCHED, &priv->state); +} + +static irqreturn_t dwxpcs_interrupt(int irq, void *dev_id) +{ + struct dwxpcs_priv *priv = (struct dwxpcs_priv *)dev_id; + + /* Handle the clearing of AN status outside of interrupt context + * as it involves mdiobus_read() & mdiobus_write(). + */ + if (!test_bit(__DWXPCS_REMOVING, &priv->state) && + !test_and_set_bit(__DWXPCS_TASK_SCHED, &priv->state)) { + queue_work(priv->int_wq, &priv->an_task); + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +#ifdef CONFIG_ACPI +static const struct acpi_device_id dwxpcs_acpi_match[] = { + { "INTC1033" }, /* EHL Ethernet PCS */ + { "INTC1034" }, /* TGL Ethernet PCS */ + { }, +}; + +MODULE_DEVICE_TABLE(acpi, dwxpcs_acpi_match); +#endif // CONFIG_ACPI + +static int dwxpcs_probe(struct mdio_device *mdiodev) +{ + struct device_node *phy_node; + struct dwxpcs_priv *priv; + struct device_node *np; + struct device *dev; + int ret; + + dev = &mdiodev->dev; + np = dev->of_node; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + if (np) { + /* Handle mdio_device registered through devicetree */ + phy_node = of_parse_phandle(np, "phy-handle", 0); + if (!phy_node) { + dev_err(dev, "Couldn't parse phy-handle\n"); + return -ENODEV; + } + + priv->phy_dev = of_phy_find_device(phy_node); + of_node_put(phy_node); + if (!priv->phy_dev) { + dev_info(dev, "Couldn't find phydev\n"); + return -EPROBE_DEFER; + } + } else { + /* Handle mdio_device registered through mdio_board_info */ + priv->pdata = (struct dwxpcs_platform_data *)dev->platform_data; + + priv->phy_dev = mdiobus_get_phy(mdiodev->bus, + priv->pdata->ext_phy_addr); + } + + if (!priv->phy_dev) { + dev_info(dev, "Couldn't find phydev\n"); + return -EPROBE_DEFER; + } + + if (!priv->phy_dev->drv) { + dev_info(dev, "Attached phy not ready\n"); + return -EPROBE_DEFER; + } + + priv->mdiodev = mdiodev; + + /* Initialize DW XPCS */ + dwxpcs_init(priv); + + priv->phy_drv = priv->phy_dev->drv; + memcpy(&priv->conv_phy_drv, priv->phy_dev->drv, + sizeof(struct phy_driver)); + priv->conv_phy_drv.read_status = dwxpcs_read_status; + /* Store a copy of phy_dev info for remove() later */ + priv->cached_phy_dev.priv = priv->phy_dev->priv; + priv->cached_phy_dev.drv = priv->phy_dev->drv; + priv->phy_dev->priv = priv; + priv->phy_dev->drv = &priv->conv_phy_drv; + + if (priv->pdata->irq > 0) { + char *int_name; + + INIT_WORK(&priv->an_task, dwxpcs_an_task); + clear_bit(__DWXPCS_TASK_SCHED, &priv->state); + + int_name = priv->int_name; + sprintf(int_name, "%s-%d", "dwxpcs", priv->mdiodev->dev.id); + priv->int_wq = create_singlethread_workqueue(int_name); + if (!priv->int_wq) { + dev_err(dev, "%s: Failed to create workqueue\n", + int_name); + return -ENOMEM; + } + + ret = request_irq(priv->pdata->irq, dwxpcs_interrupt, + IRQF_SHARED, int_name, priv); + if (unlikely(ret < 0)) { + destroy_workqueue(priv->int_wq); + dev_err(dev, "%s: Allocating DW XPCS IRQ %d (%d)\n", + __func__, priv->pdata->irq, ret); + return ret; + } + } + dev_info(dev, "%s: DW XPCS mdio device (IRQ: %d) probed successful\n", + __func__, priv->pdata->irq); + + mdiodev->priv = priv; + + return 0; +} + +static void dwxpcs_remove(struct mdio_device *mdiodev) +{ + struct dwxpcs_priv *priv = (struct dwxpcs_priv *)mdiodev->priv; + + set_bit(__DWXPCS_REMOVING, &priv->state); + + /* Restore the original phy_device info */ + priv->phy_dev->priv = priv->cached_phy_dev.priv; + priv->phy_dev->drv = priv->cached_phy_dev.drv; + + free_irq(priv->pdata->irq, priv); + if (priv->int_wq) + destroy_workqueue(priv->int_wq); +} + +static struct mdio_driver dwxpcs_driver = { + .probe = dwxpcs_probe, + .remove = dwxpcs_remove, + .mdiodrv.driver = { + .name = "dwxpcs", + .acpi_match_table = ACPI_PTR(dwxpcs_acpi_match), + }, +}; + +mdio_module_driver(dwxpcs_driver); + +MODULE_DESCRIPTION("DW xPCS converter driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/dwxpcs.h b/include/linux/dwxpcs.h new file mode 100644 index 000000000000..2082e800ee04 --- /dev/null +++ b/include/linux/dwxpcs.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_DWXPCS_H +#define __LINUX_DWXPCS_H + +enum dwxpcs_pcs_mode { + DWXPCS_MODE_SGMII_AN, + DWXPCS_MODE_1000BASEX_AN, +}; + +struct dwxpcs_platform_data { + int irq; + enum dwxpcs_pcs_mode mode; + int ext_phy_addr; +}; + +#endif From patchwork Wed Aug 28 17:47:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ong Boon Leong X-Patchwork-Id: 1154706 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46JYBD56wgz9sN1 for ; Thu, 29 Aug 2019 03:48:20 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727110AbfH1RsR (ORCPT ); Wed, 28 Aug 2019 13:48:17 -0400 Received: from mga02.intel.com ([134.134.136.20]:20453 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726925AbfH1Rry (ORCPT ); Wed, 28 Aug 2019 13:47:54 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Aug 2019 10:47:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,442,1559545200"; d="scan'208";a="192675402" Received: from glass.png.intel.com ([172.30.181.95]) by orsmga002.jf.intel.com with ESMTP; 28 Aug 2019 10:47:41 -0700 From: Ong Boon Leong To: davem@davemloft.net, linux@armlinux.org.uk, mcoquelin.stm32@gmail.com, joabreu@synopsys.com, f.fainelli@gmail.com, andrew@lunn.ch Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, peppe.cavallaro@st.com, alexandre.torgue@st.com, weifeng.voon@intel.com Subject: [RFC net-next v2 5/5] net: stmmac: add dwxpcs boardinfo for mdio_device registration Date: Thu, 29 Aug 2019 01:47:22 +0800 Message-Id: <20190828174722.6726-6-boon.leong.ong@intel.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20190828174722.6726-1-boon.leong.ong@intel.com> References: <20190828174722.6726-1-boon.leong.ong@intel.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 --- 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 +#include #include #include - +#include #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 #include #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;