From ec501ab5a184f2ead26a12324ea8453e019c69d5 Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Sat, 31 Oct 2026 11:54:45 +0100 Subject: [PATCH 1/9] drm/asahi: g18: start stage 10 without a G18GFX01 capture Stage 10 (the DRM render node) loaded asahi/g18-26a428-color-a-v2.bin, a private capture of a macOS render job, only to build the H1 job it then never runs: every application frame clears the encoded command and rebuilds it from Mesa's parameters ("no capture bytes execute"). When the file is absent at stage 10, map the colour-a page layout with zeroed pages (output pages poisoned as before) and skip the H1 encode. The capture is still required by stage 9 and still preferred when present. Tested on the J873g: firmware live, G18_DRM_READY, GLES clear and triangle read back exactly at 64, 256 and 1920 square; sway, alacritty and mpv render on the GPU. Signed-off-by: Thomas Glanzmann (cherry picked from commit 150ba9aa9ce8109a6005a61c3078c3d4fc6e20fe) --- .../gpu/drm/asahi/g18/fw/graphics_payload.rs | 7 ++ drivers/gpu/drm/asahi/g18/initdata/mod.rs | 3 +- .../gpu/drm/asahi/g18/runtime/graphics_job.rs | 1 + .../drm/asahi/g18/runtime/graphics_memory.rs | 74 +++++++++++++------ 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/asahi/g18/fw/graphics_payload.rs b/drivers/gpu/drm/asahi/g18/fw/graphics_payload.rs index 71a82541685e0..5e60e8bf37b84 100644 --- a/drivers/gpu/drm/asahi/g18/fw/graphics_payload.rs +++ b/drivers/gpu/drm/asahi/g18/fw/graphics_payload.rs @@ -78,6 +78,13 @@ const WITNESS_RANGES: [(u64, usize, u32); 25] = [ (0x100_002d_8000, 0xc0000, 4), ]; +/// Every colour-a page (address, captured usage) in file order, for the +/// stage-10 layout that is mapped without a capture file. +pub(crate) fn color_a_pages() -> impl Iterator { + RANGES.iter().flat_map(|&(base, length, usage)| + (0..length).step_by(PAGE_BYTES).map(move |offset| (base + offset as u64, usage))) +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(crate) enum Capture { ColorA = 1, ColorB = 2, GearsG1 = 3, FragmentWitness = 4 } diff --git a/drivers/gpu/drm/asahi/g18/initdata/mod.rs b/drivers/gpu/drm/asahi/g18/initdata/mod.rs index 05c0d1c17633e..50b8901e252a4 100644 --- a/drivers/gpu/drm/asahi/g18/initdata/mod.rs +++ b/drivers/gpu/drm/asahi/g18/initdata/mod.rs @@ -424,7 +424,8 @@ impl G18FirmwareMemory { let pool = self.uma_pool.prepare_binding()?; self.uma_pool.load_hardware_descriptor(dev, &mut self.uma, pool, j873_sma_device_words(2, 6)?)?; job.parameter_buffer().load_row(&mut self.pbdesc)?; - job.encode_h1(dev)?; + // Without a capture (stage 10 only) the first application frame encodes. + if !job.layout_only_payload() { job.encode_h1(dev)?; } Ok(pool) } diff --git a/drivers/gpu/drm/asahi/g18/runtime/graphics_job.rs b/drivers/gpu/drm/asahi/g18/runtime/graphics_job.rs index de7e2cd51f5d2..6080cd3bf4b05 100644 --- a/drivers/gpu/drm/asahi/g18/runtime/graphics_job.rs +++ b/drivers/gpu/drm/asahi/g18/runtime/graphics_job.rs @@ -136,6 +136,7 @@ impl G18GraphicsJob { } pub(crate) fn vm(&self) -> &mmu::Vm { self.program.vm() } + pub(crate) fn layout_only_payload(&self) -> bool { self.program.layout_only_payload() } pub(crate) fn context_id(&self) -> u8 { self.program.context_id() } pub(crate) fn scheduler_record(&self) -> Result { Ok(self.scheduler.binding(0)?.record) } pub(crate) fn queues(&mut self) -> &mut G18GraphicsQueues { &mut self.queues } diff --git a/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs b/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs index 0a9a9504925b2..10c9573166088 100644 --- a/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs +++ b/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs @@ -30,49 +30,81 @@ impl G18GraphicsMemory { _ => return Err(EINVAL), }; if !uat.is_t8152_geometry() || mmu::UAT_PGSZ != payload::PAGE_BYTES { return Err(ENODEV); } - let firmware = Firmware::request(name, dev.as_ref().as_ref())?; + let firmware = match Firmware::request(name, dev.as_ref().as_ref()) { + Ok(firmware) => firmware, + // Stage 10 executes no capture bytes: every application command + // is rebuilt from Mesa's parameters. It needs only the colour-a + // page layout, which is mapped here with zeroed contents. + Err(e) if e == ENOENT && profile == 1 + && *crate::module_parameters::g18_initdata_test.value() == 10 => + return Self::layout_only(dev, uat), + Err(e) => return Err(e), + }; let input = payload::GraphicsPayload::parse(firmware.data()).map_err(|_| EINVAL)?; if input.capture() as u32 != profile { return Err(EINVAL); } + let (context, aliases, pages) = Self::map_pages(dev, uat, + (0..input.page_count()).map(|index| input.page(index).map(|page| (page.address, Some(page.bytes)))))?; + let mut command = KVec::new(); + command.extend_from_slice(input.command(), GFP_KERNEL)?; + let owner = Self { context, aliases, vdm_alias: None, ppp_aliased: false, pages, capture: input.capture(), command, + body_digest: input.body_digest(), command_digest: payload::fnv64(input.command()) }; + fence(Ordering::SeqCst); + dev_info!(dev.as_ref(), "G18_RENDER_PAYLOAD profile={} pages={} low_aliases={} body_fnv={:#018x} command_fnv={:#018x} context={} roots={:x?}; unpublished\n", + profile, owner.pages.len(), owner.aliases.len(), owner.body_digest, owner.command_digest, + owner.context_id(), owner.roots()); + Ok(owner) + } + + /// The colour-a VM layout without its capture: zeroed pages, no command. + fn layout_only(dev: &AsahiDrmDevice, uat: &mmu::Uat) -> Result { + let (context, aliases, pages) = Self::map_pages(dev, uat, + payload::color_a_pages().map(|(address, _)| Some((address, None))))?; + let owner = Self { context, aliases, vdm_alias: None, ppp_aliased: false, pages, + capture: payload::Capture::ColorA, command: KVec::new(), body_digest: 0, command_digest: 0 }; + fence(Ordering::SeqCst); + dev_info!(dev.as_ref(), "G18_RENDER_PAYLOAD layout-only colour-a pages={} low_aliases={} context={} roots={:x?}; no capture, stage 10 encodes from Mesa only\n", + owner.pages.len(), owner.aliases.len(), owner.context_id(), owner.roots()); + Ok(owner) + } + + /// True when no capture was loaded: there is no H1 command to encode. + pub(crate) fn layout_only_payload(&self) -> bool { self.command.is_empty() } + + fn map_pages<'a>(dev: &AsahiDrmDevice, uat: &mmu::Uat, + sources: impl Iterator)>>) + -> Result<(mmu::G18ExecutionContext, KVec, KVec)> { let vm = uat.new_t8152_compute_fixture_vm()?; let context = uat.prepare_t8152_execution_context(&vm)?; let mut pages = KVec::new(); let mut aliases = KVec::new(); - for index in 0..input.page_count() { - let source = input.page(index).ok_or(EINVAL)?; + for source in sources { + let (address, bytes) = source.ok_or(EINVAL)?; // Captured usage flags are not PTE permissions. These private // fixture mappings have an explicit diagnostic RW policy. - let mut page = MappedObject::new_wc_at(dev, &vm, source.address, + let mut page = MappedObject::new_wc_at(dev, &vm, address, payload::PAGE_BYTES, mmu::PROT_GPU_SHARED_RW)?; page.with_bytes_mut(|out| { - out.copy_from_slice(source.bytes); - if (payload::OUTPUT..payload::OUTPUT + payload::OUTPUT_BYTES).contains(&source.address) { + match bytes { Some(bytes) => out.copy_from_slice(bytes), None => out.fill(0) } + if (payload::OUTPUT..payload::OUTPUT + payload::OUTPUT_BYTES).contains(&address) { out.fill(0xa5); } Ok(()) })?; - if source.address < 0x78000 { - aliases.push(page.map_alias_at(&vm, va::COMPACT_BIAS + source.address, + if address < 0x78000 { + aliases.push(page.map_alias_at(&vm, va::COMPACT_BIAS + address, mmu::PROT_GPU_SHARED_RW)?, GFP_KERNEL)?; for delta in [0, va::PAGE - 1] { - if vm.translate_iova(source.address + delta)? - != vm.translate_iova(va::COMPACT_BIAS + source.address + delta)? { + if vm.translate_iova(address + delta)? + != vm.translate_iova(va::COMPACT_BIAS + address + delta)? { return Err(EFAULT); } } } - vm.translate_iova(source.address)?; - vm.translate_iova(source.address + va::PAGE - 1)?; + vm.translate_iova(address)?; + vm.translate_iova(address + va::PAGE - 1)?; pages.push(page, GFP_KERNEL)?; } - let mut command = KVec::new(); - command.extend_from_slice(input.command(), GFP_KERNEL)?; - let owner = Self { context, aliases, vdm_alias: None, ppp_aliased: false, pages, capture: input.capture(), command, - body_digest: input.body_digest(), command_digest: payload::fnv64(input.command()) }; - fence(Ordering::SeqCst); - dev_info!(dev.as_ref(), "G18_RENDER_PAYLOAD profile={} pages={} low_aliases={} body_fnv={:#018x} command_fnv={:#018x} context={} roots={:x?}; unpublished\n", - profile, owner.pages.len(), owner.aliases.len(), owner.body_digest, owner.command_digest, - owner.context_id(), owner.roots()); - Ok(owner) + Ok((context, aliases, pages)) } pub(crate) fn vm(&self) -> &mmu::Vm { self.context.vm() } From e80afbf5e5abc19178a71deb434a044e63f1af98 Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Sat, 31 Oct 2026 11:54:45 +0100 Subject: [PATCH 2/9] drm/asahi: g18: log application remaps only with g18_kick_log With two clients (a compositor and a video player) every frame of each is a new client to the single application job, so G18_APP_VM and six G18_APP_TARGET lines were printed per frame, about 330 lines a second, synchronously to the boot console. Print them with g18_kick_info! like the other per-kick lines. Signed-off-by: Thomas Glanzmann (cherry picked from commit 79886333e01497b5cd2c5afa20bc1fc58d6e3546) --- drivers/gpu/drm/asahi/g18/runtime/graphics_job_application.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/asahi/g18/runtime/graphics_job_application.rs b/drivers/gpu/drm/asahi/g18/runtime/graphics_job_application.rs index 5a43ad3816e62..3eb58cce499b9 100644 --- a/drivers/gpu/drm/asahi/g18/runtime/graphics_job_application.rs +++ b/drivers/gpu/drm/asahi/g18/runtime/graphics_job_application.rs @@ -93,10 +93,10 @@ impl ApplicationJob { self.guard=Some(guard);self.generation=frame.generation;self.retired=false; self.client_frames=if new_client {1} else {self.client_frames.saturating_add(1)}; if remap { - dev_info!(dev.as_ref(),"G18_APP_VM frame={} vm={} context={} target={}x{} aliases={}\n", + crate::g18_kick_info!(dev.as_ref(),"G18_APP_VM frame={} vm={} context={} target={}x{} aliases={}\n", frame.generation,vm.id(),self.job.context_id(),render.target.width,render.target.height,self.user_aliases.len()); for (target,name) in self.job.targets.iter().zip(assembly::TARGET_NAMES) { - dev_info!(dev.as_ref(),"G18_APP_TARGET name={} va={:#x} bytes={:#x} context={}\n", + crate::g18_kick_info!(dev.as_ref(),"G18_APP_TARGET name={} va={:#x} bytes={:#x} context={}\n", name,target.iova(),target.logical_size,self.job.context_id()); } } From cf3e2dc18cae8ab0839aa4b19c06f17cd01935d0 Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Sat, 31 Oct 2026 12:34:29 +0100 Subject: [PATCH 3/9] dt-bindings: power: apple,pmc: add T8152 The T8152 (M6) PMC has the T8140 voter interface: perf-state floors at agent << 14 and a rails block with the honoured states and per-rail voter enables, with three rails (DCS, SOC, DISP) and higher maxima. Add apple,t8152-pmc and its performance controller, apple,t8152-clpc. Signed-off-by: Thomas Glanzmann (cherry picked from commit afb23328ea94f6ce32b0be7bc4f96f17e47b4097) --- Documentation/devicetree/bindings/power/apple,pmc.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/power/apple,pmc.yaml b/Documentation/devicetree/bindings/power/apple,pmc.yaml index c94de57c40596..825d68ce51998 100644 --- a/Documentation/devicetree/bindings/power/apple,pmc.yaml +++ b/Documentation/devicetree/bindings/power/apple,pmc.yaml @@ -29,6 +29,7 @@ properties: - apple,t8132-pmc - apple,t8140-pmc - apple,t8142-pmc + - apple,t8152-pmc reg: minItems: 2 @@ -230,6 +231,7 @@ patternProperties: - apple,t8132-clpc - apple,t8140-clpc - apple,t8142-clpc + - apple,t8152-clpc reg: maxItems: 1 From 26f8fc80230b2f0f6dbff067c435526d5d945b16 Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Sat, 31 Oct 2026 12:34:29 +0100 Subject: [PATCH 4/9] pmdomain/soc: apple: T8152 PMC voters and CLPC iBoot leaves every PMC voter enable at 0 on the J873g, so no floor is honoured and DRAM and fabric stay at their lowest states: one core copies at 6.6 GB/s and the GPU clears 4K in 4.2 ms. The AppleT8152PMGR accessors (26A434) use RegMap 0x1c0 = pmgr reg 46 at 0x302800000: floors at agent << 14, honoured states at 0x1c6000, voter enables at 0x1c8000 + rail * 4 (PMC::getVoterEnablesOffset), rails DCS, SOC and DISP with maxima 7, 4 and 3. That is the T8140 layout with a rails block at 0x1c6000. Add apple,t8152-pmc and apple,t8152-clpc, the latter with per-SoC default state maps (T8140 keeps its maps). With PMP, CLPC and AP enabled: 23.5 GB/s, 4K clear 1.45 ms. Signed-off-by: Thomas Glanzmann (cherry picked from commit e19dcfa40295b9702abe25287b3161e914dd765c) --- drivers/pmdomain/apple/pmc.c | 13 +++++++++++++ drivers/soc/apple/clpc.c | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/pmdomain/apple/pmc.c b/drivers/pmdomain/apple/pmc.c index 881d5ef0b1210..3765e9a775ff7 100644 --- a/drivers/pmdomain/apple/pmc.c +++ b/drivers/pmdomain/apple/pmc.c @@ -1373,10 +1373,23 @@ static const struct apple_pmc_hw apple_pmc_hw_t6040 = { .ap_agent = 3, }; +/* T8152 uses the T8142 voter interface with its rails at 0x3029c6000. */ +static const struct apple_pmc_hw apple_pmc_hw_t8152 = { + .agent_stride = 0x4000, + .agents = 4, + .rails = 3, + .agent_state = 0x0, + .rail_enable = 0x2000, + .dcs_rail = 0, + .dcs_max = 7, + .ap_agent = 3, +}; + static const struct of_device_id apple_pmc_of_match[] = { { .compatible = "apple,t8132-pmc", .data = &apple_pmc_hw_t8132 }, { .compatible = "apple,t8140-pmc", .data = &apple_pmc_hw_t8140 }, { .compatible = "apple,t8142-pmc", .data = &apple_pmc_hw_t8142 }, + { .compatible = "apple,t8152-pmc", .data = &apple_pmc_hw_t8152 }, { .compatible = "apple,t6041-pmc", .data = &apple_pmc_hw_t6040 }, {} }; diff --git a/drivers/soc/apple/clpc.c b/drivers/soc/apple/clpc.c index b31a46b050358..c7b29f0e6a49b 100644 --- a/drivers/soc/apple/clpc.c +++ b/drivers/soc/apple/clpc.c @@ -1141,10 +1141,20 @@ static struct kunit_suite apple_clpc_suite = { kunit_test_suite(apple_clpc_suite); #endif +/* T8152: DCS states 0-7 and fabric states 0-4. */ +static const struct apple_clpc_hw apple_clpc_hw_t8152 = { + .rail = { [APPLE_CLPC_DCS] = 0, [APPLE_CLPC_SOC] = 1 }, + .map = { + [APPLE_CLPC_DCS] = { 2, 4, 6, 7 }, + [APPLE_CLPC_SOC] = { 1, 2, 3, 4 }, + }, +}; + static const struct of_device_id apple_clpc_of_match[] = { { .compatible = "apple,t8132-clpc", .data = &apple_clpc_hw_t8132 }, { .compatible = "apple,t8140-clpc", .data = &apple_clpc_hw_t8140 }, { .compatible = "apple,t8142-clpc", .data = &apple_clpc_hw_t8142 }, + { .compatible = "apple,t8152-clpc", .data = &apple_clpc_hw_t8152 }, { .compatible = "apple,t6041-clpc", .data = &apple_clpc_hw_t6040 }, {} }; From ac61317b7116812d3064be2325bf988c2c99dcc7 Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Sat, 31 Oct 2026 11:34:29 +0000 Subject: [PATCH 5/9] arm64: dts: apple: j873: PMC voters and CLPC Bind the PMC voter interface (pmgr reg 46, rails block at 0x3029c6000) with the PMP, CLPC and AP agents as static voters, and the CLPC. Signed-off-by: Thomas Glanzmann Adapt the PMC node to the public t8152-j873g RAM-boot device tree. (cherry picked from commit 9cac3b9679803baa1b11fcb25607848151c9cc8e) --- arch/arm64/boot/dts/apple/t8152-j873-pmc.dtsi | 27 +++++++++++++++++++ arch/arm64/boot/dts/apple/t8152-j873g.dts | 2 ++ 2 files changed, 29 insertions(+) create mode 100644 arch/arm64/boot/dts/apple/t8152-j873-pmc.dtsi diff --git a/arch/arm64/boot/dts/apple/t8152-j873-pmc.dtsi b/arch/arm64/boot/dts/apple/t8152-j873-pmc.dtsi new file mode 100644 index 0000000000000..3b809b363b84e --- /dev/null +++ b/arch/arm64/boot/dts/apple/t8152-j873-pmc.dtsi @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT + +/ { + soc { + /* + * Perf-state floors of voter agents 0-3 (PMP, CLPC, GFX, AP) and, + * at 0x1c6000, the honoured states and per-rail voter enables + * (rails DCS, SOC, DISP) in the PMC window, pmgr reg 46. + */ + pmc: power-management@302800000 { + compatible = "apple,t8152-pmc"; + reg = <0x3 0x02800000 0x0 0x10000>, + <0x3 0x029c6000 0x0 0x3000>; + reg-names = "voters", "rails"; + #address-cells = <1>; + #size-cells = <0>; + #cooling-cells = <2>; + /* PMP, CLPC and AP agents */ + apple,static-voters = <0 1 3>; + + clpc: performance-controller@1 { + compatible = "apple,t8152-clpc"; + reg = <1>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/apple/t8152-j873g.dts b/arch/arm64/boot/dts/apple/t8152-j873g.dts index f4ccb05ba0aab..ec3d591410b3d 100644 --- a/arch/arm64/boot/dts/apple/t8152-j873g.dts +++ b/arch/arm64/boot/dts/apple/t8152-j873g.dts @@ -283,3 +283,5 @@ #include "t8152-j873-gpu.dtsi" #include "t8152-j873-n1.dtsi" + +#include "t8152-j873-pmc.dtsi" From 6520267240f256535e01f62c35f4fc41913e9125 Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Sat, 31 Oct 2026 14:40:55 +0100 Subject: [PATCH 6/9] dt-bindings: spi: apple,qspi: add T8152 The T8152 (M6) boot NOR sits behind the same QSPIMC controller as on T8140 (ADT /arm-io/qspi, version 0x20100). Accept apple,t8152-qspi with apple,t8140-qspi as fallback. Signed-off-by: Thomas Glanzmann (cherry picked from commit 9aafd590cd45720a93f8c7a5e19c27adbe30fa30) --- .../devicetree/bindings/spi/apple,qspi.yaml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/apple,qspi.yaml b/Documentation/devicetree/bindings/spi/apple,qspi.yaml index 0b98af1ad68d2..40d08a8273712 100644 --- a/Documentation/devicetree/bindings/spi/apple,qspi.yaml +++ b/Documentation/devicetree/bindings/spi/apple,qspi.yaml @@ -19,11 +19,15 @@ allOf: properties: compatible: - enum: - - apple,t8122-qspi - - apple,t8132-qspi - - apple,t6041-qspi - - apple,t8140-qspi + oneOf: + - enum: + - apple,t8122-qspi + - apple,t8132-qspi + - apple,t6041-qspi + - apple,t8140-qspi + - items: + - const: apple,t8152-qspi + - const: apple,t8140-qspi reg: maxItems: 1 From 96aac9b95abf6770d731c4eb22af0b40796e68e7 Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Sat, 31 Oct 2026 13:51:19 +0000 Subject: [PATCH 7/9] arm64: dts: apple: t8152-j873: boot NOR with the NVRAM through QSPIMC The J873g's boot NOR (Winbond, JEDEC ef 65 14, 2 MiB) sits behind a QSPIMC controller at 0x331118000 (ADT /arm-io/qspi, version 0x20100), the one spi-apple-qspi drives on T8140. Its PMGR power states (devices SPI_P and QSPI) are off once iBoot is done; touching the controller without them takes an asynchronous SError, so describe them as power domains. The NVRAM v3 banks ("3VVN", 64 KiB each) run from 0x24000 to 0x1f4000, as on T8140 J700; the partition needs 4 KiB erase sectors to be writable (CONFIG_MTD_SPI_NOR_USE_4K_SECTORS). Tested on the J873g: asahi-nvram reads, writes and deletes variables; asahi-bless lists Macintosh HD and LinuxStub, and asahi-bless --next --set-boot "Macintosh HD" boots macOS once, after which the mini boots LinuxStub again. Signed-off-by: Thomas Glanzmann Describe the QSPI controller and its required PMGR domains in the public t8152-j873g device tree, without the unrelated legacy audio nodes. (cherry picked from commit 5164bb8e5e3cb419934fdd91eb9ddd192be3b031) --- .../arm64/boot/dts/apple/t8152-j873-qspi.dtsi | 85 +++++++++++++++++++ arch/arm64/boot/dts/apple/t8152-j873g.dts | 1 + 2 files changed, 86 insertions(+) create mode 100644 arch/arm64/boot/dts/apple/t8152-j873-qspi.dtsi diff --git a/arch/arm64/boot/dts/apple/t8152-j873-qspi.dtsi b/arch/arm64/boot/dts/apple/t8152-j873-qspi.dtsi new file mode 100644 index 0000000000000..c03fbf04b24e4 --- /dev/null +++ b/arch/arm64/boot/dts/apple/t8152-j873-qspi.dtsi @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT + +/* + * The boot NOR behind the QSPIMC controller (ADT /arm-io/qspi/spinor: firmware, + * anvram, syscfg), for asahi-nvram and asahi-bless. The controller's power + * states (PMGR devices SPI_P and QSPI) are off once iBoot is done with it; + * reading it without them takes an SError. + */ +/ { + aliases { + nvram = &nvram; + }; + + /* QSPIMC input clock, as on T8140 (ADT clock-ids 412) */ + clk_200m: clock-200m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <200000000>; + clock-output-names = "clk_200m"; + }; + + soc { + pmgr: power-management@300700000 { + compatible = "apple,t8152-pmgr", "apple,t8103-pmgr", + "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x3 0x700000 0x0 0x14000>; + }; + + qspi: spi@331118000 { + compatible = "apple,t8152-qspi", "apple,t8140-qspi"; + /* One aperture; the command block starts at offset 0x800. */ + reg = <0x3 0x31118000 0x0 0x4800>; + interrupt-parent = <&aic>; + interrupts = ; + clocks = <&clk_200m>; + power-domains = <&ps_qspi>; + #address-cells = <1>; + #size-cells = <0>; + + spinor: flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * 64 KiB NVRAM v3 banks ("3VVN") from 0x24000 + * to 0x1f4000, as on T8140 J700. + */ + nvram: partition@24000 { + label = "nvram"; + reg = <0x24000 0x1d0000>; + }; + }; + }; + }; + }; +}; + +&pmgr { + ps_spi_p: power-controller@d40 { + compatible = "apple,t8152-pmgr-pwrstate", + "apple,t8103-pmgr-pwrstate"; + reg = <0xd40 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "spi_p"; + }; + + ps_qspi: power-controller@1140 { + compatible = "apple,t8152-pmgr-pwrstate", + "apple,t8103-pmgr-pwrstate"; + reg = <0x1140 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "qspi"; + power-domains = <&ps_spi_p>; + }; +}; diff --git a/arch/arm64/boot/dts/apple/t8152-j873g.dts b/arch/arm64/boot/dts/apple/t8152-j873g.dts index ec3d591410b3d..1513a2abbc83f 100644 --- a/arch/arm64/boot/dts/apple/t8152-j873g.dts +++ b/arch/arm64/boot/dts/apple/t8152-j873g.dts @@ -285,3 +285,4 @@ #include "t8152-j873-n1.dtsi" #include "t8152-j873-pmc.dtsi" +#include "t8152-j873-qspi.dtsi" From 90c347e9255d2f2057b51184ff7767667ce15fae Mon Sep 17 00:00:00 2001 From: Acelogic Date: Fri, 6 Nov 2026 04:24:46 -0500 Subject: [PATCH 8/9] drm/asahi: use current G18 parameter namespace in capture-free path --- drivers/gpu/drm/asahi/g18/runtime/graphics_job.rs | 2 +- drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/asahi/g18/runtime/graphics_job.rs b/drivers/gpu/drm/asahi/g18/runtime/graphics_job.rs index 6080cd3bf4b05..01952223a0593 100644 --- a/drivers/gpu/drm/asahi/g18/runtime/graphics_job.rs +++ b/drivers/gpu/drm/asahi/g18/runtime/graphics_job.rs @@ -289,7 +289,7 @@ impl G18GraphicsJob { /// Caller has allocated/retained PB and pool owners and filled all native /// fields. In particular a default resource word is not an admitted policy. #[inline(never)] - pub(crate) fn encode(&mut self, dev: &AsahiDrmDevice, inputs: &cmd::G18RenderCommandInputs) -> Result { + pub(crate) fn encode(&mut self, _dev: &AsahiDrmDevice, inputs: &cmd::G18RenderCommandInputs) -> Result { if self.encoded.is_some() || self.controls.ta.resource_word == 0 || self.controls.fragment.resource_word == 0 || inputs.context_id != u32::from(self.context_id()) diff --git a/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs b/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs index 10c9573166088..f07b7204b6ab7 100644 --- a/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs +++ b/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs @@ -36,7 +36,7 @@ impl G18GraphicsMemory { // is rebuilt from Mesa's parameters. It needs only the colour-a // page layout, which is mapped here with zeroed contents. Err(e) if e == ENOENT && profile == 1 - && *crate::module_parameters::g18_initdata_test.value() == 10 => + && *crate::g18::params::g18_initdata_test.value() == 10 => return Self::layout_only(dev, uat), Err(e) => return Err(e), }; From 4b3ec237a5379e6b28ce7566ea956e948b34a9eb Mon Sep 17 00:00:00 2001 From: Acelogic Date: Fri, 6 Nov 2026 04:26:19 -0500 Subject: [PATCH 9/9] drm/asahi: read the G18 stage parameter by value --- drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs b/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs index f07b7204b6ab7..3175072b950e8 100644 --- a/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs +++ b/drivers/gpu/drm/asahi/g18/runtime/graphics_memory.rs @@ -36,7 +36,7 @@ impl G18GraphicsMemory { // is rebuilt from Mesa's parameters. It needs only the colour-a // page layout, which is mapped here with zeroed contents. Err(e) if e == ENOENT && profile == 1 - && *crate::g18::params::g18_initdata_test.value() == 10 => + && crate::g18::params::g18_initdata_test.value() == 10 => return Self::layout_only(dev, uat), Err(e) => return Err(e), };