{"id":2230209,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2230209/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/patch/20260429-add-ethernet-support-for-genio-520-720-v3-6-1f65e18d4f54@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":"<20260429-add-ethernet-support-for-genio-520-720-v3-6-1f65e18d4f54@baylibre.com>","date":"2026-04-29T09:17:14","name":"[v3,6/9] net: phy: Add airoha AN8801 ethernet phy driver","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"704d7b3ce0ae95b3ec66acd59b9af21c7104fc1f","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/20260429-add-ethernet-support-for-genio-520-720-v3-6-1f65e18d4f54@baylibre.com/mbox/","series":[{"id":502052,"url":"http://patchwork.ozlabs.org/api/1.1/series/502052/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/list/?series=502052","date":"2026-04-29T09:17:08","name":"Add ethernet support for genio 520/720 EVK boards","version":3,"mbox":"http://patchwork.ozlabs.org/series/502052/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2230209/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2230209/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=UHadThxy;\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=\"UHadThxy\";\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 4g5H4B2sPyz1yHX\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 22:41:46 +1000 (AEST)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 0F19E84887;\n\tWed, 29 Apr 2026 14:40:51 +0200 (CEST)","by phobos.denx.de (Postfix, from userid 109)\n id 29AD884709; Wed, 29 Apr 2026 11:17:41 +0200 (CEST)","from mail-wm1-x329.google.com (mail-wm1-x329.google.com\n [IPv6:2a00:1450:4864:20::329])\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 BED3F84713\n for <u-boot@lists.denx.de>; Wed, 29 Apr 2026 11:17:38 +0200 (CEST)","by mail-wm1-x329.google.com with SMTP id\n 5b1f17b1804b1-4896c22fcbaso94413395e9.0\n for <u-boot@lists.denx.de>; Wed, 29 Apr 2026 02:17:38 -0700 (PDT)","from [192.168.1.64]\n (2a02-842a-d52e-6101-6fd0-06c4-5d68-f0a5.rev.sfr.net.\n [2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-48a7b9dee18sm44478375e9.0.2026.04.29.02.17.35\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 29 Apr 2026 02: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=1777454258;\n x=1778059058;\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=HElj6HrTUG/EgNdqXAaMKxM52pcGGfJKceBIOKrOKnk=;\n b=UHadThxyYKq5nKK2cPPm+XA4wYCvLfU8gmuIQDPhEOaLw/cE7fTjFeN8Gf3ELzz10K\n gLG9xz9lAEaBZ4OF1BuXzGMp6aJeQITopRplPclPgFYpejV9xMAHI6YemNMZL1sR7yOU\n rWaYvm7Am8evMPwdhKh/TnEBOGRvE4nvRE6VPMBEp/ktQQsHG7YYV233afb0UgP9y0JK\n /+7DSuOIrmXRvBpu+O5Z3+2Ls79cm2jcYVLDWL+1meh1Zkk2t5dEfC8o4JW/rAbLTixZ\n RpvfhqZsT4sSmuQd8IV96k9aMJRuc2yvm1JicmIjYSf4BrbWV0fdf122Za0rk6+CUvoH\n Y/RQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777454258; x=1778059058;\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=HElj6HrTUG/EgNdqXAaMKxM52pcGGfJKceBIOKrOKnk=;\n b=YCZtL+q2rHNGkrd3iP6DPrcVFFGJFN5kPhEMe0PNRWF7NtqABCkLNaDruR/1n5d835\n 4Qzy2TQPiwAtKrqYk8h+4QTG0JuHPNLDCSkUOUU4JnwhHtWMI8RbQ9tfxnkqxdwP44AS\n X96QQeP0jON9JRKxKKhiSbA/ixjTtRi23OWkiKpCJBxNupDuRWjl/huHp9P6JOX304LP\n da8eYkZ9fic82poulb29nV3HqtKzaUnZHkN2yEqPpmrifGzqryIKfVyMIKcbkvHljq6L\n C2EDUIYk59/MvACjcg5ae8+oATB/Q9fjwT53RhX5NojgX0iqEGAAPWamaA/CCcbt5nC+\n 4N+g==","X-Gm-Message-State":"AOJu0Ywh+g3DAIj7PT1sUk5mMGnu54S8NdgeW+/R1RzXPK1uNaX69qUT\n Thbgp0iSONgE7rhyvom6HHYjji0+9BU49ocyH1NpKQCJ7Y4P4UckWSz5LEaV6wjhq1U=","X-Gm-Gg":"AeBDievnXVjlqgAlajZsl2oQyepEf97VAHj83+Wy8slKsSJ8od/l8JW6CfGQwF3T82J\n iA1cSkVvMVz894MRRjzJ43lq8/OPpjmLxejbdQq9iML9ZVz0tFIUN3IdbA2R0oCsV6Oh6Zjr8Fo\n xoGZmB1JNjuE0HByDLWXT2KnoW8T2x3eGGysOQzqrgbaEK8sl62buUp4qAU50lLSWkZJeo/jGHP\n CWcFnr8OosN5iaaaQBvqqAm/LUtlRCAHvo+qgviu4L/ce41kQu7SVBrx0ZtRqYmJ0KJtntRyoqs\n /BWNaPFuyDFiR9JINI9gLnLgXx9ZnxUgmX/YKZFdWxguzKy4pjCKTzk7Kil6g93j+jANM/JoZge\n OqwVlRJRCneaJ8inEY97rm6vWqUtG6F2pd1r6m6MWcOIhfiui4RLkq0eTBgiWcB+BhASJFpBnVp\n ShmLQJi2HKxwCBZZF5OLlqtLm/KeTNn2GBCGQQ9tjSS2H6ZO89AL0fR7P76PW2oCiQlfzKIr7/e\n knFMaqVr8f/0sjXXm+waKwWloO9B3pFyM6x8/YL5+TRozqAlAlZg9C2ayV+9nB1LcAj0180KbCV\n Qjjj4OtRHYk2uomA","X-Received":"by 2002:a05:600c:1382:b0:488:b99b:4177 with SMTP id\n 5b1f17b1804b1-48a77b232femr102978585e9.25.1777454257879;\n Wed, 29 Apr 2026 02:17:37 -0700 (PDT)","From":"Julien Stephan <jstephan@baylibre.com>","Date":"Wed, 29 Apr 2026 11:17:14 +0200","Subject":"[PATCH v3 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 <20260429-add-ethernet-support-for-genio-520-720-v3-6-1f65e18d4f54@baylibre.com>","References":"\n <20260429-add-ethernet-support-for-genio-520-720-v3-0-1f65e18d4f54@baylibre.com>","In-Reply-To":"\n <20260429-add-ethernet-support-for-genio-520-720-v3-0-1f65e18d4f54@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":"Wed, 29 Apr 2026 14:40: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":"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 | 594 ++++++++++++++++++++++++++++++++++++\n 4 files changed, 603 insertions(+)","diff":"diff --git a/MAINTAINERS b/MAINTAINERS\nindex 735ecc36210..165994cd72f 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 5b109d5c6b4..eb267ac0a40 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_AIROHA_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..9d9958fc665\n--- /dev/null\n+++ b/drivers/net/phy/airoha/air_an8801.c\n@@ -0,0 +1,594 @@\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 led_en;\n+\tu16 gpio;\n+\tu16 led_polarity;\n+\tu16 led_on_cfg;\n+\tu16 led_blk_cfg;\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].led_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].led_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].led_polarity,\n+\t\t\t\t\t      led_cfg[led_id].led_on_cfg,\n+\t\t\t\t\t      led_cfg[led_id].led_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\treturn 0;\n+\t}\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 = malloc(sizeof(*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":["v3","6/9"]}