From patchwork Tue Oct 24 17:57:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corentin Labbe X-Patchwork-Id: 10025305 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C5D006035E for ; Tue, 24 Oct 2017 18:04:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B62EB28A0E for ; Tue, 24 Oct 2017 18:04:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AA8E628A14; Tue, 24 Oct 2017 18:04:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9B60228A0E for ; Tue, 24 Oct 2017 18:04:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=B/bkY4QcJ83wYZldXDaR7rfC/o1I9mPz2qpOK6v7Jx4=; b=RFyR8FLAMNNBd0Nj8RamhNLR2e ZY6PmVq1nMH8d/e08hz1gsoh4IHHHwTSni4Toa44ZZ3CBNYh3qTFyxt/iOA7lZlULroe/WKjRMgsx rkS5QIinRr5g2VkM2rMitdlWlXwLFlzWjZ6v1ACMIzzC2kBhfAYHML3LVUENsdS537/agYnddIH4Q Hu1OR9n/8g8fF97SG2iXD9Fb7RNXYdgfUmixeoZTieJqcBPIjFP4XeXz15ZCM7NrqWrrFD7oHL0wo 2A06AbECFU7fYaRTD1lL5DdYvhNQjkhsvRUXoPfYSM6nbdpHEG2qGty5rXhXXcpbH24/QwdkueMFS IG0RnUeQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e73ZJ-0000Jq-Up; Tue, 24 Oct 2017 18:04:49 +0000 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e73Vs-0006Gp-4T for linux-arm-kernel@lists.infradead.org; Tue, 24 Oct 2017 18:01:22 +0000 Received: by mail-wm0-x241.google.com with SMTP id b9so12271817wmh.0 for ; Tue, 24 Oct 2017 11:00:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=SD96LGCJ92R9np+MmDHeox2iRyFDSnokyqvldaaOX8M=; b=nv4IIXOA3MzJsrCU/U7xWKk4vH5Y/XK6UUlKBUNuZ3qpOwM7M+WitCOYEY/HQj8Ygi 0LsVeRAeurvhVh5VrM00eOR/MWm1+BgFYAlsqn1Le7bjhEY3RqMycOkQP1na5imEqGZa YNfOmbzKE17fPVIFcxQ6OTh5iXxlGmoxdl0Ltbt7ZJPJpJi6j2HKsKT9Tt9aBVI/RATN 1ne47Jy4MTfXqC/O0KuaZM/2UTBe6ALTfj6CwhkWBltLuPKWkcHdyPIFQa+26B+G9bcU t2HU2aK96LHwcKA+Gd+raNNbp+QWYMzy8kJ0RMQh7vhizwcCFewrRGfnDOBvkkyxJQbS Ud8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=SD96LGCJ92R9np+MmDHeox2iRyFDSnokyqvldaaOX8M=; b=lAmo/cDcRnDsdt5FUmitv+F/W2ySoF2LzA87wvkxOb2D8Eua7WyNVqIF11dDonHOfw GMGPnCY40AWJR714vfsiHmevak8Vh0jvJDDoDubmUwWv608w0sfo45oCRTVJCQWJ1iey ZcpS881W3PVVGDF5PDKqWilLq4y6fL5UmlXbXGSp6FiTcNWrYGDM6va6sZtieeguOpCG zwPoqPGNaOgjHwCgmWDZiXYhlQ8STFRTUF2++wPdCXqdyp33D4Ww2MMWFexiMair+EPv 1r38PA6UeboFKQvcI0eh1mP8cOTmatJOSl0VW00v4BXgoFxP/EwZA+Yan+SXa6fGom0Y sBRQ== X-Gm-Message-State: AMCzsaVf5pgFc9uZLnesmxZ49qJeBHEPnG3VsVKAqvrapEqiJ87rD3UT LhZeavtYxWdpdoXyyBqZxs8= X-Google-Smtp-Source: ABhQp+Qo5BlWZMCh8sZex7dCR6r5XsJGZQBtqtdqJJjH6GHgfPoeo2T7VJO47ac6UGWu37sPJlaung== X-Received: by 10.28.142.147 with SMTP id q141mr8567483wmd.155.1508868054222; Tue, 24 Oct 2017 11:00:54 -0700 (PDT) Received: from Red.local (LFbn-MAR-1-580-96.w90-118.abo.wanadoo.fr. [90.118.159.96]) by smtp.googlemail.com with ESMTPSA id s18sm818968wrg.87.2017.10.24.11.00.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 24 Oct 2017 11:00:53 -0700 (PDT) From: Corentin Labbe To: robh+dt@kernel.org, mark.rutland@arm.com, maxime.ripard@free-electrons.com, wens@csie.org, linux@armlinux.org.uk, catalin.marinas@arm.com, will.deacon@arm.com, peppe.cavallaro@st.com, alexandre.torgue@st.com, andrew@lunn.ch, f.fainelli@gmail.com Subject: [PATCH v9 09/10] net: stmmac: dwmac-sun8i: Handle integrated/external MDIOs Date: Tue, 24 Oct 2017 19:57:13 +0200 Message-Id: <20171024175714.15840-10-clabbe.montjoie@gmail.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20171024175714.15840-1-clabbe.montjoie@gmail.com> References: <20171024175714.15840-1-clabbe.montjoie@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171024_110116_509963_3DE0C1F9 X-CRM114-Status: GOOD ( 28.62 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, Corentin Labbe , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The Allwinner H3 SoC have two distinct MDIO bus, only one could be active at the same time. The selection of the active MDIO bus are done via some bits in the EMAC register of the system controller. This patch implement this MDIO switch via a custom MDIO-mux. Signed-off-by: Corentin Labbe Reviewed-by: Andrew Lunn --- drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 353 ++++++++++++++-------- 2 files changed, 224 insertions(+), 130 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 97035766c291..e28c0d2c58e9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -159,6 +159,7 @@ config DWMAC_SUN8I tristate "Allwinner sun8i GMAC support" default ARCH_SUNXI depends on OF && (ARCH_SUNXI || COMPILE_TEST) + select MDIO_BUS_MUX ---help--- Support for Allwinner H3 A83T A64 EMAC ethernet controllers. diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index 39c2122a4f26..b3eb344bb158 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -41,14 +42,14 @@ * This value is used for disabling properly EMAC * and used as a good starting value in case of the * boot process(uboot) leave some stuff. - * @internal_phy: Does the MAC embed an internal PHY + * @soc_has_internal_phy: Does the MAC embed an internal PHY * @support_mii: Does the MAC handle MII * @support_rmii: Does the MAC handle RMII * @support_rgmii: Does the MAC handle RGMII */ struct emac_variant { u32 default_syscon_value; - int internal_phy; + bool soc_has_internal_phy; bool support_mii; bool support_rmii; bool support_rgmii; @@ -61,7 +62,8 @@ struct emac_variant { * @rst_ephy: reference to the optional EPHY reset for the internal PHY * @variant: reference to the current board variant * @regmap: regmap for using the syscon - * @use_internal_phy: Does the current PHY choice imply using the internal PHY + * @internal_phy_powered: Does the internal PHY is enabled + * @mux_handle: Internal pointer used by mdio-mux lib */ struct sunxi_priv_data { struct clk *tx_clk; @@ -70,12 +72,13 @@ struct sunxi_priv_data { struct reset_control *rst_ephy; const struct emac_variant *variant; struct regmap *regmap; - bool use_internal_phy; + bool internal_phy_powered; + void *mux_handle; }; static const struct emac_variant emac_variant_h3 = { .default_syscon_value = 0x58000, - .internal_phy = PHY_INTERFACE_MODE_MII, + .soc_has_internal_phy = true, .support_mii = true, .support_rmii = true, .support_rgmii = true @@ -83,20 +86,20 @@ static const struct emac_variant emac_variant_h3 = { static const struct emac_variant emac_variant_v3s = { .default_syscon_value = 0x38000, - .internal_phy = PHY_INTERFACE_MODE_MII, + .soc_has_internal_phy = true, .support_mii = true }; static const struct emac_variant emac_variant_a83t = { .default_syscon_value = 0, - .internal_phy = 0, + .soc_has_internal_phy = false, .support_mii = true, .support_rgmii = true }; static const struct emac_variant emac_variant_a64 = { .default_syscon_value = 0, - .internal_phy = 0, + .soc_has_internal_phy = false, .support_mii = true, .support_rmii = true, .support_rgmii = true @@ -195,6 +198,9 @@ static const struct emac_variant emac_variant_a64 = { #define H3_EPHY_LED_POL BIT(17) /* 1: active low, 0: active high */ #define H3_EPHY_SHUTDOWN BIT(16) /* 1: shutdown, 0: power up */ #define H3_EPHY_SELECT BIT(15) /* 1: internal PHY, 0: external PHY */ +#define H3_EPHY_MUX_MASK (H3_EPHY_SHUTDOWN | H3_EPHY_SELECT) +#define DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID 1 +#define DWMAC_SUN8I_MDIO_MUX_EXTERNAL_ID 2 /* H3/A64 specific bits */ #define SYSCON_RMII_EN BIT(13) /* 1: enable RMII (overrides EPIT) */ @@ -634,6 +640,159 @@ static int sun8i_dwmac_reset(struct stmmac_priv *priv) return 0; } +/* Search in mdio-mux node for internal PHY node and get its clk/reset */ +static int get_ephy_nodes(struct stmmac_priv *priv) +{ + struct sunxi_priv_data *gmac = priv->plat->bsp_priv; + struct device_node *mdio_mux, *iphynode; + struct device_node *mdio_internal; + int ret; + + mdio_mux = of_get_child_by_name(priv->device->of_node, "mdio-mux"); + if (!mdio_mux) { + dev_err(priv->device, "Cannot get mdio-mux node\n"); + return -ENODEV; + } + + mdio_internal = of_find_compatible_node(mdio_mux, NULL, + "allwinner,sun8i-h3-mdio-internal"); + if (!mdio_internal) { + dev_err(priv->device, "Cannot get internal_mdio node\n"); + return -ENODEV; + } + + /* Seek for internal PHY */ + for_each_child_of_node(mdio_internal, iphynode) { + gmac->ephy_clk = of_clk_get(iphynode, 0); + if (IS_ERR(gmac->ephy_clk)) + continue; + gmac->rst_ephy = of_reset_control_get_exclusive(iphynode, NULL); + if (IS_ERR(gmac->rst_ephy)) { + ret = PTR_ERR(gmac->rst_ephy); + if (ret == -EPROBE_DEFER) + return ret; + continue; + } + dev_info(priv->device, "Found internal PHY node\n"); + return 0; + } + return -ENODEV; +} + +static int sun8i_dwmac_power_internal_phy(struct stmmac_priv *priv) +{ + struct sunxi_priv_data *gmac = priv->plat->bsp_priv; + int ret; + + if (gmac->internal_phy_powered) { + dev_warn(priv->device, "Internal PHY already powered\n"); + return 0; + } + + dev_info(priv->device, "Powering internal PHY\n"); + ret = clk_prepare_enable(gmac->ephy_clk); + if (ret) { + dev_err(priv->device, "Cannot enable internal PHY\n"); + return ret; + } + + /* Make sure the EPHY is properly reseted, as U-Boot may leave + * it at deasserted state, and thus it may fail to reset EMAC. + */ + reset_control_assert(gmac->rst_ephy); + + ret = reset_control_deassert(gmac->rst_ephy); + if (ret) { + dev_err(priv->device, "Cannot deassert internal phy\n"); + clk_disable_unprepare(gmac->ephy_clk); + return ret; + } + + gmac->internal_phy_powered = true; + + return 0; +} + +static int sun8i_dwmac_unpower_internal_phy(struct sunxi_priv_data *gmac) +{ + if (!gmac->internal_phy_powered) + return 0; + + clk_disable_unprepare(gmac->ephy_clk); + reset_control_assert(gmac->rst_ephy); + gmac->internal_phy_powered = false; + return 0; +} + +/* MDIO multiplexing switch function + * This function is called by the mdio-mux layer when it thinks the mdio bus + * multiplexer needs to switch. + * 'current_child' is the current value of the mux register + * 'desired_child' is the value of the 'reg' property of the target child MDIO + * node. + * The first time this function is called, current_child == -1. + * If current_child == desired_child, then the mux is already set to the + * correct bus. + */ +static int mdio_mux_syscon_switch_fn(int current_child, int desired_child, + void *data) +{ + struct stmmac_priv *priv = data; + struct sunxi_priv_data *gmac = priv->plat->bsp_priv; + u32 reg, val; + int ret = 0; + bool need_power_ephy = false; + + if (current_child ^ desired_child) { + regmap_read(gmac->regmap, SYSCON_EMAC_REG, ®); + switch (desired_child) { + case DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID: + dev_info(priv->device, "Switch mux to internal PHY"); + val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SELECT; + + need_power_ephy = true; + break; + case DWMAC_SUN8I_MDIO_MUX_EXTERNAL_ID: + dev_info(priv->device, "Switch mux to external PHY"); + val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SHUTDOWN; + need_power_ephy = false; + break; + default: + dev_err(priv->device, "Invalid child ID %x\n", + desired_child); + return -EINVAL; + } + regmap_write(gmac->regmap, SYSCON_EMAC_REG, val); + if (need_power_ephy) { + ret = sun8i_dwmac_power_internal_phy(priv); + if (ret) + return ret; + } else { + sun8i_dwmac_unpower_internal_phy(gmac); + } + /* After changing syscon value, the MAC need reset or it will + * use the last value (and so the last PHY set). + */ + ret = sun8i_dwmac_reset(priv); + } + return ret; +} + +static int sun8i_dwmac_register_mdio_mux(struct stmmac_priv *priv) +{ + int ret; + struct device_node *mdio_mux; + struct sunxi_priv_data *gmac = priv->plat->bsp_priv; + + mdio_mux = of_get_child_by_name(priv->device->of_node, "mdio-mux"); + if (!mdio_mux) + return -ENODEV; + + ret = mdio_mux_init(priv->device, mdio_mux, mdio_mux_syscon_switch_fn, + &gmac->mux_handle, priv, priv->mii); + return ret; +} + static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) { struct sunxi_priv_data *gmac = priv->plat->bsp_priv; @@ -648,35 +807,25 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) "Current syscon value is not the default %x (expect %x)\n", val, reg); - if (gmac->variant->internal_phy) { - if (!gmac->use_internal_phy) { - /* switch to external PHY interface */ - reg &= ~H3_EPHY_SELECT; - } else { - reg |= H3_EPHY_SELECT; - reg &= ~H3_EPHY_SHUTDOWN; - dev_dbg(priv->device, "Select internal_phy %x\n", reg); - - if (of_property_read_bool(priv->plat->phy_node, - "allwinner,leds-active-low")) - reg |= H3_EPHY_LED_POL; - else - reg &= ~H3_EPHY_LED_POL; - - /* Force EPHY xtal frequency to 24MHz. */ - reg |= H3_EPHY_CLK_SEL; - - ret = of_mdio_parse_addr(priv->device, - priv->plat->phy_node); - if (ret < 0) { - dev_err(priv->device, "Could not parse MDIO addr\n"); - return ret; - } - /* of_mdio_parse_addr returns a valid (0 ~ 31) PHY - * address. No need to mask it again. - */ - reg |= ret << H3_EPHY_ADDR_SHIFT; + if (gmac->variant->soc_has_internal_phy) { + if (of_property_read_bool(priv->plat->phy_node, + "allwinner,leds-active-low")) + reg |= H3_EPHY_LED_POL; + else + reg &= ~H3_EPHY_LED_POL; + + /* Force EPHY xtal frequency to 24MHz. */ + reg |= H3_EPHY_CLK_SEL; + + ret = of_mdio_parse_addr(priv->device, priv->plat->phy_node); + if (ret < 0) { + dev_err(priv->device, "Could not parse MDIO addr\n"); + return ret; } + /* of_mdio_parse_addr returns a valid (0 ~ 31) PHY + * address. No need to mask it again. + */ + reg |= 1 << H3_EPHY_ADDR_SHIFT; } if (!of_property_read_u32(node, "allwinner,tx-delay-ps", &val)) { @@ -746,81 +895,21 @@ static void sun8i_dwmac_unset_syscon(struct sunxi_priv_data *gmac) regmap_write(gmac->regmap, SYSCON_EMAC_REG, reg); } -static int sun8i_dwmac_power_internal_phy(struct stmmac_priv *priv) +static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv) { - struct sunxi_priv_data *gmac = priv->plat->bsp_priv; - int ret; - - if (!gmac->use_internal_phy) - return 0; - - ret = clk_prepare_enable(gmac->ephy_clk); - if (ret) { - dev_err(priv->device, "Cannot enable ephy\n"); - return ret; - } - - /* Make sure the EPHY is properly reseted, as U-Boot may leave - * it at deasserted state, and thus it may fail to reset EMAC. - */ - reset_control_assert(gmac->rst_ephy); + struct sunxi_priv_data *gmac = priv; - ret = reset_control_deassert(gmac->rst_ephy); - if (ret) { - dev_err(priv->device, "Cannot deassert ephy\n"); - clk_disable_unprepare(gmac->ephy_clk); - return ret; + if (gmac->variant->soc_has_internal_phy) { + /* sun8i_dwmac_exit could be called with mdiomux uninit */ + if (gmac->mux_handle) + mdio_mux_uninit(gmac->mux_handle); + if (gmac->internal_phy_powered) + sun8i_dwmac_unpower_internal_phy(gmac); } - return 0; -} - -static int sun8i_dwmac_unpower_internal_phy(struct sunxi_priv_data *gmac) -{ - if (!gmac->use_internal_phy) - return 0; - - clk_disable_unprepare(gmac->ephy_clk); - reset_control_assert(gmac->rst_ephy); - return 0; -} - -/* sun8i_power_phy() - Activate the PHY: - * In case of error, no need to call sun8i_unpower_phy(), - * it will be called anyway by sun8i_dwmac_exit() - */ -static int sun8i_power_phy(struct stmmac_priv *priv) -{ - int ret; - - ret = sun8i_dwmac_power_internal_phy(priv); - if (ret) - return ret; - - ret = sun8i_dwmac_set_syscon(priv); - if (ret) - return ret; - - /* After changing syscon value, the MAC need reset or it will use - * the last value (and so the last PHY set. - */ - ret = sun8i_dwmac_reset(priv); - if (ret) - return ret; - return 0; -} - -static void sun8i_unpower_phy(struct sunxi_priv_data *gmac) -{ sun8i_dwmac_unset_syscon(gmac); - sun8i_dwmac_unpower_internal_phy(gmac); -} - -static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv) -{ - struct sunxi_priv_data *gmac = priv; - sun8i_unpower_phy(gmac); + reset_control_put(gmac->rst_ephy); clk_disable_unprepare(gmac->tx_clk); @@ -849,7 +938,7 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv) if (!mac) return NULL; - ret = sun8i_power_phy(priv); + ret = sun8i_dwmac_set_syscon(priv); if (ret) return NULL; @@ -889,6 +978,8 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) struct sunxi_priv_data *gmac; struct device *dev = &pdev->dev; int ret; + struct stmmac_priv *priv; + struct net_device *ndev; ret = stmmac_get_platform_resources(pdev, &stmmac_res); if (ret) @@ -932,29 +1023,6 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) } plat_dat->interface = of_get_phy_mode(dev->of_node); - if (plat_dat->interface == gmac->variant->internal_phy) { - dev_info(&pdev->dev, "Will use internal PHY\n"); - gmac->use_internal_phy = true; - gmac->ephy_clk = of_clk_get(plat_dat->phy_node, 0); - if (IS_ERR(gmac->ephy_clk)) { - ret = PTR_ERR(gmac->ephy_clk); - dev_err(&pdev->dev, "Cannot get EPHY clock: %d\n", ret); - return -EINVAL; - } - - gmac->rst_ephy = of_reset_control_get(plat_dat->phy_node, NULL); - if (IS_ERR(gmac->rst_ephy)) { - ret = PTR_ERR(gmac->rst_ephy); - if (ret == -EPROBE_DEFER) - return ret; - dev_err(&pdev->dev, "No EPHY reset control found %d\n", - ret); - return -EINVAL; - } - } else { - dev_info(&pdev->dev, "Will use external PHY\n"); - gmac->use_internal_phy = false; - } /* platform data specifying hardware features and callbacks. * hardware features were copied from Allwinner drivers. @@ -973,9 +1041,34 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) - sun8i_dwmac_exit(pdev, plat_dat->bsp_priv); + goto dwmac_exit; + + ndev = dev_get_drvdata(&pdev->dev); + priv = netdev_priv(ndev); + /* The mux must be registered after parent MDIO + * so after stmmac_dvr_probe() + */ + if (gmac->variant->soc_has_internal_phy) { + ret = get_ephy_nodes(priv); + if (ret) + goto dwmac_exit; + ret = sun8i_dwmac_register_mdio_mux(priv); + if (ret) { + dev_err(&pdev->dev, "Failed to register mux\n"); + goto dwmac_mux; + } + } else { + ret = sun8i_dwmac_reset(priv); + if (ret) + goto dwmac_exit; + } return ret; +dwmac_mux: + sun8i_dwmac_unset_syscon(gmac); +dwmac_exit: + sun8i_dwmac_exit(pdev, plat_dat->bsp_priv); +return ret; } static const struct of_device_id sun8i_dwmac_match[] = {