From nobody Fri Dec 19 15:29:47 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 4EC9A30C603; Mon, 13 Oct 2025 16:03:58 +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=1760371438; cv=none; b=bt8kKf8O9fe8VZxFI+WjgV+SKOSy8J9FkR4yDVPkN4s4dNukpxDWnih9Q5phshvqBATu7Ci8XiwmGyp2NXcpGKNe5S9CzAn1aT8T340oBsbtfWg+XB+OfmBpcuw1dDMZ48sJ21lTZ/KuMr5aNRWeOzyg7+ohkTBYTbLuslWu5/Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760371438; 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=GJytM+VpuP0KyuOFdQUKQMGWfWchEQxf//7raf14C+ZscNLnp2U92K4vVM/HwmHd+F8FIacOb4JLkRVaJk/nDhb5MCJTv7jipSwKTjFTSzzhpyEYYSyeRK53bdZH5PUt0Vi1TK39EAgVfbukCcr2RYLjTTIfYOyqs0+P/3qtqt0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Fl0aqPEr; 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="Fl0aqPEr" Received: by smtp.kernel.org (Postfix) with ESMTPS id EFF74C116B1; Mon, 13 Oct 2025 16:03:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760371438; bh=z/OSrLCIdtmRJvitAMSoC1V/ZcKkiBQ7+CQlgJR3nQ4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Fl0aqPErkVW14o7xQ6K2Ak8ZjFqCTZEf0HlOb98c7a0rJPv8SVW5qVegVCv2/JnMq E3YXshFL83zhgF0g2dd1VVeUWFvFvFbhcztLC4sTb+i7XzJ5aREqLdSzE3iPVUa6JQ ilVVBIBJAQuTDtbrfATuELgnD78aUuF5/wG6o5GaMYvOHP+5cgXwzWxmNQb7+XRGu6 xkXaVkhAUOCLSLi6bYdskKfFxvpjZYuvUPNPkwoZU1LcOYp3LnezOqLlI5tIbwu1nT JXZqZQiDiqzVgSpuH2FfPjyNvot6zbAZRxCkJoxfqu0vDW5Mea1VABcEiN8hTWaG5F 8a6kvf6lyWIOg== 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 DEF4CCCD18E; Mon, 13 Oct 2025 16:03:57 +0000 (UTC) From: Sven Peter Date: Mon, 13 Oct 2025 16:03:25 +0000 Subject: [PATCH 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: <20251013-b4-aplpe-dwc3-v1-1-12a78000c014@kernel.org> References: <20251013-b4-aplpe-dwc3-v1-0-12a78000c014@kernel.org> In-Reply-To: <20251013-b4-aplpe-dwc3-v1-0-12a78000c014@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=owGbwMvMwCHmIlirolUq95LxtFoSQ8Zbpccz9skv/7P7evUj9/3eN09drrF6fvLsnTceX5qnG M+asmPpy45SFgYxDgZZMUWW7fvtTZ88fCO4dNOl9zBzWJlAhjBwcQrARAy8Gf7Xai0MeXTJam+Z ieivNVYa5yYdPLF49uZJSt9POjYGGKyVZPjD0bVG/wLTh+Qd/q9ElDZP/NRx85Cq9jGjRMsis6U ZFZV8AA== 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:47 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 4EB93228CB0; Mon, 13 Oct 2025 16:03:58 +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=1760371438; cv=none; b=TZR59JC/vYD0d8wECj7yuRI3xXu9ajfBOpxoVySkmg0CNhA3A09FycKp5haowF5kdMvP4pG+sEZFL94SS5/f1JarauPfxpExVTnUlcgZYeKN4mBRLf2ap6U2qEHXADQjSV8mreDS47WmAO5dzLcHFQ5Pu5ZAXlPL7GYC6cX2/nY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760371438; c=relaxed/simple; bh=1msbnw19IZ4ZHbNE1uvoShSsPtMAyhJKh5i9EIHWbqU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ChFom5zIGUXKvA8c438MWKbHxAcUtsm0piQeYo2pQhzTq/CoTVNGG8RU7ha000AM7SLNLoSJuhbbNt95LVSKsJE0rIU3YeajOg6U+Zsni+uOUjnR7dQVRvo/d/dn4uSlz9Ko19+UTZUyzR/JRPghTidg9soIwH80VmucvChNkgo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tcgrY57x; 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="tcgrY57x" Received: by smtp.kernel.org (Postfix) with ESMTPS id 07B83C4CEE7; Mon, 13 Oct 2025 16:03:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760371438; bh=1msbnw19IZ4ZHbNE1uvoShSsPtMAyhJKh5i9EIHWbqU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tcgrY57xbQJPNoedJMEgxY56xS2Dm6qFSuAVD6JQtugMah1NTOWGkBFet1tA7mYr2 hcFVE86nZuHst2FuW6t7Yiur7XYMbMYarRPG2mehUIn4l8SukgGmalv8lIOSmQDiic vn2FKnp1A9CKQWew0xxh4fK2w+oUoEZserb0iyNf3eFj0D8jFczYucy8awUTW5kNAw kx7tUerxkiwL8NlmG0vZiM9HwPJv08VneZ7+5PZYhM5FfMM3IabxhhzFacw8vTtU0S iwolXKTNgV8Sxw4VxT4cMZ4Dg+ejuz5WkwmNkZXdxBAssICyV4iqQ7GqNwxmQZ2LR5 ef2JDTYXUrWcw== 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 EDC9CCCD18F; Mon, 13 Oct 2025 16:03:57 +0000 (UTC) From: Sven Peter Date: Mon, 13 Oct 2025 16:03:26 +0000 Subject: [PATCH 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: <20251013-b4-aplpe-dwc3-v1-2-12a78000c014@kernel.org> References: <20251013-b4-aplpe-dwc3-v1-0-12a78000c014@kernel.org> In-Reply-To: <20251013-b4-aplpe-dwc3-v1-0-12a78000c014@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=owGbwMvMwCHmIlirolUq95LxtFoSQ8Zbpae/bNrM77haON2MDD4TO4Xn+02Np08KvjaX/pDm6 agtv8naUcrCIMbBICumyLJ9v73pk4dvBJduuvQeZg4rE8gQBi5OAZhIwT1Ghum8ydkWR9aZvDTb 9XX+WrX7JyqTp57NK7yitn+aitrXts+MDM+2F5uJx3e9/p7rF3nX0ztgtapY7M2w75G+d1IeGLm 6cQMA 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:47 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 5A24330CD9C; Mon, 13 Oct 2025 16:03:58 +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=1760371438; cv=none; b=bBbrPx1Ca8bl7PFgeQjI5QrXX4xbf2Knas7pO6YH4R5IT4UeOCIc1I9uG/ghShtmWMT3+Epk4rvDMvDX5BsS3kDw/tToYq1zsoMotS41YtwAhb3Ui/AE14MlQj1EW/j4L8lNotlgO7zbSaoi6FHIpHs+UwkO0fvOF9w8vn8v7lU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760371438; c=relaxed/simple; bh=b88sn5mMVCk/oe5CLT9hyAX+U6n1DTFMv6pGutiyXM0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=J2WN2zc2UetgMbtffUdqEJlhtRrI25++eirKN1ni5EohJGZsIz3GWbiRSfKXdOaMdDwu1x2Mpduf9fOkDHMVOuL0DyqCHjwugoQh/FD/5cYnHkDYcuMb5PwQjlBy4qJS8H4oTEb1v3RleDVezU5s1O3GgiT/ldUoKlR3Z+Z2ack= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=psItepZl; 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="psItepZl" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1584BC116C6; Mon, 13 Oct 2025 16:03:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760371438; bh=b88sn5mMVCk/oe5CLT9hyAX+U6n1DTFMv6pGutiyXM0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=psItepZlr5BidPnhnrXeKzfcN+bhsV8zT7H/KZogbgEXuuPLi0JHfn5v+/FJkOFtp UNhZM36g7Kcou49QDr6dv38inMPlAIz7SZWGKbvStunUBf4Q6lM09rNUYyy39wQP5R wZV9eXOWLQjSEI4ujbumA9+KXK89nQ7JGYFZqoZqEQVDFIeWzCq9cLOUH6wrBOFiNA O2JnKt2xUOdWXGwJcZ4qgPMW3cJHywdKBZaank+2mnIqLITsgyq0f+6Q9cKDcIeIep rxncTFTbHKrN0TH8fXWG/NQUa0LAanJjIaCsxgriO2CBfoSDsQ2um5nDoWvkQCk1EU wDg/zPtfMCsqQ== 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 07735CCD183; Mon, 13 Oct 2025 16:03:58 +0000 (UTC) From: Sven Peter Date: Mon, 13 Oct 2025 16:03:27 +0000 Subject: [PATCH 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: <20251013-b4-aplpe-dwc3-v1-3-12a78000c014@kernel.org> References: <20251013-b4-aplpe-dwc3-v1-0-12a78000c014@kernel.org> In-Reply-To: <20251013-b4-aplpe-dwc3-v1-0-12a78000c014@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=2106; i=sven@kernel.org; h=from:subject:message-id; bh=b88sn5mMVCk/oe5CLT9hyAX+U6n1DTFMv6pGutiyXM0=; b=owGbwMvMwCHmIlirolUq95LxtFoSQ8Zbpeez9SvfLDxyJURQn3vStN9Rsh5lJ2ZkP9//cuWvO YEbd25g7ShlYRDjYJAVU2TZvt/e9MnDN4JLN116DzOHlQlkCAMXpwBM5HUrw/+EnzNf9P47v+js /+//tFbfE5wZdqUi5ojfU+XvpeYO13oiGRme73yzLqXW7vGi1OxAvaxkhYrCEDNxnhXXPDIOKUj 2B/IDAA== 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. 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 2efd00e763be4fc51911f32d43054059e61fb43a..7f326cff12458901904d4c32f62= ed9357d0f6e3b 100644 --- a/drivers/usb/dwc3/glue.h +++ b/drivers/usb/dwc3/glue.h @@ -22,9 +22,36 @@ struct dwc3_probe_data { bool ignore_clocks_and_resets; }; =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:47 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 5A2BE30CDB0; Mon, 13 Oct 2025 16:03:58 +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=1760371438; cv=none; b=VnsfkxsRnNkN1TB8dO3TvmRSvd8k0fzg8gRJngKMSWFjkMiV5JbZFWsVFmtRrJWXEqNSpirnM/y9vAIJ1egj/mEVEmDgm69BOoGfwoKJplviaye37FAWtK1utPrARGQjkY0OYQlklOdqRGiNYq4vA9Mr7HoYLSIedbbLXy1ByH4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760371438; c=relaxed/simple; bh=T61ohRMVKcvJNe8i5gn6zOUU4mTTUUvrMUaTCo42RLE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eKB3UFMhoQ1NFP6j0qcZToTqccG7Bh1y7HZRCgxB0g292fZPgSrB/v3gsSbTTzUzxmzbGOOhzgODFB92CfYe1ndNsBmGDPhKA6zOnzISFf5lm5fOQVMPJm1kjp51C98KEzBqsR6ZcxDXWQa1rJqi3tW8GCN2IY6nvXy0aFqY2wA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UUZg/wn8; 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="UUZg/wn8" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1E55AC19421; Mon, 13 Oct 2025 16:03:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760371438; bh=T61ohRMVKcvJNe8i5gn6zOUU4mTTUUvrMUaTCo42RLE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=UUZg/wn8fz+NyfwnSpmD1TlswIbkWGsu/DndpG2qvtWObwhzYJj7LFXMs2hv3Y4zh GPeiXhGo2k4lDVZ0yqkyFZu0UKEPC/2E4UqZJPwwvaATGdlc4jGX957eIhyFfIDiF1 +bn9+x75578/b2G5/yX9+UFlU26jyTx9aKOayWdcr6DFxkfCmg2hjpJWKFftAqUZdB bnqrF9V7hRFOikhLyOSClzT2t/lTpoKwAgrzXldTDlXHh4hy4NSGHMSh23mwipATBT 7CfAofe2YW0xWBQwYjGRwS6xmNPMxLvyxEeV1MPBVh5lgjrEVOVWaPmCLjNtyXAlL3 5EbBjq6u/Cy8w== 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 14975CCD192; Mon, 13 Oct 2025 16:03:58 +0000 (UTC) From: Sven Peter Date: Mon, 13 Oct 2025 16:03:28 +0000 Subject: [PATCH 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: <20251013-b4-aplpe-dwc3-v1-4-12a78000c014@kernel.org> References: <20251013-b4-aplpe-dwc3-v1-0-12a78000c014@kernel.org> In-Reply-To: <20251013-b4-aplpe-dwc3-v1-0-12a78000c014@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=9617; i=sven@kernel.org; h=from:subject:message-id; bh=T61ohRMVKcvJNe8i5gn6zOUU4mTTUUvrMUaTCo42RLE=; b=owGbwMvMwCHmIlirolUq95LxtFoSQ8ZbpZdxZaLazW5vZun8PX7uGG/YeubX9ofTzmqqhd+/J HCh6bt6RykLgxgHg6yYIsv2/famTx6+EVy66dJ7mDmsTCBDGLg4BWAirf8Y/hnln87coJIZPKlY n3+9z2dB4dAbx+wNDxUUX3yfX8a6fRsjw7/AKoeO+2+vKLCeLQz/v0+71u7qWl2O2xx95ppZYRw v2QE= 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. 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 ae140c356295c03df3982ff4fa95f8638296e52d..526c0453b99aad79d99a842797e= 52d9290456d76 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) { @@ -2299,9 +2303,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 7f326cff12458901904d4c32f62ed9357d0f6e3b..376e7aa74281c13bfb3a85dc033= 622bcff8d2acb 100644 --- a/drivers/usb/dwc3/glue.h +++ b/drivers/usb/dwc3/glue.h @@ -15,11 +15,14 @@ * @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 */ struct dwc3_probe_data { struct dwc3 *dwc; struct resource *res; bool ignore_clocks_and_resets; + bool skip_core_init_mode; }; =20 /** @@ -60,4 +63,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:47 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 82A5330DD0D; Mon, 13 Oct 2025 16:03:58 +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=1760371438; cv=none; b=DdtL0vKu7nx5V95YF+/GqMrxRgACdipgpEIzjRHOvlsBYpeXkJBaiHhJCubhfW9Dah2OV0U6jy/B4Z5K8h9qoVXNij/JcwJGRvh+6R0VS3F8XfyY8JZQQ2WgslfWUjn0vfGB2a1qftQjtSYCT+GXPg2uppSCp+vav8jf1Eg9q6c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760371438; c=relaxed/simple; bh=RIBWEE3JkR/GSj0no1dERpptc6SWzMFAeXAp9B63Eq8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=L98M/A8g1bLHXcAyqi71Zk3NPB1f9/LVzvCgDe0BKQnfyoOgj3FFFxYcwImiyqJWWO9XRQG3jWPnR+jiz5NCmltNeU8DTC7kd6RrcZ6PfNTJasAOKm+HwE2wHAkLfVKThv5RN8EOwu7lUFolYpDCV41MXdvRtUYfytimcHT1n5w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Dzt5F+xC; 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="Dzt5F+xC" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2941EC2BC87; Mon, 13 Oct 2025 16:03:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1760371438; bh=RIBWEE3JkR/GSj0no1dERpptc6SWzMFAeXAp9B63Eq8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Dzt5F+xCdpYRRI8E3P6McFO4EBrOn3h1sv8aMkgMZM82dc8GxspRh5HnxeCUlzMYP MuT07VGxKIoCWe0S1WSl2N3AY8Zy3RKiWIlcb+hA78leTOqwiT5o/7r2lb5h/HxigD +AOgWsT7bo5i9cVmoUj9YHvrYp7DQePhcHfebibsiaByOx+yNYhqOJQxCxH7cqhJLs ukPI7eBD5pf1/JxX/pEeVYIAMPIRC8uA+miJcotUcjaKRvSKICtbj+qHvQh3MTF7Mp qmlZUJWHOEeI4quYKnhL5KO+Dhw6kPnDzqD4HX8i2M8c6vYw6O5iOuI59L/F7Vlyk8 FT163rDdMRjxw== 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 21566CCD190; Mon, 13 Oct 2025 16:03:58 +0000 (UTC) From: Sven Peter Date: Mon, 13 Oct 2025 16:03:29 +0000 Subject: [PATCH 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: <20251013-b4-aplpe-dwc3-v1-5-12a78000c014@kernel.org> References: <20251013-b4-aplpe-dwc3-v1-0-12a78000c014@kernel.org> In-Reply-To: <20251013-b4-aplpe-dwc3-v1-0-12a78000c014@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=20457; i=sven@kernel.org; h=from:subject:message-id; bh=RIBWEE3JkR/GSj0no1dERpptc6SWzMFAeXAp9B63Eq8=; b=owGbwMvMwCHmIlirolUq95LxtFoSQ8Zbpdef50/dqL+L9aQ/8/e3Jp/qy7fs1Mh88LckaNP0F 7XLhA7M7ChlYRDjYJAVU2TZvt/e9MnDN4JLN116DzOHlQlkCAMXpwBM5Ptrhn8WjxkazLh3r6ny 3CNuzWe8aaE8960PIYU8wdUSNtJxspMZGRp+dt6d0CuXsCG2Xfk579cTFbc7lbnXm0RdqDB9zbf /NB8A 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 Signed-off-by: Sven Peter --- MAINTAINERS | 1 + drivers/usb/dwc3/Kconfig | 11 + drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/dwc3-apple.c | 488 ++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 501 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..e9dd6b22f485daed01618e64d93= a40487fb20e3c --- /dev/null +++ b/drivers/usb/dwc3/dwc3-apple.c @@ -0,0 +1,488 @@ +// 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; + + 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