mediatek: switch to pending XFI 10G Ethernet drivers

Replace previous patch adding paths and SerDes modes with patch series
pending upstream adding dedicated drivers for XFI T-PHY and USXGMII PCS,
extends LynxI PCS to be a standalone platform driver and as a consequence
makes much less changes to the actual Ethernet driver mtk_eth_soc.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
Daniel Golle 2024-01-28 03:55:15 +00:00
parent c36de2e73a
commit 4cb6bd9a6d
28 changed files with 2087 additions and 1112 deletions

View File

@ -343,7 +343,7 @@ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19281,6 +19281,14 @@ T: git git://linuxtv.org/media_tree.git
@@ -19283,6 +19283,14 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
F: drivers/media/i2c/imx412.c

View File

@ -177,7 +177,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19289,6 +19289,14 @@ T: git git://linuxtv.org/media_tree.git
@@ -19291,6 +19291,14 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/imx477.yaml
F: drivers/media/i2c/imx477.c

View File

@ -132,7 +132,7 @@ Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19286,6 +19286,7 @@ M: Raspberry Pi Kernel Maintenance <kern
@@ -19288,6 +19288,7 @@ M: Raspberry Pi Kernel Maintenance <kern
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git

View File

@ -138,7 +138,7 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19330,6 +19330,14 @@ T: git git://linuxtv.org/media_tree.git
@@ -19332,6 +19332,14 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/imx519.yaml
F: drivers/media/i2c/imx519.c

View File

@ -128,7 +128,7 @@ Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19272,6 +19272,14 @@ T: git git://linuxtv.org/media_tree.git
@@ -19274,6 +19274,14 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/imx290.txt
F: drivers/media/i2c/imx290.c

View File

@ -23,7 +23,7 @@ Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19279,6 +19279,7 @@ L: linux-media@vger.kernel.org
@@ -19281,6 +19281,7 @@ L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx296.yaml

View File

@ -219,7 +219,7 @@ Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19269,7 +19269,7 @@ M: Manivannan Sadhasivam <manivannan.sad
@@ -19271,7 +19271,7 @@ M: Manivannan Sadhasivam <manivannan.sad
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git

View File

@ -271,7 +271,7 @@ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19344,7 +19344,7 @@ M: Raspberry Pi Kernel Maintenance <kern
@@ -19346,7 +19346,7 @@ M: Raspberry Pi Kernel Maintenance <kern
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git

View File

@ -67,7 +67,7 @@ Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17895,6 +17895,13 @@ S: Maintained
@@ -17897,6 +17897,13 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/light/bh1750.yaml
F: drivers/iio/light/bh1750.c

View File

@ -16,7 +16,7 @@ Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15321,6 +15321,14 @@ S: Maintained
@@ -15323,6 +15323,14 @@ S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/ov5695.c

View File

@ -4838,6 +4838,7 @@ CONFIG_PCI_SYSCALL=y
# CONFIG_PCNET32 is not set
# CONFIG_PCPU_DEV_REFCNT is not set
# CONFIG_PCSPKR_PLATFORM is not set
# CONFIG_PCS_MTK_USXGMII is not set
# CONFIG_PCS_XPCS is not set
# CONFIG_PD6729 is not set
# CONFIG_PDA_POWER is not set
@ -4872,6 +4873,7 @@ CONFIG_PCI_SYSCALL=y
# CONFIG_PHY_MIXEL_MIPI_DPHY is not set
# CONFIG_PHY_MTK_HDMI is not set
# CONFIG_PHY_MTK_MIPI_DSI is not set
# CONFIG_PHY_MTK_XFI_TPHY is not set
# CONFIG_PHY_MVEBU_CP110_UTMI is not set
# CONFIG_PHY_OCELOT_SERDES is not set
# CONFIG_PHY_PISTACHIO_USB is not set

View File

