From nobody Sun May 24 21:39:30 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 437F0355F46; Thu, 21 May 2026 08:22:41 +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=1779351765; cv=none; b=UXi6g6WHK8LUXzdr+TCFhGVooXQfYq2lbsK/X2ZifZpByrxpqiqmrkpfpJ00rlpiAQ53E8K7tKqRVVClgkUBmTZjpoPq209G6uX8QCC9Dh2bND+1LKDDq7amnmZEkEdetJ4O79F22VXHUCl3Q8pLUNKnWbUkPIgrbvgmuBeimQk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779351765; c=relaxed/simple; bh=Y+IAJzkmd/rISxvlVyEkLmIzLfH8WWPE8aSMRq9pKGo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rBdTOlNoxdwrZ5m+caMAr9+is7NIHVfRufqv7S6YxvGUIzYOhmgvoYfQk+K7rS6XTyopU/eF5LrXYt4nyLKQlZPravVWkHmS1jzUou7U335e88IgXd+V8ae+PYg8U6R8jd0M5DVMfsrD1+fpQb+/yUi/ZWUiu30zEmED1qWVaE0= 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=nTxFTC0B; 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="nTxFTC0B" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1779351754; bh=Y+IAJzkmd/rISxvlVyEkLmIzLfH8WWPE8aSMRq9pKGo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=nTxFTC0BhxE765aJIxaBOV+ofGsmoZ4wfYpc1m/YKXgQ4CVaS8F+WNLxkArXEayUJ drU9Ep4GkU1v9MpjnSaIO9oT6IolH36Kujelif9hOY/EoP8omFr2HyQrH7fC+9v+3J suZe8EWiokuhpCPYyGyG14bK3vhfbJUpy9+t4LWK8FdSDuBgl6jsPB05ONJwJLdhpS Uc7LzaB5kEJzxWEh+SMC/x0XkkDoVNaVaYROKqHtFXBK1RZ//i/InExIuRa+lPet/n JfVXR8r7bVspdBpt75nwS+paVTjz4NbUsC93X+Bc0TO+DztJk5ByzqnNjX8HZYhFu6 SaMfQqQUSZSDg== 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 86B7517E1305; Thu, 21 May 2026 10:22:32 +0200 (CEST) From: Louis-Alexis Eyraud Date: Thu, 21 May 2026 10:21:54 +0200 Subject: [PATCH net-next v4 1/6] dt-bindings: net: Add support for Airoha AN8801R 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: <20260521-add-airoha-an8801-support-v4-1-1e4837d30ef4@collabora.com> References: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@collabora.com> In-Reply-To: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@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=1779351750; l=3910; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=YsYp+8rtZbrNoe09ovitl7Xxad+fzu5FOYhv2w4KdT0=; b=bPZzJxP2ZZmJVZxzmCZAJkwL8nSKR4arDuOZSjnswQBPoG/ZQBkCtWbyLGCgC1O2Ixuc4a1H3 5tBBEJbZMyeC8VNnO5PgogihaWOj/ruSCbk+n11L8zcUi/GxLHWyMyH 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 | 116 +++++++++++++++++= ++++ 1 file changed, 116 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..fb2f70ceb33a --- /dev/null +++ b/Documentation/devicetree/bindings/net/airoha,an8801.yaml @@ -0,0 +1,116 @@ +# 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: + type: object + description: + Describes the LEDs associated to the PHY + + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + patternProperties: + "^led@[0-2]$": + type: object + description: PHY LEDs + $ref: /schemas/leds/common.yaml# + + properties: + reg: + enum: [0, 1, 2] + + function-enumerator: + enum: [0, 1, 2] + description: | + Specifies a function for offloading LED functionality to the= PHY: + 0 - No offloading + 1 - Link Availability + 2 - Network Activity + + required: + - reg + + 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 Sun May 24 21:39:30 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 028B835AC20; Thu, 21 May 2026 08:22:43 +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=1779351766; cv=none; b=XglojGWqroBMdC9LdOviBsjP3NEox74GwwDo7xBq7NXrwGEgCthVoXvtjwwlXmTcG+5CuFKL1OXdS0atJAYi7iltGMs+NA1D2/JOzD/LvbeZVxFaHKBHyxKGL7Irw2UCr+jG6DJ4eSG2sUeecfild88/AtvBH72m958skAcpjiY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779351766; c=relaxed/simple; bh=KFfk0PhMePzxO9UxVYUfEp185S/glCJ9TCT8OX9EIZk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HGLP0qh/uPA0PXbft0hdyX/rhJjHEAKyiZkvwJk/0Agp9GMpGUn0oXEMvNgH+2xXjVPHOj6TWiLzSvrVl7jsjcm9f7Ka/nIQwWOBjF3FKulnJoxo/HAC1NnhmPN/HqwbwXVxlORD1Cr3Z0IRj70kgJH1Y35r3xLr1a5UlizSmkA= 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=RFqQEX0c; 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="RFqQEX0c" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1779351755; bh=KFfk0PhMePzxO9UxVYUfEp185S/glCJ9TCT8OX9EIZk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=RFqQEX0c8TJpilpd393qokbv8ryL5offnypPkd8c/qOs+6tOAvu3Gfm3ukEG/mqO6 ujAS9k7mHv2oh6C9x5wOXt7EoQd74W7eQ7e+xKxxL5zcbBLVSAGjdo9Cd/RDzoIZXt IBQiINm9+XfoT7+rarKJ7el2hNcpdR/Szhx/DJF7ucFtEb0ZtjdGRBtqipmxTUBiaN TBoc4BRG+fKUR92Nm1dVflbxfSSFgXZoMVTIyWzRzwuczhXRJQ1qz/E9P8wrMlCBA3 UnYK5vBegx93wfF3LMqUOUVHNE5I4pgE8GEY/CyPYKC5VpPHk1rGUwbmdlJ00FQ6Kk JgzszTbBXklcg== 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 3855A17E1315; Thu, 21 May 2026 10:22:34 +0200 (CEST) From: Louis-Alexis Eyraud Date: Thu, 21 May 2026 10:21:55 +0200 Subject: [PATCH net-next v4 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: <20260521-add-airoha-an8801-support-v4-2-1e4837d30ef4@collabora.com> References: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@collabora.com> In-Reply-To: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@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=1779351750; l=4623; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=KFfk0PhMePzxO9UxVYUfEp185S/glCJ9TCT8OX9EIZk=; b=iD1m0U2NoNznc6UeE9xtVIuX6Am87vVKREsllRpi0mnFlOC5+1Rnw4NqtYg+YOm7RIXDVb/KK N1UseYyZlgxDsptCEgJLHfRldwMDwHG5TDsndqONiRiaYD9Dd8NM/og 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. Reviewed-by: Andrew Lunn Signed-off-by: Louis-Alexis Eyraud --- 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 8b51bdc2e945..d969a792beb5 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 Sun May 24 21:39:30 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 A85D538425A; Thu, 21 May 2026 08:22:44 +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=1779351767; cv=none; b=K5GxWP3rJppN7cOCenRaUyNIUPP2a+Gi3BZMT4L6cnoUhb/QCWTbAlIMt71VY5kRvJbcr3Eey6wwLcTHtOOXOcJdDz7nmoItpxCGV8u6y3S9YfZ6374MF79kBX4ymcsr7hddWpeMse8PMKemkrhQruSA558oWVxpHQCbE0DEANQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779351767; c=relaxed/simple; bh=RUycHHP1Y0L/ZH0+76X6ndWUTpwKu3V/QnwT1hPq1FY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QUE2Emrkbe1UB94l2x0tti+O1tMdpnyy9NUNXUp8Ig6Vpubu2TOEneLB8RUd5dTJnsNPhr/nrS1gs28JIinQyt5MrABR4r6caOOnbCLm9aEsyfrWuHNXSd1xa01/KAgdGFVYZbXH/z3wQZF24EjZt0AGw/lXrol2fmTWv2u0EF8= 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=dcTeB416; 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="dcTeB416" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1779351757; bh=RUycHHP1Y0L/ZH0+76X6ndWUTpwKu3V/QnwT1hPq1FY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=dcTeB416Pdt5jfBMucRpLgc7AvzMTWjRLIftziWIBeoO9Ecdape1j61nQE1ibgt4J vAnU48HqvjA10IR8NUDzMkT6Zro7XyQlnOluaejhWUdNvOXNU+lJKtuZqov2nAG1hh A7DMK4Oe1ord+u5UvU0/vVGL23ntGjZqrFjXyfxaDGx7YrlwnsL/Iqhg/KnbMdWaxI aIXbhbuV7TXeIRhZe7KVAzrotIL+C9Z3McSOJp+ehEyOqjKOuHsxwaji7dJmA8EhzO umR+D4kLRCxK7bk9jC73Ea1oHsqaFtBhbND5gz0yYAuV7AtM83jfMnIWVHO24cqkvN UH5qAuKJVDZRg== 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 D3E2D17E1412; Thu, 21 May 2026 10:22:35 +0200 (CEST) From: Louis-Alexis Eyraud Date: Thu, 21 May 2026 10:21:56 +0200 Subject: [PATCH net-next v4 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: <20260521-add-airoha-an8801-support-v4-3-1e4837d30ef4@collabora.com> References: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@collabora.com> In-Reply-To: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@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=1779351750; l=12880; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=RUycHHP1Y0L/ZH0+76X6ndWUTpwKu3V/QnwT1hPq1FY=; b=TLqZjAty9JKVzTIO4APLzqs8DTIzZpmSPaQpuC4FMjkg9p9jgDV4EWXUZZGGLQfuH31PsqSm9 N0n8Iehs+kmDcKDnD1qN/22kJvCsxJSnHiwTSLZtxggA2OkFIj9C4NH 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. Reviewed-by: Andrew Lunn Signed-off-by: Louis-Alexis Eyraud --- drivers/net/phy/air_en8811h.c | 193 --------------------------------------= ---- drivers/net/phy/air_phy_lib.c | 181 +++++++++++++++++++++++++++++++++++++++ drivers/net/phy/air_phy_lib.h | 23 +++++ 3 files changed, 204 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..aba4f95fe9e6 100644 --- a/drivers/net/phy/air_phy_lib.c +++ b/drivers/net/phy/air_phy_lib.c @@ -10,11 +10,192 @@ #include #include #include +#include =20 #include "air_phy_lib.h" =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 Sun May 24 21:39:30 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 0A52131F98E; Thu, 21 May 2026 08:22:40 +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=1779351764; cv=none; b=dSXV7w5uD7DTboDpn+jQS62TqJBcINNaOPpMg6rC6J1tmyUV0nWq7QuQ+N4oBhFQEzDejVo0GSM+Mdy9SBUcOzZQ1fYlU8joERXo5hEV9HKrlafiuuuxbG2ctxTraHuDm/Vsq+f5Tr88o0I3fn/XRSsAUwohgC6ClOxWjWS8nEE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779351764; c=relaxed/simple; bh=ET2I3+lfoBkM0vWRX1UaWCbkopH2M3jyubM2in/C+LY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RlvzJhZE2nyJEg4UOMpWRP5RyHiYrPMN/tlIRZPsMQGsXS/jbU/yBBeKOc7VhiEAtxbaNhBO9VPcDfYIopQGXS28RqJYNnqIeYepyL2pKp4PHoOwGyMwdSiNtK0dSZ0UPd0/o6BEzaugABbPfvMYdI0KP21LwUzoxrpSRbtKh2c= 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=pZdJI8+R; 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="pZdJI8+R" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1779351758; bh=ET2I3+lfoBkM0vWRX1UaWCbkopH2M3jyubM2in/C+LY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=pZdJI8+RwIRxmDNlzwa09ZqvtvDS4SwvyCVfTAGXKXjSli9Ps9RXHxcrzAfmN0NWQ CvK4qD+DwBENYXo2jygtvEIUTIN+Joihuw/eGI7VN2WDygi13Dy7eWfjdVWoc8Dbxx g+gtyuGXbW60J8QrtnbhSKe+7MRHKIaCz0fiKnEFs62ewYgTooEXPNwPqYyojr+WBf /8/CGXy5EGYf3l3D9i1MKHyyvxuvCPWp6q64Ow3fqY7elzBiimBSsHYujZ+LWpPqC4 FyR8p5+IAq3xKkSzWNKdLggTMLbTyzuIz+vb8Uas2YyP5Uu5LDO7JRs7WizsssZn9a uleF4ygACYCcg== 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 72F7717E124A; Thu, 21 May 2026 10:22:37 +0200 (CEST) From: Louis-Alexis Eyraud Date: Thu, 21 May 2026 10:21:57 +0200 Subject: [PATCH net-next v4 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: <20260521-add-airoha-an8801-support-v4-4-1e4837d30ef4@collabora.com> References: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@collabora.com> In-Reply-To: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@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=1779351750; l=13356; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=ET2I3+lfoBkM0vWRX1UaWCbkopH2M3jyubM2in/C+LY=; b=ULYBlW41m/dJg0IZaZ3MmjHMYJ5rUnCjamsyzErfKDWglmyj+97CiZGnsMuJY5m08oJjzN7L/ dHDqaOc3+W/AYr4cNFjPzrXb7zjwBtxhk005GzqJjqWVXREnwhCVc97 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. Reviewed-by: Andrew Lunn Signed-off-by: Louis-Alexis Eyraud --- 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 aba4f95fe9e6..859fa41406d1 100644 --- a/drivers/net/phy/air_phy_lib.c +++ b/drivers/net/phy/air_phy_lib.c @@ -137,8 +137,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; @@ -154,10 +154,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; @@ -174,10 +174,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; @@ -194,7 +194,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 Sun May 24 21:39:30 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 B90383A3825; Thu, 21 May 2026 08:22:45 +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=1779351769; cv=none; b=AZly6h4mTWzBniKJBl0U/ywTUxeIpATWJ8YOYi7y7CiBgX6TjDUTcbLs5Eh42QnxuxH1FZohZs1J2cJOaH7qovTSC+p7uzSupa+pTiH1LyMcchSctYE8sbR8h7SPQgnYUEK9PLjNuVrFDgpqzibJJK/XdVyi/M/9lg6cfRHrAq4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779351769; c=relaxed/simple; bh=2d9HFUGF1KqwQzL8+3LwftY3F3uWVFvNr31JSfiF168=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NvRmyZl+et31YMTzmi5wx6sQ7Y+KjM/qVX7kU4DefJPyQ2IZCe6DRYJbbGsmZxI87HmCBTBnp9T3HOjprtQq1PXdaEO96JaCr8YksiDYbOjvNDwRzaqszMQah2zrjadXVwl17j7qRLv2PbniD18F0dhgSJMY2nP48utqtUqFnCc= 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=fgK3sVML; 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="fgK3sVML" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1779351760; bh=2d9HFUGF1KqwQzL8+3LwftY3F3uWVFvNr31JSfiF168=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=fgK3sVML61ZJL4cnTeDNddKCTKkiOq2VsrzU70fD6kFDj3Ky64LS6Rni9wV4p0RpX cQ2meaF1Z6Iudr9UArrbhahP7kuwyH9NuspUnadaH0V0fNzKGaAqjMrEIM3tcqjZHK g61Pr/bQGnU1zdhN8pN7/Pjxh6uWDJQ9KEX2dhssrNmnkKtMcMA8Xv3mHysNKCUzAO QRUC/v5XTBOPRPNGSMM4PUIg/H9t4ZKjlAZFyhNqS81VDm0/3roc7F5v40UL4nr2JL dI9n8coiOyeLV+L8uvyu0pUvLPeo7/6It4IHhzqzAox9lPnPOoWPpz7Kl/noFMMp7V dJl9Ka0FzFA6w== 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 2515117E125C; Thu, 21 May 2026 10:22:39 +0200 (CEST) From: Louis-Alexis Eyraud Date: Thu, 21 May 2026 10:21:58 +0200 Subject: [PATCH net-next v4 5/6] net: phy: Introduce Airoha AN8801R 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: <20260521-add-airoha-an8801-support-v4-5-1e4837d30ef4@collabora.com> References: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@collabora.com> In-Reply-To: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@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=1779351750; l=32619; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=6tq6A+Jk/NqTbXie5JtZEm4kwOSs8tSP3hCJ5MSj4/E=; b=ukvhvyYCs+RKGFhy0ctZ3fmR0eIz4+pNHWFvGxaet6+GqTkj0NXPkAuF0aqDdGppjRcLHXrTC ivJq6IvdIS6Aq/hTZZIIxs0GzHufjWM2WHueCOYJP06NxbdnIdlcIoG 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 | 1101 ++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 1108 insertions(+) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index d969a792beb5..099f25dceabb 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..73f94e84da07 --- /dev/null +++ b/drivers/net/phy/air_an8801.c @@ -0,0 +1,1101 @@ +// 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) + +/* Default RGMII TX delay setting, corresponding to a 1.883ns delay */ +#define AN8801_RGMII_TXDELAY_DEFAULT RGMII_DELAY_STEP_4 + +#define AN8801_BPBUS_REG_RXDLY_STEP 0x21c02c +#define RGMII_RXDELAY_ALIGN BIT(4) +#define RGMII_RXDELAY_FORCE_MODE BIT(24) + +/* Default RGMII RX delay setting, corresponding to a 1.992ns delay, + * when align bit is set or -0.008ns otherwise. + */ +#define AN8801_RGMII_RXDELAY_DEFAULT RGMII_DELAY_NO_STEP + +#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(3, 2) +#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 const unsigned long an8801r_led_trig =3D BIT(TRIGGER_NETDEV_LINK) | + BIT(TRIGGER_NETDEV_LINK_10) | + BIT(TRIGGER_NETDEV_LINK_100) | + BIT(TRIGGER_NETDEV_LINK_1000) | + BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_RX_ERR) | + BIT(TRIGGER_NETDEV_TX); + +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 * NSEC_PER_MSEC; + + /* 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) & + LED_BLINK_DUR_MASK); + 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) +{ + /* All combinations of the supported triggers are allowed */ + if (rules & ~an8801r_led_trig) + return -EOPNOTSUPP; + + 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; + + 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; + bool irq_handled =3D false; + 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); + irq_handled =3D true; + } + + if (irq_status & AN8801_IRQ_WAKE_LNKCHG) { + phy_trigger_machine(phydev); + irq_handled =3D true; + } + + return irq_handled ? IRQ_HANDLED : 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) + return -EINVAL; + + 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 =3D 0; + + 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) { + /* Set force mode bit to enable RX delay insertion */ + reg_val =3D delay_steps | RGMII_RXDELAY_FORCE_MODE; + + /* Set align bit to add extra offset for RX delay */ + reg_val |=3D RGMII_RXDELAY_ALIGN; + } 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) { + /* Set force mode bit to enable TX delay insertion */ + reg_val =3D delay_steps | 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 Sun May 24 21:39:30 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 B8D543A3816; Thu, 21 May 2026 08:22:45 +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=1779351767; cv=none; b=K6amoCExnKLe6Rfe5R2AMOpPpUZhpUeSa0M4YZtWY3kunLpxqxTonj0Qxzox4aETK55BMVhRBacWAPViVSoio4gX2kskQY7xC4Vw4XuLuyrkiKAYCK4JmBpWe4VCc7E/qhIcbC7HbpLn76FZaubfJUsR7eXCP7UShGefiOBAAzU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779351767; c=relaxed/simple; bh=CWjNHp3lVq1P1BWK7ilWt1phFCJ5rYaKgQ1jBzqDdC4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=taQXOwWCIEn7woJP7g07CzaHLHYUTPOtjSjDkJGP+FD7sFBKJTOpPYpEXXUH0c1qAlns2fkSVAjYlHCV2U6Q/5XXtcBwefcbICMJ4ga8HhasXmp+oU6FDnYju3dOEbp9JUlYAyJo+xeM7Js++IWGdCM+A6H0WpqL7XzkyENm1tc= 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=eYn7FEC4; 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="eYn7FEC4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1779351762; bh=CWjNHp3lVq1P1BWK7ilWt1phFCJ5rYaKgQ1jBzqDdC4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=eYn7FEC4jU99Os15lM7ysV8MVNZ5cDHrPV2RrLJtQyJZNSfSx/3nLbeQgY1RQY7LK 9cRRM3OJ/cBeavnPMiX0r6yQoePltpsfq9TmBRiUXrX4RtGhi45b5Ft/GkcarK1cO2 TcXKgQWdUV87RHJ+Kp12fnCFlWTiEudDkB4gFFDkrw97reER9a64jHA+FOwPNTxgVt FA4lE+zLw+ecA3oM8Il7MHo0htM6qZek0vj31XvRCVDf8OyUEGXX6IMRIzD+qbAz+L fY3q9HbPVCXJRbvlpfQAiSYLKFgj7jLBLTB8i9dk9GpQ1Swo7j/rWs9P/rcPFhp+mo /ikV7Mg9pt15Q== 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 CADAE17E132E; Thu, 21 May 2026 10:22:40 +0200 (CEST) From: Louis-Alexis Eyraud Date: Thu, 21 May 2026 10:21:59 +0200 Subject: [PATCH net-next v4 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: <20260521-add-airoha-an8801-support-v4-6-1e4837d30ef4@collabora.com> References: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@collabora.com> In-Reply-To: <20260521-add-airoha-an8801-support-v4-0-1e4837d30ef4@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=1779351750; l=2402; i=louisalexis.eyraud@collabora.com; s=20250113; h=from:subject:message-id; bh=CWjNHp3lVq1P1BWK7ilWt1phFCJ5rYaKgQ1jBzqDdC4=; b=VyzIoCdpeWn8XvAgkZ+U0CxFZMGW7ROgymrXgmziebcmXzI3bFPS7IqXSmZswrGGXY0MFsfe6 dQXDwoabVL4DJO8krNlUYO3VktXt3im52mbwf5gN+b3TNutVvD0dUPM 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 | 43 ++++++++++++++++++++++++++++++++++++++++= +++ 1 file changed, 43 insertions(+) diff --git a/drivers/net/phy/air_an8801.c b/drivers/net/phy/air_an8801.c index 73f94e84da07..c64fa153b738 100644 --- a/drivers/net/phy/air_an8801.c +++ b/drivers/net/phy/air_an8801.c @@ -977,6 +977,48 @@ 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) { + phydev->speed =3D SPEED_UNKNOWN; + return 0; + } + + if (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; + + ret =3D an8801_buckpbus_reg_rmw(phydev, + AN8801_BPBUS_REG_LINK_MODE, + AN8801_BPBUS_LINK_MODE_1000, + val); + if (ret) { + /* Restore previous speed on failure to ensure this + * register setting is retried on the next poll + */ + phydev->speed =3D prev_speed; + return ret; + } + } + + return 0; +} + static int an8801r_probe(struct phy_device *phydev) { struct device *dev =3D &phydev->mdio.dev; @@ -1074,6 +1116,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