From nobody Fri Dec 19 15:29:50 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F1993322DD0; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760542870; cv=none; b=AnqXd4ADWw4n8NKM3Uw+TjioTQJ/qj/uQd/3y/eqguvDoCbhtiJ649YhaEE6+cE1a+RcDJQ4EBIJI/hGeAOPVYSxARoiZ6zrQxV26J8bkD3ac0Bsj4I6xLRz2T68UfNvRQEKJRBUu/zCp5zZK+7CCl95C4UE2wziXJW/eiuEolA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760542870; c=relaxed/simple; bh=z/OSrLCIdtmRJvitAMSoC1V/ZcKkiBQ7+CQlgJR3nQ4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Z1cqGwpmte0PSB82UQv5tEOlIP9WW6J++yDK1OaOy9bQ/33Y+iZYbhTQ92hgBwjc8hN0V91LYf08hkl9GtsvxOuDWvqYQJIVaqVRcrKvVE93pw60AuDei6GiQZClj39l0EPfdCs1FxL04hG1eqxnuhyGgH4cQGlqvMlqXrKP03s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CWEUMbZ7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CWEUMbZ7" Received: by smtp.kernel.org (Postfix) with ESMTPS id 724D1C4CEFB; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760542869; bh=z/OSrLCIdtmRJvitAMSoC1V/ZcKkiBQ7+CQlgJR3nQ4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CWEUMbZ7FkIaiyoh13AUuwttA8tD/Rb7mB6L1upR6nEj5AvQzsFbMn3Zu6BC1ieMg NjOBlWmjyDytBDeqwLWEn8o6CJp8KlSXZRcXJ5aI2Slb8FnWXVcmHE5nCM/TUNVTEF gAjm6cOg+0nrncu/Sdq6tnv4Kin0R7mYfiEv2tMaNHQWmL4vXGxxqmmVXHnr7GadNu LkTG2XLNPnWy4bhHW99Yy96R8yHSdi+MxZ97iRluGZdgoYKvQonXWNXwjf0U7n/Sre 4eBFw/JjJ1qd7whJx+LBbCBmJdpUG/hlsb0W0gWKrntlURy6hM4P/Sok08E3DHqYpl gQCs024IdKOVA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 68A63CCD194; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) From: Sven Peter Date: Wed, 15 Oct 2025 15:40:41 +0000 Subject: [PATCH usb-next v2 1/5] dt-bindings: usb: Add Apple dwc3 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251015-b4-aplpe-dwc3-v2-1-cbd65a2d511a@kernel.org> References: <20251015-b4-aplpe-dwc3-v2-0-cbd65a2d511a@kernel.org> In-Reply-To: <20251015-b4-aplpe-dwc3-v2-0-cbd65a2d511a@kernel.org> To: Janne Grunau , Neal Gompa , Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Thinh Nguyen , Philipp Zabel Cc: asahi@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Sven Peter , Krzysztof Kozlowski X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3194; i=sven@kernel.org; h=from:subject:message-id; bh=z/OSrLCIdtmRJvitAMSoC1V/ZcKkiBQ7+CQlgJR3nQ4=; b=owGbwMvMwCHmIlirolUq95LxtFoSQ8b7A70WgSbmX7V3HjZ/Jrxpq6XVobuLPLzehC258XnnT u2EJc8EO0pZGMQ4GGTFFFm277c3ffLwjeDSTZfew8xhZQIZwsDFKQATcc1gZLh7w3j77f+bWsWq nazmfpN0Oxn+6bd4uPHh8wczS1eHTp/MyHD2YWH2Fqkr4iU1offTi5/s903c9+Pr3UWBb0OTz3Q rhLECAA== X-Developer-Key: i=sven@kernel.org; a=openpgp; fpr=A1E3E34A2B3C820DBC4955E5993B08092F131F93 X-Endpoint-Received: by B4 Relay for sven@kernel.org/default with auth_id=407 Apple Silicon uses Synopsys DesignWare dwc3 based USB controllers for their Type-C ports. Reviewed-by: Krzysztof Kozlowski Reviewed-by: Neal Gompa Signed-off-by: Sven Peter --- .../devicetree/bindings/usb/apple,dwc3.yaml | 80 ++++++++++++++++++= ++++ MAINTAINERS | 1 + 2 files changed, 81 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/apple,dwc3.yaml b/Docume= ntation/devicetree/bindings/usb/apple,dwc3.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f70c33f32c5d6172224c524fe8e= 7218071eb4e9b --- /dev/null +++ b/Documentation/devicetree/bindings/usb/apple,dwc3.yaml @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/apple,dwc3.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Apple Silicon DWC3 USB controller + +maintainers: + - Sven Peter + +description: + Apple Silicon SoCs use a Synopsys DesignWare DWC3 based controller for e= ach of + their Type-C ports. + +allOf: + - $ref: snps,dwc3-common.yaml# + +properties: + compatible: + oneOf: + - items: + - enum: + - apple,t6000-dwc3 + - apple,t6020-dwc3 + - apple,t8112-dwc3 + - const: apple,t8103-dwc3 + - const: apple,t8103-dwc3 + + reg: + items: + - description: Core DWC3 region + - description: Apple-specific DWC3 region + + reg-names: + items: + - const: dwc3-core + - const: dwc3-apple + + interrupts: + maxItems: 1 + + iommus: + maxItems: 2 + + resets: + maxItems: 1 + + power-domains: + maxItems: 1 + +required: + - compatible + - reg + - reg-names + - interrupts + - iommus + - resets + - power-domains + - usb-role-switch + +unevaluatedProperties: false + +examples: + - | + #include + #include + + usb@82280000 { + compatible =3D "apple,t8103-dwc3"; + reg =3D <0x82280000 0xcd00>, <0x8228cd00 0x3200>; + reg-names =3D "dwc3-core", "dwc3-apple"; + interrupts =3D ; + iommus =3D <&dwc3_0_dart_0 0>, <&dwc3_0_dart_1 1>; + + power-domains =3D <&ps_atc0_usb>; + resets =3D <&atcphy0>; + + usb-role-switch; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 46126ce2f968e4f9260263f1574ee29f5ff0de1c..fa238b5371b9c5942dc89ec4fa6= b1d28e2d4dda3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2437,6 +2437,7 @@ F: Documentation/devicetree/bindings/power/reset/appl= e,smc-reboot.yaml F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml F: Documentation/devicetree/bindings/spi/apple,spi.yaml F: Documentation/devicetree/bindings/spmi/apple,spmi.yaml +F: Documentation/devicetree/bindings/usb/apple,dwc3.yaml F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml F: arch/arm64/boot/dts/apple/ F: drivers/bluetooth/hci_bcm4377.c --=20 2.34.1 From nobody Fri Dec 19 15:29:50 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F1BAE32A3C0; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760542870; cv=none; b=d52G/n1/jRwc0ZJFgtvSVI4okcv+gCoBO0lr0QU3/K3GdO/O/aGSrMep2CcZOM+yJJ6YHzDlwS6jCLuNjPeu/8CyKJkBkapsb42LE9IMg/gClagjNSXTCnMaQwRiE7Fpj+Ped7bs5UpIIJP+6xigjFL0N81kK6AD0CxVD5R+AyY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760542870; c=relaxed/simple; bh=1msbnw19IZ4ZHbNE1uvoShSsPtMAyhJKh5i9EIHWbqU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JZFtuzueAjZhlRmRzdKtpK+e1fyEZUjFX2rATyhmccox3EE8152jgkwmH8+XySUKTxr/+OFrnjLQRKvog7qEOtbbfTALsUSm+wrtQD5ExWzYja43ya/f0v8DdEZ9+PCLBHdI2j4PQfNxTuAi/6dmGCDzaDz/zE6TNovre55dKUI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DM5PC09c; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DM5PC09c" Received: by smtp.kernel.org (Postfix) with ESMTPS id 7FC48C4CEF9; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760542869; bh=1msbnw19IZ4ZHbNE1uvoShSsPtMAyhJKh5i9EIHWbqU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DM5PC09cOpAw/OkwZysLUDgkYwR4cLoLHgaya5FeN5uKfFVoI8739VjpU7Ju8MiEF LPYwi9Sr+oA+c7SywRsRGuFYJf+ZJQqw2fxe4HQRFId0Go2ysHVXbJhvrWM+eOA1mu ySXfyPk+6IfqJ1n3Vjqi2z2bBJLdgGPGo54VRQMy4qBhyFqpozuLKJ+r4Nr05Lqt/L 68KdZBYr4RqoKUl8Hy43AelM32djaPsvBFdsX585fKYehibkmIQFCmkATkVaGihxZX dXArLzJ1R91OQTyKB2UaPPtBPkppEobjpfwk00pph56b3py2VwkqtVDwjBIt1XNHix Xt4w0S45fv6zw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76B2ACCD185; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) From: Sven Peter Date: Wed, 15 Oct 2025 15:40:42 +0000 Subject: [PATCH usb-next v2 2/5] usb: dwc3: dwc3_power_off_all_roothub_ports: Use ioremap_np when required Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251015-b4-aplpe-dwc3-v2-2-cbd65a2d511a@kernel.org> References: <20251015-b4-aplpe-dwc3-v2-0-cbd65a2d511a@kernel.org> In-Reply-To: <20251015-b4-aplpe-dwc3-v2-0-cbd65a2d511a@kernel.org> To: Janne Grunau , Neal Gompa , Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Thinh Nguyen , Philipp Zabel Cc: asahi@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Sven Peter , stable@kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1424; i=sven@kernel.org; h=from:subject:message-id; bh=1msbnw19IZ4ZHbNE1uvoShSsPtMAyhJKh5i9EIHWbqU=; b=owGbwMvMwCHmIlirolUq95LxtFoSQ8b7A31sSjEtDvUzzR5N+yvqwxrwkdNxxVX+gO2x53NWL TZT6WToKGVhEONgkBVTZNm+3970ycM3gks3XXoPM4eVCWQIAxenANzkQIY/vFbmLtp2ixbxnQqK ZAgqYN1yvj68SVhMtC4uWay5iPshw//kQuufIYo5OT9S1l188z6RM2W6ToLFYQaHqg/zPdM/neM DAA== X-Developer-Key: i=sven@kernel.org; a=openpgp; fpr=A1E3E34A2B3C820DBC4955E5993B08092F131F93 X-Endpoint-Received: by B4 Relay for sven@kernel.org/default with auth_id=407 On Apple Silicon machines we can't use ioremap() / Device-nGnRE to map most regions but must use ioremap_np() / Device-nGnRnE whenever IORESOURCE_MEM_NONPOSTED is set. Make sure this is also done inside dwc3_power_off_all_roothub_ports to prevent SErrors. Fixes: 2d2a3349521d ("usb: dwc3: Add workaround for host mode VBUS glitch w= hen boot") Cc: stable@kernel.org Acked-by: Thinh Nguyen Reviewed-by: Neal Gompa Signed-off-by: Sven Peter --- drivers/usb/dwc3/host.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index 1c513bf8002ec9ec91b41bfd096cbd0da1dd2d2e..e77fd86d09cf0a36161c20ad3c8= 3f10e67099775 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -37,7 +37,10 @@ static void dwc3_power_off_all_roothub_ports(struct dwc3= *dwc) =20 /* xhci regs are not mapped yet, do it temporarily here */ if (dwc->xhci_resources[0].start) { - xhci_regs =3D ioremap(dwc->xhci_resources[0].start, DWC3_XHCI_REGS_END); + if (dwc->xhci_resources[0].flags & IORESOURCE_MEM_NONPOSTED) + xhci_regs =3D ioremap_np(dwc->xhci_resources[0].start, DWC3_XHCI_REGS_E= ND); + else + xhci_regs =3D ioremap(dwc->xhci_resources[0].start, DWC3_XHCI_REGS_END); if (!xhci_regs) { dev_err(dwc->dev, "Failed to ioremap xhci_regs\n"); return; --=20 2.34.1 From nobody Fri Dec 19 15:29:50 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F1AAD326D77; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760542870; cv=none; b=iLWTdO69DB40dI4ZBiCyHiaJrC0itmu7u9iouI86DA+Xs19BnO/ySRRoIAkuTPSMGCoAPDoPPusyffy013vw2+KNsU4xOoiBjhq5xSrfPbc4JaJJlwRtkxUSaKBrDLoCWXURiUnc6UxRkiQCq2BRoU4tevGXzo6LM/BCO+IDeJ0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760542870; c=relaxed/simple; bh=DMGFEJn/13K8pCwgFfOu2qPEs9uFdthFJZx/jrrxzCc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ccUcioJfNn1UBScyk7Ah1jKGRpxTDA0XKH1kI2AW/YmyUwQM4r4jB+RLBrmjeiOB9Jr35PcPKzg0vNd5bnps7KmXT+/aUT68OtoxV3XsDfj98pSjyWWCqcMC/wzvSNQveJB3bar6+wo8X8Yb/It7cyYc8NKJO7go6J8XsGtG6vc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UJKinHNk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UJKinHNk" Received: by smtp.kernel.org (Postfix) with ESMTPS id 8BC6FC16AAE; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760542869; bh=DMGFEJn/13K8pCwgFfOu2qPEs9uFdthFJZx/jrrxzCc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=UJKinHNkHuv/YhT9h/SGrKXTNHeypMG7qbLqNxoX0fSrT7IuLhQTp0nXMAEaUpRDH NKfhqiRX/PQmMR9iGrO7DII6VsPDc1nrmZbNxVi2mLgS2WUbHa5W2WVvpKsp4RWEf4 X0J5PLWZKhoz0wO6/L3DsNqg+QJX0PxIZmTurWRpRn/AJ3JE6r0oV7jn7E8QJWqUMi ZCHJvZC3domSXaVe8SFs6cIoNF5Uzu6vE7eo9p2guRXeOzWtJFxThLjL73Wh549D6+ Ea0Llu0HQGY30AC8Xp87Od31o2YcuF4jF59pcqjJbbiUgCZfcHTo3m6PigI9ealc8t V7q/t+apbVjzw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 83AE4CCD19D; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) From: Sven Peter Date: Wed, 15 Oct 2025 15:40:43 +0000 Subject: [PATCH usb-next v2 3/5] usb: dwc3: glue: Add documentation Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251015-b4-aplpe-dwc3-v2-3-cbd65a2d511a@kernel.org> References: <20251015-b4-aplpe-dwc3-v2-0-cbd65a2d511a@kernel.org> In-Reply-To: <20251015-b4-aplpe-dwc3-v2-0-cbd65a2d511a@kernel.org> To: Janne Grunau , Neal Gompa , Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Thinh Nguyen , Philipp Zabel Cc: asahi@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Sven Peter X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=2162; i=sven@kernel.org; h=from:subject:message-id; bh=DMGFEJn/13K8pCwgFfOu2qPEs9uFdthFJZx/jrrxzCc=; b=owGbwMvMwCHmIlirolUq95LxtFoSQ8b7AxN27CuRbuBSvboh5cUa/m7xUK/kymuzX22YsPO2S PY8rfS3HaUsDGIcDLJiiizb99ubPnn4RnDppkvvYeawMoEMYeDiFICJ7PJkZJh7crHvoRfbJvLK Ts7JCK01Spd4G1ipwDij7rP/HlbBsAhGhjlvXxvVZnCWHE7kCr7OohSv/1JYjSntzOnLVwL2GHg ycwEA X-Developer-Key: i=sven@kernel.org; a=openpgp; fpr=A1E3E34A2B3C820DBC4955E5993B08092F131F93 X-Endpoint-Received: by B4 Relay for sven@kernel.org/default with auth_id=407 We're about to add more exported functions to be used inside glue driver which will need more detailed documentation explaining how they must be used. Let's also add documentation for the functions already available. Acked-by: Thinh Nguyen Signed-off-by: Sven Peter --- drivers/usb/dwc3/glue.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/usb/dwc3/glue.h b/drivers/usb/dwc3/glue.h index cc6e138bd9ef2500215aba665300e7638f3d5214..bef4d9d68558f130f36a9088d7b= b3b1220e4c048 100644 --- a/drivers/usb/dwc3/glue.h +++ b/drivers/usb/dwc3/glue.h @@ -36,9 +36,36 @@ struct dwc3_probe_data { struct dwc3_properties properties; }; =20 +/** + * dwc3_core_probe - Initialize the core dwc3 driver + * @data: Initialization and configuration parameters for the controller + * + * Initializes the DesignWare USB3 core driver by setting up resources, + * registering interrupts, performing hardware setup, and preparing + * the controller for operation in the appropriate mode (host, gadget, + * or OTG). This is the main initialization function called by glue + * layer drivers to set up the core controller. + * + * Return: 0 on success, negative error code on failure + */ int dwc3_core_probe(const struct dwc3_probe_data *data); + +/** + * dwc3_core_remove - Deinitialize and remove the core dwc3 driver + * @dwc: Pointer to DWC3 controller context + * + * Cleans up resources and disables the dwc3 core driver. This should be c= alled + * during driver removal or when the glue layer needs to shut down the + * controller completely. + */ void dwc3_core_remove(struct dwc3 *dwc); =20 +/* + * The following callbacks are provided for glue drivers to call from their + * own pm callbacks provided in struct dev_pm_ops. Glue drivers can perform + * platform-specific work before or after calling these functions and dele= gate + * the core suspend/resume operations to the core driver. + */ int dwc3_runtime_suspend(struct dwc3 *dwc); int dwc3_runtime_resume(struct dwc3 *dwc); int dwc3_runtime_idle(struct dwc3 *dwc); --=20 2.34.1 From nobody Fri Dec 19 15:29:50 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F1A10323406; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760542870; cv=none; b=kFM9Yvy/u3NYP1lC+QAsRMIHetZFCteFTf9VJVS7OoXXlBrvrQyWF0uBsQ8V+8GiQ235qNz744iaWPviwHVpIoTaKxxYL7zWaZNMyVySxPapTEILu5Jztv5vdCgvHJPJswO985b576mvB9Q+Av8cg5yyG7OCTRMWNb1x+L5bTXk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760542870; c=relaxed/simple; bh=FhJohleAF66JXf154AOmPBA84Xh/YtcCnfugNuoKdV0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hu///tHsEbX45B6QaqmSehqYV7D6CqGH0bK1H+XxoP7JYAdHLiGCvCeSJgCCMdTcgmxDxsX+eC2rfY39FGNGOVUoQRWSpa67oQIQYcMqq9fcRG1FlVWQa51Dp1SENLckrUUVfLmkBtJB/r1QXzPUsKxN/dTrB5ud+kxDEYNV93I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cEsBohtV; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cEsBohtV" Received: by smtp.kernel.org (Postfix) with ESMTPS id 97B6AC19423; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760542869; bh=FhJohleAF66JXf154AOmPBA84Xh/YtcCnfugNuoKdV0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=cEsBohtV0Yl7ZXOgo27FHVFeC/Dfn0Qyc1Lup9Lf0g5Ssn2ai8/ZeA2EQYvFpSRvS jBHF5a7AvDQdnSttubU0AGfWA8BPNs16swhQKhIhh6nkTPVWDnUGreEO/IH2XreHLa dvEpHIOkLwkPS7G/546UZMFNNOkAP6xOsIHgWOYXVc4eF0FkeIa7uSZInZVQtpjR7+ Ty8njjq7XAnFQvo5WbEcbc189vmlwjsiXdEYx3X+RecUl1roogH/VUySSlaNYA13R6 i+CKpyeie94U8VGStiDznGlg9PVNQyf7vp5LZFCmrZaKGey6nSaI88uHDUUPuH5K2Q ArMcbrrVArs8w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 90528CCD194; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) From: Sven Peter Date: Wed, 15 Oct 2025 15:40:44 +0000 Subject: [PATCH usb-next v2 4/5] usb: dwc3: glue: Allow more fine grained control over mode switches Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251015-b4-aplpe-dwc3-v2-4-cbd65a2d511a@kernel.org> References: <20251015-b4-aplpe-dwc3-v2-0-cbd65a2d511a@kernel.org> In-Reply-To: <20251015-b4-aplpe-dwc3-v2-0-cbd65a2d511a@kernel.org> To: Janne Grunau , Neal Gompa , Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Thinh Nguyen , Philipp Zabel Cc: asahi@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Sven Peter X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=9776; i=sven@kernel.org; h=from:subject:message-id; bh=FhJohleAF66JXf154AOmPBA84Xh/YtcCnfugNuoKdV0=; b=owGbwMvMwCHmIlirolUq95LxtFoSQ8b7AxMNnbVmyE/5/VzOcE1C9JW/fWemNS1KO9SRbVeVd XrzsW3nOkpZGMQ4GGTFFFm277c3ffLwjeDSTZfew8xhZQIZwsDFKQATua7L8IfjqGCljbMMf8ln RlVjjc5vwY+yHLj4V4XOKLXYct8tupbhn0pJpyTfW52Gd7XumvteLrNwZhX7ceWhkY7X4Q9eUR/ mcgAA X-Developer-Key: i=sven@kernel.org; a=openpgp; fpr=A1E3E34A2B3C820DBC4955E5993B08092F131F93 X-Endpoint-Received: by B4 Relay for sven@kernel.org/default with auth_id=407 We need fine grained control over mode switched on the DWC3 controller present on Apple Silicon. Export core, host and gadget init and exit, ptrcap and susphy control functions. Also introduce an additional parameter to probe_data that allows to skip the final initialization step that would bring up host or gadget mode. Acked-by: Thinh Nguyen Signed-off-by: Sven Peter --- drivers/usb/dwc3/core.c | 16 +++++-- drivers/usb/dwc3/gadget.c | 2 + drivers/usb/dwc3/glue.h | 116 ++++++++++++++++++++++++++++++++++++++++++= ++++ drivers/usb/dwc3/host.c | 2 + 4 files changed, 131 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c5076580616e81c79b2da65a271f5b75e76c90e8..96f85eada047949e752776c671b= 030a1f32da1a2 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -132,6 +132,7 @@ void dwc3_enable_susphy(struct dwc3 *dwc, bool enable) dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg); } } +EXPORT_SYMBOL_GPL(dwc3_enable_susphy); =20 void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy) { @@ -158,6 +159,7 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool i= gnore_susphy) dwc->current_dr_role =3D mode; trace_dwc3_set_prtcap(mode); } +EXPORT_SYMBOL_GPL(dwc3_set_prtcap); =20 static void __dwc3_set_mode(struct work_struct *work) { @@ -975,7 +977,7 @@ static void dwc3_clk_disable(struct dwc3 *dwc) clk_disable_unprepare(dwc->bus_clk); } =20 -static void dwc3_core_exit(struct dwc3 *dwc) +void dwc3_core_exit(struct dwc3 *dwc) { dwc3_event_buffers_cleanup(dwc); dwc3_phy_power_off(dwc); @@ -983,6 +985,7 @@ static void dwc3_core_exit(struct dwc3 *dwc) dwc3_clk_disable(dwc); reset_control_assert(dwc->reset); } +EXPORT_SYMBOL_GPL(dwc3_core_exit); =20 static bool dwc3_core_is_valid(struct dwc3 *dwc) { @@ -1328,7 +1331,7 @@ static void dwc3_config_threshold(struct dwc3 *dwc) * * Returns 0 on success otherwise negative errno. */ -static int dwc3_core_init(struct dwc3 *dwc) +int dwc3_core_init(struct dwc3 *dwc) { unsigned int hw_mode; u32 reg; @@ -1528,6 +1531,7 @@ static int dwc3_core_init(struct dwc3 *dwc) =20 return ret; } +EXPORT_SYMBOL_GPL(dwc3_core_init); =20 static int dwc3_core_get_phy(struct dwc3 *dwc) { @@ -2306,9 +2310,11 @@ int dwc3_core_probe(const struct dwc3_probe_data *da= ta) dwc3_check_params(dwc); dwc3_debugfs_init(dwc); =20 - ret =3D dwc3_core_init_mode(dwc); - if (ret) - goto err_exit_debugfs; + if (!data->skip_core_init_mode) { + ret =3D dwc3_core_init_mode(dwc); + if (ret) + goto err_exit_debugfs; + } =20 pm_runtime_put(dev); =20 diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 6f18b4840a25d176abb4134581ad0ce68ba19ffc..1f67fb6aead5725c2e7b553c635= eab985c9e1d48 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -4810,6 +4810,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) err0: return ret; } +EXPORT_SYMBOL_GPL(dwc3_gadget_init); =20 /* -----------------------------------------------------------------------= --- */ =20 @@ -4828,6 +4829,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc) dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, dwc->ep0_trb, dwc->ep0_trb_addr); } +EXPORT_SYMBOL_GPL(dwc3_gadget_exit); =20 int dwc3_gadget_suspend(struct dwc3 *dwc) { diff --git a/drivers/usb/dwc3/glue.h b/drivers/usb/dwc3/glue.h index bef4d9d68558f130f36a9088d7bb3b1220e4c048..df86e14cb706ca509206677f644= da2a7225b1b26 100644 --- a/drivers/usb/dwc3/glue.h +++ b/drivers/usb/dwc3/glue.h @@ -27,12 +27,15 @@ struct dwc3_properties { * @res: resource for the DWC3 core mmio region * @ignore_clocks_and_resets: clocks and resets defined for the device sho= uld * be ignored by the DWC3 core, as they are managed by the glue + * @skip_core_init_mode: Skip the finial initialization of the target mode= , as + * it must be managed by the glue * @properties: dwc3 software manage properties */ struct dwc3_probe_data { struct dwc3 *dwc; struct resource *res; bool ignore_clocks_and_resets; + bool skip_core_init_mode; struct dwc3_properties properties; }; =20 @@ -74,4 +77,117 @@ int dwc3_pm_resume(struct dwc3 *dwc); void dwc3_pm_complete(struct dwc3 *dwc); int dwc3_pm_prepare(struct dwc3 *dwc); =20 + +/* All of the following functions must only be used with skip_core_init_mo= de */ + +/** + * dwc3_core_init - Initialize DWC3 core hardware + * @dwc: Pointer to DWC3 controller context + * + * Configures and initializes the core hardware, usually done by dwc3_core= _probe. + * This function is provided for platforms that use skip_core_init_mode an= d need + * to finalize the core initialization after some platform-specific setup. + * It must only be called when using skip_core_init_mode and before + * dwc3_host_init or dwc3_gadget_init. + * + * Return: 0 on success, negative error code on failure + */ +int dwc3_core_init(struct dwc3 *dwc); + +/** + * dwc3_core_exit - Shut down DWC3 core hardware + * @dwc: Pointer to DWC3 controller context + * + * Disables and cleans up the core hardware state. This is usually handled + * internally by dwc3 and must only be called when using skip_core_init_mo= de + * and only after dwc3_core_init. Afterwards, dwc3_core_init may be called + * again. + */ +void dwc3_core_exit(struct dwc3 *dwc); + +/** + * dwc3_host_init - Initialize host mode operation + * @dwc: Pointer to DWC3 controller context + * + * Initializes the controller for USB host mode operation, usually done by + * dwc3_core_probe or from within the dwc3 USB role switch callback. + * This function is provided for platforms that use skip_core_init_mode an= d need + * to finalize the host initialization after some platform-specific setup. + * It must not be called before dwc3_core_init or when skip_core_init_mode= is + * not used. It must also not be called when gadget or host mode has alrea= dy + * been initialized. + * + * Return: 0 on success, negative error code on failure + */ +int dwc3_host_init(struct dwc3 *dwc); + +/** + * dwc3_host_exit - Shut down host mode operation + * @dwc: Pointer to DWC3 controller context + * + * Disables and cleans up host mode resources, usually done by + * the dwc3 USB role switch callback before switching controller mode. + * It must only be called when skip_core_init_mode is used and only after + * dwc3_host_init. + */ +void dwc3_host_exit(struct dwc3 *dwc); + +/** + * dwc3_gadget_init - Initialize gadget mode operation + * @dwc: Pointer to DWC3 controller context + * + * Initializes the controller for USB gadget mode operation, usually done = by + * dwc3_core_probe or from within the dwc3 USB role switch callback. This + * function is provided for platforms that use skip_core_init_mode and nee= d to + * finalize the gadget initialization after some platform-specific setup. + * It must not be called before dwc3_core_init or when skip_core_init_mode= is + * not used. It must also not be called when gadget or host mode has alrea= dy + * been initialized. + * + * Return: 0 on success, negative error code on failure + */ +int dwc3_gadget_init(struct dwc3 *dwc); + +/** + * dwc3_gadget_exit - Shut down gadget mode operation + * @dwc: Pointer to DWC3 controller context + * + * Disables and cleans up gadget mode resources, usually done by + * the dwc3 USB role switch callback before switching controller mode. + * It must only be called when skip_core_init_mode is used and only after + * dwc3_gadget_init. + */ +void dwc3_gadget_exit(struct dwc3 *dwc); + +/** + * dwc3_enable_susphy - Control SUSPHY status for all USB ports + * @dwc: Pointer to DWC3 controller context + * @enable: True to enable SUSPHY, false to disable + * + * Enables or disables the USB3 PHY SUSPEND and USB2 PHY SUSPHY feature for + * all available ports. + * This is usually handled by the dwc3 core code and should only be used + * when skip_core_init_mode is used and the glue layer needs to manage SUS= PHY + * settings itself, e.g., due to platform-specific requirements during mode + * switches. + */ +void dwc3_enable_susphy(struct dwc3 *dwc, bool enable); + +/** + * dwc3_set_prtcap - Set the USB controller PRTCAP mode + * @dwc: Pointer to DWC3 controller context + * @mode: Target mode, must be one of DWC3_GCTL_PRTCAP_{HOST,DEVICE,OTG} + * @ignore_susphy: If true, skip disabling the SUSPHY and keep the current= state + * + * Updates PRTCAP of the controller and current_dr_role inside the dwc3 + * structure. For DRD controllers, this also disables SUSPHY unless explic= itly + * told to skip via the ignore_susphy parameter. + * + * This is usually handled by the dwc3 core code and should only be used + * when skip_core_init_mode is used and the glue layer needs to manage mode + * transitions itself due to platform-specific requirements. It must be ca= lled + * with the correct mode before calling dwc3_host_init or dwc3_gadget_init. + */ +void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy); + #endif diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index e77fd86d09cf0a36161c20ad3c83f10e67099775..cf6512ed17a69134e6ca1b884f7= 6c1439693fab1 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -220,6 +220,7 @@ int dwc3_host_init(struct dwc3 *dwc) platform_device_put(xhci); return ret; } +EXPORT_SYMBOL_GPL(dwc3_host_init); =20 void dwc3_host_exit(struct dwc3 *dwc) { @@ -230,3 +231,4 @@ void dwc3_host_exit(struct dwc3 *dwc) platform_device_unregister(dwc->xhci); dwc->xhci =3D NULL; } +EXPORT_SYMBOL_GPL(dwc3_host_exit); --=20 2.34.1 From nobody Fri Dec 19 15:29:50 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 099BD32ED40; Wed, 15 Oct 2025 15:41:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760542871; cv=none; b=GBQc/uZzySwZUU3zT9a6BMOK2us00RQ2DXzadjVth1tZdLhZ7vircDbM/xS20/Fve6fcZZFUK0x0kdy3WhzZR6Pe68/Pz++sjO6zAoUcP6Ef0wW87Om4gI61QranOeu4XTvEuIpzsUCvvP6xpmAUZqJ+oYBIJHLGyh63cwOZTFg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760542871; c=relaxed/simple; bh=mDrGMlwhavpiAsAEsqwVeZFbFYgaOlnTOqQaexF4gHw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=la59kDNGDN6CR9fES6oI/tkrpVWhZY1CHA8U4c17IKJHvVV5tGSAw2RM6XrkTqawStZU39naSxj0tmL+7Y8JFAtXBy6RGjcqiFiiczrL+jh9vcFXw0aZ50P9i/r5XkJYj+MQcNZhqOUT2VG4fudg1h9tsuhN50NPWiJx9DSA8hA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Sl0fEwps; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Sl0fEwps" Received: by smtp.kernel.org (Postfix) with ESMTPS id A6AEBC2BC87; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760542869; bh=mDrGMlwhavpiAsAEsqwVeZFbFYgaOlnTOqQaexF4gHw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Sl0fEwps1kQNf4tyT63kNzgUnE76G+JX0x7jhYpKwJaLCojyPmZmvnL0rCLmRLo7T 5DaF0hoYVG1/U+zfsPaQflTpzSN/QJIsvlERFDC56Ef+CA2uCLVgbFKOHA2zLF4fa4 uXoZVlPSS+4xz3UC63beFJPLaiB4y+umgRYVO3XbzbAxswQ8a4S4Vqzv8ENhdGwFhS BMvol9zCu5A7Q0DegiATyDAM85mZ1W4cxRFHPSjc/u+Oq3Z1iMwKXNrD2vdRTCV7gM Wqofneh2sZ4aP7Jr0/Q2IK7/+Y+Uptlq6q3gTIs/xHvgtetyM/oNDGHNog/qZI6qLb z6elEws9i67jg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9DFE9CCD185; Wed, 15 Oct 2025 15:41:09 +0000 (UTC) From: Sven Peter Date: Wed, 15 Oct 2025 15:40:45 +0000 Subject: [PATCH usb-next v2 5/5] usb: dwc3: Add Apple Silicon DWC3 glue layer driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251015-b4-aplpe-dwc3-v2-5-cbd65a2d511a@kernel.org> References: <20251015-b4-aplpe-dwc3-v2-0-cbd65a2d511a@kernel.org> In-Reply-To: <20251015-b4-aplpe-dwc3-v2-0-cbd65a2d511a@kernel.org> To: Janne Grunau , Neal Gompa , Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Thinh Nguyen , Philipp Zabel Cc: asahi@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Sven Peter X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=20561; i=sven@kernel.org; h=from:subject:message-id; bh=mDrGMlwhavpiAsAEsqwVeZFbFYgaOlnTOqQaexF4gHw=; b=owGbwMvMwCHmIlirolUq95LxtFoSQ8b7A5MvOpxPqhPlnBI/NeBw+kWppKftV77nW158vKbmj dXLmImNHaUsDGIcDLJiiizb99ubPnn4RnDppkvvYeawMoEMYeDiFICJROky/DN0tPvyTF+5TuDb 1EjH5Ye+X3y8df7j9f9ijyU18Jc9Tn/O8FdwT+6hgAfM/t/7Juca1m7e4b9c/tFXf8fVbg+e1kT uLuUAAA== X-Developer-Key: i=sven@kernel.org; a=openpgp; fpr=A1E3E34A2B3C820DBC4955E5993B08092F131F93 X-Endpoint-Received: by B4 Relay for sven@kernel.org/default with auth_id=407 The dwc3 controller present on Apple Silicon SoCs like the M1 requires a specific order of operations synchronized between its PHY and its Type-C controller. Specifically, the PHY first has to go through initial bringup (which requires knowledge of the lane mode and orientation) before dwc3 itself can be brought up and can then finalize the PHY configuration. Additionally, dwc3 has to be teared down and re-initialized whenever the cable is changed due to hardware quirks that prevent a new device from being recognized and due to the PHY being unable to switch lane mode or orientation while dwc3 is up and running. These controllers also have a Apple-specific MMIO region after the common dwc3 region where some controls have to be updated. PHY bringup and shutdown also requires SUSPHY to be enabled for the ports to work correctly. In the future, this driver will also gain support for USB3-via-USB4 tunneling which will require additional tweaks. Add a glue driver that takes of all of these constraints. Reviewed-by: Neal Gompa Acked-by: Thinh Nguyen Signed-off-by: Sven Peter --- MAINTAINERS | 1 + drivers/usb/dwc3/Kconfig | 11 + drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/dwc3-apple.c | 489 ++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 502 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index fa238b5371b9c5942dc89ec4fa6b1d28e2d4dda3..28bfefd7ecb895e2721800dbb3b= 954c4bdd9f539 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2462,6 +2462,7 @@ F: drivers/pwm/pwm-apple.c F: drivers/soc/apple/* F: drivers/spi/spi-apple.c F: drivers/spmi/spmi-apple-controller.c +F: drivers/usb/dwc3/dwc3-apple.c F: drivers/video/backlight/apple_dwi_bl.c F: drivers/watchdog/apple_wdt.c F: include/dt-bindings/interrupt-controller/apple-aic.h diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 4925d15084f816d3ff92059b476ebcc799b56b51..bf3e04635131005096c6bc1802b= 251490ad2f483 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -200,4 +200,15 @@ config USB_DWC3_GENERIC_PLAT the dwc3 child node in the device tree. Say 'Y' or 'M' here if your platform integrates DWC3 in a similar way. =20 +config USB_DWC3_APPLE + tristate "Apple Silicon DWC3 Platform Driver" + depends on OF && ARCH_APPLE + default USB_DWC3 + select USB_ROLE_SWITCH + help + Support Apple Silicon SoCs with DesignWare Core USB3 IP. + The DesignWare Core USB3 IP has to be used in dual-role + mode on these machines. + Say 'Y' or 'M' if you have such device. + endif diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 96469e48ff9d189cc8d0b65e65424eae2158bcfe..89d46ab5006856c51b5007ecdd8= fbdf431ecba40 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -43,6 +43,7 @@ endif ## =20 obj-$(CONFIG_USB_DWC3_AM62) +=3D dwc3-am62.o +obj-$(CONFIG_USB_DWC3_APPLE) +=3D dwc3-apple.o obj-$(CONFIG_USB_DWC3_OMAP) +=3D dwc3-omap.o obj-$(CONFIG_USB_DWC3_EXYNOS) +=3D dwc3-exynos.o obj-$(CONFIG_USB_DWC3_PCI) +=3D dwc3-pci.o diff --git a/drivers/usb/dwc3/dwc3-apple.c b/drivers/usb/dwc3/dwc3-apple.c new file mode 100644 index 0000000000000000000000000000000000000000..6e41bd0e34f461b0c3db9b8a646= 116458ff816b6 --- /dev/null +++ b/drivers/usb/dwc3/dwc3-apple.c @@ -0,0 +1,489 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Apple Silicon DWC3 Glue driver + * Copyright (C) The Asahi Linux Contributors + * + * Based on: + * - dwc3-qcom.c Copyright (c) 2018, The Linux Foundation. All rights res= erved. + * - dwc3-of-simple.c Copyright (c) 2015 Texas Instruments Incorporated -= https://www.ti.com + */ + +#include +#include +#include +#include +#include + +#include "glue.h" + +/* + * This platform requires a very specific sequence of operations to bring = up dwc3 and its USB3 PHY: + * + * 1) The PHY itself has to be brought up; for this we need to know the mo= de (USB3, + * USB3+DisplayPort, USB4, etc) and the lane orientation. This happens = through typec_mux_set. + * 2) DWC3 has to be brought up but we must not touch the gadget area or s= tart xhci yet. + * 3) The PHY bring-up has to be finalized and dwc3's PIPE interface has t= o be switched to the + * USB3 PHY, this is done inside phy_set_mode. + * 4) We can now initialize xhci or gadget mode. + * + * We can switch 1 and 2 but 3 has to happen after (1 and 2) and 4 has to = happen after 3. + * + * And then to bring this all down again: + * + * 1) DWC3 has to exit host or gadget mode and must no longer touch those = registers + * 2) The PHY has to switch dwc3's PIPE interface back to the dummy backend + * 3) The PHY itself can be shut down, this happens from typec_mux_set + * + * We also can't transition the PHY from one mode to another while dwc3 is= up and running (this is + * slightly wrong, some transitions are possible, others aren't but becaus= e we have no documentation + * for this I'd rather play it safe). + * + * After both the PHY and dwc3 are initialized we will only ever see a sin= gle "new device connected" + * event. If we just keep them running only the first device plugged in wi= ll ever work. XHCI's port + * status register actually does show the correct state but no interrupt e= ver comes in. In gadget + * mode we don't even get a USBDisconnected event and everything looks lik= e there's still something + * connected on the other end. + * This can be partially explained because the USB2 D+/D- lines are connec= ted through a stateful + * eUSB2 repeater which in turn is controlled by a variant of the TI TPS65= 98x USB PD chip which + * resets the repeater out-of-band everytime the CC lines are (dis)connect= ed. This then requires a + * PHY reset to make sure the PHY and the eUSB2 repeater state are synchro= nized again. + * + * And to make this all extra fun: If we get the order of some of this wro= ng either the port is just + * broken until a phy+dwc3 reset, or it's broken until a full SoC reset (l= ikely because we can't + * reset some parts of the PHY), or some watchdog kicks in after a few sec= onds and forces a full SoC + * reset (mostly seen this with USB4/Thunderbolt but there's clearly some = watchdog that hates + * invalid states). + * + * Hence there's really no good way to keep dwc3 fully up and running afte= r we disconnect a cable + * because then we can't shut down the PHY anymore. And if we kept the PHY= running in whatever mode + * it was until the next cable is connected we'd need to tear it all down = and bring it back up again + * anyway to detect and use the next device. + * + * Instead, we just shut down everything when a cable is disconnected and = transition to + * DWC3_APPLE_NO_CABLE. + * During initial probe we don't have any information about the connected = cable and can't bring up + * the PHY properly and thus also can't fully bring up dwc3. Instead, we j= ust keep everything off + * and defer the first dwc3 probe until we get the first cable connected e= vent. Until then we stay + * in DWC3_APPLE_PROBE_PENDING. + * Once a cable is connected we then keep track of the controller mode her= e by transitioning to + * DWC3_APPLE_HOST or DWC3_APPLE_DEVICE. + */ +enum dwc3_apple_state { + DWC3_APPLE_PROBE_PENDING, /* Before first cable connection, dwc3_core_pro= be not called */ + DWC3_APPLE_NO_CABLE, /* No cable connected, dwc3 suspended after dwc3_cor= e_exit */ + DWC3_APPLE_HOST, /* Cable connected, dwc3 in host mode */ + DWC3_APPLE_DEVICE, /* Cable connected, dwc3 in device mode */ +}; + +/** + * struct dwc3_apple - Apple-specific DWC3 USB controller + * @dwc: Core DWC3 structure + * @dev: Pointer to the device structure + * @mmio_resource: Resource to be passed to dwc3_core_probe + * @apple_regs: Apple-specific DWC3 registers + * @resets: Reset control + * @role_sw: USB role switch + * @lock: Mutex for synchronizing access + * @state: Current state of the controller, see documentation for the enum= for details + */ +struct dwc3_apple { + struct dwc3 dwc; + + struct device *dev; + struct resource *mmio_resource; + void __iomem *apple_regs; + + struct reset_control *resets; + struct usb_role_switch *role_sw; + + struct mutex lock; + + enum dwc3_apple_state state; +}; + +#define to_dwc3_apple(d) container_of((d), struct dwc3_apple, dwc) + +/* + * Apple Silicon dwc3 vendor-specific registers + * + * These registers were identified by tracing XNU's memory access patterns= and correlating them with + * debug output over serial to determine their names. We don't exactly kno= w what these do but + * without these USB3 devices sometimes don't work. + */ +#define APPLE_DWC3_REGS_START 0xcd00 +#define APPLE_DWC3_REGS_END 0xcdff + +#define APPLE_DWC3_CIO_LFPS_OFFSET 0xcd38 +#define APPLE_DWC3_CIO_LFPS_OFFSET_VALUE 0xf800f80 + +#define APPLE_DWC3_CIO_BW_NGT_OFFSET 0xcd3c +#define APPLE_DWC3_CIO_BW_NGT_OFFSET_VALUE 0xfc00fc0 + +#define APPLE_DWC3_CIO_LINK_TIMER 0xcd40 +#define APPLE_DWC3_CIO_PENDING_HP_TIMER GENMASK(23, 16) +#define APPLE_DWC3_CIO_PENDING_HP_TIMER_VALUE 0x14 +#define APPLE_DWC3_CIO_PM_LC_TIMER GENMASK(15, 8) +#define APPLE_DWC3_CIO_PM_LC_TIMER_VALUE 0xa +#define APPLE_DWC3_CIO_PM_ENTRY_TIMER GENMASK(7, 0) +#define APPLE_DWC3_CIO_PM_ENTRY_TIMER_VALUE 0x10 + +static inline void dwc3_apple_writel(struct dwc3_apple *appledwc, u32 offs= et, u32 value) +{ + writel(value, appledwc->apple_regs + offset - APPLE_DWC3_REGS_START); +} + +static inline u32 dwc3_apple_readl(struct dwc3_apple *appledwc, u32 offset) +{ + return readl(appledwc->apple_regs + offset - APPLE_DWC3_REGS_START); +} + +static inline void dwc3_apple_mask(struct dwc3_apple *appledwc, u32 offset= , u32 mask, u32 value) +{ + u32 reg; + + reg =3D dwc3_apple_readl(appledwc, offset); + reg &=3D ~mask; + reg |=3D value; + dwc3_apple_writel(appledwc, offset, reg); +} + +static void dwc3_apple_setup_cio(struct dwc3_apple *appledwc) +{ + dwc3_apple_writel(appledwc, APPLE_DWC3_CIO_LFPS_OFFSET, APPLE_DWC3_CIO_LF= PS_OFFSET_VALUE); + dwc3_apple_writel(appledwc, APPLE_DWC3_CIO_BW_NGT_OFFSET, + APPLE_DWC3_CIO_BW_NGT_OFFSET_VALUE); + dwc3_apple_mask(appledwc, APPLE_DWC3_CIO_LINK_TIMER, APPLE_DWC3_CIO_PENDI= NG_HP_TIMER, + FIELD_PREP(APPLE_DWC3_CIO_PENDING_HP_TIMER, + APPLE_DWC3_CIO_PENDING_HP_TIMER_VALUE)); + dwc3_apple_mask(appledwc, APPLE_DWC3_CIO_LINK_TIMER, APPLE_DWC3_CIO_PM_LC= _TIMER, + FIELD_PREP(APPLE_DWC3_CIO_PM_LC_TIMER, APPLE_DWC3_CIO_PM_LC_TIMER_VALUE= )); + dwc3_apple_mask(appledwc, APPLE_DWC3_CIO_LINK_TIMER, APPLE_DWC3_CIO_PM_EN= TRY_TIMER, + FIELD_PREP(APPLE_DWC3_CIO_PM_ENTRY_TIMER, + APPLE_DWC3_CIO_PM_ENTRY_TIMER_VALUE)); +} + +static void dwc3_apple_set_ptrcap(struct dwc3_apple *appledwc, u32 mode) +{ + guard(spinlock_irqsave)(&appledwc->dwc.lock); + dwc3_set_prtcap(&appledwc->dwc, mode, false); +} + +static int dwc3_apple_core_probe(struct dwc3_apple *appledwc) +{ + struct dwc3_probe_data probe_data =3D {}; + int ret; + + lockdep_assert_held(&appledwc->lock); + WARN_ON_ONCE(appledwc->state !=3D DWC3_APPLE_PROBE_PENDING); + + appledwc->dwc.dev =3D appledwc->dev; + probe_data.dwc =3D &appledwc->dwc; + probe_data.res =3D appledwc->mmio_resource; + probe_data.ignore_clocks_and_resets =3D true; + probe_data.skip_core_init_mode =3D true; + probe_data.properties =3D DWC3_DEFAULT_PROPERTIES; + + ret =3D dwc3_core_probe(&probe_data); + if (ret) + return ret; + + appledwc->state =3D DWC3_APPLE_NO_CABLE; + return 0; +} + +static int dwc3_apple_core_init(struct dwc3_apple *appledwc) +{ + int ret; + + lockdep_assert_held(&appledwc->lock); + + switch (appledwc->state) { + case DWC3_APPLE_PROBE_PENDING: + ret =3D dwc3_apple_core_probe(appledwc); + if (ret) + dev_err(appledwc->dev, "Failed to probe DWC3 Core, err=3D%d\n", ret); + break; + case DWC3_APPLE_NO_CABLE: + ret =3D dwc3_core_init(&appledwc->dwc); + if (ret) + dev_err(appledwc->dev, "Failed to initialize DWC3 Core, err=3D%d\n", re= t); + break; + default: + /* Unreachable unless there's a bug in this driver */ + WARN_ON_ONCE(1); + ret =3D -EINVAL; + break; + } + + return ret; +} + +static void dwc3_apple_phy_set_mode(struct dwc3_apple *appledwc, enum phy_= mode mode) +{ + lockdep_assert_held(&appledwc->lock); + + /* + * This platform requires SUSPHY to be enabled here already in order to p= roperly configure + * the PHY and switch dwc3's PIPE interface to USB3 PHY. + */ + dwc3_enable_susphy(&appledwc->dwc, true); + phy_set_mode(appledwc->dwc.usb2_generic_phy[0], mode); + phy_set_mode(appledwc->dwc.usb3_generic_phy[0], mode); +} + +static int dwc3_apple_init(struct dwc3_apple *appledwc, enum dwc3_apple_st= ate state) +{ + int ret, ret_reset; + + lockdep_assert_held(&appledwc->lock); + + ret =3D reset_control_deassert(appledwc->resets); + if (ret) { + dev_err(appledwc->dev, "Failed to deassert resets, err=3D%d\n", ret); + return ret; + } + + ret =3D dwc3_apple_core_init(appledwc); + if (ret) + goto reset_assert; + + /* + * Now that the core is initialized and already went through dwc3_core_so= ft_reset we can + * configure some unknown Apple-specific settings and then bring up xhci = or gadget mode. + */ + dwc3_apple_setup_cio(appledwc); + + switch (state) { + case DWC3_APPLE_HOST: + appledwc->dwc.dr_mode =3D USB_DR_MODE_HOST; + dwc3_apple_set_ptrcap(appledwc, DWC3_GCTL_PRTCAP_HOST); + dwc3_apple_phy_set_mode(appledwc, PHY_MODE_USB_HOST); + ret =3D dwc3_host_init(&appledwc->dwc); + if (ret) { + dev_err(appledwc->dev, "Failed to initialize host, ret=3D%d\n", ret); + goto core_exit; + } + + break; + case DWC3_APPLE_DEVICE: + appledwc->dwc.dr_mode =3D USB_DR_MODE_PERIPHERAL; + dwc3_apple_set_ptrcap(appledwc, DWC3_GCTL_PRTCAP_DEVICE); + dwc3_apple_phy_set_mode(appledwc, PHY_MODE_USB_DEVICE); + ret =3D dwc3_gadget_init(&appledwc->dwc); + if (ret) { + dev_err(appledwc->dev, "Failed to initialize gadget, ret=3D%d\n", ret); + goto core_exit; + } + break; + default: + /* Unreachable unless there's a bug in this driver */ + WARN_ON_ONCE(1); + ret =3D -EINVAL; + goto core_exit; + } + + appledwc->state =3D state; + return 0; + +core_exit: + dwc3_core_exit(&appledwc->dwc); +reset_assert: + ret_reset =3D reset_control_assert(appledwc->resets); + if (ret_reset) + dev_warn(appledwc->dev, "Failed to assert resets, err=3D%d\n", ret_reset= ); + + return ret; +} + +static int dwc3_apple_exit(struct dwc3_apple *appledwc) +{ + int ret =3D 0; + + lockdep_assert_held(&appledwc->lock); + + switch (appledwc->state) { + case DWC3_APPLE_PROBE_PENDING: + case DWC3_APPLE_NO_CABLE: + /* Nothing to do if we're already off */ + return 0; + case DWC3_APPLE_DEVICE: + dwc3_gadget_exit(&appledwc->dwc); + break; + case DWC3_APPLE_HOST: + dwc3_host_exit(&appledwc->dwc); + break; + } + + /* + * This platform requires SUSPHY to be enabled in order to properly power= down the PHY + * and switch dwc3's PIPE interface back to a dummy PHY (i.e. no USB3 sup= port and USB2 via + * a different PHY connected through ULPI). + */ + dwc3_enable_susphy(&appledwc->dwc, true); + dwc3_core_exit(&appledwc->dwc); + appledwc->state =3D DWC3_APPLE_NO_CABLE; + + ret =3D reset_control_assert(appledwc->resets); + if (ret) { + dev_err(appledwc->dev, "Failed to assert resets, err=3D%d\n", ret); + return ret; + } + + return 0; +} + +static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, enum usb_r= ole role) +{ + struct dwc3_apple *appledwc =3D usb_role_switch_get_drvdata(sw); + int ret; + + guard(mutex)(&appledwc->lock); + + /* + * We need to tear all of dwc3 down and re-initialize it every time a cab= le is + * connected or disconnected or when the mode changes. See the documentat= ion for enum + * dwc3_apple_state for details. + */ + ret =3D dwc3_apple_exit(appledwc); + if (ret) + return ret; + + switch (role) { + case USB_ROLE_NONE: + /* Nothing to do if no cable is connected */ + return 0; + case USB_ROLE_HOST: + return dwc3_apple_init(appledwc, DWC3_APPLE_HOST); + case USB_ROLE_DEVICE: + return dwc3_apple_init(appledwc, DWC3_APPLE_DEVICE); + default: + dev_err(appledwc->dev, "Invalid target role: %d\n", role); + return -EINVAL; + } +} + +static enum usb_role dwc3_usb_role_switch_get(struct usb_role_switch *sw) +{ + struct dwc3_apple *appledwc =3D usb_role_switch_get_drvdata(sw); + + guard(mutex)(&appledwc->lock); + + switch (appledwc->state) { + case DWC3_APPLE_HOST: + return USB_ROLE_HOST; + case DWC3_APPLE_DEVICE: + return USB_ROLE_DEVICE; + case DWC3_APPLE_NO_CABLE: + case DWC3_APPLE_PROBE_PENDING: + return USB_ROLE_NONE; + default: + /* Unreachable unless there's a bug in this driver */ + dev_err(appledwc->dev, "Invalid internal state: %d\n", appledwc->state); + return USB_ROLE_NONE; + } +} + +static int dwc3_apple_setup_role_switch(struct dwc3_apple *appledwc) +{ + struct usb_role_switch_desc dwc3_role_switch =3D { NULL }; + + dwc3_role_switch.fwnode =3D dev_fwnode(appledwc->dev); + dwc3_role_switch.set =3D dwc3_usb_role_switch_set; + dwc3_role_switch.get =3D dwc3_usb_role_switch_get; + dwc3_role_switch.driver_data =3D appledwc; + appledwc->role_sw =3D usb_role_switch_register(appledwc->dev, &dwc3_role_= switch); + if (IS_ERR(appledwc->role_sw)) + return PTR_ERR(appledwc->role_sw); + + return 0; +} + +static int dwc3_apple_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct dwc3_apple *appledwc; + int ret; + + appledwc =3D devm_kzalloc(&pdev->dev, sizeof(*appledwc), GFP_KERNEL); + if (!appledwc) + return -ENOMEM; + + appledwc->dev =3D &pdev->dev; + mutex_init(&appledwc->lock); + + appledwc->resets =3D devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(appledwc->resets)) + return dev_err_probe(&pdev->dev, PTR_ERR(appledwc->resets), + "Failed to get resets\n"); + + ret =3D reset_control_assert(appledwc->resets); + if (ret) { + dev_err(&pdev->dev, "Failed to assert resets, err=3D%d\n", ret); + return ret; + } + + appledwc->mmio_resource =3D platform_get_resource_byname(pdev, IORESOURCE= _MEM, "dwc3-core"); + if (!appledwc->mmio_resource) { + dev_err(dev, "Failed to get DWC3 MMIO\n"); + return -EINVAL; + } + + appledwc->apple_regs =3D devm_platform_ioremap_resource_byname(pdev, "dwc= 3-apple"); + if (IS_ERR(appledwc->apple_regs)) + return dev_err_probe(dev, PTR_ERR(appledwc->apple_regs), + "Failed to map Apple-specific MMIO\n"); + + /* + * On this platform, DWC3 can only be brought up after parts of the PHY h= ave been + * initialized with knowledge of the target mode and cable orientation fr= om typec_set_mux. + * Since this has not happened here we cannot setup DWC3 yet and instead = defer this until + * the first cable is connected. See the documentation for enum dwc3_appl= e_state for + * details. + */ + appledwc->state =3D DWC3_APPLE_PROBE_PENDING; + ret =3D dwc3_apple_setup_role_switch(appledwc); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Failed to setup role switch\n"); + + return 0; +} + +static void dwc3_apple_remove(struct platform_device *pdev) +{ + struct dwc3 *dwc =3D platform_get_drvdata(pdev); + struct dwc3_apple *appledwc =3D to_dwc3_apple(dwc); + + guard(mutex)(&appledwc->lock); + + usb_role_switch_unregister(appledwc->role_sw); + + /* + * If we're still in DWC3_APPLE_PROBE_PENDING we never got any cable conn= ected event and + * dwc3_core_probe was never called and there's hence no need to call dwc= 3_core_remove. + * dwc3_apple_exit can be called unconditionally because it checks the st= ate itself. + */ + dwc3_apple_exit(appledwc); + if (appledwc->state !=3D DWC3_APPLE_PROBE_PENDING) + dwc3_core_remove(&appledwc->dwc); +} + +static const struct of_device_id dwc3_apple_of_match[] =3D { + { .compatible =3D "apple,t8103-dwc3" }, + {} +}; +MODULE_DEVICE_TABLE(of, dwc3_apple_of_match); + +static struct platform_driver dwc3_apple_driver =3D { + .probe =3D dwc3_apple_probe, + .remove =3D dwc3_apple_remove, + .driver =3D { + .name =3D "dwc3-apple", + .of_match_table =3D dwc3_apple_of_match, + }, +}; + +module_platform_driver(dwc3_apple_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sven Peter "); +MODULE_DESCRIPTION("DesignWare DWC3 Apple Silicon Glue Driver"); --=20 2.34.1