@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -92,14 +92,23 @@ static void mtk_pcs_lynxi_get_state(stru
@@ -114,14 +114,23 @@ static void mtk_pcs_lynxi_get_state(stru
struct phylink_link_state *state)
{
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
@ -40,8 +40,8 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ phylink_mii_c22_pcs_decode_state(state, bmsr, FIELD_GET(SGMII_LPA, adv));
}
static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode,
@@ -130,7 +139,8 @@ static int mtk_pcs_lynxi_config(struct p
static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs)
@@ -163,7 +172,8 @@ static int mtk_pcs_lynxi_config(struct p
if (neg_mode & PHYLINK_PCS_NEG_INBAND)
sgm_mode |= SGMII_REMOTE_FAULT_DIS;

View File

@ -32,7 +32,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4885,7 +4885,10 @@ static int mtk_probe(struct platform_dev
@@ -4963,7 +4963,10 @@ static int mtk_probe(struct platform_dev
}
if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) {

View File

@ -0,0 +1,136 @@
From patchwork Thu Feb 1 21:52:20 2024
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
X-Patchwork-Id: 13541842
Date: Thu, 1 Feb 2024 21:52:20 +0000
From: Daniel Golle <daniel@makrotopia.org>
To: Bc-bocun Chen <bc-bocun.chen@mediatek.com>,
Steven Liu <steven.liu@mediatek.com>,
John Crispin <john@phrozen.org>,
Chunfeng Yun <chunfeng.yun@mediatek.com>,
Vinod Koul <vkoul@kernel.org>,
Kishon Vijay Abraham I <kishon@kernel.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
Daniel Golle <daniel@makrotopia.org>,
Qingfang Deng <dqfext@gmail.com>,
SkyLake Huang <SkyLake.Huang@mediatek.com>,
Matthias Brugger <matthias.bgg@gmail.com>,
AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>,
Philipp Zabel <p.zabel@pengutronix.de>,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org, linux-phy@lists.infradead.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org
Subject: [PATCH 1/2] dt-bindings: phy: mediatek,xfi-tphy: add new bindings
Message-ID:
<702afb0c1246d95c90b22e57105304028bdd3083.1706823233.git.daniel@makrotopia.org>
MIME-Version: 1.0
Content-Disposition: inline
List-Id: Linux Phy Mailing list <linux-phy.lists.infradead.org>
Add bindings for the MediaTek XFI T-PHY Ethernet SerDes PHY found in the
MediaTek MT7988 SoC which can operate at various interfaces modes:
via USXGMII PCS:
* USXGMII
* 10GBase-R
* 5GBase-R
via LynxI SGMII PCS:
* 2500Base-X
* 1000Base-X
* Cisco SGMII (MAC side)
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
.../bindings/phy/mediatek,xfi-tphy.yaml | 80 +++++++++++++++++++
1 file changed, 80 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/mediatek,xfi-tphy.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/mediatek,xfi-tphy.yaml
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/mediatek,xfi-tphy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek XFI T-PHY
+
+maintainers:
+ - Daniel Golle <daniel@makrotopia.org>
+
+description:
+ The MediaTek XFI SerDes T-PHY provides the physical SerDes lanes
+ used by the (10G/5G) USXGMII PCS and (1G/2.5G) LynxI PCS found in
+ MediaTek's 10G-capabale SoCs.
+
+properties:
+ $nodename:
+ pattern: "^phy@[0-9a-f]+$"
+
+ compatible:
+ const: mediatek,mt7988-xfi-tphy
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: XFI PHY clock
+ - description: XFI register clock
+
+ clock-names:
+ items:
+ - const: xfipll
+ - const: topxtal
+
+ resets:
+ items:
+ - description: PEXTP reset
+
+ mediatek,usxgmii-performance-errata:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ One instance of the T-PHY on MT7988 suffers from a performance
+ problem in 10GBase-R mode which needs a work-around in the driver.
+ The work-around is enabled using this flag.
+
+ "#phy-cells":
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - resets
+ - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mediatek,mt7988-clk.h>
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ phy@11f20000 {
+ compatible = "mediatek,mt7988-xfi-tphy";
+ reg = <0 0x11f20000 0 0x10000>;
+ clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>,
+ <&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>;
+ clock-names = "xfipll", "topxtal";
+ resets = <&watchdog 14>;
+ mediatek,usxgmii-performance-errata;
+ #phy-cells = <0>;
+ };
+ };
+
+...

View File

@ -0,0 +1,497 @@
From patchwork Thu Feb 1 21:53:06 2024
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
X-Patchwork-Id: 13541843
Date: Thu, 1 Feb 2024 21:53:06 +0000
From: Daniel Golle <daniel@makrotopia.org>
To: Bc-bocun Chen <bc-bocun.chen@mediatek.com>,
Chunfeng Yun <chunfeng.yun@mediatek.com>,
Vinod Koul <vkoul@kernel.org>,
Kishon Vijay Abraham I <kishon@kernel.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
Daniel Golle <daniel@makrotopia.org>,
Qingfang Deng <dqfext@gmail.com>,
SkyLake Huang <SkyLake.Huang@mediatek.com>,
Matthias Brugger <matthias.bgg@gmail.com>,
AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>,
Philipp Zabel <p.zabel@pengutronix.de>,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org, linux-phy@lists.infradead.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org
Subject: [PATCH 2/2] phy: add driver for MediaTek XFI T-PHY
Message-ID:
<dd6b40ea1f7f8459a9a2cfe7fa60c1108332ade6.1706823233.git.daniel@makrotopia.org>
References:
<702afb0c1246d95c90b22e57105304028bdd3083.1706823233.git.daniel@makrotopia.org>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To:
<702afb0c1246d95c90b22e57105304028bdd3083.1706823233.git.daniel@makrotopia.org>
List-Id: Linux Phy Mailing list <linux-phy.lists.infradead.org>
Add driver for MediaTek's XFI T-PHY, 10 Gigabit/s Ethernet SerDes PHY
which can be found in the MT7988 SoC.
The PHY can operates only in PHY_MODE_ETHERNET, the submode is one of
PHY_INTERFACE_MODE_* corresponding to the supported modes:
* USXGMII \
* 10GBase-R }- USXGMII PCS - XGDM \
* 5GBase-R / \
}- Ethernet MAC
* 2500Base-X \ /
* 1000Base-X }- LynxI PCS - GDM /
* Cisco SGMII (MAC side) /
In order to work-around a performance issue present on the first of
two XFI T-PHYs present in MT7988, special tuning is applied which can be
selected by adding the 'mediatek,usxgmii-performance-errata' property to
the device tree node.
There is no documentation for most registers used for the
analog/tuning part, however, most of the registers have been partially
reverse-engineered from MediaTek's SDK implementation (an opaque
sequence of 32-bit register writes) and descriptions for all relevant
digital registers and bits such as resets and muxes have been supplied
by MediaTek.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
MAINTAINERS | 1 +
drivers/phy/mediatek/Kconfig | 12 +
drivers/phy/mediatek/Makefile | 1 +
drivers/phy/mediatek/phy-mtk-xfi-tphy.c | 392 ++++++++++++++++++++++++
4 files changed, 406 insertions(+)
create mode 100644 drivers/phy/mediatek/phy-mtk-xfi-tphy.c
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -13,6 +13,18 @@ config PHY_MTK_PCIE
callback for PCIe GEN3 port, it supports software efuse
initialization.
+config PHY_MTK_XFI_TPHY
+ tristate "MediaTek XFI T-PHY Driver"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on OF && OF_ADDRESS
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ help
+ Say 'Y' here to add support for MediaTek XFI T-PHY driver.
+ The driver provides access to the Ethernet SerDes T-PHY supporting
+ 1GE and 2.5GE modes via the LynxI PCS, and 5GE and 10GE modes
+ via the USXGMII PCS found in MediaTek SoCs with 10G Ethernet.
+
config PHY_MTK_TPHY
tristate "MediaTek T-PHY Driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
--- a/drivers/phy/mediatek/Makefile
+++ b/drivers/phy/mediatek/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_MTK_PCIE) += phy-mtk-p
obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o
obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o
obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o
+obj-$(CONFIG_PHY_MTK_XFI_TPHY) += phy-mtk-xfi-tphy.o
phy-mtk-hdmi-drv-y := phy-mtk-hdmi.o
phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt2701.o
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-xfi-tphy.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* MediaTek 10GE SerDes PHY driver
+ *
+ * Copyright (c) 2024 Daniel Golle <daniel@makrotopia.org>
+ * Bc-bocun Chen <bc-bocun.chen@mediatek.com>
+ * based on mtk_usxgmii.c found in MediaTek's SDK released under GPL-2.0
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Henry Yen <henry.yen@mediatek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+
+#define MTK_XFI_TPHY_NUM_CLOCKS 2
+
+#define REG_DIG_GLB_70 0x0070
+#define XTP_PCS_RX_EQ_IN_PROGRESS(x) FIELD_PREP(GENMASK(25, 24), (x))
+#define XTP_PCS_MODE_MASK GENMASK(17, 16)
+#define XTP_PCS_MODE(x) FIELD_PREP(GENMASK(17, 16), (x))
+#define XTP_PCS_RST_B BIT(15)
+#define XTP_FRC_PCS_RST_B BIT(14)
+#define XTP_PCS_PWD_SYNC_MASK GENMASK(13, 12)
+#define XTP_PCS_PWD_SYNC(x) FIELD_PREP(XTP_PCS_PWD_SYNC_MASK, (x))
+#define XTP_PCS_PWD_ASYNC_MASK GENMASK(11, 10)
+#define XTP_PCS_PWD_ASYNC(x) FIELD_PREP(XTP_PCS_PWD_ASYNC_MASK, (x))
+#define XTP_FRC_PCS_PWD_ASYNC BIT(8)
+#define XTP_PCS_UPDT BIT(4)
+#define XTP_PCS_IN_FR_RG BIT(0)
+
+#define REG_DIG_GLB_F4 0x00f4
+#define XFI_DPHY_PCS_SEL BIT(0)
+#define XFI_DPHY_PCS_SEL_SGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 1)
+#define XFI_DPHY_PCS_SEL_USXGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 0)
+#define XFI_DPHY_AD_SGDT_FRC_EN BIT(5)
+
+#define REG_DIG_LN_TRX_40 0x3040
+#define XTP_LN_FRC_TX_DATA_EN BIT(29)
+#define XTP_LN_TX_DATA_EN BIT(28)
+
+#define REG_DIG_LN_TRX_B0 0x30b0
+#define XTP_LN_FRC_TX_MACCK_EN BIT(5)
+#define XTP_LN_TX_MACCK_EN BIT(4)
+
+#define REG_ANA_GLB_D0 0x90d0
+#define XTP_GLB_USXGMII_SEL_MASK GENMASK(3, 1)
+#define XTP_GLB_USXGMII_SEL(x) FIELD_PREP(GENMASK(3, 1), (x))
+#define XTP_GLB_USXGMII_EN BIT(0)
+
+struct mtk_xfi_tphy {
+ void __iomem *base;
+ struct device *dev;
+ struct reset_control *reset;
+ struct clk_bulk_data clocks[MTK_XFI_TPHY_NUM_CLOCKS];
+ bool da_war;
+};
+
+static void mtk_xfi_tphy_write(struct mtk_xfi_tphy *xfi_tphy, u16 reg,
+ u32 value)
+{
+ iowrite32(value, xfi_tphy->base + reg);
+}
+
+static void mtk_xfi_tphy_rmw(struct mtk_xfi_tphy *xfi_tphy, u16 reg,
+ u32 clr, u32 set)
+{
+ u32 val;
+
+ val = ioread32(xfi_tphy->base + reg);
+ val &= ~clr;
+ val |= set;
+ iowrite32(val, xfi_tphy->base + reg);
+}
+
+static void mtk_xfi_tphy_set(struct mtk_xfi_tphy *xfi_tphy, u16 reg,
+ u32 set)
+{
+ mtk_xfi_tphy_rmw(xfi_tphy, reg, 0, set);
+}
+
+static void mtk_xfi_tphy_clear(struct mtk_xfi_tphy *xfi_tphy, u16 reg,
+ u32 clr)
+{
+ mtk_xfi_tphy_rmw(xfi_tphy, reg, clr, 0);
+}
+
+static void mtk_xfi_tphy_setup(struct mtk_xfi_tphy *xfi_tphy,
+ phy_interface_t interface)
+{
+ bool is_2p5g = (interface == PHY_INTERFACE_MODE_2500BASEX);
+ bool is_1g = (interface == PHY_INTERFACE_MODE_1000BASEX ||
+ interface == PHY_INTERFACE_MODE_SGMII);
+ bool is_10g = (interface == PHY_INTERFACE_MODE_10GBASER ||
+ interface == PHY_INTERFACE_MODE_USXGMII);
+ bool is_5g = (interface == PHY_INTERFACE_MODE_5GBASER);
+ bool is_xgmii = (is_10g || is_5g);
+
+ dev_dbg(xfi_tphy->dev, "setting up for mode %s\n", phy_modes(interface));
+
+ /* Setup PLL setting */
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x9024, 0x100000, is_10g ? 0x0 : 0x100000);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x2020, 0x202000, is_5g ? 0x202000 : 0x0);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x2030, 0x500, is_1g ? 0x0 : 0x500);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x2034, 0xa00, is_1g ? 0x0 : 0xa00);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x2040, 0x340000, is_1g ? 0x200000 :
+ 0x140000);
+
+ /* Setup RXFE BW setting */
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x50f0, 0xc10, is_1g ? 0x410 :
+ is_5g ? 0x800 : 0x400);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x50e0, 0x4000, is_5g ? 0x0 : 0x4000);
+
+ /* Setup RX CDR setting */
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x506c, 0x30000, is_5g ? 0x0 : 0x30000);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x5070, 0x670000, is_5g ? 0x620000 : 0x50000);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x5074, 0x180000, is_5g ? 0x180000 : 0x0);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x5078, 0xf000400, is_5g ? 0x8000000 :
+ 0x7000400);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x507c, 0x5000500, is_5g ? 0x4000400 :
+ 0x1000100);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x5080, 0x1410, is_1g ? 0x400 :
+ is_5g ? 0x1010 : 0x0);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x5084, 0x30300, is_1g ? 0x30300 :
+ is_5g ? 0x30100 :
+ 0x100);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x5088, 0x60200, is_1g ? 0x20200 :
+ is_5g ? 0x40000 :
+ 0x20000);
+
+ /* Setting RXFE adaptation range setting */
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x50e4, 0xc0000, is_5g ? 0x0 : 0xc0000);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x50e8, 0x40000, is_5g ? 0x0 : 0x40000);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x50ec, 0xa00, is_1g ? 0x200 : 0x800);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x50a8, 0xee0000, is_5g ? 0x800000 :
+ 0x6e0000);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x6004, 0x190000, is_5g ? 0x0 : 0x190000);
+ if (is_10g)
+ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x01423342);
+ else if (is_5g)
+ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x00a132a1);
+ else if (is_2p5g)
+ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x009c329c);
+ else
+ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x00fa32fa);
+
+ /* Force SGDT_OUT off and select PCS */
+ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_F4,
+ XFI_DPHY_AD_SGDT_FRC_EN | XFI_DPHY_PCS_SEL,
+ XFI_DPHY_AD_SGDT_FRC_EN |
+ (is_xgmii ? XFI_DPHY_PCS_SEL_USXGMII :
+ XFI_DPHY_PCS_SEL_SGMII));
+
+
+ /* Force GLB_CKDET_OUT */
+ mtk_xfi_tphy_set(xfi_tphy, 0x0030, 0xc00);
+
+ /* Force AEQ on */
+ mtk_xfi_tphy_write(xfi_tphy, REG_DIG_GLB_70,
+ XTP_PCS_RX_EQ_IN_PROGRESS(2) |
+ XTP_PCS_PWD_SYNC(2) |
+ XTP_PCS_PWD_ASYNC(2));
+
+ usleep_range(1, 5);
+
+ /* Setup TX DA default value */
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x30b0, 0x30, 0x20);
+ mtk_xfi_tphy_write(xfi_tphy, 0x3028, 0x00008a01);
+ mtk_xfi_tphy_write(xfi_tphy, 0x302c, 0x0000a884);
+ mtk_xfi_tphy_write(xfi_tphy, 0x3024, 0x00083002);
+
+ /* Setup RG default value */
+ if (is_xgmii) {
+ mtk_xfi_tphy_write(xfi_tphy, 0x3010, 0x00022220);
+ mtk_xfi_tphy_write(xfi_tphy, 0x5064, 0x0f020a01);
+ mtk_xfi_tphy_write(xfi_tphy, 0x50b4, 0x06100600);
+ if (interface == PHY_INTERFACE_MODE_USXGMII)
+ mtk_xfi_tphy_write(xfi_tphy, 0x3048, 0x40704000);
+ else
+ mtk_xfi_tphy_write(xfi_tphy, 0x3048, 0x47684100);
+ } else {
+ mtk_xfi_tphy_write(xfi_tphy, 0x3010, 0x00011110);
+ mtk_xfi_tphy_write(xfi_tphy, 0x3048, 0x40704000);
+ }
+
+ if (is_1g)
+ mtk_xfi_tphy_write(xfi_tphy, 0x3064, 0x0000c000);
+
+ /* Setup RX EQ initial value */
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x3050, 0xa8000000,
+ (interface != PHY_INTERFACE_MODE_10GBASER) ?
+ 0xa8000000 : 0x0);
+ mtk_xfi_tphy_rmw(xfi_tphy, 0x3054, 0xaa,
+ (interface != PHY_INTERFACE_MODE_10GBASER) ?
+ 0xaa : 0x0);
+
+ if (is_xgmii)
+ mtk_xfi_tphy_write(xfi_tphy, 0x306c, 0x00000f00);
+ else if (is_2p5g)
+ mtk_xfi_tphy_write(xfi_tphy, 0x306c, 0x22000f00);
+ else
+ mtk_xfi_tphy_write(xfi_tphy, 0x306c, 0x20200f00);
+
+ if (interface == PHY_INTERFACE_MODE_10GBASER && xfi_tphy->da_war)
+ mtk_xfi_tphy_rmw(xfi_tphy, 0xa008, 0x10000, 0x10000);
+
+ mtk_xfi_tphy_rmw(xfi_tphy, 0xa060, 0x50000, is_xgmii ? 0x40000 :
+ 0x50000);
+
+ /* Setup PHYA speed */
+ mtk_xfi_tphy_rmw(xfi_tphy, REG_ANA_GLB_D0,
+ XTP_GLB_USXGMII_SEL_MASK | XTP_GLB_USXGMII_EN,
+ is_10g ? XTP_GLB_USXGMII_SEL(0) :
+ is_5g ? XTP_GLB_USXGMII_SEL(1) :
+ is_2p5g ? XTP_GLB_USXGMII_SEL(2) :
+ XTP_GLB_USXGMII_SEL(3));
+ mtk_xfi_tphy_set(xfi_tphy, REG_ANA_GLB_D0, XTP_GLB_USXGMII_EN);
+
+ /* Release reset */
+ mtk_xfi_tphy_set(xfi_tphy, REG_DIG_GLB_70,
+ XTP_PCS_RST_B | XTP_FRC_PCS_RST_B);
+ usleep_range(150, 500);
+
+ /* Switch to P0 */
+ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_70,
+ XTP_PCS_PWD_SYNC_MASK |
+ XTP_PCS_PWD_ASYNC_MASK,
+ XTP_FRC_PCS_PWD_ASYNC |
+ XTP_PCS_UPDT | XTP_PCS_IN_FR_RG);
+ usleep_range(1, 5);
+
+ mtk_xfi_tphy_clear(xfi_tphy, REG_DIG_GLB_70, XTP_PCS_UPDT);
+ usleep_range(15, 50);
+
+ if (is_xgmii) {
+ /* Switch to Gen3 */
+ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_70,
+ XTP_PCS_MODE_MASK | XTP_PCS_UPDT,
+ XTP_PCS_MODE(2) | XTP_PCS_UPDT);
+ } else {
+ /* Switch to Gen2 */
+ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_70,
+ XTP_PCS_MODE_MASK | XTP_PCS_UPDT,
+ XTP_PCS_MODE(1) | XTP_PCS_UPDT);
+ }
+ usleep_range(1, 5);
+
+ mtk_xfi_tphy_clear(xfi_tphy, REG_DIG_GLB_70, XTP_PCS_UPDT);
+
+ usleep_range(100, 500);
+
+ /* Enable MAC CK */
+ mtk_xfi_tphy_set(xfi_tphy, REG_DIG_LN_TRX_B0, XTP_LN_TX_MACCK_EN);
+ mtk_xfi_tphy_clear(xfi_tphy, REG_DIG_GLB_F4, XFI_DPHY_AD_SGDT_FRC_EN);
+
+ /* Enable TX data */
+ mtk_xfi_tphy_set(xfi_tphy, REG_DIG_LN_TRX_40,
+ XTP_LN_FRC_TX_DATA_EN | XTP_LN_TX_DATA_EN);
+ usleep_range(400, 1000);
+}
+
+static int mtk_xfi_tphy_set_mode(struct phy *phy, enum phy_mode mode, int
+ submode)
+{
+ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
+
+ if (mode != PHY_MODE_ETHERNET)
+ return -EINVAL;
+
+ switch (submode) {
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_5GBASER:
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_USXGMII:
+ mtk_xfi_tphy_setup(xfi_tphy, submode);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mtk_xfi_tphy_reset(struct phy *phy)
+{
+ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
+
+ reset_control_assert(xfi_tphy->reset);
+ usleep_range(100, 500);
+ reset_control_deassert(xfi_tphy->reset);
+ usleep_range(1, 10);
+
+ return 0;
+}
+
+static int mtk_xfi_tphy_power_on(struct phy *phy)
+{
+ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
+
+ return clk_bulk_prepare_enable(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks);
+}
+
+static int mtk_xfi_tphy_power_off(struct phy *phy)
+{
+ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
+
+ clk_bulk_disable_unprepare(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks);
+
+ return 0;
+}
+
+static const struct phy_ops mtk_xfi_tphy_ops = {
+ .power_on = mtk_xfi_tphy_power_on,
+ .power_off = mtk_xfi_tphy_power_off,
+ .set_mode = mtk_xfi_tphy_set_mode,
+ .reset = mtk_xfi_tphy_reset,
+ .owner = THIS_MODULE,
+};
+
+static int mtk_xfi_tphy_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct phy_provider *phy_provider;
+ struct mtk_xfi_tphy *xfi_tphy;
+ struct phy *phy;
+
+ if (!np)
+ return -ENODEV;
+
+ xfi_tphy = devm_kzalloc(&pdev->dev, sizeof(*xfi_tphy), GFP_KERNEL);
+ if (!xfi_tphy)
+ return -ENOMEM;
+
+ xfi_tphy->base = devm_of_iomap(&pdev->dev, np, 0, NULL);
+ if (!xfi_tphy->base)
+ return -EIO;
+
+ xfi_tphy->dev = &pdev->dev;
+
+ xfi_tphy->clocks[0].id = "topxtal";
+ xfi_tphy->clocks[0].clk = devm_clk_get(&pdev->dev, xfi_tphy->clocks[0].id);
+ if (IS_ERR(xfi_tphy->clocks[0].clk))
+ return PTR_ERR(xfi_tphy->clocks[0].clk);
+
+ xfi_tphy->clocks[1].id = "xfipll";
+ xfi_tphy->clocks[1].clk = devm_clk_get(&pdev->dev, xfi_tphy->clocks[1].id);
+ if (IS_ERR(xfi_tphy->clocks[1].clk))
+ return PTR_ERR(xfi_tphy->clocks[1].clk);
+
+ xfi_tphy->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(xfi_tphy->reset))
+ return PTR_ERR(xfi_tphy->reset);
+
+ xfi_tphy->da_war = of_property_read_bool(np,
+ "mediatek,usxgmii-performance-errata");
+
+ phy = devm_phy_create(&pdev->dev, NULL, &mtk_xfi_tphy_ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ phy_set_drvdata(phy, xfi_tphy);
+
+ phy_provider = devm_of_phy_provider_register(&pdev->dev,
+ of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id mtk_xfi_tphy_match[] = {
+ { .compatible = "mediatek,mt7988-xfi-tphy", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mtk_xfi_tphy_match);
+
+static struct platform_driver mtk_xfi_tphy_driver = {
+ .probe = mtk_xfi_tphy_probe,
+ .driver = {
+ .name = "mtk-xfi-tphy",
+ .of_match_table = mtk_xfi_tphy_match,
+ },
+};
+module_platform_driver(mtk_xfi_tphy_driver);
+
+MODULE_DESCRIPTION("MediaTek XFI T-PHY driver");
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_AUTHOR("Bc-bocun Chen <bc-bocun.chen@mediatek.com>");
+MODULE_LICENSE("GPL");

View File

@ -0,0 +1,371 @@
From 4b1a2716299c0e96a698044aebf3f80513509ae7 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Tue, 12 Dec 2023 03:47:18 +0000
Subject: [PATCH 3/5] net: pcs: pcs-mtk-lynxi: add platform driver for MT7988
Introduce a proper platform MFD driver for the LynxI (H)SGMII PCS which
is going to initially be used for the MT7988 SoC.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/pcs/pcs-mtk-lynxi.c | 227 ++++++++++++++++++++++++++++--
include/linux/pcs/pcs-mtk-lynxi.h | 11 ++
2 files changed, 227 insertions(+), 11 deletions(-)
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018-2019 MediaTek Inc.
-/* A library for MediaTek SGMII circuit
+/* A library and platform driver for the MediaTek LynxI SGMII circuit
*
* Author: Sean Wang <sean.wang@mediatek.com>
* Author: Alexander Couzens <lynxis@fe80.eu>
@@ -8,11 +8,17 @@
*
*/
+#include <linux/clk.h>
#include <linux/mdio.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/pcs/pcs-mtk-lynxi.h>
#include <linux/phylink.h>
+#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
/* SGMII subsystem config registers */
/* BMCR (low 16) BMSR (high 16) */
@@ -65,6 +71,8 @@
#define SGMII_PN_SWAP_MASK GENMASK(1, 0)
#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1))
+#define MTK_NETSYS_V3_AMA_RGC3 0x128
+
/* struct mtk_pcs_lynxi - This structure holds each sgmii regmap andassociated
* data
* @regmap: The register map pointing at the range used to setup
@@ -74,15 +82,29 @@
* @interface: Currently configured interface mode
* @pcs: Phylink PCS structure
* @flags: Flags indicating hardware properties
+ * @rstc: Reset controller
+ * @sgmii_sel: SGMII Register Clock
+ * @sgmii_rx: SGMII RX Clock
+ * @sgmii_tx: SGMII TX Clock
+ * @node: List node
*/
struct mtk_pcs_lynxi {
struct regmap *regmap;
+ struct device *dev;
u32 ana_rgc3;
phy_interface_t interface;
struct phylink_pcs pcs;
u32 flags;
+ struct reset_control *rstc;
+ struct clk *sgmii_sel;
+ struct clk *sgmii_rx;
+ struct clk *sgmii_tx;
+ struct list_head node;
};
+static LIST_HEAD(mtk_pcs_lynxi_instances);
+static DEFINE_MUTEX(instance_mutex);
+
static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs)
{
return container_of(pcs, struct mtk_pcs_lynxi, pcs);
@@ -102,6 +124,17 @@ static void mtk_pcs_lynxi_get_state(stru
FIELD_GET(SGMII_LPA, adv));
}
+static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs)
+{
+ if (!mpcs->rstc)
+ return;
+
+ reset_control_assert(mpcs->rstc);
+ udelay(100);
+ reset_control_deassert(mpcs->rstc);
+ mdelay(1);
+}
+
static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
@@ -148,6 +181,7 @@ static int mtk_pcs_lynxi_config(struct p
SGMII_PHYA_PWD);
/* Reset SGMII PCS state */
+ mtk_sgmii_reset(mpcs);
regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0,
SGMII_SW_RESET);
@@ -234,10 +268,29 @@ static void mtk_pcs_lynxi_link_up(struct
}
}
+static int mtk_pcs_lynxi_enable(struct phylink_pcs *pcs)
+{
+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
+
+ if (mpcs->sgmii_tx && mpcs->sgmii_rx) {
+ clk_prepare_enable(mpcs->sgmii_rx);
+ clk_prepare_enable(mpcs->sgmii_tx);
+ }
+
+ return 0;
+}
+
static void mtk_pcs_lynxi_disable(struct phylink_pcs *pcs)
{
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
+ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
+
+ if (mpcs->sgmii_tx && mpcs->sgmii_rx) {
+ clk_disable_unprepare(mpcs->sgmii_tx);
+ clk_disable_unprepare(mpcs->sgmii_rx);
+ }
+
mpcs->interface = PHY_INTERFACE_MODE_NA;
}
@@ -247,11 +300,12 @@ static const struct phylink_pcs_ops mtk_
.pcs_an_restart = mtk_pcs_lynxi_restart_an,
.pcs_link_up = mtk_pcs_lynxi_link_up,
.pcs_disable = mtk_pcs_lynxi_disable,
+ .pcs_enable = mtk_pcs_lynxi_enable,
};
-struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev,
- struct regmap *regmap, u32 ana_rgc3,
- u32 flags)
+static struct phylink_pcs *mtk_pcs_lynxi_init(struct device *dev, struct regmap *regmap,
+ u32 ana_rgc3, u32 flags,
+ struct mtk_pcs_lynxi *prealloc)
{
struct mtk_pcs_lynxi *mpcs;
u32 id, ver;
@@ -259,29 +313,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create
ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id);
if (ret < 0)
- return NULL;
+ return ERR_PTR(ret);
if (id != SGMII_LYNXI_DEV_ID) {
dev_err(dev, "unknown PCS device id %08x\n", id);
- return NULL;
+ return ERR_PTR(-ENODEV);
}
ret = regmap_read(regmap, SGMSYS_PCS_SCRATCH, &ver);
if (ret < 0)
- return NULL;
+ return ERR_PTR(ret);
ver = FIELD_GET(SGMII_DEV_VERSION, ver);
if (ver != 0x1) {
dev_err(dev, "unknown PCS device version %04x\n", ver);
- return NULL;
+ return ERR_PTR(-ENODEV);
}
dev_dbg(dev, "MediaTek LynxI SGMII PCS (id 0x%08x, ver 0x%04x)\n", id,
ver);
- mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL);
- if (!mpcs)
- return NULL;
+ if (prealloc) {
+ mpcs = prealloc;
+ } else {
+ mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL);
+ if (!mpcs)
+ return ERR_PTR(-ENOMEM);
+ };
mpcs->ana_rgc3 = ana_rgc3;
mpcs->regmap = regmap;
@@ -292,6 +350,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create
mpcs->interface = PHY_INTERFACE_MODE_NA;
return &mpcs->pcs;
+};
+
+struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev,
+ struct regmap *regmap, u32 ana_rgc3,
+ u32 flags)
+{
+ return mtk_pcs_lynxi_init(dev, regmap, ana_rgc3, flags, NULL);
}
EXPORT_SYMBOL(mtk_pcs_lynxi_create);
@@ -304,4 +369,144 @@ void mtk_pcs_lynxi_destroy(struct phylin
}
EXPORT_SYMBOL(mtk_pcs_lynxi_destroy);
+static int mtk_pcs_lynxi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct mtk_pcs_lynxi *mpcs;
+ struct phylink_pcs *pcs;
+ struct regmap *regmap;
+ u32 flags = 0;
+
+ mpcs = devm_kzalloc(dev, sizeof(*mpcs), GFP_KERNEL);
+ if (!mpcs)
+ return -ENOMEM;
+
+ mpcs->dev = dev;
+ regmap = syscon_node_to_regmap(np->parent);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ if (of_property_read_bool(np->parent, "mediatek,pnswap"))
+ flags |= MTK_SGMII_FLAG_PN_SWAP;
+
+ mpcs->rstc = of_reset_control_get_shared(np->parent, NULL);
+ if (IS_ERR(mpcs->rstc))
+ return PTR_ERR(mpcs->rstc);
+
+ reset_control_deassert(mpcs->rstc);
+ mpcs->sgmii_sel = devm_clk_get_enabled(dev, "sgmii_sel");
+ if (IS_ERR(mpcs->sgmii_sel))
+ return PTR_ERR(mpcs->sgmii_sel);
+
+ mpcs->sgmii_rx = devm_clk_get(dev, "sgmii_rx");
+ if (IS_ERR(mpcs->sgmii_rx))
+ return PTR_ERR(mpcs->sgmii_rx);
+
+ mpcs->sgmii_tx = devm_clk_get(dev, "sgmii_tx");
+ if (IS_ERR(mpcs->sgmii_tx))
+ return PTR_ERR(mpcs->sgmii_tx);
+
+ pcs = mtk_pcs_lynxi_init(dev, regmap, (uintptr_t)of_device_get_match_data(dev),
+ flags, mpcs);
+ if (IS_ERR(pcs))
+ return PTR_ERR(pcs);
+
+ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
+
+ platform_set_drvdata(pdev, mpcs);
+
+ mutex_lock(&instance_mutex);
+ list_add_tail(&mpcs->node, &mtk_pcs_lynxi_instances);
+ mutex_unlock(&instance_mutex);
+
+ return 0;
+}
+
+static int mtk_pcs_lynxi_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_pcs_lynxi *cur, *tmp;
+
+ mutex_lock(&instance_mutex);
+ list_for_each_entry_safe(cur, tmp, &mtk_pcs_lynxi_instances, node)
+ if (cur->dev == dev) {
+ list_del(&cur->node);
+ kfree(cur);
+ break;
+ }
+ mutex_unlock(&instance_mutex);
+
+ return 0;
+}
+
+static const struct of_device_id mtk_pcs_lynxi_of_match[] = {
+ { .compatible = "mediatek,mt7988-sgmii", .data = (void *)MTK_NETSYS_V3_AMA_RGC3 },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mtk_pcs_lynxi_of_match);
+
+struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np)
+{
+ struct platform_device *pdev;
+ struct mtk_pcs_lynxi *mpcs;
+
+ if (!np)
+ return NULL;
+
+ if (!of_device_is_available(np))
+ return ERR_PTR(-ENODEV);
+
+ if (!of_match_node(mtk_pcs_lynxi_of_match, np))
+ return ERR_PTR(-EINVAL);
+
+ pdev = of_find_device_by_node(np);
+ if (!pdev || !platform_get_drvdata(pdev)) {
+ if (pdev)
+ put_device(&pdev->dev);
+ return ERR_PTR(-EPROBE_DEFER);
+ }
+
+ mpcs = platform_get_drvdata(pdev);
+ device_link_add(dev, mpcs->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+
+ return &mpcs->pcs;
+}
+EXPORT_SYMBOL(mtk_pcs_lynxi_get);
+
+void mtk_pcs_lynxi_put(struct phylink_pcs *pcs)
+{
+ struct mtk_pcs_lynxi *cur, *mpcs = NULL;
+
+ if (!pcs)
+ return;
+
+ mutex_lock(&instance_mutex);
+ list_for_each_entry(cur, &mtk_pcs_lynxi_instances, node)
+ if (pcs == &cur->pcs) {
+ mpcs = cur;
+ break;
+ }
+ mutex_unlock(&instance_mutex);
+
+ if (WARN_ON(!mpcs))
+ return;
+
+ put_device(mpcs->dev);
+}
+EXPORT_SYMBOL(mtk_pcs_lynxi_put);
+
+static struct platform_driver mtk_pcs_lynxi_driver = {
+ .driver = {
+ .name = "mtk-pcs-lynxi",
+ .suppress_bind_attrs = true,
+ .of_match_table = mtk_pcs_lynxi_of_match,
+ },
+ .probe = mtk_pcs_lynxi_probe,
+ .remove = mtk_pcs_lynxi_remove,
+};
+module_platform_driver(mtk_pcs_lynxi_driver);
+
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_DESCRIPTION("MediaTek LynxI HSGMII PCS");
MODULE_LICENSE("GPL");
--- a/include/linux/pcs/pcs-mtk-lynxi.h
+++ b/include/linux/pcs/pcs-mtk-lynxi.h
@@ -10,4 +10,15 @@ struct phylink_pcs *mtk_pcs_lynxi_create
struct regmap *regmap,
u32 ana_rgc3, u32 flags);
void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs);
+
+#if IS_ENABLED(CONFIG_PCS_MTK_LYNXI)
+struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np);
+void mtk_pcs_lynxi_put(struct phylink_pcs *pcs);
+#else
+static inline struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np)
+{
+ return NULL;
+}
+static inline void mtk_pcs_lynxi_put(struct phylink_pcs *pcs) { }
+#endif /* IS_ENABLED(CONFIG_PCS_MTK_LYNXI) */
#endif

