From ad39d06df7f6c6af6249c0f33358ae2d799ec4b4 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 4 Jun 2020 15:07:28 +0200 Subject: [PATCH] mediatek: add mt7531 DSA support Signed-off-by: John Crispin --- .../mt7622-bananapi-bpi-r64-rootdisk.dts | 87 +- .../mt7622/base-files/etc/board.d/02_network | 4 + target/linux/mediatek/mt7622/config-5.4 | 7 +- ...dsa-mt7530-Refine-message-in-Kconfig.patch | 100 ++ ...data-ready-for-adding-a-new-hardware.patch | 445 +++++++ ...new-MT7531-binding-to-support-MT7531.patch | 181 +++ ...530-Add-the-support-of-MT7531-switch.patch | 1102 +++++++++++++++++ ...mt7531-dsa-to-bananapi-bpi-r64-board.patch | 140 +++ 8 files changed, 2028 insertions(+), 38 deletions(-) create mode 100644 target/linux/mediatek/patches-5.4/0600-1-6-net-dsa-mt7530-Refine-message-in-Kconfig.patch create mode 100644 target/linux/mediatek/patches-5.4/0600-2-6-net-dsa-mt7530-Extend-device-data-ready-for-adding-a-new-hardware.patch create mode 100644 target/linux/mediatek/patches-5.4/0600-3-6-dt-bindings-net-dsa-add-new-MT7531-binding-to-support-MT7531.patch create mode 100644 target/linux/mediatek/patches-5.4/0600-4-6-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch create mode 100644 target/linux/mediatek/patches-5.4/0600-6-6-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-rootdisk.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-rootdisk.dts index 9d80366a18..6a14ef369b 100644 --- a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-rootdisk.dts +++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-rootdisk.dts @@ -53,13 +53,6 @@ }; }; - gsw: gsw@0 { - compatible = "mediatek,mt753x"; - mediatek,ethsys = <ðsys>; - #address-cells = <1>; - #size-cells = <0>; - }; - leds { compatible = "gpio-leds"; @@ -150,37 +143,57 @@ mdio: mdio-bus { #address-cells = <1>; #size-cells = <0>; - }; -}; -&gsw { - mediatek,mdio = <&mdio>; - mediatek,portmap = "wllll"; - mediatek,mdio_master_pinmux = <0>; - reset-gpios = <&pio 54 0>; - interrupt-parent = <&pio>; - interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; - status = "okay"; - - port5: port@5 { - compatible = "mediatek,mt753x-port"; - reg = <5>; - phy-mode = "rgmii"; - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - port6: port@6 { - compatible = "mediatek,mt753x-port"; - reg = <6>; - phy-mode = "sgmii"; - fixed-link { - speed = <2500>; - full-duplex; - }; - }; + switch@1f { + compatible = "mediatek,mt7531"; + reg = <0x1f>; + reset-gpios = <&pio 54 0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + wan: port@0 { + reg = <0>; + label = "wan"; + }; + + port@1 { + reg = <1>; + label = "lan0"; + }; + + port@2 { + reg = <2>; + label = "lan1"; + }; + + port@3 { + reg = <3>; + label = "lan2"; + }; + + port@4 { + reg = <4>; + label = "lan3"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + + }; }; &i2c1 { diff --git a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network index b87a24fc2a..eed01a9293 100755 --- a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network @@ -9,6 +9,10 @@ mediatek_setup_interfaces() local board="$1" case $board in + bananapi,bpi-r64-rootdisk|\ + bananapi,bpi-r64) + ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3" wan + ;; *) ucidef_add_switch "switch0" \ "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "6u@eth0" "5u@eth1" diff --git a/target/linux/mediatek/mt7622/config-5.4 b/target/linux/mediatek/mt7622/config-5.4 index 040de2fbc0..1a00636968 100755 --- a/target/linux/mediatek/mt7622/config-5.4 +++ b/target/linux/mediatek/mt7622/config-5.4 @@ -393,7 +393,7 @@ CONFIG_MMC_MTK=y # CONFIG_MMC_TIFM_SD is not set CONFIG_MODULES_TREE_LOOKUP=y CONFIG_MODULES_USE_ELF_RELA=y -CONFIG_MT753X_GSW=y +# CONFIG_MT753X_GSW is not set CONFIG_MTD_NAND_CORE=y CONFIG_MTD_NAND_ECC_SW_HAMMING=y CONFIG_MTD_NAND_MTK=y @@ -415,8 +415,13 @@ CONFIG_MTK_TIMER=y CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_MEDIATEK_SOC=y +CONFIG_NET_SWITCHDEV=y CONFIG_NET_VENDOR_MEDIATEK=y CONFIG_NLS=y CONFIG_NO_HZ_COMMON=y diff --git a/target/linux/mediatek/patches-5.4/0600-1-6-net-dsa-mt7530-Refine-message-in-Kconfig.patch b/target/linux/mediatek/patches-5.4/0600-1-6-net-dsa-mt7530-Refine-message-in-Kconfig.patch new file mode 100644 index 0000000000..5c56765ecc --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0600-1-6-net-dsa-mt7530-Refine-message-in-Kconfig.patch @@ -0,0 +1,100 @@ +From patchwork Tue Dec 10 08:14:37 2019 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Landen Chao +X-Patchwork-Id: 1206962 +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 (no SPF record) + 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=pass (p=none dis=none) + header.from=mediatek.com +Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; + unprotected) header.d=mediatek.com header.i=@mediatek.com + header.b="pTp2PPKi"; dkim-atps=neutral +Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) + by ozlabs.org (Postfix) with ESMTP id 47XCY42hJqz9sRf + for ; + Tue, 10 Dec 2019 19:15:20 +1100 (AEDT) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1727061AbfLJIO5 (ORCPT + ); + Tue, 10 Dec 2019 03:14:57 -0500 +Received: from mailgw02.mediatek.com ([210.61.82.184]:45567 "EHLO + mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by + vger.kernel.org with ESMTP id S1726932AbfLJIO4 (ORCPT + ); Tue, 10 Dec 2019 03:14:56 -0500 +X-UUID: f5656f2ff80846ebb40e3da87d60fb90-20191210 +DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; + d=mediatek.com; s=dk; + h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; + bh=THbuVAlbiUyMgTyO0rwrKX/mskzsxNwDv9gxXp2O2c8=; + b=pTp2PPKiPwR8QPOOf5yohf9lFERpEDlo/g/t2ChREfzFb9c+wylx++/div4hAB337+Ja2KIzbSu4URgdj5XHXUly8yuxrD8OBvV+ox0jlNLiRIN2dkCgL4fyzPr7ZPSk9lObJW05Yx2LY6Jy6eJZZXSShLlqLd0lDKwy6FT+hSI=; +X-UUID: f5656f2ff80846ebb40e3da87d60fb90-20191210 +Received: from mtkcas07.mediatek.inc [(172.21.101.84)] by + mailgw02.mediatek.com (envelope-from ) + (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) + with ESMTP id 565263134; Tue, 10 Dec 2019 16:14:47 +0800 +Received: from mtkcas08.mediatek.inc (172.21.101.126) by + mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server + (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:38 +0800 +Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc + (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via + Frontend Transport; Tue, 10 Dec 2019 16:14:26 +0800 +From: Landen Chao +To: , , + , , + , +CC: , , + , + , , + , , + , Landen Chao +Subject: [PATCH net-next 1/6] net: dsa: mt7530: Refine message in Kconfig +Date: Tue, 10 Dec 2019 16:14:37 +0800 +Message-ID: <6ecf6cbf38223f35854bc361c2eefa1d85c724d2.1575914275.git.landen.chao@mediatek.com> +X-Mailer: git-send-email 2.18.0 +In-Reply-To: +References: +MIME-Version: 1.0 +X-MTK: N +Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org + +Refine message in Kconfig with fixing typo and an explicit MT7621 support. + +Signed-off-by: Landen Chao +Signed-off-by: Sean Wang +Reviewed-by: Florian Fainelli +--- + drivers/net/dsa/Kconfig | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig +index c7667645f04a..467f80157acf 100644 +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -33,12 +33,12 @@ config NET_DSA_LANTIQ_GSWIP + the xrx200 / VR9 SoC. + + config NET_DSA_MT7530 +- tristate "Mediatek MT7530 Ethernet switch support" ++ tristate "MediaTek MT7530 and MT7621 Ethernet switch support" + depends on NET_DSA + select NET_DSA_TAG_MTK + ---help--- +- This enables support for the Mediatek MT7530 Ethernet switch +- chip. ++ This enables support for the MediaTek MT7530 and MT7621 Ethernet ++ switch chip. + + config NET_DSA_MV88E6060 + tristate "Marvell 88E6060 ethernet switch chip support" diff --git a/target/linux/mediatek/patches-5.4/0600-2-6-net-dsa-mt7530-Extend-device-data-ready-for-adding-a-new-hardware.patch b/target/linux/mediatek/patches-5.4/0600-2-6-net-dsa-mt7530-Extend-device-data-ready-for-adding-a-new-hardware.patch new file mode 100644 index 0000000000..637f9e3c58 --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0600-2-6-net-dsa-mt7530-Extend-device-data-ready-for-adding-a-new-hardware.patch @@ -0,0 +1,445 @@ +From patchwork Tue Dec 10 08:14:38 2019 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Landen Chao +X-Patchwork-Id: 1206963 +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 (no SPF record) + 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=pass (p=none dis=none) + header.from=mediatek.com +Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; + unprotected) header.d=mediatek.com header.i=@mediatek.com + header.b="UJ5NATux"; dkim-atps=neutral +Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) + by ozlabs.org (Postfix) with ESMTP id 47XCY92tBkz9sR7 + for ; + Tue, 10 Dec 2019 19:15:25 +1100 (AEDT) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1727003AbfLJIO4 (ORCPT + ); + Tue, 10 Dec 2019 03:14:56 -0500 +Received: from mailgw02.mediatek.com ([210.61.82.184]:45567 "EHLO + mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by + vger.kernel.org with ESMTP id S1726071AbfLJIOy (ORCPT + ); Tue, 10 Dec 2019 03:14:54 -0500 +X-UUID: a18674d7b33c423e9e67b7440f4771cf-20191210 +DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; + d=mediatek.com; s=dk; + h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; + bh=c2C/fEHYw/8uqadmiP2m2xa2hsUpAd52urXVJTPlYck=; + b=UJ5NATuxMtqHln5i6BTpWiLnxGKgWvp4DpRsKVO2xdnz2cJaT4XL8F/T5fK3CTF4nAai0EKPAcqp+rr8eCLq7uURJv5e5h+ZIzKLSAB4zgnchXesQLo0uFS8vs5w2yp49j6bez1z3v/uN+1+Lpq0uYid9awCqzvbnovrooEysu4=; +X-UUID: a18674d7b33c423e9e67b7440f4771cf-20191210 +Received: from mtkcas09.mediatek.inc [(172.21.101.178)] by + mailgw02.mediatek.com (envelope-from ) + (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) + with ESMTP id 1965641267; Tue, 10 Dec 2019 16:14:46 +0800 +Received: from mtkcas08.mediatek.inc (172.21.101.126) by + mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server + (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:31 +0800 +Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc + (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via + Frontend Transport; Tue, 10 Dec 2019 16:14:26 +0800 +From: Landen Chao +To: , , + , , + , +CC: , , + , + , , + , , + , Landen Chao +Subject: [PATCH net-next 2/6] net: dsa: mt7530: Extend device data ready for + adding a new hardware +Date: Tue, 10 Dec 2019 16:14:38 +0800 +Message-ID: <2d546d6bb15ff8b4b75af2220e20db4e634f4145.1575914275.git.landen.chao@mediatek.com> +X-Mailer: git-send-email 2.18.0 +In-Reply-To: +References: +MIME-Version: 1.0 +X-MTK: N +Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org + +Add a structure holding required operations for each device such as device +initialization, PHY port read or write, a checker whether PHY interface is +supported on a certain port, MAC port setup for either bus pad or a +specific PHY interface. + +The patch is done for ready adding a new hardware MT7531. + +Signed-off-by: Landen Chao +Signed-off-by: Sean Wang +--- + drivers/net/dsa/mt7530.c | 231 +++++++++++++++++++++++++++++---------- + drivers/net/dsa/mt7530.h | 29 ++++- + 2 files changed, 203 insertions(+), 57 deletions(-) + +Index: linux-5.4.43/drivers/net/dsa/mt7530.c +=================================================================== +--- linux-5.4.43.orig/drivers/net/dsa/mt7530.c ++++ linux-5.4.43/drivers/net/dsa/mt7530.c +@@ -373,7 +373,7 @@ mt7530_fdb_write(struct mt7530_priv *pri + } + + static int +-mt7530_pad_clk_setup(struct dsa_switch *ds, int mode) ++mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t mode) + { + struct mt7530_priv *priv = ds->priv; + u32 ncpo1, ssc_delta, trgint, i, xtal; +@@ -1355,13 +1355,111 @@ mt7530_setup(struct dsa_switch *ds) + return 0; + } + +-static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port, ++static bool mt7530_phy_supported(struct dsa_switch *ds, int port, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ switch (port) { ++ case 0: /* Internal phy */ ++ case 1: ++ case 2: ++ case 3: ++ case 4: ++ if (state->interface != PHY_INTERFACE_MODE_GMII) ++ goto unsupported; ++ break; ++ case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ ++ if (!phy_interface_mode_is_rgmii(state->interface) && ++ state->interface != PHY_INTERFACE_MODE_MII && ++ state->interface != PHY_INTERFACE_MODE_GMII) ++ goto unsupported; ++ break; ++ case 6: /* 1st cpu port */ ++ if (state->interface != PHY_INTERFACE_MODE_RGMII && ++ state->interface != PHY_INTERFACE_MODE_TRGMII) ++ goto unsupported; ++ break; ++ default: ++ dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, ++ port); ++ goto unsupported; ++ } ++ ++ return true; ++ ++unsupported: ++ return false; ++} ++ ++static bool mt753x_phy_supported(struct dsa_switch *ds, int port, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->phy_supported(ds, port, state); ++} ++ ++static int ++mt7530_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ /* Setup TX circuit incluing relevant PAD and driving */ ++ mt7530_pad_clk_setup(ds, state->interface); ++ ++ if (priv->id == ID_MT7530) { ++ /* Setup RX circuit, relevant PAD and driving on the ++ * host which must be placed after the setup on the ++ * device side is all finished. ++ */ ++ mt7623_pad_clk_setup(ds); ++ } ++ ++ return 0; ++} ++ ++static int ++mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->pad_setup(ds, state); ++} ++ ++static int ++mt7530_mac_setup(struct dsa_switch *ds, int port, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ /* Only need to setup port5. */ ++ if (port != 5) ++ return 0; ++ ++ mt7530_setup_port5(priv->ds, state->interface); ++ ++ return 0; ++} ++ ++static int mt753x_mac_setup(struct dsa_switch *ds, int port, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->mac_setup(ds, port, mode, state); ++} ++ ++static void mt753x_phylink_mac_config(struct dsa_switch *ds, int port, + unsigned int mode, + const struct phylink_link_state *state) + { + struct mt7530_priv *priv = ds->priv; + u32 mcr_cur, mcr_new; + ++ if (!mt753x_phy_supported(ds, port, state)) ++ return; ++ + switch (port) { + case 0: /* Internal phy */ + case 1: +@@ -1374,24 +1472,15 @@ static void mt7530_phylink_mac_config(st + case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ + if (priv->p5_interface == state->interface) + break; +- if (!phy_interface_mode_is_rgmii(state->interface) && +- state->interface != PHY_INTERFACE_MODE_MII && +- state->interface != PHY_INTERFACE_MODE_GMII) +- return; +- +- mt7530_setup_port5(ds, state->interface); ++ if (mt753x_mac_setup(ds, port, mode, state) < 0) ++ goto unsupported; + break; + case 6: /* 1st cpu port */ + if (priv->p6_interface == state->interface) + break; +- +- if (state->interface != PHY_INTERFACE_MODE_RGMII && +- state->interface != PHY_INTERFACE_MODE_TRGMII) +- return; +- +- /* Setup TX circuit incluing relevant PAD and driving */ +- mt7530_pad_clk_setup(ds, state->interface); +- ++ mt753x_pad_setup(ds, state); ++ if (mt753x_mac_setup(ds, port, mode, state) < 0) ++ goto unsupported; + priv->p6_interface = state->interface; + break; + default: +@@ -1459,38 +1548,14 @@ static void mt7530_phylink_mac_link_up(s + mt7530_port_set_status(priv, port, 1); + } + +-static void mt7530_phylink_validate(struct dsa_switch *ds, int port, ++static void mt753x_phylink_validate(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state) + { + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + +- switch (port) { +- case 0: /* Internal phy */ +- case 1: +- case 2: +- case 3: +- case 4: +- if (state->interface != PHY_INTERFACE_MODE_NA && +- state->interface != PHY_INTERFACE_MODE_GMII) +- goto unsupported; +- break; +- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ +- if (state->interface != PHY_INTERFACE_MODE_NA && +- !phy_interface_mode_is_rgmii(state->interface) && +- state->interface != PHY_INTERFACE_MODE_MII && +- state->interface != PHY_INTERFACE_MODE_GMII) +- goto unsupported; +- break; +- case 6: /* 1st cpu port */ +- if (state->interface != PHY_INTERFACE_MODE_NA && +- state->interface != PHY_INTERFACE_MODE_RGMII && +- state->interface != PHY_INTERFACE_MODE_TRGMII) +- goto unsupported; +- break; +- default: +- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); +-unsupported: ++ if (state->interface != PHY_INTERFACE_MODE_NA && ++ !mt753x_phy_supported(ds, port, state)) { + linkmode_zero(supported); + return; + } +@@ -1609,12 +1674,36 @@ static int mt7530_set_mac_eee(struct dsa + return 0; + } + ++static int ++mt753x_setup(struct dsa_switch *ds) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->setup(ds); ++} ++ ++static int ++mt753x_phy_read(struct dsa_switch *ds, int port, int regnum) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->phy_read(ds, port, regnum); ++} ++ ++static int ++mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->phy_write(ds, port, regnum, val); ++} ++ + static const struct dsa_switch_ops mt7530_switch_ops = { + .get_tag_protocol = mtk_get_tag_protocol, +- .setup = mt7530_setup, ++ .setup = mt753x_setup, + .get_strings = mt7530_get_strings, +- .phy_read = mt7530_phy_read, +- .phy_write = mt7530_phy_write, ++ .phy_read = mt753x_phy_read, ++ .phy_write = mt753x_phy_write, + .get_ethtool_stats = mt7530_get_ethtool_stats, + .get_sset_count = mt7530_get_sset_count, + .port_enable = mt7530_port_enable, +@@ -1631,18 +1720,39 @@ static const struct dsa_switch_ops mt753 + .port_vlan_del = mt7530_port_vlan_del, + .port_mirror_add = mt7530_port_mirror_add, + .port_mirror_del = mt7530_port_mirror_del, +- .phylink_validate = mt7530_phylink_validate, ++ .phylink_validate = mt753x_phylink_validate, + .phylink_mac_link_state = mt7530_phylink_mac_link_state, +- .phylink_mac_config = mt7530_phylink_mac_config, ++ .phylink_mac_config = mt753x_phylink_mac_config, + .phylink_mac_link_down = mt7530_phylink_mac_link_down, + .phylink_mac_link_up = mt7530_phylink_mac_link_up, + .get_mac_eee = mt7530_get_mac_eee, + .set_mac_eee = mt7530_set_mac_eee, + }; + +-static const struct of_device_id mt7530_of_match[] = { +- { .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, }, +- { .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, }, ++static const struct mt753x_info mt753x_table[] = { ++ [ID_MT7621] = { ++ .id = ID_MT7621, ++ .setup = mt7530_setup, ++ .phy_read = mt7530_phy_read, ++ .phy_write = mt7530_phy_write, ++ .phy_supported = mt7530_phy_supported, ++ .pad_setup = mt7530_pad_setup, ++ .mac_setup = mt7530_mac_setup, ++ }, ++ [ID_MT7530] = { ++ .id = ID_MT7530, ++ .setup = mt7530_setup, ++ .phy_read = mt7530_phy_read, ++ .phy_write = mt7530_phy_write, ++ .phy_supported = mt7530_phy_supported, ++ .pad_setup = mt7530_pad_setup, ++ .mac_setup = mt7530_mac_setup, ++ }, ++}; ++ ++ static const struct of_device_id mt7530_of_match[] = { ++ { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, ++ { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, mt7530_of_match); +@@ -1680,8 +1790,19 @@ mt7530_probe(struct mdio_device *mdiodev + /* Get the hardware identifier from the devicetree node. + * We will need it for some of the clock and regulator setup. + */ +- priv->id = (unsigned int)(unsigned long) +- of_device_get_match_data(&mdiodev->dev); ++ priv->info = of_device_get_match_data(&mdiodev->dev); ++ if (!priv->info) ++ return -EINVAL; ++ ++ /* Sanity check if these required device operstaions are filled ++ * properly. ++ */ ++ if (!priv->info->setup || !priv->info->phy_read || ++ !priv->info->phy_write || !priv->info->phy_supported || ++ !priv->info->pad_setup || !priv->info->mac_setup) ++ return -EINVAL; ++ ++ priv->id = priv->info->id; + + if (priv->id == ID_MT7530) { + priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); +Index: linux-5.4.43/drivers/net/dsa/mt7530.h +=================================================================== +--- linux-5.4.43.orig/drivers/net/dsa/mt7530.h ++++ linux-5.4.43/drivers/net/dsa/mt7530.h +@@ -11,7 +11,7 @@ + #define MT7530_NUM_FDB_RECORDS 2048 + #define MT7530_ALL_MEMBERS 0xff + +-enum { ++enum mt753x_id { + ID_MT7530 = 0, + ID_MT7621 = 1, + }; +@@ -447,6 +447,32 @@ static const char *p5_intf_modes(unsigne + } + } + ++/* struct mt753x_info - This is the main data structure for holding the specific ++ * part for each supported device ++ * @setup: Holding the handler to a device initialization ++ * @phy_read: Holding the way reading PHY port ++ * @phy_write: Holding the way writing PHY port ++ * @phy_supported: Check if the PHY type is being supported on a certain ++ * port ++ * @pad_setup: Holding the way setting up the bus pad for a certain MAC ++ * port ++ * @mac_setup: Holding the way setting up the PHY attribute for a ++ * certain MAC port ++ */ ++struct mt753x_info { ++ enum mt753x_id id; ++ ++ int (*setup)(struct dsa_switch *ds); ++ int (*phy_read)(struct dsa_switch *ds, int port, int regnum); ++ int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val); ++ bool (*phy_supported)(struct dsa_switch *ds, int port, ++ const struct phylink_link_state *state); ++ int (*pad_setup)(struct dsa_switch *ds, ++ const struct phylink_link_state *state); ++ int (*mac_setup)(struct dsa_switch *ds, int port, unsigned int mode, ++ const struct phylink_link_state *state); ++}; ++ + /* struct mt7530_priv - This is the main data structure for holding the state + * of the driver + * @dev: The device pointer +@@ -472,6 +498,7 @@ struct mt7530_priv { + struct regulator *core_pwr; + struct regulator *io_pwr; + struct gpio_desc *reset; ++ const struct mt753x_info *info; + unsigned int id; + bool mcm; + phy_interface_t p6_interface; diff --git a/target/linux/mediatek/patches-5.4/0600-3-6-dt-bindings-net-dsa-add-new-MT7531-binding-to-support-MT7531.patch b/target/linux/mediatek/patches-5.4/0600-3-6-dt-bindings-net-dsa-add-new-MT7531-binding-to-support-MT7531.patch new file mode 100644 index 0000000000..3ca12b9172 --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0600-3-6-dt-bindings-net-dsa-add-new-MT7531-binding-to-support-MT7531.patch @@ -0,0 +1,181 @@ +From patchwork Tue Dec 10 08:14:39 2019 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Landen Chao +X-Patchwork-Id: 1206955 +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 (no SPF record) + 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=pass (p=none dis=none) + header.from=mediatek.com +Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; + unprotected) header.d=mediatek.com header.i=@mediatek.com + header.b="SuczJHZp"; dkim-atps=neutral +Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) + by ozlabs.org (Postfix) with ESMTP id 47XCXj3BBNz9sPh + for ; + Tue, 10 Dec 2019 19:15:01 +1100 (AEDT) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1727133AbfLJIPA (ORCPT + ); + Tue, 10 Dec 2019 03:15:00 -0500 +Received: from mailgw02.mediatek.com ([210.61.82.184]:45567 "EHLO + mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by + vger.kernel.org with ESMTP id S1727022AbfLJIO7 (ORCPT + ); Tue, 10 Dec 2019 03:14:59 -0500 +X-UUID: a1d9a42928d44d63b201d5ad84c05baa-20191210 +DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; + d=mediatek.com; s=dk; + h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; + bh=KJqQ2m7z9H4vre+SZyxgKEGRWb9Edp5pJlYnepJNMyM=; + b=SuczJHZpeY7vF8UsCGorYUAcT2lEUX2E0ciiyQBS1rDLPzTYnufK8OXyAw5Uq8U1m72TGWYCaq1o0VWtI1meJpEmCL2TVK/d+Y+IaacHlO716BmX77+0MU0crczE8zx1Nz2pNh+GicsB6AoC9qbBU+p5egbKDMBhpRaGQNAeBww=; +X-UUID: a1d9a42928d44d63b201d5ad84c05baa-20191210 +Received: from mtkcas07.mediatek.inc [(172.21.101.84)] by + mailgw02.mediatek.com (envelope-from ) + (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) + with ESMTP id 297826603; Tue, 10 Dec 2019 16:14:47 +0800 +Received: from mtkcas08.mediatek.inc (172.21.101.126) by + mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server + (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:38 +0800 +Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc + (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via + Frontend Transport; Tue, 10 Dec 2019 16:14:26 +0800 +From: Landen Chao +To: , , + , , + , +CC: , , + , + , , + , , + , Landen Chao +Subject: [PATCH net-next 3/6] dt-bindings: net: dsa: add new MT7531 binding + to support MT7531 +Date: Tue, 10 Dec 2019 16:14:39 +0800 +Message-ID: <1c382fd916b66bfe3ce8ef18c12f954dbcbddbbc.1575914275.git.landen.chao@mediatek.com> +X-Mailer: git-send-email 2.18.0 +In-Reply-To: +References: +MIME-Version: 1.0 +X-MTK: N +Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org + +Add devicetree binding to support the compatible mt7531 switch as used +in the MediaTek MT7531 switch. + +Signed-off-by: Sean Wang +Signed-off-by: Landen Chao +--- + .../devicetree/bindings/net/dsa/mt7530.txt | 77 ++++++++++++++++++- + 1 file changed, 74 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/dsa/mt7530.txt b/Documentation/devicetree/bindings/net/dsa/mt7530.txt +index c5ed5d25f642..dc226a4e402a 100644 +--- a/Documentation/devicetree/bindings/net/dsa/mt7530.txt ++++ b/Documentation/devicetree/bindings/net/dsa/mt7530.txt +@@ -5,6 +5,7 @@ Required properties: + + - compatible: may be compatible = "mediatek,mt7530" + or compatible = "mediatek,mt7621" ++ or compatible = "mediatek,mt7531" + - #address-cells: Must be 1. + - #size-cells: Must be 0. + - mediatek,mcm: Boolean; if defined, indicates that either MT7530 is the part +@@ -32,10 +33,13 @@ Required properties for the child nodes within ports container: + + - reg: Port address described must be 6 for CPU port and from 0 to 5 for + user ports. +-- phy-mode: String, must be either "trgmii" or "rgmii" for port labeled +- "cpu". ++- phy-mode: String, the follow value would be acceptable for port labeled "cpu" ++ If compatible mediatek,mt7530 or mediatek,mt7621 is set, ++ must be either "trgmii" or "rgmii" ++ If compatible mediatek,mt7531 is set, ++ must be either "sgmii", "1000base-x" or "2500base-x" + +-Port 5 of the switch is muxed between: ++Port 5 of mt7530 and mt7621 switch is muxed between: + 1. GMAC5: GMAC5 can interface with another external MAC or PHY. + 2. PHY of port 0 or port 4: PHY interfaces with an external MAC like 2nd GMAC + of the SOC. Used in many setups where port 0/4 becomes the WAN port. +@@ -308,3 +312,70 @@ Example 3: MT7621: Port 5 is connected to external PHY: Port 5 -> external PHY. + }; + }; + }; ++ ++Example 4: ++ ++ð { ++ gmac0: mac@0 { ++ compatible = "mediatek,eth-mac"; ++ reg = <0>; ++ phy-mode = "2500base-x"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ pause; ++ }; ++ }; ++ ++ &mdio0 { ++ switch@0 { ++ compatible = "mediatek,mt7531"; ++ reg = <0>; ++ reset-gpios = <&pio 54 0>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ port@0 { ++ reg = <0>; ++ label = "lan0"; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ reg = <3>; ++ label = "lan3"; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ label = "wan"; ++ }; ++ ++ port@6 { ++ reg = <6>; ++ label = "cpu"; ++ ethernet = <&gmac0>; ++ phy-mode = "2500base-x"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ pause; ++ }; ++ }; ++ }; ++ }; ++ }; diff --git a/target/linux/mediatek/patches-5.4/0600-4-6-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch b/target/linux/mediatek/patches-5.4/0600-4-6-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch new file mode 100644 index 0000000000..a93b802c17 --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0600-4-6-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch @@ -0,0 +1,1102 @@ +From patchwork Tue Dec 10 08:14:40 2019 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Landen Chao +X-Patchwork-Id: 1206959 +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 (no SPF record) + 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=pass (p=none dis=none) + header.from=mediatek.com +Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; + unprotected) header.d=mediatek.com header.i=@mediatek.com + header.b="A6fsNqWU"; dkim-atps=neutral +Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) + by ozlabs.org (Postfix) with ESMTP id 47XCXz2fDsz9sPh + for ; + Tue, 10 Dec 2019 19:15:15 +1100 (AEDT) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1727198AbfLJIPC (ORCPT + ); + Tue, 10 Dec 2019 03:15:02 -0500 +Received: from mailgw02.mediatek.com ([210.61.82.184]:39119 "EHLO + mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by + vger.kernel.org with ESMTP id S1726750AbfLJIPC (ORCPT + ); Tue, 10 Dec 2019 03:15:02 -0500 +X-UUID: 38155314c18e497aacbec5bc0f664b9a-20191210 +DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; + d=mediatek.com; s=dk; + h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; + bh=sEkoMPWKI3m+K/8A3kC0uuYTNxZZaGCvfLKvnEmwQQ4=; + b=A6fsNqWUmjxIiZPLPb43Hs36qwwvYXMLQ/LlU24IcsfBro20uMkDbzGq522r69u0071Qgekwc/zs4yujo0pz40jCfnAo38JIDP73w4ZyVGuOENM5gdE+qNNUednOVSi052hcMRhS7zpVD0Rfl7vKKOU42F7Tl+cadVzjUl0ow/s=; +X-UUID: 38155314c18e497aacbec5bc0f664b9a-20191210 +Received: from mtkcas09.mediatek.inc [(172.21.101.178)] by + mailgw02.mediatek.com (envelope-from ) + (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) + with ESMTP id 452927388; Tue, 10 Dec 2019 16:14:46 +0800 +Received: from mtkcas08.mediatek.inc (172.21.101.126) by + mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server + (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:31 +0800 +Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc + (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via + Frontend Transport; Tue, 10 Dec 2019 16:14:26 +0800 +From: Landen Chao +To: , , + , , + , +CC: , , + , + , , + , , + , Landen Chao +Subject: [PATCH net-next 4/6] net: dsa: mt7530: Add the support of MT7531 + switch +Date: Tue, 10 Dec 2019 16:14:40 +0800 +Message-ID: <6d608dd024edc90b09ba4fe35417b693847f973c.1575914275.git.landen.chao@mediatek.com> +X-Mailer: git-send-email 2.18.0 +In-Reply-To: +References: +MIME-Version: 1.0 +X-MTK: N +Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org + +Add new support for MT7531: + +MT7531 is the next generation of MT7530. It is also a 7-ports switch with +5 giga embedded phys, 2 cpu ports, and the same MAC logic of MT7530. Cpu +port 6 only supports HSGMII interface. Cpu port 5 supports either RGMII +or HSGMII in different HW sku. Due to HSGMII interface support, pll, and +pad setting are different from MT7530. This patch adds different initial +setting of MT7531. + +Signed-off-by: Landen Chao +Signed-off-by: Sean Wang +--- + drivers/net/dsa/Kconfig | 6 +- + drivers/net/dsa/mt7530.c | 643 ++++++++++++++++++++++++++++++++++++++- + drivers/net/dsa/mt7530.h | 144 +++++++++ + 3 files changed, 784 insertions(+), 9 deletions(-) + +Index: linux-5.4.43/drivers/net/dsa/Kconfig +=================================================================== +--- linux-5.4.43.orig/drivers/net/dsa/Kconfig ++++ linux-5.4.43/drivers/net/dsa/Kconfig +@@ -33,12 +33,12 @@ config NET_DSA_LANTIQ_GSWIP + the xrx200 / VR9 SoC. + + config NET_DSA_MT7530 +- tristate "MediaTek MT7530 and MT7621 Ethernet switch support" ++ tristate "MediaTek MT753x and MT7621 Ethernet switch support" + depends on NET_DSA + select NET_DSA_TAG_MTK + ---help--- +- This enables support for the MediaTek MT7530 and MT7621 Ethernet +- switch chip. ++ This enables support for the MediaTek MT7530, MT7531 and MT7621 ++ Ethernet switch chip. + + config NET_DSA_MV88E6060 + tristate "Marvell 88E6060 ethernet switch chip support" +Index: linux-5.4.43/drivers/net/dsa/mt7530.c +=================================================================== +--- linux-5.4.43.orig/drivers/net/dsa/mt7530.c ++++ linux-5.4.43/drivers/net/dsa/mt7530.c +@@ -234,6 +234,12 @@ mt7530_write(struct mt7530_priv *priv, u + } + + static u32 ++_mt7530_unlocked_read(struct mt7530_dummy_poll *p) ++{ ++ return mt7530_mii_read(p->priv, p->reg); ++} ++ ++static u32 + _mt7530_read(struct mt7530_dummy_poll *p) + { + struct mii_bus *bus = p->priv->bus; +@@ -287,6 +293,102 @@ mt7530_clear(struct mt7530_priv *priv, u + } + + static int ++mt7531_ind_mmd_phy_read(struct mt7530_priv *priv, int port, int devad, ++ int regnum) ++{ ++ struct mii_bus *bus = priv->bus; ++ struct mt7530_dummy_poll p; ++ u32 reg, val; ++ int ret; ++ ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ reg = MDIO_CL45_ADDR | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad) | ++ regnum; ++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ reg = MDIO_CL45_READ | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad); ++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ ret = val & MDIO_RW_DATA_MASK; ++out: ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ ++static int ++mt7531_ind_mmd_phy_write(struct mt7530_priv *priv, int port, int devad, ++ int regnum, u32 data) ++{ ++ struct mii_bus *bus = priv->bus; ++ struct mt7530_dummy_poll p; ++ u32 val, reg; ++ int ret; ++ ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ reg = MDIO_CL45_ADDR | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad) | ++ regnum; ++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ reg = MDIO_CL45_WRITE | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad) | ++ data; ++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++out: ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ ++static int + mt7530_fdb_cmd(struct mt7530_priv *priv, enum mt7530_fdb_cmd cmd, u32 *rsp) + { + u32 val; +@@ -516,6 +618,83 @@ static int mt7530_phy_write(struct dsa_s + return mdiobus_write_nested(priv->bus, port, regnum, val); + } + ++static int ++mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ struct mii_bus *bus = priv->bus; ++ struct mt7530_dummy_poll p; ++ int ret; ++ u32 val; ++ ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ val = MDIO_CL22_READ | MDIO_PHY_ADDR(port) | MDIO_REG_ADDR(regnum); ++ ++ mt7530_mii_write(priv, MT7531_PHY_IAC, val | PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ ret = val & MDIO_RW_DATA_MASK; ++out: ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ ++static int ++mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum, ++ u16 data) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ struct mii_bus *bus = priv->bus; ++ struct mt7530_dummy_poll p; ++ int ret; ++ u32 reg; ++ ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg, ++ !(reg & PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ reg = MDIO_CL22_WRITE | MDIO_PHY_ADDR(port) | MDIO_REG_ADDR(regnum) | ++ data; ++ ++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg, ++ !(reg & PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++out: ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ + static void + mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset, + uint8_t *data) +@@ -1355,6 +1534,86 @@ mt7530_setup(struct dsa_switch *ds) + return 0; + } + ++static int mt7531_setup(struct dsa_switch *ds) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ struct mt7530_dummy_poll p; ++ u32 val, id; ++ int ret, i; ++ ++ /* Reset whole chip through gpio pin or memory-mapped registers for ++ * different type of hardware ++ */ ++ if (priv->mcm) { ++ reset_control_assert(priv->rstc); ++ usleep_range(1000, 1100); ++ reset_control_deassert(priv->rstc); ++ } else { ++ gpiod_set_value_cansleep(priv->reset, 0); ++ usleep_range(1000, 1100); ++ gpiod_set_value_cansleep(priv->reset, 1); ++ } ++ ++ /* Waiting for MT7530 got to stable */ ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_HWTRAP); ++ ret = readx_poll_timeout(_mt7530_read, &p, val, val != 0, ++ 20, 1000000); ++ if (ret < 0) { ++ dev_err(priv->dev, "reset timeout\n"); ++ return ret; ++ } ++ ++ id = mt7530_read(priv, MT7531_CREV); ++ id >>= CHIP_NAME_SHIFT; ++ ++ if (id != MT7531_ID) { ++ dev_err(priv->dev, "chip %x can't be supported\n", id); ++ return -ENODEV; ++ } ++ ++ /* Reset the switch through internal reset */ ++ mt7530_write(priv, MT7530_SYS_CTRL, ++ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | ++ SYS_CTRL_REG_RST); ++ ++ priv->p6_interface = PHY_INTERFACE_MODE_NA; ++ ++ /* Enable PHY power, since phy_device has not yet been created ++ * provided for phy_[read,write]_mmd_indirect is called, we provide ++ * our own mt7531_ind_mmd_phy_[read,write] to complete this ++ * function. ++ */ ++ val = mt7531_ind_mmd_phy_read(priv, 0, PHY_DEV1F, ++ MT7531_PHY_DEV1F_REG_403); ++ val |= MT7531_PHY_EN_BYPASS_MODE; ++ val &= ~MT7531_PHY_POWER_OFF; ++ mt7531_ind_mmd_phy_write(priv, 0, PHY_DEV1F, ++ MT7531_PHY_DEV1F_REG_403, val); ++ ++ /* Enable and reset MIB counters */ ++ mt7530_mib_reset(ds); ++ ++ mt7530_clear(priv, MT7530_MFC, UNU_FFP_MASK); ++ ++ for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ /* Disable forwarding by default on all ports */ ++ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, ++ PCR_MATRIX_CLR); ++ ++ if (dsa_is_cpu_port(ds, i)) ++ mt7530_cpu_port_enable(priv, i); ++ else ++ mt7530_port_disable(ds, i); ++ } ++ ++ /* Flush the FDB table */ ++ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + static bool mt7530_phy_supported(struct dsa_switch *ds, int port, + const struct phylink_link_state *state) + { +@@ -1392,6 +1651,49 @@ unsupported: + return false; + } + ++static bool mt7531_dual_sgmii_supported(struct mt7530_priv *priv) ++{ ++ u32 val; ++ ++ val = mt7530_read(priv, MT7531_TOP_SIG_SR); ++ return ((val & PAD_DUAL_SGMII_EN) != 0); ++} ++ ++static bool mt7531_phy_supported(struct dsa_switch *ds, int port, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ switch (port) { ++ case 0: /* Internal phy */ ++ case 1: ++ case 2: ++ case 3: ++ case 4: ++ if (state->interface != PHY_INTERFACE_MODE_GMII) ++ goto unsupported; ++ break; ++ case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */ ++ if (!mt7531_dual_sgmii_supported(priv)) ++ return phy_interface_mode_is_rgmii(state->interface); ++ /* fall through */ ++ case 6: /* 1st cpu port supports sgmii/8023z only */ ++ if (state->interface != PHY_INTERFACE_MODE_SGMII && ++ !phy_interface_mode_is_8023z(state->interface)) ++ goto unsupported; ++ break; ++ default: ++ dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, ++ port); ++ goto unsupported; ++ } ++ ++ return true; ++ ++unsupported: ++ return false; ++} ++ + static bool mt753x_phy_supported(struct dsa_switch *ds, int port, + const struct phylink_link_state *state) + { +@@ -1413,7 +1715,144 @@ mt7530_pad_setup(struct dsa_switch *ds, + * host which must be placed after the setup on the + * device side is all finished. + */ +- mt7623_pad_clk_setup(ds); ++ //mt7623_pad_clk_setup(ds); ++ } ++ ++ return 0; ++} ++ ++static int ++mt7531_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 xtal, val; ++ ++ if (mt7531_dual_sgmii_supported(priv)) ++ return 0; ++ ++ xtal = mt7530_read(priv, MT7531_HWTRAP) & HWTRAP_XTAL_FSEL_MASK; ++ ++ switch (xtal) { ++ case HWTRAP_XTAL_FSEL_25MHZ: ++ /* Step 1 : Disable MT7531 COREPLL */ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val &= ~EN_COREPLL; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ ++ /* Step 2: switch to XTAL output */ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val |= SW_CLKSW; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_EN; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ /* Step 3: disable PLLGP and enable program PLLGP */ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val |= SW_PLLGP; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ ++ /* Step 4: program COREPLL output frequency to 500MHz */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_POSDIV_M; ++ val |= 2 << RG_COREPLL_POSDIV_S; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ usleep_range(25, 35); ++ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_SDM_PCW_M; ++ val |= 0x140000 << RG_COREPLL_SDM_PCW_S; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ /* Set feedback divide ratio update signal to high */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val |= RG_COREPLL_SDM_PCW_CHG; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ /* Wait for at least 16 XTAL clocks */ ++ usleep_range(10, 20); ++ ++ /* Step 5: set feedback divide ratio update signal to low */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_SDM_PCW_CHG; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ /* Enable 325M clock for SGMII */ ++ mt7530_write(priv, MT7531_ANA_PLLGP_CR5, 0xad0000); ++ ++ /* Enable 250SSC clock for RGMII */ ++ mt7530_write(priv, MT7531_ANA_PLLGP_CR2, 0x4f40000); ++ ++ /* Step 6: Enable MT7531 PLL */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val |= RG_COREPLL_EN; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val |= EN_COREPLL; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ usleep_range(25, 35); ++ break; ++ case HWTRAP_XTAL_FSEL_40MHZ: ++ /* Step 1 : Disable MT7531 COREPLL */ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val &= ~EN_COREPLL; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ ++ /* Step 2: switch to XTAL output */ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val |= SW_CLKSW; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_EN; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ /* Step 3: disable PLLGP and enable program PLLGP */ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val |= SW_PLLGP; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ ++ /* Step 4: program COREPLL output frequency to 500MHz */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_POSDIV_M; ++ val |= 2 << RG_COREPLL_POSDIV_S; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ usleep_range(25, 35); ++ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_SDM_PCW_M; ++ val |= 0x190000 << RG_COREPLL_SDM_PCW_S; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ /* Set feedback divide ratio update signal to high */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val |= RG_COREPLL_SDM_PCW_CHG; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ /* Wait for at least 16 XTAL clocks */ ++ usleep_range(10, 20); ++ ++ /* Step 5: set feedback divide ratio update signal to low */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_SDM_PCW_CHG; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ /* Enable 325M clock for SGMII */ ++ mt7530_write(priv, MT7531_ANA_PLLGP_CR5, 0xad0000); ++ ++ /* Enable 250SSC clock for RGMII */ ++ mt7530_write(priv, MT7531_ANA_PLLGP_CR2, 0x4f40000); ++ ++ /* Step 6: Enable MT7531 PLL */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val |= RG_COREPLL_EN; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val |= EN_COREPLL; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ usleep_range(25, 35); ++ break; + } + + return 0; +@@ -1442,6 +1881,149 @@ mt7530_mac_setup(struct dsa_switch *ds, + return 0; + } + ++static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port) ++{ ++ u32 val; ++ ++ if (port != 5) { ++ dev_err(priv->dev, "RGMII mode is not available for port %d\n", ++ port); ++ return -EINVAL; ++ } ++ ++ val = mt7530_read(priv, MT7531_CLKGEN_CTRL); ++ val |= GP_CLK_EN; ++ val &= ~GP_MODE_MASK; ++ val |= GP_MODE(MT7531_GP_MODE_RGMII); ++ val |= TXCLK_NO_REVERSE; ++ val |= RXCLK_NO_DELAY; ++ val &= ~CLK_SKEW_IN_MASK; ++ val |= CLK_SKEW_IN(MT7531_CLK_SKEW_NO_CHG); ++ val &= ~CLK_SKEW_OUT_MASK; ++ val |= CLK_SKEW_OUT(MT7531_CLK_SKEW_NO_CHG); ++ mt7530_write(priv, MT7531_CLKGEN_CTRL, val); ++ ++ return 0; ++} ++ ++static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port, ++ const struct phylink_link_state *state) ++{ ++ u32 val; ++ ++ if (port != 5 && port != 6) ++ return -EINVAL; ++ ++ val = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port)); ++ val |= MT7531_SGMII_PHYA_PWD; ++ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val); ++ ++ val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port)); ++ val &= ~MT7531_RG_TPHY_SPEED_MASK; ++ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) ++ val |= MT7531_RG_TPHY_SPEED_3_125G; ++ mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val); ++ ++ val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); ++ val &= ~MT7531_SGMII_AN_ENABLE; ++ mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); ++ ++ val = mt7530_read(priv, MT7531_SGMII_MODE(port)); ++ val &= ~MT7531_SGMII_IF_MODE_MASK; ++ ++ switch (state->speed) { ++ case SPEED_10: ++ val |= MT7531_SGMII_FORCE_SPEED_10; ++ break; ++ case SPEED_100: ++ val |= MT7531_SGMII_FORCE_SPEED_100; ++ break; ++ case SPEED_2500: ++ case SPEED_1000: ++ val |= MT7531_SGMII_FORCE_SPEED_1000; ++ break; ++ }; ++ ++ val &= ~MT7531_SGMII_FORCE_DUPLEX; ++ /* For sgmii force mode, 0 is full duplex and 1 is half duplex */ ++ if (state->duplex == DUPLEX_HALF) ++ val |= MT7531_SGMII_FORCE_DUPLEX; ++ ++ mt7530_write(priv, MT7531_SGMII_MODE(port), val); ++ ++ val = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port)); ++ val &= ~MT7531_SGMII_PHYA_PWD; ++ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val); ++ ++ return 0; ++} ++ ++static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port, ++ const struct phylink_link_state *state) ++{ ++ u32 val; ++ ++ if (port != 5 && port != 6) ++ return -EINVAL; ++ ++ val = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port)); ++ val |= MT7531_SGMII_PHYA_PWD; ++ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val); ++ ++ switch (state->speed) { ++ case SPEED_10: ++ case SPEED_100: ++ case SPEED_1000: ++ val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port)); ++ val &= ~MT7531_RG_TPHY_SPEED_MASK; ++ mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val); ++ break; ++ default: ++ dev_info(priv->dev, "invalid SGMII speed idx %d for port %d\n", ++ state->speed, port); ++ ++ return -EINVAL; ++ } ++ ++ val = mt7530_read(priv, MT7531_SGMII_MODE(port)); ++ val |= MT7531_SGMII_REMOTE_FAULT_DIS; ++ mt7530_write(priv, MT7531_SGMII_MODE(port), val); ++ ++ val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); ++ val |= MT7531_SGMII_AN_RESTART; ++ mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); ++ ++ val = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port)); ++ val &= ~MT7531_SGMII_PHYA_PWD; ++ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val); ++ ++ return 0; ++} ++ ++static int ++mt7531_mac_setup(struct dsa_switch *ds, int port, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ if (port < 5 || port >= MT7530_NUM_PORTS) { ++ dev_err(priv->dev, "port %d is not a MAC port\n", port); ++ return -EINVAL; ++ } ++ ++ switch (state->interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ return mt7531_rgmii_setup(priv, port); ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ return mt7531_sgmii_setup_mode_force(priv, port, state); ++ case PHY_INTERFACE_MODE_SGMII: ++ return mt7531_sgmii_setup_mode_an(priv, port, state); ++ default: ++ return -EINVAL; ++ } ++} ++ + static int mt753x_mac_setup(struct dsa_switch *ds, int port, unsigned int mode, + const struct phylink_link_state *state) + { +@@ -1473,22 +2055,23 @@ static void mt753x_phylink_mac_config(st + if (priv->p5_interface == state->interface) + break; + if (mt753x_mac_setup(ds, port, mode, state) < 0) +- goto unsupported; ++ break; ++ priv->p5_interface = state->interface; + break; + case 6: /* 1st cpu port */ + if (priv->p6_interface == state->interface) + break; + mt753x_pad_setup(ds, state); + if (mt753x_mac_setup(ds, port, mode, state) < 0) +- goto unsupported; ++ break; + priv->p6_interface = state->interface; + break; + default: +- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); + return; + } + +- if (phylink_autoneg_inband(mode)) { ++ if (phylink_autoneg_inband(mode) && ++ state->interface != PHY_INTERFACE_MODE_SGMII) { + dev_err(ds->dev, "%s: in-band negotiation unsupported\n", + __func__); + return; +@@ -1499,13 +2082,15 @@ static void mt753x_phylink_mac_config(st + mcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 | + PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN); + mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN | +- PMCR_BACKPR_EN | PMCR_FORCE_MODE; ++ PMCR_BACKPR_EN | PMCR_FORCE_MODE_ID(priv->id) | ++ PMCR_FORCE_LNK; + + /* Are we connected to external phy */ + if (port == 5 && dsa_is_user_port(ds, 5)) + mcr_new |= PMCR_EXT_PHY; + + switch (state->speed) { ++ case SPEED_2500: + case SPEED_1000: + mcr_new |= PMCR_FORCE_SPEED_1000; + if (priv->eee_enable & BIT(port)) +@@ -1529,6 +2114,27 @@ static void mt753x_phylink_mac_config(st + mt7530_write(priv, MT7530_PMCR_P(port), mcr_new); + } + ++void mt7531_sgmii_restart_an(struct dsa_switch *ds, int port) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 val; ++ ++ val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); ++ val |= MT7531_SGMII_AN_RESTART; ++ mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); ++} ++ ++static void ++mt753x_phylink_mac_an_restart(struct dsa_switch *ds, int port) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ if (!priv->info->port_an_restart) ++ return; ++ ++ priv->info->port_an_restart(ds, port); ++} ++ + static void mt7530_phylink_mac_link_down(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface) +@@ -1563,9 +2169,20 @@ static void mt753x_phylink_validate(stru + phylink_set_port_modes(mask); + phylink_set(mask, Autoneg); + +- if (state->interface == PHY_INTERFACE_MODE_TRGMII) { ++ switch (state->interface) { ++ case PHY_INTERFACE_MODE_TRGMII: + phylink_set(mask, 1000baseT_Full); +- } else { ++ break; ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ phylink_set(mask, 1000baseX_Full); ++ phylink_set(mask, 2500baseX_Full); ++ break; ++ case PHY_INTERFACE_MODE_SGMII: ++ phylink_set(mask, 1000baseT_Full); ++ phylink_set(mask, 1000baseX_Full); ++ /* fall through */ ++ default: + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); +@@ -1577,6 +2194,7 @@ static void mt753x_phylink_validate(stru + if (port == 5) + phylink_set(mask, 1000baseX_Full); + } ++ break; + } + + phylink_set(mask, Pause); +@@ -1721,8 +2339,9 @@ static const struct dsa_switch_ops mt753 + .port_mirror_add = mt7530_port_mirror_add, + .port_mirror_del = mt7530_port_mirror_del, + .phylink_validate = mt753x_phylink_validate, +- .phylink_mac_link_state = mt7530_phylink_mac_link_state, ++ .phylink_mac_link_state = mt7530_phylink_mac_link_state, + .phylink_mac_config = mt753x_phylink_mac_config, ++ .phylink_mac_an_restart = mt753x_phylink_mac_an_restart, + .phylink_mac_link_down = mt7530_phylink_mac_link_down, + .phylink_mac_link_up = mt7530_phylink_mac_link_up, + .get_mac_eee = mt7530_get_mac_eee, +@@ -1748,11 +2367,22 @@ static const struct mt753x_info mt753x_t + .pad_setup = mt7530_pad_setup, + .mac_setup = mt7530_mac_setup, + }, ++ [ID_MT7531] = { ++ .id = ID_MT7531, ++ .setup = mt7531_setup, ++ .phy_read = mt7531_ind_phy_read, ++ .phy_write = mt7531_ind_phy_write, ++ .phy_supported = mt7531_phy_supported, ++ .pad_setup = mt7531_pad_setup, ++ .mac_setup = mt7531_mac_setup, ++ .port_an_restart = mt7531_sgmii_restart_an, ++ }, + }; + + static const struct of_device_id mt7530_of_match[] = { + { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, + { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, ++ { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, mt7530_of_match); +Index: linux-5.4.43/drivers/net/dsa/mt7530.h +=================================================================== +--- linux-5.4.43.orig/drivers/net/dsa/mt7530.h ++++ linux-5.4.43/drivers/net/dsa/mt7530.h +@@ -14,6 +14,7 @@ + enum mt753x_id { + ID_MT7530 = 0, + ID_MT7621 = 1, ++ ID_MT7531 = 2, + }; + + #define NUM_TRGMII_CTRL 5 +@@ -222,6 +223,19 @@ enum mt7530_vlan_port_attr { + #define PMCR_FORCE_LNK BIT(0) + #define PMCR_SPEED_MASK (PMCR_FORCE_SPEED_100 | \ + PMCR_FORCE_SPEED_1000) ++#define MT7531_FORCE_LNK BIT(31) ++#define MT7531_FORCE_SPD BIT(30) ++#define MT7531_FORCE_DPX BIT(29) ++#define MT7531_FORCE_RX_FC BIT(28) ++#define MT7531_FORCE_TX_FC BIT(27) ++#define MT7531_FORCE_MODE (MT7531_FORCE_LNK | \ ++ MT7531_FORCE_SPD | \ ++ MT7531_FORCE_DPX | \ ++ MT7531_FORCE_RX_FC | \ ++ MT7531_FORCE_TX_FC) ++#define PMCR_FORCE_MODE_ID(id) (((id) == ID_MT7531) ? \ ++ MT7531_FORCE_MODE : \ ++ PMCR_FORCE_MODE) + + #define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100) + #define PMSR_EEE1G BIT(7) +@@ -258,12 +272,111 @@ enum mt7530_vlan_port_attr { + CCR_RX_OCT_CNT_BAD | \ + CCR_TX_OCT_CNT_GOOD | \ + CCR_TX_OCT_CNT_BAD) ++ ++/* SGMII registers */ ++#define MT7531_SGMII_REG_BASE 0x5000 ++#define MT7531_SGMII_REG(p, r) (MT7531_SGMII_REG_BASE + \ ++ ((p) - 5) * 0x1000 + (r)) ++ ++/* SGMII PCS_CONTROL_1 */ ++#define MT7531_PCS_CONTROL_1(p) MT7531_SGMII_REG(p, 0x00) ++#define MT7531_SGMII_LINK_STATUS BIT(18) ++#define MT7531_SGMII_AN_ENABLE BIT(12) ++#define MT7531_SGMII_AN_RESTART BIT(9) ++ ++/* Fields of SGMII_MODE */ ++#define MT7531_SGMII_MODE(p) MT7531_SGMII_REG(p, 0x20) ++#define MT7531_SGMII_REMOTE_FAULT_DIS BIT(8) ++#define MT7531_SGMII_FORCE_DUPLEX BIT(4) ++#define MT7531_SGMII_IF_MODE_MASK GENMASK(5, 1) ++#define MT7531_SGMII_FORCE_SPEED_10 0x0 ++#define MT7531_SGMII_FORCE_SPEED_100 BIT(2) ++#define MT7531_SGMII_FORCE_SPEED_1000 BIT(3) ++ ++/* Fields of QPHY_PWR_STATE_CTRL */ ++#define MT7531_QPHY_PWR_STATE_CTRL(p) MT7531_SGMII_REG(p, 0xe8) ++#define MT7531_SGMII_PHYA_PWD BIT(4) ++ ++/* Values of SGMII SPEED */ ++#define MT7531_PHYA_CTRL_SIGNAL3(p) MT7531_SGMII_REG(p, 0x128) ++#define MT7531_RG_TPHY_SPEED_MASK (BIT(2) | BIT(3)) ++#define MT7531_RG_TPHY_SPEED_1_25G 0x0 ++#define MT7531_RG_TPHY_SPEED_3_125G BIT(2) ++ + /* Register for system reset */ + #define MT7530_SYS_CTRL 0x7000 + #define SYS_CTRL_PHY_RST BIT(2) + #define SYS_CTRL_SW_RST BIT(1) + #define SYS_CTRL_REG_RST BIT(0) + ++/* Register for PHY Indirect Access Control */ ++#define MT7531_PHY_IAC 0x701C ++#define PHY_ACS_ST BIT(31) ++#define MDIO_REG_ADDR_MASK (0x1f << 25) ++#define MDIO_PHY_ADDR_MASK (0x1f << 20) ++#define MDIO_CMD_MASK (0x3 << 18) ++#define MDIO_ST_MASK (0x3 << 16) ++#define MDIO_RW_DATA_MASK (0xffff) ++#define MDIO_REG_ADDR(x) (((x) & 0x1f) << 25) ++#define MDIO_DEV_ADDR(x) (((x) & 0x1f) << 25) ++#define MDIO_PHY_ADDR(x) (((x) & 0x1f) << 20) ++#define MDIO_CMD(x) (((x) & 0x3) << 18) ++#define MDIO_ST(x) (((x) & 0x3) << 16) ++ ++enum mt7531_phy_iac_cmd { ++ MT7531_MDIO_ADDR = 0, ++ MT7531_MDIO_WRITE = 1, ++ MT7531_MDIO_READ = 2, ++ MT7531_MDIO_READ_CL45 = 3, ++}; ++ ++/* MDIO_ST: MDIO start field */ ++enum mt7531_mdio_st { ++ MT7531_MDIO_ST_CL45 = 0, ++ MT7531_MDIO_ST_CL22 = 1, ++}; ++ ++#define MDIO_CL22_READ (MDIO_ST(MT7531_MDIO_ST_CL22) | \ ++ MDIO_CMD(MT7531_MDIO_READ)) ++#define MDIO_CL22_WRITE (MDIO_ST(MT7531_MDIO_ST_CL22) | \ ++ MDIO_CMD(MT7531_MDIO_WRITE)) ++#define MDIO_CL45_ADDR (MDIO_ST(MT7531_MDIO_ST_CL45) | \ ++ MDIO_CMD(MT7531_MDIO_ADDR)) ++#define MDIO_CL45_READ (MDIO_ST(MT7531_MDIO_ST_CL45) | \ ++ MDIO_CMD(MT7531_MDIO_READ)) ++#define MDIO_CL45_WRITE (MDIO_ST(MT7531_MDIO_ST_CL45) | \ ++ MDIO_CMD(MT7531_MDIO_WRITE)) ++ ++#define MT7531_CLKGEN_CTRL 0x7500 ++#define CLK_SKEW_OUT(x) (((x) & 0x3) << 8) ++#define CLK_SKEW_OUT_MASK (0x3 << 8) ++#define CLK_SKEW_IN(x) (((x) & 0x3) << 6) ++#define CLK_SKEW_IN_MASK (0x3 << 6) ++#define RXCLK_NO_DELAY BIT(5) ++#define TXCLK_NO_REVERSE BIT(4) ++#define GP_MODE(x) (((x) & 0x3) << 1) ++#define GP_MODE_MASK (0x3 << 1) ++#define GP_CLK_EN BIT(0) ++ ++#define PHY_DEV1F 0x1f ++#define MT7531_PHY_DEV1F_REG_403 0x403 ++ ++#define MT7531_PHY_EN_BYPASS_MODE BIT(4) ++#define MT7531_PHY_POWER_OFF BIT(5) ++ ++enum mt7531_gp_mode { ++ MT7531_GP_MODE_RGMII = 0, ++ MT7531_GP_MODE_MII = 1, ++ MT7531_GP_MODE_REV_MII = 2 ++}; ++ ++enum mt7531_clk_skew { ++ MT7531_CLK_SKEW_NO_CHG = 0, ++ MT7531_CLK_SKEW_DLY_100PPS = 1, ++ MT7531_CLK_SKEW_DLY_200PPS = 2, ++ MT7531_CLK_SKEW_REVERSE = 3, ++}; ++ + /* Register for hw trap status */ + #define MT7530_HWTRAP 0x7800 + #define HWTRAP_XTAL_MASK (BIT(10) | BIT(9)) +@@ -271,6 +384,11 @@ enum mt7530_vlan_port_attr { + #define HWTRAP_XTAL_40MHZ (BIT(10)) + #define HWTRAP_XTAL_20MHZ (BIT(9)) + ++#define MT7531_HWTRAP 0x7800 ++#define HWTRAP_XTAL_FSEL_MASK BIT(7) ++#define HWTRAP_XTAL_FSEL_25MHZ BIT(7) ++#define HWTRAP_XTAL_FSEL_40MHZ 0 ++ + /* Register for hw trap modification */ + #define MT7530_MHWTRAP 0x7804 + #define MHWTRAP_PHY0_SEL BIT(20) +@@ -285,14 +403,34 @@ enum mt7530_vlan_port_attr { + #define MT7530_TOP_SIG_CTRL 0x7808 + #define TOP_SIG_CTRL_NORMAL (BIT(17) | BIT(16)) + ++#define MT7531_TOP_SIG_SR 0x780c ++#define PAD_DUAL_SGMII_EN BIT(1) ++ + #define MT7530_IO_DRV_CR 0x7810 + #define P5_IO_CLK_DRV(x) ((x) & 0x3) + #define P5_IO_DATA_DRV(x) (((x) & 0x3) << 4) + ++#define MT7531_PLLGP_EN 0x7820 ++#define EN_COREPLL BIT(2) ++#define SW_CLKSW BIT(1) ++#define SW_PLLGP BIT(0) ++ ++#define MT7531_PLLGP_CR0 0x78a8 ++#define RG_COREPLL_EN BIT(22) ++#define RG_COREPLL_POSDIV_S 23 ++#define RG_COREPLL_POSDIV_M 0x3800000 ++#define RG_COREPLL_SDM_PCW_S 1 ++#define RG_COREPLL_SDM_PCW_M 0x3ffffe ++#define RG_COREPLL_SDM_PCW_CHG BIT(0) ++ + #define MT7530_P6ECR 0x7830 + #define P6_INTF_MODE_MASK 0x3 + #define P6_INTF_MODE(x) ((x) & 0x3) + ++/* RGMII and SGMII PLL clock */ ++#define MT7531_ANA_PLLGP_CR2 0x78b0 ++#define MT7531_ANA_PLLGP_CR5 0x78bc ++ + /* Registers for TRGMII on the both side */ + #define MT7530_TRGMII_RCK_CTRL 0x7a00 + #define RX_RST BIT(31) +@@ -335,6 +473,9 @@ enum mt7530_vlan_port_attr { + #define CHIP_NAME_SHIFT 16 + #define MT7530_ID 0x7530 + ++#define MT7531_CREV 0x781C ++#define MT7531_ID 0x7531 ++ + /* Registers for core PLL access through mmd indirect */ + #define CORE_PLL_GROUP2 0x401 + #define RG_SYSPLL_EN_NORMAL BIT(15) +@@ -458,6 +599,8 @@ static const char *p5_intf_modes(unsigne + * port + * @mac_setup: Holding the way setting up the PHY attribute for a + * certain MAC port ++ * @port_an_restart Holding the way restarting 802.3z BaseX autonegotiation ++ * for a certain MAC port + */ + struct mt753x_info { + enum mt753x_id id; +@@ -471,6 +614,7 @@ struct mt753x_info { + const struct phylink_link_state *state); + int (*mac_setup)(struct dsa_switch *ds, int port, unsigned int mode, + const struct phylink_link_state *state); ++ void (*port_an_restart)(struct dsa_switch *ds, int port); + }; + + /* struct mt7530_priv - This is the main data structure for holding the state diff --git a/target/linux/mediatek/patches-5.4/0600-6-6-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch b/target/linux/mediatek/patches-5.4/0600-6-6-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch new file mode 100644 index 0000000000..a4899caee5 --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0600-6-6-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch @@ -0,0 +1,140 @@ +From patchwork Tue Dec 10 08:14:42 2019 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Landen Chao +X-Patchwork-Id: 1206964 +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 (no SPF record) + 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=pass (p=none dis=none) + header.from=mediatek.com +Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; + unprotected) header.d=mediatek.com header.i=@mediatek.com + header.b="eagJVm76"; dkim-atps=neutral +Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) + by ozlabs.org (Postfix) with ESMTP id 47XCYF2fNjz9sR7 + for ; + Tue, 10 Dec 2019 19:15:29 +1100 (AEDT) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1727295AbfLJIP0 (ORCPT + ); + Tue, 10 Dec 2019 03:15:26 -0500 +Received: from mailgw01.mediatek.com ([210.61.82.183]:21469 "EHLO + mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by + vger.kernel.org with ESMTP id S1726062AbfLJIO4 (ORCPT + ); Tue, 10 Dec 2019 03:14:56 -0500 +X-UUID: f9b456136baf42daba0957485d388010-20191210 +DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; + d=mediatek.com; s=dk; + h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; + bh=BT+q/z4xoeKXCk+y25bvARvW/z0vRa1uB7kHqAjvpaw=; + b=eagJVm76XNgnVVvxDHR4QtcIyynPPYY4k7twyvlRAQeSnsJbABh1afLK+LlxnJ0TM069F+hNNzWXq7ZGru/I+gYhmqZcYCt/SkEYgxdTb0VNE+DIW0hmNAOoJ0i23gobJ3xa7JVRfIfeZcbjwRJSuqwzLBRZBLIFzqSs71VZx1Y=; +X-UUID: f9b456136baf42daba0957485d388010-20191210 +Received: from mtkcas07.mediatek.inc [(172.21.101.84)] by + mailgw01.mediatek.com (envelope-from ) + (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) + with ESMTP id 1831961689; Tue, 10 Dec 2019 16:14:48 +0800 +Received: from mtkcas08.mediatek.inc (172.21.101.126) by + mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server + (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:32 +0800 +Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc + (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via + Frontend Transport; Tue, 10 Dec 2019 16:14:27 +0800 +From: Landen Chao +To: , , + , , + , +CC: , , + , + , , + , , + , Landen Chao +Subject: [PATCH net-next 6/6] arm64: dts: mt7622: add mt7531 dsa to + bananapi-bpi-r64 board +Date: Tue, 10 Dec 2019 16:14:42 +0800 +Message-ID: <62eef5503c117f48d4b41e94fd28d75e123590b4.1575914275.git.landen.chao@mediatek.com> +X-Mailer: git-send-email 2.18.0 +In-Reply-To: +References: +MIME-Version: 1.0 +X-MTK: N +Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org + +Add mt7531 dsa to bananapi-bpi-r64 board for 5 giga Ethernet ports support. + +Signed-off-by: Landen Chao +--- + .../dts/mediatek/mt7622-bananapi-bpi-r64.dts | 50 +++++++++++++++++++ + 1 file changed, 50 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +index 83e10591e0e5..ffacefee8e2a 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -143,6 +143,56 @@ + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; ++ ++ switch@0 { ++ compatible = "mediatek,mt7531"; ++ reg = <0>; ++ reset-gpios = <&pio 54 0>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ label = "wan"; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ label = "lan0"; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ label = "lan1"; ++ }; ++ ++ port@3 { ++ reg = <3>; ++ label = "lan2"; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ label = "lan3"; ++ }; ++ ++ port@6 { ++ reg = <6>; ++ label = "cpu"; ++ ethernet = <&gmac0>; ++ phy-mode = "2500base-x"; ++ ++ fixed-link { ++ speed = <2500>; ++ full-duplex; ++ pause; ++ }; ++ }; ++ }; ++ }; ++ + }; + }; + -- 2.30.2