get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2229627,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2229627/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20260428-add-ethernet-support-for-genio-520-720-v2-6-9cf2f0884bd8@baylibre.com/",
    "project": {
        "id": 18,
        "url": "http://patchwork.ozlabs.org/api/1.1/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
    },
    "msgid": "<20260428-add-ethernet-support-for-genio-520-720-v2-6-9cf2f0884bd8@baylibre.com>",
    "date": "2026-04-28T13:17:13",
    "name": "[v2,6/9] net: phy: Add airoha AN8801 ethernet phy driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "efc7a98b684dec0f984fe41059fb489119daeac7",
    "submitter": {
        "id": 84831,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/84831/?format=api",
        "name": "Julien Stephan",
        "email": "jstephan@baylibre.com"
    },
    "delegate": {
        "id": 161331,
        "url": "http://patchwork.ozlabs.org/api/1.1/users/161331/?format=api",
        "username": "dlech",
        "first_name": "David",
        "last_name": "Lechner",
        "email": "dlechner@baylibre.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20260428-add-ethernet-support-for-genio-520-720-v2-6-9cf2f0884bd8@baylibre.com/mbox/",
    "series": [
        {
            "id": 501871,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/501871/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=501871",
            "date": "2026-04-28T13:17:07",
            "name": "Add ethernet support for genio 520/720 EVK boards",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/501871/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2229627/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2229627/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=uUujHEtK;\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=\"uUujHEtK\";\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 4g4kDk4gtMz1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 01:02:14 +1000 (AEST)",
            "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id AFCEC84656;\n\tTue, 28 Apr 2026 17:00:45 +0200 (CEST)",
            "by phobos.denx.de (Postfix, from userid 109)\n id 7DB7B842A2; Tue, 28 Apr 2026 15:17:41 +0200 (CEST)",
            "from mail-wr1-x435.google.com (mail-wr1-x435.google.com\n [IPv6:2a00:1450:4864:20::435])\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 66A8F8426E\n for <u-boot@lists.denx.de>; Tue, 28 Apr 2026 15:17:38 +0200 (CEST)",
            "by mail-wr1-x435.google.com with SMTP id\n ffacd0b85a97d-43d77f6092eso7980039f8f.2\n for <u-boot@lists.denx.de>; Tue, 28 Apr 2026 06:17:38 -0700 (PDT)",
            "from [192.168.1.100]\n (2a02-842a-d52e-6101-1bf9-06eb-939c-90d1.rev.sfr.net.\n [2a02:842a:d52e:6101:1bf9:6eb:939c:90d1])\n by smtp.gmail.com with ESMTPSA id\n ffacd0b85a97d-4463d5ee9ecsm7139599f8f.16.2026.04.28.06.17.35\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 28 Apr 2026 06:17:37 -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=1777382258;\n x=1777987058;\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=reRMrqd5oSc7sahRrBZXSUH7B3givxt/EDoQj6JnJvc=;\n b=uUujHEtKZSuOPDejCdHWIgVDvHOAR/FSvh56Wac7SwScv14eEi+SIoU7OT2z8gqM/p\n 3wpZMFJdRgHCWaUaTL2hn40ZAzYLbiZFlrlLxVLmwCGVZ8Db8DLFJy99dtCebdXZMNh7\n cl3nk8NR0hf5rUCxjWgJG6djpiF0PlPUiYkiYYMqMW94SUhXsbRCYVfYJiocK6eqtA6m\n CrJxPH9frGpP5XrlEJTiXFwVgp0lgj9hnCxEuvbJn+MV4jRjIB/L4QgzbBPyWAzdLJcP\n SEbY7ZGXOgCv+5Ze2V+3lLSwWImVFuCvC3HjybymlLzBTegCqNhYFaB+Bsm5ZJTgSZMr\n Rc+g==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777382258; x=1777987058;\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=reRMrqd5oSc7sahRrBZXSUH7B3givxt/EDoQj6JnJvc=;\n b=RL5ShQSzcY5kxK53SJrzvOrRplR1gvigHnZfxw6/kFeUrW9fr3S9iEiQxFTUZcpx5h\n yzl3pFFq0NG1oB0J2BbGZuOBfPUBrYWpKjLte1XOPxFRE4YZ2JCsKp+vTsIElYV/Bn7r\n D/OPTHU0la5N/37TcIxfEEg1sVaotZvmSEDrv1oBLcgaSHi58+mB9yKp71OgrzIhk33k\n LzuzRk29BuRKb9yFa9cBaCQxDabb1WtFcLKB7Cw9R04SFefB65HtO0HVFflwpWTU82RQ\n +Q26xU+M5coR1mPaZ8a+QlnuyeZk18PBgwGe9wLKGrifTibMWHdkNvny2hGCOZwoB/lt\n /Sww==",
        "X-Gm-Message-State": "AOJu0Yyfq5lrQPBS6OQJpdk+ufvrj5sMof9aZ3POh3emBRX/7PbqsRUD\n SYp8KrECsKNlduh9NH5ccBldnEf8B/5Z1Mqn0dk6N2agr32ruQQMePVzRhndJ5RPBkk=",
        "X-Gm-Gg": "AeBDieuAL9WkfMWjIgEQ5IfpVB1mWn3OwR1q+y3ZsUzwjwg//ObbuOU9Tmcov+g/63z\n HGcyp3EgXRnM2tBXf/jqn9nmdLYuOS4FwGM1LeNv2EqZ2NKoGEuE96J19uUh8+F/ZnWs8j1nMv+\n Ua4bsu8NSGQCIBsJeZAEc7LDLz8JHkDLIoWPK6miuZ0W8VNx9LiOzaXbRZdOg6g3WZPQBHBgFEI\n oJB5yR0wLW9dnXGzT1uEkcEbKS0J8ez9MvHvvfWQhKw7W9I4ZQQUSofPUc6cRles5MOQGp9Qlb/\n bik6aGqpmD7IBYImvFfZmCN5UGLiVG2BaLPUl3201lSaDwxYTI/9kKgIAV3ZelLjAdojNH8xWOP\n Jztnc8b7YtsYapHWiLo9CppziBje8Atyd0I51gr0Ryf2B6XV0vT4O+7uhiLTVQX1wLlHH3dRFSR\n P6fDCCDEzEeZak9WFsEO37tnBSE51zgy6zoqKGs1nAhwKFdJ60E83br/xhDTaTnWdU1luOhNRU4\n CaJ0sW20v7GL0s1yG5Q1BSiWLieVKQ05cze9IlYknSz8/DAfJ31dw4tb9802AzOocl6hc5dxZ/h\n wqbAgEv3+zWHraUdKA==",
        "X-Received": "by 2002:a05:6000:2908:b0:442:c577:72b8 with SMTP id\n ffacd0b85a97d-4464b2acdf1mr5894214f8f.36.1777382257496;\n Tue, 28 Apr 2026 06:17:37 -0700 (PDT)",
        "From": "Julien Stephan <jstephan@baylibre.com>",
        "Date": "Tue, 28 Apr 2026 15:17:13 +0200",
        "Subject": "[PATCH v2 6/9] net: phy: Add airoha AN8801 ethernet phy driver",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "\n <20260428-add-ethernet-support-for-genio-520-720-v2-6-9cf2f0884bd8@baylibre.com>",
        "References": "\n <20260428-add-ethernet-support-for-genio-520-720-v2-0-9cf2f0884bd8@baylibre.com>",
        "In-Reply-To": "\n <20260428-add-ethernet-support-for-genio-520-720-v2-0-9cf2f0884bd8@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": "Tue, 28 Apr 2026 17:00:38 +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": "Add Airoha AN8801 Ethernet PHY driver (air_an8801.c).\nImplement CL22/CL45 MDIO access, LED control, and RGMII delay\nconfiguration. Provide probe, initialization, LED setup, and status\nhandling. Expose DTS properties for clock delays. Register driver with\nPHY framework and trigger on startup.\n\nSigned-off-by: Yanqing Wang <ot_yanqing.wang@mediatek.com>\nSigned-off-by: Julien Stephan <jstephan@baylibre.com>\n---\n MAINTAINERS                         |   1 +\n drivers/net/phy/airoha/Kconfig      |   7 +\n drivers/net/phy/airoha/Makefile     |   1 +\n drivers/net/phy/airoha/air_an8801.c | 595 ++++++++++++++++++++++++++++++++++++\n 4 files changed, 604 insertions(+)",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 4bda6b9e8c4..a59342de3e7 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -60,6 +60,7 @@ F:\tlib/acpi/\n \n AIROHA PHY\n M:\tTommy Shih <tommy.shih@airoha.com>\n+M:\tKevin-KW Huang <kevin-kw.huang@airoha.com>\n S:\tMaintained\n F:\tdrivers/net/phy/airoha/\n \ndiff --git a/drivers/net/phy/airoha/Kconfig b/drivers/net/phy/airoha/Kconfig\nindex 2a2f4f05bb2..cbceb0cfdb4 100644\n--- a/drivers/net/phy/airoha/Kconfig\n+++ b/drivers/net/phy/airoha/Kconfig\n@@ -2,6 +2,13 @@\n menuconfig PHY_AIROHA\n \tbool \"Airoha Ethernet PHYs support\"\n \n+config PHY_AIROHA_AN8801\n+\tbool \"Airoha Ethernet AN8801 support\"\n+\tdepends on PHY_AIROHA\n+\tselect PHY_AIRONA_PHYLIB\n+\thelp\n+\t  Currently support AIROHA AN8801 1G PHY.\n+\n config PHY_AIROHA_EN8811\n \tbool \"Airoha Ethernet EN8811H support\"\n \tdepends on PHY_AIROHA\ndiff --git a/drivers/net/phy/airoha/Makefile b/drivers/net/phy/airoha/Makefile\nindex cbf123986f2..3144f1dc54f 100644\n--- a/drivers/net/phy/airoha/Makefile\n+++ b/drivers/net/phy/airoha/Makefile\n@@ -1,4 +1,5 @@\n # SPDX-License-Identifier: GPL-2.0\n \n+obj-$(CONFIG_PHY_AIROHA_AN8801) += air_an8801.o\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_an8801.c b/drivers/net/phy/airoha/air_an8801.c\nnew file mode 100644\nindex 00000000000..659c149defe\n--- /dev/null\n+++ b/drivers/net/phy/airoha/air_an8801.c\n@@ -0,0 +1,595 @@\n+// SPDX-License-Identifier: GPL-2.0+\n+/*\n+ * air_an8801.c - PHY driver for Airoha AN8801.\n+ * Copyright (c) 2026 Airoha Technology Corp.\n+ * Copyright (C) 2026 BayLibre, SAS.\n+ * Author: Kevin-KW Huang <kevin-kw.huang@airoha.com>\n+ *         Sita Huang <sita.huang@airoha.com>\n+ *         Julien Stephan <jstephan@baylibre.com>\n+ */\n+\n+#include <malloc.h>\n+#include <phy.h>\n+#include <dm/device_compat.h>\n+\n+#include \"air_phy_lib.h\"\n+\n+#define AN8801R_PHY_ID1\t\t\t0xc0ff\n+#define AN8801R_PHY_ID2\t\t\t0x0421\n+#define AN8801R_PHY_ID\t\t\t((u32)((AN8801R_PHY_ID1 << 16) | AN8801R_PHY_ID2))\n+\n+#define AN8801R_MAX_LED_SIZE\t\t3\n+\n+/* MII Registers - Airoha Page 4 */\n+#define AN8801_PBUS_ACCESS\t\tBIT(28)\n+\n+/* BPBUS Registers */\n+#define AN8801_BPBUS_REG_LED_GPIO\t0x54\n+#define AN8801_BPBUS_REG_LED_ID_SEL\t0x58\n+#define  LED_ID_GPIO_SEL(led, gpio)\t((led) << ((gpio) * 3))\n+\n+#define AN8801_BPBUS_REG_GPIO_MODE\t0x70\n+\n+#define AN8801_BPBUS_REG_LINK_MODE\t0x5054\n+#define  AN8801_BPBUS_LINK_MODE_1000\tBIT(0)\n+\n+#define AN8801_BPBUS_REG_BYPASS_PTP\t0x21c004\n+#define   AN8801_BYP_PTP_RGMII_TO_GPHY\tBIT(0)\n+\n+#define AN8801_BPBUS_REG_TXDLY_STEP\t0x21c024\n+#define  RGMII_DELAY_STEP_MASK\t\tGENMASK(2, 0)\n+#define  AIR_RGMII_DELAY_NOSTEP\t\t0\n+#define  AIR_RGMII_DELAY_STEP_1\t\t1\n+#define  AIR_RGMII_DELAY_STEP_2\t\t2\n+#define  AIR_RGMII_DELAY_STEP_3\t\t3\n+#define  AIR_RGMII_DELAY_STEP_4\t\t4\n+#define  AIR_RGMII_DELAY_STEP_5\t\t5\n+#define  AIR_RGMII_DELAY_STEP_6\t\t6\n+#define  AIR_RGMII_DELAY_STEP_7\t\t7\n+#define  RGMII_TXDELAY_FORCE_MODE\tBIT(24)\n+\n+#define AN8801_BPBUS_REG_RXDLY_STEP\t0x21c02c\n+#define  RGMII_RXDELAY_ALIGN\t\tBIT(4)\n+#define  RGMII_RXDELAY_FORCE_MODE\tBIT(24)\n+\n+#define AN8801_BPBUS_REG_EFIFO_CTL(x)\t(0x270004 + (0x100 * (x))) /* 0..2 */\n+#define   AN8801_EFIFO_ALL_EN\t\tGENMASK(7, 0)\n+#define   AN8801_EFIFO_RX_EN\t\tBIT(0)\n+#define   AN8801_EFIFO_TX_EN\t\tBIT(1)\n+#define   AN8801_EFIFO_RX_CLK_EN\tBIT(2)\n+#define   AN8801_EFIFO_TX_CLK_EN\tBIT(3)\n+#define   AN8801_EFIFO_RX_EEE_EN\tBIT(4)\n+#define   AN8801_EFIFO_TX_EEE_EN\tBIT(5)\n+#define   AN8801_EFIFO_RX_ODD_NIBBLE_EN\tBIT(6)\n+#define   AN8801_EFIFO_TX_ODD_NIBBLE_EN\tBIT(7)\n+\n+#define AN8801_BPBUS_REG_HWRST_DE_GLITCH\t0xc8\n+#define  AN8801_DE_GLITCH_EN\t\t\tBIT(2)\n+#define  AN8801_11_CYCLE_XTAL_PERIOD_DE_GLITCH\tGENMASK(1, 0)\n+\n+#define LED_BCR\t\t\t\t0x21\n+#define  LED_BCR_MODE_MASK\t\tGENMASK(1, 0)\n+#define  LED_BCR_TIME_TEST\t\tBIT(2)\n+#define  LED_BCR_CLK_EN\t\t\tBIT(3)\n+#define  LED_BCR_EVT_ALL\t\tBIT(4)\n+#define  LED_BCR_EXT_CTRL\t\tBIT(15)\n+#define LED_BCR_MODE_DISABLE\t\t0\n+#define LED_BCR_MODE_2LED\t\t1\n+#define LED_BCR_MODE_3LED_1\t\t2\n+#define LED_BCR_MODE_3LED_2\t\t3\n+\n+#define LED_ON_DUR\t\t\t0x22\n+#define LED_ON_DUR_MASK\t\t\tGENMASK(15, 0)\n+\n+#define LED_BLINK_DUR\t\t\t0x23\n+#define LED_BLINK_DUR_MASK\t\tGENMASK(15, 0)\n+\n+#define LED_ON_CTRL(i)\t\t\t(0x024 + ((i) * 2))\n+#define  LED_ON_EVT_MASK\t\tGENMASK(6, 0)\n+#define  LED_ON_EVT_LINK_1000M\t\tBIT(0)\n+#define  LED_ON_EVT_LINK_100M\t\tBIT(1)\n+#define  LED_ON_EVT_LINK_10M\t\tBIT(2)\n+#define  LED_ON_EVT_LINK_DN\t\tBIT(3)\n+#define  LED_ON_EVT_FDX\t\t\tBIT(4)\n+#define  LED_ON_EVT_HDX\t\t\tBIT(5)\n+#define  LED_ON_EVT_FORCE\t\tBIT(6)\n+#define  LED_ON_POL\t\t\tBIT(14)\n+#define  LED_ON_EN\t\t\tBIT(15)\n+\n+#define LED_BLINK_CTRL(i)\t\t(0x025 + ((i) * 2))\n+#define  LED_BLINK_EVT_MASK\t\tGENMASK(9, 0)\n+#define  LED_BLINK_EVT_1000M_TX\t\tBIT(0)\n+#define  LED_BLINK_EVT_1000M_RX\t\tBIT(1)\n+#define  LED_BLINK_EVT_100M_TX\t\tBIT(2)\n+#define  LED_BLINK_EVT_100M_RX\t\tBIT(3)\n+#define  LED_BLINK_EVT_10M_TX\t\tBIT(4)\n+#define  LED_BLINK_EVT_10M_RX\t\tBIT(5)\n+#define  LED_BLINK_EVT_FORCE\t\tBIT(9)\n+\n+#define UNIT_LED_BLINK_DURATION\t\t780\n+#define LED_BLINK_DURATION(f)\t\t(UNIT_LED_BLINK_DURATION << (f))\n+\n+/* Link on(1G/100M/10M), no activity */\n+#define AIR_LED0_ON \\\n+\t(LED_ON_EVT_LINK_1000M | LED_ON_EVT_LINK_100M | LED_ON_EVT_LINK_10M)\n+#define AIR_LED0_BLINK\t\t\t0x0\n+/* No link on, activity(1G/100M/10M TX/RX) */\n+#define AIR_LED1_ON\t\t\t0x0\n+#define AIR_LED1_BLINK \\\n+\t(LED_BLINK_EVT_1000M_TX | LED_BLINK_EVT_1000M_RX | \\\n+\tLED_BLINK_EVT_100M_TX | LED_BLINK_EVT_100M_RX | \\\n+\tLED_BLINK_EVT_10M_TX | LED_BLINK_EVT_10M_RX)\n+/* Link on(100M/10M), activity(100M/10M TX/RX) */\n+#define AIR_LED2_ON \\\n+\t(LED_ON_EVT_LINK_100M | LED_ON_EVT_LINK_10M)\n+#define AIR_LED2_BLINK \\\n+\t(LED_BLINK_EVT_100M_TX | LED_BLINK_EVT_100M_RX | \\\n+\tLED_BLINK_EVT_10M_TX | LED_BLINK_EVT_10M_RX)\n+\n+#define INVALID_DATA\t\t\tGENMASK(31, 0)\n+\n+#define AN8801_REG_PHY_INTERNAL0\t0x600\n+#define AN8801_REG_PHY_INTERNAL1\t0x601\n+\n+#define AN8801_LED_ENABLE\t\t1\n+\n+enum air_led_gpio_pin {\n+\tAIR_LED_GPIO1 = 1,\n+\tAIR_LED_GPIO2,\n+\tAIR_LED_GPIO3\n+};\n+\n+enum air_led {\n+\tAIR_LED0 = 0,\n+\tAIR_LED1,\n+\tAIR_LED2,\n+\tAIR_LED3\n+};\n+\n+enum air_led_blink_dut {\n+\tAIR_LED_BLINK_DUR_32M = 0,\n+\tAIR_LED_BLINK_DUR_64M,\n+\tAIR_LED_BLINK_DUR_128M,\n+\tAIR_LED_BLINK_DUR_256M,\n+\tAIR_LED_BLINK_DUR_512M,\n+\tAIR_LED_BLINK_DUR_1024M,\n+\tAIR_LED_BLINK_DUR_LAST\n+};\n+\n+enum air_led_polarity {\n+\tAIR_ACTIVE_LOW = 0,\n+\tAIR_ACTIVE_HIGH,\n+};\n+\n+enum air_led_mode {\n+\tAIR_LED_MODE_DISABLE = 0,\n+\tAIR_LED_MODE_USER_DEFINE,\n+\tAIR_LED_MODE_LAST\n+};\n+\n+struct air_led_cfg {\n+\tu16 en;\t\t/* LED Enable */\n+\tu16 gpio;\t/* GPIO */\n+\tu16 pol;\t/* LED Polarity */\n+\tu16 on_cfg;\t/* LED On */\n+\tu16 blk_cfg;\t/* LED Blink */\n+};\n+\n+struct an8801r_priv {\n+\tstruct air_led_cfg\tled_cfg[AN8801R_MAX_LED_SIZE];\n+\tu32\t\t\tled_blink_cfg;\n+\tu8\t\t\trxdelay_force;\n+\tu8\t\t\ttxdelay_force;\n+\tu16\t\t\trxdelay_step;\n+\tu8\t\t\trxdelay_align;\n+\tu16\t\t\ttxdelay_step;\n+};\n+\n+#define phydev_cfg(phy)\t\t((struct an8801r_priv *)(phy)->priv)\n+\n+/*\n+ *\tGPIO1 <-> LED0,\n+ *\tGPIO2 <-> LED1,\n+ *\tGPIO3 <-> LED2,\n+ */\n+static const struct an8801r_priv an8801r_priv_defaults = {\n+\t.led_cfg = {\n+\t\t/* LED Enable, GPIO, LED Polarity, LED ON, LED Blink */\n+\t\t{AN8801_LED_ENABLE, AIR_LED_GPIO1, AIR_ACTIVE_LOW,  AIR_LED0_ON, AIR_LED0_BLINK},\n+\t\t{AN8801_LED_ENABLE, AIR_LED_GPIO2, AIR_ACTIVE_HIGH, AIR_LED1_ON, AIR_LED1_BLINK},\n+\t\t{AN8801_LED_ENABLE, AIR_LED_GPIO3, AIR_ACTIVE_HIGH, AIR_LED2_ON, AIR_LED2_BLINK},\n+\t},\n+\t.led_blink_cfg = AIR_LED_BLINK_DUR_64M,\n+\t.rxdelay_force = false,\n+\t.txdelay_force = false,\n+\t.rxdelay_step = AIR_RGMII_DELAY_NOSTEP,\n+\t.rxdelay_align = false,\n+\t.txdelay_step = AIR_RGMII_DELAY_NOSTEP,\n+};\n+\n+static int an8801_buckpbus_reg_rmw(struct phy_device *phydev,\n+\t\t\t\t   u32 addr, u32 mask, u32 set)\n+{\n+\treturn air_phy_buckpbus_reg_modify(phydev,\n+\t\t\t\t\t  addr | AN8801_PBUS_ACCESS,\n+\t\t\t\t\t  mask, set);\n+}\n+\n+static int an8801_buckpbus_reg_set_bits(struct phy_device *phydev,\n+\t\t\t\t\tu32 addr, u32 mask)\n+{\n+\treturn air_phy_buckpbus_reg_modify(phydev,\n+\t\t\t\t\t  addr | AN8801_PBUS_ACCESS,\n+\t\t\t\t\t  mask, mask);\n+}\n+\n+static int an8801_buckpbus_reg_clear_bits(struct phy_device *phydev,\n+\t\t\t\t\t  u32 addr, u32 mask)\n+{\n+\treturn air_phy_buckpbus_reg_modify(phydev,\n+\t\t\t\t\t  addr | AN8801_PBUS_ACCESS,\n+\t\t\t\t\t  mask, 0);\n+}\n+\n+static int an8801_buckpbus_reg_write(struct phy_device *phydev, u32 addr, u32 data)\n+{\n+\treturn air_phy_buckpbus_reg_write(phydev, addr | AN8801_PBUS_ACCESS, data);\n+}\n+\n+static int an8801r_led_set_usr_def(struct phy_device *phydev, u8 entity,\n+\t\t\t\t   u16 polar, u16 on_evt, u16 blk_evt)\n+{\n+\tint ret;\n+\n+\tif (polar == AIR_ACTIVE_HIGH)\n+\t\ton_evt |= LED_ON_POL;\n+\telse\n+\t\ton_evt &= ~LED_ON_POL;\n+\n+\ton_evt |= LED_ON_EN;\n+\n+\tret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(entity), on_evt);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_CTRL(entity), blk_evt);\n+}\n+\n+static int an8801r_led_set_blink(struct phy_device *phydev, u16 blink)\n+{\n+\tint ret;\n+\n+\tret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_DUR,\n+\t\t\t    LED_BLINK_DURATION(blink));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_ON_DUR,\n+\t\t\t     LED_BLINK_DURATION(blink) / 2);\n+}\n+\n+static int an8801r_led_set_mode(struct phy_device *phydev, u8 mode)\n+{\n+\tint ret;\n+\n+\tret = phy_read_mmd(phydev, MDIO_MMD_VEND2, LED_BCR);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tswitch (mode) {\n+\tcase AIR_LED_MODE_DISABLE:\n+\t\tret &= ~LED_BCR_EXT_CTRL;\n+\t\tret &= ~LED_BCR_MODE_MASK;\n+\t\tret |= LED_BCR_MODE_DISABLE;\n+\t\tbreak;\n+\tcase AIR_LED_MODE_USER_DEFINE:\n+\t\tret |= LED_BCR_EXT_CTRL | LED_BCR_CLK_EN;\n+\t\tbreak;\n+\t}\n+\treturn phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_BCR, ret);\n+}\n+\n+static int an8801r_led_set_state(struct phy_device *phydev, u8 entity, u8 state)\n+{\n+\tint ret;\n+\n+\tret = phy_read_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(entity));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (state)\n+\t\tret |= LED_ON_EN;\n+\telse\n+\t\tret &= ~LED_ON_EN;\n+\n+\treturn phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(entity), ret);\n+}\n+\n+static int an8801r_led_init(struct phy_device *phydev)\n+{\n+\tstruct an8801r_priv *priv = phydev_cfg(phydev);\n+\tstruct air_led_cfg *led_cfg = priv->led_cfg;\n+\tu16 led_blink_cfg = priv->led_blink_cfg;\n+\tint ret, led_id;\n+\n+\tret = an8801r_led_set_blink(phydev, led_blink_cfg);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = an8801r_led_set_mode(phydev, AIR_LED_MODE_USER_DEFINE);\n+\tif (ret) {\n+\t\tdev_err(phydev->dev, \"AN8801R: Fail to set LED mode, ret %d!\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tfor (led_id = AIR_LED0; led_id < AN8801R_MAX_LED_SIZE; led_id++) {\n+\t\tret = an8801r_led_set_state(phydev, led_id, led_cfg[led_id].en);\n+\t\tif (ret) {\n+\t\t\tdev_err(phydev->dev, \"AN8801R: Fail to set LED%d state, ret %d!\\n\",\n+\t\t\t\tled_id, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\n+\t\tif (!led_cfg[led_id].en)\n+\t\t\tcontinue;\n+\n+\t\tret = an8801_buckpbus_reg_set_bits(phydev, AN8801_BPBUS_REG_LED_GPIO,\n+\t\t\t\t\t\t   BIT(led_cfg[led_id].gpio));\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = an8801_buckpbus_reg_set_bits(phydev, AN8801_BPBUS_REG_LED_ID_SEL,\n+\t\t\t\t\t\t   LED_ID_GPIO_SEL(led_id,\n+\t\t\t\t\t\t\t\t   led_cfg[led_id].gpio));\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = an8801_buckpbus_reg_clear_bits(phydev, AN8801_BPBUS_REG_GPIO_MODE,\n+\t\t\t\t\t\t     BIT(led_cfg[led_id].gpio));\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = an8801r_led_set_usr_def(phydev, led_id,\n+\t\t\t\t\t      led_cfg[led_id].pol,\n+\t\t\t\t\t      led_cfg[led_id].on_cfg,\n+\t\t\t\t\t      led_cfg[led_id].blk_cfg);\n+\t\tif (ret) {\n+\t\t\tdev_err(phydev->dev, \"AN8801R: Fail to set LED%d, ret %d!\\n\",\n+\t\t\t\tled_id, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int an8801r_of_init(struct phy_device *phydev)\n+{\n+\tstruct an8801r_priv *priv = phydev_cfg(phydev);\n+\tofnode node = phy_get_ofnode(phydev);\n+\tu32 val = 0;\n+\tint ret;\n+\n+\tif (!ofnode_valid(node))\n+\t\treturn -EINVAL;\n+\n+\tif (ofnode_has_property(node, \"airoha,rxclk-delay\")) {\n+\t\tret = ofnode_read_u32(node, \"airoha,rxclk-delay\", &val);\n+\t\tif (ret) {\n+\t\t\tdev_err(phydev->dev, \"airoha,rxclk-delay value is invalid.\\n\");\n+\t\t\treturn ret;\n+\t\t}\n+\t\tif (val > AIR_RGMII_DELAY_STEP_7) {\n+\t\t\tdev_err(phydev->dev, \"airoha,rxclk-delay value %u out of range.\\n\", val);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tpriv->rxdelay_force = true;\n+\t\tpriv->rxdelay_step = val;\n+\t\tpriv->rxdelay_align = ofnode_read_bool(node,\n+\t\t\t\t\t\t       \"airoha,rxclk-delay-align\");\n+\t}\n+\n+\tif (ofnode_has_property(node, \"airoha,txclk-delay\")) {\n+\t\tret = ofnode_read_u32(node, \"airoha,txclk-delay\", &val);\n+\t\tif (ret) {\n+\t\t\tdev_err(phydev->dev, \"airoha,txclk-delay value is invalid.\\n\");\n+\t\t\treturn ret;\n+\t\t}\n+\t\tif (val > AIR_RGMII_DELAY_STEP_7) {\n+\t\t\tdev_err(phydev->dev, \"airoha,txclk-delay value %u out of range.\\n\", val);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tpriv->txdelay_force = true;\n+\t\tpriv->txdelay_step = val;\n+\t}\n+\treturn 0;\n+}\n+\n+static int an8801r_rgmii_rxdelay(struct phy_device *phydev, u16 delay, u8 align)\n+{\n+\tu32 reg_val = delay & RGMII_DELAY_STEP_MASK;\n+\tint ret;\n+\n+\tif (align) {\n+\t\treg_val |= RGMII_RXDELAY_ALIGN;\n+\t\tdebug(\"AN8801R: Rxdelay align\\n\");\n+\t}\n+\treg_val |= RGMII_RXDELAY_FORCE_MODE;\n+\tret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_RXDLY_STEP, reg_val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdebug(\"AN8801R: Force rxdelay = %d(0x%x)\\n\", delay, reg_val);\n+\treturn 0;\n+}\n+\n+static int an8801r_rgmii_txdelay(struct phy_device *phydev, u16 delay)\n+{\n+\tu32 reg_val = delay & RGMII_DELAY_STEP_MASK;\n+\tint ret;\n+\n+\treg_val |= RGMII_TXDELAY_FORCE_MODE;\n+\tret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_TXDLY_STEP, reg_val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdebug(\"AN8801R: Force txdelay = %d(0x%x)\\n\", delay, reg_val);\n+\treturn 0;\n+}\n+\n+static int an8801r_rgmii_delay_config(struct phy_device *phydev)\n+{\n+\tstruct an8801r_priv *priv = phydev_cfg(phydev);\n+\tint ret;\n+\n+\tswitch (phydev->interface) {\n+\tcase PHY_INTERFACE_MODE_RGMII_TXID:\n+\t\treturn an8801r_rgmii_txdelay(phydev, AIR_RGMII_DELAY_STEP_4);\n+\tcase PHY_INTERFACE_MODE_RGMII_RXID:\n+\t\treturn an8801r_rgmii_rxdelay(phydev, AIR_RGMII_DELAY_NOSTEP, true);\n+\tcase PHY_INTERFACE_MODE_RGMII_ID:\n+\t\tret = an8801r_rgmii_txdelay(phydev, AIR_RGMII_DELAY_STEP_4);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t\treturn an8801r_rgmii_rxdelay(phydev, AIR_RGMII_DELAY_NOSTEP, true);\n+\tcase PHY_INTERFACE_MODE_RGMII:\n+\tdefault:\n+\t\tif (priv->rxdelay_force) {\n+\t\t\tret = an8801r_rgmii_rxdelay(phydev, priv->rxdelay_step,\n+\t\t\t\t\t\t    priv->rxdelay_align);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t}\n+\t\tif (priv->txdelay_force)\n+\t\t\treturn an8801r_rgmii_txdelay(phydev, priv->txdelay_step);\n+\t\tbreak;\n+\t}\n+\treturn 0;\n+}\n+\n+static int an8801r_config_init(struct phy_device *phydev)\n+{\n+\tint ret;\n+\n+\tret = an8801r_of_init(phydev);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_HWRST_DE_GLITCH,\n+\t\t\t\t\tAN8801_DE_GLITCH_EN |\n+\t\t\t\t\tAN8801_11_CYCLE_XTAL_PERIOD_DE_GLITCH);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AN8801_REG_PHY_INTERNAL0, 0x1e);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AN8801_REG_PHY_INTERNAL1, 0x02);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_BYPASS_PTP,\n+\t\t\t\t\tAN8801_BYP_PTP_RGMII_TO_GPHY);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(0),\n+\t\t\t\t\tAN8801_EFIFO_RX_EN |\n+\t\t\t\t\tAN8801_EFIFO_TX_EN |\n+\t\t\t\t\tAN8801_EFIFO_RX_CLK_EN |\n+\t\t\t\t\tAN8801_EFIFO_TX_CLK_EN |\n+\t\t\t\t\tAN8801_EFIFO_RX_EEE_EN |\n+\t\t\t\t\tAN8801_EFIFO_TX_EEE_EN);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(1),\n+\t\t\t\t\tAN8801_EFIFO_ALL_EN);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(2),\n+\t\t\t\t\tAN8801_EFIFO_ALL_EN);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = an8801r_rgmii_delay_config(phydev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = an8801r_led_init(phydev);\n+\tif (ret) {\n+\t\tdev_err(phydev->dev, \"AN8801R: LED initialize fail, ret %d!\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\treturn 0;\n+}\n+\n+static int an8801r_phy_probe(struct phy_device *phydev)\n+{\n+\tstruct an8801r_priv *priv;\n+\tu32 phy_id;\n+\tint ret;\n+\n+\tret = get_phy_id(phydev->bus, phydev->addr, MDIO_DEVAD_NONE, &phy_id);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (phy_id != AN8801R_PHY_ID) {\n+\t\tdev_err(phydev->dev,\n+\t\t\t\"AN8801R can't be detected (id=0x%08x).\\n\", phy_id);\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tpriv = calloc(1, sizeof(struct an8801r_priv));\n+\tif (!priv)\n+\t\treturn -ENOMEM;\n+\n+\t*priv = an8801r_priv_defaults;\n+\n+\tphydev->priv = priv;\n+\n+\treturn 0;\n+}\n+\n+static int an8801r_read_status(struct phy_device *phydev)\n+{\n+\tu32 data;\n+\n+\tif (!phydev->link)\n+\t\treturn 0;\n+\n+\tdebug(\"AN8801R: SPEED %d\\n\", phydev->speed);\n+\tdata = phydev->speed == SPEED_1000 ? AN8801_BPBUS_LINK_MODE_1000 : 0;\n+\n+\treturn an8801_buckpbus_reg_rmw(phydev, AN8801_BPBUS_REG_LINK_MODE,\n+\t\t\t\t       AN8801_BPBUS_LINK_MODE_1000, data);\n+}\n+\n+static int an8801r_startup(struct phy_device *phydev)\n+{\n+\tint ret;\n+\n+\tret = genphy_startup(phydev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn an8801r_read_status(phydev);\n+}\n+\n+U_BOOT_PHY_DRIVER(an8801r) = {\n+\t.name = \"Airoha AN8801R\",\n+\t.uid = AN8801R_PHY_ID,\n+\t.mask = 0x0ffffff0,\n+\t.features = PHY_GBIT_FEATURES,\n+\t.probe = &an8801r_phy_probe,\n+\t.config = &an8801r_config_init,\n+\t.read_page = &air_phy_read_page,\n+\t.write_page = &air_phy_write_page,\n+\t.startup = &an8801r_startup,\n+\t.shutdown = &genphy_shutdown,\n+};\n",
    "prefixes": [
        "v2",
        "6/9"
    ]
}