diff --git a/Documentation/admin-guide/media/apple-jpeg.rst b/Documentation/admin-guide/media/apple-jpeg.rst index 35cca8b11d9de..f1d1faffc6a39 100644 --- a/Documentation/admin-guide/media/apple-jpeg.rst +++ b/Documentation/admin-guide/media/apple-jpeg.rst @@ -8,7 +8,7 @@ Apple JPEG scaffold This driver provides a common platform and V4L2 memory-to-memory scaffold for the Apple T6041 and T8140 JPEG engines. Each DT platform device owns one independent m2m scheduler, with formats and VB2 queues allocated per open file. -T6041's nodes reside in ``t6040.dtsi`` in this source tree. All JPEG engine +T6041's nodes reside in ``t604x.dtsi`` in this source tree. All JPEG engine nodes and the new T8140 DART remain disabled. SoC DART defaults are disabled; existing board overrides are preserved. In particular, J700 already enables its first JPEG DART independently of the disabled codec engines. diff --git a/Documentation/devicetree/bindings/gpu/apple,agx.yaml b/Documentation/devicetree/bindings/gpu/apple,agx.yaml index 2004c43d42b1d..9b5dc5b51241e 100644 --- a/Documentation/devicetree/bindings/gpu/apple,agx.yaml +++ b/Documentation/devicetree/bindings/gpu/apple,agx.yaml @@ -18,6 +18,7 @@ properties: - apple,agx-g14g - apple,agx-g14s - apple,agx-t6040 + - apple,agx-t6041 - apple,agx-t8132 - apple,agx-t8140 - items: @@ -309,6 +310,15 @@ allOf: apple,afr-leak-coef: minItems: 1 maxItems: 1 + - if: + properties: + compatible: + contains: + enum: + - apple,agx-t6040 + - apple,agx-t6041 + then: + properties: reg: items: - description: GFX coprocessor control registers @@ -356,6 +366,7 @@ allOf: contains: enum: - apple,agx-t6040 + - apple,agx-t6041 - apple,agx-t8132 - apple,agx-t8140 then: diff --git a/arch/arm64/boot/dts/apple/Makefile b/arch/arm64/boot/dts/apple/Makefile index c7487bcac3d35..52b15f4bdb8cb 100644 --- a/arch/arm64/boot/dts/apple/Makefile +++ b/arch/arm64/boot/dts/apple/Makefile @@ -97,6 +97,7 @@ dtb-$(CONFIG_ARCH_APPLE) += t6034-j516m.dtb dtb-$(CONFIG_ARCH_APPLE) += t6040-j614s.dtb dtb-$(CONFIG_ARCH_APPLE) += t6040-j616s.dtb dtb-$(CONFIG_ARCH_APPLE) += t6040-j616s-tether.dtb +dtb-$(CONFIG_ARCH_APPLE) += t6041-j616c.dtb dtb-$(CONFIG_ARCH_APPLE) += t8112-j413.dtb dtb-$(CONFIG_ARCH_APPLE) += t8112-j415.dtb dtb-$(CONFIG_ARCH_APPLE) += t8112-j473.dtb diff --git a/arch/arm64/boot/dts/apple/t6040-j616s-extdisp-usbc.dtsi b/arch/arm64/boot/dts/apple/t6040-j616s-extdisp-usbc.dtsi index fb151f79ecd5b..d4e7d32a06b31 100644 --- a/arch/arm64/boot/dts/apple/t6040-j616s-extdisp-usbc.dtsi +++ b/arch/arm64/boot/dts/apple/t6040-j616s-extdisp-usbc.dtsi @@ -24,7 +24,7 @@ /* * DISPEXT1_SYS sits on FAB7_SOC (ADT pmgr device id2 134, pmgr_aux 0x488, parent - * FAB6_SOC, off at boot), which t6040-pmgr.dtsi does not describe. m4.62 enabled + * FAB6_SOC, off at boot), which t604x-pmgr.dtsi does not describe. m4.62 enabled * DISPEXT1_SYS without it and the first DCPEXT1 register access (its DART) reset * the SoC. DISPEXT0_SYS's parent FAB2_SOC is on anyway through ATC0..2_COMMON. */ diff --git a/arch/arm64/boot/dts/apple/t6040.dtsi b/arch/arm64/boot/dts/apple/t6040.dtsi index 8625894da6ea4..38dc7888509fd 100644 --- a/arch/arm64/boot/dts/apple/t6040.dtsi +++ b/arch/arm64/boot/dts/apple/t6040.dtsi @@ -2,2440 +2,22 @@ /* * Apple T6040 "M4 Pro" SoC * - * Unit addresses are the Apple Device Tree's /arm-io addresses plus the - * 0x2_00000000 arm-io base. The nodes sit at the root, not under a - * simple-bus: the boot loader edits several of them by path. The blocks - * known to need non-posted writes carry nonposted-mmio themselves. - * * Copyright The Asahi Linux Contributors */ -#include -#include -#include -#include -#include -#include - -/ { - #address-cells = <2>; - #size-cells = <2>; - - cpuidle: cpuidle { - compatible = "apple,t6041-cpuidle"; - status = "disabled"; - }; - - cpus { - #address-cells = <2>; - #size-cells = <0>; - - /* - * The clusters are MPIDR Aff1, which are also the L2 groups. - * capacity-dmips-mhz comes from pinned single-core throughput - * at the lowest p-state (E 1018 MHz, P 1257 MHz): E/P is 0.652 - * per MHz, so E 668 and P 1024. - */ - cpu-map { - cluster0 { - core0 { - cpu = <&cpu_e0>; - }; - core1 { - cpu = <&cpu_e1>; - }; - core2 { - cpu = <&cpu_e2>; - }; - core3 { - cpu = <&cpu_e3>; - }; - }; - - cluster1 { - core0 { - cpu = <&cpu_p00>; - }; - core1 { - cpu = <&cpu_p01>; - }; - core2 { - cpu = <&cpu_p02>; - }; - core3 { - cpu = <&cpu_p03>; - }; - core4 { - cpu = <&cpu_p04>; - }; - }; - - cluster2 { - core0 { - cpu = <&cpu_p10>; - }; - core1 { - cpu = <&cpu_p11>; - }; - core2 { - cpu = <&cpu_p12>; - }; - core3 { - cpu = <&cpu_p13>; - }; - core4 { - cpu = <&cpu_p14>; - }; - }; - }; - - cpu_e0: cpu@0 { - compatible = "apple,brava-e"; - device_type = "cpu"; - reg = <0x0 0x0>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_e>; - operating-points-v2 = <&opp_e>; - capacity-dmips-mhz = <668>; - performance-domains = <&cpufreq_e>; - #cooling-cells = <2>; - }; - - cpu_e1: cpu@1 { - compatible = "apple,brava-e"; - device_type = "cpu"; - reg = <0x0 0x1>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_e>; - operating-points-v2 = <&opp_e>; - capacity-dmips-mhz = <668>; - performance-domains = <&cpufreq_e>; - #cooling-cells = <2>; - }; - - cpu_e2: cpu@2 { - compatible = "apple,brava-e"; - device_type = "cpu"; - reg = <0x0 0x2>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_e>; - operating-points-v2 = <&opp_e>; - capacity-dmips-mhz = <668>; - performance-domains = <&cpufreq_e>; - #cooling-cells = <2>; - }; - - cpu_e3: cpu@3 { - compatible = "apple,brava-e"; - device_type = "cpu"; - reg = <0x0 0x3>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_e>; - operating-points-v2 = <&opp_e>; - capacity-dmips-mhz = <668>; - performance-domains = <&cpufreq_e>; - #cooling-cells = <2>; - }; - - /* The boot CPU: the boot loader enters the kernel on it. */ - cpu_p00: cpu@10100 { - compatible = "apple,brava-p"; - device_type = "cpu"; - reg = <0x0 0x10100>; - next-level-cache = <&l2_cache_p0>; - operating-points-v2 = <&opp_p0>; - capacity-dmips-mhz = <1024>; - performance-domains = <&cpufreq_p0>; - #cooling-cells = <2>; - }; - - cpu_p01: cpu@10101 { - compatible = "apple,brava-p"; - device_type = "cpu"; - reg = <0x0 0x10101>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_p0>; - operating-points-v2 = <&opp_p0>; - capacity-dmips-mhz = <1024>; - performance-domains = <&cpufreq_p0>; - #cooling-cells = <2>; - }; - - cpu_p02: cpu@10102 { - compatible = "apple,brava-p"; - device_type = "cpu"; - reg = <0x0 0x10102>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_p0>; - operating-points-v2 = <&opp_p0>; - capacity-dmips-mhz = <1024>; - performance-domains = <&cpufreq_p0>; - #cooling-cells = <2>; - }; - - cpu_p03: cpu@10103 { - compatible = "apple,brava-p"; - device_type = "cpu"; - reg = <0x0 0x10103>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_p0>; - operating-points-v2 = <&opp_p0>; - capacity-dmips-mhz = <1024>; - performance-domains = <&cpufreq_p0>; - #cooling-cells = <2>; - }; - - cpu_p04: cpu@10104 { - compatible = "apple,brava-p"; - device_type = "cpu"; - reg = <0x0 0x10104>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_p0>; - operating-points-v2 = <&opp_p0>; - capacity-dmips-mhz = <1024>; - performance-domains = <&cpufreq_p0>; - #cooling-cells = <2>; - }; - - cpu_p10: cpu@10200 { - compatible = "apple,brava-p"; - device_type = "cpu"; - reg = <0x0 0x10200>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_p1>; - operating-points-v2 = <&opp_p1>; - capacity-dmips-mhz = <1024>; - performance-domains = <&cpufreq_p1>; - #cooling-cells = <2>; - }; - - cpu_p11: cpu@10201 { - compatible = "apple,brava-p"; - device_type = "cpu"; - reg = <0x0 0x10201>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_p1>; - operating-points-v2 = <&opp_p1>; - capacity-dmips-mhz = <1024>; - performance-domains = <&cpufreq_p1>; - #cooling-cells = <2>; - }; - - cpu_p12: cpu@10202 { - compatible = "apple,brava-p"; - device_type = "cpu"; - reg = <0x0 0x10202>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_p1>; - operating-points-v2 = <&opp_p1>; - capacity-dmips-mhz = <1024>; - performance-domains = <&cpufreq_p1>; - #cooling-cells = <2>; - }; - - cpu_p13: cpu@10203 { - compatible = "apple,brava-p"; - device_type = "cpu"; - reg = <0x0 0x10203>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_p1>; - operating-points-v2 = <&opp_p1>; - capacity-dmips-mhz = <1024>; - performance-domains = <&cpufreq_p1>; - #cooling-cells = <2>; - }; - - cpu_p14: cpu@10204 { - compatible = "apple,brava-p"; - device_type = "cpu"; - reg = <0x0 0x10204>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* To be filled by loader */ - next-level-cache = <&l2_cache_p1>; - operating-points-v2 = <&opp_p1>; - capacity-dmips-mhz = <1024>; - performance-domains = <&cpufreq_p1>; - #cooling-cells = <2>; - }; - }; - - l2_cache_e: l2-cache-cluster0 { - compatible = "cache"; - cache-level = <2>; - cache-unified; - cache-size = <0x400000>; - }; - - l2_cache_p0: l2-cache-cluster1 { - compatible = "cache"; - cache-level = <2>; - cache-unified; - cache-size = <0x1000000>; - }; - - l2_cache_p1: l2-cache-cluster2 { - compatible = "cache"; - cache-level = <2>; - cache-unified; - cache-size = <0x1000000>; - }; - - /* - * DVFS states from the ADT: /arm-io/pmgr voltage-states1-sram (E), - * voltage-states5-sram (P0) and voltage-states13-sram (P1), word 0 - * in kHz. opp-level is the hardware p-state. Each P cluster has its - * own table even though the frequencies are the same: opp-shared - * means one clock domain per table. - * - * opp-microwatt is the power of one busy core, measured on a J616s - * from the SMC core-rail meters (P0 PR0b, P1 PP0b, E PP2b) with the - * cluster pinned at each state. The P values follow a k * V^2 * f + c - * fit to the sweep, because the PMP's die-temperature limit clips the - * two top states within seconds. One busy E core does not register on - * its meter below 2352 MHz, so the E values are the idle cluster plus - * a quarter of the four-core increase. - */ - opp_e: opp-table-e { - compatible = "operating-points-v2"; - opp-shared; - - opp01 { - opp-hz = /bits/ 64 <1020000000>; - opp-level = <1>; - opp-microwatt = <81900>; - }; - opp02 { - opp-hz = /bits/ 64 <1404000000>; - opp-level = <2>; - opp-microwatt = <133100>; - }; - opp03 { - opp-hz = /bits/ 64 <1788000000>; - opp-level = <3>; - opp-microwatt = <209400>; - }; - opp04 { - opp-hz = /bits/ 64 <2112000000>; - opp-level = <4>; - opp-microwatt = <301400>; - }; - opp05 { - opp-hz = /bits/ 64 <2352000000>; - opp-level = <5>; - opp-microwatt = <383900>; - }; - opp06 { - opp-hz = /bits/ 64 <2532000000>; - opp-level = <6>; - opp-microwatt = <478500>; - }; - opp07 { - opp-hz = /bits/ 64 <2592000000>; - opp-level = <7>; - opp-microwatt = <531000>; - }; - }; - - opp_p0: opp-table-p0 { - compatible = "operating-points-v2"; - opp-shared; - - opp01 { - opp-hz = /bits/ 64 <1260000000>; - opp-level = <1>; - opp-microwatt = <513000>; - }; - opp02 { - opp-hz = /bits/ 64 <1512000000>; - opp-level = <2>; - opp-microwatt = <715000>; - }; - opp03 { - opp-hz = /bits/ 64 <1800000000>; - opp-level = <3>; - opp-microwatt = <907500>; - }; - opp04 { - opp-hz = /bits/ 64 <2088000000>; - opp-level = <4>; - opp-microwatt = <1158200>; - }; - opp05 { - opp-hz = /bits/ 64 <2352000000>; - opp-level = <5>; - opp-microwatt = <1494500>; - }; - opp06 { - opp-hz = /bits/ 64 <2616000000>; - opp-level = <6>; - opp-microwatt = <1782600>; - }; - opp07 { - opp-hz = /bits/ 64 <2868000000>; - opp-level = <7>; - opp-microwatt = <2209600>; - }; - opp08 { - opp-hz = /bits/ 64 <3096000000>; - opp-level = <8>; - opp-microwatt = <2636700>; - }; - opp09 { - opp-hz = /bits/ 64 <3300000000>; - opp-level = <9>; - opp-microwatt = <3247200>; - }; - opp10 { - opp-hz = /bits/ 64 <3468000000>; - opp-level = <10>; - opp-microwatt = <3668700>; - }; - opp11 { - opp-hz = /bits/ 64 <3624000000>; - opp-level = <11>; - opp-microwatt = <4128200>; - }; - opp12 { - opp-hz = /bits/ 64 <3756000000>; - opp-level = <12>; - opp-microwatt = <4819300>; - }; - opp13 { - opp-hz = /bits/ 64 <3852000000>; - opp-level = <13>; - opp-microwatt = <4977700>; - }; - opp14 { - opp-hz = /bits/ 64 <3924000000>; - opp-level = <14>; - opp-microwatt = <5315900>; - }; - opp15 { - opp-hz = /bits/ 64 <3996000000>; - opp-level = <15>; - opp-microwatt = <5575900>; - }; - opp16 { - opp-hz = /bits/ 64 <4044000000>; - opp-level = <16>; - opp-microwatt = <5773400>; - }; - opp17 { - opp-hz = /bits/ 64 <4104000000>; - opp-level = <17>; - opp-microwatt = <5969200>; - }; - opp18 { - opp-hz = /bits/ 64 <4416000000>; - opp-level = <18>; - opp-microwatt = <8274900>; - }; - opp19 { - opp-hz = /bits/ 64 <4512000000>; - opp-level = <19>; - opp-microwatt = <9256900>; - }; - }; - - opp_p1: opp-table-p1 { - compatible = "operating-points-v2"; - opp-shared; - - opp01 { - opp-hz = /bits/ 64 <1260000000>; - opp-level = <1>; - opp-microwatt = <561800>; - }; - opp02 { - opp-hz = /bits/ 64 <1512000000>; - opp-level = <2>; - opp-microwatt = <772500>; - }; - opp03 { - opp-hz = /bits/ 64 <1800000000>; - opp-level = <3>; - opp-microwatt = <988900>; - }; - opp04 { - opp-hz = /bits/ 64 <2088000000>; - opp-level = <4>; - opp-microwatt = <1302300>; - }; - opp05 { - opp-hz = /bits/ 64 <2352000000>; - opp-level = <5>; - opp-microwatt = <1644100>; - }; - opp06 { - opp-hz = /bits/ 64 <2616000000>; - opp-level = <6>; - opp-microwatt = <2003700>; - }; - opp07 { - opp-hz = /bits/ 64 <2868000000>; - opp-level = <7>; - opp-microwatt = <2349000>; - }; - opp08 { - opp-hz = /bits/ 64 <3096000000>; - opp-level = <8>; - opp-microwatt = <2723000>; - }; - opp09 { - opp-hz = /bits/ 64 <3300000000>; - opp-level = <9>; - opp-microwatt = <3333200>; - }; - opp10 { - opp-hz = /bits/ 64 <3468000000>; - opp-level = <10>; - opp-microwatt = <3711900>; - }; - opp11 { - opp-hz = /bits/ 64 <3624000000>; - opp-level = <11>; - opp-microwatt = <4129900>; - }; - opp12 { - opp-hz = /bits/ 64 <3756000000>; - opp-level = <12>; - opp-microwatt = <4666300>; - }; - opp13 { - opp-hz = /bits/ 64 <3852000000>; - opp-level = <13>; - opp-microwatt = <4881000>; - }; - opp14 { - opp-hz = /bits/ 64 <3924000000>; - opp-level = <14>; - opp-microwatt = <5176700>; - }; - opp15 { - opp-hz = /bits/ 64 <3996000000>; - opp-level = <15>; - opp-microwatt = <5306500>; - }; - opp16 { - opp-hz = /bits/ 64 <4044000000>; - opp-level = <16>; - opp-microwatt = <5618900>; - }; - opp17 { - opp-hz = /bits/ 64 <4104000000>; - opp-level = <17>; - opp-microwatt = <5843100>; - }; - opp18 { - opp-hz = /bits/ 64 <4416000000>; - opp-level = <18>; - opp-microwatt = <8075300>; - }; - opp19 { - opp-hz = /bits/ 64 <4512000000>; - opp-level = <19>; - opp-microwatt = <8949200>; - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupt-parent = <&aic>; - interrupt-names = "phys", "virt", "hyp-phys", "hyp-virt"; - interrupts = , - , - , - ; - }; - - pmu { - compatible = "apple,t6040-pmu"; - interrupt-parent = <&aic>; - /* The AIC raises both clusters' PMU FIQs as this one. */ - interrupts = ; - }; - - /* The 24 MHz reference clock (ADT clock-ids 4) of the I2C, PWM and watchdog blocks */ - clkref: clock-ref { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <24000000>; - clock-output-names = "clkref"; - }; - - /* - * Display component master. It has no registers; the boot loader - * enables it with the DCP when it hands the display over. - */ - display: display-subsystem { - compatible = "apple,display-subsystem"; - iommus = <&disp0_dart 0>; - status = "disabled"; - }; - - cpufreq_e: cpufreq@210e20000 { - compatible = "apple,t6041-cluster-cpufreq", "apple,t8112-cluster-cpufreq"; - reg = <0x2 0x10e20000 0x0 0x1000>; - nonposted-mmio; - #performance-domain-cells = <0>; - /* PMP fast die-temperature effort, byte 0 of FAST-DIE-CE */ - apple,fast-die-effort = <&pmp_report 0>; - }; - - cpufreq_p0: cpufreq@211e20000 { - compatible = "apple,t6041-cluster-cpufreq", "apple,t8112-cluster-cpufreq"; - reg = <0x2 0x11e20000 0x0 0x1000>; - nonposted-mmio; - #performance-domain-cells = <0>; - apple,fast-die-effort = <&pmp_report 1>; - }; - - cpufreq_p1: cpufreq@212e20000 { - compatible = "apple,t6041-cluster-cpufreq", "apple,t8112-cluster-cpufreq"; - reg = <0x2 0x12e20000 0x0 0x1000>; - nonposted-mmio; - #performance-domain-cells = <0>; - apple,fast-die-effort = <&pmp_report 2>; - }; - - /* - * System level cache planes: four AMCCs with four planes each. - * Allocation waits for the display, which takes over the scan-out DMA - * the boot loader left running. - */ - mcc: memory-controller@220000000 { - compatible = "apple,t6041-mcc", "apple,t8140-mcc"; - reg = <0x2 0x20000000 0x0 0x4000>, - <0x2 0x20040000 0x0 0x4000>, - <0x2 0x20080000 0x0 0x4000>, - <0x2 0x200c0000 0x0 0x4000>, - <0x2 0x22000000 0x0 0x4000>, - <0x2 0x22040000 0x0 0x4000>, - <0x2 0x22080000 0x0 0x4000>, - <0x2 0x220c0000 0x0 0x4000>, - <0x2 0x24000000 0x0 0x4000>, - <0x2 0x24040000 0x0 0x4000>, - <0x2 0x24080000 0x0 0x4000>, - <0x2 0x240c0000 0x0 0x4000>, - <0x2 0x26000000 0x0 0x4000>, - <0x2 0x26040000 0x0 0x4000>, - <0x2 0x26080000 0x0 0x4000>, - <0x2 0x260c0000 0x0 0x4000>; - nonposted-mmio; - apple,boot-dma-devices = <&display>; - status = "disabled"; - }; - - /* - * The decoder firmware programs the T8122/T8132 register family, so - * the driver binds through its T8132 entry. The ADT gives the whole - * block (0x2_80000000, 0x1404000); the windows follow the T6030/T8140 - * layout, with the CM3 SRAM between its code and the mailbox. - */ - avd: avd@280000000 { - compatible = "apple,t6041-avd", "apple,t8132-avd"; - reg = <0x2 0x81080000 0x0 0x14000>, - <0x2 0x81094000 0x0 0x14000>, - <0x2 0x810a8000 0x0 0x4000>, - <0x2 0x81100000 0x0 0x10000>; - reg-names = "code", "sram", "mbox", "ctrl"; - interrupt-parent = <&aic>; - interrupts = , - ; - power-domains = <&ps_avd_sys>, <&pmc_soc_max>; - power-domain-names = "core", "perf"; - resets = <&ps_avd_sys>; - iommus = <&avd_dart 0>; - }; - - avd_dart: iommu@281020000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x2 0x81020000 0x0 0xc000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_avd_sys>; - }; - - /* Named after its sgx range: the coprocessor range is the mailbox node's too. */ - gpu: gpu@288000000 { - compatible = "apple,agx-t6040"; - reg = <0x2 0x8a600000 0x0 0x88000>, - <0x2 0x88000000 0x0 0x3758000>; - reg-names = "asc", "sgx"; - mboxes = <&gfx_mbox>; - power-domains = <&pmp_gfx>; - apple,clpc = <&clpc>; - status = "disabled"; - }; - - pmgr_gfx: power-management@288e80000 { - compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0x2 0x88e80000 0x0 0x4000>; - /* child nodes are added in t6040-pmgr.dtsi */ - }; - - gfx_mbox: mailbox@28a600000 { - compatible = "apple,t6040-ascwrap-v6"; - reg = <0x2 0x8a600000 0x0 0x88000>, - <0x2 0x8a050000 0x0 0x8>; - reg-names = "wrapper", "iop-vbar"; - interrupt-parent = <&aic>; - interrupts = , - ; - interrupt-names = "send-empty", "recv-not-empty"; - apple,firmware-role = "GFX"; - power-domains = <&ps_gfx>; - #mbox-cells = <0>; - status = "disabled"; - }; - - disp0_dart: iommu@402300000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x02300000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x10 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - dcp_dart: iommu@402340000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x02340000 0x0 0x20000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x10 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - dcp: dcp@402e00000 { - compatible = "apple,t6041-dcp", "apple,dcp"; - reg = <0x4 0x02e00000 0x0 0x4000>, - <0x4 0x00000000 0x0 0x4000000>, - <0x4 0x02240000 0x0 0x10000>, - <0x4 0x023a8000 0x0 0x4000>, - <0x4 0x02800000 0x0 0x800000>; - reg-names = "coproc", "disp-0", "disp-1", "disp-2", "disp-3"; - mboxes = <&dcp_mbox>; - mbox-names = "mbox"; - iommus = <&dcp_dart 23>; - apple,bw-scratch = <&pmgr_dcp 0 4 0x20000>; - apple,iomfb-surfaces = <1 1 0 0>; - /* the boot loader describes the piodma's regions with 2+2 cells */ - #address-cells = <2>; - #size-cells = <2>; - /* enabled once the boot loader has handed the display over */ - status = "disabled"; - - disp0_piodma: piodma { - iommus = <&disp0_dart 16>; - }; - }; - - dcp_mbox: mailbox@402e08000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x4 0x02e08000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - status = "disabled"; - }; - - /* - * iBoot hands over a running SEP. Keep Linux off its DART at boot; - * apple_sep enables it when the driver binds. The SEP only accepts - * IOVAs in the window iBoot programmed (ADT vm-base 0x10000004000, - * vm-size 0x3ff00000), which carries the BIT(40) alias the DART - * translates. - */ - sep_dart: iommu@404c80000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x04c80000 0x0 0x20000>; - interrupt-parent = <&aic>; - interrupts = ; - #iommu-cells = <1>; - apple,dma-range = /bits/ 64 <0x10000004000 0x3ff00000>; - apple,dma-offset = /bits/ 64 <0x0>; - status = "disabled"; - }; - - sep: sep@406600000 { - compatible = "apple,sep"; - reg = <0x4 0x06600000 0x0 0x88000>; - mboxes = <&sep_mbox>; - mbox-names = "mbox"; - iommus = <&sep_dart 0>; - power-domains = <&ps_sep>; - status = "disabled"; - }; - - sep_mbox: mailbox@406608000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x4 0x06608000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - status = "disabled"; - }; - - ans_mbox: mailbox@409608000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x4 0x09608000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - power-domains = <&ps_ans>; - #mbox-cells = <0>; - status = "disabled"; - }; - - ans_sart: sart@40dc50000 { - compatible = "apple,t6041-sart", "apple,t6000-sart"; - reg = <0x4 0x0dc50000 0x0 0xc000>; - power-domains = <&ps_ans>; - status = "disabled"; - }; - - pcie_dart: iommu@410000000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x10000000 0x0 0x20000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - /* iBoot leaves the I2C gates on and the pins muxed to I2C. */ - i2c1: i2c@429014000 { - compatible = "apple,t6041-i2c", "apple,t8103-i2c"; - reg = <0x4 0x29014000 0x0 0x4000>; - clocks = <&clkref>; - interrupt-parent = <&aic>; - interrupts = ; - pinctrl-0 = <&i2c1_pins>; - pinctrl-names = "default"; - power-domains = <&ps_i2c1>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c2: i2c@429018000 { - compatible = "apple,t6041-i2c", "apple,t8103-i2c"; - reg = <0x4 0x29018000 0x0 0x4000>; - clocks = <&clkref>; - interrupt-parent = <&aic>; - interrupts = ; - pinctrl-0 = <&i2c2_pins>; - pinctrl-names = "default"; - power-domains = <&ps_i2c2>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c3: i2c@42901c000 { - compatible = "apple,t6041-i2c", "apple,t8103-i2c"; - reg = <0x4 0x2901c000 0x0 0x4000>; - clocks = <&clkref>; - interrupt-parent = <&aic>; - interrupts = ; - pinctrl-0 = <&i2c3_pins>; - pinctrl-names = "default"; - power-domains = <&ps_i2c3>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c4: i2c@429020000 { - compatible = "apple,t6041-i2c", "apple,t8103-i2c"; - reg = <0x4 0x29020000 0x0 0x4000>; - clocks = <&clkref>; - interrupt-parent = <&aic>; - interrupts = ; - pinctrl-0 = <&i2c4_pins>; - pinctrl-names = "default"; - power-domains = <&ps_i2c4>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c6: i2c@429028000 { - compatible = "apple,t6041-i2c", "apple,t8103-i2c"; - reg = <0x4 0x29028000 0x0 0x4000>; - clocks = <&clkref>; - interrupt-parent = <&aic>; - interrupts = ; - pinctrl-0 = <&i2c6_pins>; - pinctrl-names = "default"; - power-domains = <&ps_i2c6>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c8: i2c@429030000 { - compatible = "apple,t6041-i2c", "apple,t8103-i2c"; - reg = <0x4 0x29030000 0x0 0x4000>; - clocks = <&clkref>; - interrupt-parent = <&aic>; - interrupts = ; - pinctrl-0 = <&i2c8_pins>; - pinctrl-names = "default"; - power-domains = <&ps_i2c8>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - fpwm0: pwm@429040000 { - compatible = "apple,t6041-fpwm", "apple,s5l-fpwm"; - reg = <0x4 0x29040000 0x0 0x4000>; - clocks = <&clkref>; - power-domains = <&ps_fpwm0>; - #pwm-cells = <2>; - status = "disabled"; - }; - - /* - * Touch ID. iBoot leaves the pads muxed and the controller uses its - * native chip select, so there is no pinctrl here. - */ - spi2: spi@429108000 { - compatible = "apple,t6041-spi", "apple,t8103-spi"; - reg = <0x4 0x29108000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = ; - clocks = <&clkref>; - power-domains = <&ps_spi2>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - - mesa: fingerprint@0 { - compatible = "apple,mesa-fingerprint"; - reg = <0>; - spi-max-frequency = <8000000>; - spi-cpol; - status = "disabled"; - }; - }; - - nvme: nvme@44dcc0000 { - compatible = "apple,t6041-nvme-ans2"; - reg = <0x4 0x4dcc0000 0x0 0x10000>, - <0x4 0x09600000 0x0 0x4000>, - <0x4 0x0dcc0000 0x0 0x60000>; - reg-names = "nvme", "ans", "nvmmu"; - interrupt-parent = <&aic>; - interrupts = ; - mboxes = <&ans_mbox>; - apple,sart = <&ans_sart>; - power-domains = <&ps_ans>, <&ps_apcie_sys_st0>, - <&ps_apcie_sys_st1>; - power-domain-names = "ans", "apcie0", "apcie1"; - resets = <&ps_ans>; - status = "disabled"; - }; - - /* - * PMP (power management coprocessor). iBoot locks its DART (PROTECT - * 0x1e7, SIDs 0 and 1 translating): apple-dart adopts iBoot's SID 0 - * table and leaves SID 1 alone. apple,dma-range keeps Linux's IOVAs - * in the ADT window (vm-base 0x100_0000_0000, 64 GiB). The DART's - * second ADT range is the SoC's shared clock-protection block, not - * part of the DART. - */ - pmp_dart: iommu@500300000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x5 0x00300000 0x0 0xc000>; - interrupt-parent = <&aic>; - interrupts = ; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x10 0x0>; - power-domains = <&ps_pmp>; - status = "disabled"; - }; - - /* - * Report (PTD) region: reads 16 bytes per entry at +0x0, writes 8 - * bytes per entry at +0x10000. Entries are PMP soc-devices; every - * entry reads 0 while the PMP is stopped. - */ - pmp_report: pmp-report@5003c0000 { - compatible = "apple,t6041-pmp-v2-report"; - reg = <0x5 0x003c0000 0x0 0x20000>; - nonposted-mmio; - power-domains = <&ps_pms_sram>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - - /* The CPU clusters, for their fast die-temperature loops */ - report@a { - compatible = "apple,t6041-pmp-v2-report-entry", - "apple,t6000-pmp-v2-report-entry"; - reg = <0xa>; - label = "pmp-eacc0"; - #power-domain-cells = <0>; - apple,always-on; - }; - - report@b { - compatible = "apple,t6041-pmp-v2-report-entry", - "apple,t6000-pmp-v2-report-entry"; - reg = <0xb>; - label = "pmp-pacc0"; - #power-domain-cells = <0>; - apple,always-on; - }; - - report@c { - compatible = "apple,t6041-pmp-v2-report-entry", - "apple,t6000-pmp-v2-report-entry"; - reg = <0xc>; - label = "pmp-pacc1"; - #power-domain-cells = <0>; - apple,always-on; - }; - - /* - * The GPU (soc-device 13). Without it the running PMP treats - * the GPU as off and holds it at its lowest state, but claiming - * it while nothing powers the GPU crashes the PMP firmware - * (SError) right after it starts. It sits on the GPU's own - * power state. The GPU consumer takes this domain, so the request - * follows the GFX domain's power lifetime. - */ - pmp_gfx: report@d { - compatible = "apple,t6041-pmp-v2-report-entry", - "apple,t6000-pmp-v2-report-entry"; - reg = <0xd>; - label = "pmp-gfx"; - #power-domain-cells = <0>; - power-domains = <&ps_gfx>; - }; - }; - - /* - * The boot loader adds the per-unit properties (board, DRAM) and the - * firmware tunables the driver needs before it starts the PMP. - */ - pmp: pmp@500700000 { - compatible = "apple,t6041-pmp-v2", "apple,t6000-pmp-v2"; - reg = <0x5 0x00700000 0x0 0xe0000>, - <0x5 0x00e00000 0x0 0x4000>; - reg-names = "pmp", "asc"; - mboxes = <&pmp_mbox>; - mbox-names = "mbox"; - iommus = <&pmp_dart 0>; - power-domains = <&ps_pmp>; - apple,pmc = <1>; - apple,pmc-pmgr = <0x3f>; - status = "disabled"; - }; - - pmp_mbox: mailbox@500e08000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x5 0x00e08000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - power-domains = <&ps_pmp>, <&ps_pms_sram>; - #mbox-cells = <0>; - status = "disabled"; - }; - - pmgr: power-management@502280000 { - compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0x5 0x02280000 0x0 0x4000>; - /* child nodes are added in t6040-pmgr.dtsi */ - }; - - pmgr_ane: power-management@50228c000 { - compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; - reg = <0x5 0x0228c000 0x0 0x4000>; - #address-cells = <1>; - #size-cells = <1>; - }; - - pmgr_disp: power-management@502290000 { - compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; - reg = <0x5 0x02290000 0x0 0x4000>; - #address-cells = <1>; - #size-cells = <1>; - }; - - pmgr_venc: power-management@502808000 { - compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; - reg = <0x5 0x02808000 0x0 0x4000>; - #address-cells = <1>; - #size-cells = <1>; - }; - - pmgr_isp: power-management@502284000 { - compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0x5 0x02284000 0x0 0x4000>; - /* child nodes are added in t6040-pmgr.dtsi */ - }; - - aic: interrupt-controller@502400000 { - compatible = "apple,t6041-aic3", "apple,t8122-aic3"; - #interrupt-cells = <3>; - interrupt-controller; - reg = <0x5 0x02400000 0x0 0x184000>, - <0x5 0x02440000 0x0 0x4>; - reg-names = "core", "event"; - }; - - pmgr_aux: power-management@502800000 { - compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0x5 0x02800000 0x0 0x4000>; - /* child nodes are added in t6040-pmgr.dtsi */ - }; - - /* - * The PMGR range the DCP driver hands to its firmware; apple,bw-scratch - * points into it. - */ - pmgr_dcp: power-management@504800000 { - reg = <0x5 0x04800000 0x0 0xbc000>; - reg-names = "dcp-fw-pmgr"; - #apple,bw-scratch-cells = <3>; - }; - - /* - * PMC voter interface: the floor word of agent a at "voters" + - * 0x4000 * a, the floors the PMC honours and the rail enable words - * at "rails". Both lie inside pmgr_dcp's range, which the DCP driver - * only hands to its firmware, so the two do not conflict; "rails" - * comes first so that this node's unit address differs from - * pmgr_dcp's. - * Static voters are the PMP (0), CLPC (1) and AP (3). The PMP votes - * the DCS and fabric for memory clients other than the CPUs, the GPU - * among them; without its agent, GPU work runs at a low DCS - * state unless a CPU is busy. iBoot leaves the PMP's floor at the top - * DCS state, so its agent must stay off while the PMP does not run: - * apple,pmp holds off the PMC until the PMP driver has bound, and - * unbinds the PMC first. - */ - pmc: power-management@5048aa000 { - compatible = "apple,t6041-pmc"; - reg = <0x5 0x048aa000 0x0 0x3000>, - <0x5 0x04800000 0x0 0x10000>; - reg-names = "rails", "voters"; - nonposted-mmio; - #address-cells = <1>; - #size-cells = <0>; - apple,pmp = <&pmp>; - apple,static-voters = <0 1 3>; - status = "disabled"; - - clpc: performance-controller@1 { - compatible = "apple,t6041-clpc"; - reg = <1>; - - }; - - /* - * The SoC rail at its highest state. The video encoder runs on - * the fabric clock and encodes at less than half speed below it. - */ - pmc_soc_max: floor-soc-max { - label = "soc-max"; - #power-domain-cells = <0>; - apple,rail = <1>; - apple,level = <2>; - }; - }; - - /* - * The always-on GPIO bank (ADT /arm-io/nub-gpio0, 61 pins). Its power - * state is in the always-on PMGR. - */ - pinctrl_nub: pinctrl@5081e4000 { - compatible = "apple,t6041-pinctrl", "apple,t8103-pinctrl"; - reg = <0x5 0x081e4000 0x0 0x4000>; - power-domains = <&ps_nub_gpio>; - - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&pinctrl_nub 0 0 61>; - apple,npins = <61>; - - interrupt-controller; - #interrupt-cells = <2>; - interrupt-parent = <&aic>; - interrupts = , - , - , - , - , - , - ; - status = "disabled"; - }; - - pmgr_mini: power-management@508300000 { - compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0x5 0x08300000 0x0 0x4000>; - /* child nodes are added in t6040-pmgr.dtsi */ - }; - - /* - * The driver arms the reset only when userspace opens /dev/watchdog - * or the firmware left it running; it also provides restart. - */ - wdt: watchdog@50836c000 { - compatible = "apple,t6041-wdt", "apple,t8103-wdt"; - reg = <0x5 0x0836c000 0x0 0x4000>; - clocks = <&clkref>; - interrupt-parent = <&aic>; - interrupts = ; - }; - - nub_spmi0: spmi@509014000 { - compatible = "apple,t6041-spmi", "apple,t8103-spmi"; - reg = <0x5 0x09014000 0x0 0x100>; - #address-cells = <2>; - #size-cells = <0>; - #interrupt-cells = <2>; - interrupt-controller; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - - pmic@e { - compatible = "apple,abbey-pmic", "apple,spmi-nvmem"; - reg = <0xe SPMI_USID>; - - pmu_rtc: rtc { - compatible = "apple,t6041-pmu-rtc"; - interrupt-parent = <&nub_spmi0>; - interrupts = <2 IRQ_TYPE_EDGE_RISING>; - nvmem-cells = <&rtc_offset>; - nvmem-cell-names = "rtc_offset"; - wakeup-source; - }; - - nvmem-layout { - compatible = "fixed-layout"; - #address-cells = <1>; - #size-cells = <1>; - - rtc_offset: rtc-offset@2100 { - reg = <0x2100 0x6>; - }; - - boot_stage: boot-stage@f801 { - reg = <0xf801 0x1>; - }; - - boot_error_count: boot-error-count@f802,0 { - reg = <0xf802 0x1>; - bits = <0 4>; - }; - - panic_count: panic-count@f802,4 { - reg = <0xf802 0x1>; - bits = <4 4>; - }; - - shutdown_flag: shutdown-flag@f80f,3 { - reg = <0xf80f 0x1>; - bits = <3 1>; - }; - }; - }; - }; - - smc: smc@50c600000 { - compatible = "apple,t6041-smc", "apple,t8103-smc"; - reg = <0x5 0x0c600000 0x0 0x4000>, - <0x5 0x0de70000 0x0 0x100000>; - reg-names = "smc", "sram"; - mboxes = <&smc_mbox>; - status = "disabled"; - - smc_gpio: gpio { - compatible = "apple,smc-gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - - smc_hwmon: hwmon { - compatible = "apple,smc-hwmon"; - #thermal-sensor-cells = <1>; - }; - - smc_reboot: reboot { - compatible = "apple,smc-reboot"; - nvmem-cells = <&shutdown_flag>, <&boot_stage>, - <&boot_error_count>, <&panic_count>; - nvmem-cell-names = "shutdown_flag", "boot_stage", - "boot_error_count", "panic_count"; - }; - - smc_rtc: rtc { - compatible = "apple,smc-rtc"; - nvmem-cells = <&rtc_offset>; - nvmem-cell-names = "rtc_offset"; - }; - }; - - smc_mbox: mailbox@50c608000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x5 0x0c608000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - status = "disabled"; - }; - - /* - * AOP (always-on processor). The boot loader loads its RTKit firmware - * and leaves it stopped; Linux starts it. - */ - aop: aop@510600000 { - compatible = "apple,t6041-aop"; - reg = <0x5 0x10c10000 0x0 0x2e0000>, - <0x5 0x10600000 0x0 0x88000>, - <0x5 0x10050000 0x0 0x4000>, - <0x5 0x08328000 0x0 0x24>; - reg-names = "firmware", "asc", "asc-aux", "config"; - mboxes = <&aop_mbox>; - mbox-names = "mbox"; - iommus = <&aop_dart 0>; - status = "disabled"; - - /* - * "dma" is the microphones' LEAP ADMAC channel; "spkr" and - * "sense" are the speaker stream's base-ns ADMAC channels 0 and - * 1 (ADT audio-speaker dma-channels), "cout" and "cin" the - * headphone jack's channels 4 and 5 (TX2 and RX2, ADT - * audio-codec-output and audio-codec-input). - */ - aop_audio: audio { - compatible = "apple,t6041-aop-audio", "apple,t6030-aop-audio"; - dmas = <&admac0 1>, <&admac1 0>, <&admac1 1>, <&admac1 4>, - <&admac1 5>; - dma-names = "dma", "spkr", "sense", "cout", "cin"; - #sound-dai-cells = <1>; - }; - - aop_als: als { - compatible = "apple,t6041-aop-als", "apple,aop-als"; - }; - - aop_las: las { - compatible = "apple,t6041-aop-las", "apple,aop-las"; - }; - - /* The calibration properties come from the bootloader. */ - aop_accel: accel { - compatible = "apple,t6041-aop-accel", "apple,aop-accel"; - }; - - aop_gyro: gyro { - compatible = "apple,t6041-aop-gyro", "apple,aop-gyro"; - }; - }; - - /* ADT lists the interrupts as 1, 0, 3, 2 of the block: send-empty is the lowest. */ - aop_mbox: mailbox@510608000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x5 0x10608000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - status = "disabled"; - }; - - aop_dart: iommu@510f00000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x5 0x10f00000 0x0 0xc000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - /* The audio fabric's ADMACs: admac-leap-ns (DART stream 10) and admac-base-ns (stream 8) */ - admac0: dma-controller@513300000 { - compatible = "apple,t6041-admac", "apple,t8132-admac"; - reg = <0x5 0x13300000 0x0 0x34000>; - #dma-cells = <1>; - dma-channels = <18>; - /* the ADT gives the first of the four outputs */ - interrupts-extended = <&aic AIC_IRQ 757 IRQ_TYPE_LEVEL_HIGH>, - <0>, <0>, <0>; - iommus = <&aop_dart 10>; - status = "disabled"; - }; - - admac1: dma-controller@513800000 { - compatible = "apple,t6041-admac", "apple,t8132-admac"; - reg = <0x5 0x13800000 0x0 0x34000>; - #dma-cells = <1>; - dma-channels = <13>; - /* the ADT gives the first of the four outputs */ - interrupts-extended = <&aic AIC_IRQ 754 IRQ_TYPE_LEVEL_HIGH>, - <0>, <0>, <0>; - iommus = <&aop_dart 8>; - status = "disabled"; - }; - - mtp: mtp@514600000 { - compatible = "apple,t6041-mtp", "apple,t6041-rtk-helper-asc4", - "apple,mtp", "apple,rtk-helper-asc4"; - reg = <0x5 0x14600000 0x0 0x4000>; - reg-names = "asc"; - mboxes = <&mtp_mbox>; - iommus = <&mtp_dart 0>; - #helper-cells = <0>; - status = "disabled"; - }; - - mtp_mbox: mailbox@514608000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x5 0x14608000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - status = "disabled"; - }; - - mtp_dart: iommu@514800000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x5 0x14800000 0x0 0xc000>; - interrupt-parent = <&aic>; - interrupts = ; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; - /* ADT "remap": streams 1 2 3 are stream 0 */ - apple,remap-streams = <1 0>, <2 0>, <3 0>; - status = "disabled"; - }; - - mtp_dockchannel: fifo@514b14000 { - compatible = "apple,t6041-dockchannel", "apple,dockchannel"; - reg = <0x5 0x14b14000 0x0 0x1000>; - reg-names = "irq"; - interrupt-parent = <&aic>; - interrupts = ; - - ranges = <0x0 0x5 0x14b28000 0x10000>; - nonposted-mmio; - #address-cells = <1>; - #size-cells = <1>; - - interrupt-controller; - #interrupt-cells = <2>; - status = "disabled"; - - mtp_hid: input@0 { - compatible = "apple,t6041-dockchannel-hid", "apple,dockchannel-hid"; - reg = <0x0000 0x1000>, - <0x4000 0x1000>, - <0x8000 0x1000>, - <0xc000 0x1000>; - reg-names = "rmt-config", "rmt-data", "config", "data"; - iommus = <&mtp_dart 0>; - interrupt-parent = <&mtp_dockchannel>; - interrupts = <2 IRQ_TYPE_LEVEL_HIGH>, - <3 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "tx", "rx"; - apple,fifo-size = <0x800>; - apple,helper-cpu = <&mtp>; - }; - }; - - pinctrl: pinctrl@51c000000 { - compatible = "apple,t6041-pinctrl", "apple,t8103-pinctrl"; - reg = <0x5 0x1c000000 0x0 0x4000>; - - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&pinctrl 0 0 200>; - apple,npins = <200>; - - interrupt-controller; - #interrupt-cells = <2>; - interrupt-parent = <&aic>; - interrupts = , - , - , - , - , - , - ; - status = "disabled"; - - /* I2C is function 1 (ADT gpio-iic_scl/sda) */ - i2c1_pins: i2c1-pins { - pinmux = , - ; - }; - - i2c2_pins: i2c2-pins { - pinmux = , - ; - }; - - i2c3_pins: i2c3-pins { - pinmux = , - ; - }; - - i2c4_pins: i2c4-pins { - pinmux = , - ; - }; - - i2c6_pins: i2c6-pins { - pinmux = , - ; - }; - - i2c8_pins: i2c8-pins { - pinmux = , - ; - }; - }; - - /* - * ISP (ADT isp0, firmware loaded by iBoot). "coproc" is the - * coprocessor up to its control block; "mbox", "gpio" and "mbox2" are - * the interrupt words, the firmware handshake words and the doorbell - * of its mailbox at +0x2924000. The first of the ADT's four - * interrupts carries the mailbox. - */ - isp: isp@580000000 { - compatible = "apple,t6041-isp", "apple,isp"; - reg = <0x5 0x80000000 0x0 0x1604000>, - <0x5 0x82924000 0x0 0x40>, - <0x5 0x829241d0 0x0 0x20>, - <0x5 0x82924464 0x0 0x10>; - reg-names = "coproc", "mbox", "gpio", "mbox2"; - interrupt-parent = <&aic>; - interrupts = ; - iommus = <&isp_dart0 0>, <&isp_dart1 0>, <&isp_dart2 0>; - power-domains = <&ps_isp_sys>, <&ps_isp_cpu>, <&ps_isp_fe>, - <&ps_isp_dprx>, <&ps_isp_secure>, <&ps_isp_be>, - <&ps_isp_clr>, <&ps_ispsens0>; - /* the shared memory window above the firmware's 32 MiB */ - apple,dart-vm-size = /bits/ 64 <0xde600000>; - status = "disabled"; - }; - - /* - * ADT dart-isp0: three instances on one interrupt; ADT "remap": streams - * 1, 6, 7, 10 and 11 are stream 0. - */ - isp_dart0: iommu@5828c0000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x5 0x828c0000 0x0 0xc000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_isp_sys>; - apple,remap-streams = <1 0>, <6 0>, <7 0>, <10 0>, <11 0>; - status = "disabled"; - }; - - isp_dart1: iommu@5828e0000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x5 0x828e0000 0x0 0xc000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_isp_sys>; - apple,remap-streams = <1 0>, <6 0>, <7 0>, <10 0>, <11 0>; - status = "disabled"; - }; - - isp_dart2: iommu@582900000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x5 0x82900000 0x0 0xc000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_isp_sys>; - apple,remap-streams = <1 0>, <6 0>, <7 0>, <10 0>, <11 0>; - status = "disabled"; - }; - - /* - * The three Type-C ports (ADT usb-drdN, atc-phyN, dart-usbN, - * acio-phy-cpuN) and the SPMI buses of their PD controllers. - */ - nub_spmi_a0: spmi@509188000 { - compatible = "apple,t6041-spmi", "apple,t8103-spmi"; - reg = <0x5 0x09188000 0x0 0x100>; - #address-cells = <2>; - #size-cells = <0>; - #interrupt-cells = <2>; - interrupt-controller; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_nub_spmi_a0>; - status = "disabled"; - }; - - nub_spmi_a1: spmi@509198000 { - compatible = "apple,t6041-spmi", "apple,t8103-spmi"; - reg = <0x5 0x09198000 0x0 0x100>; - #address-cells = <2>; - #size-cells = <0>; - #interrupt-cells = <2>; - interrupt-controller; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_nub_spmi_a1>; - status = "disabled"; - }; - - atcphy0: phy@382a90000 { - compatible = "apple,t6040-atcphy"; - reg = <0x3 0x82a90000 0x0 0x4000>, - <0x3 0x82800000 0x0 0x4000>, - <0x3 0x82a84000 0x0 0x4000>, - <0x3 0x83000000 0x0 0x30000>, - <0x3 0x83200000 0x0 0x4000>, - <0x3 0x83140000 0x0 0x4000>, - <0x3 0x830c0000 0x0 0x10000>, - <0x3 0x80000000 0x0 0x8000>, - <0x3 0x80020000 0x0 0x4000>, - <0x3 0x83244000 0x0 0x4000>, - <0x3 0x83250000 0x0 0x4000>; - reg-names = "bank0", "bank1", "pipehandler", "core", "cfg", "cpu", - "cpu-data", "axi2af", "axi2af-lioa", "fabric", "common-cfg"; - #phy-cells = <1>; - #reset-cells = <0>; - power-domains = <&ps_atc0_common_dp>; - mboxes = <&atcphy0_mbox>; - mbox-names = "phy-cpu"; - nonposted-mmio; - orientation-switch; - status = "disabled"; - }; - - atcphy0_mbox: mailbox@383148000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x3 0x83148000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - power-domains = <&ps_atc0_phymxwrap>; - status = "disabled"; - }; - - usb_drd0_dart_0: iommu@382f00000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x82f00000 0x0 0xc000>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_atc0_usb>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; - status = "disabled"; - }; +#include "t604x.dtsi" - usb_drd0_dart_1: iommu@382f80000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x82f80000 0x0 0xc000>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_atc0_usb>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; - status = "disabled"; - }; - - usb_drd0: usb@382280000 { - compatible = "apple,t6040-dwc3", "apple,t8103-dwc3"; - reg = <0x3 0x82280000 0x0 0xcd00>, - <0x3 0x8228cd00 0x0 0x3200>, - <0x3 0x82200000 0x0 0x4000>; - reg-names = "dwc3-core", "dwc3-apple", "drd-cfg"; - interrupt-parent = <&aic>; - interrupts = ; - /* - * A role switch rather than a fixed host: the PD controller - * resets the eUSB2 repeater on every connect, so the PHY and - * the core start after the attach and stop on detach. - */ - dr_mode = "otg"; - usb-role-switch; - role-switch-default-mode = "host"; - iommus = <&usb_drd0_dart_0 0>, <&usb_drd0_dart_1 1>; - power-domains = <&ps_atc0_usb>; - resets = <&atcphy0>; - phys = <&atcphy0 PHY_TYPE_USB2>, <&atcphy0 PHY_TYPE_USB3>; - phy-names = "usb2-phy", "usb3-phy"; - status = "disabled"; - }; - - atcphy1: phy@38aa90000 { - compatible = "apple,t6040-atcphy"; - reg = <0x3 0x8aa90000 0x0 0x4000>, - <0x3 0x8a800000 0x0 0x4000>, - <0x3 0x8aa84000 0x0 0x4000>, - <0x3 0x8b000000 0x0 0x30000>, - <0x3 0x8b200000 0x0 0x4000>, - <0x3 0x8b140000 0x0 0x4000>, - <0x3 0x8b0c0000 0x0 0x10000>, - <0x3 0x88000000 0x0 0x8000>, - <0x3 0x88020000 0x0 0x4000>, - <0x3 0x8b244000 0x0 0x4000>, - <0x3 0x8b250000 0x0 0x4000>; - reg-names = "bank0", "bank1", "pipehandler", "core", "cfg", "cpu", - "cpu-data", "axi2af", "axi2af-lioa", "fabric", "common-cfg"; - #phy-cells = <1>; - #reset-cells = <0>; - power-domains = <&ps_atc1_common_dp>; - mboxes = <&atcphy1_mbox>; - mbox-names = "phy-cpu"; - nonposted-mmio; - orientation-switch; - status = "disabled"; - }; - - atcphy1_mbox: mailbox@38b148000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x3 0x8b148000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - power-domains = <&ps_atc1_phymxwrap>; - status = "disabled"; - }; - - usb_drd1_dart_0: iommu@38af00000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x8af00000 0x0 0xc000>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_atc1_usb>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; - status = "disabled"; - }; - - usb_drd1_dart_1: iommu@38af80000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x8af80000 0x0 0xc000>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_atc1_usb>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; - status = "disabled"; - }; - - usb_drd1: usb@38a280000 { - compatible = "apple,t6040-dwc3", "apple,t8103-dwc3"; - reg = <0x3 0x8a280000 0x0 0xcd00>, - <0x3 0x8a28cd00 0x0 0x3200>, - <0x3 0x8a200000 0x0 0x4000>; - reg-names = "dwc3-core", "dwc3-apple", "drd-cfg"; - interrupt-parent = <&aic>; - interrupts = ; - /* - * A role switch rather than a fixed host: the PD controller - * resets the eUSB2 repeater on every connect, so the PHY and - * the core start after the attach and stop on detach. - */ - dr_mode = "otg"; - usb-role-switch; - role-switch-default-mode = "host"; - iommus = <&usb_drd1_dart_0 0>, <&usb_drd1_dart_1 1>; - power-domains = <&ps_atc1_usb>; - resets = <&atcphy1>; - phys = <&atcphy1 PHY_TYPE_USB2>, <&atcphy1 PHY_TYPE_USB3>; - phy-names = "usb2-phy", "usb3-phy"; - status = "disabled"; - }; - - atcphy2: phy@392a90000 { - compatible = "apple,t6040-atcphy"; - reg = <0x3 0x92a90000 0x0 0x4000>, - <0x3 0x92800000 0x0 0x4000>, - <0x3 0x92a84000 0x0 0x4000>, - <0x3 0x93000000 0x0 0x30000>, - <0x3 0x93200000 0x0 0x4000>, - <0x3 0x93140000 0x0 0x4000>, - <0x3 0x930c0000 0x0 0x10000>, - <0x3 0x90000000 0x0 0x8000>, - <0x3 0x90020000 0x0 0x4000>, - <0x3 0x93244000 0x0 0x4000>, - <0x3 0x93250000 0x0 0x4000>; - reg-names = "bank0", "bank1", "pipehandler", "core", "cfg", "cpu", - "cpu-data", "axi2af", "axi2af-lioa", "fabric", "common-cfg"; - #phy-cells = <1>; - #reset-cells = <0>; - power-domains = <&ps_atc2_common_dp>; - mboxes = <&atcphy2_mbox>; - mbox-names = "phy-cpu"; - nonposted-mmio; - orientation-switch; - status = "disabled"; - }; - - atcphy2_mbox: mailbox@393148000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x3 0x93148000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - power-domains = <&ps_atc2_phymxwrap>; - status = "disabled"; - }; - - usb_drd2_dart_0: iommu@392f00000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x92f00000 0x0 0xc000>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_atc2_usb>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; - status = "disabled"; - }; - - usb_drd2_dart_1: iommu@392f80000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x92f80000 0x0 0xc000>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_atc2_usb>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; - status = "disabled"; - }; - - usb_drd2: usb@392280000 { - compatible = "apple,t6040-dwc3", "apple,t8103-dwc3"; - reg = <0x3 0x92280000 0x0 0xcd00>, - <0x3 0x9228cd00 0x0 0x3200>, - <0x3 0x92200000 0x0 0x4000>; - reg-names = "dwc3-core", "dwc3-apple", "drd-cfg"; - interrupt-parent = <&aic>; - interrupts = ; - /* - * A role switch rather than a fixed host: the PD controller - * resets the eUSB2 repeater on every connect, so the PHY and - * the core start after the attach and stop on detach. - */ - dr_mode = "otg"; - usb-role-switch; - role-switch-default-mode = "host"; - iommus = <&usb_drd2_dart_0 0>, <&usb_drd2_dart_1 1>; - power-domains = <&ps_atc2_usb>; - resets = <&atcphy2>; - phys = <&atcphy2 PHY_TYPE_USB2>, <&atcphy2 PHY_TYPE_USB3>; - phy-names = "usb2-phy", "usb3-phy"; - status = "disabled"; - }; - /* Additional DARTs; enabled together with their DMA consumers. */ - ave0_dart1: iommu@283080000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x2 0x83080000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x00004000 0x0 0xffffc000>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_venc0_sys>; - status = "disabled"; - }; - - ave0_dart0: iommu@2830a0000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x2 0x830a0000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x00004000 0x0 0xffffc000>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_venc0_sys>; - status = "disabled"; - }; - - apr0_dart: iommu@301020000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x01020000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x300 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_scodec>; - status = "disabled"; - }; - - apciec0_dart: iommu@384000000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x84000000 0x0 0x20000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - apciec1_dart: iommu@38c000000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x8c000000 0x0 0x20000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - apciec2_dart: iommu@394000000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x94000000 0x0 0x20000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - dispext0_dart: iommu@3a2300000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0xa2300000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x10 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - dcpext0_dart: iommu@3a2340000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0xa2340000 0x0 0x20000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x10 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - apcie1_dart: iommu@411000000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x11000000 0x0 0x20000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - sio_dart: iommu@429060000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x29060000 0x0 0x20000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x1c000 0x2ff 0xfffe4000>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_sio>; - status = "disabled"; - }; - - ane0_dart0: iommu@485800000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x85800000 0x0 0xc000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_ane_sys>; - /* Include firmware identity MMIO pages below the preload DVAs. */ - apple,dma-range = <0x0 0x0 0x400 0x0>; - status = "disabled"; - }; - - ane0_dart1: iommu@485820000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x85820000 0x0 0xc000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_ane_sys>; - /* Include firmware identity MMIO pages below the preload DVAs. */ - apple,dma-range = <0x0 0x0 0x400 0x0>; - status = "disabled"; - }; - - ane0_dart2: iommu@485840000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x85840000 0x0 0xc000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_ane_sys>; - /* Include firmware identity MMIO pages below the preload DVAs. */ - apple,dma-range = <0x0 0x0 0x400 0x0>; - status = "disabled"; - }; - - jpeg0: jpeg@487000000 { - compatible = "apple,t6041-jpeg"; - reg = <0x4 0x87000000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = ; - iommus = <&jpeg0_dart 0>; - power-domains = <&ps_jpg>; - apple,dma-range = /bits/ 64 <0x10000000000 0x100000000>; - status = "disabled"; - }; - - jpeg0_dart: iommu@487020000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x87020000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x300 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_jpg>; - status = "disabled"; - }; - - jpeg1: jpeg@487060000 { - compatible = "apple,t6041-jpeg"; - reg = <0x4 0x87060000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = ; - iommus = <&jpeg1_dart 0>; - power-domains = <&ps_jpg>; - apple,dma-range = /bits/ 64 <0x10000000000 0x100000000>; - status = "disabled"; - }; - - jpeg1_dart: iommu@487080000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x4 0x87080000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x300 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_jpg>; - status = "disabled"; - }; - - scaler0_dart: iommu@521260000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x5 0x21260000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x300 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_msr0>; - status = "disabled"; - }; - - dispext1_dart: iommu@602300000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x6 0x02300000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x10 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - dcpext1_dart: iommu@602340000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x6 0x02340000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x10 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - pinctrl_aop: pinctrl@510824000 { - compatible = "apple,t6041-pinctrl", "apple,t8103-pinctrl"; - reg = <0x5 0x10824000 0x0 0x4000>; - clocks = <&clkref>; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&pinctrl_aop 0 0 85>; - apple,npins = <85>; - interrupt-controller; - #interrupt-cells = <2>; - interrupt-parent = <&aic>; - interrupts = , - , - , - , - , - , - ; - /* Coprocessor pins and interrupt groups need an ownership handoff. */ - status = "disabled"; - }; - - pinctrl_smc: pinctrl@50c824000 { - compatible = "apple,t6041-pinctrl", "apple,t8103-pinctrl"; - reg = <0x5 0x0c824000 0x0 0x4000>; - clocks = <&clkref>; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&pinctrl_smc 0 0 24>; - apple,npins = <24>; - interrupt-controller; - #interrupt-cells = <2>; - interrupt-parent = <&aic>; - interrupts = , - , - , - , - , - , - ; - /* Coprocessor pins and interrupt groups need an ownership handoff. */ - status = "disabled"; - }; - - nub_spmi1: spmi@509054000 { - compatible = "apple,t6041-spmi", "apple,t8103-spmi"; - reg = <0x5 0x09054000 0x0 0x100>; - #address-cells = <2>; - #size-cells = <0>; - power-domains = <&ps_nub_spmi1>; - status = "disabled"; - }; - - nub_spmi2: spmi@509094000 { - compatible = "apple,t6041-spmi", "apple,t8103-spmi"; - reg = <0x5 0x09094000 0x0 0x100>; - #address-cells = <2>; - #size-cells = <0>; - power-domains = <&ps_nub_spmi2>; - status = "disabled"; - }; - - nub_spmi3: spmi@5090d4000 { - compatible = "apple,t6041-spmi", "apple,t8103-spmi"; - reg = <0x5 0x090d4000 0x0 0x100>; - #address-cells = <2>; - #size-cells = <0>; - power-domains = <&ps_nub_spmi3>; - status = "disabled"; - }; - - nub_spmi4: spmi@509114000 { - compatible = "apple,t6041-spmi", "apple,t8103-spmi"; - reg = <0x5 0x09114000 0x0 0x100>; - #address-cells = <2>; - #size-cells = <0>; - power-domains = <&ps_nub_spmi4>; - status = "disabled"; - }; - - aop_spmi0: spmi@510914000 { - compatible = "apple,t6041-spmi", "apple,t8103-spmi"; - reg = <0x5 0x10914000 0x0 0x100>; - #address-cells = <2>; - #size-cells = <0>; - /* Shared with AOP firmware; no AP bus ownership handoff yet. */ - status = "disabled"; - }; - - /* The QSPIMC input is ADT clock 434 (200 MHz). */ - clk_200m: clock-200m { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <200000000>; - clock-output-names = "clk_200m"; - }; - - spi4: spi@429110000 { - compatible = "apple,t6041-spi", "apple,t8103-spi"; - reg = <0x4 0x29110000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = ; - clocks = <&clkref>; - power-domains = <&ps_spi4>; - #address-cells = <1>; - #size-cells = <0>; - /* Panel/TCON control belongs to the display firmware. */ - status = "disabled"; - }; - - qspi: spi@429118000 { - compatible = "apple,t6041-qspi"; - reg = <0x4 0x29118000 0x0 0x4800>; - interrupt-parent = <&aic>; - interrupts = ; - clocks = <&clk_200m>; - power-domains = <&ps_qspi>; - #address-cells = <1>; - #size-cells = <0>; - /* Boards enable it with their flash and its nvram partition. */ - status = "disabled"; - }; - - /* The loader supplies the SIO firmware regions and protocol tables. */ - sio: dma-controller@429e00000 { - compatible = "apple,t6041-sio"; - reg = <0x4 0x29e00000 0x0 0x8000>; - dma-channels = <128>; - #dma-cells = <1>; - mboxes = <&sio_mbox>; - iommus = <&sio_dart 0>; - power-domains = <&ps_sio_cpu>; - status = "disabled"; - }; - - sio_mbox: mailbox@429e08000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x4 0x29e08000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - power-domains = <&ps_sio_cpu>; - status = "disabled"; - }; - - /* - * Disabled until the H16 firmware path is proven on hardware. The - * loader fills the preload reservations and the firmware IOVAs from - * the ADT, so enabling it then only takes status = "okay" here and on - * the three DARTs. - */ - ane: ane@484000000 { - compatible = "apple,t6041-ane"; - reg = <0x4 0x84000000 0x0 0x2000000>, - <0x5 0x02280000 0x0 0x18000>, - <0x5 0x022a0000 0x0 0x4000>, - <0x5 0x003c0000 0x0 0x30000>, - <0x2 0x12000000 0x0 0xff4000>, - <0x5 0x22000000 0x0 0x2000000>, - <0x5 0x08374000 0x0 0x4000>; - reg-names = "engine", "pmgr", "aux-0", "aux-1", "aux-2", - "aux-3", "aux-4"; - interrupt-parent = <&aic>; - interrupts = ; - /* Stream 0 only: the MPM stream 11 is not given to the host. */ - iommus = <&ane0_dart0 0>, <&ane0_dart1 0>, <&ane0_dart2 0>; - power-domains = <&ps_ane_sys>, <&ps_ane_cpu>, <&ps_ane_mpm>, - <&ps_ane_td>, <&ps_ane_base>; - apple,ane-type = <0x110>; - apple,firmware-preloaded; - /* Inclusive DAPF bounds, in hardware record order. */ - apple,dapf-ranges = /bits/ 64 <0x5022803c0 0x5022803c3>, - /bits/ 64 <0x50228c000 0x50228c01b>, - /bits/ 64 <0x581668000 0x581668003>, - /bits/ 64 <0x28a668000 0x28a668003>; - /* Default firmware layout; the loader rewrites it from the ADT. */ - apple,firmware-iovas = /bits/ 64 <0x10000000000 0x100000c0000>; - /* The bootloader supplies the physical TEXT/DATA reservations. */ - status = "disabled"; - }; - - /* The video encoder stays disabled until its firmware backend is available. */ - ave: video-codec@283100000 { - compatible = "apple,t6041-ave"; - reg = <0x2 0x83100000 0x0 0x45c000>, - <0x2 0x83050000 0x0 0x4000>, - <0x2 0x83800000 0x0 0x800000>; - reg-names = "codec", "mailbox", "coproc"; - interrupt-parent = <&aic>; - interrupts = , - , - , - , - ; - power-domains = <&ps_venc0_dma>, <&ps_venc0_pipe4>, - <&ps_venc0_pipe5>, <&ps_venc0_me0>, <&ps_venc0_me1>, - <&pmc_soc_max>; - power-domain-names = "dma", "pipe4", "pipe5", "me0", "me1", "perf"; - iommus = <&ave0_dart0 0>, <&ave0_dart1 0>; - status = "disabled"; - }; - - serial0: serial@429200000 { - compatible = "apple,s5l-uart"; - reg = <0x4 0x29200000 0x0 0x4000>; - reg-io-width = <4>; - interrupt-parent = <&aic>; - interrupts = ; - clocks = <&clkref>, <&clkref>; - clock-names = "uart", "clk_uart_baud0"; - power-domains = <&ps_uart0>; - status = "disabled"; - }; - - dcuart: serial@50883c000 { - compatible = "apple,dockchannel-uart"; - reg = <0x5 0x0883c000 0x0 0x4000>, - <0x5 0x08838000 0x0 0x4000>, - <0x5 0x0880c000 0x0 0x4000>; - reg-names = "data", "config", "irq"; - interrupt-parent = <&aic>; - interrupts = ; - apple,channel = <2>; - apple,sw-drain; - status = "disabled"; - }; - - /* ACIO 0 remains disabled until its host-router handoff is supported. */ - usb4_0_mbox: mailbox@381108000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x3 0x81108000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - power-domains = <&ps_atc0_cio>; - status = "disabled"; - }; - - usb4_0_dart: iommu@381a80000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x81a80000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x300 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - /* ACIO 1 remains disabled until its host-router handoff is supported. */ - usb4_1_mbox: mailbox@389108000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x3 0x89108000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - power-domains = <&ps_atc1_cio>; - status = "disabled"; - }; - - usb4_1_dart: iommu@389a80000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x89a80000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x300 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; - - /* ACIO 2 remains disabled until its host-router handoff is supported. */ - usb4_2_mbox: mailbox@391108000 { - compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; - reg = <0x3 0x91108000 0x0 0x4000>; - interrupt-parent = <&aic>; - interrupts = , - , - , - ; - interrupt-names = "send-empty", "send-not-empty", - "recv-empty", "recv-not-empty"; - #mbox-cells = <0>; - power-domains = <&ps_atc2_cio>; - status = "disabled"; - }; - - usb4_2_dart: iommu@391a80000 { - compatible = "apple,t6041-dart", "apple,t8110-dart"; - reg = <0x3 0x91a80000 0x0 0xc000>; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x300 0x0>; - interrupt-parent = <&aic>; - interrupts = ; - status = "disabled"; - }; +/* The M4 Pro has five cores in each P cluster. */ +/delete-node/ &cpu_p05; +/delete-node/ &cpu_p15; +&{/cpus/cpu-map/cluster1} { + /delete-node/ core5; }; -#include "t6040-pmgr.dtsi" +&{/cpus/cpu-map/cluster2} { + /delete-node/ core5; +}; /* * DRAM interface class: width and maximum rate are inferred from topology diff --git a/arch/arm64/boot/dts/apple/t6041-j616c.dts b/arch/arm64/boot/dts/apple/t6041-j616c.dts new file mode 100644 index 0000000000000..813a14be78d3c --- /dev/null +++ b/arch/arm64/boot/dts/apple/t6041-j616c.dts @@ -0,0 +1,889 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +// Copyright The Asahi Linux Contributors + +/dts-v1/; + +#include "t6041.dtsi" +#include +#include + +/ { + compatible = "apple,j616c", "apple,t6041", "apple,arm-platform"; + model = "Apple MacBook Pro (16-inch, M4 Max, Nov 2024)"; + chassis-type = "laptop"; + + aliases { + serial0 = &serial0; + keyboard = &keyboard; + wifi0 = "/pcie@1cb0000000/pci@0,0/wifi@0,0"; + bluetooth0 = "/pcie@1cb0000000/pci@0,0/bluetooth@0,1"; + mtp = &mtp; + dcp = &dcp; + disp0 = &display; + disp0-piodma = &disp0_piodma; + gpu = &gpu; + }; + + chosen { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + stdout-path = "serial0:115200n8"; + + framebuffer0: framebuffer@0 { + compatible = "apple,simple-framebuffer", "simple-framebuffer"; + reg = <0 0 0 0>; + status = "disabled"; + }; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + }; + + memory@0 { + device_type = "memory"; + reg = <0 0 0 0>; + }; + + serial0: serial@429200000 { + compatible = "apple,s5l-uart"; + reg = <0x4 0x29200000 0x0 0x1000>; + reg-io-width = <4>; + interrupt-parent = <&aic>; + interrupts = ; + clocks = <&clkref>, <&clkref>; + clock-names = "uart", "clk_uart_baud0"; + }; + + clk_disp0: clock-disp0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <712000000>; + clock-output-names = "disp0"; + }; + + thermal-zones { + cpu-die-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + thermal-sensors = <&smc_hwmon 0>; + + trips { + cpu_die_passive: cpu-die-passive { + temperature = <113000>; + hysteresis = <5000>; + type = "passive"; + }; + + cpu-die-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-e { + trip = <&cpu_die_passive>; + cooling-device = + <&cpu_e0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_e1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_e2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_e3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + + map-p0 { + trip = <&cpu_die_passive>; + cooling-device = + <&cpu_p00 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_p01 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_p02 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_p03 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_p04 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_p05 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + + map-p1 { + trip = <&cpu_die_passive>; + cooling-device = + <&cpu_p10 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_p11 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_p12 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_p13 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_p14 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_p15 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; +}; + +&cpufreq_e { + /delete-property/ apple,fast-die-effort; +}; + +&cpufreq_p0 { + /delete-property/ apple,fast-die-effort; +}; + +&cpufreq_p1 { + /delete-property/ apple,fast-die-effort; +}; + +&wdt { + timeout-sec = <140>; +}; + +&smc { + status = "okay"; + + smc_gpio_low: gpio-low { + compatible = "apple,smc-low-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +&smc_mbox { + status = "okay"; +}; + +&nub_spmi0 { + status = "okay"; +}; + +&smc_hwmon { + temperature-TCMz { + apple,key-id = "TCMz"; + label = "CPU Die Max"; + }; + temperature-TCMb { apple,key-id = "TCMb"; label = "CPU TCMb"; }; + temperature-Tpx0 { apple,key-id = "Tpx0"; label = "CPU Tpx0"; }; + temperature-Tpx1 { apple,key-id = "Tpx1"; label = "CPU Tpx1"; }; + temperature-Tpx2 { apple,key-id = "Tpx2"; label = "CPU Tpx2"; }; + temperature-Tpx3 { apple,key-id = "Tpx3"; label = "CPU Tpx3"; }; + temperature-Tpx4 { apple,key-id = "Tpx4"; label = "CPU Tpx4"; }; + temperature-Tpx5 { apple,key-id = "Tpx5"; label = "CPU Tpx5"; }; + temperature-Tpx8 { apple,key-id = "Tpx8"; label = "CPU Tpx8"; }; + temperature-Tpx9 { apple,key-id = "Tpx9"; label = "CPU Tpx9"; }; + temperature-TpxA { apple,key-id = "TpxA"; label = "CPU TpxA"; }; + temperature-TpxB { apple,key-id = "TpxB"; label = "CPU TpxB"; }; + temperature-TpxC { apple,key-id = "TpxC"; label = "CPU TpxC"; }; + temperature-TpxD { apple,key-id = "TpxD"; label = "CPU TpxD"; }; + temperature-Tex0 { apple,key-id = "Tex0"; label = "CPU Tex0"; }; + temperature-Tex1 { apple,key-id = "Tex1"; label = "CPU Tex1"; }; + temperature-Tex2 { apple,key-id = "Tex2"; label = "CPU Tex2"; }; + temperature-Tex3 { apple,key-id = "Tex3"; label = "CPU Tex3"; }; + temperature-TH0x { apple,key-id = "TH0x"; label = "NAND Flash Temperature"; }; + temperature-TB0T { apple,key-id = "TB0T"; label = "Battery Hotspot"; }; + temperature-TCHP { apple,key-id = "TCHP"; label = "Charge Regulator Temp"; }; + temperature-TW0P { apple,key-id = "TW0P"; label = "WiFi/BT Module Temp"; }; + power-PSTR { apple,key-id = "PSTR"; label = "Total System Power"; }; + power-PHPC { apple,key-id = "PHPC"; label = "Heatpipe Power"; }; + power-PDTR { apple,key-id = "PDTR"; label = "AC Input Power"; }; + voltage-VD0R { apple,key-id = "VD0R"; label = "AC Input Voltage"; }; + voltage-SBAV { apple,key-id = "SBAV"; label = "Battery Voltage"; }; + current-ID0R { apple,key-id = "ID0R"; label = "AC Input Current"; }; +}; + +&pinctrl { + status = "okay"; + + wifi_clkreq_pins: wifi-clkreq-pins { + pinmux = ; + }; +}; + +&pinctrl_nub { + status = "okay"; + /delete-property/ interrupt-controller; + /delete-property/ #interrupt-cells; + /delete-property/ interrupts; +}; + +&mtp { + status = "okay"; +}; + +&mtp_mbox { + status = "okay"; +}; + +&mtp_dart { + status = "okay"; +}; + +&mtp_dockchannel { + status = "okay"; +}; + +&mtp_hid { + compatible = "apple,dockchannel-hid"; + apple,afe-reset-gpios = <&smc_gpio_low 25 GPIO_ACTIVE_LOW>; + apple,stm-reset-gpios = <&smc_gpio_low 26 GPIO_ACTIVE_LOW>; + + multi-touch { + firmware-name = "apple/tpmtfw-j616c.bin"; + apple,power-method = <2>; + }; + + keyboard: keyboard { + hid-country-code = <0>; + apple,keyboard-layout-id = <0>; + }; + + stm { + }; + + actuator { + }; + + tp-accel { + }; + + mtp { + }; +}; + +&pcie_dart { + status = "okay"; +}; + +/ { + pcie0: pcie@1cb0000000 { + compatible = "apple,t6041-pcie", "apple,t6020-pcie"; + reg = <0x1c 0xb0000000 0x0 0x1000000>, + <0x4 0x14000000 0x0 0x4000>, + <0x4 0x10028000 0x0 0x4000>, + <0x4 0x11028000 0x0 0x4000>, + <0x4 0x12028000 0x0 0x4000>, + <0x4 0x13028000 0x0 0x4000>, + <0x4 0x17020000 0x0 0x4000>, + <0x4 0x17024000 0x0 0x4000>, + <0x4 0x17028000 0x0 0x4000>, + <0x4 0x1702c000 0x0 0x4000>; + reg-names = "config", "rc", + "port0", "port1", "port2", "port3", + "phy0", "phy1", "phy2", "phy3"; + ranges = <0x43000000 0xb 0xc0000000 0xb 0xc0000000 0 0x20000000 0x2000000 0 0x80000000 0xb 0x80000000 0 0x40000000>; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_clkreq_pins>; + #size-cells = <2>; + #address-cells = <3>; + bus-range = <0 1>; + iommu-map-mask = <0xffff>; + iommu-map = <0x100 &pcie_dart 1 2>; + msi-ranges = <&aic AIC_IRQ 2071 IRQ_TYPE_EDGE_RISING 32>; + msi-parent = <&pcie0>; + msi-controller; + interrupts = <0 0x6bb 4>; + interrupt-parent = <&aic>; + device_type = "pci"; + + port00: pci@0,0 { + compatible = "pciclass,0604"; + reg = <0 0 0 0 0>; + ranges; + interrupt-map = <0 0 0 1 &port00 0 0 0 0 0 0 0 2 &port00 0 0 0 1 0 0 0 3 &port00 0 0 0 2 0 0 0 4 &port00 0 0 0 3>; + interrupt-map-mask = <0 0 0 7>; + #interrupt-cells = <1>; + interrupt-controller; + #size-cells = <2>; + #address-cells = <3>; + pwren-gpios = <&smc_gpio 0x13 0>; + reset-gpios = <&pinctrl 4 1>; + device_type = "pci"; + + bluetooth@0,1 { + compatible = "pci14e4,5f72"; + reg = <0x100 0 0 0 0>; + local-bd-address = [00 00 00 00 00 00]; + brcm,board-type = "apple,hostomel"; + status = "okay"; + }; + + wifi@0,0 { + compatible = "brcm,bcm4329-fmac"; + reg = <0 0 0 0 0>; + brcm,ccode-map-trivial; + brcm,board-type = "apple,hostomel"; + }; + }; + }; +}; + +&ans_mbox { + status = "okay"; +}; + +&ans_sart { + status = "okay"; +}; + +&nvme { + status = "okay"; +}; + +&display { + phandle = <&display>; + status = "okay"; +}; + +&dcp { + clocks = <&clk_disp0>; + phandle = <&dcp>; + + panel { + compatible = "apple,panel-j616", "apple,panel-mini-led", "apple,panel"; + width-mm = <346>; + height-mm = <223>; + adj-height-mm = <216>; + apple,max-brightness = <500>; + }; +}; + +&disp0_piodma { + phandle = <&disp0_piodma>; +}; + +&nub_spmi_a0 { + status = "okay"; + + hpm1: usb-pd@a { + compatible = "apple,sn201202x"; + reg = <0xa SPMI_USID>; + interrupts = <37 IRQ_TYPE_EDGE_RISING>, + <39 IRQ_TYPE_EDGE_RISING>, + <43 IRQ_TYPE_EDGE_RISING>, + <45 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "irq", "select", "sleep", "wake"; + + typec1: connector { + compatible = "usb-c-connector"; + label = "USB-C Left Front"; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + typec1_con_hs: endpoint { + remote-endpoint = <&usb_drd1_hs>; + }; + }; + }; + }; + }; +}; + +&nub_spmi_a1 { + status = "okay"; + + hpm2: usb-pd@c { + compatible = "apple,sn201202x"; + reg = <0xc SPMI_USID>; + interrupts = <11 IRQ_TYPE_EDGE_RISING>, + <13 IRQ_TYPE_EDGE_RISING>, + <17 IRQ_TYPE_EDGE_RISING>, + <19 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "irq", "select", "sleep", "wake"; + + typec2: connector { + compatible = "usb-c-connector"; + label = "USB-C Right"; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + typec2_con_hs: endpoint { + remote-endpoint = <&usb_drd2_hs>; + }; + }; + }; + }; + }; +}; + +&atcphy1 { + apple,tunable-usb2-host = <0x8 0x7003 0x3>; + status = "okay"; +}; + +&usb_drd1_dart_0 { + status = "okay"; +}; + +&usb_drd1_dart_1 { + status = "okay"; +}; + +&usb_drd1 { + maximum-speed = "high-speed"; + phys = <&atcphy1 PHY_TYPE_USB2>; + phy-names = "usb2-phy"; + apple,tunable-gbl-host = <0x4 0x0001ef00 0x00002f00>, <0x1c 0x00000100 0x0>, + <0x2c 0x000a07ff 0x000800c8>, <0x100 0x02000100 0x02000100>, + <0x504 0x00001000 0x0>, <0x528 0xff0000ff 0x06000006>, + <0x52c 0xff0000ff 0x08000008>, <0x538 0x00000800 0x00000800>, + <0x580 0xffffffff 0x6f000006>; + apple,tunable-cfg-host = <0x20 0xff 0x1b>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usb_drd1_hs: endpoint { + remote-endpoint = <&typec1_con_hs>; + }; + }; + }; +}; + +&atcphy2 { + apple,tunable-usb2-host = <0x8 0x7003 0x3>; + status = "okay"; +}; + +&usb_drd2_dart_0 { + status = "okay"; +}; + +&usb_drd2_dart_1 { + status = "okay"; +}; + +&usb_drd2 { + maximum-speed = "high-speed"; + phys = <&atcphy2 PHY_TYPE_USB2>; + phy-names = "usb2-phy"; + apple,tunable-gbl-host = <0x4 0x0001ef00 0x00002f00>, <0x1c 0x00000100 0x0>, + <0x2c 0x000a07ff 0x000800c8>, <0x100 0x02000100 0x02000100>, + <0x504 0x00001000 0x0>, <0x528 0xff0000ff 0x06000006>, + <0x52c 0xff0000ff 0x08000008>, <0x538 0x00000800 0x00000800>, + <0x580 0xffffffff 0x6f000006>; + apple,tunable-cfg-host = <0x20 0xff 0x1b>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usb_drd2_hs: endpoint { + remote-endpoint = <&typec2_con_hs>; + }; + }; + }; +}; + +/ { + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpu_uat_ttbs: uat-ttbs { + no-map; + status = "disabled"; + }; + + gpu_uat_pagetables: uat-pagetables { + no-map; + status = "disabled"; + }; + + gpu_uat_l2_pagetables: uat-l2-pagetables { + no-map; + status = "disabled"; + }; + + gpu_uat_handoff: uat-handoff { + no-map; + status = "disabled"; + }; + + gpu_fw_text: gpu-fw-text { + no-map; + status = "disabled"; + }; + + gpu_fw_data: gpu-fw-data { + no-map; + status = "disabled"; + }; + }; + + gpu_opp: opp-table-gpu { + compatible = "operating-points-v2"; + + opp00 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <125000 125000 125000 125000>; + }; + opp01 { + opp-hz = /bits/ 64 <338000000>; + opp-microvolt = <600000 600000 600000 600000>; + }; + opp02 { + opp-hz = /bits/ 64 <618000000>; + opp-microvolt = <665000 665000 660000 660000>; + }; + opp03 { + opp-hz = /bits/ 64 <796000000>; + opp-microvolt = <705000 705000 700000 705000>; + }; + opp04 { + opp-hz = /bits/ 64 <924000000>; + opp-microvolt = <725000 725000 715000 730000>; + }; + opp05 { + opp-hz = /bits/ 64 <952000000>; + opp-microvolt = <770000 770000 770000 780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1056000000>; + opp-microvolt = <770000 770000 770000 780000>; + }; + opp07 { + opp-hz = /bits/ 64 <1062000000>; + opp-microvolt = <810000 810000 805000 810000>; + }; + opp08 { + opp-hz = /bits/ 64 <1182000000>; + opp-microvolt = <810000 810000 805000 810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1182000000>; + opp-microvolt = <860000 860000 860000 860000>; + }; + opp10 { + opp-hz = /bits/ 64 <1312000000>; + opp-microvolt = <860000 860000 860000 860000>; + }; + opp11 { + opp-hz = /bits/ 64 <1242000000>; + opp-microvolt = <900000 895000 900000 900000>; + }; + opp12 { + opp-hz = /bits/ 64 <1380000000>; + opp-microvolt = <900000 895000 900000 900000>; + }; + opp13 { + opp-hz = /bits/ 64 <1326000000>; + opp-microvolt = <940000 925000 940000 940000>; + }; + opp14 { + opp-hz = /bits/ 64 <1470000000>; + opp-microvolt = <940000 925000 940000 940000>; + }; + opp15 { + opp-hz = /bits/ 64 <1578000000>; + opp-microvolt = <1020000 1020000 1020000 1020000>; + }; + }; + + gpu_cs_opp: opp-table-gpucs { + compatible = "operating-points-v2"; + + opp00 { + opp-hz = /bits/ 64 <24000000>; + opp-microvolt = <585000>; + }; + opp01 { + opp-hz = /bits/ 64 <338000000>; + opp-microvolt = <585000>; + }; + opp02 { + opp-hz = /bits/ 64 <618000000>; + opp-microvolt = <635000>; + }; + opp03 { + opp-hz = /bits/ 64 <796000000>; + opp-microvolt = <685000>; + }; + opp04 { + opp-hz = /bits/ 64 <992000000>; + opp-microvolt = <720000>; + }; + opp05 { + opp-hz = /bits/ 64 <1188000000>; + opp-microvolt = <770000>; + }; + opp06 { + opp-hz = /bits/ 64 <1380000000>; + opp-microvolt = <855000>; + }; + opp07 { + opp-hz = /bits/ 64 <1470000000>; + opp-microvolt = <885000>; + }; + }; + + gpu_afr_opp: opp-table-gpuafr { + compatible = "operating-points-v2"; + + opp00 { + opp-hz = /bits/ 64 <24000000>; + opp-microvolt = <585000>; + }; + opp01 { + opp-hz = /bits/ 64 <338000000>; + opp-microvolt = <585000>; + }; + opp02 { + opp-hz = /bits/ 64 <618000000>; + opp-microvolt = <635000>; + }; + opp03 { + opp-hz = /bits/ 64 <796000000>; + opp-microvolt = <685000>; + }; + opp04 { + opp-hz = /bits/ 64 <992000000>; + opp-microvolt = <720000>; + }; + opp05 { + opp-hz = /bits/ 64 <1188000000>; + opp-microvolt = <770000>; + }; + opp06 { + opp-hz = /bits/ 64 <1380000000>; + opp-microvolt = <855000>; + }; + opp07 { + opp-hz = /bits/ 64 <1470000000>; + opp-microvolt = <885000>; + }; + }; +}; + +&gpu { + memory-region = <&gpu_uat_ttbs>, <&gpu_uat_pagetables>, + <&gpu_uat_handoff>, <&gpu_fw_data>, + <&gpu_uat_l2_pagetables>, <&gpu_fw_text>; + memory-region-names = "ttbs", "pagetables", "handoff", "fw-data", + "l2-pagetables", "fw-text"; + operating-points-v2 = <&gpu_opp>; + apple,cs-opp = <&gpu_cs_opp>; + apple,afr-opp = <&gpu_afr_opp>; + apple,firmware-version = <26 5 2>; +}; + +/ { + aliases { + aop = &aop; + }; + speaker_sdz: regulator-sn012776-sdz { + compatible = "regulator-fixed"; + regulator-name = "sn012776-sdz"; + gpios = <&pinctrl 54 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + sound: sound { + compatible = "apple,j616-macaudio", "apple,macaudio"; + model = "MacBook Pro J616"; + #address-cells = <1>; + #size-cells = <0>; + + dai-link@0 { + reg = <0>; + link-name = "Speakers"; + dai-tdm-idle-mode-0 = "zero"; + dai-tdm-idle-mode-1 = "zero"; + dai-tdm-slot-tx-idle-mask-0 = <0xf0f0f0>; + dai-tdm-slot-tx-idle-mask-1 = <0x0f0f0f>; + + cpu { + sound-dai = <&aop_audio 3>; + }; + + codec { + sound-dai = <&speaker_left_woof1>, <&speaker_right_woof1>, + <&speaker_left_woof2>, <&speaker_right_woof2>, + <&speaker_left_tweet>, <&speaker_right_tweet>; + }; + }; + }; + + sound_jack: sound-jack { + compatible = "apple,j616-macaudio-jack", "apple,macaudio"; + model = "MacBook Pro J616 Jack"; + #address-cells = <1>; + #size-cells = <0>; + + dai-link@0 { + reg = <0>; + link-name = "Headphone Jack"; + + cpu { + sound-dai = <&aop_audio 4>; + }; + + codec { + sound-dai = <&jack_codec>; + }; + }; + }; +}; + +&aop { + status = "okay"; +}; + +&aop_mbox { + status = "okay"; +}; + +&aop_dart { + status = "okay"; +}; + +&admac0 { + status = "okay"; +}; + +&admac1 { + status = "okay"; +}; + +&aop_audio { + apple,chassis-name = "J616"; + apple,machine-kind = "MacBook Pro"; +}; + +&i2c1 { + status = "okay"; + + speaker_left_woof1: codec@38 { + compatible = "ti,sn012776", "ti,tas2764"; + reg = <0x38>; + SDZ-supply = <&speaker_sdz>; + apple,sdz-group-fail-closed; + #sound-dai-cells = <0>; + sound-name-prefix = "Left Woofer 1"; + interrupts-extended = <&pinctrl 55 IRQ_TYPE_LEVEL_LOW>; + ti,imon-slot-no = <0>; + ti,vmon-slot-no = <2>; + }; + + speaker_left_woof2: codec@39 { + compatible = "ti,sn012776", "ti,tas2764"; + reg = <0x39>; + SDZ-supply = <&speaker_sdz>; + apple,sdz-group-fail-closed; + #sound-dai-cells = <0>; + sound-name-prefix = "Left Woofer 2"; + interrupts-extended = <&pinctrl 55 IRQ_TYPE_LEVEL_LOW>; + ti,imon-slot-no = <8>; + ti,vmon-slot-no = <10>; + }; + + speaker_left_tweet: codec@3a { + compatible = "ti,sn012776", "ti,tas2764"; + reg = <0x3a>; + SDZ-supply = <&speaker_sdz>; + apple,sdz-group-fail-closed; + #sound-dai-cells = <0>; + sound-name-prefix = "Left Tweeter"; + interrupts-extended = <&pinctrl 55 IRQ_TYPE_LEVEL_LOW>; + ti,imon-slot-no = <16>; + ti,vmon-slot-no = <18>; + }; +}; + +&i2c3 { + status = "okay"; + + speaker_right_woof1: codec@3b { + compatible = "ti,sn012776", "ti,tas2764"; + reg = <0x3b>; + SDZ-supply = <&speaker_sdz>; + apple,sdz-group-fail-closed; + #sound-dai-cells = <0>; + sound-name-prefix = "Right Woofer 1"; + interrupts-extended = <&pinctrl 55 IRQ_TYPE_LEVEL_LOW>; + ti,imon-slot-no = <4>; + ti,vmon-slot-no = <6>; + }; + + speaker_right_woof2: codec@3c { + compatible = "ti,sn012776", "ti,tas2764"; + reg = <0x3c>; + SDZ-supply = <&speaker_sdz>; + apple,sdz-group-fail-closed; + #sound-dai-cells = <0>; + sound-name-prefix = "Right Woofer 2"; + interrupts-extended = <&pinctrl 55 IRQ_TYPE_LEVEL_LOW>; + ti,imon-slot-no = <12>; + ti,vmon-slot-no = <14>; + }; + + speaker_right_tweet: codec@3d { + compatible = "ti,sn012776", "ti,tas2764"; + reg = <0x3d>; + SDZ-supply = <&speaker_sdz>; + apple,sdz-group-fail-closed; + #sound-dai-cells = <0>; + sound-name-prefix = "Right Tweeter"; + interrupts-extended = <&pinctrl 55 IRQ_TYPE_LEVEL_LOW>; + ti,imon-slot-no = <20>; + ti,vmon-slot-no = <22>; + }; +}; + +&i2c2 { + status = "okay"; + + jack_codec: codec@4b { + compatible = "cirrus,cs42l84"; + reg = <0x4b>; + reset-gpios = <&pinctrl_nub 58 GPIO_ACTIVE_HIGH>; + #sound-dai-cells = <0>; + interrupts-extended = <&pinctrl 106 IRQ_TYPE_LEVEL_LOW>; + sound-name-prefix = "Jack"; + }; +}; + +&aop { nonposted-mmio; }; + +&aop_als { status = "disabled"; }; +&aop_las { status = "disabled"; }; + +&admac1 { dma-channels = <26>; nonposted-mmio; }; +&admac0 { nonposted-mmio; }; +&aop_dart { nonposted-mmio; }; +&i2c1 { nonposted-mmio; }; +&i2c2 { nonposted-mmio; }; +&i2c3 { nonposted-mmio; }; + +/ { + reserved-memory { + aop_mmio_pmgr: aop-mmio-pmgr@508304000 { + reg = <0x5 0x08304000 0x0 0x4000>; + iommu-addresses = <&aop 0x5 0x08304000 0x0 0x4000>; + no-map; + }; + }; +}; + +&aop { + dma-noncoherent; + memory-region = <&aop_mmio_pmgr>; +}; diff --git a/arch/arm64/boot/dts/apple/t6041.dtsi b/arch/arm64/boot/dts/apple/t6041.dtsi new file mode 100644 index 0000000000000..514a3fa11d9f3 --- /dev/null +++ b/arch/arm64/boot/dts/apple/t6041.dtsi @@ -0,0 +1,603 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +// Copyright The Asahi Linux Contributors + +#include "t604x.dtsi" + + +/* Keep the validated T6041 topology independent of unqualified T6040 blocks. */ +/delete-node/ &ane; +/delete-node/ &clk_200m; +/delete-node/ &sio; +/delete-node/ &ave0_dart1; +/delete-node/ &ave0_dart0; +/delete-node/ &apr0_dart; +/delete-node/ &usb4_0_dart; +/delete-node/ &apciec0_dart; +/delete-node/ &usb4_1_dart; +/delete-node/ &apciec1_dart; +/delete-node/ &usb4_2_dart; +/delete-node/ &apciec2_dart; +/delete-node/ &dispext0_dart; +/delete-node/ &dcpext0_dart; +/delete-node/ &sep_dart; +/delete-node/ &apcie1_dart; +/delete-node/ &sio_dart; +/delete-node/ &ane0_dart0; +/delete-node/ &ane0_dart1; +/delete-node/ &ane0_dart2; +/delete-node/ &jpeg0; +/delete-node/ &jpeg1; +/delete-node/ &jpeg0_dart; +/delete-node/ &jpeg1_dart; +/delete-node/ &scaler0_dart; +/delete-node/ &dispext1_dart; +/delete-node/ &dcpext1_dart; +/delete-node/ &usb4_0_mbox; +/delete-node/ &usb4_1_mbox; +/delete-node/ &usb4_2_mbox; +/delete-node/ &sep_mbox; +/delete-node/ &sio_mbox; +/delete-node/ &pinctrl_smc; +/delete-node/ &pinctrl_aop; +/delete-node/ &ps_gpx; +/delete-node/ &ps_apcie_gp; +/delete-node/ &ps_fab4_soc; +/delete-node/ &ps_sio_cpu; +/delete-node/ &ps_fpwm1; +/delete-node/ &ps_fpwm2; +/delete-node/ &ps_i2c0; +/delete-node/ &ps_i2c5; +/delete-node/ &ps_i2c7; +/delete-node/ &ps_spi_p; +/delete-node/ &ps_uart_p; +/delete-node/ &ps_dpa_p; +/delete-node/ &ps_aes; +/delete-node/ &ps_spi0; +/delete-node/ &ps_spi1; +/delete-node/ &ps_spi2; +/delete-node/ &ps_spi3; +/delete-node/ &ps_spi4; +/delete-node/ &ps_spi5; +/delete-node/ &ps_qspi; +/delete-node/ &ps_uart_n; +/delete-node/ &ps_uart0; +/delete-node/ &ps_uart1; +/delete-node/ &ps_uart2; +/delete-node/ &ps_uart3; +/delete-node/ &ps_uart4; +/delete-node/ &ps_uart5; +/delete-node/ &ps_uart6; +/delete-node/ &ps_dpa0; +/delete-node/ &ps_dpa1; +/delete-node/ &ps_dpa2; +/delete-node/ &ps_dpa3; +/delete-node/ &ps_dpa4; +/delete-node/ &ps_disp_sys; +/delete-node/ &ps_amcc4; +/delete-node/ &ps_amcc5; +/delete-node/ &ps_amcc6; +/delete-node/ &ps_amcc7; +/delete-node/ &ps_amcc12; +/delete-node/ &ps_amcc13; +/delete-node/ &ps_amcc14; +/delete-node/ &ps_amcc15; +/delete-node/ &ps_dcs_04; +/delete-node/ &ps_dcs_05; +/delete-node/ &ps_dcs_06; +/delete-node/ &ps_dcs_07; +/delete-node/ &ps_dcs_12; +/delete-node/ &ps_dcs_13; +/delete-node/ &ps_dcs_14; +/delete-node/ &ps_dcs_15; +/delete-node/ &ps_disp_fe; +/delete-node/ &ps_apcie_sys_gp; +/delete-node/ &ps_apcie_phy_sw; +/delete-node/ &ps_jpg; +/delete-node/ &ps_ane_sys; +/delete-node/ &ps_sep; +/delete-node/ &pmgr_ane; +/delete-node/ &pmgr_disp; +/delete-node/ &ps_ecpu_0; +/delete-node/ &ps_ecpu_2; +/delete-node/ &ps_dwi; +/delete-node/ &ps_aic; +/delete-node/ &ps_pmc; +/delete-node/ &ps_pms_c1ppt; +/delete-node/ &ps_soc_dpe; +/delete-node/ &ps_pmgr_soc_ocla; +/delete-node/ &ps_pms_fpwm0; +/delete-node/ &ps_pms_fpwm1; +/delete-node/ &ps_pms_fpwm2; +/delete-node/ &ps_pms_fpwm3; +/delete-node/ &ps_pms_fpwm4; +/delete-node/ &ps_fab0_soc; +/delete-node/ &ps_ecpu_3; +/delete-node/ &ps_amcc0; +/delete-node/ &ps_dcs_00; +/delete-node/ &ps_rom; +/delete-node/ &ps_amcc1; +/delete-node/ &ps_dcs_01; +/delete-node/ &ps_amcc2; +/delete-node/ &ps_dcs_02; +/delete-node/ &ps_amcc3; +/delete-node/ &ps_dcs_03; +/delete-node/ &ps_amcc8; +/delete-node/ &ps_dcs_08; +/delete-node/ &ps_amcc9; +/delete-node/ &ps_dcs_09; +/delete-node/ &ps_amcc10; +/delete-node/ &ps_dcs_10; +/delete-node/ &ps_amcc11; +/delete-node/ &ps_pcpu0_0; +/delete-node/ &ps_dcs_11; +/delete-node/ &ps_venc0_sys; +/delete-node/ &ps_pcpu0_1; +/delete-node/ &ps_fab_gw_0; +/delete-node/ &ps_fab_gw_1; +/delete-node/ &ps_fab_afr; +/delete-node/ &ps_fab1_soc; +/delete-node/ &ps_pcpu0_2; +/delete-node/ &ps_scodec; +/delete-node/ &ps_scodec_streaming; +/delete-node/ &ps_fab2_soc; +/delete-node/ &ps_dispext0_sys; +/delete-node/ &ps_dispext0_fe; +/delete-node/ &ps_dispext0_cpu; +/delete-node/ &ps_pcpu0_3; +/delete-node/ &ps_atc0_cio; +/delete-node/ &ps_atc0_pcie; +/delete-node/ &ps_atc0_cio_pcie; +/delete-node/ &ps_atc0_cio_usb; +/delete-node/ &ps_atc1_cio; +/delete-node/ &ps_atc1_pcie; +/delete-node/ &ps_atc1_cio_pcie; +/delete-node/ &ps_atc1_cio_usb; +/delete-node/ &ps_atc2_cio; +/delete-node/ &ps_atc2_pcie; +/delete-node/ &ps_atc2_cio_pcie; +/delete-node/ &ps_pcpu0_4; +/delete-node/ &ps_atc2_cio_usb; +/delete-node/ &ps_atc3_common; +/delete-node/ &ps_atc3_cio; +/delete-node/ &ps_atc3_pcie; +/delete-node/ &ps_atc3_cio_pcie; +/delete-node/ &ps_atc3_cio_usb; +/delete-node/ &ps_fab5_soc; +/delete-node/ &ps_sbr; +/delete-node/ &ps_gpio; +/delete-node/ &ps_msg; +/delete-node/ &ps_ap_tmm; +/delete-node/ &ps_msr0; +/delete-node/ &ps_msr0_ase_core; +/delete-node/ &ps_pcpu0_5; +/delete-node/ &ps_fab7_soc; +/delete-node/ &ps_dispext1_sys; +/delete-node/ &ps_dispext1_fe; +/delete-node/ &ps_dispext1_cpu; +/delete-node/ &ps_pcpu1_0; +/delete-node/ &ps_pcpu1_1; +/delete-node/ &ps_pcpu1_2; +/delete-node/ &ps_pcpu1_3; +/delete-node/ &ps_pcpu1_4; +/delete-node/ &ps_pcpu1_5; +/delete-node/ &ps_ecpu_1; +/delete-node/ &ps_ecpm; +/delete-node/ &ps_pcpm0; +/delete-node/ &ps_pcpm1; +/delete-node/ &pmgr_venc; +/delete-node/ &ps_debug_gated; +/delete-node/ &ps_nub_fabric; +/delete-node/ &ps_nub_sram; +/delete-node/ &ps_debug_switch; +/delete-node/ &ps_atc3_usb; +/delete-node/ &ps_atc3_phymxwrap; +/delete-node/ &ps_nub_spmi_ahb; +/delete-node/ &ps_nub_spmi0; +/delete-node/ &ps_nub_spmi_a2; +/delete-node/ &ps_nub_spi0; +/delete-node/ &ps_nub_aon; +/delete-node/ &ps_nub_ocla; +/delete-node/ &ps_atc3_common_dp; +/delete-node/ &ps_nub_spmi1; +/delete-node/ &ps_atc3_usb_aon; +/delete-node/ &ps_nub_spmi2; +/delete-node/ &ps_nub_spmi3; +/delete-node/ &ps_nub_spmi4; +/delete-node/ &sep; +/delete-node/ &dcuart; +/delete-node/ &spi2; +/delete-node/ &spi4; +/delete-node/ &qspi; +/delete-node/ &nub_spmi1; +/delete-node/ &nub_spmi2; +/delete-node/ &nub_spmi3; +/delete-node/ &nub_spmi4; +/delete-node/ &aop_spmi0; +/delete-node/ &ave; + +/delete-node/ &aop_accel; +/delete-node/ &aop_gyro; +/delete-node/ &pmc_soc_max; +/delete-node/ &pmu_rtc; + +/ { + /delete-node/ pmu; +}; + +&avd { + power-domains = <&ps_avd_sys>; + /delete-property/ power-domain-names; +}; + +&nub_spmi0 { + /delete-property/ interrupt-controller; + /delete-property/ #interrupt-cells; + /delete-property/ interrupt-parent; + /delete-property/ interrupts; +}; + +&usb_drd0_dart_0 { + /delete-property/ apple,dma-range; +}; + +&usb_drd0_dart_1 { + /delete-property/ apple,dma-range; +}; + +&usb_drd1_dart_0 { + /delete-property/ apple,dma-range; +}; + +&usb_drd1_dart_1 { + /delete-property/ apple,dma-range; +}; + +&usb_drd2_dart_0 { + /delete-property/ apple,dma-range; +}; + +&usb_drd2_dart_1 { + /delete-property/ apple,dma-range; +}; + +&mtp_dart { + /delete-property/ apple,dma-range; +}; + +&{/opp-table-e/opp01} { + /delete-property/ opp-microwatt; +}; + +&{/opp-table-e/opp02} { + /delete-property/ opp-microwatt; +}; + +&{/opp-table-e/opp03} { + /delete-property/ opp-microwatt; +}; + +&{/opp-table-e/opp04} { + /delete-property/ opp-microwatt; +}; + +&{/opp-table-e/opp05} { + /delete-property/ opp-microwatt; +}; + +&{/opp-table-e/opp06} { + /delete-property/ opp-microwatt; +}; + +&{/opp-table-e/opp07} { + /delete-property/ opp-microwatt; +}; + +&ps_avd_sys { + /delete-property/ power-domains; +}; + +&ps_atc0_common { + /delete-property/ power-domains; +}; + +&ps_atc1_common { + /delete-property/ power-domains; +}; + +&ps_atc2_common { + /delete-property/ power-domains; +}; + +&ps_pmp { + /delete-property/ power-domains; +}; + +&ps_pms_sram { + /delete-property/ power-domains; +}; + +&serial0 { + /delete-property/ power-domains; + /delete-property/ status; +}; + +/delete-node/ &gpu; +/delete-node/ &gfx_mbox; +/delete-node/ &opp_p0; +/delete-node/ &opp_p1; + +/ { + opp_p0: opp-table-p0 { + compatible = "operating-points-v2"; + opp-shared; + + opp01 { + opp-hz = /bits/ 64 <1260000000>; + opp-level = <1>; + clock-latency-ns = <7200>; + }; + opp02 { + opp-hz = /bits/ 64 <1512000000>; + opp-level = <2>; + clock-latency-ns = <19000>; + }; + opp03 { + opp-hz = /bits/ 64 <1800000000>; + opp-level = <3>; + clock-latency-ns = <20000>; + }; + opp04 { + opp-hz = /bits/ 64 <2088000000>; + opp-level = <4>; + clock-latency-ns = <22000>; + }; + opp05 { + opp-hz = /bits/ 64 <2352000000>; + opp-level = <5>; + clock-latency-ns = <30000>; + }; + opp06 { + opp-hz = /bits/ 64 <2616000000>; + opp-level = <6>; + clock-latency-ns = <34000>; + }; + opp07 { + opp-hz = /bits/ 64 <2868000000>; + opp-level = <7>; + clock-latency-ns = <37000>; + }; + opp08 { + opp-hz = /bits/ 64 <3096000000>; + opp-level = <8>; + clock-latency-ns = <38000>; + }; + opp09 { + opp-hz = /bits/ 64 <3300000000>; + opp-level = <9>; + clock-latency-ns = <40000>; + }; + opp10 { + opp-hz = /bits/ 64 <3468000000>; + opp-level = <10>; + clock-latency-ns = <41000>; + }; + opp11 { + opp-hz = /bits/ 64 <3624000000>; + opp-level = <11>; + clock-latency-ns = <43000>; + }; + opp12 { + opp-hz = /bits/ 64 <3756000000>; + opp-level = <12>; + clock-latency-ns = <44000>; + }; + opp13 { + opp-hz = /bits/ 64 <3828000000>; + opp-level = <13>; + clock-latency-ns = <45000>; + }; + opp14 { + opp-hz = /bits/ 64 <3888000000>; + opp-level = <14>; + clock-latency-ns = <46000>; + }; + opp15 { + opp-hz = /bits/ 64 <3948000000>; + opp-level = <15>; + clock-latency-ns = <47000>; + }; + opp16 { + opp-hz = /bits/ 64 <3996000000>; + opp-level = <16>; + clock-latency-ns = <48000>; + }; + opp17 { + opp-hz = /bits/ 64 <4044000000>; + opp-level = <17>; + clock-latency-ns = <49000>; + }; + opp18 { + opp-hz = /bits/ 64 <4104000000>; + opp-level = <18>; + clock-latency-ns = <50000>; + }; + opp19 { + opp-hz = /bits/ 64 <4416000000>; + opp-level = <19>; + clock-latency-ns = <55000>; + turbo-mode; + }; + opp20 { + opp-hz = /bits/ 64 <4512000000>; + opp-level = <20>; + clock-latency-ns = <56000>; + turbo-mode; + }; + }; + + opp_p1: opp-table-p1 { + compatible = "operating-points-v2"; + opp-shared; + + opp01 { + opp-hz = /bits/ 64 <1260000000>; + opp-level = <1>; + clock-latency-ns = <7200>; + }; + opp02 { + opp-hz = /bits/ 64 <1512000000>; + opp-level = <2>; + clock-latency-ns = <19000>; + }; + opp03 { + opp-hz = /bits/ 64 <1800000000>; + opp-level = <3>; + clock-latency-ns = <20000>; + }; + opp04 { + opp-hz = /bits/ 64 <2088000000>; + opp-level = <4>; + clock-latency-ns = <22000>; + }; + opp05 { + opp-hz = /bits/ 64 <2352000000>; + opp-level = <5>; + clock-latency-ns = <30000>; + }; + opp06 { + opp-hz = /bits/ 64 <2616000000>; + opp-level = <6>; + clock-latency-ns = <34000>; + }; + opp07 { + opp-hz = /bits/ 64 <2868000000>; + opp-level = <7>; + clock-latency-ns = <37000>; + }; + opp08 { + opp-hz = /bits/ 64 <3096000000>; + opp-level = <8>; + clock-latency-ns = <38000>; + }; + opp09 { + opp-hz = /bits/ 64 <3300000000>; + opp-level = <9>; + clock-latency-ns = <40000>; + }; + opp10 { + opp-hz = /bits/ 64 <3468000000>; + opp-level = <10>; + clock-latency-ns = <41000>; + }; + opp11 { + opp-hz = /bits/ 64 <3624000000>; + opp-level = <11>; + clock-latency-ns = <43000>; + }; + opp12 { + opp-hz = /bits/ 64 <3756000000>; + opp-level = <12>; + clock-latency-ns = <44000>; + }; + opp13 { + opp-hz = /bits/ 64 <3828000000>; + opp-level = <13>; + clock-latency-ns = <45000>; + }; + opp14 { + opp-hz = /bits/ 64 <3888000000>; + opp-level = <14>; + clock-latency-ns = <46000>; + }; + opp15 { + opp-hz = /bits/ 64 <3948000000>; + opp-level = <15>; + clock-latency-ns = <47000>; + }; + opp16 { + opp-hz = /bits/ 64 <3996000000>; + opp-level = <16>; + clock-latency-ns = <48000>; + }; + opp17 { + opp-hz = /bits/ 64 <4044000000>; + opp-level = <17>; + clock-latency-ns = <49000>; + }; + opp18 { + opp-hz = /bits/ 64 <4104000000>; + opp-level = <18>; + clock-latency-ns = <50000>; + }; + opp19 { + opp-hz = /bits/ 64 <4416000000>; + opp-level = <19>; + clock-latency-ns = <55000>; + turbo-mode; + }; + opp20 { + opp-hz = /bits/ 64 <4512000000>; + opp-level = <20>; + clock-latency-ns = <56000>; + turbo-mode; + }; + }; + +}; + +&cpu_p00 { + enable-method = "spin-table"; + cpu-release-addr = <0 0>; +}; + +&aic { + reg = <0x5 0x02400000 0x0 0x1cc000>, + <0x5 0x02440000 0x0 0x4>; +}; + +&smc { + reg = <0x5 0x0c600000 0x0 0x4000>, + <0x5 0x0de00000 0x0 0x170000>; +}; + +&pmc { + /delete-property/ apple,pmp; + apple,static-voters = <1 3>; +}; + +/ { + gpu: gpu@288000000 { + compatible = "apple,agx-t6041"; + reg = <0x2 0x8a600000 0x0 0x88000>, + <0x2 0x88000000 0x0 0x3758000>; + reg-names = "asc", "sgx"; + mboxes = <&gfx_mbox>; + power-domains = <&ps_gfx>; + status = "disabled"; + }; + + gfx_mbox: mailbox@28a600000 { + compatible = "apple,t6041-ascwrap-v6", "apple,t6040-ascwrap-v6"; + reg = <0x2 0x8a600000 0x0 0x88000>, + <0x2 0x8a050000 0x0 0x8>; + reg-names = "wrapper", "iop-vbar"; + interrupt-parent = <&aic>; + interrupts = , + ; + interrupt-names = "send-empty", "recv-not-empty"; + apple,firmware-role = "GFX"; + power-domains = <&ps_gfx>; + #mbox-cells = <0>; + status = "disabled"; + }; +}; + +&ps_afr { + apple,always-on; + apple,no-auto-pm; +}; + +&ps_gfx { + apple,always-on; + apple,no-auto-pm; +}; diff --git a/arch/arm64/boot/dts/apple/t6040-pmgr.dtsi b/arch/arm64/boot/dts/apple/t604x-pmgr.dtsi similarity index 100% rename from arch/arm64/boot/dts/apple/t6040-pmgr.dtsi rename to arch/arm64/boot/dts/apple/t604x-pmgr.dtsi diff --git a/arch/arm64/boot/dts/apple/t604x.dtsi b/arch/arm64/boot/dts/apple/t604x.dtsi new file mode 100644 index 0000000000000..178f1b061283e --- /dev/null +++ b/arch/arm64/boot/dts/apple/t604x.dtsi @@ -0,0 +1,2471 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * Apple T604x SoC base + * + * Unit addresses are the Apple Device Tree's /arm-io addresses plus the + * 0x2_00000000 arm-io base. The nodes sit at the root, not under a + * simple-bus: the boot loader edits several of them by path. The blocks + * known to need non-posted writes carry nonposted-mmio themselves. + * + * Copyright The Asahi Linux Contributors + */ + +#include +#include +#include +#include +#include +#include + +/ { + #address-cells = <2>; + #size-cells = <2>; + + cpuidle: cpuidle { + compatible = "apple,t6041-cpuidle"; + status = "disabled"; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + /* + * The clusters are MPIDR Aff1, which are also the L2 groups. + * capacity-dmips-mhz comes from pinned single-core throughput + * at the lowest p-state (E 1018 MHz, P 1257 MHz): E/P is 0.652 + * per MHz, so E 668 and P 1024. + */ + cpu-map { + cluster0 { + core0 { + cpu = <&cpu_e0>; + }; + core1 { + cpu = <&cpu_e1>; + }; + core2 { + cpu = <&cpu_e2>; + }; + core3 { + cpu = <&cpu_e3>; + }; + }; + + cluster1 { + core0 { + cpu = <&cpu_p00>; + }; + core1 { + cpu = <&cpu_p01>; + }; + core2 { + cpu = <&cpu_p02>; + }; + core3 { + cpu = <&cpu_p03>; + }; + core4 { + cpu = <&cpu_p04>; + }; + core5 { + cpu = <&cpu_p05>; + }; + }; + + cluster2 { + core0 { + cpu = <&cpu_p10>; + }; + core1 { + cpu = <&cpu_p11>; + }; + core2 { + cpu = <&cpu_p12>; + }; + core3 { + cpu = <&cpu_p13>; + }; + core4 { + cpu = <&cpu_p14>; + }; + core5 { + cpu = <&cpu_p15>; + }; + }; + }; + + /* m1n1 requires CPU nodes in MPIDR order. */ + cpu_e0: cpu@0 { + compatible = "apple,brava-e"; + device_type = "cpu"; + reg = <0x0 0x0>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_e>; + operating-points-v2 = <&opp_e>; + capacity-dmips-mhz = <668>; + performance-domains = <&cpufreq_e>; + #cooling-cells = <2>; + }; + + cpu_e1: cpu@1 { + compatible = "apple,brava-e"; + device_type = "cpu"; + reg = <0x0 0x1>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_e>; + operating-points-v2 = <&opp_e>; + capacity-dmips-mhz = <668>; + performance-domains = <&cpufreq_e>; + #cooling-cells = <2>; + }; + + cpu_e2: cpu@2 { + compatible = "apple,brava-e"; + device_type = "cpu"; + reg = <0x0 0x2>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_e>; + operating-points-v2 = <&opp_e>; + capacity-dmips-mhz = <668>; + performance-domains = <&cpufreq_e>; + #cooling-cells = <2>; + }; + + cpu_e3: cpu@3 { + compatible = "apple,brava-e"; + device_type = "cpu"; + reg = <0x0 0x3>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_e>; + operating-points-v2 = <&opp_e>; + capacity-dmips-mhz = <668>; + performance-domains = <&cpufreq_e>; + #cooling-cells = <2>; + }; + + /* The boot CPU: the boot loader enters the kernel on it. */ + cpu_p00: cpu@10100 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10100>; + next-level-cache = <&l2_cache_p0>; + operating-points-v2 = <&opp_p0>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p0>; + #cooling-cells = <2>; + }; + + cpu_p01: cpu@10101 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10101>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_p0>; + operating-points-v2 = <&opp_p0>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p0>; + #cooling-cells = <2>; + }; + + cpu_p02: cpu@10102 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10102>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_p0>; + operating-points-v2 = <&opp_p0>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p0>; + #cooling-cells = <2>; + }; + + cpu_p03: cpu@10103 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10103>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_p0>; + operating-points-v2 = <&opp_p0>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p0>; + #cooling-cells = <2>; + }; + + cpu_p04: cpu@10104 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10104>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_p0>; + operating-points-v2 = <&opp_p0>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p0>; + #cooling-cells = <2>; + }; + + cpu_p05: cpu@10105 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10105>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; + next-level-cache = <&l2_cache_p0>; + operating-points-v2 = <&opp_p0>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p0>; + #cooling-cells = <2>; + }; + + cpu_p10: cpu@10200 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10200>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_p1>; + operating-points-v2 = <&opp_p1>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p1>; + #cooling-cells = <2>; + }; + + cpu_p11: cpu@10201 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10201>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_p1>; + operating-points-v2 = <&opp_p1>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p1>; + #cooling-cells = <2>; + }; + + cpu_p12: cpu@10202 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10202>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_p1>; + operating-points-v2 = <&opp_p1>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p1>; + #cooling-cells = <2>; + }; + + cpu_p13: cpu@10203 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10203>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_p1>; + operating-points-v2 = <&opp_p1>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p1>; + #cooling-cells = <2>; + }; + + cpu_p14: cpu@10204 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10204>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + next-level-cache = <&l2_cache_p1>; + operating-points-v2 = <&opp_p1>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p1>; + #cooling-cells = <2>; + }; + + cpu_p15: cpu@10205 { + compatible = "apple,brava-p"; + device_type = "cpu"; + reg = <0x0 0x10205>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; + next-level-cache = <&l2_cache_p1>; + operating-points-v2 = <&opp_p1>; + capacity-dmips-mhz = <1024>; + performance-domains = <&cpufreq_p1>; + #cooling-cells = <2>; + }; + }; + + l2_cache_e: l2-cache-cluster0 { + compatible = "cache"; + cache-level = <2>; + cache-unified; + cache-size = <0x400000>; + }; + + l2_cache_p0: l2-cache-cluster1 { + compatible = "cache"; + cache-level = <2>; + cache-unified; + cache-size = <0x1000000>; + }; + + l2_cache_p1: l2-cache-cluster2 { + compatible = "cache"; + cache-level = <2>; + cache-unified; + cache-size = <0x1000000>; + }; + + /* + * DVFS states from the ADT: /arm-io/pmgr voltage-states1-sram (E), + * voltage-states5-sram (P0) and voltage-states13-sram (P1), word 0 + * in kHz. opp-level is the hardware p-state. Each P cluster has its + * own table even though the frequencies are the same: opp-shared + * means one clock domain per table. + * + * opp-microwatt is the power of one busy core, measured on a J616s + * from the SMC core-rail meters (P0 PR0b, P1 PP0b, E PP2b) with the + * cluster pinned at each state. The P values follow a k * V^2 * f + c + * fit to the sweep, because the PMP's die-temperature limit clips the + * two top states within seconds. One busy E core does not register on + * its meter below 2352 MHz, so the E values are the idle cluster plus + * a quarter of the four-core increase. + */ + opp_e: opp-table-e { + compatible = "operating-points-v2"; + opp-shared; + + opp01 { + opp-hz = /bits/ 64 <1020000000>; + opp-level = <1>; + opp-microwatt = <81900>; + }; + opp02 { + opp-hz = /bits/ 64 <1404000000>; + opp-level = <2>; + opp-microwatt = <133100>; + }; + opp03 { + opp-hz = /bits/ 64 <1788000000>; + opp-level = <3>; + opp-microwatt = <209400>; + }; + opp04 { + opp-hz = /bits/ 64 <2112000000>; + opp-level = <4>; + opp-microwatt = <301400>; + }; + opp05 { + opp-hz = /bits/ 64 <2352000000>; + opp-level = <5>; + opp-microwatt = <383900>; + }; + opp06 { + opp-hz = /bits/ 64 <2532000000>; + opp-level = <6>; + opp-microwatt = <478500>; + }; + opp07 { + opp-hz = /bits/ 64 <2592000000>; + opp-level = <7>; + opp-microwatt = <531000>; + }; + }; + + opp_p0: opp-table-p0 { + compatible = "operating-points-v2"; + opp-shared; + + opp01 { + opp-hz = /bits/ 64 <1260000000>; + opp-level = <1>; + opp-microwatt = <513000>; + }; + opp02 { + opp-hz = /bits/ 64 <1512000000>; + opp-level = <2>; + opp-microwatt = <715000>; + }; + opp03 { + opp-hz = /bits/ 64 <1800000000>; + opp-level = <3>; + opp-microwatt = <907500>; + }; + opp04 { + opp-hz = /bits/ 64 <2088000000>; + opp-level = <4>; + opp-microwatt = <1158200>; + }; + opp05 { + opp-hz = /bits/ 64 <2352000000>; + opp-level = <5>; + opp-microwatt = <1494500>; + }; + opp06 { + opp-hz = /bits/ 64 <2616000000>; + opp-level = <6>; + opp-microwatt = <1782600>; + }; + opp07 { + opp-hz = /bits/ 64 <2868000000>; + opp-level = <7>; + opp-microwatt = <2209600>; + }; + opp08 { + opp-hz = /bits/ 64 <3096000000>; + opp-level = <8>; + opp-microwatt = <2636700>; + }; + opp09 { + opp-hz = /bits/ 64 <3300000000>; + opp-level = <9>; + opp-microwatt = <3247200>; + }; + opp10 { + opp-hz = /bits/ 64 <3468000000>; + opp-level = <10>; + opp-microwatt = <3668700>; + }; + opp11 { + opp-hz = /bits/ 64 <3624000000>; + opp-level = <11>; + opp-microwatt = <4128200>; + }; + opp12 { + opp-hz = /bits/ 64 <3756000000>; + opp-level = <12>; + opp-microwatt = <4819300>; + }; + opp13 { + opp-hz = /bits/ 64 <3852000000>; + opp-level = <13>; + opp-microwatt = <4977700>; + }; + opp14 { + opp-hz = /bits/ 64 <3924000000>; + opp-level = <14>; + opp-microwatt = <5315900>; + }; + opp15 { + opp-hz = /bits/ 64 <3996000000>; + opp-level = <15>; + opp-microwatt = <5575900>; + }; + opp16 { + opp-hz = /bits/ 64 <4044000000>; + opp-level = <16>; + opp-microwatt = <5773400>; + }; + opp17 { + opp-hz = /bits/ 64 <4104000000>; + opp-level = <17>; + opp-microwatt = <5969200>; + }; + opp18 { + opp-hz = /bits/ 64 <4416000000>; + opp-level = <18>; + opp-microwatt = <8274900>; + }; + opp19 { + opp-hz = /bits/ 64 <4512000000>; + opp-level = <19>; + opp-microwatt = <9256900>; + }; + }; + + opp_p1: opp-table-p1 { + compatible = "operating-points-v2"; + opp-shared; + + opp01 { + opp-hz = /bits/ 64 <1260000000>; + opp-level = <1>; + opp-microwatt = <561800>; + }; + opp02 { + opp-hz = /bits/ 64 <1512000000>; + opp-level = <2>; + opp-microwatt = <772500>; + }; + opp03 { + opp-hz = /bits/ 64 <1800000000>; + opp-level = <3>; + opp-microwatt = <988900>; + }; + opp04 { + opp-hz = /bits/ 64 <2088000000>; + opp-level = <4>; + opp-microwatt = <1302300>; + }; + opp05 { + opp-hz = /bits/ 64 <2352000000>; + opp-level = <5>; + opp-microwatt = <1644100>; + }; + opp06 { + opp-hz = /bits/ 64 <2616000000>; + opp-level = <6>; + opp-microwatt = <2003700>; + }; + opp07 { + opp-hz = /bits/ 64 <2868000000>; + opp-level = <7>; + opp-microwatt = <2349000>; + }; + opp08 { + opp-hz = /bits/ 64 <3096000000>; + opp-level = <8>; + opp-microwatt = <2723000>; + }; + opp09 { + opp-hz = /bits/ 64 <3300000000>; + opp-level = <9>; + opp-microwatt = <3333200>; + }; + opp10 { + opp-hz = /bits/ 64 <3468000000>; + opp-level = <10>; + opp-microwatt = <3711900>; + }; + opp11 { + opp-hz = /bits/ 64 <3624000000>; + opp-level = <11>; + opp-microwatt = <4129900>; + }; + opp12 { + opp-hz = /bits/ 64 <3756000000>; + opp-level = <12>; + opp-microwatt = <4666300>; + }; + opp13 { + opp-hz = /bits/ 64 <3852000000>; + opp-level = <13>; + opp-microwatt = <4881000>; + }; + opp14 { + opp-hz = /bits/ 64 <3924000000>; + opp-level = <14>; + opp-microwatt = <5176700>; + }; + opp15 { + opp-hz = /bits/ 64 <3996000000>; + opp-level = <15>; + opp-microwatt = <5306500>; + }; + opp16 { + opp-hz = /bits/ 64 <4044000000>; + opp-level = <16>; + opp-microwatt = <5618900>; + }; + opp17 { + opp-hz = /bits/ 64 <4104000000>; + opp-level = <17>; + opp-microwatt = <5843100>; + }; + opp18 { + opp-hz = /bits/ 64 <4416000000>; + opp-level = <18>; + opp-microwatt = <8075300>; + }; + opp19 { + opp-hz = /bits/ 64 <4512000000>; + opp-level = <19>; + opp-microwatt = <8949200>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&aic>; + interrupt-names = "phys", "virt", "hyp-phys", "hyp-virt"; + interrupts = , + , + , + ; + }; + + pmu { + compatible = "apple,t6040-pmu"; + interrupt-parent = <&aic>; + /* The AIC raises both clusters' PMU FIQs as this one. */ + interrupts = ; + }; + + /* The 24 MHz reference clock (ADT clock-ids 4) of the I2C, PWM and watchdog blocks */ + clkref: clock-ref { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "clkref"; + }; + + /* + * Display component master. It has no registers; the boot loader + * enables it with the DCP when it hands the display over. + */ + display: display-subsystem { + compatible = "apple,display-subsystem"; + iommus = <&disp0_dart 0>; + status = "disabled"; + }; + + cpufreq_e: cpufreq@210e20000 { + compatible = "apple,t6041-cluster-cpufreq", "apple,t8112-cluster-cpufreq"; + reg = <0x2 0x10e20000 0x0 0x1000>; + nonposted-mmio; + #performance-domain-cells = <0>; + /* PMP fast die-temperature effort, byte 0 of FAST-DIE-CE */ + apple,fast-die-effort = <&pmp_report 0>; + }; + + cpufreq_p0: cpufreq@211e20000 { + compatible = "apple,t6041-cluster-cpufreq", "apple,t8112-cluster-cpufreq"; + reg = <0x2 0x11e20000 0x0 0x1000>; + nonposted-mmio; + #performance-domain-cells = <0>; + apple,fast-die-effort = <&pmp_report 1>; + }; + + cpufreq_p1: cpufreq@212e20000 { + compatible = "apple,t6041-cluster-cpufreq", "apple,t8112-cluster-cpufreq"; + reg = <0x2 0x12e20000 0x0 0x1000>; + nonposted-mmio; + #performance-domain-cells = <0>; + apple,fast-die-effort = <&pmp_report 2>; + }; + + /* + * System level cache planes: four AMCCs with four planes each. + * Allocation waits for the display, which takes over the scan-out DMA + * the boot loader left running. + */ + mcc: memory-controller@220000000 { + compatible = "apple,t6041-mcc", "apple,t8140-mcc"; + reg = <0x2 0x20000000 0x0 0x4000>, + <0x2 0x20040000 0x0 0x4000>, + <0x2 0x20080000 0x0 0x4000>, + <0x2 0x200c0000 0x0 0x4000>, + <0x2 0x22000000 0x0 0x4000>, + <0x2 0x22040000 0x0 0x4000>, + <0x2 0x22080000 0x0 0x4000>, + <0x2 0x220c0000 0x0 0x4000>, + <0x2 0x24000000 0x0 0x4000>, + <0x2 0x24040000 0x0 0x4000>, + <0x2 0x24080000 0x0 0x4000>, + <0x2 0x240c0000 0x0 0x4000>, + <0x2 0x26000000 0x0 0x4000>, + <0x2 0x26040000 0x0 0x4000>, + <0x2 0x26080000 0x0 0x4000>, + <0x2 0x260c0000 0x0 0x4000>; + nonposted-mmio; + apple,boot-dma-devices = <&display>; + status = "disabled"; + }; + + /* + * The decoder firmware programs the T8122/T8132 register family, so + * the driver binds through its T8132 entry. The ADT gives the whole + * block (0x2_80000000, 0x1404000); the windows follow the T6030/T8140 + * layout, with the CM3 SRAM between its code and the mailbox. + */ + avd: avd@280000000 { + compatible = "apple,t6041-avd", "apple,t8132-avd"; + reg = <0x2 0x81080000 0x0 0x14000>, + <0x2 0x81094000 0x0 0x14000>, + <0x2 0x810a8000 0x0 0x4000>, + <0x2 0x81100000 0x0 0x10000>; + reg-names = "code", "sram", "mbox", "ctrl"; + interrupt-parent = <&aic>; + interrupts = , + ; + power-domains = <&ps_avd_sys>, <&pmc_soc_max>; + power-domain-names = "core", "perf"; + resets = <&ps_avd_sys>; + iommus = <&avd_dart 0>; + }; + + avd_dart: iommu@281020000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x2 0x81020000 0x0 0xc000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_avd_sys>; + }; + + /* Named after its sgx range: the coprocessor range is the mailbox node's too. */ + gpu: gpu@288000000 { + compatible = "apple,agx-t6040"; + reg = <0x2 0x8a600000 0x0 0x88000>, + <0x2 0x88000000 0x0 0x3758000>; + reg-names = "asc", "sgx"; + mboxes = <&gfx_mbox>; + power-domains = <&pmp_gfx>; + apple,clpc = <&clpc>; + status = "disabled"; + }; + + pmgr_gfx: power-management@288e80000 { + compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x2 0x88e80000 0x0 0x4000>; + /* child nodes are added in t604x-pmgr.dtsi */ + }; + + gfx_mbox: mailbox@28a600000 { + compatible = "apple,t6040-ascwrap-v6"; + reg = <0x2 0x8a600000 0x0 0x88000>, + <0x2 0x8a050000 0x0 0x8>; + reg-names = "wrapper", "iop-vbar"; + interrupt-parent = <&aic>; + interrupts = , + ; + interrupt-names = "send-empty", "recv-not-empty"; + apple,firmware-role = "GFX"; + power-domains = <&ps_gfx>; + #mbox-cells = <0>; + status = "disabled"; + }; + + disp0_dart: iommu@402300000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x02300000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + dcp_dart: iommu@402340000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x02340000 0x0 0x20000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + dcp: dcp@402e00000 { + compatible = "apple,t6041-dcp", "apple,dcp"; + reg = <0x4 0x02e00000 0x0 0x4000>, + <0x4 0x00000000 0x0 0x4000000>, + <0x4 0x02240000 0x0 0x10000>, + <0x4 0x023a8000 0x0 0x4000>, + <0x4 0x02800000 0x0 0x800000>; + reg-names = "coproc", "disp-0", "disp-1", "disp-2", "disp-3"; + mboxes = <&dcp_mbox>; + mbox-names = "mbox"; + iommus = <&dcp_dart 23>; + apple,bw-scratch = <&pmgr_dcp 0 4 0x20000>; + apple,iomfb-surfaces = <1 1 0 0>; + /* the boot loader describes the piodma's regions with 2+2 cells */ + #address-cells = <2>; + #size-cells = <2>; + /* enabled once the boot loader has handed the display over */ + status = "disabled"; + + disp0_piodma: piodma { + iommus = <&disp0_dart 16>; + }; + }; + + dcp_mbox: mailbox@402e08000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x4 0x02e08000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + status = "disabled"; + }; + + /* + * iBoot hands over a running SEP. Keep Linux off its DART at boot; + * apple_sep enables it when the driver binds. The SEP only accepts + * IOVAs in the window iBoot programmed (ADT vm-base 0x10000004000, + * vm-size 0x3ff00000), which carries the BIT(40) alias the DART + * translates. + */ + sep_dart: iommu@404c80000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x04c80000 0x0 0x20000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = /bits/ 64 <0x10000004000 0x3ff00000>; + apple,dma-offset = /bits/ 64 <0x0>; + status = "disabled"; + }; + + sep: sep@406600000 { + compatible = "apple,sep"; + reg = <0x4 0x06600000 0x0 0x88000>; + mboxes = <&sep_mbox>; + mbox-names = "mbox"; + iommus = <&sep_dart 0>; + power-domains = <&ps_sep>; + status = "disabled"; + }; + + sep_mbox: mailbox@406608000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x4 0x06608000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + status = "disabled"; + }; + + ans_mbox: mailbox@409608000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x4 0x09608000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + power-domains = <&ps_ans>; + #mbox-cells = <0>; + status = "disabled"; + }; + + ans_sart: sart@40dc50000 { + compatible = "apple,t6041-sart", "apple,t6000-sart"; + reg = <0x4 0x0dc50000 0x0 0xc000>; + power-domains = <&ps_ans>; + status = "disabled"; + }; + + pcie_dart: iommu@410000000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x10000000 0x0 0x20000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + /* iBoot leaves the I2C gates on and the pins muxed to I2C. */ + i2c1: i2c@429014000 { + compatible = "apple,t6041-i2c", "apple,t8103-i2c"; + reg = <0x4 0x29014000 0x0 0x4000>; + clocks = <&clkref>; + interrupt-parent = <&aic>; + interrupts = ; + pinctrl-0 = <&i2c1_pins>; + pinctrl-names = "default"; + power-domains = <&ps_i2c1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@429018000 { + compatible = "apple,t6041-i2c", "apple,t8103-i2c"; + reg = <0x4 0x29018000 0x0 0x4000>; + clocks = <&clkref>; + interrupt-parent = <&aic>; + interrupts = ; + pinctrl-0 = <&i2c2_pins>; + pinctrl-names = "default"; + power-domains = <&ps_i2c2>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c3: i2c@42901c000 { + compatible = "apple,t6041-i2c", "apple,t8103-i2c"; + reg = <0x4 0x2901c000 0x0 0x4000>; + clocks = <&clkref>; + interrupt-parent = <&aic>; + interrupts = ; + pinctrl-0 = <&i2c3_pins>; + pinctrl-names = "default"; + power-domains = <&ps_i2c3>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c4: i2c@429020000 { + compatible = "apple,t6041-i2c", "apple,t8103-i2c"; + reg = <0x4 0x29020000 0x0 0x4000>; + clocks = <&clkref>; + interrupt-parent = <&aic>; + interrupts = ; + pinctrl-0 = <&i2c4_pins>; + pinctrl-names = "default"; + power-domains = <&ps_i2c4>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c6: i2c@429028000 { + compatible = "apple,t6041-i2c", "apple,t8103-i2c"; + reg = <0x4 0x29028000 0x0 0x4000>; + clocks = <&clkref>; + interrupt-parent = <&aic>; + interrupts = ; + pinctrl-0 = <&i2c6_pins>; + pinctrl-names = "default"; + power-domains = <&ps_i2c6>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c8: i2c@429030000 { + compatible = "apple,t6041-i2c", "apple,t8103-i2c"; + reg = <0x4 0x29030000 0x0 0x4000>; + clocks = <&clkref>; + interrupt-parent = <&aic>; + interrupts = ; + pinctrl-0 = <&i2c8_pins>; + pinctrl-names = "default"; + power-domains = <&ps_i2c8>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + fpwm0: pwm@429040000 { + compatible = "apple,t6041-fpwm", "apple,s5l-fpwm"; + reg = <0x4 0x29040000 0x0 0x4000>; + clocks = <&clkref>; + power-domains = <&ps_fpwm0>; + #pwm-cells = <2>; + status = "disabled"; + }; + + /* + * Touch ID. iBoot leaves the pads muxed and the controller uses its + * native chip select, so there is no pinctrl here. + */ + spi2: spi@429108000 { + compatible = "apple,t6041-spi", "apple,t8103-spi"; + reg = <0x4 0x29108000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + clocks = <&clkref>; + power-domains = <&ps_spi2>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + mesa: fingerprint@0 { + compatible = "apple,mesa-fingerprint"; + reg = <0>; + spi-max-frequency = <8000000>; + spi-cpol; + status = "disabled"; + }; + }; + + nvme: nvme@44dcc0000 { + compatible = "apple,t6041-nvme-ans2"; + reg = <0x4 0x4dcc0000 0x0 0x10000>, + <0x4 0x09600000 0x0 0x4000>, + <0x4 0x0dcc0000 0x0 0x60000>; + reg-names = "nvme", "ans", "nvmmu"; + interrupt-parent = <&aic>; + interrupts = ; + mboxes = <&ans_mbox>; + apple,sart = <&ans_sart>; + power-domains = <&ps_ans>, <&ps_apcie_sys_st0>, + <&ps_apcie_sys_st1>; + power-domain-names = "ans", "apcie0", "apcie1"; + resets = <&ps_ans>; + status = "disabled"; + }; + + /* + * PMP (power management coprocessor). iBoot locks its DART (PROTECT + * 0x1e7, SIDs 0 and 1 translating): apple-dart adopts iBoot's SID 0 + * table and leaves SID 1 alone. apple,dma-range keeps Linux's IOVAs + * in the ADT window (vm-base 0x100_0000_0000, 64 GiB). The DART's + * second ADT range is the SoC's shared clock-protection block, not + * part of the DART. + */ + pmp_dart: iommu@500300000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x5 0x00300000 0x0 0xc000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_pmp>; + status = "disabled"; + }; + + /* + * Report (PTD) region: reads 16 bytes per entry at +0x0, writes 8 + * bytes per entry at +0x10000. Entries are PMP soc-devices; every + * entry reads 0 while the PMP is stopped. + */ + pmp_report: pmp-report@5003c0000 { + compatible = "apple,t6041-pmp-v2-report"; + reg = <0x5 0x003c0000 0x0 0x20000>; + nonposted-mmio; + power-domains = <&ps_pms_sram>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + /* The CPU clusters, for their fast die-temperature loops */ + report@a { + compatible = "apple,t6041-pmp-v2-report-entry", + "apple,t6000-pmp-v2-report-entry"; + reg = <0xa>; + label = "pmp-eacc0"; + #power-domain-cells = <0>; + apple,always-on; + }; + + report@b { + compatible = "apple,t6041-pmp-v2-report-entry", + "apple,t6000-pmp-v2-report-entry"; + reg = <0xb>; + label = "pmp-pacc0"; + #power-domain-cells = <0>; + apple,always-on; + }; + + report@c { + compatible = "apple,t6041-pmp-v2-report-entry", + "apple,t6000-pmp-v2-report-entry"; + reg = <0xc>; + label = "pmp-pacc1"; + #power-domain-cells = <0>; + apple,always-on; + }; + + /* + * The GPU (soc-device 13). Without it the running PMP treats + * the GPU as off and holds it at its lowest state, but claiming + * it while nothing powers the GPU crashes the PMP firmware + * (SError) right after it starts. It sits on the GPU's own + * power state. The GPU consumer takes this domain, so the request + * follows the GFX domain's power lifetime. + */ + pmp_gfx: report@d { + compatible = "apple,t6041-pmp-v2-report-entry", + "apple,t6000-pmp-v2-report-entry"; + reg = <0xd>; + label = "pmp-gfx"; + #power-domain-cells = <0>; + power-domains = <&ps_gfx>; + }; + }; + + /* + * The boot loader adds the per-unit properties (board, DRAM) and the + * firmware tunables the driver needs before it starts the PMP. + */ + pmp: pmp@500700000 { + compatible = "apple,t6041-pmp-v2", "apple,t6000-pmp-v2"; + reg = <0x5 0x00700000 0x0 0xe0000>, + <0x5 0x00e00000 0x0 0x4000>; + reg-names = "pmp", "asc"; + mboxes = <&pmp_mbox>; + mbox-names = "mbox"; + iommus = <&pmp_dart 0>; + power-domains = <&ps_pmp>; + apple,pmc = <1>; + apple,pmc-pmgr = <0x3f>; + status = "disabled"; + }; + + pmp_mbox: mailbox@500e08000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x5 0x00e08000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + power-domains = <&ps_pmp>, <&ps_pms_sram>; + #mbox-cells = <0>; + status = "disabled"; + }; + + pmgr: power-management@502280000 { + compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x5 0x02280000 0x0 0x4000>; + /* child nodes are added in t604x-pmgr.dtsi */ + }; + + pmgr_ane: power-management@50228c000 { + compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; + reg = <0x5 0x0228c000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + }; + + pmgr_disp: power-management@502290000 { + compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; + reg = <0x5 0x02290000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + }; + + pmgr_venc: power-management@502808000 { + compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; + reg = <0x5 0x02808000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + }; + + pmgr_isp: power-management@502284000 { + compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x5 0x02284000 0x0 0x4000>; + /* child nodes are added in t604x-pmgr.dtsi */ + }; + + aic: interrupt-controller@502400000 { + compatible = "apple,t6041-aic3", "apple,t8122-aic3"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x5 0x02400000 0x0 0x184000>, + <0x5 0x02440000 0x0 0x4>; + reg-names = "core", "event"; + }; + + pmgr_aux: power-management@502800000 { + compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x5 0x02800000 0x0 0x4000>; + /* child nodes are added in t604x-pmgr.dtsi */ + }; + + /* + * The PMGR range the DCP driver hands to its firmware; apple,bw-scratch + * points into it. + */ + pmgr_dcp: power-management@504800000 { + reg = <0x5 0x04800000 0x0 0xbc000>; + reg-names = "dcp-fw-pmgr"; + #apple,bw-scratch-cells = <3>; + }; + + /* + * PMC voter interface: the floor word of agent a at "voters" + + * 0x4000 * a, the floors the PMC honours and the rail enable words + * at "rails". Both lie inside pmgr_dcp's range, which the DCP driver + * only hands to its firmware, so the two do not conflict; "rails" + * comes first so that this node's unit address differs from + * pmgr_dcp's. + * Static voters are the PMP (0), CLPC (1) and AP (3). The PMP votes + * the DCS and fabric for memory clients other than the CPUs, the GPU + * among them; without its agent, GPU work runs at a low DCS + * state unless a CPU is busy. iBoot leaves the PMP's floor at the top + * DCS state, so its agent must stay off while the PMP does not run: + * apple,pmp holds off the PMC until the PMP driver has bound, and + * unbinds the PMC first. + */ + pmc: power-management@5048aa000 { + compatible = "apple,t6041-pmc"; + reg = <0x5 0x048aa000 0x0 0x3000>, + <0x5 0x04800000 0x0 0x10000>; + reg-names = "rails", "voters"; + nonposted-mmio; + #address-cells = <1>; + #size-cells = <0>; + apple,pmp = <&pmp>; + apple,static-voters = <0 1 3>; + status = "disabled"; + + clpc: performance-controller@1 { + compatible = "apple,t6041-clpc"; + reg = <1>; + + }; + + /* + * The SoC rail at its highest state. The video encoder runs on + * the fabric clock and encodes at less than half speed below it. + */ + pmc_soc_max: floor-soc-max { + label = "soc-max"; + #power-domain-cells = <0>; + apple,rail = <1>; + apple,level = <2>; + }; + }; + + /* + * The always-on GPIO bank (ADT /arm-io/nub-gpio0, 61 pins). Its power + * state is in the always-on PMGR. + */ + pinctrl_nub: pinctrl@5081e4000 { + compatible = "apple,t6041-pinctrl", "apple,t8103-pinctrl"; + reg = <0x5 0x081e4000 0x0 0x4000>; + power-domains = <&ps_nub_gpio>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl_nub 0 0 61>; + apple,npins = <61>; + + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + , + , + ; + status = "disabled"; + }; + + pmgr_mini: power-management@508300000 { + compatible = "apple,t6041-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x5 0x08300000 0x0 0x4000>; + /* child nodes are added in t604x-pmgr.dtsi */ + }; + + /* + * The driver arms the reset only when userspace opens /dev/watchdog + * or the firmware left it running; it also provides restart. + */ + wdt: watchdog@50836c000 { + compatible = "apple,t6041-wdt", "apple,t8103-wdt"; + reg = <0x5 0x0836c000 0x0 0x4000>; + clocks = <&clkref>; + interrupt-parent = <&aic>; + interrupts = ; + }; + + nub_spmi0: spmi@509014000 { + compatible = "apple,t6041-spmi", "apple,t8103-spmi"; + reg = <0x5 0x09014000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <0>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + + pmic@e { + compatible = "apple,abbey-pmic", "apple,spmi-nvmem"; + reg = <0xe SPMI_USID>; + + pmu_rtc: rtc { + compatible = "apple,t6041-pmu-rtc"; + interrupt-parent = <&nub_spmi0>; + interrupts = <2 IRQ_TYPE_EDGE_RISING>; + nvmem-cells = <&rtc_offset>; + nvmem-cell-names = "rtc_offset"; + wakeup-source; + }; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + rtc_offset: rtc-offset@2100 { + reg = <0x2100 0x6>; + }; + + boot_stage: boot-stage@f801 { + reg = <0xf801 0x1>; + }; + + boot_error_count: boot-error-count@f802,0 { + reg = <0xf802 0x1>; + bits = <0 4>; + }; + + panic_count: panic-count@f802,4 { + reg = <0xf802 0x1>; + bits = <4 4>; + }; + + shutdown_flag: shutdown-flag@f80f,3 { + reg = <0xf80f 0x1>; + bits = <3 1>; + }; + }; + }; + }; + + smc: smc@50c600000 { + compatible = "apple,t6041-smc", "apple,t8103-smc"; + reg = <0x5 0x0c600000 0x0 0x4000>, + <0x5 0x0de70000 0x0 0x100000>; + reg-names = "smc", "sram"; + mboxes = <&smc_mbox>; + status = "disabled"; + + smc_gpio: gpio { + compatible = "apple,smc-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + + smc_hwmon: hwmon { + compatible = "apple,smc-hwmon"; + #thermal-sensor-cells = <1>; + }; + + smc_reboot: reboot { + compatible = "apple,smc-reboot"; + nvmem-cells = <&shutdown_flag>, <&boot_stage>, + <&boot_error_count>, <&panic_count>; + nvmem-cell-names = "shutdown_flag", "boot_stage", + "boot_error_count", "panic_count"; + }; + + smc_rtc: rtc { + compatible = "apple,smc-rtc"; + nvmem-cells = <&rtc_offset>; + nvmem-cell-names = "rtc_offset"; + }; + }; + + smc_mbox: mailbox@50c608000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x5 0x0c608000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + status = "disabled"; + }; + + /* + * AOP (always-on processor). The boot loader loads its RTKit firmware + * and leaves it stopped; Linux starts it. + */ + aop: aop@510600000 { + compatible = "apple,t6041-aop"; + reg = <0x5 0x10c10000 0x0 0x2e0000>, + <0x5 0x10600000 0x0 0x88000>, + <0x5 0x10050000 0x0 0x4000>, + <0x5 0x08328000 0x0 0x24>; + reg-names = "firmware", "asc", "asc-aux", "config"; + mboxes = <&aop_mbox>; + mbox-names = "mbox"; + iommus = <&aop_dart 0>; + status = "disabled"; + + /* + * "dma" is the microphones' LEAP ADMAC channel; "spkr" and + * "sense" are the speaker stream's base-ns ADMAC channels 0 and + * 1 (ADT audio-speaker dma-channels), "cout" and "cin" the + * headphone jack's channels 4 and 5 (TX2 and RX2, ADT + * audio-codec-output and audio-codec-input). + */ + aop_audio: audio { + compatible = "apple,t6041-aop-audio", "apple,t6030-aop-audio"; + dmas = <&admac0 1>, <&admac1 0>, <&admac1 1>, <&admac1 4>, + <&admac1 5>; + dma-names = "dma", "spkr", "sense", "cout", "cin"; + #sound-dai-cells = <1>; + }; + + aop_als: als { + compatible = "apple,t6041-aop-als", "apple,aop-als"; + }; + + aop_las: las { + compatible = "apple,t6041-aop-las", "apple,aop-las"; + }; + + /* The calibration properties come from the bootloader. */ + aop_accel: accel { + compatible = "apple,t6041-aop-accel", "apple,aop-accel"; + }; + + aop_gyro: gyro { + compatible = "apple,t6041-aop-gyro", "apple,aop-gyro"; + }; + }; + + /* ADT lists the interrupts as 1, 0, 3, 2 of the block: send-empty is the lowest. */ + aop_mbox: mailbox@510608000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x5 0x10608000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + status = "disabled"; + }; + + aop_dart: iommu@510f00000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x5 0x10f00000 0x0 0xc000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + /* The audio fabric's ADMACs: admac-leap-ns (DART stream 10) and admac-base-ns (stream 8) */ + admac0: dma-controller@513300000 { + compatible = "apple,t6041-admac", "apple,t8132-admac"; + reg = <0x5 0x13300000 0x0 0x34000>; + #dma-cells = <1>; + dma-channels = <18>; + /* the ADT gives the first of the four outputs */ + interrupts-extended = <&aic AIC_IRQ 757 IRQ_TYPE_LEVEL_HIGH>, + <0>, <0>, <0>; + iommus = <&aop_dart 10>; + status = "disabled"; + }; + + admac1: dma-controller@513800000 { + compatible = "apple,t6041-admac", "apple,t8132-admac"; + reg = <0x5 0x13800000 0x0 0x34000>; + #dma-cells = <1>; + dma-channels = <13>; + /* the ADT gives the first of the four outputs */ + interrupts-extended = <&aic AIC_IRQ 754 IRQ_TYPE_LEVEL_HIGH>, + <0>, <0>, <0>; + iommus = <&aop_dart 8>; + status = "disabled"; + }; + + mtp: mtp@514600000 { + compatible = "apple,t6041-mtp", "apple,t6041-rtk-helper-asc4", + "apple,mtp", "apple,rtk-helper-asc4"; + reg = <0x5 0x14600000 0x0 0x4000>; + reg-names = "asc"; + mboxes = <&mtp_mbox>; + iommus = <&mtp_dart 0>; + #helper-cells = <0>; + status = "disabled"; + }; + + mtp_mbox: mailbox@514608000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x5 0x14608000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + status = "disabled"; + }; + + mtp_dart: iommu@514800000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x5 0x14800000 0x0 0xc000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; + /* ADT "remap": streams 1 2 3 are stream 0 */ + apple,remap-streams = <1 0>, <2 0>, <3 0>; + status = "disabled"; + }; + + mtp_dockchannel: fifo@514b14000 { + compatible = "apple,t6041-dockchannel", "apple,dockchannel"; + reg = <0x5 0x14b14000 0x0 0x1000>; + reg-names = "irq"; + interrupt-parent = <&aic>; + interrupts = ; + + ranges = <0x0 0x5 0x14b28000 0x10000>; + nonposted-mmio; + #address-cells = <1>; + #size-cells = <1>; + + interrupt-controller; + #interrupt-cells = <2>; + status = "disabled"; + + mtp_hid: input@0 { + compatible = "apple,t6041-dockchannel-hid", "apple,dockchannel-hid"; + reg = <0x0000 0x1000>, + <0x4000 0x1000>, + <0x8000 0x1000>, + <0xc000 0x1000>; + reg-names = "rmt-config", "rmt-data", "config", "data"; + iommus = <&mtp_dart 0>; + interrupt-parent = <&mtp_dockchannel>; + interrupts = <2 IRQ_TYPE_LEVEL_HIGH>, + <3 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tx", "rx"; + apple,fifo-size = <0x800>; + apple,helper-cpu = <&mtp>; + }; + }; + + pinctrl: pinctrl@51c000000 { + compatible = "apple,t6041-pinctrl", "apple,t8103-pinctrl"; + reg = <0x5 0x1c000000 0x0 0x4000>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl 0 0 200>; + apple,npins = <200>; + + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + , + , + ; + status = "disabled"; + + /* I2C is function 1 (ADT gpio-iic_scl/sda) */ + i2c1_pins: i2c1-pins { + pinmux = , + ; + }; + + i2c2_pins: i2c2-pins { + pinmux = , + ; + }; + + i2c3_pins: i2c3-pins { + pinmux = , + ; + }; + + i2c4_pins: i2c4-pins { + pinmux = , + ; + }; + + i2c6_pins: i2c6-pins { + pinmux = , + ; + }; + + i2c8_pins: i2c8-pins { + pinmux = , + ; + }; + }; + + /* + * ISP (ADT isp0, firmware loaded by iBoot). "coproc" is the + * coprocessor up to its control block; "mbox", "gpio" and "mbox2" are + * the interrupt words, the firmware handshake words and the doorbell + * of its mailbox at +0x2924000. The first of the ADT's four + * interrupts carries the mailbox. + */ + isp: isp@580000000 { + compatible = "apple,t6041-isp", "apple,isp"; + reg = <0x5 0x80000000 0x0 0x1604000>, + <0x5 0x82924000 0x0 0x40>, + <0x5 0x829241d0 0x0 0x20>, + <0x5 0x82924464 0x0 0x10>; + reg-names = "coproc", "mbox", "gpio", "mbox2"; + interrupt-parent = <&aic>; + interrupts = ; + iommus = <&isp_dart0 0>, <&isp_dart1 0>, <&isp_dart2 0>; + power-domains = <&ps_isp_sys>, <&ps_isp_cpu>, <&ps_isp_fe>, + <&ps_isp_dprx>, <&ps_isp_secure>, <&ps_isp_be>, + <&ps_isp_clr>, <&ps_ispsens0>; + /* the shared memory window above the firmware's 32 MiB */ + apple,dart-vm-size = /bits/ 64 <0xde600000>; + status = "disabled"; + }; + + /* + * ADT dart-isp0: three instances on one interrupt; ADT "remap": streams + * 1, 6, 7, 10 and 11 are stream 0. + */ + isp_dart0: iommu@5828c0000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x5 0x828c0000 0x0 0xc000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_isp_sys>; + apple,remap-streams = <1 0>, <6 0>, <7 0>, <10 0>, <11 0>; + status = "disabled"; + }; + + isp_dart1: iommu@5828e0000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x5 0x828e0000 0x0 0xc000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_isp_sys>; + apple,remap-streams = <1 0>, <6 0>, <7 0>, <10 0>, <11 0>; + status = "disabled"; + }; + + isp_dart2: iommu@582900000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x5 0x82900000 0x0 0xc000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_isp_sys>; + apple,remap-streams = <1 0>, <6 0>, <7 0>, <10 0>, <11 0>; + status = "disabled"; + }; + + /* + * The three Type-C ports (ADT usb-drdN, atc-phyN, dart-usbN, + * acio-phy-cpuN) and the SPMI buses of their PD controllers. + */ + nub_spmi_a0: spmi@509188000 { + compatible = "apple,t6041-spmi", "apple,t8103-spmi"; + reg = <0x5 0x09188000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <0>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_nub_spmi_a0>; + status = "disabled"; + }; + + nub_spmi_a1: spmi@509198000 { + compatible = "apple,t6041-spmi", "apple,t8103-spmi"; + reg = <0x5 0x09198000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <0>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_nub_spmi_a1>; + status = "disabled"; + }; + + atcphy0: phy@382a90000 { + compatible = "apple,t6040-atcphy"; + reg = <0x3 0x82a90000 0x0 0x4000>, + <0x3 0x82800000 0x0 0x4000>, + <0x3 0x82a84000 0x0 0x4000>, + <0x3 0x83000000 0x0 0x30000>, + <0x3 0x83200000 0x0 0x4000>, + <0x3 0x83140000 0x0 0x4000>, + <0x3 0x830c0000 0x0 0x10000>, + <0x3 0x80000000 0x0 0x8000>, + <0x3 0x80020000 0x0 0x4000>, + <0x3 0x83244000 0x0 0x4000>, + <0x3 0x83250000 0x0 0x4000>; + reg-names = "bank0", "bank1", "pipehandler", "core", "cfg", "cpu", + "cpu-data", "axi2af", "axi2af-lioa", "fabric", "common-cfg"; + #phy-cells = <1>; + #reset-cells = <0>; + power-domains = <&ps_atc0_common_dp>; + mboxes = <&atcphy0_mbox>; + mbox-names = "phy-cpu"; + nonposted-mmio; + orientation-switch; + status = "disabled"; + }; + + atcphy0_mbox: mailbox@383148000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x3 0x83148000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + power-domains = <&ps_atc0_phymxwrap>; + status = "disabled"; + }; + + usb_drd0_dart_0: iommu@382f00000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x82f00000 0x0 0xc000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_atc0_usb>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; + status = "disabled"; + }; + + usb_drd0_dart_1: iommu@382f80000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x82f80000 0x0 0xc000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_atc0_usb>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; + status = "disabled"; + }; + + usb_drd0: usb@382280000 { + compatible = "apple,t6040-dwc3", "apple,t8103-dwc3"; + reg = <0x3 0x82280000 0x0 0xcd00>, + <0x3 0x8228cd00 0x0 0x3200>, + <0x3 0x82200000 0x0 0x4000>; + reg-names = "dwc3-core", "dwc3-apple", "drd-cfg"; + interrupt-parent = <&aic>; + interrupts = ; + /* + * A role switch rather than a fixed host: the PD controller + * resets the eUSB2 repeater on every connect, so the PHY and + * the core start after the attach and stop on detach. + */ + dr_mode = "otg"; + usb-role-switch; + role-switch-default-mode = "host"; + iommus = <&usb_drd0_dart_0 0>, <&usb_drd0_dart_1 1>; + power-domains = <&ps_atc0_usb>; + resets = <&atcphy0>; + phys = <&atcphy0 PHY_TYPE_USB2>, <&atcphy0 PHY_TYPE_USB3>; + phy-names = "usb2-phy", "usb3-phy"; + status = "disabled"; + }; + + atcphy1: phy@38aa90000 { + compatible = "apple,t6040-atcphy"; + reg = <0x3 0x8aa90000 0x0 0x4000>, + <0x3 0x8a800000 0x0 0x4000>, + <0x3 0x8aa84000 0x0 0x4000>, + <0x3 0x8b000000 0x0 0x30000>, + <0x3 0x8b200000 0x0 0x4000>, + <0x3 0x8b140000 0x0 0x4000>, + <0x3 0x8b0c0000 0x0 0x10000>, + <0x3 0x88000000 0x0 0x8000>, + <0x3 0x88020000 0x0 0x4000>, + <0x3 0x8b244000 0x0 0x4000>, + <0x3 0x8b250000 0x0 0x4000>; + reg-names = "bank0", "bank1", "pipehandler", "core", "cfg", "cpu", + "cpu-data", "axi2af", "axi2af-lioa", "fabric", "common-cfg"; + #phy-cells = <1>; + #reset-cells = <0>; + power-domains = <&ps_atc1_common_dp>; + mboxes = <&atcphy1_mbox>; + mbox-names = "phy-cpu"; + nonposted-mmio; + orientation-switch; + status = "disabled"; + }; + + atcphy1_mbox: mailbox@38b148000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x3 0x8b148000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + power-domains = <&ps_atc1_phymxwrap>; + status = "disabled"; + }; + + usb_drd1_dart_0: iommu@38af00000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x8af00000 0x0 0xc000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_atc1_usb>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; + status = "disabled"; + }; + + usb_drd1_dart_1: iommu@38af80000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x8af80000 0x0 0xc000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_atc1_usb>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; + status = "disabled"; + }; + + usb_drd1: usb@38a280000 { + compatible = "apple,t6040-dwc3", "apple,t8103-dwc3"; + reg = <0x3 0x8a280000 0x0 0xcd00>, + <0x3 0x8a28cd00 0x0 0x3200>, + <0x3 0x8a200000 0x0 0x4000>; + reg-names = "dwc3-core", "dwc3-apple", "drd-cfg"; + interrupt-parent = <&aic>; + interrupts = ; + /* + * A role switch rather than a fixed host: the PD controller + * resets the eUSB2 repeater on every connect, so the PHY and + * the core start after the attach and stop on detach. + */ + dr_mode = "otg"; + usb-role-switch; + role-switch-default-mode = "host"; + iommus = <&usb_drd1_dart_0 0>, <&usb_drd1_dart_1 1>; + power-domains = <&ps_atc1_usb>; + resets = <&atcphy1>; + phys = <&atcphy1 PHY_TYPE_USB2>, <&atcphy1 PHY_TYPE_USB3>; + phy-names = "usb2-phy", "usb3-phy"; + status = "disabled"; + }; + + atcphy2: phy@392a90000 { + compatible = "apple,t6040-atcphy"; + reg = <0x3 0x92a90000 0x0 0x4000>, + <0x3 0x92800000 0x0 0x4000>, + <0x3 0x92a84000 0x0 0x4000>, + <0x3 0x93000000 0x0 0x30000>, + <0x3 0x93200000 0x0 0x4000>, + <0x3 0x93140000 0x0 0x4000>, + <0x3 0x930c0000 0x0 0x10000>, + <0x3 0x90000000 0x0 0x8000>, + <0x3 0x90020000 0x0 0x4000>, + <0x3 0x93244000 0x0 0x4000>, + <0x3 0x93250000 0x0 0x4000>; + reg-names = "bank0", "bank1", "pipehandler", "core", "cfg", "cpu", + "cpu-data", "axi2af", "axi2af-lioa", "fabric", "common-cfg"; + #phy-cells = <1>; + #reset-cells = <0>; + power-domains = <&ps_atc2_common_dp>; + mboxes = <&atcphy2_mbox>; + mbox-names = "phy-cpu"; + nonposted-mmio; + orientation-switch; + status = "disabled"; + }; + + atcphy2_mbox: mailbox@393148000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x3 0x93148000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + power-domains = <&ps_atc2_phymxwrap>; + status = "disabled"; + }; + + usb_drd2_dart_0: iommu@392f00000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x92f00000 0x0 0xc000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_atc2_usb>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; + status = "disabled"; + }; + + usb_drd2_dart_1: iommu@392f80000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x92f80000 0x0 0xc000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_atc2_usb>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x4000 0x0 0xffff0000>; + status = "disabled"; + }; + + usb_drd2: usb@392280000 { + compatible = "apple,t6040-dwc3", "apple,t8103-dwc3"; + reg = <0x3 0x92280000 0x0 0xcd00>, + <0x3 0x9228cd00 0x0 0x3200>, + <0x3 0x92200000 0x0 0x4000>; + reg-names = "dwc3-core", "dwc3-apple", "drd-cfg"; + interrupt-parent = <&aic>; + interrupts = ; + /* + * A role switch rather than a fixed host: the PD controller + * resets the eUSB2 repeater on every connect, so the PHY and + * the core start after the attach and stop on detach. + */ + dr_mode = "otg"; + usb-role-switch; + role-switch-default-mode = "host"; + iommus = <&usb_drd2_dart_0 0>, <&usb_drd2_dart_1 1>; + power-domains = <&ps_atc2_usb>; + resets = <&atcphy2>; + phys = <&atcphy2 PHY_TYPE_USB2>, <&atcphy2 PHY_TYPE_USB3>; + phy-names = "usb2-phy", "usb3-phy"; + status = "disabled"; + }; + /* Additional DARTs; enabled together with their DMA consumers. */ + ave0_dart1: iommu@283080000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x2 0x83080000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x00004000 0x0 0xffffc000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_venc0_sys>; + status = "disabled"; + }; + + ave0_dart0: iommu@2830a0000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x2 0x830a0000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x00004000 0x0 0xffffc000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_venc0_sys>; + status = "disabled"; + }; + + apr0_dart: iommu@301020000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x01020000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x300 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_scodec>; + status = "disabled"; + }; + + apciec0_dart: iommu@384000000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x84000000 0x0 0x20000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + apciec1_dart: iommu@38c000000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x8c000000 0x0 0x20000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + apciec2_dart: iommu@394000000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x94000000 0x0 0x20000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + dispext0_dart: iommu@3a2300000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0xa2300000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + dcpext0_dart: iommu@3a2340000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0xa2340000 0x0 0x20000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + apcie1_dart: iommu@411000000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x11000000 0x0 0x20000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + sio_dart: iommu@429060000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x29060000 0x0 0x20000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x1c000 0x2ff 0xfffe4000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_sio>; + status = "disabled"; + }; + + ane0_dart0: iommu@485800000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x85800000 0x0 0xc000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_ane_sys>; + /* Include firmware identity MMIO pages below the preload DVAs. */ + apple,dma-range = <0x0 0x0 0x400 0x0>; + status = "disabled"; + }; + + ane0_dart1: iommu@485820000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x85820000 0x0 0xc000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_ane_sys>; + /* Include firmware identity MMIO pages below the preload DVAs. */ + apple,dma-range = <0x0 0x0 0x400 0x0>; + status = "disabled"; + }; + + ane0_dart2: iommu@485840000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x85840000 0x0 0xc000>; + #iommu-cells = <1>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_ane_sys>; + /* Include firmware identity MMIO pages below the preload DVAs. */ + apple,dma-range = <0x0 0x0 0x400 0x0>; + status = "disabled"; + }; + + jpeg0: jpeg@487000000 { + compatible = "apple,t6041-jpeg"; + reg = <0x4 0x87000000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + iommus = <&jpeg0_dart 0>; + power-domains = <&ps_jpg>; + apple,dma-range = /bits/ 64 <0x10000000000 0x100000000>; + status = "disabled"; + }; + + jpeg0_dart: iommu@487020000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x87020000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x300 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_jpg>; + status = "disabled"; + }; + + jpeg1: jpeg@487060000 { + compatible = "apple,t6041-jpeg"; + reg = <0x4 0x87060000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + iommus = <&jpeg1_dart 0>; + power-domains = <&ps_jpg>; + apple,dma-range = /bits/ 64 <0x10000000000 0x100000000>; + status = "disabled"; + }; + + jpeg1_dart: iommu@487080000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x4 0x87080000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x300 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_jpg>; + status = "disabled"; + }; + + scaler0_dart: iommu@521260000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x5 0x21260000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x300 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_msr0>; + status = "disabled"; + }; + + dispext1_dart: iommu@602300000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x6 0x02300000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + dcpext1_dart: iommu@602340000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x6 0x02340000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + pinctrl_aop: pinctrl@510824000 { + compatible = "apple,t6041-pinctrl", "apple,t8103-pinctrl"; + reg = <0x5 0x10824000 0x0 0x4000>; + clocks = <&clkref>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl_aop 0 0 85>; + apple,npins = <85>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + , + , + ; + /* Coprocessor pins and interrupt groups need an ownership handoff. */ + status = "disabled"; + }; + + pinctrl_smc: pinctrl@50c824000 { + compatible = "apple,t6041-pinctrl", "apple,t8103-pinctrl"; + reg = <0x5 0x0c824000 0x0 0x4000>; + clocks = <&clkref>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl_smc 0 0 24>; + apple,npins = <24>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + , + , + ; + /* Coprocessor pins and interrupt groups need an ownership handoff. */ + status = "disabled"; + }; + + nub_spmi1: spmi@509054000 { + compatible = "apple,t6041-spmi", "apple,t8103-spmi"; + reg = <0x5 0x09054000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <0>; + power-domains = <&ps_nub_spmi1>; + status = "disabled"; + }; + + nub_spmi2: spmi@509094000 { + compatible = "apple,t6041-spmi", "apple,t8103-spmi"; + reg = <0x5 0x09094000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <0>; + power-domains = <&ps_nub_spmi2>; + status = "disabled"; + }; + + nub_spmi3: spmi@5090d4000 { + compatible = "apple,t6041-spmi", "apple,t8103-spmi"; + reg = <0x5 0x090d4000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <0>; + power-domains = <&ps_nub_spmi3>; + status = "disabled"; + }; + + nub_spmi4: spmi@509114000 { + compatible = "apple,t6041-spmi", "apple,t8103-spmi"; + reg = <0x5 0x09114000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <0>; + power-domains = <&ps_nub_spmi4>; + status = "disabled"; + }; + + aop_spmi0: spmi@510914000 { + compatible = "apple,t6041-spmi", "apple,t8103-spmi"; + reg = <0x5 0x10914000 0x0 0x100>; + #address-cells = <2>; + #size-cells = <0>; + /* Shared with AOP firmware; no AP bus ownership handoff yet. */ + status = "disabled"; + }; + + /* The QSPIMC input is ADT clock 434 (200 MHz). */ + clk_200m: clock-200m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <200000000>; + clock-output-names = "clk_200m"; + }; + + spi4: spi@429110000 { + compatible = "apple,t6041-spi", "apple,t8103-spi"; + reg = <0x4 0x29110000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + clocks = <&clkref>; + power-domains = <&ps_spi4>; + #address-cells = <1>; + #size-cells = <0>; + /* Panel/TCON control belongs to the display firmware. */ + status = "disabled"; + }; + + qspi: spi@429118000 { + compatible = "apple,t6041-qspi"; + reg = <0x4 0x29118000 0x0 0x4800>; + interrupt-parent = <&aic>; + interrupts = ; + clocks = <&clk_200m>; + power-domains = <&ps_qspi>; + #address-cells = <1>; + #size-cells = <0>; + /* Boards enable it with their flash and its nvram partition. */ + status = "disabled"; + }; + + /* The loader supplies the SIO firmware regions and protocol tables. */ + sio: dma-controller@429e00000 { + compatible = "apple,t6041-sio"; + reg = <0x4 0x29e00000 0x0 0x8000>; + dma-channels = <128>; + #dma-cells = <1>; + mboxes = <&sio_mbox>; + iommus = <&sio_dart 0>; + power-domains = <&ps_sio_cpu>; + status = "disabled"; + }; + + sio_mbox: mailbox@429e08000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x4 0x29e08000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + power-domains = <&ps_sio_cpu>; + status = "disabled"; + }; + + /* + * Disabled until the H16 firmware path is proven on hardware. The + * loader fills the preload reservations and the firmware IOVAs from + * the ADT, so enabling it then only takes status = "okay" here and on + * the three DARTs. + */ + ane: ane@484000000 { + compatible = "apple,t6041-ane"; + reg = <0x4 0x84000000 0x0 0x2000000>, + <0x5 0x02280000 0x0 0x18000>, + <0x5 0x022a0000 0x0 0x4000>, + <0x5 0x003c0000 0x0 0x30000>, + <0x2 0x12000000 0x0 0xff4000>, + <0x5 0x22000000 0x0 0x2000000>, + <0x5 0x08374000 0x0 0x4000>; + reg-names = "engine", "pmgr", "aux-0", "aux-1", "aux-2", + "aux-3", "aux-4"; + interrupt-parent = <&aic>; + interrupts = ; + /* Stream 0 only: the MPM stream 11 is not given to the host. */ + iommus = <&ane0_dart0 0>, <&ane0_dart1 0>, <&ane0_dart2 0>; + power-domains = <&ps_ane_sys>, <&ps_ane_cpu>, <&ps_ane_mpm>, + <&ps_ane_td>, <&ps_ane_base>; + apple,ane-type = <0x110>; + apple,firmware-preloaded; + /* Inclusive DAPF bounds, in hardware record order. */ + apple,dapf-ranges = /bits/ 64 <0x5022803c0 0x5022803c3>, + /bits/ 64 <0x50228c000 0x50228c01b>, + /bits/ 64 <0x581668000 0x581668003>, + /bits/ 64 <0x28a668000 0x28a668003>; + /* Default firmware layout; the loader rewrites it from the ADT. */ + apple,firmware-iovas = /bits/ 64 <0x10000000000 0x100000c0000>; + /* The bootloader supplies the physical TEXT/DATA reservations. */ + status = "disabled"; + }; + + /* The video encoder stays disabled until its firmware backend is available. */ + ave: video-codec@283100000 { + compatible = "apple,t6041-ave"; + reg = <0x2 0x83100000 0x0 0x45c000>, + <0x2 0x83050000 0x0 0x4000>, + <0x2 0x83800000 0x0 0x800000>; + reg-names = "codec", "mailbox", "coproc"; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + ; + power-domains = <&ps_venc0_dma>, <&ps_venc0_pipe4>, + <&ps_venc0_pipe5>, <&ps_venc0_me0>, <&ps_venc0_me1>, + <&pmc_soc_max>; + power-domain-names = "dma", "pipe4", "pipe5", "me0", "me1", "perf"; + iommus = <&ave0_dart0 0>, <&ave0_dart1 0>; + status = "disabled"; + }; + + serial0: serial@429200000 { + compatible = "apple,s5l-uart"; + reg = <0x4 0x29200000 0x0 0x4000>; + reg-io-width = <4>; + interrupt-parent = <&aic>; + interrupts = ; + clocks = <&clkref>, <&clkref>; + clock-names = "uart", "clk_uart_baud0"; + power-domains = <&ps_uart0>; + status = "disabled"; + }; + + dcuart: serial@50883c000 { + compatible = "apple,dockchannel-uart"; + reg = <0x5 0x0883c000 0x0 0x4000>, + <0x5 0x08838000 0x0 0x4000>, + <0x5 0x0880c000 0x0 0x4000>; + reg-names = "data", "config", "irq"; + interrupt-parent = <&aic>; + interrupts = ; + apple,channel = <2>; + apple,sw-drain; + status = "disabled"; + }; + + /* ACIO 0 remains disabled until its host-router handoff is supported. */ + usb4_0_mbox: mailbox@381108000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x3 0x81108000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + power-domains = <&ps_atc0_cio>; + status = "disabled"; + }; + + usb4_0_dart: iommu@381a80000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x81a80000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x300 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + /* ACIO 1 remains disabled until its host-router handoff is supported. */ + usb4_1_mbox: mailbox@389108000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x3 0x89108000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + power-domains = <&ps_atc1_cio>; + status = "disabled"; + }; + + usb4_1_dart: iommu@389a80000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x89a80000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x300 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + + /* ACIO 2 remains disabled until its host-router handoff is supported. */ + usb4_2_mbox: mailbox@391108000 { + compatible = "apple,t6041-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x3 0x91108000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + power-domains = <&ps_atc2_cio>; + status = "disabled"; + }; + + usb4_2_dart: iommu@391a80000 { + compatible = "apple,t6041-dart", "apple,t8110-dart"; + reg = <0x3 0x91a80000 0x0 0xc000>; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x300 0x0>; + interrupt-parent = <&aic>; + interrupts = ; + status = "disabled"; + }; + +}; + +#include "t604x-pmgr.dtsi" diff --git a/drivers/gpu/drm/apple/apple_drv.c b/drivers/gpu/drm/apple/apple_drv.c index a1680f12c2d2f..09894999f9b48 100644 --- a/drivers/gpu/drm/apple/apple_drv.c +++ b/drivers/gpu/drm/apple/apple_drv.c @@ -572,7 +572,14 @@ static void apple_atomic_commit_tail(struct drm_atomic_commit *state) dcp_retain_framebuffer(to_apple_crtc(old->crtc)->dcp, entry); } - drm_atomic_helper_commit_tail_rpm(state); + drm_atomic_helper_commit_modeset_disables(state->dev, state); + drm_atomic_helper_commit_modeset_enables(state->dev, state); + drm_atomic_helper_commit_planes(state->dev, state, + DRM_PLANE_COMMIT_ACTIVE_ONLY); + drm_atomic_helper_fake_vblank(state); + drm_atomic_helper_commit_hw_done(state); + drm_atomic_helper_wait_for_flip_done(state->dev, state); + drm_atomic_helper_cleanup_planes(state->dev, state); } static const struct drm_mode_config_helper_funcs apple_mode_config_helpers = { diff --git a/drivers/gpu/drm/apple/dcp.c b/drivers/gpu/drm/apple/dcp.c index be07aff95d776..0a2992a2f0dad 100644 --- a/drivers/gpu/drm/apple/dcp.c +++ b/drivers/gpu/drm/apple/dcp.c @@ -229,6 +229,11 @@ bool dcp_t6041_ext_enabled(void) #include "iomfb_v26_6_swap.h" #include "dcp-peer-v26_6.inc" +static bool t6041_fw_26_5; +module_param(t6041_fw_26_5, bool, 0444); +MODULE_PARM_DESC(t6041_fw_26_5, + "T6041: drive DCP firmware 26.5.2 with the desktop 26.6 interface (unqualified)"); + /* * The backlight maximum of a desktop 26.x panel whose node has no * apple,max-brightness: the J616s panel's user-accessible SDR maximum (ADT @@ -4732,6 +4737,15 @@ static enum dcp_firmware_version dcp_check_firmware_version(struct device *dev) if (ret >= 0 && compat_ret >= 0 && !strcmp(fw_str, "26.6.2") && !strcmp(compat_str, "26.6.2")) return DCP_FIRMWARE_V_26_6_DESKTOP; + if (ret >= 0 && compat_ret >= 0 && !strcmp(fw_str, "26.5.2") && + !strcmp(compat_str, "26.5.2")) { + if (t6041_fw_26_5) { + dev_warn(dev, "T6041 DCP firmware 26.5.2 is unqualified; trying the desktop 26.6 interface\n"); + return DCP_FIRMWARE_V_26_6_DESKTOP; + } + dev_err(dev, "T6041 display not started: DCP firmware 26.5.2 is unqualified (appledrm.t6041_fw_26_5=1 tries it)\n"); + return DCP_FIRMWARE_UNKNOWN; + } dev_err(dev, "T6041 display not started: DCP firmware %s (compat %s) is not 26.6.2\n", ret >= 0 ? fw_str : "missing", compat_ret >= 0 ? compat_str : "missing"); diff --git a/drivers/gpu/drm/apple/parser.c b/drivers/gpu/drm/apple/parser.c index fff8b3465c60c..1c4bd3c4784b8 100644 --- a/drivers/gpu/drm/apple/parser.c +++ b/drivers/gpu/drm/apple/parser.c @@ -2380,3 +2380,39 @@ int parse_panel_edid_data(const void *blob, size_t len, const u8 **edid, size_t ret = parse(blob, len, &ctx); return ret ?: parse_panel_edid_value(&ctx, 0, &budget, true, edid, size); } +int parse_system_log_mnits_pairs(const void *blob, size_t size, + struct dcp_system_ev_mnits *entry) +{ + struct dcp_parse_ctx ctx = { .blob = blob, .len = size, .pos = 0 }; + s64 mnits = -1, idac = -1, timestamp = 0; + int ret = 0; + + if (size > U32_MAX) + return -EINVAL; + + while (round_up(ctx.pos, 4) + sizeof(u32) <= size) { + char *key = parse_string(&ctx); + + if (IS_ERR(key)) + break; + if (!strcmp(key, "mNits")) + ret = parse_int(&ctx, &mnits); + else if (!strcmp(key, "iDAC")) + ret = parse_int(&ctx, &idac); + else if (!strcmp(key, "timestamp")) + ret = parse_int(&ctx, ×tamp); + else + ret = skip(&ctx); + kfree(key); + if (ret) + break; + } + + if (mnits < 0 || mnits > U32_MAX) + return -EINVAL; + + entry->millinits = mnits; + entry->idac = idac < 0 ? 0 : idac; + entry->timestamp = timestamp; + return 0; +} diff --git a/drivers/gpu/drm/apple/parser.h b/drivers/gpu/drm/apple/parser.h index 81c75143c8f9d..4f7fcf721f5fc 100644 --- a/drivers/gpu/drm/apple/parser.h +++ b/drivers/gpu/drm/apple/parser.h @@ -265,5 +265,7 @@ struct dcp_system_ev_mnits { int parse_system_log_mnits(struct dcp_parse_ctx *handle, struct dcp_system_ev_mnits *entry); +int parse_system_log_mnits_pairs(const void *blob, size_t size, + struct dcp_system_ev_mnits *entry); #endif diff --git a/drivers/gpu/drm/apple/systemep.c b/drivers/gpu/drm/apple/systemep.c index 44e239c6016b0..392c2ca58f312 100644 --- a/drivers/gpu/drm/apple/systemep.c +++ b/drivers/gpu/drm/apple/systemep.c @@ -87,6 +87,13 @@ static int powerlog_report(struct apple_epic_service *service, enum epic_subtype ret = parse(data, data_size, &parse_ctx); if (ret) { + if (dcp->fw_compat == DCP_FIRMWARE_V_26_6_DESKTOP && + !parse_system_log_mnits_pairs(data, data_size, &mnits)) { + dev_info(dcp->dev, "systemep: powerlog mNits %u.%03u iDAC %u\n", + mnits.millinits / 1000, mnits.millinits % 1000, + mnits.idac); + goto have_mnits; + } dev_warn(service->ep->dcp->dev, "systemep: failed to parse report: %d\n", ret); return ret; } @@ -100,6 +107,7 @@ static int powerlog_report(struct apple_epic_service *service, enum epic_subtype dev_dbg(dcp->dev, "systemep: mNits event: Nits: %u.%03u, iDAC: %u\n", mnits.millinits / 1000, mnits.millinits % 1000, mnits.idac); +have_mnits: if ((dcp->fw_compat == DCP_FIRMWARE_H17P && dcp->hw.iomfb_method_profile != DCP_IOMFB_METHODS_H17G) || dcp->fw_compat == DCP_FIRMWARE_V_26_6_DESKTOP) { diff --git a/drivers/gpu/drm/asahi/asahi_core.rs b/drivers/gpu/drm/asahi/asahi_core.rs index decf16ea09647..ccaded83869d4 100644 --- a/drivers/gpu/drm/asahi/asahi_core.rs +++ b/drivers/gpu/drm/asahi/asahi_core.rs @@ -222,5 +222,13 @@ module! { default: 1, description: "G16: validate CDM/VDM stream records", }, + t6041_serial_render: u32 { + default: 0, + description: "T6041 25F84 diagnostic workaround: admit one render lease at a time (0: normal concurrency)", + }, + t6041_fw_log: u32 { + default: 0, + description: "T6041 bring-up: enable the firmware's log at boot (main configuration +0x250 = 1, status A debug flags 3)", + }, }, } diff --git a/drivers/gpu/drm/asahi/driver.rs b/drivers/gpu/drm/asahi/driver.rs index d6e461a7c3210..ff82d8c118e85 100644 --- a/drivers/gpu/drm/asahi/driver.rs +++ b/drivers/gpu/drm/asahi/driver.rs @@ -161,6 +161,10 @@ macro_rules! asahi_of_device_table { of::DeviceId::new(c"apple,agx-t6040"), ProbeConfig::G17(&hw::t6040::CONFIG) ), + ( + of::DeviceId::new(c"apple,agx-t6041"), + ProbeConfig::G17(&hw::t6041::CONFIG) + ), ( of::DeviceId::new(c"apple,agx-t8103"), ProbeConfig::Legacy(&hw::t8103::HWCONFIG) diff --git a/drivers/gpu/drm/asahi/g17/fw/compute.rs b/drivers/gpu/drm/asahi/g17/fw/compute.rs index b1afdad816b6b..211a9e419e976 100644 --- a/drivers/gpu/drm/asahi/g17/fw/compute.rs +++ b/drivers/gpu/drm/asahi/g17/fw/compute.rs @@ -26,6 +26,33 @@ pub(crate) const COMPUTE_KICK_EVENT_MASK: [u64; 4] = [0, 0, 4, 0]; const COMPUTE_REGISTERS: usize = 41; const COMPUTE_REGISTERS_MAX: usize = COMPUTE_REGISTERS + 1; +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[repr(u8)] +pub(crate) enum ComputeProgram { + G17P = 0, + V25F84 = 1, +} + +static PROGRAM: core::sync::atomic::AtomicU8 = + core::sync::atomic::AtomicU8::new(ComputeProgram::G17P as u8); + +impl ComputeProgram { + pub(crate) fn select(self) { + PROGRAM.store(self as u8, core::sync::atomic::Ordering::Relaxed); + } + + pub(crate) fn current() -> Self { + match PROGRAM.load(core::sync::atomic::Ordering::Relaxed) { + 1 => Self::V25F84, + _ => Self::G17P, + } + } +} + +const V25F84_REGISTERS: usize = 36; +const V25F84_CHECKPOINTS: [u16; 4] = [34, 35, 35, V25F84_REGISTERS as u16]; +const V25F84_UNK_0A599_FIRST: u64 = 0x0000_0132_0040_0020; + /// Validated per-command shader-context scratch request. /// /// The layout word is Apple's packed SCS layout: depth (bits 0:15), levels @@ -134,7 +161,10 @@ impl ScratchRequest { } fn checkpoints(self) -> [u16; 4] { - CHECKPOINTS.map(|count| count + u16::from(self.enabled())) + match ComputeProgram::current() { + ComputeProgram::G17P => CHECKPOINTS.map(|count| count + u16::from(self.enabled())), + ComputeProgram::V25F84 => V25F84_CHECKPOINTS, + } } } const ALT_REGISTERS: usize = 4; @@ -187,6 +217,15 @@ impl OperandState { r0a5c9: 0x1e000, size: 0x44000, }; + pub(crate) const FOUR_BY_TEN: OperandState = OperandState { + r10229: 0x78800, + r140a8: 0x7a800, + r10099: 0x3c405, + r10091: 0x78400, + r0a5c1: 0x0005, + r0a5c9: 0x3c000, + size: 0x80000, + }; } /// Checkpoints into the main register array, as entry counts: after the @@ -392,6 +431,61 @@ fn compute_registers(args: &ComputeArgs) -> Result<[RegisterWrite; COMPUTE_REGIS ]) } +fn compute_registers_25f84(args: &ComputeArgs) -> Result<[RegisterWrite; V25F84_REGISTERS]> { + let preempt = args.preempt_va; + let operand = args.operand_state_va; + let state = args.operand; + let key = work_key(args.context_id, args.work_state); + let ids = OBJECT_IDS.word(); + let intersection = args.intersection.words(); + + Ok([ + RegisterWrite::new(0x1a510, preempt), + RegisterWrite::new(0x1a420, args.cdm_va), + RegisterWrite::new(0x1a4d0, offset_va(preempt, PREEMPT_STATE[0])?), + RegisterWrite::new(0x1a4d8, offset_va(preempt, PREEMPT_STATE[1])?), + RegisterWrite::new(0x1a4e0, offset_va(preempt, PREEMPT_STATE[2])?), + RegisterWrite::new(0x1a4e8, offset_va(preempt, PREEMPT_STATE[3])?), + RegisterWrite::new(0x1a440, UNK_1A440), + RegisterWrite::new(0x1a458, UNK_1A458), + RegisterWrite::new(0x101d9, UNK_101D9), + RegisterWrite::new(0x1a089, intersection[0]), + RegisterWrite::new(0x1a091, intersection[1]), + RegisterWrite::new(0x1a059, intersection[2]), + RegisterWrite::new(0x1a061, intersection[3]), + RegisterWrite::new(0x1a0b9, intersection[4]), + RegisterWrite::new(0x1a0c1, intersection[5]), + RegisterWrite::new(0x101d1, args.scratch.size_word()), + RegisterWrite::new( + 0x0d479, + if args.intersection.auxiliary == 0 { + args.scratch.tail_word() + } else { + u64::from(args.intersection.auxiliary) + }, + ), + RegisterWrite::new(0x1a0e9, args.scratch.stack_word()), + RegisterWrite::new(0x107a1, args.scratch.window_word()), + RegisterWrite::new(0x0a599, V25F84_UNK_0A599_FIRST), + RegisterWrite::new(0x0d411, UNK_0D411), + RegisterWrite::new(0x1a540, ids), + RegisterWrite::new(0x014a9, ids), + RegisterWrite::new(0x0a351, ids), + RegisterWrite::new(0x10201, key), + RegisterWrite::new(0x10428, key), + RegisterWrite::new(0x14028, u64::from(args.free_list_slot)), + RegisterWrite::new(0x14070, args.usage_va | 1), + RegisterWrite::new(0x10229, offset_va(operand, state.r10229)?), + RegisterWrite::new(0x140a8, offset_va(operand, state.r140a8)?), + RegisterWrite::new(0x10099, offset_va(operand, state.r10099)?), + RegisterWrite::new(0x10091, offset_va(operand, state.r10091)?), + RegisterWrite::new(0x0a5c1, offset_va(operand, state.r0a5c1)?), + RegisterWrite::new(0x0a5c9, offset_va(operand, state.r0a5c9)?), + RegisterWrite::new(0x1a440, UNK_1A440_FINAL), + RegisterWrite::new(0x0a599, UNK_0A599), + ]) +} + /// The second array exchanges the operand-state regions of registers /// 0x10099/0x0a5c1 and 0x10091/0x0a5c9. fn alt_registers(args: &ComputeArgs) -> Result<[RegisterWrite; ALT_REGISTERS]> { @@ -506,6 +600,8 @@ impl ComputeDescriptor { const UNK_FB0: u16 = 0x1a; const UNK_FBA: u32 = 0xe0a0_0001; const UNK_FC5: u8 = 0x9f; + const UNK_FBA_25F84: u32 = 0x6c00_0001; + const UNK_FC5_25F84: u8 = 0x5f; /// Fills a descriptor cleared by `Object::initialize`. The unused firmware /// fields and padding retain that zero initialization. @@ -516,7 +612,7 @@ impl ComputeDescriptor { { return Err(EINVAL); } - let registers = compute_registers(args)?; + let program = ComputeProgram::current(); let alt_registers = alt_registers(args)?; let registers_va = offset_va(args.descriptor_va, Self::REGISTERS_OFFSET)?; let alt_registers_va = offset_va(args.descriptor_va, Self::ALT_REGISTERS_OFFSET)?; @@ -527,10 +623,17 @@ impl ComputeDescriptor { self.context_id = args.context_id.into(); self.work_state_va = args.work_state_va; self.checkpoints = args.scratch.checkpoints(); - // The enabled program prepends one register; disabled descriptors keep - // the same forty writes, trailer count and resume checkpoints. - let first = usize::from(!args.scratch.enabled()); - self.registers.set(registers_va, ®isters[first..])?; + match program { + ComputeProgram::G17P => { + let registers = compute_registers(args)?; + let first = usize::from(!args.scratch.enabled()); + self.registers.set(registers_va, ®isters[first..])?; + } + ComputeProgram::V25F84 => { + self.registers + .set(registers_va, &compute_registers_25f84(args)?)?; + } + } self.alt_registers.set(alt_registers_va, &alt_registers)?; self.preempt_va = args.preempt_va; self.cdm_end_va = args.cdm_end_va; @@ -552,8 +655,18 @@ impl ComputeDescriptor { self.timestamp_end_va = timestamp_end_va; self.unk_fb0 = Self::UNK_FB0; self.free_list_control_va = args.free_list_control_va; - self.unk_fba = Self::UNK_FBA; - self.unk_fc5 = Self::UNK_FC5; + match program { + ComputeProgram::G17P => { + self.unk_fba = Self::UNK_FBA; + self.unk_fc5 = Self::UNK_FC5; + } + ComputeProgram::V25F84 => { + self.unk_fba = Self::UNK_FBA_25F84; + self.unk_fbe[0] = 0x06; + self.unk_fc5 = Self::UNK_FC5_25F84; + self.unk_fc6[0] = 0x04; + } + } self.usage_va = args.usage_fw_va; self.context_generation = args.context_generation; Ok(()) diff --git a/drivers/gpu/drm/asahi/g17/fw/compute_pool.rs b/drivers/gpu/drm/asahi/g17/fw/compute_pool.rs index 0f0614f6155a1..8ce8807cd71c0 100644 --- a/drivers/gpu/drm/asahi/g17/fw/compute_pool.rs +++ b/drivers/gpu/drm/asahi/g17/fw/compute_pool.rs @@ -18,9 +18,22 @@ pub(crate) fn extra_bytes(active_cores: u32, scs_pages: u16) -> Result { Ok(extra) } +static BASE_BLOCKS: core::sync::atomic::AtomicUsize = + core::sync::atomic::AtomicUsize::new(COMPUTE_BLOCKS); + +pub(crate) fn set_base_blocks(blocks: usize) -> Result { + if blocks < COMPUTE_BLOCKS || blocks > PAGE_LIST_SIZE / (FREE_LIST_BLOCK_PAGES as usize * 8) { + return Err(EINVAL); + } + BASE_BLOCKS.store(blocks, core::sync::atomic::Ordering::Relaxed); + Ok(()) +} + pub(crate) fn required_blocks(active_cores: u32, scs_pages: u16) -> Result { let extra = extra_bytes(active_cores, scs_pages)?; - let bytes = extra.checked_add((COMPUTE_BLOCKS * FREE_LIST_BLOCK_SIZE) as u64) + let base = BASE_BLOCKS.load(core::sync::atomic::Ordering::Relaxed); + let bytes = extra + .checked_add((base * FREE_LIST_BLOCK_SIZE) as u64) .ok_or(EOVERFLOW)?; let blocks = usize::try_from(bytes.div_ceil(FREE_LIST_BLOCK_SIZE as u64)) .map_err(|_| EOVERFLOW)?; diff --git a/drivers/gpu/drm/asahi/g17/fw/initdata.rs b/drivers/gpu/drm/asahi/g17/fw/initdata.rs index 3092e599caa84..387cebb28a368 100644 --- a/drivers/gpu/drm/asahi/g17/fw/initdata.rs +++ b/drivers/gpu/drm/asahi/g17/fw/initdata.rs @@ -781,6 +781,15 @@ impl PerfGroup { } } } + + pub(crate) fn replicate_first_lane(&mut self, lanes: usize) { + for index in 0..PERF_STATES { + for lane in lanes.max(1)..PERF_LANES { + self.core_mv[index][lane] = self.core_mv[index][0]; + self.sram_mv[index][lane] = self.sram_mv[index][0]; + } + } + } } /// Returns the performance states selected by `map` from `opps`. diff --git a/drivers/gpu/drm/asahi/g17/fw/initdata/v25g83.rs b/drivers/gpu/drm/asahi/g17/fw/initdata/v25g83.rs index f4c3ee5db22e2..5e15dba2b0e6e 100644 --- a/drivers/gpu/drm/asahi/g17/fw/initdata/v25g83.rs +++ b/drivers/gpu/drm/asahi/g17/fw/initdata/v25g83.rs @@ -1,23 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only -//! Initialization data of the 25G83 firmware build (macOS 26.6, `mBoot-18000.161.10`). -//! -//! The M4 Pro (T6040) runs this build. It has the interface version of the A18 Pro's -//! 26A428 build and the same objects, with these differences: -//! -//! - [`HwData25G83`]: the A18 Pro's hardware data up to `0x2554`, eight bytes inserted before -//! `0x2570` and four more before `0x2614`, and the CS and AFR performance tables; -//! - [`PowerConfig25G83`]: the power configuration with two blocks removed (`0xa8` and `0xa0` -//! bytes), at bundle `+0x5380`, followed by the auxiliary data; -//! - region C and the power state ([`POWER_STATE_WORDS`]) with other values; -//! - one firmware instance carrying both roles, with a larger status B ([`private`]), five -//! separately allocated views and a firmware area ([`kernel_window`]). -//! -//! The constant contents were derived from the G16 encoders of Gravity Linux, which run this -//! firmware on the M4 Pro, by evaluating them for this SoC; see the commit that added them. use super::{ - fill_words, perf_states, CompletionRingDescriptor, HwDataArgs, Opp, PerfGroup, + fill_words, perf_states, CompletionRingDescriptor, HwDataArgs, Opp, PerfGroup, RegionC, RegisterMapEntry, Words, COMPLETION_RING_ENTRIES, COMPLETION_RING_ENTRY_SIZE, COMPLETION_RING_INDEX, PERF_STATES, REGISTER_MAP_SLOTS, }; @@ -107,6 +92,7 @@ pub(crate) struct HwDataArgs25G83<'a> { pub(crate) cs_opps: &'a [Opp], /// Operating points of the AFR clock domain. pub(crate) afr_opps: &'a [Opp], + pub(crate) chip: Option<&'a Chip>, } /// The hardware data of the 25G83 build, at the base of the bundle. @@ -300,8 +286,12 @@ impl HwData25G83 { } self.register_map[window.slot] = RegisterMapEntry::window(window); } - if !args.reserved_slots.is_empty() { - return Err(EINVAL); + for &slot in args.reserved_slots { + match used.get_mut(slot) { + Some(used) if !*used => *used = true, + _ => return Err(EINVAL), + } + self.register_map[slot] = RegisterMapEntry::reserved(); } self.chip_id = args.chip_id; @@ -336,6 +326,9 @@ impl HwData25G83 { } self.perf_a.fill(&states_a, 1); self.perf_b.fill(&states_b, 1); + if ext.chip.is_some_and(|chip| chip.perf_a_replicate_lanes) { + self.perf_a.replicate_first_lane(states_a[0].cells); + } for (index, state) in states_b.iter().enumerate() { self.perf_b_freq_mhz[index] = state.freq_mhz; self.perf_a_states[index] = perf.states_a[index].into(); @@ -344,7 +337,9 @@ impl HwData25G83 { self.perf_a_relative = perf.relative_a; self.perf_b_relative = perf.relative_b; self.unk_1848 = [0x3f82_8f5c; 11]; - self.cs_perf.fill(ext.cs_opps, perf.sram_min_mv)?; + if ext.chip.is_none_or(|chip| chip.cs_perf_table) { + self.cs_perf.fill(ext.cs_opps, perf.sram_min_mv)?; + } self.afr_perf.fill(ext.afr_opps, perf.sram_min_mv)?; self.unk_2544 = 5; @@ -361,6 +356,24 @@ impl HwData25G83 { self.unk_25fc = 1; self.unk_2614 = 1; self.unk_261c = 0x100; + self.set_runtime_words(args); + self.unk_26c0 = 1; + self.unk_26c4 = 1; + self.unk_26f4 = 1; + // SAFETY: `HwData25G83` consists of integers only and has no padding, so any bytes are a + // valid value. + let bytes = unsafe { + core::slice::from_raw_parts_mut((self as *mut Self).cast::(), size_of::()) + }; + if let Some(chip) = ext.chip { + overlay_words(bytes, chip.hw_data_words)?; + } + Ok(()) + } + + /// Writes the words the host sets at every boot: the completion-ring descriptors and the + /// QoS pointer. + fn set_runtime_words(&mut self, args: &HwDataArgs<'_>) { for (ring, index) in args.completion_rings.iter().zip(COMPLETION_RING_INDEX) { self.completion_rings[index as usize] = CompletionRingDescriptor { low_va: ring.low_va, @@ -372,11 +385,93 @@ impl HwData25G83 { }; } self.qos_va = args.qos_va; - self.unk_26c0 = 1; - self.unk_26c4 = 1; - self.unk_26f4 = 1; + } + + /// Initializes the hardware data from captured contents, then writes the runtime words. + /// + /// The captured chip identifier and register map must be the ones `args` names: the + /// firmware finds its register windows through the map, and the driver maps exactly + /// `args.windows`. + pub(crate) fn init_captured(&mut self, captured: &Captured, args: &HwDataArgs<'_>) -> Result { + fill_words(self.bytes_mut(), captured.hw_data); + if !args.reserved_slots.is_empty() || { self.chip_id } != args.chip_id { + return Err(EINVAL); + } + let mut expected = [[0u8; size_of::()]; REGISTER_MAP_SLOTS]; + let mut used = [false; REGISTER_MAP_SLOTS]; + for window in args.windows { + match used.get_mut(window.slot) { + Some(used) if !*used => *used = true, + _ => return Err(EINVAL), + } + expected[window.slot] = RegisterMapEntry::window(window).to_bytes(); + } + let map = core::mem::offset_of!(Self, register_map); + let bytes = self.bytes_mut(); + for (slot, entry) in expected.iter().enumerate() { + let at = map + slot * entry.len(); + if bytes[at..at + entry.len()] != entry[..] { + return Err(EINVAL); + } + } + self.set_runtime_words(args); Ok(()) } + + /// The runtime words, which [`Self::hash_captured`] leaves out. + const RUNTIME: [(usize, usize); 2] = [(COMPLETION_DESCRIPTORS, 0x80), (QOS_POINTER, 8)]; + + /// Hash of captured contents: everything but the runtime words. + pub(crate) fn hash_captured(&self) -> u64 { + hash_without(self.bytes(), &Self::RUNTIME) + } + + fn bytes(&self) -> &[u8] { + // SAFETY: `HwData25G83` consists of integers only and has no padding. + unsafe { + core::slice::from_raw_parts((self as *const Self).cast::(), size_of::()) + } + } + + fn bytes_mut(&mut self) -> &mut [u8] { + // SAFETY: `HwData25G83` consists of integers only and has no padding, so every byte is + // initialized and any byte pattern is a valid value. + unsafe { + core::slice::from_raw_parts_mut((self as *mut Self).cast::(), size_of::()) + } + } +} + +impl RegisterMapEntry { + /// The entry as the firmware reads it. + fn to_bytes(&self) -> [u8; size_of::()] { + let mut bytes = [0; size_of::()]; + for (at, field) in [ + (0x0, &self.phys.to_le_bytes()[..]), + (0x8, &self.va.to_le_bytes()[..]), + (0x10, &self.total_size.to_le_bytes()[..]), + (0x14, &self.element_size.to_le_bytes()[..]), + (0x18, &self.unk_18.to_le_bytes()[..]), + (0x20, &self.unk_20.to_le_bytes()[..]), + (0x24, &self.unk_24.to_le_bytes()[..]), + ] { + bytes[at..at + field.len()].copy_from_slice(field); + } + bytes + } +} + +fn overlay_words(bytes: &mut [u8], words: Words) -> Result { + for &(offset, value, repeat) in words { + for index in 0..repeat { + let at = offset + 4 * index; + bytes + .get_mut(at..at + 4) + .ok_or(EINVAL)? + .copy_from_slice(&value.to_le_bytes()); + } + } + Ok(()) } /// Power configuration control period, in 24 MHz clocks (8 ms). @@ -384,7 +479,16 @@ const PERIOD_CLOCKS: u32 = 200_000; /// Temperature sensors read by the die and MTR temperature limiters. const TEMP_SENSOR_MASK: u32 = 0x2a22_2aa2; -/// Offset of the per-chip leakage coefficients in the power configuration. +pub(crate) struct Chip { + pub(crate) max_power_mw: u32, + pub(crate) leakage: [u32; 56], + pub(crate) aon_table: &'static [u32], + pub(crate) hw_data_words: Words, + pub(crate) power_config_words: Words, + pub(crate) perf_a_replicate_lanes: bool, + pub(crate) cs_perf_table: bool, +} + const LEAKAGE_OFFSET: usize = 0x642c; /// Offset in the power configuration of the GPU address of the configuration's status (the /// configuration named by the root, `+0x80`). @@ -592,15 +696,92 @@ impl PowerConfig25G83 { for offset in [0x9e0, 0x2a04] { self.0[offset..offset + 4].copy_from_slice(&power.to_le_bytes()); } + self.set_runtime_words(config_va, aon_va, entropy); + } + + pub(crate) fn apply_chip(&mut self, chip: &Chip) -> Result { + overlay_words(&mut self.0, chip.power_config_words) + } + + /// Initializes the power configuration from captured contents, then writes the runtime + /// words. + pub(crate) fn init_captured( + &mut self, + words: Words, + config_va: u64, + aon_va: u64, + entropy: u32, + ) { + fill_words(&mut self.0, words); + self.set_runtime_words(config_va, aon_va, entropy); + } + + /// Writes the pointers and the random word ([`Self::RUNTIME`]). + fn set_runtime_words(&mut self, config_va: u64, aon_va: u64, entropy: u32) { self.0[CONFIG_STATUS_POINTER..CONFIG_STATUS_POINTER + 8] .copy_from_slice(&(config_va + 0x80).to_le_bytes()); self.0[AON_POINTER..AON_POINTER + 8].copy_from_slice(&aon_va.to_le_bytes()); self.0[ENTROPY..ENTROPY + 4].copy_from_slice(&entropy.to_le_bytes()); } + + /// The pointers and the random word, which [`Self::hash`] leaves out. + const RUNTIME: [(usize, usize); 3] = + [(CONFIG_STATUS_POINTER, 8), (AON_POINTER, 8), (ENTROPY, 4)]; + + /// Hash of the contents without the pointers and the random word. + pub(crate) fn hash(&self) -> u64 { + hash_without(&self.0, &Self::RUNTIME) + } +} + +/// 25G83 initialization contents captured on one unit, which a configuration whose device +/// tree has no inputs for the builders above applies instead of what they produce. Only the +/// runtime words are written over them. +pub(crate) struct Captured { + /// The [`HwData25G83`], without its runtime words. + pub(crate) hw_data: Words, + /// The [`PowerConfig25G83`] and its auxiliary data, without the runtime words. + pub(crate) power_config: Words, + /// Region C. + pub(crate) region_c: Words, + /// The AON temperature-source rows. + pub(crate) aon_table: &'static [u32], + /// Enabled GPU cores the contents were captured with. The captured performance tables + /// are that unit's binned operating points; another core count is another part. + pub(crate) active_cores: u32, + /// Hashes ([`hash_without`]) of the captured hardware data without its runtime words + /// ([`HwData25G83::hash_captured`]), power configuration ([`PowerConfig25G83::hash`]) and + /// region C, which what the driver wrote must equal. + pub(crate) expected: [u64; 3], +} + +impl RegionC { + /// Initializes region C from captured contents. + pub(crate) fn init_captured(&mut self, words: Words) { + // SAFETY: `RegionC` consists of integers only and is packed, so every byte is + // initialized and any byte pattern is a valid value. + let bytes = unsafe { + core::slice::from_raw_parts_mut((self as *mut Self).cast::(), size_of::()) + }; + fill_words(bytes, words); + } +} + +/// FNV-1a 64 of `bytes` with the `(offset, length)` ranges in `skip` left out. +pub(crate) fn hash_without(bytes: &[u8], skip: &[(usize, usize)]) -> u64 { + let mut hash = 0xcbf2_9ce4_8422_2325u64; + for (offset, byte) in bytes.iter().enumerate() { + if skip + .iter() + .any(|&(at, len)| (at..at + len).contains(&offset)) + { + continue; + } + hash = (hash ^ u64::from(*byte)).wrapping_mul(0x100_0000_01b3); + } + hash } -/// The AON temperature-source rows the power configuration names: the GPU cluster 0, GPU -/// cluster 1 and SoC sensors. pub(crate) const AON_TABLE: [u32; 9] = [ u32::from_be_bytes(*b"g0TR"), 0x006b_0001, diff --git a/drivers/gpu/drm/asahi/g17/fw/kick.rs b/drivers/gpu/drm/asahi/g17/fw/kick.rs index ca2b6604a302b..2a035524bdffb 100644 --- a/drivers/gpu/drm/asahi/g17/fw/kick.rs +++ b/drivers/gpu/drm/asahi/g17/fw/kick.rs @@ -507,10 +507,46 @@ impl KickEntry { } } +pub(crate) fn ksm_slot_descriptor( + ring_va: u64, + data_master: super::queue::DataMaster, + priority: u8, +) -> Result { + if ring_va & !RenderRegistration::ADDRESS_MASK != 0 || priority >= Policy::PRIORITIES { + return Err(EINVAL); + } + let term = (3 * (4 - u64::from(priority)) + 0x3fe).wrapping_shl(54); + Ok(((data_master as u64 + 1) << 60) | ring_va | term) +} + +#[derive(Copy, Clone, Debug)] +pub(crate) struct KsmQueue { + pub(crate) qid: u8, + pub(crate) descriptor: u64, +} + +impl KsmQueue { + pub(crate) fn new( + qid: u8, + ring_va: u64, + data_master: super::queue::DataMaster, + priority: u8, + ) -> Result { + if qid > QID_MAX { + return Err(EINVAL); + } + Ok(Self { + qid, + descriptor: ksm_slot_descriptor(ring_va, data_master, priority)?, + }) + } +} + /// The complete write-only installation of a fragment/tiling queue pair. /// Firmware must see both queues configured before either outer command. pub(crate) struct RenderRegistration { writes: [(usize, u64); 8], + queues: [KsmQueue; 2], } impl RenderRegistration { @@ -540,8 +576,7 @@ impl RenderRegistration { if qid > QID_MAX || va & !Self::ADDRESS_MASK != 0 { return Err(EINVAL); } - let completion = (3 * (4 - u64::from(priority)) + 0x3fe).wrapping_shl(54); - let payload = ((engine as u64 + 1) << 60) | va | completion; + let payload = ksm_slot_descriptor(va, engine, priority)?; let (low, high) = if qid < 64 { (1u64 << qid, 0) } else { @@ -554,10 +589,30 @@ impl RenderRegistration { (Self::VALID_LOW, low), ]); } - Ok(Self { writes }) + Ok(Self { + writes, + queues: [ + KsmQueue::new( + fragment.0, + fragment.1, + super::queue::DataMaster::Fragment, + priority, + )?, + KsmQueue::new( + tiling.0, + tiling.1, + super::queue::DataMaster::Tiling, + priority, + )?, + ], + }) } pub(crate) fn writes(&self) -> &[(usize, u64); 8] { &self.writes } + + pub(crate) fn queues(&self) -> &[KsmQueue; 2] { + &self.queues + } } diff --git a/drivers/gpu/drm/asahi/g17/fw/render.rs b/drivers/gpu/drm/asahi/g17/fw/render.rs index d0000282cef82..e188c96e560d4 100644 --- a/drivers/gpu/drm/asahi/g17/fw/render.rs +++ b/drivers/gpu/drm/asahi/g17/fw/render.rs @@ -70,6 +70,10 @@ impl Deflake { sub: [0xa0, 0x820], viewport: false, }; + pub(crate) const FOUR_CLUSTERS: Deflake = Deflake { + sub: [0x120, 0xda0], + viewport: false, + }; } /// The register programs of a firmware build's render descriptors. @@ -372,6 +376,8 @@ pub(crate) struct RenderArgs<'a> { pub(crate) fragment: RenderStage, /// Register programs of the firmware build. pub(crate) programs: RegisterPrograms, + /// Device/build policy for registers 0x1c890 and 0x1c918 in V25G83-format arrays. + pub(crate) ta_mode_1: bool, /// Deflake-buffer layout of the GPU. pub(crate) deflake: Deflake, } @@ -662,6 +668,8 @@ fn ta_registers( /// Tiler segment control of a two-cluster pass, what macOS writes. const VDM_SEGMENT_CONTROL: u64 = 0x20_0440; const VDM_SEGMENT_INDEX: u64 = 4; +/// 0x1c890 of the experimental T6041 25F84 TA mode, with 0x1c918 = 0. +const T6041_TA_MODE_1: u64 = 1; /// Pages the tiler keeps out of a partial render's segments: without them the pages a pass /// returns shrink to none and the tiler can't advance. Fifteen blocks, macOS's minimum heap. const MIN_FREE_TVB_PAGES: u64 = 0x3c; @@ -716,8 +724,13 @@ fn ta_registers_25g83( push(find(0x1c880, 0)?); push(RegisterWrite::new(0x1c948, gtp(4)?)); push(RegisterWrite::new(0x1c888, gtp(5)?)); - push(RegisterWrite::new(0x1c890, VDM_SEGMENT_CONTROL)); - push(RegisterWrite::new(0x1c918, VDM_SEGMENT_INDEX)); + let (segment_control, segment_index) = if args.ta_mode_1 { + (T6041_TA_MODE_1, 0) + } else { + (VDM_SEGMENT_CONTROL, VDM_SEGMENT_INDEX) + }; + push(RegisterWrite::new(0x1c890, segment_control)); + push(RegisterWrite::new(0x1c918, segment_index)); push(find(0x1c079, 0)?); push(find(0x1c9d8, 0)?); push(RegisterWrite::new(0x1c089, gtp2)); @@ -1596,3 +1609,171 @@ impl FragmentSlot { Ok(Some(table)) } } + +#[kunit_tests(asahi_g17_ta_mode)] +mod ta_mode_tests { + use super::*; + use crate::g17::fw::{ + compute::{IntersectionTables, ScratchRequest}, + render_rt::RayQueryStage, + variant::{Firmware, Variant, V25F84, V25G83, V26A428}, + }; + + fn selected(firmware: &Firmware) -> &'static Variant { + match firmware { + Firmware::Fixed(variant) => variant, + Firmware::Identified(builds) => { + assert_eq!(builds.len(), 1); + builds[0].variant + } + } + } + + /// The variants of the builds T6041 admits: 25F84, then 25G83. + fn t6041_variants() -> [&'static Variant; 2] { + let Firmware::Identified(builds) = crate::hw::t6041::CONFIG.firmware else { + panic!("T6041 must identify its loaded firmware"); + }; + assert_eq!(builds.len(), 2); + [builds[0].variant, builds[1].variant] + } + + /// The TA mode of every admitted T6041 build. + fn t6041_ta_mode_1() -> bool { + let [f84, g83] = t6041_variants(); + assert_eq!(f84.ta_mode_1, g83.ta_mode_1); + f84.ta_mode_1 + } + + #[test] + fn policy_is_local_to_the_admitted_t6041_builds() { + let [f84, g83] = t6041_variants(); + let pro = selected(&crate::hw::t6040::CONFIG.firmware); + assert!(f84.is_25f84()); + assert!(!g83.is_25f84()); + for max in [f84, g83] { + assert_eq!(max.programs, RegisterPrograms::V25G83); + assert!(max.ta_mode_1); + } + assert!(!pro.ta_mode_1); + assert!(!V25F84.ta_mode_1); + assert!(!V25G83.ta_mode_1); + assert!(!V26A428.ta_mode_1); + } + + fn fixture() -> (RenderPass, RenderResources) { + // SAFETY: These two types contain only integers, bools and structs of + // those types, for which all-zero bytes are valid. Required render + // dimensions and user-window addresses are filled below. + let mut pass: RenderPass = unsafe { core::mem::zeroed() }; + // SAFETY: RenderResources contains only integers and integer structs. + let mut resources: RenderResources = unsafe { core::mem::zeroed() }; + pass.width = 64; + pass.height = 64; + pass.layers = 1; + pass.utile_width = 32; + pass.utile_height = 32; + pass.sample_size = 4; + pass.vdm_va = USER_BASE + 0x10000; + resources.tilemap_va = USER_BASE + 0x20000; + resources.layermeta_va = USER_BASE + 0x30000; + resources.heapmeta_va = USER_BASE + 0x40000; + resources.tpc_va = USER_BASE + 0x50000; + resources.deflake_va = USER_BASE + 0x60000; + resources.gtp_va = core::array::from_fn(|i| USER_BASE + 0x70000 + i as u64 * 0x1000); + (pass, resources) + } + + fn args<'a>(pass: &'a RenderPass, resources: &'a RenderResources, scs: bool) -> RenderArgs<'a> { + let stage = RenderStage { + qid: 1, + descriptor_va: USER_BASE + 0x80000, + state_word: 1, + stamp_va: USER_BASE + 0x90000, + aux_stamp_va: USER_BASE + 0x90008, + }; + // Exercise the array with and without its optional SCS entry. + let ray = RayQueryStage { + intersection: IntersectionTables::NONE, + scratch: ScratchRequest::new(if scs { (1 << 32) | (1 << 24) | 8 } else { 0 }).unwrap(), + }; + RenderArgs { + pass, + resources, + ray_query: [ray; 2], + ordinal: 0, + ta: stage, + fragment: stage, + programs: RegisterPrograms::V25G83, + ta_mode_1: false, + deflake: Deflake::FOUR_CLUSTERS, + } + } + + #[test] + fn ta_mode_changes_only_the_segment_writes_with_or_without_scs() { + let (mut pass, resources) = fixture(); + for (width, height, layers) in [(64, 64, 1), (3456, 2234, 2)] { + pass.width = width; + pass.height = height; + pass.layers = layers; + let geometry = Geometry::new(&pass).unwrap(); + let words = PassWords::new(&pass).unwrap(); + for scs in [false, true] { + let mut args = args(&pass, &resources, scs); + let (before, count) = ta_registers_25g83(&args, &geometry, &words).unwrap(); + args.ta_mode_1 = t6041_ta_mode_1(); + let (after, new_count) = ta_registers_25g83(&args, &geometry, &words).unwrap(); + assert_eq!(count, 83 + usize::from(scs)); + assert_eq!(new_count, count); + let slot = after[79 + usize::from(scs)].reg; + assert_eq!(slot, 0x14308); + let mut changed = 0; + for (old, new) in before.iter().zip(&after).take(count) { + let old = (old.reg, old.value); + let new = (new.reg, new.value); + if old.0 == 0x1c890 { + assert_eq!(old.1, VDM_SEGMENT_CONTROL); + assert_eq!(new, (0x1c890, T6041_TA_MODE_1)); + changed += 1; + } else if old.0 == 0x1c918 { + assert_eq!(old.1, VDM_SEGMENT_INDEX); + assert_eq!(new, (0x1c918, 0)); + changed += 1; + } else { + // Includes every merge-buffer write and 0x1c9a8. + assert_eq!(old, new); + } + } + assert_eq!(changed, 2); + } + } + } + + #[test] + fn mode_does_not_change_fragment_or_g17p_arrays() { + let (pass, resources) = fixture(); + let geometry = Geometry::new(&pass).unwrap(); + let words = PassWords::new(&pass).unwrap(); + for scs in [false, true] { + let mut args = args(&pass, &resources, scs); + let (before, count) = fragment_registers_25g83(&args, &geometry, &words).unwrap(); + args.ta_mode_1 = true; + let (after, new_count) = fragment_registers_25g83(&args, &geometry, &words).unwrap(); + assert_eq!(count, 91 + usize::from(scs)); + assert_eq!(new_count, count); + for (old, new) in before.iter().zip(&after).take(count) { + assert_eq!((old.reg, old.value), (new.reg, new.value)); + } + args.programs = RegisterPrograms::G17P; + args.ta_mode_1 = false; + let before = ta_registers(&args, &geometry, &words).unwrap(); + args.ta_mode_1 = true; + let after = ta_registers(&args, &geometry, &words).unwrap(); + for (old, new) in before.iter().zip(&after) { + assert_eq!((old.reg, old.value), (new.reg, new.value)); + assert_ne!({ new.reg }, 0x1c890); + } + } + } +} diff --git a/drivers/gpu/drm/asahi/g17/fw/variant.rs b/drivers/gpu/drm/asahi/g17/fw/variant.rs index 03d5bfccafeca..5eb3047890f90 100644 --- a/drivers/gpu/drm/asahi/g17/fw/variant.rs +++ b/drivers/gpu/drm/asahi/g17/fw/variant.rs @@ -36,7 +36,22 @@ pub(crate) enum InitGraph { V25G83, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub(crate) enum QueueRegistration { + Firmware, + PoweredRenderPairs, + Mailbox, +} + +#[derive(Copy, Clone, PartialEq, Eq)] +pub(crate) enum FirmwareVersion { + V26A428, + V25G83, + V25F84, +} + /// The layouts and rules of one G17 firmware build. +#[derive(Copy, Clone)] pub(crate) struct Variant { /// The initialization graph. pub(crate) graph: InitGraph, @@ -49,8 +64,7 @@ pub(crate) struct Variant { pub(crate) qid_floor: usize, /// Host words of a queue's pointer block. pub(crate) pointers: PointerLayout, - /// The host registers each render pair through the GPU's MMIO queue ports. - pub(crate) mmio_pair_registration: bool, + pub(crate) registration: QueueRegistration, /// Render kick entries may name an MCache table. pub(crate) mcache: bool, /// Renders may set the few-primitives auxiliary framebuffer flag. @@ -65,6 +79,12 @@ pub(crate) struct Variant { pub(crate) lead_commands: bool, /// Register programs of the render descriptors. pub(crate) programs: super::render::RegisterPrograms, + /// Use 0x1c890 = 1, 0x1c918 = 0 in V25G83-format tiling arrays (device/build policy). + pub(crate) ta_mode_1: bool, + pub(crate) compute: super::compute::ComputeProgram, + pub(crate) opening_record: bool, + pub(crate) split_firmware_area: bool, + pub(crate) version: FirmwareVersion, } /// A firmware build a SoC supports, identified by its loaded TEXT. @@ -77,6 +97,9 @@ pub(crate) struct Build { pub(crate) images: &'static [crate::fwid::FirmwareBuild], /// Layouts and rules of the build. pub(crate) variant: &'static Variant, + /// The SoC configuration measured with this build, which replaces the probed one when + /// the build is identified; `None` keeps the probed configuration. + pub(crate) config: Option<&'static crate::g17::Config>, } /// How a SoC's firmware build is determined. @@ -98,13 +121,18 @@ pub(crate) const V26A428: Variant = Variant { producer: 0x40, recovery_target: Some(0x50), }, - mmio_pair_registration: true, + registration: QueueRegistration::PoweredRenderPairs, mcache: true, few_primitives: true, ray_traversal: true, fragment_busy: true, lead_commands: false, programs: super::render::RegisterPrograms::G17P, + ta_mode_1: false, + compute: super::compute::ComputeProgram::G17P, + opening_record: true, + split_firmware_area: false, + version: FirmwareVersion::V26A428, }; /// The M4 Pro firmware (25G83, `mBoot-18000.161.10`). @@ -122,7 +150,7 @@ pub(crate) const V25G83: Variant = Variant { }, // Whether this build tolerates the MMIO registration is unknown; the M4 Pro has only run // without it. - mmio_pair_registration: false, + registration: QueueRegistration::Firmware, mcache: false, // A fragment stage with the few-primitives flag hangs. few_primitives: false, @@ -132,9 +160,31 @@ pub(crate) const V25G83: Variant = Variant { fragment_busy: false, lead_commands: true, programs: super::render::RegisterPrograms::V25G83, + ta_mode_1: false, + compute: super::compute::ComputeProgram::G17P, + opening_record: true, + split_firmware_area: false, + version: FirmwareVersion::V25G83, }; +pub(crate) const V25F84: Variant = Variant { + version: FirmwareVersion::V25F84, + qid_floor: 0, + registration: QueueRegistration::Mailbox, + compute: super::compute::ComputeProgram::V25F84, + opening_record: false, + split_firmware_area: true, + ..V25G83 +}; + +impl Variant { + pub(crate) const fn is_25f84(&self) -> bool { + matches!(self.version, FirmwareVersion::V25F84) + } +} + const _: () = { assert!(super::queue::PointerBlock::valid_layout(&V26A428.pointers)); assert!(super::queue::PointerBlock::valid_layout(&V25G83.pointers)); + assert!(super::queue::PointerBlock::valid_layout(&V25F84.pointers)); }; diff --git a/drivers/gpu/drm/asahi/g17/initdata.rs b/drivers/gpu/drm/asahi/g17/initdata.rs index 578bb7533f3c9..56e7335a23bd2 100644 --- a/drivers/gpu/drm/asahi/g17/initdata.rs +++ b/drivers/gpu/drm/asahi/g17/initdata.rs @@ -862,7 +862,7 @@ impl InitData { clusters, }; if variant.graph == super::fw::variant::InitGraph::V25G83 { - return self.build_25g83(&env, cfg, metrics, active_cores); + return self.build_25g83(&env, cfg, metrics, active_cores, variant); } self.map_register_windows(&env, cfg.windows)?; let tables = self.build_descriptor_tables(&env, abi::private::SIZE)?; diff --git a/drivers/gpu/drm/asahi/g17/initdata/v25g83.rs b/drivers/gpu/drm/asahi/g17/initdata/v25g83.rs index 670f4b96dcb76..838c88870c1e8 100644 --- a/drivers/gpu/drm/asahi/g17/initdata/v25g83.rs +++ b/drivers/gpu/drm/asahi/g17/initdata/v25g83.rs @@ -18,6 +18,7 @@ use kernel::{c_str, prelude::*}; struct Objects { views: [usize; 5], firmware_area: usize, + firmware_area_2: Option, power_state: usize, aon: usize, } @@ -30,6 +31,7 @@ impl InitData { cfg: &Config, metrics: &KernelObject, active_cores: u32, + variant: &crate::g17::fw::Variant, ) -> Result { self.status_a = v::private::STATUS_A; self.status_b = v::private::STATUS_B; @@ -39,9 +41,9 @@ impl InitData { let first_block = self.build_render_pool(env)?; self.build_compute_pools(env, first_block)?; let bundle = self.build_bundle(env, cfg, metrics)?; - let objects = self.build_25g83_objects(env)?; + let objects = self.build_25g83_objects(env, variant.split_firmware_area)?; self.views = Some(objects.views); - self.initialize_25g83(env, cfg, active_cores, &tables, &bundle, &objects)?; + self.initialize_25g83(env, cfg, active_cores, &tables, &bundle, &objects, variant)?; if cfg.uat_quirks.clean_tables { // Write back every host-built byte before the firmware may read it. for object in self.objects.iter_mut() { @@ -53,8 +55,7 @@ impl InitData { Ok(()) } - /// The views, the firmware area, the power-state object and the AON table. - fn build_25g83_objects(&mut self, env: &BuildEnv<'_>) -> Result { + fn build_25g83_objects(&mut self, env: &BuildEnv<'_>, split: bool) -> Result { use mmu::{PROT_FW_PRIV_RW as FP, PROT_FW_SHARED_RW as FS}; use CpuMap::WriteCombined as WC; let mut views = [0; 5]; @@ -63,12 +64,17 @@ impl InitData { } let firmware_area = self.add(env.fixed(v::kernel_window::FIRMWARE_AREA, mmu::UAT_PGSZ, FP, WC)?)?; + let firmware_area_2 = match split { + true => Some(self.add(env.dynamic(mmu::UAT_PGSZ, mmu::UAT_PGSZ as u64, FP, WC)?)?), + false => None, + }; let power_state = self.add(env.fixed(v::kernel_window::POWER_STATE, mmu::UAT_PGSZ, FS, WC)?)?; let aon = self.add(env.fixed(v::kernel_window::AON_TABLE, mmu::UAT_PGSZ, FP, WC)?)?; Ok(Objects { views, firmware_area, + firmware_area_2, power_state, aon, }) @@ -84,70 +90,103 @@ impl InitData { tables: &DescriptorTables, bundle: &BundleObjects, objects: &Objects, + variant: &crate::g17::fw::Variant, ) -> Result { let bundle_va = self.object(self.bundle)?.gpu_va(); let cluster_va = self.object(self.cluster)?.gpu_va(); let config_va = cluster_va + v::private::CONFIG as u64; let status_a_va = cluster_va + v::private::STATUS_A as u64; let status_b_va = cluster_va + v::private::STATUS_B as u64; - let aon_va = self.object(objects.aon)?.gpu_va(); + let chip = cfg.chip; + let aon_table = match cfg.captured { + Some(captured) => captured.aon_table, + None => chip.map_or(v::AON_TABLE.as_slice(), |chip| chip.aon_table), + }; + let aon_va = match aon_table.is_empty() { + true => 0, + false => self.object(objects.aon)?.gpu_va(), + }; let power_state_va = self.object(objects.power_state)?.gpu_va(); let firmware_area_va = self.object(objects.firmware_area)?.gpu_va(); + let firmware_area_2_va = match objects.firmware_area_2 { + Some(index) => self.object(index)?.gpu_va(), + None => firmware_area_va, + }; let mut view_va = [0; 5]; for (va, index) in view_va.iter_mut().zip(objects.views) { *va = self.object(index)?.gpu_va(); } - let opps = Self::opps(env.dev, cfg.opps, env.clusters)?; - let cs_opps = Self::opp_table(env.dev, c_str!("apple,cs-opp"))?; - let afr_opps = Self::opp_table(env.dev, c_str!("apple,afr-opp"))?; - let calibration = Calibration::read(env.dev)?; - calibration.check_opps(&opps)?; - let hw_args = abi::HwDataArgs { - chip_id: cfg.chip_id, - windows: cfg.windows, - reserved_slots: cfg.reserved_slots, - opps: &opps, - perf: &calibration.perf, - completion_rings: bundle.completion_rings, - qos_va: self.object(bundle.qos)?.gpu_va(), - }; - let hw_args_25g83 = v::HwDataArgs25G83 { - active_cores, - cs_opps: &cs_opps, - afr_opps: &afr_opps, - }; - // SAFETY: Plain C entropy source. - let entropy = unsafe { kernel::bindings::get_random_u32() }; - self.object_mut(self.bundle)? - .initialize::(0, |hw| { - hw.init(&hw_args, &hw_args_25g83)?; - Ok(()) - })?; - self.object_mut(self.bundle)? - .initialize::(v::POWER_CONFIG, |power| { - power.init( - config_va, - aon_va, - entropy, + if let Some(captured) = cfg.captured { + self.write_captured_25g83(env, cfg, captured, active_cores, bundle, config_va, aon_va)?; + } else { + let opps = Self::opps(env.dev, cfg.opps, env.clusters)?; + let cs_opps = Self::opp_table(env.dev, c_str!("apple,cs-opp"))?; + let afr_opps = Self::opp_table(env.dev, c_str!("apple,afr-opp"))?; + let calibration = if chip.is_none() { + let calibration = Calibration::read(env.dev)?; + calibration.check_opps(&opps)?; + Some(calibration) + } else { + None + }; + let (perf, max_power_mw, leakage) = match (calibration.as_ref(), chip) { + (Some(calibration), None) => ( + &calibration.perf, calibration.max_power_mw, &calibration.leakage, - ); - Ok(()) - })?; - self.object_mut(self.region_c)? - .initialize::(0, |region| { - region.init(cfg.region_c); - region.max_power_mw = calibration.max_power_mw; - Ok(()) - })?; - for (index, word) in v::AON_TABLE.iter().enumerate() { + ), + (None, Some(chip)) => (cfg.perf, chip.max_power_mw, &chip.leakage), + _ => return Err(EINVAL), + }; + let hw_args = abi::HwDataArgs { + chip_id: cfg.chip_id, + windows: cfg.windows, + reserved_slots: cfg.reserved_slots, + opps: &opps, + perf, + completion_rings: bundle.completion_rings, + qos_va: self.object(bundle.qos)?.gpu_va(), + }; + let hw_args_25g83 = v::HwDataArgs25G83 { + active_cores, + cs_opps: &cs_opps, + afr_opps: &afr_opps, + chip, + }; + // SAFETY: Plain C entropy source. + let entropy = unsafe { kernel::bindings::get_random_u32() }; + self.object_mut(self.bundle)? + .initialize::(0, |hw| { + hw.init(&hw_args, &hw_args_25g83)?; + Ok(()) + })?; + self.object_mut(self.bundle)? + .initialize::(v::POWER_CONFIG, |power| { + power.init(config_va, aon_va, entropy, max_power_mw, leakage); + if let Some(chip) = chip { + power.apply_chip(chip)?; + } + Ok(()) + })?; + self.object_mut(self.region_c)? + .initialize::(0, |region| { + region.init(cfg.region_c); + region.max_power_mw = max_power_mw; + Ok(()) + })?; + } + for (index, word) in aon_table.iter().enumerate() { self.object_mut(objects.aon)?.write(index * 4, *word)?; } // Status A and B: only the boot words and the firmware-control pointers. + let mut status_a = abi::StatusBlock::new(); + if variant.is_25f84() && crate::module_parameters::t6041_fw_log.value() != 0 { + status_a.unk_0 = 3; + } self.object_mut(self.cluster)? - .write(v::private::STATUS_A, abi::StatusBlock::new())?; + .write(v::private::STATUS_A, status_a)?; self.object_mut(self.cluster)? .write(v::private::STATUS_B, abi::StatusBlock::new())?; // Status B keeps the A18 Pro's field offsets up to its recovery words. @@ -180,19 +219,24 @@ impl InitData { .initialize::(main_offset, |main| { main.init_primary(&args, &views); main.view_va = view_va; - main.firmware_area_va = [firmware_area_va; 2]; + main.firmware_area_va = [firmware_area_va, firmware_area_2_va]; main.unk_18 = (cluster_va + v::private::MAIN_HEADER as u64).to_le_bytes(); // The secondary role's words, on the single instance. main.unk_300 = 4; main.power_config_va = bundle_va + v::POWER_CONFIG as u64; main.unk_32c = 0; main.unk_344 = 0; + if variant.is_25f84() && crate::module_parameters::t6041_fw_log.value() != 0 { + main.log_enable = 1; + } Ok(()) })?; - self.object_mut(self.bundle)?.write( - main_offset + abi::MainConfig::CONTROL_RING, - abi::OpeningRecord::new(abi::Role::Primary), - )?; + if variant.opening_record { + self.object_mut(self.bundle)?.write( + main_offset + abi::MainConfig::CONTROL_RING, + abi::OpeningRecord::new(abi::Role::Primary), + )?; + } // The merged root. let root = abi::RootArgs { @@ -214,12 +258,11 @@ impl InitData { } } - // The opening control record is staged in slot 0. - for (offset, value) in [ - (0, 0), - (0x10, 0), - (abi::ChannelState::PRODUCER, abi::OPENING_PRODUCER), - ] { + let producer = match variant.opening_record { + true => abi::OPENING_PRODUCER, + false => 0, + }; + for (offset, value) in [(0, 0), (0x10, 0), (abi::ChannelState::PRODUCER, producer)] { self.object(self.cluster)? .word(self.state_offset(Role::Primary) + abi::CONTROL_STATE_OFFSET + offset)? .store(value, Ordering::Relaxed); @@ -227,4 +270,74 @@ impl InitData { fence(Ordering::SeqCst); Ok(()) } + + /// Writes the hardware data, power configuration and region C captured on one unit, with + /// this boot's runtime words over them, and checks the result against the capture's hashes. + /// No operating points are read from the device tree: the captured tables hold the unit's. + fn write_captured_25g83( + &mut self, + env: &BuildEnv<'_>, + cfg: &Config, + captured: &v::Captured, + active_cores: u32, + bundle: &BundleObjects, + config_va: u64, + aon_va: u64, + ) -> Result { + if active_cores != captured.active_cores { + dev_err!( + env.dev.as_ref(), + "25G83 initialization data was captured with {} cores, the GPU has {}\n", + captured.active_cores, + active_cores + ); + return Err(EINVAL); + } + let hw_args = abi::HwDataArgs { + chip_id: cfg.chip_id, + windows: cfg.windows, + reserved_slots: cfg.reserved_slots, + opps: &[], + perf: cfg.perf, + completion_rings: bundle.completion_rings, + qos_va: self.object(bundle.qos)?.gpu_va(), + }; + // SAFETY: Plain C entropy source. + let entropy = unsafe { kernel::bindings::get_random_u32() }; + let mut hashes = [0; 3]; + self.object_mut(self.bundle)? + .initialize::(0, |hw| { + hw.init_captured(captured, &hw_args).inspect_err(|_| { + dev_err!( + env.dev.as_ref(), + "Captured 25G83 hardware data does not match chip {:#x} and its register windows\n", + cfg.chip_id + ); + })?; + hashes[0] = hw.hash_captured(); + Ok(()) + })?; + self.object_mut(self.bundle)? + .initialize::(v::POWER_CONFIG, |power| { + power.init_captured(captured.power_config, config_va, aon_va, entropy); + hashes[1] = power.hash(); + Ok(()) + })?; + self.object_mut(self.region_c)? + .initialize::(0, |region| { + region.init_captured(captured.region_c); + Ok(()) + })?; + hashes[2] = v::hash_without(self.object_mut(self.region_c)?.bytes_mut(), &[]); + if hashes != captured.expected { + dev_err!( + env.dev.as_ref(), + "25G83 initialization data differs from its capture: {:#x?}, expected {:#x?}\n", + hashes, + captured.expected + ); + return Err(EINVAL); + } + Ok(()) + } } diff --git a/drivers/gpu/drm/asahi/g17/mod.rs b/drivers/gpu/drm/asahi/g17/mod.rs index cc3b1297f0467..bc65660e290e9 100644 --- a/drivers/gpu/drm/asahi/g17/mod.rs +++ b/drivers/gpu/drm/asahi/g17/mod.rs @@ -193,6 +193,10 @@ pub(crate) struct Config { pub(crate) fabric_bridge: bool, /// The SoC's values of region C. pub(crate) region_c: &'static fw::initdata::RegionCConfig, + pub(crate) chip: Option<&'static fw::initdata::v25g83::Chip>, + /// 25G83 initialization contents captured on one unit, written instead of what the + /// builders produce; `None` builds them. + pub(crate) captured: Option<&'static fw::initdata::v25g83::Captured>, /// Physical address of the firmware's per-slot recovery keys, read while the firmware is /// halted to attribute a fault; `None` where it is unknown (recovery then relies on the /// firmware's own blame). @@ -214,6 +218,7 @@ pub(crate) struct CoreLayout { pub(crate) operand_state: fw::compute::OperandState, /// A render's deflake buffer. pub(crate) deflake: fw::render::Deflake, + pub(crate) compute_blocks: usize, } /// Where a G17 target's crash log buffers live. @@ -1124,8 +1129,9 @@ impl Shared { self.crashed.store(true, Ordering::Release); dev_err!( self.dev.as_ref(), - "GPU firmware ({:?}) crashed, device lost\n", - role + "GPU firmware ({:?}) crashed, device lost (crash log {} bytes)\n", + role, + crashlog.map_or(0, |log| log.len()) ); // The GPU dev coredump support this used is gone; the crash log is not published. @@ -1166,7 +1172,12 @@ impl Gpu { } else { None }; - let variant = Self::firmware_variant(dev, &cfg.firmware)?; + let (variant, measured) = Self::firmware_variant(dev, &cfg.firmware)?; + // A build measured with its own configuration of the SoC runs with that one. + let cfg = measured.unwrap_or(cfg); + variant.compute.select(); + fw::compute_pool::set_base_blocks(cfg.core_layout.compute_blocks) + .inspect_err(|_| dev_err!(dev.as_ref(), "Invalid compute pool size\n"))?; let id = regs.get_g17_id()?; if let Some(calibration) = calibration { calibration.check_cores(&id.core_masks)?; @@ -1300,14 +1311,15 @@ impl Gpu { Ok(gpu) } - /// Returns the variant of the loaded firmware build. An identified SoC refuses a build it - /// does not know, before anything is written to the GPU. + /// Returns the variant of the loaded firmware build and the configuration measured with it, + /// if it has its own. An identified SoC refuses a build it does not know, before anything + /// is written to the GPU. fn firmware_variant( dev: &AsahiDrmDevice, firmware: &fw::variant::Firmware, - ) -> Result<&'static fw::Variant> { + ) -> Result<(&'static fw::Variant, Option<&'static Config>)> { let builds = match firmware { - fw::variant::Firmware::Fixed(variant) => return Ok(variant), + fw::variant::Firmware::Fixed(variant) => return Ok((variant, None)), fw::variant::Firmware::Identified(builds) => builds, }; let version = Self::os_firmware_version(dev); @@ -1322,7 +1334,7 @@ impl Gpu { for build in Iterator::chain(preferred, others) { if Self::identify_image(dev, build).is_ok() { dev_info!(dev.as_ref(), "GPU firmware: {}\n", build.name); - return Ok(build.variant); + return Ok((build.variant, build.config)); } } dev_err!( @@ -1493,18 +1505,24 @@ impl Gpu { session.port.attach( session.init.port_views(mailbox)?, session.bridge.regs.clone(), + shared.variant.registration, )?; session.uat.mirror_secondary_root()?; if cfg.fabric_bridge { session.bridge.regs.enable_g17_gating()?; } let ack = shared.variant.init_ack; - session - .primary - .init(session.init.root_va(Role::Primary)?, ack)?; + let root_va = session.init.root_va(Role::Primary)?; + dev_info!( + dev.as_ref(), + "bring-up: initialization data built, publishing root {:#x}\n", + root_va + ); + session.primary.init(root_va, ack)?; if ack == fw::variant::InitAck::Status { Self::wait_for_init_accepted(dev, &session.init, &session.primary)?; } + dev_info!(dev.as_ref(), "bring-up: initialization data accepted\n"); if let Some(secondary) = session.secondary.as_mut() { secondary.init(session.init.root_va(Role::Secondary)?, ack)?; } @@ -1514,15 +1532,25 @@ impl Gpu { secondary.notify(MSG_POWER_ON_DONE)?; } } - Self::wait_for_opening( - dev, - &session.init, - &session.primary, - session.secondary.as_ref(), - )?; + if shared.variant.opening_record { + Self::wait_for_opening( + dev, + &session.init, + &session.primary, + session.secondary.as_ref(), + )?; + dev_info!(dev.as_ref(), "bring-up: opening record retired\n"); + } else { + dev_info!( + dev.as_ref(), + "bring-up: no opening record staged; device-control counters {:?}\n", + session.init.control_counters()? + ); + } session .uat .activate_render_context(&session._render_global)?; + dev_info!(dev.as_ref(), "bring-up: firmware running\n"); Ok(firmware) } diff --git a/drivers/gpu/drm/asahi/g17/port.rs b/drivers/gpu/drm/asahi/g17/port.rs index 6f9d1c7d956c0..5e759bb2b7d18 100644 --- a/drivers/gpu/drm/asahi/g17/port.rs +++ b/drivers/gpu/drm/asahi/g17/port.rs @@ -91,8 +91,8 @@ unsafe impl Sync for Views {} #[pin_data] pub(super) struct Port { views: SetOnce, - /// Register access for tracing the core power state at the doorbell. regs: SetOnce, + registration: SetOnce, /// Compute work-ring slots reserved by publishers that have not exposed them yet. #[pin] rings: SpinLock<[u32; PRIORITIES]>, @@ -163,6 +163,7 @@ impl Port { pin_init!(Self { views: SetOnce::new(), regs: SetOnce::new(), + registration: SetOnce::new(), rings <- new_spinlock!([0; PRIORITIES], "g17::Port::rings"), qos <- new_spinlock!(qos::Accounting::new(), "g17::Port::qos"), rx: SetOnce::new(), @@ -182,17 +183,37 @@ impl Port { } /// Called once while the session is built, before any publisher can see the port. - pub(super) fn attach(&self, views: Views, regs: crate::regs::G17Resources) -> Result { - // SAFETY: The session's primary coprocessor owns the mailbox and outlives the port, and - // with it every use of the handle. + pub(super) fn attach( + &self, + views: Views, + regs: crate::regs::G17Resources, + registration: super::fw::variant::QueueRegistration, + ) -> Result { + // SAFETY: The session owns the mailbox and outlives every port user. let rx = unsafe { (*views.mailbox).rx_util_min_handle() }; - if self.views.populate(views) && self.regs.populate(regs) && self.rx.populate(rx) { + if self.views.populate(views) + && self.regs.populate(regs) + && self.registration.populate(registration) + && self.rx.populate(rx) + { Ok(()) } else { Err(EBUSY) } } + pub(super) fn register_queues(&self, queues: &[super::fw::kick::KsmQueue]) -> Result { + use super::fw::variant::QueueRegistration; + if self.registration.as_ref() != Some(&QueueRegistration::Mailbox) { + return Ok(()); + } + let regs = self.regs.as_ref().ok_or(ENODEV)?; + for queue in queues { + regs.register_ksm_queue(queue.qid, queue.descriptor)?; + } + Ok(()) + } + fn views(&self) -> Result<&Views> { self.views.as_ref().ok_or(ENODEV) } diff --git a/drivers/gpu/drm/asahi/g17/queue/admission.rs b/drivers/gpu/drm/asahi/g17/queue/admission.rs index f09e629aa047e..c0804f2d84594 100644 --- a/drivers/gpu/drm/asahi/g17/queue/admission.rs +++ b/drivers/gpu/drm/asahi/g17/queue/admission.rs @@ -62,6 +62,7 @@ fn wait_slice_ms(deadline_ns: u64, now_ns: u64) -> Result { } struct State { + serial_render: bool, active: u64, refs: [u8; cfg::RENDER_SLOTS], owners: [u64; cfg::RENDER_SLOTS], @@ -88,6 +89,7 @@ impl State { const MASK: u64 = (u64::MAX >> (64 - cfg::RENDER_SLOTS)) & !1; const fn new() -> Self { Self { + serial_render: false, active: 0, refs: [0; cfg::RENDER_SLOTS], owners: [0; cfg::RENDER_SLOTS], @@ -334,8 +336,15 @@ impl State { ) } + fn serial_busy(&self) -> bool { + self.serial_render && self.refs.iter().any(|&count| count != 0) + } + /// Whether `pick` would return a slot, without taking it. fn can_pick(&self, owner: u64, plan: Plan) -> bool { + if self.serial_busy() { + return false; + } let usable = |slot: usize| { self.owners[slot] == owner && (self.quarantined | self.kill_hold) & (1u64 << slot) == 0 @@ -357,6 +366,9 @@ impl State { } fn pick(&mut self, owner: u64, plan: Plan) -> Option { + if self.serial_busy() { + return None; + } match plan { Plan::Any => self.acquire(owner), Plan::Wait => None, @@ -466,6 +478,10 @@ impl Pool { GFP_KERNEL, ) } + pub(crate) fn serialize_render(&self) { + self.state.lock().serial_render = true; + } + /// Every pair or lease return, owner close and quarantine change. fn returned(&self) { self.released.notify_all(); diff --git a/drivers/gpu/drm/asahi/g17/queue/compute.rs b/drivers/gpu/drm/asahi/g17/queue/compute.rs index 55994066825f8..a9f5c48e9a0b5 100644 --- a/drivers/gpu/drm/asahi/g17/queue/compute.rs +++ b/drivers/gpu/drm/asahi/g17/queue/compute.rs @@ -2149,6 +2149,7 @@ pub(crate) trait Host { ) -> Result; fn qos_cancel(&mut self, publication: qos::Publication) -> Result; fn publish_qid(&mut self, id: kick::Id) -> Result; + fn register_queue(&mut self, queue: &crate::g17::fw::kick::KsmQueue) -> Result; fn publish_outer(&mut self, priority: u8, slot: &crate::g17::fw::channels::WorkSlot) -> Result; fn notify(&mut self, message: u64) -> Result; fn note_submission(&mut self) -> Result; @@ -2364,9 +2365,16 @@ impl Queue { )?; wait_vas.push(address, GFP_KERNEL)?; } + let kick_ring_va = self.kick.low_va(); let prepared_kick = self.kick.prepare_entry(&kick_args)?; let mut producer; if first { + host.register_queue(&crate::g17::fw::kick::KsmQueue::new( + qid, + kick_ring_va, + DataMaster::Compute, + policy.priority(), + )?)?; producer = self.graph.first_descriptor(descriptor_high)?; host.prepare_compute_shared()?; packet.mark_published(); diff --git a/drivers/gpu/drm/asahi/g17/queue/mod.rs b/drivers/gpu/drm/asahi/g17/queue/mod.rs index b7037a1c35f75..8d9d589dca362 100644 --- a/drivers/gpu/drm/asahi/g17/queue/mod.rs +++ b/drivers/gpu/drm/asahi/g17/queue/mod.rs @@ -165,6 +165,7 @@ impl Queue { fn prune_frontier(&mut self, index: usize) { let failure = &mut self.failures[index]; + let transient_ok = self.variant.is_25f84(); // Without room the entries are released here, as they always could be. let mut finished = if self .finished @@ -183,7 +184,13 @@ impl Queue { if let Some(finished) = finished.as_mut() { let _ = finished.push_within_capacity(fences.clone()); } - failure.note(*sequence, status, fences); + let transient = transient_ok + && [ECANCELED, ENODATA, EBUSY] + .iter() + .any(|error| error.to_errno() == status); + if !transient { + failure.note(*sequence, status, fences); + } false }); } diff --git a/drivers/gpu/drm/asahi/g17/queue/render.rs b/drivers/gpu/drm/asahi/g17/queue/render.rs index 2436cfd33ed35..9019271b239d0 100644 --- a/drivers/gpu/drm/asahi/g17/queue/render.rs +++ b/drivers/gpu/drm/asahi/g17/queue/render.rs @@ -466,6 +466,7 @@ impl Pair { aux_stamp_va: addresses.stamps[1][1], }, programs: self.variant.programs, + ta_mode_1: self.variant.ta_mode_1, deflake: deflake_layout, }; self.memory.graph.claim(ordinal)?; diff --git a/drivers/gpu/drm/asahi/g17/recovery.rs b/drivers/gpu/drm/asahi/g17/recovery.rs index ca8da8b03545f..b19642ead54e1 100644 --- a/drivers/gpu/drm/asahi/g17/recovery.rs +++ b/drivers/gpu/drm/asahi/g17/recovery.rs @@ -282,7 +282,8 @@ pub(super) fn service( host.recovery_mut().pending = None; let (listed, exact, fallback) = (entries.listed, entries.exact, entries.fallback); - let (cancelled, blame) = classify(host, entries, request.blamed, attribution); + let lenient = sources.spare_reason_zero && sources.reason == Some(0); + let (cancelled, blame) = classify(host, entries, request.blamed, attribution, lenient); if listed != 0 { pr_warn!( "G17: GPU recovery: {} commands were in flight ({} matched by stamp, {} by queue); they fail instead of completing\n", @@ -336,7 +337,7 @@ fn read_entries(host: &mut H) -> Entries { /// Also returns whether the firmware's blamed QID is still guilty after attribution: a blamed /// render that had not started while others had (or with no culprit at all) is innocent, and its /// work is spared like that of every other innocent VM instead of failing with EIO. -fn classify(queues: &mut Q, entries: Entries, blamed: Option, attribution: Attribution) -> (u128, bool) { +fn classify(queues: &mut Q, entries: Entries, blamed: Option, attribution: Attribution, lenient: bool) -> (u128, bool) { let mut guilty_qids = entries.guilty | blamed.map_or(0, |qid| 1u128 << qid); let cancelled = entries.cancelled; match attribution { @@ -385,6 +386,9 @@ fn classify(queues: &mut Q, entries: Entries, blamed: Option, att if unresolved || (count == 0 && collateral == 0 && !no_culprit) { return (0, blame); } + if lenient && count != 0 { + pr_warn!("G17: GPU recovery reason 0 is not a decoded fault; a first-time blamed VM stays usable\n"); + } let spared = queues.classify_work(&|status| { guilty[..count] .iter() @@ -392,7 +396,13 @@ fn classify(queues: &mut Q, entries: Entries, blamed: Option, att known .as_ref() .filter(|known| Arc::ptr_eq(known, status)) - .map(|_| Class::Guilty) + .map(|_| { + if lenient && status.reported_error() == 0 { + Class::Spared + } else { + Class::Guilty + } + }) }) .unwrap_or(Class::Spared) }); diff --git a/drivers/gpu/drm/asahi/g17/recovery/attribution.rs b/drivers/gpu/drm/asahi/g17/recovery/attribution.rs index 38ad8612a0b99..fc910df58b370 100644 --- a/drivers/gpu/drm/asahi/g17/recovery/attribution.rs +++ b/drivers/gpu/drm/asahi/g17/recovery/attribution.rs @@ -17,6 +17,7 @@ pub(super) struct Source { pub(crate) struct Sources { pub(crate) reason: Option, + pub(crate) spare_reason_zero: bool, mask: u32, records: [Source; SLOTS], count: usize, @@ -52,6 +53,7 @@ impl Sources { pub(crate) fn sample(mask: u32, mut read: impl FnMut(usize) -> Option<(u64, u32)>) -> Self { let mut sources = Self { reason: None, + spare_reason_zero: false, mask, records: [Source::default(); SLOTS], count: 0, diff --git a/drivers/gpu/drm/asahi/g17/runtime.rs b/drivers/gpu/drm/asahi/g17/runtime.rs index d391fbb3001bb..da5eb866234e9 100644 --- a/drivers/gpu/drm/asahi/g17/runtime.rs +++ b/drivers/gpu/drm/asahi/g17/runtime.rs @@ -213,7 +213,14 @@ impl Registry { buffers <- BufferIds::new(), metrics: Arc::new(MetricsIds::new(), GFP_KERNEL)?, qos_ids: QosIds::new()?, - admission: admission::Pool::with_waiters(kick::queue_limit(variant.qid_floor), queues, renders)?, + admission: { + let admission = admission::Pool::with_waiters(kick::queue_limit(variant.qid_floor), queues, renders)?; + if variant.is_25f84() && crate::module_parameters::t6041_serial_render.value() != 0 { + admission.serialize_render(); + pr_warn!("T6041 25F84: serial render admission enabled (one outstanding render lease)\n"); + } + admission + }, render: render::RenderState::new(clusters, deflake, descriptor_flags)?, identities: queue::Identities::new(), compute: { @@ -1399,6 +1406,9 @@ impl compute::Host for ComputeHost<'_> { fn publish_qid(&mut self, id: kick::Id) -> Result { self.qids.publish(id) } + fn register_queue(&mut self, queue: &super::fw::kick::KsmQueue) -> Result { + self.port.register_queues(core::slice::from_ref(queue)) + } fn publish_outer(&mut self, _priority: u8, slot: &super::fw::channels::WorkSlot) -> Result { self.port.publish_compute(self.outer.take().ok_or(EIO)?, slot).map(|_| ()) } @@ -1443,6 +1453,9 @@ impl compute::Host for DirectHost<'_> { // An installed queue published its identity with its first command. Ok(()) } + fn register_queue(&mut self, _queue: &super::fw::kick::KsmQueue) -> Result { + Err(EAGAIN) + } fn publish_outer(&mut self, _priority: u8, slot: &super::fw::channels::WorkSlot) -> Result { self.port.publish_compute(self.outer.take().ok_or(EIO)?, slot).map(|_| ()) } diff --git a/drivers/gpu/drm/asahi/g17/runtime/events.rs b/drivers/gpu/drm/asahi/g17/runtime/events.rs index 3e779bba4fbbf..f97b6b4413c6b 100644 --- a/drivers/gpu/drm/asahi/g17/runtime/events.rs +++ b/drivers/gpu/drm/asahi/g17/runtime/events.rs @@ -137,7 +137,9 @@ impl recovery::Memory for Service<'_> { self.firmware.init.host_recovery() } fn fault_sources(&self) -> Result { - self.firmware.init.fault_sources() + let mut sources = self.firmware.init.fault_sources()?; + sources.spare_reason_zero = self.firmware.variant.is_25f84(); + Ok(sources) } fn transition(&self, expected: u32, next: u32) -> Result { diff --git a/drivers/gpu/drm/asahi/g17/runtime/render.rs b/drivers/gpu/drm/asahi/g17/runtime/render.rs index 6657f83e9e738..fc2e01be761ae 100644 --- a/drivers/gpu/drm/asahi/g17/runtime/render.rs +++ b/drivers/gpu/drm/asahi/g17/runtime/render.rs @@ -572,10 +572,14 @@ impl crate::g17::queue::render::Host for Host<'_> { /// check let the firmware gate the cores between the host's configuration /// writes while several clients installed their first pairs at once. fn install_pair(&mut self, registration: &crate::g17::fw::kick::RenderRegistration) -> Result { - // Firmware builds without MMIO registration install the pair from its queue - // configuration alone. - if !self.firmware.variant.mmio_pair_registration { - return Ok(()); + use crate::g17::fw::variant::QueueRegistration; + match self.firmware.variant.registration { + QueueRegistration::Firmware => return Ok(()), + QueueRegistration::Mailbox => { + self.firmware.port.register_queues(registration.queues())?; + return Ok(()); + } + QueueRegistration::PoweredRenderPairs => {} } if !self.registration_powered { self.firmware.acquire_registration_power()?; diff --git a/drivers/gpu/drm/asahi/hw/mod.rs b/drivers/gpu/drm/asahi/hw/mod.rs index 2650131a4a293..53ce20c85351a 100644 --- a/drivers/gpu/drm/asahi/hw/mod.rs +++ b/drivers/gpu/drm/asahi/hw/mod.rs @@ -14,6 +14,10 @@ const MAX_POWERZONES: usize = 5; pub(crate) mod t600x; pub(crate) mod t602x; pub(crate) mod t6040; +pub(crate) mod t6041; +mod t6041_25g83; +mod t6041_captured; +mod t604x; pub(crate) mod t8103; pub(crate) mod t8112; pub(crate) mod t8140; diff --git a/drivers/gpu/drm/asahi/hw/t6040.rs b/drivers/gpu/drm/asahi/hw/t6040.rs index 11ed37a7c1ef8..adb596a1921d4 100644 --- a/drivers/gpu/drm/asahi/hw/t6040.rs +++ b/drivers/gpu/drm/asahi/hw/t6040.rs @@ -11,6 +11,7 @@ use crate::g17::fw::{ }; use crate::g17::{Config, CoreLayout, CrashBuffers, FixedBuffer, Identity}; use crate::hw::{GpuGen, GpuVariant}; +use super::t604x::{instances, window}; use crate::mmu::UatQuirks; /// Static configuration of the T6040 GPU. @@ -51,6 +52,8 @@ pub(crate) const CONFIG: Config = Config { native_gpu_permissions: true, }, region_c: ®ION_C, + chip: None, + captured: None, adopt_root_entries: false, fabric_bridge: false, // The firmware's per-slot recovery keys are not known for this build; recovery relies on @@ -98,50 +101,20 @@ pub(crate) const CONFIG: Config = Config { }, ], variant: &fw::variant::V25G83, + config: None, }]), // Measured on the 20-core M4 Pro; other core counts are refused at probe. core_layout: CoreLayout { cores: Some((2, 20)), operand_state: fw::compute::OperandState::TWO_BY_TEN, deflake: fw::render::Deflake::TWO_CLUSTERS, + compute_blocks: fw::freelist::COMPUTE_BLOCKS, }, }; /// Chip identifier written to the hardware data. pub(crate) const CHIP_ID: u32 = 0x6040; -/// Base of the firmware MMIO aperture in the kernel window. -const MMIO_APERTURE: u64 = 0xffff_fc21_8000_0000; - -const fn window( - slot: usize, - phys: u64, - offset: u64, - size: u32, - unk_18: u64, - unk_20: u32, -) -> RegisterWindow { - RegisterWindow { - slot, - phys, - va: MMIO_APERTURE + offset, - size, - unk_18, - unk_20, - instances: 1, - phys_stride: 0, - } -} - -/// `window` repeated `instances` times, `phys_stride` apart in physical memory. -const fn instances(window: RegisterWindow, instances: u32, phys_stride: u64) -> RegisterWindow { - RegisterWindow { - instances, - phys_stride, - ..window - } -} - /// Register windows the firmware maps, by register-map slot. Slot 3 holds the four memory /// controllers (ADT /arm-io/mcc), slot 20 the four AFR blocks. pub(crate) const REGISTER_WINDOWS: [RegisterWindow; 25] = [ diff --git a/drivers/gpu/drm/asahi/hw/t6041.rs b/drivers/gpu/drm/asahi/hw/t6041.rs new file mode 100644 index 0000000000000..a6979b1063de3 --- /dev/null +++ b/drivers/gpu/drm/asahi/hw/t6041.rs @@ -0,0 +1,506 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +use crate::g17::fw::{ + self, + initdata::{v25g83, PerfConfig, RegionCConfig, RegisterWindow, PERF_STATES}, +}; +use crate::g17::{Config, CoreLayout, CrashBuffers, FixedBuffer, Identity}; +use crate::hw::{GpuGen, GpuVariant}; +use super::t604x::{instances, window}; +use crate::mmu::UatQuirks; + +pub(crate) const CONFIG: Config = Config { + chip_id: CHIP_ID, + identity: Identity { + family: 0xa, + variant: 4, + num_dies: 1, + gpu_variant: GpuVariant::C, + usc_generation: 3, + hal_generation: 200, + }, + uat_ias: 42, + uat_oas: 42, + secondary_root_offset: None, + crash_buffers: CrashBuffers::FirmwareData, + // Unverified placement; use the M4 Pro layout. + pm_metrics: FixedBuffer { + va: 0x10_0008_0000, + size: 0x8000, + }, + windows: ®ISTER_WINDOWS, + reserved_slots: &RESERVED_SLOTS, + perf: &PERF, + opps: OPPS, + uat_quirks: UatQuirks { + reserved_tables: true, + clean_tables: true, + page_tlbi: true, + handoff_lock: false, + handoff_slot: 0xffff_ffff, + native_gpu_permissions: true, + }, + region_c: ®ION_C, + chip: Some(&CHIP), + captured: None, + adopt_root_entries: false, + fabric_bridge: false, + recovery_slot_keys: None, + gpu_generation: GpuGen::G16, + // 25F84 runs the static profile of this configuration; 25G83 runs the profile captured on + // the 32-core J616C ([`super::t6041_25g83::CONFIG`]). + firmware: fw::variant::Firmware::Identified(&[ + fw::variant::Build { + os_version: [26, 5, 2], + name: "macOS 26.5.2 (25F84, iBoot mBoot-18000.121.3)", + images: &[crate::fwid::FirmwareBuild { + name: "Apple GFX 25F84 for T6041 (normalized loaded image)", + text_size: 0x60000, + data_size: 0x138000, + entropy: [0x5983a, 0x5991d], + text_sha256: [ + 0x6d, 0xa4, 0xd4, 0x42, 0x35, 0x35, 0x14, 0x44, 0xf6, 0xec, 0x00, 0x33, 0xf1, + 0x9c, 0xbf, 0x98, 0xd3, 0x43, 0x91, 0x28, 0x83, 0xe4, 0xe2, 0x94, 0xc1, 0x8b, + 0xb8, 0xb8, 0xa3, 0xc1, 0x83, 0xe8, + ], + }], + // Experimental TA-mode workaround: reported on another J616C/25G83 + // implementation, not yet hardware-verified here on 25F84. Keep the + // shared firmware profiles (in particular M4 Pro's) unchanged. + variant: &fw::variant::Variant { + ta_mode_1: true, + ..fw::variant::V25F84 + }, + config: None, + }, + fw::variant::Build { + config: Some(&super::t6041_25g83::CONFIG), + ..super::t6041_25g83::BUILD + }, + ]), + core_layout: CoreLayout { + cores: Some((4, 40)), + operand_state: fw::compute::OperandState::FOUR_BY_TEN, + deflake: fw::render::Deflake::FOUR_CLUSTERS, + compute_blocks: 160, + }, +}; + +pub(crate) const CHIP_ID: u32 = 0x6041; + +pub(crate) const REGISTER_WINDOWS: [RegisterWindow; 25] = [ + window(0, 0x5_0241_4000, 0x0, 0x4000, 0, 2), + instances( + window(3, 0x2_201c_4000, 0x8000, 0x1_8000, 0, 2), + 8, + 0x200_0000, + ), + window(4, 0x5_0244_c000, 0xd_0000, 0x4000, 0, 0), + window(9, 0x5_003d_0000, 0xd_8000, 0x4000, 0, 2), + window(10, 0x5_003c_0000, 0xe_0000, 0x4000, 0, 0), + window(11, 0x5_003d_8000, 0xe_8000, 0x4000, 0, 2), + window(12, 0x4_8565_c000, 0xf_0000, 0x4000, 0, 2), + window(14, 0x5_0040_0000, 0xf_8000, 0x1_0000, 0, 0), + window(15, 0x5_0cdc_0000, 0x11_0000, 0x4000, 0, 0), + window(17, 0x2_8800_0000, 0x11_8000, 0x2_1400, 0, 2), + instances( + window(20, 0x2_8b00_0000, 0x14_0000, 0x4_0000, 0, 2), + 4, + 0x20_0000, + ), + window(22, 0x2_8900_0000, 0x24_8000, 0x8000, 0, 2), + window(26, 0x2_88d0_4000, 0x25_8000, 0x8000, 0xd0_4000, 2), + window(28, 0x2_88d5_8000, 0x26_8000, 0x8000, 0xd5_8000, 2), + window(29, 0x2_88d1_0000, 0x27_8000, 0x4000, 0xd1_0000, 2), + window(31, 0x2_88d4_0000, 0x28_0000, 0x4000, 0xd4_0000, 2), + window(32, 0x2_88d6_0000, 0x28_8000, 0x2_0000, 0xd6_0000, 2), + window(33, 0x2_88d4_4000, 0x2b_0000, 0x4000, 0xd4_4000, 2), + window(34, 0x2_88d4_c000, 0x2b_8000, 0x200, 0xd4_c000, 2), + window(35, 0x2_88e0_0000, 0x2c_0000, 0x4000, 0xe0_0000, 2), + window(37, 0x2_88e4_0000, 0x2c_8000, 0x4000, 0xe4_0000, 2), + window(39, 0x2_88e0_8000, 0x2d_0000, 0x8000, 0, 2), + window(40, 0x2_88e1_c000, 0x2e_0000, 0x4000, 0xe1_c000, 2), + window(41, 0x2_88e1_f800, 0x2e_b800, 0x4000, 0, 2), + window(43, 0x2_88e6_0000, 0x2f_8000, 0x58, 0xe6_0000, 2), +]; + +const RESERVED_SLOTS: [usize; 14] = [2, 5, 6, 7, 8, 27, 30, 38, 42, 46, 47, 48, 49, 52]; + +pub(crate) const PERF: PerfConfig = PerfConfig { + states_a: [0, 1, 2, 3, 4, 6, 8, 10, 12, 14, 15], + states_b: [0, 1, 2, 3, 4, 6, 7, 9, 11, 13, 15], + relative_a: [0, 10, 18, 25, 31, 40, 50, 62, 70, 78, 100], + relative_b: [0, 0, 22, 36, 47, 57, 68, 78, 84, 91, 100], + sram_min_mv: 810, +}; + +pub(crate) const OPPS: usize = 16; + +const _: () = { + let mut index = 0; + while index < PERF_STATES { + assert!((PERF.states_a[index] as usize) < OPPS); + assert!((PERF.states_b[index] as usize) < OPPS); + index += 1; + } +}; + +const MAX_POWER_MW: u32 = 129_702; + +const REGION_C: RegionCConfig = RegionCConfig { + unk_54: 0x0fa0, + unk_78: [1, 0, 0], + max_power_mw: MAX_POWER_MW, + unk_9c: 0, + unk_a0: 0, + unk_7c4: 1500, + unk_9e0: [ + 1, + 0x0102_0200, + 0x010a_2801, + 0x2802_0101, + 0x0101_010a, + 0x010a_2802, + 0x2801_0101, + 0x0001_010a, + ], +}; + +const CHIP: v25g83::Chip = v25g83::Chip { + max_power_mw: MAX_POWER_MW, + leakage: { + let mut words = [0; 56]; + words[0] = 0x44f9_c000; + words[1] = 0x44f7_2000; + words[2] = 0x44f4_b000; + words[3] = 0x44f1_5000; + words[32] = 0x43e4_0000; + words[33] = 0x43e4_0000; + words[34] = 0x43e4_0000; + words[35] = 0x43e4_0000; + words[52] = 0x4404_0000; + words[54] = 0x43df_8000; + words + }, + aon_table: &[], + hw_data_words: HW_DATA_WORDS, + power_config_words: POWER_CONFIG_WORDS, + perf_a_replicate_lanes: true, + cs_perf_table: false, +}; + +const HW_DATA_WORDS: &[(usize, u32, usize)] = &[ + (0xe0, 0x2008, 1), + (0xe8, 0x20080000, 1), + (0xf4, 0x2008, 1), + (0xf8, 0x24cb, 1), + (0xfc, 0xc98a2cfa, 1), + (0x100, 0xf4f624cb, 1), + (0x104, 0x1877e917, 1), + (0x108, 0x38d924cb, 1), + (0x10c, 0xbdab0000, 1), + (0x2d8, 0xfff82000, 1), + (0x2dc, 0xd32d2cdb, 1), + (0x2e0, 0xf5002000, 1), + (0x2e4, 0x21dae926, 1), + (0x2e8, 0x38b62000, 1), + (0x2ec, 0xc7420008, 1), + (0x3e0, 0x7fe0, 1), + (0x3e8, 0x7fe00000, 1), + (0x3f4, 0x7fe0, 1), + (0x3f8, 0x8000, 1), + (0x400, 0x80000000, 1), + (0x40c, 0x8000, 1), + (0x5d8, 0x4b232645, 1), + (0x5dc, 0xe98, 1), + (0x5e0, 0xd5a2ea5f, 1), + (0x5e4, 0x40003fff, 1), + (0x5e8, 0xca5e4000, 1), + (0x5ec, 0x4000f5a2, 1), + (0xf6c, 0x1, 1), + (0xf8c, 0xff, 1), + (0xfac, 0x1, 1), + (0xfb8, 0x1d, 1), + (0x2594, 0x2e0000, 1), + (0x2610, 0x1, 1), +]; + +const POWER_CONFIG_WORDS: &[(usize, u32, usize)] = &[ + (0x0, 0x1, 1), + (0x44, 0xc, 1), + (0x9c, 0x43a90000, 1), + (0x200, 0x1, 1), + (0x208, 0x162, 1), + (0x210, 0xd89165f9, 1), + (0x218, 0x1254c, 1), + (0x698, 0xd8917807, 1), + (0x69c, 0x13, 1), + (0x6a8, 0x129a8, 1), + (0x728, 0x4a714, 1), + (0x7a8, 0x4a714, 1), + (0x920, 0x3dd00000, 1), + (0x9ec, 0xbbfca403, 1), + (0x9f0, 0x28, 1), + (0xa70, 0x4, 1), + (0xa7c, 0x0, 1), + (0xa84, 0x3f800000, 1), + (0xa8c, 0x3e0b4396, 1), + (0xa9c, 0x3e99999a, 1), + (0xaa8, 0x28, 1), + (0xab8, 0x43b10000, 1), + (0xac0, 0x162, 1), + (0xad0, 0x0, 1), + (0xae0, 0xc7fca200, 1), + (0xaf0, 0x3e8, 1), + (0xafc, 0x3f800000, 1), + (0xb00, 0x3e0b4396, 1), + (0xb04, 0x3e99999a, 1), + (0xb08, 0x162, 1), + (0xb2c, 0x2, 1), + (0xb88, 0x42a00000, 1), + (0xb90, 0x7, 1), + (0xbc8, 0x3f7eb852, 1), + (0xbcc, 0x3ba3d70a, 1), + (0xbd0, 0x3f64c986, 1), + (0xbd4, 0x403ea7f0, 1), + (0x21f4, 0x42200000, 1), + (0x2210, 0x28, 1), + (0x2264, 0x1020, 1), + (0x226c, 0x2a222aa2, 1), + (0x2294, 0x40baaaaa, 1), + (0x22a4, 0x42080000, 1), + (0x22b0, 0x28, 1), + (0x22c8, 0x1020, 1), + (0x2868, 0x389d8, 1), + (0x2874, 0x154, 1), + (0x28d8, 0x47fd5300, 1), + (0x29bc, 0x74, 1), + (0x29c8, 0x3f772c23, 1), + (0x29d0, 0x3d0d3dcb, 1), + (0x29d8, 0x3cf5c290, 1), + (0x29e8, 0x3f19999a, 1), + (0x2a04, 0x4304ad79, 1), + (0x2a0c, 0x162, 1), + (0x2a2c, 0xc7fd10a9, 1), + (0x2a44, 0x3f772c23, 1), + (0x2a48, 0x3d0d3dcb, 1), + (0x2a4c, 0x3cf5c290, 1), + (0x2a50, 0x3f19999a, 1), + (0x2a54, 0x162, 1), + (0x2b18, 0x2ef94, 2), + (0x2b20, 0x2e89, 1), + (0x2b24, 0xe36, 1), + (0x2b40, 0x1, 1), + (0x2b94, 0x46023400, 1), + (0x2b9c, 0x208d, 1), + (0x2bc4, 0x47800000, 1), + (0x2bcc, 0x3e8, 1), + (0x2be8, 0x208d, 1), + (0x2c40, 0x28, 1), + (0x2c88, 0x3e8, 1), + (0x2cec, 0x1, 1), + (0x2cf0, 0xf, 1), + (0x2cf4, 0x3, 1), + (0x2cfc, 0x6, 1), + (0x2f0c, 0x2a222aa2, 1), + (0x3140, 0x29, 1), + (0x3144, 0x24dd, 1), + (0x3148, 0x4, 1), + (0x314c, 0x20, 1), + (0x3150, 0x29, 1), + (0x3154, 0x10d2c39d, 1), + (0x315c, 0x1d441, 1), + (0x31e0, 0x29, 1), + (0x31e4, 0x24a0, 1), + (0x31e8, 0x4, 1), + (0x31ec, 0x20, 1), + (0x31f0, 0x29, 1), + (0x31f4, 0x10f5cfb4, 1), + (0x31fc, 0x1d4d8, 1), + (0x3230, 0x29, 1), + (0x3234, 0x24ba, 1), + (0x3238, 0x4, 1), + (0x323c, 0x20, 1), + (0x3240, 0x29, 1), + (0x3244, 0x10fe2d62, 1), + (0x324c, 0x1d554, 1), + (0x3280, 0x28, 1), + (0x3284, 0x245c, 1), + (0x3288, 0x4, 1), + (0x328c, 0x20, 1), + (0x3290, 0x28, 1), + (0x3294, 0x10ec3bb1, 1), + (0x329c, 0x1d5bc, 1), + (0x32d0, 0x28, 1), + (0x32d4, 0x246e, 1), + (0x32d8, 0x4, 1), + (0x32dc, 0x20, 1), + (0x32e0, 0x29, 1), + (0x32e4, 0x1101cc20, 1), + (0x32ec, 0x1d640, 1), + (0x3320, 0x28, 1), + (0x3324, 0x2439, 1), + (0x3328, 0x4, 1), + (0x332c, 0x20, 1), + (0x3330, 0x28, 1), + (0x3334, 0x10f01dbd, 1), + (0x333c, 0x1d6dd, 1), + (0x33c0, 0x29, 1), + (0x33c4, 0x2497, 1), + (0x33c8, 0x4, 1), + (0x33cc, 0x20, 1), + (0x33d0, 0x29, 1), + (0x33d4, 0x111077fe, 1), + (0x33dc, 0x1d847, 1), + (0x3460, 0x29, 1), + (0x3464, 0x2480, 1), + (0x3468, 0x4, 1), + (0x346c, 0x20, 1), + (0x3470, 0x29, 1), + (0x3474, 0x110f91ba, 1), + (0x347c, 0x1d8fa, 1), + (0x3500, 0x28, 1), + (0x3504, 0x243a, 1), + (0x3508, 0x4, 1), + (0x350c, 0x20, 1), + (0x3510, 0x28, 1), + (0x3514, 0x10f2bfe8, 1), + (0x351c, 0x1d9a7, 1), + (0x3550, 0x28, 1), + (0x3554, 0x246d, 1), + (0x3558, 0x4, 1), + (0x355c, 0x20, 1), + (0x3560, 0x28, 1), + (0x3564, 0x113b3172, 1), + (0x356c, 0x1da43, 1), + (0x35a0, 0x28, 1), + (0x35a4, 0x2483, 1), + (0x35a8, 0x4, 1), + (0x35ac, 0x20, 1), + (0x35b0, 0x29, 1), + (0x35b4, 0x114027af, 1), + (0x35bc, 0x1dace, 1), + (0x3640, 0x28, 1), + (0x3644, 0x2486, 1), + (0x3648, 0x4, 1), + (0x364c, 0x20, 1), + (0x3650, 0x29, 1), + (0x3654, 0x112421ab, 1), + (0x365c, 0x1db07, 1), + (0x36e0, 0x29, 1), + (0x36e4, 0x24ce, 1), + (0x36e8, 0x4, 1), + (0x36ec, 0x20, 1), + (0x36f0, 0x29, 1), + (0x36f4, 0x114de7b5, 1), + (0x36fc, 0x1dbaa, 1), + (0x3730, 0x29, 1), + (0x3734, 0x24a1, 1), + (0x3738, 0x4, 1), + (0x373c, 0x20, 1), + (0x3740, 0x29, 1), + (0x3744, 0x11342213, 1), + (0x374c, 0x1dc2e, 1), + (0x3780, 0x28, 1), + (0x3784, 0x2446, 1), + (0x3788, 0x4, 1), + (0x378c, 0x20, 1), + (0x3790, 0x28, 1), + (0x3794, 0x111ec867, 1), + (0x379c, 0x1dcb7, 1), + (0x37d0, 0x28, 1), + (0x37d4, 0x2453, 1), + (0x37d8, 0x4, 1), + (0x37dc, 0x20, 1), + (0x37e0, 0x29, 1), + (0x37e4, 0x11273f2d, 1), + (0x37ec, 0x1dd49, 1), + (0x3820, 0x28, 1), + (0x3824, 0x2470, 1), + (0x3828, 0x4, 1), + (0x382c, 0x20, 1), + (0x3830, 0x28, 1), + (0x3834, 0x1131becf, 1), + (0x383c, 0x1ddc8, 1), + (0x38c0, 0x29, 1), + (0x38c4, 0x249c, 1), + (0x38c8, 0x4, 1), + (0x38cc, 0x20, 1), + (0x38d0, 0x29, 1), + (0x38d4, 0x1153d78e, 1), + (0x38dc, 0x1df60, 1), + (0x3960, 0x29, 1), + (0x3964, 0x2484, 1), + (0x3968, 0x4, 1), + (0x396c, 0x20, 1), + (0x3970, 0x29, 1), + (0x3974, 0x114b8bd5, 1), + (0x397c, 0x1dfe3, 1), + (0x3a00, 0x29, 1), + (0x3a04, 0x2522, 1), + (0x3a08, 0x4, 1), + (0x3a0c, 0x20, 1), + (0x3a10, 0x29, 1), + (0x3a14, 0x116ebefa, 1), + (0x3a1c, 0x1e077, 1), + (0x3a50, 0x29, 1), + (0x3a54, 0x2494, 1), + (0x3a58, 0x4, 1), + (0x3a5c, 0x20, 1), + (0x3a60, 0x29, 1), + (0x3a64, 0x11455238, 1), + (0x3a6c, 0x1e0d8, 1), + (0x3aa0, 0x29, 1), + (0x3aa4, 0x24a1, 1), + (0x3aa8, 0x4, 1), + (0x3aac, 0x20, 1), + (0x3ab0, 0x29, 1), + (0x3ab4, 0x1157064b, 1), + (0x3abc, 0x1e165, 1), + (0x3b1c, 0x2522, 1), + (0x3b20, 0x4, 1), + (0x3b24, 0x20, 1), + (0x3b28, 0x29, 1), + (0x3b2c, 0x116cd390, 1), + (0x3b34, 0x1dbf1, 1), + (0x3b40, 0x29, 1), + (0x3b44, 0x34, 1), + (0x3b5c, 0x2a222aa2, 1), + (0x62c4, 0x1000000, 1), + (0x62cc, 0x1010202, 1), + (0x62d0, 0x1010a28, 1), + (0x62d4, 0xa280201, 1), + (0x62d8, 0x2010101, 1), + (0x62dc, 0x1010a28, 1), + (0x62e0, 0xa280101, 1), + (0x62e4, 0x45000101, 1), + (0x62e8, 0x4000200, 1), + (0x62f4, 0x4a000000, 1), + (0x62f8, 0x100, 1), + (0x6304, 0xd7000000, 1), + (0x6308, 0x29, 1), + (0x6328, 0x67325452, 1), + (0x632c, 0x67335452, 1), + (0x6360, 0xf, 1), + (0x63c8, 0x1, 1), + (0x63cc, 0xd88be35c, 1), + (0x63d0, 0x13, 1), + (0x63d8, 0x13, 1), + (0x63dc, 0xd891fc7b, 1), + (0x63e0, 0x13, 1), + (0x63e4, 0xd8633257, 1), + (0x63e8, 0x13, 1), + (0x63ec, 0xd863f8ef, 1), + (0x63f0, 0x13, 1), + (0x63f4, 0xd8903ed2, 1), + (0x63f8, 0x13, 1), + (0x63fc, 0xd89165f9, 1), + (0x6400, 0x13, 1), + (0x6404, 0xd891fc7b, 1), + (0x6408, 0x13, 1), + (0x6414, 0xab2ab62, 1), + (0x6418, 0x7, 1), + (0x641c, 0x30d40, 1), + (0x6428, 0x1, 1), + (0x650c, 0x89778246, 1), +]; diff --git a/drivers/gpu/drm/asahi/hw/t6041_25g83.rs b/drivers/gpu/drm/asahi/hw/t6041_25g83.rs new file mode 100644 index 0000000000000..a5eba18a13c5d --- /dev/null +++ b/drivers/gpu/drm/asahi/hw/t6041_25g83.rs @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +//! T6041 (M4 Max) on the 25G83 firmware build: the profile captured on the 32-core J616C. +//! +//! The J616C boots through a macOS 26.6.2 stub (iBoot mBoot-18000.161.10), which loads a T6041 +//! image of the 25G83 build the M4 Pro runs ([`fw::variant::V25G83`]). [`super::t6041::CONFIG`] +//! selects this configuration when it identifies that image. +//! +//! The hardware data, power configuration, region C and AON table are the ones built on this +//! unit and captured from it ([`super::t6041_captured`]), with only the runtime words written +//! over them ([`Captured`]): the device tree the J616C boots with has no GPU operating-point, +//! CS or AFR tables and no calibration for the builders. The register windows are the captured +//! register map; the GPU is not started if the two differ. + +use super::t604x::{instances, window}; +use super::{t6041, t6041_captured as captured}; +use crate::g17::fw::{ + self, + initdata::{v25g83::Captured, PerfConfig, RegionCConfig, RegisterWindow, PERF_STATES}, +}; +use crate::g17::{Config, CoreLayout, CrashBuffers, FixedBuffer, Identity}; +use crate::hw::{GpuGen, GpuVariant}; +use crate::mmu::UatQuirks; + +pub(super) const CONFIG: Config = Config { + chip_id: t6041::CHIP_ID, + identity: Identity { + family: 0xa, + // ID register 0x0a04_1100 (J616C): family 0xa, variant 4, revision 0x11 (B1). + variant: 4, + num_dies: 1, + gpu_variant: GpuVariant::C, + usc_generation: 3, + hal_generation: 200, + }, + uat_ias: 42, + uat_oas: 42, + secondary_root_offset: None, + crash_buffers: CrashBuffers::FirmwareData, + pm_metrics: FixedBuffer { + va: 0x10_0008_0000, + size: 0x8000, + }, + windows: ®ISTER_WINDOWS, + reserved_slots: &[], + perf: &PERF, + opps: OPPS, + // The M4 Pro's policy, which the J616C has run with on this build. + uat_quirks: UatQuirks { + reserved_tables: true, + clean_tables: true, + page_tlbi: true, + handoff_lock: false, + handoff_slot: 0xffff_ffff, + native_gpu_permissions: true, + }, + region_c: ®ION_C, + chip: None, + captured: Some(&CAPTURED), + adopt_root_entries: false, + fabric_bridge: false, + recovery_slot_keys: None, + gpu_generation: GpuGen::G16, + firmware: fw::variant::Firmware::Identified(&[BUILD]), + // The cores the contents were captured with; other core counts are refused at probe. + core_layout: CoreLayout { + cores: Some((4, 32)), + // Banks for all forty core slots: the firmware indexes them by physical slot, and the + // J616C's enabled slots run to 39 (core mask 0xf6_fdbf6fdb). + operand_state: fw::compute::OperandState::FOUR_BY_TEN, + deflake: fw::render::Deflake::FOUR_CLUSTERS, + // The compute pool the J616C has run with since 23 Oct 2026; the M4 Pro's 21 blocks + // hang this GPU's firmware on grids of more than ten workgroups. + compute_blocks: 96, + }, +}; + +/// The 25G83 build as the J616C loads it. +pub(super) const BUILD: fw::variant::Build = fw::variant::Build { + os_version: [26, 6, 2], + name: "macOS 26.6.2 (25G83, iBoot mBoot-18000.161.10)", + images: &[crate::fwid::FirmwareBuild { + name: "Apple GFX 25G83 for T6041 (normalized loaded image)", + text_size: 0x60000, + data_size: 0x138000, + entropy: [0x59839, 0x5991c], + text_sha256: [ + 0xaa, 0x11, 0x3e, 0xd6, 0x20, 0x79, 0xbc, 0xfd, 0xee, 0xf0, 0xf8, 0x6c, 0x2a, 0x8d, + 0x7e, 0xae, 0x9f, 0x90, 0x7b, 0x03, 0xbe, 0x28, 0xcc, 0xf2, 0x98, 0xc9, 0x43, 0x95, + 0x1d, 0x0e, 0xff, 0xc5, + ], + }], + // Non-clustered tiling (TA mode 1), as for 25F84. Clustered tiling hangs the J616C unless + // the cluster buffers are sized for four clusters, which this driver does not do yet. + variant: &fw::variant::Variant { + ta_mode_1: true, + ..fw::variant::V25G83 + }, + config: None, +}; + +/// The captured register map: slot 3 holds the six memory controllers (ADT +/// `apple,sgx-active-mcc-bit-vector` 0x3f, 32 MiB apart), slot 20 the four AFR blocks. The +/// windows after slot 3 lie 0x30000 further than the M4 Pro's. +const REGISTER_WINDOWS: [RegisterWindow; 25] = [ + window(0, 0x5_0241_4000, 0x20_0000, 0x4000, 0, 2), + instances( + window(3, 0x2_201c_4000, 0x20_8000, 0x1_8000, 0, 2), + 6, + 0x200_0000, + ), + window(4, 0x5_0244_c000, 0x29_c000, 0x4000, 0, 0), + window(9, 0x5_003d_0000, 0x2a_4000, 0x4000, 0, 2), + window(10, 0x5_003c_0000, 0x2a_c000, 0x4000, 0, 0), + window(11, 0x5_003d_8000, 0x2b_4000, 0x4000, 0, 2), + window(12, 0x4_8565_c000, 0x2b_c000, 0x4000, 0, 2), + window(14, 0x5_0040_0000, 0x2c_4000, 0x1_0000, 0, 0), + window(15, 0x5_0cdc_0000, 0x2d_8000, 0x4000, 0, 0), + window(17, 0x2_8800_0000, 0x2e_0000, 0x2_1400, 0, 2), + instances( + window(20, 0x2_8b00_0000, 0x30_8000, 0x4_0000, 0, 2), + 4, + 0x20_0000, + ), + window(22, 0x2_8900_0000, 0x40_c000, 0x8000, 0, 2), + window(26, 0x2_88d0_4000, 0x41_8000, 0x8000, 0xd0_4000, 2), + window(28, 0x2_88d5_8000, 0x42_4000, 0x8000, 0xd5_8000, 2), + window(29, 0x2_88d1_0000, 0x43_0000, 0x4000, 0xd1_0000, 2), + window(31, 0x2_88d4_0000, 0x43_8000, 0x4000, 0xd4_0000, 2), + window(32, 0x2_88d6_0000, 0x44_0000, 0x2_0000, 0xd6_0000, 2), + window(33, 0x2_88d4_4000, 0x46_4000, 0x4000, 0xd4_4000, 2), + window(34, 0x2_88d4_c000, 0x46_c000, 0x200, 0xd4_c000, 2), + window(35, 0x2_88e0_0000, 0x47_4000, 0x4000, 0xe0_0000, 2), + window(37, 0x2_88e4_0000, 0x47_c000, 0x4000, 0xe4_0000, 2), + window(39, 0x2_88e0_8000, 0x48_4000, 0x8000, 0, 2), + window(40, 0x2_88e1_c000, 0x49_0000, 0x4000, 0xe1_c000, 2), + window(41, 0x2_88e1_f800, 0x49_b800, 0x4000, 0, 2), + window(43, 0x2_88e6_0000, 0x4a_4000, 0x58, 0xe6_0000, 2), +]; + +/// The ADT ladders of this unit (`apple,m4-index-a`, `apple,m4-index-b`, `apple,m4-relative-a`, +/// `apple,m4-relative-b`), which the captured performance tables hold. The builders, which +/// would use them, do not run for this configuration. +const PERF: PerfConfig = PerfConfig { + states_a: [0, 1, 2, 3, 4, 6, 8, 10, 12, 14, 15], + states_b: [0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15], + relative_a: [0, 9, 16, 23, 29, 38, 49, 60, 69, 79, 100], + relative_b: [0, 0, 22, 36, 47, 57, 68, 78, 84, 91, 100], + sram_min_mv: 810, +}; + +const OPPS: usize = 16; + +const _: () = { + let mut index = 0; + while index < PERF_STATES { + assert!((PERF.states_a[index] as usize) < OPPS); + assert!((PERF.states_b[index] as usize) < OPPS); + index += 1; + } +}; + +/// Region C as captured: the M4 Pro's with this unit's power limit (110586 mW, +/// `apple,m4-max-power-mw`). Only the builders would use it. +const REGION_C: RegionCConfig = RegionCConfig { + unk_54: 0x0fa0, + unk_78: [1, 0, 0], + max_power_mw: 110_586, + unk_9c: 0, + unk_a0: 0, + unk_7c4: 1500, + unk_9e0: [ + 1, + 0x0102_0200, + 0x010a_2801, + 0x2802_0101, + 0x0101_010a, + 0x010a_2802, + 0x2801_0101, + 0x0001_010a, + ], +}; + +/// The contents captured on the J616C on 25 Oct 2026. +const CAPTURED: Captured = Captured { + hw_data: captured::HW_DATA, + power_config: captured::POWER_CONFIG, + region_c: captured::REGION_C, + aon_table: &captured::AON_TABLE, + active_cores: 32, + expected: captured::EXPECTED, +}; diff --git a/drivers/gpu/drm/asahi/hw/t6041_captured.rs b/drivers/gpu/drm/asahi/hw/t6041_captured.rs new file mode 100644 index 0000000000000..bbc8ef18e864d --- /dev/null +++ b/drivers/gpu/drm/asahi/hw/t6041_captured.rs @@ -0,0 +1,710 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +//! The 25G83 initialization contents of the M4 Max (T6041), captured on the J616C. +//! +//! Generated from `j616c-fwdata-dump-25oct.txt` (sha256 `fbf179298c02a67e…`), the nonzero +//! 32-byte rows of the hardware data, power configuration, region C and AON table that the +//! previous T6041 driver (j616c/b25, Gravity Linux encoders evaluated from the device tree) +//! built on this unit on 25 Oct 2026, the contents the GPU has run with since 22 Oct. +//! +//! The words the host writes at every boot are left out (zero here): the completion-ring +//! descriptors and QoS pointer of the hardware data, the configuration-status pointer, AON +//! pointer and random word of the power configuration. [`EXPECTED`] holds the hashes +//! ([`hash_without`](crate::g17::fw::initdata::v25g83::hash_without), without those words) of +//! the dumped objects; the GPU is not started if what the driver wrote differs. +//! +//! What differs from the M4 Pro constants: chip 0x6041, 32 enabled cores, this unit's binned +//! operating points (four voltage lanes, the 15-step ladders of the ADT), six memory controller +//! instances in register slot 3 (and the register windows after it 0x30000 further), the 110586 +//! mW power limit (`apple,m4-max-power-mw`, the M4 Pro's scaled to 32 cores), four GPU cluster +//! temperature sources, four clusters' leakage coefficients and the second temperature-sensor +//! mask word at `+0x3b5c`. + +/// The hardware data ([`HwData25G83`], `0x3db4` bytes at bundle `+0`), without the +/// completion-ring descriptors and the QoS pointer. +pub(super) const HW_DATA: &[(usize, u32, usize)] = &[ + (0x0004, 0x0000006f, 1), + (0x0008, 0xffc00000, 1), + (0x0014, 0x00000010, 1), + (0x001c, 0x00000010, 1), + (0x0020, 0xffff8000, 1), + (0x0024, 0x000002ff, 1), + (0x0028, 0x81400000, 1), + (0x002c, 0xfffffc21, 1), + (0x0640, 0x02414000, 1), + (0x0644, 0x00000005, 1), + (0x0648, 0x80200000, 1), + (0x064c, 0xfffffc21, 1), + (0x0650, 0x00004000, 2), + (0x0660, 0x00000002, 1), + (0x06b8, 0x201c4000, 1), + (0x06bc, 0x00000002, 1), + (0x06c0, 0x80208000, 1), + (0x06c4, 0xfffffc21, 1), + (0x06c8, 0x00090000, 1), + (0x06cc, 0x00018000, 1), + (0x06d8, 0x00000002, 1), + (0x06e0, 0x0244c000, 1), + (0x06e4, 0x00000005, 1), + (0x06e8, 0x8029c000, 1), + (0x06ec, 0xfffffc21, 1), + (0x06f0, 0x00004000, 2), + (0x07a8, 0x003d0000, 1), + (0x07ac, 0x00000005, 1), + (0x07b0, 0x802a4000, 1), + (0x07b4, 0xfffffc21, 1), + (0x07b8, 0x00004000, 2), + (0x07c8, 0x00000002, 1), + (0x07d0, 0x003c0000, 1), + (0x07d4, 0x00000005, 1), + (0x07d8, 0x802ac000, 1), + (0x07dc, 0xfffffc21, 1), + (0x07e0, 0x00004000, 2), + (0x07f8, 0x003d8000, 1), + (0x07fc, 0x00000005, 1), + (0x0800, 0x802b4000, 1), + (0x0804, 0xfffffc21, 1), + (0x0808, 0x00004000, 2), + (0x0818, 0x00000002, 1), + (0x0820, 0x8565c000, 1), + (0x0824, 0x00000004, 1), + (0x0828, 0x802bc000, 1), + (0x082c, 0xfffffc21, 1), + (0x0830, 0x00004000, 2), + (0x0840, 0x00000002, 1), + (0x0870, 0x00400000, 1), + (0x0874, 0x00000005, 1), + (0x0878, 0x802c4000, 1), + (0x087c, 0xfffffc21, 1), + (0x0880, 0x00010000, 2), + (0x0898, 0x0cdc0000, 1), + (0x089c, 0x00000005, 1), + (0x08a0, 0x802d8000, 1), + (0x08a4, 0xfffffc21, 1), + (0x08a8, 0x00004000, 2), + (0x08e8, 0x88000000, 1), + (0x08ec, 0x00000002, 1), + (0x08f0, 0x802e0000, 1), + (0x08f4, 0xfffffc21, 1), + (0x08f8, 0x00021400, 2), + (0x0908, 0x00000002, 1), + (0x0960, 0x8b000000, 1), + (0x0964, 0x00000002, 1), + (0x0968, 0x80308000, 1), + (0x096c, 0xfffffc21, 1), + (0x0970, 0x00100000, 1), + (0x0974, 0x00040000, 1), + (0x0980, 0x00000002, 1), + (0x09b0, 0x89000000, 1), + (0x09b4, 0x00000002, 1), + (0x09b8, 0x8040c000, 1), + (0x09bc, 0xfffffc21, 1), + (0x09c0, 0x00008000, 2), + (0x09d0, 0x00000002, 1), + (0x0a50, 0x88d04000, 1), + (0x0a54, 0x00000002, 1), + (0x0a58, 0x80418000, 1), + (0x0a5c, 0xfffffc21, 1), + (0x0a60, 0x00008000, 2), + (0x0a68, 0x00d04000, 1), + (0x0a70, 0x00000002, 1), + (0x0aa0, 0x88d58000, 1), + (0x0aa4, 0x00000002, 1), + (0x0aa8, 0x80424000, 1), + (0x0aac, 0xfffffc21, 1), + (0x0ab0, 0x00008000, 2), + (0x0ab8, 0x00d58000, 1), + (0x0ac0, 0x00000002, 1), + (0x0ac8, 0x88d10000, 1), + (0x0acc, 0x00000002, 1), + (0x0ad0, 0x80430000, 1), + (0x0ad4, 0xfffffc21, 1), + (0x0ad8, 0x00004000, 2), + (0x0ae0, 0x00d10000, 1), + (0x0ae8, 0x00000002, 1), + (0x0b18, 0x88d40000, 1), + (0x0b1c, 0x00000002, 1), + (0x0b20, 0x80438000, 1), + (0x0b24, 0xfffffc21, 1), + (0x0b28, 0x00004000, 2), + (0x0b30, 0x00d40000, 1), + (0x0b38, 0x00000002, 1), + (0x0b40, 0x88d60000, 1), + (0x0b44, 0x00000002, 1), + (0x0b48, 0x80440000, 1), + (0x0b4c, 0xfffffc21, 1), + (0x0b50, 0x00020000, 2), + (0x0b58, 0x00d60000, 1), + (0x0b60, 0x00000002, 1), + (0x0b68, 0x88d44000, 1), + (0x0b6c, 0x00000002, 1), + (0x0b70, 0x80464000, 1), + (0x0b74, 0xfffffc21, 1), + (0x0b78, 0x00004000, 2), + (0x0b80, 0x00d44000, 1), + (0x0b88, 0x00000002, 1), + (0x0b90, 0x88d4c000, 1), + (0x0b94, 0x00000002, 1), + (0x0b98, 0x8046c000, 1), + (0x0b9c, 0xfffffc21, 1), + (0x0ba0, 0x00000200, 2), + (0x0ba8, 0x00d4c000, 1), + (0x0bb0, 0x00000002, 1), + (0x0bb8, 0x88e00000, 1), + (0x0bbc, 0x00000002, 1), + (0x0bc0, 0x80474000, 1), + (0x0bc4, 0xfffffc21, 1), + (0x0bc8, 0x00004000, 2), + (0x0bd0, 0x00e00000, 1), + (0x0bd8, 0x00000002, 1), + (0x0c08, 0x88e40000, 1), + (0x0c0c, 0x00000002, 1), + (0x0c10, 0x8047c000, 1), + (0x0c14, 0xfffffc21, 1), + (0x0c18, 0x00004000, 2), + (0x0c20, 0x00e40000, 1), + (0x0c28, 0x00000002, 1), + (0x0c58, 0x88e08000, 1), + (0x0c5c, 0x00000002, 1), + (0x0c60, 0x80484000, 1), + (0x0c64, 0xfffffc21, 1), + (0x0c68, 0x00008000, 2), + (0x0c78, 0x00000002, 1), + (0x0c80, 0x88e1c000, 1), + (0x0c84, 0x00000002, 1), + (0x0c88, 0x80490000, 1), + (0x0c8c, 0xfffffc21, 1), + (0x0c90, 0x00004000, 2), + (0x0c98, 0x00e1c000, 1), + (0x0ca0, 0x00000002, 1), + (0x0ca8, 0x88e1f800, 1), + (0x0cac, 0x00000002, 1), + (0x0cb0, 0x8049b800, 1), + (0x0cb4, 0xfffffc21, 1), + (0x0cb8, 0x00004000, 2), + (0x0cc8, 0x00000002, 1), + (0x0cf8, 0x88e60000, 1), + (0x0cfc, 0x00000002, 1), + (0x0d00, 0x804a4000, 1), + (0x0d04, 0xfffffc21, 1), + (0x0d08, 0x00000058, 2), + (0x0d10, 0x00e60000, 1), + (0x0d18, 0x00000002, 1), + (0x0e90, 0x00006041, 1), + (0x0e94, 0x00000001, 2), + (0x0ea0, 0x00000001, 2), + (0x0eb8, 0x00000001, 1), + (0x0ec0, 0x00000001, 1), + (0x0ec8, 0x00000001, 1), + (0x0ed0, 0x00005dc0, 1), + (0x0ed4, 0x00000001, 1), + (0x0ed8, 0x00000008, 1), + (0x0ee0, 0x00000001, 3), + (0x0f04, 0x0000001f, 1), + (0x0f24, 0x07002004, 1), + (0x0f28, 0x00000006, 1), + (0x0f34, 0x00000001, 2), + (0x0f4c, 0x00000031, 1), + (0x0f88, 0x00000020, 1), + (0x0f8c, 0x0000000f, 1), + (0x0fb8, 0x0000001c, 1), + (0x0fbc, 0x00000004, 1), + (0x0fc0, 0x00000020, 1), + (0x0fc4, 0x0000000a, 1), + (0x0fcc, 0x00000152, 1), + (0x0fd0, 0x0000026a, 1), + (0x0fd4, 0x0000031c, 1), + (0x0fd8, 0x0000039c, 1), + (0x0fdc, 0x00000420, 1), + (0x0fe0, 0x0000049e, 1), + (0x0fe4, 0x00000520, 1), + (0x0fe8, 0x00000564, 1), + (0x0fec, 0x000005be, 1), + (0x0ff0, 0x0000062a, 1), + (0x1008, 0x0000007d, 4), + (0x1048, 0x00000258, 1), + (0x104c, 0x00000253, 1), + (0x1050, 0x00000267, 1), + (0x1054, 0x00000258, 1), + (0x1088, 0x0000028a, 1), + (0x108c, 0x00000285, 1), + (0x1090, 0x00000294, 2), + (0x10c8, 0x000002b7, 1), + (0x10cc, 0x000002b2, 1), + (0x10d0, 0x000002c1, 1), + (0x10d4, 0x000002bc, 1), + (0x1108, 0x000002d0, 2), + (0x1110, 0x000002d5, 1), + (0x1114, 0x000002cb, 1), + (0x1148, 0x00000302, 1), + (0x114c, 0x000002f8, 1), + (0x1150, 0x00000307, 1), + (0x1154, 0x00000302, 1), + (0x1188, 0x0000032f, 1), + (0x118c, 0x00000325, 3), + (0x11c8, 0x00000366, 1), + (0x11cc, 0x00000352, 1), + (0x11d0, 0x00000357, 1), + (0x11d4, 0x0000035c, 1), + (0x1208, 0x0000038e, 1), + (0x120c, 0x0000037a, 1), + (0x1210, 0x0000037f, 1), + (0x1214, 0x00000384, 1), + (0x1248, 0x000003b6, 1), + (0x124c, 0x000003a2, 1), + (0x1250, 0x000003a7, 1), + (0x1254, 0x000003ac, 1), + (0x1288, 0x00000406, 1), + (0x128c, 0x00000401, 1), + (0x1290, 0x00000406, 1), + (0x1294, 0x000003fc, 1), + (0x1408, 0x0000032a, 4), + (0x1448, 0x0000032a, 4), + (0x1488, 0x0000032a, 4), + (0x14c8, 0x0000032a, 4), + (0x1508, 0x0000032a, 4), + (0x1548, 0x0000032a, 4), + (0x1588, 0x0000032f, 1), + (0x158c, 0x0000032a, 3), + (0x15c8, 0x00000366, 1), + (0x15cc, 0x00000352, 1), + (0x15d0, 0x00000357, 1), + (0x15d4, 0x0000035c, 1), + (0x1608, 0x0000038e, 1), + (0x160c, 0x0000037a, 1), + (0x1610, 0x0000037f, 1), + (0x1614, 0x00000384, 1), + (0x1648, 0x000003b6, 1), + (0x164c, 0x000003a2, 1), + (0x1650, 0x000003a7, 1), + (0x1654, 0x000003ac, 1), + (0x1688, 0x00000406, 1), + (0x168c, 0x00000401, 1), + (0x1690, 0x00000406, 1), + (0x1694, 0x000003fc, 1), + (0x180c, 0x00000152, 1), + (0x1810, 0x0000026a, 1), + (0x1814, 0x0000031c, 1), + (0x1818, 0x0000039c, 1), + (0x181c, 0x000003b8, 1), + (0x1820, 0x00000426, 1), + (0x1824, 0x0000049e, 1), + (0x1828, 0x000004da, 1), + (0x182c, 0x0000052e, 1), + (0x1830, 0x0000062a, 1), + (0x1848, 0x3f828f5c, 11), + (0x18cc, 0x00000009, 1), + (0x18d0, 0x00000010, 1), + (0x18d4, 0x00000017, 1), + (0x18d8, 0x0000001d, 1), + (0x18dc, 0x00000026, 1), + (0x18e0, 0x00000031, 1), + (0x18e4, 0x0000003c, 1), + (0x18e8, 0x00000045, 1), + (0x18ec, 0x0000004f, 1), + (0x18f0, 0x00000064, 1), + (0x1910, 0x00000016, 1), + (0x1914, 0x00000024, 1), + (0x1918, 0x0000002f, 1), + (0x191c, 0x00000039, 1), + (0x1920, 0x00000044, 1), + (0x1924, 0x0000004e, 1), + (0x1928, 0x00000054, 1), + (0x192c, 0x0000005b, 1), + (0x1930, 0x00000064, 1), + (0x19cc, 0x00000001, 1), + (0x19d0, 0x00000002, 1), + (0x19d4, 0x00000003, 1), + (0x19d8, 0x00000004, 1), + (0x19dc, 0x00000006, 1), + (0x19e0, 0x00000008, 1), + (0x19e4, 0x0000000a, 1), + (0x19e8, 0x0000000c, 1), + (0x19ec, 0x0000000e, 1), + (0x19f0, 0x0000000f, 1), + (0x1a0c, 0x00000001, 1), + (0x1a10, 0x00000002, 1), + (0x1a14, 0x00000003, 1), + (0x1a18, 0x00000004, 1), + (0x1a1c, 0x00000005, 1), + (0x1a20, 0x00000007, 1), + (0x1a24, 0x00000009, 1), + (0x1a28, 0x0000000b, 1), + (0x1a2c, 0x0000000d, 1), + (0x1a30, 0x0000000f, 1), + (0x1a48, 0x00000007, 2), + (0x1a50, 0x00000018, 1), + (0x1a54, 0x00000152, 1), + (0x1a58, 0x0000026a, 1), + (0x1a5c, 0x0000031c, 1), + (0x1a60, 0x000003e0, 1), + (0x1a64, 0x000004a4, 1), + (0x1a68, 0x00000564, 1), + (0x1a6c, 0x000005be, 1), + (0x1a90, 0x00000249, 1), + (0x1a98, 0x00000249, 1), + (0x1aa0, 0x00000276, 1), + (0x1aa8, 0x000002a8, 1), + (0x1ab0, 0x000002d0, 1), + (0x1ab8, 0x00000302, 1), + (0x1ac0, 0x00000361, 1), + (0x1ac8, 0x00000384, 1), + (0x1b10, 0x0000032a, 1), + (0x1b18, 0x0000032a, 1), + (0x1b20, 0x0000032a, 1), + (0x1b28, 0x0000032a, 1), + (0x1b30, 0x0000032a, 1), + (0x1b38, 0x0000032a, 1), + (0x1b40, 0x00000361, 1), + (0x1b48, 0x00000384, 1), + (0x1b90, 0x00000007, 2), + (0x1b98, 0x00000018, 1), + (0x1b9c, 0x00000152, 1), + (0x1ba0, 0x0000026a, 1), + (0x1ba4, 0x0000031c, 1), + (0x1ba8, 0x000003e0, 1), + (0x1bac, 0x000004a4, 1), + (0x1bb0, 0x00000564, 1), + (0x1bb4, 0x000005be, 1), + (0x1bd8, 0x00000249, 1), + (0x1be0, 0x00000249, 1), + (0x1be8, 0x00000276, 1), + (0x1bf0, 0x000002a8, 1), + (0x1bf8, 0x000002d0, 1), + (0x1c00, 0x00000302, 1), + (0x1c08, 0x00000361, 1), + (0x1c10, 0x00000384, 1), + (0x1c58, 0x0000032a, 1), + (0x1c60, 0x0000032a, 1), + (0x1c68, 0x0000032a, 1), + (0x1c70, 0x0000032a, 1), + (0x1c78, 0x0000032a, 1), + (0x1c80, 0x0000032a, 1), + (0x1c88, 0x00000361, 1), + (0x1c90, 0x00000384, 1), + (0x1cd8, 0x0000000a, 1), + (0x1ce0, 0x00000152, 1), + (0x1ce4, 0x0000026a, 1), + (0x1ce8, 0x0000031c, 1), + (0x1cec, 0x0000039c, 1), + (0x1cf0, 0x000003b8, 1), + (0x1cf4, 0x00000426, 1), + (0x1cf8, 0x0000049e, 1), + (0x1cfc, 0x000004da, 1), + (0x1d00, 0x0000052e, 1), + (0x1d04, 0x0000062a, 1), + (0x1d1c, 0x0000007d, 4), + (0x1d5c, 0x00000258, 1), + (0x1d60, 0x00000253, 1), + (0x1d64, 0x00000267, 1), + (0x1d68, 0x00000258, 1), + (0x1d9c, 0x0000028a, 1), + (0x1da0, 0x00000285, 1), + (0x1da4, 0x00000294, 2), + (0x1ddc, 0x000002b7, 1), + (0x1de0, 0x000002b2, 1), + (0x1de4, 0x000002c1, 1), + (0x1de8, 0x000002bc, 1), + (0x1e1c, 0x000002d0, 2), + (0x1e24, 0x000002d5, 1), + (0x1e28, 0x000002cb, 1), + (0x1e5c, 0x00000302, 1), + (0x1e60, 0x000002f8, 1), + (0x1e64, 0x00000307, 1), + (0x1e68, 0x00000302, 1), + (0x1e9c, 0x0000032f, 1), + (0x1ea0, 0x00000325, 3), + (0x1edc, 0x00000366, 1), + (0x1ee0, 0x00000352, 1), + (0x1ee4, 0x00000357, 1), + (0x1ee8, 0x0000035c, 1), + (0x1f1c, 0x0000038e, 1), + (0x1f20, 0x0000037a, 1), + (0x1f24, 0x0000037f, 1), + (0x1f28, 0x00000384, 1), + (0x1f5c, 0x000003b6, 1), + (0x1f60, 0x000003a2, 1), + (0x1f64, 0x000003a7, 1), + (0x1f68, 0x000003ac, 1), + (0x1f9c, 0x00000406, 1), + (0x1fa0, 0x00000401, 1), + (0x1fa4, 0x00000406, 1), + (0x1fa8, 0x000003fc, 1), + (0x211c, 0x0000032a, 4), + (0x215c, 0x0000032a, 4), + (0x219c, 0x0000032a, 4), + (0x21dc, 0x0000032a, 4), + (0x221c, 0x0000032a, 4), + (0x225c, 0x0000032a, 4), + (0x229c, 0x0000032f, 1), + (0x22a0, 0x0000032a, 3), + (0x22dc, 0x00000366, 1), + (0x22e0, 0x00000352, 1), + (0x22e4, 0x00000357, 1), + (0x22e8, 0x0000035c, 1), + (0x231c, 0x0000038e, 1), + (0x2320, 0x0000037a, 1), + (0x2324, 0x0000037f, 1), + (0x2328, 0x00000384, 1), + (0x235c, 0x000003b6, 1), + (0x2360, 0x000003a2, 1), + (0x2364, 0x000003a7, 1), + (0x2368, 0x000003ac, 1), + (0x239c, 0x00000406, 1), + (0x23a0, 0x00000401, 1), + (0x23a4, 0x00000406, 1), + (0x23a8, 0x000003fc, 1), + (0x2544, 0x00000005, 1), + (0x2548, 0x00000006, 1), + (0x254c, 0x00000003, 1), + (0x2550, 0x00000007, 2), + (0x2570, 0x00000020, 1), + (0x2578, 0x00000001, 1), + (0x259c, 0x00000001, 3), + (0x25ac, 0x00000001, 3), + (0x25bc, 0xffffffff, 12), + (0x25f4, 0x00000002, 1), + (0x25fc, 0x00000001, 1), + (0x2614, 0x00000001, 1), + (0x261c, 0x00000100, 1), + (0x26c0, 0x00000001, 2), + (0x26f4, 0x00000001, 1), +]; + +/// The power configuration and its auxiliary data ([`PowerConfig25G83`], `0x6510` bytes at +/// bundle `+0x5380`), without the configuration-status and AON pointers and the random word. +pub(super) const POWER_CONFIG: &[(usize, u32, usize)] = &[ + (0x0004, 0x00030d40, 2), + (0x0010, 0x00000004, 1), + (0x0014, 0x3f800000, 1), + (0x002c, 0x00000001, 2), + (0x0040, 0x00000064, 1), + (0x0044, 0x00000001, 1), + (0x0048, 0x000003e8, 1), + (0x0050, 0x00000064, 1), + (0x0060, 0x00000004, 1), + (0x0064, 0x3f800000, 1), + (0x006c, 0x00000001, 2), + (0x0080, 0x00000064, 1), + (0x0084, 0x00000001, 1), + (0x0088, 0x000003e8, 1), + (0x0090, 0x00000064, 1), + (0x00c0, 0x3f828f5c, 11), + (0x09b8, 0x00000271, 1), + (0x09c4, 0x3f7f2e9f, 1), + (0x09cc, 0x3b516154, 1), + (0x09d4, 0x3ca59586, 1), + (0x09e0, 0x47d7fd00, 1), + (0x09e4, 0x40a90fdb, 1), + (0x09ec, 0xbc1427fc, 1), + (0x09f0, 0x00000064, 1), + (0x09f4, 0x000003e8, 2), + (0x0a04, 0x0001affa, 1), + (0x0a38, 0x000003e8, 1), + (0x0a70, 0x00000008, 1), + (0x0a7c, 0x3f000000, 1), + (0x0a84, 0x3f000000, 1), + (0x0a8c, 0x3e3bd7b3, 1), + (0x0a98, 0x47800000, 1), + (0x0a9c, 0x3ecf2e49, 1), + (0x0aa8, 0x00000064, 1), + (0x0aac, 0x000003e8, 1), + (0x0abc, 0x0001affa, 1), + (0x0ac8, 0x00000010, 1), + (0x0ad0, 0x0005dc00, 1), + (0x0b28, 0x00000050, 1), + (0x0b30, 0x00000055, 1), + (0x0b34, 0x00000032, 1), + (0x0b38, 0x00000006, 1), + (0x0b40, 0x00000006, 1), + (0x0b44, 0x00000001, 1), + (0x0b4c, 0x3f4ccccd, 1), + (0x0b50, 0x3f7eb852, 1), + (0x0b54, 0x3e4ccccd, 1), + (0x0b58, 0x3ba3d70a, 1), + (0x0b5c, 0x3f64c986, 2), + (0x0b68, 0x42be0000, 1), + (0x0b6c, 0x403ea7f0, 2), + (0x0b74, 0x41179436, 1), + (0x0b78, 0x00000064, 1), + (0x0b7c, 0x000003e8, 1), + (0x0b80, 0x00000064, 1), + (0x0b8c, 0x00000050, 1), + (0x0bc0, 0x00000064, 1), + (0x1bec, 0xff000000, 1), + (0x1bf0, 0xff7fff7f, 255), + (0x1fec, 0x007fff7f, 1), + (0x21f0, 0x47800000, 1), + (0x21f4, 0x42c80000, 1), + (0x21f8, 0x447a0000, 1), + (0x21fc, 0x0000062a, 1), + (0x2210, 0x00000064, 1), + (0x2218, 0x42c80000, 1), + (0x221c, 0x000003e8, 1), + (0x2224, 0x3f4ccccd, 1), + (0x2228, 0x3e4ccccd, 1), + (0x2268, 0x2a222aa2, 1), + (0x2270, 0x00001f40, 1), + (0x2278, 0x00000004, 1), + (0x228c, 0x3f800000, 1), + (0x2294, 0x414eeeee, 1), + (0x22a0, 0x47800000, 1), + (0x22a4, 0x42140000, 1), + (0x22b0, 0x00000064, 1), + (0x22b4, 0x000003e8, 2), + (0x22c4, 0x00002af8, 1), + (0x22f8, 0x000003e8, 1), + (0x2728, 0xb8520000, 1), + (0x272c, 0x00003f7e, 1), + (0x2730, 0xd70a0000, 1), + (0x2734, 0x00003ba3, 1), + (0x273c, 0x000043c8, 1), + (0x2748, 0x00004780, 1), + (0x274c, 0x000042c8, 1), + (0x2754, 0x0384bac8, 1), + (0x2758, 0x03e80000, 2), + (0x2764, 0x80000000, 1), + (0x2768, 0x26ac453b, 1), + (0x279c, 0x03e80000, 1), + (0x27b8, 0x00c80000, 1), + (0x2870, 0x000003e8, 1), + (0x28c0, 0x00000001, 1), + (0x28c8, 0x0001affa, 3), + (0x28e0, 0x3f800000, 1), + (0x28e4, 0x00000004, 1), + (0x28e8, 0x00000008, 1), + (0x28ec, 0x0002ee00, 1), + (0x29bc, 0x0000007c, 1), + (0x29c8, 0x3f77bdef, 1), + (0x29d0, 0x3d042108, 1), + (0x29d8, 0x3d25bea1, 1), + (0x29e4, 0x47800000, 1), + (0x29e8, 0x3f4f2e49, 1), + (0x29f4, 0x00000028, 1), + (0x29f8, 0x000003e8, 2), + (0x2a04, 0x47d7fd00, 1), + (0x2a08, 0x0001affa, 1), + (0x2a14, 0x000000f8, 1), + (0x2a1c, 0x005ad200, 1), + (0x2a3c, 0x000003e8, 1), + (0x2b4c, 0x00000032, 1), + (0x2b50, 0x00000001, 1), + (0x2b58, 0x3f638e39, 1), + (0x2b5c, 0x3f2aaaab, 1), + (0x2b60, 0x3de38e39, 1), + (0x2b64, 0x3eaaaaab, 1), + (0x2b68, 0xbecccccd, 2), + (0x2b74, 0x47800000, 1), + (0x2b78, 0xc0a00000, 2), + (0x2b84, 0x00000064, 1), + (0x2b88, 0x000003e8, 1), + (0x2b8c, 0x00000064, 1), + (0x2b94, 0x45fa0000, 1), + (0x2b98, 0x00000578, 1), + (0x2ba4, 0x00000048, 1), + (0x2ba8, 0x00000018, 1), + (0x2bac, 0x001a5e00, 1), + (0x2bb4, 0x0008ca00, 1), + (0x2bc0, 0x47800000, 1), + (0x2be8, 0x00001f40, 1), + (0x2bec, 0x00000004, 1), + (0x2bf0, 0x000009c4, 1), + (0x2bf4, 0x00000258, 1), + (0x2bf8, 0x00000002, 1), + (0x2bfc, 0x00000004, 1), + (0x2c00, 0x00000032, 1), + (0x2c30, 0x47800000, 1), + (0x2c40, 0x00000064, 1), + (0x2c44, 0x000003e8, 1), + (0x2e2c, 0x00000004, 1), + (0x2e38, 0x3f780000, 1), + (0x2e40, 0x3d000000, 1), + (0x2e48, 0x40a00000, 1), + (0x2e54, 0x47800000, 1), + (0x2e58, 0x41700000, 1), + (0x2e64, 0x00000384, 1), + (0x2e68, 0x000003e8, 2), + (0x2e78, 0x000003e8, 1), + (0x2eac, 0x000003e8, 1), + (0x2eec, 0x00000064, 1), + (0x2f08, 0x2a222aa2, 1), + (0x2f10, 0x0000007d, 1), + (0x2f14, 0x00000001, 1), + (0x3b58, 0x2a222aa2, 2), + (0x3b60, 0x00000001, 1), + (0x5b64, 0x40a00000, 1), + (0x6320, 0x67305452, 1), + (0x6324, 0x67315452, 1), + (0x6328, 0x67325452, 1), + (0x632c, 0x67335452, 1), + (0x6360, 0x00000005, 1), + (0x6368, 0x72305452, 1), + (0x6370, 0x00000001, 1), + (0x6420, 0x00000001, 1), + (0x642c, 0x44f03000, 1), + (0x6430, 0x44f30000, 1), + (0x6434, 0x44f03000, 1), + (0x6438, 0x44f30000, 1), + (0x64ac, 0x43730000, 4), + (0x64fc, 0x437b0000, 1), + (0x6504, 0x43bdc000, 1), +]; + +/// Region C (`0x1000` bytes). +pub(super) const REGION_C: &[(usize, u32, usize)] = &[ + (0x0024, 0x00000bb8, 1), + (0x0030, 0x00000001, 2), + (0x003c, 0x00000078, 1), + (0x0054, 0x00280fa0, 1), + (0x0058, 0x0000ffff, 1), + (0x005c, 0x00010000, 2), + (0x0064, 0x00030000, 1), + (0x0068, 0x00010000, 1), + (0x0078, 0x00000001, 1), + (0x0084, 0x0001affa, 1), + (0x0088, 0x000003e8, 2), + (0x0098, 0x000003e8, 1), + (0x07c4, 0x000005dc, 1), + (0x07c8, 0x3f800000, 1), + (0x07cc, 0x3f4ccccd, 1), + (0x07d0, 0x3e4ccccd, 1), + (0x07d4, 0x3f666666, 1), + (0x07d8, 0x3dcccccd, 1), + (0x07dc, 0x3e800000, 1), + (0x07e0, 0x3f19999a, 1), + (0x07e4, 0x3f666666, 1), + (0x07e8, 0x00000006, 1), + (0x07ec, 0x00000001, 2), + (0x07f4, 0x00000064, 2), + (0x0998, 0x00000028, 1), + (0x099c, 0x0000000a, 1), + (0x09a0, 0x000000fa, 1), + (0x09a4, 0x00000001, 1), + (0x09b8, 0x00000002, 1), + (0x09bc, 0x00000028, 1), + (0x09c0, 0x00000005, 1), + (0x09c8, 0x00000028, 1), + (0x09cc, 0x00000032, 1), + (0x09d0, 0x00000001, 1), + (0x09e0, 0x00000001, 1), + (0x09e4, 0x01020200, 1), + (0x09e8, 0x010a2801, 1), + (0x09ec, 0x28020101, 1), + (0x09f0, 0x0101010a, 1), + (0x09f4, 0x010a2802, 1), + (0x09f8, 0x28010101, 1), + (0x09fc, 0x0001010a, 1), + (0x0e1c, 0x00000100, 1), + (0x0e38, 0x00000300, 1), + (0x0e3c, 0x00000100, 1), +]; + +/// The AON temperature-source rows (12 bytes each) the power configuration names: GPU +/// clusters 0 to 3 and the SoC. +pub(super) const AON_TABLE: [u32; 15] = [ + 0x67305452, 0x00c20001, 0x00001401, 0x67315452, 0x00970001, 0x00001401, 0x67325452, 0x00920001, + 0x00001401, 0x67335452, 0x00c70001, 0x00001401, 0x72305452, 0x012c0001, 0x00001401, +]; + +/// Hashes of the hardware data, power configuration and region C, without the runtime words. +pub(super) const EXPECTED: [u64; 3] = [0xd781973f99831e35, 0xc36d7dbaa597aac4, 0x91a4c67017e30a24]; diff --git a/drivers/gpu/drm/asahi/hw/t604x.rs b/drivers/gpu/drm/asahi/hw/t604x.rs new file mode 100644 index 0000000000000..961cef76cf4aa --- /dev/null +++ b/drivers/gpu/drm/asahi/hw/t604x.rs @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +use crate::g17::fw::initdata::RegisterWindow; + +const MMIO_APERTURE: u64 = 0xffff_fc21_8000_0000; + +pub(super) const fn window( + slot: usize, + phys: u64, + offset: u64, + size: u32, + unk_18: u64, + unk_20: u32, +) -> RegisterWindow { + RegisterWindow { + slot, + phys, + va: MMIO_APERTURE + offset, + size, + unk_18, + unk_20, + instances: 1, + phys_stride: 0, + } +} + +pub(super) const fn instances(window: RegisterWindow, instances: u32, phys_stride: u64) -> RegisterWindow { + RegisterWindow { + instances, + phys_stride, + ..window + } +} diff --git a/drivers/gpu/drm/asahi/hw/t8140.rs b/drivers/gpu/drm/asahi/hw/t8140.rs index 47dc4d583a5fc..a4e7bc5d6e2e3 100644 --- a/drivers/gpu/drm/asahi/hw/t8140.rs +++ b/drivers/gpu/drm/asahi/hw/t8140.rs @@ -51,6 +51,8 @@ pub(crate) const CONFIG: Config = Config { opps: OPPS, uat_quirks: crate::mmu::UatQuirks::DEFAULT, region_c: &crate::g17::fw::initdata::REGION_C_26A428, + chip: None, + captured: None, adopt_root_entries: true, fabric_bridge: true, firmware: crate::g17::fw::variant::Firmware::Fixed(&crate::g17::fw::variant::V26A428), @@ -59,6 +61,7 @@ pub(crate) const CONFIG: Config = Config { cores: None, operand_state: crate::g17::fw::compute::OperandState::ONE_BY_SIX, deflake: crate::g17::fw::render::Deflake::ONE_CLUSTER, + compute_blocks: crate::g17::fw::freelist::COMPUTE_BLOCKS, }, }; diff --git a/drivers/gpu/drm/asahi/regs.rs b/drivers/gpu/drm/asahi/regs.rs index e8b845cba989f..2b04726e43878 100644 --- a/drivers/gpu/drm/asahi/regs.rs +++ b/drivers/gpu/drm/asahi/regs.rs @@ -46,6 +46,16 @@ const FAULT_INFO: usize = 0x17030; const G17_HOST_IRQ_SUMMARY: usize = 0xe01000; const G17_HOST_POWERED: u32 = 0xf; +const KSM_MAILBOX_TAG: usize = 0x4090; +const KSM_MAILBOX_DATA: usize = 0x4098; +const KSM_MAILBOX_FLAGS: u64 = (1 << 42) | (1 << 53); +const KSM_SLOT_DESCRIPTOR: u64 = 0x21008; +const KSM_SLOT_TIMESTAMP: u64 = 0x21020; +const KSM_SELECT: usize = 0x103a8; +const KSM_RUN_SET: usize = 0x21068; +const KSM_RUN_CLEAR: usize = 0x21078; +const KSM_RUNNING: [usize; 2] = [0x21038, 0x21040]; + const ID_VERSION: usize = 0xd04000; const ID_UNK08: usize = 0xd04008; const ID_COUNTS_1: usize = 0xd04010; @@ -602,6 +612,52 @@ impl G17Resources { Ok(true) } + /// Registers a queue KSM slot through the firmware mailbox. + pub(crate) fn register_ksm_queue(&self, qid: u8, descriptor: u64) -> Result { + if qid > 127 { + return Err(EINVAL); + } + let sgx = self.sgx.try_access().ok_or(ENODEV)?; + let sgx = (&*sgx).as_view(); + let tag = |reg: u64| reg | KSM_MAILBOX_FLAGS | (u64::from(qid) << 43); + let bit = 1u64 << (qid & 63); + let (low, high) = if qid < 64 { (bit, 0) } else { (0, bit) }; + let running = KSM_RUNNING[usize::from(qid >= 64)]; + if sgx.try_read64(running)? & bit != 0 { + sgx.try_write64(high, KSM_RUN_CLEAR + 8)?; + sgx.try_write64(low, KSM_RUN_CLEAR)?; + } + sgx.try_write64(tag(KSM_SLOT_DESCRIPTOR), KSM_MAILBOX_TAG)?; + sgx.try_write64(descriptor, KSM_MAILBOX_DATA)?; + sgx.try_write64(tag(KSM_SLOT_TIMESTAMP), KSM_MAILBOX_TAG)?; + sgx.try_read64(KSM_MAILBOX_DATA)?; + sgx.try_write64(tag(KSM_SLOT_DESCRIPTOR), KSM_MAILBOX_TAG)?; + let mut readback = sgx.try_read64(KSM_MAILBOX_DATA)?; + let direct = readback != descriptor; + if direct { + sgx.try_write64(u64::from(qid), KSM_SELECT)?; + sgx.try_write64(descriptor, KSM_SLOT_DESCRIPTOR as usize)?; + readback = sgx.try_read64(KSM_SLOT_DESCRIPTOR as usize)?; + } + if readback != descriptor { + dev_err!( + self.dev.as_ref(), + "KSM queue {} slot descriptor {:#x} did not take (reads {:#x})\n", + qid, + descriptor, + readback + ); + return Err(EIO); + } + if sgx.try_read64(running)? & bit == 0 { + sgx.try_write64(high, KSM_RUN_SET + 8)?; + sgx.try_write64(low, KSM_RUN_SET)?; + } + sgx.try_write64(tag(KSM_SLOT_TIMESTAMP), KSM_MAILBOX_TAG)?; + sgx.try_read64(KSM_MAILBOX_DATA)?; + Ok(()) + } + fn sgx_read32(&self) -> u32 { if let Some(sgx) = self.sgx.try_access() { (&*sgx).as_view().relaxed().read32(OFF) diff --git a/drivers/media/platform/apple/avd/avd-backend-open.c b/drivers/media/platform/apple/avd/avd-backend-open.c index d2054d06f948b..480837586ba72 100644 --- a/drivers/media/platform/apple/avd/avd-backend-open.c +++ b/drivers/media/platform/apple/avd/avd-backend-open.c @@ -209,8 +209,14 @@ static void avd_open_capabilities(struct avd_dev *avd) if (!avd->fw || avd->fw->size < 0x40) return; info = (const char *)avd->fw->data + avd->fw->size - 0x40; - if (memcmp(info, "CODECS:", 7)) - return; /* fw_capabilities already set above */ + if (memcmp(info, "CODECS:", 7)) { + /* The qualified J616c image has no CODECS trailer. */ + if (avd_t6041_hevc_supported(avd)) { + avd->capabilities |= AVD_CAPABILITY_HEVC; + avd->fw_capabilities = avd->capabilities; + } + return; + } avd->capabilities = 0; for (i = 0; i < ARRAY_SIZE(codecs); i++) if (strnstr(info, codecs[i].name, 0x40)) diff --git a/drivers/media/platform/apple/avd/avd-drv.c b/drivers/media/platform/apple/avd/avd-drv.c index 57021503e6e10..a0fbdb69ceff8 100644 --- a/drivers/media/platform/apple/avd/avd-drv.c +++ b/drivers/media/platform/apple/avd/avd-drv.c @@ -565,6 +565,14 @@ static const struct of_device_id avd_of_match[] = { MODULE_DEVICE_TABLE(of, avd_of_match); +bool avd_t6041_hevc_supported(struct avd_dev *avd) +{ + return of_machine_is_compatible("apple,j616c") && + avd->variant == &avd_t6040_variant && + (avd->variant->quirks & AVD_QUIRK_HEVC_V5_HEADER) && + avd->fw->size == 0x12000; +} + static void avd_release_open_firmware(void *data) { struct avd_dev *avd = data; diff --git a/drivers/media/platform/apple/avd/avd.h b/drivers/media/platform/apple/avd/avd.h index a1825a1029ec5..9ba28fb4bf64b 100644 --- a/drivers/media/platform/apple/avd/avd.h +++ b/drivers/media/platform/apple/avd/avd.h @@ -413,6 +413,7 @@ bool avd_backend_is_qfw(const struct avd_dev *avd); bool avd_qfw_has_vp_done(const struct avd_dev *avd); unsigned int avd_qfw_picture_banks(const struct avd_dev *avd, unsigned int codec); int avd_backend_select(struct avd_dev *avd); +bool avd_t6041_hevc_supported(struct avd_dev *avd); bool avd_mbox_pop(struct avd_dev *avd, u32 *msg); int avd_backend_boot(struct avd_dev *avd); void avd_shutdown(struct avd_dev *avd); diff --git a/drivers/soc/apple/aop.rs b/drivers/soc/apple/aop.rs index 0a63aeb752204..20e78e2b542cb 100644 --- a/drivers/soc/apple/aop.rs +++ b/drivers/soc/apple/aop.rs @@ -1594,16 +1594,34 @@ impl AopData { &self, aop_mmio: &Mmio<'_, Region>, patches: &[(u32, u64)], + word_access: bool, ) -> Result<()> { let offset = aop_mmio.read32(BOOTARGS_OFFSET) as usize; let size = aop_mmio.read32(BOOTARGS_SIZE) as usize; if offset > aop_mmio.size() || size > aop_mmio.size() - offset { return Err(EINVAL); } - let mut arg_bytes = KVec::::from_elem(0, size, GFP_KERNEL)?; + let start = if word_access { offset & !3 } else { offset }; + let end = if word_access { + (offset + size).checked_add(3).ok_or(EINVAL)? & !3 + } else { + offset + size + }; + if end > aop_mmio.size() || (word_access && size == 0) { + return Err(EINVAL); + } + let mut bytes = KVec::::from_elem(0, end - start, GFP_KERNEL)?; let aop_io_array: Mmio<'_, [u8; AOP_MMIO_SIZE]> = aop_mmio.try_cast()?; let bootargs = io_project!(aop_io_array, [try: offset .. offset+size]); - bootargs.copy_to_slice(&mut arg_bytes); + if word_access { + for (i, chunk) in bytes.chunks_exact_mut(4).enumerate() { + chunk.copy_from_slice(&aop_mmio.try_read32(start + i * 4)?.to_le_bytes()); + } + } else { + bootargs.copy_to_slice(&mut bytes); + } + let first = offset - start; + let arg_bytes = &mut bytes[first..first + size]; let mut idx = 0; while idx < size { if size - idx < 8 { @@ -1627,7 +1645,21 @@ impl AopData { } idx += len; } - bootargs.copy_from_slice(&arg_bytes); + if word_access { + for (i, chunk) in bytes.chunks_exact(4).enumerate() { + let address = start + i * 4; + let value = u32::from_le_bytes(chunk.try_into().unwrap()); + if aop_mmio.try_read32(address)? == value { + continue; + } + aop_mmio.try_write32(value, address)?; + if aop_mmio.try_read32(address)? != value { + return Err(EIO); + } + } + } else { + bootargs.copy_from_slice(arg_bytes); + } Ok(()) } @@ -2530,6 +2562,7 @@ struct AopHwConfig { /// and lists in `memory-region`; check their IOMMU mappings before /// starting it (T6040). fw_regions: bool, + bootargs_word_access: bool, /// Halt the co-processor again when its start fails (T6040). halt_on_failed_start: bool, } @@ -2545,6 +2578,7 @@ const HW_CFG_T8103: AopHwConfig = AopHwConfig { quiesce_on_unbind: false, required_endpoints: &[], fw_regions: false, + bootargs_word_access: false, halt_on_failed_start: false, }; const HW_CFG_T8112: AopHwConfig = AopHwConfig { @@ -2558,6 +2592,7 @@ const HW_CFG_T8112: AopHwConfig = AopHwConfig { quiesce_on_unbind: false, required_endpoints: &[], fw_regions: false, + bootargs_word_access: false, halt_on_failed_start: false, }; const HW_CFG_T6000: AopHwConfig = AopHwConfig { @@ -2571,6 +2606,7 @@ const HW_CFG_T6000: AopHwConfig = AopHwConfig { quiesce_on_unbind: false, required_endpoints: &[], fw_regions: false, + bootargs_word_access: false, halt_on_failed_start: false, }; const HW_CFG_T6020: AopHwConfig = AopHwConfig { @@ -2584,6 +2620,7 @@ const HW_CFG_T6020: AopHwConfig = AopHwConfig { quiesce_on_unbind: false, required_endpoints: &[], fw_regions: false, + bootargs_word_access: false, halt_on_failed_start: false, }; /// T6040 (J616s): the firmware's external code and log live in DRAM, mapped @@ -2602,6 +2639,7 @@ const HW_CFG_T6040: AopHwConfig = AopHwConfig { quiesce_on_unbind: true, required_endpoints: &[], fw_regions: true, + bootargs_word_access: true, halt_on_failed_start: true, }; /// T8132 (J713): as T6040. The bootloader hands the AOP over the same way, with @@ -2624,6 +2662,7 @@ const HW_CFG_T8140: AopHwConfig = AopHwConfig { quiesce_on_unbind: true, required_endpoints: &[0x20, 0x21, 0x22, 0x23, 0x2b], fw_regions: false, + bootargs_word_access: false, halt_on_failed_start: false, }; @@ -2684,6 +2723,7 @@ impl platform::Driver for AopDriver { (from_fourcc(b"alig"), cfg.alig), (from_fourcc(b"AOPt"), cfg.aopt), ], + cfg.bootargs_word_access, )?; } let rtkit = rtkit::RtKit::::new(pdev.as_ref(), None, 0, data.clone())?; diff --git a/drivers/watchdog/apple_wdt.c b/drivers/watchdog/apple_wdt.c index f533953294f62..e1b8fa6a83972 100644 --- a/drivers/watchdog/apple_wdt.c +++ b/drivers/watchdog/apple_wdt.c @@ -53,6 +53,11 @@ #define APPLE_WDT_TIMEOUT_DEFAULT 30 +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + struct apple_wdt { struct watchdog_device wdd; void __iomem *regs; @@ -178,6 +183,7 @@ static int apple_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, wdt); + wdt->wdd.parent = dev; wdt->wdd.ops = &apple_wdt_ops; wdt->wdd.info = &apple_wdt_info; wdt->wdd.max_hw_heartbeat_ms = U32_MAX / wdt->clk_rate * 1000; @@ -187,6 +193,7 @@ static int apple_wdt_probe(struct platform_device *pdev) if (wdt_ctrl & APPLE_WDT_CTRL_RESET_EN) set_bit(WDOG_HW_RUNNING, &wdt->wdd.status); + watchdog_set_nowayout(&wdt->wdd, nowayout); watchdog_init_timeout(&wdt->wdd, 0, dev); apple_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout); watchdog_stop_on_unregister(&wdt->wdd); diff --git a/sound/soc/apple/macaudio.c b/sound/soc/apple/macaudio.c index 3e51478e8797e..e56d40783457e 100644 --- a/sound/soc/apple/macaudio.c +++ b/sound/soc/apple/macaudio.c @@ -651,6 +651,9 @@ static void macaudio_vlimit_update(struct macaudio_snd_data *ma) atomic_inc(&ma->sw_gain_lock_epoch); schedule_work(&ma->sw_gain_stop_work); } + if (!unlock && !ma->pm_quiesced && ma->cfg->fe_cpu_is_platform && + ma->cfg->amp == AMP_SN012776) + schedule_work(&ma->sw_gain_stop_work); ma->speaker_volume_unlocked = unlock; snd_ctl_notify(ma->card.snd_card, SNDRV_CTL_EVENT_MASK_VALUE, &ma->speaker_lock_kctl->id); @@ -815,7 +818,7 @@ static void macaudio_sw_gain_stop_work(struct work_struct *work) struct macaudio_snd_data *ma = container_of(work, struct macaudio_snd_data, sw_gain_stop_work); - macaudio_stop_playback(ma, true); + macaudio_stop_playback(ma, ma->cfg->amp == AMP_MAX98360A); } static int macaudio_copy_link(struct device *dev, struct snd_soc_dai_link *target, diff --git a/tools/asahi/aop-bootargs-tests.py b/tools/asahi/aop-bootargs-tests.py new file mode 100644 index 0000000000000..aba3842077664 --- /dev/null +++ b/tools/asahi/aop-bootargs-tests.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-only OR MIT +"""Exercise production bootarg patching with synthetic MMIO.""" +import argparse +import os +from pathlib import Path +import subprocess +import tempfile + +HARNESS = r''' +#![allow(dead_code)] +use std::{cell::{Cell,RefCell},marker::PhantomData,mem,ops::{Deref,DerefMut}}; +type Result = std::result::Result; +const EINVAL:i32=-22; const EIO:i32=-5; const GFP_KERNEL:u32=0; +const AOP_MMIO_SIZE:usize=128; const BOOTARGS_OFFSET:usize=16; const BOOTARGS_SIZE:usize=20; +struct KVec(Vec); +impl KVec{fn from_elem(v:T,n:usize,_:u32)->Result{Ok(Self(vec![v;n]))}} +impl Deref for KVec{type Target=Vec;fn deref(&self)->&Vec{&self.0}} +impl DerefMut for KVec{fn deref_mut(&mut self)->&mut Vec{&mut self.0}} +struct Region; +struct Device{bytes:RefCell>,writes:RefCell>,fail:Cell} +struct Mmio<'a,T>{dev:&'a Device,_p:PhantomData} +impl<'a,T> Mmio<'a,T>{ + fn size(&self)->usize{self.dev.bytes.borrow().len()} + fn read32(&self,at:usize)->u32{self.try_read32(at).unwrap()} + fn try_read32(&self,at:usize)->Result{assert_eq!(at%4,0);Ok(u32::from_le_bytes(self.dev.bytes.borrow()[at..at+4].try_into().unwrap()))} + fn try_write32(&self,v:u32,at:usize)->Result{assert_eq!(at%4,0);self.dev.writes.borrow_mut().push(at);if !self.dev.fail.get(){self.dev.bytes.borrow_mut()[at..at+4].copy_from_slice(&v.to_le_bytes());}Ok(())} + fn try_cast(&self)->Result>{Ok(Mmio{dev:self.dev,_p:PhantomData})} +} +struct IoSlice<'a>{dev:&'a Device,start:usize,end:usize} +impl IoSlice<'_>{ + fn copy_to_slice(&self,v:&mut[u8]){v.copy_from_slice(&self.dev.bytes.borrow()[self.start..self.end]);} + fn copy_from_slice(&self,v:&[u8]){self.dev.bytes.borrow_mut()[self.start..self.end].copy_from_slice(v);} +} +macro_rules! io_project {($io:ident,[try: $start:ident .. $($end:tt)*])=>{IoSlice{dev:$io.dev,start:$start,end:$($end)*}};} +struct Aop; +impl Aop { METHOD } +fn fixture(offset:usize,table:&[u8])->Device{ + let mut bytes=vec![0xa5;AOP_MMIO_SIZE];bytes[16..20].copy_from_slice(&(offset as u32).to_le_bytes());bytes[20..24].copy_from_slice(&(table.len() as u32).to_le_bytes()); + if offset+table.len()<=bytes.len(){bytes[offset..offset+table.len()].copy_from_slice(table);} + Device{bytes:RefCell::new(bytes),writes:RefCell::new(Vec::new()),fail:Cell::new(false)} +} +fn patch(dev:&Device,word:bool)->Result{Aop.patch_bootargs(&Mmio{dev,_p:PhantomData::>},&[(1,0x12345678),(2,0x87654321)],word)} +fn main(){ + let table:[u8;24]=[1,0,0,0,4,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,0,0,0,0]; + for offset in 32..36 {for word in [false,true] { + let d=fixture(offset,&table);let mut expected=d.bytes.borrow().clone();expected[offset+8..offset+12].copy_from_slice(&0x12345678u32.to_le_bytes());expected[offset+20..offset+24].copy_from_slice(&0x87654321u32.to_le_bytes()); + assert_eq!(patch(&d,word),Ok(()));assert_eq!(*d.bytes.borrow(),expected,"adjacent bytes changed"); + assert!(d.writes.borrow().iter().all(|&x|x%4==0&&x>=offset&!3&&x+4<=(offset+table.len()+3)&!3)); + if word {assert!(!d.writes.borrow().is_empty());}else{assert!(d.writes.borrow().is_empty());} + let writes=d.writes.borrow().len();assert_eq!(patch(&d,word),Ok(()));assert_eq!(d.writes.borrow().len(),writes,"unchanged words rewritten"); + }} + let mut malformed=table;malformed[16..20].copy_from_slice(&9u32.to_le_bytes()); + for word in [false,true]{let d=fixture(35,&malformed);let before=d.bytes.borrow().clone();assert_eq!(patch(&d,word),Err(EINVAL));assert_eq!(*d.bytes.borrow(),before);assert!(d.writes.borrow().is_empty());} + for tail in 1..8 {let d=fixture(35,&table[..12+tail]);assert_eq!(patch(&d,true),Err(EINVAL));assert!(d.writes.borrow().is_empty());} + let d=fixture(35,&table);d.fail.set(true);assert_eq!(patch(&d,true),Err(EIO),"readback error ignored"); + assert_eq!(patch(&fixture(35,&[]),true),Err(EINVAL));assert_eq!(patch(&fixture(35,&[]),false),Ok(())); + assert_eq!(patch(&fixture(120,&table),true),Err(EINVAL)); + println!("PASS aligned/unaligned byte and word access, unchanged writes, malformed tables, bounds and failed readback"); +} +''' + + +def method(source): + start = source.index(' fn patch_bootargs(') + at = source.index('{', start) + depth = 1 + end = at + 1 + while depth: + depth += (source[end] == '{') - (source[end] == '}') + end += 1 + return source[start:end] + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--source', type=Path, default=Path(__file__).resolve().parents[2] / 'drivers/soc/apple/aop.rs') + args = parser.parse_args() + production = method(args.source.read_text()) + macros = ''.join('macro_rules! ' + name + ' {($($t:tt)*)=>{()};}\n' for name in ['dev_info', 'dev_err'] if name + '!' in production) + code = HARNESS.replace('METHOD', production).replace('struct Aop;', macros + 'struct Aop;') + with tempfile.TemporaryDirectory(prefix='aop-bootargs-') as tmp: + p = Path(tmp) / 'test.rs' + binary = p.with_suffix('') + p.write_text(code) + subprocess.run([os.environ.get('RUSTC', 'rustc'), '--edition=2021', str(p), '-o', str(binary)], check=True) + subprocess.run([str(binary)], check=True) + bad = code.replace('if aop_mmio.try_read32(address)? != value {', 'if false {') + assert bad != code + p.write_text(bad) + subprocess.run([os.environ.get('RUSTC', 'rustc'), '--edition=2021', str(p), '-o', str(binary)], check=True) + result = subprocess.run([str(binary)], capture_output=True, text=True) + assert result.returncode != 0 and 'readback error ignored' in result.stderr + print('PASS negative control: missing write verification') + + +if __name__ == '__main__': + main() diff --git a/tools/asahi/g17-firmware-selection-tests.py b/tools/asahi/g17-firmware-selection-tests.py index 771c9c19c6e1e..7bd936c5ce125 100644 --- a/tools/asahi/g17-firmware-selection-tests.py +++ b/tools/asahi/g17-firmware-selection-tests.py @@ -34,6 +34,7 @@ def method(source, signature): image: u32, checked: std::cell::RefCell>, } +pub struct Config(pub u32); mod fw { pub struct Variant(pub u32); pub mod variant { @@ -43,6 +44,7 @@ def method(source, signature): pub name: &'static str, pub image: u32, pub variant: &'static Variant, + pub config: Option<&'static crate::Config>, } pub enum Firmware { Fixed(&'static Variant), Identified(&'static [Build]) } } @@ -60,9 +62,11 @@ def method(source, signature): } static FIRST: fw::Variant = fw::Variant(1); static SECOND: fw::Variant = fw::Variant(2); +static SECOND_CONFIG: Config = Config(2); static BUILDS: [fw::variant::Build; 2] = [ - fw::variant::Build { os_version: [26,6,2], name: "first", image: 1, variant: &FIRST }, - fw::variant::Build { os_version: [27,0,0], name: "second", image: 2, variant: &SECOND }, + fw::variant::Build { os_version: [26,6,2], name: "first", image: 1, variant: &FIRST, config: None }, + fw::variant::Build { os_version: [27,0,0], name: "second", image: 2, variant: &SECOND, + config: Some(&SECOND_CONFIG) }, ]; fn device(version: Option<[u32; 3]>, image: u32) -> AsahiDrmDevice { AsahiDrmDevice { version, image, checked: std::cell::RefCell::new(Vec::new()) } @@ -71,18 +75,28 @@ def method(source, signature): use fw::variant::Firmware; for version in [None, Some([26,6,2]), Some([26,7,0]), Some([99,0,0])] { let dev = device(version, 1); - assert_eq!(Gpu::firmware_variant(&dev, &Firmware::Identified(&BUILDS)).unwrap().0, 1); + let (variant, config) = Gpu::firmware_variant(&dev, &Firmware::Identified(&BUILDS)).unwrap(); + assert_eq!(variant.0, 1); + assert!(config.is_none(), "a build without a configuration keeps the probed one"); } + let dev = device(None, 2); + let (variant, config) = Gpu::firmware_variant(&dev, &Firmware::Identified(&BUILDS)).unwrap(); + assert_eq!(variant.0, 2); + assert_eq!(config.unwrap().0, 2, "the configuration follows the identified image"); let dev = device(Some([27,0,0]), 1); - assert_eq!(Gpu::firmware_variant(&dev, &Firmware::Identified(&BUILDS)).unwrap().0, 1); + let (variant, config) = Gpu::firmware_variant(&dev, &Firmware::Identified(&BUILDS)).unwrap(); + assert_eq!(variant.0, 1); + assert!(config.is_none(), "the OS hint does not pick a configuration"); assert_eq!(*dev.checked.borrow(), [2,1], "the OS version only orders the candidates"); let dev = device(Some([26,6,2]), 9); assert!(Gpu::firmware_variant(&dev, &Firmware::Identified(&BUILDS)).is_err()); assert_eq!(*dev.checked.borrow(), [1,2]); let dev = device(None, 9); - assert_eq!(Gpu::firmware_variant(&dev, &Firmware::Fixed(&SECOND)).unwrap().0, 2); + let (variant, config) = Gpu::firmware_variant(&dev, &Firmware::Fixed(&SECOND)).unwrap(); + assert_eq!(variant.0, 2); + assert!(config.is_none()); assert!(dev.checked.borrow().is_empty(), "fixed Neo admission is unchanged"); - println!("PASS G17 selection: exact image required, OS hint optional, fixed Neo unchanged"); + println!("PASS G17 selection: exact image required, OS hint optional, fixed Neo unchanged, configuration follows the image"); } ''' diff --git a/tools/asahi/g17-t6041-initdata-tests.py b/tools/asahi/g17-t6041-initdata-tests.py new file mode 100644 index 0000000000000..34815f80cf383 --- /dev/null +++ b/tools/asahi/g17-t6041-initdata-tests.py @@ -0,0 +1,322 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-only OR MIT +"""Check T6041 initialization data against caller-supplied captures.""" + +import argparse +import re +import struct +import subprocess +import sys +import tempfile +from pathlib import Path + +DRIVER = Path(__file__).resolve().parents[2] / "drivers/gpu/drm/asahi" + + +def item(source, start): + """Extract an item and its attributes.""" + at = source.index(start) + line = source.rfind("\n", 0, at) + 1 + while True: + previous = source.rfind("\n", 0, line - 1) + 1 + if line == 0 or not source[previous:line].lstrip().startswith("#["): + break + line = previous + depth = 0 + end = at + while True: + c = source[end] + if c in "([{": + depth += 1 + elif c in ")]}": + depth -= 1 + if depth == 0 and c == "}" and not re.match( + r"(pub\(crate\) )?(const|static) (?!fn )", source[at:] + ): + return source[line : end + 1] + elif c == ";" and depth == 0: + return source[line : end + 1] + end += 1 + + +HEADER = r""" +#![allow(dead_code, unused_imports, unused_variables, clippy::all)] +use core::mem::size_of; +#[derive(Debug)] +pub struct Error(i32); +pub const EINVAL: Error = Error(-22); +pub const EOVERFLOW: Error = Error(-75); +impl From for Error { + fn from(_: core::num::TryFromIntError) -> Self { EINVAL } +} +pub type Result = core::result::Result; +pub unsafe trait Zeroable {} +macro_rules! static_assert { ($e:expr $(,)?) => { const _: () = assert!($e); }; } +pub fn clear(object: &mut T) { + unsafe { core::ptr::write_bytes(object as *mut T, 0, 1) } +} +const PAGE_SIZE: usize = 0x4000; +""" + +INITDATA_ITEMS = [ + "pub(crate) const REGISTER_MAP_SLOTS", + "pub(crate) struct RegisterWindow", + "const RESERVED_SLOT_UNK_20", + "pub(crate) struct RegisterMapEntry", + "unsafe impl Zeroable for RegisterMapEntry", + "impl RegisterMapEntry", + "pub(crate) const PERF_STATES", + "const PERF_LANES", + "pub(crate) const OPP_CELLS", + "pub(crate) struct Opp ", + "pub(crate) struct PerfConfig", + "pub(crate) struct PerfGroup", + "unsafe impl Zeroable for PerfGroup", + "struct PerfState", + "impl PerfGroup", + "fn perf_states", + "pub(crate) struct CompletionRingDescriptor", + "unsafe impl Zeroable for CompletionRingDescriptor", + "const COMPLETION_RING_DESCRIPTORS", + "pub(crate) const COMPLETION_RING_INDEX", + "const COMPLETION_RING_ENTRIES", + "const COMPLETION_RING_ENTRY_SIZE", + "pub(crate) struct CompletionRing ", + "pub(crate) struct HwDataArgs", + "type Words", + "fn fill_words", + "pub(crate) const CONTEXT_SWITCH_TIMER_MASK", + "pub(crate) const CONTEXT_SWITCH_TIMER_MULTIPLIER", + "pub(crate) struct RegionCConfig", + "pub(crate) struct RegionC ", + "unsafe impl Zeroable for RegionC ", + "impl RegionC ", +] + +SOC_ITEMS = [ + "pub(crate) const CHIP_ID", + "pub(crate) const REGISTER_WINDOWS", + "pub(crate) const PERF", + "pub(crate) const OPPS", + "const REGION_C", +] + +T6041_ITEMS = SOC_ITEMS + [ + "const RESERVED_SLOTS", + "const MAX_POWER_MW", + "const CHIP: ", + "const HW_DATA_WORDS", + "const POWER_CONFIG_WORDS", +] + +T6041_OPP_HZ = [0, 338, 618, 796, 924, 952, 1056, 1062, 1182, 1182, 1312, 1242, 1380, 1326, + 1470, 1578] +T6041_OPP_MV = [ + [125, 600, 665, 705, 725, 770, 770, 810, 810, 860, 860, 900, 900, 940, 940, 1020], + [125, 600, 665, 705, 725, 770, 770, 810, 810, 860, 860, 895, 895, 925, 925, 1020], + [125, 600, 660, 700, 715, 770, 770, 805, 805, 860, 860, 900, 900, 940, 940, 1020], + [125, 600, 660, 705, 730, 780, 780, 810, 810, 860, 860, 900, 900, 940, 940, 1020], +] +T6041_AUX = [(24, 585000), (338, 585000), (618, 635000), (796, 685000), (992, 720000), + (1188, 770000), (1380, 855000), (1470, 885000)] + + +def opps(name, hz, mv): + rows = [] + for index, freq in enumerate(hz): + cells = [m[index] * 1000 for m in mv] + [0] * (16 - len(mv)) + rows.append( + "Opp { freq_hz: %d, volt_uv: [%s], cells: %d }" + % (freq * 1_000_000, ", ".join(map(str, cells)), len(mv)) + ) + return "const %s: [Opp; %d] = [%s];\n" % (name, len(rows), ",\n".join(rows)) + + +def aux(name, rows): + body = ",\n".join( + "Opp { freq_hz: %d, volt_uv: [%d, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], cells: 1 }" + % (mhz * 1_000_000, uv) + for mhz, uv in rows + ) + return "const %s: [Opp; %d] = [%s];\n" % (name, len(rows), body) + + +MAIN = r""" +fn build( + chip_id: u32, + windows: &[RegisterWindow], + reserved: &[usize], + perf: &PerfConfig, + opps: &[Opp], + aux: &[Opp], + chip: &v25g83::Chip, + region_c: &RegionCConfig, + cores: u32, +) -> (Vec, Vec, Vec) { + let args = HwDataArgs { + chip_id, + windows, + reserved_slots: reserved, + opps, + perf, + completion_rings: [ + CompletionRing { low_va: 0x70_03f0_0000, high_va: 0xffff_fc20_0000_0000 }, + CompletionRing { low_va: 0x70_03f2_8000, high_va: 0xffff_fc20_0002_8000 }, + ], + qos_va: 0xffff_fc20_0004_0000, + }; + let ext = v25g83::HwDataArgs25G83 { active_cores: cores, cs_opps: aux, afr_opps: aux, chip: Some(chip) }; + let mut hw: Box = unsafe { Box::new(core::mem::zeroed()) }; + hw.init(&args, &ext).unwrap(); + let mut power: Box = unsafe { Box::new(core::mem::zeroed()) }; + power.init(0xffff_fc20_000d_3440, 0, 0, chip.max_power_mw, &chip.leakage); + power.apply_chip(chip).unwrap(); + let mut region: Box = unsafe { Box::new(core::mem::zeroed()) }; + region.init(region_c); + region.max_power_mw = region_c.max_power_mw; + let hw_bytes = unsafe { + core::slice::from_raw_parts((&*hw as *const v25g83::HwData25G83).cast::(), + size_of::()) + }.to_vec(); + let region_bytes = unsafe { + core::slice::from_raw_parts((&*region as *const RegionC).cast::(), size_of::()) + }.to_vec(); + (hw_bytes, power.0.to_vec(), region_bytes) +} + +fn main() { + let out = std::env::args().nth(1).unwrap(); + let (hw, power, region) = build(t6041::CHIP_ID, &t6041::REGISTER_WINDOWS, + &t6041::RESERVED_SLOTS, &t6041::PERF, &T6041_OPPS, &T6041_AUX, &t6041::CHIP, + &t6041::REGION_C, 40); + println!("T6041 initialization objects built"); + std::fs::write(format!("{}/t6041-hwdata.bin", out), hw).unwrap(); + std::fs::write(format!("{}/t6041-power-config.bin", out), power).unwrap(); + std::fs::write(format!("{}/t6041-region-c.bin", out), region).unwrap(); +} +""" + + +def program(): + initdata = (DRIVER / "g17/fw/initdata.rs").read_text() + v25g83 = (DRIVER / "g17/fw/initdata/v25g83.rs").read_text() + t6041 = (DRIVER / "hw/t6041.rs").read_text() + v25g83 = re.sub(r"use super::\{[^}]*\};", "use super::*;", v25g83, count=1) + v25g83 = v25g83.replace("use kernel::prelude::*;", "") + float_source = (DRIVER / "float.rs").read_text().split("impl<'a> TryFrom