From patchwork Mon Aug 3 05:14:11 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2893 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id C9F471C057E for ; Mon, 3 Aug 2026 07:16:30 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24912-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24912-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id ED7C23036D4D for ; Mon, 3 Aug 2026 05:15:26 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8D9FC390219; Mon, 3 Aug 2026 05:15:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MhXwd61k" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f50.google.com (mail-ot1-f50.google.com [209.85.210.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E6CA919EED3 for ; Mon, 3 Aug 2026 05:15:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734124; cv=none; b=V+jDITplVo5L/X72mthifZ3mUb75pYe9FTU3u6Ae6Rt7o0g3/zlhfLjjGoKGhBqAAV5LpSXqC9nQgUQzSBRg4RfX5q9xZRIEQ9PJV5a3Kn8QAyG2ASbjgzNwSqzrK5Vwk03mjbA7piyf8O+0KVxNvOfXH79GSOgTfpyY1Aa7j8w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734124; c=relaxed/simple; bh=n3evcqugoeKkN8mct7F9d78wCyor72fP/A5f+80l5jE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CdiiLGUf5vUxFW3IQq12+h6wOK9uBneyiM9PQ8ZyqR4aDGxLnx/6t5QzZgTqmyuBJHxelvOlT03O7Cn7QAeoO7/A/UMoQafNS2xQT3bAmwYAXdtAEf+lYL7z/F5QkQd8Z5f8nTv4d5kxhy/OvXXpuqUhfzz6oUKd++Hqa48NZZ4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=MhXwd61k; arc=none smtp.client-ip=209.85.210.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f50.google.com with SMTP id 46e09a7af769-7ec49608332so1441041a34.3 for ; Sun, 02 Aug 2026 22:15:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734122; x=1786338922; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=LDt8py0RwqfKJ99qa00T7ayi3DardBnaCg62Nlf4UJY=; b=MhXwd61kjF8aYhGmyl+OEY5DxKM1pvzPBzM63EbYmoJWroMQ3EjOf/VzdheVlgZJKk 0yG/crDUMQF3snTOXkaYhYzOeR88t/EX5TPilCS5Jb0M+t8ScMJcM15UMvQxzSVlBu7W adWrd+DQV9QMl8pLh+Tk5k9a2GlsgM+hgW787eQQMYXt89Xd1ZwCR++KQoOocqB/6C+s dNuU2OmTDWAU425DMYvr6bv1gAXj2COflUJ76m0ngUCC/tyESmE2DrLay4tbDENs3gpq 4kvhYUjbfHkcFRkObRK7Desw9LXbnLF2J2Y+m3GoPPyScOIiHnmlmePjgaWaeEB0PPNb iz5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734122; x=1786338922; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=LDt8py0RwqfKJ99qa00T7ayi3DardBnaCg62Nlf4UJY=; b=oPTJwp6k0AEvQ3Sb8Vu6EHP7MtlFTyI+Bo+h9WLD+Al5qER7mFEtZ6XaBUIFcIECuO SqllC30vpwRRBvx0l+L8hY2zc9ncJ2H1wcLN8j/YceYZJP7kaOcEI0vM8aWmnLxuNaYN e7IgqDdPM9v1vmaSiaw4laEo2Q3kLeWaUIllQcT3ersoTSksU4q4s07QAoP8BDhQcFaM nh0d2cWH3AYgpIw+9iKh2uuqF0SlAIo1U92ONV7Mcg+jxP5+AzCaKVl9Mqq3WzUxyBWI ks3EVQpTie/t2ybo21wONt7gRG5I+YKYBeW+vSPlFjOTxZjD/ax1uWiYn1WNptvJuiG+ Lhcg== X-Forwarded-Encrypted: i=1; AHgh+Rqh4sJLBtOW0F4ARCR+hRMCSpCBafbHAz8QLoF/0nBdUDR00lvhEbdQS1HfJIRL7Q3IXdu0P1yNEWlBXg==@lists.linux.dev X-Gm-Message-State: AOJu0Yxef+FQ0uV4PMIQJYSd/VUMZR9hoEDb4sJgrAuaDLZpUFqvtvQi APqGHec8ejFv3+gj1wSKKsPyClzlRWCq+PfaHqjt2ngRwt/Okq5S1Pgo X-Gm-Gg: AR+sD117N8sVlHFVhJtMmK8wGZQOmq/TzsWrGTWpqB4cJ6sjyeEf9Ma+LSA7fUkskX3 yz3qx4jrAG4tYgATZGbCYEFYNRz6rkr9jFlc3ofYrdjK0lXQYzsVbmkXuY1jH8uh+ctcFR9tCI4 XBrDB5BGCq29mgad6epuaXgHPW5g/UOUNC+FyaBNoX/KjW1qsGOtZw9zAj8Cy7OASICizLZBmLR CYA44+OcVxpB1IATrx9AIz1T4mOv8NZCfn4qp5nf1SyrlMQwdz2YC2wGyZXOOzUmHr8xLcd4NBC lWTV6Sl+M1oxnDpIFOeevvvSShxJDvXg1a/A8ooQ6rQj3cxL0R3gPnhyUgrCEVXNJgjp1EmfLEc lyoMxV8t5SZvJPW2TtkBllVgM5zfBW0qwWFhfrIHhvtEBuMAIdE2ckDelwRgEbDFF0uP5VGoex5 yQAEgzFNIWLCe7hNm80+uzqAPPIWXHs124WMhNTA2eu5Y8pQRJpoDYT4IQON2gC1G7Le1s0vray fg9SGy6AvP/QSoDegw/jpiRJmUggyJibAYqvnOFmO8UgAl2UquixPAFWHAU1M1v+OX+cnzhRTru jN3Cpd0VcaZJyhVNw8pAjgFLYtuccLuf6q+o7hVEsXiyHXzyRZG4D6KtOjkhQhS2qLUuf3+jMix Ebf6jsN0wql0IVUBuVZeEmafmwK7TTvY63ZbW X-Received: by 2002:a05:6830:83b8:b0:7e9:d277:6e2e with SMTP id 46e09a7af769-7f196cae28amr13872954a34.7.1785734121347; Sun, 02 Aug 2026 22:15:21 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:20 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:11 -0600 Subject: [PATCH 01/21] dt-bindings: net: allwinner: add H616 EMAC1 Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-1-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [4.34 / 15.00]; RBL_SENDERSCORE(2.00)[172.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; HAS_LIST_UNSUB(-0.01)[]; PRECEDENCE_BULK(0.00)[]; RCPT_COUNT_TWELVE(0.00)[34]; FROM_HAS_DN(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo,bootlin.com:email]; TAGGED_RCPT(0.00)[netdev,dt]; FREEMAIL_CC(0.00)[vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com]; FORGED_SENDER_MAILLIST(0.00)[]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; TAGGED_FROM(0.00)[bounces-24912-noreply=patchwork.local]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10]; FREEMAIL_TO(0.00)[lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,arm.com,bootlin.com,foss.st.com,st.com,synopsys.com,armlinux.org.uk,sntech.de]; FREEMAIL_FROM(0.00)[gmail.com]; TO_DN_SOME(0.00)[]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+]; MID_RHS_MATCH_FROM(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: C9F471C057E X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= From: Richard Genoud The H616 secondary EMAC uses a separate system-control clock register and supports only RMII at 10/100 Mbps. Add its distinct compatible without an older fallback, since using the primary EMAC clock register would not work. Constrain the PHY interface mode to RMII, matching the hardware. The EMAC1 clock register also retains the three-bit TX and five-bit RX delay chains, so allow the existing Allwinner delay properties for this compatible. Signed-off-by: Richard Genoud Signed-off-by: James Hilliard --- .../bindings/net/allwinner,sun8i-a83t-emac.yaml | 18 ++++++++++++++++-- Documentation/devicetree/bindings/net/snps,dwmac.yaml | 2 ++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml index 323a669fa982..34def84e6c21 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml +++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml @@ -21,6 +21,7 @@ select: - allwinner,sun8i-r40-gmac - allwinner,sun8i-v3s-emac - allwinner,sun50i-a64-emac + - allwinner,sun50i-h616-emac1 - allwinner,sun55i-a523-gmac200 required: - compatible @@ -33,6 +34,7 @@ properties: - const: allwinner,sun8i-r40-gmac - const: allwinner,sun8i-v3s-emac - const: allwinner,sun50i-a64-emac + - const: allwinner,sun50i-h616-emac1 - items: - enum: - allwinner,sun20i-d1-emac @@ -91,6 +93,17 @@ required: allOf: - $ref: snps,dwmac.yaml# + - if: + properties: + compatible: + contains: + const: allwinner,sun50i-h616-emac1 + + then: + properties: + phy-mode: + const: rmii + - if: properties: compatible: @@ -100,6 +113,7 @@ allOf: - allwinner,sun8i-h3-emac - allwinner,sun8i-v3s-emac - allwinner,sun50i-a64-emac + - allwinner,sun50i-h616-emac1 then: properties: @@ -109,7 +123,7 @@ allOf: maximum: 700 multipleOf: 100 description: - External RGMII PHY TX clock delay chain value in ps. + PHY interface TX clock delay chain value in ps. allwinner,rx-delay-ps: default: 0 @@ -117,7 +131,7 @@ allOf: maximum: 3100 multipleOf: 100 description: - External RGMII PHY TX clock delay chain value in ps. + PHY interface RX clock delay chain value in ps. - if: properties: diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml index 2449311c6d28..102ec98ac2a0 100644 --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml @@ -57,6 +57,7 @@ properties: - allwinner,sun8i-r40-gmac - allwinner,sun8i-v3s-emac - allwinner,sun50i-a64-emac + - allwinner,sun50i-h616-emac1 - amlogic,meson6-dwmac - amlogic,meson8b-dwmac - amlogic,meson8m2-dwmac @@ -622,6 +623,7 @@ allOf: - allwinner,sun8i-r40-gmac - allwinner,sun8i-v3s-emac - allwinner,sun50i-a64-emac + - allwinner,sun50i-h616-emac1 - loongson,ls2k-dwmac - loongson,ls7a-dwmac - ingenic,jz4775-mac From patchwork Mon Aug 3 05:14:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2895 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 613ED1C057E for ; Mon, 3 Aug 2026 07:17:06 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24913-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24913-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 0B087303CE20 for ; Mon, 3 Aug 2026 05:15:28 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 72DF739185C; Mon, 3 Aug 2026 05:15:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nzq//8Gj" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E2CBB360EC0 for ; Mon, 3 Aug 2026 05:15:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734125; cv=none; b=fIzheELJ643wnz2Yhml83VCLf8Q7Ltmgv1UNIA0lUm+F2QSppDQOef5QlD4SzYGgjBLn1akw9CPCFkMCnFgUelA8Xjka5FkptDGKETQQnlbUNepXLSoaKzcSZKKLZyl0LHVaL27RuIBEQFuWvy4EfUpicuTteIBXjGoxizSQVs0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734125; c=relaxed/simple; bh=LuLd1Fgsqz/EvyuQmaammKLeRagaqJ0vM3tIyUpmvMk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZC2ReVB3BkppNfdQ51LMGGkkOwkW3vhPCNFBj6uZvt7oTJ3uu4kfwOAW2Xu5+EWVMUmo8mUbaa9Tn+2VGofhhwDjeSnn5Dqy5jay4UteILBMKzlmX0VQ/BWSwlRtDhE+UdYNmji+QiwXvz7Yhxe+zg6VMt25DHaHNjzPD4ki310= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nzq//8Gj; arc=none smtp.client-ip=209.85.210.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f53.google.com with SMTP id 46e09a7af769-7e6b554044fso2627193a34.0 for ; Sun, 02 Aug 2026 22:15:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734123; x=1786338923; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=SlcJviNfe1A7bPODjwx5akEOsNAeWr5kscTUhAqnE8U=; b=nzq//8GjDezkf+Cr0hjKGKsQGz7qmrGz5sRAhHL7sbw1rd07JZrkUhzDJT4juBJINg T2aYSfu4U8DXdJz8ps9yYRRoeOuqvU6VCo7GRGYGsQ/mDqkQwUrNW8eBYChdMPHPGqnu dPi5OS1MofaXbfKZK2Iz/C3Ib2SEPRc2DE/G12H6dpZY1ilVbnvAXGp1hf/KELwp1Ui4 j1RpNwVGR5sPPmEppCQnL6j+MzRRAqE/sntJEQpyqx5vgs4asWCxfYp+BfLt8FQDlpLH FBQgxOEnLAdQpvnKPUyDOCkrX8/zNFtVnQ/JzOgl5iCW3FuraXmETYtL72Q887AvI2Gb BTJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734123; x=1786338923; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=SlcJviNfe1A7bPODjwx5akEOsNAeWr5kscTUhAqnE8U=; b=P+In5otIodji5myhm9ZY5cRowCcm0c5x3zZOyR7yLv7P4610GcpC9F9UJkG2+OlwrI e7XjpL7T3c8AOP1kVzdwNc2iNHTN3OALwDHNYSUxHIIWxuN+3pxSpHOs9wIvJyQWbnWh qlpVdL2aSaCMQAVjp87xxWJACCFhWFqQ4rQ0BCOJ2E8QZO9OjzVQ7s/GZvtRQA2Fc4+N BJBwDwpVouFhclIakNH/hJEGehkInpNv17VcZBuuAsVqNtk6wbHnnLr6RDYCKCwCxpff wGrE6FgTDUHsAjXEZNht4yWp0TLAe5n8nYCzgvh5jVgihsg0UlegAAdKyG/ITyM0vXFJ 6IqA== X-Forwarded-Encrypted: i=1; AHgh+RpLkoG5vpQcQYaOy1PNGxEWM2lq2j0ex6SXXHx35bH1qnqLrKFzAvy4WDscKKUkVnn9ixKwNyFFwF7SCA==@lists.linux.dev X-Gm-Message-State: AOJu0YxfZahG7+AYddyOoijMS5jsXqr0e50uAXMD54+H01sajnNIKFyP skhxiUqMePbWmATKIltH8zCZTfUw6OAF54tIUIe0yHmKtwpJQ7QPGC0r X-Gm-Gg: AR+sD11YuJRuL3+E1row8yLe6ayhMBMH8WaINIS4Y2pSdl9gBPTV8kbUYN5que+OHOe tr6QkVVtNx3P7bpJcOORw9+buPwjXwIznEorGhAjkDWofRgGb0klK/J9z8QDbflkMe3/Blkq1+7 oVsJTzO+iqZfWfsx2P5F90SPUev+XtqIeDagqj33ncmuEK17z9XfSHvRfB9DX5tZC8MvO8FVWSh YckMUFoD+SJAbB6UpewjVhPjaYvcXexIsYJCduyOgxD8gnOyByi2EQiyP+40+ko6BDaKSm5xxZH RRRlYPBFxnASpFLPgc9I+oURiMOsjTeM4rgxBZX5qPjGSYjVe3ORXYtbx7ugFU14Oa5z4Tqppcx m7wsrrvJgHp5wIzqt03fiIs0tAQ2//QO1yW3X0ack4aIbgSaWQxc7TVsGJzPuoFUgUA4ViaxNM4 nSZ+2LsqWxz5QFoLSXrh/AZVzpo8yO9DW3870RiRUbuTY6kV/piJaUVVuab7dLpk7DLNKVu7QjZ tLLebYsGJ8PZPSlKzv1tqmKOPY9WFPU9RCi3xF+uUzMDpwIBdSPi0Gaqc274CG9exsKAxJOIkmw If9M3/O920K6tIZw+UwjgkcmqGZcXAs/PQe+KepglOxfZdUD6wZyVUJNsqwJMfXbCSDiCytvlKD i4GT6ga2stBEdCrxj X-Received: by 2002:a05:6830:211b:b0:7e9:c102:333d with SMTP id 46e09a7af769-7f196f8ad8cmr14493591a34.9.1785734122667; Sun, 02 Aug 2026 22:15:22 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:22 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:12 -0600 Subject: [PATCH 02/21] net: stmmac: sun8i: add support for Allwinner H616 EMAC1 Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-2-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= From: Richard Genoud The H616 secondary EMAC uses a separate system-control clock register and supports only RMII at 10/100 Mbps. Its EPHY is provided by a companion AC200 or AC300 package rather than an internal PHY block. Add an EMAC1 variant using the dedicated register and mark the PHY as external. The register retains the standard five-bit RX and three-bit TX clock delay chains, so expose their supported ranges to the shared syscon setup. Signed-off-by: Richard Genoud Signed-off-by: James Hilliard --- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index 48c52eb96233..fdc0c3384af8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -81,6 +81,13 @@ static const struct reg_field sun8i_syscon_reg_field = { .msb = 31, }; +/* EMAC1 clock register @ 0x34 in the "system control" address range */ +static const struct reg_field sun8i_syscon_reg_field_emac1 = { + .reg = 0x34, + .lsb = 0, + .msb = 31, +}; + /* EMAC clock register @ 0x164 in the CCU address range */ static const struct reg_field sun8i_ccu_reg_field = { .reg = 0x164, @@ -143,6 +150,18 @@ static const struct emac_variant emac_variant_h6 = { .tx_delay_max = 7, }; +static const struct emac_variant emac_variant_h616_emac1 = { + .syscon_field = &sun8i_syscon_reg_field_emac1, + /* + * The "internal PHY" is in a companion AC200 or AC300 package, + * rather than on the H616 die. + */ + .soc_has_internal_phy = false, + .support_rmii = true, + .rx_delay_max = 31, + .tx_delay_max = 7, +}; + #define EMAC_BASIC_CTL0 0x00 #define EMAC_BASIC_CTL1 0x04 #define EMAC_INT_STA 0x08 @@ -1278,6 +1297,8 @@ static const struct of_device_id sun8i_dwmac_match[] = { .data = &emac_variant_a64 }, { .compatible = "allwinner,sun50i-h6-emac", .data = &emac_variant_h6 }, + { .compatible = "allwinner,sun50i-h616-emac1", + .data = &emac_variant_h616_emac1 }, { } }; MODULE_DEVICE_TABLE(of, sun8i_dwmac_match); From patchwork Mon Aug 3 05:14:13 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2898 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id A89331C0585 for ; Mon, 3 Aug 2026 07:19:56 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24915-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24915-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 355F330782E5 for ; Mon, 3 Aug 2026 05:15:39 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C83A03955D1; Mon, 3 Aug 2026 05:15:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RA2ajKuw" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f47.google.com (mail-ot1-f47.google.com [209.85.210.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6840D3911DC for ; Mon, 3 Aug 2026 05:15:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734131; cv=none; b=l2WRHc9R3uW77MuRrdIBCgD337ErmgUMwsQq4kiJHGztef1C+bxPHKRo0PM2XQpXyMX5rVFblC10zogO/yd7ObUMrX17CUDSutjagoA073vjUEiLZJB32qt83FkMNvxH9vwHnBd884xWpSfg51lWx/NE4ZbqSH1kgPpSABKTmnI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734131; c=relaxed/simple; bh=zKmrq4Io78YBlcSoFkA6zgzyWtU0hC2kx2tv6Vt1nvQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jjs4/lOhf3tydn5i2y5TTQmyoPDt26VtEC3eYfI03uleQuEsC672TtnLzWzr7gzrZJ55Rh2ajT1UtDuM11d0D9h6lmbEDH90/zre17OxB0tWy8gk1A8MyvicGWbxU2qg75tBosJpcdZAGgrJeUZd6wAJzl4nSrAJ4+Tq0IWUfYs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RA2ajKuw; arc=none smtp.client-ip=209.85.210.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f47.google.com with SMTP id 46e09a7af769-7eb63dbd229so2049680a34.1 for ; Sun, 02 Aug 2026 22:15:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734127; x=1786338927; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=gb4LPnphqc1DtduXOsyl640sXOpfiOxS2LbjD6EtoY4=; b=RA2ajKuwCcH90pFFfHEK7pivdJi65/A6Rxxpq/616sgmB7+keK/X0top/ZzcWl9ng5 uCKXAZFH7RPrHdtod3JSpqmX0ZwdBXDkbAoPLN2nArOPXkwB/K/4zcvcZvaFbV6Vi8Io 1Qc4hXNCc76j7bDEKIur1minFAV9eH1mPP4bQ6BMZsnwYqFSVDlFs3wEEQsBxQKBiHAh 0nN5WodKcmn4xINFPekYysmHq2uZtnLZa98zZqC3m9ZG9Nvf1Pxs//Ss/A4nycX+oNIN nLHdDkxm6haC4QGR1XFjDMUUd+NOtJ6ZiDVbWD0uHtnXbqFCIP+Tspz8ir6yAWFhOHcI x9Bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734127; x=1786338927; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=gb4LPnphqc1DtduXOsyl640sXOpfiOxS2LbjD6EtoY4=; b=DQUSYvVhoVF4RNQpz+hG0I6BWTHP7SdxvrWc/9DCPMmcZ9b3Qs5UIO16GbDn5T7L7R nqyQGbI8XzP5oM/PKjoT3ut9q2Q3XdR0tpp3jrGecO0WPR4ZbsXYXUBdg2PtVS4Zhvcq D8njhbUzdh/y0oY8Ktgd/rnUa49fPBqkxsNSXQrrXncwgx1rxwerjivWID3sQRoCPlAs NHVrKJKQNyFb62NJ8sn3kDPj5UW2VTl7mFfrHT6LjIQJR5hGcV4fVC4VFAmhtfbMZBQZ zHPHafyX5TzVAzcmZ8kISQOomgLkqCFgPz2Xudt/+DA+aNWAtSabyIPbfUIIpZjlvRzS EMzw== X-Forwarded-Encrypted: i=1; AHgh+RpnGgTL297eiklQHiR3MIUjDWCk+DD7ygWv9vnNeBqiLQPxmYc3tRh0kNAu3rK2fnAg7zyqvE3qqtNTuA==@lists.linux.dev X-Gm-Message-State: AOJu0YzzEUO+nOwZxnfTDXFy51F+HK/ORP3WMXSC7ZHr5GJnI/YmNo+4 jHJLnJTTtVzRKHr4RMXvhaGBea79zvSeF+A5GpH84vAKdKoQRVPkrgwR X-Gm-Gg: AR+sD10C69FPtG5Jf+rwGsnvE0GJFMoUsF9b2iSfKkYXm27Z86mbc62U5VrlsDLkKFK zlQ3BNumFmir2Mu1GYxizB9ZcXTuLmIUxR2AtjGA/jOBX6iRt/K5SX9yzi4WTqwioLGXyo8LJc8 0hsmr9MpngpHOxL8ls3fG84NV5yCqmyTKH1VDWiqDTc19AW1akyL4TntlzFvuD3+/OUcaTuArIv oGrB4U2QGE8fawa1En5Q7BNTTisY34RgzHHZgQapJNQTVlRFY4sxMeYr1rY2pmLJP7tHyXZu/+c rungOxEhJibHwdAa2vcJiYMtdiXPalIgjjD5r/VamzeUo791g4FuhliLO0BJ4SOr62ASgymf9uh oSbqI9i+Li6At9sHoGXrIbCAyZNkf3UUdjWzuaKLHqFyU5FWOt8CyVjxNZASomneAWHgC7DPHGo l/klUIj9qeW0jAYhBrks+LVHY/uDfGIuByZNyOqNZA0SfOM8QzaZfp3Ap4T2xwT4nBTYZDZrz+j NzFng+/RBxh+YifbREtZ85M1kTr6L+Hc2idwyZs4y6aP34tiepH9+V6CPu0O32pB8aTcp2fgdD9 oGG3q3wKMxhzaRqtLPOYYat6uzuE8+ECx+w9YmvPeKo6mu33bJ+CwAvqcJrouKT6IlRht4KJVMe QYuH+www5VG5D5bOdETO1C/epIQ== X-Received: by 2002:a05:6830:7086:10b0:7db:a297:9e62 with SMTP id 46e09a7af769-7f1892c8017mr4283606a34.8.1785734124209; Sun, 02 Aug 2026 22:15:24 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:23 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:13 -0600 Subject: [PATCH 03/21] arm64: dts: allwinner: h616: add EMAC1 controller Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-3-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[172.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; HAS_LIST_UNSUB(-0.01)[]; RCPT_COUNT_TWELVE(0.00)[34]; PRECEDENCE_BULK(0.00)[]; FROM_HAS_DN(0.00)[]; FORGED_SENDER_MAILLIST(0.00)[]; TAGGED_RCPT(0.00)[netdev,dt]; FREEMAIL_CC(0.00)[vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo,bootlin.com:email,0.77.92.176:email]; DBL_PROHIBIT(0.00)[0.76.192.112:email]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10]; FREEMAIL_TO(0.00)[lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,arm.com,bootlin.com,foss.st.com,st.com,synopsys.com,armlinux.org.uk,sntech.de]; FREEMAIL_FROM(0.00)[gmail.com]; TO_DN_SOME(0.00)[]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; TAGGED_FROM(0.00)[bounces-24915-noreply=patchwork.local]; MIME_TRACE(0.00)[0:+]; MID_RHS_MATCH_FROM(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: A89331C0585 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= From: Richard Genoud The H616 has a secondary EMAC controller that supports only RMII at 10/100 Mbps. It connects through PA0-PA9 to an EPHY in a companion AC200 or AC300 package. Add the EMAC1 controller and RMII pin group. Leave the controller disabled for boards to enable when the companion Ethernet hardware is present. Signed-off-by: Richard Genoud Signed-off-by: James Hilliard --- arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi index 90fe56a1d3cd..6879f27c2b2b 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi @@ -432,6 +432,14 @@ pwm5_pin: pwm5-pin { function = "pwm5"; }; + /omit-if-no-ref/ + rmii_emac1_pins: rmii-emac1-pins { + pins = "PA0", "PA1", "PA2", "PA3", "PA4", + "PA5", "PA6", "PA7", "PA8", "PA9"; + function = "emac1"; + drive-strength = <40>; + }; + /omit-if-no-ref/ spi0_pins: spi0-pins { pins = "PC0", "PC2", "PC4"; @@ -789,6 +797,28 @@ mdio0: mdio { }; }; + emac1: ethernet@5030000 { + compatible = "allwinner,sun50i-h616-emac1"; + reg = <0x05030000 0x10000>; + interrupts = ; + interrupt-names = "macirq"; + clocks = <&ccu CLK_BUS_EMAC1>; + clock-names = "stmmaceth"; + resets = <&ccu RST_BUS_EMAC1>; + reset-names = "stmmaceth"; + syscon = <&syscon>; + pinctrl-names = "default"; + pinctrl-0 = <&rmii_emac1_pins>; + phy-mode = "rmii"; + status = "disabled"; + + mdio1: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + gpadc: adc@5070000 { compatible = "allwinner,sun50i-h616-gpadc", "allwinner,sun20i-d1-gpadc"; From patchwork Mon Aug 3 05:14:14 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2890 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4]) by mxe881.netcup.net (Postfix) with ESMTPS id 22FBF1C0582 for ; Mon, 3 Aug 2026 07:15:57 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 104.64.211.4) smtp.mailfrom=linux-sunxi+bounces-24914-noreply=patchwork.local@lists.linux.dev smtp.helo=sin.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 104.64.211.4 as permitted sender) client-ip=104.64.211.4; envelope-from=linux-sunxi+bounces-24914-noreply=patchwork.local@lists.linux.dev; helo=sin.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sin.lore.kernel.org (Postfix) with ESMTP id 2CCE1300B0B2 for ; Mon, 3 Aug 2026 05:15:36 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 979BB3939DB; Mon, 3 Aug 2026 05:15:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="JEccS9VL" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F3C038A714 for ; Mon, 3 Aug 2026 05:15:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734129; cv=none; b=Nr3jEmGg5SQkvOwxeY5Z2dy2kNHACfE+VwLjCZgHynOgApoxEE1pkff79dqyBbYK9jPAUfJDb9YNOgvjuSS2I+Cs8fbhkggkKJ8NYj1SS8xNljbagU3zspyDgefI0YaLmmDwWbG3htCy7yDkrq/EW8+EhD5ZFq0HW9Ljxb80GWo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734129; c=relaxed/simple; bh=APfgpJTVA4pOI91gbDaanL4SMg80qg6DwGibNA5NVGQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sksvJ78MXQiwpyzpaiY2FuO8S5nAbAb/yv0voN/fzxFs9aL+Lcmp4UQdNS+OVWUPrsw7oxL5JZpwymo+OfaEYuYQSc73GHAWYD5iA1paUU6coRK/aRMdlIwbYoIaYSA+e6BoBZlewURjqN8pVUK3Cg7iVtcFal6IpGBnMdXA5bU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=JEccS9VL; arc=none smtp.client-ip=209.85.210.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f53.google.com with SMTP id 46e09a7af769-7e9ef94c0e2so1586085a34.3 for ; Sun, 02 Aug 2026 22:15:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734126; x=1786338926; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=fkDHET87UFExhpdvkNx3ant78q307rzdUT3zfbIoItk=; b=JEccS9VLc/PlJD0Mo1D5Vg85nXMsC4fIaegbruqeTzwtCbS3a0cw1CV5vyp6toFPAR K9WfSZIDMIqoCDHEal3wePPURMoZFTs9Rhdv2hAHF1hh0jXEL3Q9aiAZ8o4yR6wxjozp 2YYbPRmvKvJS+FHGskBeB28OMCTD0/Tv0W1fzV8UOpjVElkFI8zRB60ociILp3miC53D YgLbaJgjzeRLU3OZdq8Pw35bDNq35NWfe9BnaSLNoaC9As7zw1IQ+0iZ5Jrakctl4qTd UQUxNibqEyBRsd0IAlEnTOZPaUx9+ybry5TX5PACkOJMmcBQJsJp2eyMMDTTd+oLQkgj cq/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734126; x=1786338926; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=fkDHET87UFExhpdvkNx3ant78q307rzdUT3zfbIoItk=; b=izksQj6FBJsRRA/9TzFSKmkTAsxLBOMGLJwmL1If+NEPpR9ngD2jHpJ5yPbD491GtO TkhB1JrwfDdI7a4y6wXg6k1BsMG0hCO5y43gkMNuVgxuMQg8ox/0ApgUjwNZsr3bvz9p nj36tadtzSNDIMirWffpwl8r4t9FLbJbMkTAriC9EPv9FnSaS1TPfuTcrLQ2x4Za7+k5 4Uy2tC85h5BhsFBQ24SMNQ434JeI4VhS33V9hRfdoiEDFR7z72HIXkbexgwJVkfTOBsv f0hxPTx5cprJTigv33bAQvMubTMGvW7mJoHE+fg5qDnJ3CI48rjPMlyUYEMKsijwO84Z 3fqg== X-Forwarded-Encrypted: i=1; AHgh+RqUuwf6qWtTuEuy2gbQVPPin/RYlXEW28in1VN8qXbu6h8YsZNqBQWLx3/A/k2TqE6FR0TmKqr5bvasGg==@lists.linux.dev X-Gm-Message-State: AOJu0YyvhCu+yP20kkjbi4P/voqWBZHmTobRmngIjg1RkXq9waBAJ/5U mw80DCF/k1qVoe9c08FtMnMEtEhAnYhBdNgb5e/lCFYxeSLMZbzP1Grh X-Gm-Gg: AR+sD10Dz7k/6GQp03bbc4ovMbO8Kbd0dMDgtymyArCgAK8F7mjBUmD5uEQNqJQ0lxw pKeMoylIQlCOUVsRN405cjY+2o0QxZjzQuUx2Kkc8ujpNjJ0eCYyFl+zSgxFciuoMpFhju9znJo zMmBFEpRFOHAQCzCQDYHVi/B4yYSyZr5zq7hpjKLRPU5vz7jQqqq4UsiWa68he3YO3+TswpxyTM /jsOZHxAjNpWu7u/JRpylHy+ySF+aIohFSuBrvV/Hy+6H0XXLvQ/88CMOhjSI03szBIGv7fefCL 5ThbvB6ya4vIEhG0p1l/RK98wMnd6P63KjH3JU+Aa6Z/ohKhcjDGbkNmKF5b2Y4E8MbPvx+qTTx cWLkUusEFdQWXpZXBFsZbg2jz/QOTXku6etH3Ze0aCOzl3+1JD6gOW+rkCUjGrTTS/sPZYOcuJ6 nE5CGXCAo193xtqwvsH0r1sF95QBQ45Ho+bDhDNKfd4pDJyHDN6kXQalrY7a4aGbiUaWObRNmP1 slHHBv7iOt7ln/ym60Rg29XPIhpVTMhvWrS3OzdL40FevRz6yQRCzZCmdFrOQ41WwrS+clDCLKC y1pmWx9zSOh/rNvlWLU3DySDyAceeq7M/IajNpRAz0iGgyvVI57LWeZ4HADgbXTEyEJliBMqwU5 oMlZd1Brla2kO5pav4rd+eUHk9D2L0ssokJFJqg== X-Received: by 2002:a05:6830:8389:b0:7e9:e709:44f6 with SMTP id 46e09a7af769-7f196ea3b40mr13694676a34.12.1785734125552; Sun, 02 Aug 2026 22:15:25 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:25 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:14 -0600 Subject: [PATCH 04/21] net: mdio: factor out OF child registration helpers Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-4-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[104.64.211.4:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; HAS_LIST_UNSUB(-0.01)[]; FREEMAIL_CC(0.00)[vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com]; FORGED_SENDER_MAILLIST(0.00)[]; RCPT_COUNT_TWELVE(0.00)[34]; FROM_HAS_DN(0.00)[]; TAGGED_RCPT(0.00)[netdev,dt]; PRECEDENCE_BULK(0.00)[]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; TAGGED_FROM(0.00)[bounces-24914-noreply=patchwork.local]; R_SPF_ALLOW(0.00)[+ip4:104.64.211.4]; FREEMAIL_TO(0.00)[lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,arm.com,bootlin.com,foss.st.com,st.com,synopsys.com,armlinux.org.uk,sntech.de]; FREEMAIL_FROM(0.00)[gmail.com]; TO_DN_SOME(0.00)[]; ASN(0.00)[asn:63949, ipnet:104.64.192.0/19, country:SG]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+]; MID_RHS_MATCH_FROM(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 22FBF1C0582 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Live OF reconfiguration needs to create the same PHY and generic MDIO devices as initial bus population, including legacy PHY nodes that need address scanning. Factor fixed-address child registration and PHY address scanning into helpers. The old scan loop also visited every free address for a child without a reg property even when the child was not a PHY. Reject that case before scanning while preserving enumeration of valid PHY and generic MDIO children. Signed-off-by: James Hilliard --- drivers/net/mdio/of_mdio.c | 66 ++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c index b8d298c04d3f..051e449bbe7c 100644 --- a/drivers/net/mdio/of_mdio.c +++ b/drivers/net/mdio/of_mdio.c @@ -77,6 +77,15 @@ static int of_mdiobus_register_device(struct mii_bus *mdio, return 0; } +static int of_mdiobus_register_child(struct mii_bus *mdio, + struct device_node *child, u32 addr) +{ + if (of_mdiobus_child_is_phy(child)) + return of_mdiobus_register_phy(mdio, child, addr); + + return of_mdiobus_register_device(mdio, child, addr); +} + /* The following is a list of PHY compatible strings which appear in * some DTBs. The compatible string is never matched against a PHY * driver, so is pointless. We only expect devices which are not PHYs @@ -136,6 +145,32 @@ bool of_mdiobus_child_is_phy(struct device_node *child) } EXPORT_SYMBOL(of_mdiobus_child_is_phy); +static int of_mdiobus_scan_phy(struct mii_bus *mdio, + struct device_node *child) +{ + int addr, rc; + + if (!of_mdiobus_child_is_phy(child)) + return -ENODEV; + + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { + if (mdiobus_is_registered_device(mdio, addr)) + continue; + + dev_info(&mdio->dev, "scan phy %pOFn at address %i\n", + child, addr); + + /* -ENODEV means that scanning should continue. */ + rc = of_mdiobus_register_child(mdio, child, addr); + if (!rc) + return 0; + if (rc != -ENODEV) + return rc; + } + + return -ENODEV; +} + static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np, bool *scanphys) { @@ -164,10 +199,7 @@ static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np, continue; } - if (of_mdiobus_child_is_phy(child)) - rc = of_mdiobus_register_phy(mdio, child, addr); - else - rc = of_mdiobus_register_device(mdio, child, addr); + rc = of_mdiobus_register_child(mdio, child, addr); if (rc == -ENODEV) dev_err(&mdio->dev, @@ -197,7 +229,7 @@ int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np, { struct device_node *child; bool scanphys = false; - int addr, rc; + int rc; if (!np) return __mdiobus_register(mdio, owner); @@ -238,27 +270,9 @@ int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np, of_node_name_eq(child, "ethernet-phy-package")) continue; - for (addr = 0; addr < PHY_MAX_ADDR; addr++) { - /* skip already registered PHYs */ - if (mdiobus_is_registered_device(mdio, addr)) - continue; - - /* be noisy to encourage people to set reg property */ - dev_info(&mdio->dev, "scan phy %pOFn at address %i\n", - child, addr); - - if (of_mdiobus_child_is_phy(child)) { - /* -ENODEV is the return code that PHYLIB has - * standardized on to indicate that bus - * scanning should continue. - */ - rc = of_mdiobus_register_phy(mdio, child, addr); - if (!rc) - break; - if (rc != -ENODEV) - goto put_unregister; - } - } + rc = of_mdiobus_scan_phy(mdio, child); + if (rc && rc != -ENODEV) + goto put_unregister; } return 0; From patchwork Mon Aug 3 05:14:15 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2899 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 12D151C0583 for ; Mon, 3 Aug 2026 07:20:12 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24916-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24916-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id E85CA3081B53 for ; Mon, 3 Aug 2026 05:15:41 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8AA0023E325; Mon, 3 Aug 2026 05:15:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FFvLnoIZ" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f42.google.com (mail-ot1-f42.google.com [209.85.210.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 584DF3909B8 for ; Mon, 3 Aug 2026 05:15:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734134; cv=none; b=nEjxQ8YJj6ptTZM/VyV8CS0TFK+L2wI8IQVLWTUJq5awEzfNegUS5/5lQqvwGxvccHy+gwiyfJs1NlCSy8c9ae26/b/hFBfJaYWVMYrcb1HWNM/YnlgdWhddqT/uk6tU/fTzdiFK16fG+3iEYsCMZ2tX4UwKHjSuONvLkIxso5o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734134; c=relaxed/simple; bh=06Ndjp2qmfFDz4dq/1g4wiH9y+i9NX4WqoGE7f9jRYQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ajbxW/DH4tD4qk+Vyp3CUDq7S9w6cAp+elZjs52o/DRKSPBWmZwzTiEJPQcR17iWIS939wuY1CIAbO6dsb0w6SkR6Cy49e2g1QmuLqN6c6Rw2Trzt8NfFzxQ3+6NYktD40wzZN//i/DlktzMCXgbbBTST2913yaKMNgy1r5CL8c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=FFvLnoIZ; arc=none smtp.client-ip=209.85.210.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f42.google.com with SMTP id 46e09a7af769-7eb1dc6bd53so1828524a34.2 for ; Sun, 02 Aug 2026 22:15:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734127; x=1786338927; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=wwVnovEquKlLXg/zw4hAH7SWHSDxoW5mo3oFAsopbqY=; b=FFvLnoIZTIWKFUX7H2h8PJXEeFN8NLJzAU4MSm1H4aXK4Ix6eAfBQv4onQ7T364ZuA C4gPSXJJMPbGQXbi//PhyeL72kUApFjsGuMhcBqElq38V967cfYx8XUWgtLJjrf3Cr5z bembDjEf3vt/ekt77Zo2WfgBRCL70yd7n+2GcxG0NUWThtYjXw44u5nR6oVgeBrQOvEc 3Z4ZwlkiGF05XLkikAuluKi/Ap7yjkw1KTvzToz3APeRP9A1PZMaycDE5upWnc4NdmN2 cLSMfdpVbcRyt5/b324JH5AWqUaAVdBKsECh+FNTo4m3WyocukFmGA840hRA1jHVQus5 OpSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734127; x=1786338927; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=wwVnovEquKlLXg/zw4hAH7SWHSDxoW5mo3oFAsopbqY=; b=Tt/xD0B86/zBuA2IKd8SuwSOYkG9i0VGP6VNLv7SWqD+HpQ7IDME4VnovDVqEhj9U4 LfPHq0QTzJoumh0byQRy/F7NqSiOMEK8qo7RPLED93WeSCp3req77OT79B+pVUQkQizE f8PqM+yYuADr6OSLOoxawC7DFpd83X5chKhPsCUCPNYGWi5otPfA+0W9hNkGvcKaq1Vt 0fxxdZH+sJrUfHVZvGLBVCfVcGmziWjdm8G4XRn90LX9RbGZY/j/eG+io0FufFyvXX7W wM8hXR5bu104y65+GAE7gCkjwqbwXPcLOf6s0vbSKXv++ho+l+yN4HaZwwfpVKWbxjJf If/w== X-Forwarded-Encrypted: i=1; AHgh+RpmMP9boQrfx/aYfKoKLB1uGYq4hNDKh1zhEi8mxNkfX4YbS6l6eRxUrTn5TsHt7dylu9Hby5RaEWbHBA==@lists.linux.dev X-Gm-Message-State: AOJu0Yw3Rv4X72oW15Eq6tEe9b0Qe3nk5hEANaU0f9ua9YZCU3GH18vF uBT2lI4/96CHuwE6ewRH/AN1Tie7fknm6jCWFM6QP3o21z9KkdHCljT2 X-Gm-Gg: AR+sD106u8wkUXNNKa9bLJnouDjZD8iykkS84jeeWbS9Ht9RO/0hBp10IGZnsRSKl6w gGNZ/CTxpgikIkdTP/C+GrZfDni9h+jj3ljQ+3Bmg1NwSPAsKaWi+/nLKU0mIVNSHW3uaaYRioP uXSXGjxMLy97O9Gw8/YFlySfzeUa/n4hxKTgjG9g54GWdAv2hU1NoxT0zH2VVO0Yo79NfEUpm5Z AuYFb9vwKkKQMYm2sApNGgR2fjW48Tdl4W+nHAy1z4FK6cEHJup2hPEvJV1EDhEUrZJvnWVEspl bXI3rTKE99GUVo+sO0zunM0JPOaoBreK1qnjWkGVefr/qUc/t/mvy7/BUrNMXGqRsGrUrcGopmV LwVxmRu5LlgoXi4sEJKiM6J4Jfmw9pvPQ0BiWYtRG0NXvN1iqb71fiH5tW/uS6K1rtw3hiRP7rX /eI7QHqxmBZI+GKD3AKhbd5LgyOE7ekb+2szACdNuZrbKz5s7zvuMsDmnBZILdmYiDyifPM/AKM lb73DL9sOkZXwWPS02X6FHkrF386b8nEJEQP7/a2DxkGpxAoQyWVsWz25unHSTvbCeFXEmkjCDT VDbkVGyJ0FR99Xj4MYz4IhCMfaYvZhzGVtx5X7t0CWnnGxyS2ebAfLnmTk1hZLQvRA32vC99CUI vllQFQCatwYamidgEa9QYIoHwZ88= X-Received: by 2002:a05:6830:601b:b0:7e9:c72e:e5d6 with SMTP id 46e09a7af769-7f197075663mr13841824a34.14.1785734126952; Sun, 02 Aug 2026 22:15:26 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:26 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:15 -0600 Subject: [PATCH 05/21] net: mdio: make device map changes hotplug-safe Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-5-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= MDIO device registration currently publishes directly into mdio_map without serializing address ownership, and removal frees the object immediately. That is sufficient while bus population is static, but dynamic firmware changes can race registration, PHY attachment and bus teardown. It also cannot safely preserve mdiobus_get_phy()'s borrowed-pointer convention. Serialize device-map state and reserve addresses while registration is in progress. Track active scans, registrations and firmware changes so bus teardown first blocks new work and waits for existing work before consuming the final map. Block new registrations and PHY attachment while a firmware removal owns the map. Publish initialized devices with release ordering and make PHY attachment atomic with map removal, including standalone PHY users. Have address scans atomically claim a matching OF node as well, so explicit OF population cannot instantiate the same device concurrently. Keep dynamically removed devices pinned until the MDIO bus is torn down so existing borrowed pointers cannot become use-after-free references. Drop their firmware-node reference after device_del() so this does not keep an overlay node alive. Normal MDIO removal and driver APIs remain unchanged, and consumers do not need to adopt a new refcounting API. Signed-off-by: James Hilliard --- drivers/net/phy/mdio_bus.c | 14 ++- drivers/net/phy/mdio_bus_provider.c | 140 +++++++++++++++------ drivers/net/phy/mdio_device.c | 235 ++++++++++++++++++++++++++++++++---- drivers/net/phy/phy_device.c | 102 ++++++++++++---- drivers/net/phy/phylib-internal.h | 4 +- include/linux/mdio.h | 6 + include/linux/phy.h | 18 +++ 7 files changed, 434 insertions(+), 85 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 00d0e4159e9b..f45c936fe5aa 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -34,7 +34,8 @@ static struct mdio_device *mdiobus_find_device(struct mii_bus *bus, int addr) if (WARN_ONCE(!addr_valid, "addr %d out of range\n", addr)) return NULL; - return bus->mdio_map[addr]; + /* Pair with map publication in mdiobus_register_device(). */ + return smp_load_acquire(&bus->mdio_map[addr]); } struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr) @@ -54,7 +55,16 @@ EXPORT_SYMBOL(mdiobus_get_phy); bool mdiobus_is_registered_device(struct mii_bus *bus, int addr) { - return mdiobus_find_device(bus, addr) != NULL; + bool addr_valid = addr >= 0 && addr < ARRAY_SIZE(bus->mdio_map); + bool registered; + + if (WARN_ONCE(!addr_valid, "addr %d out of range\n", addr)) + return false; + + registered = READ_ONCE(bus->mdio_map[addr]) || + (READ_ONCE(bus->mdio_map_pending) & BIT(addr)); + + return registered; } EXPORT_SYMBOL(mdiobus_is_registered_device); diff --git a/drivers/net/phy/mdio_bus_provider.c b/drivers/net/phy/mdio_bus_provider.c index ce3a607a40cb..b83a0a7a4235 100644 --- a/drivers/net/phy/mdio_bus_provider.c +++ b/drivers/net/phy/mdio_bus_provider.c @@ -330,6 +330,9 @@ struct mii_bus *mdiobus_alloc_size(size_t size) return NULL; bus->state = MDIOBUS_ALLOCATED; + mutex_init(&bus->mdio_map_lock); + init_waitqueue_head(&bus->mdio_map_wait); + INIT_LIST_HEAD(&bus->mdio_map_retired); if (size) bus->priv = (void *)bus + aligned_size; @@ -360,18 +363,21 @@ static int of_mdiobus_find_phy(struct device *dev, struct mdio_device *mdiodev, int addr; if (of_node_name_eq(child, "ethernet-phy-package")) { + int ret; + /* Validate PHY package reg presence */ if (!of_property_present(child, "reg")) { of_node_put(child); return -EINVAL; } - if (!of_mdiobus_find_phy(dev, mdiodev, child)) { + ret = of_mdiobus_find_phy(dev, mdiodev, child); + if (ret != -ENODEV) { /* The refcount for the PHY package will be * incremented later when PHY join the Package. */ of_node_put(child); - return 0; + return ret; } continue; @@ -382,6 +388,11 @@ static int of_mdiobus_find_phy(struct device *dev, struct mdio_device *mdiodev, continue; if (addr == mdiodev->addr) { + if (of_node_test_and_set_flag(child, OF_POPULATED)) { + of_node_put(child); + return -EBUSY; + } + device_set_node(dev, of_fwnode_handle(child)); /* The refcount on "child" is passed to the mdio * device. Do _not_ use of_node_put(child) here. @@ -393,22 +404,26 @@ static int of_mdiobus_find_phy(struct device *dev, struct mdio_device *mdiodev, return -ENODEV; } -static void of_mdiobus_link_mdiodev(struct mii_bus *bus, - struct mdio_device *mdiodev) +static int of_mdiobus_link_mdiodev(struct mii_bus *bus, + struct mdio_device *mdiodev) { struct device *dev = &mdiodev->dev; if (dev->of_node || !bus->dev.of_node) - return; + return 0; - of_mdiobus_find_phy(dev, mdiodev, bus->dev.of_node); + return of_mdiobus_find_phy(dev, mdiodev, bus->dev.of_node); } #endif -static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr, bool c45) +static struct phy_device *__mdiobus_scan(struct mii_bus *bus, int addr, + bool c45) { struct phy_device *phydev = ERR_PTR(-ENODEV); struct fwnode_handle *fwnode; +#if IS_ENABLED(CONFIG_OF_MDIO) + bool of_node_populated = false; +#endif char node_name[16]; int err; @@ -420,7 +435,12 @@ static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr, bool c45) /* For DT, see if the auto-probed phy has a corresponding child * in the bus node, and set the of_node pointer in this case. */ - of_mdiobus_link_mdiodev(bus, &phydev->mdio); + err = of_mdiobus_link_mdiodev(bus, &phydev->mdio); + if (err == -EBUSY) { + phy_device_free(phydev); + return ERR_PTR(-ENODEV); + } + of_node_populated = !!phydev->mdio.dev.of_node; #endif /* Search for a swnode for the phy in the swnode hierarchy of the bus. @@ -437,6 +457,11 @@ static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr, bool c45) err = phy_device_register(phydev); if (err) { +#if IS_ENABLED(CONFIG_OF_MDIO) + if (of_node_populated) + of_node_clear_flag(phydev->mdio.dev.of_node, + OF_POPULATED); +#endif phy_device_free(phydev); return ERR_PTR(-ENODEV); } @@ -458,7 +483,17 @@ static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr, bool c45) */ struct phy_device *mdiobus_scan_c22(struct mii_bus *bus, int addr) { - return mdiobus_scan(bus, addr, false); + struct phy_device *phydev; + int err; + + err = mdiobus_device_change_begin(bus, false); + if (err) + return ERR_PTR(err); + + phydev = __mdiobus_scan(bus, addr, false); + mdiobus_device_change_end(bus, false); + + return phydev; } EXPORT_SYMBOL(mdiobus_scan_c22); @@ -476,7 +511,7 @@ EXPORT_SYMBOL(mdiobus_scan_c22); */ static struct phy_device *mdiobus_scan_c45(struct mii_bus *bus, int addr) { - return mdiobus_scan(bus, addr, true); + return __mdiobus_scan(bus, addr, true); } static int mdiobus_scan_bus_c22(struct mii_bus *bus) @@ -487,7 +522,7 @@ static int mdiobus_scan_bus_c22(struct mii_bus *bus) if ((bus->phy_mask & BIT(i)) == 0) { struct phy_device *phydev; - phydev = mdiobus_scan_c22(bus, i); + phydev = __mdiobus_scan(bus, i, false); if (IS_ERR(phydev) && (PTR_ERR(phydev) != -ENODEV)) return PTR_ERR(phydev); } @@ -504,7 +539,7 @@ static int mdiobus_scan_bus_c45(struct mii_bus *bus) struct phy_device *phydev; /* Don't scan C45 if we already have a C22 device */ - if (bus->mdio_map[i]) + if (mdiobus_is_registered_device(bus, i)) continue; phydev = mdiobus_scan_c45(bus, i); @@ -536,6 +571,44 @@ static bool mdiobus_prevent_c45_scan(struct mii_bus *bus) return false; } +static void mdiobus_stop_device_changes(struct mii_bus *bus) +{ + mutex_lock(&bus->mdio_map_lock); + bus->state = MDIOBUS_UNREGISTERING; + mutex_unlock(&bus->mdio_map_lock); + + wait_event(bus->mdio_map_wait, !READ_ONCE(bus->mdio_map_ops)); +} + +static void mdiobus_remove_devices(struct mii_bus *bus) +{ + LIST_HEAD(removed); + struct mdio_device *mdiodev, *next; + int i; + + for (i = 0; i < PHY_MAX_ADDR; i++) { + mdiodev = bus->mdio_map[i]; + if (!mdiodev) + continue; + + mdiodev->device_remove(mdiodev); + mdiodev->device_free(mdiodev); + } + + mutex_lock(&bus->mdio_map_lock); + list_splice_init(&bus->mdio_map_retired, &removed); + mutex_unlock(&bus->mdio_map_lock); + + list_for_each_entry_safe(mdiodev, next, &removed, retired_node) { + list_del_init(&mdiodev->retired_node); + mdio_device_put(mdiodev); + } + + mutex_lock(&bus->mdio_map_lock); + bus->state = MDIOBUS_UNREGISTERED; + mutex_unlock(&bus->mdio_map_lock); +} + /** * __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus * @bus: target mii_bus @@ -552,10 +625,9 @@ static bool mdiobus_prevent_c45_scan(struct mii_bus *bus) */ int __mdiobus_register(struct mii_bus *bus, struct module *owner) { - struct mdio_device *mdiodev; struct gpio_desc *gpiod; bool prevent_c45_scan; - int i, err; + int err; if (!bus || !bus->name) return -EINVAL; @@ -596,7 +668,9 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) * * State will be updated later in this function in case of success */ + mutex_lock(&bus->mdio_map_lock); bus->state = MDIOBUS_UNREGISTERED; + mutex_unlock(&bus->mdio_map_lock); err = device_register(&bus->dev); if (err) { @@ -613,8 +687,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) err = dev_err_probe(&bus->dev, PTR_ERR(gpiod), "mii_bus %s couldn't get reset GPIO\n", bus->id); - device_del(&bus->dev); - return err; + goto error_reset_gpiod; } else if (gpiod) { bus->reset_gpiod = gpiod; fsleep(bus->reset_delay_us); @@ -629,6 +702,10 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) goto error_reset_gpiod; } + mutex_lock(&bus->mdio_map_lock); + bus->state = MDIOBUS_REGISTERING; + mutex_unlock(&bus->mdio_map_lock); + if (bus->read) { err = mdiobus_scan_bus_c22(bus); if (err) @@ -643,20 +720,17 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) goto error; } + mutex_lock(&bus->mdio_map_lock); bus->state = MDIOBUS_REGISTERED; + mutex_unlock(&bus->mdio_map_lock); dev_dbg(&bus->dev, "probed\n"); return 0; error: - for (i = 0; i < PHY_MAX_ADDR; i++) { - mdiodev = bus->mdio_map[i]; - if (!mdiodev) - continue; - - mdiodev->device_remove(mdiodev); - mdiodev->device_free(mdiodev); - } error_reset_gpiod: + mdiobus_stop_device_changes(bus); + mdiobus_remove_devices(bus); + /* Put PHYs in RESET to save power */ if (bus->reset_gpiod) gpiod_set_value_cansleep(bus->reset_gpiod, 1); @@ -668,21 +742,11 @@ EXPORT_SYMBOL(__mdiobus_register); void mdiobus_unregister(struct mii_bus *bus) { - struct mdio_device *mdiodev; - int i; - if (WARN_ON_ONCE(bus->state != MDIOBUS_REGISTERED)) return; - bus->state = MDIOBUS_UNREGISTERED; - - for (i = 0; i < PHY_MAX_ADDR; i++) { - mdiodev = bus->mdio_map[i]; - if (!mdiodev) - continue; - mdiodev->device_remove(mdiodev); - mdiodev->device_free(mdiodev); - } + mdiobus_stop_device_changes(bus); + mdiobus_remove_devices(bus); /* Put PHYs in RESET to save power */ if (bus->reset_gpiod) @@ -702,8 +766,11 @@ EXPORT_SYMBOL(mdiobus_unregister); */ void mdiobus_free(struct mii_bus *bus) { + mutex_lock(&bus->mdio_map_lock); + /* For compatibility with error handling in drivers. */ if (bus->state == MDIOBUS_ALLOCATED) { + mutex_unlock(&bus->mdio_map_lock); kfree(bus); return; } @@ -711,6 +778,7 @@ void mdiobus_free(struct mii_bus *bus) WARN(bus->state != MDIOBUS_UNREGISTERED, "%s: not in UNREGISTERED state\n", bus->id); bus->state = MDIOBUS_RELEASED; + mutex_unlock(&bus->mdio_map_lock); put_device(&bus->dev); } diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c index 56080d3d2d25..49092045831f 100644 --- a/drivers/net/phy/mdio_device.c +++ b/drivers/net/phy/mdio_device.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -38,8 +39,12 @@ static int mdio_device_register_reset(struct mdio_device *mdiodev) /* Deassert the optional reset signal */ mdiodev->reset_gpio = gpiod_get_optional(&mdiodev->dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(mdiodev->reset_gpio)) - return PTR_ERR(mdiodev->reset_gpio); + if (IS_ERR(mdiodev->reset_gpio)) { + int err = PTR_ERR(mdiodev->reset_gpio); + + mdiodev->reset_gpio = NULL; + return err; + } if (mdiodev->reset_gpio) gpiod_set_consumer_name(mdiodev->reset_gpio, "PHY reset"); @@ -117,6 +122,13 @@ static void mdio_device_release(struct device *dev) kfree(to_mdio_device(dev)); } +static int __mdio_device_remove(struct mdio_device *mdiodev, bool dynamic); + +static int mdio_device_remove_dynamic(struct mdio_device *mdiodev) +{ + return __mdio_device_remove(mdiodev, true); +} + struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr) { struct mdio_device *mdiodev; @@ -131,9 +143,11 @@ struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr) mdiodev->dev.bus = &mdio_bus_type; mdiodev->device_free = mdio_device_free; mdiodev->device_remove = mdio_device_remove; + mdiodev->device_remove_dynamic = mdio_device_remove_dynamic; mdiodev->bus = bus; mdiodev->addr = addr; mdiodev->reset_state = -1; + INIT_LIST_HEAD(&mdiodev->retired_node); dev_set_name(&mdiodev->dev, PHY_ID_FMT, bus->id, addr); @@ -160,19 +174,27 @@ int mdio_device_register(struct mdio_device *mdiodev) return err; err = device_add(&mdiodev->dev); - if (err) { + if (err) pr_err("MDIO %d failed to add\n", mdiodev->addr); - goto out; - } - - return 0; - out: - mdiobus_unregister_device(mdiodev); - return err; + return mdiobus_registration_done(mdiodev, err); } EXPORT_SYMBOL(mdio_device_register); +static int __mdio_device_remove(struct mdio_device *mdiodev, bool dynamic) +{ + int err; + + err = mdiobus_begin_remove(mdiodev, dynamic); + if (err) + return err; + + device_del(&mdiodev->dev); + mdiobus_finish_remove(mdiodev, dynamic); + + return 0; +} + /** * mdio_device_remove - Remove a previously registered mdio device from the * MDIO bus @@ -184,42 +206,211 @@ EXPORT_SYMBOL(mdio_device_register); */ void mdio_device_remove(struct mdio_device *mdiodev) { - device_del(&mdiodev->dev); - mdiobus_unregister_device(mdiodev); + __mdio_device_remove(mdiodev, false); } EXPORT_SYMBOL(mdio_device_remove); int mdiobus_register_device(struct mdio_device *mdiodev) { + struct mii_bus *bus = mdiodev->bus; int err; - if (mdiodev->bus->mdio_map[mdiodev->addr]) - return -EBUSY; + mutex_lock(&bus->mdio_map_lock); + if (bus->state != MDIOBUS_REGISTERING && + bus->state != MDIOBUS_REGISTERED) { + err = -ENODEV; + goto out_unlock; + } + if (bus->mdio_map_removals) { + err = -EBUSY; + goto out_unlock; + } + + if (bus->mdio_map[mdiodev->addr] || + bus->mdio_map_pending & BIT(mdiodev->addr)) { + err = -EBUSY; + goto out_unlock; + } + + bus->mdio_map_pending |= BIT(mdiodev->addr); + bus->mdio_map_ops++; + mutex_unlock(&bus->mdio_map_lock); if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) { err = mdio_device_register_reset(mdiodev); - if (err) + if (err) { + mdiobus_registration_done(mdiodev, err); return err; + } /* Assert the reset signal */ mdio_device_reset(mdiodev, 1); } - mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev; + mutex_lock(&bus->mdio_map_lock); + /* Teardown waits for this registration before consuming the map. */ + smp_store_release(&bus->mdio_map[mdiodev->addr], mdiodev); + mutex_unlock(&bus->mdio_map_lock); return 0; + +out_unlock: + mutex_unlock(&bus->mdio_map_lock); + return err; } -int mdiobus_unregister_device(struct mdio_device *mdiodev) +/** + * mdiobus_device_change_begin - start changing devices on a registered bus + * @bus: MDIO bus that will be scanned or changed + * @removing: whether PHY attachment must be blocked during the change + * + * Return: zero on success or a negative error code when the bus is unavailable + */ +int mdiobus_device_change_begin(struct mii_bus *bus, bool removing) { - if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev) - return -EINVAL; + int err = 0; + + mutex_lock(&bus->mdio_map_lock); + if (bus->state != MDIOBUS_REGISTERED) { + err = -ENODEV; + } else { + bus->mdio_map_ops++; + if (removing) + bus->mdio_map_removals++; + } + mutex_unlock(&bus->mdio_map_lock); + + return err; +} +EXPORT_SYMBOL_GPL(mdiobus_device_change_begin); - mdio_device_unregister_reset(mdiodev); +static void mdiobus_operation_done_locked(struct mii_bus *bus) +{ + lockdep_assert_held(&bus->mdio_map_lock); - mdiodev->bus->mdio_map[mdiodev->addr] = NULL; + if (WARN_ON_ONCE(!bus->mdio_map_ops)) + return; + bus->mdio_map_ops--; + if (!bus->mdio_map_ops) + wake_up_all(&bus->mdio_map_wait); +} - return 0; +/** + * mdiobus_device_change_end - finish changing devices on an MDIO bus + * @bus: MDIO bus previously passed to mdiobus_device_change_begin() + * @removing: value passed to mdiobus_device_change_begin() + */ +void mdiobus_device_change_end(struct mii_bus *bus, bool removing) +{ + mutex_lock(&bus->mdio_map_lock); + if (removing) { + if (!WARN_ON_ONCE(!bus->mdio_map_removals)) + bus->mdio_map_removals--; + } + mdiobus_operation_done_locked(bus); + mutex_unlock(&bus->mdio_map_lock); +} +EXPORT_SYMBOL_GPL(mdiobus_device_change_end); + +static void mdiobus_operation_done(struct mii_bus *bus) +{ + mutex_lock(&bus->mdio_map_lock); + mdiobus_operation_done_locked(bus); + mutex_unlock(&bus->mdio_map_lock); +} + +static void mdiobus_unpublish_device(struct mdio_device *mdiodev) +{ + struct mii_bus *bus = mdiodev->bus; + + lockdep_assert_held(&bus->mdio_map_lock); + + if (bus->mdio_map[mdiodev->addr] == mdiodev) + WRITE_ONCE(bus->mdio_map[mdiodev->addr], NULL); + if (mdiodev->dev.of_node) + of_node_clear_flag(mdiodev->dev.of_node, OF_POPULATED); +} + +int mdiobus_registration_done(struct mdio_device *mdiodev, int err) +{ + struct mii_bus *bus = mdiodev->bus; + + mutex_lock(&bus->mdio_map_lock); + if (WARN_ON_ONCE(!(bus->mdio_map_pending & BIT(mdiodev->addr)))) + goto out_unlock; + + if (err) + mdiobus_unpublish_device(mdiodev); + else + WARN_ON_ONCE(bus->mdio_map[mdiodev->addr] != mdiodev); + + bus->mdio_map_pending &= ~BIT(mdiodev->addr); + +out_unlock: + mutex_unlock(&bus->mdio_map_lock); + if (err) { + if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) { + mdio_device_reset(mdiodev, 1); + mdio_device_unregister_reset(mdiodev); + } + } + mdiobus_operation_done(bus); + + return err; +} + +int mdiobus_begin_remove(struct mdio_device *mdiodev, bool dynamic) +{ + struct mii_bus *bus = mdiodev->bus; + int err = 0; + + mutex_lock(&bus->mdio_map_lock); + if (dynamic && (bus->state == MDIOBUS_UNREGISTERED || + bus->state == MDIOBUS_RELEASED)) { + err = -ENODEV; + goto out_unlock; + } + if (bus->mdio_map_pending & BIT(mdiodev->addr)) { + err = -EBUSY; + goto out_unlock; + } + + if (bus->mdio_map[mdiodev->addr] != mdiodev) { + err = -ENODEV; + goto out_unlock; + } + + if (dynamic && mdiodev->flags & MDIO_DEVICE_FLAG_PHY && + to_phy_device(&mdiodev->dev)->attached) { + err = -EBUSY; + goto out_unlock; + } + + mdiobus_unpublish_device(mdiodev); + + if (dynamic) { + mdio_device_get(mdiodev); + list_add_tail(&mdiodev->retired_node, &bus->mdio_map_retired); + } + +out_unlock: + mutex_unlock(&bus->mdio_map_lock); + return err; +} + +void mdiobus_finish_remove(struct mdio_device *mdiodev, bool dynamic) +{ + struct fwnode_handle *fwnode; + + if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) + mdio_device_unregister_reset(mdiodev); + + /* Do not keep an overlay node alive with the retired device. */ + if (dynamic) { + fwnode = dev_fwnode(&mdiodev->dev); + device_set_node(&mdiodev->dev, NULL); + fwnode_handle_put(fwnode); + } } /** diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 0615228459ef..f7472a743185 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -227,6 +227,8 @@ static void phy_device_release(struct device *dev) kfree(to_phy_device(dev)); } +static int __phy_device_remove(struct phy_device *phydev, bool dynamic); + static void phy_mdio_device_remove(struct mdio_device *mdiodev) { struct phy_device *phydev; @@ -235,6 +237,14 @@ static void phy_mdio_device_remove(struct mdio_device *mdiodev) phy_device_remove(phydev); } +static int phy_mdio_device_remove_dynamic(struct mdio_device *mdiodev) +{ + struct phy_device *phydev; + + phydev = container_of(mdiodev, struct phy_device, mdio); + return __phy_device_remove(phydev, true); +} + static struct phy_driver genphy_driver; static LIST_HEAD(phy_fixup_list); @@ -768,7 +778,9 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id, mdiodev->flags = MDIO_DEVICE_FLAG_PHY; mdiodev->device_free = phy_mdio_device_free; mdiodev->device_remove = phy_mdio_device_remove; + mdiodev->device_remove_dynamic = phy_mdio_device_remove_dynamic; mdiodev->reset_state = -1; + INIT_LIST_HEAD(&mdiodev->retired_node); dev->speed = SPEED_UNKNOWN; dev->duplex = DUPLEX_UNKNOWN; @@ -1121,25 +1133,40 @@ int phy_device_register(struct phy_device *phydev) err = phy_scan_fixups(phydev); if (err) { phydev_err(phydev, "failed to initialize\n"); - goto out; + return mdiobus_registration_done(&phydev->mdio, err); } err = device_add(&phydev->mdio.dev); - if (err) { + if (err) phydev_err(phydev, "failed to add\n"); - goto out; - } - return 0; + return mdiobus_registration_done(&phydev->mdio, err); +} +EXPORT_SYMBOL(phy_device_register); + +static int __phy_device_remove(struct phy_device *phydev, bool dynamic) +{ + int err; + + err = mdiobus_begin_remove(&phydev->mdio, dynamic); + if (dynamic && err == -EBUSY) + dev_warn(&phydev->mdio.dev, + "cannot remove a PHY while it is attached or being registered\n"); + if (err) + return err; + + unregister_mii_timestamper(phydev->mii_ts); + pse_control_put(phydev->psec); + + device_del(&phydev->mdio.dev); - out: /* Assert the reset signal */ phy_device_reset(phydev, 1); - mdiobus_unregister_device(&phydev->mdio); - return err; + mdiobus_finish_remove(&phydev->mdio, dynamic); + + return 0; } -EXPORT_SYMBOL(phy_device_register); /** * phy_device_remove - Remove a previously registered phy device from the MDIO bus @@ -1151,15 +1178,7 @@ EXPORT_SYMBOL(phy_device_register); */ void phy_device_remove(struct phy_device *phydev) { - unregister_mii_timestamper(phydev->mii_ts); - pse_control_put(phydev->psec); - - device_del(&phydev->mdio.dev); - - /* Assert the reset signal */ - phy_device_reset(phydev, 1); - - mdiobus_unregister_device(&phydev->mdio); + __phy_device_remove(phydev, false); } EXPORT_SYMBOL(phy_device_remove); @@ -1734,6 +1753,36 @@ static bool phy_drv_supports_irq(const struct phy_driver *phydrv) return phydrv->config_intr && phydrv->handle_interrupt; } +static int phy_claim(struct phy_device *phydev) +{ + struct mdio_device *mdiodev = &phydev->mdio; + struct mii_bus *bus = mdiodev->bus; + int err = 0; + + mutex_lock(&bus->mdio_map_lock); + if (bus->state != MDIOBUS_REGISTERED || + bus->mdio_map_removals || + bus->mdio_map[mdiodev->addr] != mdiodev || + (bus->mdio_map_pending & BIT(mdiodev->addr))) + err = -ENODEV; + else if (phydev->attached) + err = -EBUSY; + else + phydev->attached = true; + mutex_unlock(&bus->mdio_map_lock); + + return err; +} + +static void phy_release(struct phy_device *phydev) +{ + struct mii_bus *bus = phydev->mdio.bus; + + mutex_lock(&bus->mdio_map_lock); + phydev->attached = false; + mutex_unlock(&bus->mdio_map_lock); +} + /** * phy_attach_direct - attach a network device to a given PHY device pointer * @dev: network device to attach @@ -1755,6 +1804,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, struct mii_bus *bus = phydev->mdio.bus; struct device *d = &phydev->mdio.dev; struct module *ndev_owner = NULL; + bool claimed = false; int err; /* For Ethernet device drivers that register their own MDIO bus, we @@ -1770,6 +1820,13 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, } get_device(d); + err = phy_claim(phydev); + if (err == -EBUSY) + phydev_err(phydev, "PHY already attached\n"); + if (!err) + claimed = true; + if (err) + goto error_put_device; /* Assume that if there is no driver, that it doesn't * exist, and we should use the genphy driver. @@ -1798,12 +1855,6 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, goto error_module_put; } - if (phydev->attached_dev) { - dev_err(&dev->dev, "PHY already attached\n"); - err = -EBUSY; - goto error; - } - phydev->phy_link_change = phy_link_change; if (dev) { phydev->attached_dev = dev; @@ -1899,6 +1950,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, phydev->is_genphy_driven = 0; d->driver = NULL; error_put_device: + if (claimed) + phy_release(phydev); put_device(d); if (ndev_owner != bus->owner) module_put(bus->owner); @@ -1977,6 +2030,7 @@ void phy_detach(struct phy_device *phydev) * a use-after-free bug by reading the underlying bus first. */ bus = phydev->mdio.bus; + phy_release(phydev); put_device(&phydev->mdio.dev); if (dev) diff --git a/drivers/net/phy/phylib-internal.h b/drivers/net/phy/phylib-internal.h index 664ed7faa518..7e9161fcdd90 100644 --- a/drivers/net/phy/phylib-internal.h +++ b/drivers/net/phy/phylib-internal.h @@ -25,7 +25,9 @@ int phy_speed_down_core(struct phy_device *phydev); void phy_check_downshift(struct phy_device *phydev); int mdiobus_register_device(struct mdio_device *mdiodev); -int mdiobus_unregister_device(struct mdio_device *mdiodev); +int mdiobus_registration_done(struct mdio_device *mdiodev, int err); +int mdiobus_begin_remove(struct mdio_device *mdiodev, bool dynamic); +void mdiobus_finish_remove(struct mdio_device *mdiodev, bool dynamic); int genphy_c45_read_eee_adv(struct phy_device *phydev, unsigned long *adv); diff --git a/include/linux/mdio.h b/include/linux/mdio.h index f4f9d9609448..41c60798fa0e 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -8,6 +8,7 @@ #include #include +#include #include struct gpio_desc; @@ -33,6 +34,9 @@ struct mdio_device { int (*bus_match)(struct device *dev, const struct device_driver *drv); void (*device_free)(struct mdio_device *mdiodev); void (*device_remove)(struct mdio_device *mdiodev); + int (*device_remove_dynamic)(struct mdio_device *mdiodev); + /* Entry in mii_bus::mdio_map_retired. */ + struct list_head retired_node; /* Bus address of the MDIO device (0-31) */ int addr; @@ -690,6 +694,8 @@ static inline int mdiodev_c45_write(struct mdio_device *mdiodev, u32 devad, bool mdiobus_is_registered_device(struct mii_bus *bus, int addr); struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr); +int mdiobus_device_change_begin(struct mii_bus *bus, bool removing); +void mdiobus_device_change_end(struct mii_bus *bus, bool removing); /** * mdio_module_driver() - Helper macro for registering mdio drivers diff --git a/include/linux/phy.h b/include/linux/phy.h index fc680901275b..2eba54e068f6 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -391,7 +392,9 @@ struct mii_bus { /** @state: State of bus structure */ enum { MDIOBUS_ALLOCATED = 1, + MDIOBUS_REGISTERING, MDIOBUS_REGISTERED, + MDIOBUS_UNREGISTERING, MDIOBUS_UNREGISTERED, MDIOBUS_RELEASED, } state; @@ -401,6 +404,18 @@ struct mii_bus { /** @mdio_map: list of all MDIO devices on bus */ struct mdio_device *mdio_map[PHY_MAX_ADDR]; + /** @mdio_map_pending: addresses with registration in progress */ + u32 mdio_map_pending; + /** @mdio_map_lock: protects the MDIO device map and bus state */ + struct mutex mdio_map_lock; + /** @mdio_map_wait: wait for active map operations during teardown */ + wait_queue_head_t mdio_map_wait; + /** @mdio_map_ops: active registrations and firmware changes */ + unsigned int mdio_map_ops; + /** @mdio_map_removals: firmware removals blocking PHY attachment */ + unsigned int mdio_map_removals; + /** @mdio_map_retired: removed devices pinned until bus teardown */ + struct list_head mdio_map_retired; /** @phy_mask: PHY addresses to be ignored when probing */ u32 phy_mask; @@ -652,6 +667,8 @@ struct phy_oatc14_sqi_capability { * @n_ports: Number of ports currently attached to the PHY * @max_n_ports: Max number of ports this PHY can expose * @lock: Mutex for serialization access to PHY + * @attached: Whether a network device or standalone user attached the PHY; + * protected by the MDIO bus map lock * @state_queue: Work queue for state machine * @link_down_events: Number of times link was lost * @shared: Pointer to private data shared by phys in one package @@ -781,6 +798,7 @@ struct phy_device { struct delayed_work state_queue; struct mutex lock; + bool attached; /* This may be modified under the rtnl lock */ bool sfp_bus_attached; From patchwork Mon Aug 3 05:14:16 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2900 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id DE23D1C057E for ; Mon, 3 Aug 2026 07:20:15 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24917-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24917-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 66E4130841D2 for ; Mon, 3 Aug 2026 05:15:42 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4832E31E84F; Mon, 3 Aug 2026 05:15:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="XHN0Sy1h" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f47.google.com (mail-ot1-f47.google.com [209.85.210.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A0F8E38A70A for ; Mon, 3 Aug 2026 05:15:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734135; cv=none; b=nhb4q8sQU623t+Cu/6lCJRDwFbleeRglSPyJypEgAcXa3u1CZ0MUIGy1UHlnmKf6dSMC7md6IAYFwZrHFcoqsB8+ECjL9sHwjQdMJ+yrburZ0CCGOAl1qhnvqN4k+ZKMC3IW1bBsB4BnneECg8fJdBuzry/3zg+YgTKxtpvwPd8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734135; c=relaxed/simple; bh=Tw9U9x3x5olXZaLQIjQpOA/JFbVYSe4nj6Dx94hoQbg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AVY+um5DqHWPvY3T8cchvGV2UosgxcbzBMAzFixH3a+2ZYeYDC1JgTYo2XaUF93ls6tDijnddjPVkYxPFij9uzMZNx8dmp7u8y6w0oUrTCfTJLrDJEsl7+LimBDESuP4NyaTFx+7AGGrvfFWZ6CtbzAcnb8EZJYVSU1X4GisdCg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=XHN0Sy1h; arc=none smtp.client-ip=209.85.210.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f47.google.com with SMTP id 46e09a7af769-7eb64371a2aso1680073a34.0 for ; Sun, 02 Aug 2026 22:15:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734128; x=1786338928; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=maRxG9UiuybqBbIKlnDyAqHdPuODzpVicj9v0akXa2o=; b=XHN0Sy1h2lu6xX+D570KZSXV85aQPcVZDLm2LzoNfW2xDGWV3YSqfn0YSQWlMqrQgL SrumggipUGvVQ6NYDtMFbLbKIhkaPPPLlxCI5OVZLcwREtUK0EeJfDAfQUgqRMev7ubE JzCkvdnyN/Kv0tOCifH87omccheqS3+9PVs0nVL2Dgg1OPGCbHnW4TjP6vgKOhBbZlps DmRlyZETjD1cIlLodEs/gK0NAFYs9RAf9xRHaETdDomrTVwjAZZm2l21oZ6pRvnMhz6o RI4R7MVFcthW/FVlLkRzuUlKpp8HIVLSXKueyPWpU8T3lljMbiFU9Lx0S/sVu/jDmXb1 upWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734128; x=1786338928; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=maRxG9UiuybqBbIKlnDyAqHdPuODzpVicj9v0akXa2o=; b=c1FRSiugZOYrJ2Npk14bPngYuI06D2xI4LWxqXBXnDPNf8/9XInFtUyD0E7qSGzJse YsBWieGYxDPUT+FC15VFs0VheZLVk/dlmKFp159ydOoYfSfbayIRh3w7gd/ecDRL6Gjl 9i7McmS984murjQckfeO/5Mm5nusZHwy9uwry7ZIjyiPINWGX0d9achXLgRLFj0Fhqj2 CvEKKpoqpBXiqmq3sF0ObG8GnmtrMnYCDn4Ew/VQTvKTAdqFMOatATXYwSX3QWxai7k6 FlIdwOqRs5leNgVAGCxwWGzm+/EOciwF9KST2gu5LV43j49tkb2x0OfY5EpZ3mRNEQtF v+Jg== X-Forwarded-Encrypted: i=1; AHgh+Rob2WeHLORRiOxYEh69eStKEycV5UiOqGw7RpVCzOhI2uNey1gcniL1ZsHm3O1SMaEkHHvmXmg5dEWKyQ==@lists.linux.dev X-Gm-Message-State: AOJu0YxaXi9XRqDsum79NwzDJtfRfb/0tQzcu+kfyfRtf6HP0ho4ZKD2 iQ6UIj/BUgYx4ZYoJWCn4+1+ljKM//sXkJxxv2M5QfZEjFZNOwrfPD+M X-Gm-Gg: AR+sD12mxycKw1bTkmEXN7iYrf1kVN6FjoVNtZetWomwyVyylZYvUwRnkZTOyvxo5ME iqBIpw/2awTDQ6NuswiK9xYoocdA6TqEQrOHeSyhN9rLBhZH4fjFeOQqI+Jw2ZNI3DBZYV407Hh rL3QNx9N8rOXKD6E0xTLh5hpGt58xxC2+boSn79qBtywsTfniDZmV9d13U7S8i7FBVqGsnDrHB9 PoPru4diEPQgzwP1qziWhLEr95QA8uaw45xf0fDCzEYky7Lk7+J5YP606Lak/PGuKltr/4DfHom irYK0kRJk2ydQwj6aj1DMd/nPHmKTM+ESbjTwqt4+P88Fp1ZhPnoWhN6iQm2U1+1llhYeeJpYPp fj/Te2qiWhEf7IQFRA4Q4w1PxYjQycGN9XAtTA3vUB9fbeMXsE8oabPsU92thWhyLeGJ9uHhCS5 N+vTEiVjocNwWaeVT7CLySRMESYvm9fRPKNWR82fr5c5g9lb93QeoGNnJrkMXw/XaH1PmV/sNXB 3JBe5iaw9JtapMZ6XgwAAIQ9PE9fuViixLeDzqtJsd8v3/SA0pX2xBrISpF68oygS/nDKkIxr/n FbEUEDgGCqTmPNElHnN1n6SSNWgG3dcxJMBtjEq3HbTgk5AO8UVzEoEd44gmh/swZqfByawHWhF KFUoQUQTh7hCxycJ1 X-Received: by 2002:a05:6830:61ce:b0:7dc:3db6:f02 with SMTP id 46e09a7af769-7f196d51885mr15457605a34.9.1785734128311; Sun, 02 Aug 2026 22:15:28 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:27 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:16 -0600 Subject: [PATCH 06/21] net: mdio: support dynamic OF device changes Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-6-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= MDIO buses enumerate firmware children only when the bus is registered. A later DT overlay or status transition is ignored, unlike I2C and SPI. Add an OF reconfiguration notifier. On addition, create fixed-address PHYs and generic MDIO devices, scan free addresses for legacy PHY nodes without reg, and recurse into Ethernet PHY packages. Track populated nodes so static enumeration, address scanning and notifier-driven enumeration cannot create duplicates. Walk every package child and report the first population error without undoing devices which may already have acquired consumers. Serialize static and notifier-driven population while allowing a PHY probe to enable another node on the same bus. Check the node's current state after taking that lock so an older notification cannot override a newer status change. On removal, reject attached or in-flight PHYs and unregister the object found by its OF node. This also covers PHYs found by address scanning. Treat all PHYs in a package as one removal scope, so removing one member cannot invalidate state used by an attached peer. Preflight overlay removal while it can still be refused; normal changeset errors are propagated so the caller can restore the previous state. Hold a core MDIO change transaction across discovery and registration so bus teardown cannot race the MDIO reads used to identify a PHY. Compile the notifier only with CONFIG_OF_DYNAMIC and the overlay preflight only with CONFIG_OF_OVERLAY. Signed-off-by: James Hilliard --- drivers/net/mdio/of_mdio.c | 448 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 438 insertions(+), 10 deletions(-) diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c index 051e449bbe7c..a8313b3721f6 100644 --- a/drivers/net/mdio/of_mdio.c +++ b/drivers/net/mdio/of_mdio.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,8 @@ #include #include #include +#include +#include #define DEFAULT_GPIO_RESET_DELAY 10 /* in microseconds */ @@ -27,6 +30,52 @@ MODULE_AUTHOR("Grant Likely "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("OpenFirmware MDIO bus (Ethernet PHY) accessors"); +#if IS_ENABLED(CONFIG_OF_DYNAMIC) +/* + * OF changes can nest when probing one MDIO device enables another node on + * the same bus. Serialize independent changes while allowing that nesting. + */ +static DEFINE_MUTEX(of_mdio_reconfig_mutex); +static struct task_struct *of_mdio_reconfig_owner; +static unsigned int of_mdio_reconfig_depth; + +static void of_mdio_reconfig_lock(void) +{ + if (!mutex_trylock(&of_mdio_reconfig_mutex)) { + if (of_mdio_reconfig_owner == current) { + of_mdio_reconfig_depth++; + return; + } + mutex_lock(&of_mdio_reconfig_mutex); + } + + WARN_ON_ONCE(of_mdio_reconfig_owner); + WARN_ON_ONCE(of_mdio_reconfig_depth); + of_mdio_reconfig_owner = current; + of_mdio_reconfig_depth = 1; +} + +static void of_mdio_reconfig_unlock(void) +{ + WARN_ON_ONCE(of_mdio_reconfig_owner != current); + WARN_ON_ONCE(!of_mdio_reconfig_depth); + + if (--of_mdio_reconfig_depth) + return; + + of_mdio_reconfig_owner = NULL; + mutex_unlock(&of_mdio_reconfig_mutex); +} +#else +static inline void of_mdio_reconfig_lock(void) +{ +} + +static inline void of_mdio_reconfig_unlock(void) +{ +} +#endif + /* Extract the clause 22 phy ID from the compatible string of the form * ethernet-phy-idAAAA.BBBB */ static int of_get_phy_id(struct device_node *device, u32 *phy_id) @@ -44,7 +93,7 @@ int of_mdiobus_phy_device_register(struct mii_bus *mdio, struct phy_device *phy, EXPORT_SYMBOL(of_mdiobus_phy_device_register); static int of_mdiobus_register_phy(struct mii_bus *mdio, - struct device_node *child, u32 addr) + struct device_node *child, u32 addr) { return fwnode_mdiobus_register_phy(mdio, of_fwnode_handle(child), addr); } @@ -80,10 +129,20 @@ static int of_mdiobus_register_device(struct mii_bus *mdio, static int of_mdiobus_register_child(struct mii_bus *mdio, struct device_node *child, u32 addr) { + int rc; + + if (of_node_test_and_set_flag(child, OF_POPULATED)) + return 0; + if (of_mdiobus_child_is_phy(child)) - return of_mdiobus_register_phy(mdio, child, addr); + rc = of_mdiobus_register_phy(mdio, child, addr); + else + rc = of_mdiobus_register_device(mdio, child, addr); - return of_mdiobus_register_device(mdio, child, addr); + if (rc) + of_node_clear_flag(child, OF_POPULATED); + + return rc; } /* The following is a list of PHY compatible strings which appear in @@ -255,13 +314,21 @@ int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np, if (rc) return rc; + of_mdio_reconfig_lock(); + rc = mdiobus_device_change_begin(mdio, false); + if (rc) { + of_mdio_reconfig_unlock(); + mdiobus_unregister(mdio); + return rc; + } + /* Loop over the child nodes and register a phy_device for each phy */ rc = __of_mdiobus_parse_phys(mdio, np, &scanphys); if (rc) - goto unregister; + goto out_change; if (!scanphys) - return 0; + goto out_change; /* auto scan for PHYs with empty reg property */ for_each_available_child_of_node(np, child) { @@ -272,19 +339,380 @@ int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np, rc = of_mdiobus_scan_phy(mdio, child); if (rc && rc != -ENODEV) - goto put_unregister; + goto put_child; + rc = 0; } - return 0; +out_change: + mdiobus_device_change_end(mdio, false); + of_mdio_reconfig_unlock(); + if (!rc) + return 0; -put_unregister: - of_node_put(child); -unregister: mdiobus_unregister(mdio); return rc; + +put_child: + of_node_put(child); + goto out_change; } EXPORT_SYMBOL(__of_mdiobus_register); +#if IS_ENABLED(CONFIG_OF_DYNAMIC) +static bool of_mdiobus_node_is_available(struct device_node *node) +{ + return !of_node_check_flag(node, OF_DETACHED) && + of_device_is_available(node); +} + +static int of_mdiobus_add_node(struct mii_bus *mdio, + struct device_node *node) +{ + struct device_node *child; + int addr, rc, ret = 0; + + if (!of_mdiobus_node_is_available(node)) + return 0; + + if (of_node_name_eq(node, "ethernet-phy-package")) { + if (!of_property_present(node, "reg")) + return 0; + + for_each_available_child_of_node(node, child) { + rc = of_mdiobus_add_node(mdio, child); + if (rc && rc != -ENODEV && !ret) + ret = rc; + } + + return ret; + } + + addr = of_mdio_parse_addr(&mdio->dev, node); + if (addr < 0) + rc = of_mdiobus_scan_phy(mdio, node); + else + rc = of_mdiobus_register_child(mdio, node, addr); + + if (rc == -ENODEV && addr >= 0) + dev_err(&mdio->dev, + "MDIO device at address %d is missing.\n", addr); + + return rc; +} + +static bool of_mdiobus_node_is_busy(struct mii_bus *mdio, + struct device_node *node) +{ + struct mdio_device *mdiodev; + bool busy = false; + + if (of_node_name_eq(node, "ethernet-phy-package")) { + for_each_child_of_node_scoped(node, child) { + if (of_mdiobus_node_is_busy(mdio, child)) + return true; + } + + return false; + } + + if (!of_node_check_flag(node, OF_POPULATED)) + return false; + + mdiodev = of_mdio_find_device(node); + if (!mdiodev) + return true; + if (mdiodev->bus != mdio) { + put_device(&mdiodev->dev); + return false; + } + + mutex_lock(&mdio->mdio_map_lock); + busy = mdio->mdio_map[mdiodev->addr] != mdiodev || + (mdio->mdio_map_pending & BIT(mdiodev->addr)); + if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) { + struct phy_device *phydev = to_phy_device(&mdiodev->dev); + + if (phydev->attached) { + busy = true; + dev_warn(&mdiodev->dev, + "cannot remove an attached PHY; remove its consumer first\n"); + } + } + mutex_unlock(&mdio->mdio_map_lock); + put_device(&mdiodev->dev); + + return busy; +} + +static struct device_node * +of_mdiobus_get_removal_scope(struct device_node *node) +{ + struct device_node *parent; + + if (of_node_name_eq(node, "ethernet-phy-package")) + return of_node_get(node); + + parent = of_get_parent(node); + if (of_node_name_eq(parent, "ethernet-phy-package")) + return parent; + + of_node_put(parent); + return of_node_get(node); +} + +static int of_mdiobus_remove_node(struct mii_bus *mdio, + struct device_node *node) +{ + struct mdio_device *mdiodev; + struct device_node *child; + int ret; + + if (of_node_name_eq(node, "ethernet-phy-package")) { + for_each_child_of_node(node, child) { + ret = of_mdiobus_remove_node(mdio, child); + if (ret) { + of_node_put(child); + return ret; + } + } + return 0; + } + + if (!of_node_check_flag(node, OF_POPULATED)) + return 0; + + /* The OF node lookup also covers PHYs found by address scanning. */ + mdiodev = of_mdio_find_device(node); + if (!mdiodev) + return -EBUSY; + if (mdiodev->bus != mdio) { + put_device(&mdiodev->dev); + return -ENODEV; + } + + ret = mdiodev->device_remove_dynamic(mdiodev); + if (!ret) + mdiodev->device_free(mdiodev); + put_device(&mdiodev->dev); + + return ret == -ENODEV ? 0 : ret; +} + +static struct mii_bus *of_mdiobus_find_parent(struct device_node *node) +{ + struct device_node *parent, *bus_node; + struct mii_bus *mdio; + + parent = of_get_parent(node); + if (!parent) + return NULL; + + if (of_node_name_eq(parent, "ethernet-phy-package")) { + if (!of_device_is_available(parent) || + !of_property_present(parent, "reg")) { + of_node_put(parent); + return NULL; + } + + bus_node = of_get_parent(parent); + of_node_put(parent); + } else { + bus_node = parent; + } + + mdio = of_mdio_find_bus(bus_node); + of_node_put(bus_node); + + return mdio; +} + +#if IS_ENABLED(CONFIG_OF_OVERLAY) +/* Overlay entry notifier errors cannot stop removal after the tree changed. */ +static bool of_mdiobus_live_node_is_busy(struct device_node *node) +{ + struct device_node *scope; + struct mii_bus *mdio; + bool busy = true; + + scope = of_mdiobus_get_removal_scope(node); + mdio = of_mdiobus_find_parent(scope); + if (!mdio) + goto out_put_scope; + + if (!mdiobus_device_change_begin(mdio, true)) { + busy = of_mdiobus_node_is_busy(mdio, scope); + mdiobus_device_change_end(mdio, true); + } + put_device(&mdio->dev); + +out_put_scope: + of_node_put(scope); + return busy; +} + +static struct device_node * +of_mdiobus_overlay_target_child(struct device_node *target, + struct device_node *overlay_child) +{ + const char *name = kbasename(overlay_child->full_name); + struct device_node *child; + + for_each_child_of_node(target, child) { + if (!of_node_cmp(kbasename(child->full_name), name)) + return child; + } + + return NULL; +} + +static bool of_mdiobus_overlay_node_is_busy(struct device_node *overlay, + struct device_node *target, + bool added) +{ + struct device_node *overlay_child, *target_child; + bool busy, child_added; + + if ((added || of_property_present(overlay, "status")) && + of_mdiobus_live_node_is_busy(target)) + return true; + + for_each_child_of_node(overlay, overlay_child) { + target_child = of_mdiobus_overlay_target_child(target, + overlay_child); + if (!target_child) + continue; + + child_added = of_node_check_flag(target_child, OF_OVERLAY); + busy = of_mdiobus_overlay_node_is_busy(overlay_child, + target_child, child_added); + of_node_put(target_child); + if (busy) { + of_node_put(overlay_child); + return true; + } + } + + return false; +} + +static int of_mdiobus_overlay_notify(struct notifier_block *nb, + unsigned long action, void *arg) +{ + struct of_overlay_notify_data *nd = arg; + bool busy; + + if (action != OF_OVERLAY_PRE_REMOVE) + return NOTIFY_OK; + + of_mdio_reconfig_lock(); + busy = of_mdiobus_overlay_node_is_busy(nd->overlay, nd->target, + false); + of_mdio_reconfig_unlock(); + + return busy ? notifier_from_errno(-EBUSY) : NOTIFY_OK; +} + +static struct notifier_block of_mdio_overlay_notifier = { + .notifier_call = of_mdiobus_overlay_notify, +}; +#endif + +static int of_mdiobus_notify(struct notifier_block *nb, unsigned long action, + void *arg) +{ + struct of_reconfig_data *rd = arg; + struct device_node *scope; + struct mii_bus *mdio; + enum of_reconfig_change change; + bool removing; + int rc, ret = NOTIFY_OK; + + of_mdio_reconfig_lock(); + change = of_reconfig_get_state_change(action, rd); + switch (change) { + case OF_RECONFIG_CHANGE_ADD: + /* A newer change may have made this notification stale. */ + if (!of_mdiobus_node_is_available(rd->dn)) + goto out_unlock; + removing = false; + break; + case OF_RECONFIG_CHANGE_REMOVE: + /* A newer change may have made this notification stale. */ + if (of_mdiobus_node_is_available(rd->dn)) + goto out_unlock; + removing = true; + break; + default: + goto out_unlock; + } + + mdio = of_mdiobus_find_parent(rd->dn); + if (!mdio) + goto out_unlock; + + rc = mdiobus_device_change_begin(mdio, removing); + if (rc) { + if (!removing) + ret = notifier_from_errno(-EPROBE_DEFER); + goto out_put_mdio; + } + + if (!removing) { + rc = of_mdiobus_add_node(mdio, rd->dn); + } else { + /* The node may already be detached from its parent hierarchy. */ + scope = of_mdiobus_get_removal_scope(rd->dn); + if (of_mdiobus_node_is_busy(mdio, scope)) + rc = -EBUSY; + else + rc = of_mdiobus_remove_node(mdio, rd->dn); + of_node_put(scope); + } + + mdiobus_device_change_end(mdio, removing); + if (rc && (removing || rc != -ENODEV)) + ret = notifier_from_errno(rc); + +out_put_mdio: + put_device(&mdio->dev); +out_unlock: + of_mdio_reconfig_unlock(); + + return ret; +} + +static struct notifier_block of_mdio_notifier = { + .notifier_call = of_mdiobus_notify, +}; + +static int __init of_mdio_init(void) +{ + int ret; + + ret = of_reconfig_notifier_register(&of_mdio_notifier); + if (ret) + return ret; + +#if IS_ENABLED(CONFIG_OF_OVERLAY) + ret = of_overlay_notifier_register(&of_mdio_overlay_notifier); + if (ret) + of_reconfig_notifier_unregister(&of_mdio_notifier); +#endif + + return ret; +} +module_init(of_mdio_init); + +static void __exit of_mdio_exit(void) +{ +#if IS_ENABLED(CONFIG_OF_OVERLAY) + of_overlay_notifier_unregister(&of_mdio_overlay_notifier); +#endif + of_reconfig_notifier_unregister(&of_mdio_notifier); +} +module_exit(of_mdio_exit); +#endif /* CONFIG_OF_DYNAMIC */ + /** * of_mdio_find_device - Given a device tree node, find the mdio_device * @np: pointer to the mdio_device's device tree node From patchwork Mon Aug 3 05:14:17 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2902 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 54A2B1C0583 for ; Mon, 3 Aug 2026 07:21:13 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24919-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24919-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id DBA23309DAF9 for ; Mon, 3 Aug 2026 05:15:49 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 1326C397B1B; Mon, 3 Aug 2026 05:15:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZX1rcUaU" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62BC6395AC3 for ; Mon, 3 Aug 2026 05:15:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734138; cv=none; b=IYqY4rU4pHiO/Opa1gJmDQVDm9voW9FUoqWz2Cq3ck9r7Co5FqnGoujqJlgncvkNiZHmzLC7ReoxqTvpIzkvYNZv3hEDn5XIp0fec5JWi2UnLpoMVqixJNrWdWPjDtY1xwInpYnbZjhCHlrs5wN0Fy6HSZr3UrIWASuAmaOQJUU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734138; c=relaxed/simple; bh=vV8lMZbs024nEM6mXjaIv6nOjnfVCGoiA5FCDI8jrNk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cJNCkMAb25KwJezoR6atcKZBxOa1ebRzqOwh7NhpJy/8GJbUEy1rUdTy/ZGve3Qj+u/FGdqXzmadqXpqRaQW8r1IZQPysKURPiNe1Rc2uMvYla4DDnmirB22xNDZFC4nbiTsLdHuLQ/6ySlTNauuiLg0bUaYNhR0NNR4556JnVk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ZX1rcUaU; arc=none smtp.client-ip=209.85.210.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f53.google.com with SMTP id 46e09a7af769-7f18c0e03e3so1152273a34.2 for ; Sun, 02 Aug 2026 22:15:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734130; x=1786338930; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=ufELgsZA/AuhdmDVFD2N+JzOSgNytpSBYv7TBEiLCKU=; b=ZX1rcUaUJq5VWQat+cIQ+ZBcFC8dLqzdm2sR0U2Y59uXmocQhaNWRHSZm/HzJuCACh sCYO/r0jcwhktLUiy27eoJJFy7ATqzwSNl3ct/JWJU2e7vINf9OnCpSN7WW92iAdy/0d c/So+aTbwScF7BKrXhE85fx2VljmHgRSGp83XCISpCJ9nmz45xw27b+uTVrVaQTNuiyp 52ieDpD7yMgsQqeJMHEmrZMXCjyCK5ChPAGKZeP5c/tL/sts8IpRbgpMeUx8Jabocuf8 7vzw9mIsWUJJxFEIdZ3nWGAQZLo94ve8yU4kG/KIt9HB3XqMPxoHJEHI8Ku36uB2CVIO KvKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734130; x=1786338930; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=ufELgsZA/AuhdmDVFD2N+JzOSgNytpSBYv7TBEiLCKU=; b=Uj3N+PX49oxWTlCpwjGt4ivMSnwuygzo8ZGnaZWHIDcV6CdI+6Y8R9lxqvtlwoK91G 3VsU2JK56FyR6jbrQh3S9cjJnuqgQNGA2r6ismX7d5/0OhPMaAPJCOvYchkMWP+TGiKn v7L1XKwBmDkkHfomQcvpXCfKoS7vvGxr6xsx03pdNYDxvkb+TBkrDM+9vEAekg3XqTSY 7pbupaemjpilox8xnoGVPbpELck+Vt1w37voX5CwZUQ1yM/uMxWuWe5evh1a+CE+p02I 4d9nQOtDaWfcmWPEIZP5zXAdTho4zR3fJ4YDxJTTqcZyJNyLGcIvcI2kjSiztpZef9vV cdSg== X-Forwarded-Encrypted: i=1; AHgh+RrdIbTkzn/o9v9dKjvEsB6lhTDgJSCNIZDMv9RCt864WT248pj+f20E3CASP8T35EXIfJYcBtICCkwlBQ==@lists.linux.dev X-Gm-Message-State: AOJu0YynRfI8uVFZzwzSTIi6CTm8kEj82zoLtrBLJ6gwSKxBjYtHPdHz WROG2BTAj1u2/TPZPrhsnp47E6qu7rFvtws0xVNhv9eArQ6oBB1cK3bK X-Gm-Gg: AR+sD11BugNbDq7KQA8I0o4YXjz5sUPMWCZ7Io1Sp26KLiD0IavosMyRd6AXidBJWWK mtZz54pF76QtGi79YmJuw+CSEBZVHUA0iNeS+kJsnU8zv89UZIAn3rq6tRaPaM99XKtFk/mLn19 SwPLsMdw6+gY9jg3vLZetpvA3Cxpugw+xkM5pj9gMylB5c704z0NLqAkRMtgrSSMafjkC3cbqG6 osTX3okk73y/snQ2rqHPyJDlvTCK3K7eyPao6J/Wy/DJeyXIhFlWIr5rAUVCXnpUYz/6aANRTvA ZGAzm92GD3at4VxoRIhVwbe9n9/3kli0E/MJx+8TaRqFlE0/PlFC98bJtY9jeuYlQ+YotGsR5Ul GZn6pq6UfEnDQyt/SbGYelOra3HhFpcqkBZWUA2xh+4LGCWvPMwJHnDHG82ayCn8XFFXke7c+Rd 3XWxIh50MZweY0XHDUQFZidiFom2e0r46LFmmICkAkkRNFD3ZUW++gaqUt8p0aNkqb5oi57xsJY lUXc5sf6aqIbuFbVf/8voigN20jvg1y+lZU8KDg1/76TvXCmo9Ooj2WhWQPhoQLBp1LhfRjBbvH 9yEdedGsCMQGd5ulKBonb3uLm602YmAL9T8t3iHZ2IyX8yn041g5JDiPY32NDCIFIKGXbtzTdJO e7zYy/mUqY979BB//8GoIpRGlBWFN X-Received: by 2002:a05:6830:81f0:b0:7e9:cad9:4bd0 with SMTP id 46e09a7af769-7f196b1550cmr14686937a34.3.1785734130353; Sun, 02 Aug 2026 22:15:30 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:29 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:17 -0600 Subject: [PATCH 07/21] dt-bindings: net: x-powers: add AC200 EPHY control Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-7-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[172.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; TAGGED_RCPT(0.00)[netdev,dt]; PRECEDENCE_BULK(0.00)[]; RCPT_COUNT_TWELVE(0.00)[34]; TO_DN_SOME(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo,devicetree.org:url]; FORGED_SENDER_MAILLIST(0.00)[]; FREEMAIL_CC(0.00)[vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com]; FREEMAIL_FROM(0.00)[gmail.com]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10:c]; MIME_TRACE(0.00)[0:+]; RCVD_TLS_LAST(0.00)[]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; FREEMAIL_TO(0.00)[lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,arm.com,bootlin.com,foss.st.com,st.com,synopsys.com,armlinux.org.uk,sntech.de]; FROM_HAS_DN(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; TAGGED_FROM(0.00)[bounces-24919-noreply=patchwork.local]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 54A2B1C0583 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The AC200 companion IC contains a Fast Ethernet PHY controlled through the parent AC200 I2C regmap. Describe its control function, including the interface mode and optional SoC SID calibration cell. The vendor sequence adds three to the calibration value modulo 16 before writing the BPS_EFFUSE field. If the SID cell is omitted, the driver can use the AC200's internal copy of the calibration eFuse. The link-PHY driver supplies its Clause 22 address when enabling the control function. Signed-off-by: James Hilliard --- .../bindings/net/x-powers,ac200-ephy-ctl.yaml | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Documentation/devicetree/bindings/net/x-powers,ac200-ephy-ctl.yaml b/Documentation/devicetree/bindings/net/x-powers,ac200-ephy-ctl.yaml new file mode 100644 index 000000000000..b3337c3aa62a --- /dev/null +++ b/Documentation/devicetree/bindings/net/x-powers,ac200-ephy-ctl.yaml @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/x-powers,ac200-ephy-ctl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: X-Powers AC200 Ethernet PHY control + +maintainers: + - James Hilliard + +description: + The AC200 Ethernet PHY control function configures and powers the Fast + Ethernet PHY in the AC200. Its registers are accessed through the parent + AC200 I2C regmap. + +properties: + compatible: + const: x-powers,ac200-ephy-ctl + + nvmem-cells: + maxItems: 1 + description: + Optional SoC SID cell containing the Ethernet PHY calibration value + written to the AC200 BPS_EFFUSE field after adding 3 modulo 16, as + prescribed by the vendor initialization sequence. If omitted, the + driver reads the AC200's internal copy of the calibration eFuse. + + nvmem-cell-names: + const: calibration + + phy-mode: + enum: + - mii + - rmii + +required: + - compatible + - phy-mode + +dependentRequired: + nvmem-cells: [ nvmem-cell-names ] + nvmem-cell-names: [ nvmem-cells ] + +additionalProperties: false +... From patchwork Mon Aug 3 05:14:18 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2901 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id F0A291C057E for ; Mon, 3 Aug 2026 07:21:12 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24918-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24918-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id D6DE6309DAC1 for ; Mon, 3 Aug 2026 05:15:49 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0D09E39185A; Mon, 3 Aug 2026 05:15:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WuZslsfX" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f50.google.com (mail-ot1-f50.google.com [209.85.210.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C6A638E5ED for ; Mon, 3 Aug 2026 05:15:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734138; cv=none; b=NSGJDOxn+JmvQ/40JnY/FxDnEG3d0+ICkjHmuPrHBcRQsyPUe1G9m00u+VJynUfRNxt+cIDVoAIEON5Tbyk5pOEdnci9r8m+4s+mKBBHIlNickqDw6/grPqoP91Uf3hPTPboelKwuhBzE/Ou78B1CpTZSUI0EX11xVJ7yAxmPZA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734138; c=relaxed/simple; bh=6OQnGRpMnyrb+bp+bGTn43xoUYsbGDK19SjrvuCzOUU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=W+bH64u0aIbHHVS2wohnnk3v9JappABhRSRAMzIJvwJ6B9yvg9CZNSK1vTR0ISa5/t+ZWRe3qhLPYUXUzCIrNhs5T6eYjLbdsjKv2G+X2k/cUFq52SGzfykn9rTJ0xP76LaaE6RwtsT5MKRvKPn+UHGMMMmRLN7eFrc8Obywmxo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WuZslsfX; arc=none smtp.client-ip=209.85.210.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f50.google.com with SMTP id 46e09a7af769-7e9ecb1e13cso3366344a34.3 for ; Sun, 02 Aug 2026 22:15:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734132; x=1786338932; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=ws0LFhZuUjZTnhwPoD3ztO16rIL3gtosandi83LBFNY=; b=WuZslsfXI4IkD1It7KD8ELwzrH7eC320X2pb+4Gt4DWrpWarSaXAXR+m2wXTmACOi5 lmiWSDJu/9mJj7Jq50qhOBdR6WuXScfXBqoEiF9+XhtAbth0zC0MIOrYQBJuR7fmV6rG ObyXoaCT7c8oFEOFWuBdZvGZjPRTrKVe/RjLacYazWTHdqWcNePMd+JcD6gYY2p4iQUJ Wdq6v1g0700yQiiZzE0i2Vb4mnc/y3skPXfhYKmvMpsb4i+tluGRQqBzDMWhxhJmgZ5G W0YPWqHNkA2soe3mTHN8bxfpw+7aAkzcVH5YEJfY8tptFWFJNthkUiWAajK8Z8VVsP0x qMdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734132; x=1786338932; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=ws0LFhZuUjZTnhwPoD3ztO16rIL3gtosandi83LBFNY=; b=QvkQo7n6OvljNc6CgCPXWoc7bsoqcx1bmG/72W0Y7Xu7c8FLAVmHjdUIse9SQmcYDa czZ3cLotDSP9IjNwfu76e2WU43sgl48aU78dUkHGVAEAzfBZ7D4fQtR6tmHuOMXyFag6 +o+qyxPC0G1GBeglfcSNo5LRUYvJrsaAv9DmMV8sahFjKILa4KH6V5iPYgyEpiWOf6BU 51A6VD0IdVBj2D64nea1Wwx82KaaCnKEbzW/ljCx7wDZtdxUulQJnY6EChHQSe/i2k/J 19uTPPTHqJBN6wxgZcq0E3Q2r752Ti53iYkFUUZAB0//xCIy1Tk8tBrJI7EoVlluPcKU CrQw== X-Forwarded-Encrypted: i=1; AHgh+Rp8tOd4d+hFeQqINP0B4p0DCKBRXzZYO6s+CaUybOWBt5p4BgCVIkQ0Bc49U9cpHd8dM1VVcV64fmf+uQ==@lists.linux.dev X-Gm-Message-State: AOJu0YwHMGcOTLQ67kkCWAJGorqZvYWpezkffXWWQpq4x3qY1dClL9NT IsKN9kDXx+lPDISIrm9SSw3GEUXKhC6cUJSz7oPc9RTRF/kBbnJ+GXvu X-Gm-Gg: AR+sD11mGWV8dhfQkjtrf0okDb7L9Y49CitUObOx0B5JY+gB3garj0eoEp4+m5oUg5Y uEzcpH8FsXqr5l0HL0loDgx1xaPNqFqPeCiXyBPw6EwMdXtOhVWodC8Ev0jKbssaQzA8V4tmz8g oG55LCCrdFrm2L/pqCz7EIvjLr4p0NnATmMwJ2p+55ITezFWnvWoAVsrHEt/i7hcHJyq/Fftt2D pd/sFDF5IouIXDUXb3Br+Otct+IaGANWfoKsm/Rs8TGIDUDb7XG6RHL9j7WtXVJzN4RKRdugGva KSRCY9EvWjMJ7J2fCowU4StmoK37UcUKqgfaQR9vlBmuFuDf9C3N1RQaubqFI2JGwbFXT4GNllY rMCyDd72eggkGsOHGZOhfHPVliz3k6oCFkVN28IdhFUPuA+KGIqJFjs0PCegLVwUVIXJtbscpPj oBOboAmlrGwgUZRfCfw8GGsjnwp7YvO78Yjb9FNaEa/TJKXtshPc9A9VFx0czdhiCTx5+dfDZWP Qh2RIOvQqBKawfubHaSQb7I+q8LT2Ui1M+2IEN3fSGsnu0ks05mLtegpmlGhkAAOQ5VTyZyQieH 8yI2mRz32C/dmzR9fy7ZJaiEag7slP4+Dg/E+mfY6Pv72LBedtBZMcnLvzILoT0YKyg72+gRyLW GyfFBxJD1hXlyrZWP X-Received: by 2002:a05:6830:6737:b0:7dc:df37:844b with SMTP id 46e09a7af769-7f196baee6fmr14985696a34.4.1785734132204; Sun, 02 Aug 2026 22:15:32 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:31 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:18 -0600 Subject: [PATCH 08/21] dt-bindings: mfd: x-powers: add AC200 Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-8-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The AC200 is an I2C-controlled mixed-signal companion IC containing audio, video, RTC and Fast Ethernet PHY functions. Describe the parent device, its input clock, required function supplies, the optional SID bandgap calibration cell used by the vendor initialization sequence, and its optional Ethernet PHY control child. Document the 24 and 27 MHz rates encoded by the public EPHY clock selector. Also describe the optional open-drain, level-triggered INTB output and the nested interrupt controller which exposes the TV encoder, Ethernet PHY and RTC sources. Define the interrupt source numbers for child consumers. Signed-off-by: James Hilliard --- .../devicetree/bindings/mfd/x-powers,ac200.yaml | 118 +++++++++++++++++++++ include/dt-bindings/mfd/x-powers,ac200.h | 13 +++ 2 files changed, 131 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/x-powers,ac200.yaml b/Documentation/devicetree/bindings/mfd/x-powers,ac200.yaml new file mode 100644 index 000000000000..017629cca73c --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/x-powers,ac200.yaml @@ -0,0 +1,118 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/x-powers,ac200.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: X-Powers AC200 mixed-signal IC + +maintainers: + - James Hilliard + +description: + The AC200 is a mixed-signal companion IC containing audio, video, RTC and + Fast Ethernet PHY functions. Its control registers are accessed over I2C. + +properties: + compatible: + const: x-powers,ac200 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + description: + AC200 input clock. When using the Ethernet PHY, its configured rate must + be 24 or 27 MHz, matching the rates encoded by the documented EPHY clock + selector. + + interrupts: + maxItems: 1 + description: + The INTB pin, which is a shared open-drain, level-triggered output for + the TV encoder, Ethernet PHY and RTC interrupt sources. + + interrupt-controller: true + + '#interrupt-cells': + const: 1 + description: + The interrupt number, as defined in + include/dt-bindings/mfd/x-powers,ac200.h. + + ac-ldoin-supply: + description: 3.3 V supply for the audio-codec LDO input + + ephy-vcc-supply: + description: 3.3 V supply for the Ethernet PHY analog front end + + rtc-vcc-supply: + description: 3.3 V supply for the RTC + + tv-vcc-supply: + description: 3.3 V supply for the TV encoder DAC + + nvmem-cells: + maxItems: 1 + description: + Optional SoC SID cell containing the AC200 bandgap calibration value. + The trim is used by the TV encoder; the public AC200 datasheet does not + document the corresponding register fields. + + nvmem-cell-names: + const: bandgap + + ethernet-phy-control: + $ref: /schemas/net/x-powers,ac200-ephy-ctl.yaml# + +required: + - compatible + - reg + - clocks + - ac-ldoin-supply + - ephy-vcc-supply + - rtc-vcc-supply + - tv-vcc-supply + +dependencies: + interrupts: [ interrupt-controller ] + interrupt-controller: [ '#interrupt-cells', interrupts ] + '#interrupt-cells': [ interrupt-controller ] + nvmem-cells: [ nvmem-cell-names ] + nvmem-cell-names: [ nvmem-cells ] + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + mixed-signal@10 { + compatible = "x-powers,ac200"; + reg = <0x10>; + clocks = <&pwm 5>; + ac-ldoin-supply = <®_3v3>; + ephy-vcc-supply = <®_3v3>; + rtc-vcc-supply = <®_3v3>; + tv-vcc-supply = <®_3v3>; + interrupt-parent = <&pio>; + interrupts = <1 20 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <1>; + nvmem-cells = <&ac200_bandgap>; + nvmem-cell-names = "bandgap"; + + ethernet-phy-control { + compatible = "x-powers,ac200-ephy-ctl"; + nvmem-cells = <&ephy_calibration>; + nvmem-cell-names = "calibration"; + phy-mode = "rmii"; + }; + }; + }; +... diff --git a/include/dt-bindings/mfd/x-powers,ac200.h b/include/dt-bindings/mfd/x-powers,ac200.h new file mode 100644 index 000000000000..cc59e2ab4912 --- /dev/null +++ b/include/dt-bindings/mfd/x-powers,ac200.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Interrupt numbers of the X-Powers AC200 interrupt controller. + */ + +#ifndef _DT_BINDINGS_MFD_X_POWERS_AC200_H +#define _DT_BINDINGS_MFD_X_POWERS_AC200_H + +#define AC200_IRQ_TVE 0 +#define AC200_IRQ_EPHY 1 +#define AC200_IRQ_RTC 2 + +#endif /* _DT_BINDINGS_MFD_X_POWERS_AC200_H */ From patchwork Mon Aug 3 05:14:19 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2891 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id 66C4F1C0582 for ; Mon, 3 Aug 2026 07:16:15 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-24920-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-24920-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id AD673300EEB7 for ; Mon, 3 Aug 2026 05:15:54 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 42882399CF0; Mon, 3 Aug 2026 05:15:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G0AT+HyL" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f49.google.com (mail-ot1-f49.google.com [209.85.210.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4DB4F390614 for ; Mon, 3 Aug 2026 05:15:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734139; cv=none; b=Nxq87SRl/l9DqNz5kWd+Xrk4PBV/r8mhrALfuTqEZyG41ZJOD6c4hHIYUaAxRXpBb00J70bFbajKXx3HUZRCP4RxYsUqnc5h6Z8rfflHA0gJu3aunC9RWJyppEeWSjDV7lgzcV84h6AJsyFf/i9q6maVg/BV70q0yQeErZ1gY9M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734139; c=relaxed/simple; bh=MqlazHFPg7A93Yw8yIBqrOlNXVcT4LqcT4gU0kTc88M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Zp+Pdu9ir7HThgeIDXxigujJ+8jU5l3eoC/I60zi3KeOPSRpKMLeblcAuVMxki/s6N4mAuqciMLSOxHFZO2YOSbgtnA/7fLzRxP5eqXX3CcxmcMeByTuFUtZwqJr6y+xzyi3asZQcN3uYY1EA87kIr/ZwPl3gzr+OVu1MeLOQ9A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=G0AT+HyL; arc=none smtp.client-ip=209.85.210.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f49.google.com with SMTP id 46e09a7af769-7eb61bbeb25so2151941a34.1 for ; Sun, 02 Aug 2026 22:15:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734134; x=1786338934; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=o3n69SozBgBa42qBZUQe+SN94PjOayvFQRwUM8nAj08=; b=G0AT+HyLkCQT4rO6OZ6gR2SiVnrPshYMQlb9CNedpT3p9miEVWRp+BVwoR+g8j7zRF MUQ9MPgCkIX2ONZi2Dnaxevjv0c9mkzBUHZEL/v85XY+Laua9a7LcM9eIPXz+XzZKiyy pbOKi0YLCF9YV/cncuBgY0NW1p9TcxhTFnIHany2ghXL7qJ6OUqofUomJTrIB/F7bmHN koxjhUEVhUoe0DYnQ9qYtkyliYpbMRQMoRVblK1a6GO6jqor7YquI0FdfJVKC7yX8xP0 uwAtTHMv1kh/LI+VsrfM48R+gz4OgwclIjZ+bO0sJL8YIIuDcMGU79n8obqjdmUl06Fp dVpg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734134; x=1786338934; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=o3n69SozBgBa42qBZUQe+SN94PjOayvFQRwUM8nAj08=; b=Jbbv7a6d8ay440RapsU11o/YMnk3PRzcBcaaPE+Ji33IXv0Bf7JB8YqLF0JRhdEtoS NWtf20ec0U49Ea9ouKwnkGtb5P8WxS7lTWCoutJDr2+LhHypZwPjvvpkSz2xrHrwuXv3 mJwFaVV0qDYqmul8OFfKscukKhlSN9scBWfVzunrL173STRlmvff2UWWEDWNDw8lUGKz un8HYLiqgeRBHyV0VM8QwpmLCDbMwqTraLR1F+wPhBtl0OUVWZ57OmC95em+nQUYtMWP Dg+xpb1XP0pTh8gBNjGkGQU15VilJjg7vlEi23Mw5epnpYonPGZmnN3Yv7q5Pc5wFZcp 2XkA== X-Forwarded-Encrypted: i=1; AHgh+RoN5c/fpg8ljwiQw7ZF9kBCmj2YtARs6pJkeLgRM9c4RK2Be7h1fyxB2PBTiQwkmjgDQth/M1jryUFdRw==@lists.linux.dev X-Gm-Message-State: AOJu0YwSHV158IjyIaS0QP6Nj5rf3z4f49LxPyiUmOSQ4XbP6ytZB/Uk RO6k2LzSzBxaJXVB4YmlxQQCaAXaP7s28vVL+Vv25S5zHlDnBHQK6rcH X-Gm-Gg: AR+sD13WA2vOD0QrapsUvx6qYgfDH6WPwyfOYo+hSEMjuiHyNZEvySq+p9OIVEui1uW tbhsp+6Z+NbFE0ugM5HmOrWFCSEGXc1oFWqgjvVaURaOXK7JnTYrkU3f69t22QHoTrbmxa5J5pK ihbRCVWGrdkXqKD+WRF8ypf4M839TOMYZtyLjKSLUxSetAQttlZWafb/VJBAWyxT/tf8Ayl4ghN Z2kIPKBFddpbtma2j9MmfKxz4MPBPmGvr0rvLDTGuONOzyxnJ7V0WLiFMm0HT9XCO6bOhL3Knxi iXbQTFD/tyiSeexBG6dXDqkDziZxgey+VOimLdLlsjEvjKY+EI67PZgESi+3fKanQiJZIn67pRa 7VK5YuP0waKvA9fPGdre+xmZbv9qFIKDVKL8LvDyOWy99kV6cNkwlrzMr156/Zw2o/dIh8Gd0Ma vUUHcdWro01phfyZ9kkB+868iVfvcSVQ27ow7tZ7HR8d4iIr9hBC6jHMO4CjQ5Ok/7SoBTZ7rTH hV4CvYsaN/fhPXe5BEf05OEDkr3jdlwSTosyJq/g/+INRyx+6gV1IZ56Q4o0ZqaHOJGu5H4ckLs 6lHzNE57b04Utrn3ALnJPa+IAgepVdRWnSGB6ifLKkH9YUSEuLYTf9GjLatZ2tJjLR2XWPB6ZEN YisvcBlVEbjA4Rj4q X-Received: by 2002:a05:6830:7003:b0:7e9:e288:2b60 with SMTP id 46e09a7af769-7f196b465fcmr14384631a34.1.1785734134150; Sun, 02 Aug 2026 22:15:34 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:33 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:19 -0600 Subject: [PATCH 09/21] mfd: add X-Powers AC200 support Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-9-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The X-Powers AC200 is a mixed-signal companion IC with a paged register map accessed over I2C. Enable its required supplies and board-configured input clock, lock the clock rate, and wait for the settling interval used by the vendor initialization sequence before accessing the device. Initialize the common control interface, report the chip and package revision, and populate the Ethernet PHY control child when firmware describes it. Cache only the common page selector because individual function resets can invalidate functional registers without regmap's knowledge. Optionally apply the SoC SID bandgap calibration using the opaque fixed bits from the vendor sequence. The public manual marks that register as reserved. Boards which do not use the affected TV encoder path may omit the calibration cell. When firmware describes INTB, register a regmap IRQ domain for the TV encoder, Ethernet PHY and RTC sources. Program the shared output enable and requested level polarity while preserving the independently managed source enables. Systems without a routed interrupt remain unchanged. The AC200 and its children cannot initiate DMA. Mark the parent as DMA-incapable before adding the MFD cells so OF DMA setup does not synthesize a mask for the child. Register a managed action that disables the AC200 control block before adding the MFD children. Managed resources unwind in reverse order, so the children are removed before their parent control block is disabled on driver removal or a later probe failure. Disable the block during system shutdown as well. Signed-off-by: James Hilliard --- drivers/mfd/Kconfig | 13 +++ drivers/mfd/Makefile | 1 + drivers/mfd/ac200.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 316 insertions(+) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 763ce6a34782..a71870bcf868 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -205,6 +205,19 @@ config MFD_AC100 This driver include only the core APIs. You have to select individual components like codecs or RTC under the corresponding menus. +config MFD_AC200 + tristate "X-Powers AC200" + depends on I2C + depends on OF + select MFD_CORE + select REGMAP_I2C + select REGMAP_IRQ + help + Support for the X-Powers AC200 mixed-signal companion IC. The AC200 + contains audio, video, RTC and Fast Ethernet PHY functions and is + co-packaged with some Allwinner H6 and H616 SoCs. This driver provides + the shared register access used by the individual function drivers. + config MFD_AXP20X tristate select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index dd4bb7e77c33..890e76a9ad00 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -150,6 +150,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o obj-$(CONFIG_MFD_AC100) += ac100.o +obj-$(CONFIG_MFD_AC200) += ac200.o obj-$(CONFIG_MFD_AXP20X) += axp20x.o obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o diff --git a/drivers/mfd/ac200.c b/drivers/mfd/ac200.c new file mode 100644 index 000000000000..bd9930a02cb2 --- /dev/null +++ b/drivers/mfd/ac200.c @@ -0,0 +1,302 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MFD core driver for the X-Powers AC200 + * + * Copyright (C) 2026 James Hilliard + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define AC200_SYS_VERSION_REG 0x0000 +#define AC200_SYS_VERSION_PACKAGE_MASK GENMASK(15, 14) +#define AC200_SYS_VERSION_CHIP_MASK GENMASK(11, 0) + +#define AC200_SYS_CONTROL_REG 0x0002 +#define AC200_SYS_CONTROL_CHIP_RESET_DEASSERT BIT(0) + +#define AC200_SYS_IRQ_ENABLE_REG 0x0004 +#define AC200_SYS_IRQ_INTB_ENABLE BIT(15) +#define AC200_SYS_IRQ_INTB_ACTIVE_HIGH BIT(14) +#define AC200_SYS_IRQ_RTC_ENABLE BIT(12) +#define AC200_SYS_IRQ_EPHY_ENABLE BIT(8) +#define AC200_SYS_IRQ_TVE_ENABLE BIT(4) + +#define AC200_SYS_IRQ_STATUS_REG 0x0006 + +#define AC200_SYS_BG_CTL_REG 0x0050 +/* + * The vendor initialization sequence composes this as SID data | BIT(15) | + * (0xa << 6). The public datasheet marks the whole register reserved and + * does not name the fixed fields. + */ +#define AC200_SYS_BG_CTL_FIXED_BITS (BIT(15) | (0xa << 6)) + +/* Interface register accessible from every register page. */ +#define AC200_TWI_REG_ADDR_H 0x00fe +#define AC200_MAX_REG 0xa1f2 + +struct ac200 { + struct regmap *regmap; +}; + +static const char * const ac200_supplies[] = { + "ac-ldoin", + "ephy-vcc", + "rtc-vcc", + "tv-vcc", +}; + +static const struct regmap_range_cfg ac200_range_cfg[] = { + { + .range_max = AC200_MAX_REG, + .selector_reg = AC200_TWI_REG_ADDR_H, + .selector_mask = 0xff, + .window_len = 256, + }, +}; + +/* + * Each AC200 sub-block can reset independently, invalidating its register + * contents without regmap's knowledge. Cache only the common page selector; + * this avoids a selector read-modify-write for every access on the same page + * without ever returning stale functional-register values. + */ +static bool ac200_volatile_reg(struct device *dev, unsigned int reg) +{ + return reg != AC200_TWI_REG_ADDR_H; +} + +static const struct regmap_config ac200_regmap_config = { + .name = "ac200", + .reg_bits = 8, + .reg_stride = 2, + .val_bits = 16, + .ranges = ac200_range_cfg, + .num_ranges = ARRAY_SIZE(ac200_range_cfg), + .max_register = AC200_MAX_REG, + .volatile_reg = ac200_volatile_reg, + .cache_type = REGCACHE_MAPLE, +}; + +static const struct regmap_irq ac200_irqs[] = { + REGMAP_IRQ_REG(AC200_IRQ_TVE, 0, AC200_SYS_IRQ_TVE_ENABLE), + REGMAP_IRQ_REG(AC200_IRQ_EPHY, 0, AC200_SYS_IRQ_EPHY_ENABLE), + REGMAP_IRQ_REG(AC200_IRQ_RTC, 0, AC200_SYS_IRQ_RTC_ENABLE), +}; + +/* + * SYS_IRQ_ENABLE is an enable register rather than a mask register, hence + * unmask_base. The INTB output enable and polarity bits share the register, + * but regmap-irq only updates the bits described by ac200_irqs. + * + * SYS_IRQ_STATUS follows the state of each source block and is read-only. + * Interrupts must therefore be acknowledged in the source block itself. + */ +static const struct regmap_irq_chip ac200_irq_chip = { + .name = "ac200", + .status_base = AC200_SYS_IRQ_STATUS_REG, + .unmask_base = AC200_SYS_IRQ_ENABLE_REG, + .num_regs = 1, + .irqs = ac200_irqs, + .num_irqs = ARRAY_SIZE(ac200_irqs), +}; + +static const struct mfd_cell ac200_cells[] = { + { + .name = "ac200-ephy-ctl", + .of_compatible = "x-powers,ac200-ephy-ctl", + }, +}; + +static int ac200_disable(struct ac200 *ac200) +{ + return regmap_write(ac200->regmap, AC200_SYS_CONTROL_REG, 0); +} + +static void ac200_disable_action(void *data) +{ + ac200_disable(data); +} + +static int ac200_init_irq(struct ac200 *ac200, int irq) +{ + struct device *dev = regmap_get_device(ac200->regmap); + struct regmap_irq_chip_data *irq_data; + u16 value = AC200_SYS_IRQ_INTB_ENABLE; + u32 trigger; + int ret; + + trigger = irq_get_trigger_type(irq); + switch (trigger) { + case IRQ_TYPE_LEVEL_HIGH: + value |= AC200_SYS_IRQ_INTB_ACTIVE_HIGH; + break; + case IRQ_TYPE_NONE: + case IRQ_TYPE_LEVEL_LOW: + break; + default: + return dev_err_probe(dev, -EINVAL, + "INTB requires a level interrupt, not type %u\n", + trigger); + } + + ret = regmap_update_bits(ac200->regmap, AC200_SYS_IRQ_ENABLE_REG, + AC200_SYS_IRQ_INTB_ENABLE | + AC200_SYS_IRQ_INTB_ACTIVE_HIGH, value); + if (ret) + return ret; + + ret = devm_regmap_add_irq_chip(dev, ac200->regmap, irq, IRQF_ONESHOT, + 0, &ac200_irq_chip, &irq_data); + if (ret) + return dev_err_probe(dev, ret, + "failed to add interrupt controller\n"); + + return 0; +} + +static int ac200_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct device_node *ephy_node __free(device_node) = NULL; + struct ac200 *ac200; + struct clk *clk; + unsigned int version; + u16 bandgap_calibration = 0; + int ret; + + ac200 = devm_kzalloc(dev, sizeof(*ac200), GFP_KERNEL); + if (!ac200) + return -ENOMEM; + + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ac200_supplies), + ac200_supplies); + if (ret) + return dev_err_probe(dev, ret, "failed to enable supplies\n"); + + clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), + "failed to enable input clock\n"); + + ret = devm_clk_rate_exclusive_get(dev, clk); + if (ret) + return dev_err_probe(dev, ret, "failed to lock clock rate\n"); + + ac200->regmap = devm_regmap_init_i2c(client, &ac200_regmap_config); + if (IS_ERR(ac200->regmap)) + return dev_err_probe(dev, PTR_ERR(ac200->regmap), + "failed to initialize regmap\n"); + + i2c_set_clientdata(client, ac200); + + if (device_property_present(dev, "nvmem-cells")) { + ret = nvmem_cell_read_u16(dev, "bandgap", + &bandgap_calibration); + if (ret) + return dev_err_probe(dev, ret, + "failed to read bandgap data\n"); + } + + /* + * No minimum delay is documented. Match the vendor driver's 40 ms delay + * before its first AC200 register access after enabling the input clock. + */ + msleep(40); + + ret = regmap_read(ac200->regmap, AC200_SYS_VERSION_REG, &version); + if (ret) + return dev_err_probe(dev, ret, + "failed to read chip version\n"); + + dev_info(dev, "AC200 revision %#lx in package %lu\n", + FIELD_GET(AC200_SYS_VERSION_CHIP_MASK, version), + FIELD_GET(AC200_SYS_VERSION_PACKAGE_MASK, version)); + + /* Run after the MFD children have been removed. */ + ret = devm_add_action_or_reset(dev, ac200_disable_action, ac200); + if (ret) + return ret; + + ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL_REG, 0); + if (ret) + return ret; + + ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL_REG, + AC200_SYS_CONTROL_CHIP_RESET_DEASSERT); + if (ret) + return ret; + + if (bandgap_calibration) { + ret = regmap_write(ac200->regmap, AC200_SYS_BG_CTL_REG, + AC200_SYS_BG_CTL_FIXED_BITS | + bandgap_calibration); + if (ret) + return ret; + } + + if (client->irq > 0) { + ret = ac200_init_irq(ac200, client->irq); + if (ret) + return ret; + } + + /* Neither the AC200 nor its child devices can perform DMA. */ + dev->coherent_dma_mask = 0; + dev->dma_mask = &dev->coherent_dma_mask; + ephy_node = of_get_compatible_child(dev->of_node, + "x-powers,ac200-ephy-ctl"); + if (!ephy_node) + return 0; + + return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, ac200_cells, + ARRAY_SIZE(ac200_cells), NULL, 0, NULL); +} + +static void ac200_shutdown(struct i2c_client *client) +{ + struct ac200 *ac200 = i2c_get_clientdata(client); + + ac200_disable(ac200); +} + +static const struct of_device_id ac200_of_match[] = { + { .compatible = "x-powers,ac200" }, + { } +}; +MODULE_DEVICE_TABLE(of, ac200_of_match); + +static const struct i2c_device_id ac200_i2c_ids[] = { + { "ac200" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ac200_i2c_ids); + +static struct i2c_driver ac200_driver = { + .driver = { + .name = "ac200", + .of_match_table = ac200_of_match, + }, + .probe = ac200_probe, + .shutdown = ac200_shutdown, + .id_table = ac200_i2c_ids, +}; +module_i2c_driver(ac200_driver); + +MODULE_AUTHOR("James Hilliard "); +MODULE_DESCRIPTION("X-Powers AC200 MFD core driver"); +MODULE_LICENSE("GPL"); From patchwork Mon Aug 3 05:14:20 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2892 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4]) by mxe881.netcup.net (Postfix) with ESMTPS id 046901C0580 for ; Mon, 3 Aug 2026 07:16:36 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 104.64.211.4) smtp.mailfrom=linux-sunxi+bounces-24921-noreply=patchwork.local@lists.linux.dev smtp.helo=sin.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 104.64.211.4 as permitted sender) client-ip=104.64.211.4; envelope-from=linux-sunxi+bounces-24921-noreply=patchwork.local@lists.linux.dev; helo=sin.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sin.lore.kernel.org (Postfix) with ESMTP id 54811300F0F3 for ; Mon, 3 Aug 2026 05:15:56 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7986139A4BA; Mon, 3 Aug 2026 05:15:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BpeYstte" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f41.google.com (mail-ot1-f41.google.com [209.85.210.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 81F0C395AF2 for ; Mon, 3 Aug 2026 05:15:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734140; cv=none; b=Nz0N8Nr7uz3WpyjUnAmcJFPLjnH0sq7yai7qJKZHaYfpXrkxa+mFdDKn3Rz/BbLe9OhOSIEkJ+3mfxJlvNHPBjgvKK7vIeJ3e4Jzn+WaxEc3g9/u3Z+xjb14FzgRSVOaacF/Uz/Vd6cnZxKTqr8aZ+qN5R1sc6fOwBoyuGomiVI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734140; c=relaxed/simple; bh=FJxa6pnlwH8NOKl4g0tgsIa3AWI3yPSDz31JZnSznJk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nvjOj0Y/JFjT3LDgQA0MYaq6EpdmshfwUnD9f+7YdcL8sNIzn4yGd/owEXGYr0evcQfVOcx53RaZHAbvlEBDwGlGDpRRPR8DjLJDWyMGsH7POeUzksnNevLAKSIkSTQxT4llzbX2uPeud457LxMnifMsozghECnay0ejBkBA8F4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=BpeYstte; arc=none smtp.client-ip=209.85.210.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f41.google.com with SMTP id 46e09a7af769-7ee37dc91f5so1801382a34.3 for ; Sun, 02 Aug 2026 22:15:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734136; x=1786338936; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=DdvS6JgS1wsN4XXB/DPlHPE/KXR5tqJa5L67sBE8VSE=; b=BpeYstte3yr/Uf+GnrQXSnysX7Qiq/rKna6h6U0U6NonE9fGZuDwE9N/0ARcrs7jv+ eTXH7Qq3FHR/G0CgoaQexQznayVc905LR0+b9OMqbS+/q/0X7ivfSYQrT5bSwNm4HPB1 Hz+snwoS2iN4TwzbL5j0DVpJC5pafDtZqDGGjWaTprOqY4zqr1+we8Nc0bOz/XEB/xYj WlXcf+eAfAp46Z5WSctqYY1g6yqwfYyctI3kmanhvVrO6ieXZFP92sHZ2L2+G8B68tuP oZCyR9WB04uV9N5HgGqvNSGFYYWX69lcS7N+vvhvi6poLDmkViFiipZLrw9GZuEcD8FT lvbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734136; x=1786338936; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=DdvS6JgS1wsN4XXB/DPlHPE/KXR5tqJa5L67sBE8VSE=; b=mvLogKg4DkZZByi1gqA6Fl/Od5wnTMY5ucY3yI96odUrS/+76lj1IzzDTniMO/snRa ujAKgx/BlGfu/wnC1wlkxbyQXougWnfh4qQGZ+UyWnOrGqrlwnpHPG6aPZwbq6KawDrq cr99IX+StvpXjfu5udyrMxMag4Qn5b0q/RXxkCDppXMMMBUmN4oLxRIRNXteE4ujvyqU +ktEdnAuSeIblM6p2KAxdhqeTfzK1SFvQ0HgiAKeeT+NSI3OkcIfSwu5IUGhspW1DRCn 1Lw4Fvhr0tlmIS+1t5qkY5mvROP5iVPYQNQ6OSAfZb670UYGC5ephKQ4SMj3P7F8bIXv XLUQ== X-Forwarded-Encrypted: i=1; AHgh+Roul97yu4mSqplZ8hOtRhE6biPSWUVFiI7nP590WOD+VV3JFEsa8B9r+/qz5IaikffldGOZdTi96uwCLQ==@lists.linux.dev X-Gm-Message-State: AOJu0YxvsJd1xLqpQdbpihsvBNDDXeDZbgMvAuID8VgITwugMQgI7es/ Ak6Ls5ufV4f9w4Va7oifrS9SBBExrYUSaFUJoT/52qsO/5itl/Vue/TG X-Gm-Gg: AR+sD135kfYkqBKZNhPd+1YdIjvnSKvpqioG0eb00XaWKiN+TheSQUMBTnITbIcdyPX FCp4HxRqiJ/AuooTaIKpBZACFyQTPz8ax/10TAGsZWeouW4iuEZFYcp5yjzerPsnOFrwEnQx0Vc zwWvjYosIo8SSNHc0nVeXTsYH61jAFBr9XvwNqFRqtJRy6ISDVu8rj01IkCJ1kGwTau6rjLSidc xZD7HBxzrpbBlySwQ+wlXfbI8/zYe4wfK6Hko7DqPxgMUb+oXQF9tVB1IxcgzTzcPLWxAb10T+m A6hVpIJkb74aef56T1k/7TjnjhvdxkhhEIfKxrKN06uaXO1do2CM2hDXBK4pUnFY4S3nzGFJEP7 voxlV119j4srInZ3KkWXrZLOfxy3ZG01evaybOPntF75NIJNM7+7sGaLu3WrE+RDn/XFNZ4mZ+Q kJ/L0WYyh4+BCSVrAKRob6uc9djDyudNBrjFun4N+0DRqwY2GtJ3JZAZBZ/+TLImNRWxDLN6RE3 v6R3uDJGtPVxNIy/lNPIj8yRSzwUTErqhlubyP1SsNrkkmfXQVT8dcn+/OmFMBylMjaxEAxaZTR f3jiowS8UWVfDqUYqpYtJYYcayrzLr7qbjX47UJf43sK8Ef6OXF6te7nR0Xobbl9Rbyx8qHNn9K GvezWgsRnoRpqOHU3 X-Received: by 2002:a05:6830:3814:b0:7e6:ca29:9609 with SMTP id 46e09a7af769-7f196d82b85mr13995078a34.13.1785734136211; Sun, 02 Aug 2026 22:15:36 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:35 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:20 -0600 Subject: [PATCH 10/21] net: phy: add X-Powers AC200 EPHY control driver Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-10-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The AC200 Fast Ethernet PHY is powered and configured through registers in the parent I2C regmap before its Clause 22 link registers become usable. Add a control driver that prepares the calibration value and vendor offset, interface mode and input-clock selection. Use an optional SoC SID cell when supplied, otherwise read the AC200's internal calibration eFuse. Derive the documented 24 or 27 MHz selector from the actual locked clock rate. Although the feature summary also mentions 25 MHz, EPHY_CTL provides no encoding for it, so reject that rate rather than silently selecting 27 MHz. Program the link PHY MDIO address into EPHY_CTL.PHY_ADDR before bringing the PHY out of its disabled state using the vendor initialization sequence. Expose serialized, idempotent power-on and power-off operations so the link-PHY driver can sequence the control block across resets and system sleep. Also expose operations for the global LED polarity and package pad enables. Initialize all three outputs active-low as in the vendor kernel, while allowing an explicit link-PHY LED topology to replace that fallback. Quiesce the block during probe failures, driver removal and system shutdown. Signed-off-by: James Hilliard --- drivers/net/phy/Kconfig | 9 + drivers/net/phy/Makefile | 1 + drivers/net/phy/xpowers-ac200-ctl.c | 330 ++++++++++++++++++++++++++++++++++++ drivers/net/phy/xpowers-acx00.h | 25 +++ 4 files changed, 365 insertions(+) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 099f25dceabb..e059bd6c5eda 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -469,6 +469,15 @@ config VITESSE_PHY help Currently supports the vsc8244 +config XPOWERS_AC200_PHY_CTL + tristate "X-Powers AC200 Ethernet PHY control" + depends on MFD_AC200 + help + Enable the control driver for the Fast Ethernet PHY function in + the X-Powers AC200 mixed-signal companion IC. It programs the PHY + address, interface mode, calibration and I/O controls through the + parent AC200 I2C regmap. + config XILINX_GMII2RGMII tristate "Xilinx GMII2RGMII converter driver" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index de660ae94945..e53ca319f9c4 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -99,4 +99,5 @@ obj-$(CONFIG_SMSC_PHY) += smsc.o obj-$(CONFIG_STE10XP) += ste10Xp.o obj-$(CONFIG_TERANETICS_PHY) += teranetics.o obj-$(CONFIG_VITESSE_PHY) += vitesse.o +obj-$(CONFIG_XPOWERS_AC200_PHY_CTL) += xpowers-ac200-ctl.o obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o diff --git a/drivers/net/phy/xpowers-ac200-ctl.c b/drivers/net/phy/xpowers-ac200-ctl.c new file mode 100644 index 000000000000..c2a37f958565 --- /dev/null +++ b/drivers/net/phy/xpowers-ac200-ctl.c @@ -0,0 +1,330 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * X-Powers AC200 Ethernet PHY control driver + * + * Copyright (C) 2026 James Hilliard + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xpowers-acx00.h" + +#define AC200_EPHY_BPS_EFFUSE_OFFSET 3 + +#define AC200_SYS_EPHY_CTL0_REG 0x0014 +#define AC200_EPHY_RESET_DEASSERT BIT(0) +#define AC200_EPHY_SYSCLK_ENABLE BIT(1) + +#define AC200_SYS_EPHY_CTL1_REG 0x0016 +#define AC200_EPHY_MII_IO_ENABLE BIT(0) +#define AC200_EPHY_LINK_LED_IO_ENABLE BIT(1) +#define AC200_EPHY_SPEED_LED_IO_ENABLE BIT(2) +#define AC200_EPHY_DUPLEX_LED_IO_ENABLE BIT(3) +#define AC200_EPHY_LED_IO_ENABLE_MASK \ + (AC200_EPHY_LINK_LED_IO_ENABLE | AC200_EPHY_SPEED_LED_IO_ENABLE | \ + AC200_EPHY_DUPLEX_LED_IO_ENABLE) + +/* AC200-internal copy of the Ethernet PHY calibration eFuse. */ +#define AC200_EFUSE_EPHY_REG 0x8004 + +#define AC200_EPHY_CTL_REG 0x6000 +#define AC200_EPHY_SHUTDOWN BIT(0) +#define AC200_EPHY_LED_ACTIVE_LOW BIT(1) +#define AC200_EPHY_CLK_SEL_24_MHZ BIT(2) +#define AC200_EPHY_PHY_ADDR_MASK GENMASK(8, 4) +#define AC200_EPHY_RMII_SEL BIT(11) +#define AC200_EPHY_BPS_EFFUSE_MASK GENMASK(15, 12) + +struct ac200_ephy_ctl { + struct acx00_ephy_control control; + struct regmap *regmap; + struct mutex lock; /* Serializes power sequencing and state. */ + u16 ephy_ctl; + u16 led_io_enable; + unsigned int phy_addr; + bool powered; +}; + +static int +ac200_ephy_ctl_set_led_outputs(struct acx00_ephy_control *control, + unsigned long outputs) +{ + struct ac200_ephy_ctl *priv = + container_of(control, struct ac200_ephy_ctl, control); + u16 led_io_enable; + int ret = 0; + + if (outputs & ~GENMASK(ACX00_EPHY_LED_COUNT - 1, 0)) + return -EINVAL; + + led_io_enable = (outputs << 1) & AC200_EPHY_LED_IO_ENABLE_MASK; + + mutex_lock(&priv->lock); + if (priv->powered) + ret = regmap_update_bits(priv->regmap, AC200_SYS_EPHY_CTL1_REG, + AC200_EPHY_LED_IO_ENABLE_MASK, + led_io_enable); + if (!ret) + priv->led_io_enable = led_io_enable; + mutex_unlock(&priv->lock); + + return ret; +} + +static int +ac200_ephy_ctl_set_led_polarity(struct acx00_ephy_control *control, + bool active_low) +{ + struct ac200_ephy_ctl *priv = + container_of(control, struct ac200_ephy_ctl, control); + u16 value = active_low ? AC200_EPHY_LED_ACTIVE_LOW : 0; + int ret = 0; + + mutex_lock(&priv->lock); + if (priv->powered) + ret = regmap_update_bits(priv->regmap, AC200_EPHY_CTL_REG, + AC200_EPHY_LED_ACTIVE_LOW, value); + if (!ret) { + priv->ephy_ctl &= ~AC200_EPHY_LED_ACTIVE_LOW; + priv->ephy_ctl |= value; + } + mutex_unlock(&priv->lock); + + return ret; +} + +static int ac200_ephy_ctl_power_off_locked(struct ac200_ephy_ctl *priv) +{ + int err; + int ret; + + if (!priv->powered) + return 0; + + ret = regmap_write(priv->regmap, AC200_EPHY_CTL_REG, + priv->ephy_ctl | + FIELD_PREP(AC200_EPHY_PHY_ADDR_MASK, + priv->phy_addr) | + AC200_EPHY_SHUTDOWN); + err = regmap_write(priv->regmap, AC200_SYS_EPHY_CTL1_REG, 0); + if (!ret) + ret = err; + err = regmap_write(priv->regmap, AC200_SYS_EPHY_CTL0_REG, 0); + if (!ret) + ret = err; + + priv->powered = false; + + return ret; +} + +static int ac200_ephy_ctl_power_off(struct acx00_ephy_control *control) +{ + struct ac200_ephy_ctl *priv = + container_of(control, struct ac200_ephy_ctl, control); + int ret; + + mutex_lock(&priv->lock); + ret = ac200_ephy_ctl_power_off_locked(priv); + mutex_unlock(&priv->lock); + + return ret; +} + +static int ac200_ephy_ctl_power_on(struct acx00_ephy_control *control, + unsigned int phy_addr) +{ + struct ac200_ephy_ctl *priv = + container_of(control, struct ac200_ephy_ctl, control); + u16 ephy_ctl; + int ret; + + if (phy_addr > FIELD_MAX(AC200_EPHY_PHY_ADDR_MASK)) + return -EINVAL; + + mutex_lock(&priv->lock); + if (priv->powered && priv->phy_addr == phy_addr) { + ret = 0; + goto out_unlock; + } + if (priv->powered) { + ret = ac200_ephy_ctl_power_off_locked(priv); + if (ret) + goto out_unlock; + } + + ephy_ctl = priv->ephy_ctl | + FIELD_PREP(AC200_EPHY_PHY_ADDR_MASK, phy_addr); + + /* Start from a disabled state before applying the configuration. */ + ret = regmap_write(priv->regmap, AC200_SYS_EPHY_CTL0_REG, 0); + if (ret) + goto err_disable; + + ret = regmap_write(priv->regmap, AC200_SYS_EPHY_CTL1_REG, + AC200_EPHY_MII_IO_ENABLE | + priv->led_io_enable); + if (ret) + goto err_disable; + + ret = regmap_write(priv->regmap, AC200_EPHY_CTL_REG, + ephy_ctl | AC200_EPHY_SHUTDOWN); + if (ret) + goto err_disable; + + ret = regmap_write(priv->regmap, AC200_SYS_EPHY_CTL0_REG, + AC200_EPHY_RESET_DEASSERT | + AC200_EPHY_SYSCLK_ENABLE); + if (ret) + goto err_disable; + + fsleep(10000); + + ret = regmap_write(priv->regmap, AC200_EPHY_CTL_REG, ephy_ctl); + if (ret) + goto err_disable; + + priv->phy_addr = phy_addr; + priv->powered = true; + goto out_unlock; + +err_disable: + /* Mark it active so the cleanup sequence is always attempted. */ + priv->phy_addr = phy_addr; + priv->powered = true; + ac200_ephy_ctl_power_off_locked(priv); +out_unlock: + mutex_unlock(&priv->lock); + + return ret; +} + +static int ac200_ephy_ctl_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct ac200_ephy_ctl *priv; + phy_interface_t interface; + struct clk *clk; + unsigned long clk_rate; + unsigned int calibration; + u8 nvmem_calibration; + u8 bps_effuse_code; + u16 ephy_ctl; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + mutex_init(&priv->lock); + + priv->regmap = dev_get_regmap(dev->parent, NULL); + if (!priv->regmap) + return dev_err_probe(dev, -EPROBE_DEFER, + "parent regmap is not ready\n"); + + if (device_property_present(dev, "nvmem-cells")) { + ret = nvmem_cell_read_u8(dev, "calibration", + &nvmem_calibration); + if (ret) + return dev_err_probe(dev, ret, + "failed to read calibration data\n"); + calibration = nvmem_calibration; + } else { + ret = regmap_read(priv->regmap, AC200_EFUSE_EPHY_REG, + &calibration); + if (ret) + return dev_err_probe(dev, ret, + "failed to read on-chip calibration data\n"); + } + + ret = device_get_phy_mode(dev); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to read PHY mode\n"); + interface = ret; + + /* The vendor driver supplies no transfer function beyond this offset. */ + bps_effuse_code = (calibration + AC200_EPHY_BPS_EFFUSE_OFFSET) & + FIELD_MAX(AC200_EPHY_BPS_EFFUSE_MASK); + ephy_ctl = FIELD_PREP(AC200_EPHY_BPS_EFFUSE_MASK, bps_effuse_code) | + AC200_EPHY_LED_ACTIVE_LOW; + /* EPHY_MODE and BIST_CLK_EN stay clear for normal operation. */ + + switch (interface) { + case PHY_INTERFACE_MODE_MII: + break; + case PHY_INTERFACE_MODE_RMII: + ephy_ctl |= AC200_EPHY_RMII_SEL; + break; + default: + return dev_err_probe(dev, -EINVAL, + "unsupported PHY mode %s\n", + phy_modes(interface)); + } + + clk = clk_get(dev->parent, NULL); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), + "failed to get input clock\n"); + + clk_rate = clk_get_rate(clk); + clk_put(clk); + + switch (clk_rate) { + case 24000000: + ephy_ctl |= AC200_EPHY_CLK_SEL_24_MHZ; + break; + case 27000000: + break; + default: + return dev_err_probe(dev, -EINVAL, + "unsupported input clock rate %lu Hz\n", + clk_rate); + } + + priv->control.power_on = ac200_ephy_ctl_power_on; + priv->control.power_off = ac200_ephy_ctl_power_off; + priv->control.set_led_outputs = ac200_ephy_ctl_set_led_outputs; + priv->control.set_led_polarity = ac200_ephy_ctl_set_led_polarity; + priv->control.interface = interface; + priv->ephy_ctl = ephy_ctl; + priv->led_io_enable = AC200_EPHY_LED_IO_ENABLE_MASK; + platform_set_drvdata(pdev, &priv->control); + return 0; +} + +static void ac200_ephy_ctl_remove(struct platform_device *pdev) +{ + struct acx00_ephy_control *control = platform_get_drvdata(pdev); + + control->power_off(control); +} + +static const struct of_device_id ac200_ephy_ctl_of_match[] = { + { .compatible = "x-powers,ac200-ephy-ctl" }, + { } +}; +MODULE_DEVICE_TABLE(of, ac200_ephy_ctl_of_match); + +static struct platform_driver ac200_ephy_ctl_driver = { + .probe = ac200_ephy_ctl_probe, + .remove = ac200_ephy_ctl_remove, + .shutdown = ac200_ephy_ctl_remove, + .driver = { + .name = "ac200-ephy-ctl", + .of_match_table = ac200_ephy_ctl_of_match, + }, +}; +module_platform_driver(ac200_ephy_ctl_driver); + +MODULE_AUTHOR("James Hilliard "); +MODULE_DESCRIPTION("X-Powers AC200 Ethernet PHY control driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/xpowers-acx00.h b/drivers/net/phy/xpowers-acx00.h new file mode 100644 index 000000000000..8cf6fe616137 --- /dev/null +++ b/drivers/net/phy/xpowers-acx00.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __DRIVERS_NET_PHY_XPOWERS_ACX00_H +#define __DRIVERS_NET_PHY_XPOWERS_ACX00_H + +#include + +enum acx00_ephy_led { + ACX00_EPHY_LED_LINK_ACTIVITY, + ACX00_EPHY_LED_SPEED, + ACX00_EPHY_LED_DUPLEX, + ACX00_EPHY_LED_COUNT, +}; + +struct acx00_ephy_control { + phy_interface_t interface; + int (*power_on)(struct acx00_ephy_control *control, + unsigned int phy_addr); + int (*power_off)(struct acx00_ephy_control *control); + int (*set_led_outputs)(struct acx00_ephy_control *control, + unsigned long outputs); + int (*set_led_polarity)(struct acx00_ephy_control *control, + bool active_low); +}; + +#endif From patchwork Mon Aug 3 05:14:21 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2894 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id B97E81C0583 for ; Mon, 3 Aug 2026 07:16:43 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-24922-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-24922-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id 575723015C0D for ; Mon, 3 Aug 2026 05:16:07 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9C8D53845D5; Mon, 3 Aug 2026 05:15:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iTkhOC5R" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f51.google.com (mail-ot1-f51.google.com [209.85.210.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 08ED439792B for ; Mon, 3 Aug 2026 05:15:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734141; cv=none; b=ofC1bpk3bHW9y1E7rG850QHtBXruooBoVoqBuzghBPxI7EBuqmgMG9OzUIlbu7nkhak1gibJ5KtqlzzsyWyL/VrWrRsLMbd+G7FtND6WvKb3cav0MXGRn02MySX3WnNRY4bry7OyNyjh6ehg+Jq+LflF2aSDMX0we3llndUpIus= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734141; c=relaxed/simple; bh=2SOkuuUqffJAqXcEW7ZDhEaFHvF0SZKllJC1Nh5E8zo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZCuBFz81O8rq70+PNDz166aR5hHJxFH+4lvPy5Vw3zfftFw7R/s7zyLKRSSYczzuv+4+oOLvQrICXJw5ZLaFUf0mwYda3b0foPgoVYF08tbailHCB6Hn49SQUoTSHlOfEWLueEwixsa1zo5KmZ6lzNo7V336f0Hi2YWMjpubZ54= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=iTkhOC5R; arc=none smtp.client-ip=209.85.210.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f51.google.com with SMTP id 46e09a7af769-7ee37dc91f5so1801398a34.3 for ; Sun, 02 Aug 2026 22:15:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734138; x=1786338938; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=GTwjTV5MzEj5mt/lgWMCGvinpE29xZysk84NZ5krcS8=; b=iTkhOC5RzevZ2n3mto9+6mPC8FDrCc9ucrWkW0FRCOWf62RY4+lOXHVvWkKtFGcIIC /9YpLXdkLAZajpwjPFxNbhZBngTnMNQzTB5/ndgQjxRPpAQGi/VnQ+N/7Dh9d+jlZca6 OwiuH1HHpOOzA3zivFI6p+PXd+PqowndRiY2KVO6aNrfqWcU0aFtAlfpj15ff6//yLHC TMDnQm9fZxvBshXFCVB1sDSDUFHbmkYAhrsU969pthJhxx1h3jAvXWZlQ+vQwYoD4w57 kWypzlp54TJLKTlfMGbmsaixlwZVnOIjen/4vqt/Vr6fKtJUh1fI2RhWrrDsMNj5LKzw RWzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734138; x=1786338938; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=GTwjTV5MzEj5mt/lgWMCGvinpE29xZysk84NZ5krcS8=; b=HEbFLsQSusl/p3yrU1+N+qPO6E8ll6rDDYBb42ds0DT+OMuMXgNrwOe/rhOAbV/Eoh YTUV9gsC1LUIlCHi0N7qxz2COxoOpeeyMt81J/cFOo7WiS6N6kDN9Y1we9skLUv1j1Qa 05bDQGu5+lB7kce2U1SxWh/bBB5u1F17swnR/j5b7Z62sM1WdGB0lICJuFZeUoFN0HJd RrnzFn0EBjE6IEa8UxiCy48NFFlb7ZlxEu2sTadKCuSQqMVBz54+BMYNGVaSxvDv1dEA EJT3EMEC/Rc+LJVUEnMX58E3ZUTYbibH8XmmWS0XuXuLeyOnJj+5KxK0bQHE/NHjcnKq qpvw== X-Forwarded-Encrypted: i=1; AHgh+RrUT0CKgNdqYzgXgRHEVaYlFvvH39Xx/07SkB7ZTVE7RjezlmFggX7zqfWCRYAPnB+od7BcdJBUN9GZwg==@lists.linux.dev X-Gm-Message-State: AOJu0YzmdDCN3eiZHa7JuPAITYJGcacdw5hJdCp9KrOpC9O9+ETaLvEc qVpkKIx/QG8WdnEA6h1eUp4fgTjqvefPa8wXDUi3mg4naWSsH1ouJoPD X-Gm-Gg: AR+sD10IfzRTW6jfL/zMBjSrw8pB1aqnRMFIEJvMvN4zzPmGcMXkUAos/WG0vKljP6v ue9VeKIt33hQsn04Z6bP1yw6xjSj5OQudQagPmCQ8JEAnKYClkOUYNw5J9T986I41gRY8mca7zM EOPqXYpUUhp7mFQ1VQw/AOyp8mQg91izCo8i/4Y4IlZpqNg4Gq6xsUdOtWEsQSTRNgbhW7d7M+T Z0uV1Mr2J0ia1aB3F4bWCFoaNLgq7QfGdsRdhqY+MHyvrStX+PPuIyngIXKK+d2tEmrYQPczSbv vijflMhwluXkvaidpyUrXMOSVqg3ocibQXMHE3FR+S+ljANj9V4QiVsoPVicdmj7xE2nDHBSC59 QdkqlKt/1bfQatsgNw/kgucWHzBkmHrXH9sYJ5bBPf6u7zmCBYSUKjp3pnM06BSu1F3+IK16y87 14yuC9Xqu8wlLRE9XTmQIvq/PGXszIe/3t5q0yK7ynHJS6jAgq8cCscl7K0QVrxqMXLmvc8Cp7w W/Iff0zs8alOqXHJpo0XkKe2UkBPeX1LMrDY8T9ugfaozLxlT+vhPRZgvynPRNNdqvxzzF6x2+P njxsE/6BDD2O5z4pT+xnGxMio6jS13Gp8kDAocP8nP1tvCyGHAMb5Y0yTMxffhGnpiDaUw0yZA1 lNE8S1c0jkFWMVG6/ X-Received: by 2002:a05:6830:4489:b0:7e9:cddb:142a with SMTP id 46e09a7af769-7f196bd63a9mr15354948a34.7.1785734137863; Sun, 02 Aug 2026 22:15:37 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:37 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:21 -0600 Subject: [PATCH 11/21] dt-bindings: net: x-powers: add AC300 EPHY control Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-11-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[172.232.135.74:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; TAGGED_RCPT(0.00)[netdev,dt]; PRECEDENCE_BULK(0.00)[]; RCPT_COUNT_TWELVE(0.00)[34]; TO_DN_SOME(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[devicetree.org:url,sto.lore.kernel.org:rdns,sto.lore.kernel.org:helo,0.0.0.10:email]; FORGED_SENDER_MAILLIST(0.00)[]; FREEMAIL_CC(0.00)[vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com]; FREEMAIL_FROM(0.00)[gmail.com]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; R_SPF_ALLOW(0.00)[+ip4:172.232.135.74:c]; MIME_TRACE(0.00)[0:+]; RCVD_TLS_LAST(0.00)[]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; FREEMAIL_TO(0.00)[lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,arm.com,bootlin.com,foss.st.com,st.com,synopsys.com,armlinux.org.uk,sntech.de]; FROM_HAS_DN(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; ASN(0.00)[asn:63949, ipnet:172.232.128.0/19, country:SG]; TAGGED_FROM(0.00)[bounces-24922-noreply=patchwork.local]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: B97E81C0583 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The AC300 companion IC exposes the Fast Ethernet PHY control registers through a separate non-PHY Clause 22 address. The manual defines the control address as the link-PHY address plus 16, giving address ranges of 16-23 and 0-7 respectively. Describe the control endpoint, its required VCC1 supply, its 24, 25 or 27 MHz input clock, interface mode and calibration cell. Signed-off-by: James Hilliard --- .../bindings/net/x-powers,ac300-ephy-ctl.yaml | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/Documentation/devicetree/bindings/net/x-powers,ac300-ephy-ctl.yaml b/Documentation/devicetree/bindings/net/x-powers,ac300-ephy-ctl.yaml new file mode 100644 index 000000000000..a6634fcfafd4 --- /dev/null +++ b/Documentation/devicetree/bindings/net/x-powers,ac300-ephy-ctl.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/x-powers,ac300-ephy-ctl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: X-Powers AC300 Ethernet PHY control interface + +maintainers: + - James Hilliard + +description: + The AC300 Fast Ethernet PHY has a separate control interface accessed as a + non-PHY Clause 22 device. Its address is 16 plus the address of the link PHY. + +properties: + compatible: + const: x-powers,ac300-ephy-ctl + + reg: + minimum: 16 + maximum: 23 + + clocks: + maxItems: 1 + description: + AC300 input clock. Its configured rate must be 24, 25, or 27 MHz and + determines the corresponding EPHY_CLK_SEL value. + + vcc1-supply: + description: + 3.3 V supply for the AC300 I/O, bandgap, Ethernet PHY analog front end, + and internal digital LDO + + nvmem-cells: + maxItems: 1 + description: + SoC SID cell containing the Ethernet PHY calibration value written to + the AC300 BGS_EFFUSE field after adding 3 modulo 16, as prescribed by + the vendor initialization sequence. + + nvmem-cell-names: + const: calibration + + phy-mode: + enum: + - mii + - rmii + +required: + - compatible + - reg + - clocks + - vcc1-supply + - nvmem-cells + - nvmem-cell-names + - phy-mode + +additionalProperties: false + +examples: + - | + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy-control@10 { + compatible = "x-powers,ac300-ephy-ctl"; + reg = <0x10>; + clocks = <&pwm 5>; + vcc1-supply = <®_3v3>; + nvmem-cells = <&ephy_calibration>; + nvmem-cell-names = "calibration"; + phy-mode = "rmii"; + }; + }; +... From patchwork Mon Aug 3 05:14:22 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2904 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id A23611C1E65 for ; Mon, 3 Aug 2026 07:22:32 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24923-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24923-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 6EA8E30B4BBC for ; Mon, 3 Aug 2026 05:16:35 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id ABDE039EF0B; Mon, 3 Aug 2026 05:15:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="k8s2F4hY" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f49.google.com (mail-ot1-f49.google.com [209.85.210.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8895E39BFF2 for ; Mon, 3 Aug 2026 05:15:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734145; cv=none; b=gbDPqf8J5r69YQfqwHvH24u1HNmVWhgNFtxTfynFT2iTVdsXSNAO24eO563f2AOYY8e44swb1CBRW6KLXDqf0AEj3QIQfJvjbX6IqBPjXJbG8lJhga9mFVDMgEPXpIyuDrncEFzsrE6Ft/MsP2e56fxbhSHUPXBIkOQvGmLSL8I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734145; c=relaxed/simple; bh=ivlB4EsccJlR8c56XVzqea+fP0pw7c0V38csFjkA2GA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Ru4xAGFKCNGaKLLLwGSAsz/W7EhCtueoUnv5b4Wwh6yA2HrpODiT0TnPSDaBP7q3FBuSOR1ZO4z6riYlqk1oS/seU4kvZe2XVE5+YJzj6PqW4kzoEhuRn0dHE/AWok6WWIGNpvRkkjPCRoF+76z4Lut8AtH7dHrAtx5qVclDq+A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=k8s2F4hY; arc=none smtp.client-ip=209.85.210.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f49.google.com with SMTP id 46e09a7af769-7ebd88be784so1889374a34.2 for ; Sun, 02 Aug 2026 22:15:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734140; x=1786338940; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=qMpLqvLPj4rvPj5SZvuQI1CV6P3xEdk1nLLBNVxHBq8=; b=k8s2F4hY3quIQbAxUiF9AF3/JE9r6a9Bsp+jA0KPcSNmyKuvVGQC5y3ytRygZbZXXS Oy056rp8T6W1trmUMBgVKNcwKrj22Me6uxfuipAzplSMeom3CNvhuihpl/nEWaltkTB2 8CL+UmAMis2jKizHx6JhJ90ZGOSRr5NQmN4xgYeNaNquTS1Sk9PG2B7w3am5e/dbLu/i 3bsOJ5zWNwXirQwEyNpNYy9MAJsbO9E/JUBME2gAulXqEAOFXJWMwvIAfejOsINw7jCV TLY6NCbbevbJ6NdJVUWF6CxSpv8tFggeBpdVwn4R8dVdaHCvAltOq7znNEarM/Flgzpm wqGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734140; x=1786338940; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=qMpLqvLPj4rvPj5SZvuQI1CV6P3xEdk1nLLBNVxHBq8=; b=hiNujXe0o2spxDC7MlR1KSgnl8fsfYjncPS3RiUZYA+cub1/sFr0qXrOb2gBHM7Q/8 k9FTvXaHIuwRd2QKPrK9Gh6weHrBZbGIRbu2ztUesggxeOUoBbtL5P8UewEu5pSooH7e wczRRDz9367XRF3EYJ8/0/NYXjGthhnlCJuZ1kJ3jHAfMPRGn4+VciBgEp4BbDVhD6E2 oE+Juqz8aJkcaG9LiJuCaAycpJlT5B853BlRzCSNof9UZ70QgAH/4zL5xJMKDa4RB2dH hafl2NTIaOaWTEBfRXL+whcr3EC812MBJ6rYnYjbyeZKstMH5WfiV0SR3m5Lt1x1opa8 gl3w== X-Forwarded-Encrypted: i=1; AHgh+RrnWPcdh5w/r1tIRgnFFysXlBnchGDqsrLhgcn6YeTsEGr81gbvqjQ8PLuFPkNSPUERmE2qKCbS54MOzg==@lists.linux.dev X-Gm-Message-State: AOJu0YybHFJpswlkHvMCz3mnVXLQA2bD5nph5ibvoQscJUK9n1bau0T8 c85Z6gmqOw6M6ncBnbtMsc4269xk6MLrl9mOjoPAHPhTHjCoA0zehBmI X-Gm-Gg: AR+sD11xeI0R7UhmFr1YxUPVFlWJy0ITokYGv8rZ9PCMcVu0rj5fM5/9IGgiM8B1Epv mcZ9eKbVb7Glwrx9PWDL+BVkpLoyX0nRErzqoUF2stNMpqEriOm3obCt8WoEAbYY79rIyWmTf2X 0TzkaX3S9jZPXJ2KmErxjyAlCyJyQZ0NfMwKBNgl0D2t8T5EibnYFgYl7JU5PAqry5BIYBIeowo G9v1RIN3GvL78k1sP1kR8DkaHtLxnCiBVMMk8mUPIuMoJdZi04IrMw3P7zvGGvMD1WH//rx7Om1 Arfc7dCktob7N2lgSw9lJX8pkFtthSmau5GASv5/dk78aYNJUBfmEeBtuPPPr0I+H8HafOtokSG 0dcbREfsttvkN88Dr1imRhO4rYU8974GSRBo41bYUh+/W2574zgJCmWmzfIpdCCZmoFAxfErhgw 3ukK2gjMvnb+skuH1z9DkC8VmF1MpZkLAS48WeLl7iLOxtoGrCxsR1BPP5oeF1gdM39j7Jd998A TThbiHulLahuk8H4H8NFKabZ8m9b48Hg6bcJQ9uw5NV4znCTj10wkdY0MVpEzar+6BA6VEL5AMI urP3a3pvjoN99VbDDV9aXobh0bYYsXlfmea6Eee4Jf8Zu8b+oXeSObpQSzj8kQlzj+n5dRsM33U 7bFwYUH6twk2O2vbZDw== X-Received: by 2002:a05:6830:67f6:b0:7e6:e022:4b44 with SMTP id 46e09a7af769-7f196f1c52bmr14209690a34.15.1785734139942; Sun, 02 Aug 2026 22:15:39 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:39 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:22 -0600 Subject: [PATCH 12/21] net: phy: add X-Powers AC300 EPHY control driver Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-12-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The AC300 Fast Ethernet PHY uses a non-PHY Clause 22 endpoint for the power-up and configuration sequence required before its link registers become usable. Enable the required VCC1 supply and wait the manual's 10 ms power-on-reset interval before accessing the device. Accept the configured 24, 25 or 27 MHz input clock and program its corresponding selector, apply the SoC SID calibration value and vendor offset, select the interface mode, configure the I/O drive controls, and follow the manual reset-before-clock power-up sequence. Retain the vendor eFuse and register-clock enable settings. Validate the control address and supply configuration against the package strap state. Clear a latched MDIO error after reset and fail power-up if it remains asserted. Enable the internal digital LDO only for the corresponding package and preserve the external-supply configuration across later power cycles. Report the chip, mask and package revisions. Expose serialized, idempotent power-on and power-off operations so the link-PHY driver can sequence the input clock and control block across resets and system sleep. Also expose operations for the global LED polarity and package pad enables, retaining the documented default drive strength. Initialize all three outputs active-low as in the vendor kernel, while allowing an explicit link-PHY LED topology to replace that fallback. Signed-off-by: James Hilliard --- drivers/net/phy/Kconfig | 9 + drivers/net/phy/Makefile | 1 + drivers/net/phy/xpowers-ac300-ctl.c | 454 ++++++++++++++++++++++++++++++++++++ drivers/net/phy/xpowers-acx00.h | 2 + 4 files changed, 466 insertions(+) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index e059bd6c5eda..9b202072d5a0 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -478,6 +478,15 @@ config XPOWERS_AC200_PHY_CTL address, interface mode, calibration and I/O controls through the parent AC200 I2C regmap. +config XPOWERS_AC300_PHY_CTL + tristate "X-Powers AC300 Ethernet PHY control" + depends on COMMON_CLK && NVMEM && OF_MDIO + help + Enable the MDIO control driver for the Fast Ethernet PHY in the + X-Powers AC300 companion IC. It programs the PHY calibration, + interface mode, clock and I/O controls through the separate MDIO + control address. + config XILINX_GMII2RGMII tristate "Xilinx GMII2RGMII converter driver" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index e53ca319f9c4..2d22d5a4c93d 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -100,4 +100,5 @@ obj-$(CONFIG_STE10XP) += ste10Xp.o obj-$(CONFIG_TERANETICS_PHY) += teranetics.o obj-$(CONFIG_VITESSE_PHY) += vitesse.o obj-$(CONFIG_XPOWERS_AC200_PHY_CTL) += xpowers-ac200-ctl.o +obj-$(CONFIG_XPOWERS_AC300_PHY_CTL) += xpowers-ac300-ctl.o obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o diff --git a/drivers/net/phy/xpowers-ac300-ctl.c b/drivers/net/phy/xpowers-ac300-ctl.c new file mode 100644 index 000000000000..eb3faaab9337 --- /dev/null +++ b/drivers/net/phy/xpowers-ac300-ctl.c @@ -0,0 +1,454 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * X-Powers AC300 Ethernet PHY control driver + * + * Copyright (C) 2026 James Hilliard + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xpowers-acx00.h" + +#define AC300_EPHY_BGS_EFFUSE_OFFSET 3 + +#define AC300_SYS_CONTROL_REG 0x00 +#define AC300_CHIP_VERSION_MASK GENMASK(15, 12) +#define AC300_PACKAGE_STATUS_MASK GENMASK(11, 8) +#define AC300_EPHY_CLK_SEL_MASK GENMASK(7, 6) +#define AC300_EPHY_CLK_SEL_25_MHZ FIELD_PREP(AC300_EPHY_CLK_SEL_MASK, 0) +#define AC300_EPHY_CLK_SEL_27_MHZ FIELD_PREP(AC300_EPHY_CLK_SEL_MASK, 1) +#define AC300_EPHY_CLK_SEL_24_MHZ FIELD_PREP(AC300_EPHY_CLK_SEL_MASK, 2) +#define AC300_EFUSE_CLK_ENABLE BIT(5) +#define AC300_EPHY_REG_CLK_ENABLE BIT(4) +#define AC300_MDIO_ERROR BIT(3) +#define AC300_CLKIN_GATING_ENABLE BIT(2) +#define AC300_EPHY_RESET_DEASSERT BIT(1) +#define AC300_CHIP_RESET_DEASSERT BIT(0) + +#define AC300_MASK_VERSION_REG 0x04 +#define AC300_MASK_VERSION_MASK GENMASK(2, 0) + +#define AC300_PACKAGE_POR_INTERNAL_DLDO BIT(3) +#define AC300_PACKAGE_PHY_ADDR_MASK GENMASK(2, 0) + +#define AC300_SYS_BIAS1_REG 0x02 +#define AC300_INTERNAL_DLDO_ENABLE BIT(15) + +#define AC300_SYS_IO_REG 0x05 +#define AC300_MDIO_DRV_MASK GENMASK(15, 14) +#define AC300_LED_DRV_MASK GENMASK(13, 12) +#define AC300_MII_DRV_MASK GENMASK(11, 10) +#define AC300_IO_DRV_LEVEL_2 2 +#define AC300_CLKIN_PAD_ENABLE BIT(4) +#define AC300_DUPLEX_LED_IO_ENABLE BIT(3) +#define AC300_SPEED_LED_IO_ENABLE BIT(2) +#define AC300_LINK_LED_IO_ENABLE BIT(1) +#define AC300_EPHY_MII_IO_ENABLE BIT(0) +#define AC300_LED_IO_ENABLE_MASK \ + (AC300_DUPLEX_LED_IO_ENABLE | AC300_SPEED_LED_IO_ENABLE | \ + AC300_LINK_LED_IO_ENABLE) + +#define AC300_EPHY_CONFIG_REG 0x06 +#define AC300_EPHY_BGS_EFFUSE_MASK GENMASK(15, 12) +#define AC300_EPHY_RMII_SEL BIT(11) +#define AC300_EPHY_LED_ACTIVE_LOW BIT(1) +#define AC300_EPHY_SHUTDOWN BIT(0) + +#define AC300_SYS_CONTROL_ENABLE_BITS \ + (AC300_EFUSE_CLK_ENABLE | AC300_EPHY_REG_CLK_ENABLE | \ + AC300_CLKIN_GATING_ENABLE | \ + AC300_EPHY_RESET_DEASSERT | AC300_CHIP_RESET_DEASSERT) + +#define AC300_SYS_IO_BASE_VALUE \ + (FIELD_PREP(AC300_MDIO_DRV_MASK, AC300_IO_DRV_LEVEL_2) | \ + FIELD_PREP(AC300_LED_DRV_MASK, AC300_IO_DRV_LEVEL_2) | \ + FIELD_PREP(AC300_MII_DRV_MASK, AC300_IO_DRV_LEVEL_2) | \ + AC300_CLKIN_PAD_ENABLE | AC300_EPHY_MII_IO_ENABLE) + +struct ac300_ephy_ctl { + struct acx00_ephy_control control; + struct mdio_device *mdiodev; + struct clk *clk; + struct mutex lock; /* Serializes power sequencing and state. */ + u16 sys_control; + u16 ephy_config; + u16 led_io_enable; + bool package_known; + bool internal_dldo; + bool powered; +}; + +static unsigned int +ac300_ephy_ctl_link_addr(const struct ac300_ephy_ctl *priv) +{ + return priv->mdiodev->addr - AC300_EPHY_CONTROL_ADDR_OFFSET; +} + +static int +ac300_ephy_ctl_set_led_outputs(struct acx00_ephy_control *control, + unsigned long outputs) +{ + struct ac300_ephy_ctl *priv = + container_of(control, struct ac300_ephy_ctl, control); + u16 led_io_enable; + int ret = 0; + + if (outputs & ~GENMASK(ACX00_EPHY_LED_COUNT - 1, 0)) + return -EINVAL; + + led_io_enable = (outputs << 1) & AC300_LED_IO_ENABLE_MASK; + + mutex_lock(&priv->lock); + if (priv->powered) + ret = mdiodev_modify(priv->mdiodev, AC300_SYS_IO_REG, + AC300_LED_IO_ENABLE_MASK, led_io_enable); + if (!ret) + priv->led_io_enable = led_io_enable; + mutex_unlock(&priv->lock); + + return ret; +} + +static int +ac300_ephy_ctl_set_led_polarity(struct acx00_ephy_control *control, + bool active_low) +{ + struct ac300_ephy_ctl *priv = + container_of(control, struct ac300_ephy_ctl, control); + u16 value = active_low ? AC300_EPHY_LED_ACTIVE_LOW : 0; + int ret = 0; + + mutex_lock(&priv->lock); + if (priv->powered) + ret = mdiodev_modify(priv->mdiodev, AC300_EPHY_CONFIG_REG, + AC300_EPHY_LED_ACTIVE_LOW, value); + if (!ret) { + priv->ephy_config &= ~AC300_EPHY_LED_ACTIVE_LOW; + priv->ephy_config |= value; + } + mutex_unlock(&priv->lock); + + return ret; +} + +static int ac300_ephy_ctl_power_off_locked(struct ac300_ephy_ctl *priv) +{ + int err; + int ret; + + if (!priv->powered) + return 0; + + ret = mdiodev_write(priv->mdiodev, AC300_EPHY_CONFIG_REG, + priv->ephy_config | AC300_EPHY_SHUTDOWN); + err = mdiodev_write(priv->mdiodev, AC300_SYS_IO_REG, 0); + if (!ret) + ret = err; + err = mdiodev_write(priv->mdiodev, AC300_SYS_CONTROL_REG, + priv->package_known && !priv->internal_dldo ? + AC300_CHIP_RESET_DEASSERT : 0); + if (!ret) + ret = err; + + clk_disable_unprepare(priv->clk); + priv->powered = false; + + return ret; +} + +static int ac300_ephy_ctl_power_off(struct acx00_ephy_control *control) +{ + struct ac300_ephy_ctl *priv = + container_of(control, struct ac300_ephy_ctl, control); + int ret; + + mutex_lock(&priv->lock); + ret = ac300_ephy_ctl_power_off_locked(priv); + mutex_unlock(&priv->lock); + + return ret; +} + +static int ac300_ephy_ctl_power_on(struct acx00_ephy_control *control, + unsigned int phy_addr) +{ + struct ac300_ephy_ctl *priv = + container_of(control, struct ac300_ephy_ctl, control); + u8 package_status; + int sys_control; + u16 reset_value; + int ret; + + if (phy_addr != ac300_ephy_ctl_link_addr(priv)) + return -EINVAL; + + mutex_lock(&priv->lock); + if (priv->powered) { + ret = 0; + goto out_unlock; + } + + ret = clk_prepare_enable(priv->clk); + if (ret) + goto out_unlock; + priv->powered = true; + + /* Keep the external-supply configuration across subsequent resets. */ + reset_value = priv->package_known && !priv->internal_dldo ? + AC300_CHIP_RESET_DEASSERT : 0; + ret = mdiodev_write(priv->mdiodev, AC300_SYS_CONTROL_REG, reset_value); + if (ret) + goto err_power_off; + + /* The manual requires both resets to be released before the clocks. */ + ret = mdiodev_write(priv->mdiodev, AC300_SYS_CONTROL_REG, + AC300_EPHY_RESET_DEASSERT | + AC300_CHIP_RESET_DEASSERT); + if (ret) + goto err_power_off; + + /* Retain the vendor clock-enable defaults, including the eFuse clock. */ + ret = mdiodev_write(priv->mdiodev, AC300_SYS_CONTROL_REG, + priv->sys_control); + if (ret) + goto err_power_off; + + sys_control = mdiodev_read(priv->mdiodev, AC300_SYS_CONTROL_REG); + if (sys_control < 0) { + ret = sys_control; + goto err_power_off; + } + if (sys_control & AC300_MDIO_ERROR) { + ret = mdiodev_write(priv->mdiodev, AC300_SYS_CONTROL_REG, + priv->sys_control | AC300_MDIO_ERROR); + if (ret) + goto err_power_off; + + sys_control = mdiodev_read(priv->mdiodev, AC300_SYS_CONTROL_REG); + if (sys_control < 0) { + ret = sys_control; + goto err_power_off; + } + if (sys_control & AC300_MDIO_ERROR) { + ret = -EIO; + goto err_power_off; + } + } + + package_status = FIELD_GET(AC300_PACKAGE_STATUS_MASK, sys_control); + if ((~package_status & AC300_PACKAGE_PHY_ADDR_MASK) != + ac300_ephy_ctl_link_addr(priv)) { + ret = -EINVAL; + goto err_power_off; + } + + priv->internal_dldo = package_status & + AC300_PACKAGE_POR_INTERNAL_DLDO; + priv->package_known = true; + ret = mdiodev_modify(priv->mdiodev, AC300_SYS_BIAS1_REG, + AC300_INTERNAL_DLDO_ENABLE, + priv->internal_dldo ? + AC300_INTERNAL_DLDO_ENABLE : 0); + if (ret) + goto err_power_off; + + /* Keep the documented default drive level and leave the IRQ disabled. */ + ret = mdiodev_write(priv->mdiodev, AC300_SYS_IO_REG, + AC300_SYS_IO_BASE_VALUE | priv->led_io_enable); + if (ret) + goto err_power_off; + + fsleep(10000); + + ret = mdiodev_write(priv->mdiodev, AC300_EPHY_CONFIG_REG, + priv->ephy_config | AC300_EPHY_SHUTDOWN); + if (ret) + goto err_power_off; + + fsleep(10000); + + ret = mdiodev_write(priv->mdiodev, AC300_EPHY_CONFIG_REG, + priv->ephy_config); + if (ret) + goto err_power_off; + + goto out_unlock; + +err_power_off: + ac300_ephy_ctl_power_off_locked(priv); +out_unlock: + mutex_unlock(&priv->lock); + + return ret; +} + +static int ac300_ephy_ctl_probe(struct mdio_device *mdiodev) +{ + struct device *dev = &mdiodev->dev; + struct ac300_ephy_ctl *priv; + phy_interface_t interface; + u8 calibration; + u8 bgs_effuse_code; + u8 package_status; + u16 ephy_config; + struct clk *clk; + int mask_version; + int sys_control; + unsigned long clk_rate; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + if (mdiodev->addr < AC300_EPHY_CONTROL_ADDR_OFFSET || + mdiodev->addr > AC300_EPHY_CONTROL_ADDR_OFFSET + + FIELD_MAX(AC300_PACKAGE_PHY_ADDR_MASK)) + return dev_err_probe(dev, -EINVAL, + "control address is outside the package range\n"); + priv->mdiodev = mdiodev; + mutex_init(&priv->lock); + + ret = devm_regulator_get_enable(dev, "vcc1"); + if (ret) + return dev_err_probe(dev, ret, + "failed to enable VCC1 supply\n"); + + /* Wait for the power-on reset interval specified by the manual. */ + fsleep(10000); + + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), + "failed to get input clock\n"); + priv->clk = clk; + + ret = devm_clk_rate_exclusive_get(dev, clk); + if (ret) + return dev_err_probe(dev, ret, "failed to lock clock rate\n"); + + clk_rate = clk_get_rate(clk); + switch (clk_rate) { + case 24000000: + priv->sys_control = AC300_EPHY_CLK_SEL_24_MHZ; + break; + case 25000000: + priv->sys_control = AC300_EPHY_CLK_SEL_25_MHZ; + break; + case 27000000: + priv->sys_control = AC300_EPHY_CLK_SEL_27_MHZ; + break; + default: + return dev_err_probe(dev, -EINVAL, + "unsupported input clock rate %lu Hz\n", + clk_rate); + } + priv->sys_control |= AC300_SYS_CONTROL_ENABLE_BITS; + + ret = nvmem_cell_read_u8(dev, "calibration", &calibration); + if (ret) + return dev_err_probe(dev, ret, + "failed to read calibration data\n"); + + ret = device_get_phy_mode(dev); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to read PHY mode\n"); + interface = ret; + + /* The vendor driver supplies no transfer function beyond this offset. */ + bgs_effuse_code = (calibration + AC300_EPHY_BGS_EFFUSE_OFFSET) & + FIELD_MAX(AC300_EPHY_BGS_EFFUSE_MASK); + ephy_config = FIELD_PREP(AC300_EPHY_BGS_EFFUSE_MASK, bgs_effuse_code) | + AC300_EPHY_LED_ACTIVE_LOW; + /* EPHY_MODE and BIST_CLK_EN stay clear for normal operation. */ + + switch (interface) { + case PHY_INTERFACE_MODE_MII: + break; + case PHY_INTERFACE_MODE_RMII: + ephy_config |= AC300_EPHY_RMII_SEL; + break; + default: + return dev_err_probe(dev, -EINVAL, + "unsupported PHY mode %s\n", + phy_modes(interface)); + } + + priv->control.power_on = ac300_ephy_ctl_power_on; + priv->control.power_off = ac300_ephy_ctl_power_off; + priv->control.set_led_outputs = ac300_ephy_ctl_set_led_outputs; + priv->control.set_led_polarity = ac300_ephy_ctl_set_led_polarity; + priv->control.interface = interface; + priv->ephy_config = ephy_config; + priv->led_io_enable = AC300_LED_IO_ENABLE_MASK; + mdiodev_set_drvdata(mdiodev, &priv->control); + + ret = ac300_ephy_ctl_power_on(&priv->control, + ac300_ephy_ctl_link_addr(priv)); + if (ret) + goto err_disable; + + sys_control = mdiodev_read(mdiodev, AC300_SYS_CONTROL_REG); + if (sys_control < 0) { + ret = sys_control; + goto err_disable; + } + package_status = FIELD_GET(AC300_PACKAGE_STATUS_MASK, sys_control); + + mask_version = mdiodev_read(mdiodev, AC300_MASK_VERSION_REG); + if (mask_version < 0) { + ret = mask_version; + goto err_disable; + } + + dev_info(dev, "chip version %u, mask version %u, package %#x, %s supplies, PHY %u, %lu Hz clock\n", + (unsigned int)FIELD_GET(AC300_CHIP_VERSION_MASK, sys_control), + (unsigned int)FIELD_GET(AC300_MASK_VERSION_MASK, mask_version), + package_status, + package_status & AC300_PACKAGE_POR_INTERNAL_DLDO ? + "POR/internal DLDO" : "reset pin/external VDD", + ac300_ephy_ctl_link_addr(priv), clk_rate); + + return 0; + +err_disable: + ac300_ephy_ctl_power_off(&priv->control); + return ret; +} + +static void ac300_ephy_ctl_remove(struct mdio_device *mdiodev) +{ + struct acx00_ephy_control *control = mdiodev_get_drvdata(mdiodev); + + control->power_off(control); +} + +static const struct of_device_id ac300_ephy_ctl_of_match[] = { + { .compatible = "x-powers,ac300-ephy-ctl" }, + { } +}; +MODULE_DEVICE_TABLE(of, ac300_ephy_ctl_of_match); + +static struct mdio_driver ac300_ephy_ctl_driver = { + .probe = ac300_ephy_ctl_probe, + .remove = ac300_ephy_ctl_remove, + .shutdown = ac300_ephy_ctl_remove, + .mdiodrv.driver = { + .name = "ac300-ephy-ctl", + .of_match_table = ac300_ephy_ctl_of_match, + }, +}; + +mdio_module_driver(ac300_ephy_ctl_driver); + +MODULE_AUTHOR("James Hilliard "); +MODULE_DESCRIPTION("X-Powers AC300 Ethernet PHY control driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/xpowers-acx00.h b/drivers/net/phy/xpowers-acx00.h index 8cf6fe616137..8ed15bc4eed5 100644 --- a/drivers/net/phy/xpowers-acx00.h +++ b/drivers/net/phy/xpowers-acx00.h @@ -4,6 +4,8 @@ #include +#define AC300_EPHY_CONTROL_ADDR_OFFSET 16 + enum acx00_ephy_led { ACX00_EPHY_LED_LINK_ACTIVITY, ACX00_EPHY_LED_SPEED, From patchwork Mon Aug 3 05:14:23 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2896 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id 0F97C1C057E for ; Mon, 3 Aug 2026 07:18:18 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-24924-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-24924-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id BB2023017B8B for ; Mon, 3 Aug 2026 05:16:49 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id DC4F13A1684; Mon, 3 Aug 2026 05:15:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="n9VvLMbP" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f46.google.com (mail-ot1-f46.google.com [209.85.210.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC85439CCF3 for ; Mon, 3 Aug 2026 05:15:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734146; cv=none; b=hULTl3OVJR1k+sSgJkpkKNoCAl50VJnrnoQ6BlfRP9eX4bcjeAA54mXPc05eKeZDJy/9KqHKk7UDLZGNTmwOyZx+mBcmufxnZn46gfvZcAObv7fvbmKz1t52a53Tz/4U3ISaUPT9pg/cFNlK5KWpZo4+0GCfd6JVGZqMihYtu7s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734146; c=relaxed/simple; bh=DTn/pnAwjoqAyUd80mDT7MV7oTEK5ffPq/Jme8VHnRg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gMnoJxRxw+INq0bX5n0heVWQeBg90WDvwvUW/F0xfC2Shb6RngSYnyVggcMd6fK3AIlfT8si79D2DuGBwk2YVn9DVOvaTJe4jbogkuOID0edS+oBJY9b/QJw5rFv/vpyzYy04B1soM72l/j4IA01UhlTKiFgonPeRI3b3KRyhjc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=n9VvLMbP; arc=none smtp.client-ip=209.85.210.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f46.google.com with SMTP id 46e09a7af769-7e9f69ee6f4so2714704a34.2 for ; Sun, 02 Aug 2026 22:15:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734142; x=1786338942; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Jidbxiox7dX03nOKASiwvW/wC69oSzUN52btxDpp97E=; b=n9VvLMbPpOGNZIIatWvSqH4lmcFFwoD//DyvycwNGgJGT6s60+kmR816GoBd6ZFEii nvT1ofILfwkwE5gB5qegrLjU6Lw74IXeNiEOL+m4zufMqrT+fCNw9YMOytB+nQFB+znu QJPGO+Oa/W/QzpQNoXyVCXsy5fWNRvJ3A4aKAc7IdZ2Lts40KnfycsvwCVYCQM/2TBJv o7gOHRNdrtDhvQ/OGiy86RugRpvCs7dBzy7BzZ8wvmAANf88970rf8qFvqBkEkYhp1B9 ynUm8qp2OTCJ5D6h2wWllSbdNnFHUdU7gWzFLsoXNW65oHd0ZlI32j5XujM4rCPn/2HG b+xw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734142; x=1786338942; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Jidbxiox7dX03nOKASiwvW/wC69oSzUN52btxDpp97E=; b=as7VrXkbKsrmMSbdMSLlKR4j6RPpMEd2Xn12WNl1k9ZI7frDIVA9+a+f9pO7X53MgY 3JmvZOh3CqUYDXwr1lnUP1FQ1F9d+0lyIqEmeuu8bEXWQ2d74J0Ak7Nfo17fmyAO7iQI EbaMggrQfRbXwgx7xMDgzsQLApgdE4PQCVjjDzIgNTgrfYk3wPojXfsGGNZq+qHFx6ae gad0frusAuhl9qEDygLL7zkWy8pDzHk8O6tpUKI/GMqqWUiHdHl9OICJ6lTXw/UD7XBP 5TtRIjfyQ0jiLFOYI/D8qbXUtUxhGQEIII0M+OvpUR912HO3QjP9kkTNuRtPXG2XGHWk FjgA== X-Forwarded-Encrypted: i=1; AHgh+RrZiT4mY/SDUgnDXlbGe60i4emuGMjIRDNYUHFtawr5Edwy8JW5ZfJrJ5UNn5xL51IB6okJBi/+d+d4QQ==@lists.linux.dev X-Gm-Message-State: AOJu0YxoHkhDA0B46/1lEbh9vnkFOFs55jHfNAhXO1O/lkwl+XlDraAa sN0CWhDGhDZPcqMiN3Y2sc7E4URQBi5yxlVdQl0vYUihu0MNuez1gln1 X-Gm-Gg: AR+sD11VmkYe/WmYaV0QId9nFcH4m1kD0IdK5op0Dzi1e7LsMUAwzppJ6evMZrhmPp/ KSVPuUchZuZWOL/VydBB3sShH3cA2IwnWLIQZlAk1pc5EjibZEy5uYDeMbSk0yvXY1KRwHQ9kr9 tC+HGbStqLque6GlUMXW0ztqyvutbLlFLD8JIOeLV5S66Bm2heuxHcGxVVBGw7Dc0pV5RxPknme gNfPvx+ZdnJLPzj2XZhMnUtcqYidXy8CDhkCznGxxxgUF3kcEt8OS204mQhFhPd322guD6ttRjN 79egG61UxRLHHy5bOSiBPXsyImmD8ppVXMJ2CwYiMTNyhGjKaBCFntjGywH0QF/suIih1uUJt+W kEEj1QraLWqXrCTUkwtW4x62eIWzanX3jEED+zNh9iqhLkJYxr0vTnLWPXl+UioWWqEjaf4/7xh 3xlK1nFiDselLyESvQPumNggsyfOmejQovRnRcMz2FgQdZSzSHgHwERSnNAsmMHM6god0smeEls sW3nmtAjRT+fEgzy7vp9pKDuPLz2/PJFGOSIgg2TmKwQ1V4Ox4sqNpk8ld4FuNvJVlH0Wh/Tubq 3Befnvhyxobsk62Hv6iX5MnsXNUTwNsUsEzVN+zUP5Lm7nVJmRzzGXH7eWUOGdJ5rQUFygqHe+L Hoksdmpxl468/51pg X-Received: by 2002:a05:6830:411d:b0:7d9:f50f:9691 with SMTP id 46e09a7af769-7f1968c88e1mr15370101a34.0.1785734141726; Sun, 02 Aug 2026 22:15:41 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:40 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:23 -0600 Subject: [PATCH 13/21] dt-bindings: net: x-powers: add AC200/AC300 EPHY Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-13-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= AC200 and AC300 companion ICs contain compatible Fast Ethernet link-PHY implementations which report the same PHY ID but use different control interfaces. Describe the forced-ID link PHY and its control-device references. Fixed systems reference one already enabled control interface. A fixed AC300 system may optionally provide the configuration field for its calibration-range bit; omitting it selects the normal range. Systems which can contain either companion reference both candidates and require a logical two-bit NVMEM field for variant selection and AC300 calibration- range tuning. The link node reg value is programmed through the AC200 control interface, while AC300 requires it to match the package-strapped address. A control reference is required to distinguish this integration from other PHYs which report the same ID. Also describe the optional xMII receive-clock inversion required by some integrations. Describe the three fixed-function package LED outputs using standard PHY LED children. Their functions are link/activity, 100 Mbps speed and duplex, and their polarity is shared. Omitting the container retains the vendor fallback with all outputs active-low; an explicit container enables only the outputs it describes and may select the shared polarity. Allow a PHY with a routed interrupt to be marked as a wakeup source for magic-packet and link-change Wake-on-LAN. Signed-off-by: James Hilliard --- .../bindings/net/x-powers,acx00-ephy.yaml | 217 +++++++++++++++++++++ 1 file changed, 217 insertions(+) diff --git a/Documentation/devicetree/bindings/net/x-powers,acx00-ephy.yaml b/Documentation/devicetree/bindings/net/x-powers,acx00-ephy.yaml new file mode 100644 index 000000000000..3e01f6b44006 --- /dev/null +++ b/Documentation/devicetree/bindings/net/x-powers,acx00-ephy.yaml @@ -0,0 +1,217 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/x-powers,acx00-ephy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: X-Powers AC200 and AC300 Ethernet PHY + +maintainers: + - James Hilliard + +description: + The AC200 and AC300 contain compatible Fast Ethernet link-PHY + implementations which report the same PHY ID, but use different control + interfaces. Systems with a fixed companion IC describe one control + interface, which must already be enabled. A fixed AC300 system may provide + an NVMEM configuration field to select its calibration range; omitting the + field selects the normal range. Systems that can contain either companion IC + describe both control interfaces and require the field to select the + matching one before the PHY identification registers are accessible. In + that dual-control topology, the AC200 I2C controller and AC300 control + device may use status "fail-needs-probe" so the selected one can be enabled + dynamically. The PHY node's reg value is programmed through the AC200 + control interface. For AC300, it must match the address selected by the + package straps. + +select: + properties: + compatible: + contains: + const: ethernet-phy-id0044.1400 + required: + - compatible + anyOf: + - required: + - x-powers,ac200-control + - required: + - x-powers,ac300-control + +properties: + compatible: + const: ethernet-phy-id0044.1400 + + nvmem-cells: + maxItems: 1 + description: + Logical SoC SID field whose bit 0 selects the AC300 control interface in + a dual-control topology and whose bit 1 selects its low-calibration + tuning sequence. + + nvmem-cell-names: + description: + In a dual-control topology the configuration field uses bit 0 to select + AC200 (zero) or AC300 (one). Bit 1 selects the AC300 vendor sequence for + a low-level calibration value in both dual and fixed AC300 topologies. + const: configuration + + x-powers,ac200-control: + $ref: /schemas/types.yaml#/definitions/phandle + description: Reference to the AC200 Ethernet PHY control function + + x-powers,ac300-control: + $ref: /schemas/types.yaml#/definitions/phandle + description: Reference to the AC300 MDIO Ethernet PHY control device + + x-powers,xmii-rx-clock-inverted: + type: boolean + description: + Invert the xMII receive clock inside the PHY. This is required by some + SoC integrations, including the Allwinner H6 AC200 connection. + + wakeup-source: + $ref: /schemas/types.yaml#/definitions/flag + description: + Indicates that the PHY interrupt is routed to a wake-capable interrupt + controller and may be used for magic-packet or link-change Wake-on-LAN. + + leds: + type: object + description: | + Package LED outputs. Output 0 indicates link and flashes for transmit or + receive activity, output 1 indicates a 100 Mbps link, and output 2 + indicates full duplex and flashes on a half-duplex collision. The + polarity setting is shared by all outputs, so active-high or active-low + declarations on different children must agree. Without an leds + container, all three outputs are enabled active-low to match the vendor + initialization. An explicit container replaces that fallback: only + outputs described by available child nodes are enabled, with active-low + used when no child specifies a polarity. + + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + patternProperties: + '^led@[0-2]$': + type: object + $ref: /schemas/leds/common.yaml# + + properties: + reg: + enum: [0, 1, 2] + + inactive-high-impedance: false + + required: + - reg + + unevaluatedProperties: false + + additionalProperties: false + +required: + - compatible + +oneOf: + - properties: + nvmem-cells: false + nvmem-cell-names: false + x-powers,ac300-control: false + required: + - x-powers,ac200-control + - properties: + x-powers,ac200-control: false + required: + - x-powers,ac300-control + - required: + - nvmem-cells + - nvmem-cell-names + - x-powers,ac200-control + - x-powers,ac300-control + +dependentRequired: + nvmem-cells: [ nvmem-cell-names ] + nvmem-cell-names: [ nvmem-cells ] + +allOf: + - $ref: ethernet-phy.yaml# + - if: + required: + - x-powers,ac300-control + then: + properties: + reg: + maximum: 7 + +unevaluatedProperties: false + +examples: + - | + #include + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@0 { + compatible = "ethernet-phy-id0044.1400"; + reg = <0>; + nvmem-cells = <&ephy_config>; + nvmem-cell-names = "configuration"; + x-powers,ac300-control = <&ac300_ephy_ctl>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_LAN; + active-low; + default-state = "keep"; + }; + + led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + active-low; + default-state = "keep"; + }; + }; + }; + }; + + - | + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@0 { + compatible = "ethernet-phy-id0044.1400"; + reg = <0>; + x-powers,ac200-control = <&ac200_ephy_ctl>; + }; + }; + + - | + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@0 { + compatible = "ethernet-phy-id0044.1400"; + reg = <0>; + nvmem-cells = <&ephy_config>; + nvmem-cell-names = "configuration"; + x-powers,ac200-control = <&ac200_ephy_ctl>; + x-powers,ac300-control = <&ac300_ephy_ctl>; + }; + }; +... From patchwork Mon Aug 3 05:14:24 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2897 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id 582A41C0583 for ; Mon, 3 Aug 2026 07:18:34 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-24925-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-24925-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id DC46B301ABB6 for ; Mon, 3 Aug 2026 05:16:55 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7C0FC397341; Mon, 3 Aug 2026 05:15:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nueuBIvO" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f49.google.com (mail-ot1-f49.google.com [209.85.210.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B647D39DBC5 for ; Mon, 3 Aug 2026 05:15:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734147; cv=none; b=C75Mwc1+2NH+m0RY7ZLxpaZo5Sq4VqasQrvK653CIsoTUVK5oknop7m4dEFcmKNVZE0y5V/JDcj2IeiqR8q75+lxoPARjqTl+mKErVcGmoSIJsaz/nt+6FrB1SABcf6Lcu/yeBDki3ObHEzLZz5q6FDlGglHC8lTgx5tnFBam58= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734147; c=relaxed/simple; bh=z1D09xijThRsRnsDX/ozKwmhi7sR7kyQDCuYiAXqUqg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YGkVLxubUw2TqM2Cw+wlHNTYFcYjI3zNxxXn97NG5AEvbzV64rntS+mAIc6HESnnf5f3e4hwSRcN+1HiKrJh9Au9wwGBGKk0Yj/ZVN7nY5+Svvr6T45JOLNor59A8VPscm7Bjlgm3+X7z1u49NIhYAMRGIeCD7/ZCerzEnfpJu8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nueuBIvO; arc=none smtp.client-ip=209.85.210.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f49.google.com with SMTP id 46e09a7af769-7eb61bbeb25so2152011a34.1 for ; Sun, 02 Aug 2026 22:15:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734143; x=1786338943; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=S/5/uq1wl03WMsz5ualIqMKCury9OUeuYtebMNsXO2w=; b=nueuBIvOgLEPeqQ3Vt0Q6TBxQfOd4bZQGdc7ZKku/U9WOmMRW5ZFTwC2/CeyYDUArV BfLgfw6oiwMUNaHyUMV8tMsLZV9FWKJpjcVOi9FwRA9OJ4gNbVFDCpKmPFoG806NN9zF yW1LECQqC3MN3feRj9Nees/AhCFXwug0PVz3Xy4Q5MC2oYCQ0Iqgt2JMvkSA1kMzQa2h bvDrLJ5Rpl8lWGlcco32H9srHsiz4rKccm8xQ3V2q6O6oDfVfCkNJ6025GymuCimtAjS LLcg1j/7qnRFSBP2j9ZVpp/bQbiGim58yoNY5qY7zP5Mlrh5XqkEhnU64JfjhsLpH1Dg NnlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734143; x=1786338943; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=S/5/uq1wl03WMsz5ualIqMKCury9OUeuYtebMNsXO2w=; b=gkYmRrsvMJk/0zQNJ/eUkVKFuTewPqilRc/DTdsL09EyD75YUmeFXw0xkpMaCJQTap NXkH1wQuTnBHqPmzl2wrTYfTvczUswsDDZ1idZp8rRAU+MkyJUsukhx86VGaKNqPXDem YTnBkcyfDaG0ONU8O6NyqBIpn3lRcqrIkWkY9hTNTWNAZs9Eq3NdMSBEI5SDu1lnmIxI Go0A+5+7HsPWRTUw/wW/9YN3skZzm+KndnxAROJYDgnDQGIavHAatotQAyiJJRCKOHfy iehev6En9xraReUZssyaOi4ppx1nmZjbT/2P0xS1IuvcEyXIAoBuecb+2JIwWZomQQHi PpMw== X-Forwarded-Encrypted: i=1; AHgh+Rqy3D4BbcZCNo76ojioY4wLf7jtzpHHHm8S6JegMSSN4u7wXuqai03Pw2T5XYhawPPKeYTnFxhFityCKg==@lists.linux.dev X-Gm-Message-State: AOJu0Ywp1MuxIZIAH0/YcZQbMjTcdpF0oOkAWzOefXeqWq5xbCvYleEa X2HoY08vNLiqgCqA7aj1xnNfVq8j3DXZzmgmKCXmDmkk0/ptX2XXZTbU X-Gm-Gg: AR+sD10tFn+InCE9e0aOButJg9ua3HkB3/xXWQ9fqAVcHIvO0DLuoqoDBVeGzb3tdfS yhLN9BqBZb99YuS1oxh+9ALDDc71zOAw85IYeFyFLbfWe53Nr7qX4TJmq033U6yaBmc7eV5YK4k vxf0MzMLIskWKaaqiJspWjL0c7f34H6+WQtFTbB8WGt3wLXMx7fRdHOngNWM7o7/Z7PuSQ0qtvu rs4T2WH7CCeNJUiW1NvSOTEM1ARDNXayhANkZwYEUZWt7OWZ402MZxbJyY5FVm0uExfu3A0AMMp Tn50bG2EmgfqosJdqv7M4zClf0nJgF0N5FHaulZxiV1n5v/5xVhBUFM4tAkRp/r9enV9JrWEage KpooqZ9PCcX8OiTMe5RsUfWDC5mMVzB3a3rlkI//iFPBrAhh73sOgj+UGufsLQ3yN4zRc0VATEf El+xThTpbXaRX54i8DY3FZDfAoxuQOR+w0/DpKRJl1qf7M/jSAekiDRtG19LFgMK1xYcLxil7+X S+5PLPekoEh868r6VZpitq09eoSbCLtN/9nzEEbpWtXbcsBgvOuupoBnbfBsw4Yu0UYh9W6V55R J9v+UaFnete4S0GCJcjmoYE1nLQCDc52Luip8r9cNNJhG8osJ22g0J/MVwspclEQ8hixLX7iHyJ b2SSYrz/lk0D0I1EV X-Received: by 2002:a05:6830:4114:b0:7e9:bd00:c6ad with SMTP id 46e09a7af769-7f196f29291mr14805744a34.16.1785734143562; Sun, 02 Aug 2026 22:15:43 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:42 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:24 -0600 Subject: [PATCH 14/21] net: phy: support configuring PHY-autonomous Tx LPI Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-14-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The ethtool Tx LPI fields currently update phylib software state and notify an attached MAC, but they do not configure PHYs which generate LPI autonomously. This can make a successful ethtool request leave the PHY hardware unchanged. Add a PHY driver callback for applying the Tx LPI enable state and timer. Call it before updating EEE advertisement, and attempt to restore the old hardware state if either the callback itself or the advertisement update fails. Use the callback to disable autonomous LPI when phy_support_eee() hands LPI control to the MAC, and reapply that state after PHY reset. Drivers without the new callback retain the existing behavior in which the Tx LPI fields configure phylib and the attached MAC. Existing drivers which only implement disable_autonomous_eee() therefore need no changes. Signed-off-by: James Hilliard --- drivers/net/phy/phy.c | 35 +++++++++++++++++++++++++++++++++-- drivers/net/phy/phy_device.c | 25 ++++++++++++++++++++----- include/linux/phy.h | 18 ++++++++++++++++++ 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index fce9bc7be330..c76d5baa1f84 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -1996,6 +1996,8 @@ static void phy_ethtool_set_eee_noneg(struct phy_device *phydev, int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data) { struct eee_config old_cfg; + bool tx_lpi_cfg_attempted = false; + bool tx_lpi_cfg_changed; int ret; if (!phydev->drv) @@ -2005,16 +2007,45 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data) old_cfg = phydev->eee_cfg; eee_to_eeecfg(&phydev->eee_cfg, data); + tx_lpi_cfg_changed = phydev->eee_cfg.tx_lpi_enabled != + old_cfg.tx_lpi_enabled || + phydev->eee_cfg.tx_lpi_timer != + old_cfg.tx_lpi_timer; + + if (tx_lpi_cfg_changed && !phydev->autonomous_eee_disabled && + phydev->drv->set_tx_lpi) { + ret = phydev->drv->set_tx_lpi(phydev, &phydev->eee_cfg); + tx_lpi_cfg_attempted = true; + if (ret) + goto restore_tx_lpi; + } ret = genphy_c45_ethtool_set_eee(phydev, data); if (ret == 0) phy_ethtool_set_eee_noneg(phydev, &old_cfg); else if (ret < 0) - phydev->eee_cfg = old_cfg; + goto restore_tx_lpi; mutex_unlock(&phydev->lock); - return ret < 0 ? ret : 0; + return 0; + +restore_tx_lpi: + if (tx_lpi_cfg_attempted) { + int rollback_ret; + + rollback_ret = phydev->drv->set_tx_lpi(phydev, &old_cfg); + if (rollback_ret) + phydev_warn(phydev, + "Failed to restore autonomous Tx LPI: %pe\n", + ERR_PTR(rollback_ret)); + } + + phydev->eee_cfg = old_cfg; + + mutex_unlock(&phydev->lock); + + return ret; } EXPORT_SYMBOL(phy_ethtool_set_eee); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index f7472a743185..30929b0354b6 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1357,6 +1357,21 @@ static int phy_poll_reset(struct phy_device *phydev) return 0; } +static int phy_disable_autonomous_tx_lpi(struct phy_device *phydev) +{ + struct eee_config config = phydev->eee_cfg; + + if (phydev->drv->set_tx_lpi) { + config.tx_lpi_enabled = false; + return phydev->drv->set_tx_lpi(phydev, &config); + } + + if (phydev->drv->disable_autonomous_eee) + return phydev->drv->disable_autonomous_eee(phydev); + + return 0; +} + int phy_init_hw(struct phy_device *phydev) { int ret = 0; @@ -1395,9 +1410,8 @@ int phy_init_hw(struct phy_device *phydev) } /* Re-apply autonomous EEE disable after soft reset */ - if (phydev->autonomous_eee_disabled && - phydev->drv->disable_autonomous_eee) { - ret = phydev->drv->disable_autonomous_eee(phydev); + if (phydev->autonomous_eee_disabled) { + ret = phy_disable_autonomous_tx_lpi(phydev); if (ret) return ret; } @@ -2973,8 +2987,9 @@ void phy_support_eee(struct phy_device *phydev) * manage LPI signaling instead. The flag is stored so it can be * re-applied after a PHY soft reset (e.g. suspend/resume). */ - if (phydev->drv && phydev->drv->disable_autonomous_eee) { - int ret = phydev->drv->disable_autonomous_eee(phydev); + if (phydev->drv && (phydev->drv->set_tx_lpi || + phydev->drv->disable_autonomous_eee)) { + int ret = phy_disable_autonomous_tx_lpi(phydev); if (ret) phydev_warn(phydev, "Failed to disable autonomous EEE: %pe\n", diff --git a/include/linux/phy.h b/include/linux/phy.h index 2eba54e068f6..55053b914144 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1391,6 +1391,24 @@ struct phy_driver { */ int (*disable_autonomous_eee)(struct phy_device *dev); + /** + * @set_tx_lpi: Configure PHY-autonomous Tx LPI + * @dev: PHY device to configure + * @config: Requested Tx LPI enable state and idle timer + * + * The presence of this callback advertises that the driver supports + * configuring PHY-autonomous LPI through the ethtool EEE Tx LPI fields. + * It is not used for userspace configuration after phylib has handed LPI + * control to the MAC. Drivers without this callback retain the legacy + * behavior in which those fields only configure phylib and the attached + * MAC. A request with Tx LPI disabled must be accepted regardless of the + * timer, since the timer has no meaning while the transmitter is disabled. + * + * Return: 0 on success, negative errno on failure. + */ + int (*set_tx_lpi)(struct phy_device *dev, + const struct eee_config *config); + /* Get and Set PHY tunables */ /** @get_tunable: Return the value of a tunable */ int (*get_tunable)(struct phy_device *dev, From patchwork Mon Aug 3 05:14:25 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2905 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id B33B21C0575 for ; Mon, 3 Aug 2026 07:23:01 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24926-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24926-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 99BE730C149C for ; Mon, 3 Aug 2026 05:17:07 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CFC7A395AFE; Mon, 3 Aug 2026 05:15:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gAWIJngv" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f47.google.com (mail-ot1-f47.google.com [209.85.210.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F05739FCD8 for ; Mon, 3 Aug 2026 05:15:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734148; cv=none; b=bhKqX4GlGskwmxVYfvR88yEg8mgTEuo7CC4uKBbaD0UQrjerm71gd1HbtSoDSP8ozQ4URzLh8fVW8CcD6EJgkanMJXsKHtPwSeL4oH68BMD6PDU5bncgqmiLj/cBqcSqjid05r3n9kxdMzHwWREypw3vWTk+m/q2zAQPEPlmWzY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734148; c=relaxed/simple; bh=okw70boujGKEoFWervTiqut+PCDZlczcehiMArR7er0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=M/709UOQPlpD5HCu6Ik7XROiZd9+ilfbuSpYzukRfw+mtAL0J5wzo52QoExp2K+fCXMlRkviOJWmq52OlvEr5Uk7PFCQBqHvGCxhC9trBXO954gbK5ZUaYQmi1UUnQYwO/WbC+SKuzKHhMy0U7Hn+Z96p5WbRyiF2GXwEcwq1Iw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=gAWIJngv; arc=none smtp.client-ip=209.85.210.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f47.google.com with SMTP id 46e09a7af769-7e9fc3de7ceso1363076a34.1 for ; Sun, 02 Aug 2026 22:15:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734145; x=1786338945; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=GBn8+Hx956XQS2N8rfelEGrUn9IDXjKs/rR491vlUQk=; b=gAWIJngvah2ho6bMT011F9CQ6T6fBgWr5ua8qRv1Fzz+wtujkRD1j4L6iw1ayMyxa1 uN2+XH4LGsPbEIVoNeVe/A5ioCd6ffKMx4A23XEVx2WymVzE3AcdqZSytCbdNPjJAn0V W96W0TL9tHTz5cwFhggNrFviMlbjSFHC649MP5CYspbGppnO1yeHIoIavs7KXOMTOfHG ulYkc1Og58Pvqt+klF94drZtas7Kbkq7FjI10JTPISZQNIkja8cHxMje8zjV0zn+xsch GWDiAcyL21xus7a03JeRfsl9nVXF1S4voHicGdXW9zcFSk//zSMuJfK/Ao52PtxjhsRG aisQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734145; x=1786338945; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=GBn8+Hx956XQS2N8rfelEGrUn9IDXjKs/rR491vlUQk=; b=tJwecJsas3tPCaRmKA4ctiJg/b11CQDPQ4qHxJYVrJ9MXCx4HGsTJNTLEHl6tgKUfq 7fSaMEnv3KnJBKBn5sF/DWMCVND7s+Cd/zXQTgQCC/vY+t4wo2BBHYdbDcn2hTfpQnVT twA2Vgj5nnMYHtE0mIPg81mwcVaooVarjWQQib1xr5xhBN6j7RWfZ7ORAj9Kd/HsfzC4 gSrizR8+fkBPMmnysfi40/LyzSugDRXSAajoRjanBwaBt94fP9Le6cCHqMimbPL4M66t Guewf8upFsh9fbyNOespy+zykOPhb5hr40BqYc60EHZ0rWlRMPf2PvmqZDylG2+mtROc /Lkg== X-Forwarded-Encrypted: i=1; AHgh+RqvZcoPNK9H6BImuDT2/EcIjKygYKNl1SWDQPpSK4fKKTFgkCgrhcYICKl16C8eF3w4lNQs5pINU0RjfA==@lists.linux.dev X-Gm-Message-State: AOJu0YyA+bdjMYuw+FY2D88Q6FsPjr5VGGXgRpORoYAqSZV3Fc8oaO4V X/82g9LpQC6HBzQUTOH0auFmlpaZRFg3vf6uWMaIGA647ke3ki6ueQL5 X-Gm-Gg: AR+sD107ZmyYjV+OvMAL7m29tygtxr0y9KuI/DoA2NXLrwflrDPKwOVTkrCO9+liVD6 XwsApmwA7i2xF4a0GwWjIYAUglq+J+/hV8ppT8+teXdaIo25g9b4USVUKi+wLKMRlPDDmB/O0fQ AX1Ow8SxCTfaVRpTvekf/Sduyn6uIoxNAasfFeJWES/rst+KN94rVaSoZHOerojbTSoEIpCRAFe ZUWx5WGq+7tYdl3a0awSTL/xGgvLs3IDkoVD5IMeNtPLptS26PrBMS483W+7kYW5TrXLoJrbCHK RbD1uow4qU8PFm++p9hDnogRPhfgtu5KTTF36YewRgBaMWVFsXaaRbNjMh+FCB0l28NMvBkpYpo 3BRgEbAzqlXmhKl76CyKkbjOcbAZaKf6GVS68Kh0PpiLTnT4MTgiB4XxDsfZXaCFitM71XqIsq2 ZbsXtNMRYO9pAZMFel9ymaIdeenAcFVyhZoIowxtbgKv2VxgPKGrMkSO1FB84MGtQ/pCyBJjGOs nwgiR19YbYw6G5mANaHOrzQCwToLbxTUB+zOCmvIbMenmrWCehR0yLn3sFV8Xv1sUJrQk9TX5iR 2OJODGSjtB0z4d60/OlKfaiG7H7gtpXl0MhYlXcz4zfmtJDz7VgjV4oR6/02u1sb56YoQUOAt3T 5aANneULzrTo8Ub8whg== X-Received: by 2002:a05:6830:f95:b0:7dc:4947:36a1 with SMTP id 46e09a7af769-7f19714f993mr12573380a34.12.1785734145466; Sun, 02 Aug 2026 22:15:45 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:44 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:25 -0600 Subject: [PATCH 15/21] net: phylink: allow PHY-autonomous EEE without MAC LPI Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-15-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Phylink treats a MAC which implements its LPI operations but advertises no LPI capability as incapable of EEE. It disables PHY EEE during attach and rejects ethtool EEE requests. The same problem occurs when the MAC supports LPI on another interface but not on the interface currently connected to the PHY. Both cases are incorrect when the attached PHY can generate LPI autonomously without help from the MAC. Recognize the PHY autonomous-EEE capability, preserve its EEE advertisement, and allow ethtool EEE requests in that configuration. Evaluate MAC LPI support for the active interface, and restrict EEE modes to the MAC capability mask only when the MAC actually manages LPI. Signed-off-by: James Hilliard --- drivers/net/phy/phylink.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 18d2ead97aa5..e64f72793aa0 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1512,6 +1512,19 @@ static void phylink_deactivate_lpi(struct phylink *pl) } } +static bool phylink_phy_supports_autonomous_eee(struct phy_device *phy) +{ + return phy && phy->drv && phy->drv->set_tx_lpi; +} + +static bool +phylink_mac_supports_eee_interface(struct phylink *pl, + phy_interface_t interface) +{ + return pl->mac_supports_eee && + test_bit(interface, pl->config->lpi_interfaces); +} + static void phylink_activate_lpi(struct phylink *pl) { int err; @@ -2090,6 +2103,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, { struct phylink_link_state config; __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); + bool mac_eee; char *irq_str; int ret; @@ -2106,6 +2120,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, linkmode_copy(supported, phy->supported); linkmode_copy(config.advertising, phy->advertising); config.interface = interface; + mac_eee = phylink_mac_supports_eee_interface(pl, interface); ret = phylink_validate_phy(pl, phy, supported, &config); if (ret) { @@ -2144,7 +2159,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, /* If the MAC supports phylink managed EEE, restrict the EEE * advertisement according to the MAC's LPI capabilities. */ - if (pl->mac_supports_eee) { + if (mac_eee) { /* If EEE is enabled, then we need to call phy_support_eee() * to ensure that the advertising mask is appropriately set. * This also enables EEE at the PHY. @@ -2165,7 +2180,8 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, */ linkmode_and(phy->advertising_eee, phy->advertising_eee, pl->supported_lpi); - } else if (pl->mac_supports_eee_ops) { + } else if (pl->mac_supports_eee_ops && + !phylink_phy_supports_autonomous_eee(phy)) { /* MAC supports phylink EEE, but wants EEE always disabled. */ phy_disable_eee(phy); } @@ -3300,17 +3316,20 @@ EXPORT_SYMBOL_GPL(phylink_get_eee_err); */ int phylink_ethtool_get_eee(struct phylink *pl, struct ethtool_keee *eee) { + bool mac_eee; int ret = -EOPNOTSUPP; ASSERT_RTNL(); + mac_eee = phylink_mac_supports_eee_interface(pl, pl->cur_interface); - if (pl->mac_supports_eee_ops && !pl->mac_supports_eee) + if (pl->mac_supports_eee_ops && !mac_eee && + !phylink_phy_supports_autonomous_eee(pl->phydev)) return ret; if (pl->phydev) { ret = phy_ethtool_get_eee(pl->phydev, eee); /* Restrict supported linkmode mask */ - if (ret == 0 && pl->mac_supports_eee_ops) + if (ret == 0 && mac_eee) linkmode_and(eee->supported, eee->supported, pl->supported_lpi); } @@ -3326,10 +3345,11 @@ EXPORT_SYMBOL_GPL(phylink_ethtool_get_eee); */ int phylink_ethtool_set_eee(struct phylink *pl, struct ethtool_keee *eee) { - bool mac_eee = pl->mac_supports_eee; + bool mac_eee; int ret = -EOPNOTSUPP; ASSERT_RTNL(); + mac_eee = phylink_mac_supports_eee_interface(pl, pl->cur_interface); phylink_dbg(pl, "mac %s phylink EEE%s, adv %*pbl, LPI%s timer %uus\n", mac_eee ? "supports" : "does not support", @@ -3337,12 +3357,13 @@ int phylink_ethtool_set_eee(struct phylink *pl, struct ethtool_keee *eee) __ETHTOOL_LINK_MODE_MASK_NBITS, eee->advertised, eee->tx_lpi_enabled ? " enabled" : "", eee->tx_lpi_timer); - if (pl->mac_supports_eee_ops && !mac_eee) + if (pl->mac_supports_eee_ops && !mac_eee && + !phylink_phy_supports_autonomous_eee(pl->phydev)) return ret; if (pl->phydev) { /* Restrict advertisement mask */ - if (pl->mac_supports_eee_ops) + if (mac_eee) linkmode_and(eee->advertised, eee->advertised, pl->supported_lpi); ret = phy_ethtool_set_eee(pl->phydev, eee); From patchwork Mon Aug 3 05:14:26 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2903 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4]) by mxe881.netcup.net (Postfix) with ESMTPS id 02A831C0244 for ; Mon, 3 Aug 2026 07:22:15 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 104.64.211.4) smtp.mailfrom=linux-sunxi+bounces-24928-noreply=patchwork.local@lists.linux.dev smtp.helo=sin.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 104.64.211.4 as permitted sender) client-ip=104.64.211.4; envelope-from=linux-sunxi+bounces-24928-noreply=patchwork.local@lists.linux.dev; helo=sin.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sin.lore.kernel.org (Postfix) with ESMTP id 79B9A3038AD3 for ; Mon, 3 Aug 2026 05:17:37 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 915C73A7586; Mon, 3 Aug 2026 05:15:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="pRMG/R4o" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f44.google.com (mail-ot1-f44.google.com [209.85.210.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C475F3A5E65 for ; Mon, 3 Aug 2026 05:15:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734154; cv=none; b=Wchln0TbQ0cIcn25rJgb3lSUhwjunznwyvS2QKyrlif3RRt8fLiytsEjMPhfCLzh6wvtCsShbXGCiEi20Wyrb6gbEuGiHCjKuTuOiKo3F8x227p0O2i7Cbz7TyzbW9KdJmfFl1hq8fNcie8YWZ1pYo4UZJEtovlOJWSTuwWvPu8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734154; c=relaxed/simple; bh=bnher73HZdEx/bFsEwg8sn4H6jH4c9JplUY8GfqkPZg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Sj8TQKmsOeQo9lZwgna6rc6PRLksO0+yjoExiuSdor8/ty2UveAfAC0P9p3zb2zi/9Bm58GEC4ZvrNN8+SvVpgVYI9qz7XyFPie/C1hO/AY2EyZu1j1hymePGRlmXEMp1k3XiLbsEngfqAVcYdhD8WqXyAj8Ho+xlm+4ARGXpIE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=pRMG/R4o; arc=none smtp.client-ip=209.85.210.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f44.google.com with SMTP id 46e09a7af769-7e6b554044fso2627351a34.0 for ; Sun, 02 Aug 2026 22:15:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734149; x=1786338949; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=9HocqQSvZ/shIczHi/ecOhIrdfwufvBQyfBRX301nvk=; b=pRMG/R4o921cFNxHOAlRL4J6ZJG0FjOq67DB46tNAAf13q2YRwNqfLqT/z4G5AgZlq hgCbYUz8xvRDJs5wvAmJL+vbFxlKqaGfqf8akmNBmwFg86gaOUjqDyMwAh7dCTJRikxB vNiCVV5TonbMgw4W93zhoG8al4STjAU7Q3Fyk51FdluKZyoF/VMQzskVa4lKfMRW+8JQ d816Zy/pqwokd4OFUOYRMzQ3VP9jz1IKfld+ehtVxyefDvLg3VT1nDb6c4BGy/AIvu7v +ovyVR0n2+SskyOrgFTL0P3m3zeiLErInaoEfqXf/TeaPMnMn1VuoPJZdtK3z4Rd0aiL 3UQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734149; x=1786338949; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=9HocqQSvZ/shIczHi/ecOhIrdfwufvBQyfBRX301nvk=; b=Yyf1e+hmXhhFWQmxYj8C+/vaLM7aS6B2Xc24QPKSpyCcihRu1NRoq6hhM0i4RuF4ZT ulc8LwVRFRVpQtqVpQ5WOmOWwTCcVX+NfgB9Da1OuAPWpeM73CI03kfj7xSW3rSdwbfV 42cGITiFvgvjkZLEbfoBPHup7qTe83tRzgulvG3PmS05zZJQQzFze/J5bvjTX/H+/6O+ KRy/gP6Y6KmUlA78cXFiteKFDcMvFourqOv9BknFIP6rdkdrxIVG2oN9w73AYthZruWb a/ygDYqr2wwc4wTspvqZufV2IPVdEVb5Xb3kIW5uaUkHPdaxv8rg/TIU9FwSMLDNvcZ0 OOxQ== X-Forwarded-Encrypted: i=1; AHgh+RpAaN4yk9QSfrShB7CO4bODQhwdNQTclvFiZ4B1ZdAGnNqanBxT9w2nBHlfJ8ujZ8kECJDV/drl6Bp9Hg==@lists.linux.dev X-Gm-Message-State: AOJu0YwPXX/MONGNsPvqX7gzDsl7v3oEg/mx02Kj7nIY+fCcZsnZZrti jGidutgaRsIhV0bY40Kqx7haSm/w9vZwAw17Ug3fViWoqbzPSpYsUOyr X-Gm-Gg: AR+sD13vv80m7c5603qr6SjKdDeufHonrBFYz2lsQc/fXbkT7jFUyJMKS1jqvL3GUhK v2Nlw28cLETjxOS2Z2OcpKqrPGit+5b/s6XVy2RvbErmcuKzqmj7TZQTNIolDdT/fOL5GRTBXOF unu+y296ciIHT6j23QeMg7/MrxhLK31OiiMJN6Yhj5bQfvqhlh6G9aOy31+J8DYzqDWn4catc00 uVZhMuIfk7VIgSnGl91aRKf9XmLlUfvUmik+4Rq44rZscm9UPth+iFuKE/c/DWt8XYytCVzOzjK GR/ii8RRARxjXWVWi2X6d8YPahtqL5ZvYNGorW4kGAX21Jv/+2aPWCm+qsrDMJ+xzFJFOMlFxZU QDJxVMZj3MaCIPpCm897/U2w74c2mIdGmgYSLm5+Oc9wbtv4i4CfOqIePNklU9sKdZveET48NGq 9U/ZBu1h17gucopZjqbqyAxYZ+QlbIDJ+DRquKmkOSg6t+p6B9X/wAOYT/J4jNK/UFH6cDu9/uJ vvB04IOURgYTc+OtJTL2LPTR4Xy+D9EnnYR+VHXKZ+Eq+GAfhcag3h1v+san5ZFgnX1Dq4Yz8dW mpes3HrSOfvzm+m8L6bBat7WWwMZX/YUiExNAC8BYtPfV8Z8gxIlJu8I6twE23Eowk7vLR0m/Uj g5A6CxFS/vDoi1Z0oeK+Vh0rl2g== X-Received: by 2002:a05:6830:3155:b0:7e6:eb9c:3781 with SMTP id 46e09a7af769-7f19701bb7dmr14624186a34.12.1785734147064; Sun, 02 Aug 2026 22:15:47 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:46 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:26 -0600 Subject: [PATCH 16/21] net: phy: add X-Powers AC200/AC300 EPHY driver Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-16-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[104.64.211.4:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; HAS_LIST_UNSUB(-0.01)[]; PRECEDENCE_BULK(0.00)[]; FROM_HAS_DN(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[sin.lore.kernel.org:rdns,sin.lore.kernel.org:helo]; TAGGED_RCPT(0.00)[netdev,dt]; FORGED_SENDER_MAILLIST(0.00)[]; FREEMAIL_CC(0.00)[vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com]; RCPT_COUNT_TWELVE(0.00)[34]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:104.64.192.0/19, country:SG]; R_SPF_ALLOW(0.00)[+ip4:104.64.211.4]; FREEMAIL_TO(0.00)[lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,arm.com,bootlin.com,foss.st.com,st.com,synopsys.com,armlinux.org.uk,sntech.de]; FREEMAIL_FROM(0.00)[gmail.com]; TO_DN_SOME(0.00)[]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; TAGGED_FROM(0.00)[bounces-24928-noreply=patchwork.local]; MIME_TRACE(0.00)[0:+]; MID_RHS_MATCH_FROM(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 02A831C0244 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= AC200 and AC300 contain compatible Fast Ethernet link-PHY implementations which report the same ID, but their identification registers are not accessible until the companion-specific control interface completes its power-up sequence. Match the ID supplied by firmware and require an X-Powers control reference because the Rockchip RK630 PHY reports the same ID. On fixed hardware, reference one already enabled control device. A fixed AC300 system may optionally read the configuration field for calibration- range tuning; its absence selects the normal range. On systems which may contain either companion, require a logical two-bit NVMEM field to select the control interface and the AC300 calibration range. Enable a selected fail-needs-probe node when CONFIG_OF_DYNAMIC is available; otherwise the same topology works when both candidate providers are already enabled. Validate that each phandle references the expected control-device type and restore the selector's status changeset if dynamic device creation fails. Keep a device link to the selected provider and defer until its driver binds. Verify that the MAC interface agrees with the provider's phy-mode before resetting the hardware. Power the control block before each PHY reset, shut it down during PHY suspend, and restore the vendor configuration after resume. If control power-off fails during suspend, attempt to power the PHY back on and restore its link configuration before returning the error. Pass the link address to the AC200 provider for EPHY_CTL.PHY_ADDR programming; the AC300 provider instead validates its package-strapped address relationship. Apply the common vendor analog initialization and SID-derived tuning while preserving unrelated register fields. Support a board-selected xMII receive-clock inversion and report and configure forced or automatic MDI/MDI-X state. Expose UAPS through the ethtool energy-detect power-down tunable as its no-transmit mode. Accumulate the hardware receive-byte, receive-packet and receive-CRC-error counters across PHY resets, expose all three as driver statistics and map CRC errors to the standardized PHY receive-error counter. Treat counter snapshots as best-effort telemetry so a read failure cannot prevent PHY recovery. Start both standard EEE advertisement and the PHY-autonomous Intelligent EEE transmitter disabled, matching the vendor configuration. Preserve the supported modes so ethtool can enable and configure both at runtime. The PHY has no documented programmable LPI timer, so reject a nonzero timer when enabling Tx LPI while accepting any timer value when disabling it. Clear BMCR_PDOWN before soft reset because ACx00 can acknowledge reset while powered down without restarting its link logic. Use the shared PHY interrupt for link changes when firmware provides one; otherwise retain the normal phylib polling fallback. On wakeup-source systems with a routed interrupt, expose magic-packet and link-change Wake-on-LAN, program the detector MAC address for magic wake, and arm the nested IRQ as a wake source. Keep the PHY powered while either PHY or MAC Wake-on-LAN is active. During suspend, leave only requested PHY wake events unmasked, then restore normal link monitoring on resume. Do not advertise either wake mode in polling mode because the CPU cannot poll while suspended. Register standard PHY LEDs for the described package outputs and expose their fixed link/activity, 100 Mbps speed and duplex rules to the netdev trigger. Use the vendor fallback of all three outputs active-low when no LED topology is provided; otherwise apply the described output set and shared polarity. Quiesce the provider if PHY probing or removal tears down the link device. Signed-off-by: James Hilliard --- drivers/net/phy/Kconfig | 12 + drivers/net/phy/Makefile | 1 + drivers/net/phy/xpowers-acx00.c | 1457 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 1470 insertions(+) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 9b202072d5a0..e3796a2b7be4 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -487,6 +487,18 @@ config XPOWERS_AC300_PHY_CTL interface mode, clock and I/O controls through the separate MDIO control address. +config XPOWERS_ACX00_PHY + tristate "X-Powers AC200/AC300 Ethernet PHY" + depends on OF_MDIO + help + Enable the Fast Ethernet PHY driver shared by the X-Powers AC200 + and AC300 companion ICs. This driver configures the common link PHY + and can select the matching control device at runtime on systems which + contain either variant. Runtime variant detection requires NVMEM + support. Dynamically enabling a control device which is not already + available requires OF_DYNAMIC support. Fixed-function package LED + outputs can be exposed through the PHY LED framework. + config XILINX_GMII2RGMII tristate "Xilinx GMII2RGMII converter driver" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 2d22d5a4c93d..c4b17e1965aa 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -101,4 +101,5 @@ obj-$(CONFIG_TERANETICS_PHY) += teranetics.o obj-$(CONFIG_VITESSE_PHY) += vitesse.o obj-$(CONFIG_XPOWERS_AC200_PHY_CTL) += xpowers-ac200-ctl.o obj-$(CONFIG_XPOWERS_AC300_PHY_CTL) += xpowers-ac300-ctl.o +obj-$(CONFIG_XPOWERS_ACX00_PHY) += xpowers-acx00.o obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o diff --git a/drivers/net/phy/xpowers-acx00.c b/drivers/net/phy/xpowers-acx00.c new file mode 100644 index 000000000000..98d0ee3937ef --- /dev/null +++ b/drivers/net/phy/xpowers-acx00.c @@ -0,0 +1,1457 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * X-Powers AC200/AC300 Ethernet PHY driver + * + * Copyright (C) 2026 James Hilliard + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xpowers-acx00.h" + +#define ACX00_EPHY_ID 0x00441400 + +#define ACX00_EPHY_CONFIG_VARIANT_AC300 BIT(0) +#define ACX00_EPHY_CONFIG_CALIBRATION_LOW BIT(1) + +#define ACX00_PAGE_SELECT_REG 0x1f +#define ACX00_PAGE_SELECT_MASK GENMASK(12, 8) +#define ACX00_PAGE_0 0 +#define ACX00_PAGE_1 1 +#define ACX00_PAGE_2 2 +#define ACX00_PAGE_6 6 +#define ACX00_PAGE_8 8 +#define ACX00_PAGE_9 9 + +#define ACX00_PAGE0_INTERRUPT_STATUS_REG 0x10 +#define ACX00_PAGE0_INTERRUPT_MASK_REG 0x11 +#define ACX00_PAGE0_INTERRUPT_LINK_CHANGE BIT(15) +#define ACX00_PAGE0_INTERRUPT_MAGIC_PACKET BIT(14) +#define ACX00_PAGE0_INTERRUPT_MANAGED_EVENTS \ + (ACX00_PAGE0_INTERRUPT_LINK_CHANGE | \ + ACX00_PAGE0_INTERRUPT_MAGIC_PACKET) +#define ACX00_PAGE0_GLOBAL_CONFIG_REG 0x13 +#define ACX00_PAGE0_XMII_RX_CLOCK_INVERT BIT(12) +#define ACX00_PAGE0_MAGIC_PACKET_WAKE_ENABLE BIT(10) +#define ACX00_PAGE0_MAGIC_PACKET_BROADCAST_ENABLE BIT(8) +#define ACX00_PAGE0_MAGIC_PACKET_PASSWORD_ENABLE BIT(7) +#define ACX00_PAGE0_MDI_MODE_MASK GENMASK(1, 0) +#define ACX00_PAGE0_MDI_MODE_MDI 0 +#define ACX00_PAGE0_MDI_MODE_MDIX 1 +#define ACX00_PAGE0_MDI_MODE_AUTO 2 +#define ACX00_PAGE0_STATUS_REG 0x19 +#define ACX00_PAGE0_STATUS_MDIX BIT(7) +#define ACX00_PAGE0_MAGIC_PACKET_MAC_REG(_index) (0x16 + (_index)) + +#define ACX00_PAGE1_APS_CONTROL_REG 0x12 +#define ACX00_PAGE1_APS_DISABLED_4S_VALUE 0x4824 +#define ACX00_PAGE1_UAPS_CONTROL_REG 0x13 +#define ACX00_PAGE1_UAPS_ENABLE BIT(15) +#define ACX00_PAGE1_INTELLIGENT_EEE_CONTROL_REG 0x17 +#define ACX00_PAGE1_INTELLIGENT_EEE_ENABLE BIT(3) + +#define ACX00_PAGE2_TX_DATA_CONTROL_REG 0x18 +#define ACX00_PAGE2_10BT_FIR_SELECT_MASK GENMASK(14, 12) +#define ACX00_PAGE2_10BT_FIR_SELECT_DEFAULT 0 + +#define ACX00_PAGE6_ADC_CONTROL_REG 0x10 +#define ACX00_PAGE6_ADC_CONTROL_LOW_CAL_VALUE 0x5523 +#define ACX00_PAGE6_AFE_RX_CONTROL_REG 0x13 +#define ACX00_PAGE6_AFE_RX_CONTROL_VALUE 0xf000 +#define ACX00_PAGE6_AFE_EQ_RX_DETECT_CONTROL_REG 0x14 +#define ACX00_PAGE6_AFE_EQ_RX_DETECT_VALUE 0x708b +#define ACX00_PAGE6_AFE_EQ_RX_DETECT_LOW_CAL_VALUE 0x7809 +#define ACX00_PAGE6_TX_LEVEL_REG 0x15 +#define ACX00_PAGE6_TX_LEVEL_100M_MASK GENMASK(15, 8) +#define ACX00_PAGE6_TX_LEVEL_10M_MASK GENMASK(7, 0) +#define ACX00_PAGE6_TX_LEVEL_VALUE(_100m, _10m) \ + (FIELD_PREP(ACX00_PAGE6_TX_LEVEL_100M_MASK, (_100m)) | \ + FIELD_PREP(ACX00_PAGE6_TX_LEVEL_10M_MASK, (_10m))) +#define ACX00_PAGE6_TX_LEVEL_100M_DEFAULT 0x15 +#define ACX00_PAGE6_TX_LEVEL_10M_DEFAULT 0x30 +#define ACX00_PAGE6_TX_LEVEL_100M_LOW_CAL 0x35 +#define ACX00_PAGE6_TX_LEVEL_10M_LOW_CAL 0x33 +#define ACX00_PAGE6_TX_LEVEL_DEFAULT_VALUE \ + ACX00_PAGE6_TX_LEVEL_VALUE(ACX00_PAGE6_TX_LEVEL_100M_DEFAULT, \ + ACX00_PAGE6_TX_LEVEL_10M_DEFAULT) +#define ACX00_PAGE6_TX_LEVEL_LOW_CAL_VALUE \ + ACX00_PAGE6_TX_LEVEL_VALUE(ACX00_PAGE6_TX_LEVEL_100M_LOW_CAL, \ + ACX00_PAGE6_TX_LEVEL_10M_LOW_CAL) + +#define ACX00_PAGE8_AFE_CONTROL_REG 0x18 +#define ACX00_PAGE8_AFE_CONTROL_VALUE 0x00bc +#define ACX00_PAGE8_AUTO_CAL_CONTROL_REG 0x1d +#define ACX00_PAGE8_AUTO_CAL_TX_LEVEL_ADJUST_BYPASS BIT(11) +#define ACX00_PAGE8_AUTO_CAL_LOW_CAL_OPAQUE_BITS 0x0044 +#define ACX00_PAGE8_AUTO_CAL_LOW_VALUE \ + (ACX00_PAGE8_AUTO_CAL_TX_LEVEL_ADJUST_BYPASS | \ + ACX00_PAGE8_AUTO_CAL_LOW_CAL_OPAQUE_BITS) + +#define ACX00_PAGE9_EPGC_COMMAND_REG 0x10 +#define ACX00_PAGE9_EPC_CLEAR_COUNTERS BIT(3) +#define ACX00_PAGE9_EPG_CLEAR_COUNTERS BIT(2) +#define ACX00_PAGE9_RX_BYTES_HIGH_REG 0x19 +#define ACX00_PAGE9_RX_BYTES_LOW_REG 0x1a +#define ACX00_PAGE9_RX_PACKETS_HIGH_REG 0x1b +#define ACX00_PAGE9_RX_PACKETS_LOW_REG 0x1c +#define ACX00_PAGE9_RX_CRC_ERRORS_HIGH_REG 0x1d +#define ACX00_PAGE9_RX_CRC_ERRORS_LOW_REG 0x1e + +enum acx00_ephy_stat { + ACX00_STAT_RX_BYTES, + ACX00_STAT_RX_PACKETS, + ACX00_STAT_RX_CRC_ERRORS, + ACX00_STAT_COUNT, +}; + +static const char acx00_ephy_stat_names[][ETH_GSTRING_LEN] = { + [ACX00_STAT_RX_BYTES] = "phy_rx_bytes", + [ACX00_STAT_RX_PACKETS] = "phy_rx_packets", + [ACX00_STAT_RX_CRC_ERRORS] = "phy_rx_crc_errors", +}; + +/* + * Another integration of this exact-ID PHY documents its digital vendor + * register map, which also matches the observed ACx00 reset values. The ACx00 + * analog-page field encodings remain unpublished, so keep those as opaque + * vendor initialization values instead of inventing bit definitions. + */ + +struct acx00_ephy_priv { + struct acx00_ephy_control *control; + bool is_ac300; + bool use_low_calibration_tuning; + bool xmii_rx_clock_inverted; + bool eee_initialized; + bool uaps_enabled; + bool stats_valid; + bool wol_irq_enabled; + bool wol_suspended; + unsigned long led_outputs; + int led_polarity_mode; + u32 wolopts; + u32 stats_last[ACX00_STAT_COUNT]; + u64 stats[ACX00_STAT_COUNT]; +}; + +#if IS_ENABLED(CONFIG_OF_DYNAMIC) +static int acx00_enable_node(struct device *dev, struct device_node *node) +{ + struct of_changeset ocs; + const char *status; + int revert_ret; + int ret; + + ret = of_property_read_string(node, "status", &status); + if (ret || strcmp(status, "fail-needs-probe")) + return dev_err_probe(dev, -EINVAL, + "%pOF must use status fail-needs-probe\n", + node); + + of_changeset_init(&ocs); + ret = of_changeset_update_prop_string(&ocs, node, "status", "okay"); + if (!ret) { + ret = of_changeset_apply(&ocs); + if (ret && of_device_is_available(node)) { + revert_ret = of_changeset_revert(&ocs); + if (revert_ret) + dev_err(dev, + "failed to restore %pOF after enable error: %pe\n", + node, ERR_PTR(revert_ret)); + } + } + of_changeset_destroy(&ocs); + + return ret; +} +#endif + +static int acx00_prepare_node(struct device *dev, struct device_node *node, + bool runtime_selection) +{ + if (of_device_is_available(node)) + return 0; + + if (!runtime_selection) + return dev_err_probe(dev, -ENODEV, + "%pOF must be enabled for static control selection\n", + node); + +#if IS_ENABLED(CONFIG_OF_DYNAMIC) + return acx00_enable_node(dev, node); +#else + return dev_err_probe(dev, -EOPNOTSUPP, + "enabling %pOF requires CONFIG_OF_DYNAMIC\n", node); +#endif +} + +static struct device_node * +acx00_ac200_get_enable_node(struct device *dev, struct device_node *control) +{ + struct device_node *parent; + struct device_node *enable_node; + + if (!of_device_is_available(control)) { + dev_err(dev, "%pOF must be enabled\n", control); + return ERR_PTR(-ENODEV); + } + + parent = of_get_parent(control); + if (!parent) + return ERR_PTR(-EINVAL); + + if (!of_device_is_compatible(parent, "x-powers,ac200")) { + dev_err(dev, "%pOF is not an AC200 control function\n", control); + of_node_put(parent); + return ERR_PTR(-EINVAL); + } + if (!of_device_is_available(parent)) { + dev_err(dev, "%pOF must be enabled\n", parent); + of_node_put(parent); + return ERR_PTR(-ENODEV); + } + + enable_node = of_get_parent(parent); + of_node_put(parent); + if (!enable_node) + return ERR_PTR(-EINVAL); + + return enable_node; +} + +static struct device * +acx00_find_supplier(struct device_node *control, bool is_ac300) +{ + struct platform_device *pdev; + struct mdio_device *mdiodev; + + if (is_ac300) { + mdiodev = of_mdio_find_device(control); + return mdiodev ? &mdiodev->dev : NULL; + } + + pdev = of_find_device_by_node(control); + return pdev ? &pdev->dev : NULL; +} + +static int acx00_select_control(struct phy_device *phydev, bool is_ac300, + bool runtime_selection, + unsigned long led_outputs, + bool led_active_low, + struct acx00_ephy_control **selected_control) +{ + struct acx00_ephy_control *ephy_control; + struct device *dev = &phydev->mdio.dev; + struct device_node *control; + struct device_node *enable_node; + struct device *supplier; + struct device_link *link; + const char *control_compatible; + const char *control_property; + u32 configured_addr; + int ret; + + control_property = is_ac300 ? "x-powers,ac300-control" : + "x-powers,ac200-control"; + control_compatible = is_ac300 ? "x-powers,ac300-ephy-ctl" : + "x-powers,ac200-ephy-ctl"; + control = of_parse_phandle(dev->of_node, control_property, 0); + if (!control) + return dev_err_probe(dev, -EINVAL, + "missing %s phandle\n", control_property); + if (!of_device_is_compatible(control, control_compatible)) { + ret = dev_err_probe(dev, -EINVAL, + "%s does not reference a %s device\n", + control_property, control_compatible); + goto out_put_control; + } + + if (is_ac300) { + ret = of_property_read_u32(control, "reg", &configured_addr); + if (ret || configured_addr != phydev->mdio.addr + + AC300_EPHY_CONTROL_ADDR_OFFSET) { + ret = dev_err_probe(dev, -EINVAL, + "AC300 control address does not match PHY address\n"); + goto out_put_control; + } + + enable_node = of_node_get(control); + } else { + enable_node = acx00_ac200_get_enable_node(dev, control); + if (IS_ERR(enable_node)) { + ret = PTR_ERR(enable_node); + goto out_put_control; + } + } + + ret = acx00_prepare_node(dev, enable_node, runtime_selection); + of_node_put(enable_node); + if (ret) + goto out_put_control; + + supplier = acx00_find_supplier(control, is_ac300); + if (!supplier) { + ret = -EPROBE_DEFER; + goto out_put_control; + } + + link = device_link_add(dev, supplier, DL_FLAG_AUTOPROBE_CONSUMER); + if (!link) { + ret = -EINVAL; + } else { + device_lock(supplier); + if (!device_is_bound(supplier)) { + ret = -EPROBE_DEFER; + } else { + ephy_control = dev_get_drvdata(supplier); + if (!ephy_control || !ephy_control->power_on || + !ephy_control->power_off || + !ephy_control->set_led_outputs || + !ephy_control->set_led_polarity) { + ret = -EINVAL; + } else { + ret = ephy_control->set_led_polarity(ephy_control, + led_active_low); + if (!ret) + ret = ephy_control->set_led_outputs(ephy_control, + led_outputs); + if (!ret) + ret = ephy_control->power_on(ephy_control, + phydev->mdio.addr); + if (!ret) { + *selected_control = ephy_control; + } else { + ephy_control->set_led_outputs(ephy_control, 0); + ephy_control->set_led_polarity(ephy_control, + false); + } + } + } + device_unlock(supplier); + } + + put_device(supplier); + if (ret && ret != -EPROBE_DEFER) + ret = dev_err_probe(dev, ret, + "failed to enable %s control\n", + is_ac300 ? "AC300" : "AC200"); + +out_put_control: + of_node_put(control); + return ret; +} + +static int acx00_ephy_parse_leds(struct phy_device *phydev, + unsigned long *led_outputs, + int *led_polarity_mode) +{ + struct device_node *leds; + u32 index; + int ret = 0; + + /* Match the vendor fallback when firmware provides no LED topology. */ + *led_outputs = GENMASK(ACX00_EPHY_LED_COUNT - 1, 0); + *led_polarity_mode = 1; + + leds = of_get_child_by_name(phydev->mdio.dev.of_node, "leds"); + if (!leds) + return 0; + + /* An explicit container replaces the fallback package configuration. */ + *led_outputs = 0; + *led_polarity_mode = -1; + + for_each_available_child_of_node_scoped(leds, led) { + bool active_high = of_property_read_bool(led, "active-high"); + bool active_low = of_property_read_bool(led, "active-low"); + int polarity_mode; + + ret = of_property_read_u32(led, "reg", &index); + if (ret) + break; + if (index >= ACX00_EPHY_LED_COUNT || + (*led_outputs & BIT(index))) { + ret = -EINVAL; + break; + } + *led_outputs |= BIT(index); + + if (active_high && active_low) { + ret = -EINVAL; + break; + } + if (of_property_read_bool(led, "inactive-high-impedance")) { + ret = -EOPNOTSUPP; + break; + } + if (!active_high && !active_low) + continue; + + polarity_mode = active_low; + if (*led_polarity_mode >= 0 && + *led_polarity_mode != polarity_mode) { + ret = -EINVAL; + break; + } + *led_polarity_mode = polarity_mode; + } + + of_node_put(leds); + if (ret) + return dev_err_probe(&phydev->mdio.dev, ret, + "invalid EPHY LED description\n"); + if (*led_polarity_mode < 0) + *led_polarity_mode = 1; + + return 0; +} + +static void acx00_ephy_power_off(void *data) +{ + struct phy_device *phydev = data; + struct acx00_ephy_priv *priv = phydev->priv; + int ret; + + ret = priv->control->set_led_outputs(priv->control, 0); + if (ret) + phydev_warn(phydev, "failed to disable LED outputs: %pe\n", + ERR_PTR(ret)); + + ret = priv->control->set_led_polarity(priv->control, false); + if (ret) + phydev_warn(phydev, "failed to restore LED polarity: %pe\n", + ERR_PTR(ret)); + + ret = priv->control->power_off(priv->control); + if (ret) + phydev_warn(phydev, "failed to power off control block: %pe\n", + ERR_PTR(ret)); +} + +static int acx00_ephy_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct acx00_ephy_priv *priv; + bool has_ac200_control; + bool has_ac300_control; + bool runtime_selection; + u32 configuration = 0; + int led_polarity_mode; + unsigned long led_outputs; + int ret; + + has_ac200_control = of_property_present(dev->of_node, + "x-powers,ac200-control"); + has_ac300_control = of_property_present(dev->of_node, + "x-powers,ac300-control"); + if (!has_ac200_control && !has_ac300_control) + return -ENODEV; + runtime_selection = has_ac200_control && has_ac300_control; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ret = acx00_ephy_parse_leds(phydev, &led_outputs, + &led_polarity_mode); + if (ret) + return ret; + + if (has_ac300_control && + (runtime_selection || + of_property_present(dev->of_node, "nvmem-cells"))) { + ret = nvmem_cell_read_variable_le_u32(dev, "configuration", + &configuration); + if (ret) + return dev_err_probe(dev, ret, + "failed to read PHY configuration\n"); + } + + if (runtime_selection) { + priv->is_ac300 = configuration & + ACX00_EPHY_CONFIG_VARIANT_AC300; + } else { + priv->is_ac300 = has_ac300_control; + } + if (priv->is_ac300) + priv->use_low_calibration_tuning = configuration & + ACX00_EPHY_CONFIG_CALIBRATION_LOW; + priv->xmii_rx_clock_inverted = + device_property_read_bool(dev, + "x-powers,xmii-rx-clock-inverted"); + + ret = acx00_select_control(phydev, priv->is_ac300, + runtime_selection, + led_outputs, led_polarity_mode > 0, + &priv->control); + if (ret) + return ret; + + priv->led_outputs = led_outputs; + priv->led_polarity_mode = led_polarity_mode; + phydev->priv = priv; + ret = devm_add_action_or_reset(dev, acx00_ephy_power_off, phydev); + if (ret) + return ret; + + phydev->mdix_ctrl = ETH_TP_MDI_AUTO; + + /* + * The Wake-on-LAN events use the normal PHY interrupt. Only advertise + * wake support when firmware describes a routed interrupt. + */ + if (device_property_read_bool(dev, "wakeup-source") && + phy_interrupt_is_valid(phydev)) + device_set_wakeup_capable(dev, true); + + return 0; +} + +static int acx00_ephy_led_rules(u8 index, unsigned long *rules) +{ + switch (index) { + case ACX00_EPHY_LED_LINK_ACTIVITY: + *rules = BIT(TRIGGER_NETDEV_LINK) | BIT(TRIGGER_NETDEV_TX) | + BIT(TRIGGER_NETDEV_RX); + break; + case ACX00_EPHY_LED_SPEED: + *rules = BIT(TRIGGER_NETDEV_LINK_100); + break; + case ACX00_EPHY_LED_DUPLEX: + /* Half-duplex collision flashing is fixed and has no rule bit. */ + *rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int acx00_ephy_led_hw_is_supported(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + struct acx00_ephy_priv *priv = phydev->priv; + unsigned long supported_rules; + int ret; + + if (index >= ACX00_EPHY_LED_COUNT || + !test_bit(index, &priv->led_outputs)) + return -EINVAL; + + ret = acx00_ephy_led_rules(index, &supported_rules); + if (ret) + return ret; + + return rules == supported_rules ? 0 : -EOPNOTSUPP; +} + +static int acx00_ephy_led_hw_control_set(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + return acx00_ephy_led_hw_is_supported(phydev, index, rules); +} + +static int acx00_ephy_led_hw_control_get(struct phy_device *phydev, u8 index, + unsigned long *rules) +{ + struct acx00_ephy_priv *priv = phydev->priv; + + if (index >= ACX00_EPHY_LED_COUNT || + !test_bit(index, &priv->led_outputs)) + return -EINVAL; + + return acx00_ephy_led_rules(index, rules); +} + +static int acx00_ephy_led_polarity_set(struct phy_device *phydev, int index, + unsigned long modes) +{ + struct acx00_ephy_priv *priv = phydev->priv; + bool active_high; + bool active_low; + int polarity_mode; + int ret; + + if (index < 0 || index >= ACX00_EPHY_LED_COUNT || + !test_bit(index, &priv->led_outputs)) + return -EINVAL; + + active_high = test_bit(PHY_LED_ACTIVE_HIGH, &modes); + active_low = test_bit(PHY_LED_ACTIVE_LOW, &modes); + if (modes & ~(BIT(PHY_LED_ACTIVE_HIGH) | + BIT(PHY_LED_ACTIVE_LOW))) + return -EOPNOTSUPP; + if (active_high == active_low) + return -EINVAL; + + polarity_mode = active_low; + if (priv->led_polarity_mode != polarity_mode) { + phydev_err(phydev, + "LED polarity is global and must match for all outputs\n"); + return -EINVAL; + } + + ret = priv->control->set_led_polarity(priv->control, active_low); + + return ret; +} + +static int acx00_ephy_read_counter(struct phy_device *phydev, u32 high_reg, + u32 low_reg, u32 *counter) +{ + int high; + int high_check; + int low; + + do { + high = __phy_read(phydev, high_reg); + if (high < 0) + return high; + + low = __phy_read(phydev, low_reg); + if (low < 0) + return low; + + high_check = __phy_read(phydev, high_reg); + if (high_check < 0) + return high_check; + } while (high != high_check); + + *counter = (u32)high << 16 | low; + + return 0; +} + +static int acx00_ephy_update_stats(struct phy_device *phydev) +{ + struct acx00_ephy_priv *priv = phydev->priv; + u32 counters[ACX00_STAT_COUNT]; + int oldpage; + int ret; + int i; + + oldpage = phy_select_page(phydev, ACX00_PAGE_9); + if (oldpage < 0) + return phy_restore_page(phydev, oldpage, 0); + + ret = acx00_ephy_read_counter(phydev, + ACX00_PAGE9_RX_BYTES_HIGH_REG, + ACX00_PAGE9_RX_BYTES_LOW_REG, + &counters[ACX00_STAT_RX_BYTES]); + if (ret) + goto out_restore_page; + + ret = acx00_ephy_read_counter(phydev, + ACX00_PAGE9_RX_PACKETS_HIGH_REG, + ACX00_PAGE9_RX_PACKETS_LOW_REG, + &counters[ACX00_STAT_RX_PACKETS]); + if (ret) + goto out_restore_page; + + ret = acx00_ephy_read_counter(phydev, + ACX00_PAGE9_RX_CRC_ERRORS_HIGH_REG, + ACX00_PAGE9_RX_CRC_ERRORS_LOW_REG, + &counters[ACX00_STAT_RX_CRC_ERRORS]); + +out_restore_page: + ret = phy_restore_page(phydev, oldpage, ret); + if (ret) + return ret; + + if (priv->stats_valid) { + for (i = 0; i < ACX00_STAT_COUNT; i++) + priv->stats[i] += counters[i] - priv->stats_last[i]; + } + + memcpy(priv->stats_last, counters, sizeof(counters)); + priv->stats_valid = true; + + return 0; +} + +static void acx00_ephy_snapshot_and_invalidate_stats(struct phy_device *phydev) +{ + struct acx00_ephy_priv *priv = phydev->priv; + int ret; + + if (!priv->stats_valid) + return; + + ret = acx00_ephy_update_stats(phydev); + if (ret) + phydev_dbg(phydev, "failed to snapshot statistics: %pe\n", + ERR_PTR(ret)); + priv->stats_valid = false; +} + +static int acx00_ephy_validate_interface(struct phy_device *phydev) +{ + struct acx00_ephy_priv *priv = phydev->priv; + + if (phydev->interface == priv->control->interface) + return 0; + + phydev_err(phydev, "MAC uses %s but control device is configured for %s\n", + phy_modes(phydev->interface), + phy_modes(priv->control->interface)); + + return -EINVAL; +} + +static int acx00_ephy_soft_reset(struct phy_device *phydev) +{ + struct acx00_ephy_priv *priv = phydev->priv; + int ret; + + ret = acx00_ephy_validate_interface(phydev); + if (ret) + return ret; + + /* The control sequence below may reset the hardware counters. */ + acx00_ephy_snapshot_and_invalidate_stats(phydev); + + ret = priv->control->power_on(priv->control, phydev->mdio.addr); + if (ret) + return ret; + + /* + * ACx00 acknowledges reset while powered down but does not restart. + * This can happen when reattaching a previously suspended PHY. + */ + ret = genphy_resume(phydev); + if (ret) + return ret; + + return genphy_soft_reset(phydev); +} + +static int acx00_ephy_read_page(struct phy_device *phydev) +{ + int ret; + + ret = __phy_read(phydev, ACX00_PAGE_SELECT_REG); + if (ret < 0) + return ret; + + return FIELD_GET(ACX00_PAGE_SELECT_MASK, ret); +} + +static int acx00_ephy_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, ACX00_PAGE_SELECT_REG, + FIELD_PREP(ACX00_PAGE_SELECT_MASK, page)); +} + +static int __acx00_ephy_ack_interrupt(struct phy_device *phydev) +{ + int status; + + status = __phy_read(phydev, ACX00_PAGE0_INTERRUPT_STATUS_REG); + if (status < 0) + return status; + + /* All interrupt status bits are write-one-to-clear. */ + return __phy_write(phydev, ACX00_PAGE0_INTERRUPT_STATUS_REG, status); +} + +static int __acx00_ephy_config_interrupts(struct phy_device *phydev, + u32 wolopts, bool wake_only) +{ + u16 disable; + u16 mask = 0; + int ret; + + if ((!wake_only && phydev->interrupts == PHY_INTERRUPT_ENABLED) || + (wolopts & WAKE_PHY)) + mask |= ACX00_PAGE0_INTERRUPT_LINK_CHANGE; + if (wolopts & WAKE_MAGIC) + mask |= ACX00_PAGE0_INTERRUPT_MAGIC_PACKET; + + /* Mask sources being removed before clearing their latched status. */ + disable = ACX00_PAGE0_INTERRUPT_MANAGED_EVENTS & ~mask; + if (disable) { + ret = __phy_modify(phydev, ACX00_PAGE0_INTERRUPT_MASK_REG, + disable, 0); + if (ret) + return ret; + } + + ret = __acx00_ephy_ack_interrupt(phydev); + if (ret) + return ret; + + return __phy_modify(phydev, ACX00_PAGE0_INTERRUPT_MASK_REG, + ACX00_PAGE0_INTERRUPT_MANAGED_EVENTS, mask); +} + +static int acx00_ephy_config_interrupts(struct phy_device *phydev, + u32 wolopts, bool wake_only) +{ + int oldpage; + int ret; + + oldpage = phy_select_page(phydev, ACX00_PAGE_0); + if (oldpage < 0) + return phy_restore_page(phydev, oldpage, 0); + + ret = __acx00_ephy_config_interrupts(phydev, wolopts, wake_only); + + return phy_restore_page(phydev, oldpage, ret); +} + +static int acx00_ephy_config_intr(struct phy_device *phydev) +{ + struct acx00_ephy_priv *priv = phydev->priv; + + return acx00_ephy_config_interrupts(phydev, priv->wolopts, + priv->wol_suspended); +} + +static irqreturn_t acx00_ephy_handle_interrupt(struct phy_device *phydev) +{ + unsigned int active = 0; + int oldpage; + int enabled; + int status; + int ret = 0; + + oldpage = phy_select_page(phydev, ACX00_PAGE_0); + if (oldpage < 0) { + ret = phy_restore_page(phydev, oldpage, 0); + goto out_error; + } + + enabled = __phy_read(phydev, ACX00_PAGE0_INTERRUPT_MASK_REG); + if (enabled < 0) { + ret = enabled; + goto out_restore_page; + } + + status = __phy_read(phydev, ACX00_PAGE0_INTERRUPT_STATUS_REG); + if (status < 0) { + ret = status; + goto out_restore_page; + } + + active = status & enabled; + if (active) + /* Clear every event latched in the write-one-to-clear register. */ + ret = __phy_write(phydev, ACX00_PAGE0_INTERRUPT_STATUS_REG, + status); + +out_restore_page: + ret = phy_restore_page(phydev, oldpage, ret); + if (ret) + goto out_error; + + if (!active) + return IRQ_NONE; + + if (active & ACX00_PAGE0_INTERRUPT_LINK_CHANGE) + phy_trigger_machine(phydev); + + return IRQ_HANDLED; + +out_error: + phy_error(phydev); + return IRQ_NONE; +} + +/* + * Arm the nested interrupt as a wake source immediately. The AC200 is on an + * I2C bus, so deferring this until the noirq suspend phase could require an + * I2C register update after the controller has already been suspended. + */ +static int acx00_ephy_set_wake_irq(struct phy_device *phydev, bool enable) +{ + struct acx00_ephy_priv *priv = phydev->priv; + int ret; + + if (priv->wol_irq_enabled == enable) + return 0; + if (!phy_interrupt_is_valid(phydev)) + return enable ? -EOPNOTSUPP : 0; + + if (enable) + ret = enable_irq_wake(phydev->irq); + else + ret = disable_irq_wake(phydev->irq); + if (ret) + return ret; + + priv->wol_irq_enabled = enable; + + return 0; +} + +static void acx00_ephy_get_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + struct acx00_ephy_priv *priv = phydev->priv; + struct device *dev = &phydev->mdio.dev; + + wol->supported = 0; + wol->wolopts = 0; + + if (!device_can_wakeup(dev) || !phy_interrupt_is_valid(phydev)) + return; + + wol->supported = WAKE_MAGIC | WAKE_PHY; + wol->wolopts = priv->wolopts; +} + +static int acx00_ephy_config_wol(struct phy_device *phydev, u32 wolopts) +{ + struct acx00_ephy_priv *priv = phydev->priv; + struct net_device *ndev = phydev->attached_dev; + const u8 *mac; + int oldpage; + int ret = 0; + int i; + + if (wolopts & WAKE_MAGIC && !ndev) + return -ENODEV; + + oldpage = phy_select_page(phydev, ACX00_PAGE_0); + if (oldpage < 0) + return phy_restore_page(phydev, oldpage, 0); + + if (wolopts & WAKE_MAGIC) { + /* The detector stores the MAC address big-endian in three registers. */ + mac = ndev->dev_addr; + for (i = 0; i < ETH_ALEN / 2; i++) { + ret = __phy_write(phydev, + ACX00_PAGE0_MAGIC_PACKET_MAC_REG(i), + mac[2 * i] << 8 | mac[2 * i + 1]); + if (ret) + goto out_restore_page; + } + } + + ret = __phy_modify(phydev, ACX00_PAGE0_GLOBAL_CONFIG_REG, + ACX00_PAGE0_MAGIC_PACKET_WAKE_ENABLE | + ACX00_PAGE0_MAGIC_PACKET_BROADCAST_ENABLE | + ACX00_PAGE0_MAGIC_PACKET_PASSWORD_ENABLE, + wolopts & WAKE_MAGIC ? + ACX00_PAGE0_MAGIC_PACKET_WAKE_ENABLE | + ACX00_PAGE0_MAGIC_PACKET_BROADCAST_ENABLE : 0); + if (ret) + goto out_restore_page; + + ret = __acx00_ephy_config_interrupts(phydev, wolopts, + priv->wol_suspended); + +out_restore_page: + return phy_restore_page(phydev, oldpage, ret); +} + +static int acx00_ephy_set_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + struct acx00_ephy_priv *priv = phydev->priv; + struct device *dev = &phydev->mdio.dev; + u32 old_wolopts = priv->wolopts; + bool enable = !!wol->wolopts; + bool old_enable = !!old_wolopts; + int rollback_ret; + int ret; + + if (wol->wolopts & ~(WAKE_MAGIC | WAKE_PHY)) + return -EOPNOTSUPP; + if (enable && (!device_can_wakeup(dev) || + !phy_interrupt_is_valid(phydev))) + return -EOPNOTSUPP; + + ret = acx00_ephy_config_wol(phydev, wol->wolopts); + if (ret) + goto out_rollback; + + ret = acx00_ephy_set_wake_irq(phydev, enable); + if (ret) + goto out_rollback; + + ret = device_set_wakeup_enable(dev, enable); + if (ret) + goto out_rollback; + + priv->wolopts = wol->wolopts; + + return 0; + +out_rollback: + rollback_ret = acx00_ephy_config_wol(phydev, old_wolopts); + if (rollback_ret) + phydev_warn(phydev, + "failed to restore Wake-on-LAN configuration: %pe\n", + ERR_PTR(rollback_ret)); + + rollback_ret = acx00_ephy_set_wake_irq(phydev, old_enable); + if (rollback_ret) + phydev_warn(phydev, + "failed to restore wake IRQ state: %pe\n", + ERR_PTR(rollback_ret)); + + rollback_ret = device_set_wakeup_enable(dev, old_enable); + if (rollback_ret) + phydev_warn(phydev, + "failed to restore device wake state: %pe\n", + ERR_PTR(rollback_ret)); + + return ret; +} + +static int acx00_ephy_config_init(struct phy_device *phydev) +{ + struct acx00_ephy_priv *priv = phydev->priv; + bool use_low_calibration_tuning = priv->use_low_calibration_tuning; + bool is_ac300 = priv->is_ac300; + u16 afe_eq_rx_detect = ACX00_PAGE6_AFE_EQ_RX_DETECT_VALUE; + u16 tx_level_value = ACX00_PAGE6_TX_LEVEL_DEFAULT_VALUE; + int oldpage; + int ret; + bool tx_lpi_enabled; + + /* Configuration clears the hardware counters below. */ + acx00_ephy_snapshot_and_invalidate_stats(phydev); + + if (!priv->eee_initialized) { + /* The vendor configuration starts with both EEE modes disabled. */ + phydev->eee_cfg.eee_enabled = false; + phydev->eee_cfg.tx_lpi_enabled = false; + priv->eee_initialized = true; + } + tx_lpi_enabled = phydev->eee_cfg.tx_lpi_enabled && + !phydev->autonomous_eee_disabled; + + ret = phy_modify_paged(phydev, ACX00_PAGE_0, + ACX00_PAGE0_GLOBAL_CONFIG_REG, + ACX00_PAGE0_XMII_RX_CLOCK_INVERT, + priv->xmii_rx_clock_inverted ? + ACX00_PAGE0_XMII_RX_CLOCK_INVERT : 0); + if (ret) + return ret; + + if (is_ac300) { + if (use_low_calibration_tuning) { + afe_eq_rx_detect = + ACX00_PAGE6_AFE_EQ_RX_DETECT_LOW_CAL_VALUE; + tx_level_value = ACX00_PAGE6_TX_LEVEL_LOW_CAL_VALUE; + } + } + + oldpage = phy_select_page(phydev, ACX00_PAGE_1); + if (oldpage < 0) + return phy_restore_page(phydev, oldpage, 0); + + ret = __phy_write(phydev, ACX00_PAGE1_APS_CONTROL_REG, + ACX00_PAGE1_APS_DISABLED_4S_VALUE); + if (ret) + goto out_restore_page; + ret = __phy_modify(phydev, ACX00_PAGE1_UAPS_CONTROL_REG, + ACX00_PAGE1_UAPS_ENABLE, + priv->uaps_enabled ? ACX00_PAGE1_UAPS_ENABLE : 0); + if (ret) + goto out_restore_page; + /* Intelligent EEE lets the PHY generate LPI without MAC support. */ + ret = __phy_modify(phydev, ACX00_PAGE1_INTELLIGENT_EEE_CONTROL_REG, + ACX00_PAGE1_INTELLIGENT_EEE_ENABLE, + tx_lpi_enabled ? + ACX00_PAGE1_INTELLIGENT_EEE_ENABLE : 0); + if (ret) + goto out_restore_page; + + ret = acx00_ephy_write_page(phydev, ACX00_PAGE_2); + if (ret) + goto out_restore_page; + ret = __phy_modify(phydev, ACX00_PAGE2_TX_DATA_CONTROL_REG, + ACX00_PAGE2_10BT_FIR_SELECT_MASK, + FIELD_PREP(ACX00_PAGE2_10BT_FIR_SELECT_MASK, + ACX00_PAGE2_10BT_FIR_SELECT_DEFAULT)); + if (ret) + goto out_restore_page; + + ret = acx00_ephy_write_page(phydev, ACX00_PAGE_6); + if (ret) + goto out_restore_page; + ret = __phy_write(phydev, ACX00_PAGE6_AFE_EQ_RX_DETECT_CONTROL_REG, + afe_eq_rx_detect); + if (ret) + goto out_restore_page; + ret = __phy_write(phydev, ACX00_PAGE6_AFE_RX_CONTROL_REG, + ACX00_PAGE6_AFE_RX_CONTROL_VALUE); + if (ret) + goto out_restore_page; + if (is_ac300 && use_low_calibration_tuning) { + ret = __phy_write(phydev, ACX00_PAGE6_ADC_CONTROL_REG, + ACX00_PAGE6_ADC_CONTROL_LOW_CAL_VALUE); + if (ret) + goto out_restore_page; + } + ret = __phy_write(phydev, ACX00_PAGE6_TX_LEVEL_REG, tx_level_value); + if (ret) + goto out_restore_page; + + ret = acx00_ephy_write_page(phydev, ACX00_PAGE_8); + if (ret) + goto out_restore_page; + if (is_ac300 && use_low_calibration_tuning) { + ret = __phy_write(phydev, ACX00_PAGE8_AUTO_CAL_CONTROL_REG, + ACX00_PAGE8_AUTO_CAL_LOW_VALUE); + if (ret) + goto out_restore_page; + } + ret = __phy_write(phydev, ACX00_PAGE8_AFE_CONTROL_REG, + ACX00_PAGE8_AFE_CONTROL_VALUE); + if (ret) + goto out_restore_page; + + ret = acx00_ephy_write_page(phydev, ACX00_PAGE_9); + if (ret) + goto out_restore_page; + ret = __phy_write(phydev, ACX00_PAGE9_EPGC_COMMAND_REG, + ACX00_PAGE9_EPC_CLEAR_COUNTERS | + ACX00_PAGE9_EPG_CLEAR_COUNTERS); + if (!ret) { + memset(priv->stats_last, 0, sizeof(priv->stats_last)); + priv->stats_valid = true; + } + +out_restore_page: + ret = phy_restore_page(phydev, oldpage, ret); + if (ret) + return ret; + + /* Apply the retained Linux EEE policy after every hardware reset. */ + ret = genphy_c45_an_config_eee_aneg(phydev); + if (ret < 0) + return ret; + + /* A soft reset also clears the retained Wake-on-LAN configuration. */ + return acx00_ephy_config_wol(phydev, priv->wolopts); +} + +static int acx00_ephy_set_intelligent_eee(struct phy_device *phydev, + bool enable) +{ + return phy_modify_paged(phydev, ACX00_PAGE_1, + ACX00_PAGE1_INTELLIGENT_EEE_CONTROL_REG, + ACX00_PAGE1_INTELLIGENT_EEE_ENABLE, + enable ? ACX00_PAGE1_INTELLIGENT_EEE_ENABLE : 0); +} + +static int acx00_ephy_set_tx_lpi(struct phy_device *phydev, + const struct eee_config *config) +{ + if (config->tx_lpi_enabled && config->tx_lpi_timer) + return -EOPNOTSUPP; + + return acx00_ephy_set_intelligent_eee(phydev, + config->tx_lpi_enabled); +} + +static int acx00_ephy_config_aneg(struct phy_device *phydev) +{ + u16 mode; + int ret; + + switch (phydev->mdix_ctrl) { + case ETH_TP_MDI: + mode = ACX00_PAGE0_MDI_MODE_MDI; + break; + case ETH_TP_MDI_X: + mode = ACX00_PAGE0_MDI_MODE_MDIX; + break; + case ETH_TP_MDI_AUTO: + mode = ACX00_PAGE0_MDI_MODE_AUTO; + break; + default: + return -EINVAL; + } + + ret = phy_modify_paged_changed(phydev, ACX00_PAGE_0, + ACX00_PAGE0_GLOBAL_CONFIG_REG, + ACX00_PAGE0_MDI_MODE_MASK, + FIELD_PREP(ACX00_PAGE0_MDI_MODE_MASK, + mode)); + if (ret < 0) + return ret; + + return __genphy_config_aneg(phydev, ret > 0); +} + +static int acx00_ephy_read_status(struct phy_device *phydev) +{ + int ret; + + ret = genphy_read_status(phydev); + if (ret) + return ret; + + if (!phydev->link) { + phydev->mdix = ETH_TP_MDI_INVALID; + return 0; + } + + ret = phy_read_paged(phydev, ACX00_PAGE_0, ACX00_PAGE0_STATUS_REG); + if (ret < 0) + return ret; + + phydev->mdix = ret & ACX00_PAGE0_STATUS_MDIX ? ETH_TP_MDI_X : + ETH_TP_MDI; + + return 0; +} + +static int acx00_ephy_get_sset_count(struct phy_device *phydev) +{ + return ACX00_STAT_COUNT; +} + +static void acx00_ephy_get_strings(struct phy_device *phydev, u8 *data) +{ + unsigned int i; + + for (i = 0; i < ACX00_STAT_COUNT; i++) + ethtool_puts(&data, acx00_ephy_stat_names[i]); +} + +static void acx00_ephy_get_stats(struct phy_device *phydev, + struct ethtool_stats *stats, u64 *data) +{ + struct acx00_ephy_priv *priv = phydev->priv; + unsigned int i; + int ret; + + ret = acx00_ephy_update_stats(phydev); + for (i = 0; i < ACX00_STAT_COUNT; i++) + data[i] = ret ? U64_MAX : priv->stats[i]; +} + +static void acx00_ephy_get_phy_stats(struct phy_device *phydev, + struct ethtool_eth_phy_stats *eth_stats, + struct ethtool_phy_stats *stats) +{ + struct acx00_ephy_priv *priv = phydev->priv; + + stats->rx_errors = priv->stats[ACX00_STAT_RX_CRC_ERRORS]; +} + +static int acx00_ephy_get_tunable(struct phy_device *phydev, + struct ethtool_tunable *tunable, void *data) +{ + struct acx00_ephy_priv *priv = phydev->priv; + int ret; + + if (tunable->id != ETHTOOL_PHY_EDPD) + return -EOPNOTSUPP; + + ret = phy_read_paged(phydev, ACX00_PAGE_1, + ACX00_PAGE1_UAPS_CONTROL_REG); + if (ret < 0) + return ret; + priv->uaps_enabled = ret & ACX00_PAGE1_UAPS_ENABLE; + + *(u16 *)data = priv->uaps_enabled ? ETHTOOL_PHY_EDPD_NO_TX : + ETHTOOL_PHY_EDPD_DISABLE; + + return 0; +} + +static int acx00_ephy_set_tunable(struct phy_device *phydev, + struct ethtool_tunable *tunable, + const void *data) +{ + struct acx00_ephy_priv *priv = phydev->priv; + bool enable; + u16 edpd; + int ret; + + if (tunable->id != ETHTOOL_PHY_EDPD) + return -EOPNOTSUPP; + + edpd = *(const u16 *)data; + switch (edpd) { + case ETHTOOL_PHY_EDPD_DISABLE: + enable = false; + break; + case ETHTOOL_PHY_EDPD_NO_TX: + enable = true; + break; + default: + return -EINVAL; + } + + ret = phy_modify_paged(phydev, ACX00_PAGE_1, + ACX00_PAGE1_UAPS_CONTROL_REG, + ACX00_PAGE1_UAPS_ENABLE, + enable ? ACX00_PAGE1_UAPS_ENABLE : 0); + if (!ret) + priv->uaps_enabled = enable; + + return ret; +} + +static int acx00_ephy_power_on_and_resume(struct phy_device *phydev) +{ + struct acx00_ephy_priv *priv = phydev->priv; + int ret; + + ret = priv->control->power_on(priv->control, phydev->mdio.addr); + if (ret) + return ret; + + ret = genphy_resume(phydev); + if (ret) + return ret; + + /* The control block loses the link-PHY vendor state while powered off. */ + return acx00_ephy_config_init(phydev); +} + +static int acx00_ephy_resume(struct phy_device *phydev) +{ + struct acx00_ephy_priv *priv = phydev->priv; + int ret; + + ret = acx00_ephy_validate_interface(phydev); + if (ret) + return ret; + + if (priv->wol_suspended) { + ret = acx00_ephy_config_interrupts(phydev, priv->wolopts, + false); + if (ret) + return ret; + + priv->wol_suspended = false; + return 0; + } + + return acx00_ephy_power_on_and_resume(phydev); +} + +static int acx00_ephy_suspend(struct phy_device *phydev) +{ + struct acx00_ephy_priv *priv = phydev->priv; + int resume_ret; + int ret; + + mutex_lock(&phydev->lock); + if (priv->stats_valid) + acx00_ephy_update_stats(phydev); + mutex_unlock(&phydev->lock); + + if (phydev->wol_enabled) { + ret = acx00_ephy_config_interrupts(phydev, priv->wolopts, + true); + if (!ret) + priv->wol_suspended = true; + + return ret; + } + + ret = genphy_suspend(phydev); + if (ret) + return ret; + + ret = priv->control->power_off(priv->control); + + mutex_lock(&phydev->lock); + priv->stats_valid = false; + mutex_unlock(&phydev->lock); + if (ret) { + resume_ret = acx00_ephy_power_on_and_resume(phydev); + if (resume_ret) + phydev_warn(phydev, + "failed to recover from suspend error: %pe\n", + ERR_PTR(resume_ret)); + } + + return ret; +} + +static void acx00_ephy_remove(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + int ret; + + ret = acx00_ephy_set_wake_irq(phydev, false); + if (ret) + phydev_warn(phydev, "failed to disarm wake IRQ: %pe\n", + ERR_PTR(ret)); + + device_set_wakeup_enable(dev, false); + device_set_wakeup_capable(dev, false); +} + +static int acx00_ephy_match_phy_device(struct phy_device *phydev, + const struct phy_driver *phydrv) +{ + struct device_node *node = phydev->mdio.dev.of_node; + + if (!genphy_match_phy_device(phydev, phydrv) || !node) + return 0; + + /* RK630 reports the same PHY ID, so require an X-Powers control link. */ + return of_property_present(node, "x-powers,ac200-control") || + of_property_present(node, "x-powers,ac300-control"); +} + +static struct phy_driver acx00_ephy_driver[] = { + { + PHY_ID_MATCH_MODEL(ACX00_EPHY_ID), + .name = "X-Powers AC200/AC300 EPHY", + .flags = PHY_ALWAYS_CALL_SUSPEND, + .match_phy_device = acx00_ephy_match_phy_device, + .probe = acx00_ephy_probe, + .read_page = acx00_ephy_read_page, + .write_page = acx00_ephy_write_page, + .soft_reset = acx00_ephy_soft_reset, + .config_init = acx00_ephy_config_init, + .config_aneg = acx00_ephy_config_aneg, + .read_status = acx00_ephy_read_status, + .config_intr = acx00_ephy_config_intr, + .handle_interrupt = acx00_ephy_handle_interrupt, + .get_wol = acx00_ephy_get_wol, + .set_wol = acx00_ephy_set_wol, + .remove = acx00_ephy_remove, + .set_tx_lpi = acx00_ephy_set_tx_lpi, + .get_sset_count = acx00_ephy_get_sset_count, + .get_strings = acx00_ephy_get_strings, + .get_stats = acx00_ephy_get_stats, + .get_phy_stats = acx00_ephy_get_phy_stats, + .update_stats = acx00_ephy_update_stats, + .get_tunable = acx00_ephy_get_tunable, + .set_tunable = acx00_ephy_set_tunable, + .led_hw_is_supported = acx00_ephy_led_hw_is_supported, + .led_hw_control_set = acx00_ephy_led_hw_control_set, + .led_hw_control_get = acx00_ephy_led_hw_control_get, + .led_polarity_set = acx00_ephy_led_polarity_set, + .suspend = acx00_ephy_suspend, + .resume = acx00_ephy_resume, + }, +}; +module_phy_driver(acx00_ephy_driver); + +static const struct mdio_device_id __maybe_unused acx00_ephy_tbl[] = { + { PHY_ID_MATCH_MODEL(ACX00_EPHY_ID) }, + { } +}; +MODULE_DEVICE_TABLE(mdio, acx00_ephy_tbl); + +MODULE_AUTHOR("James Hilliard "); +MODULE_DESCRIPTION("X-Powers AC200/AC300 Ethernet PHY driver"); +MODULE_LICENSE("GPL"); From patchwork Mon Aug 3 05:14:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2909 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 89E1F1C22D3 for ; Mon, 3 Aug 2026 07:25:37 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24927-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24927-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 2FC0D3044220 for ; Mon, 3 Aug 2026 05:17:26 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 666FF39D6FD; Mon, 3 Aug 2026 05:15:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ikalkrPa" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5881239768F for ; Mon, 3 Aug 2026 05:15:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734152; cv=none; b=pDlQzKvK0gDO7KCuzA1xpDcUojfG0OpMrjfOOfBJ7MH8lUt0QjdCx/zpmRXBmfLG13muiRPM5cNeTHqMoKUawA1+lozxUO1J4dAwHKTuf3EFTNfg+TMhpy5RZlWV0MRFj/4jwMUV6ALygtQaDlk9OdAZscm1DyidrFxey8jOOYY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734152; c=relaxed/simple; bh=CsTsehT4z8CJxsGhaiEo1pllL05TyPVSaHwPj6kU07s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=G/cPpN4M9hNGlJbdFYK+J0BOKRhCVCbPQKApnlegXNTY7C45henjz+AXlQMBAbpJQGmDRnT+PIB1ip2Cr4xwNDXGhOwdUbfWn8tAPy2mNlYkTpzRoA0hZPbkXT9TbnjXXTEJPjB6GG7aOnUvRrotNv6Jy3PDy6ZUy8qVEFmVpiE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ikalkrPa; arc=none smtp.client-ip=209.85.210.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f53.google.com with SMTP id 46e09a7af769-7ee37dc91f5so1801470a34.3 for ; Sun, 02 Aug 2026 22:15:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734149; x=1786338949; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=9OpRGWNf+wnvCcP1DS85gL+udlM+7o9ZcunosuNBCWA=; b=ikalkrPa/1xBk9AU4wzocyGIDDlRGEniygJgSIA4EAbBICPltH7JcmVDMJxjntIIvK 40id1Aq+JMq6n4Da/nCMXF7MkBI4a0I8Yaunn6QOfTlOh4+8jP+VYxTfXGcvFh87mgco L7GoAvDM8tE5Cj7hMJUUQ4kuM2VuFw0hNJ9YB6eJxaUWChROPDk/ClfNn7ogTeYBCxxK cTURia7eVAiSp8OSzoftDz7T+sC7w0sVaaD9gNtLMIUATmQWVXPNK6p/DeJ8nbaSFa9n 3bOaja74w2cJnAodJY2xIcguaPLkHY6had0ZZlXCyschP8tZ9ZdDn+stOlepUviovYog H0bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734149; x=1786338949; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=9OpRGWNf+wnvCcP1DS85gL+udlM+7o9ZcunosuNBCWA=; b=gnkdjB6lujkIm58mki/FsQRxwDPfEfuUH/byH5lxaT8744qFReEKNraEZSaMbclBpS vKUqrXiPUeY5oX9fksGHExcNC+1PJFuZNu194WIc28UID/UQ28FfNbOoA/uxD035+yq/ nxj50NKcJi1bmZAvDamWldaH0LSdPHEOZ0ZNh0dPxlXkSYKs4UQTUdco/u3R9s4Bss5X cY1xIXhNmBtvPefLXyPmaNZGsTQ1hJ1Bu9nVYPGhVhJtmmCOUo5qLV9o0qrEKD8k4P1M 37txH+LvjXM9VubCdjnIcOUTqj2NBRYCU1l+gH620rMS6qF+NqtQCCIoXNLPOl/3pQuI HzIw== X-Forwarded-Encrypted: i=1; AHgh+RrIoDHdntCVFKK8sTM+sP3rRNjMT3TWkac+dXI8L8dBDxJ86PA8RawYkY2m5AJ7L3BFc09GYQXAYa3JWQ==@lists.linux.dev X-Gm-Message-State: AOJu0YyCt2jg/5H/Ayabl3AvG0pjTDAUnRcHaIHYMoxIesro6oYfWYJx fkNBOMPHOMFykungW4grhtke6NNF9pLB/5vBkquyfo6Eb2jwUIardhS2 X-Gm-Gg: AR+sD10IXCCA6pXtF13qapp8HqIaEni3UtvJq76PE3PUQVvyWBMjwWhWkfmLGpD6BLX goYi6bmeKbtpALue4tAc5rrrEfL8ah5JeeQ8dZ+JG3AFU1VTLtvjpBC97hogTRPJ24VgA7t65lk m27PLten85eA7mftJIw7CLAvGKr57tE6Hrk9ns3Nq3D4i+rE+eIhPrPpCEvKenSsCMmoUZk0pWP ZGJAPmnkry35sv5e7IIeCxoUCpo6bqpnc0mCze5msKHjRE/MSMRIEqYHIWk+be36B2wNgfkddDc xwwBHB3RB7jU0xjRFQBjb2+Tk8jY7nK13RDnIwbMPUKaVIAuY7ofY2e87VZ/peB4Dk31YmIfYRD 8WiWTeKSUaNCBiRXVcYWxFlzkQk5XczxpmgSIeJFt2MUsENO4ka1joAcPjTYuRgPPkFefMdTdVh vWKqLppi+lLcBpSJ/csx5flKpkVGNTAp13/1zE63XFJNqbZu3OQU6akDRlss/SbnkhVunz8pYH1 ZLlVtjTbcpa4o0nZANacy+qlkorkqIjSdGQ+VbG0oO+juHpopI0G8sVNqlOlszMvbnEMAbWmEcA bo7qWDHiuyDgs8qZ4Cw5VsMhdp9tC9LKfTd+kgShLZndpqS5tbAUrZNCl80bsWapsiFo2U15OlH ZcN3RoHVMgh1LOxSx X-Received: by 2002:a05:6830:3592:b0:7e9:e488:3bce with SMTP id 46e09a7af769-7f196bab78dmr14968611a34.6.1785734148846; Sun, 02 Aug 2026 22:15:48 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:48 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:27 -0600 Subject: [PATCH 17/21] arm64: dts: allwinner: h616: add ACx00 EPHY resources Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-17-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Expose logical SID cells for the AC200/AC300 EPHY calibration, the combined companion-variant and AC300-calibration-range configuration, and the AC200 bandgap fields. Also describe the PA10/PA11 I2C3 pin group used by the AC200 control interface. Signed-off-by: James Hilliard --- arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi index 6879f27c2b2b..2cedda6e87a9 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi @@ -252,6 +252,20 @@ ths_calibration: thermal-sensor-calibration@14 { cpu_speed_grade: cpu-speed-grade@0 { reg = <0x0 2>; }; + + ephy_calibration: ethernet-phy-calibration@2c,0 { + reg = <0x2c 1>; + bits = <0 4>; + }; + + ephy_config: ethernet-phy-configuration@2c { + reg = <0x2c 2>; + bits = <8 2>; + }; + + ac200_bandgap: bandgap@30 { + reg = <0x30 2>; + }; }; timer0: timer@3009000 { @@ -324,6 +338,13 @@ i2c0_pins: i2c0-pins { function = "i2c0"; }; + /omit-if-no-ref/ + i2c3_pa_pins: i2c3-pa-pins { + pins = "PA10", "PA11"; + function = "i2c3"; + bias-pull-up; + }; + i2c3_ph_pins: i2c3-ph-pins { pins = "PH4", "PH5"; function = "i2c3"; From patchwork Mon Aug 3 05:14:28 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2907 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id B7E241C1C6F for ; Mon, 3 Aug 2026 07:23:53 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24930-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24930-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id C4EA330D5319 for ; Mon, 3 Aug 2026 05:17:57 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0BA223A9DAB; Mon, 3 Aug 2026 05:15:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="pQSRH865" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f43.google.com (mail-ot1-f43.google.com [209.85.210.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 22DE1399CEC for ; Mon, 3 Aug 2026 05:15:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734156; cv=none; b=p/c02Fwa41PpM5iQWO76bA03sCsNmw0CxCt9RScwLI8w8JtSGA1FvsNDG7sJ2glzTIg/nPTW9aoOVlKi3GieWKt1Mu6ZWHljtO4DiFPDLRHaB+mmExoZzcg+zBhYH4YX08ZipAh3dcdeVCoccppesC/eF/XRepL6mGklIUUGIGw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734156; c=relaxed/simple; bh=ZUVZReuwX6u+VOoUVGjsuCMz/MOgQoewZH495TiPLJ0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VFINpQeW5UNjIrbui5BF8v9Fa5nt//3DwdJFs3dw0h+4aQq7Y32rfN5sXNrYIIMs5w1ldGs2L0GAq8vn28BbF9rQreitLxE8qf70OFBP46Tgi8njhtSwMxlShqbeW/cn4bW5zKwGCf55u7zX03fRuI95VxocBD4xd0sH0CO8XD8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=pQSRH865; arc=none smtp.client-ip=209.85.210.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f43.google.com with SMTP id 46e09a7af769-7eb42a2f5feso1476478a34.1 for ; Sun, 02 Aug 2026 22:15:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734154; x=1786338954; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=OJn8bgDlexj3pTLFD/TVKu44xwgcekcV50vMMBDdgSo=; b=pQSRH865BUdH5PAKOC6mPqTdKZsLkDpX3r+H2iMRLlH9Bxek8OCpqY+HCEc3v9wZxH Sc7ozwNwHP+wWg1zfLyAOirgOfLGgvWR5D2udNoQWT3cma6/1qZVx6uPhs4ZGMEr0Ok/ o0etb8cJmYqyODGGn49+NMc4mrgKNPnTV4016cqtkROhAvguEgpAkBzIEU6KDMFHvOFp uV/Rj+htnQlOSe4xiIBVOOBEoTnU/TmX8IAch9tl9E/m82xZtnuV64AP9X+mci8xP7Tm HzaxMsHaLk/cKNqAv4YlnmFBEgLSm+ww49u/12WiFtxL/UNSFEzsCL7AYC1QutkQXMaD OYTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734154; x=1786338954; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=OJn8bgDlexj3pTLFD/TVKu44xwgcekcV50vMMBDdgSo=; b=D43y30iPSXW/OpQEXWTW1SK6HhdlCe5bCds9UMrBY87h3HxJocysUo6Iw998+WUVRT CQ/eZzeErVWQwcGJtmpakajsXOAxpipOTkp0bvOTNPUpzk7AoTwz1MdXNGYbNCHzPjEF Lns1kExtAJ/w8tH/zfPqxM1Okv5qAK9QDD1hD+j2B5anFe2qXAUCMOKDL7cmKF+kkjeE KHff60oWfzbZz0YnkXFdUeiYnIMNGBtWiHODtvtxo6IwNj2k1sf86o5iEpQXw84F7W0N hVF6JZ6PEcs36739xiwZF4l0iGiAIIQj8DmpVvQLlg1ln+YhEhTnM13vEYlH77Qm15pO 3dBw== X-Forwarded-Encrypted: i=1; AHgh+RpOkSNeuanCpNJZdj8uE4EsHfyBBDVttIU7JA5Urv/04AKUhjBd2G4ygN01lP33v/AReV+sFDNAWsJGjA==@lists.linux.dev X-Gm-Message-State: AOJu0YyOGCzUvOWynLjoFuNF6U3QkMO4OLHOAj+SWQEHyuS5Hm7X6+9h ZaYxJ2eQfiiUzjkSUyM1Uy+oj0rADZKChXNfYM+kf58rrzK9JIxuvuZL X-Gm-Gg: AR+sD10a1BBHVFM6qJQeBvllSjn8zjfZ0blYazOLi+3mPS5GKrsm9QerKdy9PblprT1 GZPqsGypSI0AsAeqmz09LEb7ifieC8tXHLXBRGAv7meQIB9fwOykvFA0qY3VevbNRJRLZznQfV9 bXpDJF+3sZePRzqlKMr9FpecxPOo7DI8CYA3APhx72CqLFcSRrSbPrIM/1hjeCMR3SPfHLVsmas K/KuKn1OczNIO2dY1ylmmZ0cYsuBGClSSfs5QTJPIijekswjtxvJTbOOEMEF7hVbXOHXtIYX2MY wPIsYp8nmjjA1Y94olCz7mfJSJMnHmKnpzBSjaHCzx/HLLiNMz5IkxEov0OJ9+hDV17vw4D/2bo xMbl3n1puiRPuqjqcTRDtsQsRXO6IpD2Lj8gIfg3A99rBmGDSpY5M2g07b4P/MxkddOMXpVs7Dz URcDx8uFl3lyQaeCyE8Yn95gVVObgF2Vw44L9PYf3cGBh9YUl/uEonfy0dDZA7P6tKwHsQylLmC jJ5nbJTHPlWiIMiQygfsvOaCY2Uxo5+YRc0ut5ktHfe7cyJju8F6GcKJ4Oup8P3zoquW7DWMW/t UbkBeG/j/WUqSLy4ahVFH7pMZfNYUJsxNHcBywGgx9685v/80iqKyo63oJGT10u6iyCxyP8evdt d35PmIObowJrkFe5/ X-Received: by 2002:a05:6830:82eb:b0:7eb:c933:eff7 with SMTP id 46e09a7af769-7f196f0d0e1mr13285248a34.9.1785734150243; Sun, 02 Aug 2026 22:15:50 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:49 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:28 -0600 Subject: [PATCH 18/21] arm64: dts: allwinner: orangepi-zero2w: enable Ethernet expansion Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-18-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[172.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; TAGGED_RCPT(0.00)[netdev,dt]; PRECEDENCE_BULK(0.00)[]; RCPT_COUNT_TWELVE(0.00)[34]; TO_DN_SOME(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo,0.0.0.0:email,0.0.0.10:email]; FORGED_SENDER_MAILLIST(0.00)[]; FREEMAIL_CC(0.00)[vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com]; FREEMAIL_FROM(0.00)[gmail.com]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10:c]; MIME_TRACE(0.00)[0:+]; RCVD_TLS_LAST(0.00)[]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; FREEMAIL_TO(0.00)[lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,arm.com,bootlin.com,foss.st.com,st.com,synopsys.com,armlinux.org.uk,sntech.de]; FROM_HAS_DN(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; TAGGED_FROM(0.00)[bounces-24930-noreply=patchwork.local]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: B7E241C1C6F X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= The optional Orange Pi Zero 2W expansion board exposes H618 EMAC1 through a 100 Mbit Ethernet jack. Add a reusable H616-family description of the AC200/AC300 EPHY wiring alongside its first board user. The forced-ID link PHY selects the populated control path and AC300 tuning range from the logical SID configuration field. Keep the AC200 I2C controller and AC300 MDIO control node at status fail-needs-probe so only the selected path claims its pins. Enable EMAC1 and its PWM clock provider through the common include, provide the board's 3.3 V rail to either companion variant, and make EMAC1 the board Ethernet alias. Signed-off-by: James Hilliard --- .../boot/dts/allwinner/sun50i-h616-acx00-ephy.dtsi | 61 ++++++++++++++++++++++ .../dts/allwinner/sun50i-h618-orangepi-zero2w.dts | 13 +++++ 2 files changed, 74 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-acx00-ephy.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616-acx00-ephy.dtsi new file mode 100644 index 000000000000..26521429957a --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-acx00-ephy.dtsi @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Common X-Powers AC200/AC300 Ethernet PHY support for H616-family SoCs + * + * Copyright (C) 2026 James Hilliard + */ + +&emac1 { + phy-handle = <&acx00_ephy>; + status = "okay"; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pa_pins>; + status = "fail-needs-probe"; + + ac200: mixed-signal@10 { + compatible = "x-powers,ac200"; + reg = <0x10>; + clocks = <&pwm 5>; + nvmem-cells = <&ac200_bandgap>; + nvmem-cell-names = "bandgap"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm5_pin>; + + ac200_ephy_ctl: ethernet-phy-control { + compatible = "x-powers,ac200-ephy-ctl"; + nvmem-cells = <&ephy_calibration>; + nvmem-cell-names = "calibration"; + phy-mode = "rmii"; + }; + }; +}; + +&mdio1 { + ac300_ephy_ctl: ethernet-phy-control@10 { + compatible = "x-powers,ac300-ephy-ctl"; + reg = <0x10>; + clocks = <&pwm 5>; + nvmem-cells = <&ephy_calibration>; + nvmem-cell-names = "calibration"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm5_pin>; + phy-mode = "rmii"; + status = "fail-needs-probe"; + }; + + acx00_ephy: ethernet-phy@0 { + compatible = "ethernet-phy-id0044.1400"; + reg = <0>; + nvmem-cells = <&ephy_config>; + nvmem-cell-names = "configuration"; + x-powers,ac200-control = <&ac200_ephy_ctl>; + x-powers,ac300-control = <&ac300_ephy_ctl>; + }; +}; + +&pwm { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts b/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts index b340bbcb710d..e833ee267c83 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts @@ -6,6 +6,7 @@ /dts-v1/; #include "sun50i-h616.dtsi" +#include "sun50i-h616-acx00-ephy.dtsi" #include "sun50i-h616-cpu-opp.dtsi" #include @@ -17,6 +18,7 @@ / { compatible = "xunlong,orangepi-zero2w", "allwinner,sun50i-h618"; aliases { + ethernet0 = &emac1; serial0 = &uart0; }; @@ -54,6 +56,17 @@ reg_vcc3v3: vcc3v3 { }; }; +&ac200 { + ac-ldoin-supply = <®_vcc3v3>; + ephy-vcc-supply = <®_vcc3v3>; + rtc-vcc-supply = <®_vcc3v3>; + tv-vcc-supply = <®_vcc3v3>; +}; + +&ac300_ephy_ctl { + vcc1-supply = <®_vcc3v3>; +}; + &codec { allwinner,audio-routing = "Line Out", "LINEOUT"; status = "okay"; From patchwork Mon Aug 3 05:14:29 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2906 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id 0D1181C0575 for ; Mon, 3 Aug 2026 07:23:39 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24929-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24929-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 8D1E43047066 for ; Mon, 3 Aug 2026 05:17:42 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 834943A872C; Mon, 3 Aug 2026 05:15:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VPHjWEgi" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oi1-f174.google.com (mail-oi1-f174.google.com [209.85.167.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B7E9B3A640C for ; Mon, 3 Aug 2026 05:15:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734155; cv=none; b=nK7ToJEHIFkjCptLDqSEXgZiQM3EToCqAQqICBMmPGhw0Dn+IhPSBnIr9jVqiB/FYhBjOLqBCEIQAAk/Opcw1rGo8bvtF03VWvQaGqS/CoFN3S7/iAGSSJ5gSxoSv3LPKPdI4vp/OIvKpHXd/xaq2GgdTRQ9bkK0u4pXGtCLlhU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734155; c=relaxed/simple; bh=6ziM+f30xkSte3zlDzpBhj7lMZ8ieILh8cGDDWCvnhA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aog0XYn7MCqdujs6AaIX9BrYNic2jqxv/Tl2jSuFpV2r2vdNmo+ahWqup2F/VbgBe50tHmSZyNAANzVBVneKmbSv9L1cxjg3WAAkZ2mV3aQrSbVAVUIHZOUhwWSQanezEe0ESOBr82cYVQbzUoKzEbjsoILsKNGyla/a9fesL2Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=VPHjWEgi; arc=none smtp.client-ip=209.85.167.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oi1-f174.google.com with SMTP id 5614622812f47-497d3e4460aso3200695b6e.1 for ; Sun, 02 Aug 2026 22:15:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734151; x=1786338951; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=e9FeknYPclzv16XYXDkTzfHxoN/DCYzLCAYv6oC+ejo=; b=VPHjWEgiiLRJYJE2xhv3ovGySiPueX8vJt2KNfKMi7iHnvep++xlNRLsTHH1TWFOjK b6sgdHxUttTEl7oU/PajYc4YCrVFeoQdOLOBOBDQsZCc5Ir7w17sUbuosHB27jkdimoc Upqsl/oanKcHBGUKqsS7NN5F3hvjfR6/LoOxBOCOi7Bw1u60ZBPYRXhdCvOmJytd9D5w ixxEkUbEeflkNWDaAR1rTClUuUAtA6qWBllD4mUaVmAbV7i1YcXVlUZT7tl2UmMAWL/6 kRJU7gdrdbeHTWA3VYq1RrKsRZGSKGAW63OOOAEKjYNheiD7r/2zHblsa/mUB+VM01Zv 1exA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734151; x=1786338951; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=e9FeknYPclzv16XYXDkTzfHxoN/DCYzLCAYv6oC+ejo=; b=LigUU8cuF4+jY3rGK4n/wgz3hmXODDRHDwxpg1qzG4lG76047DhJa7SjeziAVuCbv5 J/EQaUgJR7+cqNarFVkrWJgtt/f3IedHPL8S2b/boHMSHAijof53Qq0cvJpxfWDZS6pB 7oL027eKa8Wx8S9n2YSLfut3pk6L7ERKpEIRRdvVKIVeikV+ySJORzGENDrz0pIt98jg Jk2WCTnIyqxZGlBE6aoB3d85KUmnoyh9shcH0JwsMFqzomv5xVIKBi7tQT2HI5yTAaaa 8g8Z2sS10lSJPnZnutgbrtutzrqNAA6yKw1Fx6Vi3OEJTLOnV5v/JfejvxzOz/+9gx1W FbAg== X-Forwarded-Encrypted: i=1; AHgh+RqkORFbi2WG4sHjRQ7+3bt54TFEow222OEejqYqEiwAynqUvdswkj5fuXfgkPFbv23QMob1q3Wv79RZmw==@lists.linux.dev X-Gm-Message-State: AOJu0YyefaSOp41gR7yRSFBBXDYed3ifZnyqXKJqhj84jP4JcDOYfXhQ kHt1WDT+qMGK5gc2XETqbE5+wabBg8vL3WYxNScAqHhf3Q1KJLIyDRuT X-Gm-Gg: AR+sD13fr7+P7SkBDKfsh76B7JoKMSs640VYJDxMmGs0Aa23gIMuhF61pA4OUE0+oMB eZDwA/pTcNfSInUsr7Z3Azc3PaV1A1BjrWmif2DJ8z4IK2nGwVNzse0PQs01/WKXywmhP6hMBhF WUQKWTJ1ooAQ51f1RfXP5tbN5h224c5u+1wjMtIG/31lSia+VnEYUF60YAnQlGJ9elNKrFKxiGE pFxSk55gREb03vqKPEEXmAf+WaJqyh6vCESGWMWNxVjTnx/qmQX8z6gmdlGxiz5kogT7ZhxqTb2 wT6hpl7Cahj1hMsh7l7t88lHLIl65bf2D1iS1q4OQwd8Y68H/rXU1Ih4s/ZtglC/1c74IHb+Vds KTyLGCX4y42pqXzdEmZO0V51rD5U5AOgUhnH0cznwiRtcwoiS9kOjyWMYTg/yuOm2/SBwyTn2k2 pDrgalEBpNQc96ydXOc1QtkxD93D/Iksj0h6Ldg/OFgNhQGmUhRLpvsoV2UiYrKOhNyB0DvHYqN T7qFwepBTbv5TcAmU6Lsg/6Nd1b3e9CZg7+sz+D1cUmmgIdYIJ7B2xIOqRLJ8beGoZ2iGS7QpwQ B7Ios+jUr6i3Ww7BIuTuiUwKQczwXS5dNTcdB4m7TMRGcKl1TatchP27KbUHlsiqWSZyy3rUvNE 0t54snozpVmzDARzH X-Received: by 2002:a05:6808:1797:b0:495:f697:92d9 with SMTP id 5614622812f47-4ae3188b02dmr15246163b6e.7.1785734151556; Sun, 02 Aug 2026 22:15:51 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:51 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:29 -0600 Subject: [PATCH 19/21] arm64: dts: allwinner: h6: add AC200 EPHY resources Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-19-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[172.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; TAGGED_RCPT(0.00)[netdev,dt]; PRECEDENCE_BULK(0.00)[]; DBL_PROHIBIT(0.00)[0.76.114.80:email,0.45.233.232:email]; DBL_BLOCKED_OPENRESOLVER(0.00)[0.76.86.48:email,0.0.0.14:email,0.0.0.30:email,0.0.0.10:email,sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo]; FORGED_SENDER_MAILLIST(0.00)[]; RCPT_COUNT_TWELVE(0.00)[34]; FREEMAIL_CC(0.00)[vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com]; TO_DN_SOME(0.00)[]; FREEMAIL_FROM(0.00)[gmail.com]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10:c]; MIME_TRACE(0.00)[0:+]; RCVD_TLS_LAST(0.00)[]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; FREEMAIL_TO(0.00)[lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,arm.com,bootlin.com,foss.st.com,st.com,synopsys.com,armlinux.org.uk,sntech.de]; FROM_HAS_DN(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; TAGGED_FROM(0.00)[bounces-24929-noreply=patchwork.local]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 0D1181C0575 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Add the H6 I2C3 controller and pinmux, the PWM-derived 24 MHz AC200 clock, SID calibration cells, RMII pinmux, and the AC200 MFD and EPHY control nodes. Describe the co-packaged AC200 INTB output on PB20. Keep both reusable AC200 nodes disabled so boards must explicitly enable the parent and its EPHY control function when the companion is present. Signed-off-by: James Hilliard --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 73 ++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 72ce1a75647b..55e6e185a4e5 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -17,6 +17,16 @@ / { #address-cells = <1>; #size-cells = <1>; + ac200_pwm_clk: ac200-clock { + compatible = "pwm-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm1_pin>; + pwms = <&pwm 1 42 0>; + status = "disabled"; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -314,6 +324,15 @@ ths_calibration: thermal-sensor-calibration@14 { cpu_speed_grade: cpu-speed-grade@1c { reg = <0x1c 0x4>; }; + + ephy_calibration: ethernet-phy-calibration@2c,0 { + reg = <0x2c 1>; + bits = <0 4>; + }; + + ac200_bandgap: bandgap@30 { + reg = <0x30 2>; + }; }; timer@3009000 { @@ -368,6 +387,13 @@ ext_rgmii_pins: rgmii-pins { drive-strength = <40>; }; + ext_rmii_pins: rmii-pins { + pins = "PA0", "PA1", "PA2", "PA3", "PA4", + "PA5", "PA6", "PA7", "PA8", "PA9"; + function = "emac"; + drive-strength = <40>; + }; + hdmi_pins: hdmi-pins { pins = "PH8", "PH9", "PH10"; function = "hdmi"; @@ -388,6 +414,12 @@ i2c2_pins: i2c2-pins { function = "i2c2"; }; + i2c3_pins: i2c3-pins { + pins = "PB17", "PB18"; + function = "i2c3"; + bias-pull-up; + }; + mmc0_pins: mmc0-pins { pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5"; @@ -414,6 +446,11 @@ mmc2_pins: mmc2-pins { bias-pull-up; }; + pwm1_pin: pwm1-pin { + pins = "PB19"; + function = "pwm1"; + }; + /omit-if-no-ref/ spi0_pins: spi0-pins { pins = "PC0", "PC2", "PC3"; @@ -626,6 +663,42 @@ i2c2: i2c@5002800 { #size-cells = <0>; }; + i2c3: i2c@5002c00 { + compatible = "allwinner,sun50i-h6-i2c", + "allwinner,sun6i-a31-i2c"; + reg = <0x05002c00 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_I2C3>; + resets = <&ccu RST_BUS_I2C3>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; + clock-frequency = <400000>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + ac200: mixed-signal@10 { + compatible = "x-powers,ac200"; + reg = <0x10>; + clocks = <&ac200_pwm_clk>; + interrupt-parent = <&pio>; + interrupts = <1 20 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <1>; + nvmem-cells = <&ac200_bandgap>; + nvmem-cell-names = "bandgap"; + status = "disabled"; + + ac200_ephy_ctl: ethernet-phy-control { + compatible = "x-powers,ac200-ephy-ctl"; + nvmem-cells = <&ephy_calibration>; + nvmem-cell-names = "calibration"; + phy-mode = "rmii"; + status = "disabled"; + }; + }; + }; + spi0: spi@5010000 { compatible = "allwinner,sun50i-h6-spi", "allwinner,sun8i-h3-spi"; From patchwork Mon Aug 3 05:14:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2908 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4]) by mxe881.netcup.net (Postfix) with ESMTPS id BC3F91C0575 for ; Mon, 3 Aug 2026 07:24:58 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 104.64.211.4) smtp.mailfrom=linux-sunxi+bounces-24931-noreply=patchwork.local@lists.linux.dev smtp.helo=sin.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 104.64.211.4 as permitted sender) client-ip=104.64.211.4; envelope-from=linux-sunxi+bounces-24931-noreply=patchwork.local@lists.linux.dev; helo=sin.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sin.lore.kernel.org (Postfix) with ESMTP id 7371E304949A for ; Mon, 3 Aug 2026 05:18:21 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4692839A7F2; Mon, 3 Aug 2026 05:16:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="X5Vd9DxV" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f48.google.com (mail-ot1-f48.google.com [209.85.210.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B70743AAF6C for ; Mon, 3 Aug 2026 05:15:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734160; cv=none; b=X9JFKdEifq0zH6/OkleqadnaQJIidcUizXnCrhTW2PdqOHJn6exLI+068dvZJ88nDY8MUFaMjwm0kX5g1ijJmNVH4TfxlY9T7EbIEj+7+rywaN6KpJ8COyRbwd6la2X+ouQfhU42bBxPW7rFrwsq2LmtJ4MC4yOnkTTCdANgyCY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734160; c=relaxed/simple; bh=gC2dTirWRvmFzKHVs4SyB39x7wyh/gb+c26PdnYQrvQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OIm4hapPBXi7VD1h7qnce0KCnhT5ympjDBkxtPn+rrU+8TnTqR9mGi/r0hk/8voBlUvzH8dt3DuhlqnAgfHFo/Pwe6Q0cbBGfJsgrzYMrj6Mjsys0LvZMFevUZ9KXvvCkDz/ISeF0deeAMNKaRwfF70AJjsedJtD0O25cJVkeM8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=X5Vd9DxV; arc=none smtp.client-ip=209.85.210.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f48.google.com with SMTP id 46e09a7af769-7e6b554044fso2627424a34.0 for ; Sun, 02 Aug 2026 22:15:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734157; x=1786338957; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=1CvTLJea6zWTpGRaWOgZzRKuhjdqcAVM/Zr8VD5aTmI=; b=X5Vd9DxVAT65LmnKa+N5KTKCD3vS2IyxYuXxMGz5aeMnoEVlerxQefNDFs84D+4SH1 SrJ1ciJdvvO+84/GKeXeFWEdbbbCudbeE61kraMFhUA2AFYlUKGEk1Z7c7V1Sx1wrusz dlaocWILE+Ck/kqhyQKxYlGpAwu6/u3Twjpzb6qzyGtL47EfZCQ15Y44r1DoHohHsF16 XyQ4lwD6k0HnZbc0sjsWEGWEzYe0Uhfig81yZxxfAPDkbBCETN86Uyd8gSd2fKjxxayf 9S+pDejxt9nU801uheXLAraMDdStNokknHfJcn7Ok/3G4/yof370B4lP0I5Lk5iMnhWr 5H2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734157; x=1786338957; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=1CvTLJea6zWTpGRaWOgZzRKuhjdqcAVM/Zr8VD5aTmI=; b=Rlw/6lyfkNez2pcartmVGrSyBdmikYWXtUjdpZHkZswCMUzPUdEd9c6cu+yGKcDAbi Vpfvq86fOvCklQMTDBOEWEr12h4xbIlolwCn0MOETKodq1IEH9G+ghxLLuEmICXoFy8E 4LL+3Wgj6qQ6WPYwvwYz7rhrDqvQCPSj4wLyO3Lptm4TJURjEFzk2nEWfRBNLpMJju/G FdMq5SBfoq+9ijlsN7idE4p9QX92djQyPAhs0bDyZE2ZrW3XP8SJBSxOjp8woS5Od80o sSuv/EmNreLjs+4xAFBq8do8mCV/d3nqKlUa6uB1X1PyCeVzcID8Q7qg+hzh6/WluQDe cHRA== X-Forwarded-Encrypted: i=1; AHgh+RqhrJUlz9/MvflC2TvcVaugYDCHkAjc+L+LjngrFW9LZTH2cbSqxYwf0f+aA7L73RUvn2iJgOnZPXUBqA==@lists.linux.dev X-Gm-Message-State: AOJu0YwZY4fTNMJG/HyHLbuBe1iwLV3ch+pMNqxOhNOQqEYVLyQxsKCB ZnmVpf0GALz7qTyiK0OHvZuvyRn6Ni1tMGpq6xH+8dvi3YWF57KJv3i+ X-Gm-Gg: AR+sD10850Ks3CPEtewWaOy207vBM4Op0+hLgOhFsYxJLVN3oBqmVMEkyQL2q0vjyVs HRo6S+bxbv2XVPzL7IOTS5UFna/QaGmLDW+YwULllHHfLU70aZP6F8J6MeWkntLkUrc2aRyC0ZW FEankWqbnXOl4Il9izkk/F5SPU/IrU8fbY3hbpmeT32uIPheC/nsYuVsMV5/HYOBlbucH8y137u np33pTEH47IHQdC52pbCfxy3o7ycB9sSSRO45KD/wXaGiVCw18CpraVFRpIzMN3j3CZ37nVbpAz TPY5DiPxOwVpA53hS2pwQfVgtg0kasqLZF2IxP5oJ7gcwWbw9QqW1PXD9l3Z+BbeGHL6nDNiCbJ H026sQCJFcL023AxaGjThkwdA7VymkYcElVs+GTr1jjvfqXBor3HGz6OmiPIu5RKeJHwygryf9B zCJGIwIo9P8tsZdV38OiKO9NqDAGXKqgxGgOv5J2NW5CwvS/qy9azgqTI9Ifkt8WriItDjP7KmL iZNAXHFVaCvIYz3D2e+CkX3nKbzw7u64+Q/AfQQv+Q6L+4xixTZ/9hzDuKvuJ9skIJGbCZ8mVNK GgIyFKdOATvwwu7pZcG+jNNHr85gt15xIdUNFPnzZyGCdDCfKVOQup400391X6aGffqeU68dYVq RBGZa4HPdSWKTnFcO X-Received: by 2002:a05:6830:398d:b0:7dc:e090:68a with SMTP id 46e09a7af769-7f1969181f7mr14873339a34.0.1785734152850; Sun, 02 Aug 2026 22:15:52 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:52 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:30 -0600 Subject: [PATCH 20/21] arm64: dts: allwinner: h6: tanix: enable AC200 EPHY Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-20-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[104.64.211.4:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; HAS_LIST_UNSUB(-0.01)[]; PRECEDENCE_BULK(0.00)[]; FROM_HAS_DN(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[0.0.0.1:email,sin.lore.kernel.org:rdns,sin.lore.kernel.org:helo]; TAGGED_RCPT(0.00)[netdev,dt]; FORGED_SENDER_MAILLIST(0.00)[]; FREEMAIL_CC(0.00)[vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com]; RCPT_COUNT_TWELVE(0.00)[34]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:104.64.192.0/19, country:SG]; R_SPF_ALLOW(0.00)[+ip4:104.64.211.4]; FREEMAIL_TO(0.00)[lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,arm.com,bootlin.com,foss.st.com,st.com,synopsys.com,armlinux.org.uk,sntech.de]; FREEMAIL_FROM(0.00)[gmail.com]; TO_DN_SOME(0.00)[]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; TAGGED_FROM(0.00)[bounces-24931-noreply=patchwork.local]; MIME_TRACE(0.00)[0:+]; MID_RHS_MATCH_FROM(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: BC3F91C0575 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Enable the AC200 control path and RMII Ethernet link on the Tanix TX6 family, and provide the board's 3.3 V rail to the AC200 function supplies. Route the PHY interrupt through the AC200 interrupt controller and mark it as a wakeup source for link interrupts and magic-packet wake. Signed-off-by: James Hilliard --- arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi index bb7de37c0d58..6cd75961e3cc 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi @@ -7,9 +7,11 @@ #include "sun50i-h6-cpu-opp.dtsi" #include +#include / { aliases { + ethernet0 = &emac; serial0 = &uart0; }; @@ -84,6 +86,22 @@ wifi_pwrseq: wifi-pwrseq { }; }; +&ac200 { + ac-ldoin-supply = <®_vcc3v3>; + ephy-vcc-supply = <®_vcc3v3>; + rtc-vcc-supply = <®_vcc3v3>; + tv-vcc-supply = <®_vcc3v3>; + status = "okay"; +}; + +&ac200_ephy_ctl { + status = "okay"; +}; + +&ac200_pwm_clk { + status = "okay"; +}; + &cpu0 { cpu-supply = <®_vdd_cpu_gpu>; }; @@ -104,6 +122,14 @@ &ehci3 { status = "okay"; }; +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&ext_rmii_pins>; + phy-mode = "rmii"; + phy-handle = <&ac200_ephy>; + status = "okay"; +}; + &gpu { mali-supply = <®_vdd_cpu_gpu>; status = "okay"; @@ -119,6 +145,21 @@ hdmi_out_con: endpoint { }; }; +&i2c3 { + status = "okay"; +}; + +&mdio { + ac200_ephy: ethernet-phy@1 { + compatible = "ethernet-phy-id0044.1400"; + reg = <1>; + interrupts-extended = <&ac200 AC200_IRQ_EPHY>; + wakeup-source; + x-powers,ac200-control = <&ac200_ephy_ctl>; + x-powers,xmii-rx-clock-inverted; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; @@ -162,6 +203,10 @@ &pio { vcc-pg-supply = <®_vcc1v8>; }; +&pwm { + status = "okay"; +}; + &r_ir { status = "okay"; }; From patchwork Mon Aug 3 05:14:31 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 2910 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4]) by mxe881.netcup.net (Postfix) with ESMTPS id CA00E1C0244 for ; Mon, 3 Aug 2026 07:25:36 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 104.64.211.4) smtp.mailfrom=linux-sunxi+bounces-24932-noreply=patchwork.local@lists.linux.dev smtp.helo=sin.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 104.64.211.4 as permitted sender) client-ip=104.64.211.4; envelope-from=linux-sunxi+bounces-24932-noreply=patchwork.local@lists.linux.dev; helo=sin.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sin.lore.kernel.org (Postfix) with ESMTP id 19010301B16C for ; Mon, 3 Aug 2026 05:18:30 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 126433ACF0A; Mon, 3 Aug 2026 05:16:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="r0B5R/1j" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f50.google.com (mail-ot1-f50.google.com [209.85.210.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 864F23ACA4C for ; Mon, 3 Aug 2026 05:16:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734162; cv=none; b=nwl2XspceTh5JgLuG87ebsnSZCGbe1UiMuZYRmEOKfpPi2qm2hr3BP7eWNERLktGpSZu0ETl/U1sBXNxKd9bGVfVwoRNq6uWOtqzV6Am4JdxrTMwRQqgP+1F9haJKFJft4ppYkMe9KXkx7wcmh2+LbrY9oj48s753QKxpC+duSI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785734162; c=relaxed/simple; bh=GJHoT3sGNBaHJutusjqByQrs0uUzgfDmspxJwWo+2Fw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JYwXv+XQN9YU98ShtHxw6xxovk29AQO4j736z6etIuhGUojCDS0Iwm/APFtmLO1x3rH/fp/A+9YKT9o8q1vourHkIUiRnH2PimzGiXRPrR73VbZkQJ5Dv5ehcDusygOvwuD1eS6NAzuFG85F+eDI0fc7dvygnDF1qCDV3bOvDmc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=r0B5R/1j; arc=none smtp.client-ip=209.85.210.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f50.google.com with SMTP id 46e09a7af769-7eb6573bd52so2068286a34.3 for ; Sun, 02 Aug 2026 22:16:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785734159; x=1786338959; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=V3THAfFmoIZwxbw2uyAABLxKH+fs/K6w42J64CA1198=; b=r0B5R/1jRND4rSMHZwMlN749RtmPM2mh03SpUigttDhvTz8FHqcT26QBE2UsAXPmwR a2WuttEnYCYvR+z7Zt+6V84OyGNIkl/+8THr6groX579IH+3fmO32FB+Pz5kSPoR46Yo RwbdmNgKDnHAxlntpvkba/8BqteTWPhopjpPbwb0gToi/3Da54BuEkTztM3I0RoJpzDF 9m2FKpl253EZA7dYn9+IoCexp4bjjByC/iscf1y8v9CuNZCpHtnXQTlt+0616xy6lsAx 2dVYoLZNqOyts0KFvonvT9Y5TiHCDup35lmc3ujfBs1AniRbYA1uo1+j1z/QEhJdZuJE r+jg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785734159; x=1786338959; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=V3THAfFmoIZwxbw2uyAABLxKH+fs/K6w42J64CA1198=; b=S9HlI2EI0HDzvFCb4pCmZBXUcnpLjfN64ryyK+MD+N3qVMOpymXrQZ1yJQyWmoDSX2 /9tNdKqqmfNYE1JSgDjR6K2qO+hGQkRWZIKOB2hlUClqe8iAlrGXKyjKoyrUDLSCvQ4W SS6JJcmWBZVz2uU3N8q7bcrjXqQVZ9bZ8+ZgHurlpS9t/s8bmVnfy+deJWuwpMnePBX1 hpR8ObHMGtBk1zMp5Zu9xsR2l1xpgFW2R8iHiCvn9BUomSjP/R7XvKAQGiwFiiRWpE2C mNAUxOcllab5sc3jnG1I4TdV3QC6WyR+v3foLyEccWgbowPA3T1VzBYn5knq908L7B0S s+SA== X-Forwarded-Encrypted: i=1; AHgh+RqjJoyMQQ0/4HLyu/giuQRMpQbiZR8X0IFVvXHLZ2SXiBpeKI3Q5sYs3mJuYgdy3FPhXZoP4mztix91FA==@lists.linux.dev X-Gm-Message-State: AOJu0YwH9R+JMQrjC9PR1oB1nD89+qnjJBd8H623xVFJ6889wf7TSmC8 BNq6tk31gzBdQENTvy9KGrZBLcpadEg1vkyq8M2D6gddelLHiJYF31lU X-Gm-Gg: AR+sD10zno5sCDF96Otr85r3oI3RCR4hrA3ByYSn8trPnbnBO4umGp64DY9OZIqLwTg f/HwQQ+TNKfedIfk/bW6DpS4+QBnL0tSjHJeXwilICGVdbg9s6U3r0NR+++H124Mt+RHn6yfkDW e0+pDVMP2u4NFbE/R/Qx8OOzhNJ4AhCRkb38cGccu6Mea5hl1UJMXeVZF+ZD8Bbn5/IGVGSK8yV oL9dg7SNhCKBIC7a/Vh8CMoetOb0noVEJpCEhI0xwBiFR8rs1HY6l9iNcJu3JsSPieSKdns2md3 3KrE7qUzv6OUrotCd3BRabtV6DWZwIctiYOAUtfsKCIDvKnHnE7aUCEUeif8frXBL66uxjnGDre GeyULRiM7YCMEJea5KYlDvxpUBe6ZKDIljM+4JqwRe9F3ZgtGSzCkO+jsZReppDppuSszA9ovtJ NVlWEHgvtJgZCB58Ki4LISH/nNkmOhifsz82gt7YzpMgfhqFM6vm43+rGryHFNqKwM2eN4s9kqj mWKtYdBvtj4KPxYAubwcL1ZUkyMjewBHFuK1jsJWsios94S8BjAzgd/01prQC0Em8TsXkshRLjx 4n7wbSpDVgjSq1mZ57Edzw8f5yQr+9h7BakuAYbVntDQHzYTuKUnwZlNsp6bRBLdRzI3NwcJgLT i52+Ed078JWp7Fn+dzoUw0ljTizKLs29+bqdK X-Received: by 2002:a05:6830:2a8b:b0:7e6:f7fb:9678 with SMTP id 46e09a7af769-7f196cb65a7mr14526881a34.1.1785734154482; Sun, 02 Aug 2026 22:15:54 -0700 (PDT) Received: from [127.0.1.1] (184-96-154-59.hlrn.qwest.net. [184.96.154.59]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f18f07a5e3sm6787108a34.15.2026.08.02.22.15.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 22:15:54 -0700 (PDT) From: James Hilliard Date: Sun, 02 Aug 2026 23:14:31 -0600 Subject: [PATCH 21/21] arm64: defconfig: enable X-Powers ACx00 Ethernet support Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260802-submit-acx00-of-dynamic-v1-v1-21-0a53cd9e21cc@gmail.com> References: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> In-Reply-To: <20260802-submit-acx00-of-dynamic-v1-v1-0-0a53cd9e21cc@gmail.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andre Przywara , Richard Genoud , Maxime Ripard , Alexandre Torgue , Giuseppe Cavallaro , Jose Abreu , Maxime Chevallier , Maxime Coquelin , Andrew Lunn , Heiner Kallweit , Russell King , Saravana Kannan , Lee Jones , Heiko Stuebner Cc: netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, mfd@lists.linux.dev, linux-rockchip@lists.infradead.org, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[99.99%]; RBL_SENDERSCORE(2.00)[104.64.211.4:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; TAGGED_RCPT(0.00)[netdev,dt]; PRECEDENCE_BULK(0.00)[]; RCPT_COUNT_TWELVE(0.00)[34]; TO_DN_SOME(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[sin.lore.kernel.org:rdns,sin.lore.kernel.org:helo]; FORGED_SENDER_MAILLIST(0.00)[]; FREEMAIL_CC(0.00)[vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com]; FREEMAIL_FROM(0.00)[gmail.com]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; R_SPF_ALLOW(0.00)[+ip4:104.64.211.4:c]; MIME_TRACE(0.00)[0:+]; RCVD_TLS_LAST(0.00)[]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; FREEMAIL_TO(0.00)[lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,arm.com,bootlin.com,foss.st.com,st.com,synopsys.com,armlinux.org.uk,sntech.de]; FROM_HAS_DN(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; ASN(0.00)[asn:63949, ipnet:104.64.192.0/19, country:SG]; TAGGED_FROM(0.00)[bounces-24932-noreply=patchwork.local]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: CA00E1C0244 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Build the H616 PWM clock provider, AC200 MFD, both variant-specific EPHY control drivers and the shared link-PHY driver as modules. Enable the netdev LED trigger as a module so DT-described PHY LEDs can use hardware offload. Signed-off-by: James Hilliard --- arch/arm64/configs/defconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 654a102cb5bc..53f6b8edaf33 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -475,6 +475,9 @@ CONFIG_DP83869_PHY=m CONFIG_DP83TD510_PHY=y CONFIG_DP83TG720_PHY=m CONFIG_VITESSE_PHY=y +CONFIG_XPOWERS_AC200_PHY_CTL=m +CONFIG_XPOWERS_AC300_PHY_CTL=m +CONFIG_XPOWERS_ACX00_PHY=m CONFIG_XILINX_GMII2RGMII=m CONFIG_CAN_FLEXCAN=m CONFIG_CAN_XILINXCAN=m @@ -828,6 +831,7 @@ CONFIG_BCM7038_WDT=m CONFIG_MFD_ADP5585=m CONFIG_MFD_ALTERA_SYSMGR=y CONFIG_MFD_BD9571MWV=y +CONFIG_MFD_AC200=m CONFIG_MFD_AXP20X_I2C=y CONFIG_MFD_AXP20X_RSB=y CONFIG_MFD_MACSMC=m @@ -1325,6 +1329,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_CPU=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m CONFIG_EDAC=y CONFIG_EDAC_GHES=y CONFIG_EDAC_LAYERSCAPE=m @@ -1726,6 +1731,7 @@ CONFIG_PWM_SAMSUNG=y CONFIG_PWM_SL28CPLD=m CONFIG_PWM_STM32=m CONFIG_PWM_SUN4I=m +CONFIG_PWM_SUN8I=m CONFIG_PWM_TEGRA=m CONFIG_PWM_TIECAP=m CONFIG_PWM_TIEHRPWM=m