From patchwork Wed Jun 9 17:35:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Zhou Yanjie X-Patchwork-Id: 12310985 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5B9EAC48BCF for ; Wed, 9 Jun 2021 17:52:16 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 13E18613D4 for ; Wed, 9 Jun 2021 17:52:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 13E18613D4 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=wanyeetech.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=XZxJZVdpn8aPV6x9Glpgaltkt/p8YCqR/7fPOam6/Og=; b=PPyCVvOXeKkokW QtsnaXVycyHoCUG/Kr2WCUhMC8I5JwN+m/Vn80hrgGq8vD740CkoQvXpQ9VsI1zEDJ3SSeRr3K4JQ AtjRGmgk54hcWR6HQDwWhFC8WRHR+y4WEvEySKi1cghIkjBa5ADTKfZZE4fow5M/nZMtqN5u+XeCc 502124r2ORHy65gojgqLYDfl+gl0EsQRUKGHDywqskwTd2Boqa04ny934qcGx0NsznffEcrTkq9c6 SHEHAD8Thw84CMv8ePzRQQ026wS/z24Ik2J/EcHon22AoskI4j2jkP4us2Niy5Y9EgsY3/RjV+Qkc cHAsC4upzKZXheiECf2Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lr2LA-00FQTI-UO; Wed, 09 Jun 2021 17:50:09 +0000 Received: from out28-197.mail.aliyun.com ([115.124.28.197]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lr278-00FL2v-2K for linux-arm-kernel@lists.infradead.org; Wed, 09 Jun 2021 17:35:39 +0000 X-Alimail-AntiSpam: AC=CONTINUE; BC=0.9020496|0.6613592; CH=green; DM=|SPAM|false|; DS=CONTINUE|ham_regular_dialog|0.0829513-0.00479038-0.912258; FP=0|0|0|0|0|-1|-1|-1; HT=ay29a033018047209; MF=zhouyanjie@wanyeetech.com; NM=1; PH=DS; RN=20; RT=20; SR=0; TI=SMTPD_---.KQ26pE3_1623260120; Received: from localhost.localdomain(mailfrom:zhouyanjie@wanyeetech.com fp:SMTPD_---.KQ26pE3_1623260120) by smtp.aliyun-inc.com(10.147.41.138); Thu, 10 Jun 2021 01:35:31 +0800 From: =?utf-8?b?5ZGo55Cw5p2wIChaaG91IFlhbmppZSk=?= To: davem@davemloft.net, kuba@kernel.org, robh+dt@kernel.org, peppe.cavallaro@st.com, alexandre.torgue@foss.st.com, joabreu@synopsys.com, mcoquelin.stm32@gmail.com Cc: linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, dongsheng.qiu@ingenic.com, aric.pzqi@ingenic.com, rick.tyliu@ingenic.com, sihui.liu@ingenic.com, jun.jiang@ingenic.com, sernia.zhou@foxmail.com, paul@crapouillou.net Subject: [PATCH v2 1/2] dt-bindings: dwmac: Add bindings for new Ingenic SoCs. Date: Thu, 10 Jun 2021 01:35:09 +0800 Message-Id: <1623260110-25842-2-git-send-email-zhouyanjie@wanyeetech.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623260110-25842-1-git-send-email-zhouyanjie@wanyeetech.com> References: <1623260110-25842-1-git-send-email-zhouyanjie@wanyeetech.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210609_103538_334553_3FD92531 X-CRM114-Status: UNSURE ( 6.53 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add the dwmac bindings for the JZ4775 SoC, the X1000 SoC, the X1600 SoC, the X1830 SoC and the X2000 SoC from Ingenic. Signed-off-by: 周琰杰 (Zhou Yanjie) --- Notes: v1->v2: No change. Documentation/devicetree/bindings/net/snps,dwmac.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml index 2edd8be..9c0ce92 100644 --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml @@ -56,6 +56,11 @@ properties: - amlogic,meson8m2-dwmac - amlogic,meson-gxbb-dwmac - amlogic,meson-axg-dwmac + - ingenic,jz4775-mac + - ingenic,x1000-mac + - ingenic,x1600-mac + - ingenic,x1830-mac + - ingenic,x2000-mac - rockchip,px30-gmac - rockchip,rk3128-gmac - rockchip,rk3228-gmac @@ -310,6 +315,11 @@ allOf: - allwinner,sun8i-r40-emac - allwinner,sun8i-v3s-emac - allwinner,sun50i-a64-emac + - ingenic,jz4775-mac + - ingenic,x1000-mac + - ingenic,x1600-mac + - ingenic,x1830-mac + - ingenic,x2000-mac - snps,dwxgmac - snps,dwxgmac-2.10 - st,spear600-gmac @@ -353,6 +363,11 @@ allOf: - allwinner,sun8i-r40-emac - allwinner,sun8i-v3s-emac - allwinner,sun50i-a64-emac + - ingenic,jz4775-mac + - ingenic,x1000-mac + - ingenic,x1600-mac + - ingenic,x1830-mac + - ingenic,x2000-mac - snps,dwmac-4.00 - snps,dwmac-4.10a - snps,dwmac-4.20a From patchwork Wed Jun 9 17:35:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Zhou Yanjie X-Patchwork-Id: 12310981 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 61F05C48BCD for ; Wed, 9 Jun 2021 17:51:06 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2F40E613CB for ; Wed, 9 Jun 2021 17:51:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2F40E613CB Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=wanyeetech.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=0oiWrN9RGZcVDlpdo7MSDjMDr6x/oUONe3P+vozeCSs=; b=3g0JopfHx32ifB mSSOumeaiOjviywwA9XgTd9Hl7+HmWFrCOukZplFVyK+y5RFfzX90opB4z/Z+95hx/mc5szHH1xyK llwSoshTOQaG01cHtrbvQ+kytktkaOvpJuqVyfdbNdPSTOtVgIXCv7m2aCPy6a7BnCurzgm2T5ZMl 9TdVACuEz0SvSB5UylDx1TUx80kBIEuG36mY/kPBuzrRGFvuf94UJ6BUHMtM04tVJPEjBRyblByky ZE3e2EKvx+ELFMqLNPWqzqLdj5vJmh5S1uXau6l+VoWcB+hdzVV5D6muJEV9vQmBiKNIMZvrgv4/W SCZiG5Ns/Kew/jEyqW7w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lr2KB-00FPv8-Th; Wed, 09 Jun 2021 17:49:08 +0000 Received: from out28-121.mail.aliyun.com ([115.124.28.121]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lr278-00FL33-1h for linux-arm-kernel@lists.infradead.org; Wed, 09 Jun 2021 17:35:41 +0000 X-Alimail-AntiSpam: AC=CONTINUE; BC=0.07436282|-1; CH=green; DM=|CONTINUE|false|; DS=CONTINUE|ham_system_inform|0.0239554-0.000423683-0.975621; FP=0|0|0|0|0|-1|-1|-1; HT=ay29a033018047206; MF=zhouyanjie@wanyeetech.com; NM=1; PH=DS; RN=20; RT=20; SR=0; TI=SMTPD_---.KQ26pE3_1623260120; Received: from localhost.localdomain(mailfrom:zhouyanjie@wanyeetech.com fp:SMTPD_---.KQ26pE3_1623260120) by smtp.aliyun-inc.com(10.147.41.138); Thu, 10 Jun 2021 01:35:32 +0800 From: =?utf-8?b?5ZGo55Cw5p2wIChaaG91IFlhbmppZSk=?= To: davem@davemloft.net, kuba@kernel.org, robh+dt@kernel.org, peppe.cavallaro@st.com, alexandre.torgue@foss.st.com, joabreu@synopsys.com, mcoquelin.stm32@gmail.com Cc: linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, dongsheng.qiu@ingenic.com, aric.pzqi@ingenic.com, rick.tyliu@ingenic.com, sihui.liu@ingenic.com, jun.jiang@ingenic.com, sernia.zhou@foxmail.com, paul@crapouillou.net Subject: [PATCH v2 2/2] net: stmmac: Add Ingenic SoCs MAC support. Date: Thu, 10 Jun 2021 01:35:10 +0800 Message-Id: <1623260110-25842-3-git-send-email-zhouyanjie@wanyeetech.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1623260110-25842-1-git-send-email-zhouyanjie@wanyeetech.com> References: <1623260110-25842-1-git-send-email-zhouyanjie@wanyeetech.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210609_103538_525991_F25D095F X-CRM114-Status: GOOD ( 22.59 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add support for Ingenic SoC MAC glue layer support for the stmmac device driver. This driver is used on for the MAC ethernet controller found in the JZ4775 SoC, the X1000 SoC, the X1600 SoC, the X1830 SoC, and the X2000 SoC. Signed-off-by: 周琰杰 (Zhou Yanjie) --- Notes: v1->v2: 1.Fix uninitialized variable. 2.Add missing RGMII-ID, RGMII-RXID, and RGMII-TXID. 3.Change variable val from int to unsinged int. 4.Get tx clock delay and rx clock delay from devicetree. drivers/net/ethernet/stmicro/stmmac/Kconfig | 12 + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + .../net/ethernet/stmicro/stmmac/dwmac-ingenic.c | 434 +++++++++++++++++++++ 3 files changed, 447 insertions(+) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 7737e4d0..9a19e4d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -66,6 +66,18 @@ config DWMAC_ANARION This selects the Anarion SoC glue layer support for the stmmac driver. +config DWMAC_INGENIC + tristate "Ingenic MAC support" + default MACH_INGENIC + depends on OF && HAS_IOMEM && (MACH_INGENIC || COMPILE_TEST) + select MFD_SYSCON + help + Support for ethernet controller on Ingenic SoCs. + + This selects Ingenic SoCs glue layer support for the stmmac + device driver. This driver is used on for the Ingenic SoCs + MAC ethernet controller. + config DWMAC_IPQ806X tristate "QCA IPQ806x DWMAC support" default ARCH_QCOM diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index f2e478b..6471f93 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -14,6 +14,7 @@ stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o # Ordering matters. Generic driver must be last. obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o obj-$(CONFIG_DWMAC_ANARION) += dwmac-anarion.o +obj-$(CONFIG_DWMAC_INGENIC) += dwmac-ingenic.o obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c new file mode 100644 index 00000000..fbe2727 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c @@ -0,0 +1,434 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * dwmac-ingenic.c - Ingenic SoCs DWMAC specific glue layer + * + * Copyright (c) 2021 周琰杰 (Zhou Yanjie) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stmmac_platform.h" + +#define MACPHYC_TXCLK_SEL_MASK GENMASK(31, 31) +#define MACPHYC_TXCLK_SEL_OUTPUT 0x1 +#define MACPHYC_TXCLK_SEL_INPUT 0x0 +#define MACPHYC_MODE_SEL_MASK GENMASK(31, 31) +#define MACPHYC_MODE_SEL_RMII 0x0 +#define MACPHYC_TX_SEL_MASK GENMASK(19, 19) +#define MACPHYC_TX_SEL_ORIGIN 0x0 +#define MACPHYC_TX_SEL_DELAY 0x1 +#define MACPHYC_TX_DELAY_MASK GENMASK(18, 12) +#define MACPHYC_TX_DELAY_MAX 0x80 +#define MACPHYC_RX_SEL_MASK GENMASK(11, 11) +#define MACPHYC_RX_SEL_ORIGIN 0x0 +#define MACPHYC_RX_SEL_DELAY 0x1 +#define MACPHYC_RX_DELAY_MASK GENMASK(10, 4) +#define MACPHYC_RX_DELAY_MAX 0x80 +#define MACPHYC_SOFT_RST_MASK GENMASK(3, 3) +#define MACPHYC_PHY_INFT_MASK GENMASK(2, 0) +#define MACPHYC_PHY_INFT_RMII 0x4 +#define MACPHYC_PHY_INFT_RGMII 0x1 +#define MACPHYC_PHY_INFT_GMII 0x0 +#define MACPHYC_PHY_INFT_MII 0x0 + +enum ingenic_mac_version { + ID_JZ4775, + ID_X1000, + ID_X1600, + ID_X1830, + ID_X2000, +}; + +struct ingenic_mac { + const struct ingenic_soc_info *soc_info; + struct device *dev; + struct regmap *regmap; + + int rx_delay; + int tx_delay; +}; + +struct ingenic_soc_info { + enum ingenic_mac_version version; + u32 mask; + + int (*set_mode)(struct plat_stmmacenet_data *plat_dat); +}; + +static int ingenic_mac_init(struct plat_stmmacenet_data *plat_dat) +{ + struct ingenic_mac *mac = plat_dat->bsp_priv; + int ret; + + if (mac->soc_info->set_mode) { + ret = mac->soc_info->set_mode(plat_dat); + if (ret) + return ret; + } + + return 0; +} + +static int jz4775_mac_set_mode(struct plat_stmmacenet_data *plat_dat) +{ + struct ingenic_mac *mac = plat_dat->bsp_priv; + unsigned int val; + + switch (plat_dat->interface) { + case PHY_INTERFACE_MODE_MII: + val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) | + FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_MII); + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_MII\n"); + break; + + case PHY_INTERFACE_MODE_GMII: + val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) | + FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_GMII); + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_GMII\n"); + break; + + case PHY_INTERFACE_MODE_RMII: + val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) | + FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); + break; + + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) | + FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII); + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n"); + break; + + default: + dev_err(mac->dev, "unsupported interface %d", plat_dat->interface); + return -EINVAL; + } + + /* Update MAC PHY control register */ + return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val); +} + +static int x1000_mac_set_mode(struct plat_stmmacenet_data *plat_dat) +{ + struct ingenic_mac *mac = plat_dat->bsp_priv; + + switch (plat_dat->interface) { + case PHY_INTERFACE_MODE_RMII: + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); + break; + + default: + dev_err(mac->dev, "unsupported interface %d", plat_dat->interface); + return -EINVAL; + } + + /* Update MAC PHY control register */ + return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, 0); +} + +static int x1600_mac_set_mode(struct plat_stmmacenet_data *plat_dat) +{ + struct ingenic_mac *mac = plat_dat->bsp_priv; + unsigned int val; + + switch (plat_dat->interface) { + case PHY_INTERFACE_MODE_RMII: + val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); + break; + + default: + dev_err(mac->dev, "unsupported interface %d", plat_dat->interface); + return -EINVAL; + } + + /* Update MAC PHY control register */ + return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val); +} + +static int x1830_mac_set_mode(struct plat_stmmacenet_data *plat_dat) +{ + struct ingenic_mac *mac = plat_dat->bsp_priv; + unsigned int val; + + switch (plat_dat->interface) { + case PHY_INTERFACE_MODE_RMII: + val = FIELD_PREP(MACPHYC_MODE_SEL_MASK, MACPHYC_MODE_SEL_RMII) | + FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); + break; + + default: + dev_err(mac->dev, "unsupported interface %d", plat_dat->interface); + return -EINVAL; + } + + /* Update MAC PHY control register */ + return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val); +} + +static int x2000_mac_set_mode(struct plat_stmmacenet_data *plat_dat) +{ + struct ingenic_mac *mac = plat_dat->bsp_priv; + unsigned int val; + + switch (plat_dat->interface) { + case PHY_INTERFACE_MODE_RMII: + val = FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN) | + FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN) | + FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); + break; + + case PHY_INTERFACE_MODE_RGMII: + val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII); + + if (mac->tx_delay == 0) { + val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN); + } else { + val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_DELAY); + + if (mac->tx_delay > MACPHYC_TX_DELAY_MAX) + val |= FIELD_PREP(MACPHYC_TX_DELAY_MASK, MACPHYC_TX_DELAY_MAX - 1); + else + val |= FIELD_PREP(MACPHYC_TX_DELAY_MASK, mac->tx_delay - 1); + } + + if (mac->rx_delay == 0) { + val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN); + } else { + val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_DELAY); + + if (mac->rx_delay > MACPHYC_RX_DELAY_MAX) + val |= FIELD_PREP(MACPHYC_RX_DELAY_MASK, MACPHYC_RX_DELAY_MAX - 1); + else + val |= FIELD_PREP(MACPHYC_RX_DELAY_MASK, mac->rx_delay - 1); + } + + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n"); + break; + + case PHY_INTERFACE_MODE_RGMII_ID: + val = FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN) | + FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN) | + FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII); + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII_ID\n"); + break; + + case PHY_INTERFACE_MODE_RGMII_RXID: + val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII) | + FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN); + + if (mac->tx_delay == 0) { + val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN); + } else { + val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_DELAY); + + if (mac->tx_delay > MACPHYC_TX_DELAY_MAX) + val |= FIELD_PREP(MACPHYC_TX_DELAY_MASK, MACPHYC_TX_DELAY_MAX - 1); + else + val |= FIELD_PREP(MACPHYC_TX_DELAY_MASK, mac->tx_delay - 1); + } + + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII_RXID\n"); + break; + + case PHY_INTERFACE_MODE_RGMII_TXID: + val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII) | + FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN); + + if (mac->rx_delay == 0) { + val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN); + } else { + val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_DELAY); + + if (mac->rx_delay > MACPHYC_RX_DELAY_MAX) + val |= FIELD_PREP(MACPHYC_RX_DELAY_MASK, MACPHYC_RX_DELAY_MAX - 1); + else + val |= FIELD_PREP(MACPHYC_RX_DELAY_MASK, mac->rx_delay - 1); + } + + dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII_TXID\n"); + break; + + default: + dev_err(mac->dev, "unsupported interface %d", plat_dat->interface); + return -EINVAL; + } + + /* Update MAC PHY control register */ + return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val); +} + +static int ingenic_mac_probe(struct platform_device *pdev) +{ + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + struct ingenic_mac *mac; + const struct ingenic_soc_info *data; + int ret; + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + + mac = devm_kzalloc(&pdev->dev, sizeof(*mac), GFP_KERNEL); + if (!mac) { + ret = -ENOMEM; + goto err_remove_config_dt; + } + + data = of_device_get_match_data(&pdev->dev); + if (!data) { + dev_err(&pdev->dev, "no of match data provided\n"); + ret = -EINVAL; + goto err_remove_config_dt; + } + + /* Get MAC PHY control register */ + mac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "mode-reg"); + if (IS_ERR(mac->regmap)) { + dev_err(&pdev->dev, "%s: failed to get syscon regmap\n", __func__); + goto err_remove_config_dt; + } + + ret = of_property_read_u32(pdev->dev.of_node, "rx-clk-delay", &mac->rx_delay); + if (ret) + mac->rx_delay = 0; + + ret = of_property_read_u32(pdev->dev.of_node, "tx-clk-delay", &mac->tx_delay); + if (ret) + mac->tx_delay = 0; + + mac->soc_info = data; + mac->dev = &pdev->dev; + + plat_dat->bsp_priv = mac; + + ret = ingenic_mac_init(plat_dat); + if (ret) + goto err_remove_config_dt; + + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (ret) + goto err_remove_config_dt; + + return 0; + +err_remove_config_dt: + stmmac_remove_config_dt(pdev, plat_dat); + + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int ingenic_mac_suspend(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct stmmac_priv *priv = netdev_priv(ndev); + struct ingenic_mac *mac = priv->plat->bsp_priv; + int ret; + + ret = stmmac_suspend(dev); + + return ret; +} + +static int ingenic_mac_resume(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct stmmac_priv *priv = netdev_priv(ndev); + struct ingenic_mac *mac = priv->plat->bsp_priv; + int ret; + + ret = ingenic_mac_init(priv->plat); + if (ret) + return ret; + + ret = stmmac_resume(dev); + + return ret; +} +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(ingenic_mac_pm_ops, ingenic_mac_suspend, ingenic_mac_resume); + +static struct ingenic_soc_info jz4775_soc_info = { + .version = ID_JZ4775, + .mask = MACPHYC_TXCLK_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, + + .set_mode = jz4775_mac_set_mode, +}; + +static struct ingenic_soc_info x1000_soc_info = { + .version = ID_X1000, + .mask = MACPHYC_SOFT_RST_MASK, + + .set_mode = x1000_mac_set_mode, +}; + +static struct ingenic_soc_info x1600_soc_info = { + .version = ID_X1600, + .mask = MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, + + .set_mode = x1600_mac_set_mode, +}; + +static struct ingenic_soc_info x1830_soc_info = { + .version = ID_X1830, + .mask = MACPHYC_MODE_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, + + .set_mode = x1830_mac_set_mode, +}; + +static struct ingenic_soc_info x2000_soc_info = { + .version = ID_X2000, + .mask = MACPHYC_TX_SEL_MASK | MACPHYC_TX_DELAY_MASK | MACPHYC_RX_SEL_MASK | + MACPHYC_RX_DELAY_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK, + + .set_mode = x2000_mac_set_mode, +}; + +static const struct of_device_id ingenic_mac_of_matches[] = { + { .compatible = "ingenic,jz4775-mac", .data = &jz4775_soc_info }, + { .compatible = "ingenic,x1000-mac", .data = &x1000_soc_info }, + { .compatible = "ingenic,x1600-mac", .data = &x1600_soc_info }, + { .compatible = "ingenic,x1830-mac", .data = &x1830_soc_info }, + { .compatible = "ingenic,x2000-mac", .data = &x2000_soc_info }, + { } +}; +MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches); + +static struct platform_driver ingenic_mac_driver = { + .probe = ingenic_mac_probe, + .remove = stmmac_pltfr_remove, + .driver = { + .name = "ingenic-mac", + .pm = pm_ptr(&ingenic_mac_pm_ops), + .of_match_table = ingenic_mac_of_matches, + }, +}; +module_platform_driver(ingenic_mac_driver); + +MODULE_AUTHOR("周琰杰 (Zhou Yanjie) "); +MODULE_DESCRIPTION("Ingenic SoCs DWMAC specific glue layer"); +MODULE_LICENSE("GPL v2");