View File

@ -0,0 +1,81 @@
From 7d88d79c0f65b27a92754d7547f7af098b3de67b Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Tue, 12 Dec 2023 03:47:31 +0000
Subject: [PATCH 4/5] dt-bindings: net: pcs: add bindings for MediaTek USXGMII
PCS
MediaTek's USXGMII can be found in the MT7988 SoC. We need to access
it in order to configure and monitor the Ethernet SerDes link in
USXGMII, 10GBase-R and 5GBase-R mode. By including a wrapped
legacy 1000Base-X/2500Base-X/Cisco SGMII LynxI PCS as well, those
interface modes are also available.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
.../bindings/net/pcs/mediatek,usxgmii.yaml | 60 +++++++++++++++++++
1 file changed, 60 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/pcs/mediatek,usxgmii.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/pcs/mediatek,usxgmii.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/pcs/mediatek,usxgmii.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek USXGMII PCS
+
+maintainers:
+ - Daniel Golle <daniel@makrotopia.org>
+
+description:
+ The MediaTek USXGMII PCS provides physical link control and status
+ for USXGMII, 10GBase-R and 5GBase-R links on the SerDes interfaces
+ provided by the PEXTP PHY.
+ In order to also support legacy 2500Base-X, 1000Base-X and Cisco
+ SGMII an existing mediatek,*-sgmiisys LynxI PCS is wrapped to
+ provide those interfaces modes on the same SerDes interfaces shared
+ with the USXGMII PCS.
+
+properties:
+ $nodename:
+ pattern: "^pcs@[0-9a-f]+$"
+
+ compatible:
+ const: mediatek,mt7988-usxgmiisys
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: USXGMII top-level clock
+
+ resets:
+ items:
+ - description: XFI reset
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - resets
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mediatek,mt7988-clk.h>
+ #define MT7988_TOPRGU_XFI0_GRST 12
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ usxgmiisys0: pcs@10080000 {
+ compatible = "mediatek,mt7988-usxgmiisys";
+ reg = <0 0x10080000 0 0x1000>;
+ clocks = <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>;
+ resets = <&watchdog MT7988_TOPRGU_XFI0_GRST>;
+ };
+ };

