[openwrt/openwrt] mediatek: backport the latest version of the mt7531 support patches

LEDE Commits lede-commits at lists.infradead.org
Wed Sep 9 05:53:10 EDT 2020


nbd pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/c18a872825c8dd27a398e4f5b2f98c9b5066d8a9

commit c18a872825c8dd27a398e4f5b2f98c9b5066d8a9
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Mon Sep 7 17:47:15 2020 +0200

    mediatek: backport the latest version of the mt7531 support patches
    
    Fixes unknown unicast flooding issue
    
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 ...-net-dsa-mt7530-Refine-message-in-Kconfig.patch |   98 --
 ...vice-data-ready-for-adding-a-new-hardware.patch |  441 ------
 ...-add-new-MT7531-binding-to-support-MT7531.patch |  179 ---
 ...a-mt7530-Add-the-support-of-MT7531-switch.patch | 1096 --------------
 ...-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch |  138 --
 ...-propagate-resolved-link-config-via-mac_l.patch |  246 ++++
 ...pagate-resolved-link-config-via-mac_link_.patch |  143 ++
 ...530-use-resolved-link-config-in-mac_link_.patch |  145 ++
 ...530-Extend-device-data-ready-for-adding-a.patch |  458 ++++++
 ...a-mt7530-Add-the-support-of-MT7531-switch.patch | 1510 ++++++++++++++++++++
 ...-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch |   71 +
 11 files changed, 2573 insertions(+), 1952 deletions(-)

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
deleted file mode 100644
index 5288751e50..0000000000
--- a/target/linux/mediatek/patches-5.4/0600-1-6-net-dsa-mt7530-Refine-message-in-Kconfig.patch
+++ /dev/null
@@ -1,98 +0,0 @@
-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 <landen.chao at mediatek.com>
-X-Patchwork-Id: 1206962
-X-Patchwork-Delegate: davem at davemloft.net
-Return-Path: <netdev-owner at vger.kernel.org>
-X-Original-To: patchwork-incoming-netdev at ozlabs.org
-Delivered-To: patchwork-incoming-netdev at 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 at vger.kernel.org;
- receiver=<UNKNOWN>)
-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 <patchwork-incoming-netdev at ozlabs.org>;
- Tue, 10 Dec 2019 19:15:20 +1100 (AEDT)
-Received: (majordomo at vger.kernel.org) by vger.kernel.org via listexpand
- id S1727061AbfLJIO5 (ORCPT
- <rfc822;patchwork-incoming-netdev at ozlabs.org>);
- 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
- <rfc822;netdev at vger.kernel.org>); 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 <landen.chao at mediatek.com>)
- (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 <landen.chao at mediatek.com>
-To: <andrew at lunn.ch>, <f.fainelli at gmail.com>,
- <vivien.didelot at savoirfairelinux.com>, <matthias.bgg at gmail.com>,
- <robh+dt at kernel.org>, <mark.rutland at arm.com>
-CC: <devicetree at vger.kernel.org>, <netdev at vger.kernel.org>,
- <linux-kernel at vger.kernel.org>,
- <linux-mediatek at lists.infradead.org>, <davem at davemloft.net>,
- <sean.wang at mediatek.com>, <opensource at vdorst.com>,
- <frank-w at public-files.de>, Landen Chao <landen.chao at mediatek.com>
-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 at mediatek.com>
-X-Mailer: git-send-email 2.18.0
-In-Reply-To: <cover.1575914275.git.landen.chao at mediatek.com>
-References: <cover.1575914275.git.landen.chao at mediatek.com>
-MIME-Version: 1.0
-X-MTK: N
-Sender: netdev-owner at vger.kernel.org
-Precedence: bulk
-List-ID: <netdev.vger.kernel.org>
-X-Mailing-List: netdev at vger.kernel.org
-
-Refine message in Kconfig with fixing typo and an explicit MT7621 support.
-
-Signed-off-by: Landen Chao <landen.chao at mediatek.com>
-Signed-off-by: Sean Wang <sean.wang at mediatek.com>
-Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
----
- drivers/net/dsa/Kconfig | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- 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
deleted file mode 100644
index c4b117dcb7..0000000000
--- a/target/linux/mediatek/patches-5.4/0600-2-6-net-dsa-mt7530-Extend-device-data-ready-for-adding-a-new-hardware.patch
+++ /dev/null
@@ -1,441 +0,0 @@
-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 <landen.chao at mediatek.com>
-X-Patchwork-Id: 1206963
-X-Patchwork-Delegate: davem at davemloft.net
-Return-Path: <netdev-owner at vger.kernel.org>
-X-Original-To: patchwork-incoming-netdev at ozlabs.org
-Delivered-To: patchwork-incoming-netdev at 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 at vger.kernel.org;
- receiver=<UNKNOWN>)
-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 <patchwork-incoming-netdev at ozlabs.org>;
- Tue, 10 Dec 2019 19:15:25 +1100 (AEDT)
-Received: (majordomo at vger.kernel.org) by vger.kernel.org via listexpand
- id S1727003AbfLJIO4 (ORCPT
- <rfc822;patchwork-incoming-netdev at ozlabs.org>);
- 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
- <rfc822;netdev at vger.kernel.org>); 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 <landen.chao at mediatek.com>)
- (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 <landen.chao at mediatek.com>
-To: <andrew at lunn.ch>, <f.fainelli at gmail.com>,
- <vivien.didelot at savoirfairelinux.com>, <matthias.bgg at gmail.com>,
- <robh+dt at kernel.org>, <mark.rutland at arm.com>
-CC: <devicetree at vger.kernel.org>, <netdev at vger.kernel.org>,
- <linux-kernel at vger.kernel.org>,
- <linux-mediatek at lists.infradead.org>, <davem at davemloft.net>,
- <sean.wang at mediatek.com>, <opensource at vdorst.com>,
- <frank-w at public-files.de>, Landen Chao <landen.chao at mediatek.com>
-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 at mediatek.com>
-X-Mailer: git-send-email 2.18.0
-In-Reply-To: <cover.1575914275.git.landen.chao at mediatek.com>
-References: <cover.1575914275.git.landen.chao at mediatek.com>
-MIME-Version: 1.0
-X-MTK: N
-Sender: netdev-owner at vger.kernel.org
-Precedence: bulk
-List-ID: <netdev.vger.kernel.org>
-X-Mailing-List: netdev at 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 <landen.chao at mediatek.com>
-Signed-off-by: Sean Wang <sean.wang at mediatek.com>
----
- drivers/net/dsa/mt7530.c | 231 +++++++++++++++++++++++++++++----------
- drivers/net/dsa/mt7530.h |  29 ++++-
- 2 files changed, 203 insertions(+), 57 deletions(-)
-
---- a/drivers/net/dsa/mt7530.c
-+++ b/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");
---- a/drivers/net/dsa/mt7530.h
-+++ b/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
deleted file mode 100644
index b28f23f573..0000000000
--- a/target/linux/mediatek/patches-5.4/0600-3-6-dt-bindings-net-dsa-add-new-MT7531-binding-to-support-MT7531.patch
+++ /dev/null
@@ -1,179 +0,0 @@
-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 <landen.chao at mediatek.com>
-X-Patchwork-Id: 1206955
-X-Patchwork-Delegate: davem at davemloft.net
-Return-Path: <netdev-owner at vger.kernel.org>
-X-Original-To: patchwork-incoming-netdev at ozlabs.org
-Delivered-To: patchwork-incoming-netdev at 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 at vger.kernel.org;
- receiver=<UNKNOWN>)
-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 <patchwork-incoming-netdev at ozlabs.org>;
- Tue, 10 Dec 2019 19:15:01 +1100 (AEDT)
-Received: (majordomo at vger.kernel.org) by vger.kernel.org via listexpand
- id S1727133AbfLJIPA (ORCPT
- <rfc822;patchwork-incoming-netdev at ozlabs.org>);
- 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
- <rfc822;netdev at vger.kernel.org>); 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 <landen.chao at mediatek.com>)
- (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 <landen.chao at mediatek.com>
-To: <andrew at lunn.ch>, <f.fainelli at gmail.com>,
- <vivien.didelot at savoirfairelinux.com>, <matthias.bgg at gmail.com>,
- <robh+dt at kernel.org>, <mark.rutland at arm.com>
-CC: <devicetree at vger.kernel.org>, <netdev at vger.kernel.org>,
- <linux-kernel at vger.kernel.org>,
- <linux-mediatek at lists.infradead.org>, <davem at davemloft.net>,
- <sean.wang at mediatek.com>, <opensource at vdorst.com>,
- <frank-w at public-files.de>, Landen Chao <landen.chao at mediatek.com>
-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 at mediatek.com>
-X-Mailer: git-send-email 2.18.0
-In-Reply-To: <cover.1575914275.git.landen.chao at mediatek.com>
-References: <cover.1575914275.git.landen.chao at mediatek.com>
-MIME-Version: 1.0
-X-MTK: N
-Sender: netdev-owner at vger.kernel.org
-Precedence: bulk
-List-ID: <netdev.vger.kernel.org>
-X-Mailing-List: netdev at vger.kernel.org
-
-Add devicetree binding to support the compatible mt7531 switch as used
-in the MediaTek MT7531 switch.
-
-Signed-off-by: Sean Wang <sean.wang at mediatek.com>
-Signed-off-by: Landen Chao <landen.chao at mediatek.com>
----
- .../devicetree/bindings/net/dsa/mt7530.txt    | 77 ++++++++++++++++++-
- 1 file changed, 74 insertions(+), 3 deletions(-)
-
---- 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
- 
- - 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 t
- 		};
- 	};
- };
-+
-+Example 4:
-+
-+&eth {
-+	gmac0: mac at 0 {
-+		compatible = "mediatek,eth-mac";
-+		reg = <0>;
-+		phy-mode = "2500base-x";
-+
-+		fixed-link {
-+			speed = <1000>;
-+			full-duplex;
-+			pause;
-+		};
-+	};
-+
-+	&mdio0 {
-+		switch at 0 {
-+			compatible = "mediatek,mt7531";
-+			reg = <0>;
-+			reset-gpios = <&pio 54 0>;
-+
-+			ports {
-+				#address-cells = <1>;
-+				#size-cells = <0>;
-+				reg = <0>;
-+
-+				port at 0 {
-+					reg = <0>;
-+					label = "lan0";
-+				};
-+
-+				port at 1 {
-+					reg = <1>;
-+					label = "lan1";
-+				};
-+
-+				port at 2 {
-+					reg = <2>;
-+					label = "lan2";
-+				};
-+
-+				port at 3 {
-+					reg = <3>;
-+					label = "lan3";
-+				};
-+
-+				port at 4 {
-+					reg = <4>;
-+					label = "wan";
-+				};
-+
-+				port at 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
deleted file mode 100644
index 299ac24c79..0000000000
--- a/target/linux/mediatek/patches-5.4/0600-4-6-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch
+++ /dev/null
@@ -1,1096 +0,0 @@
-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 <landen.chao at mediatek.com>
-X-Patchwork-Id: 1206959
-X-Patchwork-Delegate: davem at davemloft.net
-Return-Path: <netdev-owner at vger.kernel.org>
-X-Original-To: patchwork-incoming-netdev at ozlabs.org
-Delivered-To: patchwork-incoming-netdev at 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 at vger.kernel.org;
- receiver=<UNKNOWN>)
-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 <patchwork-incoming-netdev at ozlabs.org>;
- Tue, 10 Dec 2019 19:15:15 +1100 (AEDT)
-Received: (majordomo at vger.kernel.org) by vger.kernel.org via listexpand
- id S1727198AbfLJIPC (ORCPT
- <rfc822;patchwork-incoming-netdev at ozlabs.org>);
- 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
- <rfc822;netdev at vger.kernel.org>); 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 <landen.chao at mediatek.com>)
- (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 <landen.chao at mediatek.com>
-To: <andrew at lunn.ch>, <f.fainelli at gmail.com>,
- <vivien.didelot at savoirfairelinux.com>, <matthias.bgg at gmail.com>,
- <robh+dt at kernel.org>, <mark.rutland at arm.com>
-CC: <devicetree at vger.kernel.org>, <netdev at vger.kernel.org>,
- <linux-kernel at vger.kernel.org>,
- <linux-mediatek at lists.infradead.org>, <davem at davemloft.net>,
- <sean.wang at mediatek.com>, <opensource at vdorst.com>,
- <frank-w at public-files.de>, Landen Chao <landen.chao at mediatek.com>
-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 at mediatek.com>
-X-Mailer: git-send-email 2.18.0
-In-Reply-To: <cover.1575914275.git.landen.chao at mediatek.com>
-References: <cover.1575914275.git.landen.chao at mediatek.com>
-MIME-Version: 1.0
-X-MTK: N
-Sender: netdev-owner at vger.kernel.org
-Precedence: bulk
-List-ID: <netdev.vger.kernel.org>
-X-Mailing-List: netdev at 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 <landen.chao at mediatek.com>
-Signed-off-by: Sean Wang <sean.wang at mediatek.com>
----
- drivers/net/dsa/Kconfig  |   6 +-
- drivers/net/dsa/mt7530.c | 643 ++++++++++++++++++++++++++++++++++++++-
- drivers/net/dsa/mt7530.h | 144 +++++++++
- 3 files changed, 784 insertions(+), 9 deletions(-)
-
---- 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 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"
---- a/drivers/net/dsa/mt7530.c
-+++ b/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);
---- a/drivers/net/dsa/mt7530.h
-+++ b/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
deleted file mode 100644
index 8919ad27e0..0000000000
--- a/target/linux/mediatek/patches-5.4/0600-6-6-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch
+++ /dev/null
@@ -1,138 +0,0 @@
-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 <landen.chao at mediatek.com>
-X-Patchwork-Id: 1206964
-X-Patchwork-Delegate: davem at davemloft.net
-Return-Path: <netdev-owner at vger.kernel.org>
-X-Original-To: patchwork-incoming-netdev at ozlabs.org
-Delivered-To: patchwork-incoming-netdev at 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 at vger.kernel.org;
- receiver=<UNKNOWN>)
-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 <patchwork-incoming-netdev at ozlabs.org>;
- Tue, 10 Dec 2019 19:15:29 +1100 (AEDT)
-Received: (majordomo at vger.kernel.org) by vger.kernel.org via listexpand
- id S1727295AbfLJIP0 (ORCPT
- <rfc822;patchwork-incoming-netdev at ozlabs.org>);
- 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
- <rfc822;netdev at vger.kernel.org>); 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 <landen.chao at mediatek.com>)
- (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 <landen.chao at mediatek.com>
-To: <andrew at lunn.ch>, <f.fainelli at gmail.com>,
- <vivien.didelot at savoirfairelinux.com>, <matthias.bgg at gmail.com>,
- <robh+dt at kernel.org>, <mark.rutland at arm.com>
-CC: <devicetree at vger.kernel.org>, <netdev at vger.kernel.org>,
- <linux-kernel at vger.kernel.org>,
- <linux-mediatek at lists.infradead.org>, <davem at davemloft.net>,
- <sean.wang at mediatek.com>, <opensource at vdorst.com>,
- <frank-w at public-files.de>, Landen Chao <landen.chao at mediatek.com>
-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 at mediatek.com>
-X-Mailer: git-send-email 2.18.0
-In-Reply-To: <cover.1575914275.git.landen.chao at mediatek.com>
-References: <cover.1575914275.git.landen.chao at mediatek.com>
-MIME-Version: 1.0
-X-MTK: N
-Sender: netdev-owner at vger.kernel.org
-Precedence: bulk
-List-ID: <netdev.vger.kernel.org>
-X-Mailing-List: netdev at vger.kernel.org
-
-Add mt7531 dsa to bananapi-bpi-r64 board for 5 giga Ethernet ports support.
-
-Signed-off-by: Landen Chao <landen.chao at mediatek.com>
----
- .../dts/mediatek/mt7622-bananapi-bpi-r64.dts  | 50 +++++++++++++++++++
- 1 file changed, 50 insertions(+)
-
---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
-+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
-@@ -150,6 +150,56 @@
- 	mdio: mdio-bus {
- 		#address-cells = <1>;
- 		#size-cells = <0>;
-+
-+		switch at 0 {
-+			compatible = "mediatek,mt7531";
-+			reg = <0>;
-+			reset-gpios = <&pio 54 0>;
-+
-+			ports {
-+				#address-cells = <1>;
-+				#size-cells = <0>;
-+
-+				port at 0 {
-+					reg = <0>;
-+					label = "wan";
-+				};
-+
-+				port at 1 {
-+					reg = <1>;
-+					label = "lan0";
-+				};
-+
-+				port at 2 {
-+					reg = <2>;
-+					label = "lan1";
-+				};
-+
-+				port at 3 {
-+					reg = <3>;
-+					label = "lan2";
-+				};
-+
-+				port at 4 {
-+					reg = <4>;
-+					label = "lan3";
-+				};
-+
-+				port at 6 {
-+					reg = <6>;
-+					label = "cpu";
-+					ethernet = <&gmac0>;
-+					phy-mode = "2500base-x";
-+
-+					fixed-link {
-+						speed = <2500>;
-+						full-duplex;
-+						pause;
-+					};
-+				};
-+			};
-+		};
-+
- 	};
- };
- 
diff --git a/target/linux/mediatek/patches-5.4/0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch b/target/linux/mediatek/patches-5.4/0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch
new file mode 100644
index 0000000000..34a15334d6
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch
@@ -0,0 +1,246 @@
+From: Russell King <rmk+kernel at armlinux.org.uk>
+Date: Wed, 26 Feb 2020 10:23:41 +0000
+Subject: [PATCH] net: phylink: propagate resolved link config via
+ mac_link_up()
+
+Propagate the resolved link parameters via the mac_link_up() call for
+MACs that do not automatically track their PCS state. We propagate the
+link parameters via function arguments so that inappropriate members
+of struct phylink_link_state can't be accessed, and creating a new
+structure just for this adds needless complexity to the API.
+
+Tested-by: Andre Przywara <andre.przywara at arm.com>
+Tested-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
+Tested-by: Vladimir Oltean <vladimir.oltean at nxp.com>
+Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+
+--- a/Documentation/networking/sfp-phylink.rst
++++ b/Documentation/networking/sfp-phylink.rst
+@@ -74,10 +74,13 @@ phylib to the sfp/phylink support.  Plea
+ this documentation.
+ 
+ 1. Optionally split the network driver's phylib update function into
+-   three parts dealing with link-down, link-up and reconfiguring the
+-   MAC settings. This can be done as a separate preparation commit.
++   two parts dealing with link-down and link-up. This can be done as
++   a separate preparation commit.
+ 
+-   An example of this preparation can be found in git commit fc548b991fb0.
++   An older example of this preparation can be found in git commit
++   fc548b991fb0, although this was splitting into three parts; the
++   link-up part now includes configuring the MAC for the link settings.
++   Please see :c:func:`mac_link_up` for more information on this.
+ 
+ 2. Replace::
+ 
+@@ -207,6 +210,14 @@ this documentation.
+    using. This is particularly important for in-band negotiation
+    methods such as 1000base-X and SGMII.
+ 
++   The :c:func:`mac_link_up` method is used to inform the MAC that the
++   link has come up. The call includes the negotiation mode and interface
++   for reference only. The finalised link parameters are also supplied
++   (speed, duplex and flow control/pause enablement settings) which
++   should be used to configure the MAC when the MAC and PCS are not
++   tightly integrated, or when the settings are not coming from in-band
++   negotiation.
++
+    The :c:func:`mac_config` method is used to update the MAC with the
+    requested state, and must avoid unnecessarily taking the link down
+    when making changes to the MAC configuration.  This means the
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -3653,9 +3653,11 @@ static void mvneta_mac_link_down(struct
+ 	mvneta_set_eee(pp, false);
+ }
+ 
+-static void mvneta_mac_link_up(struct phylink_config *config, unsigned int mode,
+-			       phy_interface_t interface,
+-			       struct phy_device *phy)
++static void mvneta_mac_link_up(struct phylink_config *config,
++			       struct phy_device *phy,
++			       unsigned int mode, phy_interface_t interface,
++			       int speed, int duplex,
++			       bool tx_pause, bool rx_pause)
+ {
+ 	struct net_device *ndev = to_net_dev(config->dev);
+ 	struct mvneta_port *pp = netdev_priv(ndev);
+--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+@@ -58,8 +58,11 @@ static struct {
+  */
+ static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode,
+ 			     const struct phylink_link_state *state);
+-static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode,
+-			      phy_interface_t interface, struct phy_device *phy);
++static void mvpp2_mac_link_up(struct phylink_config *config,
++			      struct phy_device *phy,
++			      unsigned int mode, phy_interface_t interface,
++			      int speed, int duplex,
++			      bool tx_pause, bool rx_pause);
+ 
+ /* Queue modes */
+ #define MVPP2_QDIST_SINGLE_MODE	0
+@@ -3467,8 +3470,9 @@ static void mvpp2_start_dev(struct mvpp2
+ 			.interface = port->phy_interface,
+ 		};
+ 		mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state);
+-		mvpp2_mac_link_up(&port->phylink_config, MLO_AN_INBAND,
+-				  port->phy_interface, NULL);
++		mvpp2_mac_link_up(&port->phylink_config, NULL,
++				  MLO_AN_INBAND, port->phy_interface,
++				  SPEED_UNKNOWN, DUPLEX_UNKNOWN, false, false);
+ 	}
+ 
+ 	netif_tx_start_all_queues(port->dev);
+@@ -5124,8 +5128,11 @@ static void mvpp2_mac_config(struct phyl
+ 	mvpp2_port_enable(port);
+ }
+ 
+-static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode,
+-			      phy_interface_t interface, struct phy_device *phy)
++static void mvpp2_mac_link_up(struct phylink_config *config,
++			      struct phy_device *phy,
++			      unsigned int mode, phy_interface_t interface,
++			      int speed, int duplex,
++			      bool tx_pause, bool rx_pause)
+ {
+ 	struct net_device *dev = to_net_dev(config->dev);
+ 	struct mvpp2_port *port = netdev_priv(dev);
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -445,9 +445,10 @@ static void mtk_mac_link_down(struct phy
+ 	mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+ }
+ 
+-static void mtk_mac_link_up(struct phylink_config *config, unsigned int mode,
+-			    phy_interface_t interface,
+-			    struct phy_device *phy)
++static void mtk_mac_link_up(struct phylink_config *config,
++			    struct phy_device *phy,
++			    unsigned int mode, phy_interface_t interface,
++			    int speed, int duplex, bool tx_pause, bool rx_pause)
+ {
+ 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
+ 					   phylink_config);
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -951,8 +951,10 @@ static void stmmac_mac_link_down(struct
+ }
+ 
+ static void stmmac_mac_link_up(struct phylink_config *config,
++			       struct phy_device *phy,
+ 			       unsigned int mode, phy_interface_t interface,
+-			       struct phy_device *phy)
++			       int speed, int duplex,
++			       bool tx_pause, bool rx_pause)
+ {
+ 	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
+ 
+--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+@@ -1488,9 +1488,10 @@ static void axienet_mac_link_down(struct
+ }
+ 
+ static void axienet_mac_link_up(struct phylink_config *config,
+-				unsigned int mode,
+-				phy_interface_t interface,
+-				struct phy_device *phy)
++				struct phy_device *phy,
++				unsigned int mode, phy_interface_t interface,
++				int speed, int duplex,
++				bool tx_pause, bool rx_pause)
+ {
+ 	/* nothing meaningful to do */
+ }
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -447,8 +447,11 @@ static void phylink_mac_link_up(struct p
+ 	struct net_device *ndev = pl->netdev;
+ 
+ 	pl->cur_interface = link_state.interface;
+-	pl->ops->mac_link_up(pl->config, pl->cur_link_an_mode,
+-			     pl->cur_interface, pl->phydev);
++	pl->ops->mac_link_up(pl->config, pl->phydev,
++			     pl->cur_link_an_mode, pl->cur_interface,
++			     link_state.speed, link_state.duplex,
++			     !!(link_state.pause & MLO_PAUSE_TX),
++			     !!(link_state.pause & MLO_PAUSE_RX));
+ 
+ 	if (ndev)
+ 		netif_carrier_on(ndev);
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -91,9 +91,10 @@ struct phylink_mac_ops {
+ 	void (*mac_an_restart)(struct phylink_config *config);
+ 	void (*mac_link_down)(struct phylink_config *config, unsigned int mode,
+ 			      phy_interface_t interface);
+-	void (*mac_link_up)(struct phylink_config *config, unsigned int mode,
+-			    phy_interface_t interface,
+-			    struct phy_device *phy);
++	void (*mac_link_up)(struct phylink_config *config,
++			    struct phy_device *phy, unsigned int mode,
++			    phy_interface_t interface, int speed, int duplex,
++			    bool tx_pause, bool rx_pause);
+ };
+ 
+ #if 0 /* For kernel-doc purposes only. */
+@@ -217,19 +218,34 @@ void mac_link_down(struct phylink_config
+ /**
+  * mac_link_up() - allow the link to come up
+  * @config: a pointer to a &struct phylink_config.
++ * @phy: any attached phy
+  * @mode: link autonegotiation mode
+  * @interface: link &typedef phy_interface_t mode
+- * @phy: any attached phy
++ * @speed: link speed
++ * @duplex: link duplex
++ * @tx_pause: link transmit pause enablement status
++ * @rx_pause: link receive pause enablement status
+  *
+- * If @mode is not an in-band negotiation mode (as defined by
+- * phylink_autoneg_inband()), allow the link to come up. If @phy
+- * is non-%NULL, configure Energy Efficient Ethernet by calling
++ * Configure the MAC for an established link.
++ *
++ * @speed, @duplex, @tx_pause and @rx_pause indicate the finalised link
++ * settings, and should be used to configure the MAC block appropriately
++ * where these settings are not automatically conveyed from the PCS block,
++ * or if in-band negotiation (as defined by phylink_autoneg_inband(@mode))
++ * is disabled.
++ *
++ * Note that when 802.3z in-band negotiation is in use, it is possible
++ * that the user wishes to override the pause settings, and this should
++ * be allowed when considering the implementation of this method.
++ *
++ * If in-band negotiation mode is disabled, allow the link to come up. If
++ * @phy is non-%NULL, configure Energy Efficient Ethernet by calling
+  * phy_init_eee() and perform appropriate MAC configuration for EEE.
+  * Interface type selection must be done in mac_config().
+  */
+-void mac_link_up(struct phylink_config *config, unsigned int mode,
+-		 phy_interface_t interface,
+-		 struct phy_device *phy);
++void mac_link_up(struct phylink_config *config, struct phy_device *phy,
++		 unsigned int mode, phy_interface_t interface,
++		 int speed, int duplex, bool tx_pause, bool rx_pause);
+ #endif
+ 
+ struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *,
+--- a/net/dsa/port.c
++++ b/net/dsa/port.c
+@@ -529,9 +529,11 @@ void dsa_port_phylink_mac_link_down(stru
+ EXPORT_SYMBOL_GPL(dsa_port_phylink_mac_link_down);
+ 
+ void dsa_port_phylink_mac_link_up(struct phylink_config *config,
++				  struct phy_device *phydev,
+ 				  unsigned int mode,
+ 				  phy_interface_t interface,
+-				  struct phy_device *phydev)
++				  int speed, int duplex,
++				  bool tx_pause, bool rx_pause)
+ {
+ 	struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
+ 	struct dsa_switch *ds = dp->ds;
diff --git a/target/linux/mediatek/patches-5.4/0601-net-dsa-propagate-resolved-link-config-via-mac_link_.patch b/target/linux/mediatek/patches-5.4/0601-net-dsa-propagate-resolved-link-config-via-mac_link_.patch
new file mode 100644
index 0000000000..f74bc30d9e
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0601-net-dsa-propagate-resolved-link-config-via-mac_link_.patch
@@ -0,0 +1,143 @@
+From: Russell King <rmk+kernel at armlinux.org.uk>
+Date: Wed, 26 Feb 2020 10:23:46 +0000
+Subject: [PATCH] net: dsa: propagate resolved link config via mac_link_up()
+
+Propagate the resolved link configuration down via DSA's
+phylink_mac_link_up() operation to allow split PCS/MAC to work.
+
+Tested-by: Vladimir Oltean <vladimir.oltean at nxp.com>
+Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -1276,7 +1276,9 @@ EXPORT_SYMBOL(b53_phylink_mac_link_down)
+ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
+ 			     unsigned int mode,
+ 			     phy_interface_t interface,
+-			     struct phy_device *phydev)
++			     struct phy_device *phydev,
++			     int speed, int duplex,
++			     bool tx_pause, bool rx_pause)
+ {
+ 	struct b53_device *dev = ds->priv;
+ 
+--- a/drivers/net/dsa/b53/b53_priv.h
++++ b/drivers/net/dsa/b53/b53_priv.h
+@@ -337,7 +337,9 @@ void b53_phylink_mac_link_down(struct ds
+ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
+ 			     unsigned int mode,
+ 			     phy_interface_t interface,
+-			     struct phy_device *phydev);
++			     struct phy_device *phydev,
++			     int speed, int duplex,
++			     bool tx_pause, bool rx_pause);
+ int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering);
+ int b53_vlan_prepare(struct dsa_switch *ds, int port,
+ 		     const struct switchdev_obj_port_vlan *vlan);
+--- a/drivers/net/dsa/bcm_sf2.c
++++ b/drivers/net/dsa/bcm_sf2.c
+@@ -635,7 +635,9 @@ static void bcm_sf2_sw_mac_link_down(str
+ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port,
+ 				   unsigned int mode,
+ 				   phy_interface_t interface,
+-				   struct phy_device *phydev)
++				   struct phy_device *phydev,
++				   int speed, int duplex,
++				   bool tx_pause, bool rx_pause)
+ {
+ 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
+ 	struct ethtool_eee *p = &priv->dev->ports[port].eee;
+--- a/drivers/net/dsa/lantiq_gswip.c
++++ b/drivers/net/dsa/lantiq_gswip.c
+@@ -1517,7 +1517,9 @@ static void gswip_phylink_mac_link_down(
+ static void gswip_phylink_mac_link_up(struct dsa_switch *ds, int port,
+ 				      unsigned int mode,
+ 				      phy_interface_t interface,
+-				      struct phy_device *phydev)
++				      struct phy_device *phydev,
++				      int speed, int duplex,
++				      bool tx_pause, bool rx_pause)
+ {
+ 	struct gswip_priv *priv = ds->priv;
+ 
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1452,7 +1452,9 @@ static void mt7530_phylink_mac_link_down
+ static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port,
+ 				       unsigned int mode,
+ 				       phy_interface_t interface,
+-				       struct phy_device *phydev)
++				       struct phy_device *phydev,
++				       int speed, int duplex,
++				       bool tx_pause, bool rx_pause)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
+ 
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -652,7 +652,9 @@ static void mv88e6xxx_mac_link_down(stru
+ 
+ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
+ 				  unsigned int mode, phy_interface_t interface,
+-				  struct phy_device *phydev)
++				  struct phy_device *phydev,
++				  int speed, int duplex,
++				  bool tx_pause, bool rx_pause)
+ {
+ 	if (mode == MLO_AN_FIXED)
+ 		mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_UP);
+--- a/drivers/net/dsa/sja1105/sja1105_main.c
++++ b/drivers/net/dsa/sja1105/sja1105_main.c
+@@ -830,7 +830,9 @@ static void sja1105_mac_link_down(struct
+ static void sja1105_mac_link_up(struct dsa_switch *ds, int port,
+ 				unsigned int mode,
+ 				phy_interface_t interface,
+-				struct phy_device *phydev)
++				struct phy_device *phydev,
++				int speed, int duplex,
++				bool tx_pause, bool rx_pause)
+ {
+ 	sja1105_inhibit_tx(ds->priv, BIT(port), false);
+ }
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -401,7 +401,9 @@ struct dsa_switch_ops {
+ 	void	(*phylink_mac_link_up)(struct dsa_switch *ds, int port,
+ 				       unsigned int mode,
+ 				       phy_interface_t interface,
+-				       struct phy_device *phydev);
++				       struct phy_device *phydev,
++				       int speed, int duplex,
++				       bool tx_pause, bool rx_pause);
+ 	void	(*phylink_fixed_state)(struct dsa_switch *ds, int port,
+ 				       struct phylink_link_state *state);
+ 	/*
+--- a/net/dsa/port.c
++++ b/net/dsa/port.c
+@@ -544,7 +544,8 @@ void dsa_port_phylink_mac_link_up(struct
+ 		return;
+ 	}
+ 
+-	ds->ops->phylink_mac_link_up(ds, dp->index, mode, interface, phydev);
++	ds->ops->phylink_mac_link_up(ds, dp->index, mode, interface, phydev,
++				     speed, duplex, tx_pause, rx_pause);
+ }
+ EXPORT_SYMBOL_GPL(dsa_port_phylink_mac_link_up);
+ 
+--- a/net/dsa/dsa_priv.h
++++ b/net/dsa/dsa_priv.h
+@@ -180,9 +180,11 @@ void dsa_port_phylink_mac_link_down(stru
+ 				    unsigned int mode,
+ 				    phy_interface_t interface);
+ void dsa_port_phylink_mac_link_up(struct phylink_config *config,
++				  struct phy_device *phydev,
+ 				  unsigned int mode,
+ 				  phy_interface_t interface,
+-				  struct phy_device *phydev);
++				  int speed, int duplex,
++				  bool tx_pause, bool rx_pause);
+ extern const struct phylink_mac_ops dsa_port_phylink_mac_ops;
+ 
+ /* slave.c */
diff --git a/target/linux/mediatek/patches-5.4/0602-net-dsa-mt7530-use-resolved-link-config-in-mac_link_.patch b/target/linux/mediatek/patches-5.4/0602-net-dsa-mt7530-use-resolved-link-config-in-mac_link_.patch
new file mode 100644
index 0000000000..30ce641486
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0602-net-dsa-mt7530-use-resolved-link-config-in-mac_link_.patch
@@ -0,0 +1,145 @@
+From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= <opensource at vdorst.com>
+Date: Fri, 27 Mar 2020 15:44:12 +0100
+Subject: [PATCH] net: dsa: mt7530: use resolved link config in mac_link_up()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Convert the mt7530 switch driver to use the finalised link
+parameters in mac_link_up() rather than the parameters in mac_config().
+
+Signed-off-by: René van Dorst <opensource at vdorst.com>
+Tested-by: Sean Wang <sean.wang at mediatek.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -490,17 +490,6 @@ mt7530_mib_reset(struct dsa_switch *ds)
+ 	mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE);
+ }
+ 
+-static void
+-mt7530_port_set_status(struct mt7530_priv *priv, int port, int enable)
+-{
+-	u32 mask = PMCR_TX_EN | PMCR_RX_EN | PMCR_FORCE_LNK;
+-
+-	if (enable)
+-		mt7530_set(priv, MT7530_PMCR_P(port), mask);
+-	else
+-		mt7530_clear(priv, MT7530_PMCR_P(port), mask);
+-}
+-
+ static int mt7530_phy_read(struct dsa_switch *ds, int port, int regnum)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
+@@ -674,7 +663,7 @@ mt7530_port_enable(struct dsa_switch *ds
+ 	priv->ports[port].enable = true;
+ 	mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
+ 		   priv->ports[port].pm);
+-	mt7530_port_set_status(priv, port, 0);
++	mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+ 
+ 	mutex_unlock(&priv->reg_mutex);
+ 
+@@ -697,7 +686,7 @@ mt7530_port_disable(struct dsa_switch *d
+ 	priv->ports[port].enable = false;
+ 	mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
+ 		   PCR_MATRIX_CLR);
+-	mt7530_port_set_status(priv, port, 0);
++	mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+ 
+ 	mutex_unlock(&priv->reg_mutex);
+ }
+@@ -1407,8 +1396,7 @@ static void mt7530_phylink_mac_config(st
+ 
+ 	mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port));
+ 	mcr_new = mcr_cur;
+-	mcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 |
+-		     PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN);
++	mcr_new &= ~PMCR_LINK_SETTINGS_MASK;
+ 	mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN |
+ 		   PMCR_BACKPR_EN | PMCR_FORCE_MODE;
+ 
+@@ -1416,26 +1404,6 @@ static void mt7530_phylink_mac_config(st
+ 	if (port == 5 && dsa_is_user_port(ds, 5))
+ 		mcr_new |= PMCR_EXT_PHY;
+ 
+-	switch (state->speed) {
+-	case SPEED_1000:
+-		mcr_new |= PMCR_FORCE_SPEED_1000;
+-		if (priv->eee_enable & BIT(port))
+-			mcr_new |= PMCR_FORCE_EEE1G;
+-		break;
+-	case SPEED_100:
+-		mcr_new |= PMCR_FORCE_SPEED_100;
+-		if (priv->eee_enable & BIT(port))
+-			mcr_new |= PMCR_FORCE_EEE100;
+-		break;
+-	}
+-	if (state->duplex == DUPLEX_FULL) {
+-		mcr_new |= PMCR_FORCE_FDX;
+-		if (state->pause & MLO_PAUSE_TX)
+-			mcr_new |= PMCR_TX_FC_EN;
+-		if (state->pause & MLO_PAUSE_RX)
+-			mcr_new |= PMCR_RX_FC_EN;
+-	}
+-
+ 	if (mcr_new != mcr_cur)
+ 		mt7530_write(priv, MT7530_PMCR_P(port), mcr_new);
+ }
+@@ -1446,7 +1414,7 @@ static void mt7530_phylink_mac_link_down
+ {
+ 	struct mt7530_priv *priv = ds->priv;
+ 
+-	mt7530_port_set_status(priv, port, 0);
++	mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+ }
+ 
+ static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port,
+@@ -1457,8 +1425,31 @@ static void mt7530_phylink_mac_link_up(s
+ 				       bool tx_pause, bool rx_pause)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
++	u32 mcr;
+ 
+-	mt7530_port_set_status(priv, port, 1);
++	mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK;
++
++	switch (speed) {
++	case SPEED_1000:
++		mcr |= PMCR_FORCE_SPEED_1000;
++		if (priv->eee_enable & BIT(port))
++			mcr_new |= PMCR_FORCE_EEE1G;
++		break;
++	case SPEED_100:
++		mcr |= PMCR_FORCE_SPEED_100;
++		if (priv->eee_enable & BIT(port))
++			mcr_new |= PMCR_FORCE_EEE100;
++		break;
++	}
++	if (duplex == DUPLEX_FULL) {
++		mcr |= PMCR_FORCE_FDX;
++		if (tx_pause)
++			mcr |= PMCR_TX_FC_EN;
++		if (rx_pause)
++			mcr |= PMCR_RX_FC_EN;
++	}
++
++	mt7530_set(priv, MT7530_PMCR_P(port), mcr);
+ }
+ 
+ static void mt7530_phylink_validate(struct dsa_switch *ds, int port,
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -222,6 +222,10 @@ enum mt7530_vlan_port_attr {
+ #define  PMCR_FORCE_LNK			BIT(0)
+ #define  PMCR_SPEED_MASK		(PMCR_FORCE_SPEED_100 | \
+ 					 PMCR_FORCE_SPEED_1000)
++#define  PMCR_LINK_SETTINGS_MASK	(PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \
++					 PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \
++					 PMCR_TX_FC_EN | PMCR_RX_FC_EN | \
++					 PMCR_FORCE_FDX | PMCR_FORCE_LNK)
+ 
+ #define MT7530_PMSR_P(x)		(0x3008 + (x) * 0x100)
+ #define  PMSR_EEE1G			BIT(7)
diff --git a/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch b/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch
new file mode 100644
index 0000000000..5ae3376290
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch
@@ -0,0 +1,458 @@
+From: Landen Chao <landen.chao at mediatek.com>
+Date: Fri, 4 Sep 2020 22:21:57 +0800
+Subject: [PATCH] net: dsa: mt7530: Extend device data ready for adding a
+ new hardware
+
+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, and keep the
+same setup logic of existing hardware.
+
+Signed-off-by: Landen Chao <landen.chao at mediatek.com>
+Signed-off-by: Sean Wang <sean.wang at mediatek.com>
+---
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -372,8 +372,9 @@ mt7530_fdb_write(struct mt7530_priv *pri
+ 		mt7530_write(priv, MT7530_ATA1 + (i * 4), reg[i]);
+ }
+ 
++/* Setup TX circuit including relevant PAD and driving */
+ static int
+-mt7530_pad_clk_setup(struct dsa_switch *ds, int mode)
++mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
+ 	u32 ncpo1, ssc_delta, trgint, i, xtal;
+@@ -387,7 +388,7 @@ mt7530_pad_clk_setup(struct dsa_switch *
+ 		return -EINVAL;
+ 	}
+ 
+-	switch (mode) {
++	switch (interface) {
+ 	case PHY_INTERFACE_MODE_RGMII:
+ 		trgint = 0;
+ 		/* PLL frequency: 125MHz */
+@@ -409,7 +410,8 @@ mt7530_pad_clk_setup(struct dsa_switch *
+ 		}
+ 		break;
+ 	default:
+-		dev_err(priv->dev, "xMII mode %d not supported\n", mode);
++		dev_err(priv->dev, "xMII interface %d not supported\n",
++			interface);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -1344,12 +1346,11 @@ mt7530_setup(struct dsa_switch *ds)
+ 	return 0;
+ }
+ 
+-static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port,
+-				      unsigned int mode,
+-				      const struct phylink_link_state *state)
++static bool
++mt7530_phy_mode_supported(struct dsa_switch *ds, int port,
++			  const struct phylink_link_state *state)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
+-	u32 mcr_cur, mcr_new;
+ 
+ 	switch (port) {
+ 	case 0: /* Internal phy */
+@@ -1358,33 +1359,114 @@ static void mt7530_phylink_mac_config(st
+ 	case 3:
+ 	case 4:
+ 		if (state->interface != PHY_INTERFACE_MODE_GMII)
+-			return;
++			goto unsupported;
+ 		break;
+ 	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;
++			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_mode_supported(struct dsa_switch *ds, int port,
++			  const struct phylink_link_state *state)
++{
++	struct mt7530_priv *priv = ds->priv;
++
++	return priv->info->phy_mode_supported(ds, port, state);
++}
++
++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->interface);
++}
++
++static int
++mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
++		  phy_interface_t interface)
++{
++	struct mt7530_priv *priv = ds->priv;
++
++	/* Only need to setup port5. */
++	if (port != 5)
++		return 0;
++
++	mt7530_setup_port5(priv->ds, interface);
++
++	return 0;
++}
++
++static int
++mt753x_mac_config(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_port_config(ds, port, mode, state->interface);
++}
++
++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_mode_supported(ds, port, state))
++		goto unsupported;
++
++	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 (priv->p5_interface == state->interface)
++			break;
++
++		if (mt753x_mac_config(ds, port, mode, state) < 0)
++			goto unsupported;
+ 
+-		mt7530_setup_port5(ds, state->interface);
+ 		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;
++		mt753x_pad_setup(ds, state);
+ 
+-		/* Setup TX circuit incluing relevant PAD and driving */
+-		mt7530_pad_clk_setup(ds, state->interface);
++		if (mt753x_mac_config(ds, port, mode, state) < 0)
++			goto unsupported;
+ 
+ 		priv->p6_interface = state->interface;
+ 		break;
+ 	default:
+-		dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
++unsupported:
++		dev_err(ds->dev, "%s: unsupported %s port: %i\n",
++			__func__, phy_modes(state->interface), port);
+ 		return;
+ 	}
+ 
+@@ -1452,61 +1534,44 @@ static void mt7530_phylink_mac_link_up(s
+ 	mt7530_set(priv, MT7530_PMCR_P(port), mcr);
+ }
+ 
+-static void mt7530_phylink_validate(struct dsa_switch *ds, int port,
+-				    unsigned long *supported,
+-				    struct phylink_link_state *state)
++static void
++mt7530_mac_port_validate(struct dsa_switch *ds, int port,
++			 unsigned long *supported)
+ {
++	if (port == 5)
++		phylink_set(supported, 1000baseX_Full);
++}
++
++static void
++mt753x_phylink_validate(struct dsa_switch *ds, int port,
++			unsigned long *supported,
++			struct phylink_link_state *state)
++{
++	struct mt7530_priv *priv = ds->priv;
+ 	__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_mode_supported(ds, port, state)) {
+ 		linkmode_zero(supported);
+ 		return;
+ 	}
+ 
+ 	phylink_set_port_modes(mask);
+-	phylink_set(mask, Autoneg);
+ 
+-	if (state->interface == PHY_INTERFACE_MODE_TRGMII) {
+-		phylink_set(mask, 1000baseT_Full);
+-	} else {
++	if (state->interface != PHY_INTERFACE_MODE_TRGMII) {
+ 		phylink_set(mask, 10baseT_Half);
+ 		phylink_set(mask, 10baseT_Full);
+ 		phylink_set(mask, 100baseT_Half);
+ 		phylink_set(mask, 100baseT_Full);
+-
+-		if (state->interface != PHY_INTERFACE_MODE_MII) {
+-			phylink_set(mask, 1000baseT_Half);
+-			phylink_set(mask, 1000baseT_Full);
+-			if (port == 5)
+-				phylink_set(mask, 1000baseX_Full);
+-		}
++		phylink_set(mask, Autoneg);
+ 	}
+ 
++	/* This switch only supports 1G full-duplex. */
++	if (state->interface != PHY_INTERFACE_MODE_MII)
++		phylink_set(mask, 1000baseT_Full);
++
++	priv->info->mac_port_validate(ds, port, mask);
++
+ 	phylink_set(mask, Pause);
+ 	phylink_set(mask, Asym_Pause);
+ 
+@@ -1602,12 +1667,45 @@ static int mt7530_set_mac_eee(struct dsa
+ 	return 0;
+ }
+ 
++static int
++mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port,
++			      struct phylink_link_state *state)
++{
++	struct mt7530_priv *priv = ds->priv;
++
++	return priv->info->mac_port_get_state(ds, port, state);
++}
++
++static int
++mt753x_setup(struct dsa_switch *ds)
++{
++	struct mt7530_priv *priv = ds->priv;
++
++	return priv->info->sw_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,
+@@ -1624,18 +1722,43 @@ 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_mac_link_state = mt7530_phylink_mac_link_state,
+-	.phylink_mac_config	= mt7530_phylink_mac_config,
++	.phylink_validate	= mt753x_phylink_validate,
++	.phylink_mac_link_state	= mt753x_phylink_mac_link_state,
++	.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 mt753x_info mt753x_table[] = {
++	[ID_MT7621] = {
++		.id = ID_MT7621,
++		.sw_setup = mt7530_setup,
++		.phy_read = mt7530_phy_read,
++		.phy_write = mt7530_phy_write,
++		.pad_setup = mt7530_pad_clk_setup,
++		.phy_mode_supported = mt7530_phy_mode_supported,
++		.mac_port_validate = mt7530_mac_port_validate,
++		.mac_port_get_state = mt7530_phylink_mac_link_state,
++		.mac_port_config = mt7530_mac_config,
++	},
++	[ID_MT7530] = {
++		.id = ID_MT7530,
++		.sw_setup = mt7530_setup,
++		.phy_read = mt7530_phy_read,
++		.phy_write = mt7530_phy_write,
++		.pad_setup = mt7530_pad_clk_setup,
++		.phy_mode_supported = mt7530_phy_mode_supported,
++		.mac_port_validate = mt7530_mac_port_validate,
++		.mac_port_get_state = mt7530_phylink_mac_link_state,
++		.mac_port_config = mt7530_mac_config,
++	},
++};
++
+ static const struct of_device_id mt7530_of_match[] = {
+-	{ .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, },
+-	{ .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, },
++	{ .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
++	{ .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
+ 	{ /* sentinel */ },
+ };
+ MODULE_DEVICE_TABLE(of, mt7530_of_match);
+@@ -1673,8 +1796,21 @@ 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 operations are filled
++	 * properly.
++	 */
++	if (!priv->info->sw_setup || !priv->info->pad_setup ||
++	    !priv->info->phy_read || !priv->info->phy_write ||
++	    !priv->info->phy_mode_supported ||
++	    !priv->info->mac_port_validate ||
++	    !priv->info->mac_port_get_state || !priv->info->mac_port_config)
++		return -EINVAL;
++
++	priv->id = priv->info->id;
+ 
+ 	if (priv->id == ID_MT7530) {
+ 		priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
+--- a/drivers/net/dsa/mt7530.h
++++ b/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,
+ };
+@@ -451,6 +451,40 @@ 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
++ * @sw_setup:		Holding the handler to a device initialization
++ * @phy_read:		Holding the way reading PHY port
++ * @phy_write:		Holding the way writing PHY port
++ * @pad_setup:		Holding the way setting up the bus pad for a certain
++ *			MAC port
++ * @phy_mode_supported:	Check if the PHY type is being supported on a certain
++ *			port
++ * @mac_port_validate:	Holding the way to set addition validate type for a
++ *			certan MAC port
++ * @mac_port_get_state: Holding the way getting the MAC/PCS state for a certain
++ *			MAC port
++ * @mac_port_config:	Holding the way setting up the PHY attribute to a
++ *			certain MAC port
++ */
++struct mt753x_info {
++	enum mt753x_id id;
++
++	int (*sw_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);
++	int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface);
++	bool (*phy_mode_supported)(struct dsa_switch *ds, int port,
++				   const struct phylink_link_state *state);
++	void (*mac_port_validate)(struct dsa_switch *ds, int port,
++				  unsigned long *supported);
++	int (*mac_port_get_state)(struct dsa_switch *ds, int port,
++				  struct phylink_link_state *state);
++	int (*mac_port_config)(struct dsa_switch *ds, int port,
++			       unsigned int mode,
++			       phy_interface_t interface);
++};
++
+ /* struct mt7530_priv -	This is the main data structure for holding the state
+  *			of the driver
+  * @dev:		The device pointer
+@@ -476,6 +510,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/0604-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch b/target/linux/mediatek/patches-5.4/0604-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch
new file mode 100644
index 0000000000..1e6126eb7f
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0604-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch
@@ -0,0 +1,1510 @@
+From: Landen Chao <landen.chao at mediatek.com>
+Date: Fri, 4 Sep 2020 22:21:59 +0800
+Subject: [PATCH] net: dsa: mt7530: Add the support of MT7531 switch
+
+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 SGMII interface. Cpu port 5 supports either RGMII
+or SGMII in different HW sku, but cannot be muxed to PHY of port 0/4 like
+mt7530. Due to SGMII interface support, pll, and pad setting are different
+from MT7530. This patch adds different initial setting, and SGMII phylink
+handlers of MT7531.
+
+MT7531 SGMII interface can be configured in following mode:
+- 'SGMII AN mode' with in-band negotiation capability
+    which is compatible with PHY_INTERFACE_MODE_SGMII.
+- 'SGMII force mode' without in-band negotiation
+    which is compatible with 10B/8B encoding of
+    PHY_INTERFACE_MODE_1000BASEX with fixed full-duplex and fixed pause.
+- 2.5 times faster clocked 'SGMII force mode' without in-band negotiation
+    which is compatible with 10B/8B encoding of
+    PHY_INTERFACE_MODE_2500BASEX with fixed full-duplex and fixed pause.
+
+Signed-off-by: Landen Chao <landen.chao at mediatek.com>
+Signed-off-by: Sean Wang <sean.wang at mediatek.com>
+---
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/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;
+@@ -483,6 +489,108 @@ mt7530_pad_clk_setup(struct dsa_switch *
+ 	return 0;
+ }
+ 
++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 int
++mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
++{
++	struct mt7530_priv *priv = ds->priv;
++	u32 val;
++	u32 top_sig;
++	u32 hwstrap;
++	u32 xtal;
++
++	if (mt7531_dual_sgmii_supported(priv))
++		return 0;
++
++	val = mt7530_read(priv, MT7531_CREV);
++	top_sig = mt7530_read(priv, MT7531_TOP_SIG_SR);
++	hwstrap = mt7530_read(priv, MT7531_HWTRAP);
++	if ((val & CHIP_REV_M) > 0)
++		xtal = (top_sig & PAD_MCM_SMI_EN) ? HWTRAP_XTAL_FSEL_40MHZ :
++						    HWTRAP_XTAL_FSEL_25MHZ;
++	else
++		xtal = hwstrap & HWTRAP_XTAL_FSEL_MASK;
++
++	/* 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);
++
++	switch (xtal) {
++	case HWTRAP_XTAL_FSEL_25MHZ:
++		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);
++		break;
++	case HWTRAP_XTAL_FSEL_40MHZ:
++		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);
++		break;
++	};
++
++	/* 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);
++
++	return 0;
++}
++
+ static void
+ mt7530_mib_reset(struct dsa_switch *ds)
+ {
+@@ -507,6 +615,217 @@ static int mt7530_phy_write(struct dsa_s
+ 	return mdiobus_write_nested(priv->bus, port, regnum, val);
+ }
+ 
++static int
++mt7531_ind_c45_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 & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	reg = MT7531_MDIO_CL45_ADDR | MT7531_MDIO_PHY_ADDR(port) |
++	      MT7531_MDIO_DEV_ADDR(devad) | regnum;
++	mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
++
++	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
++				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	reg = MT7531_MDIO_CL45_READ | MT7531_MDIO_PHY_ADDR(port) |
++	      MT7531_MDIO_DEV_ADDR(devad);
++	mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
++
++	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
++				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	ret = val & MT7531_MDIO_RW_DATA_MASK;
++out:
++	mutex_unlock(&bus->mdio_lock);
++
++	return ret;
++}
++
++static int
++mt7531_ind_c45_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 & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	reg = MT7531_MDIO_CL45_ADDR | MT7531_MDIO_PHY_ADDR(port) |
++	      MT7531_MDIO_DEV_ADDR(devad) | regnum;
++	mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
++
++	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
++				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	reg = MT7531_MDIO_CL45_WRITE | MT7531_MDIO_PHY_ADDR(port) |
++	      MT7531_MDIO_DEV_ADDR(devad) | data;
++	mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
++
++	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
++				 !(val & MT7531_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
++mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
++{
++	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 & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	val = MT7531_MDIO_CL22_READ | MT7531_MDIO_PHY_ADDR(port) |
++	      MT7531_MDIO_REG_ADDR(regnum);
++
++	mt7530_mii_write(priv, MT7531_PHY_IAC, val | MT7531_PHY_ACS_ST);
++
++	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
++				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	ret = val & MT7531_MDIO_RW_DATA_MASK;
++out:
++	mutex_unlock(&bus->mdio_lock);
++
++	return ret;
++}
++
++static int
++mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
++			 u16 data)
++{
++	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 & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	reg = MT7531_MDIO_CL22_WRITE | MT7531_MDIO_PHY_ADDR(port) |
++	      MT7531_MDIO_REG_ADDR(regnum) | data;
++
++	mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
++
++	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
++				 !(reg & MT7531_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
++mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum)
++{
++	struct mt7530_priv *priv = ds->priv;
++	int devad;
++	int ret;
++
++	if (regnum & MII_ADDR_C45) {
++		devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f;
++		ret = mt7531_ind_c45_phy_read(priv, port, devad,
++					      regnum & MII_REGADDR_C45_MASK);
++	} else {
++		ret = mt7531_ind_c22_phy_read(priv, port, regnum);
++	}
++
++	return ret;
++}
++
++static int
++mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum,
++		     u16 data)
++{
++	struct mt7530_priv *priv = ds->priv;
++	int devad;
++	int ret;
++
++	if (regnum & MII_ADDR_C45) {
++		devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f;
++		ret = mt7531_ind_c45_phy_write(priv, port, devad,
++					       regnum & MII_REGADDR_C45_MASK,
++					       data);
++	} else {
++		ret = mt7531_ind_c22_phy_write(priv, port, regnum, data);
++	}
++
++	return ret;
++}
++
+ static void
+ mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+ 		   uint8_t *data)
+@@ -623,9 +942,14 @@ unlock_exit:
+ }
+ 
+ static int
+-mt7530_cpu_port_enable(struct mt7530_priv *priv,
+-		       int port)
++mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
+ {
++	struct mt7530_priv *priv = ds->priv;
++
++	/* Setup max capability of CPU port at first */
++	if (priv->info->cpu_port_config)
++		priv->info->cpu_port_config(ds, port);
++
+ 	/* Enable Mediatek header mode on the cpu port */
+ 	mt7530_write(priv, MT7530_PVC_P(port),
+ 		     PORT_SPEC_TAG);
+@@ -638,7 +962,7 @@ mt7530_cpu_port_enable(struct mt7530_pri
+ 		mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
+ 
+ 	/* CPU port gets connected to all user ports of
+-	 * the switch
++	 * the switch.
+ 	 */
+ 	mt7530_write(priv, MT7530_PCR_P(port),
+ 		     PCR_MATRIX(dsa_user_ports(priv->ds)));
+@@ -1132,27 +1456,42 @@ mt7530_port_vlan_del(struct dsa_switch *
+ 	return 0;
+ }
+ 
+-static int mt7530_port_mirror_add(struct dsa_switch *ds, int port,
++static int mt753x_mirror_port_get(unsigned int id, u32 val)
++{
++	return (id == ID_MT7531) ? MT7531_MIRROR_PORT_GET(val) :
++				   MIRROR_PORT(val);
++}
++
++static int mt753x_mirror_port_set(unsigned int id, u32 val)
++{
++	return (id == ID_MT7531) ? MT7531_MIRROR_PORT_SET(val) :
++				   MIRROR_PORT(val);
++}
++
++static int mt753x_port_mirror_add(struct dsa_switch *ds, int port,
+ 				  struct dsa_mall_mirror_tc_entry *mirror,
+ 				  bool ingress)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
++	int monitor_port;
+ 	u32 val;
+ 
+ 	/* Check for existent entry */
+ 	if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port))
+ 		return -EEXIST;
+ 
+-	val = mt7530_read(priv, MT7530_MFC);
++	val = mt7530_read(priv, MT753X_MIRROR_REG(priv->id));
+ 
+ 	/* MT7530 only supports one monitor port */
+-	if (val & MIRROR_EN && MIRROR_PORT(val) != mirror->to_local_port)
++	monitor_port = mt753x_mirror_port_get(priv->id, val);
++	if (val & MT753X_MIRROR_EN(priv->id) &&
++	    monitor_port != mirror->to_local_port)
+ 		return -EEXIST;
+ 
+-	val |= MIRROR_EN;
+-	val &= ~MIRROR_MASK;
+-	val |= mirror->to_local_port;
+-	mt7530_write(priv, MT7530_MFC, val);
++	val |= MT753X_MIRROR_EN(priv->id);
++	val &= ~MT753X_MIRROR_MASK(priv->id);
++	val |= mt753x_mirror_port_set(priv->id, mirror->to_local_port);
++	mt7530_write(priv, MT753X_MIRROR_REG(priv->id), val);
+ 
+ 	val = mt7530_read(priv, MT7530_PCR_P(port));
+ 	if (ingress) {
+@@ -1167,7 +1506,7 @@ static int mt7530_port_mirror_add(struct
+ 	return 0;
+ }
+ 
+-static void mt7530_port_mirror_del(struct dsa_switch *ds, int port,
++static void mt753x_port_mirror_del(struct dsa_switch *ds, int port,
+ 				   struct dsa_mall_mirror_tc_entry *mirror)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
+@@ -1184,9 +1523,9 @@ static void mt7530_port_mirror_del(struc
+ 	mt7530_write(priv, MT7530_PCR_P(port), val);
+ 
+ 	if (!priv->mirror_rx && !priv->mirror_tx) {
+-		val = mt7530_read(priv, MT7530_MFC);
+-		val &= ~MIRROR_EN;
+-		mt7530_write(priv, MT7530_MFC, val);
++		val = mt7530_read(priv, MT753X_MIRROR_REG(priv->id));
++		val &= ~MT753X_MIRROR_EN(priv->id);
++		mt7530_write(priv, MT753X_MIRROR_REG(priv->id), val);
+ 	}
+ }
+ 
+@@ -1292,7 +1631,7 @@ mt7530_setup(struct dsa_switch *ds)
+ 			   PCR_MATRIX_CLR);
+ 
+ 		if (dsa_is_cpu_port(ds, i))
+-			mt7530_cpu_port_enable(priv, i);
++			mt753x_cpu_port_enable(ds, i);
+ 		else
+ 			mt7530_port_disable(ds, i);
+ 
+@@ -1346,6 +1685,118 @@ 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);
++
++	if (mt7531_dual_sgmii_supported(priv)) {
++		priv->p5_intf_sel = P5_INTF_SEL_GMAC5_SGMII;
++
++		/* Let ds->slave_mii_bus be able to access external phy. */
++		mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO11_RG_RXD2_MASK,
++			   MT7531_EXT_P_MDC_11);
++		mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO12_RG_RXD3_MASK,
++			   MT7531_EXT_P_MDIO_12);
++	} else {
++		priv->p5_intf_sel = P5_INTF_SEL_GMAC5;
++	}
++	dev_dbg(ds->dev, "P5 support %s interface\n",
++		p5_intf_modes(priv->p5_intf_sel));
++
++	mt7530_rmw(priv, MT7531_GPIO_MODE0, MT7531_GPIO0_MASK,
++		   MT7531_GPIO0_INTERRUPT);
++
++	/* Let phylink decide the interface later. */
++	priv->p5_interface = PHY_INTERFACE_MODE_NA;
++	priv->p6_interface = PHY_INTERFACE_MODE_NA;
++
++	/* Enable PHY core PLL, 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_c45_phy_read(priv, MT753X_CTRL_PHY_ADDR,
++				      MDIO_MMD_VEND2, CORE_PLL_GROUP4);
++	val |= MT7531_PHY_PLL_BYPASS_MODE;
++	val &= ~MT7531_PHY_PLL_OFF;
++	mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2,
++				 CORE_PLL_GROUP4, val);
++
++	/* BPDU to CPU port */
++	mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK,
++		   BIT(MT7530_CPU_PORT));
++	mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
++		   MT753X_BPDU_CPU_ONLY);
++
++	/* Enable and reset MIB counters */
++	mt7530_mib_reset(ds);
++
++	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);
++
++		mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR);
++
++		if (dsa_is_cpu_port(ds, i))
++			mt753x_cpu_port_enable(ds, i);
++		else
++			mt7530_port_disable(ds, i);
++
++		/* Enable consistent egress tag */
++		mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK,
++			   PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
++	}
++
++	ds->configure_vlan_while_not_filtering = true;
++
++	/* Flush the FDB table */
++	ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
++	if (ret < 0)
++		return ret;
++
++	return 0;
++}
++
+ static bool
+ mt7530_phy_mode_supported(struct dsa_switch *ds, int port,
+ 			  const struct phylink_link_state *state)
+@@ -1384,6 +1835,47 @@ unsupported:
+ 	return false;
+ }
+ 
++static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port)
++{
++	return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII);
++}
++
++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_is_rgmii_port(priv, port))
++			return phy_interface_mode_is_rgmii(state->interface);
++		fallthrough;
++	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_mode_supported(struct dsa_switch *ds, int port,
+ 			  const struct phylink_link_state *state)
+@@ -1416,6 +1908,227 @@ mt7530_mac_config(struct dsa_switch *ds,
+ 	return 0;
+ }
+ 
++static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port,
++			      phy_interface_t interface,
++			      struct phy_device *phydev)
++{
++	u32 val;
++
++	if (!mt7531_is_rgmii_port(priv, port)) {
++		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 &= ~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);
++	val |= TXCLK_NO_REVERSE | RXCLK_NO_DELAY;
++
++	/* Do not adjust rgmii delay when vendor phy driver presents. */
++	if (!phydev || phy_driver_is_genphy(phydev)) {
++		val &= ~(TXCLK_NO_REVERSE | RXCLK_NO_DELAY);
++		switch (interface) {
++		case PHY_INTERFACE_MODE_RGMII:
++			val |= TXCLK_NO_REVERSE;
++			val |= RXCLK_NO_DELAY;
++			break;
++		case PHY_INTERFACE_MODE_RGMII_RXID:
++			val |= TXCLK_NO_REVERSE;
++			break;
++		case PHY_INTERFACE_MODE_RGMII_TXID:
++			val |= RXCLK_NO_DELAY;
++			break;
++		case PHY_INTERFACE_MODE_RGMII_ID:
++			break;
++		default:
++			return -EINVAL;
++		}
++	}
++	mt7530_write(priv, MT7531_CLKGEN_CTRL, val);
++
++	return 0;
++}
++
++static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port,
++				  unsigned long *supported)
++{
++	/* Port5 supports ethier RGMII or SGMII.
++	 * Port6 supports SGMII only.
++	 */
++	switch (port) {
++	case 5:
++		if (mt7531_is_rgmii_port(priv, port))
++			break;
++		fallthrough;
++	case 6:
++		phylink_set(supported, 1000baseX_Full);
++		phylink_set(supported, 2500baseX_Full);
++		phylink_set(supported, 2500baseT_Full);
++	}
++}
++
++static void
++mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port,
++			   unsigned int mode, phy_interface_t interface,
++			   int speed, int duplex)
++{
++	struct mt7530_priv *priv = ds->priv;
++	unsigned int val;
++
++	/* For adjusting speed and duplex of SGMII force mode. */
++	if (interface != PHY_INTERFACE_MODE_SGMII ||
++	    phylink_autoneg_inband(mode))
++		return;
++
++	/* SGMII force mode setting */
++	val = mt7530_read(priv, MT7531_SGMII_MODE(port));
++	val &= ~MT7531_SGMII_IF_MODE_MASK;
++
++	switch (speed) {
++	case SPEED_10:
++		val |= MT7531_SGMII_FORCE_SPEED_10;
++		break;
++	case SPEED_100:
++		val |= MT7531_SGMII_FORCE_SPEED_100;
++		break;
++	case SPEED_1000:
++		val |= MT7531_SGMII_FORCE_SPEED_1000;
++		break;
++	}
++
++	/* MT7531 SGMII 1G force mode can only work in full duplex mode,
++	 * no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not.
++	 */
++	if ((speed == SPEED_10 || speed == SPEED_100) &&
++	    duplex != DUPLEX_FULL)
++		val |= MT7531_SGMII_FORCE_HALF_DUPLEX;
++
++	mt7530_write(priv, MT7531_SGMII_MODE(port), val);
++}
++
++static bool mt753x_is_mac_port(u32 port)
++{
++	return (port == 5 || port == 6);
++}
++
++static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port,
++					 phy_interface_t interface)
++{
++	u32 val;
++
++	if (!mt753x_is_mac_port(port))
++		return -EINVAL;
++
++	mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port),
++		   MT7531_SGMII_PHYA_PWD);
++
++	val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port));
++	val &= ~MT7531_RG_TPHY_SPEED_MASK;
++	/* Setup 2.5 times faster clock for 2.5Gbps data speeds with 10B/8B
++	 * encoding.
++	 */
++	val |= (interface == PHY_INTERFACE_MODE_2500BASEX) ?
++		MT7531_RG_TPHY_SPEED_3_125G : MT7531_RG_TPHY_SPEED_1_25G;
++	mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val);
++
++	mt7530_clear(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE);
++
++	/* MT7531 SGMII 1G and 2.5G force mode can only work in full duplex
++	 * mode, no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not.
++	 */
++	mt7530_rmw(priv, MT7531_SGMII_MODE(port),
++		   MT7531_SGMII_IF_MODE_MASK | MT7531_SGMII_REMOTE_FAULT_DIS,
++		   MT7531_SGMII_FORCE_SPEED_1000);
++
++	mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0);
++
++	return 0;
++}
++
++static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port,
++				      phy_interface_t interface)
++{
++	if (!mt753x_is_mac_port(port))
++		return -EINVAL;
++
++	mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port),
++		   MT7531_SGMII_PHYA_PWD);
++
++	mt7530_rmw(priv, MT7531_PHYA_CTRL_SIGNAL3(port),
++		   MT7531_RG_TPHY_SPEED_MASK, MT7531_RG_TPHY_SPEED_1_25G);
++
++	mt7530_set(priv, MT7531_SGMII_MODE(port),
++		   MT7531_SGMII_REMOTE_FAULT_DIS |
++		   MT7531_SGMII_SPEED_DUPLEX_AN);
++
++	mt7530_rmw(priv, MT7531_PCS_SPEED_ABILITY(port),
++		   MT7531_SGMII_TX_CONFIG_MASK, 1);
++
++	mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE);
++
++	mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_RESTART);
++
++	mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0);
++
++	return 0;
++}
++
++static void mt7531_sgmii_restart_an(struct dsa_switch *ds, int port)
++{
++	struct mt7530_priv *priv = ds->priv;
++	u32 val;
++
++	/* Only restart AN when AN is enabled */
++	val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
++	if (val & MT7531_SGMII_AN_ENABLE) {
++		val |= MT7531_SGMII_AN_RESTART;
++		mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val);
++	}
++}
++
++static int
++mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
++		  phy_interface_t interface)
++{
++	struct mt7530_priv *priv = ds->priv;
++	struct phy_device *phydev;
++	const struct dsa_port *dp;
++
++	if (!mt753x_is_mac_port(port)) {
++		dev_err(priv->dev, "port %d is not a MAC port\n", port);
++		return -EINVAL;
++	}
++
++	switch (interface) {
++	case PHY_INTERFACE_MODE_RGMII:
++	case PHY_INTERFACE_MODE_RGMII_ID:
++	case PHY_INTERFACE_MODE_RGMII_RXID:
++	case PHY_INTERFACE_MODE_RGMII_TXID:
++		dp = dsa_to_port(ds, port);
++		phydev = dp->slave->phydev;
++		return mt7531_rgmii_setup(priv, port, interface, phydev);
++	case PHY_INTERFACE_MODE_SGMII:
++		return mt7531_sgmii_setup_mode_an(priv, port, interface);
++	case PHY_INTERFACE_MODE_NA:
++	case PHY_INTERFACE_MODE_1000BASEX:
++	case PHY_INTERFACE_MODE_2500BASEX:
++		if (phylink_autoneg_inband(mode))
++			return -EINVAL;
++
++		return mt7531_sgmii_setup_mode_force(priv, port, interface);
++	default:
++		return -EINVAL;
++	}
++
++	return -EINVAL;
++}
++
+ static int
+ mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ 		  const struct phylink_link_state *state)
+@@ -1451,6 +2164,8 @@ mt753x_phylink_mac_config(struct dsa_swi
+ 		if (mt753x_mac_config(ds, port, mode, state) < 0)
+ 			goto unsupported;
+ 
++		if (priv->p5_intf_sel != P5_DISABLED)
++			priv->p5_interface = state->interface;
+ 		break;
+ 	case 6: /* 1st cpu port */
+ 		if (priv->p6_interface == state->interface)
+@@ -1470,7 +2185,8 @@ unsupported:
+ 		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;
+@@ -1480,7 +2196,7 @@ unsupported:
+ 	mcr_new = mcr_cur;
+ 	mcr_new &= ~PMCR_LINK_SETTINGS_MASK;
+ 	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);
+ 
+ 	/* Are we connected to external phy */
+ 	if (port == 5 && dsa_is_user_port(ds, 5))
+@@ -1490,7 +2206,18 @@ unsupported:
+ 		mt7530_write(priv, MT7530_PMCR_P(port), mcr_new);
+ }
+ 
+-static void mt7530_phylink_mac_link_down(struct dsa_switch *ds, int port,
++static void
++mt753x_phylink_mac_an_restart(struct dsa_switch *ds, int port)
++{
++	struct mt7530_priv *priv = ds->priv;
++
++	if (!priv->info->mac_pcs_an_restart)
++		return;
++
++	priv->info->mac_pcs_an_restart(ds, port);
++}
++
++static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port,
+ 					 unsigned int mode,
+ 					 phy_interface_t interface)
+ {
+@@ -1499,7 +2226,19 @@ static void mt7530_phylink_mac_link_down
+ 	mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+ }
+ 
+-static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port,
++static void mt753x_mac_pcs_link_up(struct dsa_switch *ds, int port,
++				   unsigned int mode, phy_interface_t interface,
++				   int speed, int duplex)
++{
++	struct mt7530_priv *priv = ds->priv;
++
++	if (!priv->info->mac_pcs_link_up)
++		return;
++
++	priv->info->mac_pcs_link_up(ds, port, mode, interface, speed, duplex);
++}
++
++static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
+ 				       unsigned int mode,
+ 				       phy_interface_t interface,
+ 				       struct phy_device *phydev,
+@@ -1509,18 +2248,29 @@ static void mt7530_phylink_mac_link_up(s
+ 	struct mt7530_priv *priv = ds->priv;
+ 	u32 mcr;
+ 
++	mt753x_mac_pcs_link_up(ds, port, mode, interface, speed, duplex);
++
+ 	mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK;
+ 
++	/* MT753x MAC works in 1G full duplex mode for all up-clocked
++	 * variants.
++	 */
++	if (interface == PHY_INTERFACE_MODE_TRGMII ||
++	    (phy_interface_mode_is_8023z(interface))) {
++		speed = SPEED_1000;
++		duplex = DUPLEX_FULL;
++	}
++
+ 	switch (speed) {
+ 	case SPEED_1000:
+ 		mcr |= PMCR_FORCE_SPEED_1000;
+ 		if (priv->eee_enable & BIT(port))
+-			mcr_new |= PMCR_FORCE_EEE1G;
++			mcr |= PMCR_FORCE_EEE1G;
+ 		break;
+ 	case SPEED_100:
+ 		mcr |= PMCR_FORCE_SPEED_100;
+ 		if (priv->eee_enable & BIT(port))
+-			mcr_new |= PMCR_FORCE_EEE100;
++			mcr |= PMCR_FORCE_EEE100;
+ 		break;
+ 	}
+ 	if (duplex == DUPLEX_FULL) {
+@@ -1534,6 +2284,45 @@ static void mt7530_phylink_mac_link_up(s
+ 	mt7530_set(priv, MT7530_PMCR_P(port), mcr);
+ }
+ 
++static int
++mt7531_cpu_port_config(struct dsa_switch *ds, int port)
++{
++	struct mt7530_priv *priv = ds->priv;
++	phy_interface_t interface;
++	int speed;
++
++	switch (port) {
++	case 5:
++		if (mt7531_is_rgmii_port(priv, port))
++			interface = PHY_INTERFACE_MODE_RGMII;
++		else
++			interface = PHY_INTERFACE_MODE_2500BASEX;
++
++		priv->p5_interface = interface;
++		break;
++	case 6:
++		interface = PHY_INTERFACE_MODE_2500BASEX;
++
++		mt7531_pad_setup(ds, interface);
++
++		priv->p6_interface = interface;
++		break;
++	};
++
++	if (interface == PHY_INTERFACE_MODE_2500BASEX)
++		speed = SPEED_2500;
++	else
++		speed = SPEED_1000;
++
++	mt7531_mac_config(ds, port, MLO_AN_FIXED, interface);
++	mt7530_write(priv, MT7530_PMCR_P(port),
++		     PMCR_CPU_PORT_SETTING(priv->id));
++	mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL,
++				   speed, DUPLEX_FULL, true, true);
++
++	return 0;
++}
++
+ static void
+ mt7530_mac_port_validate(struct dsa_switch *ds, int port,
+ 			 unsigned long *supported)
+@@ -1542,6 +2331,14 @@ mt7530_mac_port_validate(struct dsa_swit
+ 		phylink_set(supported, 1000baseX_Full);
+ }
+ 
++static void mt7531_mac_port_validate(struct dsa_switch *ds, int port,
++				     unsigned long *supported)
++{
++	struct mt7530_priv *priv = ds->priv;
++
++	mt7531_sgmii_validate(priv, port, supported);
++}
++
+ static void
+ mt753x_phylink_validate(struct dsa_switch *ds, int port,
+ 			unsigned long *supported,
+@@ -1558,7 +2355,8 @@ mt753x_phylink_validate(struct dsa_switc
+ 
+ 	phylink_set_port_modes(mask);
+ 
+-	if (state->interface != PHY_INTERFACE_MODE_TRGMII) {
++	if (state->interface != PHY_INTERFACE_MODE_TRGMII ||
++	    !phy_interface_mode_is_8023z(state->interface)) {
+ 		phylink_set(mask, 10baseT_Half);
+ 		phylink_set(mask, 10baseT_Full);
+ 		phylink_set(mask, 100baseT_Half);
+@@ -1577,6 +2375,11 @@ mt753x_phylink_validate(struct dsa_switc
+ 
+ 	linkmode_and(supported, supported, mask);
+ 	linkmode_and(state->advertising, state->advertising, mask);
++
++	/* We can only operate at 2500BaseX or 1000BaseX.  If requested
++	 * to advertise both, only report advertising at 2500BaseX.
++	 */
++	phylink_helper_basex_speed(state);
+ }
+ 
+ static int
+@@ -1667,6 +2470,63 @@ static int mt7530_set_mac_eee(struct dsa
+ 	return 0;
+ }
+ 
++#ifdef notyet
++static int
++mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port,
++			      struct phylink_link_state *state)
++{
++	u32 status, val;
++	u16 config_reg;
++
++	status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
++	state->link = !!(status & MT7531_SGMII_LINK_STATUS);
++	if (state->interface == PHY_INTERFACE_MODE_SGMII &&
++	    (status & MT7531_SGMII_AN_ENABLE)) {
++		val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port));
++		config_reg = val >> 16;
++
++		switch (config_reg & LPA_SGMII_SPD_MASK) {
++		case LPA_SGMII_1000:
++			state->speed = SPEED_1000;
++			break;
++		case LPA_SGMII_100:
++			state->speed = SPEED_100;
++			break;
++		case LPA_SGMII_10:
++			state->speed = SPEED_10;
++			break;
++		default:
++			dev_err(priv->dev, "invalid sgmii PHY speed\n");
++			state->link = false;
++			return -EINVAL;
++		}
++
++		if (config_reg & LPA_SGMII_FULL_DUPLEX)
++			state->duplex = DUPLEX_FULL;
++		else
++			state->duplex = DUPLEX_HALF;
++	}
++
++	return 0;
++}
++#endif
++
++static int
++mt7531_phylink_mac_link_state(struct dsa_switch *ds, int port,
++			      struct phylink_link_state *state)
++{
++#ifdef notyet
++	struct mt7530_priv *priv = ds->priv;
++
++	if (state->interface == PHY_INTERFACE_MODE_SGMII)
++		return mt7531_sgmii_pcs_get_state_an(priv, port, state);
++#else
++	return mt7530_phylink_mac_link_state(ds, port, state);
++#endif
++
++	return -EOPNOTSUPP;
++}
++
+ static int
+ mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port,
+ 			      struct phylink_link_state *state)
+@@ -1720,13 +2580,14 @@ static const struct dsa_switch_ops mt753
+ 	.port_vlan_prepare	= mt7530_port_vlan_prepare,
+ 	.port_vlan_add		= mt7530_port_vlan_add,
+ 	.port_vlan_del		= mt7530_port_vlan_del,
+-	.port_mirror_add	= mt7530_port_mirror_add,
+-	.port_mirror_del	= mt7530_port_mirror_del,
++	.port_mirror_add	= mt753x_port_mirror_add,
++	.port_mirror_del	= mt753x_port_mirror_del,
+ 	.phylink_validate	= mt753x_phylink_validate,
+ 	.phylink_mac_link_state	= mt753x_phylink_mac_link_state,
+ 	.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,
++	.phylink_mac_an_restart	= mt753x_phylink_mac_an_restart,
++	.phylink_mac_link_down	= mt753x_phylink_mac_link_down,
++	.phylink_mac_link_up	= mt753x_phylink_mac_link_up,
+ 	.get_mac_eee		= mt7530_get_mac_eee,
+ 	.set_mac_eee		= mt7530_set_mac_eee,
+ };
+@@ -1754,11 +2615,26 @@ static const struct mt753x_info mt753x_t
+ 		.mac_port_get_state = mt7530_phylink_mac_link_state,
+ 		.mac_port_config = mt7530_mac_config,
+ 	},
++	[ID_MT7531] = {
++		.id = ID_MT7531,
++		.sw_setup = mt7531_setup,
++		.phy_read = mt7531_ind_phy_read,
++		.phy_write = mt7531_ind_phy_write,
++		.pad_setup = mt7531_pad_setup,
++		.cpu_port_config = mt7531_cpu_port_config,
++		.phy_mode_supported = mt7531_phy_supported,
++		.mac_port_validate = mt7531_mac_port_validate,
++		.mac_port_get_state = mt7531_phylink_mac_link_state,
++		.mac_port_config = mt7531_mac_config,
++		.mac_pcs_an_restart = mt7531_sgmii_restart_an,
++		.mac_pcs_link_up = mt7531_sgmii_link_up_force,
++	},
+ };
+ 
+ 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);
+--- a/drivers/net/dsa/mt7530.h
++++ b/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
+@@ -41,6 +42,33 @@ enum mt753x_id {
+ #define  MIRROR_PORT(x)			((x) & 0x7)
+ #define  MIRROR_MASK			0x7
+ 
++/* Registers for CPU forward control */
++#define MT7531_CFC			0x4
++#define  MT7531_MIRROR_EN		BIT(19)
++#define  MT7531_MIRROR_MASK		(MIRROR_MASK << 16)
++#define  MT7531_MIRROR_PORT_GET(x)	(((x) >> 16) & MIRROR_MASK)
++#define  MT7531_MIRROR_PORT_SET(x)	(((x) & MIRROR_MASK) << 16)
++#define  MT7531_CPU_PMAP_MASK		GENMASK(7, 0)
++
++#define MT753X_MIRROR_REG(id)		(((id) == ID_MT7531) ? \
++					 MT7531_CFC : MT7530_MFC)
++#define MT753X_MIRROR_EN(id)		(((id) == ID_MT7531) ? \
++					 MT7531_MIRROR_EN : MIRROR_EN)
++#define MT753X_MIRROR_MASK(id)		(((id) == ID_MT7531) ? \
++					 MT7531_MIRROR_MASK : MIRROR_MASK)
++
++/* Registers for BPDU and PAE frame control*/
++#define MT753X_BPC			0x24
++#define  MT753X_BPDU_PORT_FW_MASK	GENMASK(2, 0)
++
++enum mt753x_bpdu_port_fw {
++	MT753X_BPDU_FOLLOW_MFC,
++	MT753X_BPDU_CPU_EXCLUDE = 4,
++	MT753X_BPDU_CPU_INCLUDE = 5,
++	MT753X_BPDU_CPU_ONLY = 6,
++	MT753X_BPDU_DROP = 7,
++};
++
+ /* Registers for address table access */
+ #define MT7530_ATA1			0x74
+ #define  STATIC_EMP			0
+@@ -222,10 +250,30 @@ 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  PMCR_LINK_SETTINGS_MASK	(PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \
+ 					 PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \
+ 					 PMCR_TX_FC_EN | PMCR_RX_FC_EN | \
+ 					 PMCR_FORCE_FDX | PMCR_FORCE_LNK)
++#define  PMCR_CPU_PORT_SETTING(id)	(PMCR_FORCE_MODE_ID((id)) | \
++					 PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \
++					 PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \
++					 PMCR_TX_EN | PMCR_RX_EN | \
++					 PMCR_TX_FC_EN | PMCR_RX_FC_EN | \
++					 PMCR_FORCE_SPEED_1000 | \
++					 PMCR_FORCE_FDX | PMCR_FORCE_LNK)
+ 
+ #define MT7530_PMSR_P(x)		(0x3008 + (x) * 0x100)
+ #define  PMSR_EEE1G			BIT(7)
+@@ -245,6 +293,10 @@ enum mt7530_vlan_port_attr {
+ #define  LPI_THRESH(x)			((x & 0xFFF) << 4)
+ #define  LPI_MODE_EN			BIT(0)
+ 
++/* Register for port debug count */
++#define MT7531_DBG_CNT(x)		(0x3018 + (x) * 0x100)
++#define  MT7531_DIS_CLR			BIT(31)
++
+ /* Register for MIB */
+ #define MT7530_PORT_MIB_COUNTER(x)	(0x4000 + (x) * 0x100)
+ #define MT7530_MIB_CCR			0x4fe0
+@@ -262,12 +314,118 @@ enum mt7530_vlan_port_attr {
+ 					 CCR_RX_OCT_CNT_BAD | \
+ 					 CCR_TX_OCT_CNT_GOOD | \
+ 					 CCR_TX_OCT_CNT_BAD)
++
++/* MT7531 SGMII register group */
++#define MT7531_SGMII_REG_BASE		0x5000
++#define MT7531_SGMII_REG(p, r)		(MT7531_SGMII_REG_BASE + \
++					((p) - 5) * 0x1000 + (r))
++
++/* Register forSGMII 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)
++
++/* Register for SGMII PCS_SPPED_ABILITY */
++#define MT7531_PCS_SPEED_ABILITY(p)	MT7531_SGMII_REG(p, 0x08)
++#define  MT7531_SGMII_TX_CONFIG_MASK	GENMASK(15, 0)
++#define  MT7531_SGMII_TX_CONFIG		BIT(0)
++
++/* Register for SGMII_MODE */
++#define MT7531_SGMII_MODE(p)		MT7531_SGMII_REG(p, 0x20)
++#define  MT7531_SGMII_REMOTE_FAULT_DIS	BIT(8)
++#define  MT7531_SGMII_IF_MODE_MASK	GENMASK(5, 1)
++#define  MT7531_SGMII_FORCE_DUPLEX	BIT(4)
++#define  MT7531_SGMII_FORCE_SPEED_MASK	GENMASK(3, 2)
++#define  MT7531_SGMII_FORCE_SPEED_1000	BIT(3)
++#define  MT7531_SGMII_FORCE_SPEED_100	BIT(2)
++#define  MT7531_SGMII_FORCE_SPEED_10	0
++#define  MT7531_SGMII_SPEED_DUPLEX_AN	BIT(1)
++
++enum mt7531_sgmii_force_duplex {
++	MT7531_SGMII_FORCE_FULL_DUPLEX = 0,
++	MT7531_SGMII_FORCE_HALF_DUPLEX = 0x10,
++};
++
++/* 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  MT7531_PHY_ACS_ST		BIT(31)
++#define  MT7531_MDIO_REG_ADDR_MASK	(0x1f << 25)
++#define  MT7531_MDIO_PHY_ADDR_MASK	(0x1f << 20)
++#define  MT7531_MDIO_CMD_MASK		(0x3 << 18)
++#define  MT7531_MDIO_ST_MASK		(0x3 << 16)
++#define  MT7531_MDIO_RW_DATA_MASK	(0xffff)
++#define  MT7531_MDIO_REG_ADDR(x)	(((x) & 0x1f) << 25)
++#define  MT7531_MDIO_DEV_ADDR(x)	(((x) & 0x1f) << 25)
++#define  MT7531_MDIO_PHY_ADDR(x)	(((x) & 0x1f) << 20)
++#define  MT7531_MDIO_CMD(x)		(((x) & 0x3) << 18)
++#define  MT7531_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  MT7531_MDIO_CL22_READ		(MT7531_MDIO_ST(MT7531_MDIO_ST_CL22) | \
++					 MT7531_MDIO_CMD(MT7531_MDIO_READ))
++#define  MT7531_MDIO_CL22_WRITE		(MT7531_MDIO_ST(MT7531_MDIO_ST_CL22) | \
++					 MT7531_MDIO_CMD(MT7531_MDIO_WRITE))
++#define  MT7531_MDIO_CL45_ADDR		(MT7531_MDIO_ST(MT7531_MDIO_ST_CL45) | \
++					 MT7531_MDIO_CMD(MT7531_MDIO_ADDR))
++#define  MT7531_MDIO_CL45_READ		(MT7531_MDIO_ST(MT7531_MDIO_ST_CL45) | \
++					 MT7531_MDIO_CMD(MT7531_MDIO_READ))
++#define  MT7531_MDIO_CL45_WRITE		(MT7531_MDIO_ST(MT7531_MDIO_ST_CL45) | \
++					 MT7531_MDIO_CMD(MT7531_MDIO_WRITE))
++
++/* Register for RGMII clock phase */
++#define MT7531_CLKGEN_CTRL		0x7500
++#define  CLK_SKEW_OUT(x)		(((x) & 0x3) << 8)
++#define  CLK_SKEW_OUT_MASK		GENMASK(9, 8)
++#define  CLK_SKEW_IN(x)			(((x) & 0x3) << 6)
++#define  CLK_SKEW_IN_MASK		GENMASK(7, 6)
++#define  RXCLK_NO_DELAY			BIT(5)
++#define  TXCLK_NO_REVERSE		BIT(4)
++#define  GP_MODE(x)			(((x) & 0x3) << 1)
++#define  GP_MODE_MASK			GENMASK(2, 1)
++#define  GP_CLK_EN			BIT(0)
++
++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))
+@@ -275,6 +433,16 @@ 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
++/* Unique fields of (M)HWSTRAP for MT7531 */
++#define  XTAL_FSEL_S			7
++#define  XTAL_FSEL_M			BIT(7)
++#define  PHY_EN				BIT(6)
++#define  CHG_STRAP			BIT(8)
++
+ /* Register for hw trap modification */
+ #define MT7530_MHWTRAP			0x7804
+ #define  MHWTRAP_PHY0_SEL		BIT(20)
+@@ -289,14 +457,37 @@ 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  PAD_MCM_SMI_EN			BIT(0)
++
+ #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_CHIP_REV			0x781C
++
++#define MT7531_PLLGP_EN			0x7820
++#define  EN_COREPLL			BIT(2)
++#define  SW_CLKSW			BIT(1)
++#define  SW_PLLGP			BIT(0)
++
+ #define MT7530_P6ECR			0x7830
+ #define  P6_INTF_MODE_MASK		0x3
+ #define  P6_INTF_MODE(x)		((x) & 0x3)
+ 
++#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)
++
++/* Registers for 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,10 +526,25 @@ enum mt7530_vlan_port_attr {
+ #define MT7530_P5RGMIITXCR		0x7b04
+ #define  CSR_RGMII_TXC_CFG(x)		((x) & 0x1f)
+ 
++/* Registers for GPIO mode */
++#define MT7531_GPIO_MODE0		0x7c0c
++#define  MT7531_GPIO0_MASK		GENMASK(3, 0)
++#define  MT7531_GPIO0_INTERRUPT		1
++
++#define MT7531_GPIO_MODE1		0x7c10
++#define  MT7531_GPIO11_RG_RXD2_MASK	GENMASK(15, 12)
++#define  MT7531_EXT_P_MDC_11		(2 << 12)
++#define  MT7531_GPIO12_RG_RXD3_MASK	GENMASK(19, 16)
++#define  MT7531_EXT_P_MDIO_12		(2 << 16)
++
+ #define MT7530_CREV			0x7ffc
+ #define  CHIP_NAME_SHIFT		16
+ #define  MT7530_ID			0x7530
+ 
++#define MT7531_CREV			0x781C
++#define  CHIP_REV_M			0x0f
++#define  MT7531_ID			0x7531
++
+ /* Registers for core PLL access through mmd indirect */
+ #define CORE_PLL_GROUP2			0x401
+ #define  RG_SYSPLL_EN_NORMAL		BIT(15)
+@@ -355,6 +561,10 @@ enum mt7530_vlan_port_attr {
+ #define  RG_SYSPLL_DDSFBK_EN		BIT(12)
+ #define  RG_SYSPLL_BIAS_EN		BIT(11)
+ #define  RG_SYSPLL_BIAS_LPF_EN		BIT(10)
++#define  MT7531_PHY_PLL_OFF		BIT(5)
++#define  MT7531_PHY_PLL_BYPASS_MODE	BIT(4)
++
++#define MT753X_CTRL_PHY_ADDR		0
+ 
+ #define CORE_PLL_GROUP5			0x404
+ #define  RG_LCDDS_PCW_NCPO1(x)		((x) & 0xffff)
+@@ -433,6 +643,7 @@ enum p5_interface_select {
+ 	P5_INTF_SEL_PHY_P0,
+ 	P5_INTF_SEL_PHY_P4,
+ 	P5_INTF_SEL_GMAC5,
++	P5_INTF_SEL_GMAC5_SGMII,
+ };
+ 
+ static const char *p5_intf_modes(unsigned int p5_interface)
+@@ -446,6 +657,8 @@ static const char *p5_intf_modes(unsigne
+ 		return "PHY P4";
+ 	case P5_INTF_SEL_GMAC5:
+ 		return "GMAC5";
++	case P5_INTF_SEL_GMAC5_SGMII:
++		return "GMAC5_SGMII";
+ 	default:
+ 		return "unknown";
+ 	}
+@@ -466,6 +679,10 @@ static const char *p5_intf_modes(unsigne
+  *			MAC port
+  * @mac_port_config:	Holding the way setting up the PHY attribute to a
+  *			certain MAC port
++ * @mac_pcs_an_restart	Holding the way restarting PCS autonegotiation for a
++ *			certain MAC port
++ * @mac_pcs_link_up:	Holding the way setting up the PHY attribute to the pcs
++ *			of the certain MAC port
+  */
+ struct mt753x_info {
+ 	enum mt753x_id id;
+@@ -474,6 +691,7 @@ struct mt753x_info {
+ 	int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
+ 	int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val);
+ 	int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface);
++	int (*cpu_port_config)(struct dsa_switch *ds, int port);
+ 	bool (*phy_mode_supported)(struct dsa_switch *ds, int port,
+ 				   const struct phylink_link_state *state);
+ 	void (*mac_port_validate)(struct dsa_switch *ds, int port,
+@@ -483,6 +701,10 @@ struct mt753x_info {
+ 	int (*mac_port_config)(struct dsa_switch *ds, int port,
+ 			       unsigned int mode,
+ 			       phy_interface_t interface);
++	void (*mac_pcs_an_restart)(struct dsa_switch *ds, int port);
++	void (*mac_pcs_link_up)(struct dsa_switch *ds, int port,
++				unsigned int mode, phy_interface_t interface,
++				int speed, int duplex);
+ };
+ 
+ /* struct mt7530_priv -	This is the main data structure for holding the state
diff --git a/target/linux/mediatek/patches-5.4/0605-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch b/target/linux/mediatek/patches-5.4/0605-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch
new file mode 100644
index 0000000000..8c3fe52089
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0605-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch
@@ -0,0 +1,71 @@
+From: Landen Chao <landen.chao at mediatek.com>
+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
+
+Add mt7531 dsa to bananapi-bpi-r64 board for 5 giga Ethernet ports support.
+
+Signed-off-by: Landen Chao <landen.chao at mediatek.com>
+---
+ .../dts/mediatek/mt7622-bananapi-bpi-r64.dts  | 50 +++++++++++++++++++
+ 1 file changed, 50 insertions(+)
+
+--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
+@@ -150,6 +150,56 @@
+ 	mdio: mdio-bus {
+ 		#address-cells = <1>;
+ 		#size-cells = <0>;
++
++		switch at 0 {
++			compatible = "mediatek,mt7531";
++			reg = <0>;
++			reset-gpios = <&pio 54 0>;
++
++			ports {
++				#address-cells = <1>;
++				#size-cells = <0>;
++
++				port at 0 {
++					reg = <0>;
++					label = "wan";
++				};
++
++				port at 1 {
++					reg = <1>;
++					label = "lan0";
++				};
++
++				port at 2 {
++					reg = <2>;
++					label = "lan1";
++				};
++
++				port at 3 {
++					reg = <3>;
++					label = "lan2";
++				};
++
++				port at 4 {
++					reg = <4>;
++					label = "lan3";
++				};
++
++				port at 6 {
++					reg = <6>;
++					label = "cpu";
++					ethernet = <&gmac0>;
++					phy-mode = "2500base-x";
++
++					fixed-link {
++						speed = <2500>;
++						full-duplex;
++						pause;
++					};
++				};
++			};
++		};
++
+ 	};
+ };
+ 



More information about the lede-commits mailing list