From nobody Fri Jul 24 20:51:08 2026 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.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 5D729385D8E for ; Fri, 24 Jul 2026 18:45:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784918738; cv=none; b=VNBWm2Uh1Ldr+hVqID2KCQYwOR2RC0apRreOl+R1GEKDispElTe39Gl1Qd6nprJfnyQGo77021+Q5T9vD+ilZUYyyjRB1+adUvaJKVI3B6WBGJ/CeVB3Zv7Bk6Mnjxn3IabFeJHdd0nXJt0VknsIygAEEQZMaIBLz0OKRJS3Pis= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784918738; c=relaxed/simple; bh=ynuOULMP4iOziuYv2J6d3jxrIlvxTnPee/5KsaaChHA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aCNBMmtNeTTpyZU6LLVUihUEZeIXcVADxOlUEGam7FIb1/RaLT8ZhTw3LpemiEV3e/zrLfjEGnnfeInSPo2QWsidX2wOhkjFwzWexs2TPv3G6IFBBQgk3JGsEfdy93tFTUpq7QUFZAcZlfQ+v/POdy/6iWQmHW66GsUzOlamGkY= 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=Oh7mCA6D; arc=none smtp.client-ip=209.85.128.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 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Oh7mCA6D" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-4954f5e8020so4346615e9.2 for ; Fri, 24 Jul 2026 11:45:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784918736; x=1785523536; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=mb7TOOIuiwseKoR6/vRO7kfdbaChj9w+25XESDqQWTA=; b=Oh7mCA6Dv/dApP3tGEnjl5Dmns7faKQb4Q9GHr+nAONAD/SgH6XapzEHNtURUzNxqy 0VA5s36RoMY8sLxvH+3tJ5f7c5QQOQYEfYDUfjMsVhOcB8oMz4PPDR9DXkMXoBCANace Y9leSQlADU9dz6/t9aTECAkKwBi+0XWZKZWSQuIVjvRu37xVAVAs7lECLmYNmKahlpaz s0u73ru8w1lF4gwDoRBTbmcX4ET+CbI3wxDLSJK2AjVOfRxb/KbFPW28jAFNC9mwaHeW c6GdxcrZyrZ9LavKubOJ9SW7ali762kGrSJuHbVXaJw/BZTjbJtR7yn6aW6Wf9snNJLd OGuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784918736; x=1785523536; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=mb7TOOIuiwseKoR6/vRO7kfdbaChj9w+25XESDqQWTA=; b=shpyaFNukHYLp1ngZpGhSo0ETlXyFCc50v1GlZJoFvHBJiUlCvMMKoBviAuqIaAm4q y1ZajU/dygGrfBx3VTWYEg0BsbVIxlRZz3bQZVstG4QBwWSmGMgUGGJwTZy5rEhhEyLZ G+NnmfD2WKlXQNGVJ5/dNjUNNRCdUazZFZIlbYs7iUHyJG8CG/GAwMIiWV5c8tDGwB6r bM3zMBW+P2bNaV8v9Ing1OtBHXkWPurHXmIVEqfQxzDXqB29UAkL11Cms9LModMIDEbo PHvnCmA8QaT3kC3FbK8qb6RqD4ieEdFKFDE/d+As6A6TwudZnlC2JAT8dgmMt8QcfnfT TdBA== X-Forwarded-Encrypted: i=1; AHgh+Rpclez6hOJqc239RMfB9Tx5wQsf0qyCfR+FDbGeYnQ5HP81ece6Z3ZMpicd5tEGC0fba1JlYSts6X/X4RU=@vger.kernel.org X-Gm-Message-State: AOJu0YzXpsVNGhYMs5vfq+U/CvWCpOPaft3nx5xW3qasnO28Jv4EeCk0 qBn+jrIUCMc/5Ux/pCgG/IZPNc+APRQA7hVwCDg9j0zAffguQ4Davs9G X-Gm-Gg: AR+sD10FDRWvSp6LEQgS1E2b7H+gKJQuTdOnsNA4Sx9JCcX16Xs1vHFO1IqD6RzbJNa Q9voy1Yq8klnd890WPQQM8Yl50L1V03RLhB5U94yBmpO4131qQ558y+gyZiO7/+BscFzMzrdl95 BRxRHGzxi7192P62OPQlaVhxhMMzLp7i/0+kE4j53mFdMlDU3WP3kVz2C0AII9Xd381KV/h9tXn qvBa60dF0ezmTw6GwyWLvKnwxco84yWUKRkAO4Pk0eX434+IrB7Bb1esD6sdOAMYofOuUbFO3XG f+v6rqVU990K6RlRlfrOx6iFHvn9mZXQQpHXBQFV6lwO7omn1loHIfEgS24uZpUUDyo5h5u71XR G9HE5FP69l8p3SCgiQaDfQfO5y3GRb/smP3QqhnZsKvwB3qSij4hPgvHeTyHBc4uYeRMwjDou88 zc1BDlcvmVbJDs3m175bs83LyOl8QqEVKK4fblMV8O8rtKKUVDAOfWFIDd7GtyeP0d2u4/wIooV pQ= X-Received: by 2002:a05:600c:4f87:b0:493:df5d:6ca6 with SMTP id 5b1f17b1804b1-49573cd8a8emr108469545e9.25.1784918735024; Fri, 24 Jul 2026 11:45:35 -0700 (PDT) Received: from Ansuel-XPS24.localdomain (host-87-3-249-180.retail.telecomitalia.it. [87.3.249.180]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-496b4858e85sm11278335e9.1.2026.07.24.11.45.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jul 2026 11:45:34 -0700 (PDT) From: Christian Marangi To: Christian Marangi , Vinod Koul , Neil Armstrong , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lorenzo Bianconi , linux-arm-kernel@lists.infradead.org, linux-phy@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Krzysztof Kozlowski Subject: [PATCH v11 1/3] dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY Date: Fri, 24 Jul 2026 20:45:20 +0200 Message-ID: <20260724184523.193661-2-ansuelsmth@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260724184523.193661-1-ansuelsmth@gmail.com> References: <20260724184523.193661-1-ansuelsmth@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add documentation for Airoha AN7581 USB PHY that describe the USB PHY for the USB controller. Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is always supported. The USB 3.0 mode is optional and depends on the Serdes mode currently configured on the system for the relevant USB port. To correctly calibrate, the USB 2.0 port require correct value in "airoha,usb2-monitor-clk-sel" property. Both the 2 USB 2.0 port permit selecting one of the 4 monitor clock for calibration (internal clock not exposed to the system) but each port have only one of the 4 actually connected in HW hence the correct value needs to be specified in DT based on board and the physical port. Normally it's monitor clock 1 for USB1 and monitor clock 2 for USB2. To correctly setup the Serdes mode attached to the USB 3.0 mode, a phys property is required with the phandle pointing to the correct Serdes port provided by the SCU node. Providing the phys property is optional if USB 3.0 is not used. Signed-off-by: Christian Marangi Reviewed-by: Krzysztof Kozlowski --- .../bindings/phy/airoha,an7581-usb-phy.yaml | 62 +++++++++++++++++++ MAINTAINERS | 6 ++ 2 files changed, 68 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb= -phy.yaml diff --git a/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.ya= ml b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml new file mode 100644 index 000000000000..f42e3d49a61f --- /dev/null +++ b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/airoha,an7581-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Airoha AN7581 SoC USB PHY + +maintainers: + - Christian Marangi + +description: > + The Airoha AN7581 SoC USB PHY describes the USB PHY for the USB controll= er. + + Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is + always supported. The USB 3.0 mode is optional and depends on the Serdes + mode currently configured on the system for the relevant USB port. + +properties: + compatible: + const: airoha,an7581-usb-phy + + reg: + maxItems: 1 + + airoha,usb2-monitor-clk-sel: + description: Describe what oscillator across the available 4 + should be selected for USB 2.0 Slew Rate calibration. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + phys: + items: + - description: phandle to Serdes PHY. Optional if USB 3.0 is not use= d. + + '#phy-cells': + description: The cell contains the mode, PHY_TYPE_USB2 or PHY_TYPE_USB= 3, + as defined in dt-bindings/phy/phy.h. + const: 1 + +required: + - compatible + - reg + - airoha,usb2-monitor-clk-sel + - '#phy-cells' + +additionalProperties: false + +examples: + - | + #include + + phy@1fac0000 { + compatible =3D "airoha,an7581-usb-phy"; + reg =3D <0x1fac0000 0x10000>; + + airoha,usb2-monitor-clk-sel =3D <1>; + phys =3D <&scu AIROHA_SCU_SERDES_USB1>; + + #phy-cells =3D <1>; + }; + diff --git a/MAINTAINERS b/MAINTAINERS index 1705eb823dd0..05e90c3f7fe0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -777,6 +777,12 @@ S: Maintained F: Documentation/devicetree/bindings/spi/airoha,en7581-snand.yaml F: drivers/spi/spi-airoha-snfi.c =20 +AIROHA USB PHY DRIVER +M: Christian Marangi +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml + AIRSPY MEDIA DRIVER L: linux-media@vger.kernel.org S: Orphan --=20 2.53.0 From nobody Fri Jul 24 20:51:08 2026 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (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 70A4630B53A for ; Fri, 24 Jul 2026 18:45:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784918740; cv=none; b=UTGRqRWrh4qXIZXNn7NesMRmhRzJF0DOBBSDnOaoJMN2aBiKfUBLiMYpMq7baOIutNdOMKg3xaS+Q9tOkPGW6KTYlIIVVr2jrQJX+rvsb6wAkCNn8KvgwrQAKg8JC7AupT7K1pNekCJBndlL7phqDfVot2hlbNvm4Wo9MU4nOmc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784918740; c=relaxed/simple; bh=xtzhudypbNeVsFar+T1OKjRqJ8pBCkucdqQ7a7xGCLA=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UllzkgzStHzLHCPn+TZyjSqXvB5bOQWNmySAfmBsl0zxtDH/te4dQ6oD26bHBLJkp+PPBvHRUvqgm6tuMfldmMx8ZqlMZaosnRf6dzyeYFngrm0/swCzW1fYNRmf0Zrwo+JUIJ60MBW4FHTPfql9cbc9ZzDCWlbe6/qD07wX3bE= 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=oD/Wzz5F; arc=none smtp.client-ip=209.85.128.54 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 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="oD/Wzz5F" Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-4953de5be0aso5421035e9.0 for ; Fri, 24 Jul 2026 11:45:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784918737; x=1785523537; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=19Blhbug/ViMibEwSUq3xAqJ9uRR52sZJ3C/I6CrjH0=; b=oD/Wzz5FQAFCe2zrrh078ywz9aNnX4Uoo+OsAsuCNoNqD6F6AyMLytEjoM6ELzGZv6 DXoa7Thlxa7FY4ohfvGnffbQgck+NPSa9JLzyD9gDQIXgn9H8pDDG9XjDDssOQ56//3d mDGC6o49R0ekIjMAl6VSYhA+2E0bJ+w398Ob5htZ6OgnQ7AZGIcMWgdSzXJkMosMuOAI Q2uU8ZmtsPSYCK1fFEXUSGtbo9+XcKi3W0UxZyEGii0eFKHfaTeuHLVG8iNZWW1J+z/B +upEBYGUpFf0mv6EISRgfg5CeG84fRSHoE+Re3AYKGu8KiiE75M3R+tCEDPJxK/EN5NH wilw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784918737; x=1785523537; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=19Blhbug/ViMibEwSUq3xAqJ9uRR52sZJ3C/I6CrjH0=; b=tYZchPQlEnz9hnuWv1s96D4vo9J7QtH90GFv0gIYic5rpzHEf/vIzQJvLmyt1/IBfi O5o9FIID/I4g/qBWZXW9yU++zx/qyfz6JWMPBeXj95SXOTcXlUBJtR9LYse2xS0fg8bM WU2/TM01yg0OwOKRZvq6vaE4TZ+aZCOpxpQ3SHtuA//w5HfHCAqkeTe95oVeNiBzCsx2 mEi+sbhpEY0t4zBDsrBDnIGbiH+ShbHEjmplJzYaD5aAMny13g+aSdotkm4NbP/urY1a x3B9fgHh6jdLCk0+o1Ki7jILxahNfEiJQAV67J4RJlWAmiMz4lH/scZpnlVf4Kh6vdLC qFMw== X-Forwarded-Encrypted: i=1; AHgh+RpeJAc4WJJ5VaUNwyWOuoE/xtGd5cJYrkvFXbXn/4tt0VTPL+J7NNnuaWV9i+05kgFVbTiM/V15WISNj8Y=@vger.kernel.org X-Gm-Message-State: AOJu0YxZ2qu1Jdry9nHIf/lK+12EQ3jP5LgJIpxgypC+HSx79IaFJMDy nH0gEf20IffDZBI94LG9M9nSi0KBs2R1RWl/Y0YjiWmIx1ZQUDuhbzo5 X-Gm-Gg: AR+sD13THccHRnGys6XaHwg0SLzV4bV9kTDEyCjBUiKElOH/0/vyTU7tEuj8l4Kuve6 7q9zEgvqgX55u9B1jXLe3I+S+NTxrF29sQCFhQly5Mb4nFW+HzKd5Siz3A2WFP9TCNDaGCECiw+ 4PoVYGdPSoBGBICP+rJGa2YRhPusIYbUFu2OaLIRXg1IGNENuGrXI9s/MXsRnBXx4z/WFcU3jda YTlsOs+3nk7hfLJmTIvxOBjCGO/k3Wt2CE2PbejeJxgpx4mvA2P3wo0CLqm1dw8bdtNjlqAxG6y C49bmvLyuOJHdcuvG8DeDuEHn3ka0DdV61Z+WKBxmImUi9DFl4A2AQI08zLWXwzxhqksT9ux3wQ WkhgCMTfH+yIvLF0/anLX77f+cCWWaK7ES9PbE+qLTwfx7fFdnSZN6fpluDy11YzZOIvCtJQspW RsABws8s8oUR3kkZC93OYvmxRwcsB6kfMw1kyEIVkNR45uTUuBuyHOmW4zwJ8uC84zsWhWD/omb gg= X-Received: by 2002:a05:600c:5942:b0:495:6397:14b1 with SMTP id 5b1f17b1804b1-49573cf0ec2mr70244405e9.34.1784918736409; Fri, 24 Jul 2026 11:45:36 -0700 (PDT) Received: from Ansuel-XPS24.localdomain (host-87-3-249-180.retail.telecomitalia.it. [87.3.249.180]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-496b4858e85sm11278335e9.1.2026.07.24.11.45.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jul 2026 11:45:35 -0700 (PDT) From: Christian Marangi To: Christian Marangi , Vinod Koul , Neil Armstrong , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lorenzo Bianconi , linux-arm-kernel@lists.infradead.org, linux-phy@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 2/3] phy: move and rename Airoha PCIe PHY driver to dedicated directory Date: Fri, 24 Jul 2026 20:45:21 +0200 Message-ID: <20260724184523.193661-3-ansuelsmth@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260724184523.193661-1-ansuelsmth@gmail.com> References: <20260724184523.193661-1-ansuelsmth@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" To keep the generic PHY directory tidy, move the PCIe PHY driver for Airoha AN7581 SoC to a dedicated directory. Also rename the driver and add the relevant SoC name to the .c and .h file in preparation for support of PCIe and USB PHY driver for Airoha AN7583 SoC that use a completely different implementation and calibration for PHYs and will have their own dedicated drivers. The rename permits to better identify the specific usage of the driver in the future once the airoha PHY directory will have multiple driver for multiple SoC. The config is changed from PHY_AIROHA_PCIE to PHY_AIROHA_AN7581_PCIE. Signed-off-by: Christian Marangi Acked-by: Lorenzo Bianconi --- MAINTAINERS | 4 ++-- drivers/phy/Kconfig | 11 +---------- drivers/phy/Makefile | 4 ++-- drivers/phy/airoha/Kconfig | 13 +++++++++++++ drivers/phy/airoha/Makefile | 3 +++ .../phy-an7581-pcie-regs.h} | 2 +- .../{phy-airoha-pcie.c =3D> airoha/phy-an7581-pcie.c} | 6 +++--- 7 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 drivers/phy/airoha/Kconfig create mode 100644 drivers/phy/airoha/Makefile rename drivers/phy/{phy-airoha-pcie-regs.h =3D> airoha/phy-an7581-pcie-reg= s.h} (99%) rename drivers/phy/{phy-airoha-pcie.c =3D> airoha/phy-an7581-pcie.c} (99%) diff --git a/MAINTAINERS b/MAINTAINERS index 05e90c3f7fe0..952653034c4c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -765,8 +765,8 @@ M: Lorenzo Bianconi L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.yaml -F: drivers/phy/phy-airoha-pcie-regs.h -F: drivers/phy/phy-airoha-pcie.c +F: drivers/phy/airoha/phy-an7581-pcie-regs.h +F: drivers/phy/airoha/phy-an7581-pcie.c =20 AIROHA SPI SNFI DRIVER M: Lorenzo Bianconi diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 19f3b7d12b7d..e93951a4a898 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -46,16 +46,6 @@ config GENERIC_PHY_MIPI_DPHY Provides a number of helpers a core functions for MIPI D-PHY drivers to us. =20 -config PHY_AIROHA_PCIE - tristate "Airoha PCIe-PHY Driver" - depends on ARCH_AIROHA || COMPILE_TEST - depends on OF - select GENERIC_PHY - help - Say Y here to add support for Airoha PCIe PHY driver. - This driver create the basic PHY instance and provides initialize - callback for PCIe GEN3 port. - config PHY_CAN_TRANSCEIVER tristate "CAN transceiver PHY" select GENERIC_PHY @@ -168,6 +158,7 @@ config PHY_XGENE help This option enables support for APM X-Gene SoC multi-purpose PHY. =20 +source "drivers/phy/airoha/Kconfig" source "drivers/phy/allwinner/Kconfig" source "drivers/phy/amlogic/Kconfig" source "drivers/phy/apple/Kconfig" diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index d7aa516bcc49..4ca4a07963fc 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_PHY_COMMON_PROPS) +=3D phy-common-props.o obj-$(CONFIG_PHY_COMMON_PROPS_TEST) +=3D phy-common-props-test.o obj-$(CONFIG_GENERIC_PHY) +=3D phy-core.o obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) +=3D phy-core-mipi-dphy.o -obj-$(CONFIG_PHY_AIROHA_PCIE) +=3D phy-airoha-pcie.o obj-$(CONFIG_PHY_CAN_TRANSCEIVER) +=3D phy-can-transceiver.o obj-$(CONFIG_PHY_ECONET_PCIE) +=3D phy-econet-pcie.o obj-$(CONFIG_PHY_EYEQ5_ETH) +=3D phy-eyeq5-eth.o @@ -20,7 +19,8 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) +=3D phy-pistachio-usb.o obj-$(CONFIG_PHY_SNPS_EUSB2) +=3D phy-snps-eusb2.o obj-$(CONFIG_PHY_XGENE) +=3D phy-xgene.o =20 -obj-$(CONFIG_GENERIC_PHY) +=3D allwinner/ \ +obj-$(CONFIG_GENERIC_PHY) +=3D airoha/ \ + allwinner/ \ amlogic/ \ apple/ \ axiado/ \ diff --git a/drivers/phy/airoha/Kconfig b/drivers/phy/airoha/Kconfig new file mode 100644 index 000000000000..9a1b625a7701 --- /dev/null +++ b/drivers/phy/airoha/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Phy drivers for Airoha devices +# +config PHY_AIROHA_AN7581_PCIE + tristate "Airoha AN7581 PCIe-PHY Driver" + depends on ARCH_AIROHA || COMPILE_TEST + depends on OF + select GENERIC_PHY + help + Say Y here to add support for Airoha AN7581 PCIe PHY driver. + This driver create the basic PHY instance and provides initialize + callback for PCIe GEN3 port. diff --git a/drivers/phy/airoha/Makefile b/drivers/phy/airoha/Makefile new file mode 100644 index 000000000000..912f3e11a061 --- /dev/null +++ b/drivers/phy/airoha/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_PHY_AIROHA_AN7581_PCIE) +=3D phy-an7581-pcie.o diff --git a/drivers/phy/phy-airoha-pcie-regs.h b/drivers/phy/airoha/phy-an= 7581-pcie-regs.h similarity index 99% rename from drivers/phy/phy-airoha-pcie-regs.h rename to drivers/phy/airoha/phy-an7581-pcie-regs.h index 58572c793722..b938a7b468fe 100644 --- a/drivers/phy/phy-airoha-pcie-regs.h +++ b/drivers/phy/airoha/phy-an7581-pcie-regs.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2024 AIROHA Inc * Author: Lorenzo Bianconi diff --git a/drivers/phy/phy-airoha-pcie.c b/drivers/phy/airoha/phy-an7581-= pcie.c similarity index 99% rename from drivers/phy/phy-airoha-pcie.c rename to drivers/phy/airoha/phy-an7581-pcie.c index 56e9ade8a9fd..81ddf0e7638b 100644 --- a/drivers/phy/phy-airoha-pcie.c +++ b/drivers/phy/airoha/phy-an7581-pcie.c @@ -13,7 +13,7 @@ #include #include =20 -#include "phy-airoha-pcie-regs.h" +#include "phy-an7581-pcie-regs.h" =20 #define LEQ_LEN_CTRL_MAX_VAL 7 #define FREQ_LOCK_MAX_ATTEMPT 10 @@ -1279,12 +1279,12 @@ MODULE_DEVICE_TABLE(of, airoha_pcie_phy_of_match); static struct platform_driver airoha_pcie_phy_driver =3D { .probe =3D airoha_pcie_phy_probe, .driver =3D { - .name =3D "airoha-pcie-phy", + .name =3D "airoha-an7581-pcie-phy", .of_match_table =3D airoha_pcie_phy_of_match, }, }; module_platform_driver(airoha_pcie_phy_driver); =20 -MODULE_DESCRIPTION("Airoha PCIe PHY driver"); +MODULE_DESCRIPTION("Airoha AN7581 PCIe PHY driver"); MODULE_AUTHOR("Lorenzo Bianconi "); MODULE_LICENSE("GPL"); --=20 2.53.0 From nobody Fri Jul 24 20:51:08 2026 Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.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 E3001388881 for ; Fri, 24 Jul 2026 18:45:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784918745; cv=none; b=ZA9zd56IOqm1h/XzojqAeCa96F8O329xQR7a3P0thU1Fbs4u+MTRD3zqpC5u1DGXaAGp7KP5oWQc/3ofREpKan18n9/u96G0zYNfUmihblnntxPdIEzlpEnUUvKDWzES/U9+rugIt+9eAwiDX6c+8bVtWRcIokjt5LfoS2ajL7o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784918745; c=relaxed/simple; bh=Coy0+zYpqhjJut8MYHXyp0HrmUGTQVqf6mIsK9LILxU=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FInpOz0euNz+MRTmVkoK4pP13UMdyWbRonuCyV4FQ2WEaljYN4SqfV9zGFPjSgRZoMpZdR6v598SiJDW4hZA2p0jDmXhZ/bVq4t5a9qM4uaW4AYTxtsu0jLHBVqbCRfQaU6Id4R9f4PYwuj/uHPcuYmxXqKkl1aMOiFig2Tnv6M= 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=s1329Uin; arc=none smtp.client-ip=209.85.128.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 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="s1329Uin" Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-4954c0833b4so6478715e9.1 for ; Fri, 24 Jul 2026 11:45:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784918738; x=1785523538; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=YO2AOaYZjZZgeZNz2bLOuyr9xVRDfoSchOJqgdChOTw=; b=s1329UinmIN01+IZzQV6otMY0aalgJ3SsmkQcu86fKQcsen7YA7aaf2fiZ5M20ZPv/ NfvMPp4CiRasNGf5mdKrCoMo0XNX1m6Boj/wBEi8gi+4DLHheBvxWOJNW40yH+iprzRU zAsCYBdP5pkAnaRBikOqfsqsrWgyFjWW6W/sB7LGv4Oq7L9mip5RUIQxneJVwQorNGVF 00wNtsd1Pg4fCNNg6zmMP4ZcW0fpKcidL57Qpc1JhisrbRifZ+X8d1pOtmYWlJzkI8rc u7wv94v0QG/LiwF5bIz1PasSSe6/EPS63f4d3zVfQmwBWno/HghhuGeBdhaDTCc80roa HcMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784918738; x=1785523538; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=YO2AOaYZjZZgeZNz2bLOuyr9xVRDfoSchOJqgdChOTw=; b=l+iYhlZ3W8li+BCPp8SJsYWscLLGyNSYBdxvgu3Dd4vy/bpdOWD+zbDaSM+79lWJEH IvyX0YEZ9t6KqcdFGUvdwyk0kcvgnav7QZTFE5UEIGf6flOQ2arp2me83tCDsIPw8wUX t3nKh3ZMLCBl64GYY0kDQKXrSroma6cmmmBEn92uyqjHPUL4BO89i4/faG4soIbVXJJz 1wf+pMIvxGY8ehacIeNEBFHitU8yttgEYZWVaij6V36FU8vgJkKt++uVO6SVYtdvVpzP tU7uxfaeTl6xLDqj8CJtpQnT05q4BVvZPF/QYTcVUGqmovD/2IH3SfMWZGiU3Zjz79E6 SL3Q== X-Forwarded-Encrypted: i=1; AHgh+RpIi0qSqDT1YtzwN5rAwWiHfTcoo7RhAzsZqrS5hRBWCWaXkA/bBEFgBivLvvei5ykx+pssBe99YVfg/84=@vger.kernel.org X-Gm-Message-State: AOJu0Yxnx20WpEYbjxUmdVfkaAiaa6hpFWaYSEK+DqzavDN53taKd7aP NsK5ESk9waVa4As9PLUTky3s/KZ2CmI6Ya/g5L4ijI3c11H80DMHMoMd X-Gm-Gg: AR+sD130g729Vw1mwt4DkCKcPU9kVLe2YaRrYgsFIBPRgcnQuzGxRdVtbIVqqMvHEBt bfioQVyiWCcIoH73oJia5GIhxZEkBvZgc9jeVZTwMfjcbC+Vh/FUgh3+ko+x1mWL8Y/VrPE8vgi vdshPZemEcM1Dmx32zjZi1edW+XA+w011cyS8JD3kNWKpHLiV25mYERwFUchOK4sESwH+Tfz0C+ Puk28fFAUeP5YuXI2I1/G1NXfD2N2tdXt9mCs4EPjuqsbyqpXYSGi1JSesHnR9vDh703d1rd06K F9Q245mkrJPEmFOPFFv27ik6x8Fx4Q1Hi03Q05SF5rtpCOdQX35M1B1DddPCnyrnlyXzaokuSLC 2k4KSx8CnxlyR/GULpbV9Hx3mbfcq4ALYuQZr4C2HDGLsaAOGm7ohliUpbF7CqdhFqdyvJtfS0/ rElblvlXE0P/4rvfLhupPQsnT/HTa6AMpV4H40oIbwULYxP2ABXMDSBXy051Qx1IWb X-Received: by 2002:a05:600c:1553:b0:493:f5bf:4dc6 with SMTP id 5b1f17b1804b1-49573cc2d52mr93461275e9.7.1784918737813; Fri, 24 Jul 2026 11:45:37 -0700 (PDT) Received: from Ansuel-XPS24.localdomain (host-87-3-249-180.retail.telecomitalia.it. [87.3.249.180]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-496b4858e85sm11278335e9.1.2026.07.24.11.45.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jul 2026 11:45:37 -0700 (PDT) From: Christian Marangi To: Christian Marangi , Vinod Koul , Neil Armstrong , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lorenzo Bianconi , linux-arm-kernel@lists.infradead.org, linux-phy@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 3/3] phy: airoha: Add support for Airoha AN7581 USB PHY Date: Fri, 24 Jul 2026 20:45:22 +0200 Message-ID: <20260724184523.193661-4-ansuelsmth@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260724184523.193661-1-ansuelsmth@gmail.com> References: <20260724184523.193661-1-ansuelsmth@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for Airoha AN7581 USB PHY driver. AN7581 supports up to 2 USB port with USB 2.0 mode always supported and USB 3.0 mode available only if the Serdes port is correctly configured for USB 3.0. If the USB 3.0 mode is not configured, the modes needs to be also disabled in the xHCI node or the driver will report unsable clock and fail probe. For USB 2.0 Slew Rate calibration, airoha,usb2-monitor-clk-sel is mandatory and is used to select the monitor clock for calibration. Normally it's 1 for USB port 1 and 2 for USB port 2. Signed-off-by: Christian Marangi --- MAINTAINERS | 1 + drivers/phy/airoha/Kconfig | 11 + drivers/phy/airoha/Makefile | 1 + drivers/phy/airoha/phy-an7581-usb.c | 559 ++++++++++++++++++++++++++++ 4 files changed, 572 insertions(+) create mode 100644 drivers/phy/airoha/phy-an7581-usb.c diff --git a/MAINTAINERS b/MAINTAINERS index 952653034c4c..844f676254ac 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -782,6 +782,7 @@ M: Christian Marangi L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml +F: drivers/phy/airoha/phy-an7581-usb.c =20 AIRSPY MEDIA DRIVER L: linux-media@vger.kernel.org diff --git a/drivers/phy/airoha/Kconfig b/drivers/phy/airoha/Kconfig index 9a1b625a7701..634448ee39b5 100644 --- a/drivers/phy/airoha/Kconfig +++ b/drivers/phy/airoha/Kconfig @@ -11,3 +11,14 @@ config PHY_AIROHA_AN7581_PCIE Say Y here to add support for Airoha AN7581 PCIe PHY driver. This driver create the basic PHY instance and provides initialize callback for PCIe GEN3 port. + +config PHY_AIROHA_AN7581_USB + tristate "Airoha AN7581 USB PHY Driver" + depends on ARCH_AIROHA || COMPILE_TEST + depends on OF + select GENERIC_PHY + select REGMAP_MMIO + help + Say 'Y' here to add support for Airoha AN7581 USB PHY driver. + This driver create the basic PHY instance and provides initialize + callback for USB port. diff --git a/drivers/phy/airoha/Makefile b/drivers/phy/airoha/Makefile index 912f3e11a061..944bf842deba 100644 --- a/drivers/phy/airoha/Makefile +++ b/drivers/phy/airoha/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 =20 obj-$(CONFIG_PHY_AIROHA_AN7581_PCIE) +=3D phy-an7581-pcie.o +obj-$(CONFIG_PHY_AIROHA_AN7581_USB) +=3D phy-an7581-usb.o diff --git a/drivers/phy/airoha/phy-an7581-usb.c b/drivers/phy/airoha/phy-a= n7581-usb.c new file mode 100644 index 000000000000..92c5e5c2fbf3 --- /dev/null +++ b/drivers/phy/airoha/phy-an7581-usb.c @@ -0,0 +1,559 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Author: Christian Marangi + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* U2PHY */ +#define AIROHA_USB_PHY_FMCR0 0x100 +#define AIROHA_USB_PHY_MONCLK_SEL GENMASK(27, 26) +#define AIROHA_USB_PHY_MONCLK_SEL0 FIELD_PREP_CONST(AIROHA_USB_PHY_MONC= LK_SEL, 0x0) +#define AIROHA_USB_PHY_MONCLK_SEL1 FIELD_PREP_CONST(AIROHA_USB_PHY_MONC= LK_SEL, 0x1) +#define AIROHA_USB_PHY_MONCLK_SEL2 FIELD_PREP_CONST(AIROHA_USB_PHY_MONC= LK_SEL, 0x2) +#define AIROHA_USB_PHY_MONCLK_SEL3 FIELD_PREP_CONST(AIROHA_USB_PHY_MONC= LK_SEL, 0x3) +#define AIROHA_USB_PHY_FREQDET_EN BIT(24) +#define AIROHA_USB_PHY_CYCLECNT GENMASK(23, 0) +#define AIROHA_USB_PHY_FMMONR0 0x10c +#define AIROHA_USB_PHY_USB_FM_OUT GENMASK(31, 0) +#define AIROHA_USB_PHY_FMMONR1 0x110 +#define AIROHA_USB_PHY_FRCK_EN BIT(8) + +#define AIROHA_USB_PHY_USBPHYACR4 0x310 +#define AIROHA_USB_PHY_USB20_FS_CR GENMASK(10, 8) +#define AIROHA_USB_PHY_USB20_FS_CR_MAX FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_FS_CR, 0x0) +#define AIROHA_USB_PHY_USB20_FS_CR_NORMAL FIELD_PREP_CONST(AIROHA_USB_PH= Y_USB20_FS_CR, 0x2) +#define AIROHA_USB_PHY_USB20_FS_CR_SMALLER FIELD_PREP_CONST(AIROHA_USB_P= HY_USB20_FS_CR, 0x4) +#define AIROHA_USB_PHY_USB20_FS_CR_MIN FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_FS_CR, 0x6) +#define AIROHA_USB_PHY_USB20_FS_SR GENMASK(2, 0) +#define AIROHA_USB_PHY_USB20_FS_SR_MAX FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_FS_SR, 0x0) +#define AIROHA_USB_PHY_USB20_FS_SR_NORMAL FIELD_PREP_CONST(AIROHA_USB_PH= Y_USB20_FS_SR, 0x2) +#define AIROHA_USB_PHY_USB20_FS_SR_SMALLER FIELD_PREP_CONST(AIROHA_USB_P= HY_USB20_FS_SR, 0x4) +#define AIROHA_USB_PHY_USB20_FS_SR_MIN FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_FS_SR, 0x6) +#define AIROHA_USB_PHY_USBPHYACR5 0x314 +#define AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN BIT(15) +#define AIROHA_USB_PHY_USB20_HSTX_SRCTRL GENMASK(14, 12) +#define AIROHA_USB_PHY_USBPHYACR6 0x318 +#define AIROHA_USB_PHY_USB20_BC11_SW_EN BIT(23) +#define AIROHA_USB_PHY_USB20_DISCTH GENMASK(7, 4) +#define AIROHA_USB_PHY_USB20_DISCTH_400 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0x0) +#define AIROHA_USB_PHY_USB20_DISCTH_420 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0x1) +#define AIROHA_USB_PHY_USB20_DISCTH_440 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0x2) +#define AIROHA_USB_PHY_USB20_DISCTH_460 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0x3) +#define AIROHA_USB_PHY_USB20_DISCTH_480 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0x4) +#define AIROHA_USB_PHY_USB20_DISCTH_500 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0x5) +#define AIROHA_USB_PHY_USB20_DISCTH_520 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0x6) +#define AIROHA_USB_PHY_USB20_DISCTH_540 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0x7) +#define AIROHA_USB_PHY_USB20_DISCTH_560 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0x8) +#define AIROHA_USB_PHY_USB20_DISCTH_580 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0x9) +#define AIROHA_USB_PHY_USB20_DISCTH_600 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0xa) +#define AIROHA_USB_PHY_USB20_DISCTH_620 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0xb) +#define AIROHA_USB_PHY_USB20_DISCTH_640 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0xc) +#define AIROHA_USB_PHY_USB20_DISCTH_660 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0xd) +#define AIROHA_USB_PHY_USB20_DISCTH_680 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0xe) +#define AIROHA_USB_PHY_USB20_DISCTH_700 FIELD_PREP_CONST(AIROHA_USB_PHY_= USB20_DISCTH, 0xf) +#define AIROHA_USB_PHY_USB20_SQTH GENMASK(3, 0) +#define AIROHA_USB_PHY_USB20_SQTH_85 FIELD_PREP_CONST(AIROHA_USB_PHY_US= B20_SQTH, 0x0) +#define AIROHA_USB_PHY_USB20_SQTH_90 FIELD_PREP_CONST(AIROHA_USB_PHY_US= B20_SQTH, 0x1) +#define AIROHA_USB_PHY_USB20_SQTH_95 FIELD_PREP_CONST(AIROHA_USB_PHY_US= B20_SQTH, 0x2) +#define AIROHA_USB_PHY_USB20_SQTH_100 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0x3) +#define AIROHA_USB_PHY_USB20_SQTH_105 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0x4) +#define AIROHA_USB_PHY_USB20_SQTH_110 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0x5) +#define AIROHA_USB_PHY_USB20_SQTH_115 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0x6) +#define AIROHA_USB_PHY_USB20_SQTH_120 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0x7) +#define AIROHA_USB_PHY_USB20_SQTH_125 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0x8) +#define AIROHA_USB_PHY_USB20_SQTH_130 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0x9) +#define AIROHA_USB_PHY_USB20_SQTH_135 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0xa) +#define AIROHA_USB_PHY_USB20_SQTH_140 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0xb) +#define AIROHA_USB_PHY_USB20_SQTH_145 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0xc) +#define AIROHA_USB_PHY_USB20_SQTH_150 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0xd) +#define AIROHA_USB_PHY_USB20_SQTH_155 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0xe) +#define AIROHA_USB_PHY_USB20_SQTH_160 FIELD_PREP_CONST(AIROHA_USB_PHY_U= SB20_SQTH, 0xf) + +#define AIROHA_USB_PHY_U2PHYDTM1 0x36c +#define AIROHA_USB_PHY_FORCE_IDDIG BIT(9) +#define AIROHA_USB_PHY_IDDIG BIT(1) + +#define AIROHA_USB_PHY_GPIO_CTLD 0x80c +#define AIROHA_USB_PHY_C60802_GPIO_CTLD GENMASK(31, 0) +#define AIROHA_USB_PHY_SSUSB_IP_SW_RST BIT(31) +#define AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN BIT(30) +#define AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST BIT(29) +#define AIROHA_USB_PHY_SSUSB_SW_RST BIT(28) + +#define AIROHA_USB_PHY_U3_PHYA_REG0 0xb00 +#define AIROHA_USB_PHY_SSUSB_BG_DIV GENMASK(29, 28) +#define AIROHA_USB_PHY_SSUSB_BG_DIV_2 FIELD_PREP_CONST(AIROHA_USB_PHY_S= SUSB_BG_DIV, 0x0) +#define AIROHA_USB_PHY_SSUSB_BG_DIV_4 FIELD_PREP_CONST(AIROHA_USB_PHY_S= SUSB_BG_DIV, 0x1) +#define AIROHA_USB_PHY_SSUSB_BG_DIV_8 FIELD_PREP_CONST(AIROHA_USB_PHY_S= SUSB_BG_DIV, 0x2) +#define AIROHA_USB_PHY_SSUSB_BG_DIV_16 FIELD_PREP_CONST(AIROHA_USB_PHY_S= SUSB_BG_DIV, 0x3) +#define AIROHA_USB_PHY_U3_PHYA_REG1 0xb04 +#define AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE GENMASK(25, 10) +#define AIROHA_USB_PHY_U3_PHYA_REG6 0xb18 +#define AIROHA_USB_PHY_SSUSB_CDR_RESERVE GENMASK(31, 24) +#define AIROHA_USB_PHY_U3_PHYA_REG8 0xb20 +#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY GENMASK(7, 6) +#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32 FIELD_PREP_CONST(AIROHA_USB_= PHY_SSUSB_CDR_RST_DLY, 0x0) +#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_64 FIELD_PREP_CONST(AIROHA_USB_= PHY_SSUSB_CDR_RST_DLY, 0x1) +#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_128 FIELD_PREP_CONST(AIROHA_USB= _PHY_SSUSB_CDR_RST_DLY, 0x2) +#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_216 FIELD_PREP_CONST(AIROHA_USB= _PHY_SSUSB_CDR_RST_DLY, 0x3) + +#define AIROHA_USB_PHY_U3_PHYA_DA_REG19 0xc38 +#define AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3 GENMASK(15, 0) + +#define AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT 1024 +#define AIROHA_USB_PHY_REF_CK 20 +#define AIROHA_USB_PHY_U2_SR_COEF 28 +#define AIROHA_USB_PHY_U2_SR_COEF_DIVISOR 1000 + +#define AIROHA_USB_PHY_DEFAULT_SR_CALIBRATION 0x5 +#define AIROHA_USB_PHY_FREQDET_SLEEP 1000 /* 1ms */ +#define AIROHA_USB_PHY_FREQDET_TIMEOUT (AIROHA_USB_PHY_FREQDET_SLEEP * 10) + +struct an7581_usb_phy_instance { + struct phy *phy; + u32 type; +}; + +enum an7581_usb_phy_instance_type { + AIROHA_PHY_USB2, + AIROHA_PHY_USB3, + + AIROHA_PHY_USB_MAX, +}; + +struct an7581_usb_phy_priv { + struct device *dev; + struct regmap *regmap; + + unsigned int monclk_sel; + + struct phy *serdes_phy; + struct an7581_usb_phy_instance *phys[AIROHA_PHY_USB_MAX]; +}; + +static void an7581_usb_phy_u2_slew_rate_calibration(struct an7581_usb_phy_= priv *priv) +{ + u32 fm_out =3D 0; + u32 srctrl; + + /* Enable HS TX SR calibration */ + regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5, + AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN); + + usleep_range(1000, 1500); + + /* Enable Free run clock */ + regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1, + AIROHA_USB_PHY_FRCK_EN); + + /* Select Monitor Clock */ + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0, + AIROHA_USB_PHY_MONCLK_SEL, + FIELD_PREP(AIROHA_USB_PHY_MONCLK_SEL, + priv->monclk_sel)); + + /* Set cyclecnt */ + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0, + AIROHA_USB_PHY_CYCLECNT, + FIELD_PREP(AIROHA_USB_PHY_CYCLECNT, + AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT)); + + /* Enable Frequency meter */ + regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMCR0, + AIROHA_USB_PHY_FREQDET_EN); + + /* Timeout can happen and we will apply workaround at the end */ + regmap_read_poll_timeout(priv->regmap, AIROHA_USB_PHY_FMMONR0, fm_out, + fm_out, AIROHA_USB_PHY_FREQDET_SLEEP, + AIROHA_USB_PHY_FREQDET_TIMEOUT); + + /* Disable Frequency meter */ + regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMCR0, + AIROHA_USB_PHY_FREQDET_EN); + + /* Disable Free run clock */ + regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1, + AIROHA_USB_PHY_FRCK_EN); + + /* Disable HS TX SR calibration */ + regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5, + AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN); + + usleep_range(1000, 1500); + + /* Frequency was not detected, use default SR calibration value */ + if (!fm_out) { + srctrl =3D AIROHA_USB_PHY_DEFAULT_SR_CALIBRATION; + dev_err(priv->dev, "Frequency not detected, using default SR calibration= .\n"); + } else { + /* (1024 / FM_OUT) * REF_CK * U2_SR_COEF (round to the nearest digits) */ + srctrl =3D AIROHA_USB_PHY_REF_CK * AIROHA_USB_PHY_U2_SR_COEF; + srctrl =3D (srctrl * AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT) / fm_out; + srctrl =3D DIV_ROUND_CLOSEST(srctrl, AIROHA_USB_PHY_U2_SR_COEF_DIVISOR); + dev_dbg(priv->dev, "SR calibration applied: %x\n", srctrl); + } + + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5, + AIROHA_USB_PHY_USB20_HSTX_SRCTRL, + FIELD_PREP(AIROHA_USB_PHY_USB20_HSTX_SRCTRL, srctrl)); +} + +static void an7581_usb_phy_u2_init(struct an7581_usb_phy_priv *priv) +{ + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4, + AIROHA_USB_PHY_USB20_FS_CR, + AIROHA_USB_PHY_USB20_FS_CR_MIN); + + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4, + AIROHA_USB_PHY_USB20_FS_SR, + AIROHA_USB_PHY_USB20_FS_SR_NORMAL); + + /* FIXME: evaluate if needed */ + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, + AIROHA_USB_PHY_USB20_SQTH, + AIROHA_USB_PHY_USB20_SQTH_130); + + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, + AIROHA_USB_PHY_USB20_DISCTH, + AIROHA_USB_PHY_USB20_DISCTH_600); + + /* Enable the USB port and then disable after calibration */ + regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, + AIROHA_USB_PHY_USB20_BC11_SW_EN); + + an7581_usb_phy_u2_slew_rate_calibration(priv); + + regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, + AIROHA_USB_PHY_USB20_BC11_SW_EN); + + usleep_range(1000, 1500); +} + +/* + * USB 3.0 mode can only work if USB serdes is correctly set. + * This is validated in xLate function. + */ +static void an7581_usb_phy_u3_init(struct an7581_usb_phy_priv *priv) +{ + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG8, + AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, + AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32); + + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG6, + AIROHA_USB_PHY_SSUSB_CDR_RESERVE, + FIELD_PREP(AIROHA_USB_PHY_SSUSB_CDR_RESERVE, 0xe)); + + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG0, + AIROHA_USB_PHY_SSUSB_BG_DIV, + AIROHA_USB_PHY_SSUSB_BG_DIV_4); + + regmap_set_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG1, + FIELD_PREP(AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE, 0x600)); + + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_DA_REG19, + AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3, + FIELD_PREP(AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3, 0x43)); +} + +static int an7581_usb_phy_init(struct phy *phy) +{ + struct an7581_usb_phy_instance *instance =3D phy_get_drvdata(phy); + struct an7581_usb_phy_priv *priv =3D dev_get_drvdata(phy->dev.parent); + int ret; + + switch (instance->type) { + case PHY_TYPE_USB2: + an7581_usb_phy_u2_init(priv); + break; + case PHY_TYPE_USB3: + ret =3D phy_set_mode(priv->serdes_phy, PHY_MODE_USB_DEVICE_SS); + if (ret) + return ret; + + an7581_usb_phy_u3_init(priv); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int an7581_usb_phy_u2_power_on(struct an7581_usb_phy_priv *priv) +{ + regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, + AIROHA_USB_PHY_USB20_BC11_SW_EN); + + usleep_range(1000, 1500); + + return 0; +} + +static int an7581_usb_phy_u3_power_on(struct an7581_usb_phy_priv *priv) +{ + regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD, + AIROHA_USB_PHY_SSUSB_IP_SW_RST | + AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN | + AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST | + AIROHA_USB_PHY_SSUSB_SW_RST); + + usleep_range(1000, 1500); + + return 0; +} + +static int an7581_usb_phy_power_on(struct phy *phy) +{ + struct an7581_usb_phy_instance *instance =3D phy_get_drvdata(phy); + struct an7581_usb_phy_priv *priv =3D dev_get_drvdata(phy->dev.parent); + + switch (instance->type) { + case PHY_TYPE_USB2: + an7581_usb_phy_u2_power_on(priv); + break; + case PHY_TYPE_USB3: + an7581_usb_phy_u3_power_on(priv); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int an7581_usb_phy_u2_power_off(struct an7581_usb_phy_priv *priv) +{ + regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, + AIROHA_USB_PHY_USB20_BC11_SW_EN); + + usleep_range(1000, 1500); + + return 0; +} + +static int an7581_usb_phy_u3_power_off(struct an7581_usb_phy_priv *priv) +{ + regmap_set_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD, + AIROHA_USB_PHY_SSUSB_IP_SW_RST | + AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST); + + usleep_range(1000, 1500); + + return 0; +} + +static int an7581_usb_phy_power_off(struct phy *phy) +{ + struct an7581_usb_phy_instance *instance =3D phy_get_drvdata(phy); + struct an7581_usb_phy_priv *priv =3D dev_get_drvdata(phy->dev.parent); + + switch (instance->type) { + case PHY_TYPE_USB2: + an7581_usb_phy_u2_power_off(priv); + break; + case PHY_TYPE_USB3: + an7581_usb_phy_u3_power_off(priv); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int an7581_usb_phy_u2_set_mode(struct an7581_usb_phy_priv *priv, + enum phy_mode mode) +{ + u32 val; + + /* + * For Device and Host mode, enable force IDDIG. + * For Device set IDDIG, for Host clear IDDIG. + * For OTG disable force and clear IDDIG bit while at it. + */ + switch (mode) { + case PHY_MODE_USB_DEVICE: + val =3D AIROHA_USB_PHY_FORCE_IDDIG | + AIROHA_USB_PHY_IDDIG; + break; + case PHY_MODE_USB_HOST: + val =3D AIROHA_USB_PHY_FORCE_IDDIG; + break; + case PHY_MODE_USB_OTG: + val =3D 0; + break; + default: + return 0; + } + + regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U2PHYDTM1, + AIROHA_USB_PHY_FORCE_IDDIG | + AIROHA_USB_PHY_IDDIG, val); + + return 0; +} + +static int an7581_usb_phy_set_mode(struct phy *phy, enum phy_mode mode, in= t submode) +{ + struct an7581_usb_phy_instance *instance =3D phy_get_drvdata(phy); + struct an7581_usb_phy_priv *priv =3D dev_get_drvdata(phy->dev.parent); + + switch (instance->type) { + case PHY_TYPE_USB2: + return an7581_usb_phy_u2_set_mode(priv, mode); + default: + return 0; + } +} + +static struct phy *an7581_usb_phy_xlate(struct device *dev, + const struct of_phandle_args *args) +{ + struct an7581_usb_phy_priv *priv =3D dev_get_drvdata(dev); + struct an7581_usb_phy_instance *instance =3D NULL; + unsigned int index, phy_type; + + if (args->args_count !=3D 1) { + dev_err(dev, "invalid number of cells in 'phy' property\n"); + return ERR_PTR(-EINVAL); + } + + phy_type =3D args->args[0]; + if (!(phy_type =3D=3D PHY_TYPE_USB2 || phy_type =3D=3D PHY_TYPE_USB3)) { + dev_err(dev, "unsupported device type: %d\n", phy_type); + return ERR_PTR(-EINVAL); + } + + for (index =3D 0; index < AIROHA_PHY_USB_MAX; index++) + if (priv->phys[index] && + phy_type =3D=3D priv->phys[index]->type) { + instance =3D priv->phys[index]; + break; + } + + if (!instance) { + dev_err(dev, "failed to find appropriate phy\n"); + return ERR_PTR(-EINVAL); + } + + if (instance->type =3D=3D PHY_TYPE_USB3 && !priv->serdes_phy) { + dev_err(dev, "missing serdes phy for USB 3.0\n"); + return ERR_PTR(-EINVAL); + } + + return instance->phy; +} + +static const struct phy_ops airoha_phy =3D { + .init =3D an7581_usb_phy_init, + .power_on =3D an7581_usb_phy_power_on, + .power_off =3D an7581_usb_phy_power_off, + .set_mode =3D an7581_usb_phy_set_mode, + .owner =3D THIS_MODULE, +}; + +static const struct regmap_config an7581_usb_phy_regmap_config =3D { + .reg_bits =3D 32, + .val_bits =3D 32, + .reg_stride =3D 4, +}; + +static int an7581_usb_phy_probe(struct platform_device *pdev) +{ + struct phy_provider *phy_provider; + struct an7581_usb_phy_priv *priv; + struct device *dev =3D &pdev->dev; + unsigned int index; + void __iomem *base; + int ret; + + priv =3D devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev =3D dev; + + ret =3D of_property_read_u32(dev->of_node, "airoha,usb2-monitor-clk-sel", + &priv->monclk_sel); + if (ret) + return dev_err_probe(dev, ret, "Monitor clock selection is mandatory for= USB PHY calibration\n"); + + if (priv->monclk_sel > 3) + return dev_err_probe(dev, -EINVAL, "only 4 Monitor clock are selectable = on the SoC\n"); + + base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + priv->regmap =3D devm_regmap_init_mmio(dev, base, &an7581_usb_phy_regmap_= config); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + platform_set_drvdata(pdev, priv); + + for (index =3D 0; index < AIROHA_PHY_USB_MAX; index++) { + struct an7581_usb_phy_instance *instance; + u32 phy_type; + + switch (index) { + case AIROHA_PHY_USB2: + phy_type =3D PHY_TYPE_USB2; + break; + case AIROHA_PHY_USB3: + phy_type =3D PHY_TYPE_USB3; + break; + } + + if (phy_type =3D=3D PHY_TYPE_USB3) { + priv->serdes_phy =3D devm_phy_optional_get(dev, NULL); + if (IS_ERR(priv->serdes_phy)) + return dev_err_probe(dev, PTR_ERR(priv->serdes_phy), "error on serdes = phy for USB 3.0\n"); + } + + instance =3D devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); + if (!instance) + return -ENOMEM; + + instance->type =3D phy_type; + priv->phys[index] =3D instance; + + instance->phy =3D devm_phy_create(dev, NULL, &airoha_phy); + if (IS_ERR(instance->phy)) + return dev_err_probe(dev, PTR_ERR(instance->phy), "failed to create phy= \n"); + + phy_set_drvdata(instance->phy, instance); + } + + phy_provider =3D devm_of_phy_provider_register(&pdev->dev, an7581_usb_phy= _xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id airoha_phy_id_table[] =3D { + { .compatible =3D "airoha,an7581-usb-phy" }, + { }, +}; +MODULE_DEVICE_TABLE(of, airoha_phy_id_table); + +static struct platform_driver an7581_usb_driver =3D { + .probe =3D an7581_usb_phy_probe, + .driver =3D { + .name =3D "airoha-an7581-usb-phy", + .of_match_table =3D airoha_phy_id_table, + }, +}; + +module_platform_driver(an7581_usb_driver); + +MODULE_DESCRIPTION("Airoha AN7581 USB PHY driver"); +MODULE_AUTHOR("Christian Marangi "); +MODULE_LICENSE("GPL"); --=20 2.53.0