Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1206959/?format=api
{ "id": 1206959, "url": "http://patchwork.ozlabs.org/api/patches/1206959/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/6d608dd024edc90b09ba4fe35417b693847f973c.1575914275.git.landen.chao@mediatek.com/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<6d608dd024edc90b09ba4fe35417b693847f973c.1575914275.git.landen.chao@mediatek.com>", "list_archive_url": null, "date": "2019-12-10T08:14:40", "name": "[net-next,4/6] net: dsa: mt7530: Add the support of MT7531 switch", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": false, "hash": "81ae6304a7bc9ec2a9e96d30387e55abd602b2dd", "submitter": { "id": 78098, "url": "http://patchwork.ozlabs.org/api/people/78098/?format=api", "name": "Landen Chao", "email": "landen.chao@mediatek.com" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/6d608dd024edc90b09ba4fe35417b693847f973c.1575914275.git.landen.chao@mediatek.com/mbox/", "series": [ { "id": 147499, "url": "http://patchwork.ozlabs.org/api/series/147499/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=147499", "date": "2019-12-10T08:14:36", "name": "net-next: dsa: mt7530: add support for MT7531", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/147499/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1206959/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1206959/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming-netdev@ozlabs.org", "Delivered-To": "patchwork-incoming-netdev@ozlabs.org", "Authentication-Results": [ "ozlabs.org; spf=none (no SPF record)\n\tsmtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67;\n\thelo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org; dmarc=pass (p=none dis=none)\n\theader.from=mediatek.com", "ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=mediatek.com header.i=@mediatek.com\n\theader.b=\"A6fsNqWU\"; dkim-atps=neutral" ], "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 47XCXz2fDsz9sPh\n\tfor <patchwork-incoming-netdev@ozlabs.org>;\n\tTue, 10 Dec 2019 19:15:15 +1100 (AEDT)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1727198AbfLJIPC (ORCPT\n\t<rfc822;patchwork-incoming-netdev@ozlabs.org>);\n\tTue, 10 Dec 2019 03:15:02 -0500", "from mailgw02.mediatek.com ([210.61.82.184]:39119 \"EHLO\n\tmailgw02.mediatek.com\" rhost-flags-OK-FAIL-OK-FAIL) by\n\tvger.kernel.org with ESMTP id S1726750AbfLJIPC (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Tue, 10 Dec 2019 03:15:02 -0500", "from mtkcas09.mediatek.inc [(172.21.101.178)] by\n\tmailgw02.mediatek.com (envelope-from <landen.chao@mediatek.com>)\n\t(Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS)\n\twith ESMTP id 452927388; Tue, 10 Dec 2019 16:14:46 +0800", "from mtkcas08.mediatek.inc (172.21.101.126) by\n\tmtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server\n\t(TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:31 +0800", "from mtksdccf07.mediatek.inc (172.21.84.99) by\n\tmtkcas08.mediatek.inc\n\t(172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via\n\tFrontend Transport; Tue, 10 Dec 2019 16:14:26 +0800" ], "X-UUID": [ "38155314c18e497aacbec5bc0f664b9a-20191210", "38155314c18e497aacbec5bc0f664b9a-20191210" ], "DKIM-Signature": "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=mediatek.com; s=dk; \n\th=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From;\n\tbh=sEkoMPWKI3m+K/8A3kC0uuYTNxZZaGCvfLKvnEmwQQ4=; \n\tb=A6fsNqWUmjxIiZPLPb43Hs36qwwvYXMLQ/LlU24IcsfBro20uMkDbzGq522r69u0071Qgekwc/zs4yujo0pz40jCfnAo38JIDP73w4ZyVGuOENM5gdE+qNNUednOVSi052hcMRhS7zpVD0Rfl7vKKOU42F7Tl+cadVzjUl0ow/s=;", "From": "Landen Chao <landen.chao@mediatek.com>", "To": "<andrew@lunn.ch>, <f.fainelli@gmail.com>,\n\t<vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>,\n\t<robh+dt@kernel.org>, <mark.rutland@arm.com>", "CC": "<devicetree@vger.kernel.org>, <netdev@vger.kernel.org>,\n\t<linux-kernel@vger.kernel.org>,\n\t<linux-mediatek@lists.infradead.org>, <davem@davemloft.net>,\n\t<sean.wang@mediatek.com>, <opensource@vdorst.com>,\n\t<frank-w@public-files.de>, Landen Chao <landen.chao@mediatek.com>", "Subject": "[PATCH net-next 4/6] net: dsa: mt7530: Add the support of MT7531\n\tswitch", "Date": "Tue, 10 Dec 2019 16:14:40 +0800", "Message-ID": "<6d608dd024edc90b09ba4fe35417b693847f973c.1575914275.git.landen.chao@mediatek.com>", "X-Mailer": "git-send-email 2.18.0", "In-Reply-To": "<cover.1575914275.git.landen.chao@mediatek.com>", "References": "<cover.1575914275.git.landen.chao@mediatek.com>", "MIME-Version": "1.0", "Content-Type": "text/plain", "X-MTK": "N", "Content-Transfer-Encoding": "base64", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "Add new support for MT7531:\n\nMT7531 is the next generation of MT7530. It is also a 7-ports switch with\n5 giga embedded phys, 2 cpu ports, and the same MAC logic of MT7530. Cpu\nport 6 only supports HSGMII interface. Cpu port 5 supports either RGMII\nor HSGMII in different HW sku. Due to HSGMII interface support, pll, and\npad setting are different from MT7530. This patch adds different initial\nsetting of MT7531.\n\nSigned-off-by: Landen Chao <landen.chao@mediatek.com>\nSigned-off-by: Sean Wang <sean.wang@mediatek.com>\n---\n drivers/net/dsa/Kconfig | 6 +-\n drivers/net/dsa/mt7530.c | 643 ++++++++++++++++++++++++++++++++++++++-\n drivers/net/dsa/mt7530.h | 144 +++++++++\n 3 files changed, 784 insertions(+), 9 deletions(-)", "diff": "diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig\r\nindex 467f80157acf..a77709469093 100644\r\n--- a/drivers/net/dsa/Kconfig\r\n+++ b/drivers/net/dsa/Kconfig\r\n@@ -33,12 +33,12 @@ config NET_DSA_LANTIQ_GSWIP\r\n \t the xrx200 / VR9 SoC.\r\n \r\n config NET_DSA_MT7530\r\n-\ttristate \"MediaTek MT7530 and MT7621 Ethernet switch support\"\r\n+\ttristate \"MediaTek MT753x and MT7621 Ethernet switch support\"\r\n \tdepends on NET_DSA\r\n \tselect NET_DSA_TAG_MTK\r\n \t---help---\r\n-\t This enables support for the MediaTek MT7530 and MT7621 Ethernet\r\n-\t switch chip.\r\n+\t This enables support for the MediaTek MT7530, MT7531 and MT7621\r\n+\t Ethernet switch chip.\r\n \r\n config NET_DSA_MV88E6060\r\n \ttristate \"Marvell 88E6060 ethernet switch chip support\"\r\ndiff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c\r\nindex 9a648d1f5d09..4bee04d75b49 100644\r\n--- a/drivers/net/dsa/mt7530.c\r\n+++ b/drivers/net/dsa/mt7530.c\r\n@@ -285,6 +285,12 @@ mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)\r\n \tmutex_unlock(&bus->mdio_lock);\r\n }\r\n \r\n+static u32\r\n+_mt7530_unlocked_read(struct mt7530_dummy_poll *p)\r\n+{\r\n+\treturn mt7530_mii_read(p->priv, p->reg);\r\n+}\r\n+\r\n static u32\r\n _mt7530_read(struct mt7530_dummy_poll *p)\r\n {\r\n@@ -338,6 +344,102 @@ mt7530_clear(struct mt7530_priv *priv, u32 reg, u32 val)\r\n \tmt7530_rmw(priv, reg, val, 0);\r\n }\r\n \r\n+static int\r\n+mt7531_ind_mmd_phy_read(struct mt7530_priv *priv, int port, int devad,\r\n+\t\t\tint regnum)\r\n+{\r\n+\tstruct mii_bus *bus = priv->bus;\r\n+\tstruct mt7530_dummy_poll p;\r\n+\tu32 reg, val;\r\n+\tint ret;\r\n+\r\n+\tINIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);\r\n+\r\n+\tmutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);\r\n+\r\n+\tret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,\r\n+\t\t\t\t !(val & PHY_ACS_ST), 20, 100000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"poll timeout\\n\");\r\n+\t\tgoto out;\r\n+\t}\r\n+\r\n+\treg = MDIO_CL45_ADDR | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad) |\r\n+\t regnum;\r\n+\tmt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST);\r\n+\r\n+\tret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,\r\n+\t\t\t\t !(val & PHY_ACS_ST), 20, 100000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"poll timeout\\n\");\r\n+\t\tgoto out;\r\n+\t}\r\n+\r\n+\treg = MDIO_CL45_READ | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad);\r\n+\tmt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST);\r\n+\r\n+\tret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,\r\n+\t\t\t\t !(val & PHY_ACS_ST), 20, 100000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"poll timeout\\n\");\r\n+\t\tgoto out;\r\n+\t}\r\n+\r\n+\tret = val & MDIO_RW_DATA_MASK;\r\n+out:\r\n+\tmutex_unlock(&bus->mdio_lock);\r\n+\r\n+\treturn ret;\r\n+}\r\n+\r\n+static int\r\n+mt7531_ind_mmd_phy_write(struct mt7530_priv *priv, int port, int devad,\r\n+\t\t\t int regnum, u32 data)\r\n+{\r\n+\tstruct mii_bus *bus = priv->bus;\r\n+\tstruct mt7530_dummy_poll p;\r\n+\tu32 val, reg;\r\n+\tint ret;\r\n+\r\n+\tINIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);\r\n+\r\n+\tmutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);\r\n+\r\n+\tret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,\r\n+\t\t\t\t !(val & PHY_ACS_ST), 20, 100000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"poll timeout\\n\");\r\n+\t\tgoto out;\r\n+\t}\r\n+\r\n+\treg = MDIO_CL45_ADDR | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad) |\r\n+\t regnum;\r\n+\tmt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST);\r\n+\r\n+\tret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,\r\n+\t\t\t\t !(val & PHY_ACS_ST), 20, 100000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"poll timeout\\n\");\r\n+\t\tgoto out;\r\n+\t}\r\n+\r\n+\treg = MDIO_CL45_WRITE | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad) |\r\n+\t data;\r\n+\tmt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST);\r\n+\r\n+\tret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,\r\n+\t\t\t\t !(val & PHY_ACS_ST), 20, 100000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"poll timeout\\n\");\r\n+\t\tgoto out;\r\n+\t}\r\n+\r\n+out:\r\n+\tmutex_unlock(&bus->mdio_lock);\r\n+\r\n+\treturn ret;\r\n+}\r\n+\r\n static int\r\n mt7530_fdb_cmd(struct mt7530_priv *priv, enum mt7530_fdb_cmd cmd, u32 *rsp)\r\n {\r\n@@ -589,6 +691,83 @@ static int mt7530_phy_write(struct dsa_switch *ds, int port, int regnum,\r\n \treturn mdiobus_write_nested(priv->bus, port, regnum, val);\r\n }\r\n \r\n+static int\r\n+mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum)\r\n+{\r\n+\tstruct mt7530_priv *priv = ds->priv;\r\n+\tstruct mii_bus *bus = priv->bus;\r\n+\tstruct mt7530_dummy_poll p;\r\n+\tint ret;\r\n+\tu32 val;\r\n+\r\n+\tINIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);\r\n+\r\n+\tmutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);\r\n+\r\n+\tret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,\r\n+\t\t\t\t !(val & PHY_ACS_ST), 20, 100000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"poll timeout\\n\");\r\n+\t\tgoto out;\r\n+\t}\r\n+\r\n+\tval = MDIO_CL22_READ | MDIO_PHY_ADDR(port) | MDIO_REG_ADDR(regnum);\r\n+\r\n+\tmt7530_mii_write(priv, MT7531_PHY_IAC, val | PHY_ACS_ST);\r\n+\r\n+\tret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,\r\n+\t\t\t\t !(val & PHY_ACS_ST), 20, 100000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"poll timeout\\n\");\r\n+\t\tgoto out;\r\n+\t}\r\n+\r\n+\tret = val & MDIO_RW_DATA_MASK;\r\n+out:\r\n+\tmutex_unlock(&bus->mdio_lock);\r\n+\r\n+\treturn ret;\r\n+}\r\n+\r\n+static int\r\n+mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum,\r\n+\t\t u16 data)\r\n+{\r\n+\tstruct mt7530_priv *priv = ds->priv;\r\n+\tstruct mii_bus *bus = priv->bus;\r\n+\tstruct mt7530_dummy_poll p;\r\n+\tint ret;\r\n+\tu32 reg;\r\n+\r\n+\tINIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);\r\n+\r\n+\tmutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);\r\n+\r\n+\tret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,\r\n+\t\t\t\t !(reg & PHY_ACS_ST), 20, 100000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"poll timeout\\n\");\r\n+\t\tgoto out;\r\n+\t}\r\n+\r\n+\treg = MDIO_CL22_WRITE | MDIO_PHY_ADDR(port) | MDIO_REG_ADDR(regnum) |\r\n+\t data;\r\n+\r\n+\tmt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST);\r\n+\r\n+\tret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,\r\n+\t\t\t\t !(reg & PHY_ACS_ST), 20, 100000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"poll timeout\\n\");\r\n+\t\tgoto out;\r\n+\t}\r\n+\r\n+out:\r\n+\tmutex_unlock(&bus->mdio_lock);\r\n+\r\n+\treturn ret;\r\n+}\r\n+\r\n static void\r\n mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset,\r\n \t\t uint8_t *data)\r\n@@ -1380,6 +1559,86 @@ mt7530_setup(struct dsa_switch *ds)\r\n \treturn 0;\r\n }\r\n \r\n+static int mt7531_setup(struct dsa_switch *ds)\r\n+{\r\n+\tstruct mt7530_priv *priv = ds->priv;\r\n+\tstruct mt7530_dummy_poll p;\r\n+\tu32 val, id;\r\n+\tint ret, i;\r\n+\r\n+\t/* Reset whole chip through gpio pin or memory-mapped registers for\r\n+\t * different type of hardware\r\n+\t */\r\n+\tif (priv->mcm) {\r\n+\t\treset_control_assert(priv->rstc);\r\n+\t\tusleep_range(1000, 1100);\r\n+\t\treset_control_deassert(priv->rstc);\r\n+\t} else {\r\n+\t\tgpiod_set_value_cansleep(priv->reset, 0);\r\n+\t\tusleep_range(1000, 1100);\r\n+\t\tgpiod_set_value_cansleep(priv->reset, 1);\r\n+\t}\r\n+\r\n+\t/* Waiting for MT7530 got to stable */\r\n+\tINIT_MT7530_DUMMY_POLL(&p, priv, MT7530_HWTRAP);\r\n+\tret = readx_poll_timeout(_mt7530_read, &p, val, val != 0,\r\n+\t\t\t\t 20, 1000000);\r\n+\tif (ret < 0) {\r\n+\t\tdev_err(priv->dev, \"reset timeout\\n\");\r\n+\t\treturn ret;\r\n+\t}\r\n+\r\n+\tid = mt7530_read(priv, MT7531_CREV);\r\n+\tid >>= CHIP_NAME_SHIFT;\r\n+\r\n+\tif (id != MT7531_ID) {\r\n+\t\tdev_err(priv->dev, \"chip %x can't be supported\\n\", id);\r\n+\t\treturn -ENODEV;\r\n+\t}\r\n+\r\n+\t/* Reset the switch through internal reset */\r\n+\tmt7530_write(priv, MT7530_SYS_CTRL,\r\n+\t\t SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |\r\n+\t\t SYS_CTRL_REG_RST);\r\n+\r\n+\tpriv->p6_interface = PHY_INTERFACE_MODE_NA;\r\n+\r\n+\t/* Enable PHY power, since phy_device has not yet been created\r\n+\t * provided for phy_[read,write]_mmd_indirect is called, we provide\r\n+\t * our own mt7531_ind_mmd_phy_[read,write] to complete this\r\n+\t * function.\r\n+\t */\r\n+\tval = mt7531_ind_mmd_phy_read(priv, 0, PHY_DEV1F,\r\n+\t\t\t\t MT7531_PHY_DEV1F_REG_403);\r\n+\tval |= MT7531_PHY_EN_BYPASS_MODE;\r\n+\tval &= ~MT7531_PHY_POWER_OFF;\r\n+\tmt7531_ind_mmd_phy_write(priv, 0, PHY_DEV1F,\r\n+\t\t\t\t MT7531_PHY_DEV1F_REG_403, val);\r\n+\r\n+\t/* Enable and reset MIB counters */\r\n+\tmt7530_mib_reset(ds);\r\n+\r\n+\tmt7530_clear(priv, MT7530_MFC, UNU_FFP_MASK);\r\n+\r\n+\tfor (i = 0; i < MT7530_NUM_PORTS; i++) {\r\n+\t\t/* Disable forwarding by default on all ports */\r\n+\t\tmt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,\r\n+\t\t\t PCR_MATRIX_CLR);\r\n+\r\n+\t\tif (dsa_is_cpu_port(ds, i))\r\n+\t\t\tmt7530_cpu_port_enable(priv, i);\r\n+\t\telse\r\n+\t\t\tmt7530_port_disable(ds, i);\r\n+\t}\r\n+\r\n+\t/* Flush the FDB table */\r\n+\tret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);\r\n+\tif (ret < 0)\r\n+\t\treturn ret;\r\n+\r\n+\treturn 0;\r\n+}\r\n+\r\n static bool mt7530_phy_supported(struct dsa_switch *ds, int port,\r\n \t\t\t\t const struct phylink_link_state *state)\r\n {\r\n@@ -1417,6 +1676,49 @@ static bool mt7530_phy_supported(struct dsa_switch *ds, int port,\r\n \treturn false;\r\n }\r\n \r\n+static bool mt7531_dual_sgmii_supported(struct mt7530_priv *priv)\r\n+{\r\n+\tu32 val;\r\n+\r\n+\tval = mt7530_read(priv, MT7531_TOP_SIG_SR);\r\n+\treturn ((val & PAD_DUAL_SGMII_EN) != 0);\r\n+}\r\n+\r\n+static bool mt7531_phy_supported(struct dsa_switch *ds, int port,\r\n+\t\t\t\t const struct phylink_link_state *state)\r\n+{\r\n+\tstruct mt7530_priv *priv = ds->priv;\r\n+\r\n+\tswitch (port) {\r\n+\tcase 0: /* Internal phy */\r\n+\tcase 1:\r\n+\tcase 2:\r\n+\tcase 3:\r\n+\tcase 4:\r\n+\t\tif (state->interface != PHY_INTERFACE_MODE_GMII)\r\n+\t\t\tgoto unsupported;\r\n+\t\tbreak;\r\n+\tcase 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */\r\n+\t\tif (!mt7531_dual_sgmii_supported(priv))\r\n+\t\t\treturn phy_interface_mode_is_rgmii(state->interface);\r\n+\t\t/* fall through */\r\n+\tcase 6: /* 1st cpu port supports sgmii/8023z only */\r\n+\t\tif (state->interface != PHY_INTERFACE_MODE_SGMII &&\r\n+\t\t !phy_interface_mode_is_8023z(state->interface))\r\n+\t\t\tgoto unsupported;\r\n+\t\tbreak;\r\n+\tdefault:\r\n+\t\tdev_err(priv->dev, \"%s: unsupported port: %i\\n\", __func__,\r\n+\t\t\tport);\r\n+\t\tgoto unsupported;\r\n+\t}\r\n+\r\n+\treturn true;\r\n+\r\n+unsupported:\r\n+\treturn false;\r\n+}\r\n+\r\n static bool mt753x_phy_supported(struct dsa_switch *ds, int port,\r\n \t\t\t\t const struct phylink_link_state *state)\r\n {\r\n@@ -1444,6 +1746,143 @@ mt7530_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state)\r\n \treturn 0;\r\n }\r\n \r\n+static int\r\n+mt7531_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state)\r\n+{\r\n+\tstruct mt7530_priv *priv = ds->priv;\r\n+\tu32 xtal, val;\r\n+\r\n+\tif (mt7531_dual_sgmii_supported(priv))\r\n+\t\treturn 0;\r\n+\r\n+\txtal = mt7530_read(priv, MT7531_HWTRAP) & HWTRAP_XTAL_FSEL_MASK;\r\n+\r\n+\tswitch (xtal) {\r\n+\tcase HWTRAP_XTAL_FSEL_25MHZ:\r\n+\t\t/* Step 1 : Disable MT7531 COREPLL */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_EN);\r\n+\t\tval &= ~EN_COREPLL;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_EN, val);\r\n+\r\n+\t\t/* Step 2: switch to XTAL output */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_EN);\r\n+\t\tval |= SW_CLKSW;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_EN, val);\r\n+\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval &= ~RG_COREPLL_EN;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\r\n+\t\t/* Step 3: disable PLLGP and enable program PLLGP */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_EN);\r\n+\t\tval |= SW_PLLGP;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_EN, val);\r\n+\r\n+\t\t/* Step 4: program COREPLL output frequency to 500MHz */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval &= ~RG_COREPLL_POSDIV_M;\r\n+\t\tval |= 2 << RG_COREPLL_POSDIV_S;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\t\tusleep_range(25, 35);\r\n+\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval &= ~RG_COREPLL_SDM_PCW_M;\r\n+\t\tval |= 0x140000 << RG_COREPLL_SDM_PCW_S;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\r\n+\t\t/* Set feedback divide ratio update signal to high */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval |= RG_COREPLL_SDM_PCW_CHG;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\t\t/* Wait for at least 16 XTAL clocks */\r\n+\t\tusleep_range(10, 20);\r\n+\r\n+\t\t/* Step 5: set feedback divide ratio update signal to low */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval &= ~RG_COREPLL_SDM_PCW_CHG;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\r\n+\t\t/* Enable 325M clock for SGMII */\r\n+\t\tmt7530_write(priv, MT7531_ANA_PLLGP_CR5, 0xad0000);\r\n+\r\n+\t\t/* Enable 250SSC clock for RGMII */\r\n+\t\tmt7530_write(priv, MT7531_ANA_PLLGP_CR2, 0x4f40000);\r\n+\r\n+\t\t/* Step 6: Enable MT7531 PLL */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval |= RG_COREPLL_EN;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_EN);\r\n+\t\tval |= EN_COREPLL;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_EN, val);\r\n+\t\tusleep_range(25, 35);\r\n+\t\tbreak;\r\n+\tcase HWTRAP_XTAL_FSEL_40MHZ:\r\n+\t\t/* Step 1 : Disable MT7531 COREPLL */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_EN);\r\n+\t\tval &= ~EN_COREPLL;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_EN, val);\r\n+\r\n+\t\t/* Step 2: switch to XTAL output */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_EN);\r\n+\t\tval |= SW_CLKSW;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_EN, val);\r\n+\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval &= ~RG_COREPLL_EN;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\r\n+\t\t/* Step 3: disable PLLGP and enable program PLLGP */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_EN);\r\n+\t\tval |= SW_PLLGP;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_EN, val);\r\n+\r\n+\t\t/* Step 4: program COREPLL output frequency to 500MHz */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval &= ~RG_COREPLL_POSDIV_M;\r\n+\t\tval |= 2 << RG_COREPLL_POSDIV_S;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\t\tusleep_range(25, 35);\r\n+\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval &= ~RG_COREPLL_SDM_PCW_M;\r\n+\t\tval |= 0x190000 << RG_COREPLL_SDM_PCW_S;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\r\n+\t\t/* Set feedback divide ratio update signal to high */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval |= RG_COREPLL_SDM_PCW_CHG;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\t\t/* Wait for at least 16 XTAL clocks */\r\n+\t\tusleep_range(10, 20);\r\n+\r\n+\t\t/* Step 5: set feedback divide ratio update signal to low */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval &= ~RG_COREPLL_SDM_PCW_CHG;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\r\n+\t\t/* Enable 325M clock for SGMII */\r\n+\t\tmt7530_write(priv, MT7531_ANA_PLLGP_CR5, 0xad0000);\r\n+\r\n+\t\t/* Enable 250SSC clock for RGMII */\r\n+\t\tmt7530_write(priv, MT7531_ANA_PLLGP_CR2, 0x4f40000);\r\n+\r\n+\t\t/* Step 6: Enable MT7531 PLL */\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_CR0);\r\n+\t\tval |= RG_COREPLL_EN;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_CR0, val);\r\n+\r\n+\t\tval = mt7530_read(priv, MT7531_PLLGP_EN);\r\n+\t\tval |= EN_COREPLL;\r\n+\t\tmt7530_write(priv, MT7531_PLLGP_EN, val);\r\n+\t\tusleep_range(25, 35);\r\n+\t\tbreak;\r\n+\t}\r\n+\r\n+\treturn 0;\r\n+}\r\n+\r\n static int\r\n mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state)\r\n {\r\n@@ -1467,6 +1906,149 @@ mt7530_mac_setup(struct dsa_switch *ds, int port, unsigned int mode,\r\n \treturn 0;\r\n }\r\n \r\n+static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port)\r\n+{\r\n+\tu32 val;\r\n+\r\n+\tif (port != 5) {\r\n+\t\tdev_err(priv->dev, \"RGMII mode is not available for port %d\\n\",\r\n+\t\t\tport);\r\n+\t\treturn -EINVAL;\r\n+\t}\r\n+\r\n+\tval = mt7530_read(priv, MT7531_CLKGEN_CTRL);\r\n+\tval |= GP_CLK_EN;\r\n+\tval &= ~GP_MODE_MASK;\r\n+\tval |= GP_MODE(MT7531_GP_MODE_RGMII);\r\n+\tval |= TXCLK_NO_REVERSE;\r\n+\tval |= RXCLK_NO_DELAY;\r\n+\tval &= ~CLK_SKEW_IN_MASK;\r\n+\tval |= CLK_SKEW_IN(MT7531_CLK_SKEW_NO_CHG);\r\n+\tval &= ~CLK_SKEW_OUT_MASK;\r\n+\tval |= CLK_SKEW_OUT(MT7531_CLK_SKEW_NO_CHG);\r\n+\tmt7530_write(priv, MT7531_CLKGEN_CTRL, val);\r\n+\r\n+\treturn 0;\r\n+}\r\n+\r\n+static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port,\r\n+\t\t\t\t\t const struct phylink_link_state *state)\r\n+{\r\n+\tu32 val;\r\n+\r\n+\tif (port != 5 && port != 6)\r\n+\t\treturn -EINVAL;\r\n+\r\n+\tval = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port));\r\n+\tval |= MT7531_SGMII_PHYA_PWD;\r\n+\tmt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val);\r\n+\r\n+\tval = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port));\r\n+\tval &= ~MT7531_RG_TPHY_SPEED_MASK;\r\n+\tif (state->interface == PHY_INTERFACE_MODE_2500BASEX)\r\n+\t\tval |= MT7531_RG_TPHY_SPEED_3_125G;\r\n+\tmt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val);\r\n+\r\n+\tval = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));\r\n+\tval &= ~MT7531_SGMII_AN_ENABLE;\r\n+\tmt7530_write(priv, MT7531_PCS_CONTROL_1(port), val);\r\n+\r\n+\tval = mt7530_read(priv, MT7531_SGMII_MODE(port));\r\n+\tval &= ~MT7531_SGMII_IF_MODE_MASK;\r\n+\r\n+\tswitch (state->speed) {\r\n+\tcase SPEED_10:\r\n+\t\tval |= MT7531_SGMII_FORCE_SPEED_10;\r\n+\t\tbreak;\r\n+\tcase SPEED_100:\r\n+\t\tval |= MT7531_SGMII_FORCE_SPEED_100;\r\n+\t\tbreak;\r\n+\tcase SPEED_2500:\r\n+\tcase SPEED_1000:\r\n+\t\tval |= MT7531_SGMII_FORCE_SPEED_1000;\r\n+\t\tbreak;\r\n+\t};\r\n+\r\n+\tval &= ~MT7531_SGMII_FORCE_DUPLEX;\r\n+\t/* For sgmii force mode, 0 is full duplex and 1 is half duplex */\r\n+\tif (state->duplex == DUPLEX_HALF)\r\n+\t\tval |= MT7531_SGMII_FORCE_DUPLEX;\r\n+\r\n+\tmt7530_write(priv, MT7531_SGMII_MODE(port), val);\r\n+\r\n+\tval = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port));\r\n+\tval &= ~MT7531_SGMII_PHYA_PWD;\r\n+\tmt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val);\r\n+\r\n+\treturn 0;\r\n+}\r\n+\r\n+static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port,\r\n+\t\t\t\t const struct phylink_link_state *state)\r\n+{\r\n+\tu32 val;\r\n+\r\n+\tif (port != 5 && port != 6)\r\n+\t\treturn -EINVAL;\r\n+\r\n+\tval = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port));\r\n+\tval |= MT7531_SGMII_PHYA_PWD;\r\n+\tmt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val);\r\n+\r\n+\tswitch (state->speed) {\r\n+\tcase SPEED_10:\r\n+\tcase SPEED_100:\r\n+\tcase SPEED_1000:\r\n+\t\tval = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port));\r\n+\t\tval &= ~MT7531_RG_TPHY_SPEED_MASK;\r\n+\t\tmt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val);\r\n+\t\tbreak;\r\n+\tdefault:\r\n+\t\tdev_info(priv->dev, \"invalid SGMII speed idx %d for port %d\\n\",\r\n+\t\t\t state->speed, port);\r\n+\r\n+\t\treturn -EINVAL;\r\n+\t}\r\n+\r\n+\tval = mt7530_read(priv, MT7531_SGMII_MODE(port));\r\n+\tval |= MT7531_SGMII_REMOTE_FAULT_DIS;\r\n+\tmt7530_write(priv, MT7531_SGMII_MODE(port), val);\r\n+\r\n+\tval = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));\r\n+\tval |= MT7531_SGMII_AN_RESTART;\r\n+\tmt7530_write(priv, MT7531_PCS_CONTROL_1(port), val);\r\n+\r\n+\tval = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port));\r\n+\tval &= ~MT7531_SGMII_PHYA_PWD;\r\n+\tmt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val);\r\n+\r\n+\treturn 0;\r\n+}\r\n+\r\n+static int\r\n+mt7531_mac_setup(struct dsa_switch *ds, int port, unsigned int mode,\r\n+\t\t const struct phylink_link_state *state)\r\n+{\r\n+\tstruct mt7530_priv *priv = ds->priv;\r\n+\r\n+\tif (port < 5 || port >= MT7530_NUM_PORTS) {\r\n+\t\tdev_err(priv->dev, \"port %d is not a MAC port\\n\", port);\r\n+\t\treturn -EINVAL;\r\n+\t}\r\n+\r\n+\tswitch (state->interface) {\r\n+\tcase PHY_INTERFACE_MODE_RGMII:\r\n+\t\treturn mt7531_rgmii_setup(priv, port);\r\n+\tcase PHY_INTERFACE_MODE_1000BASEX:\r\n+\tcase PHY_INTERFACE_MODE_2500BASEX:\r\n+\t\treturn mt7531_sgmii_setup_mode_force(priv, port, state);\r\n+\tcase PHY_INTERFACE_MODE_SGMII:\r\n+\t\treturn mt7531_sgmii_setup_mode_an(priv, port, state);\r\n+\tdefault:\r\n+\t\treturn -EINVAL;\r\n+\t}\r\n+}\r\n+\r\n static int mt753x_mac_setup(struct dsa_switch *ds, int port, unsigned int mode,\r\n \t\t\t const struct phylink_link_state *state)\r\n {\r\n@@ -1501,6 +2083,8 @@ static void mt753x_phylink_mac_config(struct dsa_switch *ds, int port,\r\n \t\tif (mt753x_mac_setup(ds, port, mode, state) < 0)\r\n \t\t\tgoto unsupported;\r\n \r\n+\t\tpriv->p5_interface = state->interface;\r\n+\r\n \t\tbreak;\r\n \tcase 6: /* 1st cpu port */\r\n \t\tif (priv->p6_interface == state->interface)\r\n@@ -1515,11 +2099,11 @@ static void mt753x_phylink_mac_config(struct dsa_switch *ds, int port,\r\n \t\tbreak;\r\n \tdefault:\r\n unsupported:\r\n-\t\tdev_err(ds->dev, \"%s: unsupported port: %i\\n\", __func__, port);\r\n \t\treturn;\r\n \t}\r\n \r\n-\tif (phylink_autoneg_inband(mode)) {\r\n+\tif (phylink_autoneg_inband(mode) &&\r\n+\t state->interface != PHY_INTERFACE_MODE_SGMII) {\r\n \t\tdev_err(ds->dev, \"%s: in-band negotiation unsupported\\n\",\r\n \t\t\t__func__);\r\n \t\treturn;\r\n@@ -1530,13 +2114,15 @@ static void mt753x_phylink_mac_config(struct dsa_switch *ds, int port,\r\n \tmcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 |\r\n \t\t PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN);\r\n \tmcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN |\r\n-\t\t PMCR_BACKPR_EN | PMCR_FORCE_MODE | PMCR_FORCE_LNK;\r\n+\t\t PMCR_BACKPR_EN | PMCR_FORCE_MODE_ID(priv->id) |\r\n+\t\t PMCR_FORCE_LNK;\r\n \r\n \t/* Are we connected to external phy */\r\n \tif (port == 5 && dsa_is_user_port(ds, 5))\r\n \t\tmcr_new |= PMCR_EXT_PHY;\r\n \r\n \tswitch (state->speed) {\r\n+\tcase SPEED_2500:\r\n \tcase SPEED_1000:\r\n \t\tmcr_new |= PMCR_FORCE_SPEED_1000;\r\n \t\tbreak;\r\n@@ -1556,6 +2142,27 @@ static void mt753x_phylink_mac_config(struct dsa_switch *ds, int port,\r\n \t\tmt7530_write(priv, MT7530_PMCR_P(port), mcr_new);\r\n }\r\n \r\n+void mt7531_sgmii_restart_an(struct dsa_switch *ds, int port)\r\n+{\r\n+\tstruct mt7530_priv *priv = ds->priv;\r\n+\tu32 val;\r\n+\r\n+\tval = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));\r\n+\tval |= MT7531_SGMII_AN_RESTART;\r\n+\tmt7530_write(priv, MT7531_PCS_CONTROL_1(port), val);\r\n+}\r\n+\r\n+static void\r\n+mt753x_phylink_mac_an_restart(struct dsa_switch *ds, int port)\r\n+{\r\n+\tstruct mt7530_priv *priv = ds->priv;\r\n+\r\n+\tif (!priv->info->port_an_restart)\r\n+\t\treturn;\r\n+\r\n+\tpriv->info->port_an_restart(ds, port);\r\n+}\r\n+\r\n static void mt7530_phylink_mac_link_down(struct dsa_switch *ds, int port,\r\n \t\t\t\t\t unsigned int mode,\r\n \t\t\t\t\t phy_interface_t interface)\r\n@@ -1590,9 +2197,20 @@ static void mt753x_phylink_validate(struct dsa_switch *ds, int port,\r\n \tphylink_set_port_modes(mask);\r\n \tphylink_set(mask, Autoneg);\r\n \r\n-\tif (state->interface == PHY_INTERFACE_MODE_TRGMII) {\r\n+\tswitch (state->interface) {\r\n+\tcase PHY_INTERFACE_MODE_TRGMII:\r\n \t\tphylink_set(mask, 1000baseT_Full);\r\n-\t} else {\r\n+\t\tbreak;\r\n+\tcase PHY_INTERFACE_MODE_1000BASEX:\r\n+\tcase PHY_INTERFACE_MODE_2500BASEX:\r\n+\t\tphylink_set(mask, 1000baseX_Full);\r\n+\t\tphylink_set(mask, 2500baseX_Full);\r\n+\t\tbreak;\r\n+\tcase PHY_INTERFACE_MODE_SGMII:\r\n+\t\tphylink_set(mask, 1000baseT_Full);\r\n+\t\tphylink_set(mask, 1000baseX_Full);\r\n+\t\t/* fall through */\r\n+\tdefault:\r\n \t\tphylink_set(mask, 10baseT_Half);\r\n \t\tphylink_set(mask, 10baseT_Full);\r\n \t\tphylink_set(mask, 100baseT_Half);\r\n@@ -1604,6 +2222,7 @@ static void mt753x_phylink_validate(struct dsa_switch *ds, int port,\r\n \t\t\tif (port == 5)\r\n \t\t\t\tphylink_set(mask, 1000baseX_Full);\r\n \t\t}\r\n+\t\tbreak;\r\n \t}\r\n \r\n \tphylink_set(mask, Pause);\r\n@@ -1698,8 +2317,9 @@ static const struct dsa_switch_ops mt7530_switch_ops = {\r\n \t.port_vlan_add\t\t= mt7530_port_vlan_add,\r\n \t.port_vlan_del\t\t= mt7530_port_vlan_del,\r\n \t.phylink_validate\t= mt753x_phylink_validate,\r\n-\t.phylink_mac_link_state = mt7530_phylink_mac_link_state,\r\n+\t.phylink_mac_link_state\t= mt7530_phylink_mac_link_state,\r\n \t.phylink_mac_config\t= mt753x_phylink_mac_config,\r\n+\t.phylink_mac_an_restart\t= mt753x_phylink_mac_an_restart,\r\n \t.phylink_mac_link_down\t= mt7530_phylink_mac_link_down,\r\n \t.phylink_mac_link_up\t= mt7530_phylink_mac_link_up,\r\n };\r\n@@ -1723,11 +2343,22 @@ static const struct mt753x_info mt753x_table[] = {\r\n \t\t.pad_setup = mt7530_pad_setup,\r\n \t\t.mac_setup = mt7530_mac_setup,\r\n \t},\r\n+\t[ID_MT7531] = {\r\n+\t\t.id = ID_MT7531,\r\n+\t\t.setup = mt7531_setup,\r\n+\t\t.phy_read = mt7531_ind_phy_read,\r\n+\t\t.phy_write = mt7531_ind_phy_write,\r\n+\t\t.phy_supported = mt7531_phy_supported,\r\n+\t\t.pad_setup = mt7531_pad_setup,\r\n+\t\t.mac_setup = mt7531_mac_setup,\r\n+\t\t.port_an_restart = mt7531_sgmii_restart_an,\r\n+\t},\r\n };\r\n \r\n static const struct of_device_id mt7530_of_match[] = {\r\n \t{ .compatible = \"mediatek,mt7621\", .data = &mt753x_table[ID_MT7621], },\r\n \t{ .compatible = \"mediatek,mt7530\", .data = &mt753x_table[ID_MT7530], },\r\n+\t{ .compatible = \"mediatek,mt7531\", .data = &mt753x_table[ID_MT7531], },\r\n \t{ /* sentinel */ },\r\n };\r\n MODULE_DEVICE_TABLE(of, mt7530_of_match);\r\ndiff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h\r\nindex aac86e4fc148..557328c6c032 100644\r\n--- a/drivers/net/dsa/mt7530.h\r\n+++ b/drivers/net/dsa/mt7530.h\r\n@@ -14,6 +14,7 @@\r\n enum mt753x_id {\r\n \tID_MT7530 = 0,\r\n \tID_MT7621 = 1,\r\n+\tID_MT7531 = 2,\r\n };\r\n \r\n #define\tNUM_TRGMII_CTRL\t\t\t5\r\n@@ -201,6 +202,19 @@ enum mt7530_vlan_port_attr {\r\n #define PMCR_FORCE_LNK\t\t\tBIT(0)\r\n #define PMCR_SPEED_MASK\t\t(PMCR_FORCE_SPEED_100 | \\\r\n \t\t\t\t\t PMCR_FORCE_SPEED_1000)\r\n+#define MT7531_FORCE_LNK\t\tBIT(31)\r\n+#define MT7531_FORCE_SPD\t\tBIT(30)\r\n+#define MT7531_FORCE_DPX\t\tBIT(29)\r\n+#define MT7531_FORCE_RX_FC\t\tBIT(28)\r\n+#define MT7531_FORCE_TX_FC\t\tBIT(27)\r\n+#define MT7531_FORCE_MODE\t\t(MT7531_FORCE_LNK | \\\r\n+\t\t\t\t\t MT7531_FORCE_SPD | \\\r\n+\t\t\t\t\t MT7531_FORCE_DPX | \\\r\n+\t\t\t\t\t MT7531_FORCE_RX_FC | \\\r\n+\t\t\t\t\t MT7531_FORCE_TX_FC)\r\n+#define PMCR_FORCE_MODE_ID(id)\t\t(((id) == ID_MT7531) ? \\\r\n+\t\t\t\t\t MT7531_FORCE_MODE : \\\r\n+\t\t\t\t\t PMCR_FORCE_MODE)\r\n \r\n #define MT7530_PMSR_P(x)\t\t(0x3008 + (x) * 0x100)\r\n #define PMSR_EEE1G\t\t\tBIT(7)\r\n@@ -231,12 +245,111 @@ enum mt7530_vlan_port_attr {\r\n \t\t\t\t\t CCR_RX_OCT_CNT_BAD | \\\r\n \t\t\t\t\t CCR_TX_OCT_CNT_GOOD | \\\r\n \t\t\t\t\t CCR_TX_OCT_CNT_BAD)\r\n+\r\n+/* SGMII registers */\r\n+#define MT7531_SGMII_REG_BASE\t\t0x5000\r\n+#define MT7531_SGMII_REG(p, r)\t\t(MT7531_SGMII_REG_BASE + \\\r\n+\t\t\t\t\t((p) - 5) * 0x1000 + (r))\r\n+\r\n+/* SGMII PCS_CONTROL_1 */\r\n+#define MT7531_PCS_CONTROL_1(p)\t\tMT7531_SGMII_REG(p, 0x00)\r\n+#define MT7531_SGMII_LINK_STATUS\tBIT(18)\r\n+#define MT7531_SGMII_AN_ENABLE\t\tBIT(12)\r\n+#define MT7531_SGMII_AN_RESTART\tBIT(9)\r\n+\r\n+/* Fields of SGMII_MODE */\r\n+#define MT7531_SGMII_MODE(p)\t\tMT7531_SGMII_REG(p, 0x20)\r\n+#define MT7531_SGMII_REMOTE_FAULT_DIS\tBIT(8)\r\n+#define MT7531_SGMII_FORCE_DUPLEX\tBIT(4)\r\n+#define MT7531_SGMII_IF_MODE_MASK\tGENMASK(5, 1)\r\n+#define MT7531_SGMII_FORCE_SPEED_10\t0x0\r\n+#define MT7531_SGMII_FORCE_SPEED_100\tBIT(2)\r\n+#define MT7531_SGMII_FORCE_SPEED_1000\tBIT(3)\r\n+\r\n+/* Fields of QPHY_PWR_STATE_CTRL */\r\n+#define MT7531_QPHY_PWR_STATE_CTRL(p)\tMT7531_SGMII_REG(p, 0xe8)\r\n+#define MT7531_SGMII_PHYA_PWD\t\tBIT(4)\r\n+\r\n+/* Values of SGMII SPEED */\r\n+#define MT7531_PHYA_CTRL_SIGNAL3(p)\tMT7531_SGMII_REG(p, 0x128)\r\n+#define MT7531_RG_TPHY_SPEED_MASK\t(BIT(2) | BIT(3))\r\n+#define MT7531_RG_TPHY_SPEED_1_25G\t0x0\r\n+#define MT7531_RG_TPHY_SPEED_3_125G\tBIT(2)\r\n+\r\n /* Register for system reset */\r\n #define MT7530_SYS_CTRL\t\t\t0x7000\r\n #define SYS_CTRL_PHY_RST\t\tBIT(2)\r\n #define SYS_CTRL_SW_RST\t\tBIT(1)\r\n #define SYS_CTRL_REG_RST\t\tBIT(0)\r\n \r\n+/* Register for PHY Indirect Access Control */\r\n+#define MT7531_PHY_IAC\t\t\t0x701C\r\n+#define PHY_ACS_ST\t\t\tBIT(31)\r\n+#define MDIO_REG_ADDR_MASK\t\t(0x1f << 25)\r\n+#define MDIO_PHY_ADDR_MASK\t\t(0x1f << 20)\r\n+#define MDIO_CMD_MASK\t\t\t(0x3 << 18)\r\n+#define MDIO_ST_MASK\t\t\t(0x3 << 16)\r\n+#define MDIO_RW_DATA_MASK\t\t(0xffff)\r\n+#define MDIO_REG_ADDR(x)\t\t(((x) & 0x1f) << 25)\r\n+#define MDIO_DEV_ADDR(x)\t\t(((x) & 0x1f) << 25)\r\n+#define MDIO_PHY_ADDR(x)\t\t(((x) & 0x1f) << 20)\r\n+#define MDIO_CMD(x)\t\t\t(((x) & 0x3) << 18)\r\n+#define MDIO_ST(x)\t\t\t(((x) & 0x3) << 16)\r\n+\r\n+enum mt7531_phy_iac_cmd {\r\n+\tMT7531_MDIO_ADDR = 0,\r\n+\tMT7531_MDIO_WRITE = 1,\r\n+\tMT7531_MDIO_READ = 2,\r\n+\tMT7531_MDIO_READ_CL45 = 3,\r\n+};\r\n+\r\n+/* MDIO_ST: MDIO start field */\r\n+enum mt7531_mdio_st {\r\n+\tMT7531_MDIO_ST_CL45 = 0,\r\n+\tMT7531_MDIO_ST_CL22 = 1,\r\n+};\r\n+\r\n+#define MDIO_CL22_READ\t\t\t(MDIO_ST(MT7531_MDIO_ST_CL22) | \\\r\n+\t\t\t\t\t MDIO_CMD(MT7531_MDIO_READ))\r\n+#define MDIO_CL22_WRITE\t\t(MDIO_ST(MT7531_MDIO_ST_CL22) | \\\r\n+\t\t\t\t\t MDIO_CMD(MT7531_MDIO_WRITE))\r\n+#define MDIO_CL45_ADDR\t\t\t(MDIO_ST(MT7531_MDIO_ST_CL45) | \\\r\n+\t\t\t\t\t MDIO_CMD(MT7531_MDIO_ADDR))\r\n+#define MDIO_CL45_READ\t\t\t(MDIO_ST(MT7531_MDIO_ST_CL45) | \\\r\n+\t\t\t\t\t MDIO_CMD(MT7531_MDIO_READ))\r\n+#define MDIO_CL45_WRITE\t\t(MDIO_ST(MT7531_MDIO_ST_CL45) | \\\r\n+\t\t\t\t\t MDIO_CMD(MT7531_MDIO_WRITE))\r\n+\r\n+#define MT7531_CLKGEN_CTRL\t\t0x7500\r\n+#define CLK_SKEW_OUT(x)\t\t(((x) & 0x3) << 8)\r\n+#define CLK_SKEW_OUT_MASK\t\t(0x3 << 8)\r\n+#define CLK_SKEW_IN(x)\t\t\t(((x) & 0x3) << 6)\r\n+#define CLK_SKEW_IN_MASK\t\t(0x3 << 6)\r\n+#define RXCLK_NO_DELAY\t\t\tBIT(5)\r\n+#define TXCLK_NO_REVERSE\t\tBIT(4)\r\n+#define GP_MODE(x)\t\t\t(((x) & 0x3) << 1)\r\n+#define GP_MODE_MASK\t\t\t(0x3 << 1)\r\n+#define GP_CLK_EN\t\t\tBIT(0)\r\n+\r\n+#define PHY_DEV1F\t\t\t0x1f\r\n+#define MT7531_PHY_DEV1F_REG_403\t0x403\r\n+\r\n+#define MT7531_PHY_EN_BYPASS_MODE\tBIT(4)\r\n+#define MT7531_PHY_POWER_OFF\t\tBIT(5)\r\n+\r\n+enum mt7531_gp_mode {\r\n+\tMT7531_GP_MODE_RGMII = 0,\r\n+\tMT7531_GP_MODE_MII = 1,\r\n+\tMT7531_GP_MODE_REV_MII = 2\r\n+};\r\n+\r\n+enum mt7531_clk_skew {\r\n+\tMT7531_CLK_SKEW_NO_CHG = 0,\r\n+\tMT7531_CLK_SKEW_DLY_100PPS = 1,\r\n+\tMT7531_CLK_SKEW_DLY_200PPS = 2,\r\n+\tMT7531_CLK_SKEW_REVERSE = 3,\r\n+};\r\n+\r\n /* Register for hw trap status */\r\n #define MT7530_HWTRAP\t\t\t0x7800\r\n #define HWTRAP_XTAL_MASK\t\t(BIT(10) | BIT(9))\r\n@@ -244,6 +357,11 @@ enum mt7530_vlan_port_attr {\r\n #define HWTRAP_XTAL_40MHZ\t\t(BIT(10))\r\n #define HWTRAP_XTAL_20MHZ\t\t(BIT(9))\r\n \r\n+#define MT7531_HWTRAP\t\t\t0x7800\r\n+#define HWTRAP_XTAL_FSEL_MASK\t\tBIT(7)\r\n+#define HWTRAP_XTAL_FSEL_25MHZ\t\tBIT(7)\r\n+#define HWTRAP_XTAL_FSEL_40MHZ\t\t0\r\n+\r\n /* Register for hw trap modification */\r\n #define MT7530_MHWTRAP\t\t\t0x7804\r\n #define MHWTRAP_PHY0_SEL\t\tBIT(20)\r\n@@ -258,14 +376,34 @@ enum mt7530_vlan_port_attr {\r\n #define MT7530_TOP_SIG_CTRL\t\t0x7808\r\n #define TOP_SIG_CTRL_NORMAL\t\t(BIT(17) | BIT(16))\r\n \r\n+#define MT7531_TOP_SIG_SR\t\t0x780c\r\n+#define PAD_DUAL_SGMII_EN\t\tBIT(1)\r\n+\r\n #define MT7530_IO_DRV_CR\t\t0x7810\r\n #define P5_IO_CLK_DRV(x)\t\t((x) & 0x3)\r\n #define P5_IO_DATA_DRV(x)\t\t(((x) & 0x3) << 4)\r\n \r\n+#define MT7531_PLLGP_EN\t\t\t0x7820\r\n+#define EN_COREPLL\t\t\tBIT(2)\r\n+#define SW_CLKSW\t\t\tBIT(1)\r\n+#define SW_PLLGP\t\t\tBIT(0)\r\n+\r\n+#define MT7531_PLLGP_CR0\t\t0x78a8\r\n+#define RG_COREPLL_EN\t\t\tBIT(22)\r\n+#define RG_COREPLL_POSDIV_S\t\t23\r\n+#define RG_COREPLL_POSDIV_M\t\t0x3800000\r\n+#define RG_COREPLL_SDM_PCW_S\t\t1\r\n+#define RG_COREPLL_SDM_PCW_M\t\t0x3ffffe\r\n+#define RG_COREPLL_SDM_PCW_CHG\t\tBIT(0)\r\n+\r\n #define MT7530_P6ECR\t\t\t0x7830\r\n #define P6_INTF_MODE_MASK\t\t0x3\r\n #define P6_INTF_MODE(x)\t\t((x) & 0x3)\r\n \r\n+/* RGMII and SGMII PLL clock */\r\n+#define MT7531_ANA_PLLGP_CR2\t\t0x78b0\r\n+#define MT7531_ANA_PLLGP_CR5\t\t0x78bc\r\n+\r\n /* Registers for TRGMII on the both side */\r\n #define MT7530_TRGMII_RCK_CTRL\t\t0x7a00\r\n #define GSW_TRGMII_RCK_CTRL\t\t0x300\r\n@@ -316,6 +454,9 @@ enum mt7530_vlan_port_attr {\r\n #define CHIP_NAME_SHIFT\t\t16\r\n #define MT7530_ID\t\t\t0x7530\r\n \r\n+#define MT7531_CREV\t\t\t0x781C\r\n+#define MT7531_ID\t\t\t0x7531\r\n+\r\n /* Registers for core PLL access through mmd indirect */\r\n #define CORE_PLL_GROUP2\t\t\t0x401\r\n #define RG_SYSPLL_EN_NORMAL\t\tBIT(15)\r\n@@ -439,6 +580,8 @@ static const char *p5_intf_modes(unsigned int p5_interface)\r\n *\t\t\tport\r\n * @mac_setup:\t\tHolding the way setting up the PHY attribute for a\r\n *\t\t\tcertain MAC port\r\n+ * @port_an_restart\tHolding the way restarting 802.3z BaseX autonegotiation\r\n+ *\t\t\tfor a certain MAC port\r\n */\r\n struct mt753x_info {\r\n \tenum mt753x_id id;\r\n@@ -452,6 +595,7 @@ struct mt753x_info {\r\n \t\t\t const struct phylink_link_state *state);\r\n \tint (*mac_setup)(struct dsa_switch *ds, int port, unsigned int mode,\r\n \t\t\t const struct phylink_link_state *state);\r\n+\tvoid (*port_an_restart)(struct dsa_switch *ds, int port);\r\n };\r\n \r\n /* struct mt7530_priv -\tThis is the main data structure for holding the state\r\n", "prefixes": [ "net-next", "4/6" ] }