From cbfdfdb77db26a48dd0114f42dbe07252cef288f 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 | 41 +++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c index abbd4e86af4935..52ceb25b3fd6c9 100644 --- a/drivers/iommu/apple-dart.c +++ b/drivers/iommu/apple-dart.c @@ -286,6 +286,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; @@ -2032,6 +2034,10 @@ static int apple_dart_attach_dev_paging(struct iommu_domain *domain, struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev); struct apple_dart_domain *dart_domain = to_dart_domain(domain); + 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); @@ -2101,6 +2107,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; @@ -2511,6 +2521,8 @@ static int apple_dart_def_domain_type(struct device *dev) { struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev); + if (cfg->stream_maps[0].dart->live_mtp) + return IOMMU_DOMAIN_IDENTITY; if (cfg->stream_maps[0].dart->pgsize > PAGE_SIZE) return IOMMU_DOMAIN_IDENTITY; if (!cfg->supports_bypass) @@ -3172,6 +3184,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; @@ -3187,7 +3218,7 @@ static int apple_dart_probe(struct platform_device *pdev) dart->fw_mirror = dart->locked && !dart->fw_handoff && (of_device_is_compatible(dev->of_node, "apple,t8140-dart") || of_device_is_compatible(dev->of_node, "apple,t8142-dart")); - if (!dart->locked) { + if (!dart->locked && !dart->live_mtp) { ret = apple_dart_hw_reset(dart); if (ret) goto err_clk_disable; @@ -3337,7 +3368,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 && !READ_ONCE(dart->commands_gated)) + if (!dart->locked && !dart->live_mtp && !READ_ONCE(dart->commands_gated)) apple_dart_hw_reset(dart); free_irq(dart->irq, dart); @@ -3345,7 +3376,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 const struct apple_dart_hw apple_dart_hw_t8103 = { @@ -3461,6 +3493,9 @@ static __maybe_unused int apple_dart_suspend(struct device *dev) struct apple_dart *dart = dev_get_drvdata(dev); unsigned int sid, idx; + if (dart->live_mtp) + return -EBUSY; + dart->tunnel_state_restored = false; if (READ_ONCE(dart->commands_gated)) return 0; From 5392f2cfc083db5743d345e764adc4d5c896b789 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 5f03bed772f264..be4f7dc8f1ffe1 100644 --- a/drivers/soc/apple/rtkit-helper.c +++ b/drivers/soc/apple/rtkit-helper.c @@ -195,6 +195,8 @@ static void apple_rtkit_helper_remove(struct platform_device *pdev) 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);