{"id":2228300,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2228300/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/patch/20260423-add-ethernet-support-for-genio-520-720-v1-5-47ca918e0017@baylibre.com/","project":{"id":18,"url":"http://patchwork.ozlabs.org/api/1.1/projects/18/?format=json","name":"U-Boot","link_name":"uboot","list_id":"u-boot.lists.denx.de","list_email":"u-boot@lists.denx.de","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<20260423-add-ethernet-support-for-genio-520-720-v1-5-47ca918e0017@baylibre.com>","date":"2026-04-23T13:25:56","name":"[5/9] net: phy: air_phy_lib: Factorize BuckPBus register","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"625512c09514f2c8759e33e2db97ca4f3401e7ca","submitter":{"id":84831,"url":"http://patchwork.ozlabs.org/api/1.1/people/84831/?format=json","name":"Julien Stephan","email":"jstephan@baylibre.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/uboot/patch/20260423-add-ethernet-support-for-genio-520-720-v1-5-47ca918e0017@baylibre.com/mbox/","series":[{"id":501460,"url":"http://patchwork.ozlabs.org/api/1.1/series/501460/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/list/?series=501460","date":"2026-04-23T13:25:57","name":"Add ethernet support for genio 520/720 EVK boards","version":1,"mbox":"http://patchwork.ozlabs.org/series/501460/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2228300/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2228300/checks/","tags":{},"headers":{"Return-Path":"<u-boot-bounces@lists.denx.de>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=baylibre-com.20251104.gappssmtp.com\n header.i=@baylibre-com.20251104.gappssmtp.com header.a=rsa-sha256\n header.s=20251104 header.b=nkpMmnYn;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)","phobos.denx.de;\n dmarc=none (p=none dis=none) header.from=baylibre.com","phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de","phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=baylibre-com.20251104.gappssmtp.com\n header.i=@baylibre-com.20251104.gappssmtp.com header.b=\"nkpMmnYn\";\n\tdkim-atps=neutral","phobos.denx.de;\n dmarc=none (p=none dis=none) header.from=baylibre.com","phobos.denx.de;\n spf=pass smtp.mailfrom=jstephan@baylibre.com"],"Received":["from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g32VR0pZrz1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Sun, 26 Apr 2026 07:08:15 +1000 (AEST)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 0621B84422;\n\tSat, 25 Apr 2026 23:08:04 +0200 (CEST)","by phobos.denx.de (Postfix, from userid 109)\n id 7EEFA84514; Sat, 25 Apr 2026 22:53:56 +0200 (CEST)","from mail-wr1-x430.google.com (mail-wr1-x430.google.com\n [IPv6:2a00:1450:4864:20::430])\n (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 740FA84329\n for <u-boot@lists.denx.de>; Sat, 25 Apr 2026 22:53:53 +0200 (CEST)","by mail-wr1-x430.google.com with SMTP id\n ffacd0b85a97d-43d73422431so8072628f8f.2\n for <u-boot@lists.denx.de>; Sat, 25 Apr 2026 13:53:53 -0700 (PDT)","from [192.168.1.100]\n (2a02-842a-d52e-6101-56a2-efb9-07f1-cf08.rev.sfr.net.\n [2a02:842a:d52e:6101:56a2:efb9:7f1:cf08])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-4891bb3d121sm500300885e9.14.2026.04.23.06.26.04\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 23 Apr 2026 06:26:06 -0700 (PDT)"],"X-Spam-Checker-Version":"SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de","X-Spam-Level":"","X-Spam-Status":"No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham\n autolearn_force=no version=3.4.2","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=baylibre-com.20251104.gappssmtp.com; s=20251104; t=1777150432;\n x=1777755232;\n darn=lists.denx.de;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:from:to:cc:subject:date:message-id\n :reply-to; bh=OqUqBsl7kIUdZCD3faFvhnVIGA6HBu1Xz03kb0w+fsA=;\n b=nkpMmnYndg7U66weEcW0A9WhOeJQjXLJVWzbCCj6DjXVB59l9SKAc8LZ00FAHIo/iA\n DytPhE9UeidK8vGaL7MososZvdWbRVZYMhzvyClQ8C81aIr0QtVcGMKcW57/AyQGJoN+\n 6GHjLKPtSxCgK9DJWzO80z3FJLBGci1H68Rh8/fjf8hkSS/GwKPHDgqYDzjdooDeqBv8\n rDSercceccnZTwRmMeMFQO2aaSg6jTfZ3Nw6qmClu5xZ/19miCSZT/hXc/o419FUaElV\n EnzrO2ippK2bPHaROFfhEurMiSQyb8B0HhLEOq/cRzqtQsXu7P0N7bTGe3aWmHUvVBuP\n ScIg==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777150432; x=1777755232;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=OqUqBsl7kIUdZCD3faFvhnVIGA6HBu1Xz03kb0w+fsA=;\n b=HXBu71K6+ZGCIh0ogv5U3BlruozOIwbIERIqu0wzRtzVXTAhANNrVCXhXh5YJgckZ0\n tqIqZxlmQkpTNK7P3ZYqJWJl/hruzw6i8B5p5QKFfCcTyfBoXeGGWhdSqQ/vdk56yhpJ\n NFFlUqc9MihhT9sh84vE2jWGLkf0Ctt+ff77yYiKbOI9vdgQo47jxfzsHag+/AZTfgCm\n G6l3ABlO1r+ki1AVAn0JDElnoWimT1tUcXEAjMn/fXRlxQMPQPW1m67zyUPSafnrAuEj\n UQYRSQTSwoisYwpv5Q7pEPKkVGriBpVRtI58RVt9eHGKKAMhX3Lz2sg+hVzlz/0MnBOK\n Q8BQ==","X-Gm-Message-State":"AOJu0Yxb0fjamsf32OujEGilTnIIx1bZU+QIMjiRl0InLST6o9zwUbVl\n YkP+rZuTup2fA+Cg2W4R7zfe7qjYZ+uG48pexDdryNfJd9l5NhCQ+YuANOKwodYIkPX3ZSSkyXa\n mIGRMCks=","X-Gm-Gg":"AeBDievyFZaEvnAO6DirvktArepDbDAhRGClV77V6NQNCA4ME/AXm+nX4k1kMbTA+lP\n oLnEGqxsKgssKDB0I38Qfbr76flzYptGwp7z1YslCLUXH+gZT1kGMAB/2ZFeuf6MGGGpD7uir+Y\n Tq4wqia/qIKBV2mTD42dqupNaDyv5xGQiD+ISc5ZNriAw+VuquvcoNzEDawn0f3UFhumh/Yl5ss\n ea+HflaOOhcqrvNxtvTCnGWrf3mir5j6SAwvwm8XePAntUAA2nHxNvUndo2n6WOoyWv4BlgugBS\n 3qIJbYVtFV8jLamJV59Bl3KHNL5LzQRJUacHQbhdnIPZaaYAetCa7hSZ73fPLZGiiYi+/OyDr1N\n NvPUDU0X2NgLDPsQ+EWAyHQ+H6Nrz4WGK/LcS6iCLniXBGaH09UmHLVcMwpINn1IiH0XtlYZXRE\n tdr9NunfDKrYT7wQrI/cZVwg0nrrDAcwdRo+KI8iuTnTs6Bi5Z21Cj1QPx9WSzMvKYm4VXvTN9E\n EpLejfNi6R3xWo1G6xOXka7Ubzz29TZEOkoDwF3+sNzh+/LdSWzprq/Kamawrn/L8C4WKSSFIOV\n oUw7R0t8W+o9RuMCwQ==","X-Received":"by 2002:a05:600c:444a:b0:487:1520:d107 with SMTP id\n 5b1f17b1804b1-488fb793580mr361390725e9.31.1776950766974;\n Thu, 23 Apr 2026 06:26:06 -0700 (PDT)","From":"Julien Stephan <jstephan@baylibre.com>","Date":"Thu, 23 Apr 2026 15:25:56 +0200","Subject":"[PATCH 5/9] net: phy: air_phy_lib: Factorize BuckPBus register","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"7bit","Message-Id":"\n <20260423-add-ethernet-support-for-genio-520-720-v1-5-47ca918e0017@baylibre.com>","References":"\n <20260423-add-ethernet-support-for-genio-520-720-v1-0-47ca918e0017@baylibre.com>","In-Reply-To":"\n <20260423-add-ethernet-support-for-genio-520-720-v1-0-47ca918e0017@baylibre.com>","To":"u-boot@lists.denx.de","Cc":"GSS_MTK_Uboot_upstream <GSS_MTK_Uboot_upstream@mediatek.com>,\n Jerome Forissier <jerome.forissier@arm.com>, Tom Rini <trini@konsulko.com>,\n Christian Marangi <ansuelsmth@gmail.com>,\n Robert Marko <robert.marko@sartura.hr>, Simon Glass <sjg@chromium.org>,\n Yao Zi <me@ziyao.cc>, Quentin Schulz <quentin.schulz@cherry.de>,\n Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>,\n Marek Vasut <marek.vasut+renesas@mailbox.org>,\n \"Lucien.Jheng\" <lucienzx159@gmail.com>,\n Weijie Gao <weijie.gao@mediatek.com>,\n Romain Gantois <romain.gantois@bootlin.com>,\n Siddharth Vadapalli <s-vadapalli@ti.com>,\n Yanqing Wang <ot_yanqing.wang@mediatek.com>, Beiyan Yun <root@infi.wang>,\n Ryder Lee <ryder.lee@mediatek.com>,\n Chunfeng Yun <chunfeng.yun@mediatek.com>,\n Igor Belwon <igor.belwon@mentallysanemainliners.org>,\n David Lechner <dlechner@baylibre.com>,\n Neil Armstrong <neil.armstrong@linaro.org>,\n Kory Maincent <kory.maincent@bootlin.com>,\n Ilias Apalodimas <ilias.apalodimas@linaro.org>,\n Kuan-Wei Chiu <visitorckw@gmail.com>,\n Raymond Mao <raymond.mao@riscstar.com>, Peng Fan <peng.fan@nxp.com>,\n Stefan Roese <stefan.roese@mailbox.org>,\n Philip Molloy <philip.molloy@analog.com>,\n fanyi zhang <fanyi.zhang@mediatek.com>, Jonas Karlman <jonas@kwiboo.se>,\n Kever Yang <kever.yang@rock-chips.com>,\n Marek Vasut <marek.vasut@mailbox.org>,\n Patrick Delaunay <patrick.delaunay@foss.st.com>,\n Heiko Stuebner <heiko@sntech.de>,\n Samuel Holland <samuel.holland@sifive.com>,\n Christophe Roullier <christophe.roullier@foss.st.com>,\n Patrice Chotard <patrice.chotard@foss.st.com>,\n Chris-QJ Chen <chris-qj.chen@mediatek.com>,\n Macpaul Lin <macpaul.lin@mediatek.com>,\n Sam Protsenko <semen.protsenko@linaro.org>,\n Michael Trimarchi <michael@amarulasolutions.com>,\n Sky Huang <SkyLake.Huang@mediatek.com>,\n Leo Yu-Chi Liang <ycliang@andestech.com>,\n Tommy Shih <tommy.shih@airoha.com>,\n Kevin-KW Huang <kevin-kw.huang@airoha.com>,\n Julien Stephan <jstephan@baylibre.com>","X-Mailer":"b4 0.14.3","X-Mailman-Approved-At":"Sat, 25 Apr 2026 23:08:00 +0200","X-BeenThere":"u-boot@lists.denx.de","X-Mailman-Version":"2.1.39","Precedence":"list","List-Id":"U-Boot discussion <u-boot.lists.denx.de>","List-Unsubscribe":"<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>","List-Archive":"<https://lists.denx.de/pipermail/u-boot/>","List-Post":"<mailto:u-boot@lists.denx.de>","List-Help":"<mailto:u-boot-request@lists.denx.de?subject=help>","List-Subscribe":"<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>","Errors-To":"u-boot-bounces@lists.denx.de","Sender":"\"U-Boot\" <u-boot-bounces@lists.denx.de>","X-Virus-Scanned":"clamav-milter 0.103.8 at phobos.denx.de","X-Virus-Status":"Clean"},"content":"In preparation of Airoha AN8801R PHY support, move the BuckPBus\nregister accessors and definitions, present in air_en8811h driver,\ninto the Airoha PHY shared code (air_phy_lib), so they will be usable\nby the new driver without duplicating them.\nAlso, update air_en8811h driver to use the new function names.\n\nAdapted from [1].\n\n[1]: https://lore.kernel.org/all/20260326-add-airoha-an8801-support-v2-2-1a42d6b6050f@collabora.com/\n\nSigned-off-by: Julien Stephan <jstephan@baylibre.com>\n---\n MAINTAINERS                          |   2 +-\n drivers/net/phy/airoha/Kconfig       |   6 +\n drivers/net/phy/airoha/Makefile      |   1 +\n drivers/net/phy/airoha/air_en8811.c  | 276 +++++++----------------------------\n drivers/net/phy/airoha/air_phy_lib.c | 221 ++++++++++++++++++++++++++++\n drivers/net/phy/airoha/air_phy_lib.h |  39 +++++\n 6 files changed, 320 insertions(+), 225 deletions(-)","diff":"diff --git a/MAINTAINERS b/MAINTAINERS\nindex 40ba3542ca3..4bda6b9e8c4 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -61,7 +61,7 @@ F:\tlib/acpi/\n AIROHA PHY\n M:\tTommy Shih <tommy.shih@airoha.com>\n S:\tMaintained\n-F:\tdrivers/net/phy/airoha/air_en8811.c\n+F:\tdrivers/net/phy/airoha/\n \n ALIST\n M:\tSimon Glass <sjg@chromium.org>\ndiff --git a/drivers/net/phy/airoha/Kconfig b/drivers/net/phy/airoha/Kconfig\nindex da8747939e3..2a2f4f05bb2 100644\n--- a/drivers/net/phy/airoha/Kconfig\n+++ b/drivers/net/phy/airoha/Kconfig\n@@ -7,6 +7,12 @@ config PHY_AIROHA_EN8811\n \tdepends on PHY_AIROHA\n \tdepends on SUPPORTS_FW_LOADER\n \tselect FW_LOADER\n+\tselect PHY_AIRONA_PHYLIB\n \thelp\n \t  AIROHA EN8811H supported.\n \t  AIROHA AN8811HB supported.\n+\n+config PHY_AIRONA_PHYLIB\n+\ttristate\n+\thelp\n+\t  Airoha Ethernet PHY common library\ndiff --git a/drivers/net/phy/airoha/Makefile b/drivers/net/phy/airoha/Makefile\nindex 84d23b19ab0..cbf123986f2 100644\n--- a/drivers/net/phy/airoha/Makefile\n+++ b/drivers/net/phy/airoha/Makefile\n@@ -1,3 +1,4 @@\n # SPDX-License-Identifier: GPL-2.0\n \n obj-$(CONFIG_PHY_AIROHA_EN8811) += air_en8811.o\n+obj-$(CONFIG_PHY_AIRONA_PHYLIB) += air_phy_lib.o\ndiff --git a/drivers/net/phy/airoha/air_en8811.c b/drivers/net/phy/airoha/air_en8811.c\nindex 0b974472732..04b7282072d 100644\n--- a/drivers/net/phy/airoha/air_en8811.c\n+++ b/drivers/net/phy/airoha/air_en8811.c\n@@ -24,6 +24,8 @@\n #include <dm/device_compat.h>\n #include <u-boot/crc.h>\n \n+#include \"air_phy_lib.h\"\n+\n /* MII Registers */\n #define AIR_AUX_CTRL_STATUS\t\t0x1d\n #define AIR_AUX_CTRL_STATUS_SPEED_MASK\tGENMASK(4, 2)\n@@ -32,10 +34,6 @@\n #define AIR_AUX_CTRL_STATUS_SPEED_1000\t0x8\n #define AIR_AUX_CTRL_STATUS_SPEED_2500\t0xc\n \n-#define AIR_EXT_PAGE_ACCESS\t\t0x1f\n-#define AIR_PHY_PAGE_STANDARD\t\t0x0000\n-#define AIR_PHY_PAGE_EXTENDED_4\t\t0x0004\n-\n #define AIR_PBUS_MODE_ADDR_HIGH\t\t0x1c\n /* MII Registers Page 4 */\n #define AIR_BPBUS_MODE\t\t\t0x10\n@@ -309,166 +307,6 @@ static int air_pbus_reg_write(struct phy_device *phydev,\n \treturn ret;\n }\n \n-static int air_buckpbus_reg_write(struct phy_device *phydev,\n-\t\t\t\t  u32 pbus_address, u32 pbus_data)\n-{\n-\tint ret, saved_page;\n-\n-\tsaved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);\n-\tif (saved_page < 0)\n-\t\treturn saved_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,\n-\t\t\tAIR_BPBUS_MODE_ADDR_FIXED);\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_HIGH,\n-\t\t\tupper_16_bits(pbus_address));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_LOW,\n-\t\t\tlower_16_bits(pbus_address));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_HIGH,\n-\t\t\tupper_16_bits(pbus_data));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_LOW,\n-\t\t\tlower_16_bits(pbus_data));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-restore_page:\n-\tif (ret < 0)\n-\t\tdev_err(phydev->dev, \"%s 0x%08x failed: %d\\n\", __func__,\n-\t\t\tpbus_address, ret);\n-\n-\treturn phy_restore_page(phydev, saved_page, ret);\n-}\n-\n-static int air_buckpbus_reg_read(struct phy_device *phydev,\n-\t\t\t\t u32 pbus_address, u32 *pbus_data)\n-{\n-\tint pbus_data_low, pbus_data_high;\n-\tint ret = 0, saved_page;\n-\n-\tsaved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);\n-\tif (saved_page < 0)\n-\t\treturn saved_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,\n-\t\t\tAIR_BPBUS_MODE_ADDR_FIXED);\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_HIGH,\n-\t\t\tupper_16_bits(pbus_address));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_LOW,\n-\t\t\tlower_16_bits(pbus_address));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tpbus_data_high = phy_read(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_DATA_HIGH);\n-\tif (pbus_data_high < 0) {\n-\t\tret = pbus_data_high;\n-\t\tgoto restore_page;\n-\t}\n-\n-\tpbus_data_low = phy_read(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_DATA_LOW);\n-\tif (pbus_data_low < 0) {\n-\t\tret = pbus_data_low;\n-\t\tgoto restore_page;\n-\t}\n-\n-\t*pbus_data = pbus_data_low | (pbus_data_high << 16);\n-\n-restore_page:\n-\tif (ret < 0)\n-\t\tdev_err(phydev->dev, \"%s 0x%08x failed: %d\\n\", __func__,\n-\t\t\tpbus_address, ret);\n-\n-\treturn phy_restore_page(phydev, saved_page, ret);\n-}\n-\n-static int air_buckpbus_reg_modify(struct phy_device *phydev,\n-\t\t\t\t   u32 pbus_address, u32 mask, u32 set)\n-{\n-\tint pbus_data_low, pbus_data_high;\n-\tu32 pbus_data_old, pbus_data_new;\n-\tint ret = 0, saved_page;\n-\n-\tsaved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);\n-\tif (saved_page < 0)\n-\t\treturn saved_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,\n-\t\t\tAIR_BPBUS_MODE_ADDR_FIXED);\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_HIGH,\n-\t\t\tupper_16_bits(pbus_address));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_LOW,\n-\t\t\tlower_16_bits(pbus_address));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tpbus_data_high = phy_read(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_DATA_HIGH);\n-\tif (pbus_data_high < 0) {\n-\t\tret = pbus_data_high;\n-\t\tgoto restore_page;\n-\t}\n-\n-\tpbus_data_low = phy_read(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_DATA_LOW);\n-\tif (pbus_data_low < 0) {\n-\t\tret = pbus_data_low;\n-\t\tgoto restore_page;\n-\t}\n-\n-\tpbus_data_old = pbus_data_low | (pbus_data_high << 16);\n-\tpbus_data_new = (pbus_data_old & ~mask) | set;\n-\tif (pbus_data_new == pbus_data_old)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_HIGH,\n-\t\t\tupper_16_bits(pbus_address));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_LOW,\n-\t\t\tlower_16_bits(pbus_address));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_HIGH,\n-\t\t\tupper_16_bits(pbus_data_new));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_LOW,\n-\t\t\tlower_16_bits(pbus_data_new));\n-\tif (ret < 0)\n-\t\tgoto restore_page;\n-\n-restore_page:\n-\tif (ret < 0)\n-\t\tdev_err(phydev->dev, \"%s 0x%08x failed: %d\\n\", __func__,\n-\t\t\tpbus_address, ret);\n-\n-\treturn phy_restore_page(phydev, saved_page, ret);\n-}\n-\n static int air_write_buf(struct phy_device *phydev, unsigned long address,\n \t\t\t unsigned long array_size, const unsigned char *buffer)\n {\n@@ -539,12 +377,12 @@ static int an8811hb_check_crc(struct phy_device *phydev,\n \tu32 pbus_value;\n \n \t/* Configure CRC */\n-\tret = air_buckpbus_reg_modify(phydev, set1, AN8811HB_CRC_RD_EN,\n-\t\t\t\t      AN8811HB_CRC_RD_EN);\n+\tret = air_phy_buckpbus_reg_modify(phydev, set1, AN8811HB_CRC_RD_EN,\n+\t\t\t\t\t  AN8811HB_CRC_RD_EN);\n \tif (ret < 0)\n \t\treturn ret;\n \n-\tret = air_buckpbus_reg_read(phydev, set1, &pbus_value);\n+\tret = air_phy_buckpbus_reg_read(phydev, set1, &pbus_value);\n \tif (ret < 0)\n \t\treturn ret;\n \n@@ -553,14 +391,14 @@ static int an8811hb_check_crc(struct phy_device *phydev,\n \tdo {\n \t\tmdelay(300);\n \n-\t\tret = air_buckpbus_reg_read(phydev, mon2, &pbus_value);\n+\t\tret = air_phy_buckpbus_reg_read(phydev, mon2, &pbus_value);\n \t\tif (ret < 0)\n \t\t\treturn ret;\n \n \t\tdebug(\"%d: reg 0x%x val 0x%x!\\n\", __LINE__, mon2, pbus_value);\n \n \t\tif (pbus_value & AN8811HB_CRC_ST) {\n-\t\t\tret = air_buckpbus_reg_read(phydev, mon3, &pbus_value);\n+\t\t\tret = air_phy_buckpbus_reg_read(phydev, mon3, &pbus_value);\n \t\t\tif (ret < 0)\n \t\t\t\treturn ret;\n \n@@ -584,11 +422,11 @@ static int an8811hb_check_crc(struct phy_device *phydev,\n \t\t}\n \t} while (--retry);\n \n-\tret = air_buckpbus_reg_modify(phydev, set1, AN8811HB_CRC_RD_EN, 0);\n+\tret = air_phy_buckpbus_reg_modify(phydev, set1, AN8811HB_CRC_RD_EN, 0);\n \tif (ret < 0)\n \t\treturn ret;\n \n-\tret = air_buckpbus_reg_read(phydev, set1, &pbus_value);\n+\tret = air_phy_buckpbus_reg_read(phydev, set1, &pbus_value);\n \tif (ret < 0)\n \t\treturn ret;\n \n@@ -646,8 +484,8 @@ static int an8811hb_surge_protect_cfg(struct phy_device *phydev)\n \t\treturn ret;\n \t}\n \n-\tret = air_buckpbus_reg_modify(phydev, AIR_PHY_CONTROL,\n-\t\t\t\t      AIR_PHY_CONTROL_SURGE_5R,\n+\tret = air_phy_buckpbus_reg_modify(phydev, AIR_PHY_CONTROL,\n+\t\t\t\t\t  AIR_PHY_CONTROL_SURGE_5R,\n \t\t\t\t      AIR_PHY_CONTROL_SURGE_5R);\n \tif (ret < 0)\n \t\treturn ret;\n@@ -706,13 +544,13 @@ static int en8811h_load_firmware(struct phy_device *phydev)\n \t\tgoto en8811h_load_firmware_out;\n \t}\n \n-\tret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,\n-\t\t\t\t     EN8811H_FW_CTRL_1_START);\n+\tret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,\n+\t\t\t\t\t EN8811H_FW_CTRL_1_START);\n \tif (ret < 0)\n \t\tgoto en8811h_load_firmware_out;\n \n-\tret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,\n-\t\t\t\t      EN8811H_FW_CTRL_2_LOADING,\n+\tret = air_phy_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,\n+\t\t\t\t\t  EN8811H_FW_CTRL_2_LOADING,\n \t\t\t\t      EN8811H_FW_CTRL_2_LOADING);\n \tif (ret < 0)\n \t\tgoto en8811h_load_firmware_out;\n@@ -727,13 +565,13 @@ static int en8811h_load_firmware(struct phy_device *phydev)\n \tif (ret < 0)\n \t\tgoto en8811h_load_firmware_out;\n \n-\tret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,\n-\t\t\t\t      EN8811H_FW_CTRL_2_LOADING, 0);\n+\tret = air_phy_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,\n+\t\t\t\t\t  EN8811H_FW_CTRL_2_LOADING, 0);\n \tif (ret < 0)\n \t\tgoto en8811h_load_firmware_out;\n \n-\tret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,\n-\t\t\t\t     EN8811H_FW_CTRL_1_FINISH);\n+\tret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,\n+\t\t\t\t\t EN8811H_FW_CTRL_1_FINISH);\n \tif (ret < 0)\n \t\tgoto en8811h_load_firmware_out;\n \n@@ -741,8 +579,8 @@ static int en8811h_load_firmware(struct phy_device *phydev)\n \tif (ret < 0)\n \t\tgoto en8811h_load_firmware_out;\n \n-\tair_buckpbus_reg_read(phydev, EN8811H_FW_VERSION,\n-\t\t\t      &priv->firmware_version);\n+\tair_phy_buckpbus_reg_read(phydev, EN8811H_FW_VERSION,\n+\t\t\t\t  &priv->firmware_version);\n \n \tdev_info(phydev->dev, \"MD32 firmware version: %08x\\n\",\n \t\t priv->firmware_version);\n@@ -778,8 +616,8 @@ static int an8811hb_load_firmware(struct phy_device *phydev)\n \tif (ret < 0)\n \t\tgoto an8811hb_load_firmware_out;\n \n-\tret = air_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,\n-\t\t\t\t     AIR_PHY_FW_CTRL_1_START);\n+\tret = air_phy_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,\n+\t\t\t\t\t AIR_PHY_FW_CTRL_1_START);\n \tif (ret < 0)\n \t\tgoto an8811hb_load_firmware_out;\n \n@@ -803,8 +641,8 @@ static int an8811hb_load_firmware(struct phy_device *phydev)\n \tif (ret < 0)\n \t\tgoto an8811hb_load_firmware_out;\n \n-\tret = air_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,\n-\t\t\t\t     AIR_PHY_FW_CTRL_1_FINISH);\n+\tret = air_phy_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,\n+\t\t\t\t\t AIR_PHY_FW_CTRL_1_FINISH);\n \tif (ret < 0)\n \t\tgoto an8811hb_load_firmware_out;\n \n@@ -817,7 +655,7 @@ static int an8811hb_load_firmware(struct phy_device *phydev)\n \tdo {\n \t\tmdelay(300);\n \n-\t\tret = air_buckpbus_reg_read(phydev, AIR_PHY_FW_CTRL_1, &reg_val);\n+\t\tret = air_phy_buckpbus_reg_read(phydev, AIR_PHY_FW_CTRL_1, &reg_val);\n \t\tif (ret < 0)\n \t\t\tgoto an8811hb_load_firmware_out;\n \n@@ -827,8 +665,8 @@ static int an8811hb_load_firmware(struct phy_device *phydev)\n \t\tdebug(\"%d: reg 0x%x val 0x%x!\\n\", __LINE__, AIR_PHY_FW_CTRL_1,\n \t\t      reg_val);\n \n-\t\tret = air_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,\n-\t\t\t\t\t     AIR_PHY_FW_CTRL_1_FINISH);\n+\t\tret = air_phy_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,\n+\t\t\t\t\t\t AIR_PHY_FW_CTRL_1_FINISH);\n \t\tif (ret < 0)\n \t\t\tgoto an8811hb_load_firmware_out;\n \n@@ -838,8 +676,8 @@ static int an8811hb_load_firmware(struct phy_device *phydev)\n \tif (ret < 0)\n \t\tgoto an8811hb_load_firmware_out;\n \n-\tair_buckpbus_reg_read(phydev, AIR_PHY_MD32FW_VERSION,\n-\t\t\t      &priv->firmware_version);\n+\tair_phy_buckpbus_reg_read(phydev, AIR_PHY_MD32FW_VERSION,\n+\t\t\t\t  &priv->firmware_version);\n \n \tdebug(\"MD32 firmware version: %08x\\n\", priv->firmware_version);\n \n@@ -858,8 +696,8 @@ int an8811hb_cko_cfg(struct phy_device *phydev)\n \tint ret = 0;\n \n \tif (!ofnode_read_bool(node, \"airoha,phy-output-clock\")) {\n-\t\tret = air_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV,\n-\t\t\t\t\t      AN8811HB_CLK_DRV_CKO_MASK,\n+\t\tret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV,\n+\t\t\t\t\t\t  AN8811HB_CLK_DRV_CKO_MASK,\n \t\t\t\t\t      AN8811HB_CLK_DRV_CKOPWD    |\n \t\t\t\t\t      AN8811HB_CLK_DRV_CKO_LDPWD |\n \t\t\t\t\t      AN8811HB_CLK_DRV_CKO_LPPWD);\n@@ -868,7 +706,7 @@ int an8811hb_cko_cfg(struct phy_device *phydev)\n \n \t\tdebug(\"CKO Output mode - Disabled\\n\");\n \t} else {\n-\t\tret = air_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value);\n+\t\tret = air_phy_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value);\n \t\tif (ret < 0)\n \t\t\treturn ret;\n \n@@ -887,12 +725,12 @@ static int en8811h_restart_mcu(struct phy_device *phydev)\n \tif (ret < 0)\n \t\treturn ret;\n \n-\tret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,\n-\t\t\t\t     EN8811H_FW_CTRL_1_START);\n+\tret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,\n+\t\t\t\t\t EN8811H_FW_CTRL_1_START);\n \tif (ret < 0)\n \t\treturn ret;\n \n-\treturn air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,\n+\treturn air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,\n \t\t\t\t      EN8811H_FW_CTRL_1_FINISH);\n }\n \n@@ -1091,8 +929,8 @@ static int en8811h_config(struct phy_device *phydev)\n \t\tpbus_value &= ~EN8811H_POLARITY_TX_NORMAL;\n \telse\n \t\tpbus_value |=  EN8811H_POLARITY_TX_NORMAL;\n-\tret = air_buckpbus_reg_modify(phydev, EN8811H_POLARITY,\n-\t\t\t\t      EN8811H_POLARITY_RX_REVERSE |\n+\tret = air_phy_buckpbus_reg_modify(phydev, EN8811H_POLARITY,\n+\t\t\t\t\t  EN8811H_POLARITY_RX_REVERSE |\n \t\t\t\t      EN8811H_POLARITY_TX_NORMAL,\n \t\t\t\t      pbus_value);\n \tif (ret < 0)\n@@ -1142,12 +980,12 @@ static int an8811hb_config(struct phy_device *phydev)\n \t\tpriv->mcu_needs_restart = true;\n \t}\n \n-\tret = air_buckpbus_reg_read(phydev, AN8811HB_PRO_ID, &pbus_value);\n+\tret = air_phy_buckpbus_reg_read(phydev, AN8811HB_PRO_ID, &pbus_value);\n \tif (ret < 0)\n \t\treturn ret;\n \tpriv->pro_id = (pbus_value & AN8811HB_PRO_ID_VERSION) + 1;\n \n-\tret = air_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value);\n+\tret = air_phy_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value);\n \tif (ret < 0)\n \t\treturn ret;\n \tpriv->pkg_sel = (pbus_value & AN8811HB_HWTRAP2_PKG) >> 12;\n@@ -1163,8 +1001,8 @@ static int an8811hb_config(struct phy_device *phydev)\n \t\tpbus_value |= AN8811HB_RX_POLARITY_NORMAL;\n \n \tdebug(\"1 pbus_value 0x%x\\n\", pbus_value);\n-\tret = air_buckpbus_reg_modify(phydev, AN8811HB_RX_POLARITY,\n-\t\t\t\t      AN8811HB_RX_POLARITY_NORMAL, pbus_value);\n+\tret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_RX_POLARITY,\n+\t\t\t\t\t  AN8811HB_RX_POLARITY_NORMAL, pbus_value);\n \tif (ret < 0)\n \t\treturn ret;\n \n@@ -1175,34 +1013,34 @@ static int an8811hb_config(struct phy_device *phydev)\n \t\tpbus_value |= AN8811HB_TX_POLARITY_NORMAL;\n \n \tdebug(\"2 pbus_value 0x%x\\n\", pbus_value);\n-\tret = air_buckpbus_reg_modify(phydev, AN8811HB_TX_POLARITY,\n-\t\t\t\t      AN8811HB_TX_POLARITY_NORMAL, pbus_value);\n+\tret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_TX_POLARITY,\n+\t\t\t\t\t  AN8811HB_TX_POLARITY_NORMAL, pbus_value);\n \tif (ret < 0)\n \t\treturn ret;\n \n \t/* Configure led gpio pins as output */\n \tif (priv->pkg_sel) {\n-\t\tret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,\n-\t\t\t\t\t      AN8811HB_GPIO_OUTPUT_MASK,\n+\t\tret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,\n+\t\t\t\t\t\t  AN8811HB_GPIO_OUTPUT_MASK,\n \t\t\t\t\t      AN8811HB_GPIO_OUTPUT_0115);\n \t\tif (ret < 0)\n \t\t\treturn ret;\n-\t\tret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_SEL_1,\n-\t\t\t\t\t      AN8811HB_GPIO_SEL_1_0_MASK |\n+\t\tret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_GPIO_SEL_1,\n+\t\t\t\t\t\t  AN8811HB_GPIO_SEL_1_0_MASK |\n \t\t\t\t\t      AN8811HB_GPIO_SEL_1_1_MASK,\n \t\t\t\t\t      AN8811HB_GPIO_SEL_1_0 |\n \t\t\t\t\t      AN8811HB_GPIO_SEL_1_1);\n \t\tif (ret < 0)\n \t\t\treturn ret;\n \n-\t\tret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_SEL_2,\n-\t\t\t\t\t      AN8811HB_GPIO_SEL_2_15_MASK,\n+\t\tret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_GPIO_SEL_2,\n+\t\t\t\t\t\t  AN8811HB_GPIO_SEL_2_15_MASK,\n \t\t\t\t\t      AN8811HB_GPIO_SEL_2_15);\n \t\tif (ret < 0)\n \t\t\treturn ret;\n \t} else {\n-\t\tret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,\n-\t\t\t\t\t      AN8811HB_GPIO_OUTPUT_345,\n+\t\tret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,\n+\t\t\t\t\t\t  AN8811HB_GPIO_OUTPUT_345,\n \t\t\t\t\t      AN8811HB_GPIO_OUTPUT_345);\n \t\tif (ret < 0)\n \t\t\treturn ret;\n@@ -1373,16 +1211,6 @@ static int en8811h_probe(struct phy_device *phydev)\n \treturn 0;\n }\n \n-static int air_phy_read_page(struct phy_device *phydev)\n-{\n-\treturn phy_read(phydev, MDIO_DEVAD_NONE, AIR_EXT_PAGE_ACCESS);\n-}\n-\n-static int air_phy_write_page(struct phy_device *phydev, int page)\n-{\n-\treturn phy_write(phydev, MDIO_DEVAD_NONE, AIR_EXT_PAGE_ACCESS, page);\n-}\n-\n U_BOOT_PHY_DRIVER(en8811h) = {\n \t.name = \"Airoha EN8811H\",\n \t.uid = EN8811H_PHY_ID,\ndiff --git a/drivers/net/phy/airoha/air_phy_lib.c b/drivers/net/phy/airoha/air_phy_lib.c\nnew file mode 100644\nindex 00000000000..133cba55bbf\n--- /dev/null\n+++ b/drivers/net/phy/airoha/air_phy_lib.c\n@@ -0,0 +1,221 @@\n+// SPDX-License-Identifier: GPL-2.0+\n+/*\n+ * Airoha Ethernet PHY common library\n+ *\n+ * Copyright (C) 2026 Airoha Technology Corp.\n+ * Copyright (C) 2026 Collabora Ltd.\n+ *                    Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>\n+ *\n+ * Adapated from https://lore.kernel.org/all/20260326-add-airoha-an8801-support-v2-2-1a42d6b6050f@collabora.com/\n+ */\n+\n+#include <dm/device_compat.h>\n+#include <linux/compat.h>\n+#include <phy.h>\n+\n+#include \"air_phy_lib.h\"\n+\n+#define AIR_EXT_PAGE_ACCESS\t0x1f\n+\n+static int __air_buckpbus_reg_read(struct phy_device *phydev,\n+\t\t\t\t   u32 pbus_address, u32 *pbus_data)\n+{\n+\tint pbus_data_low, pbus_data_high;\n+\tint ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,\n+\t\t\tAIR_BPBUS_MODE_ADDR_FIXED);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_HIGH,\n+\t\t\tupper_16_bits(pbus_address));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_LOW,\n+\t\t\tlower_16_bits(pbus_address));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tpbus_data_high = phy_read(phydev, MDIO_DEVAD_NONE,\n+\t\t\t\t  AIR_BPBUS_RD_DATA_HIGH);\n+\tif (pbus_data_high < 0)\n+\t\treturn pbus_data_high;\n+\n+\tpbus_data_low = phy_read(phydev, MDIO_DEVAD_NONE,\n+\t\t\t\t AIR_BPBUS_RD_DATA_LOW);\n+\tif (pbus_data_low < 0)\n+\t\treturn pbus_data_low;\n+\n+\t*pbus_data = pbus_data_low | (pbus_data_high << 16);\n+\treturn 0;\n+}\n+\n+static int __air_buckpbus_reg_write(struct phy_device *phydev,\n+\t\t\t\t    u32 pbus_address, u32 pbus_data)\n+{\n+\tint ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,\n+\t\t\tAIR_BPBUS_MODE_ADDR_FIXED);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_HIGH,\n+\t\t\tupper_16_bits(pbus_address));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_LOW,\n+\t\t\tlower_16_bits(pbus_address));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_HIGH,\n+\t\t\tupper_16_bits(pbus_data));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_LOW,\n+\t\t\tlower_16_bits(pbus_data));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn 0;\n+}\n+\n+static int __air_buckpbus_reg_modify(struct phy_device *phydev,\n+\t\t\t\t     u32 pbus_address, u32 mask, u32 set)\n+{\n+\tint pbus_data_low, pbus_data_high;\n+\tu32 pbus_data_old, pbus_data_new;\n+\tint ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,\n+\t\t\tAIR_BPBUS_MODE_ADDR_FIXED);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_HIGH,\n+\t\t\tupper_16_bits(pbus_address));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_LOW,\n+\t\t\tlower_16_bits(pbus_address));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tpbus_data_high = phy_read(phydev, MDIO_DEVAD_NONE,\n+\t\t\t\t  AIR_BPBUS_RD_DATA_HIGH);\n+\tif (pbus_data_high < 0)\n+\t\treturn pbus_data_high;\n+\n+\tpbus_data_low = phy_read(phydev, MDIO_DEVAD_NONE,\n+\t\t\t\t AIR_BPBUS_RD_DATA_LOW);\n+\tif (pbus_data_low < 0)\n+\t\treturn pbus_data_low;\n+\n+\tpbus_data_old = pbus_data_low | (pbus_data_high << 16);\n+\tpbus_data_new = (pbus_data_old & ~mask) | set;\n+\tif (pbus_data_new == pbus_data_old)\n+\t\treturn 0;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_HIGH,\n+\t\t\tupper_16_bits(pbus_address));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_LOW,\n+\t\t\tlower_16_bits(pbus_address));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_HIGH,\n+\t\t\tupper_16_bits(pbus_data_new));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_LOW,\n+\t\t\tlower_16_bits(pbus_data_new));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn 0;\n+}\n+\n+int air_phy_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address,\n+\t\t\t      u32 *pbus_data)\n+{\n+\tint saved_page;\n+\tint ret = 0;\n+\n+\tsaved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);\n+\n+\tif (saved_page >= 0) {\n+\t\tret = __air_buckpbus_reg_read(phydev, pbus_address, pbus_data);\n+\t\tif (ret < 0)\n+\t\t\tdev_err(phydev->dev, \"%s 0x%08x failed: %d\\n\", __func__,\n+\t\t\t\tpbus_address, ret);\n+\t}\n+\n+\treturn phy_restore_page(phydev, saved_page, ret);\n+}\n+EXPORT_SYMBOL_GPL(air_phy_buckpbus_reg_read);\n+\n+int air_phy_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address,\n+\t\t\t       u32 pbus_data)\n+{\n+\tint saved_page;\n+\tint ret = 0;\n+\n+\tsaved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);\n+\n+\tif (saved_page >= 0) {\n+\t\tret = __air_buckpbus_reg_write(phydev, pbus_address,\n+\t\t\t\t\t       pbus_data);\n+\t\tif (ret < 0)\n+\t\t\tdev_err(phydev->dev, \"%s 0x%08x failed: %d\\n\", __func__,\n+\t\t\t\tpbus_address, ret);\n+\t}\n+\n+\treturn phy_restore_page(phydev, saved_page, ret);\n+}\n+EXPORT_SYMBOL_GPL(air_phy_buckpbus_reg_write);\n+\n+int air_phy_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_address,\n+\t\t\t\tu32 mask, u32 set)\n+{\n+\tint saved_page;\n+\tint ret = 0;\n+\n+\tsaved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);\n+\n+\tif (saved_page >= 0) {\n+\t\tret = __air_buckpbus_reg_modify(phydev, pbus_address, mask,\n+\t\t\t\t\t\tset);\n+\t\tif (ret < 0)\n+\t\t\tdev_err(phydev->dev, \"%s 0x%08x failed: %d\\n\", __func__,\n+\t\t\t\tpbus_address, ret);\n+\t}\n+\n+\treturn phy_restore_page(phydev, saved_page, ret);\n+}\n+EXPORT_SYMBOL_GPL(air_phy_buckpbus_reg_modify);\n+\n+int air_phy_read_page(struct phy_device *phydev)\n+{\n+\treturn phy_read(phydev, MDIO_DEVAD_NONE, AIR_EXT_PAGE_ACCESS);\n+}\n+EXPORT_SYMBOL_GPL(air_phy_read_page);\n+\n+int air_phy_write_page(struct phy_device *phydev, int page)\n+{\n+\treturn phy_write(phydev, MDIO_DEVAD_NONE, AIR_EXT_PAGE_ACCESS, page);\n+}\n+EXPORT_SYMBOL_GPL(air_phy_write_page);\n+\n+MODULE_DESCRIPTION(\"Airoha PHY Library\");\n+MODULE_LICENSE(\"GPL\");\n+MODULE_AUTHOR(\"Louis-Alexis Eyraud\");\ndiff --git a/drivers/net/phy/airoha/air_phy_lib.h b/drivers/net/phy/airoha/air_phy_lib.h\nnew file mode 100644\nindex 00000000000..845d2f7cfb4\n--- /dev/null\n+++ b/drivers/net/phy/airoha/air_phy_lib.h\n@@ -0,0 +1,39 @@\n+/* SPDX-License-Identifier: GPL-2.0+ */\n+/*\n+ * Copyright (C) 2026 Airoha Technology Corp.\n+ * Copyright (C) 2026 Collabora Ltd.\n+ *                    Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>\n+ */\n+\n+#ifndef __AIR_PHY_LIB_H\n+#define __AIR_PHY_LIB_H\n+\n+#define AIR_EXT_PAGE_ACCESS\t0x1f\n+\n+#define AIR_PHY_PAGE_STANDARD\t\t0x0000\n+#define AIR_PHY_PAGE_EXTENDED_1\t\t0x0001\n+#define AIR_PHY_PAGE_EXTENDED_4\t\t0x0004\n+\n+/* MII Registers Page 4*/\n+#define AIR_BPBUS_MODE\t\t\t0x10\n+#define   AIR_BPBUS_MODE_ADDR_FIXED\t0x0000\n+#define   AIR_BPBUS_MODE_ADDR_INCR\tBIT(15)\n+#define AIR_BPBUS_WR_ADDR_HIGH\t\t0x11\n+#define AIR_BPBUS_WR_ADDR_LOW\t\t0x12\n+#define AIR_BPBUS_WR_DATA_HIGH\t\t0x13\n+#define AIR_BPBUS_WR_DATA_LOW\t\t0x14\n+#define AIR_BPBUS_RD_ADDR_HIGH\t\t0x15\n+#define AIR_BPBUS_RD_ADDR_LOW\t\t0x16\n+#define AIR_BPBUS_RD_DATA_HIGH\t\t0x17\n+#define AIR_BPBUS_RD_DATA_LOW\t\t0x18\n+\n+int air_phy_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_address,\n+\t\t\t\tu32 mask, u32 set);\n+int air_phy_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address,\n+\t\t\t      u32 *pbus_data);\n+int air_phy_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address,\n+\t\t\t       u32 pbus_data);\n+int air_phy_read_page(struct phy_device *phydev);\n+int air_phy_write_page(struct phy_device *phydev, int page);\n+\n+#endif /* __AIR_PHY_LIB_H */\n","prefixes":["5/9"]}