From patchwork Wed Sep 27 07:34: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: 114357 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp4721731qgf; Wed, 27 Sep 2017 00:37:20 -0700 (PDT) X-Received: by 10.84.252.129 with SMTP id y1mr476531pll.107.1506497840133; Wed, 27 Sep 2017 00:37:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1506497840; cv=none; d=google.com; s=arc-20160816; b=q0L3D8gbFemR1j/NQ9KgwLM66a+DsOwBLfe4TBDfdTLbWRuXYtq7B4229rWSucJL4x 8WOq0ev9tJcPguNyyyE/JBZiH18TylowUiOy36hCVUvkvMiFP2al4n9XvMcmRtr+j267 6Nn4YhdovWSokUJfrZXuAfSAN2/nmWt7wYElPdVHOuyJSUGBt6MdE8HXk/s8kj28jjCY CRmpuSgbuBUpEi3dR8JNkLT1iCZFJd8LibwiPX/v4ynzY/pJ+WvYh2oxvISc/vZT/xoz l7eU6Yn0TH2He8v6VFIcmMNSdQiZG+Cr6c1UmveM0gXE0SM7XCFETURHLvaRqjNyr4Z+ E81A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=Cq7Y0f+J5EAQNxEaYiqIxrHLCjh0HE/SHmEZg/inewk=; b=JZUSuD11Th0H31U0BdcANWYoQAXGXr99AMxgIPJUp94SNmagsBF5nJ7JI176hA+26Q +RGNJmaiaOTMTwhKVm3zDTLNPV7wFgLcKOS6leevo0Ioc8YSLlAEH1VL3ocMY3hWsq3g iAJODKyTcTzvyGspb1jxykbkzC9GbDyNY/IpREQ2I7iKxEqw7TxIioBDFpsh5CwR0vyw Fl3Ip+gzYd0d4cx8jUar+whNlBD6jtHP5qv1kmko80GIk9RUCKVcM00jV0rw/JXQ6Mhp DmDiiMpbG6WKjl89pIxQmoV8pnzgXBwmeLnhw7Sz2AhTbBaTS/TN9l4aWDG8CIyKwfdl bGFw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=BHceTr1E; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q3si7071678pgc.164.2017.09.27.00.37.19; Wed, 27 Sep 2017 00:37:20 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=BHceTr1E; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752453AbdI0HhS (ORCPT + 26 others); Wed, 27 Sep 2017 03:37:18 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:45576 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752189AbdI0Hgq (ORCPT ); Wed, 27 Sep 2017 03:36:46 -0400 Received: by mail-wm0-f67.google.com with SMTP id q124so14819953wmb.0; Wed, 27 Sep 2017 00:36:45 -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=Cq7Y0f+J5EAQNxEaYiqIxrHLCjh0HE/SHmEZg/inewk=; b=BHceTr1EQLFnczLhpcdtbl2OUOVqH+5m0RbE9XwxDLI89BUm4E14bu2P6p15XdAvM+ HS9ZCViPTLu3ItGxLIFVxXXL8/fcR+7ag7sDmsaxZpw74V+7FG54S9Uj7cRza2juT4sM cRXp4nQt1t0+LE35mfoKrDnBaC/352hoFYFzSQUZW6j9wEcmCIoEoacLsz2Hwr0A74XI K0W9F4SXmetxRebsA95q3ruOnatOi0+JqoMKhyaslsrVMJEIgSYY5D0iUZgqrPXgZf5n R5tRiwRXlmz4LcqfkQrJTwVls3oZmbG8NoOiynil6vkSBS3ZiU6Zdl0etQ1gDaX7Adbv zDjA== 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=Cq7Y0f+J5EAQNxEaYiqIxrHLCjh0HE/SHmEZg/inewk=; b=JDf0Af7dIaUQhq3QNZRWYH9pr0c6XFlXgvpDRjkL3ZRm4Urs5e7CfjnKN4CVZNZ0p9 yaKb1+x7U12lqfrRUBPvITEaJaiQqL3F8+eC0ROgdUYdEEg8jbUCAsq3UBo2hSb+MkKm vQ5VFD+XztsO2jn1dTvFIhrvkFgRHfGZeGQ10WLj+XxtIdZ09MYTUKgIaYXeaZqcaviD pbbmtcpv7gostN3J0CrhQQotuWqiB+PzuKcwHuSXUXRJCm7+DnkCO/vvZc2Riu8r+Tkc wcjlxOInJskiN4mu3l7eNQm1bDNPVCluoLFg4p1AsDHy429/aDJnq8yijIsmzh+216Vp wAuw== X-Gm-Message-State: AHPjjUj6RPfmF0X3Oc/H+Kr9vtBarbiZzDb6ZEJq7Rz5IHSwwNjG1vGu ZlhOnxgi1GBDpowu2h+WV9A= X-Google-Smtp-Source: AOwi7QC5s9lSiw0E+10uxrI2ps3oeCWL3mSzKbMFRn9EAGI4Dm3ZEQuYk0n2+NOObopwyJC9cngFIw== X-Received: by 10.28.29.77 with SMTP id d74mr616305wmd.106.1506497804717; Wed, 27 Sep 2017 00:36:44 -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 n9sm5660526wmd.12.2017.09.27.00.36.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 27 Sep 2017 00:36:43 -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, frowand.list@gmail.com Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-sunxi@googlegroups.com, Corentin Labbe Subject: [PATCH v6 10/11] net: stmmac: dwmac-sun8i: Handle integrated/external MDIOs Date: Wed, 27 Sep 2017 09:34:13 +0200 Message-Id: <20170927073414.17361-11-clabbe.montjoie@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170927073414.17361-1-clabbe.montjoie@gmail.com> References: <20170927073414.17361-1-clabbe.montjoie@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 116 +++++++++++++++++++--- 2 files changed, 104 insertions(+), 13 deletions(-) -- 2.13.5 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 672553b652bd..8bd500c351b4 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 @@ -71,6 +72,7 @@ struct sunxi_priv_data { const struct emac_variant *variant; struct regmap *regmap; bool use_internal_phy; + void *mux_handle; }; static const struct emac_variant emac_variant_h3 = { @@ -195,6 +197,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 +639,76 @@ static int sun8i_dwmac_reset(struct stmmac_priv *priv) 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. + * + * Note that we do not use reg/mask like mdio-mux-mmioreg because we need to + * know easily which bus is used (reset must be done only for desired 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_reset = 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; + if (gmac->use_internal_phy) + need_reset = 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; + if (!gmac->use_internal_phy) + need_reset = true; + break; + default: + dev_err(priv->device, "Invalid child id %x\n", desired_child); + return -EINVAL; + } + regmap_write(gmac->regmap, SYSCON_EMAC_REG, val); + /* After changing syscon value, the MAC need reset or it will use + * the last value (and so the last PHY set). + * Reset is necessary only when we reach the needed MDIO, + * it timeout in other case. + */ + if (need_reset) + ret = sun8i_dwmac_reset(priv); + else + dev_dbg(priv->device, "skipped reset\n"); + } + 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->plat->mdio_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; @@ -649,12 +724,7 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) val, reg); if (gmac->variant->soc_has_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; + if (gmac->use_internal_phy) { dev_dbg(priv->device, "Select internal_phy %x\n", reg); if (of_property_read_bool(priv->plat->phy_node, @@ -743,6 +813,8 @@ static void sun8i_dwmac_unset_syscon(struct sunxi_priv_data *gmac) { u32 reg = gmac->variant->default_syscon_value; + if (gmac->variant->soc_has_internal_phy && gmac->mux_handle) + mdio_mux_uninit(gmac->mux_handle); regmap_write(gmac->regmap, SYSCON_EMAC_REG, reg); } @@ -801,12 +873,6 @@ static int sun8i_power_phy(struct stmmac_priv *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; } @@ -889,6 +955,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) @@ -973,9 +1041,31 @@ 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 = 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[] = {