View File

@ -0,0 +1,547 @@
From dde0e95fff92e9f5009f3bea75278e0e34a48822 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Tue, 12 Dec 2023 03:47:47 +0000
Subject: [PATCH 5/5] net: pcs: add driver for MediaTek USXGMII PCS
Add driver for USXGMII PCS found in the MediaTek MT7988 SoC and supporting
USXGMII, 10GBase-R and 5GBase-R interface modes.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
MAINTAINERS | 2 +
drivers/net/pcs/Kconfig | 11 +
drivers/net/pcs/Makefile | 1 +
drivers/net/pcs/pcs-mtk-usxgmii.c | 456 ++++++++++++++++++++++++++++
include/linux/pcs/pcs-mtk-usxgmii.h | 27 ++
5 files changed, 497 insertions(+)
create mode 100644 drivers/net/pcs/pcs-mtk-usxgmii.c
create mode 100644 include/linux/pcs/pcs-mtk-usxgmii.h
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12934,7 +12934,9 @@ M: Daniel Golle <daniel@makrotopia.org>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/pcs/pcs-mtk-lynxi.c
+F: drivers/net/pcs/pcs-mtk-usxgmii.c
F: include/linux/pcs/pcs-mtk-lynxi.h
+F: include/linux/pcs/pcs-mtk-usxgmii.h
MEDIATEK I2C CONTROLLER DRIVER
M: Qii Wang <qii.wang@mediatek.com>
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -18,6 +18,17 @@ config PCS_LYNX
This module provides helpers to phylink for managing the Lynx PCS
which is part of the Layerscape and QorIQ Ethernet SERDES.
+config PCS_MTK_USXGMII
+ tristate "MediaTek USXGMII PCS"
+ select PCS_MTK_LYNXI
+ select PHY_MTK_PEXTP
+ select PHYLINK
+ help
+ This module provides a driver for MediaTek's USXGMII PCS supporting
+ 10GBase-R, 5GBase-R and USXGMII interface modes.
+ 1000Base-X, 2500Base-X and Cisco SGMII are supported on the same
+ differential pairs via an embedded LynxI PHY.
+
config PCS_RZN1_MIIC
tristate "Renesas RZ/N1 MII converter"
depends on OF && (ARCH_RZN1 || COMPILE_TEST)
--- a/drivers/net/pcs/Makefile
+++ b/drivers/net/pcs/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o
obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o
obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o
obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o
+obj-$(CONFIG_PCS_MTK_USXGMII) += pcs-mtk-usxgmii.o
--- /dev/null
+++ b/drivers/net/pcs/pcs-mtk-usxgmii.c
@@ -0,0 +1,456 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Henry Yen <henry.yen@mediatek.com>
+ * Daniel Golle <daniel@makrotopia.org>
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mdio.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/reset.h>
+#include <linux/pcs/pcs-mtk-usxgmii.h>
+#include <linux/platform_device.h>
+
+/* USXGMII subsystem config registers */
+/* Register to control speed */
+#define RG_PHY_TOP_SPEED_CTRL1 0x80c
+#define USXGMII_RATE_UPDATE_MODE BIT(31)
+#define USXGMII_MAC_CK_GATED BIT(29)
+#define USXGMII_IF_FORCE_EN BIT(28)
+#define USXGMII_RATE_ADAPT_MODE GENMASK(10, 8)
+#define USXGMII_RATE_ADAPT_MODE_X1 0
+#define USXGMII_RATE_ADAPT_MODE_X2 1
+#define USXGMII_RATE_ADAPT_MODE_X4 2
+#define USXGMII_RATE_ADAPT_MODE_X10 3
+#define USXGMII_RATE_ADAPT_MODE_X100 4
+#define USXGMII_RATE_ADAPT_MODE_X5 5
+#define USXGMII_RATE_ADAPT_MODE_X50 6
+#define USXGMII_XFI_RX_MODE GENMASK(6, 4)
+#define USXGMII_XFI_TX_MODE GENMASK(2, 0)
+#define USXGMII_XFI_MODE_10G 0
+#define USXGMII_XFI_MODE_5G 1
+#define USXGMII_XFI_MODE_2P5G 3
+
+/* Register to control PCS AN */
+#define RG_PCS_AN_CTRL0 0x810
+#define USXGMII_AN_RESTART BIT(31)
+#define USXGMII_AN_SYNC_CNT GENMASK(30, 11)
+#define USXGMII_AN_ENABLE BIT(0)
+
+#define RG_PCS_AN_CTRL2 0x818
+#define USXGMII_LINK_TIMER_IDLE_DETECT GENMASK(29, 20)
+#define USXGMII_LINK_TIMER_COMP_ACK_DETECT GENMASK(19, 10)
+#define USXGMII_LINK_TIMER_AN_RESTART GENMASK(9, 0)
+
+/* Register to read PCS AN status */
+#define RG_PCS_AN_STS0 0x81c
+#define USXGMII_LPA GENMASK(15, 0)
+#define USXGMII_LPA_LATCH BIT(31)
+
+/* Register to read PCS link status */
+#define RG_PCS_RX_STATUS0 0x904
+#define RG_PCS_RX_STATUS_UPDATE BIT(16)
+#define RG_PCS_RX_LINK_STATUS BIT(2)
+
+/* struct mtk_usxgmii_pcs - This structure holds each usxgmii PCS
+ * @pcs: Phylink PCS structure
+ * @dev: Pointer to device structure
+ * @base: IO memory to access PCS hardware
+ * @clk: Pointer to USXGMII clk
+ * @reset: Pointer to USXGMII reset control
+ * @interface: Currently selected interface mode
+ * @neg_mode: Currently used phylink neg_mode
+ * @node: List node
+ */
+struct mtk_usxgmii_pcs {
+ struct phylink_pcs pcs;
+ struct device *dev;
+ void __iomem *base;
+ struct clk *clk;
+ struct reset_control *reset;
+ phy_interface_t interface;
+ unsigned int neg_mode;
+ struct list_head node;
+};
+
+static LIST_HEAD(mtk_usxgmii_pcs_instances);
+static DEFINE_MUTEX(instance_mutex);
+
+static u32 mtk_r32(struct mtk_usxgmii_pcs *mpcs, unsigned int reg)
+{
+ return ioread32(mpcs->base + reg);
+}
+
+static void mtk_m32(struct mtk_usxgmii_pcs *mpcs, unsigned int reg, u32 mask, u32 set)
+{
+ u32 val;
+
+ val = ioread32(mpcs->base + reg);
+ val &= ~mask;
+ val |= set;
+ iowrite32(val, mpcs->base + reg);
+}
+
+static struct mtk_usxgmii_pcs *pcs_to_mtk_usxgmii_pcs(struct phylink_pcs *pcs)
+{
+ return container_of(pcs, struct mtk_usxgmii_pcs, pcs);
+}
+
+static void mtk_usxgmii_reset(struct mtk_usxgmii_pcs *mpcs)
+{
+ reset_control_assert(mpcs->reset);
+ udelay(100);
+ reset_control_deassert(mpcs->reset);
+
+ mdelay(10);
+}
+
+static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ bool permit_pause_to_mac)
+{
+ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
+ unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0;
+ bool mode_changed = false;
+
+ if (interface == PHY_INTERFACE_MODE_USXGMII) {
+ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) | USXGMII_AN_ENABLE;
+ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
+ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
+ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
+ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_10G) |
+ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_10G);
+ } else if (interface == PHY_INTERFACE_MODE_10GBASER) {
+ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF);
+ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
+ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
+ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
+ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_10G) |
+ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_10G);
+ adapt_mode = USXGMII_RATE_UPDATE_MODE;
+ } else if (interface == PHY_INTERFACE_MODE_5GBASER) {
+ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0xFF);
+ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x3D) |
+ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x3D) |
+ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x3D);
+ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_5G) |
+ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_5G);
+ adapt_mode = USXGMII_RATE_UPDATE_MODE;
+ } else {
+ return -EINVAL;
+ }
+
+ adapt_mode |= FIELD_PREP(USXGMII_RATE_ADAPT_MODE, USXGMII_RATE_ADAPT_MODE_X1);
+
+ if (mpcs->interface != interface) {
+ mpcs->interface = interface;
+ mode_changed = true;
+ }
+
+ mtk_usxgmii_reset(mpcs);
+
+ /* Setup USXGMII AN ctrl */
+ mtk_m32(mpcs, RG_PCS_AN_CTRL0,
+ USXGMII_AN_SYNC_CNT | USXGMII_AN_ENABLE,
+ an_ctrl);
+
+ mtk_m32(mpcs, RG_PCS_AN_CTRL2,
+ USXGMII_LINK_TIMER_IDLE_DETECT |
+ USXGMII_LINK_TIMER_COMP_ACK_DETECT |
+ USXGMII_LINK_TIMER_AN_RESTART,
+ link_timer);
+
+ mpcs->neg_mode = neg_mode;
+
+ /* Gated MAC CK */
+ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1,
+ USXGMII_MAC_CK_GATED, USXGMII_MAC_CK_GATED);
+
+ /* Enable interface force mode */
+ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1,
+ USXGMII_IF_FORCE_EN, USXGMII_IF_FORCE_EN);
+
+ /* Setup USXGMII adapt mode */
+ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1,
+ USXGMII_RATE_UPDATE_MODE | USXGMII_RATE_ADAPT_MODE,
+ adapt_mode);
+
+ /* Setup USXGMII speed */
+ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1,
+ USXGMII_XFI_RX_MODE | USXGMII_XFI_TX_MODE,
+ xfi_mode);
+
+ usleep_range(1, 10);
+
+ /* Un-gated MAC CK */
+ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, USXGMII_MAC_CK_GATED, 0);
+
+ usleep_range(1, 10);
+
+ /* Disable interface force mode for the AN mode */
+ if (an_ctrl & USXGMII_AN_ENABLE)
+ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, USXGMII_IF_FORCE_EN, 0);
+
+ return mode_changed;
+}
+
+static void mtk_usxgmii_pcs_get_fixed_speed(struct mtk_usxgmii_pcs *mpcs,
+ struct phylink_link_state *state)
+{
+ u32 val = mtk_r32(mpcs, RG_PHY_TOP_SPEED_CTRL1);
+ int speed;
+
+ /* Calculate speed from interface speed and rate adapt mode */
+ switch (FIELD_GET(USXGMII_XFI_RX_MODE, val)) {
+ case USXGMII_XFI_MODE_10G:
+ speed = 10000;
+ break;
+ case USXGMII_XFI_MODE_5G:
+ speed = 5000;
+ break;
+ case USXGMII_XFI_MODE_2P5G:
+ speed = 2500;
+ break;
+ default:
+ state->speed = SPEED_UNKNOWN;
+ return;
+ }
+
+ switch (FIELD_GET(USXGMII_RATE_ADAPT_MODE, val)) {
+ case USXGMII_RATE_ADAPT_MODE_X100:
+ speed /= 100;
+ break;
+ case USXGMII_RATE_ADAPT_MODE_X50:
+ speed /= 50;
+ break;
+ case USXGMII_RATE_ADAPT_MODE_X10:
+ speed /= 10;
+ break;
+ case USXGMII_RATE_ADAPT_MODE_X5:
+ speed /= 5;
+ break;
+ case USXGMII_RATE_ADAPT_MODE_X4:
+ speed /= 4;
+ break;
+ case USXGMII_RATE_ADAPT_MODE_X2:
+ speed /= 2;
+ break;
+ case USXGMII_RATE_ADAPT_MODE_X1:
+ break;
+ default:
+ state->speed = SPEED_UNKNOWN;
+ return;
+ }
+
+ state->speed = speed;
+ state->duplex = DUPLEX_FULL;
+}
+
+static void mtk_usxgmii_pcs_get_an_state(struct mtk_usxgmii_pcs *mpcs,
+ struct phylink_link_state *state)
+{
+ u16 lpa;
+
+ /* Refresh LPA by toggling LPA_LATCH */
+ mtk_m32(mpcs, RG_PCS_AN_STS0, USXGMII_LPA_LATCH, USXGMII_LPA_LATCH);
+ ndelay(1020);
+ mtk_m32(mpcs, RG_PCS_AN_STS0, USXGMII_LPA_LATCH, 0);
+ ndelay(1020);
+ lpa = FIELD_GET(USXGMII_LPA, mtk_r32(mpcs, RG_PCS_AN_STS0));
+
+ phylink_decode_usxgmii_word(state, lpa);
+}
+
+static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs,
+ struct phylink_link_state *state)
+{
+ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
+
+ /* Refresh USXGMII link status by toggling RG_PCS_AN_STATUS_UPDATE */
+ mtk_m32(mpcs, RG_PCS_RX_STATUS0, RG_PCS_RX_STATUS_UPDATE,
+ RG_PCS_RX_STATUS_UPDATE);
+ ndelay(1020);
+ mtk_m32(mpcs, RG_PCS_RX_STATUS0, RG_PCS_RX_STATUS_UPDATE, 0);
+ ndelay(1020);
+
+ /* Read USXGMII link status */
+ state->link = FIELD_GET(RG_PCS_RX_LINK_STATUS,
+ mtk_r32(mpcs, RG_PCS_RX_STATUS0));
+
+ /* Continuously repeat re-configuration sequence until link comes up */
+ if (!state->link) {
+ mtk_usxgmii_pcs_config(pcs, mpcs->neg_mode,
+ state->interface, NULL, false);
+ return;
+ }
+
+ if (FIELD_GET(USXGMII_AN_ENABLE, mtk_r32(mpcs, RG_PCS_AN_CTRL0)))
+ mtk_usxgmii_pcs_get_an_state(mpcs, state);
+ else
+ mtk_usxgmii_pcs_get_fixed_speed(mpcs, state);
+}
+
+static void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs)
+{
+ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
+
+ mtk_m32(mpcs, RG_PCS_AN_CTRL0, USXGMII_AN_RESTART, USXGMII_AN_RESTART);
+}
+
+static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface,
+ int speed, int duplex)
+{
+ /* Reconfiguring USXGMII to ensure the quality of the RX signal
+ * after the line side link up.
+ */
+ mtk_usxgmii_pcs_config(pcs, neg_mode, interface, NULL, false);
+}
+
+static void mtk_usxgmii_pcs_disable(struct phylink_pcs *pcs)
+{
+ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
+
+ mpcs->interface = PHY_INTERFACE_MODE_NA;
+ mpcs->neg_mode = -1;
+}
+
+static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = {
+ .pcs_config = mtk_usxgmii_pcs_config,
+ .pcs_get_state = mtk_usxgmii_pcs_get_state,
+ .pcs_an_restart = mtk_usxgmii_pcs_restart_an,
+ .pcs_link_up = mtk_usxgmii_pcs_link_up,
+ .pcs_disable = mtk_usxgmii_pcs_disable,
+};
+
+static int mtk_usxgmii_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_usxgmii_pcs *mpcs;
+
+ mpcs = devm_kzalloc(dev, sizeof(*mpcs), GFP_KERNEL);
+ if (!mpcs)
+ return -ENOMEM;
+
+ mpcs->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(mpcs->base))
+ return PTR_ERR(mpcs->base);
+
+ mpcs->dev = dev;
+ mpcs->pcs.ops = &mtk_usxgmii_pcs_ops;
+ mpcs->pcs.poll = true;
+ mpcs->pcs.neg_mode = true;
+ mpcs->interface = PHY_INTERFACE_MODE_NA;
+ mpcs->neg_mode = -1;
+
+ mpcs->clk = devm_clk_get_enabled(mpcs->dev, NULL);
+ if (IS_ERR(mpcs->clk))
+ return PTR_ERR(mpcs->clk);
+
+ mpcs->reset = devm_reset_control_get_shared(dev, NULL);
+ if (IS_ERR(mpcs->reset))
+ return PTR_ERR(mpcs->reset);
+
+ reset_control_deassert(mpcs->reset);
+
+ platform_set_drvdata(pdev, mpcs);
+
+ mutex_lock(&instance_mutex);
+ list_add_tail(&mpcs->node, &mtk_usxgmii_pcs_instances);
+ mutex_unlock(&instance_mutex);
+
+ return 0;
+}
+
+static int mtk_usxgmii_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_usxgmii_pcs *cur, *tmp;
+
+ mutex_lock(&instance_mutex);
+ list_for_each_entry_safe(cur, tmp, &mtk_usxgmii_pcs_instances, node)
+ if (cur->dev == dev) {
+ list_del(&cur->node);
+ break;
+ }
+ mutex_unlock(&instance_mutex);
+
+ return 0;
+}
+
+static const struct of_device_id mtk_usxgmii_of_mtable[] = {
+ { .compatible = "mediatek,mt7988-usxgmiisys" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mtk_usxgmii_of_mtable);
+
+struct phylink_pcs *mtk_usxgmii_pcs_get(struct device *dev, struct device_node *np)
+{
+ struct platform_device *pdev;
+ struct mtk_usxgmii_pcs *mpcs;
+
+ if (!np)
+ return NULL;
+
+ if (!of_device_is_available(np))
+ return ERR_PTR(-ENODEV);
+
+ if (!of_match_node(mtk_usxgmii_of_mtable, np))
+ return ERR_PTR(-EINVAL);
+
+ pdev = of_find_device_by_node(np);
+ if (!pdev || !platform_get_drvdata(pdev)) {
+ if (pdev)
+ put_device(&pdev->dev);
+ return ERR_PTR(-EPROBE_DEFER);
+ }
+
+ mpcs = platform_get_drvdata(pdev);
+ device_link_add(dev, mpcs->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+
+ return &mpcs->pcs;
+}
+EXPORT_SYMBOL(mtk_usxgmii_pcs_get);
+
+void mtk_usxgmii_pcs_put(struct phylink_pcs *pcs)
+{
+ struct mtk_usxgmii_pcs *cur, *mpcs = NULL;
+
+ if (!pcs)
+ return;
+
+ mutex_lock(&instance_mutex);
+ list_for_each_entry(cur, &mtk_usxgmii_pcs_instances, node)
+ if (pcs == &cur->pcs) {
+ mpcs = cur;
+ break;
+ }
+ mutex_unlock(&instance_mutex);
+
+ if (WARN_ON(!mpcs))
+ return;
+
+ put_device(mpcs->dev);
+}
+EXPORT_SYMBOL(mtk_usxgmii_pcs_put);
+
+static struct platform_driver mtk_usxgmii_driver = {
+ .driver = {
+ .name = "mtk_usxgmii",
+ .suppress_bind_attrs = true,
+ .of_match_table = mtk_usxgmii_of_mtable,
+ },
+ .probe = mtk_usxgmii_probe,
+ .remove = mtk_usxgmii_remove,
+};
+module_platform_driver(mtk_usxgmii_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MediaTek USXGMII PCS driver");
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
--- /dev/null
+++ b/include/linux/pcs/pcs-mtk-usxgmii.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_PCS_MTK_USXGMII_H
+#define __LINUX_PCS_MTK_USXGMII_H
+
+#include <linux/phylink.h>
+
+/**
+ * mtk_usxgmii_select_pcs() - Get MediaTek PCS instance
+ * @np: Pointer to device node indentifying a MediaTek USXGMII PCS
+ * @mode: Ethernet PHY interface mode
+ *
+ * Return PCS identified by a device node and the PHY interface mode in use
+ *
+ * Return: Pointer to phylink PCS instance of NULL
+ */
+#if IS_ENABLED(CONFIG_PCS_MTK_USXGMII)
+struct phylink_pcs *mtk_usxgmii_pcs_get(struct device *dev, struct device_node *np);
+void mtk_usxgmii_pcs_put(struct phylink_pcs *pcs);
+#else
+static inline struct phylink_pcs *mtk_usxgmii_pcs_get(struct device *dev, struct device_node *np)
+{
+ return NULL;
+}
+static inline void mtk_usxgmii_pcs_put(struct phylink_pcs *pcs) { }
+#endif /* IS_ENABLED(CONFIG_PCS_MTK_USXGMII) */
+
+#endif /* __LINUX_PCS_MTK_USXGMII_H */

View File

@ -32,7 +32,7 @@ Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17066,6 +17066,13 @@ L: netdev@vger.kernel.org
@@ -17068,6 +17068,13 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/qualcomm/emac/

View File

@ -64,7 +64,7 @@ Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17072,6 +17072,7 @@ L: netdev@vger.kernel.org
@@ -17074,6 +17074,7 @@ L: netdev@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/qcom,ipq4019-ess-edma.yaml
F: drivers/net/ethernet/qualcomm/ipqess/

View File

@ -10,9 +10,18 @@
#include <dt-bindings/leds/common.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/pinctrl/mt65xx.h>
#include <dt-bindings/reset/ti-syscon.h>
#include <dt-bindings/reset/mediatek,mt7988-resets.h>
#include <dt-bindings/thermal/thermal.h>
/* TOPRGU resets */
#define MT7988_TOPRGU_SGMII0_GRST 1
#define MT7988_TOPRGU_SGMII1_GRST 2
#define MT7988_TOPRGU_XFI0_GRST 12
#define MT7988_TOPRGU_XFI1_GRST 13
#define MT7988_TOPRGU_XFI_PEXTP0_GRST 14
#define MT7988_TOPRGU_XFI_PEXTP1_GRST 15
#define MT7988_TOPRGU_XFI_PLL_GRST 16
/ {
compatible = "mediatek,mt7988";
interrupt-parent = <&gic>;
@ -218,6 +227,7 @@
compatible = "mediatek,mt7988-infracfg", "syscon";
reg = <0 0x10001000 0 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
topckgen: topckgen@1001b000 {
@ -509,34 +519,52 @@
sgmiisys0: syscon@10060000 {
compatible = "mediatek,mt7988-sgmiisys",
"mediatek,mt7988-sgmiisys_0",
"syscon";
"mediatek,mt7988-sgmiisys0",
"syscon",
"simple-mfd";
reg = <0 0x10060000 0 0x1000>;
resets = <&watchdog MT7988_TOPRGU_SGMII0_GRST>;
#clock-cells = <1>;
sgmiipcs0: pcs {
compatible = "mediatek,mt7988-sgmii";
clocks = <&topckgen CLK_TOP_SGM_0_SEL>,
<&sgmiisys0 CLK_SGM0_TX_EN>,
<&sgmiisys0 CLK_SGM0_RX_EN>;
clock-names = "sgmii_sel", "sgmii_tx", "sgmii_rx";
};
};
sgmiisys1: syscon@10070000 {
compatible = "mediatek,mt7988-sgmiisys",
"mediatek,mt7988-sgmiisys_1",
"syscon";
"mediatek,mt7988-sgmiisys1",
"syscon",
"simple-mfd";
reg = <0 0x10070000 0 0x1000>;
resets = <&watchdog MT7988_TOPRGU_SGMII1_GRST>;
#clock-cells = <1>;
sgmiipcs1: pcs {
compatible = "mediatek,mt7988-sgmii";
clocks = <&topckgen CLK_TOP_SGM_1_SEL>,
<&sgmiisys1 CLK_SGM1_TX_EN>,
<&sgmiisys1 CLK_SGM1_RX_EN>;
clock-names = "sgmii_sel", "sgmii_tx", "sgmii_rx";
};
};
usxgmiisys0: usxgmiisys@10080000 {
compatible = "mediatek,mt7988-usxgmiisys",
"mediatek,mt7988-usxgmiisys_0",
"syscon";
usxgmiisys0: pcs@10080000 {
compatible = "mediatek,mt7988-usxgmiisys";
reg = <0 0x10080000 0 0x1000>;
#clock-cells = <1>;
resets = <&watchdog MT7988_TOPRGU_XFI0_GRST>;
clocks = <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>;
};
usxgmiisys1: usxgmiisys@10081000 {
compatible = "mediatek,mt7988-usxgmiisys",
"mediatek,mt7988-usxgmiisys_1",
"syscon";
usxgmiisys1: pcs@10081000 {
compatible = "mediatek,mt7988-usxgmiisys";
reg = <0 0x10081000 0 0x1000>;
#clock-cells = <1>;
resets = <&watchdog MT7988_TOPRGU_XFI1_GRST>;
clocks = <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>;
};
mcusys: mcusys@100e0000 {
@ -1018,25 +1046,29 @@
};
};
xfi_pextp0: xfi-pextp@11f20000 {
compatible = "mediatek,mt7988-xfi-pextp",
"mediatek,mt7988-xfi-pextp_0",
"syscon";
xfi_tphy0: phy@11f20000 {
compatible = "mediatek,mt7988-xfi-tphy";
reg = <0 0x11f20000 0 0x10000>;
#clock-cells = <1>;
resets = <&watchdog MT7988_TOPRGU_XFI_PEXTP0_GRST>;
clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>, <&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>;
clock-names = "xfipll", "topxtal";
mediatek,usxgmii-performance-errata;
#phy-cells = <0>;
};
xfi_pextp1: xfi-pextp@11f30000 {
compatible = "mediatek,mt7988-xfi-pextp",
"mediatek,mt7988-xfi-pextp_1",
"syscon";
xfi_tphy1: phy@11f30000 {
compatible = "mediatek,mt7988-xfi-tphy";
reg = <0 0x11f30000 0 0x10000>;
#clock-cells = <1>;
resets = <&watchdog MT7988_TOPRGU_XFI_PEXTP1_GRST>;
clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>, <&topckgen CLK_TOP_XFI_PHY_1_XTAL_SEL>;
clock-names = "xfipll", "topxtal";
#phy-cells = <0>;
};
xfi_pll: xfi-pll@11f40000 {
compatible = "mediatek,mt7988-xfi-pll", "syscon";
xfi_pll: clock-controller@11f40000 {
compatible = "mediatek,mt7988-xfi-pll";
reg = <0 0x11f40000 0 0x1000>;
resets = <&watchdog MT7988_TOPRGU_XFI_PLL_GRST>;
#clock-cells = <1>;
};
@ -1087,7 +1119,7 @@
#interrupt-cells = <1>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
resets = <&ethrst 0>;
resets = <&ethwarp MT7988_ETHWARP_RST_SWITCH>;
#address-cells = <1>;
#size-cells = <1>;
@ -1243,18 +1275,11 @@
};
};
ethwarp: syscon@15031000 {
compatible = "mediatek,mt7988-ethwarp", "syscon", "simple-mfd";
ethwarp: clock-controller@15031000 {
compatible = "mediatek,mt7988-ethwarp";
reg = <0 0x15031000 0 0x1000>;
#clock-cells = <1>;
ethrst: reset-controller {
compatible = "ti,syscon-reset";
#reset-cells = <1>;
ti,reset-bits = <
0x8 9 0x8 9 0 0 (ASSERT_SET | DEASSERT_CLEAR | STATUS_NONE)
>;
};
#reset-cells = <1>;
};
eth: ethernet@15100000 {
@ -1274,19 +1299,9 @@
<&ethsys CLK_ETHDMA_GP3_EN>,
<&ethsys CLK_ETHDMA_ESW_EN>,
<&ethsys CLK_ETHDMA_CRYPT0_EN>,
<&sgmiisys0 CLK_SGM0_TX_EN>,
<&sgmiisys0 CLK_SGM0_RX_EN>,
<&sgmiisys1 CLK_SGM1_TX_EN>,
<&sgmiisys1 CLK_SGM1_RX_EN>,
<&ethwarp CLK_ETHWARP_WOCPU2_EN>,
<&ethwarp CLK_ETHWARP_WOCPU1_EN>,
<&ethwarp CLK_ETHWARP_WOCPU0_EN>,
<&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>,
<&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>,
<&topckgen CLK_TOP_SGM_0_SEL>,
<&topckgen CLK_TOP_SGM_1_SEL>,
<&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>,
<&topckgen CLK_TOP_XFI_PHY_1_XTAL_SEL>,
<&topckgen CLK_TOP_ETH_GMII_SEL>,
<&topckgen CLK_TOP_ETH_REFCK_50M_SEL>,
<&topckgen CLK_TOP_ETH_SYS_200M_SEL>,
@ -1300,13 +1315,9 @@
<&topckgen CLK_TOP_NETSYS_PPEFB_250M_SEL>,
<&topckgen CLK_TOP_NETSYS_WARP_SEL>;
clock-names = "xgp1", "xgp2", "xgp3", "fe", "gp2", "gp1",
"gp3", "esw", "crypto", "sgmii_tx250m",
"sgmii_rx250m", "sgmii2_tx250m", "sgmii2_rx250m",
"gp3", "esw", "crypto",
"ethwarp_wocpu2", "ethwarp_wocpu1",
"ethwarp_wocpu0", "top_usxgmii0_sel",
"top_usxgmii1_sel", "top_sgm0_sel",
"top_sgm1_sel", "top_xfi_phy0_xtal_sel",
"top_xfi_phy1_xtal_sel", "top_eth_gmii_sel",
"ethwarp_wocpu0", "top_eth_gmii_sel",
"top_eth_refck_50m_sel", "top_eth_sys_200m_sel",
"top_eth_sys_sel", "top_eth_xgmii_sel",
"top_eth_mii_sel", "top_netsys_sel",
@ -1327,13 +1338,7 @@
<&apmixedsys CLK_APMIXED_SGMPLL>,
<&apmixedsys CLK_APMIXED_SGMPLL>;
mediatek,ethsys = <&ethsys>;
mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>;
mediatek,xfi-pextp = <&xfi_pextp0>, <&xfi_pextp1>;
mediatek,xfi-pll = <&xfi_pll>;
mediatek,infracfg = <&topmisc>;
mediatek,toprgu = <&watchdog>;
#reset-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
@ -1354,12 +1359,16 @@
compatible = "mediatek,eth-mac";
reg = <1>;
status = "disabled";
pcs-handle = <&sgmiipcs1>, <&usxgmiisys1>;
phys = <&xfi_tphy1>;
};
gmac2: mac@2 {
compatible = "mediatek,eth-mac";
reg = <2>;
status = "disabled";
pcs-handle = <&sgmiipcs0>, <&usxgmiisys0>;
phys = <&xfi_tphy0>;
};
mdio_bus: mdio-bus {

View File

@ -280,7 +280,6 @@ CONFIG_NET_DSA_MT7530_MMIO=y
CONFIG_NET_DSA_TAG_MTK=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_MEDIATEK_SOC=y
CONFIG_NET_MEDIATEK_SOC_USXGMII=y
CONFIG_NET_MEDIATEK_SOC_WED=y
CONFIG_NET_SELFTESTS=y
CONFIG_NET_SWITCHDEV=y
@ -327,6 +326,7 @@ CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
CONFIG_PCS_MTK_LYNXI=y
CONFIG_PCS_MTK_USXGMII=y
CONFIG_PERF_EVENTS=y
CONFIG_PGTABLE_LEVELS=3
CONFIG_PHYLIB=y
@ -337,6 +337,7 @@ CONFIG_PHYS_ADDR_T_64BIT=y
# CONFIG_PHY_MTK_PCIE is not set
CONFIG_PHY_MTK_TPHY=y
# CONFIG_PHY_MTK_UFS is not set
CONFIG_PHY_MTK_XFI_TPHY=y
CONFIG_PHY_MTK_XSPHY=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_MT2712 is not set

View File

@ -24,9 +24,9 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12936,6 +12936,15 @@ S: Maintained
F: drivers/net/pcs/pcs-mtk-lynxi.c
@@ -12938,6 +12938,15 @@ F: drivers/net/pcs/pcs-mtk-usxgmii.c
F: include/linux/pcs/pcs-mtk-lynxi.h
F: include/linux/pcs/pcs-mtk-usxgmii.h
+MEDIATEK ETHERNET PHY DRIVERS
+M: Daniel Golle <daniel@makrotopia.org>

View File

@ -15,7 +15,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1238,7 +1238,7 @@ static int mtk_init_fq_dma(struct mtk_et
@@ -1264,7 +1264,7 @@ static int mtk_init_fq_dma(struct mtk_et
eth->scratch_ring = eth->sram_base;
else
eth->scratch_ring = dma_alloc_coherent(eth->dma_dev,
@ -24,7 +24,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
&eth->phy_scratch_ring,
GFP_KERNEL);
if (unlikely(!eth->scratch_ring))
@@ -1254,16 +1254,16 @@ static int mtk_init_fq_dma(struct mtk_et
@@ -1280,16 +1280,16 @@ static int mtk_init_fq_dma(struct mtk_et
if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr)))
return -ENOMEM;
@ -44,7 +44,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE);
txd->txd4 = 0;
@@ -1512,7 +1512,7 @@ static int mtk_tx_map(struct sk_buff *sk
@@ -1538,7 +1538,7 @@ static int mtk_tx_map(struct sk_buff *sk
if (itxd == ring->last_free)
return -ENOMEM;
@ -53,7 +53,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
memset(itx_buf, 0, sizeof(*itx_buf));
txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size,
@@ -1553,7 +1553,7 @@ static int mtk_tx_map(struct sk_buff *sk
@@ -1579,7 +1579,7 @@ static int mtk_tx_map(struct sk_buff *sk
memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
txd_info.size = min_t(unsigned int, frag_size,
@ -62,7 +62,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
txd_info.qid = queue;
txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 &&
!(frag_size - txd_info.size);
@@ -1566,7 +1566,7 @@ static int mtk_tx_map(struct sk_buff *sk
@@ -1592,7 +1592,7 @@ static int mtk_tx_map(struct sk_buff *sk
mtk_tx_set_dma_desc(dev, txd, &txd_info);
tx_buf = mtk_desc_to_tx_buf(ring, txd,
@ -71,7 +71,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
if (new_desc)
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
@@ -1609,7 +1609,7 @@ static int mtk_tx_map(struct sk_buff *sk
@@ -1635,7 +1635,7 @@ static int mtk_tx_map(struct sk_buff *sk
} else {
int next_idx;
@ -80,7 +80,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
ring->dma_size);
mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0);
}
@@ -1618,7 +1618,7 @@ static int mtk_tx_map(struct sk_buff *sk
@@ -1644,7 +1644,7 @@ static int mtk_tx_map(struct sk_buff *sk
err_dma:
do {
@ -89,7 +89,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
/* unmap dma */
mtk_tx_unmap(eth, tx_buf, NULL, false);
@@ -1643,7 +1643,7 @@ static int mtk_cal_txd_req(struct mtk_et
@@ -1669,7 +1669,7 @@ static int mtk_cal_txd_req(struct mtk_et
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
frag = &skb_shinfo(skb)->frags[i];
nfrags += DIV_ROUND_UP(skb_frag_size(frag),
@ -98,7 +98,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
}
} else {
nfrags += skb_shinfo(skb)->nr_frags;
@@ -1784,7 +1784,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri
@@ -1810,7 +1810,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri
ring = &eth->rx_ring[i];
idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
@ -107,7 +107,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
if (rxd->rxd2 & RX_DMA_DONE) {
ring->calc_idx_update = true;
return ring;
@@ -1952,7 +1952,7 @@ static int mtk_xdp_submit_frame(struct m
@@ -1978,7 +1978,7 @@ static int mtk_xdp_submit_frame(struct m
}
htxd = txd;
@ -116,7 +116,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
memset(tx_buf, 0, sizeof(*tx_buf));
htx_buf = tx_buf;
@@ -1971,7 +1971,7 @@ static int mtk_xdp_submit_frame(struct m
@@ -1997,7 +1997,7 @@ static int mtk_xdp_submit_frame(struct m
goto unmap;
tx_buf = mtk_desc_to_tx_buf(ring, txd,
@ -125,7 +125,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
memset(tx_buf, 0, sizeof(*tx_buf));
n_desc++;
}
@@ -2009,7 +2009,7 @@ static int mtk_xdp_submit_frame(struct m
@@ -2035,7 +2035,7 @@ static int mtk_xdp_submit_frame(struct m
} else {
int idx;
@ -134,7 +134,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size),
MT7628_TX_CTX_IDX0);
}
@@ -2020,7 +2020,7 @@ static int mtk_xdp_submit_frame(struct m
@@ -2046,7 +2046,7 @@ static int mtk_xdp_submit_frame(struct m
unmap:
while (htxd != txd) {
@ -143,7 +143,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
mtk_tx_unmap(eth, tx_buf, NULL, false);
htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
@@ -2151,7 +2151,7 @@ static int mtk_poll_rx(struct napi_struc
@@ -2177,7 +2177,7 @@ static int mtk_poll_rx(struct napi_struc
goto rx_done;
idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
@ -152,7 +152,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
data = ring->data[idx];
if (!mtk_rx_get_desc(eth, &trxd, rxd))
@@ -2286,7 +2286,7 @@ static int mtk_poll_rx(struct napi_struc
@@ -2312,7 +2312,7 @@ static int mtk_poll_rx(struct napi_struc
rxdcsum = &trxd.rxd4;
}
@ -161,7 +161,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb_checksum_none_assert(skb);
@@ -2410,7 +2410,7 @@ static int mtk_poll_tx_qdma(struct mtk_e
@@ -2436,7 +2436,7 @@ static int mtk_poll_tx_qdma(struct mtk_e
break;
tx_buf = mtk_desc_to_tx_buf(ring, desc,
@ -170,7 +170,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
if (!tx_buf->data)
break;
@@ -2461,7 +2461,7 @@ static int mtk_poll_tx_pdma(struct mtk_e
@@ -2487,7 +2487,7 @@ static int mtk_poll_tx_pdma(struct mtk_e
}
mtk_tx_unmap(eth, tx_buf, &bq, true);
@ -179,7 +179,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
ring->last_free = desc;
atomic_inc(&ring->free_count);
@@ -2551,7 +2551,7 @@ static int mtk_napi_rx(struct napi_struc
@@ -2577,7 +2577,7 @@ static int mtk_napi_rx(struct napi_struc
do {
int rx_done;
@ -188,7 +188,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
reg_map->pdma.irq_status);
rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth);
rx_done_total += rx_done;
@@ -2567,10 +2567,10 @@ static int mtk_napi_rx(struct napi_struc
@@ -2593,10 +2593,10 @@ static int mtk_napi_rx(struct napi_struc
return budget;
} while (mtk_r32(eth, reg_map->pdma.irq_status) &
@ -201,7 +201,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
return rx_done_total;
}
@@ -2579,7 +2579,7 @@ static int mtk_tx_alloc(struct mtk_eth *
@@ -2605,7 +2605,7 @@ static int mtk_tx_alloc(struct mtk_eth *
{
const struct mtk_soc_data *soc = eth->soc;
struct mtk_tx_ring *ring = &eth->tx_ring;
@ -210,7 +210,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
struct mtk_tx_dma_v2 *txd;
int ring_size;
u32 ofs, val;
@@ -2702,14 +2702,14 @@ static void mtk_tx_clean(struct mtk_eth
@@ -2728,14 +2728,14 @@ static void mtk_tx_clean(struct mtk_eth
}
if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) {
dma_free_coherent(eth->dma_dev,
@ -227,7 +227,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
ring->dma_pdma, ring->phys_pdma);
ring->dma_pdma = NULL;
}
@@ -2764,15 +2764,15 @@ static int mtk_rx_alloc(struct mtk_eth *
@@ -2790,15 +2790,15 @@ static int mtk_rx_alloc(struct mtk_eth *
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) ||
rx_flag != MTK_RX_FLAGS_NORMAL) {
ring->dma = dma_alloc_coherent(eth->dma_dev,
@ -247,7 +247,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
}
if (!ring->dma)
@@ -2783,7 +2783,7 @@ static int mtk_rx_alloc(struct mtk_eth *
@@ -2809,7 +2809,7 @@ static int mtk_rx_alloc(struct mtk_eth *
dma_addr_t dma_addr;
void *data;
@ -256,7 +256,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
if (ring->page_pool) {
data = mtk_page_pool_get_buff(ring->page_pool,
&dma_addr, GFP_KERNEL);
@@ -2874,7 +2874,7 @@ static void mtk_rx_clean(struct mtk_eth
@@ -2900,7 +2900,7 @@ static void mtk_rx_clean(struct mtk_eth
if (!ring->data[i])
continue;
@ -265,7 +265,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
if (!rxd->rxd1)
continue;
@@ -2891,7 +2891,7 @@ static void mtk_rx_clean(struct mtk_eth
@@ -2917,7 +2917,7 @@ static void mtk_rx_clean(struct mtk_eth
if (!in_sram && ring->dma) {
dma_free_coherent(eth->dma_dev,
@ -274,7 +274,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
ring->dma, ring->phys);
ring->dma = NULL;
}
@@ -3254,7 +3254,7 @@ static void mtk_dma_free(struct mtk_eth
@@ -3280,7 +3280,7 @@ static void mtk_dma_free(struct mtk_eth
netdev_reset_queue(eth->netdev[i]);
if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) {
dma_free_coherent(eth->dma_dev,
@ -283,7 +283,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
eth->scratch_ring, eth->phy_scratch_ring);
eth->scratch_ring = NULL;
eth->phy_scratch_ring = 0;
@@ -3304,7 +3304,7 @@ static irqreturn_t mtk_handle_irq_rx(int
@@ -3330,7 +3330,7 @@ static irqreturn_t mtk_handle_irq_rx(int
eth->rx_events++;
if (likely(napi_schedule_prep(&eth->rx_napi))) {
@ -292,7 +292,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
__napi_schedule(&eth->rx_napi);
}
@@ -3330,9 +3330,9 @@ static irqreturn_t mtk_handle_irq(int ir
@@ -3356,9 +3356,9 @@ static irqreturn_t mtk_handle_irq(int ir
const struct mtk_reg_map *reg_map = eth->soc->reg_map;
if (mtk_r32(eth, reg_map->pdma.irq_mask) &
@ -304,7 +304,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
mtk_handle_irq_rx(irq, _eth);
}
if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) {
@@ -3350,10 +3350,10 @@ static void mtk_poll_controller(struct n
@@ -3376,10 +3376,10 @@ static void mtk_poll_controller(struct n
struct mtk_eth *eth = mac->hw;
mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
@ -317,7 +317,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
}
#endif
@@ -3516,7 +3516,7 @@ static int mtk_open(struct net_device *d
@@ -3545,7 +3545,7 @@ static int mtk_open(struct net_device *d
napi_enable(&eth->tx_napi);
napi_enable(&eth->rx_napi);
mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
@ -326,7 +326,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
refcount_set(&eth->dma_refcnt, 1);
}
else
@@ -3599,7 +3599,7 @@ static int mtk_stop(struct net_device *d
@@ -3628,7 +3628,7 @@ static int mtk_stop(struct net_device *d
mtk_gdm_config(eth, MTK_GDMA_DROP_ALL);
mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
@ -335,7 +335,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
napi_disable(&eth->tx_napi);
napi_disable(&eth->rx_napi);
@@ -4075,9 +4075,9 @@ static int mtk_hw_init(struct mtk_eth *e
@@ -4107,9 +4107,9 @@ static int mtk_hw_init(struct mtk_eth *e
/* FE int grouping */
mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp);
@ -347,7 +347,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
if (mtk_is_netsys_v3_or_greater(eth)) {
@@ -5175,11 +5175,15 @@ static const struct mtk_soc_data mt2701_
@@ -5270,11 +5270,15 @@ static const struct mtk_soc_data mt2701_
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.version = 1,
@ -368,7 +368,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5195,11 +5199,15 @@ static const struct mtk_soc_data mt7621_
@@ -5290,11 +5294,15 @@ static const struct mtk_soc_data mt7621_
.offload_version = 1,
.hash_offset = 2,
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
@ -389,7 +389,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5217,11 +5225,15 @@ static const struct mtk_soc_data mt7622_
@@ -5312,11 +5320,15 @@ static const struct mtk_soc_data mt7622_
.hash_offset = 2,
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
@ -410,7 +410,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5238,11 +5250,15 @@ static const struct mtk_soc_data mt7623_
@@ -5333,11 +5345,15 @@ static const struct mtk_soc_data mt7623_
.hash_offset = 2,
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.disable_pll_modes = true,
@ -431,7 +431,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5257,11 +5273,15 @@ static const struct mtk_soc_data mt7629_
@@ -5352,11 +5368,15 @@ static const struct mtk_soc_data mt7629_
.required_pctl = false,
.has_accounting = true,
.version = 1,
@ -452,7 +452,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5279,11 +5299,15 @@ static const struct mtk_soc_data mt7981_
@@ -5374,11 +5394,15 @@ static const struct mtk_soc_data mt7981_
.hash_offset = 4,
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
@ -473,7 +473,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
},
@@ -5301,11 +5325,15 @@ static const struct mtk_soc_data mt7986_
@@ -5396,11 +5420,15 @@ static const struct mtk_soc_data mt7986_
.hash_offset = 4,
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
@ -494,7 +494,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
},
@@ -5323,11 +5351,15 @@ static const struct mtk_soc_data mt7988_
@@ -5418,11 +5446,15 @@ static const struct mtk_soc_data mt7988_
.hash_offset = 4,
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V3_SIZE,
@ -515,7 +515,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
},
@@ -5340,11 +5372,15 @@ static const struct mtk_soc_data rt5350_
@@ -5435,11 +5467,15 @@ static const struct mtk_soc_data rt5350_
.required_clks = MT7628_CLKS_BITMAP,
.required_pctl = false,
.version = 1,
@ -538,7 +538,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
},
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -326,8 +326,8 @@
@@ -327,8 +327,8 @@
/* QDMA descriptor txd3 */
#define TX_DMA_OWNER_CPU BIT(31)
#define TX_DMA_LS0 BIT(30)
@ -549,7 +549,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
#define TX_DMA_SWC BIT(14)
#define TX_DMA_PQID GENMASK(3, 0)
#define TX_DMA_ADDR64_MASK GENMASK(3, 0)
@@ -347,8 +347,8 @@
@@ -348,8 +348,8 @@
/* QDMA descriptor rxd2 */
#define RX_DMA_DONE BIT(31)
#define RX_DMA_LSO BIT(30)
@ -560,7 +560,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
#define RX_DMA_VTAG BIT(15)
#define RX_DMA_ADDR64_MASK GENMASK(3, 0)
#if IS_ENABLED(CONFIG_64BIT)
@@ -1279,10 +1279,9 @@ struct mtk_reg_map {
@@ -1209,10 +1209,9 @@ struct mtk_reg_map {
* @foe_entry_size Foe table entry size.
* @has_accounting Bool indicating support for accounting of
* offloaded flows.
@ -574,7 +574,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
* @dma_max_len Max DMA tx/rx buffer length.
* @dma_len_offset Tx/Rx DMA length field offset.
*/
@@ -1300,13 +1299,17 @@ struct mtk_soc_data {
@@ -1230,13 +1229,17 @@ struct mtk_soc_data {
bool has_accounting;
bool disable_pll_modes;
struct {

View File

@ -17,7 +17,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -108,16 +108,16 @@ static const struct mtk_reg_map mt7986_r
@@ -110,16 +110,16 @@ static const struct mtk_reg_map mt7986_r
.tx_irq_mask = 0x461c,
.tx_irq_status = 0x4618,
.pdma = {
@ -44,7 +44,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
},
.qdma = {
.qtx_cfg = 0x4400,
@@ -1206,7 +1206,7 @@ static bool mtk_rx_get_desc(struct mtk_e
@@ -1232,7 +1232,7 @@ static bool mtk_rx_get_desc(struct mtk_e
rxd->rxd1 = READ_ONCE(dma_rxd->rxd1);
rxd->rxd3 = READ_ONCE(dma_rxd->rxd3);
rxd->rxd4 = READ_ONCE(dma_rxd->rxd4);
@ -53,7 +53,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
rxd->rxd5 = READ_ONCE(dma_rxd->rxd5);
rxd->rxd6 = READ_ONCE(dma_rxd->rxd6);
}
@@ -2158,7 +2158,7 @@ static int mtk_poll_rx(struct napi_struc
@@ -2184,7 +2184,7 @@ static int mtk_poll_rx(struct napi_struc
break;
/* find out which mac the packet come from. values start at 1 */
@ -62,7 +62,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5);
switch (val) {
@@ -2270,7 +2270,7 @@ static int mtk_poll_rx(struct napi_struc
@@ -2296,7 +2296,7 @@ static int mtk_poll_rx(struct napi_struc
skb->dev = netdev;
bytes += skb->len;
@ -71,7 +71,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5);
hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY;
if (hash != MTK_RXD5_FOE_ENTRY)
@@ -2820,7 +2820,7 @@ static int mtk_rx_alloc(struct mtk_eth *
@@ -2846,7 +2846,7 @@ static int mtk_rx_alloc(struct mtk_eth *
rxd->rxd3 = 0;
rxd->rxd4 = 0;
@ -80,7 +80,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
rxd->rxd5 = 0;
rxd->rxd6 = 0;
rxd->rxd7 = 0;
@@ -4021,7 +4021,7 @@ static int mtk_hw_init(struct mtk_eth *e
@@ -4053,7 +4053,7 @@ static int mtk_hw_init(struct mtk_eth *e
else
mtk_hw_reset(eth);
@ -89,7 +89,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* Set FE to PDMAv2 if necessary */
val = mtk_r32(eth, MTK_FE_GLO_MISC);
mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC);
@@ -5305,11 +5305,11 @@ static const struct mtk_soc_data mt7981_
@@ -5400,11 +5400,11 @@ static const struct mtk_soc_data mt7981_
.dma_len_offset = 8,
},
.rx = {
@ -105,7 +105,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
},
};
@@ -5331,11 +5331,11 @@ static const struct mtk_soc_data mt7986_
@@ -5426,11 +5426,11 @@ static const struct mtk_soc_data mt7986_
.dma_len_offset = 8,
},
.rx = {

View File

@ -13,7 +13,7 @@ Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13012,6 +13012,12 @@ S: Maintained
@@ -13014,6 +13014,12 @@ S: Maintained
F: Documentation/devicetree/bindings/clock/mediatek,mt7621-sysc.yaml
F: drivers/clk/ralink/clk-mt7621.c

View File

@ -14,15 +14,15 @@ Signed-off-by: René van Dorst <opensource@vdorst.com>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4612,6 +4612,7 @@ static const struct net_device_ops mtk_n
@@ -4643,6 +4643,7 @@ static const struct net_device_ops mtk_n
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
{
+ const char *name = of_get_property(np, "label", NULL);
const __be32 *_id = of_get_property(np, "reg", NULL);
struct device_node *pcs_np;
phy_interface_t phy_mode;
struct phylink *phylink;
@@ -4783,6 +4784,9 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -4840,6 +4841,9 @@ static int mtk_add_mac(struct mtk_eth *e
register_netdevice_notifier(&mac->device_notifier);
}