From 3162d9144759835e97c473916fe6fae671198335 Mon Sep 17 00:00:00 2001 From: Philip Wallage Date: Sat, 7 Nov 2026 19:41:41 +0100 Subject: [PATCH 1/7] drm/apple: drive the J516M internal display by default The 16" binned M3 Max MacBook Pro (J516M) carries the J514M's T6034 die: its ADT names the same DCP image (F493F03E-...), and m1n1 gives it the same T6034 handoff. Its chassis and panel are the J516C's. Give it a v14 board record with the J514M's DCP, image and handoff, and the J516 panel: 3456x2234 with 74 notch rows above the 3456x2160 boot framebuffer, ProMotion allowed and bring-up logging on. As on the J514M, the panel controls stay off. The display gate starts native display by default on the J514M and J516M, and apple_t6034_display.enable=0 still keeps the boot framebuffer. The T6034 GPU link follows the display on both boards. Tests: a KUnit case for the J516M record, the T6034 display host test admits the J516M and catches dropping it from the gate or the record, and the display-order test links the J516M GPU while an unknown T6034 board (apple,j999) stays refused. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Philip Wallage --- drivers/gpu/drm/apple/apple_drv.c | 3 ++- drivers/gpu/drm/apple/iomfb_v14_7.c | 21 +++++++++++++++++++++ drivers/gpu/drm/apple/v14-board-test.c | 26 +++++++++++++++++++++++++- drivers/soc/apple/t6030-display-gate.c | 5 +++-- tools/asahi/g15-display-order-tests.py | 8 +++++--- tools/asahi/t6034-display-tests.py | 4 +++- 6 files changed, 59 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/apple/apple_drv.c b/drivers/gpu/drm/apple/apple_drv.c index b6a5be040ef9c8..9c9740a53a5048 100644 --- a/drivers/gpu/drm/apple/apple_drv.c +++ b/drivers/gpu/drm/apple/apple_drv.c @@ -139,7 +139,8 @@ EXPORT_SYMBOL_GPL(apple_drm_t6031_link_device); int apple_drm_t6034_link_device(struct device *consumer) { - if (!of_machine_is_compatible("apple,j514m")) + if (!of_machine_is_compatible("apple,j514m") && + !of_machine_is_compatible("apple,j516m")) return -ENODEV; return apple_g15_link_device(consumer, "apple,t6034", "apple,agx-t6034", &apple_t6034_display); diff --git a/drivers/gpu/drm/apple/iomfb_v14_7.c b/drivers/gpu/drm/apple/iomfb_v14_7.c index 4f381ab769f315..8497de19e4ae25 100644 --- a/drivers/gpu/drm/apple/iomfb_v14_7.c +++ b/drivers/gpu/drm/apple/iomfb_v14_7.c @@ -203,6 +203,26 @@ static const struct dcp_v14_board dcp_v14_board_j514m = { .log_bringup = true, }; +/* + * J516M (MacBook Pro 16", binned M3 Max): the T6034 DCP, image and handoff + * of the J514M in the J516C chassis, so the J516 panel: 3456x2234 with 74 + * notch rows above the 3456x2160 boot framebuffer. Panel controls stay off + * as on the J514M. + */ +static const struct dcp_v14_board dcp_v14_board_j516m = { + .name = "J516M", + .debugfs = "dcp-j516m", + .dcp_compatible = "apple,t6034-dcp", + .machine = "apple,j516m", + .soc = "apple,t6034", + .firmware_uuid = DCP_V14_J516C_FIRMWARE_UUID, + .handoff = "apple,t6034-handoff", + .panel_width = 3456, + .panel_height = 2234, + .promotion = true, + .log_bringup = true, +}; + static const struct dcp_v14_board *const dcp_v14_boards[] = { &dcp_v14_board_t6030, &dcp_v14_board_j613, @@ -210,6 +230,7 @@ static const struct dcp_v14_board *const dcp_v14_boards[] = { &dcp_v14_board_j516c, &dcp_v14_board_j514c, &dcp_v14_board_j514m, + &dcp_v14_board_j516m, }; struct dcp_v14_property { diff --git a/drivers/gpu/drm/apple/v14-board-test.c b/drivers/gpu/drm/apple/v14-board-test.c index 23453f1368ee14..1b2cbd0cd8d879 100644 --- a/drivers/gpu/drm/apple/v14-board-test.c +++ b/drivers/gpu/drm/apple/v14-board-test.c @@ -125,10 +125,33 @@ static void v14_board_j514m(struct kunit *test) KUNIT_EXPECT_FALSE(test, dcp_v14_board_admits(b, T6030_DCP_IMAGE)); KUNIT_EXPECT_FALSE(test, b->panel_nits); KUNIT_EXPECT_NULL(test, board_for("apple,t6034-dcp", j514m_wrong_soc, &known)); - KUNIT_EXPECT_NULL(test, board_for("apple,t6034-dcp", j516m, &known)); + /* The J516M has a record of its own. */ + KUNIT_EXPECT_PTR_NE(test, b, board_for("apple,t6034-dcp", j516m, &known)); KUNIT_EXPECT_NULL(test, board_for("apple,t6031-dcp", j514m, &known)); } +/* The J516M: the J514M's T6034 DCP and image, with the J516 panel. */ +static void v14_board_j516m(struct kunit *test) +{ + const struct dcp_v14_board *b; + bool known; + + b = board_for("apple,t6034-dcp", j516m, &known); + KUNIT_ASSERT_NOT_NULL(test, b); + KUNIT_EXPECT_TRUE(test, known); + KUNIT_EXPECT_STREQ(test, b->name, "J516M"); + KUNIT_EXPECT_STREQ(test, b->debugfs, "dcp-j516m"); + KUNIT_EXPECT_STREQ(test, b->machine, "apple,j516m"); + KUNIT_EXPECT_STREQ(test, b->soc, "apple,t6034"); + KUNIT_EXPECT_STREQ(test, b->handoff, "apple,t6034-handoff"); + KUNIT_EXPECT_EQ(test, b->panel_width, 3456); + KUNIT_EXPECT_EQ(test, b->panel_height, 2234); + KUNIT_EXPECT_TRUE(test, dcp_v14_board_admits(b, J516C_DCP_IMAGE)); + KUNIT_EXPECT_FALSE(test, dcp_v14_board_admits(b, T6030_DCP_IMAGE)); + KUNIT_EXPECT_FALSE(test, b->panel_nits); + KUNIT_EXPECT_NULL(test, board_for("apple,t6031-dcp", j516m, &known)); +} + /* A T6031 DCP on a T6034 has no record: refused. */ static void v14_board_t6031_other_boards(struct kunit *test) { @@ -277,6 +300,7 @@ static struct kunit_case v14_board_cases[] = { KUNIT_CASE(v14_board_j516c), KUNIT_CASE(v14_board_j514c), KUNIT_CASE(v14_board_j514m), + KUNIT_CASE(v14_board_j516m), KUNIT_CASE(v14_board_t6031_other_boards), KUNIT_CASE(v14_board_j516c_image), KUNIT_CASE(v14_board_unchanged), diff --git a/drivers/soc/apple/t6030-display-gate.c b/drivers/soc/apple/t6030-display-gate.c index 016abbcf6cf96f..0de143fd52db27 100644 --- a/drivers/soc/apple/t6030-display-gate.c +++ b/drivers/soc/apple/t6030-display-gate.c @@ -190,7 +190,8 @@ static bool gate_t6034_requested __initdata; static bool __init gate_t6034_default_board(void) { return of_machine_is_compatible("apple,t6034") && - of_machine_is_compatible("apple,j514m"); + (of_machine_is_compatible("apple,j514m") || + of_machine_is_compatible("apple,j516m")); } static bool __init gate_t6034_wanted(int sw) @@ -2060,7 +2061,7 @@ static void __init gate_run(void) } gate_t6034_requested = gate_t6034_wanted(gate_t6034_switch); if (gate_t6034_switch < 0) - gate_info("native display on by default on J514M; apple_t6034_display.enable=0 keeps the boot framebuffer\n"); + gate_info("native display on by default on J514M/J516M; apple_t6034_display.enable=0 keeps the boot framebuffer\n"); } if (!*gate_soc->requested) { diff --git a/tools/asahi/g15-display-order-tests.py b/tools/asahi/g15-display-order-tests.py index 6ff26493965c60..a1f7f8ea371381 100644 --- a/tools/asahi/g15-display-order-tests.py +++ b/tools/asahi/g15-display-order-tests.py @@ -221,9 +221,11 @@ def c_source(root): CHECK(publish(&d34) == 0 && d34.refs == 1); CHECK(prepare(&g34) == 0 && links_made == 1 && last_link.supplier == &d34); machine("apple,t6034", "apple,j516m"); - CHECK(prepare(&g34) == -ENODEV && links_made == 1); + CHECK(prepare(&g34) == 0 && links_made == 2 && last_link.supplier == &d34); + machine("apple,t6034", "apple,j999"); + CHECK(prepare(&g34) == -ENODEV && links_made == 2); machine("apple,t6031", "apple,j514m"); - CHECK(prepare(&g34) == -ENODEV && links_made == 1); + CHECK(prepare(&g34) == -ENODEV && links_made == 2); machine("apple,t6034", "apple,j514m"); withdraw(&d34); CHECK(!d34.refs && prepare(&g34) == -EPROBE_DEFER); @@ -243,7 +245,7 @@ def c_source(root): "t6031-reads-t6030-slot": ("&apple_t6031_display);", "&apple_t6030_display);"), "t6034-reads-t6031-slot": ("&apple_t6034_display);", "&apple_t6031_display);"), "t6034-published-as-t6031": ("return &apple_t6034_display;", "return &apple_t6031_display;"), - "t6034-no-board-check": ('if (!of_machine_is_compatible("apple,j514m"))', 'if (false)'), + "t6034-no-board-check": ('if (!of_machine_is_compatible("apple,j514m") &&\n\t !of_machine_is_compatible("apple,j516m"))', 'if (false)'), "t6031-published-as-t6030": ("return &apple_t6031_display;", "return &apple_t6030_display;"), "no-machine-check": ("!of_machine_is_compatible(machine) ||", ""), "withdraw-keeps-display": ("*slot = NULL;", ";"), diff --git a/tools/asahi/t6034-display-tests.py b/tools/asahi/t6034-display-tests.py index ddd1cf54cc4c39..f2b1f14205edac 100644 --- a/tools/asahi/t6034-display-tests.py +++ b/tools/asahi/t6034-display-tests.py @@ -41,7 +41,7 @@ def item(s, marker): const char *socs[]={"apple,t6034","apple,t6031","apple,t6030",NULL}; dcp="apple,t6034-dcp"; for(unsigned i=0;ifirmware_uuid);','return uuid != NULL;'), } From 468da4dfc3527732b1336b93a1ac306ee749e37f Mon Sep 17 00:00:00 2001 From: Philip Wallage Date: Sat, 7 Nov 2026 19:41:41 +0100 Subject: [PATCH 2/7] arm64: dts: apple: t6034-j516m: describe the internal display Include the T6034 DCP and give the J516M's DCP its panel node. The panel is the J516C's (same 16" chassis): 346 x 223 mm, 216 mm below the notch, 500 nits. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Philip Wallage --- arch/arm64/boot/dts/apple/t6034-j516m.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/apple/t6034-j516m.dts b/arch/arm64/boot/dts/apple/t6034-j516m.dts index 22ad5251eaecef..a8d651917c313e 100644 --- a/arch/arm64/boot/dts/apple/t6034-j516m.dts +++ b/arch/arm64/boot/dts/apple/t6034-j516m.dts @@ -10,6 +10,7 @@ /dts-v1/; #include "t6034.dtsi" +#include "t6034-dcp.dtsi" #include "t603x-j514-j516.dtsi" / { @@ -29,6 +30,17 @@ brcm,board-type = "apple,jura"; }; +/* J516 panel dimensions, as on the J516C (same 16-inch chassis and panel). */ +&dcp { + panel { + compatible = "apple,panel-j516", "apple,panel-mini-led", "apple,panel"; + width-mm = <346>; + height-mm = <223>; + adj-height-mm = <216>; + apple,max-brightness = <500>; + }; +}; + &aop_audio { apple,chassis-name = "J516"; apple,machine-kind = "MacBook Pro"; From 09ffb61538a9a6b65ec2a37c2e4c6b7c92c29776 Mon Sep 17 00:00:00 2001 From: Philip Wallage Date: Sat, 7 Nov 2026 19:41:41 +0100 Subject: [PATCH 3/7] drm/asahi: admit the J516M on the measured T6034 GPU firmware The J516M loads the J514M's 14.7 G15C image: on a J516M the loaded firmware measured TEXT 0x64000, DATA 0x140000, GKTS 0x5cf28 and the J514M's TEXT sha256 (4ca24b65...04b7), and the GPU reports the same B1 identity (version 0x7041100, counts 0x21040a) with 30 enabled cores in four ten-slot clusters ([8, 8, 7, 7]). Admit apple,j516m with apple,t6034 alongside the J514M, and pin the image to the J516M on a row of its own, so neither board's row admits the other. The PMP, display, record and hardware identity checks are unchanged. The profile test checks both rows, that each board pins only its own, and that a changed digest is refused on the J516M too. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Philip Wallage --- drivers/gpu/drm/asahi/g15/boot.rs | 12 +++++++----- drivers/gpu/drm/asahi/g15/hw/t6034.rs | 13 +++++++++++++ tools/asahi/g15-t6034-profile-tests.py | 15 +++++++++++---- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/asahi/g15/boot.rs b/drivers/gpu/drm/asahi/g15/boot.rs index b0ea7bfc44aedf..2b4c22f9af0d0b 100644 --- a/drivers/gpu/drm/asahi/g15/boot.rs +++ b/drivers/gpu/drm/asahi/g15/boot.rs @@ -476,9 +476,11 @@ pub(crate) fn admit( && cfg.platform == hw::Platform::DeviceTree && glue::machine(kernel::c_str!("apple,j514c")) && glue::machine(kernel::c_str!("apple,t6031")); - let j514m_board = cfg.chip_id == 0x6034 + // T6034 boards: the J514M and the 16-inch J516M, which carries the same die. + let t6034_board = cfg.chip_id == 0x6034 && cfg.platform == hw::Platform::DeviceTree - && glue::machine(kernel::c_str!("apple,j514m")) + && (glue::machine(kernel::c_str!("apple,j514m")) + || glue::machine(kernel::c_str!("apple,j516m"))) && glue::machine(kernel::c_str!("apple,t6034")); if pmp { if !glue::board() { @@ -494,8 +496,8 @@ pub(crate) fn admit( } return Err(err); } - } else if (cfg.chip_id == 0x6034 && !j514m_board) - || (!glue::machine(cfg.machine) && !j514c_board) + } else if (cfg.chip_id == 0x6034 && !t6034_board) + || (!glue::machine(cfg.machine) && !j514c_board && !t6034_board) { dev_err!(dev, "G15: not a {} machine\n", cfg.name); return Err(ENODEV); @@ -511,7 +513,7 @@ pub(crate) fn admit( return Err(err); } } - if j514c_board || j514m_board { + if j514c_board || t6034_board { if let hw::Board::DeviceTree(reference) = cfg.board { dev_warn!( dev, diff --git a/drivers/gpu/drm/asahi/g15/hw/t6034.rs b/drivers/gpu/drm/asahi/g15/hw/t6034.rs index 1c0ec130cc177e..a26bf06ea88e02 100644 --- a/drivers/gpu/drm/asahi/g15/hw/t6034.rs +++ b/drivers/gpu/drm/asahi/g15/hw/t6034.rs @@ -85,6 +85,19 @@ pub(crate) const CONFIG: Config = Config { 0xe4, 0x1e, 0x5d, 0xaf, 0x86, 0x32, 0x51, 0x50, 0x77, 0xb5, 0x37, 0xca, 0x19, 0xe6, 0xd0, 0xdc, 0x77, 0x04, 0xb7, ], + }, FirmwareBuild { + // Measured on a J516M: the J514M's 14.7 image (RTKit 2419.140.12), + // byte for byte. Pinned to the J516M on its own row. + name: "J516M RTKit 2419.140.12", + machine: Some(kernel::c_str!("apple,j516m")), + text_size: 0x64000, + data_size: 0x140000, + marker: 0x5cf28, + text_sha256: [ + 0x4c, 0xa2, 0x4b, 0x65, 0x8f, 0x8e, 0xbe, 0x7c, 0x27, 0x37, 0x5f, 0xdf, 0x38, + 0xe4, 0x1e, 0x5d, 0xaf, 0x86, 0x32, 0x51, 0x50, 0x77, 0xb5, 0x37, 0xca, 0x19, + 0xe6, 0xd0, 0xdc, 0x77, 0x04, 0xb7, + ], }], machine: kernel::c_str!("apple,j514m"), platform: super::Platform::DeviceTree, diff --git a/tools/asahi/g15-t6034-profile-tests.py b/tools/asahi/g15-t6034-profile-tests.py index 4f73b5172aee76..16fde7183569a4 100644 --- a/tools/asahi/g15-t6034-profile-tests.py +++ b/tools/asahi/g15-t6034-profile-tests.py @@ -58,13 +58,17 @@ def item(text, marker): assert_eq!(c.gpu_revision,0x11); assert_eq!((c.hw_ids[0].version,c.hw_ids[0].counts),(0x07041100,0x0021040a)); // An empty table is the first diagnostic build. A completed profile may - // contain only the measured row for this exact board. - assert_eq!(c.firmware.len(),1); + // contain only the measured rows, each pinned to its exact board: the J514M, + // and the J516M, measured with the same image. + assert_eq!(c.firmware.len(),2); if !c.firmware.is_empty() { use lookup::{Measured,Verdict}; - assert_eq!(c.firmware.len(),1); let b=&c.firmware[0]; assert_eq!(b.machine.map(|m|m.to_bytes()),Some(b"apple,j514m".as_slice())); + let j516m=&c.firmware[1]; + assert_eq!(j516m.machine.map(|m|m.to_bytes()),Some(b"apple,j516m".as_slice())); + assert_eq!((j516m.text_size,j516m.data_size,j516m.marker,j516m.text_sha256), + (b.text_size,b.data_size,b.marker,b.text_sha256)); let exact=Measured {text_size:b.text_size,data_size:b.data_size,marker:b.marker,sha256:b.text_sha256}; let verdict=|measured:&Measured,board:&[u8]| { let qualified=c.firmware.iter().map(|b| { @@ -74,10 +78,13 @@ def item(text, marker): lookup::verdict(measured,qualified,0) }; assert_eq!(verdict(&exact,b"apple,j514m"),Verdict::Pinned(0)); - for board in [b"apple,j514c".as_slice(),b"apple,j516c",b"apple,j516m",b"apple,j514s",b"apple,j999"] { + assert_eq!(verdict(&exact,b"apple,j516m"),Verdict::Pinned(1)); + for board in [b"apple,j514c".as_slice(),b"apple,j516c",b"apple,j514s",b"apple,j999"] { assert_eq!(verdict(&exact,board),Verdict::Refused); } let mut changed=exact;changed.sha256[31]^=1; + assert_eq!(verdict(&changed,b"apple,j516m"),Verdict::Refused); + let mut changed=exact;changed.sha256[31]^=1; assert_eq!(verdict(&changed,b"apple,j514m"),Verdict::Refused); let mut changed=exact;changed.text_size+=0x4000; assert_eq!(verdict(&changed,b"apple,j514m"),Verdict::Refused); From 15b9cb8e170d1ab9cea00b36dad1f4deccae2944 Mon Sep 17 00:00:00 2001 From: Philip Wallage Date: Sat, 7 Nov 2026 19:43:59 +0100 Subject: [PATCH 4/7] apple: run Thunderbolt DP tunnels on T6034 On the T6034 (J516M) the Thunderbolt link to a display comes up and its DP tunnels are created, then torn down again: nothing drives the DP IN adapters. The T6034 has the T6030's T8122-generation ATC PHYs, so it takes the T6030 (M3) DP IN flow. Add apple_dp_tunnel_m3_soc(), true on T6030 and T6034, and use it where the display fabric, the display crossbar and the ATC PHY checked apple,t6030 alone. Put apple,t6034 on the Thunderbolt DP qualified list and give the T6031-compatible ACIO (shared by T6031 and T6034) the M3 DP IN policy. T6031 is not on the qualified list, so its policy stays disabled and the J514C/J516C are unchanged; the T6030 path is the same as before. The T6030 crossbar registers and tunnel clock sequence are assumed to hold on T6034; they do for dcpext0 on the right-side port of a J516M. The tunnel-route and T6030 clock host tests extract the production functions that now call apple_dp_tunnel_m3_soc(), so they extract it too, and the tunnel-route fixture answers apple,t6034 (no scenario there models it). Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Philip Wallage --- drivers/gpu/drm/apple/dcp-fabric.c | 12 ++++++------ drivers/mux/apple-display-crossbar.c | 2 +- drivers/phy/apple/atc.c | 5 ++--- drivers/thunderbolt/apple.c | 15 +++++++++++++++ include/linux/soc/apple/dp-tunnel.h | 11 +++++++++++ tools/asahi/t6030-clock-tests.py | 2 +- tools/asahi/tunnel-route-tests.py | 4 ++-- tools/asahi/tunnel-route/fixture.c | 3 +++ 8 files changed, 41 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/apple/dcp-fabric.c b/drivers/gpu/drm/apple/dcp-fabric.c index 29321f8032a490..1963cbb0c9ccd9 100644 --- a/drivers/gpu/drm/apple/dcp-fabric.c +++ b/drivers/gpu/drm/apple/dcp-fabric.c @@ -211,7 +211,7 @@ bool dcp_typec_dual_stream(void) bool dcp_typec_ordered_dual_stream(void) { return dcp_fabric_ordered_dual_stream(dcp_typec_dual_stream(), - of_machine_is_compatible("apple,t6030")); + apple_dp_tunnel_m3_soc()); } /* @@ -257,7 +257,7 @@ static int dcp_route_clock_rate(struct apple_dcp_typec_route *route, { int ret; - if (of_machine_is_compatible("apple,t6030")) { + if (apple_dp_tunnel_m3_soc()) { typeof(apple_atc_dp_tunnel_rate_source) *fn; if (dcp_fabric_t6030_pclk(route->mux_index, dpin) < 0) @@ -902,7 +902,7 @@ static void dcp_fabric_snapshot_port(struct apple_dcp_typec_port *port, route->core.tunnel = route->tunnel; route->core.dpin = route->tunnel_dpin; route->core.tunnel_clock_blocked = dcp_fabric_tunnel_clock_blocked( - of_machine_is_compatible("apple,t6030"), route->mux_index); + apple_dp_tunnel_m3_soc(), route->mux_index); *tail = &route->core; tail = &route->core.next; } @@ -1763,7 +1763,7 @@ int dcp_direct_crossbar_link(struct apple_dcp *dcp, bool up) struct mux_control *xbar = NULL; int ret; - if (!of_machine_is_compatible("apple,t6030")) + if (!apple_dp_tunnel_m3_soc()) return 0; guard(mutex)(&dcp->tb_lock); route = dcp->active_typec_route; @@ -1805,7 +1805,7 @@ int dcp_tunnel_set_rate(struct apple_dcp *dcp, struct phy *phy, u32 unit, return -ENODEV; if (!dcp_fabric_callback_valid(route->tunnel_generation, dcp->tb_generation)) return -ESTALE; - if (of_machine_is_compatible("apple,t6030") && + if (apple_dp_tunnel_m3_soc() && (unit || dcp->dptx_dfp_port != 1 + route->tunnel_dpin || apple_dp_tunnel_t6030_pclk(route->mux_index, route->tunnel_dpin) < 0)) @@ -1903,7 +1903,7 @@ static struct mux_control * dcp_typec_tunnel_ctl(struct apple_dcp_typec_route *route, unsigned int dpin) { if (dpin > 1 || - (dcp_fabric_tunnel_clock_blocked(of_machine_is_compatible("apple,t6030"), + (dcp_fabric_tunnel_clock_blocked(apple_dp_tunnel_m3_soc(), route->mux_index) & BIT(dpin))) return NULL; if (route->dpin[dpin]) diff --git a/drivers/mux/apple-display-crossbar.c b/drivers/mux/apple-display-crossbar.c index a02b8d9fe8a304..a3c5f3eaee4986 100644 --- a/drivers/mux/apple-display-crossbar.c +++ b/drivers/mux/apple-display-crossbar.c @@ -1003,7 +1003,7 @@ static int apple_dpxbar_probe(struct platform_device *pdev) spin_lock_init(&dpxbar->lock); dpxbar->dev = dev; - dpxbar->t6030_dpin = of_machine_is_compatible("apple,t6030"); + dpxbar->t6030_dpin = apple_dp_tunnel_m3_soc(); dpxbar->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dpxbar->regs)) return PTR_ERR(dpxbar->regs); diff --git a/drivers/phy/apple/atc.c b/drivers/phy/apple/atc.c index 4ce4ad5062504f..4735e9f4b09606 100644 --- a/drivers/phy/apple/atc.c +++ b/drivers/phy/apple/atc.c @@ -3222,7 +3222,7 @@ static int atc_tunnel_set_t602x(struct apple_atcphy *atcphy, unsigned int dpin, /* T6030 (M3 Pro) uses T8122-generation PHYs for both DP IN clock outputs. */ static bool apple_atc_tunnel_is_t6030(struct apple_atcphy *atcphy) { - return of_machine_is_compatible("apple,t6030") && + return apple_dp_tunnel_m3_soc() && atcphy->hw->gen == ATCPHY_GENERATION_T8122; } @@ -3487,8 +3487,7 @@ static int atcphy_configure(struct apple_atcphy *atcphy, enum atcphy_mode mode) /* Keep failed transitions retryable even when the requested mode is unchanged. */ atcphy->mode_dirty = true; /* the mode change below may power the PHY down: stop the tunnel clock first */ - if (of_machine_is_compatible("apple,t6030") && - atcphy->hw->gen == ATCPHY_GENERATION_T8122) { + if (apple_atc_tunnel_is_t6030(atcphy)) { ret = atc_t8122_tunnel_stop(atcphy); if (ret) return ret; diff --git a/drivers/thunderbolt/apple.c b/drivers/thunderbolt/apple.c index c6625c5cbb5d3f..d181aaf88423fb 100644 --- a/drivers/thunderbolt/apple.c +++ b/drivers/thunderbolt/apple.c @@ -151,6 +151,15 @@ static const struct apple_cio_hw apple_cio_t6030_hw = { .dp = &apple_dpin_m3, }; +/* + * T6031/T6034 (M3 Max): the ACIO bring-up stays the t8103 one it has used so + * far (the link already works with it); only the DP IN policy is the M3 one. + * DP tunnels still need the root to be on apple_dpin_qualified_soc. + */ +static const struct apple_cio_hw apple_cio_t6031_hw = { + .dp = &apple_dpin_m3, +}; + /* Type 7 uses its existing ready-state check and has no qualified DP route. */ static const struct apple_cio_hw apple_cio_t8142_hw = { .dp = &apple_dpin_disabled, @@ -376,6 +385,8 @@ static const struct of_device_id apple_dpin_qualified_soc[] = { { .compatible = "apple,t6020" }, { .compatible = "apple,t6021" }, { .compatible = "apple,t6030" }, + /* T6034: T8122-generation ATC PHYs and the M3 DP IN flow, as on T6030. */ + { .compatible = "apple,t6034" }, {}, }; @@ -3335,6 +3346,10 @@ static const struct of_device_id apple_acio_match[] = { .compatible = "apple,t6030-usb4-acio", .data = &apple_cio_t6030_hw, }, + { + .compatible = "apple,t6031-usb4-acio", + .data = &apple_cio_t6031_hw, + }, { .compatible = "apple,t6020-usb4-acio", .data = &apple_cio_t6020_hw, diff --git a/include/linux/soc/apple/dp-tunnel.h b/include/linux/soc/apple/dp-tunnel.h index 540d48fe8e0dcb..1f1c4903e4896d 100644 --- a/include/linux/soc/apple/dp-tunnel.h +++ b/include/linux/soc/apple/dp-tunnel.h @@ -180,6 +180,17 @@ static inline bool apple_dp_tunnel_route_wired(struct device_node *route, * T6030 old trees may omit DPIN names on their three-output T602X crossbar. * Consumers qualify their SoC flow separately and never select these muxes. */ +/* + * SoCs whose DP IN tunnels run the T6030 (M3) flow: T8122-generation ATC PHYs + * clocking both DP IN outputs, and a crossbar that routes every output itself. + * T6034 has the same ATC generation. + */ +static inline bool apple_dp_tunnel_m3_soc(void) +{ + return of_machine_is_compatible("apple,t6030") || + of_machine_is_compatible("apple,t6034"); +} + static inline bool apple_dp_tunnel_dual_stream(struct device_node *connector_np) { struct device_node *port __free(device_node) = NULL; diff --git a/tools/asahi/t6030-clock-tests.py b/tools/asahi/t6030-clock-tests.py index 0b75c3ade6f5d6..459006c1a7bea7 100644 --- a/tools/asahi/t6030-clock-tests.py +++ b/tools/asahi/t6030-clock-tests.py @@ -10,7 +10,7 @@ import subprocess ROOT = Path(__file__).resolve().parents[2] FUNCTIONS = { - 'include/linux/soc/apple/dp-tunnel.h': ['apple_dp_tunnel_t6030_pclk'], + 'include/linux/soc/apple/dp-tunnel.h': ['apple_dp_tunnel_t6030_pclk', 'apple_dp_tunnel_m3_soc'], 'drivers/gpu/drm/apple/dcp-fabric-core.h': ['dcp_fabric_t6030_pclk'], 'drivers/gpu/drm/apple/dcp-fabric-session.h': ['dcp_fabric_callback_valid'], 'drivers/phy/apple/atc.c': [ diff --git a/tools/asahi/tunnel-route-tests.py b/tools/asahi/tunnel-route-tests.py index 5be05c91c156f6..4bf11b24f7d5af 100644 --- a/tools/asahi/tunnel-route-tests.py +++ b/tools/asahi/tunnel-route-tests.py @@ -11,7 +11,7 @@ ROOT = Path(__file__).resolve().parents[2] FUNCTIONS = { - 'include/linux/soc/apple/dp-tunnel.h': ['apple_dp_tunnel_t6030_pclk'], + 'include/linux/soc/apple/dp-tunnel.h': ['apple_dp_tunnel_t6030_pclk', 'apple_dp_tunnel_m3_soc'], 'drivers/gpu/drm/apple/dcp-fabric-core.c': ['dcp_fabric_tunnel_clock_blocked'], 'drivers/gpu/drm/apple/dcp-fabric.c': [ 'dcp_fabric_snapshot_port', 'dcp_typec_tunnel_ctl'], @@ -19,7 +19,7 @@ def function(source, name): - match = re.search(r'^(?:static\s+)?(?:inline\s+)?(?:int|void|u8|struct mux_control \*)\s*' + + match = re.search(r'^(?:static\s+)?(?:inline\s+)?(?:int|void|u8|bool|struct mux_control \*)\s*' + name + r'\([^;]*?\)\n\{', source, re.M | re.S) if not match: raise ValueError(name) diff --git a/tools/asahi/tunnel-route/fixture.c b/tools/asahi/tunnel-route/fixture.c index dd63853c3bd369..ef5058a3443b5c 100644 --- a/tools/asahi/tunnel-route/fixture.c +++ b/tools/asahi/tunnel-route/fixture.c @@ -55,6 +55,9 @@ struct apple_dcp_typec_port { static bool t6030; static bool of_machine_is_compatible(const char *compatible) { + /* apple_dp_tunnel_m3_soc() also asks for T6034, which no scenario here models. */ + if (!strcmp(compatible, "apple,t6034")) + return false; assert(!strcmp(compatible, "apple,t6030")); return t6030; } From b5f591f608ef506626638b81f23b903e29c71894 Mon Sep 17 00:00:00 2001 From: Philip Wallage Date: Sat, 7 Nov 2026 19:43:59 +0100 Subject: [PATCH 5/7] soc: apple: display-gate: hand over the T6034 dcpext0 Let the display gate enable the T6034's external display processors on the T6030 dcpext handoff protocol: m1n1 publishes the T6030 markers for dcpext0 when chosen.asahi,t6034-dcpext=1 or -dispext=1 is set, and without them every node stays off. On T6031/T6034 dispextN_fe is the child of dispextN_cpu, as disp_fe is of disp_cpu, so the processor holds the front end and with it all three states. Resolve the power chain from the front end there (ext_fe_first), and keep the T6030 order (cpu, fe, sys) on T6030. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Philip Wallage --- drivers/soc/apple/t6030-display-gate.c | 43 ++++++++++++++++++++------ 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/drivers/soc/apple/t6030-display-gate.c b/drivers/soc/apple/t6030-display-gate.c index 0de143fd52db27..2dd0b187213397 100644 --- a/drivers/soc/apple/t6030-display-gate.c +++ b/drivers/soc/apple/t6030-display-gate.c @@ -236,6 +236,7 @@ struct gate_soc { const char *fw_uuids; /* /chosen strings naming each firmware image */ bool quiet_without_nodes; /* no display nodes in the device tree is normal */ bool dcpext; /* the external display processors and their DARTs */ + bool ext_fe_first; /* dcpext -> dispextN_fe -> _cpu -> _sys (T6031/T6034) */ }; static const struct gate_soc gate_t6030 __initconst = { @@ -345,6 +346,13 @@ static const struct gate_soc gate_t6034 __initconst = { .pmp_ps_any_pmgr = true, .describe = true, .fw_uuids = "asahi,t6034-fw-uuids", + /* + * dcpext0 on the T6030 handoff protocol (markers + * apple,t6030-dcpext-memory-ready / -dispext-handoff from m1n1 with + * chosen asahi,t6034-dcpext / -dispext). Without them it stays off. + */ + .dcpext = true, + .ext_fe_first = true, }; static const struct gate_soc *const gate_socs[] __initconst = { @@ -1371,15 +1379,32 @@ static int __init gate_ext_resolve(struct gate_ext *ext) return -EINVAL; /* Do not enable a CPU whose power ownership is not fully described. */ - ext->cpu = gate_ps_parent(ext->dcp); - if (!gate_ps_dispext(ext->cpu, "cpu", &ext->index)) - return -EINVAL; - ext->fe = gate_ps_parent(ext->cpu); - if (!gate_ps_dispext(ext->fe, "fe", &ext->index)) - return -EINVAL; - ext->sys = gate_ps_parent(ext->fe); - if (!gate_ps_dispext(ext->sys, "sys", &ext->index)) - return -EINVAL; + if (gate_soc->ext_fe_first) { + /* + * T6031/T6034: dispextN_fe is the child of dispextN_cpu, as + * disp_fe is of disp_cpu, so the processor holds the front end + * and with it all three states. Its DART and mailbox hold the CPU. + */ + ext->fe = gate_ps_parent(ext->dcp); + if (!gate_ps_dispext(ext->fe, "fe", &ext->index)) + return -EINVAL; + ext->cpu = gate_ps_parent(ext->fe); + if (!gate_ps_dispext(ext->cpu, "cpu", &ext->index)) + return -EINVAL; + ext->sys = gate_ps_parent(ext->cpu); + if (!gate_ps_dispext(ext->sys, "sys", &ext->index)) + return -EINVAL; + } else { + ext->cpu = gate_ps_parent(ext->dcp); + if (!gate_ps_dispext(ext->cpu, "cpu", &ext->index)) + return -EINVAL; + ext->fe = gate_ps_parent(ext->cpu); + if (!gate_ps_dispext(ext->fe, "fe", &ext->index)) + return -EINVAL; + ext->sys = gate_ps_parent(ext->fe); + if (!gate_ps_dispext(ext->sys, "sys", &ext->index)) + return -EINVAL; + } for (i = 0; i < 2; i++) { domain = gate_ps_parent(i ? ext->mbox : ext->dart); of_node_put(domain); From a25c3882cf721b48076ce713e0cda5e690a9e26c Mon Sep 17 00:00:00 2001 From: Philip Wallage Date: Sat, 7 Nov 2026 19:43:59 +0100 Subject: [PATCH 6/7] drm: apple: run the T6034 dcpext0 on its own 14.7 image With the gate's handoff, the T6034 dcpext0 was still refused three times on the way to a picture: - dcp_t6030_ext_native() looked only for an apple,t6030-display-subsystem, so it waited for an explicit start. - The external path admitted only the T6030 image (DDF38191-...). The T6034 external processors run the panel's own image (F493F03E-...), which the panel's DCP already drives on the same 14.7 layouts. - dcpext_check_power() and the scanout's DART check took power-domains[0] to be dispextN_cpu; on T6034 it is dispextN_fe. Accept the T6034 display subsystem, admit the T6034 image on apple,t6034 roots (dcp_ext_firmware_admitted(), used by the external prepare and the scanout's pageflip check), and find the CPU domain through dcp_ext_cpu_domain(), which follows _fe to its _cpu parent. T6030 behaves as before. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Philip Wallage --- drivers/gpu/drm/apple/dcp.c | 62 +++++++++++++++++++++++++- drivers/gpu/drm/apple/dcp.h | 2 + drivers/gpu/drm/apple/dcpext_scanout.c | 7 +-- drivers/gpu/drm/apple/iomfb_v14_7.c | 15 ++----- 4 files changed, 69 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/apple/dcp.c b/drivers/gpu/drm/apple/dcp.c index 8cb040d16d552c..6cfe67892cdc9f 100644 --- a/drivers/gpu/drm/apple/dcp.c +++ b/drivers/gpu/drm/apple/dcp.c @@ -1382,6 +1382,66 @@ static int dcp_external_start_locked(struct apple_dcp *dcp) * that DART, and stream 0 among the display subsystem's iommus, so that * framebuffers are mapped for it as for the panel. */ +/* Display subsystems an external processor on the T6030 handoff can join. */ +static const struct of_device_id dcp_ext_display_ids[] = { + { .compatible = "apple,t6030-display-subsystem" }, + /* T6034: dcpext0 on the T6030 handoff protocol. */ + { .compatible = "apple,t6034-display-subsystem" }, + {}, +}; + +/* + * The external processor images the 14.7 external path speaks to: the + * T6030 image, and on T6034 the SoC's own image, which + * the panel's DCP already runs natively on the same 14.7 layouts. + */ +bool dcp_ext_firmware_admitted(const struct device_node *np) +{ + const char *uuid; + + if (of_property_read_string(np, "apple,firmware-uuid", &uuid)) + return false; + if (!strcmp(uuid, "DDF38191-93B3-324A-BC8F-643006F5AC82")) + return true; + return of_machine_is_compatible("apple,t6034") && + !strcmp(uuid, "F493F03E-CC40-3D89-9A08-5F259BA2B246"); +} + +static bool dcp_ext_domain_is(struct device_node *ps, const char *part) +{ + const char *label; + size_t len, plen = strlen(part); + + if (!ps || of_property_read_string(ps, "label", &label) || + !strstarts(label, "dispext")) + return false; + len = strlen(label); + return len > plen && !strcmp(label + len - plen, part); +} + +/* + * The CPU power domain of an external processor's pipe, dispext_cpu, + * with a reference. T6030 names it first in the processor's power-domains; + * on T6031/T6034 the processor holds dispext_fe, the + * child of dispext_cpu there, as disp_fe is of disp_cpu. + */ +struct device_node *dcp_ext_cpu_domain(const struct device_node *np) +{ + struct device_node *ps, *parent; + + ps = of_parse_phandle(np, "power-domains", 0); + if (dcp_ext_domain_is(ps, "_fe")) { + parent = of_parse_phandle(ps, "power-domains", 0); + of_node_put(ps); + ps = parent; + } + if (!dcp_ext_domain_is(ps, "_cpu")) { + of_node_put(ps); + return NULL; + } + return ps; +} + bool dcp_t6030_ext_native(const struct device_node *np) { struct of_phandle_args dart, args; @@ -1403,7 +1463,7 @@ bool dcp_t6030_ext_native(const struct device_node *np) of_node_put(piodma); if (dart.args_count != 1 || dart.args[0] != 4 || !of_device_is_available(dart.np)) goto out; - display = of_find_compatible_node(NULL, NULL, "apple,t6030-display-subsystem"); + display = of_find_matching_node(NULL, dcp_ext_display_ids); n = display && of_device_is_available(display) ? of_count_phandle_with_args(display, "iommus", "#iommu-cells") : 0; for (i = 0; i < n && !native; i++) { diff --git a/drivers/gpu/drm/apple/dcp.h b/drivers/gpu/drm/apple/dcp.h index baff04ee201e72..eb07e7911b823d 100644 --- a/drivers/gpu/drm/apple/dcp.h +++ b/drivers/gpu/drm/apple/dcp.h @@ -97,6 +97,8 @@ void dcp_send_message(struct apple_dcp *dcp, u8 endpoint, u64 message); int dcp_dptx_connect_oob(struct platform_device *pdev, u32 port); bool dcp_t6030_ext_native(const struct device_node *np); +bool dcp_ext_firmware_admitted(const struct device_node *np); +struct device_node *dcp_ext_cpu_domain(const struct device_node *np); void dcp_external_ready(struct apple_dcp *dcp); void dcp_external_retry(struct apple_dcp *dcp, const char *why, int error, unsigned int base_ms); diff --git a/drivers/gpu/drm/apple/dcpext_scanout.c b/drivers/gpu/drm/apple/dcpext_scanout.c index f3266931bb456d..85cbff316ab841 100644 --- a/drivers/gpu/drm/apple/dcpext_scanout.c +++ b/drivers/gpu/drm/apple/dcpext_scanout.c @@ -516,7 +516,7 @@ static int scanout_recheck_dart(struct device_node *dart, struct device_node *dc return -EINVAL; /* The display DART of this processor's own pipe shares its CPU domain. */ dart_pd = of_parse_phandle(dart, "power-domains", 0); - dcp_pd = of_parse_phandle(dcp, "power-domains", 0); + dcp_pd = dcp_ext_cpu_domain(dcp); of_node_put(dart_pd); of_node_put(dcp_pd); if (!dart_pd || dart_pd != dcp_pd) @@ -760,14 +760,11 @@ int dcpext_scanout_register(struct apple_dcp *dcp) { struct device_node *node; struct dcpext_scanout *scanout; - const char *uuid; int ret; if (!dcp->external || dcp->fw_compat != DCP_FIRMWARE_V_14_7) return -ENODEV; - if (dcpext_pageflip && - (of_property_read_string(dcp->dev->of_node, "apple,firmware-uuid", &uuid) || - strcmp(uuid, "DDF38191-93B3-324A-BC8F-643006F5AC82"))) + if (dcpext_pageflip && !dcp_ext_firmware_admitted(dcp->dev->of_node)) return -EOPNOTSUPP; node = of_get_child_by_name(dcp->dev->of_node, "scanout"); if (!scanout_node_verified(node)) { diff --git a/drivers/gpu/drm/apple/iomfb_v14_7.c b/drivers/gpu/drm/apple/iomfb_v14_7.c index 8497de19e4ae25..4f1a9c529217f5 100644 --- a/drivers/gpu/drm/apple/iomfb_v14_7.c +++ b/drivers/gpu/drm/apple/iomfb_v14_7.c @@ -2066,8 +2066,8 @@ int iomfb_v14_7_external_prepare(struct apple_dcp *dcp) goto refuse; } /* The callbacks here are those of one firmware image. */ - if (of_property_read_string(dev->of_node, "apple,firmware-uuid", &uuid) || - strcmp(uuid, DCP_V14_FIRMWARE_UUID)) { + if (!dcp_ext_firmware_admitted(dev->of_node)) { + of_property_read_string(dev->of_node, "apple,firmware-uuid", &uuid); dev_err(dev, "external display processor firmware %s is not supported\n", uuid ?: "(unknown)"); ret = -ENODEV; @@ -2160,20 +2160,13 @@ static int dcpext_check_power(struct apple_dcp *dcp) struct device *dev = dcp->dev; struct device_node *ps, *entry; struct regmap *map; - const char *label; u32 offset, value; int ret; - ps = of_parse_phandle(dev->of_node, "power-domains", 0); - if (!ps) - return -ENODEV; /* The CPU domain of this pipe: dispext_cpu. */ - ret = of_property_read_string(ps, "label", &label); - if (ret || !strstarts(label, "dispext") || strlen(label) < 4 || - strcmp(label + strlen(label) - 4, "_cpu")) { - of_node_put(ps); + ps = dcp_ext_cpu_domain(dev->of_node); + if (!ps) return -EINVAL; - } ret = of_property_read_u32(ps, "reg", &offset); map = syscon_node_to_regmap(ps->parent); of_node_put(ps); From 66d6c1b1a52abd2815abb48a1f0dcc2a9a8a6be9 Mon Sep 17 00:00:00 2001 From: Philip Wallage Date: Sat, 7 Nov 2026 19:43:59 +0100 Subject: [PATCH 7/7] arm64: dts: apple: t6034-j516m: describe dcpext0 and the display crossbars Describe the T6034 external display processor dcpext0 (coprocessor, mailbox, firmware and display DARTs, display pipe), the ATC display crossbars and the Type-C routes, from the J516M ADT. dcpext0 sits 0x8000_0000 below the panel's DCP; both its DARTs are on interrupt 1047, as on T6030. Every node stays disabled; the display gate enables them only after m1n1's handoff. Include it from the J516M only: the J514M has the same SoC but is not tested. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Philip Wallage --- arch/arm64/boot/dts/apple/t6034-dcpext.dtsi | 203 ++++++++++++++++++++ arch/arm64/boot/dts/apple/t6034-j516m.dts | 1 + 2 files changed, 204 insertions(+) create mode 100644 arch/arm64/boot/dts/apple/t6034-dcpext.dtsi diff --git a/arch/arm64/boot/dts/apple/t6034-dcpext.dtsi b/arch/arm64/boot/dts/apple/t6034-dcpext.dtsi new file mode 100644 index 00000000000000..dec5e088fa9939 --- /dev/null +++ b/arch/arm64/boot/dts/apple/t6034-dcpext.dtsi @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * T6034 external display processor dcpext0. + * + * The J516M ADT places dcpext0 exactly 0x8000_0000 below the panel's DCP + * block: coprocessor 0x3_06c0_0000, mailbox 0x3_06c0_8000, firmware DART + * 0x3_0530_c000 and display DART 0x3_0530_4000 (both on interrupt 1047), + * display pipe 0x3_0400_0000. Its preloaded 14.7 firmware is the panel's + * image (F493F03E-...), and its nub has the T6030 dcpext segment layout, so + * it runs on the T6030 dcpext handoff protocol: compatible falls back to + * apple,t6030-dcpext. + * + * Power: as for the panel, dispext0_fe is the child of dispext0_cpu on + * T6031/T6034, so the processor holds the front end (and with it all three + * states); its DART and mailbox hold dispext0_cpu, which is what m1n1's + * display DART handoff and the display gate check. + * + * Every node stays disabled. m1n1 describes the firmware memory and the + * display DART only with chosen asahi,t6034-dcpext=1 / asahi,t6034-dispext=1, + * and the display gate enables the nodes only when those markers are there. + */ + +/ { + aliases { + dcpext0 = &dcpext; + }; +}; + +&soc { + dcpext_dart: iommu@30530c000 { + compatible = "apple,t6031-dart", "apple,t8110-dart"; + reg = <0x3 0x0530c000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext0_cpu>; + status = "disabled"; + }; + + dcpext_mbox: mailbox@306c08000 { + compatible = "apple,t6031-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x3 0x06c08000 0x0 0x4000>; + interrupt-parent = <&aic>; + /* ADT order 1069 1068 1071 1070, as the panel's 1030 1029 1032 1031 */ + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + power-domains = <&ps_dispext0_cpu>; + resets = <&ps_dispext0_cpu>; + status = "disabled"; + }; + + /* ADT atcN-dpxbar (compatible atc-dpxbar,t602x), one per Type-C port. */ + atcphy0_xbar: mux@70304c000 { + compatible = "apple,t6031-display-crossbar", + "apple,t6020-display-crossbar"; + reg = <0x7 0x0304c000 0x0 0x4000>; + #mux-control-cells = <1>; + power-domains = <&ps_atc0_usb>; + }; + + atcphy1_xbar: mux@b0304c000 { + compatible = "apple,t6031-display-crossbar", + "apple,t6020-display-crossbar"; + reg = <0xb 0x0304c000 0x0 0x4000>; + #mux-control-cells = <1>; + power-domains = <&ps_atc1_usb>; + }; + + atcphy2_xbar: mux@f0304c000 { + compatible = "apple,t6031-display-crossbar", + "apple,t6020-display-crossbar"; + reg = <0xf 0x0304c000 0x0 0x4000>; + #mux-control-cells = <1>; + power-domains = <&ps_atc2_usb>; + }; + + dcpext: dcp@306c00000 { + compatible = "apple,t6034-dcpext", "apple,t6030-dcpext", + "apple,dcpext"; + reg = <0x3 0x06c00000 0x0 0x4000>; + reg-names = "coproc"; + mboxes = <&dcpext_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext_dart 5>; + power-domains = <&ps_dispext0_fe>; + resets = <&ps_dispext0_cpu>; + /* + * The gate sets this too; naming it here gives the entry the + * phandle the gate requires (dtc emits one only if referenced). + */ + apple,pmp-report = <&pmp_report_dispext0>; + phys = <&atcphy0 PHY_TYPE_DP>, <&atcphy1 PHY_TYPE_DP>, + <&atcphy2 PHY_TYPE_DP>; + phy-names = "typec0", "typec1", "typec2"; + mux-controls = <&atcphy0_xbar 0>, <&atcphy1_xbar 0>, + <&atcphy2_xbar 0>, + <&atcphy0_xbar 1>, <&atcphy0_xbar 2>, + <&atcphy1_xbar 1>, <&atcphy1_xbar 2>, + <&atcphy2_xbar 1>, <&atcphy2_xbar 2>; + mux-control-names = "typec0", "typec1", "typec2", + "typec0-dpin0", "typec0-dpin1", + "typec1-dpin0", "typec1-dpin1", + "typec2-dpin0", "typec2-dpin1"; + apple,connector-type = "USB-C"; + /* display-crossbar0 upstream port: dispext0 */ + apple,dcp-index = <1>; + apple,typec-dptx-phys = <0 1 2>; + apple,typec-mux-indices = <0 0 0>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + /* Enabled together with the processor by the display gate. */ + typec-routes { + #address-cells = <1>; + #size-cells = <0>; + + route@0 { + reg = <0>; + mode-switch; + status = "disabled"; + + port { + dcpext_typec0: endpoint { + remote-endpoint = <&typec0_dcpext>; + }; + }; + }; + + route@1 { + reg = <1>; + mode-switch; + status = "disabled"; + + port { + dcpext_typec1: endpoint { + remote-endpoint = <&typec1_dcpext>; + }; + }; + }; + + route@2 { + reg = <2>; + mode-switch; + status = "disabled"; + + port { + dcpext_typec2: endpoint { + remote-endpoint = <&typec2_dcpext>; + }; + }; + }; + }; + }; +}; + +/* The driver waits for the PMP to acknowledge this request before RUN. */ +&pmp_report_dispext0 { + apple,always-on; +}; + +&typec0 { + ports { + port@3 { + reg = <3>; + + typec0_dcpext: endpoint { + remote-endpoint = <&dcpext_typec0>; + }; + }; + }; +}; + +&typec1 { + ports { + port@3 { + reg = <3>; + + typec1_dcpext: endpoint { + remote-endpoint = <&dcpext_typec1>; + }; + }; + }; +}; + +&typec2 { + ports { + port@3 { + reg = <3>; + + typec2_dcpext: endpoint { + remote-endpoint = <&dcpext_typec2>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/apple/t6034-j516m.dts b/arch/arm64/boot/dts/apple/t6034-j516m.dts index a8d651917c313e..355a6ae7192432 100644 --- a/arch/arm64/boot/dts/apple/t6034-j516m.dts +++ b/arch/arm64/boot/dts/apple/t6034-j516m.dts @@ -12,6 +12,7 @@ #include "t6034.dtsi" #include "t6034-dcp.dtsi" #include "t603x-j514-j516.dtsi" +#include "t6034-dcpext.dtsi" / { compatible = "apple,j516m", "apple,t6034", "apple,arm-platform";