[][kernel][mt7981/mt7988][eth][mediatek-ge/soc: backport mediatek gphy support]
[Description]
Add mediatek-ge-soc.c:
1. Remove "/* Registers on MDIO_MMD_VEND1 */" macros and add a short
comment to show that we set default MLT3 shaper values for MT7988:
2. "How does 13 map to GBE: +7, TBT: +1, HBT: +4, TST: +7 ?"
delete above fine-tuning because we use 100% TX amplitude on MT7981 now.
3. Remove all "inline"s
4. Enable MEDIATEK_GE_SOC_PHY.
Before we use mediatek-ge-soc.c, we need to backport some newer APIs:
* [net-next,v7,00/10] introduce read_poll_timeout
https://patchwork.ozlabs.org/project/netdev/patch/20200323150600.21382-
2-zhengdejin5@gmail.com/
We pickup:
01/10 for read_poll_timeout(), needed by phy_read_mmd_poll_timeout()
02/10
03/10 for phy_read_mmd_poll_timeout(),
needed by drivers/net/phy/mediatek-ge-soc.c
07/10 for phy_read_poll_timeout(), needed by drivers/net/phy/mxl-gpy.c
08/10
* [net-next,v3,0/3] add phy shared storage
https://patchwork.ozlabs.org/project/netdev/cover/20200506145315.13967-
1-michael@walle.cc/
We pickup 1/3 for phy_package_shared struct
* [net-next,v4,0/8] net: phy: mscc: PHC and timestamping support
https://patchwork.ozlabs.org/project/netdev/cover/20200623143014.47864-
1-antoine.tenart@bootlin.com/
We pick 1/8 for phy_package_probe_once()
mediatek-ge-soc.c file follows upstream code:
[net-next] net: phy: add driver for MediaTek SoC built-in GE PHYs
https://patchwork.kernel.org/project/linux-mediatek/patch/ZDihjfnzaZ1yh
9cT@makrotopia.org/
[Release-log]
N/A
Change-Id: I4de384b7430e22607c57a0d8ca931855b32340e2
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7374555
diff --git a/target/linux/generic/backport-5.4/790-v5.7-iopoll-introduce-read_poll_timeout-macro.patch b/target/linux/generic/backport-5.4/790-v5.7-iopoll-introduce-read_poll_timeout-macro.patch
new file mode 100644
index 0000000..26de067
--- /dev/null
+++ b/target/linux/generic/backport-5.4/790-v5.7-iopoll-introduce-read_poll_timeout-macro.patch
@@ -0,0 +1,269 @@
+From patchwork Mon Mar 23 15:05:51 2020
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Dejin Zheng <zhengdejin5@gmail.com>
+X-Patchwork-Id: 1260097
+X-Patchwork-Delegate: davem@davemloft.net
+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)
+ smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67;
+ helo=vger.kernel.org;
+ envelope-from=netdev-owner@vger.kernel.org;
+ receiver=<UNKNOWN>)
+Authentication-Results: ozlabs.org;
+ dmarc=pass (p=none dis=none) header.from=gmail.com
+Authentication-Results: ozlabs.org; dkim=pass (2048-bit key;
+ unprotected) header.d=gmail.com header.i=@gmail.com
+ header.a=rsa-sha256 header.s=20161025 header.b=N1ACwCYl;
+ dkim-atps=neutral
+Received: from vger.kernel.org (vger.kernel.org [209.132.180.67])
+ by ozlabs.org (Postfix) with ESMTP id 48mHlP3Hzhz9sSs
+ for <patchwork-incoming-netdev@ozlabs.org>;
+ Tue, 24 Mar 2020 02:06:25 +1100 (AEDT)
+Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
+ id S1727267AbgCWPGW (ORCPT
+ <rfc822;patchwork-incoming-netdev@ozlabs.org>);
+ Mon, 23 Mar 2020 11:06:22 -0400
+Received: from mail-pj1-f68.google.com ([209.85.216.68]:50286 "EHLO
+ mail-pj1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
+ with ESMTP id S1727024AbgCWPGV (ORCPT
+ <rfc822;netdev@vger.kernel.org>); Mon, 23 Mar 2020 11:06:21 -0400
+Received: by mail-pj1-f68.google.com with SMTP id v13so6312358pjb.0;
+ Mon, 23 Mar 2020 08:06:20 -0700 (PDT)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=gmail.com; s=20161025;
+ h=from:to:cc:subject:date:message-id:in-reply-to:references
+ :mime-version:content-transfer-encoding;
+ bh=GmXKgcJDZee4jC3cNKHKWCJhJ0kS9L2vONq2fIA+AaY=;
+ b=N1ACwCYlon7WkTCOGFsGWeQq6lNeUjbuQa8UGIBK7O82wFqYoTVzGY8MUnU/tEjer9
+ AtZt9996i6pDsvhpbunlFffuKPui1YOisSe6Xcn6Ur2AiFvfJr1DMpWE2PdmlLGH2bkH
+ /Oiqbikpi9dSUfgFJ7JfIyISqKyP15jsdhhl8xtA30gWb6CuhlhBuWuLV5CqTAZKGWab
+ LMFipg2GDKlx0udJoUoNAPi/hcypdWJW8DtamDxwH/OmZk2evJsfhm2MwG/1qAb95nJ0
+ rU/60e4BhqadPHfO9cyvgdbR+xcCJkuSIqKWH6utfd9RamZDS2djU3XDWhFW2blmcVLb
+ Ue5w==
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=1e100.net; s=20161025;
+ h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
+ :references:mime-version:content-transfer-encoding;
+ bh=GmXKgcJDZee4jC3cNKHKWCJhJ0kS9L2vONq2fIA+AaY=;
+ b=AwMmzIpdEKD6duSw3Dl9aQkzxRMmPOysumBp0nIE9FvhZJ+67auGBvMa7G80/DyF4x
+ BbrwsUrYoDLXs7fuLEjjZgxKwSCtYfWyPDdM/ezShIx9KZIfPiXhn6uH3eXP+g4feJN4
+ IlWVwvJMDzRJOhdZVzg934FJeMs4bW7XNm07jKxjsqksHGcw5JoHsP53xNegPbIpNb8X
+ h7+AwHXYAKzVC9aGYTA8bgxSD0d+SlO7CJ4nY+lHXcBR266/rt7rDFOwCdv9TUUAMCkY
+ rXrgSb8vThpKY/wZ8rK3SyJcPdvDt6TnmdZO7LqTbbzAHjzJml7s+5vYhk3CSOvjGTHt
+ KcMA==
+X-Gm-Message-State: ANhLgQ1lOBl50y5dc6fz/BIFJrpgXnM0GF/1DvoZm8oJbZIt2H9n38WA
+ pBi6LVse2n2Ed5tvz68N8x8=
+X-Google-Smtp-Source:
+ ADFU+vtPoQt/0UFiy7Bq0L9uIMvQbBOJzH8+jTojBCcjj2V26XqJvxqSMSsy9g8ZZ96F/Q8I4cpXYw==
+X-Received: by 2002:a17:902:9a09:: with SMTP id
+ v9mr21358610plp.341.1584975980336;
+ Mon, 23 Mar 2020 08:06:20 -0700 (PDT)
+Received: from localhost (176.122.158.203.16clouds.com. [176.122.158.203])
+ by smtp.gmail.com with ESMTPSA id
+ j19sm13485589pfe.102.2020.03.23.08.06.19
+ (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);
+ Mon, 23 Mar 2020 08:06:19 -0700 (PDT)
+From: Dejin Zheng <zhengdejin5@gmail.com>
+To: andrew@lunn.ch, f.fainelli@gmail.com, hkallweit1@gmail.com,
+ linux@armlinux.org.uk, davem@davemloft.net, corbet@lwn.net,
+ tglx@linutronix.de, gregkh@linuxfoundation.org,
+ allison@lohutok.net, mchehab+samsung@kernel.org, netdev@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org, Dejin Zheng <zhengdejin5@gmail.com>
+Subject: [PATCH net-next v7 01/10] iopoll: introduce read_poll_timeout macro
+Date: Mon, 23 Mar 2020 23:05:51 +0800
+Message-Id: <20200323150600.21382-2-zhengdejin5@gmail.com>
+X-Mailer: git-send-email 2.25.0
+In-Reply-To: <20200323150600.21382-1-zhengdejin5@gmail.com>
+References: <20200323150600.21382-1-zhengdejin5@gmail.com>
+MIME-Version: 1.0
+Sender: netdev-owner@vger.kernel.org
+Precedence: bulk
+List-ID: <netdev.vger.kernel.org>
+X-Mailing-List: netdev@vger.kernel.org
+
+this macro is an extension of readx_poll_timeout macro. the accessor
+function op just supports only one parameter in the readx_poll_timeout
+macro, but this macro can supports multiple variable parameters for
+it. so functions like phy_read(struct phy_device *phydev, u32 regnum)
+and phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) can
+also use this poll timeout core. and also expand it can sleep some time
+before read operation.
+
+Signed-off-by: Dejin Zheng <zhengdejin5@gmail.com>
+---
+v6 -> v7:
+ - add a parameter sleep_before_read to support that it can sleep
+ some time before read operation in read_poll_timeout macro.
+v5 -> v6:
+ - no changed
+v4 -> v5:
+ - no changed
+v3 -> v4:
+ - no changed
+v2 -> v3:
+ - no changed
+v1 -> v2:
+ - no changed
+
+ include/linux/iopoll.h | 44 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+--- a/include/linux/iopoll.h
++++ b/include/linux/iopoll.h
+@@ -14,36 +14,41 @@
+ #include <linux/io.h>
+
+ /**
+- * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
+- * @op: accessor function (takes @addr as its only argument)
+- * @addr: Address to poll
++ * read_poll_timeout - Periodically poll an address until a condition is
++ * met or a timeout occurs
++ * @op: accessor function (takes @args as its arguments)
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in us (0
+ * tight-loops). Should be less than ~20ms since usleep_range
+ * is used (see Documentation/timers/timers-howto.rst).
+ * @timeout_us: Timeout in us, 0 means never timeout
++ * @sleep_before_read: if it is true, sleep @sleep_us before read.
++ * @args: arguments for @op poll
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+- * case, the last read value at @addr is stored in @val. Must not
++ * case, the last read value at @args is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ *
+ * When available, you'll probably want to use one of the specialized
+ * macros defined below rather than this macro directly.
+ */
+-#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \
++#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \
++ sleep_before_read, args...) \
+ ({ \
+ u64 __timeout_us = (timeout_us); \
+ unsigned long __sleep_us = (sleep_us); \
+ ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
+ might_sleep_if((__sleep_us) != 0); \
++ if (sleep_before_read && __sleep_us) \
++ usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
+ for (;;) { \
+- (val) = op(addr); \
++ (val) = op(args); \
+ if (cond) \
+ break; \
+ if (__timeout_us && \
+ ktime_compare(ktime_get(), __timeout) > 0) { \
+- (val) = op(addr); \
++ (val) = op(args); \
+ break; \
+ } \
+ if (__sleep_us) \
+@@ -53,6 +58,27 @@
+ })
+
+ /**
++ * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
++ * @op: accessor function (takes @addr as its only argument)
++ * @addr: Address to poll
++ * @val: Variable to read the value into
++ * @cond: Break condition (usually involving @val)
++ * @sleep_us: Maximum time to sleep between reads in us (0
++ * tight-loops). Should be less than ~20ms since usleep_range
++ * is used (see Documentation/timers/timers-howto.rst).
++ * @timeout_us: Timeout in us, 0 means never timeout
++ *
++ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
++ * case, the last read value at @addr is stored in @val. Must not
++ * be called from atomic context if sleep_us or timeout_us are used.
++ *
++ * When available, you'll probably want to use one of the specialized
++ * macros defined below rather than this macro directly.
++ */
++#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \
++ read_poll_timeout(op, val, cond, sleep_us, timeout_us, false, addr)
++
++/**
+ * readx_poll_timeout_atomic - Periodically poll an address until a condition is met or a timeout occurs
+ * @op: accessor function (takes @addr as its only argument)
+ * @addr: Address to poll
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -21,6 +21,7 @@
+ #include <linux/timer.h>
+ #include <linux/workqueue.h>
+ #include <linux/mod_devicetable.h>
++#include <linux/iopoll.h>
+
+ #include <linux/atomic.h>
+
+@@ -714,6 +715,19 @@ static inline int phy_read(struct phy_de
+ return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, regnum);
+ }
+
++#define phy_read_poll_timeout(phydev, regnum, val, cond, sleep_us, \
++ timeout_us, sleep_before_read) \
++({ \
++ int __ret = read_poll_timeout(phy_read, val, (cond) || val < 0, \
++ sleep_us, timeout_us, sleep_before_read, phydev, regnum); \
++ if (val < 0) \
++ __ret = val; \
++ if (__ret) \
++ phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \
++ __ret; \
++})
++
++
+ /**
+ * __phy_read - convenience function for reading a given PHY register
+ * @phydev: the phy_device struct
+@@ -766,6 +780,19 @@ static inline int __phy_write(struct phy
+ */
+ int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
+
++#define phy_read_mmd_poll_timeout(phydev, devaddr, regnum, val, cond, \
++ sleep_us, timeout_us, sleep_before_read) \
++({ \
++ int __ret = read_poll_timeout(phy_read_mmd, val, (cond) || val < 0, \
++ sleep_us, timeout_us, sleep_before_read, \
++ phydev, devaddr, regnum); \
++ if (val < 0) \
++ __ret = val; \
++ if (__ret) \
++ phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \
++ __ret; \
++})
++
+ /**
+ * __phy_read_mmd - Convenience function for reading a register
+ * from an MMD on a given PHY.
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -1056,18 +1056,12 @@ EXPORT_SYMBOL(phy_disconnect);
+ static int phy_poll_reset(struct phy_device *phydev)
+ {
+ /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
+- unsigned int retries = 12;
+- int ret;
+-
+- do {
+- msleep(50);
+- ret = phy_read(phydev, MII_BMCR);
+- if (ret < 0)
+- return ret;
+- } while (ret & BMCR_RESET && --retries);
+- if (ret & BMCR_RESET)
+- return -ETIMEDOUT;
++ int ret, val;
+
++ ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
++ 50000, 600000, true);
++ if (ret)
++ return ret;
+ /* Some chips (smsc911x) may still need up to another 1ms after the
+ * BMCR_RESET bit is cleared before they are usable.
+ */
diff --git a/target/linux/generic/backport-5.4/791-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch b/target/linux/generic/backport-5.4/791-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
new file mode 100644
index 0000000..b47f2bf
--- /dev/null
+++ b/target/linux/generic/backport-5.4/791-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
@@ -0,0 +1,381 @@
+From patchwork Wed May 6 14:53:13 2020
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Michael Walle <michael@walle.cc>
+X-Patchwork-Id: 1284481
+X-Patchwork-Delegate: davem@davemloft.net
+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=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org
+ (client-ip=23.128.96.18; helo=vger.kernel.org;
+ envelope-from=netdev-owner@vger.kernel.org; receiver=<UNKNOWN>)
+Authentication-Results: ozlabs.org;
+ dmarc=none (p=none dis=none) header.from=walle.cc
+Authentication-Results: ozlabs.org;
+ dkim=pass (1024-bit key;
+ secure) header.d=walle.cc header.i=@walle.cc header.a=rsa-sha256
+ header.s=mail2016061301 header.b=m9HhLh3d;
+ dkim-atps=neutral
+Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
+ by ozlabs.org (Postfix) with ESMTP id 49HKQ62Q28z9sSG
+ for <patchwork-incoming-netdev@ozlabs.org>;
+ Thu, 7 May 2020 00:55:10 +1000 (AEST)
+Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
+ id S1729301AbgEFOzD (ORCPT
+ <rfc822;patchwork-incoming-netdev@ozlabs.org>);
+ Wed, 6 May 2020 10:55:03 -0400
+Received: from ssl.serverraum.org ([176.9.125.105]:43029 "EHLO
+ ssl.serverraum.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
+ with ESMTP id S1729078AbgEFOzC (ORCPT
+ <rfc822;netdev@vger.kernel.org>); Wed, 6 May 2020 10:55:02 -0400
+Received: from apollo.fritz.box (unknown
+ [IPv6:2a02:810c:c200:2e91:6257:18ff:fec4:ca34])
+ (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+ key-exchange ECDHE (P-384) server-signature RSA-PSS (2048 bits)
+ server-digest SHA256)
+ (No client certificate requested)
+ by ssl.serverraum.org (Postfix) with ESMTPSA id 2354022EEB;
+ Wed, 6 May 2020 16:54:57 +0200 (CEST)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=walle.cc;
+ s=mail2016061301;
+ t=1588776897;
+ h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
+ to:to:cc:cc:mime-version:mime-version:
+ content-transfer-encoding:content-transfer-encoding:
+ in-reply-to:in-reply-to:references:references;
+ bh=Y1HXOD90+xthCbcF5aODRvO5s4y3GjqVZeWMcm2C9hg=;
+ b=m9HhLh3dnD9BTg85PIRYHxEzW+9tKI8srVGI3MjgXJkJaWDcnUKGyPN86orzkyHrB0ai5O
+ VyiY7R2tdN04JifV18FNmxuUW/9Pc3kWUfo+q974YzVhTm0Tkrc3osn/smhyhl7PxpHZMl
+ VHiTEHII3umwamTkGQq8kpYUr38joLY=
+From: Michael Walle <michael@walle.cc>
+To: linux-kernel@vger.kernel.org, netdev@vger.kernel.org
+Cc: Andrew Lunn <andrew@lunn.ch>,
+ Florian Fainelli <f.fainelli@gmail.com>,
+ Heiner Kallweit <hkallweit1@gmail.com>,
+ Russell King <linux@armlinux.org.uk>,
+ "David S . Miller" <davem@davemloft.net>,
+ Vladimir Oltean <vladimir.oltean@nxp.com>,
+ Antoine Tenart <antoine.tenart@bootlin.com>,
+ Michael Walle <michael@walle.cc>
+Subject: [PATCH net-next v3 1/3] net: phy: add concept of shared storage for
+ PHYs
+Date: Wed, 6 May 2020 16:53:13 +0200
+Message-Id: <20200506145315.13967-2-michael@walle.cc>
+X-Mailer: git-send-email 2.20.1
+In-Reply-To: <20200506145315.13967-1-michael@walle.cc>
+References: <20200506145315.13967-1-michael@walle.cc>
+MIME-Version: 1.0
+X-Spam: Yes
+Sender: netdev-owner@vger.kernel.org
+Precedence: bulk
+List-ID: <netdev.vger.kernel.org>
+X-Mailing-List: netdev@vger.kernel.org
+
+There are packages which contain multiple PHY devices, eg. a quad PHY
+transceiver. Provide functions to allocate and free shared storage.
+
+Usually, a quad PHY contains global registers, which don't belong to any
+PHY. Provide convenience functions to access these registers.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/net/phy/mdio_bus.c | 1 +
+ drivers/net/phy/phy_device.c | 138 +++++++++++++++++++++++++++++++++++
+ include/linux/phy.h | 89 ++++++++++++++++++++++
+ 3 files changed, 228 insertions(+)
+
+--- a/drivers/net/phy/mdio_bus.c
++++ b/drivers/net/phy/mdio_bus.c
+@@ -404,6 +404,7 @@ int __mdiobus_register(struct mii_bus *b
+ }
+
+ mutex_init(&bus->mdio_lock);
++ mutex_init(&bus->shared_lock);
+
+ /* de-assert bus level PHY GPIO reset */
+ gpiod = devm_gpiod_get_optional(&bus->dev, "reset", GPIOD_OUT_LOW);
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -1448,6 +1448,144 @@ bool phy_driver_is_genphy_10g(struct phy
+ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_10g);
+
+ /**
++ * phy_package_join - join a common PHY group
++ * @phydev: target phy_device struct
++ * @addr: cookie and PHY address for global register access
++ * @priv_size: if non-zero allocate this amount of bytes for private data
++ *
++ * This joins a PHY group and provides a shared storage for all phydevs in
++ * this group. This is intended to be used for packages which contain
++ * more than one PHY, for example a quad PHY transceiver.
++ *
++ * The addr parameter serves as a cookie which has to have the same value
++ * for all members of one group and as a PHY address to access generic
++ * registers of a PHY package. Usually, one of the PHY addresses of the
++ * different PHYs in the package provides access to these global registers.
++ * The address which is given here, will be used in the phy_package_read()
++ * and phy_package_write() convenience functions. If your PHY doesn't have
++ * global registers you can just pick any of the PHY addresses.
++ *
++ * This will set the shared pointer of the phydev to the shared storage.
++ * If this is the first call for a this cookie the shared storage will be
++ * allocated. If priv_size is non-zero, the given amount of bytes are
++ * allocated for the priv member.
++ *
++ * Returns < 1 on error, 0 on success. Esp. calling phy_package_join()
++ * with the same cookie but a different priv_size is an error.
++ */
++int phy_package_join(struct phy_device *phydev, int addr, size_t priv_size)
++{
++ struct mii_bus *bus = phydev->mdio.bus;
++ struct phy_package_shared *shared;
++ int ret;
++
++ if (addr < 0 || addr >= PHY_MAX_ADDR)
++ return -EINVAL;
++
++ mutex_lock(&bus->shared_lock);
++ shared = bus->shared[addr];
++ if (!shared) {
++ ret = -ENOMEM;
++ shared = kzalloc(sizeof(*shared), GFP_KERNEL);
++ if (!shared)
++ goto err_unlock;
++ if (priv_size) {
++ shared->priv = kzalloc(priv_size, GFP_KERNEL);
++ if (!shared->priv)
++ goto err_free;
++ shared->priv_size = priv_size;
++ }
++ shared->addr = addr;
++ refcount_set(&shared->refcnt, 1);
++ bus->shared[addr] = shared;
++ } else {
++ ret = -EINVAL;
++ if (priv_size && priv_size != shared->priv_size)
++ goto err_unlock;
++ refcount_inc(&shared->refcnt);
++ }
++ mutex_unlock(&bus->shared_lock);
++
++ phydev->shared = shared;
++
++ return 0;
++
++err_free:
++ kfree(shared);
++err_unlock:
++ mutex_unlock(&bus->shared_lock);
++ return ret;
++}
++EXPORT_SYMBOL_GPL(phy_package_join);
++
++/**
++ * phy_package_leave - leave a common PHY group
++ * @phydev: target phy_device struct
++ *
++ * This leaves a PHY group created by phy_package_join(). If this phydev
++ * was the last user of the shared data between the group, this data is
++ * freed. Resets the phydev->shared pointer to NULL.
++ */
++void phy_package_leave(struct phy_device *phydev)
++{
++ struct phy_package_shared *shared = phydev->shared;
++ struct mii_bus *bus = phydev->mdio.bus;
++
++ if (!shared)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) {
++ bus->shared[shared->addr] = NULL;
++ mutex_unlock(&bus->shared_lock);
++ kfree(shared->priv);
++ kfree(shared);
++ }
++
++ phydev->shared = NULL;
++}
++EXPORT_SYMBOL_GPL(phy_package_leave);
++
++static void devm_phy_package_leave(struct device *dev, void *res)
++{
++ phy_package_leave(*(struct phy_device **)res);
++}
++
++/**
++ * devm_phy_package_join - resource managed phy_package_join()
++ * @dev: device that is registering this PHY package
++ * @phydev: target phy_device struct
++ * @addr: cookie and PHY address for global register access
++ * @priv_size: if non-zero allocate this amount of bytes for private data
++ *
++ * Managed phy_package_join(). Shared storage fetched by this function,
++ * phy_package_leave() is automatically called on driver detach. See
++ * phy_package_join() for more information.
++ */
++int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
++ int addr, size_t priv_size)
++{
++ struct phy_device **ptr;
++ int ret;
++
++ ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr),
++ GFP_KERNEL);
++ if (!ptr)
++ return -ENOMEM;
++
++ ret = phy_package_join(phydev, addr, priv_size);
++
++ if (!ret) {
++ *ptr = phydev;
++ devres_add(dev, ptr);
++ } else {
++ devres_free(ptr);
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(devm_phy_package_join);
++
++/**
+ * phy_detach - detach a PHY device from its network device
+ * @phydev: target phy_device struct
+ *
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -22,6 +22,7 @@
+ #include <linux/workqueue.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/iopoll.h>
++#include <linux/refcount.h>
+
+ #include <linux/atomic.h>
+
+@@ -208,6 +209,28 @@ struct sfp_bus;
+ struct sfp_upstream_ops;
+ struct sk_buff;
+
++/* Represents a shared structure between different phydev's in the same
++ * package, for example a quad PHY. See phy_package_join() and
++ * phy_package_leave().
++ */
++struct phy_package_shared {
++ int addr;
++ refcount_t refcnt;
++ unsigned long flags;
++ size_t priv_size;
++
++ /* private data pointer */
++ /* note that this pointer is shared between different phydevs and
++ * the user has to take care of appropriate locking. It is allocated
++ * and freed automatically by phy_package_join() and
++ * phy_package_leave().
++ */
++ void *priv;
++};
++
++/* used as bit number in atomic bitops */
++#define PHY_SHARED_F_INIT_DONE 0
++
+ /*
+ * The Bus class for PHYs. Devices which provide access to
+ * PHYs should register using this structure
+@@ -255,6 +278,12 @@ struct mii_bus {
+ int reset_delay_us;
+ /* RESET GPIO descriptor pointer */
+ struct gpio_desc *reset_gpiod;
++
++ /* protect access to the shared element */
++ struct mutex shared_lock;
++
++ /* shared state across different PHYs */
++ struct phy_package_shared *shared[PHY_MAX_ADDR];
+ };
+ #define to_mii_bus(d) container_of(d, struct mii_bus, dev)
+
+@@ -434,6 +463,10 @@ struct phy_device {
+ /* For use by PHYs to maintain extra state */
+ void *priv;
+
++ /* shared data pointer */
++ /* For use by PHYs inside the same package that need a shared state. */
++ struct phy_package_shared *shared;
++
+ /* Interrupt and Polling infrastructure */
+ struct delayed_work state_queue;
+
+@@ -1232,6 +1265,10 @@ int phy_ethtool_get_link_ksettings(struc
+ int phy_ethtool_set_link_ksettings(struct net_device *ndev,
+ const struct ethtool_link_ksettings *cmd);
+ int phy_ethtool_nway_reset(struct net_device *ndev);
++int phy_package_join(struct phy_device *phydev, int addr, size_t priv_size);
++void phy_package_leave(struct phy_device *phydev);
++int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
++ int addr, size_t priv_size);
+
+ #if IS_ENABLED(CONFIG_PHYLIB)
+ int __init mdio_bus_init(void);
+@@ -1284,6 +1321,58 @@ static inline int phy_ethtool_get_stats(
+ return 0;
+ }
+
++static inline int phy_package_read(struct phy_device *phydev, u32 regnum)
++{
++ struct phy_package_shared *shared = phydev->shared;
++
++ if (!shared)
++ return -EIO;
++
++ return mdiobus_read(phydev->mdio.bus, shared->addr, regnum);
++}
++
++static inline int __phy_package_read(struct phy_device *phydev, u32 regnum)
++{
++ struct phy_package_shared *shared = phydev->shared;
++
++ if (!shared)
++ return -EIO;
++
++ return __mdiobus_read(phydev->mdio.bus, shared->addr, regnum);
++}
++
++static inline int phy_package_write(struct phy_device *phydev,
++ u32 regnum, u16 val)
++{
++ struct phy_package_shared *shared = phydev->shared;
++
++ if (!shared)
++ return -EIO;
++
++ return mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val);
++}
++
++static inline int __phy_package_write(struct phy_device *phydev,
++ u32 regnum, u16 val)
++{
++ struct phy_package_shared *shared = phydev->shared;
++
++ if (!shared)
++ return -EIO;
++
++ return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val);
++}
++
++static inline bool phy_package_init_once(struct phy_device *phydev)
++{
++ struct phy_package_shared *shared = phydev->shared;
++
++ if (!shared)
++ return false;
++
++ return !test_and_set_bit(PHY_SHARED_F_INIT_DONE, &shared->flags);
++}
++
+ extern struct bus_type mdio_bus_type;
+
+ struct mdio_board_info {
diff --git a/target/linux/generic/backport-5.4/792-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch b/target/linux/generic/backport-5.4/792-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch
new file mode 100644
index 0000000..39b29ad
--- /dev/null
+++ b/target/linux/generic/backport-5.4/792-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch
@@ -0,0 +1,109 @@
+From patchwork Tue Jun 23 14:30:07 2020
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Antoine Tenart <antoine.tenart@bootlin.com>
+X-Patchwork-Id: 1315292
+X-Patchwork-Delegate: davem@davemloft.net
+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=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org
+ (client-ip=23.128.96.18; helo=vger.kernel.org;
+ envelope-from=netdev-owner@vger.kernel.org; receiver=<UNKNOWN>)
+Authentication-Results: ozlabs.org;
+ dmarc=none (p=none dis=none) header.from=bootlin.com
+Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
+ by ozlabs.org (Postfix) with ESMTP id 49rpjP0BTdz9sRN
+ for <patchwork-incoming-netdev@ozlabs.org>;
+ Wed, 24 Jun 2020 00:35:37 +1000 (AEST)
+Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
+ id S1732957AbgFWOf1 (ORCPT
+ <rfc822;patchwork-incoming-netdev@ozlabs.org>);
+ Tue, 23 Jun 2020 10:35:27 -0400
+Received: from relay3-d.mail.gandi.net ([217.70.183.195]:35381 "EHLO
+ relay3-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
+ with ESMTP id S1732900AbgFWOfX (ORCPT
+ <rfc822;netdev@vger.kernel.org>); Tue, 23 Jun 2020 10:35:23 -0400
+X-Originating-IP: 90.76.143.236
+Received: from localhost (lfbn-tou-1-1075-236.w90-76.abo.wanadoo.fr
+ [90.76.143.236])
+ (Authenticated sender: antoine.tenart@bootlin.com)
+ by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 38BE860006;
+ Tue, 23 Jun 2020 14:35:19 +0000 (UTC)
+From: Antoine Tenart <antoine.tenart@bootlin.com>
+To: davem@davemloft.net, andrew@lunn.ch, f.fainelli@gmail.com,
+ hkallweit1@gmail.com, richardcochran@gmail.com,
+ alexandre.belloni@bootlin.com, UNGLinuxDriver@microchip.com
+Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
+ thomas.petazzoni@bootlin.com, allan.nielsen@microchip.com,
+ foss@0leil.net, antoine.tenart@bootlin.com
+Subject: [PATCH net-next v4 1/8] net: phy: add support for a common probe
+ between shared PHYs
+Date: Tue, 23 Jun 2020 16:30:07 +0200
+Message-Id: <20200623143014.47864-2-antoine.tenart@bootlin.com>
+X-Mailer: git-send-email 2.26.2
+In-Reply-To: <20200623143014.47864-1-antoine.tenart@bootlin.com>
+References: <20200623143014.47864-1-antoine.tenart@bootlin.com>
+MIME-Version: 1.0
+Sender: netdev-owner@vger.kernel.org
+Precedence: bulk
+List-ID: <netdev.vger.kernel.org>
+X-Mailing-List: netdev@vger.kernel.org
+
+Shared PHYs (PHYs in the same hardware package) may have shared
+registers and their drivers would usually need to share information.
+There is currently a way to have a shared (part of the) init, by using
+phy_package_init_once(). This patch extends the logic to share parts of
+the probe to allow sharing the initialization of locks or resources
+retrieval.
+
+Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+---
+ include/linux/phy.h | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index 9248dd2ce4ca..457489f1951c 100644
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -244,7 +244,8 @@ struct phy_package_shared {
+ };
+
+ /* used as bit number in atomic bitops */
+-#define PHY_SHARED_F_INIT_DONE 0
++#define PHY_SHARED_F_INIT_DONE 0
++#define PHY_SHARED_F_PROBE_DONE 1
+
+ /*
+ * The Bus class for PHYs. Devices which provide access to
+@@ -1558,14 +1559,25 @@ static inline int __phy_package_write(struct phy_device *phydev,
+ return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val);
+ }
+
+-static inline bool phy_package_init_once(struct phy_device *phydev)
++static inline bool __phy_package_set_once(struct phy_device *phydev,
++ unsigned int b)
+ {
+ struct phy_package_shared *shared = phydev->shared;
+
+ if (!shared)
+ return false;
+
+- return !test_and_set_bit(PHY_SHARED_F_INIT_DONE, &shared->flags);
++ return !test_and_set_bit(b, &shared->flags);
++}
++
++static inline bool phy_package_init_once(struct phy_device *phydev)
++{
++ return __phy_package_set_once(phydev, PHY_SHARED_F_INIT_DONE);
++}
++
++static inline bool phy_package_probe_once(struct phy_device *phydev)
++{
++ return __phy_package_set_once(phydev, PHY_SHARED_F_PROBE_DONE);
+ }
+
+ extern struct bus_type mdio_bus_type;
\ No newline at end of file
diff --git a/target/linux/mediatek/patches-5.4/756-net-phy-mediatek-ge-add-mt798x-support.patch b/target/linux/generic/backport-5.4/793-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch
similarity index 70%
rename from target/linux/mediatek/patches-5.4/756-net-phy-mediatek-ge-add-mt798x-support.patch
rename to target/linux/generic/backport-5.4/793-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch
index b1734f8..83df94a 100644
--- a/target/linux/mediatek/patches-5.4/756-net-phy-mediatek-ge-add-mt798x-support.patch
+++ b/target/linux/generic/backport-5.4/793-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch
@@ -1,17 +1,28 @@
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -92,6 +92,8 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c
+ obj-$(CONFIG_LXT_PHY) += lxt.o
+ obj-$(CONFIG_MARVELL_PHY) += marvell.o
+ obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o
++obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
++obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o
+ obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
+ obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
+ obj-$(CONFIG_MICREL_PHY) += micrel.o
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
-@@ -582,6 +582,23 @@ config MEDIATEK_2P5GE_PHY
+@@ -507,6 +507,23 @@ config MESON_GXL_PHY
---help---
- Supports MediaTek internal 2.5Gb Ethernet PHYs.
+ Currently has a driver for the Amlogic Meson GXL Internal PHY
+config MEDIATEK_GE_PHY
+ tristate "MediaTek Gigabit Ethernet PHYs"
+ help
+ Supports the MediaTek Gigabit Ethernet PHYs.
+
-+config MEDIATEK_GE_PHY_SOC
++config MEDIATEK_GE_SOC_PHY
+ bool "MediaTek SoC Ethernet PHYs"
-+ depends on (ARM64 && ARCH_MEDIATEK && MEDIATEK_GE_PHY) || COMPILE_TEST
++ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
+ select NVMEM_MTK_EFUSE
+ help
+ Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
@@ -24,13 +35,3 @@
config MICREL_PHY
tristate "Micrel PHYs"
---help---
---- a/drivers/net/phy/Makefile
-+++ b/drivers/net/phy/Makefile
-@@ -100,6 +100,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o
- obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o
- obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o
- obj-$(CONFIG_MEDIATEK_2P5GE_PHY)+= mediatek-2p5ge.o
-+obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
- obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
- obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
- obj-$(CONFIG_MICREL_PHY) += micrel.o
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c
new file mode 100644
index 0000000..f25fb8e
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge-soc.c
@@ -0,0 +1,1263 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/phy.h>
+
+#define MTK_GPHY_ID_MT7981 0x03a29461
+#define MTK_GPHY_ID_MT7988 0x03a29481
+
+#define MTK_EXT_PAGE_ACCESS 0x1f
+#define MTK_PHY_PAGE_STANDARD 0x0000
+#define MTK_PHY_PAGE_EXTENDED_3 0x0003
+
+#define MTK_PHY_LPI_REG_14 0x14
+#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK GENMASK(8, 0)
+
+#define MTK_PHY_LPI_REG_1c 0x1c
+#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8)
+
+#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
+#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
+
+#define ANALOG_INTERNAL_OPERATION_MAX_US 20
+#define TXRESERVE_MIN 0
+#define TXRESERVE_MAX 7
+
+#define MTK_PHY_ANARG_RG 0x10
+#define MTK_PHY_TCLKOFFSET_MASK GENMASK(12, 8)
+
+/* Registers on MDIO_MMD_VEND1 */
+#define MTK_PHY_TXVLD_DA_RG 0x12
+#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10)
+#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 0x16
+#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK GENMASK(15, 10)
+#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 0x17
+#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 0x18
+#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 0x19
+#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 0x20
+#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 0x21
+#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 0x22
+#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_RXADC_CTRL_RG7 0xc6
+#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8)
+
+#define MTK_PHY_RXADC_CTRL_RG9 0xc8
+#define MTK_PHY_DA_RX_PSBN_TBT_MASK GENMASK(14, 12)
+#define MTK_PHY_DA_RX_PSBN_HBT_MASK GENMASK(10, 8)
+#define MTK_PHY_DA_RX_PSBN_GBE_MASK GENMASK(6, 4)
+#define MTK_PHY_DA_RX_PSBN_LP_MASK GENMASK(2, 0)
+
+#define MTK_PHY_LDO_OUTPUT_V 0xd7
+
+#define MTK_PHY_RG_ANA_CAL_RG0 0xdb
+#define MTK_PHY_RG_CAL_CKINV BIT(12)
+#define MTK_PHY_RG_ANA_CALEN BIT(8)
+#define MTK_PHY_RG_ZCALEN_A BIT(0)
+
+#define MTK_PHY_RG_ANA_CAL_RG1 0xdc
+#define MTK_PHY_RG_ZCALEN_B BIT(12)
+#define MTK_PHY_RG_ZCALEN_C BIT(8)
+#define MTK_PHY_RG_ZCALEN_D BIT(4)
+#define MTK_PHY_RG_TXVOS_CALEN BIT(0)
+
+#define MTK_PHY_RG_ANA_CAL_RG5 0xe0
+#define MTK_PHY_RG_REXT_TRIM_MASK GENMASK(13, 8)
+
+#define MTK_PHY_RG_TX_FILTER 0xfe
+
+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120 0x120
+#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK GENMASK(12, 8)
+#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK GENMASK(4, 0)
+
+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122 0x122
+#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK GENMASK(7, 0)
+
+#define MTK_PHY_RG_TESTMUX_ADC_CTRL 0x144
+#define MTK_PHY_RG_TXEN_DIG_MASK GENMASK(5, 5)
+
+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B 0x172
+#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK GENMASK(13, 8)
+#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK GENMASK(6, 0)
+
+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D 0x173
+#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK GENMASK(13, 8)
+#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0)
+
+#define MTK_PHY_RG_AD_CAL_COMP 0x17a
+#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT (8)
+
+#define MTK_PHY_RG_AD_CAL_CLK 0x17b
+#define MTK_PHY_DA_CAL_CLK BIT(0)
+
+#define MTK_PHY_RG_AD_CALIN 0x17c
+#define MTK_PHY_DA_CALIN_FLAG BIT(0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_A 0x17d
+#define MTK_PHY_DASN_DAC_IN0_A_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_B 0x17e
+#define MTK_PHY_DASN_DAC_IN0_B_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_C 0x17f
+#define MTK_PHY_DASN_DAC_IN0_C_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_D 0x180
+#define MTK_PHY_DASN_DAC_IN0_D_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_A 0x181
+#define MTK_PHY_DASN_DAC_IN1_A_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_B 0x182
+#define MTK_PHY_DASN_DAC_IN1_B_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_C 0x183
+#define MTK_PHY_DASN_DAC_IN1_C_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_D 0x184
+#define MTK_PHY_DASN_DAC_IN1_D_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DEV1E_REG19b 0x19b
+#define MTK_PHY_BYPASS_DSP_LPI_READY BIT(8)
+
+#define MTK_PHY_RG_LP_IIR2_K1_L 0x22a
+#define MTK_PHY_RG_LP_IIR2_K1_U 0x22b
+#define MTK_PHY_RG_LP_IIR2_K2_L 0x22c
+#define MTK_PHY_RG_LP_IIR2_K2_U 0x22d
+#define MTK_PHY_RG_LP_IIR2_K3_L 0x22e
+#define MTK_PHY_RG_LP_IIR2_K3_U 0x22f
+#define MTK_PHY_RG_LP_IIR2_K4_L 0x230
+#define MTK_PHY_RG_LP_IIR2_K4_U 0x231
+#define MTK_PHY_RG_LP_IIR2_K5_L 0x232
+#define MTK_PHY_RG_LP_IIR2_K5_U 0x233
+
+#define MTK_PHY_RG_DEV1E_REG234 0x234
+#define MTK_PHY_TR_OPEN_LOOP_EN_MASK GENMASK(0, 0)
+#define MTK_PHY_LPF_X_AVERAGE_MASK GENMASK(7, 4)
+#define MTK_PHY_TR_LP_IIR_EEE_EN BIT(12)
+
+#define MTK_PHY_RG_LPF_CNT_VAL 0x235
+
+#define MTK_PHY_RG_DEV1E_REG238 0x238
+#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK GENMASK(8, 0)
+#define MTK_PHY_LPI_SLV_SEND_TX_EN BIT(12)
+
+#define MTK_PHY_RG_DEV1E_REG239 0x239
+#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK GENMASK(8, 0)
+#define MTK_PHY_LPI_TXPCS_LOC_RCV BIT(12)
+
+#define MTK_PHY_RG_DEV1E_REG27C 0x27c
+#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK GENMASK(12, 8)
+#define MTK_PHY_RG_DEV1E_REG27D 0x27d
+#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK GENMASK(4, 0)
+
+#define MTK_PHY_RG_DEV1E_REG2C7 0x2c7
+#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0)
+#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8)
+
+#define MTK_PHY_RG_DEV1E_REG2D1 0x2d1
+#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK GENMASK(7, 0)
+#define MTK_PHY_LPI_SKIP_SD_SLV_TR BIT(8)
+#define MTK_PHY_LPI_TR_READY BIT(9)
+#define MTK_PHY_LPI_VCO_EEE_STG0_EN BIT(10)
+
+#define MTK_PHY_RG_DEV1E_REG323 0x323
+#define MTK_PHY_EEE_WAKE_MAS_INT_DC BIT(0)
+#define MTK_PHY_EEE_WAKE_SLV_INT_DC BIT(4)
+
+#define MTK_PHY_RG_DEV1E_REG324 0x324
+#define MTK_PHY_SMI_DETCNT_MAX_MASK GENMASK(5, 0)
+#define MTK_PHY_SMI_DET_MAX_EN BIT(8)
+
+#define MTK_PHY_RG_DEV1E_REG326 0x326
+#define MTK_PHY_LPI_MODE_SD_ON BIT(0)
+#define MTK_PHY_RESET_RANDUPD_CNT BIT(1)
+#define MTK_PHY_TREC_UPDATE_ENAB_CLR BIT(2)
+#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF BIT(4)
+#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP BIT(5)
+
+#define MTK_PHY_LDO_PUMP_EN_PAIRAB 0x502
+#define MTK_PHY_LDO_PUMP_EN_PAIRCD 0x503
+
+#define MTK_PHY_DA_TX_R50_PAIR_A 0x53d
+#define MTK_PHY_DA_TX_R50_PAIR_B 0x53e
+#define MTK_PHY_DA_TX_R50_PAIR_C 0x53f
+#define MTK_PHY_DA_TX_R50_PAIR_D 0x540
+
+/* Registers on MDIO_MMD_VEND2 */
+#define MTK_PHY_LED0_ON_CTRL 0x24
+#define MTK_PHY_LED0_ON_MASK GENMASK(6, 0)
+#define MTK_PHY_LED0_ON_LINK1000 BIT(0)
+#define MTK_PHY_LED0_ON_LINK100 BIT(1)
+#define MTK_PHY_LED0_ON_LINK10 BIT(2)
+#define MTK_PHY_LED0_ON_LINKDOWN BIT(3)
+#define MTK_PHY_LED0_ON_FDX BIT(4) /* Full duplex */
+#define MTK_PHY_LED0_ON_HDX BIT(5) /* Half duplex */
+#define MTK_PHY_LED0_FORCE_ON BIT(6)
+#define MTK_PHY_LED0_POLARITY BIT(14)
+#define MTK_PHY_LED0_ENABLE BIT(15)
+
+#define MTK_PHY_LED0_BLINK_CTRL 0x25
+#define MTK_PHY_LED0_1000TX BIT(0)
+#define MTK_PHY_LED0_1000RX BIT(1)
+#define MTK_PHY_LED0_100TX BIT(2)
+#define MTK_PHY_LED0_100RX BIT(3)
+#define MTK_PHY_LED0_10TX BIT(4)
+#define MTK_PHY_LED0_10RX BIT(5)
+#define MTK_PHY_LED0_COLLISION BIT(6)
+#define MTK_PHY_LED0_RX_CRC_ERR BIT(7)
+#define MTK_PHY_LED0_RX_IDLE_ERR BIT(8)
+#define MTK_PHY_LED0_FORCE_BLINK BIT(9)
+
+#define MTK_PHY_LED1_ON_CTRL 0x26
+#define MTK_PHY_LED1_ON_MASK GENMASK(6, 0)
+#define MTK_PHY_LED1_ON_LINK1000 BIT(0)
+#define MTK_PHY_LED1_ON_LINK100 BIT(1)
+#define MTK_PHY_LED1_ON_LINK10 BIT(2)
+#define MTK_PHY_LED1_ON_LINKDOWN BIT(3)
+#define MTK_PHY_LED1_ON_FDX BIT(4) /* Full duplex */
+#define MTK_PHY_LED1_ON_HDX BIT(5) /* Half duplex */
+#define MTK_PHY_LED1_FORCE_ON BIT(6)
+#define MTK_PHY_LED1_POLARITY BIT(14)
+#define MTK_PHY_LED1_ENABLE BIT(15)
+
+#define MTK_PHY_LED1_BLINK_CTRL 0x27
+#define MTK_PHY_LED1_1000TX BIT(0)
+#define MTK_PHY_LED1_1000RX BIT(1)
+#define MTK_PHY_LED1_100TX BIT(2)
+#define MTK_PHY_LED1_100RX BIT(3)
+#define MTK_PHY_LED1_10TX BIT(4)
+#define MTK_PHY_LED1_10RX BIT(5)
+#define MTK_PHY_LED1_COLLISION BIT(6)
+#define MTK_PHY_LED1_RX_CRC_ERR BIT(7)
+#define MTK_PHY_LED1_RX_IDLE_ERR BIT(8)
+#define MTK_PHY_LED1_FORCE_BLINK BIT(9)
+
+#define MTK_PHY_RG_BG_RASEL 0x115
+#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0)
+
+/* These macro privides efuse parsing for internal phy. */
+#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0))
+#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0))
+#define EFS_DA_TX_I2MPB_C(x) (((x) >> 12) & GENMASK(5, 0))
+#define EFS_DA_TX_I2MPB_D(x) (((x) >> 18) & GENMASK(5, 0))
+#define EFS_DA_TX_AMP_OFFSET_A(x) (((x) >> 24) & GENMASK(5, 0))
+
+#define EFS_DA_TX_AMP_OFFSET_B(x) (((x) >> 0) & GENMASK(5, 0))
+#define EFS_DA_TX_AMP_OFFSET_C(x) (((x) >> 6) & GENMASK(5, 0))
+#define EFS_DA_TX_AMP_OFFSET_D(x) (((x) >> 12) & GENMASK(5, 0))
+#define EFS_DA_TX_R50_A(x) (((x) >> 18) & GENMASK(5, 0))
+#define EFS_DA_TX_R50_B(x) (((x) >> 24) & GENMASK(5, 0))
+
+#define EFS_DA_TX_R50_C(x) (((x) >> 0) & GENMASK(5, 0))
+#define EFS_DA_TX_R50_D(x) (((x) >> 6) & GENMASK(5, 0))
+
+#define EFS_RG_BG_RASEL(x) (((x) >> 4) & GENMASK(2, 0))
+#define EFS_RG_REXT_TRIM(x) (((x) >> 7) & GENMASK(5, 0))
+
+enum {
+ NO_PAIR,
+ PAIR_A,
+ PAIR_B,
+ PAIR_C,
+ PAIR_D,
+};
+
+enum {
+ GPHY_PORT0,
+ GPHY_PORT1,
+ GPHY_PORT2,
+ GPHY_PORT3,
+};
+
+enum calibration_mode {
+ EFUSE_K,
+ SW_K
+};
+
+enum CAL_ITEM {
+ REXT,
+ TX_OFFSET,
+ TX_AMP,
+ TX_R50,
+ TX_VCM
+};
+
+enum CAL_MODE {
+ EFUSE_M,
+ SW_M
+};
+
+struct mtk_socphy_shared_priv {
+ u32 boottrap;
+};
+
+static int mtk_socphy_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+}
+
+static int mtk_socphy_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
+}
+
+/* One calibration cycle consists of:
+ * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high
+ * until AD_CAL_COMP is ready to output calibration result.
+ * 2.Wait until DA_CAL_CLK is available.
+ * 3.Fetch AD_CAL_COMP_OUT.
+ */
+static int cal_cycle(struct phy_device *phydev, int devad,
+ u32 regnum, u16 mask, u16 cal_val)
+{
+ int reg_val;
+ int ret;
+
+ phy_modify_mmd(phydev, devad, regnum,
+ mask, cal_val);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
+ MTK_PHY_DA_CALIN_FLAG);
+
+ ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_AD_CAL_CLK, reg_val,
+ reg_val & MTK_PHY_DA_CAL_CLK, 500,
+ ANALOG_INTERNAL_OPERATION_MAX_US, false);
+ if (ret) {
+ phydev_err(phydev, "Calibration cycle timeout\n");
+ return ret;
+ }
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
+ MTK_PHY_DA_CALIN_FLAG);
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >>
+ MTK_PHY_AD_CAL_COMP_OUT_SHIFT;
+ phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
+
+ return ret;
+}
+
+static int rext_fill_result(struct phy_device *phydev, u16 *buf)
+{
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
+ MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL,
+ MTK_PHY_RG_BG_RASEL_MASK, buf[1]);
+
+ return 0;
+}
+
+static int rext_cal_efuse(struct phy_device *phydev, u32 *buf)
+{
+ u16 rext_cal_val[2];
+
+ rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]);
+ rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]);
+ rext_fill_result(phydev, rext_cal_val);
+
+ return 0;
+}
+
+static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf)
+{
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
+ MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
+ MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
+ MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
+ MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]);
+
+ return 0;
+}
+
+static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf)
+{
+ u16 tx_offset_cal_val[4];
+
+ tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]);
+ tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]);
+ tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]);
+ tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]);
+
+ tx_offset_fill_result(phydev, tx_offset_cal_val);
+
+ return 0;
+}
+
+static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
+{
+ int i;
+ int bias[16] = {};
+ const int vals_9461[16] = { 7, 1, 4, 7,
+ 7, 1, 4, 7,
+ 7, 1, 4, 7,
+ 7, 1, 4, 7 };
+ const int vals_9481[16] = { 10, 6, 6, 10,
+ 10, 6, 6, 10,
+ 10, 6, 6, 10,
+ 10, 6, 6, 10 };
+ switch (phydev->drv->phy_id) {
+ case MTK_GPHY_ID_MT7981:
+ /* We add some calibration to efuse values
+ * due to board level influence.
+ * GBE: +7, TBT: +1, HBT: +4, TST: +7
+ */
+ memcpy(bias, (const void *)vals_9461, sizeof(bias));
+ break;
+ case MTK_GPHY_ID_MT7988:
+ memcpy(bias, (const void *)vals_9481, sizeof(bias));
+ break;
+ }
+
+ /* Prevent overflow */
+ for (i = 0; i < 12; i++) {
+ if (buf[i >> 2] + bias[i] > 63) {
+ buf[i >> 2] = 63;
+ bias[i] = 0;
+ }
+ }
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
+ MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
+ MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
+ MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
+ MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
+ MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
+ MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
+ MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
+ MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
+ MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
+ MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
+ MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
+ MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
+ MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
+ MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
+ MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
+ MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]);
+
+ return 0;
+}
+
+static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf)
+{
+ u16 tx_amp_cal_val[4];
+
+ tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]);
+ tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]);
+ tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]);
+ tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]);
+ tx_amp_fill_result(phydev, tx_amp_cal_val);
+
+ return 0;
+}
+
+static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val,
+ u8 txg_calen_x)
+{
+ int bias = 0;
+ u16 reg, val;
+
+ if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988)
+ bias = -2;
+
+ val = clamp_val(bias + tx_r50_cal_val, 0, 63);
+
+ switch (txg_calen_x) {
+ case PAIR_A:
+ reg = MTK_PHY_DA_TX_R50_PAIR_A;
+ break;
+ case PAIR_B:
+ reg = MTK_PHY_DA_TX_R50_PAIR_B;
+ break;
+ case PAIR_C:
+ reg = MTK_PHY_DA_TX_R50_PAIR_C;
+ break;
+ case PAIR_D:
+ reg = MTK_PHY_DA_TX_R50_PAIR_D;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8);
+
+ return 0;
+}
+
+static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf,
+ u8 txg_calen_x)
+{
+ u16 tx_r50_cal_val;
+
+ switch (txg_calen_x) {
+ case PAIR_A:
+ tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]);
+ break;
+ case PAIR_B:
+ tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]);
+ break;
+ case PAIR_C:
+ tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]);
+ break;
+ case PAIR_D:
+ tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]);
+ break;
+ default:
+ return -EINVAL;
+ }
+ tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x);
+
+ return 0;
+}
+
+static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x)
+{
+ u8 lower_idx, upper_idx, txreserve_val;
+ u8 lower_ret, upper_ret;
+ int ret;
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ANA_CALEN);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_CAL_CKINV);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_TXVOS_CALEN);
+
+ switch (rg_txreserve_x) {
+ case PAIR_A:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_A,
+ MTK_PHY_DASN_DAC_IN0_A_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_A,
+ MTK_PHY_DASN_DAC_IN1_A_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ZCALEN_A);
+ break;
+ case PAIR_B:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_B,
+ MTK_PHY_DASN_DAC_IN0_B_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_B,
+ MTK_PHY_DASN_DAC_IN1_B_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_B);
+ break;
+ case PAIR_C:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_C,
+ MTK_PHY_DASN_DAC_IN0_C_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_C,
+ MTK_PHY_DASN_DAC_IN1_C_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_C);
+ break;
+ case PAIR_D:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_D,
+ MTK_PHY_DASN_DAC_IN0_D_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_D,
+ MTK_PHY_DASN_DAC_IN1_D_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_D);
+ break;
+ default:
+ ret = -EINVAL;
+ goto restore;
+ }
+
+ lower_idx = TXRESERVE_MIN;
+ upper_idx = TXRESERVE_MAX;
+
+ phydev_dbg(phydev, "Start TX-VCM SW cal.\n");
+ while ((upper_idx - lower_idx) > 1) {
+ txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2);
+ ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ txreserve_val << 12 | txreserve_val << 8 |
+ txreserve_val << 4 | txreserve_val);
+ if (ret == 1) {
+ upper_idx = txreserve_val;
+ upper_ret = ret;
+ } else if (ret == 0) {
+ lower_idx = txreserve_val;
+ lower_ret = ret;
+ } else {
+ goto restore;
+ }
+ }
+
+ if (lower_idx == TXRESERVE_MIN) {
+ lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ lower_idx << 12 | lower_idx << 8 |
+ lower_idx << 4 | lower_idx);
+ ret = lower_ret;
+ } else if (upper_idx == TXRESERVE_MAX) {
+ upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ upper_idx << 12 | upper_idx << 8 |
+ upper_idx << 4 | upper_idx);
+ ret = upper_ret;
+ }
+ if (ret < 0)
+ goto restore;
+
+ /* We calibrate TX-VCM in different logic. Check upper index and then
+ * lower index. If this calibration is valid, apply lower index's result.
+ */
+ ret = upper_ret - lower_ret;
+ if (ret == 1) {
+ ret = 0;
+ /* Make sure we use upper_idx in our calibration system */
+ cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ upper_idx << 12 | upper_idx << 8 |
+ upper_idx << 4 | upper_idx);
+ phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx);
+ } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 &&
+ lower_ret == 1) {
+ ret = 0;
+ cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ lower_idx << 12 | lower_idx << 8 |
+ lower_idx << 4 | lower_idx);
+ phydev_warn(phydev, "TX-VCM SW cal result at low margin 0x%x\n",
+ lower_idx);
+ } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 &&
+ lower_ret == 0) {
+ ret = 0;
+ phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n",
+ upper_idx);
+ } else {
+ ret = -EINVAL;
+ }
+
+restore:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ANA_CALEN);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_TXVOS_CALEN);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ZCALEN_A);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C |
+ MTK_PHY_RG_ZCALEN_D);
+
+ return ret;
+}
+
+static void mt798x_phy_common_finetune(struct phy_device *phydev)
+{
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ /* EnabRandUpdTrig = 1 */
+ __phy_write(phydev, 0x11, 0x2f00);
+ __phy_write(phydev, 0x12, 0xe);
+ __phy_write(phydev, 0x10, 0x8fb0);
+
+ /* NormMseLoThresh = 85 */
+ __phy_write(phydev, 0x11, 0x55a0);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x83aa);
+
+ /* TrFreeze = 0 */
+ __phy_write(phydev, 0x11, 0x0);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x9686);
+
+ /* SSTrKp1000Slv = 5 */
+ __phy_write(phydev, 0x11, 0xbaef);
+ __phy_write(phydev, 0x12, 0x2e);
+ __phy_write(phydev, 0x10, 0x968c);
+
+ /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
+ * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
+ */
+ __phy_write(phydev, 0x11, 0xd10a);
+ __phy_write(phydev, 0x12, 0x34);
+ __phy_write(phydev, 0x10, 0x8f82);
+
+ /* VcoSlicerThreshBitsHigh */
+ __phy_write(phydev, 0x11, 0x5555);
+ __phy_write(phydev, 0x12, 0x55);
+ __phy_write(phydev, 0x10, 0x8ec0);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
+ MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
+ BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
+
+ /* rg_tr_lpf_cnt_val = 512 */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200);
+
+ /* IIR2 related */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe);
+
+ /* FFE peaking */
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C,
+ MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D,
+ MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e);
+
+ /* Disable LDO pump */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0);
+ /* Adjust LDO output voltage */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222);
+}
+
+static void mt7981_phy_finetune(struct phy_device *phydev)
+{
+ u16 val[8] = { 0x01ce, 0x01c1,
+ 0x020f, 0x0202,
+ 0x03d0, 0x03c0,
+ 0x0013, 0x0005 };
+ int i, k;
+
+ /* 100M eye finetune:
+ * Keep middle level of TX MLT3 shapper as default.
+ * Only change TX MLT3 overshoot level here.
+ */
+ for (k = 0, i = 1; i < 12; i++) {
+ if (i % 3 == 0)
+ continue;
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]);
+ }
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
+ __phy_write(phydev, 0x11, 0xc71);
+ __phy_write(phydev, 0x12, 0xc);
+ __phy_write(phydev, 0x10, 0x8fae);
+
+ /* ResetSyncOffset = 6 */
+ __phy_write(phydev, 0x11, 0x600);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x8fc0);
+
+ /* VgaDecRate = 1 */
+ __phy_write(phydev, 0x11, 0x4c2a);
+ __phy_write(phydev, 0x12, 0x3e);
+ __phy_write(phydev, 0x10, 0x8fa4);
+
+ /* FfeUpdGainForce = 4 */
+ __phy_write(phydev, 0x11, 0x240);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x9680);
+
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+}
+
+static void mt7988_phy_finetune(struct phy_device *phydev)
+{
+ u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182,
+ 0x020d, 0x0206, 0x0384, 0x03d0,
+ 0x03c6, 0x030a, 0x0011, 0x0005 };
+ int i;
+
+ /* Set default MLT3 shaper first */
+ for (i = 0; i < 12; i++)
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]);
+
+ /* TCT finetune */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
+
+ /* Disable TX power saving */
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+
+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */
+ __phy_write(phydev, 0x11, 0x671);
+ __phy_write(phydev, 0x12, 0xc);
+ __phy_write(phydev, 0x10, 0x8fae);
+
+ /* ResetSyncOffset = 5 */
+ __phy_write(phydev, 0x11, 0x500);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x8fc0);
+
+ /* VgaDecRate is 1 at default on mt7988 */
+
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30);
+ /* TxClkOffset = 2 */
+ __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK,
+ FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2));
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+}
+
+static void mt798x_phy_eee(struct phy_device *phydev)
+{
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120,
+ MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK |
+ MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) |
+ FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
+ MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ 0xff));
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_TESTMUX_ADC_CTRL,
+ MTK_PHY_RG_TXEN_DIG_MASK);
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY);
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238,
+ MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK |
+ MTK_PHY_LPI_SLV_SEND_TX_EN,
+ FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
+ MTK_PHY_LPI_SEND_LOC_TIMER_MASK |
+ MTK_PHY_LPI_TXPCS_LOC_RCV,
+ FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
+ MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK,
+ FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) |
+ FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1,
+ MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
+ FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
+ 0x33) |
+ MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY |
+ MTK_PHY_LPI_VCO_EEE_STG0_EN);
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323,
+ MTK_PHY_EEE_WAKE_MAS_INT_DC |
+ MTK_PHY_EEE_WAKE_SLV_INT_DC);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324,
+ MTK_PHY_SMI_DETCNT_MAX_MASK,
+ FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) |
+ MTK_PHY_SMI_DET_MAX_EN);
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326,
+ MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT |
+ MTK_PHY_TREC_UPDATE_ENAB_CLR |
+ MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF |
+ MTK_PHY_TR_READY_SKIP_AFE_WAKEUP);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ /* Regsigdet_sel_1000 = 0 */
+ __phy_write(phydev, 0x11, 0xb);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x9690);
+
+ /* REG_EEE_st2TrKf1000 = 3 */
+ __phy_write(phydev, 0x11, 0x114f);
+ __phy_write(phydev, 0x12, 0x2);
+ __phy_write(phydev, 0x10, 0x969a);
+
+ /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */
+ __phy_write(phydev, 0x11, 0x3028);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x969e);
+
+ /* RegEEE_slv_wake_int_timer_tar = 8 */
+ __phy_write(phydev, 0x11, 0x5010);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96a0);
+
+ /* RegEEE_trfreeze_timer2 = 586 */
+ __phy_write(phydev, 0x11, 0x24a);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96a8);
+
+ /* RegEEE100Stg1_tar = 16 */
+ __phy_write(phydev, 0x11, 0x3210);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96b8);
+
+ /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */
+ __phy_write(phydev, 0x11, 0x1463);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96ca);
+
+ /* DfeTailEnableVgaThresh1000 = 27 */
+ __phy_write(phydev, 0x11, 0x36);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x8f80);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
+ __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c));
+
+ __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK,
+ FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc));
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
+ MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff));
+}
+
+static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
+ u8 start_pair, u8 end_pair)
+{
+ u8 pair_n;
+ int ret;
+
+ for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
+ /* TX_OFFSET & TX_AMP have no SW calibration. */
+ switch (cal_item) {
+ case TX_VCM:
+ ret = tx_vcm_cal_sw(phydev, pair_n);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item,
+ u8 start_pair, u8 end_pair, u32 *buf)
+{
+ u8 pair_n;
+ int ret;
+
+ for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
+ /* TX_VCM has no efuse calibration. */
+ switch (cal_item) {
+ case REXT:
+ ret = rext_cal_efuse(phydev, buf);
+ break;
+ case TX_OFFSET:
+ ret = tx_offset_cal_efuse(phydev, buf);
+ break;
+ case TX_AMP:
+ ret = tx_amp_cal_efuse(phydev, buf);
+ break;
+ case TX_R50:
+ ret = tx_r50_cal_efuse(phydev, buf, pair_n);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item,
+ enum CAL_MODE cal_mode, u8 start_pair,
+ u8 end_pair, u32 *buf)
+{
+ int ret;
+
+ switch (cal_mode) {
+ case EFUSE_M:
+ ret = cal_efuse(phydev, cal_item, start_pair,
+ end_pair, buf);
+ break;
+ case SW_M:
+ ret = cal_sw(phydev, cal_item, start_pair, end_pair);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (ret) {
+ phydev_err(phydev, "cal %d failed\n", cal_item);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int mt798x_phy_calibration(struct phy_device *phydev)
+{
+ int ret = 0;
+ u32 *buf;
+ size_t len;
+ struct nvmem_cell *cell;
+
+ cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
+ if (IS_ERR(cell)) {
+ if (PTR_ERR(cell) == -EPROBE_DEFER)
+ return PTR_ERR(cell);
+ return 0;
+ }
+
+ buf = (u32 *)nvmem_cell_read(cell, &len);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+ nvmem_cell_put(cell);
+
+ if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) {
+ phydev_err(phydev, "invalid efuse data\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf);
+ if (ret)
+ goto out;
+
+out:
+ kfree(buf);
+ return ret;
+}
+
+static int mt798x_phy_config_init(struct phy_device *phydev)
+{
+ switch (phydev->drv->phy_id) {
+ case MTK_GPHY_ID_MT7981:
+ mt7981_phy_finetune(phydev);
+ break;
+ case MTK_GPHY_ID_MT7988:
+ mt7988_phy_finetune(phydev);
+ break;
+ }
+
+ mt798x_phy_common_finetune(phydev);
+ mt798x_phy_eee(phydev);
+
+ return mt798x_phy_calibration(phydev);
+}
+
+static int mt7988_phy_setup_led(struct phy_device *phydev)
+{
+ struct mtk_socphy_shared_priv *priv = phydev->shared->priv;
+ int port = phydev->mdio.addr;
+ u32 reg = priv->boottrap;
+ struct pinctrl *pinctrl;
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
+ MTK_PHY_LED0_ENABLE | MTK_PHY_LED0_POLARITY |
+ MTK_PHY_LED0_ON_LINK10 |
+ MTK_PHY_LED0_ON_LINK100 |
+ MTK_PHY_LED0_ON_LINK1000);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
+ MTK_PHY_LED1_ENABLE | MTK_PHY_LED1_POLARITY |
+ MTK_PHY_LED1_ON_LINK10 |
+ MTK_PHY_LED1_ON_LINK100 |
+ MTK_PHY_LED1_ON_LINK1000);
+
+ if ((port == GPHY_PORT0 && reg & BIT(8)) ||
+ (port == GPHY_PORT1 && reg & BIT(9)) ||
+ (port == GPHY_PORT2 && reg & BIT(10)) ||
+ (port == GPHY_PORT3 && reg & BIT(11))) {
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
+ MTK_PHY_LED0_POLARITY);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
+ MTK_PHY_LED1_POLARITY);
+ }
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_BLINK_CTRL,
+ MTK_PHY_LED0_1000TX | MTK_PHY_LED0_1000RX |
+ MTK_PHY_LED0_100TX | MTK_PHY_LED0_100RX |
+ MTK_PHY_LED0_10TX | MTK_PHY_LED0_10RX);
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_BLINK_CTRL,
+ MTK_PHY_LED1_1000TX | MTK_PHY_LED1_1000RX |
+ MTK_PHY_LED1_100TX | MTK_PHY_LED1_100RX |
+ MTK_PHY_LED1_10TX | MTK_PHY_LED1_10RX);
+
+ pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
+ if (IS_ERR(pinctrl)) {
+ dev_err(&phydev->mdio.bus->dev, "Failed to setup LED pins\n");
+ return PTR_ERR(pinctrl);
+ }
+
+ return 0;
+}
+
+static int mt7988_phy_probe_shared(struct phy_device *phydev)
+{
+ struct mtk_socphy_shared_priv *priv = phydev->shared->priv;
+ void __iomem *boottrap;
+ struct device_node *np;
+ u32 reg;
+
+ np = of_find_compatible_node(NULL, NULL, "mediatek,boottrap");
+ if (!np)
+ return -ENOENT;
+
+ boottrap = of_iomap(np, 0);
+ if (!boottrap)
+ return -ENOMEM;
+
+ reg = readl(boottrap);
+ iounmap(boottrap);
+
+ priv->boottrap = reg;
+
+ return 0;
+}
+
+static int mt7981_phy_probe(struct phy_device *phydev)
+{
+ return mt798x_phy_calibration(phydev);
+}
+
+static int mt7988_phy_probe(struct phy_device *phydev)
+{
+ int err;
+
+ err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0,
+ sizeof(struct mtk_socphy_shared_priv));
+ if (err)
+ return err;
+
+ if (phy_package_probe_once(phydev)) {
+ err = mt7988_phy_probe_shared(phydev);
+ if (err)
+ return err;
+ }
+
+ mt7988_phy_setup_led(phydev);
+
+ return mt798x_phy_calibration(phydev);
+}
+
+static struct phy_driver mtk_socphy_driver[] = {
+ {
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
+ .name = "MediaTek MT7981 PHY",
+ .config_init = mt798x_phy_config_init,
+ .config_intr = genphy_no_config_intr,
+ .handle_interrupt = genphy_no_ack_interrupt,
+ .probe = mt7981_phy_probe,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_socphy_read_page,
+ .write_page = mtk_socphy_write_page,
+ },
+ {
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988),
+ .name = "MediaTek MT7988 PHY",
+ .config_init = mt798x_phy_config_init,
+ .config_intr = genphy_no_config_intr,
+ .handle_interrupt = genphy_no_ack_interrupt,
+ .probe = mt7988_phy_probe,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_socphy_read_page,
+ .write_page = mtk_socphy_write_page,
+ },
+};
+
+module_phy_driver(mtk_socphy_driver);
+
+static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) },
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) },
+ { }
+};
+
+MODULE_DESCRIPTION("MediaTek SoC Gigabit Ethernet PHY driver");
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
+MODULE_LICENSE("GPL");
+
+MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl);
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
index 7a1233a..977a90b 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
@@ -1,350 +1,16 @@
// SPDX-License-Identifier: GPL-2.0+
#include <linux/bitfield.h>
#include <linux/module.h>
-#include <linux/nvmem-consumer.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/pinctrl/consumer.h>
#include <linux/phy.h>
-#define MTK_GPHY_ID_MT7530 0x03a29412
-#define MTK_GPHY_ID_MT7531 0x03a29441
-#ifdef CONFIG_MEDIATEK_GE_PHY_SOC
-#define MTK_GPHY_ID_MT7981 0x03a29461
-#define MTK_GPHY_ID_MT7988 0x03a29481
-#endif
-
#define MTK_EXT_PAGE_ACCESS 0x1f
#define MTK_PHY_PAGE_STANDARD 0x0000
#define MTK_PHY_PAGE_EXTENDED 0x0001
#define MTK_PHY_PAGE_EXTENDED_2 0x0002
#define MTK_PHY_PAGE_EXTENDED_3 0x0003
-/* Registers on Page 3 */
-#define MTK_PHY_LPI_REG_14 (0x14)
-#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK GENMASK(8, 0)
-
-#define MTK_PHY_LPI_REG_1c (0x1c)
-#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8)
-/*******************************/
-
#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
-#define ANALOG_INTERNAL_OPERATION_MAX_US (20)
-#define ZCAL_CTRL_MIN (0)
-#define ZCAL_CTRL_MAX (63)
-#define TXRESERVE_MIN (0)
-#define TXRESERVE_MAX (7)
-
-#define MTK_PHY_ANARG_RG (0x10)
-#define MTK_PHY_TCLKOFFSET_MASK GENMASK(12, 8)
-
-/* Registers on MDIO_MMD_VEND1 */
-enum {
- MTK_PHY_MIDDLE_LEVEL_SHAPPER_0TO1 = 0,
- MTK_PHY_1st_OVERSHOOT_LEVEL_0TO1,
- MTK_PHY_2nd_OVERSHOOT_LEVEL_0TO1,
- MTK_PHY_MIDDLE_LEVEL_SHAPPER_1TO0,
- MTK_PHY_1st_OVERSHOOT_LEVEL_1TO0,
- MTK_PHY_2nd_OVERSHOOT_LEVEL_1TO0,
- MTK_PHY_MIDDLE_LEVEL_SHAPPER_0TON1, /* N means negative */
- MTK_PHY_1st_OVERSHOOT_LEVEL_0TON1,
- MTK_PHY_2nd_OVERSHOOT_LEVEL_0TON1,
- MTK_PHY_MIDDLE_LEVEL_SHAPPER_N1TO0,
- MTK_PHY_1st_OVERSHOOT_LEVEL_N1TO0,
- MTK_PHY_2nd_OVERSHOOT_LEVEL_N1TO0,
- MTK_PHY_TX_MLT3_END,
-};
-
-#define MTK_PHY_TXVLD_DA_RG (0x12)
-#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10)
-#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK GENMASK(5, 0)
-
-#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 (0x16)
-#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK GENMASK(15, 10)
-#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK GENMASK(5, 0)
-
-#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 (0x17)
-#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK GENMASK(13, 8)
-#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK GENMASK(5, 0)
-
-#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 (0x18)
-#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK GENMASK(13, 8)
-#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK GENMASK(5, 0)
-
-#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 (0x19)
-#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK GENMASK(13, 8)
-#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK GENMASK(5, 0)
-
-#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 (0x20)
-#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK GENMASK(13, 8)
-#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK GENMASK(5, 0)
-
-#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 (0x21)
-#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK GENMASK(13, 8)
-#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK GENMASK(5, 0)
-
-#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 (0x22)
-#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK GENMASK(13, 8)
-#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK GENMASK(5, 0)
-
-#define MTK_PHY_TANA_CAL_MODE (0xc1)
-#define MTK_PHY_TANA_CAL_MODE_SHIFT (8)
-
-#define MTK_PHY_RXADC_CTRL_RG7 (0xc6)
-#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8)
-
-#define MTK_PHY_RXADC_CTRL_RG9 (0xc8)
-#define MTK_PHY_DA_RX_PSBN_TBT_MASK GENMASK(14, 12)
-#define MTK_PHY_DA_RX_PSBN_HBT_MASK GENMASK(10, 8)
-#define MTK_PHY_DA_RX_PSBN_GBE_MASK GENMASK(6, 4)
-#define MTK_PHY_DA_RX_PSBN_LP_MASK GENMASK(2, 0)
-
-#define MTK_PHY_LDO_OUTPUT_V (0xd7)
-
-#define MTK_PHY_RG_ANA_CAL_RG0 (0xdb)
-#define MTK_PHY_RG_CAL_CKINV BIT(12)
-#define MTK_PHY_RG_ANA_CALEN BIT(8)
-#define MTK_PHY_RG_REXT_CALEN BIT(4)
-#define MTK_PHY_RG_ZCALEN_A BIT(0)
-
-#define MTK_PHY_RG_ANA_CAL_RG1 (0xdc)
-#define MTK_PHY_RG_ZCALEN_B BIT(12)
-#define MTK_PHY_RG_ZCALEN_C BIT(8)
-#define MTK_PHY_RG_ZCALEN_D BIT(4)
-#define MTK_PHY_RG_TXVOS_CALEN BIT(0)
-
-#define MTK_PHY_RG_ANA_CAL_RG2 (0xdd)
-#define MTK_PHY_RG_TXG_CALEN_A BIT(12)
-#define MTK_PHY_RG_TXG_CALEN_B BIT(8)
-#define MTK_PHY_RG_TXG_CALEN_C BIT(4)
-#define MTK_PHY_RG_TXG_CALEN_D BIT(0)
-
-#define MTK_PHY_RG_ANA_CAL_RG5 (0xe0)
-#define MTK_PHY_RG_REXT_TRIM_MASK GENMASK(13, 8)
-#define MTK_PHY_RG_ZCAL_CTRL_MASK GENMASK(5, 0)
-
-#define MTK_PHY_RG_TX_FILTER (0xfe)
-
-#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120 (0x120)
-#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK GENMASK(12, 8)
-#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK GENMASK(4, 0)
-
-#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122 (0x122)
-#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK GENMASK(7, 0)
-
-#define MTK_PHY_RG_TESTMUX_ADC_CTRL (0x144)
-#define MTK_PHY_RG_TXEN_DIG_MASK GENMASK(5, 5)
-
-#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B (0x172)
-#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK GENMASK(13, 8)
-#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK GENMASK(6, 0)
-
-#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D (0x173)
-#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK GENMASK(13, 8)
-#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0)
-
-#define MTK_PHY_RG_AD_CAL_COMP (0x17a)
-#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT (8)
-
-#define MTK_PHY_RG_AD_CAL_CLK (0x17b)
-#define MTK_PHY_DA_CAL_CLK BIT(0)
-
-#define MTK_PHY_RG_AD_CALIN (0x17c)
-#define MTK_PHY_DA_CALIN_FLAG BIT(0)
-
-#define MTK_PHY_RG_DASN_DAC_IN0_A (0x17d)
-#define MTK_PHY_DASN_DAC_IN0_A_MASK GENMASK(9, 0)
-
-#define MTK_PHY_RG_DASN_DAC_IN0_B (0x17e)
-#define MTK_PHY_DASN_DAC_IN0_B_MASK GENMASK(9, 0)
-
-#define MTK_PHY_RG_DASN_DAC_IN0_C (0x17f)
-#define MTK_PHY_DASN_DAC_IN0_C_MASK GENMASK(9, 0)
-
-#define MTK_PHY_RG_DASN_DAC_IN0_D (0x180)
-#define MTK_PHY_DASN_DAC_IN0_D_MASK GENMASK(9, 0)
-
-#define MTK_PHY_RG_DASN_DAC_IN1_A (0x181)
-#define MTK_PHY_DASN_DAC_IN1_A_MASK GENMASK(9, 0)
-
-#define MTK_PHY_RG_DASN_DAC_IN1_B (0x182)
-#define MTK_PHY_DASN_DAC_IN1_B_MASK GENMASK(9, 0)
-
-#define MTK_PHY_RG_DASN_DAC_IN1_C (0x183)
-#define MTK_PHY_DASN_DAC_IN1_C_MASK GENMASK(9, 0)
-
-#define MTK_PHY_RG_DASN_DAC_IN1_D (0x184)
-#define MTK_PHY_DASN_DAC_IN1_D_MASK GENMASK(9, 0)
-
-#define MTK_PHY_RG_DEV1E_REG19b (0x19b)
-#define MTK_PHY_BYPASS_DSP_LPI_READY BIT(8)
-
-#define MTK_PHY_RG_LP_IIR2_K1_L (0x22a)
-#define MTK_PHY_RG_LP_IIR2_K1_U (0x22b)
-#define MTK_PHY_RG_LP_IIR2_K2_L (0x22c)
-#define MTK_PHY_RG_LP_IIR2_K2_U (0x22d)
-#define MTK_PHY_RG_LP_IIR2_K3_L (0x22e)
-#define MTK_PHY_RG_LP_IIR2_K3_U (0x22f)
-#define MTK_PHY_RG_LP_IIR2_K4_L (0x230)
-#define MTK_PHY_RG_LP_IIR2_K4_U (0x231)
-#define MTK_PHY_RG_LP_IIR2_K5_L (0x232)
-#define MTK_PHY_RG_LP_IIR2_K5_U (0x233)
-
-#define MTK_PHY_RG_DEV1E_REG234 (0x234)
-#define MTK_PHY_TR_OPEN_LOOP_EN_MASK GENMASK(0, 0)
-#define MTK_PHY_LPF_X_AVERAGE_MASK GENMASK(7, 4)
-#define MTK_PHY_TR_LP_IIR_EEE_EN BIT(12)
-
-#define MTK_PHY_RG_LPF_CNT_VAL (0x235)
-
-#define MTK_PHY_RG_DEV1E_REG238 (0x238)
-#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK GENMASK(8, 0)
-#define MTK_PHY_LPI_SLV_SEND_TX_EN BIT(12)
-
-#define MTK_PHY_RG_DEV1E_REG239 (0x239)
-#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK GENMASK(8, 0)
-#define MTK_PHY_LPI_TXPCS_LOC_RCV BIT(12)
-
-#define MTK_PHY_RG_DEV1E_REG27C (0x27c)
-#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK GENMASK(12, 8)
-#define MTK_PHY_RG_DEV1E_REG27D (0x27d)
-#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK GENMASK(4, 0)
-
-#define MTK_PHY_RG_DEV1E_REG2C7 (0x2c7)
-#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0)
-#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8)
-
-#define MTK_PHY_RG_DEV1E_REG2D1 (0x2d1)
-#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK GENMASK(7, 0)
-#define MTK_PHY_LPI_SKIP_SD_SLV_TR BIT(8)
-#define MTK_PHY_LPI_TR_READY BIT(9)
-#define MTK_PHY_LPI_VCO_EEE_STG0_EN BIT(10)
-
-#define MTK_PHY_RG_DEV1E_REG323 (0x323)
-#define MTK_PHY_EEE_WAKE_MAS_INT_DC BIT(0)
-#define MTK_PHY_EEE_WAKE_SLV_INT_DC BIT(4)
-
-#define MTK_PHY_RG_DEV1E_REG324 (0x324)
-#define MTK_PHY_SMI_DETCNT_MAX_MASK GENMASK(5, 0)
-#define MTK_PHY_SMI_DET_MAX_EN BIT(8)
-
-#define MTK_PHY_RG_DEV1E_REG326 (0x326)
-#define MTK_PHY_LPI_MODE_SD_ON BIT(0)
-#define MTK_PHY_RESET_RANDUPD_CNT BIT(1)
-#define MTK_PHY_TREC_UPDATE_ENAB_CLR BIT(2)
-#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF BIT(4)
-#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP BIT(5)
-
-#define MTK_PHY_LDO_PUMP_EN_PAIRAB (0x502)
-#define MTK_PHY_LDO_PUMP_EN_PAIRCD (0x503)
-
-#define MTK_PHY_DA_TX_R50_PAIR_A (0x53d)
-#define MTK_PHY_DA_TX_R50_PAIR_B (0x53e)
-#define MTK_PHY_DA_TX_R50_PAIR_C (0x53f)
-#define MTK_PHY_DA_TX_R50_PAIR_D (0x540)
-
-/* Registers on MDIO_MMD_VEND2 */
-#define MTK_PHY_LED0_ON_CTRL (0x24)
-#define MTK_PHY_LED0_ON_MASK GENMASK(6, 0)
-#define MTK_PHY_LED0_ON_LINK1000 BIT(0)
-#define MTK_PHY_LED0_ON_LINK100 BIT(1)
-#define MTK_PHY_LED0_ON_LINK10 BIT(2)
-#define MTK_PHY_LED0_ON_LINKDOWN BIT(3)
-#define MTK_PHY_LED0_ON_FDX BIT(4) /* Full duplex */
-#define MTK_PHY_LED0_ON_HDX BIT(5) /* Half duplex */
-#define MTK_PHY_LED0_FORCE_ON BIT(6)
-#define MTK_PHY_LED0_POLARITY BIT(14)
-#define MTK_PHY_LED0_ENABLE BIT(15)
-
-#define MTK_PHY_LED0_BLINK_CTRL (0x25)
-#define MTK_PHY_LED0_1000TX BIT(0)
-#define MTK_PHY_LED0_1000RX BIT(1)
-#define MTK_PHY_LED0_100TX BIT(2)
-#define MTK_PHY_LED0_100RX BIT(3)
-#define MTK_PHY_LED0_10TX BIT(4)
-#define MTK_PHY_LED0_10RX BIT(5)
-#define MTK_PHY_LED0_COLLISION BIT(6)
-#define MTK_PHY_LED0_RX_CRC_ERR BIT(7)
-#define MTK_PHY_LED0_RX_IDLE_ERR BIT(8)
-#define MTK_PHY_LED0_FORCE_BLINK BIT(9)
-
-#define MTK_PHY_ANA_TEST_BUS_CTRL_RG (0x100)
-#define MTK_PHY_ANA_TEST_MODE_MASK GENMASK(15, 8)
-
-#define MTK_PHY_RG_DASN_TXT_DMY2 (0x110)
-#define MTK_PHY_TST_DMY2_MASK GENMASK(5, 0)
-
-#define MTK_PHY_RG_BG_RASEL (0x115)
-#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0)
-
-/* These macro privides efuse parsing for internal phy. */
-#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0))
-#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0))
-#define EFS_DA_TX_I2MPB_C(x) (((x) >> 12) & GENMASK(5, 0))
-#define EFS_DA_TX_I2MPB_D(x) (((x) >> 18) & GENMASK(5, 0))
-#define EFS_DA_TX_AMP_OFFSET_A(x) (((x) >> 24) & GENMASK(5, 0))
-
-#define EFS_DA_TX_AMP_OFFSET_B(x) (((x) >> 0) & GENMASK(5, 0))
-#define EFS_DA_TX_AMP_OFFSET_C(x) (((x) >> 6) & GENMASK(5, 0))
-#define EFS_DA_TX_AMP_OFFSET_D(x) (((x) >> 12) & GENMASK(5, 0))
-#define EFS_DA_TX_R50_A(x) (((x) >> 18) & GENMASK(5, 0))
-#define EFS_DA_TX_R50_B(x) (((x) >> 24) & GENMASK(5, 0))
-
-#define EFS_DA_TX_R50_C(x) (((x) >> 0) & GENMASK(5, 0))
-#define EFS_DA_TX_R50_D(x) (((x) >> 6) & GENMASK(5, 0))
-#define EFS_DA_TX_R50_A_10M(x) (((x) >> 12) & GENMASK(5, 0))
-#define EFS_DA_TX_R50_B_10M(x) (((x) >> 18) & GENMASK(5, 0))
-
-#define EFS_RG_BG_RASEL(x) (((x) >> 4) & GENMASK(2, 0))
-#define EFS_RG_REXT_TRIM(x) (((x) >> 7) & GENMASK(5, 0))
-
-enum {
- NO_PAIR,
- PAIR_A,
- PAIR_B,
- PAIR_C,
- PAIR_D,
-};
-
-enum {
- GPHY_PORT0,
- GPHY_PORT1,
- GPHY_PORT2,
- GPHY_PORT3,
-};
-
-enum calibration_mode {
- EFUSE_K,
- SW_K
-};
-
-enum CAL_ITEM {
- REXT,
- TX_OFFSET,
- TX_AMP,
- TX_R50,
- TX_VCM
-};
-
-enum CAL_MODE {
- EFUSE_M,
- SW_M
-};
-
-const u8 mt798x_zcal_to_r50[64] = {
- 7, 8, 9, 9, 10, 10, 11, 11,
- 12, 13, 13, 14, 14, 15, 16, 16,
- 17, 18, 18, 19, 20, 21, 21, 22,
- 23, 24, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 40, 41, 42, 43, 45, 46, 48,
- 49, 51, 52, 54, 55, 57, 59, 61,
- 62, 63, 63, 63, 63, 63, 63, 63
-};
-
-const char pair[4] = {'A', 'B', 'C', 'D'};
-
static int mtk_gephy_read_page(struct phy_device *phydev)
{
return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
@@ -402,888 +68,9 @@
return 0;
}
-#ifdef CONFIG_MEDIATEK_GE_PHY_SOC
-/* One calibration cycle consists of:
- * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high
- * until AD_CAL_COMP is ready to output calibration result.
- * 2.Wait until DA_CAL_CLK is available.
- * 3.Fetch AD_CAL_COMP_OUT.
- */
-static int cal_cycle(struct phy_device *phydev, int devad,
- u32 regnum, u16 mask, u16 cal_val)
-{
- unsigned long timeout;
- int reg_val;
- int ret;
-
- phy_modify_mmd(phydev, devad, regnum,
- mask, cal_val);
- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
- MTK_PHY_DA_CALIN_FLAG);
-
- timeout = jiffies + usecs_to_jiffies(ANALOG_INTERNAL_OPERATION_MAX_US);
- do {
- reg_val = phy_read_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_AD_CAL_CLK);
- } while (time_before(jiffies, timeout) && !(reg_val & BIT(0)));
-
- if (!(reg_val & BIT(0))) {
- dev_err(&phydev->mdio.dev, "Calibration cycle timeout\n");
- return -ETIMEDOUT;
- }
-
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
- MTK_PHY_DA_CALIN_FLAG);
- ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >>
- MTK_PHY_AD_CAL_COMP_OUT_SHIFT;
- dev_dbg(&phydev->mdio.dev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
-
- return ret;
-}
-
-static int rext_fill_result(struct phy_device *phydev, u16 *buf)
-{
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
- MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8);
- phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL,
- MTK_PHY_RG_BG_RASEL_MASK, buf[1]);
-
- return 0;
-}
-
-static int rext_cal_efuse(struct phy_device *phydev, u32 *buf)
-{
- u16 rext_cal_val[2];
-
- rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]);
- rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]);
- rext_fill_result(phydev, rext_cal_val);
-
- return 0;
-}
-
-static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf)
-{
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
- MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
- MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
- MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
- MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]);
-
- return 0;
-}
-
-static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf)
-{
- u16 tx_offset_cal_val[4];
-
- tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]);
- tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]);
- tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]);
- tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]);
-
- tx_offset_fill_result(phydev, tx_offset_cal_val);
-
- return 0;
-}
-
-static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
-{
- int i;
- int bias[16] = {0};
- const int vals_9461[16] = { 7, 1, 4, 7,
- 7, 1, 4, 7,
- 7, 1, 4, 7,
- 7, 1, 4, 7 };
- const int vals_9481[16] = { 10, 6, 6, 10,
- 10, 6, 6, 10,
- 10, 6, 6, 10,
- 10, 6, 6, 10 };
-
- switch (phydev->drv->phy_id) {
- case MTK_GPHY_ID_MT7981:
- /* We add some calibration to efuse values
- * due to board level influence.
- * GBE: +7, TBT: +1, HBT: +4, TST: +7
- */
- memcpy(bias, (const void *)vals_9461, sizeof(bias));
- break;
- case MTK_GPHY_ID_MT7988:
- memcpy(bias, (const void *)vals_9481, sizeof(bias));
- break;
- default:
- break;
- }
-
- /* Prevent overflow */
- for (i = 0; i < 12; i++) {
- if (buf[i >> 2] + bias[i] > 63) {
- buf[i >> 2] = 63;
- bias[i] = 0;
- } else if (buf[i >> 2] + bias[i] < 0) {
- /* Bias caused by board design may change in the future.
- * So check negative cases, too.
- */
- buf[i >> 2] = 0;
- bias[i] = 0;
- }
- }
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
- MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
- MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
- MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
- MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]);
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
- MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
- MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
- MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
- MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]);
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
- MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
- MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
- MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
- MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]);
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
- MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
- MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
- MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
- MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]);
-
- return 0;
-}
-
-static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf)
-{
- u16 tx_amp_cal_val[4];
-
- tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]);
- tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]);
- tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]);
- tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]);
- tx_amp_fill_result(phydev, tx_amp_cal_val);
-
- return 0;
-}
-
-static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val,
- u8 txg_calen_x)
-{
- int bias = 0;
- u16 reg, val;
-
- switch (phydev->drv->phy_id) {
- case MTK_GPHY_ID_MT7988:
- {
- bias = -2;
- break;
- }
- /* MTK_GPHY_ID_MT7981 enters default case */
- default:
- break;
- }
-
- val = clamp_val(bias + tx_r50_cal_val, 0, 63);
-
- switch (txg_calen_x) {
- case PAIR_A:
- reg = MTK_PHY_DA_TX_R50_PAIR_A;
- break;
- case PAIR_B:
- reg = MTK_PHY_DA_TX_R50_PAIR_B;
- break;
- case PAIR_C:
- reg = MTK_PHY_DA_TX_R50_PAIR_C;
- break;
- case PAIR_D:
- reg = MTK_PHY_DA_TX_R50_PAIR_D;
- break;
- }
-
- phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8);
-
- return 0;
-}
-
-static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf,
- u8 txg_calen_x)
-{
- u16 tx_r50_cal_val;
-
- switch (txg_calen_x) {
- case PAIR_A:
- tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]);
- break;
- case PAIR_B:
- tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]);
- break;
- case PAIR_C:
- tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]);
- break;
- case PAIR_D:
- tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]);
- break;
- }
- tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x);
-
- return 0;
-}
-
-static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x)
-{
- u8 lower_idx, upper_idx, txreserve_val;
- u8 lower_ret, upper_ret;
- int ret;
-
- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
- MTK_PHY_RG_ANA_CALEN);
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
- MTK_PHY_RG_CAL_CKINV);
- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
- MTK_PHY_RG_TXVOS_CALEN);
-
- switch (rg_txreserve_x) {
- case PAIR_A:
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_DASN_DAC_IN0_A,
- MTK_PHY_DASN_DAC_IN0_A_MASK);
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_DASN_DAC_IN1_A,
- MTK_PHY_DASN_DAC_IN1_A_MASK);
- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_ANA_CAL_RG0,
- MTK_PHY_RG_ZCALEN_A);
- break;
- case PAIR_B:
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_DASN_DAC_IN0_B,
- MTK_PHY_DASN_DAC_IN0_B_MASK);
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_DASN_DAC_IN1_B,
- MTK_PHY_DASN_DAC_IN1_B_MASK);
- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_ANA_CAL_RG1,
- MTK_PHY_RG_ZCALEN_B);
- break;
- case PAIR_C:
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_DASN_DAC_IN0_C,
- MTK_PHY_DASN_DAC_IN0_C_MASK);
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_DASN_DAC_IN1_C,
- MTK_PHY_DASN_DAC_IN1_C_MASK);
- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_ANA_CAL_RG1,
- MTK_PHY_RG_ZCALEN_C);
- break;
- case PAIR_D:
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_DASN_DAC_IN0_D,
- MTK_PHY_DASN_DAC_IN0_D_MASK);
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_DASN_DAC_IN1_D,
- MTK_PHY_DASN_DAC_IN1_D_MASK);
- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_ANA_CAL_RG1,
- MTK_PHY_RG_ZCALEN_D);
- break;
- default:
- ret = -EINVAL;
- goto restore;
- }
-
- lower_idx = TXRESERVE_MIN;
- upper_idx = TXRESERVE_MAX;
-
- dev_dbg(&phydev->mdio.dev, "Start TX-VCM SW cal.\n");
- while ((upper_idx - lower_idx) > 1) {
- txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2);
- ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
- MTK_PHY_DA_RX_PSBN_TBT_MASK |
- MTK_PHY_DA_RX_PSBN_HBT_MASK |
- MTK_PHY_DA_RX_PSBN_GBE_MASK |
- MTK_PHY_DA_RX_PSBN_LP_MASK,
- txreserve_val << 12 | txreserve_val << 8 |
- txreserve_val << 4 | txreserve_val);
- if (ret == 1) {
- upper_idx = txreserve_val;
- upper_ret = ret;
- } else if (ret == 0) {
- lower_idx = txreserve_val;
- lower_ret = ret;
- } else {
- goto restore;
- }
- }
-
- if (lower_idx == TXRESERVE_MIN) {
- lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RXADC_CTRL_RG9,
- MTK_PHY_DA_RX_PSBN_TBT_MASK |
- MTK_PHY_DA_RX_PSBN_HBT_MASK |
- MTK_PHY_DA_RX_PSBN_GBE_MASK |
- MTK_PHY_DA_RX_PSBN_LP_MASK,
- lower_idx << 12 | lower_idx << 8 |
- lower_idx << 4 | lower_idx);
- ret = lower_ret;
- } else if (upper_idx == TXRESERVE_MAX) {
- upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RXADC_CTRL_RG9,
- MTK_PHY_DA_RX_PSBN_TBT_MASK |
- MTK_PHY_DA_RX_PSBN_HBT_MASK |
- MTK_PHY_DA_RX_PSBN_GBE_MASK |
- MTK_PHY_DA_RX_PSBN_LP_MASK,
- upper_idx << 12 | upper_idx << 8 |
- upper_idx << 4 | upper_idx);
- ret = upper_ret;
- }
- if (ret < 0)
- goto restore;
-
- /* We calibrate TX-VCM in different logic. Check upper index and then
- * lower index. If this calibration is valid, apply lower index's result.
- */
- ret = upper_ret - lower_ret;
- if (ret == 1) {
- ret = 0;
- /* Make sure we use upper_idx in our calibration system */
- cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
- MTK_PHY_DA_RX_PSBN_TBT_MASK |
- MTK_PHY_DA_RX_PSBN_HBT_MASK |
- MTK_PHY_DA_RX_PSBN_GBE_MASK |
- MTK_PHY_DA_RX_PSBN_LP_MASK,
- upper_idx << 12 | upper_idx << 8 |
- upper_idx << 4 | upper_idx);
- dev_info(&phydev->mdio.dev, "TX-VCM SW cal result: 0x%x\n",
- upper_idx);
- } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 &&
- lower_ret == 1) {
- ret = 0;
- cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
- MTK_PHY_DA_RX_PSBN_TBT_MASK |
- MTK_PHY_DA_RX_PSBN_HBT_MASK |
- MTK_PHY_DA_RX_PSBN_GBE_MASK |
- MTK_PHY_DA_RX_PSBN_LP_MASK,
- lower_idx << 12 | lower_idx << 8 |
- lower_idx << 4 | lower_idx);
- dev_warn(&phydev->mdio.dev,
- "TX-VCM SW cal result at low margin 0x%x\n",
- lower_idx);
- } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 &&
- lower_ret == 0) {
- ret = 0;
- dev_warn(&phydev->mdio.dev,
- "TX-VCM SW cal result at high margin 0x%x\n",
- upper_idx);
- } else {
- ret = -EINVAL;
- }
-
-restore:
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
- MTK_PHY_RG_ANA_CALEN);
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
- MTK_PHY_RG_TXVOS_CALEN);
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
- MTK_PHY_RG_ZCALEN_A);
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
- MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C |
- MTK_PHY_RG_ZCALEN_D);
-
- return ret;
-}
-
-static inline void mt798x_phy_common_finetune(struct phy_device *phydev)
-{
- u32 i;
-
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- /* EnabRandUpdTrig = 1 */
- __phy_write(phydev, 0x11, 0x2f00);
- __phy_write(phydev, 0x12, 0xe);
- __phy_write(phydev, 0x10, 0x8fb0);
-
- /* NormMseLoThresh = 85 */
- __phy_write(phydev, 0x11, 0x55a0);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x83aa);
-
- /* TrFreeze = 0 */
- __phy_write(phydev, 0x11, 0x0);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x9686);
-
- /* SSTrKp1000Slv = 5 */
- __phy_write(phydev, 0x11, 0xbaef);
- __phy_write(phydev, 0x12, 0x2e);
- __phy_write(phydev, 0x10, 0x968c);
-
- /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
- * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
- */
- __phy_write(phydev, 0x11, 0xd10a);
- __phy_write(phydev, 0x12, 0x34);
- __phy_write(phydev, 0x10, 0x8f82);
-
- /* VcoSlicerThreshBitsHigh */
- __phy_write(phydev, 0x11, 0x5555);
- __phy_write(phydev, 0x12, 0x55);
- __phy_write(phydev, 0x10, 0x8ec0);
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
-
- /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
- MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
- BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
-
- /* rg_tr_lpf_cnt_val = 512 */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200);
-
- /* IIR2 related */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe);
-
- /* FFE peaking */
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C,
- MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8);
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D,
- MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e);
-
- /* Disable LDO pump */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0);
- /* Adjust LDO output voltage */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222);
-}
-
-static inline void mt7981_phy_finetune(struct phy_device *phydev)
-{
- /* 100M eye finetune:
- * Keep middle level of TX MLT3 shapper as default.
- * Only change TX MLT3 overshoot level here.
- */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_1st_OVERSHOOT_LEVEL_0TO1,
- 0x1ce);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_2nd_OVERSHOOT_LEVEL_0TO1,
- 0x1c1);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_1st_OVERSHOOT_LEVEL_1TO0,
- 0x20f);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_2nd_OVERSHOOT_LEVEL_1TO0,
- 0x202);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_1st_OVERSHOOT_LEVEL_0TON1,
- 0x3d0);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_2nd_OVERSHOOT_LEVEL_0TON1,
- 0x3c0);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_1st_OVERSHOOT_LEVEL_N1TO0,
- 0x13);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_2nd_OVERSHOOT_LEVEL_N1TO0,
- 0x5);
-
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
- __phy_write(phydev, 0x11, 0xc71);
- __phy_write(phydev, 0x12, 0xc);
- __phy_write(phydev, 0x10, 0x8fae);
-
- /* ResetSyncOffset = 6 */
- __phy_write(phydev, 0x11, 0x600);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x8fc0);
-
- /* VgaDecRate = 1 */
- __phy_write(phydev, 0x11, 0x4c2a);
- __phy_write(phydev, 0x12, 0x3e);
- __phy_write(phydev, 0x10, 0x8fa4);
-
- /* FfeUpdGainForce = 4 */
- __phy_write(phydev, 0x11, 0x240);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x9680);
-
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
-}
-
-static inline void mt7988_phy_finetune(struct phy_device *phydev)
-{
- u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182,
- 0x020d, 0x0206, 0x0384, 0x03d0,
- 0x03c6, 0x030a, 0x0011, 0x0005 };
- int i;
-
- for (i = 0; i < MTK_PHY_TX_MLT3_END; i++)
- phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]);
-
- /* TCT finetune */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
-
- /* Disable TX power saving */
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
- MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
-
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
-
- /* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */
- __phy_write(phydev, 0x11, 0x671);
- __phy_write(phydev, 0x12, 0xc);
- __phy_write(phydev, 0x10, 0x8fae);
-
- /* ResetSyncOffset = 5 */
- __phy_write(phydev, 0x11, 0x500);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x8fc0);
-
- /* VgaDecRate is 1 at default on mt7988 */
-
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
-
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30);
- /* TxClkOffset = 2 */
- __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK,
- FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2));
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
-}
-
-static inline void mt798x_phy_eee(struct phy_device *phydev)
-{
- phy_modify_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120,
- MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK |
- MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK,
- FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) |
- FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14));
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
- MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
- FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
- 0xff));
-
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_TESTMUX_ADC_CTRL,
- MTK_PHY_RG_TXEN_DIG_MASK);
-
- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY);
-
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN);
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238,
- MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK |
- MTK_PHY_LPI_SLV_SEND_TX_EN,
- FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120));
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
- MTK_PHY_LPI_SEND_LOC_TIMER_MASK |
- MTK_PHY_LPI_TXPCS_LOC_RCV,
- FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117));
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
- MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK,
- FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) |
- FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13));
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1,
- MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
- FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
- 0x33) |
- MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY |
- MTK_PHY_LPI_VCO_EEE_STG0_EN);
-
- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323,
- MTK_PHY_EEE_WAKE_MAS_INT_DC |
- MTK_PHY_EEE_WAKE_SLV_INT_DC);
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324,
- MTK_PHY_SMI_DETCNT_MAX_MASK,
- FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) |
- MTK_PHY_SMI_DET_MAX_EN);
-
- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326,
- MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT |
- MTK_PHY_TREC_UPDATE_ENAB_CLR |
- MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF |
- MTK_PHY_TR_READY_SKIP_AFE_WAKEUP);
-
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- /* Regsigdet_sel_1000 = 0 */
- __phy_write(phydev, 0x11, 0xb);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x9690);
-
- /* REG_EEE_st2TrKf1000 = 3 */
- __phy_write(phydev, 0x11, 0x114f);
- __phy_write(phydev, 0x12, 0x2);
- __phy_write(phydev, 0x10, 0x969a);
-
- /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */
- __phy_write(phydev, 0x11, 0x3028);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x969e);
-
- /* RegEEE_slv_wake_int_timer_tar = 8 */
- __phy_write(phydev, 0x11, 0x5010);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x96a0);
-
- /* RegEEE_trfreeze_timer2 = 586 */
- __phy_write(phydev, 0x11, 0x24a);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x96a8);
-
- /* RegEEE100Stg1_tar = 16 */
- __phy_write(phydev, 0x11, 0x3210);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x96b8);
-
- /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */
- __phy_write(phydev, 0x11, 0x1463);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x96ca);
-
- /* DfeTailEnableVgaThresh1000 = 27 */
- __phy_write(phydev, 0x11, 0x36);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x8f80);
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
-
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
- __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
- FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c));
-
- __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK,
- FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc));
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
-
- phy_modify_mmd(phydev, MDIO_MMD_VEND1,
- MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
- MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
- FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff));
-}
-
-static inline int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
- u8 start_pair, u8 end_pair)
-{
- u8 pair_n;
- int ret;
-
- for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
- /* TX_OFFSET & TX_AMP have no SW calibration. */
- switch (cal_item) {
- case TX_VCM:
- ret = tx_vcm_cal_sw(phydev, pair_n);
- break;
- default:
- return -EINVAL;
- }
- if (ret)
- return ret;
- }
- return 0;
-}
-
-static inline int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item,
- u8 start_pair, u8 end_pair, u32 *buf)
-{
- u8 pair_n;
- int ret;
-
- for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
- /* TX_VCM has no efuse calibration. */
- switch (cal_item) {
- case REXT:
- ret = rext_cal_efuse(phydev, buf);
- break;
- case TX_OFFSET:
- ret = tx_offset_cal_efuse(phydev, buf);
- break;
- case TX_AMP:
- ret = tx_amp_cal_efuse(phydev, buf);
- break;
- case TX_R50:
- ret = tx_r50_cal_efuse(phydev, buf, pair_n);
- break;
- default:
- return -EINVAL;
- }
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item,
- enum CAL_MODE cal_mode, u8 start_pair,
- u8 end_pair, u32 *buf)
-{
- int ret;
- char cal_prop[5][20] = { "mediatek,rext", "mediatek,tx_offset",
- "mediatek,tx_amp", "mediatek,tx_r50",
- "mediatek,tx_vcm" };
-
- switch (cal_mode) {
- case EFUSE_M:
- ret = cal_efuse(phydev, cal_item, start_pair,
- end_pair, buf);
- break;
- case SW_M:
- ret = cal_sw(phydev, cal_item, start_pair, end_pair);
- break;
- default:
- return -EINVAL;
- }
-
- if (ret) {
- dev_err(&phydev->mdio.dev, "[%s]cal failed\n", cal_prop[cal_item]);
- return -EIO;
- }
-
- return 0;
-}
-
-static int mt798x_phy_calibration(struct phy_device *phydev)
-{
- int ret = 0;
- u32 *buf;
- size_t len;
- struct nvmem_cell *cell;
-
- if (phydev->interface != PHY_INTERFACE_MODE_GMII)
- return -EINVAL;
-
- cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
- if (IS_ERR(cell)) {
- if (PTR_ERR(cell) == -EPROBE_DEFER)
- return PTR_ERR(cell);
- return 0;
- }
-
- buf = (u32 *)nvmem_cell_read(cell, &len);
- if (IS_ERR(buf))
- return PTR_ERR(buf);
- nvmem_cell_put(cell);
-
- if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) {
- dev_err(&phydev->mdio.dev, "invalid efuse data\n");
- ret = -EINVAL;
- goto out;
- }
-
- ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf);
- if (ret)
- goto out;
- ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf);
- if (ret)
- goto out;
- ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf);
- if (ret)
- goto out;
- ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf);
- if (ret)
- goto out;
- ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf);
- if (ret)
- goto out;
-
-out:
- kfree(buf);
- return ret;
-}
-
-static int mt7981_phy_probe(struct phy_device *phydev)
-{
- mt798x_phy_common_finetune(phydev);
- mt7981_phy_finetune(phydev);
- mt798x_phy_eee(phydev);
-
- return mt798x_phy_calibration(phydev);
-}
-
-static int mt7988_phy_probe(struct phy_device *phydev)
-{
- struct device_node *np;
- void __iomem *boottrap;
- u32 reg;
- int port;
- int ret;
- struct pinctrl *pinctrl;
-
- /* Setup LED polarity according to boottrap's polarity */
- np = of_find_compatible_node(NULL, NULL, "mediatek,boottrap");
- if (!np)
- return -ENOENT;
- boottrap = of_iomap(np, 0);
- if (!boottrap)
- return -ENOMEM;
- reg = readl(boottrap);
- port = phydev->mdio.addr;
- if ((port == GPHY_PORT0 && reg & BIT(8)) ||
- (port == GPHY_PORT1 && reg & BIT(9)) ||
- (port == GPHY_PORT2 && reg & BIT(10)) ||
- (port == GPHY_PORT3 && reg & BIT(11))) {
- phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
- MTK_PHY_LED0_ENABLE | MTK_PHY_LED0_ON_LINK10 |
- MTK_PHY_LED0_ON_LINK100 |
- MTK_PHY_LED0_ON_LINK1000);
- } else {
- phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
- MTK_PHY_LED0_ENABLE | MTK_PHY_LED0_POLARITY |
- MTK_PHY_LED0_ON_LINK10 |
- MTK_PHY_LED0_ON_LINK100 |
- MTK_PHY_LED0_ON_LINK1000);
- }
- phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_BLINK_CTRL,
- MTK_PHY_LED0_1000TX | MTK_PHY_LED0_1000RX |
- MTK_PHY_LED0_100TX | MTK_PHY_LED0_100RX |
- MTK_PHY_LED0_10TX | MTK_PHY_LED0_10RX);
-
- if (port == GPHY_PORT3) {
- pinctrl = devm_pinctrl_get_select_default(&phydev->mdio.bus->dev);
- if (IS_ERR(pinctrl)) {
- ret = PTR_ERR(pinctrl);
- dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n");
- return -EINVAL;
- }
- }
-
- mt798x_phy_common_finetune(phydev);
- mt7988_phy_finetune(phydev);
- mt798x_phy_eee(phydev);
-
- return mt798x_phy_calibration(phydev);
-}
-#endif
-
static struct phy_driver mtk_gephy_driver[] = {
{
- PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
+ PHY_ID_MATCH_EXACT(0x03a29412),
.name = "MediaTek MT7530 PHY",
.config_init = mt7530_phy_config_init,
/* Interrupts are handled by the switch, not the PHY
@@ -1297,7 +84,7 @@
.write_page = mtk_gephy_write_page,
},
{
- PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531),
+ PHY_ID_MATCH_EXACT(0x03a29441),
.name = "MediaTek MT7531 PHY",
.config_init = mt7531_phy_config_init,
/* Interrupts are handled by the switch, not the PHY
@@ -1310,30 +97,6 @@
.read_page = mtk_gephy_read_page,
.write_page = mtk_gephy_write_page,
},
-#ifdef CONFIG_MEDIATEK_GE_PHY_SOC
- {
- PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
- .name = "MediaTek MT7981 PHY",
- .probe = mt7981_phy_probe,
- .config_intr = genphy_no_config_intr,
- .handle_interrupt = genphy_no_ack_interrupt,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
- .read_page = mtk_gephy_read_page,
- .write_page = mtk_gephy_write_page,
- },
- {
- PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988),
- .name = "MediaTek MT7988 PHY",
- .probe = mt7988_phy_probe,
- .config_intr = genphy_no_config_intr,
- .handle_interrupt = genphy_no_ack_interrupt,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
- .read_page = mtk_gephy_read_page,
- .write_page = mtk_gephy_write_page,
- },
-#endif
};
module_phy_driver(mtk_gephy_driver);
@@ -1344,8 +107,6 @@
};
MODULE_DESCRIPTION("MediaTek Gigabit Ethernet PHY driver");
-MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
-MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
MODULE_AUTHOR("DENG, Qingfang <dqfext@gmail.com>");
MODULE_LICENSE("GPL");
diff --git a/target/linux/mediatek/mt7981/config-5.4 b/target/linux/mediatek/mt7981/config-5.4
index 68c3cae..003ecf5 100644
--- a/target/linux/mediatek/mt7981/config-5.4
+++ b/target/linux/mediatek/mt7981/config-5.4
@@ -253,7 +253,7 @@
CONFIG_MDIO_DEVICE=y
# CONFIG_MEDIATEK_2P5GE_PHY is not set
CONFIG_MEDIATEK_GE_PHY=y
-CONFIG_MEDIATEK_GE_PHY_SOC=y
+CONFIG_MEDIATEK_GE_SOC_PHY=y
CONFIG_MEDIATEK_MT6577_AUXADC=y
CONFIG_MEDIATEK_NETSYS_V2=y
# CONFIG_MEDIATEK_NETSYS_V3 is not set
diff --git a/target/linux/mediatek/mt7988/config-5.4 b/target/linux/mediatek/mt7988/config-5.4
index 4c7e962..e542a51 100644
--- a/target/linux/mediatek/mt7988/config-5.4
+++ b/target/linux/mediatek/mt7988/config-5.4
@@ -272,7 +272,7 @@
CONFIG_MDIO_I2C=y
CONFIG_MEDIATEK_2P5GE_PHY=y
CONFIG_MEDIATEK_GE_PHY=y
-CONFIG_MEDIATEK_GE_PHY_SOC=y
+CONFIG_MEDIATEK_GE_SOC_PHY=y
CONFIG_MEDIATEK_MT6577_AUXADC=y
# CONFIG_MEDIATEK_NETSYS_V2 is not set
CONFIG_MEDIATEK_NETSYS_V3=y
diff --git a/target/linux/mediatek/patches-5.4/0030-introduce_read_poll_timeout_macro.patch b/target/linux/mediatek/patches-5.4/0030-introduce_read_poll_timeout_macro.patch
deleted file mode 100644
index e227037..0000000
--- a/target/linux/mediatek/patches-5.4/0030-introduce_read_poll_timeout_macro.patch
+++ /dev/null
@@ -1,149 +0,0 @@
-diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
-index 35e15df..2c8860e 100644
---- a/include/linux/iopoll.h
-+++ b/include/linux/iopoll.h
-@@ -14,36 +14,41 @@
- #include <linux/io.h>
-
- /**
-- * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
-- * @op: accessor function (takes @addr as its only argument)
-- * @addr: Address to poll
-+ * read_poll_timeout - Periodically poll an address until a condition is
-+ * met or a timeout occurs
-+ * @op: accessor function (takes @args as its arguments)
- * @val: Variable to read the value into
- * @cond: Break condition (usually involving @val)
- * @sleep_us: Maximum time to sleep between reads in us (0
- * tight-loops). Should be less than ~20ms since usleep_range
- * is used (see Documentation/timers/timers-howto.rst).
- * @timeout_us: Timeout in us, 0 means never timeout
-+ * @sleep_before_read: if it is true, sleep @sleep_us before read.
-+ * @args: arguments for @op poll
- *
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
-- * case, the last read value at @addr is stored in @val. Must not
-+ * case, the last read value at @args is stored in @val. Must not
- * be called from atomic context if sleep_us or timeout_us are used.
- *
- * When available, you'll probably want to use one of the specialized
- * macros defined below rather than this macro directly.
- */
--#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \
-+#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \
-+ sleep_before_read, args...) \
- ({ \
- u64 __timeout_us = (timeout_us); \
- unsigned long __sleep_us = (sleep_us); \
- ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
- might_sleep_if((__sleep_us) != 0); \
-+ if (sleep_before_read && __sleep_us) \
-+ usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
- for (;;) { \
-- (val) = op(addr); \
-+ (val) = op(args); \
- if (cond) \
- break; \
- if (__timeout_us && \
- ktime_compare(ktime_get(), __timeout) > 0) { \
-- (val) = op(addr); \
-+ (val) = op(args); \
- break; \
- } \
- if (__sleep_us) \
-@@ -53,42 +58,87 @@
- })
-
- /**
-- * readx_poll_timeout_atomic - Periodically poll an address until a condition is met or a timeout occurs
-- * @op: accessor function (takes @addr as its only argument)
-- * @addr: Address to poll
-+ * read_poll_timeout_atomic - Periodically poll an address until a condition is
-+ * met or a timeout occurs
-+ * @op: accessor function (takes @args as its arguments)
- * @val: Variable to read the value into
- * @cond: Break condition (usually involving @val)
- * @delay_us: Time to udelay between reads in us (0 tight-loops). Should
- * be less than ~10us since udelay is used (see
- * Documentation/timers/timers-howto.rst).
- * @timeout_us: Timeout in us, 0 means never timeout
-+ * @delay_before_read: if it is true, delay @delay_us before read.
-+ * @args: arguments for @op poll
- *
- * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
-- * case, the last read value at @addr is stored in @val.
-+ * case, the last read value at @args is stored in @val.
- *
- * When available, you'll probably want to use one of the specialized
- * macros defined below rather than this macro directly.
- */
--#define readx_poll_timeout_atomic(op, addr, val, cond, delay_us, timeout_us) \
-+#define read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, \
-+ delay_before_read, args...) \
- ({ \
- u64 __timeout_us = (timeout_us); \
- unsigned long __delay_us = (delay_us); \
- ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
-+ if (delay_before_read && __delay_us) \
-+ udelay(__delay_us); \
- for (;;) { \
-- (val) = op(addr); \
-+ (val) = op(args); \
- if (cond) \
- break; \
- if (__timeout_us && \
- ktime_compare(ktime_get(), __timeout) > 0) { \
-- (val) = op(addr); \
-+ (val) = op(args); \
- break; \
- } \
- if (__delay_us) \
-- udelay(__delay_us); \
-+ udelay(__delay_us); \
- } \
- (cond) ? 0 : -ETIMEDOUT; \
- })
-
-+/**
-+ * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
-+ * @op: accessor function (takes @addr as its only argument)
-+ * @addr: Address to poll
-+ * @val: Variable to read the value into
-+ * @cond: Break condition (usually involving @val)
-+ * @sleep_us: Maximum time to sleep between reads in us (0
-+ * tight-loops). Should be less than ~20ms since usleep_range
-+ * is used (see Documentation/timers/timers-howto.rst).
-+ * @timeout_us: Timeout in us, 0 means never timeout
-+ *
-+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
-+ * case, the last read value at @addr is stored in @val. Must not
-+ * be called from atomic context if sleep_us or timeout_us are used.
-+ *
-+ * When available, you'll probably want to use one of the specialized
-+ * macros defined below rather than this macro directly.
-+ */
-+#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \
-+ read_poll_timeout(op, val, cond, sleep_us, timeout_us, false, addr)
-+
-+/**
-+ * readx_poll_timeout_atomic - Periodically poll an address until a condition is met or a timeout occurs
-+ * @op: accessor function (takes @addr as its only argument)
-+ * @addr: Address to poll
-+ * @val: Variable to read the value into
-+ * @cond: Break condition (usually involving @val)
-+ * @delay_us: Time to udelay between reads in us (0 tight-loops). Should
-+ * be less than ~10us since udelay is used (see
-+ * Documentation/timers/timers-howto.rst).
-+ * @timeout_us: Timeout in us, 0 means never timeout
-+ *
-+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
-+ * case, the last read value at @addr is stored in @val.
-+ *
-+ * When available, you'll probably want to use one of the specialized
-+ * macros defined below rather than this macro directly.
-+ */
-+#define readx_poll_timeout_atomic(op, addr, val, cond, delay_us, timeout_us) \
-+ read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, false, addr)
-
- #define readb_poll_timeout(addr, val, cond, delay_us, timeout_us) \
- readx_poll_timeout(readb, addr, val, cond, delay_us, timeout_us)
diff --git a/target/linux/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch b/target/linux/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch
index efbec08..161e90f 100644
--- a/target/linux/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch
+++ b/target/linux/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch
@@ -1,8 +1,8 @@
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
-@@ -522,6 +522,11 @@ config MESON_GXL_PHY
- ---help---
- Currently has a driver for the Amlogic Meson GXL Internal PHY
+@@ -431,6 +431,11 @@ config MEDIATEK_GE_SOC_PHY
+ present in the SoCs efuse and will dynamically calibrate VCM
+ (common-mode voltage) during startup.
+config MEDIATEK_2P5GE_PHY
+ tristate "MediaTek 2.5Gb Ethernet PHYs"
@@ -14,10 +14,10 @@
---help---
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
-@@ -95,6 +95,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c
- obj-$(CONFIG_LXT_PHY) += lxt.o
- obj-$(CONFIG_MARVELL_PHY) += marvell.o
+@@ -79,6 +79,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o
+ obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
+ obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o
+obj-$(CONFIG_MEDIATEK_2P5GE_PHY)+= mediatek-2p5ge.o
obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
diff --git a/target/linux/mediatek/patches-5.4/746-mxl-gpy-phy-support.patch b/target/linux/mediatek/patches-5.4/746-mxl-gpy-phy-support.patch
index 9f2ecc4..5ff2798 100644
--- a/target/linux/mediatek/patches-5.4/746-mxl-gpy-phy-support.patch
+++ b/target/linux/mediatek/patches-5.4/746-mxl-gpy-phy-support.patch
@@ -20,9 +20,9 @@
obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o
+obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o
+ obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
+ obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o
obj-$(CONFIG_MEDIATEK_2P5GE_PHY)+= mediatek-2p5ge.o
- obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
- obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
--- /dev/null
+++ b/drivers/net/phy/mxl-gpy.c
@@ -0,0 +1,738 @@
@@ -764,32 +764,3 @@
+MODULE_DESCRIPTION("Maxlinear Ethernet GPY Driver");
+MODULE_AUTHOR("Xu Liang");
+MODULE_LICENSE("GPL");
---- a/include/linux/phy.h
-+++ b/include/linux/phy.h
-@@ -21,6 +21,7 @@
- #include <linux/timer.h>
- #include <linux/workqueue.h>
- #include <linux/mod_devicetable.h>
-+#include <linux/iopoll.h>
-
- #include <linux/atomic.h>
-
-@@ -711,6 +712,18 @@ static inline int phy_read(struct phy_de
- return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, regnum);
- }
-
-+#define phy_read_poll_timeout(phydev, regnum, val, cond, sleep_us, \
-+ timeout_us, sleep_before_read) \
-+({ \
-+ int __ret = read_poll_timeout(phy_read, val, (cond) || val < 0, \
-+ sleep_us, timeout_us, sleep_before_read, phydev, regnum); \
-+ if (val < 0) \
-+ __ret = val; \
-+ if (__ret) \
-+ phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \
-+ __ret; \
-+})
-+
- /**
- * __phy_read - convenience function for reading a given PHY register
- * @phydev: the phy_device struct