get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2230578/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2230578,
    "url": "http://patchwork.ozlabs.org/api/patches/2230578/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20260429-add-ethernet-support-for-genio-520-720-v4-5-be54e17239b7@baylibre.com/",
    "project": {
        "id": 18,
        "url": "http://patchwork.ozlabs.org/api/projects/18/?format=api",
        "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,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260429-add-ethernet-support-for-genio-520-720-v4-5-be54e17239b7@baylibre.com>",
    "list_archive_url": null,
    "date": "2026-04-29T13:58:58",
    "name": "[v4,5/9] net: phy: air_phy_lib: Factorize BuckPBus register",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "f45e9c324d12400635805e58a019862461cb53ee",
    "submitter": {
        "id": 84831,
        "url": "http://patchwork.ozlabs.org/api/people/84831/?format=api",
        "name": "Julien Stephan",
        "email": "jstephan@baylibre.com"
    },
    "delegate": {
        "id": 161331,
        "url": "http://patchwork.ozlabs.org/api/users/161331/?format=api",
        "username": "dlech",
        "first_name": "David",
        "last_name": "Lechner",
        "email": "dlechner@baylibre.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20260429-add-ethernet-support-for-genio-520-720-v4-5-be54e17239b7@baylibre.com/mbox/",
    "series": [
        {
            "id": 502153,
            "url": "http://patchwork.ozlabs.org/api/series/502153/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=502153",
            "date": "2026-04-29T13:58:53",
            "name": "Add ethernet support for genio 520/720 EVK boards",
            "version": 4,
            "mbox": "http://patchwork.ozlabs.org/series/502153/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2230578/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2230578/checks/",
    "tags": {},
    "related": [],
    "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=ZK9OoZBN;\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=\"ZK9OoZBN\";\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)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g5VVG2Kdjz1yGq\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 30 Apr 2026 07:16:38 +1000 (AEST)",
            "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 7D399848FB;\n\tWed, 29 Apr 2026 23:15:50 +0200 (CEST)",
            "by phobos.denx.de (Postfix, from userid 109)\n id 45B8884862; Wed, 29 Apr 2026 15:59:23 +0200 (CEST)",
            "from mail-wr1-x429.google.com (mail-wr1-x429.google.com\n [IPv6:2a00:1450:4864:20::429])\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 C9DCB84855\n for <u-boot@lists.denx.de>; Wed, 29 Apr 2026 15:59:19 +0200 (CEST)",
            "by mail-wr1-x429.google.com with SMTP id\n ffacd0b85a97d-43cfde3c3f3so12654528f8f.3\n for <u-boot@lists.denx.de>; Wed, 29 Apr 2026 06:59:19 -0700 (PDT)",
            "from [192.168.1.100]\n (2a02-842a-d52e-6101-6f8f-5617-c4b6-8627.rev.sfr.net.\n [2a02:842a:d52e:6101:6f8f:5617:c4b6:8627])\n by smtp.gmail.com with ESMTPSA id\n ffacd0b85a97d-447b7ca64ffsm6289675f8f.37.2026.04.29.06.59.16\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 29 Apr 2026 06:59:18 -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=1777471159;\n x=1778075959;\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=DC5dSp7y6c4PSah+jAZq1qwkFxPvWhgE6WBDv7qd/0s=;\n b=ZK9OoZBNCOPBAIIs4oNUAqN134qgLxtEe8BNbCODWvafIwitAuYbHItI0OwtOI5AIH\n WeoMjGGlLGEw9/mS0Yv1Vumx0KyL8Af6lmrRen77r+jRJBAMWDtbOzUvoPhmusm3+TGh\n +QZouVLw7AY8AzDQmApp56z1LhgP+ZSknbU9rh5e7NWL4FfzN7J3kerW0Ci8pEqADYPH\n 0IQqOr4XLIOJ5seBHRER6/KzpK96X/Kd7KTDR3NcV3wJiF3E1KfBN4FJHtMUD3PzQsYU\n Bh6zF5CozDwVcd0w38T0p3yzs4DwwhZ1Ffz3Rus1Y+ST7FKeL1ffaMw7Lw0eFXPW2Yov\n 2Rag==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777471159; x=1778075959;\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=DC5dSp7y6c4PSah+jAZq1qwkFxPvWhgE6WBDv7qd/0s=;\n b=F7O/xwE9Qa2antLlW5tSVxpKOXlL3tqoKZkGXincU4zA5+mr+uWItDycuR/LJiWtHZ\n x8vAdfV+naA6DVYuq6LCvrQi/k+YLyybGPD8unX+wj+aQn+XdmIM6LTo2ThIu32roT/u\n 6y9LB8ahTYtX0Wp8LmI7eR7PmgaLLZgUKKc7ML0Y+A9fc/nw117ArrqmuC6jZIYlheGr\n 4fuAFZ6k9g3Nw6osfHEEhQNlam+ElOcG+ibWV4Bjb2Eai2/WuLONLBgL5paPBoqdShh9\n 1PhQFh0/pfcyRghGQWcf0F1VYSsae5BHav6f6Zjfzk505gw9r+lamxpldGorAcqPfyvW\n cpGg==",
        "X-Gm-Message-State": "AOJu0Yx0XJFGIlfzNvbWmhSMi952JaxpEB/1jk2/6pGwLreY2LyN/Vrh\n qCv7/6PY9HFYz9jo5dAFjBuH4faitE+UQOr/5+izpUnXggki/lhT+JWFHqLbC+fdSiY=",
        "X-Gm-Gg": "AeBDiesPsRofL8u05m3QTOnjkssEQeM4+DrtkGDK0LRz3QA9b2qWL7svcaqBAWKieAI\n YV/cIgGpGLH2GueAGQMDoJgz6/ScVudAR9UK2xJ3phBkD/yJVkezqjJNPvNxJstOivxugaq0Ye5\n /9fXBBr/ZZcwvKxw34OleJ6pTIbOJiapLoiKu2v1W0yhFZ7uNCTo1eXLMWT3MnlD+LQL/WNTRr7\n pcNLMG+3hKAgQyiuHKSmD/nYMsbpR6ExuZw8IBKmlLw6B2Z7Vc8aSjPTQZaB47QKweRhoIMeR46\n gXArN7Us9uqZkIz+6yNYOHMP7FhsbHBOfDqOvrahBdZYPJEW0PlgkwKknHxNRd0GQExiet+P7Vj\n ZfbPCVrF68+hWEMrUmCENxVLFwuRNIflYdnYnmOVVN8Vf3PlhB9ZZBbvZ2TyqhQcRZMHGhWEn7/\n obJsMHeC+abqBxYM4VFHzuMxL1WZEAKZAXxFvKSrLBtXj7AJavYE//AhRcpvPe030xFOHqaoqA9\n mozNyHelSrHBiqkWs/SUREPkrv0RWG+tJmKiZwypKb0TueEFdQdJYvGbTtiknk2g07itVKt1ymi\n ovtFc+Qr5klfcAUY94o=",
        "X-Received": "by 2002:a05:6000:24c3:b0:43d:76d8:5794 with SMTP id\n ffacd0b85a97d-44649ba176fmr13813802f8f.36.1777471158926;\n Wed, 29 Apr 2026 06:59:18 -0700 (PDT)",
        "From": "Julien Stephan <jstephan@baylibre.com>",
        "Date": "Wed, 29 Apr 2026 15:58:58 +0200",
        "Subject": "[PATCH v4 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 <20260429-add-ethernet-support-for-genio-520-720-v4-5-be54e17239b7@baylibre.com>",
        "References": "\n <20260429-add-ethernet-support-for-genio-520-720-v4-0-be54e17239b7@baylibre.com>",
        "In-Reply-To": "\n <20260429-add-ethernet-support-for-genio-520-720-v4-0-be54e17239b7@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 Peter Robinson <pbrobinson@gmail.com>,\n Julien Stephan <jstephan@baylibre.com>",
        "X-Mailer": "b4 0.14.3",
        "X-Mailman-Approved-At": "Wed, 29 Apr 2026 23:15:47 +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  | 304 ++++++++---------------------------\n drivers/net/phy/airoha/air_phy_lib.c | 216 +++++++++++++++++++++++++\n drivers/net/phy/airoha/air_phy_lib.h |  39 +++++\n 6 files changed, 329 insertions(+), 239 deletions(-)",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 105590ffad0..735ecc36210 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..5b109d5c6b4 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_AIROHA_PHYLIB\n \thelp\n \t  AIROHA EN8811H supported.\n \t  AIROHA AN8811HB supported.\n+\n+config PHY_AIROHA_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..59051caecef 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_AIROHA_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..de7542eb079 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,9 +484,9 @@ 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-\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\t  AIR_PHY_CONTROL_SURGE_5R);\n \tif (ret < 0)\n \t\treturn ret;\n \n@@ -706,14 +544,14 @@ 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-\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\t  EN8811H_FW_CTRL_2_LOADING);\n \tif (ret < 0)\n \t\tgoto en8811h_load_firmware_out;\n \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,17 +696,17 @@ 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\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+\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\t  AN8811HB_CLK_DRV_CKOPWD    |\n+\t\t\t\t\t\t  AN8811HB_CLK_DRV_CKO_LDPWD |\n+\t\t\t\t\t\t  AN8811HB_CLK_DRV_CKO_LPPWD);\n \t\tif (ret < 0)\n \t\t\treturn ret;\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,13 +725,13 @@ 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-\t\t\t\t      EN8811H_FW_CTRL_1_FINISH);\n+\treturn air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,\n+\t\t\t\t\t  EN8811H_FW_CTRL_1_FINISH);\n }\n \n static int air_led_hw_control_set(struct phy_device *phydev, u8 index,\n@@ -1091,10 +929,10 @@ 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-\t\t\t\t      EN8811H_POLARITY_TX_NORMAL,\n-\t\t\t\t      pbus_value);\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\t  EN8811H_POLARITY_TX_NORMAL,\n+\t\t\t\t\t  pbus_value);\n \tif (ret < 0)\n \t\treturn ret;\n \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,35 +1013,35 @@ 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\t\t\t\t      AN8811HB_GPIO_OUTPUT_0115);\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\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\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\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\t  AN8811HB_GPIO_SEL_1_1_MASK,\n+\t\t\t\t\t\t  AN8811HB_GPIO_SEL_1_0 |\n+\t\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\t\t\t\t      AN8811HB_GPIO_SEL_2_15);\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\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\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\t  AN8811HB_GPIO_OUTPUT_345);\n \t\tif (ret < 0)\n \t\t\treturn ret;\n \t}\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..61c3bf82822\n--- /dev/null\n+++ b/drivers/net/phy/airoha/air_phy_lib.c\n@@ -0,0 +1,216 @@\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+\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+\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+\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+\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+\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": [
        "v4",
        "5/9"
    ]
}