From 21edfe36ce1d47fb9269a7b7bd33550cc1ab4a4d Mon Sep 17 00:00:00 2001 From: Satya Benson Date: Sun, 1 Nov 2026 19:04:19 -0500 Subject: [PATCH 1/2] iommu: apple-dart: preserve the live J613 MTP bypass stream Keep the boot loader DMA context for a running J613 MTP session. Admit only the T8122 MTP DART at 0x2fa808000, exactly stream 1, and verify that its control register still selects bypass before skipping reset. Select an identity domain and reject paging, blocked-domain attachment and runtime suspend while the inherited session runs. Retain the clock and bypass state at removal. This permits the existing mtp-live-v1 RTKit adoption path to keep serving input without another INIT. The C-diag11 implementation passed owner input testing on J613 with firmware 26.6.2. The rebased series requires a separate owner boot test. Signed-off-by: Satya Benson --- drivers/iommu/apple-dart.c | 42 ++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c index 65d2ac48c495..240c6e140bb4 100644 --- a/drivers/iommu/apple-dart.c +++ b/drivers/iommu/apple-dart.c @@ -292,6 +292,8 @@ struct apple_dart { u32 pgsize; u32 num_streams; u32 supports_bypass : 1; + /* J613 MTP keeps issuing DMA in the boot loader identity domain. */ + bool live_mtp; u32 four_level : 1; u32 locked : 1; u32 tunneled : 1; @@ -2593,6 +2595,10 @@ static int apple_dart_attach_dev_paging(struct iommu_domain *domain, struct apple_dart_domain *dart_domain = to_dart_domain(domain); bool streams_added = false; + for_each_stream_map(i, cfg, stream_map) + if (stream_map->dart->live_mtp) + return -EBUSY; + for_each_stream_map(i, cfg, stream_map) WARN_ON(pm_runtime_get_sync(stream_map->dart->dev) < 0); @@ -2686,6 +2692,10 @@ static int apple_dart_attach_dev_blocked(struct iommu_domain *domain, struct apple_dart_stream_map *stream_map; int i; + for_each_stream_map(i, cfg, stream_map) + if (stream_map->dart->live_mtp) + return -EBUSY; + if (cfg->locked) return -EINVAL; @@ -3377,7 +3387,8 @@ static int apple_dart_def_domain_type(struct device *dev) if (cfg->stream_maps[0].dart->managed_sids || apple_dart_has_borrowed(cfg->stream_maps[0].dart)) return IOMMU_DOMAIN_DMA; - if (cfg->stream_maps[0].dart->retained_mtp) + if (cfg->stream_maps[0].dart->retained_mtp || + cfg->stream_maps[0].dart->live_mtp) return IOMMU_DOMAIN_IDENTITY; if (cfg->stream_maps[0].dart->pgsize > PAGE_SIZE) return IOMMU_DOMAIN_IDENTITY; @@ -4302,6 +4313,25 @@ static int apple_dart_probe(struct platform_device *pdev) goto err_clk_disable; } + /* A live MTP epoch must never lose its firmware DMA addresses. */ + if (of_property_present(dev->of_node, "apple,bypass-handoff-streams")) { + u32 stream; + + if (!of_machine_is_compatible("apple,j613") || + !of_device_is_compatible(dev->of_node, "apple,t8122-dart") || + res->start != 0x2fa808000ULL || !dart->supports_bypass || + of_property_count_u32_elems(dev->of_node, + "apple,bypass-handoff-streams") != 1 || + of_property_read_u32(dev->of_node, "apple,bypass-handoff-streams", + &stream) || + stream != 1 || stream >= dart->num_streams || + apple_dart_readl(dart, DART_TCR(dart, stream)) != dart->hw->tcr_bypass) { + ret = -EINVAL; + goto err_clk_disable; + } + dart->live_mtp = true; + } + ret = apple_dart_read_remaps(dart); if (ret) goto err_clk_disable; @@ -4411,7 +4441,7 @@ static int apple_dart_probe(struct platform_device *pdev) } /* ENABLE is write-one-to-set; no foreign stream changes state. */ apple_dart_writel(dart, dart->managed_sids, dart->hw->enable_streams); - } else if (!dart->locked && !dart->retained_mtp && !dart->preserve_display) { + } else if (!dart->locked && !dart->retained_mtp && !dart->live_mtp && !dart->preserve_display) { ret = apple_dart_hw_reset(dart); if (ret) goto err_clk_disable; @@ -4650,7 +4680,7 @@ static void apple_dart_remove(struct platform_device *pdev) * A command issued then never completes. The next probe resets the * block after that clock is running again. */ - if (!dart->locked && !dart->retained_mtp && + if (!dart->locked && !dart->retained_mtp && !dart->live_mtp && !READ_ONCE(dart->commands_gated)) apple_dart_hw_reset(dart); @@ -4660,7 +4690,8 @@ static void apple_dart_remove(struct platform_device *pdev) iommu_device_unregister(&dart->iommu); iommu_device_sysfs_remove(&dart->iommu); - clk_bulk_disable_unprepare(dart->num_clks, dart->clks); + if (!dart->live_mtp) + clk_bulk_disable_unprepare(dart->num_clks, dart->clks); } static void apple_dart_shutdown(struct platform_device *pdev) @@ -4808,6 +4839,9 @@ static __maybe_unused int apple_dart_suspend(struct device *dev) { struct apple_dart *dart = dev_get_drvdata(dev); + if (dart->live_mtp) + return -EBUSY; + dart->tunnel_state_restored = false; if (READ_ONCE(dart->commands_gated)) return 0; From 739fc9d5a83b9cf9987614c997b62677fe25818a Mon Sep 17 00:00:00 2001 From: Satya Benson Date: Mon, 2 Nov 2026 12:56:58 -0500 Subject: [PATCH 2/2] soc: apple: rtkit-helper: match the T8122 helper compatible The J613 and J615 25G83 device trees list the MTP as "apple,t8122-mtp", "apple,t8122-rtk-helper-asc4", "apple,mtp" without the generic "apple,rtk-helper-asc4" fallback, and say that Linux binds the SoC-specific compatible. The helper only matches the generic one, so on those boards it never probes, DockChannel HID defers forever and the built-in keyboard and trackpad stay absent. Match "apple,t8122-rtk-helper-asc4" as well. Signed-off-by: Satya Benson --- drivers/soc/apple/rtkit-helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/apple/rtkit-helper.c b/drivers/soc/apple/rtkit-helper.c index cbb4be1ebfba..c7d9832aa0f6 100644 --- a/drivers/soc/apple/rtkit-helper.c +++ b/drivers/soc/apple/rtkit-helper.c @@ -405,6 +405,8 @@ static const struct dev_pm_ops apple_rtkit_helper_pm_ops = { static const struct of_device_id apple_rtkit_helper_of_match[] = { { .compatible = "apple,rtk-helper-asc4" }, + /* J613/J615 25G83 DTs omit the generic fallback (see t8122-j613-25g83.dts). */ + { .compatible = "apple,t8122-rtk-helper-asc4" }, {}, }; MODULE_DEVICE_TABLE(of, apple_rtkit_helper_of_match);