From nobody Tue May 26 04:51:45 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A132B2147E5; Tue, 12 May 2026 04:33:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560431; cv=none; b=JCKcZ7HIjuzhacTZk6lVdfy2snLcA//6wwQa5WkEQ54Tr9OiXGI3IlnaEZJfC/sAX17A3Y4eE8SdQUv0KvFeDEBTgbE1Xkt0QaHtUmuNfPsRD84yfSk6e6QFwjvdtl3ansgfHdu1gjNH5M6i6I2/zUu058iq7MfULtcxbgMgUWU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560431; c=relaxed/simple; bh=FTb3G2vLYxM7tcE6j6MbZT2m19/M+dWLgv+cqwFrwzQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uORG9VJG09wkQXDta3ZNENrGf+xqEefJwF+MbinWbxCuexxH2d5Loe327TGVftiDn1FYFaJT3fStfAZQSygnG4WPBJISp0VsRtsz1/5Rh0XW4XCXIlM4skXpXqv4TOtVGlUz+mjwHLe25eAYrKOUAtAM4Rorpk/aQdAI8j+yKQM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=JeVAT78n; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="JeVAT78n" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1778560427; bh=FTb3G2vLYxM7tcE6j6MbZT2m19/M+dWLgv+cqwFrwzQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JeVAT78nzlYc/Aa1+9p/QVL7ruR5Nilj03GC1XUPGzEuwzBZZAqRd5R48hcC7GZDY 2rP0lukEu+qCZcBDEATs0KA3R9KJUX25CIhVl93ajt08/yrbTlCiY1WZ46SRMcvXf5 MKRXnDvBN5IByfGdcIRIycU+LUHGs+DNJJUbjoXsrXSJGQEKB+uxwstNVXUAtw8abV JMt1oNxCMBlWlvzFl9XePXe1etOvvEaowwcTaB6V714Q0jG+/GM5j5mIpwjEntnyEY 60NZRisGwrdZgGfYkJusFsbsVjX2GJt+YKG92Fl1nvXGAlOhFIgcHbsUiwBtWvV5q9 4FdxY7Mzscsuw== Received: from yukiji.home (unknown [100.64.0.131]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: laeyraud) by bali.collaboradmins.com (Postfix) with ESMTPSA id CDF2817E1513; Tue, 12 May 2026 06:33:46 +0200 (CEST) From: Louis-Alexis Eyraud Date: Tue, 12 May 2026 06:33:18 +0200 Subject: [PATCH net-next v3 1/6] dt-bindings: net: Add support for Airoha AN8801/R GbE PHY Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260512-add-airoha-an8801-support-v3-1-1edb34e363ae@collabora.com> References: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> In-Reply-To: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , AngeloGioacchino Del Regno , Andrew Lunn , Heiner Kallweit , Russell King Cc: kevin-kw.huang@airoha.com, macpaul.lin@mediatek.com, matthias.bgg@gmail.com, kernel@collabora.com, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Louis-Alexis Eyraud X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778560425; l=3167; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=XMccUmrUacqO4GAsqwSfQksObded8gKYNJE+Y06QrTE=; b=NSOOV8lIX8V4jVnh0iqlH6eVarUNgt/lyaNS7auNTKBaNbOmkbNcjLbjHwP96kHSJgIB23BVo RcvpBwQZWLWBwpArq2jO5u+mhnz9QHeB+KK9g4r1ywjhofJxIfL6n9J X-Developer-Key: i=louisalexis.eyraud@collabora.com; a=ed25519; pk=CHFBDB2Kqh4EHc6JIqFn69GhxJJAzc0Zr4e8QxtumuM= From: AngeloGioacchino Del Regno Add a new binding to support the Airoha AN8801R Series Gigabit Ethernet PHY. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Rob Herring (Arm) Signed-off-by: Louis-Alexis Eyraud --- .../devicetree/bindings/net/airoha,an8801.yaml | 85 ++++++++++++++++++= ++++ 1 file changed, 85 insertions(+) diff --git a/Documentation/devicetree/bindings/net/airoha,an8801.yaml b/Doc= umentation/devicetree/bindings/net/airoha,an8801.yaml new file mode 100644 index 000000000000..b90b21b55053 --- /dev/null +++ b/Documentation/devicetree/bindings/net/airoha,an8801.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/airoha,an8801.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Airoha AN8801R Series PHY + +maintainers: + - AngeloGioacchino Del Regno + +description: + The Airoha AN8801R is a low power single-port Ethernet PHY Transceiver + with Single-port serdes interface for 1000Base-X/RGMII; this chip is + compliant with 10Base-T, 100Base-TX and 1000Base-T IEEE 802.3(u,ab) + and supports Energy Efficient Ethernet (802.3az), Full Duplex Control + Flow (802.3x), auto-negotiation, crossover detect and autocorrection, + Wake-on-LAN with Magic Packet, and Jumbo Frame up to 9 Kilobytes. + This PHY also supports up to three user-configurable LEDs, which are + usually used for LAN Activity, 100M, 1000M indication. + +allOf: + - $ref: ethernet-phy.yaml# + +properties: + compatible: + enum: + - ethernet-phy-idc0ff.0421 + + reg: + maxItems: 1 + + leds: true + + wakeup-source: + $ref: /schemas/types.yaml#/definitions/flag + description: + Enable Wake-on-LAN support + +required: + - reg + +unevaluatedProperties: false + +examples: + - | + #include + + mdio { + #address-cells =3D <1>; + #size-cells =3D <0>; + + ethernet-phy@0 { + compatible =3D "ethernet-phy-idc0ff.0421"; + reg =3D <0>; + + leds { + #address-cells =3D <1>; + #size-cells =3D <0>; + + led@0 { + reg =3D <0>; + color =3D ; + function =3D LED_FUNCTION_LAN; + default-state =3D "keep"; + }; + + led@1 { + reg =3D <1>; + color =3D ; + function =3D LED_FUNCTION_LAN; + function-enumerator =3D <1>; + default-state =3D "keep"; + }; + + led@2 { + reg =3D <2>; + color =3D ; + function =3D LED_FUNCTION_LAN; + function-enumerator =3D <2>; + default-state =3D "keep"; + }; + }; + }; + }; --=20 2.54.0 From nobody Tue May 26 04:51:45 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BFA5B3101B6; Tue, 12 May 2026 04:33:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560432; cv=none; b=iyELXkKN9A7VNri2VdLCBNdIhyRV9/lYbPrNoq+AFpJx0eR8WRkegupBPQggLG1tesGJlTtN+OSne++DN9KeiwgAb+tB9+aMLdKtmD3XjZjPXM/iI9jWGnSDUB3c6MRqZ/Wd4HXaup3jdxUoMAS34yhvyk7+U1qecyf1x248dbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560432; c=relaxed/simple; bh=Pz9uOkS7hxN04dyA0P80AqFBqwyETBvDpAxCbEq3u/Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MKWd50SXpXsCAw5YBEe8i5KQD3gl71kBjoZlIhnhGc/7XI3+TUU1W+qH+YfZQh0MTg6LQCDRQdC/G0m4CU5lfewDNaAM87LmYK00Nd8erc1QWhKxltg4hu3jxXkChNS/wlCKOH2IAKWfjAtwvGAxFPwWQp5oIenQRjMyEEOSQb8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=DWArqCxl; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="DWArqCxl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1778560429; bh=Pz9uOkS7hxN04dyA0P80AqFBqwyETBvDpAxCbEq3u/Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DWArqCxlBnReaXTHLF6gFcYAckZtvtzB0Pl3uQ1MqkLAwsV2enZq47s7fOVJ6x/cz V6XABbHmvSOx9ET6/kYgBHvPc0I/4ZOo6GVvn1M5vGArU/787LmqWRDaiM2gNiVn+c ED2ewZD91J0boAbzjaqNwZAPy/iH1toIIcNQ4nzIID0ZXKuU//Bj0EyDT+HawCjA3d jMwuk8CsW3H21QiqzPrMkYrvtzVlKy35oy5x2rrkBl8SlQ5KGg23YiE+8ny/vtwai0 UVN6fpW73Q8FgPK5jJFqA9axegfeVm5Vre/u7phV+eA2wCk6cGNO8xuqFVzF+X/yTN 2sRfN2Xf1SlcQ== Received: from yukiji.home (unknown [100.64.0.131]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: laeyraud) by bali.collaboradmins.com (Postfix) with ESMTPSA id 14DEF17E15A7; Tue, 12 May 2026 06:33:48 +0200 (CEST) From: Louis-Alexis Eyraud Date: Tue, 12 May 2026 06:33:19 +0200 Subject: [PATCH net-next v3 2/6] net: phy: Add Airoha phy library for shared code Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260512-add-airoha-an8801-support-v3-2-1edb34e363ae@collabora.com> References: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> In-Reply-To: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , AngeloGioacchino Del Regno , Andrew Lunn , Heiner Kallweit , Russell King Cc: kevin-kw.huang@airoha.com, macpaul.lin@mediatek.com, matthias.bgg@gmail.com, kernel@collabora.com, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Louis-Alexis Eyraud X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778560425; l=4580; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=Pz9uOkS7hxN04dyA0P80AqFBqwyETBvDpAxCbEq3u/Y=; b=HMJdv3XoKyO1NQEQASUBktCBL+ScvHDLgSCipoEYCTUmgL5vCMupM48LkM+NZUTS0bmtMAmHd YAOm8nEDK4ODBL+5o76Jw70C4kE7JYjLELNDs0GXnBHF2HLWxK1+1ZG X-Developer-Key: i=louisalexis.eyraud@collabora.com; a=ed25519; pk=CHFBDB2Kqh4EHc6JIqFn69GhxJJAzc0Zr4e8QxtumuM= In preparation of Airoha AN8801R PHY support, split out the interface functions that will be common between the already present air_en8811h driver and the new one, and put them into a new library named air_phy_lib. Signed-off-by: Louis-Alexis Eyraud Reviewed-by: Andrew Lunn --- drivers/net/phy/Kconfig | 6 ++++++ drivers/net/phy/Makefile | 1 + drivers/net/phy/air_en8811h.c | 13 ++----------- drivers/net/phy/air_phy_lib.c | 32 ++++++++++++++++++++++++++++++++ drivers/net/phy/air_phy_lib.h | 16 ++++++++++++++++ 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index b5ee338b620d..b6b1cde7e51f 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -92,10 +92,16 @@ config AS21XXX_PHY =20 config AIR_EN8811H_PHY tristate "Airoha EN8811H 2.5 Gigabit PHY" + select AIR_NET_PHYLIB select PHY_COMMON_PROPS help Currently supports the Airoha EN8811H PHY. =20 +config AIR_NET_PHYLIB + tristate + help + Airoha Ethernet PHY common library + config AMD_PHY tristate "AMD and Altima PHYs" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 05e4878af27a..7cf1fa9e12cb 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -30,6 +30,7 @@ obj-y +=3D $(sfp-obj-y) $(sfp-obj-m) obj-$(CONFIG_ADIN_PHY) +=3D adin.o obj-$(CONFIG_ADIN1100_PHY) +=3D adin1100.o obj-$(CONFIG_AIR_EN8811H_PHY) +=3D air_en8811h.o +obj-$(CONFIG_AIR_NET_PHYLIB) +=3D air_phy_lib.o obj-$(CONFIG_AMD_PHY) +=3D amd.o obj-$(CONFIG_AMCC_QT2025_PHY) +=3D qt2025.o obj-$(CONFIG_AQUANTIA_PHY) +=3D aquantia/ diff --git a/drivers/net/phy/air_en8811h.c b/drivers/net/phy/air_en8811h.c index 29ae73e65caa..be7c3426182a 100644 --- a/drivers/net/phy/air_en8811h.c +++ b/drivers/net/phy/air_en8811h.c @@ -21,6 +21,8 @@ #include #include =20 +#include "air_phy_lib.h" + #define EN8811H_PHY_ID 0x03a2a411 #define AN8811HB_PHY_ID 0xc0ff04a0 =20 @@ -40,7 +42,6 @@ #define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8 #define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc =20 -#define AIR_EXT_PAGE_ACCESS 0x1f #define AIR_PHY_PAGE_STANDARD 0x0000 #define AIR_PHY_PAGE_EXTENDED_4 0x0004 =20 @@ -244,16 +245,6 @@ static const unsigned long en8811h_led_trig =3D BIT(TR= IGGER_NETDEV_FULL_DUPLEX) | BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX); =20 -static int air_phy_read_page(struct phy_device *phydev) -{ - return __phy_read(phydev, AIR_EXT_PAGE_ACCESS); -} - -static int air_phy_write_page(struct phy_device *phydev, int page) -{ - return __phy_write(phydev, AIR_EXT_PAGE_ACCESS, page); -} - static int __air_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address, u32 pbus_data) { diff --git a/drivers/net/phy/air_phy_lib.c b/drivers/net/phy/air_phy_lib.c new file mode 100644 index 000000000000..8ef5af4becf0 --- /dev/null +++ b/drivers/net/phy/air_phy_lib.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Airoha Ethernet PHY common library + * + * Copyright (C) 2026 Airoha Technology Corp. + * Copyright (C) 2026 Collabora Ltd. + * Louis-Alexis Eyraud + */ + +#include +#include +#include + +#include "air_phy_lib.h" + +#define AIR_EXT_PAGE_ACCESS 0x1f + +int air_phy_read_page(struct phy_device *phydev) +{ + return __phy_read(phydev, AIR_EXT_PAGE_ACCESS); +} +EXPORT_SYMBOL_GPL(air_phy_read_page); + +int air_phy_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, AIR_EXT_PAGE_ACCESS, page); +} +EXPORT_SYMBOL_GPL(air_phy_write_page); + +MODULE_DESCRIPTION("Airoha PHY Library"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Louis-Alexis Eyraud"); diff --git a/drivers/net/phy/air_phy_lib.h b/drivers/net/phy/air_phy_lib.h new file mode 100644 index 000000000000..79367e8e5907 --- /dev/null +++ b/drivers/net/phy/air_phy_lib.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2026 Airoha Technology Corp. + * Copyright (C) 2026 Collabora Ltd. + * Louis-Alexis Eyraud + */ + +#ifndef __AIR_PHY_LIB_H +#define __AIR_PHY_LIB_H + +#include + +int air_phy_read_page(struct phy_device *phydev); +int air_phy_write_page(struct phy_device *phydev, int page); + +#endif /* __AIR_PHY_LIB_H */ --=20 2.54.0 From nobody Tue May 26 04:51:45 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EE328332EBC; Tue, 12 May 2026 04:33:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560434; cv=none; b=WuzD6HzrE/NV48NP/HDeowoLd6gnMec8l/ShrvyscRkUky47yK3/+bIgspEYKw/8e5xq7rLmttPsRl2njFq4jDyM6OhuVzsn612hR+kCSzsA/I62kx0m9Wvd1/0cyCgvLvaamAlDzezdNZGQ3DNSpvdUSAcg9AwCSxLpJMUi4Oc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560434; c=relaxed/simple; bh=ho2cnEg6B+UwTx0f+U/tb9gFxGOxNoMFA1nTH+F9BnM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=b7sAWrAhymwoS+UmoMjzbVgmcpfhvIm2FDrTOlcI1UgYlbORlh7KqMh8DMzKWfC+a9Ya56J/zncXtO5iSNOROeOZN3Lcvlfg56XpsSOPIzIOZCUC29HBeR3RG2+IuvEy5C/BpRckjrmsw/4CLFKNvfZzKSWQhVqwYvWJDm7QcgQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=HqQ7JXns; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="HqQ7JXns" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1778560430; bh=ho2cnEg6B+UwTx0f+U/tb9gFxGOxNoMFA1nTH+F9BnM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=HqQ7JXns7uYaL2MAIFjSB+ZY8Uvs/Yh2LZztY8WC5V8rMgtAu24nf89dbvw3rHswY lNToY40t9kATiFTkKK1h1IsekT+mONMrNpYxyh/bls+2HO3idiaNa3Cpk/4olRImdn KXoyH+e2p1PdVqGuC03jKijchtRjkDRW100aifFmt4pRMnxiPEcFAEjjYPvG4GKfAb 1Eqb3KI2oZWUECVAJOE4jpwoqwjb316Gi3BFNTCLloXt8cuDJRU0IZl+QhvbA1lE4+ 5bs0kv2Xgpo/F3PYMDGM6S7cwCHDKBZ8ivW3YadMOpOcP+khpP6tM9MjeSgvGhfzKn HnY6yL/dTwA4w== Received: from yukiji.home (unknown [100.64.0.131]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: laeyraud) by bali.collaboradmins.com (Postfix) with ESMTPSA id 4FF3617E15D7; Tue, 12 May 2026 06:33:49 +0200 (CEST) From: Louis-Alexis Eyraud Date: Tue, 12 May 2026 06:33:20 +0200 Subject: [PATCH net-next v3 3/6] net: phy: air_phy_lib: Factorize BuckPBus register accessors Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260512-add-airoha-an8801-support-v3-3-1edb34e363ae@collabora.com> References: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> In-Reply-To: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , AngeloGioacchino Del Regno , Andrew Lunn , Heiner Kallweit , Russell King Cc: kevin-kw.huang@airoha.com, macpaul.lin@mediatek.com, matthias.bgg@gmail.com, kernel@collabora.com, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Louis-Alexis Eyraud X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778560425; l=12695; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=ho2cnEg6B+UwTx0f+U/tb9gFxGOxNoMFA1nTH+F9BnM=; b=T4mTr5cm0RhLyCMx4Pd0vi3olH6CC+3EqBgTUKPuYI1LP5s5qDrEkwM9hH5vkoDqEdf2S49KX zYtk9YcqelcBWdu3S7tdZqGU/gjPu/WGQH2yrxQDRNrcVqdVgXsZW88 X-Developer-Key: i=louisalexis.eyraud@collabora.com; a=ed25519; pk=CHFBDB2Kqh4EHc6JIqFn69GhxJJAzc0Zr4e8QxtumuM= In preparation of Airoha AN8801R PHY support, move the BuckPBus register accessors and definitions, present in air_en8811h driver, into the Airoha PHY shared code (air_phy_lib), so they will be usable by the new driver without duplicating them. Signed-off-by: Louis-Alexis Eyraud Reviewed-by: Andrew Lunn --- drivers/net/phy/air_en8811h.c | 193 --------------------------------------= ---- drivers/net/phy/air_phy_lib.c | 180 +++++++++++++++++++++++++++++++++++++++ drivers/net/phy/air_phy_lib.h | 23 +++++ 3 files changed, 203 insertions(+), 193 deletions(-) diff --git a/drivers/net/phy/air_en8811h.c b/drivers/net/phy/air_en8811h.c index be7c3426182a..2498bd3f7993 100644 --- a/drivers/net/phy/air_en8811h.c +++ b/drivers/net/phy/air_en8811h.c @@ -42,22 +42,6 @@ #define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8 #define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc =20 -#define AIR_PHY_PAGE_STANDARD 0x0000 -#define AIR_PHY_PAGE_EXTENDED_4 0x0004 - -/* MII Registers Page 4*/ -#define AIR_BPBUS_MODE 0x10 -#define AIR_BPBUS_MODE_ADDR_FIXED 0x0000 -#define AIR_BPBUS_MODE_ADDR_INCR BIT(15) -#define AIR_BPBUS_WR_ADDR_HIGH 0x11 -#define AIR_BPBUS_WR_ADDR_LOW 0x12 -#define AIR_BPBUS_WR_DATA_HIGH 0x13 -#define AIR_BPBUS_WR_DATA_LOW 0x14 -#define AIR_BPBUS_RD_ADDR_HIGH 0x15 -#define AIR_BPBUS_RD_ADDR_LOW 0x16 -#define AIR_BPBUS_RD_DATA_HIGH 0x17 -#define AIR_BPBUS_RD_DATA_LOW 0x18 - /* Registers on MDIO_MMD_VEND1 */ #define EN8811H_PHY_FW_STATUS 0x8009 #define EN8811H_PHY_READY 0x02 @@ -245,183 +229,6 @@ static const unsigned long en8811h_led_trig =3D BIT(T= RIGGER_NETDEV_FULL_DUPLEX) | BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX); =20 -static int __air_buckpbus_reg_write(struct phy_device *phydev, - u32 pbus_address, u32 pbus_data) -{ - int ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH, - upper_16_bits(pbus_address)); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW, - lower_16_bits(pbus_address)); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH, - upper_16_bits(pbus_data)); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW, - lower_16_bits(pbus_data)); - if (ret < 0) - return ret; - - return 0; -} - -static int air_buckpbus_reg_write(struct phy_device *phydev, - u32 pbus_address, u32 pbus_data) -{ - int saved_page; - int ret =3D 0; - - saved_page =3D phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); - - if (saved_page >=3D 0) { - ret =3D __air_buckpbus_reg_write(phydev, pbus_address, - pbus_data); - if (ret < 0) - phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, - pbus_address, ret); - } - - return phy_restore_page(phydev, saved_page, ret); -} - -static int __air_buckpbus_reg_read(struct phy_device *phydev, - u32 pbus_address, u32 *pbus_data) -{ - int pbus_data_low, pbus_data_high; - int ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH, - upper_16_bits(pbus_address)); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW, - lower_16_bits(pbus_address)); - if (ret < 0) - return ret; - - pbus_data_high =3D __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH); - if (pbus_data_high < 0) - return pbus_data_high; - - pbus_data_low =3D __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW); - if (pbus_data_low < 0) - return pbus_data_low; - - *pbus_data =3D pbus_data_low | (pbus_data_high << 16); - return 0; -} - -static int air_buckpbus_reg_read(struct phy_device *phydev, - u32 pbus_address, u32 *pbus_data) -{ - int saved_page; - int ret =3D 0; - - saved_page =3D phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); - - if (saved_page >=3D 0) { - ret =3D __air_buckpbus_reg_read(phydev, pbus_address, pbus_data); - if (ret < 0) - phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, - pbus_address, ret); - } - - return phy_restore_page(phydev, saved_page, ret); -} - -static int __air_buckpbus_reg_modify(struct phy_device *phydev, - u32 pbus_address, u32 mask, u32 set) -{ - int pbus_data_low, pbus_data_high; - u32 pbus_data_old, pbus_data_new; - int ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH, - upper_16_bits(pbus_address)); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW, - lower_16_bits(pbus_address)); - if (ret < 0) - return ret; - - pbus_data_high =3D __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH); - if (pbus_data_high < 0) - return pbus_data_high; - - pbus_data_low =3D __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW); - if (pbus_data_low < 0) - return pbus_data_low; - - pbus_data_old =3D pbus_data_low | (pbus_data_high << 16); - pbus_data_new =3D (pbus_data_old & ~mask) | set; - if (pbus_data_new =3D=3D pbus_data_old) - return 0; - - ret =3D __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH, - upper_16_bits(pbus_address)); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW, - lower_16_bits(pbus_address)); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH, - upper_16_bits(pbus_data_new)); - if (ret < 0) - return ret; - - ret =3D __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW, - lower_16_bits(pbus_data_new)); - if (ret < 0) - return ret; - - return 0; -} - -static int air_buckpbus_reg_modify(struct phy_device *phydev, - u32 pbus_address, u32 mask, u32 set) -{ - int saved_page; - int ret =3D 0; - - saved_page =3D phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); - - if (saved_page >=3D 0) { - ret =3D __air_buckpbus_reg_modify(phydev, pbus_address, mask, - set); - if (ret < 0) - phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, - pbus_address, ret); - } - - return phy_restore_page(phydev, saved_page, ret); -} - static int __air_write_buf(struct phy_device *phydev, u32 address, const struct firmware *fw) { diff --git a/drivers/net/phy/air_phy_lib.c b/drivers/net/phy/air_phy_lib.c index 8ef5af4becf0..687c59197b16 100644 --- a/drivers/net/phy/air_phy_lib.c +++ b/drivers/net/phy/air_phy_lib.c @@ -15,6 +15,186 @@ =20 #define AIR_EXT_PAGE_ACCESS 0x1f =20 +static int __air_buckpbus_reg_read(struct phy_device *phydev, + u32 pbus_address, u32 *pbus_data) +{ + int pbus_data_low, pbus_data_high; + int ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH, + upper_16_bits(pbus_address)); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW, + lower_16_bits(pbus_address)); + if (ret < 0) + return ret; + + pbus_data_high =3D __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH); + if (pbus_data_high < 0) + return pbus_data_high; + + pbus_data_low =3D __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW); + if (pbus_data_low < 0) + return pbus_data_low; + + *pbus_data =3D pbus_data_low | (pbus_data_high << 16); + return 0; +} + +static int __air_buckpbus_reg_write(struct phy_device *phydev, + u32 pbus_address, u32 pbus_data) +{ + int ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH, + upper_16_bits(pbus_address)); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW, + lower_16_bits(pbus_address)); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH, + upper_16_bits(pbus_data)); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW, + lower_16_bits(pbus_data)); + if (ret < 0) + return ret; + + return 0; +} + +static int __air_buckpbus_reg_modify(struct phy_device *phydev, + u32 pbus_address, u32 mask, u32 set) +{ + int pbus_data_low, pbus_data_high; + u32 pbus_data_old, pbus_data_new; + int ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH, + upper_16_bits(pbus_address)); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW, + lower_16_bits(pbus_address)); + if (ret < 0) + return ret; + + pbus_data_high =3D __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH); + if (pbus_data_high < 0) + return pbus_data_high; + + pbus_data_low =3D __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW); + if (pbus_data_low < 0) + return pbus_data_low; + + pbus_data_old =3D pbus_data_low | (pbus_data_high << 16); + pbus_data_new =3D (pbus_data_old & ~mask) | set; + if (pbus_data_new =3D=3D pbus_data_old) + return 0; + + ret =3D __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH, + upper_16_bits(pbus_address)); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW, + lower_16_bits(pbus_address)); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH, + upper_16_bits(pbus_data_new)); + if (ret < 0) + return ret; + + ret =3D __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW, + lower_16_bits(pbus_data_new)); + if (ret < 0) + return ret; + + return 0; +} + +int air_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address, + u32 *pbus_data) +{ + int saved_page; + int ret =3D 0; + + saved_page =3D phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); + + if (saved_page >=3D 0) { + ret =3D __air_buckpbus_reg_read(phydev, pbus_address, pbus_data); + if (ret < 0) + phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, + pbus_address, ret); + } + + return phy_restore_page(phydev, saved_page, ret); +} +EXPORT_SYMBOL_GPL(air_buckpbus_reg_read); + +int air_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address, + u32 pbus_data) +{ + int saved_page; + int ret =3D 0; + + saved_page =3D phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); + + if (saved_page >=3D 0) { + ret =3D __air_buckpbus_reg_write(phydev, pbus_address, + pbus_data); + if (ret < 0) + phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, + pbus_address, ret); + } + + return phy_restore_page(phydev, saved_page, ret); +} +EXPORT_SYMBOL_GPL(air_buckpbus_reg_write); + +int air_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_address, + u32 mask, u32 set) +{ + int saved_page; + int ret =3D 0; + + saved_page =3D phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); + + if (saved_page >=3D 0) { + ret =3D __air_buckpbus_reg_modify(phydev, pbus_address, mask, + set); + if (ret < 0) + phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, + pbus_address, ret); + } + + return phy_restore_page(phydev, saved_page, ret); +} +EXPORT_SYMBOL_GPL(air_buckpbus_reg_modify); + int air_phy_read_page(struct phy_device *phydev) { return __phy_read(phydev, AIR_EXT_PAGE_ACCESS); diff --git a/drivers/net/phy/air_phy_lib.h b/drivers/net/phy/air_phy_lib.h index 79367e8e5907..b637f3e0f2d5 100644 --- a/drivers/net/phy/air_phy_lib.h +++ b/drivers/net/phy/air_phy_lib.h @@ -10,6 +10,29 @@ =20 #include =20 +#define AIR_PHY_PAGE_STANDARD 0x0000 +#define AIR_PHY_PAGE_EXTENDED_1 0x0001 +#define AIR_PHY_PAGE_EXTENDED_4 0x0004 + +/* MII Registers Page 4*/ +#define AIR_BPBUS_MODE 0x10 +#define AIR_BPBUS_MODE_ADDR_FIXED 0x0000 +#define AIR_BPBUS_MODE_ADDR_INCR BIT(15) +#define AIR_BPBUS_WR_ADDR_HIGH 0x11 +#define AIR_BPBUS_WR_ADDR_LOW 0x12 +#define AIR_BPBUS_WR_DATA_HIGH 0x13 +#define AIR_BPBUS_WR_DATA_LOW 0x14 +#define AIR_BPBUS_RD_ADDR_HIGH 0x15 +#define AIR_BPBUS_RD_ADDR_LOW 0x16 +#define AIR_BPBUS_RD_DATA_HIGH 0x17 +#define AIR_BPBUS_RD_DATA_LOW 0x18 + +int air_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_address, + u32 mask, u32 set); +int air_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address, + u32 *pbus_data); +int air_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address, + u32 pbus_data); int air_phy_read_page(struct phy_device *phydev); int air_phy_write_page(struct phy_device *phydev, int page); =20 --=20 2.54.0 From nobody Tue May 26 04:51:45 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4AF5133AD8C; Tue, 12 May 2026 04:33:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560435; cv=none; b=QLWz1NBdG1cvplpGY+Nx1Gw01k5wY9zvhzIDxF43K8i6XFUGGxgOSp3NpN8S4rXLGVUK9D0j6hvqtU/q1UW41A2opLPP4p/2/1SrEICZL4z2PmgsrXDHDMyCGbCx1E1zuKweaj3oCen0ZKDpEY11hhdUSDBMNVU08OD0nPnfE58= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560435; c=relaxed/simple; bh=a59kRVQiR8XH63n+a6PWRw2wkz0pqXohRFcy4+WfMmI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GXd2bfqYh2shj74523tEn7+VO7sXIqK875VryerkF6Zu7KbXCH9wgPaPfhjkq5Me9fkExyGhqZWilhR6o+KdljSzhyEqTP9/POCLMSoT92g8y414isJO41UV/NTjMgI6QYcQrCbZtLSE/wTpr3Qblesm/l76Ab6ppaTcdfgBqp4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=b/AiPDwz; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="b/AiPDwz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1778560431; bh=a59kRVQiR8XH63n+a6PWRw2wkz0pqXohRFcy4+WfMmI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=b/AiPDwz/H8nhUEcZUFOUKdq9VoDHlyM1RJ960APHAJ2wte21R6dqQiK5l8WTNOIx BAGI+zNQGU3A3ox0R7WYmciLud1rxmAYFcHfY++hI8wlDK0FJVMmC5GNEtmfBnxh2X hu/FyNA8HXiwu6pdX7zX2oo0rcmX8YKC/8jbtRNAAYb2ENrzT2oa4oa8NpjVTPPwO4 DoCNzQFQUVPSNEq1ssGScUjalVcK3rm7hJHXJvY5kiOoXiOCNvM7nCRiKsiR7QfMxL l8y6jpNUF9u76bQcuGIXlgVEtydX3+fF70InxWiNOhl8098oENr9Wgo0a8oQmFleNu 5vGNIca4O2Y0Q== Received: from yukiji.home (unknown [100.64.0.131]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: laeyraud) by bali.collaboradmins.com (Postfix) with ESMTPSA id 8857817E15E3; Tue, 12 May 2026 06:33:50 +0200 (CEST) From: Louis-Alexis Eyraud Date: Tue, 12 May 2026 06:33:21 +0200 Subject: [PATCH net-next v3 4/6] net: phy: Rename Airoha common BuckPBus register accessors Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260512-add-airoha-an8801-support-v3-4-1edb34e363ae@collabora.com> References: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> In-Reply-To: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , AngeloGioacchino Del Regno , Andrew Lunn , Heiner Kallweit , Russell King Cc: kevin-kw.huang@airoha.com, macpaul.lin@mediatek.com, matthias.bgg@gmail.com, kernel@collabora.com, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Louis-Alexis Eyraud X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778560425; l=13313; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=a59kRVQiR8XH63n+a6PWRw2wkz0pqXohRFcy4+WfMmI=; b=eHuw3edwJpGLASeuGugjuJjL2mAfLlfZKF/KzuF3jvv/dOEvl9I525KCrFvVkVsPdloAmc1yy iZjb1qbL0YeBIwoRdhrQqSFbZTV8Xqz7x1/AetmRVVkH42vNSwdRpvr X-Developer-Key: i=louisalexis.eyraud@collabora.com; a=ed25519; pk=CHFBDB2Kqh4EHc6JIqFn69GhxJJAzc0Zr4e8QxtumuM= Rename the BuckPBus register accessors functions present in air_phy_lib and their calls in air_en8811h driver, so all exported functions start with the same prefix. Signed-off-by: Louis-Alexis Eyraud Reviewed-by: Andrew Lunn --- drivers/net/phy/air_en8811h.c | 110 +++++++++++++++++++++-----------------= ---- drivers/net/phy/air_phy_lib.c | 18 +++---- drivers/net/phy/air_phy_lib.h | 12 ++--- 3 files changed, 71 insertions(+), 69 deletions(-) diff --git a/drivers/net/phy/air_en8811h.c b/drivers/net/phy/air_en8811h.c index 2498bd3f7993..a42898ae4135 100644 --- a/drivers/net/phy/air_en8811h.c +++ b/drivers/net/phy/air_en8811h.c @@ -287,8 +287,8 @@ static int en8811h_wait_mcu_ready(struct phy_device *ph= ydev) { int ret, reg_value; =20 - ret =3D air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, - EN8811H_FW_CTRL_1_FINISH); + ret =3D air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, + EN8811H_FW_CTRL_1_FINISH); if (ret) return ret; =20 @@ -313,28 +313,29 @@ static int an8811hb_check_crc(struct phy_device *phyd= ev, u32 set1, int ret; =20 /* Configure CRC */ - ret =3D air_buckpbus_reg_modify(phydev, set1, - AN8811HB_CRC_RD_EN, - AN8811HB_CRC_RD_EN); + ret =3D air_phy_buckpbus_reg_modify(phydev, set1, + AN8811HB_CRC_RD_EN, + AN8811HB_CRC_RD_EN); if (ret < 0) return ret; - air_buckpbus_reg_read(phydev, set1, &pbus_value); + air_phy_buckpbus_reg_read(phydev, set1, &pbus_value); =20 do { msleep(300); - air_buckpbus_reg_read(phydev, mon2, &pbus_value); + air_phy_buckpbus_reg_read(phydev, mon2, &pbus_value); =20 /* We do not know what errors this check is supposed * catch or what to do about a failure. So print the * result and continue like the vendor driver does. */ if (pbus_value & AN8811HB_CRC_ST) { - air_buckpbus_reg_read(phydev, mon3, &pbus_value); + air_phy_buckpbus_reg_read(phydev, mon3, &pbus_value); phydev_dbg(phydev, "CRC Check %s!\n", pbus_value & AN8811HB_CRC_CHECK_PASS ? "PASS" : "FAIL"); - return air_buckpbus_reg_modify(phydev, set1, - AN8811HB_CRC_RD_EN, 0); + return air_phy_buckpbus_reg_modify(phydev, set1, + AN8811HB_CRC_RD_EN, + 0); } } while (--retry); =20 @@ -346,8 +347,8 @@ static void en8811h_print_fw_version(struct phy_device = *phydev) { struct en8811h_priv *priv =3D phydev->priv; =20 - air_buckpbus_reg_read(phydev, EN8811H_FW_VERSION, - &priv->firmware_version); + air_phy_buckpbus_reg_read(phydev, EN8811H_FW_VERSION, + &priv->firmware_version); phydev_info(phydev, "MD32 firmware version: %08x\n", priv->firmware_version); } @@ -372,8 +373,8 @@ static int an8811hb_load_firmware(struct phy_device *ph= ydev) { int ret; =20 - ret =3D air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, - EN8811H_FW_CTRL_1_START); + ret =3D air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, + EN8811H_FW_CTRL_1_START); if (ret < 0) return ret; =20 @@ -414,14 +415,14 @@ static int en8811h_load_firmware(struct phy_device *p= hydev) if (ret < 0) goto en8811h_load_firmware_rel1; =20 - ret =3D air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, - EN8811H_FW_CTRL_1_START); + ret =3D air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, + EN8811H_FW_CTRL_1_START); if (ret < 0) goto en8811h_load_firmware_out; =20 - ret =3D air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2, - EN8811H_FW_CTRL_2_LOADING, - EN8811H_FW_CTRL_2_LOADING); + ret =3D air_phy_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2, + EN8811H_FW_CTRL_2_LOADING, + EN8811H_FW_CTRL_2_LOADING); if (ret < 0) goto en8811h_load_firmware_out; =20 @@ -433,8 +434,8 @@ static int en8811h_load_firmware(struct phy_device *phy= dev) if (ret < 0) goto en8811h_load_firmware_out; =20 - ret =3D air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2, - EN8811H_FW_CTRL_2_LOADING, 0); + ret =3D air_phy_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2, + EN8811H_FW_CTRL_2_LOADING, 0); if (ret < 0) goto en8811h_load_firmware_out; =20 @@ -460,8 +461,8 @@ static int en8811h_restart_mcu(struct phy_device *phyde= v) { int ret; =20 - ret =3D air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, - EN8811H_FW_CTRL_1_START); + ret =3D air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, + EN8811H_FW_CTRL_1_START); if (ret < 0) return ret; =20 @@ -755,7 +756,7 @@ static unsigned long an8811hb_clk_recalc_rate(struct cl= k_hw *hw, u32 pbus_value; int ret; =20 - ret =3D air_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value); + ret =3D air_phy_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value); if (ret < 0) return ret; =20 @@ -767,9 +768,9 @@ static int an8811hb_clk_enable(struct clk_hw *hw) struct en8811h_priv *priv =3D clk_hw_to_en8811h_priv(hw); struct phy_device *phydev =3D priv->phydev; =20 - return air_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV, - AN8811HB_CLK_DRV_CKO_MASK, - AN8811HB_CLK_DRV_CKO_MASK); + return air_phy_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV, + AN8811HB_CLK_DRV_CKO_MASK, + AN8811HB_CLK_DRV_CKO_MASK); } =20 static void an8811hb_clk_disable(struct clk_hw *hw) @@ -777,8 +778,8 @@ static void an8811hb_clk_disable(struct clk_hw *hw) struct en8811h_priv *priv =3D clk_hw_to_en8811h_priv(hw); struct phy_device *phydev =3D priv->phydev; =20 - air_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV, - AN8811HB_CLK_DRV_CKO_MASK, 0); + air_phy_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV, + AN8811HB_CLK_DRV_CKO_MASK, 0); } =20 static int an8811hb_clk_is_enabled(struct clk_hw *hw) @@ -788,7 +789,7 @@ static int an8811hb_clk_is_enabled(struct clk_hw *hw) u32 pbus_value; int ret; =20 - ret =3D air_buckpbus_reg_read(phydev, AN8811HB_CLK_DRV, &pbus_value); + ret =3D air_phy_buckpbus_reg_read(phydev, AN8811HB_CLK_DRV, &pbus_value); if (ret < 0) return ret; =20 @@ -854,7 +855,7 @@ static unsigned long en8811h_clk_recalc_rate(struct clk= _hw *hw, u32 pbus_value; int ret; =20 - ret =3D air_buckpbus_reg_read(phydev, EN8811H_HWTRAP1, &pbus_value); + ret =3D air_phy_buckpbus_reg_read(phydev, EN8811H_HWTRAP1, &pbus_value); if (ret < 0) return ret; =20 @@ -866,9 +867,9 @@ static int en8811h_clk_enable(struct clk_hw *hw) struct en8811h_priv *priv =3D clk_hw_to_en8811h_priv(hw); struct phy_device *phydev =3D priv->phydev; =20 - return air_buckpbus_reg_modify(phydev, EN8811H_CLK_CGM, - EN8811H_CLK_CGM_CKO, - EN8811H_CLK_CGM_CKO); + return air_phy_buckpbus_reg_modify(phydev, EN8811H_CLK_CGM, + EN8811H_CLK_CGM_CKO, + EN8811H_CLK_CGM_CKO); } =20 static void en8811h_clk_disable(struct clk_hw *hw) @@ -876,8 +877,8 @@ static void en8811h_clk_disable(struct clk_hw *hw) struct en8811h_priv *priv =3D clk_hw_to_en8811h_priv(hw); struct phy_device *phydev =3D priv->phydev; =20 - air_buckpbus_reg_modify(phydev, EN8811H_CLK_CGM, - EN8811H_CLK_CGM_CKO, 0); + air_phy_buckpbus_reg_modify(phydev, EN8811H_CLK_CGM, + EN8811H_CLK_CGM_CKO, 0); } =20 static int en8811h_clk_is_enabled(struct clk_hw *hw) @@ -887,7 +888,7 @@ static int en8811h_clk_is_enabled(struct clk_hw *hw) u32 pbus_value; int ret; =20 - ret =3D air_buckpbus_reg_read(phydev, EN8811H_CLK_CGM, &pbus_value); + ret =3D air_phy_buckpbus_reg_read(phydev, EN8811H_CLK_CGM, &pbus_value); if (ret < 0) return ret; =20 @@ -998,9 +999,9 @@ static int an8811hb_probe(struct phy_device *phydev) return ret; =20 /* Configure led gpio pins as output */ - ret =3D air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT, - AN8811HB_GPIO_OUTPUT_345, - AN8811HB_GPIO_OUTPUT_345); + ret =3D air_phy_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT, + AN8811HB_GPIO_OUTPUT_345, + AN8811HB_GPIO_OUTPUT_345); if (ret < 0) return ret; =20 @@ -1039,9 +1040,9 @@ static int en8811h_probe(struct phy_device *phydev) return ret; =20 /* Configure led gpio pins as output */ - ret =3D air_buckpbus_reg_modify(phydev, EN8811H_GPIO_OUTPUT, - EN8811H_GPIO_OUTPUT_345, - EN8811H_GPIO_OUTPUT_345); + ret =3D air_phy_buckpbus_reg_modify(phydev, EN8811H_GPIO_OUTPUT, + EN8811H_GPIO_OUTPUT_345, + EN8811H_GPIO_OUTPUT_345); if (ret < 0) return ret; =20 @@ -1061,9 +1062,9 @@ static int an8811hb_config_serdes_polarity(struct phy= _device *phydev) return ret; if (pol =3D=3D PHY_POL_NORMAL) pbus_value |=3D AN8811HB_RX_POLARITY_NORMAL; - ret =3D air_buckpbus_reg_modify(phydev, AN8811HB_RX_POLARITY, - AN8811HB_RX_POLARITY_NORMAL, - pbus_value); + ret =3D air_phy_buckpbus_reg_modify(phydev, AN8811HB_RX_POLARITY, + AN8811HB_RX_POLARITY_NORMAL, + pbus_value); if (ret < 0) return ret; =20 @@ -1074,9 +1075,9 @@ static int an8811hb_config_serdes_polarity(struct phy= _device *phydev) pbus_value =3D 0; if (pol =3D=3D PHY_POL_NORMAL) pbus_value |=3D AN8811HB_TX_POLARITY_NORMAL; - return air_buckpbus_reg_modify(phydev, AN8811HB_TX_POLARITY, - AN8811HB_TX_POLARITY_NORMAL, - pbus_value); + return air_phy_buckpbus_reg_modify(phydev, AN8811HB_TX_POLARITY, + AN8811HB_TX_POLARITY_NORMAL, + pbus_value); } =20 static int en8811h_config_serdes_polarity(struct phy_device *phydev) @@ -1110,9 +1111,10 @@ static int en8811h_config_serdes_polarity(struct phy= _device *phydev) if (pol =3D=3D PHY_POL_NORMAL) pbus_value |=3D EN8811H_POLARITY_TX_NORMAL; =20 - return air_buckpbus_reg_modify(phydev, EN8811H_POLARITY, - EN8811H_POLARITY_RX_REVERSE | - EN8811H_POLARITY_TX_NORMAL, pbus_value); + return air_phy_buckpbus_reg_modify(phydev, EN8811H_POLARITY, + EN8811H_POLARITY_RX_REVERSE | + EN8811H_POLARITY_TX_NORMAL, + pbus_value); } =20 static int an8811hb_config_init(struct phy_device *phydev) @@ -1264,8 +1266,8 @@ static int en8811h_read_status(struct phy_device *phy= dev) val & MDIO_AN_10GBT_STAT_LP2_5G); } else { /* Get link partner 2.5GBASE-T ability from vendor register */ - ret =3D air_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA, - &pbus_value); + ret =3D air_phy_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA, + &pbus_value); if (ret < 0) return ret; linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, diff --git a/drivers/net/phy/air_phy_lib.c b/drivers/net/phy/air_phy_lib.c index 687c59197b16..1212dd0a37b7 100644 --- a/drivers/net/phy/air_phy_lib.c +++ b/drivers/net/phy/air_phy_lib.c @@ -136,8 +136,8 @@ static int __air_buckpbus_reg_modify(struct phy_device = *phydev, return 0; } =20 -int air_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address, - u32 *pbus_data) +int air_phy_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address, + u32 *pbus_data) { int saved_page; int ret =3D 0; @@ -153,10 +153,10 @@ int air_buckpbus_reg_read(struct phy_device *phydev, = u32 pbus_address, =20 return phy_restore_page(phydev, saved_page, ret); } -EXPORT_SYMBOL_GPL(air_buckpbus_reg_read); +EXPORT_SYMBOL_GPL(air_phy_buckpbus_reg_read); =20 -int air_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address, - u32 pbus_data) +int air_phy_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address, + u32 pbus_data) { int saved_page; int ret =3D 0; @@ -173,10 +173,10 @@ int air_buckpbus_reg_write(struct phy_device *phydev,= u32 pbus_address, =20 return phy_restore_page(phydev, saved_page, ret); } -EXPORT_SYMBOL_GPL(air_buckpbus_reg_write); +EXPORT_SYMBOL_GPL(air_phy_buckpbus_reg_write); =20 -int air_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_address, - u32 mask, u32 set) +int air_phy_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_addres= s, + u32 mask, u32 set) { int saved_page; int ret =3D 0; @@ -193,7 +193,7 @@ int air_buckpbus_reg_modify(struct phy_device *phydev, = u32 pbus_address, =20 return phy_restore_page(phydev, saved_page, ret); } -EXPORT_SYMBOL_GPL(air_buckpbus_reg_modify); +EXPORT_SYMBOL_GPL(air_phy_buckpbus_reg_modify); =20 int air_phy_read_page(struct phy_device *phydev) { diff --git a/drivers/net/phy/air_phy_lib.h b/drivers/net/phy/air_phy_lib.h index b637f3e0f2d5..a2f8b3725761 100644 --- a/drivers/net/phy/air_phy_lib.h +++ b/drivers/net/phy/air_phy_lib.h @@ -27,12 +27,12 @@ #define AIR_BPBUS_RD_DATA_HIGH 0x17 #define AIR_BPBUS_RD_DATA_LOW 0x18 =20 -int air_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_address, - u32 mask, u32 set); -int air_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address, - u32 *pbus_data); -int air_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address, - u32 pbus_data); +int air_phy_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_addres= s, + u32 mask, u32 set); +int air_phy_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address, + u32 *pbus_data); +int air_phy_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address, + u32 pbus_data); int air_phy_read_page(struct phy_device *phydev); int air_phy_write_page(struct phy_device *phydev, int page); =20 --=20 2.54.0 From nobody Tue May 26 04:51:45 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B817328B77; Tue, 12 May 2026 04:33:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560441; cv=none; b=NCBlx70IDhIU+JWAj6hlPNwjRha8gKxavR292noJ0a6AsUuRDA2D0BLRtmnwmUgZ8hYQfmFKH0jTWsf0p0HozbRKneYV+nDSrQJWIfJzLe+eeoQDhRoDOAsReMGSDMRcSuCNpcB8eKxPF5AaeQaTKYMX/nm5h7R3R8GjK22R1FM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560441; c=relaxed/simple; bh=dROUwQFmxko29ltqI6aVu+r5RpUI7xRxI8lCpTmuylQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=F820s/O2c3yP6maPjv5UXpzSkdaG8W6UtjSwbuUvV51Spxeo/kwdl4+jo05NJBu3aYAOM+RaAim+Nl4FPok5qHgqRoYgjxvoU3Q+jau2cr7InuMbnw+TGRimtPk+FA6ahjTvtlpAKpStua83YHH95IvB5Fti2RM/DArhojg+avw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=LCT1MSzU; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="LCT1MSzU" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1778560432; bh=dROUwQFmxko29ltqI6aVu+r5RpUI7xRxI8lCpTmuylQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=LCT1MSzUTL1zW6p5mYz/GIPMubN2/BSytxDqoeG2+/KXdWrDwmzkKIIcpvaWfjjCw xa7k9FETD5ICFC641p+taAny+qMIk8DGgTYH/Adx5P3X9mS5VxLcA7KN2vEk84EevV Zs2lTcd9G0XMxTgxfOZSF6dohAuSQ/bqmlfcl/1SSWEYR3fclswVUNCkFs0rtz+gnV JXLQI3FH296N8IkUyKimL+Yh5lta6NoMcvlP8lrGsrFx0nn6pSl0mB3nH6lE8Yd8MV sTDruifGMw+3EhVI/O6UsD61cYj0wLVIvu+y+LSL00mKMwDlgewYqyT/sdGp9jpT8v IavM2GfLgIoVA== Received: from yukiji.home (unknown [100.64.0.131]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: laeyraud) by bali.collaboradmins.com (Postfix) with ESMTPSA id C180117E38C7; Tue, 12 May 2026 06:33:51 +0200 (CEST) From: Louis-Alexis Eyraud Date: Tue, 12 May 2026 06:33:22 +0200 Subject: [PATCH net-next v3 5/6] net: phy: Introduce Airoha AN8801/R Gigabit Ethernet PHY driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260512-add-airoha-an8801-support-v3-5-1edb34e363ae@collabora.com> References: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> In-Reply-To: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , AngeloGioacchino Del Regno , Andrew Lunn , Heiner Kallweit , Russell King Cc: kevin-kw.huang@airoha.com, macpaul.lin@mediatek.com, matthias.bgg@gmail.com, kernel@collabora.com, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Louis-Alexis Eyraud X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778560425; l=31996; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=gs5C6MHXu0Q2nFhe9UcodR63nvgUOa8nK6RSScvakhg=; b=HELD9RKkAn7RNsl6b8OpNhmFX+nYQNmCz/YwUCCicRr4VvoUtPMtoY9+wbTvx7ko7yYAhWyPn O1GxMGmfireCkVw8xexzFLRWwcDlQm/Ix8z8S66y1HMk/oyGEmkbmkJ X-Developer-Key: i=louisalexis.eyraud@collabora.com; a=ed25519; pk=CHFBDB2Kqh4EHc6JIqFn69GhxJJAzc0Zr4e8QxtumuM= From: AngeloGioacchino Del Regno Introduce a driver for the Airoha AN8801R Series Gigabit Ethernet PHY; this currently supports setting up PHY LEDs, 10/100M, 1000M speeds, and Wake on LAN and PHY interrupts. Signed-off-by: AngeloGioacchino Del Regno Signed-off-by: Louis-Alexis Eyraud --- drivers/net/phy/Kconfig | 6 + drivers/net/phy/Makefile | 1 + drivers/net/phy/air_an8801.c | 1088 ++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 1095 insertions(+) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index b6b1cde7e51f..4dd77ba48776 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -90,6 +90,12 @@ config AS21XXX_PHY AS21210PB1 that all register with the PHY ID 0x7500 0x7500 before the firmware is loaded. =20 +config AIR_AN8801_PHY + tristate "Airoha AN8801 Gigabit PHY" + select AIR_NET_PHYLIB + help + Currently supports the Airoha AN8801R PHY. + config AIR_EN8811H_PHY tristate "Airoha EN8811H 2.5 Gigabit PHY" select AIR_NET_PHYLIB diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 7cf1fa9e12cb..de660ae94945 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -29,6 +29,7 @@ obj-y +=3D $(sfp-obj-y) $(sfp-obj-m) =20 obj-$(CONFIG_ADIN_PHY) +=3D adin.o obj-$(CONFIG_ADIN1100_PHY) +=3D adin1100.o +obj-$(CONFIG_AIR_AN8801_PHY) +=3D air_an8801.o obj-$(CONFIG_AIR_EN8811H_PHY) +=3D air_en8811h.o obj-$(CONFIG_AIR_NET_PHYLIB) +=3D air_phy_lib.o obj-$(CONFIG_AMD_PHY) +=3D amd.o diff --git a/drivers/net/phy/air_an8801.c b/drivers/net/phy/air_an8801.c new file mode 100644 index 000000000000..a0f164cbf92b --- /dev/null +++ b/drivers/net/phy/air_an8801.c @@ -0,0 +1,1088 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver for the Airoha AN8801 Gigabit PHY. + * + * Copyright (C) 2025 Airoha Technology Corp. + * Copyright (C) 2025 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "air_phy_lib.h" + +#define AN8801R_PHY_ID 0xc0ff0421 + +/* MII Registers */ + +/* MII Registers - Airoha Page 1 */ +#define AN8801_EXT_REG_PHY 0x14 +#define AN8801_EXT_PHY_STATUS0 GENMASK(1, 0) +#define AN8801_EXT_PHY_DOWNSHIFT_CTL GENMASK(3, 2) /* 2 to 5 1G auto-neg= attempts (0..3) */ +#define AN8801_EXT_PHY_DOWNSHIFT_EN BIT(4) +#define AN8801_EXT_PHY_CTRL0 BIT(5) +#define AN8801_EXT_PHY_STATUS1 GENMASK(8, 6) +#define AN8801_EXT_PHY_CTRL1 GENMASK(14, 9) + +/* MII Registers - Airoha Page 4 */ +#define AN8801_PBUS_ACCESS BIT(28) +#define AN8801_PBUS_EPHY_ACCESS BIT(24) +#define AN8801_PBUS_CL22_ACCESS BIT(23) + +/* BPBUS Registers */ +#define AN8801_BPBUS_REG_LED_GPIO 0x54 +#define AN8801_BPBUS_REG_LED_ID_SEL 0x58 +#define LED_ID_GPIO_SEL(led, gpio) ((led) << ((gpio) * 3)) +#define LED_ID_GPIO_SEL_MASK(gpio) (0x7 << ((gpio) * 3)) +#define AN8801_BPBUS_REG_GPIO_MODE 0x70 +#define AN8801_BPBUS_REG_PHY_IRQ_GPIO 0x7c +#define AN8801_PHY_IRQ_GPIO_NUM_MASK GENMASK(19, 16) +#define AN8801_PHY_IRQ_GPIO_NUM 1 + +#define AN8801_BPBUS_REG_CKO 0x1a4 +#define AN8801_CKO_OUTPUT_MODE_AUTO 3 + +#define AN8801_BPBUS_REG_LINK_MODE 0x5054 +#define AN8801_BPBUS_LINK_MODE_1000 BIT(0) + +#define AN8801_BPBUS_REG_BYPASS_PTP 0x21c004 +#define AN8801_BYP_PTP_SGMII_TO_GPHY BIT(8) +#define AN8801_BYP_PTP_RGMII_TO_GPHY BIT(0) + +#define AN8801_BPBUS_REG_TXDLY_STEP 0x21c024 +#define RGMII_DELAY_STEP_MASK GENMASK(2, 0) +#define RGMII_DELAY_NO_STEP 0 +#define RGMII_DELAY_STEP_1 1 +#define RGMII_DELAY_STEP_2 2 +#define RGMII_DELAY_STEP_3 3 +#define RGMII_DELAY_STEP_4 4 +#define RGMII_DELAY_STEP_5 5 +#define RGMII_DELAY_STEP_6 6 +#define RGMII_DELAY_STEP_7 7 +#define RGMII_TXDELAY_FORCE_MODE BIT(24) + +#define AN8801_RGMII_TXDELAY_DEFAULT RGMII_DELAY_STEP_4 /* 1.883ns delay */ + +#define AN8801_BPBUS_REG_RXDLY_STEP 0x21c02c +#define RGMII_RXDELAY_ALIGN BIT(4) +#define RGMII_RXDELAY_FORCE_MODE BIT(24) + +#define AN8801_RGMII_RXDELAY_DEFAULT RGMII_DELAY_NO_STEP /* 1.992ns delay = */ + +#define AN8801_BPBUS_REG_EFIFO_CTL(x) (0x270004 + (0x100 * (x))) /* 0..2 */ +#define AN8801_EFIFO_ALL_EN GENMASK(7, 0) +#define AN8801_EFIFO_RX_EN BIT(0) +#define AN8801_EFIFO_TX_EN BIT(1) +#define AN8801_EFIFO_RX_CLK_EN BIT(2) +#define AN8801_EFIFO_TX_CLK_EN BIT(3) +#define AN8801_EFIFO_RX_EEE_EN BIT(4) +#define AN8801_EFIFO_TX_EEE_EN BIT(5) +#define AN8801_EFIFO_RX_ODD_NIBBLE_EN BIT(6) +#define AN8801_EFIFO_TX_ODD_NIBBLE_EN BIT(7) + +#define AN8801_BPBUS_REG_WOL_MAC_16_47 0x285114 +#define AN8801_BPBUS_REG_WOL_MAC_0_15 0x285118 + +#define AN8801_BPBUS_REG_WAKEUP_CTL1 0x285400 +#define AN8801_WOL_WAKE_MAGIC_EN GENMASK(3, 1) +#define AN8801_WOL_WAKE_LNKCHG_EN BIT(4) + +#define AN8801_BPBUS_REG_WAKEUP_CTL2 0x285404 +#define AN8801_WAKE_OUT_TYPE_PULSE BIT(0) /* Set/Unset: Pulse/Static */ +#define AN8801_WAKE_OUT_POLARITY_NEG BIT(1) /* Set/Unset: Negative/Posit= ive */ +#define AN8801_WAKE_OUT_WIDTH GENMASK(2, 3) +#define AN8801_WAKE_OUT_84MS 0 +#define AN8801_WAKE_OUT_168MS 1 +#define AN8801_WAKE_OUT_336MS 2 +#define AN8801_WAKE_OUT_672MS 3 +#define AN8801_WAKE_OUT_EN BIT(4) +#define AN8801_PME_WAKEUP_CLR BIT(8) + +#define AN8801_BPBUS_REG_WAKE_IRQ_EN 0x285700 +#define AN8801_BPBUS_REG_WAKE_IRQ_STS 0x285704 +#define AN8801_IRQ_WAKE_LNKCHG BIT(0) /* Wake on link change */ +#define AN8801_IRQ_WAKE_UNIPKT BIT(1) /* Wake on unicast packet */ +#define AN8801_IRQ_WAKE_MULPKT BIT(2) /* Wake on multicast packet */ +#define AN8801_IRQ_WAKE_BCPKT BIT(3) /* Wake on broadcast packet */ +#define AN8801_IRQ_WAKE_MAGICPKT BIT(4) /* Wake on magic packet */ +#define AN8801_IRQ_WAKE_ALL GENMASK(4, 0) + +/* MDIO_MMD_VEND1 Registers */ +#define AN8801_PHY_TX_PAIR_DLY_SEL_GBE 0x13 +#define AN8801_PHY_PAIR_DLY_SEL_A_GBE GENMASK(14, 12) +#define AN8801_PHY_PAIR_DLY_SEL_B_GBE GENMASK(10, 8) +#define AN8801_PHY_PAIR_DLY_SEL_C_GBE GENMASK(6, 4) +#define AN8801_PHY_PAIR_DLY_SEL_D_GBE GENMASK(2, 0) +#define AN8801_PHY_RXADC_CTRL 0xd8 +#define AN8801_PHY_RXADC_SAMP_PHSEL_A BIT(12) +#define AN8801_PHY_RXADC_SAMP_PHSEL_B BIT(8) +#define AN8801_PHY_RXADC_SAMP_PHSEL_C BIT(4) +#define AN8801_PHY_RXADC_SAMP_PHSEL_D BIT(0) +#define AN8801_PHY_RXADC_REV_0 0xd9 +#define AN8801_PHY_RXADC_REV_MASK_A GENMASK(15, 8) +#define AN8801_PHY_RXADC_REV_MASK_B GENMASK(7, 0) +#define AN8801_PHY_RXADC_REV_1 0xda +#define AN8801_PHY_RXADC_REV_MASK_C GENMASK(15, 8) +#define AN8801_PHY_RXADC_REV_MASK_D GENMASK(7, 0) + +/* MDIO_MMD_VEND2 Registers */ +#define LED_BCR 0x21 +#define LED_BCR_MODE_MASK GENMASK(1, 0) +#define LED_BCR_TIME_TEST BIT(2) +#define LED_BCR_CLK_EN BIT(3) +#define LED_BCR_EVT_ALL BIT(4) +#define LED_BCR_EXT_CTRL BIT(15) +#define LED_BCR_MODE_DISABLE 0 +#define LED_BCR_MODE_2LED 1 +#define LED_BCR_MODE_3LED_1 2 +#define LED_BCR_MODE_3LED_2 3 + +#define LED_ON_DUR 0x22 +#define LED_ON_DUR_MASK GENMASK(15, 0) + +#define LED_BLINK_DUR 0x23 +#define LED_BLINK_DUR_MASK GENMASK(15, 0) + +#define LED_ON_CTRL(i) (0x24 + ((i) * 2)) +#define LED_ON_EVT_MASK GENMASK(6, 0) +#define LED_ON_EVT_LINK_1000M BIT(0) +#define LED_ON_EVT_LINK_100M BIT(1) +#define LED_ON_EVT_LINK_10M BIT(2) +#define LED_ON_EVT_LINK_DN BIT(3) +#define LED_ON_EVT_FDX BIT(4) +#define LED_ON_EVT_HDX BIT(5) +#define LED_ON_EVT_FORCE BIT(6) +#define LED_ON_POL BIT(14) +#define LED_ON_EN BIT(15) + +#define LED_BLINK_CTRL(i) (0x25 + ((i) * 2)) +#define LED_BLINK_EVT_MASK GENMASK(9, 0) +#define LED_BLINK_EVT_1000M_TX BIT(0) +#define LED_BLINK_EVT_1000M_RX BIT(1) +#define LED_BLINK_EVT_100M_TX BIT(2) +#define LED_BLINK_EVT_100M_RX BIT(3) +#define LED_BLINK_EVT_10M_TX BIT(4) +#define LED_BLINK_EVT_10M_RX BIT(5) +#define LED_BLINK_EVT_COLLISION BIT(6) +#define LED_BLINK_EVT_RX_CRC_ERR BIT(7) +#define LED_BLINK_EVT_RX_IDLE_ERR BIT(8) +#define LED_BLINK_EVT_FORCE BIT(9) + +#define AN8801R_NUM_LEDS 3 +#define AN8801_PERIOD_SHIFT 15 +#define AN8801_PERIOD_UNIT 32768 /* (1 << AN8801_PERIOD_SHIFT) */ +#define AN8801_MAX_PERIOD_MS 2147 + +#define AN8801_LED_DURATION_UNIT_US 32768 + +#define AN8801_REG_PHY_INTERNAL0 0x600 +#define AN8801_REG_PHY_INTERNAL1 0x601 +#define AN8801_PHY_INTFUNC_MASK GENMASK(15, 0) /* PHY internal functions= */ + +enum an8801r_led_fn { + AN8801R_LED_FN_NONE, + AN8801R_LED_FN_LINK, + AN8801R_LED_FN_ACTIVITY, + AN8801R_LED_FN_MAX, +}; + +struct an8801r_priv { + bool wake_magic_enabled; + bool wake_lnkchg_enabled; +}; + +static int an8801_buckpbus_reg_rmw(struct phy_device *phydev, + u32 addr, u32 mask, u32 set) +{ + return air_phy_buckpbus_reg_modify(phydev, + addr | AN8801_PBUS_ACCESS, + mask, set); +} + +static int an8801_buckpbus_reg_set_bits(struct phy_device *phydev, + u32 addr, u32 mask) +{ + return air_phy_buckpbus_reg_modify(phydev, + addr | AN8801_PBUS_ACCESS, + mask, mask); +} + +static int an8801_buckpbus_reg_clear_bits(struct phy_device *phydev, + u32 addr, u32 mask) +{ + return air_phy_buckpbus_reg_modify(phydev, + addr | AN8801_PBUS_ACCESS, + mask, 0); +} + +static int an8801_buckpbus_reg_write(struct phy_device *phydev, u32 addr, + u32 data) +{ + return air_phy_buckpbus_reg_write(phydev, + addr | AN8801_PBUS_ACCESS, + data); +} + +static int an8801_buckpbus_reg_read(struct phy_device *phydev, u32 addr, + u32 *data) +{ + return air_phy_buckpbus_reg_read(phydev, + addr | AN8801_PBUS_ACCESS, + data); +} + +static u32 an8801r_led_blink_ms_to_hw(unsigned long req_ms) +{ + u32 req_ns, regval; + + if (req_ms > AN8801_MAX_PERIOD_MS) + req_ms =3D AN8801_MAX_PERIOD_MS; + + req_ns =3D req_ms * 1000000; + + /* Round to the nearest period unit... */ + regval =3D req_ns + (AN8801_PERIOD_UNIT / 2); + + /* ...and now divide by the full period */ + regval >>=3D AN8801_PERIOD_SHIFT; + + return regval; +} + +static int an8801r_led_blink_set(struct phy_device *phydev, u8 index, + unsigned long *delay_on, + unsigned long *delay_off) +{ + u32 hw_delay_on, hw_delay_off; + bool blink; + int ret; + + if (index >=3D AN8801R_NUM_LEDS) + return -EINVAL; + + if (delay_on && delay_off) { + blink =3D true; + + if (*delay_on =3D=3D 0 || *delay_off =3D=3D 0) { + *delay_on =3D 64; + *delay_off =3D 64; + } + + hw_delay_on =3D an8801r_led_blink_ms_to_hw(*delay_on); + hw_delay_off =3D an8801r_led_blink_ms_to_hw(*delay_off); + } else { + blink =3D false; + } + + if (blink) { + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_DUR, + hw_delay_on + hw_delay_off); + if (ret) + goto error; + + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_ON_DUR, + hw_delay_on); + if (ret) + goto error; + } + + ret =3D phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_CTRL(index), + LED_BLINK_EVT_MASK, + blink ? LED_BLINK_EVT_FORCE : 0); + if (ret) + return ret; + + ret =3D phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index), + LED_ON_EVT_MASK, + 0); + if (ret) + return ret; + + return phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index), + LED_ON_EN, blink ? LED_ON_EN : 0); + +error: + phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index), + LED_ON_EN, 0); + return ret; +} + +static int an8801r_led_brightness_set(struct phy_device *phydev, u8 index, + enum led_brightness value) +{ + int ret; + + if (index >=3D AN8801R_NUM_LEDS) + return -EINVAL; + + ret =3D phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index), + LED_ON_EVT_MASK, + (value =3D=3D LED_OFF) ? 0 : LED_ON_EVT_FORCE); + if (ret) + return ret; + + return phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index), + LED_ON_EN, (value =3D=3D LED_OFF) ? 0 : LED_ON_EN); +} + +static int an8801r_led_hw_control_get(struct phy_device *phydev, u8 index, + unsigned long *rules) +{ + int on, blink; + + on =3D phy_read_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index)); + if (on < 0) + return on; + + blink =3D phy_read_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_CTRL(index)); + if (blink < 0) + return blink; + + if (FIELD_GET(LED_ON_EVT_LINK_10M, on)) + __set_bit(TRIGGER_NETDEV_LINK_10, rules); + + if (FIELD_GET(LED_ON_EVT_LINK_100M, on)) + __set_bit(TRIGGER_NETDEV_LINK_100, rules); + + if (FIELD_GET(LED_ON_EVT_LINK_1000M, on)) + __set_bit(TRIGGER_NETDEV_LINK_1000, rules); + + if (FIELD_GET(LED_ON_EVT_LINK_10M, on) && + FIELD_GET(LED_ON_EVT_LINK_100M, on) && + FIELD_GET(LED_ON_EVT_LINK_1000M, on)) + __set_bit(TRIGGER_NETDEV_LINK, rules); + + if (FIELD_GET(LED_BLINK_EVT_10M_RX, blink) || + FIELD_GET(LED_BLINK_EVT_100M_RX, blink) || + FIELD_GET(LED_BLINK_EVT_1000M_RX, blink)) + __set_bit(TRIGGER_NETDEV_RX, rules); + + if (FIELD_GET(LED_BLINK_EVT_10M_TX, blink) || + FIELD_GET(LED_BLINK_EVT_100M_TX, blink) || + FIELD_GET(LED_BLINK_EVT_1000M_TX, blink)) + __set_bit(TRIGGER_NETDEV_TX, rules); + + if (FIELD_GET(LED_BLINK_EVT_RX_CRC_ERR, blink)) + __set_bit(TRIGGER_NETDEV_RX_ERR, rules); + + return 0; +} + +static int an8801r_led_trig_to_hw(unsigned long rules, u16 *on, u16 *blink) +{ + if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) + *on |=3D LED_ON_EVT_LINK_10M; + + if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) + *on |=3D LED_ON_EVT_LINK_100M; + + if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) + *on |=3D LED_ON_EVT_LINK_1000M; + + if (test_bit(TRIGGER_NETDEV_LINK, &rules)) { + *on |=3D LED_ON_EVT_LINK_10M; + *on |=3D LED_ON_EVT_LINK_100M; + *on |=3D LED_ON_EVT_LINK_1000M; + } + + if (test_bit(TRIGGER_NETDEV_RX, &rules)) { + *blink |=3D LED_BLINK_EVT_10M_RX; + *blink |=3D LED_BLINK_EVT_100M_RX; + *blink |=3D LED_BLINK_EVT_1000M_RX; + } + + if (test_bit(TRIGGER_NETDEV_TX, &rules)) { + *blink |=3D LED_BLINK_EVT_10M_TX; + *blink |=3D LED_BLINK_EVT_100M_TX; + *blink |=3D LED_BLINK_EVT_1000M_TX; + } + + if (test_bit(TRIGGER_NETDEV_RX_ERR, &rules)) + *blink |=3D LED_BLINK_EVT_RX_CRC_ERR; + + if (rules && !*on && !*blink) + return -EOPNOTSUPP; + + return 0; +} + +static int an8801r_led_hw_is_supported(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + u16 on =3D 0, blink =3D 0; + + if (index >=3D AN8801R_NUM_LEDS) + return -EINVAL; + + return an8801r_led_trig_to_hw(rules, &on, &blink); +} + +static int an8801r_led_hw_control_set(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + u16 on =3D 0, blink =3D 0; + int ret; + + if (index >=3D AN8801R_NUM_LEDS) + return -EINVAL; + + ret =3D an8801r_led_trig_to_hw(rules, &on, &blink); + if (ret) + return ret; + + ret =3D phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index), + LED_ON_EVT_MASK, on); + if (ret) + return ret; + + ret =3D phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_CTRL(index), + LED_BLINK_EVT_MASK, blink); + + if (ret) + return ret; + + return phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index), + LED_ON_EN, on | blink ? LED_ON_EN : 0); +} + +static int an8801r_led_polarity_set(struct phy_device *phydev, int index, + unsigned long modes) +{ + bool active_high =3D true; + unsigned long mode; + + if (index >=3D AN8801R_NUM_LEDS) + return -EINVAL; + + for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { + switch (mode) { + case PHY_LED_ACTIVE_HIGH: + break; + case PHY_LED_ACTIVE_LOW: + active_high =3D false; + break; + default: + return -EINVAL; + } + } + + return phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index), + LED_ON_POL, active_high ? LED_ON_POL : 0); +} + +static int an8801r_led_init(struct phy_device *phydev, u8 *led_cfg) +{ + int led_id, ret; + + /* Set LED BCR Enable */ + ret =3D phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, LED_BCR, + LED_BCR_EXT_CTRL | LED_BCR_CLK_EN); + if (ret) + return ret; + + for (led_id =3D 0; led_id < AN8801R_NUM_LEDS; led_id++) { + unsigned long led_trigger =3D 0; + u32 led_gpio =3D led_id + 1; + + switch (led_cfg[led_id]) { + case AN8801R_LED_FN_LINK: + led_trigger =3D BIT(TRIGGER_NETDEV_LINK); + break; + case AN8801R_LED_FN_ACTIVITY: + led_trigger =3D BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX); + break; + default: + led_trigger =3D 0; + break; + } + + ret =3D an8801_buckpbus_reg_set_bits(phydev, + AN8801_BPBUS_REG_LED_GPIO, + BIT(led_gpio)); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_rmw(phydev, + AN8801_BPBUS_REG_LED_ID_SEL, + LED_ID_GPIO_SEL_MASK(led_gpio), + LED_ID_GPIO_SEL(led_id, + led_gpio)); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_clear_bits(phydev, + AN8801_BPBUS_REG_GPIO_MODE, + BIT(led_gpio)); + if (ret) + return ret; + + if (!led_trigger) + continue; + + ret =3D an8801r_led_hw_control_set(phydev, led_id, led_trigger); + if (ret) + return ret; + } + + return ret; +} + +static int an8801r_reset_wake(struct phy_device *phydev) +{ + struct an8801r_priv *priv =3D phydev->priv; + u32 reg_val =3D 0; + int ret; + + /* Enable wakeup clear and disable wake up output */ + ret =3D an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_WAKEUP_CTL2, + AN8801_PME_WAKEUP_CLR | + AN8801_WAKE_OUT_POLARITY_NEG); + if (ret) + return ret; + + /* Clear WAKEUP_CTL1 register before enabling the wakeup events + * again + */ + ret =3D an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_WAKEUP_CTL1, + 0); + if (ret) + return ret; + + if (priv->wake_magic_enabled) + reg_val |=3D AN8801_WOL_WAKE_MAGIC_EN; + + if (priv->wake_lnkchg_enabled) + reg_val |=3D AN8801_WOL_WAKE_LNKCHG_EN; + + ret =3D an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_WAKEUP_CTL1, + reg_val); + if (ret) + return ret; + + /* Disable wake up clear and re-enable wake up output */ + return an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_WAKEUP_CTL2, + AN8801_WAKE_OUT_POLARITY_NEG | + AN8801_WAKE_OUT_EN); +} + +static int an8801r_ack_interrupt(struct phy_device *phydev) +{ + int ret; + + /* Reset wake status */ + ret =3D an8801r_reset_wake(phydev); + if (ret) + return ret; + + /* Clear the interrupts by writing the reg */ + return an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_WAKE_IRQ_STS, + AN8801_IRQ_WAKE_ALL); +} + +static int an8801r_config_intr(struct phy_device *phydev) +{ + int ret; + + if (phydev->interrupts =3D=3D PHY_INTERRUPT_ENABLED) { + u32 val =3D FIELD_PREP(AN8801_PHY_IRQ_GPIO_NUM_MASK, + AN8801_PHY_IRQ_GPIO_NUM); + + ret =3D an8801_buckpbus_reg_write(phydev, + AN8801_BPBUS_REG_PHY_IRQ_GPIO, + val); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_set_bits(phydev, + AN8801_BPBUS_REG_WAKE_IRQ_EN, + AN8801_IRQ_WAKE_LNKCHG); + if (ret) + return ret; + + } else { + ret =3D an8801_buckpbus_reg_write(phydev, + AN8801_BPBUS_REG_PHY_IRQ_GPIO, + 0); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_clear_bits(phydev, + AN8801_BPBUS_REG_WAKE_IRQ_EN, + AN8801_IRQ_WAKE_LNKCHG); + if (ret) + return ret; + } + + return an8801r_ack_interrupt(phydev); +} + +static irqreturn_t an8801r_handle_interrupt(struct phy_device *phydev) +{ + u32 irq_status =3D 0; + int ret; + + ret =3D an8801_buckpbus_reg_read(phydev, AN8801_BPBUS_REG_WAKE_IRQ_STS, + &irq_status); + if (ret) + return IRQ_NONE; + + ret =3D an8801r_ack_interrupt(phydev); + if (ret) + return IRQ_NONE; + + if (irq_status & AN8801_IRQ_WAKE_MAGICPKT) { + pm_wakeup_event(&phydev->mdio.dev, 0); + return IRQ_HANDLED; + } + + if (irq_status & AN8801_IRQ_WAKE_LNKCHG) { + phy_trigger_machine(phydev); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void an8801r_get_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + u32 reg_val; + int ret; + + /* If the PHY is not capable of waking the system, then WoL can not + * be supported. + */ + if (!device_can_wakeup(&phydev->mdio.dev)) { + wol->supported =3D 0; + return; + } + + wol->supported =3D WAKE_MAGIC; + wol->wolopts =3D 0; + + ret =3D an8801_buckpbus_reg_read(phydev, AN8801_BPBUS_REG_WAKEUP_CTL1, + ®_val); + if (ret) + return; + + if (reg_val & AN8801_WOL_WAKE_MAGIC_EN) + wol->wolopts |=3D WAKE_MAGIC; + else + wol->wolopts &=3D ~WAKE_MAGIC; +} + +static int an8801r_set_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + struct net_device *attach_dev =3D phydev->attached_dev; + const unsigned char *macaddr =3D attach_dev->dev_addr; + struct an8801r_priv *priv =3D phydev->priv; + u32 reg_val; + int ret; + + if (!device_can_wakeup(&phydev->mdio.dev)) + return -EOPNOTSUPP; + + if (wol->wolopts & WAKE_MAGIC) { + /* MAC bits 16..47 */ + reg_val =3D (macaddr[2] << 24) | (macaddr[3] << 16); + reg_val |=3D (macaddr[4] << 8) | (macaddr[5]); + + ret =3D an8801_buckpbus_reg_write(phydev, + AN8801_BPBUS_REG_WOL_MAC_16_47, + reg_val); + if (ret) + return ret; + + /* MAC bits 0..15 */ + reg_val =3D (macaddr[0] << 8) | (macaddr[1]); + + ret =3D an8801_buckpbus_reg_write(phydev, + AN8801_BPBUS_REG_WOL_MAC_0_15, + reg_val); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_set_bits(phydev, + AN8801_BPBUS_REG_WAKEUP_CTL1, + AN8801_WOL_WAKE_MAGIC_EN); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_set_bits(phydev, + AN8801_BPBUS_REG_WAKE_IRQ_EN, + AN8801_IRQ_WAKE_MAGICPKT); + if (ret) + return ret; + + } else { + ret =3D an8801_buckpbus_reg_clear_bits(phydev, + AN8801_BPBUS_REG_WAKEUP_CTL1, + AN8801_WOL_WAKE_MAGIC_EN); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_clear_bits(phydev, + AN8801_BPBUS_REG_WAKE_IRQ_EN, + AN8801_IRQ_WAKE_MAGICPKT); + if (ret) + return ret; + } + + priv->wake_magic_enabled =3D !!(wol->wolopts & WAKE_MAGIC); + + return device_set_wakeup_enable(&phydev->mdio.dev, + priv->wake_magic_enabled); +} + +static int an8801r_of_init_leds(struct phy_device *phydev, u8 *led_cfg) +{ + struct device *dev =3D &phydev->mdio.dev; + struct device_node *np =3D dev->of_node; + struct device_node *leds; + u32 function_enum_idx; + int ret; + + if (!np) + return 0; + + /* If devicetree is present, leds configuration is required */ + leds =3D of_get_child_by_name(np, "leds"); + if (!leds) + return 0; + + for_each_available_child_of_node_scoped(leds, led) { + u32 led_idx; + + ret =3D of_property_read_u32(led, "reg", &led_idx); + if (ret) + goto out; + + if (led_idx >=3D AN8801R_NUM_LEDS) { + ret =3D -EINVAL; + goto out; + } + + ret =3D of_property_read_u32(led, "function-enumerator", + &function_enum_idx); + if (ret) { + function_enum_idx =3D AN8801R_LED_FN_NONE; + ret =3D 0; + } + + if (function_enum_idx >=3D AN8801R_LED_FN_MAX) { + ret =3D -EINVAL; + goto out; + } + + led_cfg[led_idx] =3D function_enum_idx; + } +out: + of_node_put(leds); + return ret; +} + +static int an8801r_rgmii_rxdelay(struct phy_device *phydev, bool enable, + u16 delay_steps) +{ + u32 reg_val; + + if (delay_steps > RGMII_DELAY_STEP_MASK) + return -EINVAL; + + if (enable) { + reg_val =3D delay_steps & RGMII_DELAY_STEP_MASK; + + /* Set align bit to add extra offset for RX delay */ + reg_val |=3D RGMII_RXDELAY_ALIGN; + + /* Set force mode bit to enable RX delay insertion */ + reg_val |=3D RGMII_RXDELAY_FORCE_MODE; + } else { + reg_val =3D 0; + } + + return an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_RXDLY_STEP, + reg_val); +} + +static int an8801r_rgmii_txdelay(struct phy_device *phydev, bool enable, + u16 delay_steps) +{ + u32 reg_val; + + if (delay_steps > RGMII_DELAY_STEP_MASK) + return -EINVAL; + + if (enable) { + reg_val =3D delay_steps & RGMII_DELAY_STEP_MASK; + + /* Set force mode bit to enable TX delay insertion */ + reg_val |=3D RGMII_TXDELAY_FORCE_MODE; + } else { + reg_val =3D 0; + } + + return an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_TXDLY_STEP, + reg_val); +} + +static int an8801r_rgmii_delay_config(struct phy_device *phydev) +{ + bool enable_delay; + u16 delay_step; + int ret; + + if (phydev->interface =3D=3D PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface =3D=3D PHY_INTERFACE_MODE_RGMII_TXID) { + enable_delay =3D true; + delay_step =3D AN8801_RGMII_TXDELAY_DEFAULT; + } else { + enable_delay =3D false; + delay_step =3D RGMII_DELAY_NO_STEP; + } + + ret =3D an8801r_rgmii_txdelay(phydev, enable_delay, delay_step); + if (ret) + return ret; + + if (phydev->interface =3D=3D PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface =3D=3D PHY_INTERFACE_MODE_RGMII_RXID) { + enable_delay =3D true; + delay_step =3D AN8801_RGMII_RXDELAY_DEFAULT; + } else { + enable_delay =3D false; + delay_step =3D RGMII_DELAY_NO_STEP; + } + + return an8801r_rgmii_rxdelay(phydev, enable_delay, delay_step); +} + +static int an8801r_config_init(struct phy_device *phydev) +{ + u8 led_default_function[AN8801R_NUM_LEDS] =3D { 0 }; + int ret; + + ret =3D an8801r_of_init_leds(phydev, led_default_function); + if (ret) + return ret; + + /* Disable Low Power Mode (LPM) */ + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND2, AN8801_REG_PHY_INTERNAL0, + FIELD_PREP(AN8801_PHY_INTFUNC_MASK, 0x1e)); + if (ret) + return ret; + + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND2, AN8801_REG_PHY_INTERNAL1, + FIELD_PREP(AN8801_PHY_INTFUNC_MASK, 0x2)); + if (ret) + return ret; + + /* Set the PHY to perform auto-downshift after 3 auto-negotiation + * attempts + */ + ret =3D phy_write_paged(phydev, AIR_PHY_PAGE_EXTENDED_1, + AN8801_EXT_REG_PHY, + FIELD_PREP(AN8801_EXT_PHY_CTRL1, 0x1d) | + FIELD_PREP(AN8801_EXT_PHY_DOWNSHIFT_CTL, 1) | + AN8801_EXT_PHY_DOWNSHIFT_EN); + if (ret < 0) + return ret; + + ret =3D an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_BYPASS_PTP, + AN8801_BYP_PTP_RGMII_TO_GPHY); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(0), + AN8801_EFIFO_RX_EN | + AN8801_EFIFO_TX_EN | + AN8801_EFIFO_RX_CLK_EN | + AN8801_EFIFO_TX_CLK_EN | + AN8801_EFIFO_RX_EEE_EN | + AN8801_EFIFO_TX_EEE_EN); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(1), + AN8801_EFIFO_ALL_EN); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(2), + AN8801_EFIFO_ALL_EN); + if (ret) + return ret; + + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND1, + AN8801_PHY_TX_PAIR_DLY_SEL_GBE, + FIELD_PREP(AN8801_PHY_PAIR_DLY_SEL_A_GBE, 4) | + FIELD_PREP(AN8801_PHY_PAIR_DLY_SEL_C_GBE, 4)); + if (ret) + return ret; + + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8801_PHY_RXADC_CTRL, + AN8801_PHY_RXADC_SAMP_PHSEL_A | + AN8801_PHY_RXADC_SAMP_PHSEL_C); + if (ret) + return ret; + + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8801_PHY_RXADC_REV_0, + FIELD_PREP(AN8801_PHY_RXADC_REV_MASK_A, 1)); + if (ret) + return ret; + + ret =3D phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8801_PHY_RXADC_REV_1, + FIELD_PREP(AN8801_PHY_RXADC_REV_MASK_C, 1)); + if (ret) + return ret; + + ret =3D an8801r_rgmii_delay_config(phydev); + if (ret) + return ret; + + ret =3D an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_CKO, + AN8801_CKO_OUTPUT_MODE_AUTO); + if (ret) + return ret; + + ret =3D an8801r_led_init(phydev, led_default_function); + if (ret) { + phydev_err(phydev, "Cannot initialize LEDs: %d\n", ret); + return ret; + } + + return 0; +} + +static int an8801r_probe(struct phy_device *phydev) +{ + struct device *dev =3D &phydev->mdio.dev; + struct an8801r_priv *priv; + + priv =3D devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->wake_lnkchg_enabled =3D true; + + phydev->priv =3D priv; + + /* Mark this PHY as wakeup capable and register the interrupt as a + * wakeup IRQ if the PHY is marked as a wakeup source in devicetree, + * and the interrupt is valid. + */ + if (of_property_read_bool(dev->of_node, "wakeup-source") && + phy_interrupt_is_valid(phydev)) { + device_set_wakeup_capable(dev, true); + devm_pm_set_wake_irq(dev, phydev->irq); + } + + return 0; +} + +static int an8801r_suspend(struct phy_device *phydev) +{ + struct an8801r_priv *priv =3D phydev->priv; + int ret; + + /* If the PHY may wake up by a wake-on-line event, disable the link + * interrupt to only keep the WOL magic interrupt enabled + */ + if (device_may_wakeup(&phydev->mdio.dev)) { + priv->wake_lnkchg_enabled =3D false; + + if (phydev->interrupts =3D=3D PHY_INTERRUPT_ENABLED) { + ret =3D an8801_buckpbus_reg_clear_bits(phydev, + AN8801_BPBUS_REG_WAKE_IRQ_EN, + AN8801_IRQ_WAKE_LNKCHG); + if (ret) + return ret; + } + + /* Reset Wol status */ + ret =3D an8801r_reset_wake(phydev); + if (ret) + return ret; + } + + if (!phydev->wol_enabled) + return genphy_suspend(phydev); + + return 0; +} + +static int an8801r_resume(struct phy_device *phydev) +{ + struct an8801r_priv *priv =3D phydev->priv; + int ret; + + ret =3D genphy_resume(phydev); + if (ret) + return ret; + + /* Restore the interrupt enable so phylib can receive link + * state interrupts. + */ + if (device_may_wakeup(&phydev->mdio.dev)) { + priv->wake_lnkchg_enabled =3D true; + + ret =3D an8801_buckpbus_reg_set_bits(phydev, + AN8801_BPBUS_REG_WAKEUP_CTL1, + AN8801_WOL_WAKE_LNKCHG_EN); + if (ret) + return ret; + + if (phydev->interrupts =3D=3D PHY_INTERRUPT_ENABLED) { + ret =3D an8801_buckpbus_reg_set_bits(phydev, + AN8801_BPBUS_REG_WAKE_IRQ_EN, + AN8801_IRQ_WAKE_LNKCHG); + } + } + + return ret; +} + +static struct phy_driver airoha_driver[] =3D { +{ + PHY_ID_MATCH_MODEL(AN8801R_PHY_ID), + .name =3D "Airoha AN8801R", + .probe =3D an8801r_probe, + .config_init =3D an8801r_config_init, + .suspend =3D an8801r_suspend, + .resume =3D an8801r_resume, + .config_aneg =3D genphy_config_aneg, + .config_intr =3D an8801r_config_intr, + .handle_interrupt =3D an8801r_handle_interrupt, + .set_wol =3D an8801r_set_wol, + .get_wol =3D an8801r_get_wol, + .read_page =3D air_phy_read_page, + .write_page =3D air_phy_write_page, + .flags =3D PHY_ALWAYS_CALL_SUSPEND, + .led_brightness_set =3D an8801r_led_brightness_set, + .led_blink_set =3D an8801r_led_blink_set, + .led_hw_is_supported =3D an8801r_led_hw_is_supported, + .led_hw_control_set =3D an8801r_led_hw_control_set, + .led_hw_control_get =3D an8801r_led_hw_control_get, + .led_polarity_set =3D an8801r_led_polarity_set, +} }; +module_phy_driver(airoha_driver); + +static struct mdio_device_id __maybe_unused an8801_tbl[] =3D { + { PHY_ID_MATCH_MODEL(AN8801R_PHY_ID) }, + { } +}; +MODULE_DEVICE_TABLE(mdio, an8801_tbl); + +MODULE_DESCRIPTION("Airoha AN8801 PHY driver"); +MODULE_AUTHOR("AngeloGioacchino Del Regno "); +MODULE_LICENSE("GPL"); --=20 2.54.0 From nobody Tue May 26 04:51:45 2026 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8FA9C331A66; Tue, 12 May 2026 04:33:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560441; cv=none; b=BWV8rslLc/cg2Y5n3gr3GwA78FYOzHHuxUZg+uPQhuvVNXwTwbPaVURowwBNP7fLQoJv7Ls53I/Pce5JzHAdO2XeQFWPt4go4csjLRKhwMmelFpXz9UmM8DU1HPCKRVMNa1kgsXOmkxkAoKf8JvaHnzuaJK971Yjud+jeZKTxbo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778560441; c=relaxed/simple; bh=zhnYMihbLOfkVEZ4q/kjQvAho+Gw9BO7XUM9RnKRnI8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DwTNsyxHl8CLYQoUS3sHOqB4EcOYGqLe1D3mbuqMiyYh9Eu02hmr2OO8gQGXa9RdtCUOHxFMAeH9R36vxx68c7yx4mh6f84xDONQPq+tc6mrlF85hAzZorBUMymhUcmYncYEVRNMP+4ZKPTc1lEG3hstdsPbDYbLx2pMQ7IQNwQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=j8SrvDb5; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="j8SrvDb5" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1778560434; bh=zhnYMihbLOfkVEZ4q/kjQvAho+Gw9BO7XUM9RnKRnI8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=j8SrvDb5jKutc+aAOgfmB6DpL7/FAgUUqb2Ym+CI4pqEY+6fPvqju3LEDcROXR6c8 GhbwdMidkyNuvLF0kx7oo7Oe7E1y/NMQEpr7Sc16o1lyMtBzHxM/CcdqWfmzx9E6wN X8/l9A8ACpqJZZar097p9p7zPiCPuOEv4Q9wYgh/YKgfURQvCNz6s9JhVMoAZKzzti OAZ4Er/PMLtDh1S44tjRe7TG4wpmkzwEq3hkzYan/iTftYUoiBsBwGYjnq6zAkWLsn Sk9k0jTeK8U6pulzV68NXw595XlzaSNEszybKKbzjCZCeuHfquF1uO/n8Ana5Ya4mH 2+StPZCfHecUQ== Received: from yukiji.home (unknown [100.64.0.131]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: laeyraud) by bali.collaboradmins.com (Postfix) with ESMTPSA id 1275917E38D0; Tue, 12 May 2026 06:33:53 +0200 (CEST) From: Louis-Alexis Eyraud Date: Tue, 12 May 2026 06:33:23 +0200 Subject: [PATCH net-next v3 6/6] net: phy: air_an8801: ensure maximum available speed link use Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260512-add-airoha-an8801-support-v3-6-1edb34e363ae@collabora.com> References: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> In-Reply-To: <20260512-add-airoha-an8801-support-v3-0-1edb34e363ae@collabora.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , AngeloGioacchino Del Regno , Andrew Lunn , Heiner Kallweit , Russell King Cc: kevin-kw.huang@airoha.com, macpaul.lin@mediatek.com, matthias.bgg@gmail.com, kernel@collabora.com, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Louis-Alexis Eyraud X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778560425; l=2139; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=zhnYMihbLOfkVEZ4q/kjQvAho+Gw9BO7XUM9RnKRnI8=; b=d9T+rQISrxFOFaBe5BEpNIhybPQ7T/mE0r+jxzAnoMd/s5SMIVX9pDgBRUQduTC/sMI1uMTx0 z1/pbJUG4CxAmJ3BnRae6UjsTcN/Lwq48VnZL74ZQIstjStA7rbhbbM X-Developer-Key: i=louisalexis.eyraud@collabora.com; a=ed25519; pk=CHFBDB2Kqh4EHc6JIqFn69GhxJJAzc0Zr4e8QxtumuM= To ensure that the Airoha AN8801R PHY uses the maximum available link speed, an additional register write is needed to configure the function mode for either 1G or 100M/10M operation after link detection. So, in air_an8801 driver, implement a custom read_status callback, that after genphy_read_status determines the link speed, sets the bit 0 of the link mode register (REG_LINK_MODE) if the detected speed is 1Gbps, or unsets it otherwise. Signed-off-by: Louis-Alexis Eyraud --- drivers/net/phy/air_an8801.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/net/phy/air_an8801.c b/drivers/net/phy/air_an8801.c index a0f164cbf92b..af46951b1a33 100644 --- a/drivers/net/phy/air_an8801.c +++ b/drivers/net/phy/air_an8801.c @@ -964,6 +964,36 @@ static int an8801r_config_init(struct phy_device *phyd= ev) return 0; } =20 +static int an8801r_read_status(struct phy_device *phydev) +{ + int prev_speed, ret; + u32 val; + + prev_speed =3D phydev->speed; + + ret =3D genphy_read_status(phydev); + if (ret) + return ret; + + if (phydev->link && prev_speed !=3D phydev->speed) { + /* Ensure that PHY switches to 1G speed when available, + * by configuring the function mode for either 1G or 100M/10M + * operation. + * Therefore, set the link mode register, after read_status + * determines the link speed. + */ + val =3D phydev->speed =3D=3D SPEED_1000 ? + AN8801_BPBUS_LINK_MODE_1000 : 0; + + return an8801_buckpbus_reg_rmw(phydev, + AN8801_BPBUS_REG_LINK_MODE, + AN8801_BPBUS_LINK_MODE_1000, + val); + } + + return 0; +} + static int an8801r_probe(struct phy_device *phydev) { struct device *dev =3D &phydev->mdio.dev; @@ -1061,6 +1091,7 @@ static struct phy_driver airoha_driver[] =3D { .suspend =3D an8801r_suspend, .resume =3D an8801r_resume, .config_aneg =3D genphy_config_aneg, + .read_status =3D an8801r_read_status, .config_intr =3D an8801r_config_intr, .handle_interrupt =3D an8801r_handle_interrupt, .set_wol =3D an8801r_set_wol, --=20 2.54.0