diff --git a/arch/arm64/boot/dts/apple/t6021-display2.dtsi b/arch/arm64/boot/dts/apple/t6021-display2.dtsi index 5bd77f4c788549..33ff2edd0ba19c 100644 --- a/arch/arm64/boot/dts/apple/t6021-display2.dtsi +++ b/arch/arm64/boot/dts/apple/t6021-display2.dtsi @@ -15,6 +15,11 @@ * Copyright The Asahi Linux Contributors */ +/* The node the DCPs live under: /soc on t6021, die 0 (&die0) on t6022. */ +#ifndef DISPLAY2_SOC +#define DISPLAY2_SOC &{/soc} +#endif + / { aliases { dcpext2 = &dcpext2; @@ -36,7 +41,7 @@ }; }; -&{/soc} { +DISPLAY2_SOC { dispext2_dart: iommu@48d304000 { compatible = "apple,t6020-dart", "apple,t8110-dart"; diff --git a/arch/arm64/boot/dts/apple/t6022-j475d.dts b/arch/arm64/boot/dts/apple/t6022-j475d.dts index 6c09afcffc9a69..139e3b3afaa22e 100644 --- a/arch/arm64/boot/dts/apple/t6022-j475d.dts +++ b/arch/arm64/boot/dts/apple/t6022-j475d.dts @@ -45,6 +45,217 @@ power-domains = <&ps_dispext0_cpu0_die1>, <&ps_dptx_phy_ps_die1>; }; +/* + * HDMI scans out through dispext0 on die 1, and the rear USB-C ports through + * dcpext1/dispext1 on die 0 (see t602x-j474-j475.dtsi). + */ +&display { + iommus = <&dispext0_dart_die1 0 0x100 0x0 0x10 0x0>, + <&dispext0_dart 0 0x100 0x0 0x10 0x0>, + <&dispext1_dart 0 0x100 0x0 0x10 0x0>; +}; + +/* + * Thunderbolt DP tunnels on M2 need two pipelines per port with named DPIN + * crossbar controls, as on the 14/16-inch boards. HDMI uses die 1 here, so + * die-0 dcpext0 is free to be the second rear-port pipeline (crossbar state + * 0, dcpext1 state 2). + */ +/ { + aliases { + /* m1n1 fills apple,firmware-compat through the ADT-indexed alias */ + dcpext0 = &dcpext0; + }; +}; + +&dispext0_dart { + status = "okay"; +}; + +&dcpext0_dart { + status = "okay"; +}; + +&dcpext0_mbox { + status = "okay"; +}; + +&dpaudio1 { + status = "okay"; +}; + +&dcpext0 { + status = "okay"; + apple,connector-type = "USB-C"; + phys = <&atcphy0 PHY_TYPE_DP>, <&atcphy1 PHY_TYPE_DP>, + <&atcphy2 PHY_TYPE_DP>, <&atcphy3 PHY_TYPE_DP>; + phy-names = "typec0", "typec1", "typec2", "typec3"; + mux-controls = <&atcphy0_xbar 0>, + <&atcphy1_xbar 0>, + <&atcphy2_xbar 0>, + <&atcphy3_xbar 0>, + <&atcphy0_xbar 1>, + <&atcphy1_xbar 1>, + <&atcphy2_xbar 1>, + <&atcphy3_xbar 1>, + <&atcphy0_xbar 2>, + <&atcphy1_xbar 2>, + <&atcphy2_xbar 2>, + <&atcphy3_xbar 2>; + mux-control-names = "typec0", "typec1", "typec2", "typec3", + "typec0-dpin0", "typec1-dpin0", "typec2-dpin0", "typec3-dpin0", + "typec0-dpin1", "typec1-dpin1", "typec2-dpin1", "typec3-dpin1"; + apple,typec-mux-indices = <0 0 0 0>; + apple,typec-dptx-phys = <0 1 2 3>; + + typec-routes { + #address-cells = <1>; + #size-cells = <0>; + + route@0 { + reg = <0>; + mode-switch; + + port { + dcpext0_typec0: endpoint { + remote-endpoint = <&typec0_dcpext0>; + }; + }; + }; + + route@1 { + reg = <1>; + mode-switch; + + port { + dcpext0_typec1: endpoint { + remote-endpoint = <&typec1_dcpext0>; + }; + }; + }; + + route@2 { + reg = <2>; + mode-switch; + + port { + dcpext0_typec2: endpoint { + remote-endpoint = <&typec2_dcpext0>; + }; + }; + }; + + route@3 { + reg = <3>; + mode-switch; + + port { + dcpext0_typec3: endpoint { + remote-endpoint = <&typec3_dcpext0>; + }; + }; + }; + }; +}; + +&dcpext1 { + mux-controls = <&atcphy0_xbar 0>, + <&atcphy1_xbar 0>, + <&atcphy2_xbar 0>, + <&atcphy3_xbar 0>, + <&atcphy0_xbar 1>, + <&atcphy1_xbar 1>, + <&atcphy2_xbar 1>, + <&atcphy3_xbar 1>, + <&atcphy0_xbar 2>, + <&atcphy1_xbar 2>, + <&atcphy2_xbar 2>, + <&atcphy3_xbar 2>; + mux-control-names = "typec0", "typec1", "typec2", "typec3", + "typec0-dpin0", "typec1-dpin0", "typec2-dpin0", "typec3-dpin0", + "typec0-dpin1", "typec1-dpin1", "typec2-dpin1", "typec3-dpin1"; +}; + +&typec0 { + ports { + port@3 { + #address-cells = <1>; + #size-cells = <0>; + /delete-node/ endpoint; + + typec0_dcp: endpoint@0 { + reg = <0>; + remote-endpoint = <&dcpext1_typec0>; + }; + + typec0_dcpext0: endpoint@1 { + reg = <1>; + remote-endpoint = <&dcpext0_typec0>; + }; + }; + }; +}; + +&typec1 { + ports { + port@3 { + #address-cells = <1>; + #size-cells = <0>; + /delete-node/ endpoint; + + typec1_dcp: endpoint@0 { + reg = <0>; + remote-endpoint = <&dcpext1_typec1>; + }; + + typec1_dcpext0: endpoint@1 { + reg = <1>; + remote-endpoint = <&dcpext0_typec1>; + }; + }; + }; +}; + +&typec2 { + ports { + port@3 { + #address-cells = <1>; + #size-cells = <0>; + /delete-node/ endpoint; + + typec2_dcp: endpoint@0 { + reg = <0>; + remote-endpoint = <&dcpext1_typec2>; + }; + + typec2_dcpext0: endpoint@1 { + reg = <1>; + remote-endpoint = <&dcpext0_typec2>; + }; + }; + }; +}; + +&typec3 { + ports { + port@3 { + #address-cells = <1>; + #size-cells = <0>; + /delete-node/ endpoint; + + typec3_dcp: endpoint@0 { + reg = <0>; + remote-endpoint = <&dcpext1_typec3>; + }; + + typec3_dcpext0: endpoint@1 { + reg = <1>; + remote-endpoint = <&dcpext0_typec3>; + }; + }; + }; +}; + &dcpext0_die1 { // J180 misses "function-dp2hdmi_pwr_en" dp2hdmi-pwren-gpios = <&smc_gpio 25 GPIO_ACTIVE_HIGH>; @@ -96,6 +307,86 @@ /delete-node/ &ps_atc3_usb_aon_die1; /delete-node/ &ps_atc3_usb_die1; +/* + * Die 0 is the M2 Max die, with four external DCPs. dcpext0/1 above carry the + * Thunderbolt DPIN pairs; add dcpext2/3 (crossbar states 4 and 6) as further + * DP-alt candidates on the four rear ports, as on the 14/16-inch M2 Max. + */ +#define DISPLAY2_SOC &die0 +#include "t6021-display2.dtsi" +#undef DISPLAY2_SOC + +&dcpext2 { + phys = <&atcphy0 PHY_TYPE_DP>, <&atcphy1 PHY_TYPE_DP>, + <&atcphy2 PHY_TYPE_DP>, <&atcphy3 PHY_TYPE_DP>; + phy-names = "typec0", "typec1", "typec2", "typec3"; + mux-controls = <&atcphy0_xbar 0>, <&atcphy1_xbar 0>, + <&atcphy2_xbar 0>, <&atcphy3_xbar 0>; + mux-control-names = "typec0", "typec1", "typec2", "typec3"; + apple,typec-mux-indices = <4 4 4 4>; + apple,typec-dptx-phys = <0 1 2 3>; + + typec-routes { + route@3 { + reg = <3>; + mode-switch; + + port { + dcpext2_typec3: endpoint { + remote-endpoint = <&typec3_dcpext2>; + }; + }; + }; + }; +}; + +&dcpext3 { + phys = <&atcphy0 PHY_TYPE_DP>, <&atcphy1 PHY_TYPE_DP>, + <&atcphy2 PHY_TYPE_DP>, <&atcphy3 PHY_TYPE_DP>; + phy-names = "typec0", "typec1", "typec2", "typec3"; + mux-controls = <&atcphy0_xbar 0>, <&atcphy1_xbar 0>, + <&atcphy2_xbar 0>, <&atcphy3_xbar 0>; + mux-control-names = "typec0", "typec1", "typec2", "typec3"; + apple,typec-mux-indices = <6 6 6 6>; + apple,typec-dptx-phys = <0 1 2 3>; + + typec-routes { + route@3 { + reg = <3>; + mode-switch; + + port { + dcpext3_typec3: endpoint { + remote-endpoint = <&typec3_dcpext3>; + }; + }; + }; + }; +}; + +&typec3 { + ports { + port@3 { + typec3_dcpext2: endpoint@2 { + reg = <2>; + remote-endpoint = <&dcpext2_typec3>; + }; + typec3_dcpext3: endpoint@3 { + reg = <3>; + remote-endpoint = <&dcpext3_typec3>; + }; + }; + }; +}; + +/* t6021-display2.dtsi sets the laptop list; HDMI here is on die 1. */ +&display { + iommus = <&dispext0_dart_die1 0 0x100 0x0 0x10 0x0>, + <&dispext0_dart 0 0x100 0x0 0x10 0x0>, + <&dispext1_dart 0 0x100 0x0 0x10 0x0>, + <&dispext2_dart 0>, <&dispext3_dart 0>; +}; + &wifi0 { compatible = "pci14e4,4434"; brcm,board-type = "apple,canary"; diff --git a/arch/arm64/boot/dts/apple/t602x-j474-j475.dtsi b/arch/arm64/boot/dts/apple/t602x-j474-j475.dtsi index 822760c80ae598..22827a0ffab38f 100644 --- a/arch/arm64/boot/dts/apple/t602x-j474-j475.dtsi +++ b/arch/arm64/boot/dts/apple/t602x-j474-j475.dtsi @@ -24,7 +24,6 @@ #ifdef APPLE_T602X_NON_ULTRA / { aliases { - dcpext1 = &dcpext1; /* Same Thunderbolt aliases as the 14/16-inch boards. This mini * brings up a fourth controller. */ @@ -67,6 +66,19 @@ iommus = <&dispext0_dart 0 0x100 0x0 0x10 0x0>, <&dispext1_dart 0 0x100 0x0 0x10 0x0>; }; +#endif + +/* + * dcpext1 on die 0 drives the rear USB-C ports through the display crossbar + * on all of these boards, M2 Ultra included: macOS routes a DP alt mode + * display on the J475d's rear ports to DCPEXT1 as well. Only the USB4 and + * PCIe-C wiring below stays non-Ultra. + */ +/ { + aliases { + dcpext1 = &dcpext1; + }; +}; &dispext1_dart { status = "okay"; @@ -229,6 +241,7 @@ apple,always-on; }; +#ifdef APPLE_T602X_NON_ULTRA &usb4_0_acio { apple,pcie-tunnel = <&usb4_0_pcie_tunnel>; }; diff --git a/drivers/phy/apple/atc-tunnel-test.c b/drivers/phy/apple/atc-tunnel-test.c index 15f10557073328..4e1a33474ec5f3 100644 --- a/drivers/phy/apple/atc-tunnel-test.c +++ b/drivers/phy/apple/atc-tunnel-test.c @@ -12,7 +12,7 @@ static void atc_tunnel_soc_qualification(struct kunit *test) } cases[] = { { "apple,t6020", true }, { "apple,t6021", true }, - { "apple,t6022", false }, + { "apple,t6022", true }, { "apple,t8103", false }, { "apple,t6000", false }, { "apple,t6001", false }, @@ -47,7 +47,7 @@ static void atc_tunnel_core_qualification(struct kunit *test) { "apple,t6020-atcphy", 0xb03000000ULL, 0x7048, true }, { "apple,t6020-atcphy", 0xf03000000ULL, 0x7048, true }, { "apple,t6020-atcphy", 0x703000000ULL, 0x7047, false }, - { "apple,t6020-atcphy", 0x1303000000ULL, 0x4c000, false }, + { "apple,t6020-atcphy", 0x1303000000ULL, 0x4c000, true }, { "apple,t6020-atcphy", 0x2703000000ULL, 0x4c000, false }, { "apple,t8103-atcphy", 0x703000000ULL, 0x4c000, false }, }; diff --git a/drivers/phy/apple/atc-tunnel.h b/drivers/phy/apple/atc-tunnel.h index e06d10b4a3e3d4..2bc4dae3425a85 100644 --- a/drivers/phy/apple/atc-tunnel.h +++ b/drivers/phy/apple/atc-tunnel.h @@ -9,13 +9,15 @@ static inline bool apple_atc_t602x_qualified(const struct device_node *root) { return of_device_is_compatible(root, "apple,t6020") || - of_device_is_compatible(root, "apple,t6021"); + of_device_is_compatible(root, "apple,t6021") || + of_device_is_compatible(root, "apple,t6022"); } static inline bool apple_atc_t602x_core_valid(const struct device_node *np, u64 base, u64 size) { return of_device_is_compatible(np, "apple,t6020-atcphy") && - (base == 0x703000000ULL || base == 0xb03000000ULL || base == 0xf03000000ULL) && + (base == 0x703000000ULL || base == 0xb03000000ULL || base == 0xf03000000ULL || + base == 0x1303000000ULL) && size >= 0x7048; } diff --git a/drivers/thunderbolt/apple-dpin-test.c b/drivers/thunderbolt/apple-dpin-test.c index c22da168bd8bc9..2417768ebd0ea9 100644 --- a/drivers/thunderbolt/apple-dpin-test.c +++ b/drivers/thunderbolt/apple-dpin-test.c @@ -355,7 +355,8 @@ static void apple_dpin_qualification_profiles(struct kunit *test) { "apple,t6021", &apple_dpin_m2, true, &apple_dpin_m2 }, { "apple,t6020", &apple_dpin_m2, false, &apple_dpin_disabled }, { "apple,t6021", &apple_dpin_m2, false, &apple_dpin_disabled }, - { "apple,t6022", &apple_dpin_m2, true, &apple_dpin_disabled }, + { "apple,t6022", &apple_dpin_m2, true, &apple_dpin_m2 }, + { "apple,t6022", &apple_dpin_m2, false, &apple_dpin_disabled }, { "apple,t6030", &apple_dpin_m3, true, &apple_dpin_m3 }, { "apple,t6031", &apple_dpin_m3, true, &apple_dpin_disabled }, { "apple,unknown", &apple_dpin_m1, true, &apple_dpin_disabled }, diff --git a/drivers/thunderbolt/apple.c b/drivers/thunderbolt/apple.c index c6625c5cbb5d3f..8e7df5aa30f874 100644 --- a/drivers/thunderbolt/apple.c +++ b/drivers/thunderbolt/apple.c @@ -375,6 +375,8 @@ static const struct of_device_id apple_dpin_qualified_soc[] = { { .compatible = "apple,t6001" }, { .compatible = "apple,t6020" }, { .compatible = "apple,t6021" }, + /* The M2 Ultra's die-0 ACIO, ATC and display crossbar are t6021's. */ + { .compatible = "apple,t6022" }, { .compatible = "apple,t6030" }, {}, };