diff --git a/Documentation/ABI/testing/sysfs-driver-aop-als b/Documentation/ABI/testing/sysfs-driver-aop-als index c5b6acd796242..410b9d2f1341a 100644 --- a/Documentation/ABI/testing/sysfs-driver-aop-als +++ b/Documentation/ABI/testing/sysfs-driver-aop-als @@ -1,8 +1,9 @@ -What: /sys/bus/iio/devices/iio:deviceX/in_cct_input +What: /sys/bus/iio/devices/iio:deviceX/in_colortemp_input Date: October 2026 Contact: linux-iio@vger.kernel.org Description: - Firmware-computed correlated colour temperature in Kelvin on + Firmware-computed light colour temperature (correlated colour + temperature) in Kelvin, processed, on aop-sensors-als devices with a Redbird (VD6286) sensor. Fractional Kelvin are reported with micro resolution. There is no raw photodiode-to-CCT conversion in the host driver. diff --git a/Documentation/accel/apple-ane.rst b/Documentation/accel/apple-ane.rst index 80feec377a251..63eed84a36287 100644 --- a/Documentation/accel/apple-ane.rst +++ b/Documentation/accel/apple-ane.rst @@ -334,7 +334,12 @@ cannot distinguish a control request; its lookup request layout remains unproved. No control reply is invented. IRQ service reads pending once, rejects bits above 7 and writes the exact -nonzero snapshot to acknowledge. The wait helper services one allocation at +nonzero snapshot to acknowledge. Only a SHAREDMALLOC notification authorizes +allocation service: a fresh slot and an allocation request both have a zero +header, so the body becoming visible does not establish publication. After +acknowledging, the transport captures the number of queued entries before +answering any of them. This handles coalesced notifications without admitting +a later request using an earlier notification. The wait helper services one allocation at a time and checks the original absolute monotonic deadline, including time spent inside the allocation callback. Servicing never starts a new timeout. diff --git a/Documentation/devicetree/bindings/opp/operating-points-v2-apple-dcs.yaml b/Documentation/devicetree/bindings/opp/operating-points-v2-apple-dcs.yaml index 28315f6f799c4..b035f0515d2a7 100644 --- a/Documentation/devicetree/bindings/opp/operating-points-v2-apple-dcs.yaml +++ b/Documentation/devicetree/bindings/opp/operating-points-v2-apple-dcs.yaml @@ -13,6 +13,8 @@ allOf: - $ref: opp-v2-base.yaml# description: | + T6000 DCS raw states are 5, 6, 7 and 9. State 8 is invalid; fabric + states are a separate controller and are not DCS states. Each OPP maps a verified raw PMGR desired performance state to measured sustainable bandwidth. Values are decimal kB/s, not DRAM clock frequencies, theoretical peak bandwidth or firmware policy thresholds. State codes and @@ -31,8 +33,7 @@ patternProperties: turbo-mode: false opp-level: description: Verified raw PMGR desired state, without a state-index bias - minimum: 7 - maximum: 15 + enum: [5, 6, 7, 9] opp-peak-kBps: description: Measured sustainable bandwidth at this raw state items: diff --git a/Documentation/devicetree/bindings/sound/apple,macaudio.yaml b/Documentation/devicetree/bindings/sound/apple,macaudio.yaml index 755c5d195cf0f..e0b330720fdb7 100644 --- a/Documentation/devicetree/bindings/sound/apple,macaudio.yaml +++ b/Documentation/devicetree/bindings/sound/apple,macaudio.yaml @@ -20,6 +20,8 @@ properties: - apple,j274-macaudio - apple,j293-macaudio - apple,j314-macaudio + - apple,j614-macaudio + - apple,j614-macaudio-jack - apple,j616-macaudio - apple,j616-macaudio-jack - apple,j700-macaudio diff --git a/Documentation/driver-api/apple-pmgr-dcs.rst b/Documentation/driver-api/apple-pmgr-dcs.rst index edf6fc4af52f5..b7dd79bc7cb7c 100644 --- a/Documentation/driver-api/apple-pmgr-dcs.rst +++ b/Documentation/driver-api/apple-pmgr-dcs.rst @@ -14,8 +14,8 @@ The provider is enabled only by an explicit ``operating-points-v2`` phandle and ``#interconnect-cells = <1>`` on the existing PMGR miscellaneous node. Its table uses ``operating-points-v2-apple-dcs``. Each enabled OPP supplies a raw ``opp-level`` and one ``opp-peak-kBps`` value. The driver validates duplicate -states, zero or decreasing capacities, the T600x sleep floor of 7, and the -boot-state ceiling before publishing the provider. It does not derive states +states, zero or decreasing capacities, the sparse T6000 raw state set +``{5, 6, 7, 9}``, and the boot-state ceiling before publishing the provider. It does not derive states from child order or convert firmware thresholds to bandwidth. Existing DTs without this table retain their boot and suspend policy. @@ -23,8 +23,13 @@ The highest table entry must equal the boot desired state. That entry remains the initial vote until interconnect sync_state releases boot constraints. Nonzero bandwidth also holds the fabric at its boot state so untracked DMA clients cannot lose their fabric bandwidth to the idle governor. Requests -change only the desired low nibble and wait for the actual field to -confirm the requested state. A timeout restores the previous confirmed vote. +write the raw state as one complete 32-bit command word, with all upper +bits zero, and wait for the actual field to confirm it. Readback status +bits must not be preserved in the command. Raw 8 is invalid; raw 9 is the +highest DCS state. Fabric has a separate state map. A timeout restores the +previous confirmed vote with the same complete-word command. The current +desired and actual fields must agree with the last confirmed vote before +a new request. If restoration also times out, the fabric hold remains asserted and subsequent requests and system sleep fail with ``-EIO`` until reboot. Errors propagate to consumers, which must not start work requiring a bandwidth request that failed. Firmware ownership and system sleep reject diff --git a/Documentation/iio/apple-aop-als.rst b/Documentation/iio/apple-aop-als.rst index a19625a84be75..bf96aaebec858 100644 --- a/Documentation/iio/apple-aop-als.rst +++ b/Documentation/iio/apple-aop-als.rst @@ -17,7 +17,8 @@ must not be distributed with test fixtures. The `public Redbird report description `_ identifies a 122-byte report carrying a firmware-computed CCT float at byte -0x45. The driver exports that layout as ``in_cct_input``, in Kelvin, without +0x45. The driver exports that value as the standard IIO colour temperature +channel, ``in_colortemp_input``, processed and in Kelvin, without recalculating colour temperature from raw channels. Other lengths do not supply a CCT reading. This layout must be verified on each firmware family before its CCT readings are used for display policy. The existing CT720 and @@ -29,7 +30,7 @@ device number:: for d in /sys/bus/iio/devices/iio:device*; do [ "$(cat "$d/name" 2>/dev/null)" = aop-sensors-als ] || continue cat "$d/in_illuminance_input" - [ ! -e "$d/in_cct_input" ] || cat "$d/in_cct_input" + [ ! -e "$d/in_colortemp_input" ] || cat "$d/in_colortemp_input" done These attributes contain the last valid reading, not a sample counter. Polling diff --git a/arch/arm64/boot/dts/apple/Makefile b/arch/arm64/boot/dts/apple/Makefile index b351a6626f683..c7487bcac3d35 100644 --- a/arch/arm64/boot/dts/apple/Makefile +++ b/arch/arm64/boot/dts/apple/Makefile @@ -94,6 +94,7 @@ dtb-$(CONFIG_ARCH_APPLE) += t6031-j516c.dtb dtb-$(CONFIG_ARCH_APPLE) += t6032-j575d.dtb dtb-$(CONFIG_ARCH_APPLE) += t6034-j514m.dtb 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) += t8112-j413.dtb diff --git a/arch/arm64/boot/dts/apple/t6040-j614s.dts b/arch/arm64/boot/dts/apple/t6040-j614s.dts new file mode 100644 index 0000000000000..9ef0cf1194eec --- /dev/null +++ b/arch/arm64/boot/dts/apple/t6040-j614s.dts @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * MacBook Pro (14-inch, M4 Pro) + * + * target-type: J614s + * + * Copyright The Asahi Linux Contributors + */ + +/dts-v1/; + +#include "t6040.dtsi" +#include "t604x-j614-j616.dtsi" + +/ { + compatible = "apple,j614s", "apple,t6040", "apple,arm-platform"; + model = "Apple MacBook Pro (14-inch, M4 Pro)"; +}; + +/* ADT /arm-io/wlan module-instance */ +&wifi0 { + brcm,board-type = "apple,mriya"; +}; + +&bluetooth0 { + brcm,board-type = "apple,mriya"; +}; + +&panel { + compatible = "apple,panel-j614", "apple,panel-mini-led", "apple,panel"; + width-mm = <302>; + height-mm = <196>; + adj-height-mm = <189>; +}; + +&aop_audio { + apple,chassis-name = "J614"; +}; + +/* + * The speakers wait for their own bring-up and a J614 protection profile. + * Until then the speaker card and the six amps stay disabled, so nothing + * can drive them; the headphone jack card is unaffected. + */ +&sound { + compatible = "apple,j614-macaudio", "apple,macaudio"; + model = "MacBook Pro J614"; + status = "disabled"; +}; + +&speaker_left_woof1 { + status = "disabled"; +}; + +&speaker_left_woof2 { + status = "disabled"; +}; + +&speaker_left_tweet { + status = "disabled"; +}; + +&speaker_right_woof1 { + status = "disabled"; +}; + +&speaker_right_woof2 { + status = "disabled"; +}; + +&speaker_right_tweet { + status = "disabled"; +}; + +&sound_jack { + compatible = "apple,j614-macaudio-jack", "apple,macaudio"; + model = "MacBook Pro J614 Jack"; +}; + +&mtp_mt { + firmware-name = "apple/tpmtfw-j614s.bin"; +}; + +/* + * Per-device factory data from this Mac's own iBoot system container: the + * sealed calibration and the sealed root key. + */ +&mesa { + firmware-name = "apple/mesacal-j614s.bin", "apple/msrk-j614s.bin"; +}; + +/* + * The GL9755 SD reader. Its supply is the SMC's gP19 output, which the + * J614s firmware describes as active high. Both CLKREQ pins go on the + * controller so that the Wi-Fi and SD ports do not claim the same pins. + */ +&apcie1_dart { + status = "okay"; +}; + +&pcie0 { + bus-range = <0 2>; + pinctrl-0 = <&wifi_clkreq_pins &sd_clkreq_pins>; +}; + +&port01 { + /delete-property/ pinctrl-0; + /delete-property/ pinctrl-names; + bus-range = <2 2>; + pwren-gpios = <&smc_gpio 0x19 GPIO_ACTIVE_HIGH>; + status = "okay"; + + mmc@0,0 { + compatible = "pci17a0,9755"; + reg = <0x20000 0 0 0 0>; + cd-inverted; + wp-inverted; + }; +}; diff --git a/arch/arm64/boot/dts/apple/t6040-j616s.dts b/arch/arm64/boot/dts/apple/t6040-j616s.dts index 693f136a849f4..5895e848d99ce 100644 --- a/arch/arm64/boot/dts/apple/t6040-j616s.dts +++ b/arch/arm64/boot/dts/apple/t6040-j616s.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ OR MIT /* - * MacBook Pro (16-inch, M4 Pro, Nov 2024) + * MacBook Pro (16-inch, M4 Pro) * * target-type: J616s * @@ -10,4775 +10,51 @@ /dts-v1/; #include "t6040.dtsi" -#include -#include -#include +#include "t604x-j614-j616.dtsi" / { compatible = "apple,j616s", "apple,t6040", "apple,arm-platform"; - model = "Apple MacBook Pro (16-inch, M4 Pro, Nov 2024)"; - chassis-type = "laptop"; - - aliases { - keyboard = &keyboard; - nvram = &nvram; - spi0 = &qspi; - rtc0 = &smc_rtc; - rtc1 = &pmu_rtc; - wifi0 = "/pcie@1cb0000000/pci@0,0/wifi@0,0"; - bluetooth0 = "/pcie@1cb0000000/pci@0,0/bluetooth@0,1"; - /* used by the loader to hand over the display */ - dcp = &dcp; - disp0 = &display; - disp0-piodma = &disp0_piodma; - /* the boot loader finds the GPU node through this alias */ - gpu = &gpu; - pmp = &pmp; - /* the boot loader reserves the SEP firmware through this alias */ - sep = &sep; - }; - - chosen { - #address-cells = <2>; - #size-cells = <2>; - ranges; - - framebuffer0: framebuffer@0 { - compatible = "apple,simple-framebuffer", "simple-framebuffer"; - reg = <0 0 0 0>; /* To be filled by loader */ - /* Format properties will be added by loader */ - status = "disabled"; - }; - }; - - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - /* The loader adds its own reservations */ - - /* - * The loader must fill reg from ane0 segment-ranges, rename each - * node to match its physical address and enable it. Leave these - * disabled until then; allocating replacement memory would lose - * the personalized preload. TEXT is 0xc0000 bytes and DATA is - * 0x2ac000 bytes. Neither segment may be reclaimed before reboot. - */ - ane_fw_text: ane-firmware-text@0 { - compatible = "apple,asc-mem"; - reg = <0 0 0 0>; - no-map; - status = "disabled"; - }; - - ane_fw_data: ane-firmware-data@0 { - compatible = "apple,asc-mem"; - reg = <0 0 0 0>; - no-map; - status = "disabled"; - }; - - /* - * iBoot loads the ISP firmware below the kernel's memory. Its - * segments are the ADT's isp0 segment-ranges (macOS 26.6.2, - * iBoot mBoot-18000.161.10), mapped where the firmware runs them: - * 0x100_0000_0000 onwards, its 32 MiB main memory. The driver - * checks that the coprocessor's reset vector is this text before - * it starts the firmware. - */ - isp_fw_text: isp-firmware-text@10000c44000 { - reg = <0x100 0x00c44000 0x0 0xca8000>; - iommu-addresses = <&isp 0x100 0x0 0x0 0xca8000>; - no-map; - }; - - isp_fw_data: isp-firmware-data@10001e7c000 { - reg = <0x100 0x01e7c000 0x0 0x1344000>; - iommu-addresses = <&isp 0x100 0xca8000 0x0 0x1344000>; - no-map; - }; - - /* the firmware's main memory, the driver allocates above it */ - isp_heap: isp-heap { - iommu-addresses = <&isp 0x100 0x0 0x0 0x2000000>; - }; - - /* - * Text segment of the loaded GPU firmware (ADT gfx-asc - * segment-ranges[0]); the driver identifies the build from it. - */ - gpu_fw_text: gpu-fw-text { - reg = <0 0 0 0>; - status = "disabled"; - no-map; - }; - - /* - * Data segment of the loaded GPU firmware (ADT sgx gfx-data-*); it - * places its crash log here. - */ - gpu_fw_data: gpu-fw-data { - reg = <0 0 0 0>; - status = "disabled"; - no-map; - }; - - /* - * The UAT ranges (ADT sgx gpu-region-*, gfx-shared-region-*, - * gfx-shared-l2-region-*, gfx-handoff-*). They stay no-map until - * the boot loader adds them to /memory. - */ - uat_ttbs: uat-ttbs { - reg = <0 0 0 0>; - status = "disabled"; - no-map; - }; - - uat_pagetables: uat-pagetables { - reg = <0 0 0 0>; - status = "disabled"; - no-map; - }; - - uat_l2_pagetables: uat-l2-pagetables { - reg = <0 0 0 0>; - status = "disabled"; - no-map; - }; - - uat_handoff: uat-handoff { - reg = <0 0 0 0>; - status = "disabled"; - no-map; - }; - }; - - memory@0 { - device_type = "memory"; - reg = <0 0 0 0>; /* To be filled by loader */ - }; - - led-controller { - compatible = "pwm-leds"; - - led-0 { - pwms = <&fpwm0 0 40000>; - label = "apple::kbd_backlight"; - function = LED_FUNCTION_KBD_BACKLIGHT; - color = ; - max-brightness = <255>; - }; - }; - - /* - * GPU performance states, one opp-microvolt cell per cluster (ADT - * /arm-io/sgx perf-states and perf-states1). The operating points are - * binned per device: the loader fills these placeholders. - * The driver requires a completed calibration handoff. Entries keep the - * order of the GPU performance states, which is not sorted by frequency. - */ - gpu_opp: opp-table-gpu { - compatible = "operating-points-v2"; - - opp00 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp01 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp02 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp03 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp04 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp05 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp06 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp07 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp08 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp09 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp10 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp11 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp12 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp13 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp14 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - opp15 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0 0>; - }; - }; - - /* The GPU's CS clock domain (ADT cs-perf-states) */ - gpu_cs_opp: opp-table-gpucs { - compatible = "operating-points-v2"; - - opp00 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp01 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp02 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp03 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp04 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp05 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp06 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp07 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - }; - - /* The GPU's AFR clock domain (ADT afr-perf-states) */ - gpu_afr_opp: opp-table-gpuafr { - compatible = "operating-points-v2"; - - opp00 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp01 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp02 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp03 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp04 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp05 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp06 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - opp07 { - opp-hz = /bits/ 64 <0>; - opp-microvolt = <0>; - }; - }; - - /* - * CPU die temperature: SMC key TCMz (CPU die max), sensor 0 of - * smc_hwmon. The PMP's fast die-temperature limit regulates: its loop - * holds its own hot-spot sensors at 110 C (ADT fast-die-ctrl-loop), - * and under a sustained all-core load TCMz then settles at 113.4 to - * 114.7 C with the fans running. This zone is the backstop above that: - * passive at 116 C, critical (orderly shutdown) at 118 C, polled once a - * second as the SMC refreshes TCMz. The cpufreq cooling device sits on a - * cluster's policy CPU, so each map lists every CPU of its cluster. - * - * Per-cluster and GPU zones follow, one per SMC die-maximum sensor - * (smc_hwmon channels 1-23, in the order of the temperature nodes - * below): Tex0-3 throttle the E cluster, Tpx0-5 the first P cluster - * and Tpx8-D the second, with the same 116/118 C backstop as TCMz. - * Unlike the fanless J700, this machine has two SMC-driven fans and - * the PMP regulates the dies itself, so these zones only catch a - * failure of that loop; they never act in normal use. - * - * The GPU has no cooling device of its own: its firmware sets the GPU - * performance state and starts limiting at 101 C. So when a GPU die - * sensor reaches the GPU firmware's limit, the seven - * hottest ones (Tg05, Tg0S, Tg0Y, Tg0k, Tg0z, Tg1V, Tg1l) also shed - * CPU power through the CPU clusters, from the same 101 C, leaving the - * shared heat budget to the GPU. They shut down at 118 C. While the - * GPU is powered off its sensors report placeholder values from -4 to - * 4 C. - * - * The fans: left to themselves (SMC mode 3, with no OS asking for - * cooling) they stay off, or switch on late and ramp slowly, while the - * dies heat up under load. So the CPU die zone and the GPU zones also - * run both fans through a ladder of active trips; a fan takes the - * highest state any zone asks for and goes back to the SMC once no - * zone asks for anything. States 1-8 of a fan run it from its minimum - * (1350 rpm) to its maximum (5777 rpm) in even steps. - * - * sustainable-power is what the CPUs dissipate with the die held at - * its operating point: 720 s of all-core load (10 P, 4 E busy loops), - * headless, SMC fans in their own mode. Over the last 600 s TCMz held - * 112.0 to 113.8 C with the PMP limiting the P clusters to a mean of - * about 3.7 GHz and the fans at 3450/3730 rpm (where macOS settles - * too). The SMC core rails then read P0 25.3 W, P1 23.9 W and E 2.1 W - * on average, the units of the energy model. Each zone gets the sum - * over the clusters it throttles. Without it the power allocator - * estimates a budget from the cooling devices' lowest states, which - * throttles far below what this machine sustains. - */ -#define J616S_FAN_TRIP(label, node, temp, hyst) \ - label: node { \ - temperature = ; \ - hysteresis = ; \ - type = "active"; \ - }; - -#define J616S_FAN_TRIPS(zone) \ - J616S_FAN_TRIP(zone##_fan1, trip-fan1, 75000, 10000) \ - J616S_FAN_TRIP(zone##_fan2, trip-fan2, 80000, 5000) \ - J616S_FAN_TRIP(zone##_fan3, trip-fan3, 85000, 5000) \ - J616S_FAN_TRIP(zone##_fan4, trip-fan4, 90000, 5000) \ - J616S_FAN_TRIP(zone##_fan5, trip-fan5, 95000, 5000) - -#define J616S_FAN_MAP(trip_label, node, state) \ - node { \ - trip = <&trip_label>; \ - cooling-device = <&smc_hwmon 0 state state>, \ - <&smc_hwmon 1 state state>; \ - }; - -#define J616S_FAN_MAPS(zone) \ - J616S_FAN_MAP(zone##_fan1, map-fan1, 1) \ - J616S_FAN_MAP(zone##_fan2, map-fan2, 2) \ - J616S_FAN_MAP(zone##_fan3, map-fan3, 3) \ - J616S_FAN_MAP(zone##_fan4, map-fan4, 5) \ - J616S_FAN_MAP(zone##_fan5, map-fan5, 8) - - thermal-zones { - cpu-die-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <51300>; - thermal-sensors = <&smc_hwmon 0>; /* TCMz */ - - trips { - J616S_FAN_TRIPS(cpu_die) - - cpu_die_passive: cpu-die-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - cpu-die-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - J616S_FAN_MAPS(cpu_die) - - 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>; - }; - - 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-e0-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <2100>; - thermal-sensors = <&smc_hwmon 1>; /* Tex0 */ - - trips { - cpu_e0_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-e { - trip = <&cpu_e0_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>; - }; - }; - }; - - cpu-e1-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <2100>; - thermal-sensors = <&smc_hwmon 2>; /* Tex1 */ - - trips { - cpu_e1_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-e { - trip = <&cpu_e1_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>; - }; - }; - }; - - cpu-e2-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <2100>; - thermal-sensors = <&smc_hwmon 3>; /* Tex2 */ - - trips { - cpu_e2_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-e { - trip = <&cpu_e2_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>; - }; - }; - }; - - cpu-e3-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <2100>; - thermal-sensors = <&smc_hwmon 4>; /* Tex3 */ - - trips { - cpu_e3_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-e { - trip = <&cpu_e3_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>; - }; - }; - }; - - cpu-p00-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <25300>; - thermal-sensors = <&smc_hwmon 5>; /* Tpx0 */ - - trips { - cpu_p00_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p0 { - trip = <&cpu_p00_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-p01-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <25300>; - thermal-sensors = <&smc_hwmon 6>; /* Tpx1 */ - - trips { - cpu_p01_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p0 { - trip = <&cpu_p01_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-p02-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <25300>; - thermal-sensors = <&smc_hwmon 7>; /* Tpx2 */ - - trips { - cpu_p02_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p0 { - trip = <&cpu_p02_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-p03-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <25300>; - thermal-sensors = <&smc_hwmon 8>; /* Tpx3 */ - - trips { - cpu_p03_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p0 { - trip = <&cpu_p03_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-p04-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <25300>; - thermal-sensors = <&smc_hwmon 9>; /* Tpx4 */ - - trips { - cpu_p04_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p0 { - trip = <&cpu_p04_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 { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <25300>; - thermal-sensors = <&smc_hwmon 10>; /* Tpx5 */ - - trips { - cpu_p05_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p0 { - trip = <&cpu_p05_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-p10-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <23900>; - thermal-sensors = <&smc_hwmon 11>; /* Tpx8 */ - - trips { - cpu_p10_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p1 { - trip = <&cpu_p10_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-p11-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <23900>; - thermal-sensors = <&smc_hwmon 12>; /* Tpx9 */ - - trips { - cpu_p11_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p1 { - trip = <&cpu_p11_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-p12-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <23900>; - thermal-sensors = <&smc_hwmon 13>; /* TpxA */ - - trips { - cpu_p12_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p1 { - trip = <&cpu_p12_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-p13-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <23900>; - thermal-sensors = <&smc_hwmon 14>; /* TpxB */ - - trips { - cpu_p13_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p1 { - trip = <&cpu_p13_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-p14-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <23900>; - thermal-sensors = <&smc_hwmon 15>; /* TpxC */ - - trips { - cpu_p14_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p1 { - trip = <&cpu_p14_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 { - polling-delay-passive = <1000>; - polling-delay = <1000>; - sustainable-power = <23900>; - thermal-sensors = <&smc_hwmon 16>; /* TpxD */ - - trips { - cpu_p15_passive: trip-passive { - temperature = <116000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - map-p1 { - trip = <&cpu_p15_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>; - }; - }; - }; - - gpu0-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&smc_hwmon 17>; /* Tg05 */ - - trips { - J616S_FAN_TRIPS(gpu0) - - gpu0_passive: trip-passive { - temperature = <101000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - J616S_FAN_MAPS(gpu0) - - map-e { - trip = <&gpu0_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 = <&gpu0_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>; - }; - - map-p1 { - trip = <&gpu0_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>; - }; - }; - }; - - gpu1-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&smc_hwmon 18>; /* Tg0S */ - - trips { - J616S_FAN_TRIPS(gpu1) - - gpu1_passive: trip-passive { - temperature = <101000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - J616S_FAN_MAPS(gpu1) - - map-e { - trip = <&gpu1_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 = <&gpu1_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>; - }; - - map-p1 { - trip = <&gpu1_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>; - }; - }; - }; - - gpu2-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&smc_hwmon 19>; /* Tg0Y */ - - trips { - J616S_FAN_TRIPS(gpu2) - - gpu2_passive: trip-passive { - temperature = <101000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - J616S_FAN_MAPS(gpu2) - - map-e { - trip = <&gpu2_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 = <&gpu2_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>; - }; - - map-p1 { - trip = <&gpu2_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>; - }; - }; - }; - - gpu3-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&smc_hwmon 20>; /* Tg0k */ - - trips { - J616S_FAN_TRIPS(gpu3) - - gpu3_passive: trip-passive { - temperature = <101000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - J616S_FAN_MAPS(gpu3) - - map-e { - trip = <&gpu3_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 = <&gpu3_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>; - }; - - map-p1 { - trip = <&gpu3_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>; - }; - }; - }; - - gpu4-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&smc_hwmon 21>; /* Tg0z */ - - trips { - J616S_FAN_TRIPS(gpu4) - - gpu4_passive: trip-passive { - temperature = <101000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - J616S_FAN_MAPS(gpu4) - - map-e { - trip = <&gpu4_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 = <&gpu4_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>; - }; - - map-p1 { - trip = <&gpu4_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>; - }; - }; - }; - - gpu5-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&smc_hwmon 22>; /* Tg1V */ - - trips { - J616S_FAN_TRIPS(gpu5) - - gpu5_passive: trip-passive { - temperature = <101000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - J616S_FAN_MAPS(gpu5) - - map-e { - trip = <&gpu5_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 = <&gpu5_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>; - }; - - map-p1 { - trip = <&gpu5_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>; - }; - }; - }; - - gpu6-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&smc_hwmon 23>; /* Tg1l */ - - trips { - J616S_FAN_TRIPS(gpu6) - - gpu6_passive: trip-passive { - temperature = <101000>; - hysteresis = <5000>; - type = "passive"; - }; - - trip-critical { - temperature = <118000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - cooling-maps { - J616S_FAN_MAPS(gpu6) - - map-e { - trip = <&gpu6_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 = <&gpu6_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>; - }; - - map-p1 { - trip = <&gpu6_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>; - }; - }; - }; - }; - - /* - * The speaker amps' shared shutdown line (SDZ, AP pin 54, low = - * shutdown). One fixed regulator, the SDZ supply of all six, not - * per-amp shutdown-gpios: with GPIO_SHARED six references become a - * vote, and one amp driving the line low would not shut the other - * five down. - */ - speaker_sdz: regulator-sn012776-sdz { - compatible = "regulator-fixed"; - regulator-name = "sn012776-sdz"; - gpios = <&pinctrl 54 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; - - /* - * The AOP firmware runs the stream (MCA cluster 0, one serializer for - * all six amps); the J616 variant of macaudio links the AOP audio - * component's speaker back-end (DAI 3) to the amps. The codecs are - * listed in the ADT provider order, so each gets its native playback - * slot (LW1 0, RW1 1, LW2 2, RW2 3, LT 4, RT 5). The idle masks are the - * ADT amp-tx-zd-config rows 0 and 1: LW1 drives zeros in the right - * amps' sense slots, RW1 in the left amps'. - */ - sound: sound { - compatible = "apple,j616-macaudio", "apple,macaudio"; - model = "MacBook Pro J616"; - speaker-id-gpios = <&pinctrl 52 GPIO_ACTIVE_HIGH>, - <&pinctrl 53 GPIO_ACTIVE_HIGH>; - #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>; - }; - }; - }; - - /* - * The headphone jack: the AOP audio component's jack back-end (DAI 4) - * to the CS42L84. A card of its own, so a codec that does not answer - * costs the jack only, never the speakers. - */ - 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>; - }; - }; - }; -}; - -&cpuidle { - status = "okay"; -}; - -&smc { - status = "okay"; -}; - -&smc_mbox { - status = "okay"; -}; - -&nub_spmi0 { - status = "okay"; -}; - -&pinctrl { - status = "okay"; - - wifi_clkreq_pins: wifi-clkreq-pins { - pinmux = ; - }; -}; - -/* - * The AP takes none of the always-on bank's interrupts: the AOP firmware - * owns some of its pins and interrupt registers, and a chained handler here - * would see their pending bits without a handler of ours. - */ -&pinctrl_nub { - status = "okay"; - /delete-property/ interrupt-controller; - /delete-property/ #interrupt-cells; - /delete-property/ interrupts; -}; - -&fpwm0 { - status = "okay"; -}; - -/* apple_sep enables the SEP and its DART when it loads. */ -&sep_mbox { - status = "okay"; -}; - -/* - * Boot NOR. The partition is the J616s ADT /arm-io/qspi/spinor/anvram, - * flash-relative; asahi-bless and asahi-nvram find it by its label. - */ -&qspi { - status = "okay"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <10000000>; - spi-rx-bus-width = <1>; - spi-tx-bus-width = <1>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - nvram: partition@700000 { - label = "nvram"; - reg = <0x700000 0x100000>; - }; - }; - }; -}; - -/* The QSPI controller cannot probe while its power state is disabled. */ -&ps_qspi { - status = "okay"; -}; - -/* - * Touch ID sensor (Mesa 0x3356). Its power is NUB GPIO 53 and its - * data-ready line is AP GPIO 116, as the J616s ADT describes them. - */ -&spi2 { - status = "okay"; -}; - -&mesa { - status = "okay"; - enable-gpios = <&pinctrl_nub 53 GPIO_ACTIVE_HIGH>; - interrupt-parent = <&pinctrl>; - interrupts = <116 IRQ_TYPE_EDGE_RISING>; - spi-cs-setup-delay-ns = <20>; - spi-cs-hold-delay-ns = <20>; - /* - * Per-device factory data from this Mac's own iBoot system container: - * the sealed calibration and the sealed root key. - */ - firmware-name = "apple/mesacal-j616s.bin", "apple/msrk-j616s.bin"; -}; - -/* The Type-C retimers (ADT atcrt at 0x18/0x19/0x1a) sit on this bus; no driver yet. */ -&i2c6 { - status = "okay"; -}; - -&mtp { - status = "okay"; -}; - -&mtp_mbox { - status = "okay"; -}; - -&mtp_dart { - status = "okay"; -}; - -&mtp_dockchannel { - status = "okay"; -}; - -&mtp_hid { - /* SMC key gp1c powers the trackpad analog front end. */ - apple,afe-smc = <&smc>; - - multi-touch { - firmware-name = "apple/tpmtfw-j616s.bin"; - }; - - keyboard: keyboard { - hid-country-code = <0>; - apple,keyboard-layout-id = <2>; - }; - - stm { - }; - - actuator { - }; - - tp-accel { - }; - - mtp { - }; -}; - -&smc_hwmon { - /* - * TCMz and the 23 zone sensors after it must stay the first - * temperature children: the thermal zones name a sensor by its index, - * so the shared hwmon includes below only append after them. - * - * Every key below is in this machine's SMC key table as a readable - * float and was read on the J616s (SMC firmware of macOS 26.6.2). - * Keys that only ever read a fixed placeholder (Tz1*, Ta0*) or a - * fixed limit (TVMx, TVmS, TVms, PHPB, PHPM) are left out; rails that - * read 0 W while idle are kept. GPU (Tg*), P-cluster (Tp*) and - * E-cluster (Te*) labels follow load tests: Tg* only read live while - * the GPU is powered and rise with GPU load, Tp* and Te* rise with CPU - * load. Other names follow the SMC key groups and are not otherwise - * verified. SBA1-3 are the three cells of the 3S battery. - */ - temperature-TCMz { - apple,key-id = "TCMz"; - label = "CPU Die Max"; - }; - - temperature-Tex0 { - apple,key-id = "Tex0"; - label = "E-cluster Tex0"; - }; - - temperature-Tex1 { - apple,key-id = "Tex1"; - label = "E-cluster Tex1"; - }; - - temperature-Tex2 { - apple,key-id = "Tex2"; - label = "E-cluster Tex2"; - }; - - temperature-Tex3 { - apple,key-id = "Tex3"; - label = "E-cluster Tex3"; - }; - - temperature-Tpx0 { - apple,key-id = "Tpx0"; - label = "P-cluster Tpx0"; - }; - - temperature-Tpx1 { - apple,key-id = "Tpx1"; - label = "P-cluster Tpx1"; - }; - - temperature-Tpx2 { - apple,key-id = "Tpx2"; - label = "P-cluster Tpx2"; - }; - - temperature-Tpx3 { - apple,key-id = "Tpx3"; - label = "P-cluster Tpx3"; - }; - - temperature-Tpx4 { - apple,key-id = "Tpx4"; - label = "P-cluster Tpx4"; - }; - - temperature-Tpx5 { - apple,key-id = "Tpx5"; - label = "P-cluster Tpx5"; - }; - - temperature-Tpx8 { - apple,key-id = "Tpx8"; - label = "P-cluster Tpx8"; - }; - - temperature-Tpx9 { - apple,key-id = "Tpx9"; - label = "P-cluster Tpx9"; - }; - - temperature-TpxA { - apple,key-id = "TpxA"; - label = "P-cluster TpxA"; - }; - - temperature-TpxB { - apple,key-id = "TpxB"; - label = "P-cluster TpxB"; - }; - - temperature-TpxC { - apple,key-id = "TpxC"; - label = "P-cluster TpxC"; - }; - - temperature-TpxD { - apple,key-id = "TpxD"; - label = "P-cluster TpxD"; - }; - - temperature-Tg05 { - apple,key-id = "Tg05"; - label = "GPU Tg05"; - }; - - temperature-Tg0S { - apple,key-id = "Tg0S"; - label = "GPU Tg0S"; - }; - - temperature-Tg0Y { - apple,key-id = "Tg0Y"; - label = "GPU Tg0Y"; - }; - - temperature-Tg0k { - apple,key-id = "Tg0k"; - label = "GPU Tg0k"; - }; - - temperature-Tg0z { - apple,key-id = "Tg0z"; - label = "GPU Tg0z"; - }; - - temperature-Tg1V { - apple,key-id = "Tg1V"; - label = "GPU Tg1V"; - }; - - temperature-Tg1l { - apple,key-id = "Tg1l"; - label = "GPU Tg1l"; - }; - - temperature-TAOL { - apple,key-id = "TAOL"; - label = "SMC TAOL"; - }; - - temperature-TB1T { - apple,key-id = "TB1T"; - label = "Battery 1"; - }; - - temperature-TB2T { - apple,key-id = "TB2T"; - label = "Battery 2"; - }; - - temperature-TCMb { - apple,key-id = "TCMb"; - label = "SMC TCMb"; - }; - - temperature-TD00 { - apple,key-id = "TD00"; - label = "SMC TD00"; - }; - - temperature-TD01 { - apple,key-id = "TD01"; - label = "SMC TD01"; - }; - - temperature-TD02 { - apple,key-id = "TD02"; - label = "SMC TD02"; - }; - - temperature-TD03 { - apple,key-id = "TD03"; - label = "SMC TD03"; - }; - - temperature-TD04 { - apple,key-id = "TD04"; - label = "SMC TD04"; - }; - - temperature-TD10 { - apple,key-id = "TD10"; - label = "SMC TD10"; - }; - - temperature-TD11 { - apple,key-id = "TD11"; - label = "SMC TD11"; - }; - - temperature-TD12 { - apple,key-id = "TD12"; - label = "SMC TD12"; - }; - - temperature-TD13 { - apple,key-id = "TD13"; - label = "SMC TD13"; - }; - - temperature-TD14 { - apple,key-id = "TD14"; - label = "SMC TD14"; - }; - - temperature-TD20 { - apple,key-id = "TD20"; - label = "SMC TD20"; - }; - - temperature-TD21 { - apple,key-id = "TD21"; - label = "SMC TD21"; - }; - - temperature-TD22 { - apple,key-id = "TD22"; - label = "SMC TD22"; - }; - - temperature-TD23 { - apple,key-id = "TD23"; - label = "SMC TD23"; - }; - - temperature-TD24 { - apple,key-id = "TD24"; - label = "SMC TD24"; - }; - - temperature-TDBP { - apple,key-id = "TDBP"; - label = "SMC TDBP"; - }; - - temperature-TDCR { - apple,key-id = "TDCR"; - label = "SMC TDCR"; - }; - - temperature-TDEC { - apple,key-id = "TDEC"; - label = "SMC TDEC"; - }; - - temperature-TDEL { - apple,key-id = "TDEL"; - label = "SMC TDEL"; - }; - - temperature-TDER { - apple,key-id = "TDER"; - label = "SMC TDER"; - }; - - temperature-TDTP { - apple,key-id = "TDTP"; - label = "SMC TDTP"; - }; - - temperature-TDVx { - apple,key-id = "TDVx"; - label = "SMC TDVx"; - }; - - temperature-TDeL { - apple,key-id = "TDeL"; - label = "SMC TDeL"; - }; - - temperature-TDeR { - apple,key-id = "TDeR"; - label = "SMC TDeR"; - }; - - temperature-TF2S { - apple,key-id = "TF2S"; - label = "SMC TF2S"; - }; - - temperature-TH0a { - apple,key-id = "TH0a"; - label = "SMC TH0a"; - }; - - temperature-TH0b { - apple,key-id = "TH0b"; - label = "SMC TH0b"; - }; - - temperature-TMVR { - apple,key-id = "TMVR"; - label = "SMC TMVR"; - }; - - temperature-TPD0 { - apple,key-id = "TPD0"; - label = "SMC TPD0"; - }; - - temperature-TPD1 { - apple,key-id = "TPD1"; - label = "SMC TPD1"; - }; - - temperature-TPD2 { - apple,key-id = "TPD2"; - label = "SMC TPD2"; - }; - - temperature-TPD3 { - apple,key-id = "TPD3"; - label = "SMC TPD3"; - }; - - temperature-TPD4 { - apple,key-id = "TPD4"; - label = "SMC TPD4"; - }; - - temperature-TPD5 { - apple,key-id = "TPD5"; - label = "SMC TPD5"; - }; - - temperature-TPD6 { - apple,key-id = "TPD6"; - label = "SMC TPD6"; - }; - - temperature-TPD7 { - apple,key-id = "TPD7"; - label = "SMC TPD7"; - }; - - temperature-TPD8 { - apple,key-id = "TPD8"; - label = "SMC TPD8"; - }; - - temperature-TPD9 { - apple,key-id = "TPD9"; - label = "SMC TPD9"; - }; - - temperature-TPDX { - apple,key-id = "TPDX"; - label = "SMC TPDX"; - }; - - temperature-TPDa { - apple,key-id = "TPDa"; - label = "SMC TPDa"; - }; - - temperature-TPDb { - apple,key-id = "TPDb"; - label = "SMC TPDb"; - }; - - temperature-TPDc { - apple,key-id = "TPDc"; - label = "SMC TPDc"; - }; - - temperature-TPDd { - apple,key-id = "TPDd"; - label = "SMC TPDd"; - }; - - temperature-TPDe { - apple,key-id = "TPDe"; - label = "SMC TPDe"; - }; - - temperature-TPDf { - apple,key-id = "TPDf"; - label = "SMC TPDf"; - }; - - temperature-TPH3 { - apple,key-id = "TPH3"; - label = "SMC TPH3"; - }; - - temperature-TPMP { - apple,key-id = "TPMP"; - label = "SMC TPMP"; - }; - - temperature-TPSP { - apple,key-id = "TPSP"; - label = "SMC TPSP"; - }; - - temperature-TRD0 { - apple,key-id = "TRD0"; - label = "SMC TRD0"; - }; - - temperature-TRD1 { - apple,key-id = "TRD1"; - label = "SMC TRD1"; - }; - - temperature-TRD2 { - apple,key-id = "TRD2"; - label = "SMC TRD2"; - }; - - temperature-TRD3 { - apple,key-id = "TRD3"; - label = "SMC TRD3"; - }; - - temperature-TRD4 { - apple,key-id = "TRD4"; - label = "SMC TRD4"; - }; - - temperature-TRD5 { - apple,key-id = "TRD5"; - label = "SMC TRD5"; - }; - - temperature-TRD6 { - apple,key-id = "TRD6"; - label = "SMC TRD6"; - }; - - temperature-TRD7 { - apple,key-id = "TRD7"; - label = "SMC TRD7"; - }; - - temperature-TRD8 { - apple,key-id = "TRD8"; - label = "SMC TRD8"; - }; - - temperature-TRD9 { - apple,key-id = "TRD9"; - label = "SMC TRD9"; - }; - - temperature-TRDX { - apple,key-id = "TRDX"; - label = "SMC TRDX"; - }; - - temperature-TRDa { - apple,key-id = "TRDa"; - label = "SMC TRDa"; - }; - - temperature-TRDb { - apple,key-id = "TRDb"; - label = "SMC TRDb"; - }; - - temperature-TRDc { - apple,key-id = "TRDc"; - label = "SMC TRDc"; - }; - - temperature-TRDd { - apple,key-id = "TRDd"; - label = "SMC TRDd"; - }; - - temperature-TRDe { - apple,key-id = "TRDe"; - label = "SMC TRDe"; - }; - - temperature-TRDf { - apple,key-id = "TRDf"; - label = "SMC TRDf"; - }; - - temperature-TS0P { - apple,key-id = "TS0P"; - label = "SMC TS0P"; - }; - - temperature-TSG1 { - apple,key-id = "TSG1"; - label = "SMC TSG1"; - }; - - temperature-TUD0 { - apple,key-id = "TUD0"; - label = "SMC TUD0"; - }; - - temperature-TUD1 { - apple,key-id = "TUD1"; - label = "SMC TUD1"; - }; - - temperature-TUD2 { - apple,key-id = "TUD2"; - label = "SMC TUD2"; - }; - - temperature-TUD3 { - apple,key-id = "TUD3"; - label = "SMC TUD3"; - }; - - temperature-TUD4 { - apple,key-id = "TUD4"; - label = "SMC TUD4"; - }; - - temperature-TUD5 { - apple,key-id = "TUD5"; - label = "SMC TUD5"; - }; - - temperature-TUD6 { - apple,key-id = "TUD6"; - label = "SMC TUD6"; - }; - - temperature-TUD7 { - apple,key-id = "TUD7"; - label = "SMC TUD7"; - }; - - temperature-TUD8 { - apple,key-id = "TUD8"; - label = "SMC TUD8"; - }; - - temperature-TUD9 { - apple,key-id = "TUD9"; - label = "SMC TUD9"; - }; - - temperature-TUDX { - apple,key-id = "TUDX"; - label = "SMC TUDX"; - }; - - temperature-TUDa { - apple,key-id = "TUDa"; - label = "SMC TUDa"; - }; - - temperature-TUDb { - apple,key-id = "TUDb"; - label = "SMC TUDb"; - }; - - temperature-TUDc { - apple,key-id = "TUDc"; - label = "SMC TUDc"; - }; - - temperature-TUDd { - apple,key-id = "TUDd"; - label = "SMC TUDd"; - }; - - temperature-TUDe { - apple,key-id = "TUDe"; - label = "SMC TUDe"; - }; - - temperature-TUDf { - apple,key-id = "TUDf"; - label = "SMC TUDf"; - }; - - temperature-TVA0 { - apple,key-id = "TVA0"; - label = "SMC TVA0"; - }; - - temperature-TVD0 { - apple,key-id = "TVD0"; - label = "SMC TVD0"; - }; - - temperature-TVMR { - apple,key-id = "TVMR"; - label = "SMC TVMR"; - }; - - temperature-TVMX { - apple,key-id = "TVMX"; - label = "SMC TVMX"; - }; - - temperature-TVMr { - apple,key-id = "TVMr"; - label = "SMC TVMr"; - }; - - temperature-TVS0 { - apple,key-id = "TVS0"; - label = "SMC TVS0"; - }; - - temperature-TVS1 { - apple,key-id = "TVS1"; - label = "SMC TVS1"; - }; - - temperature-TVS2 { - apple,key-id = "TVS2"; - label = "SMC TVS2"; - }; - - temperature-TVV0 { - apple,key-id = "TVV0"; - label = "SMC TVV0"; - }; - - temperature-TVXX { - apple,key-id = "TVXX"; - label = "SMC TVXX"; - }; - - temperature-TVXh { - apple,key-id = "TVXh"; - label = "SMC TVXh"; - }; - - temperature-TVXm { - apple,key-id = "TVXm"; - label = "SMC TVXm"; - }; - - temperature-TVh0 { - apple,key-id = "TVh0"; - label = "SMC TVh0"; - }; - - temperature-TVh1 { - apple,key-id = "TVh1"; - label = "SMC TVh1"; - }; - - temperature-TVm0 { - apple,key-id = "TVm0"; - label = "SMC TVm0"; - }; - - temperature-TVxx { - apple,key-id = "TVxx"; - label = "SMC TVxx"; - }; - - temperature-TaLP { - apple,key-id = "TaLP"; - label = "SMC TaLP"; - }; - - temperature-TaLT { - apple,key-id = "TaLT"; - label = "SMC TaLT"; - }; - - temperature-TaLW { - apple,key-id = "TaLW"; - label = "SMC TaLW"; - }; - - temperature-TaRF { - apple,key-id = "TaRF"; - label = "SMC TaRF"; - }; - - temperature-TaRT { - apple,key-id = "TaRT"; - label = "SMC TaRT"; - }; - - temperature-TaRW { - apple,key-id = "TaRW"; - label = "SMC TaRW"; - }; - - temperature-TaTP { - apple,key-id = "TaTP"; - label = "SMC TaTP"; - }; - - temperature-Te04 { - apple,key-id = "Te04"; - label = "E-cluster Te04"; - }; - - temperature-Te05 { - apple,key-id = "Te05"; - label = "E-cluster Te05"; - }; - - temperature-Te06 { - apple,key-id = "Te06"; - label = "E-cluster Te06"; - }; - - temperature-Te0R { - apple,key-id = "Te0R"; - label = "E-cluster Te0R"; - }; - - temperature-Te0S { - apple,key-id = "Te0S"; - label = "E-cluster Te0S"; - }; - - temperature-Te0T { - apple,key-id = "Te0T"; - label = "E-cluster Te0T"; - }; - - temperature-TfC0 { - apple,key-id = "TfC0"; - label = "SMC TfC0"; - }; - - temperature-TfC1 { - apple,key-id = "TfC1"; - label = "SMC TfC1"; - }; - - temperature-TfC2 { - apple,key-id = "TfC2"; - label = "SMC TfC2"; - }; - - temperature-TfC3 { - apple,key-id = "TfC3"; - label = "SMC TfC3"; - }; - - temperature-TfC4 { - apple,key-id = "TfC4"; - label = "SMC TfC4"; - }; - - temperature-Tg04 { - apple,key-id = "Tg04"; - label = "GPU Tg04"; - }; - - temperature-Tg0K { - apple,key-id = "Tg0K"; - label = "GPU Tg0K"; - }; - - temperature-Tg0L { - apple,key-id = "Tg0L"; - label = "GPU Tg0L"; - }; - - temperature-Tg0R { - apple,key-id = "Tg0R"; - label = "GPU Tg0R"; - }; - - temperature-Tg0X { - apple,key-id = "Tg0X"; - label = "GPU Tg0X"; - }; - - temperature-Tg0d { - apple,key-id = "Tg0d"; - label = "GPU Tg0d"; - }; - - temperature-Tg0e { - apple,key-id = "Tg0e"; - label = "GPU Tg0e"; - }; - - temperature-Tg0j { - apple,key-id = "Tg0j"; - label = "GPU Tg0j"; - }; - - temperature-Tg0y { - apple,key-id = "Tg0y"; - label = "GPU Tg0y"; - }; - - temperature-Tg1E { - apple,key-id = "Tg1E"; - label = "GPU Tg1E"; - }; - - temperature-Tg1F { - apple,key-id = "Tg1F"; - label = "GPU Tg1F"; - }; - - temperature-Tg1U { - apple,key-id = "Tg1U"; - label = "GPU Tg1U"; - }; - - temperature-Tg1c { - apple,key-id = "Tg1c"; - label = "GPU Tg1c"; - }; - - temperature-Tg1d { - apple,key-id = "Tg1d"; - label = "GPU Tg1d"; - }; - - temperature-Tg1k { - apple,key-id = "Tg1k"; - label = "GPU Tg1k"; - }; - - temperature-Tp00 { - apple,key-id = "Tp00"; - label = "P-cluster Tp00"; - }; - - temperature-Tp01 { - apple,key-id = "Tp01"; - label = "P-cluster Tp01"; - }; - - temperature-Tp02 { - apple,key-id = "Tp02"; - label = "P-cluster Tp02"; - }; - - temperature-Tp04 { - apple,key-id = "Tp04"; - label = "P-cluster Tp04"; - }; - - temperature-Tp05 { - apple,key-id = "Tp05"; - label = "P-cluster Tp05"; - }; - - temperature-Tp06 { - apple,key-id = "Tp06"; - label = "P-cluster Tp06"; - }; - - temperature-Tp08 { - apple,key-id = "Tp08"; - label = "P-cluster Tp08"; - }; - - temperature-Tp09 { - apple,key-id = "Tp09"; - label = "P-cluster Tp09"; - }; - - temperature-Tp0A { - apple,key-id = "Tp0A"; - label = "P-cluster Tp0A"; - }; - - temperature-Tp0C { - apple,key-id = "Tp0C"; - label = "P-cluster Tp0C"; - }; - - temperature-Tp0D { - apple,key-id = "Tp0D"; - label = "P-cluster Tp0D"; - }; - - temperature-Tp0E { - apple,key-id = "Tp0E"; - label = "P-cluster Tp0E"; - }; - - temperature-Tp0G { - apple,key-id = "Tp0G"; - label = "P-cluster Tp0G"; - }; - - temperature-Tp0H { - apple,key-id = "Tp0H"; - label = "P-cluster Tp0H"; - }; - - temperature-Tp0I { - apple,key-id = "Tp0I"; - label = "P-cluster Tp0I"; - }; - - temperature-Tp0K { - apple,key-id = "Tp0K"; - label = "P-cluster Tp0K"; - }; - - temperature-Tp0L { - apple,key-id = "Tp0L"; - label = "P-cluster Tp0L"; - }; - - temperature-Tp0M { - apple,key-id = "Tp0M"; - label = "P-cluster Tp0M"; - }; - - temperature-Tp0O { - apple,key-id = "Tp0O"; - label = "P-cluster Tp0O"; - }; - - temperature-Tp0P { - apple,key-id = "Tp0P"; - label = "P-cluster Tp0P"; - }; - - temperature-Tp0Q { - apple,key-id = "Tp0Q"; - label = "P-cluster Tp0Q"; - }; - - temperature-Tp0S { - apple,key-id = "Tp0S"; - label = "P-cluster Tp0S"; - }; - - temperature-Tp0T { - apple,key-id = "Tp0T"; - label = "P-cluster Tp0T"; - }; - - temperature-Tp0U { - apple,key-id = "Tp0U"; - label = "P-cluster Tp0U"; - }; - - temperature-Tp0W { - apple,key-id = "Tp0W"; - label = "P-cluster Tp0W"; - }; - - temperature-Tp0X { - apple,key-id = "Tp0X"; - label = "P-cluster Tp0X"; - }; - - temperature-Tp0Y { - apple,key-id = "Tp0Y"; - label = "P-cluster Tp0Y"; - }; - - temperature-Tp0a { - apple,key-id = "Tp0a"; - label = "P-cluster Tp0a"; - }; - - temperature-Tp0b { - apple,key-id = "Tp0b"; - label = "P-cluster Tp0b"; - }; - - temperature-Tp0c { - apple,key-id = "Tp0c"; - label = "P-cluster Tp0c"; - }; - - temperature-Tp0d { - apple,key-id = "Tp0d"; - label = "P-cluster Tp0d"; - }; - - temperature-Tp0e { - apple,key-id = "Tp0e"; - label = "P-cluster Tp0e"; - }; - - temperature-Tp0f { - apple,key-id = "Tp0f"; - label = "P-cluster Tp0f"; - }; - - temperature-Tp0g { - apple,key-id = "Tp0g"; - label = "P-cluster Tp0g"; - }; - - temperature-Tp0i { - apple,key-id = "Tp0i"; - label = "P-cluster Tp0i"; - }; - - temperature-Tp0k { - apple,key-id = "Tp0k"; - label = "P-cluster Tp0k"; - }; - - temperature-Tp0l { - apple,key-id = "Tp0l"; - label = "P-cluster Tp0l"; - }; - - temperature-Tp0m { - apple,key-id = "Tp0m"; - label = "P-cluster Tp0m"; - }; - - temperature-Tp0n { - apple,key-id = "Tp0n"; - label = "P-cluster Tp0n"; - }; - - temperature-Tp0o { - apple,key-id = "Tp0o"; - label = "P-cluster Tp0o"; - }; - - temperature-Tp0q { - apple,key-id = "Tp0q"; - label = "P-cluster Tp0q"; - }; - - temperature-Tp0t { - apple,key-id = "Tp0t"; - label = "P-cluster Tp0t"; - }; - - temperature-Tp0u { - apple,key-id = "Tp0u"; - label = "P-cluster Tp0u"; - }; - - temperature-Tp0v { - apple,key-id = "Tp0v"; - label = "P-cluster Tp0v"; - }; - - temperature-Tp0w { - apple,key-id = "Tp0w"; - label = "P-cluster Tp0w"; - }; - - temperature-Tp1i { - apple,key-id = "Tp1i"; - label = "P-cluster Tp1i"; - }; - - temperature-Tp1j { - apple,key-id = "Tp1j"; - label = "P-cluster Tp1j"; - }; - - temperature-Tp1k { - apple,key-id = "Tp1k"; - label = "P-cluster Tp1k"; - }; - - temperature-Tp1m { - apple,key-id = "Tp1m"; - label = "P-cluster Tp1m"; - }; - - temperature-Tp1n { - apple,key-id = "Tp1n"; - label = "P-cluster Tp1n"; - }; - - temperature-Tp1o { - apple,key-id = "Tp1o"; - label = "P-cluster Tp1o"; - }; - - temperature-Tp1q { - apple,key-id = "Tp1q"; - label = "P-cluster Tp1q"; - }; - - temperature-Tp1t { - apple,key-id = "Tp1t"; - label = "P-cluster Tp1t"; - }; - - temperature-Tp1u { - apple,key-id = "Tp1u"; - label = "P-cluster Tp1u"; - }; - - temperature-Tp1v { - apple,key-id = "Tp1v"; - label = "P-cluster Tp1v"; - }; - - temperature-Tp1w { - apple,key-id = "Tp1w"; - label = "P-cluster Tp1w"; - }; - - temperature-Tp1x { - apple,key-id = "Tp1x"; - label = "P-cluster Tp1x"; - }; - - temperature-Tp1y { - apple,key-id = "Tp1y"; - label = "P-cluster Tp1y"; - }; - - temperature-Tp1z { - apple,key-id = "Tp1z"; - label = "P-cluster Tp1z"; - }; - - temperature-Tp20 { - apple,key-id = "Tp20"; - label = "P-cluster Tp20"; - }; - - temperature-Tp21 { - apple,key-id = "Tp21"; - label = "P-cluster Tp21"; - }; - - temperature-Tp22 { - apple,key-id = "Tp22"; - label = "P-cluster Tp22"; - }; - - temperature-Tp23 { - apple,key-id = "Tp23"; - label = "P-cluster Tp23"; - }; - - temperature-Tp24 { - apple,key-id = "Tp24"; - label = "P-cluster Tp24"; - }; - - temperature-Tp25 { - apple,key-id = "Tp25"; - label = "P-cluster Tp25"; - }; - - temperature-Tp26 { - apple,key-id = "Tp26"; - label = "P-cluster Tp26"; - }; - - temperature-Tp27 { - apple,key-id = "Tp27"; - label = "P-cluster Tp27"; - }; - - temperature-Tp28 { - apple,key-id = "Tp28"; - label = "P-cluster Tp28"; - }; - - temperature-Tp29 { - apple,key-id = "Tp29"; - label = "P-cluster Tp29"; - }; - - temperature-Tp2A { - apple,key-id = "Tp2A"; - label = "P-cluster Tp2A"; - }; - - temperature-Tp2B { - apple,key-id = "Tp2B"; - label = "P-cluster Tp2B"; - }; - - temperature-Tp2C { - apple,key-id = "Tp2C"; - label = "P-cluster Tp2C"; - }; - - temperature-Tp2D { - apple,key-id = "Tp2D"; - label = "P-cluster Tp2D"; - }; - - temperature-Tp2E { - apple,key-id = "Tp2E"; - label = "P-cluster Tp2E"; - }; - - temperature-Tp2G { - apple,key-id = "Tp2G"; - label = "P-cluster Tp2G"; - }; - - temperature-Tp2I { - apple,key-id = "Tp2I"; - label = "P-cluster Tp2I"; - }; - - temperature-Tp2J { - apple,key-id = "Tp2J"; - label = "P-cluster Tp2J"; - }; - - temperature-Tp2K { - apple,key-id = "Tp2K"; - label = "P-cluster Tp2K"; - }; - - temperature-Tp2L { - apple,key-id = "Tp2L"; - label = "P-cluster Tp2L"; - }; - - temperature-Tp2M { - apple,key-id = "Tp2M"; - label = "P-cluster Tp2M"; - }; - - temperature-Tp2N { - apple,key-id = "Tp2N"; - label = "P-cluster Tp2N"; - }; - - temperature-Tp2O { - apple,key-id = "Tp2O"; - label = "P-cluster Tp2O"; - }; - - temperature-Tp2Q { - apple,key-id = "Tp2Q"; - label = "P-cluster Tp2Q"; - }; - - temperature-Tp2R { - apple,key-id = "Tp2R"; - label = "P-cluster Tp2R"; - }; - - temperature-Tp2S { - apple,key-id = "Tp2S"; - label = "P-cluster Tp2S"; - }; - - temperature-Tp2T { - apple,key-id = "Tp2T"; - label = "P-cluster Tp2T"; - }; - - temperature-Tp2U { - apple,key-id = "Tp2U"; - label = "P-cluster Tp2U"; - }; - - temperature-Tp2V { - apple,key-id = "Tp2V"; - label = "P-cluster Tp2V"; - }; - - temperature-Tp2W { - apple,key-id = "Tp2W"; - label = "P-cluster Tp2W"; - }; - - temperature-Tp2X { - apple,key-id = "Tp2X"; - label = "P-cluster Tp2X"; - }; - - temperature-Ts00 { - apple,key-id = "Ts00"; - label = "SMC Ts00"; - }; - - temperature-Ts01 { - apple,key-id = "Ts01"; - label = "SMC Ts01"; - }; - - temperature-Ts02 { - apple,key-id = "Ts02"; - label = "SMC Ts02"; - }; - - temperature-Ts04 { - apple,key-id = "Ts04"; - label = "SMC Ts04"; - }; - - temperature-Ts05 { - apple,key-id = "Ts05"; - label = "SMC Ts05"; - }; - - temperature-Ts06 { - apple,key-id = "Ts06"; - label = "SMC Ts06"; - }; - - temperature-Ts08 { - apple,key-id = "Ts08"; - label = "SMC Ts08"; - }; - - temperature-Ts09 { - apple,key-id = "Ts09"; - label = "SMC Ts09"; - }; - - temperature-Ts0A { - apple,key-id = "Ts0A"; - label = "SMC Ts0A"; - }; - - temperature-Ts0C { - apple,key-id = "Ts0C"; - label = "SMC Ts0C"; - }; - - temperature-Ts0D { - apple,key-id = "Ts0D"; - label = "SMC Ts0D"; - }; - - temperature-Ts0E { - apple,key-id = "Ts0E"; - label = "SMC Ts0E"; - }; - - temperature-Ts0G { - apple,key-id = "Ts0G"; - label = "SMC Ts0G"; - }; - - temperature-Ts0H { - apple,key-id = "Ts0H"; - label = "SMC Ts0H"; - }; - - temperature-Ts0I { - apple,key-id = "Ts0I"; - label = "SMC Ts0I"; - }; - - temperature-Ts0K { - apple,key-id = "Ts0K"; - label = "SMC Ts0K"; - }; - - temperature-Ts0L { - apple,key-id = "Ts0L"; - label = "SMC Ts0L"; - }; - - temperature-Ts0M { - apple,key-id = "Ts0M"; - label = "SMC Ts0M"; - }; - - temperature-Ts0O { - apple,key-id = "Ts0O"; - label = "SMC Ts0O"; - }; - - temperature-Ts0P { - apple,key-id = "Ts0P"; - label = "SMC Ts0P"; - }; - - temperature-Ts0Q { - apple,key-id = "Ts0Q"; - label = "SMC Ts0Q"; - }; - - temperature-Ts0R { - apple,key-id = "Ts0R"; - label = "SMC Ts0R"; - }; - - temperature-Ts0T { - apple,key-id = "Ts0T"; - label = "SMC Ts0T"; - }; - - temperature-Ts0U { - apple,key-id = "Ts0U"; - label = "SMC Ts0U"; - }; - - temperature-Ts0W { - apple,key-id = "Ts0W"; - label = "SMC Ts0W"; - }; - - temperature-Ts1P { - apple,key-id = "Ts1P"; - label = "SMC Ts1P"; - }; - - temperature-Tsx0 { - apple,key-id = "Tsx0"; - label = "SMC Tsx0"; - }; - - temperature-Tsx1 { - apple,key-id = "Tsx1"; - label = "SMC Tsx1"; - }; - - voltage-VDM2 { - apple,key-id = "VDM2"; - label = "SMC VDM2"; - }; - - voltage-VDMA { - apple,key-id = "VDMA"; - label = "SMC VDMA"; - }; - - voltage-VDMM { - apple,key-id = "VDMM"; - label = "SMC VDMM"; - }; - - voltage-VP0R { - apple,key-id = "VP0R"; - label = "SMC VP0R"; - }; - - voltage-VP0b { - apple,key-id = "VP0b"; - label = "SMC VP0b"; - }; - - voltage-VP1b { - apple,key-id = "VP1b"; - label = "SMC VP1b"; - }; - - voltage-VP1l { - apple,key-id = "VP1l"; - label = "SMC VP1l"; - }; - - voltage-VP2b { - apple,key-id = "VP2b"; - label = "SMC VP2b"; - }; - - voltage-VP3b { - apple,key-id = "VP3b"; - label = "SMC VP3b"; - }; - - voltage-VP4b { - apple,key-id = "VP4b"; - label = "SMC VP4b"; - }; - - voltage-VP5l { - apple,key-id = "VP5l"; - label = "SMC VP5l"; - }; - - voltage-VP7b { - apple,key-id = "VP7b"; - label = "SMC VP7b"; - }; - - voltage-VP7l { - apple,key-id = "VP7l"; - label = "SMC VP7l"; - }; - - voltage-VP9b { - apple,key-id = "VP9b"; - label = "SMC VP9b"; - }; - - voltage-VP9l { - apple,key-id = "VP9l"; - label = "SMC VP9l"; - }; - - voltage-VPal { - apple,key-id = "VPal"; - label = "SMC VPal"; - }; - - voltage-VPbb { - apple,key-id = "VPbb"; - label = "SMC VPbb"; - }; - - voltage-VPdb { - apple,key-id = "VPdb"; - label = "SMC VPdb"; - }; - - voltage-VPeb { - apple,key-id = "VPeb"; - label = "SMC VPeb"; - }; - - voltage-VR0b { - apple,key-id = "VR0b"; - label = "SMC VR0b"; - }; - - voltage-VR1b { - apple,key-id = "VR1b"; - label = "SMC VR1b"; - }; - - voltage-VR2b { - apple,key-id = "VR2b"; - label = "SMC VR2b"; - }; - - voltage-VR3b { - apple,key-id = "VR3b"; - label = "SMC VR3b"; - }; - - voltage-VR3l { - apple,key-id = "VR3l"; - label = "SMC VR3l"; - }; - - voltage-VR4b { - apple,key-id = "VR4b"; - label = "SMC VR4b"; - }; - - voltage-VR7b { - apple,key-id = "VR7b"; - label = "SMC VR7b"; - }; - - voltage-VR8l { - apple,key-id = "VR8l"; - label = "SMC VR8l"; - }; - - voltage-VR9b { - apple,key-id = "VR9b"; - label = "SMC VR9b"; - }; - - voltage-VR9l { - apple,key-id = "VR9l"; - label = "SMC VR9l"; - }; - - voltage-VRal { - apple,key-id = "VRal"; - label = "SMC VRal"; - }; - - voltage-VRbb { - apple,key-id = "VRbb"; - label = "SMC VRbb"; - }; - - voltage-VRdb { - apple,key-id = "VRdb"; - label = "SMC VRdb"; - }; - - voltage-VReb { - apple,key-id = "VReb"; - label = "SMC VReb"; - }; - - voltage-VS0b { - apple,key-id = "VS0b"; - label = "SMC VS0b"; - }; - - voltage-VS1b { - apple,key-id = "VS1b"; - label = "SMC VS1b"; - }; - - voltage-VS2b { - apple,key-id = "VS2b"; - label = "SMC VS2b"; - }; - - voltage-VS3b { - apple,key-id = "VS3b"; - label = "SMC VS3b"; - }; - - voltage-VS4b { - apple,key-id = "VS4b"; - label = "SMC VS4b"; - }; - - voltage-VS7b { - apple,key-id = "VS7b"; - label = "SMC VS7b"; - }; - - voltage-VS9b { - apple,key-id = "VS9b"; - label = "SMC VS9b"; - }; - - voltage-VS9l { - apple,key-id = "VS9l"; - label = "SMC VS9l"; - }; - - voltage-VSal { - apple,key-id = "VSal"; - label = "SMC VSal"; - }; - - voltage-VSbb { - apple,key-id = "VSbb"; - label = "SMC VSbb"; - }; - - voltage-VSeb { - apple,key-id = "VSeb"; - label = "SMC VSeb"; - }; - - voltage-Vb0f { - apple,key-id = "Vb0f"; - label = "SMC Vb0f"; - }; - - voltage-Vb1f { - apple,key-id = "Vb1f"; - label = "SMC Vb1f"; - }; - - voltage-SBA1 { - apple,key-id = "SBA1"; - label = "Battery Cell 1"; - }; - - voltage-SBA2 { - apple,key-id = "SBA2"; - label = "Battery Cell 2"; - }; - - voltage-SBA3 { - apple,key-id = "SBA3"; - label = "Battery Cell 3"; - }; - - current-I3F2 { - apple,key-id = "I3F2"; - label = "SMC I3F2"; - }; - - current-I5SR { - apple,key-id = "I5SR"; - label = "SMC I5SR"; - }; - - current-IALR { - apple,key-id = "IALR"; - label = "SMC IALR"; - }; - - current-IARR { - apple,key-id = "IARR"; - label = "SMC IARR"; - }; - - current-ICMC { - apple,key-id = "ICMC"; - label = "SMC ICMC"; - }; - - current-ID3C { - apple,key-id = "ID3C"; - label = "SMC ID3C"; - }; - - current-IDBC { - apple,key-id = "IDBC"; - label = "SMC IDBC"; - }; - - current-IDBR { - apple,key-id = "IDBR"; - label = "SMC IDBR"; - }; - - current-IFLR { - apple,key-id = "IFLR"; - label = "SMC IFLR"; - }; - - current-IH0R { - apple,key-id = "IH0R"; - label = "SMC IH0R"; - }; - - current-IHCR { - apple,key-id = "IHCR"; - label = "SMC IHCR"; - }; - - current-IIDR { - apple,key-id = "IIDR"; - label = "SMC IIDR"; - }; - - current-IINC { - apple,key-id = "IINC"; - label = "SMC IINC"; - }; - - current-IMVC { - apple,key-id = "IMVC"; - label = "SMC IMVC"; - }; - - current-IMVR { - apple,key-id = "IMVR"; - label = "SMC IMVR"; - }; - - current-IP0b { - apple,key-id = "IP0b"; - label = "SMC IP0b"; - }; - - current-IP1b { - apple,key-id = "IP1b"; - label = "SMC IP1b"; - }; - - current-IP1l { - apple,key-id = "IP1l"; - label = "SMC IP1l"; - }; - - current-IP2b { - apple,key-id = "IP2b"; - label = "SMC IP2b"; - }; - - current-IP3b { - apple,key-id = "IP3b"; - label = "SMC IP3b"; - }; - - current-IP4b { - apple,key-id = "IP4b"; - label = "SMC IP4b"; - }; - - current-IP5l { - apple,key-id = "IP5l"; - label = "SMC IP5l"; - }; - - current-IP7b { - apple,key-id = "IP7b"; - label = "SMC IP7b"; - }; - - current-IP7l { - apple,key-id = "IP7l"; - label = "SMC IP7l"; - }; - - current-IP9b { - apple,key-id = "IP9b"; - label = "SMC IP9b"; - }; - - current-IP9l { - apple,key-id = "IP9l"; - label = "SMC IP9l"; - }; - - current-IPBR { - apple,key-id = "IPBR"; - label = "SMC IPBR"; - }; - - current-IPMC { - apple,key-id = "IPMC"; - label = "SMC IPMC"; - }; - - current-IPSC { - apple,key-id = "IPSC"; - label = "SMC IPSC"; - }; - - current-IPal { - apple,key-id = "IPal"; - label = "SMC IPal"; - }; - - current-IPbb { - apple,key-id = "IPbb"; - label = "SMC IPbb"; - }; - - current-IPdb { - apple,key-id = "IPdb"; - label = "SMC IPdb"; - }; - - current-IPeb { - apple,key-id = "IPeb"; - label = "SMC IPeb"; - }; - - current-IR0b { - apple,key-id = "IR0b"; - label = "SMC IR0b"; - }; - - current-IR1b { - apple,key-id = "IR1b"; - label = "SMC IR1b"; - }; - - current-IR2b { - apple,key-id = "IR2b"; - label = "SMC IR2b"; - }; - - current-IR3b { - apple,key-id = "IR3b"; - label = "SMC IR3b"; - }; - - current-IR3l { - apple,key-id = "IR3l"; - label = "SMC IR3l"; - }; - - current-IR4b { - apple,key-id = "IR4b"; - label = "SMC IR4b"; - }; - - current-IR7b { - apple,key-id = "IR7b"; - label = "SMC IR7b"; - }; - - current-IR8l { - apple,key-id = "IR8l"; - label = "SMC IR8l"; - }; - - current-IR9b { - apple,key-id = "IR9b"; - label = "SMC IR9b"; - }; - - current-IR9l { - apple,key-id = "IR9l"; - label = "SMC IR9l"; - }; - - current-IRal { - apple,key-id = "IRal"; - label = "SMC IRal"; - }; - - current-IRbb { - apple,key-id = "IRbb"; - label = "SMC IRbb"; - }; - - current-IRdb { - apple,key-id = "IRdb"; - label = "SMC IRdb"; - }; - - current-IReb { - apple,key-id = "IReb"; - label = "SMC IReb"; - }; - - current-IS0b { - apple,key-id = "IS0b"; - label = "SMC IS0b"; - }; - - current-IS1b { - apple,key-id = "IS1b"; - label = "SMC IS1b"; - }; - - current-IS2b { - apple,key-id = "IS2b"; - label = "SMC IS2b"; - }; - - current-IS3b { - apple,key-id = "IS3b"; - label = "SMC IS3b"; - }; - - current-IS4b { - apple,key-id = "IS4b"; - label = "SMC IS4b"; - }; - - current-IS7b { - apple,key-id = "IS7b"; - label = "SMC IS7b"; - }; - - current-IS9b { - apple,key-id = "IS9b"; - label = "SMC IS9b"; - }; - - current-IS9l { - apple,key-id = "IS9l"; - label = "SMC IS9l"; - }; - - current-ISDR { - apple,key-id = "ISDR"; - label = "SMC ISDR"; - }; - - current-ISal { - apple,key-id = "ISal"; - label = "SMC ISal"; - }; - - current-ISbb { - apple,key-id = "ISbb"; - label = "SMC ISbb"; - }; - - current-ISeb { - apple,key-id = "ISeb"; - label = "SMC ISeb"; - }; - - current-IU1C { - apple,key-id = "IU1C"; - label = "SMC IU1C"; - }; - - current-IU1R { - apple,key-id = "IU1R"; - label = "SMC IU1R"; - }; - - current-IU2C { - apple,key-id = "IU2C"; - label = "SMC IU2C"; - }; - - current-IU2R { - apple,key-id = "IU2R"; - label = "SMC IU2R"; - }; - - current-IW3C { - apple,key-id = "IW3C"; - label = "SMC IW3C"; - }; - - current-Ib0f { - apple,key-id = "Ib0f"; - label = "SMC Ib0f"; - }; - - current-Ib8f { - apple,key-id = "Ib8f"; - label = "SMC Ib8f"; - }; - - current-SBAC { - apple,key-id = "SBAC"; - label = "Battery Current"; - }; - - power-P3F2 { - apple,key-id = "P3F2"; - label = "SMC P3F2"; - }; - - power-P5SR { - apple,key-id = "P5SR"; - label = "SMC P5SR"; - }; - - power-PALR { - apple,key-id = "PALR"; - label = "SMC PALR"; - }; - - power-PARR { - apple,key-id = "PARR"; - label = "SMC PARR"; - }; - - power-PCMC { - apple,key-id = "PCMC"; - label = "SMC PCMC"; - }; - - power-PD3C { - apple,key-id = "PD3C"; - label = "SMC PD3C"; - }; - - power-PDBC { - apple,key-id = "PDBC"; - label = "SMC PDBC"; - }; - - power-PDBR { - apple,key-id = "PDBR"; - label = "SMC PDBR"; - }; - - power-PFLR { - apple,key-id = "PFLR"; - label = "SMC PFLR"; - }; - - power-PH0R { - apple,key-id = "PH0R"; - label = "SMC PH0R"; - }; - - power-PHCR { - apple,key-id = "PHCR"; - label = "SMC PHCR"; - }; - - power-PIDR { - apple,key-id = "PIDR"; - label = "SMC PIDR"; - }; - - power-PINC { - apple,key-id = "PINC"; - label = "SMC PINC"; - }; - - power-PMVC { - apple,key-id = "PMVC"; - label = "SMC PMVC"; - }; - - power-PP0b { - apple,key-id = "PP0b"; - label = "SMC PP0b"; - }; - - power-PP1b { - apple,key-id = "PP1b"; - label = "SMC PP1b"; - }; - - power-PP1l { - apple,key-id = "PP1l"; - label = "SMC PP1l"; - }; - - power-PP2b { - apple,key-id = "PP2b"; - label = "SMC PP2b"; - }; - - power-PP3b { - apple,key-id = "PP3b"; - label = "SMC PP3b"; - }; - - power-PP4b { - apple,key-id = "PP4b"; - label = "SMC PP4b"; - }; - - power-PP5l { - apple,key-id = "PP5l"; - label = "SMC PP5l"; - }; - - power-PP7b { - apple,key-id = "PP7b"; - label = "SMC PP7b"; - }; - - power-PP7l { - apple,key-id = "PP7l"; - label = "SMC PP7l"; - }; - - power-PP9b { - apple,key-id = "PP9b"; - label = "SMC PP9b"; - }; - - power-PP9l { - apple,key-id = "PP9l"; - label = "SMC PP9l"; - }; - - power-PPBR { - apple,key-id = "PPBR"; - label = "SMC PPBR"; - }; - - power-PPMC { - apple,key-id = "PPMC"; - label = "SMC PPMC"; - }; - - power-PPSC { - apple,key-id = "PPSC"; - label = "SMC PPSC"; - }; - - power-PPal { - apple,key-id = "PPal"; - label = "SMC PPal"; - }; - - power-PPbb { - apple,key-id = "PPbb"; - label = "SMC PPbb"; - }; - - power-PPdb { - apple,key-id = "PPdb"; - label = "SMC PPdb"; - }; - - power-PPeb { - apple,key-id = "PPeb"; - label = "SMC PPeb"; - }; - - power-PR0b { - apple,key-id = "PR0b"; - label = "SMC PR0b"; - }; - - power-PR1b { - apple,key-id = "PR1b"; - label = "SMC PR1b"; - }; - - power-PR2b { - apple,key-id = "PR2b"; - label = "SMC PR2b"; - }; - - power-PR3b { - apple,key-id = "PR3b"; - label = "SMC PR3b"; - }; - - power-PR3l { - apple,key-id = "PR3l"; - label = "SMC PR3l"; - }; - - power-PR4b { - apple,key-id = "PR4b"; - label = "SMC PR4b"; - }; - - power-PR7b { - apple,key-id = "PR7b"; - label = "SMC PR7b"; - }; - - power-PR8l { - apple,key-id = "PR8l"; - label = "SMC PR8l"; - }; - - power-PR9b { - apple,key-id = "PR9b"; - label = "SMC PR9b"; - }; - - power-PR9l { - apple,key-id = "PR9l"; - label = "SMC PR9l"; - }; - - power-PRal { - apple,key-id = "PRal"; - label = "SMC PRal"; - }; - - power-PRbb { - apple,key-id = "PRbb"; - label = "SMC PRbb"; - }; - - power-PRdb { - apple,key-id = "PRdb"; - label = "SMC PRdb"; - }; - - power-PReb { - apple,key-id = "PReb"; - label = "SMC PReb"; - }; - - power-PS0b { - apple,key-id = "PS0b"; - label = "SMC PS0b"; - }; - - power-PS1b { - apple,key-id = "PS1b"; - label = "SMC PS1b"; - }; - - power-PS2b { - apple,key-id = "PS2b"; - label = "SMC PS2b"; - }; - - power-PS3b { - apple,key-id = "PS3b"; - label = "SMC PS3b"; - }; - - power-PS4b { - apple,key-id = "PS4b"; - label = "SMC PS4b"; - }; - - power-PS7b { - apple,key-id = "PS7b"; - label = "SMC PS7b"; - }; - - power-PS9b { - apple,key-id = "PS9b"; - label = "SMC PS9b"; - }; - - power-PS9l { - apple,key-id = "PS9l"; - label = "SMC PS9l"; - }; - - power-PSDR { - apple,key-id = "PSDR"; - label = "SMC PSDR"; - }; - - power-PSal { - apple,key-id = "PSal"; - label = "SMC PSal"; - }; - - power-PSbb { - apple,key-id = "PSbb"; - label = "SMC PSbb"; - }; - - power-PSeb { - apple,key-id = "PSeb"; - label = "SMC PSeb"; - }; - - power-PTHS { - apple,key-id = "PTHS"; - label = "SMC PTHS"; - }; - - power-PU1C { - apple,key-id = "PU1C"; - label = "SMC PU1C"; - }; - - power-PU1R { - apple,key-id = "PU1R"; - label = "SMC PU1R"; - }; - - power-PU2C { - apple,key-id = "PU2C"; - label = "SMC PU2C"; - }; - - power-PU2R { - apple,key-id = "PU2R"; - label = "SMC PU2R"; - }; - - power-PW3C { - apple,key-id = "PW3C"; - label = "SMC PW3C"; - }; - - power-PZC0 { - apple,key-id = "PZC0"; - label = "SMC PZC0"; - }; - - power-PZC1 { - apple,key-id = "PZC1"; - label = "SMC PZC1"; - }; - - power-PZCB { - apple,key-id = "PZCB"; - label = "SMC PZCB"; - }; - - power-PZCU { - apple,key-id = "PZCU"; - label = "SMC PZCU"; - }; - - power-PZD1 { - apple,key-id = "PZD1"; - label = "SMC PZD1"; - }; - - power-PZT0 { - apple,key-id = "PZT0"; - label = "SMC PZT0"; - }; - - power-Pb0f { - apple,key-id = "Pb0f"; - label = "SMC Pb0f"; - }; - - power-SBAP { - apple,key-id = "SBAP"; - label = "Battery Power"; - }; -}; - -/* Fan monitoring and explicit userspace manual control. */ -#include "hwmon-common.dtsi" -#include "hwmon-fan-dual.dtsi" -#include "hwmon-laptop.dtsi" - -&smc_hwmon { - apple,thermal-pressure-key = "mTPL"; - - /* - * The SMC accepts a manual speed for both fans once its fan test - * key unlocks them, and returns them to system mode when the - * request is dropped. - */ - fan-F0Ac { - apple,fan-manual-control; - }; - - fan-F1Ac { - apple,fan-manual-control; - }; -}; - -&pcie_dart { - status = "okay"; -}; - -/* - * Wi-Fi and Bluetooth (BCM4388). The boot loader finds these nodes by - * the paths in the wifi0 and bluetooth0 aliases and adds the per-unit - * calibration, the antenna SKU and the addresses to them. - */ -/ { - pcie0: pcie@1cb0000000 { - compatible = "apple,t6041-pcie", "apple,t6020-pcie"; - reg = <0x1c 0xb0000000 0x0 0x1000000>, /* config */ - <0x4 0x14000000 0x0 0x4000>, /* rc */ - <0x4 0x10028000 0x0 0x4000>, /* port0 */ - <0x4 0x11028000 0x0 0x4000>, /* port1 */ - <0x4 0x12028000 0x0 0x4000>, /* port2 */ - <0x4 0x13028000 0x0 0x4000>, /* port3 */ - <0x4 0x17020000 0x0 0x4000>, /* phy0 */ - <0x4 0x17024000 0x0 0x4000>, /* phy1 */ - <0x4 0x17028000 0x0 0x4000>, /* phy2 */ - <0x4 0x1702c000 0x0 0x4000>; /* phy3 */ - 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 { - 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>; - /* To be filled by the loader */ - local-bd-address = [00 00 00 00 00 00]; - brcm,board-type = "apple,hostomel"; - status = "okay"; - }; - - wifi@0,0 { - compatible = "pci14e4,4434", "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"; -}; - -&pmp_dart { - status = "okay"; -}; - -&pmp_report { - status = "okay"; -}; - -&pmp { - status = "okay"; -}; - -&pmp_mbox { - status = "okay"; -}; - -&dcp { - panel { - compatible = "apple,panel-j616", "apple,panel-mini-led", "apple,panel"; - width-mm = <345>; - height-mm = <223>; - adj-height-mm = <216>; - status = "disabled"; - }; -}; - -&pmc { - status = "okay"; -}; - -&mcc { - status = "okay"; -}; - -&aop { - status = "okay"; -}; - -&aop_mbox { - status = "okay"; -}; - -&aop_dart { - status = "okay"; + model = "Apple MacBook Pro (16-inch, M4 Pro)"; }; -/* The sensor is on the logic board, in the base. */ -&aop_accel { - label = "accel-base"; +/* ADT /arm-io/wlan module-instance */ +&wifi0 { + brcm,board-type = "apple,hostomel"; }; -&admac0 { - status = "okay"; +&bluetooth0 { + brcm,board-type = "apple,hostomel"; }; -&admac1 { - status = "okay"; +&panel { + compatible = "apple,panel-j616", "apple,panel-mini-led", "apple,panel"; + width-mm = <345>; + height-mm = <223>; + adj-height-mm = <216>; }; &aop_audio { apple,chassis-name = "J616"; - apple,machine-kind = "MacBook Pro"; -}; - -/* - * The six SN012776 speaker amps, held in hardware shutdown until a sound - * card enables them (ADT /arm-io/i2c1/audio-speaker@38): one interrupt line - * on AP pin 55, level low; sense slots from speaker-config (speaker i at RX - * bytes 4i and 4i + 2, order LW1 RW1 LW2 RW2 LT RT). Names as on the J314 - * and J316, which speakersafetyd's profile uses. Every amp joins the SDZ - * fail-closed group: an over-temperature or over-current fault on any one - * forces the shared shutdown line low. - */ -&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>; - }; -}; - -/* - * The CS42L84 headphone codec (ADT /arm-io/i2c2/audio-codec-output@4B). Its - * reset line is nub GPIO pin 58, driven high to run the codec (the driver's - * "reset" is an enable, as on the J514/J516); its interrupt is AP pin 106, - * level low. The AOP firmware runs the jack's stream on MCA cluster 2. - */ -&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"; - }; -}; - -&isp { - memory-region = <&isp_fw_text>, <&isp_fw_data>, <&isp_heap>; - memory-region-names = "text", "data", "heap"; - apple,platform-id = <5>; - /* ADT isp0 cam-connections-scheme */ - apple,cam-connections-scheme = <0x10>; - status = "okay"; - - /* - * The front camera, an IMX958: firmware configuration 5 as the - * firmware reports it. - */ - sensor-presets { - /* 1920x1080 */ - preset0 { - apple,config-index = <5>; - apple,input-size = <1920 2160>; - apple,output-size = <1920 1080>; - apple,crop = <0 0 1920 1080>; - }; - /* 1280x720 */ - preset1 { - apple,config-index = <5>; - apple,input-size = <1920 2160>; - apple,output-size = <1280 720>; - apple,crop = <0 0 1280 720>; - }; - }; -}; - -&isp_dart0 { - status = "okay"; -}; - -&isp_dart1 { - status = "okay"; -}; - -&isp_dart2 { - status = "okay"; -}; - -/* - * The loaded GPU firmware keeps running across system sleep. Like the Neo's - * GFX domain, these domains must not be switched off while that image lives. - * The PMP report vote is still owned by the GPU consumer. - */ -&ps_afr { - apple,always-on; -}; - -&ps_gfx { - apple,always-on; -}; - -/* The loader fills the operating points, calibration and all six memory regions. */ -&gfx_mbox { - status = "okay"; -}; - -&gpu { - memory-region = <&uat_ttbs>, <&uat_pagetables>, <&uat_handoff>, - <&gpu_fw_data>, <&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>; - /* Avoid a core power cycle between interactive submissions, then release. */ - apple,idle-off-delay-ms = <16>; - status = "okay"; -}; - -/* - * The Type-C ports (ADT nub-spmi-a0 hpm0/hpm1, nub-spmi-a1 hpm2) and the - * MagSafe controller (nub-spmi-a0 hpm5). The ADT lists the event, sleep and - * wake interrupts; select is event + 2. - */ -&nub_spmi_a0 { - status = "okay"; - - hpm0: 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"; - - typec0: connector { - compatible = "usb-c-connector"; - label = "USB-C Left Back"; - power-role = "dual"; - data-role = "dual"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - typec0_con_hs: endpoint { - remote-endpoint = <&usb_drd0_hs>; - }; - }; - - port@1 { - reg = <1>; - typec0_con_ss: endpoint { - remote-endpoint = <&atcphy0_ss>; - }; - }; - }; - }; - }; - - 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>; - }; - }; - - port@1 { - reg = <1>; - typec1_con_ss: endpoint { - remote-endpoint = <&atcphy1_ss>; - }; - }; - }; - }; - }; - - /* MagSafe port */ - hpm5: usb-pd@8 { - compatible = "apple,sn201202x"; - reg = <0x8 SPMI_USID>; - interrupts = <63 IRQ_TYPE_EDGE_RISING>, - <65 IRQ_TYPE_EDGE_RISING>, - <69 IRQ_TYPE_EDGE_RISING>, - <71 IRQ_TYPE_EDGE_RISING>; - interrupt-names = "irq", "select", "sleep", "wake"; - }; -}; - -&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>; - }; - }; - - port@1 { - reg = <1>; - typec2_con_ss: endpoint { - remote-endpoint = <&atcphy2_ss>; - }; - }; - }; - }; - }; -}; - -&atcphy0 { - status = "okay"; - - port { - atcphy0_ss: endpoint { - remote-endpoint = <&typec0_con_ss>; - }; - }; -}; - -&atcphy0_mbox { - status = "okay"; -}; - -&usb_drd0_dart_0 { - status = "okay"; -}; - -&usb_drd0_dart_1 { - status = "okay"; -}; - -&usb_drd0 { - status = "okay"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - usb_drd0_hs: endpoint { - remote-endpoint = <&typec0_con_hs>; - }; - }; - }; -}; - -&atcphy1 { - status = "okay"; - - port { - atcphy1_ss: endpoint { - remote-endpoint = <&typec1_con_ss>; - }; - }; -}; - -&atcphy1_mbox { - status = "okay"; -}; - -&usb_drd1_dart_0 { - status = "okay"; -}; - -&usb_drd1_dart_1 { - status = "okay"; -}; - -&usb_drd1 { - status = "okay"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - usb_drd1_hs: endpoint { - remote-endpoint = <&typec1_con_hs>; - }; - }; - }; -}; - -&atcphy2 { - status = "okay"; - - port { - atcphy2_ss: endpoint { - remote-endpoint = <&typec2_con_ss>; - }; - }; -}; - -&atcphy2_mbox { - status = "okay"; -}; - -&usb_drd2_dart_0 { - status = "okay"; -}; - -&usb_drd2_dart_1 { - status = "okay"; -}; - -&usb_drd2 { - status = "okay"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - usb_drd2_hs: endpoint { - remote-endpoint = <&typec2_con_hs>; - }; - }; - }; -}; - -/* The video encoder, its DARTs and its power domains. */ -&ps_venc0_sys { - status = "okay"; -}; - -&ps_venc0_dma { - status = "okay"; -}; - -&ps_venc0_pipe4 { - status = "okay"; -}; - -&ps_venc0_pipe5 { - status = "okay"; -}; - -&ps_venc0_me0 { - status = "okay"; -}; - -&ps_venc0_me1 { - status = "okay"; -}; - -&ave0_dart0 { - status = "okay"; -}; - -&ave0_dart1 { - status = "okay"; -}; - -&ave { - status = "okay"; -}; - -#include "t6040-j616s-usb3.dtsi" - -/* External display chain, all disabled: the gate in drivers/soc/apple/display-gate.c enables it. */ -#include "t6040-j616s-extdisp.dtsi" -#include "t6040-j616s-extdisp-mem-loader.dtsi" -#include "t6040-j616s-extdisp-hdmi.dtsi" -#include "t6040-j616s-extdisp-usbc.dtsi" -#include "t6040-j616s-dpaudio.dtsi" -/* Additional Abbey PMICs on the two independent NUB SPMI buses. */ -&nub_spmi1 { - status = "okay"; - - pmic@e { - compatible = "apple,abbey-pmic", "apple,spmi-nvmem"; - reg = <0xe SPMI_USID>; - }; -}; - -&nub_spmi2 { - status = "okay"; - - pmic@e { - compatible = "apple,abbey-pmic", "apple,spmi-nvmem"; - reg = <0xe SPMI_USID>; - }; -}; - -&ps_nub_spmi_ahb { - status = "okay"; -}; - -&ps_nub_spmi1 { - status = "okay"; -}; - -&ps_nub_spmi2 { - status = "okay"; }; -&pinctrl { - sd_clkreq_pins: sd-clkreq-pins { - pinmux = ; - }; +&sound { + compatible = "apple,j616-macaudio", "apple,macaudio"; + model = "MacBook Pro J616"; }; -&pcie0 { - interrupts = , - ; - /* Widen bus-range only with the SD power/port ownership handoff. */ - iommu-map = <0x100 &pcie_dart 1 2>, <0x200 &apcie1_dart 1 1>; - - port01: pci@1,0 { - device_type = "pci"; - reg = <0x800 0 0 0 0>; - reset-gpios = <&pinctrl 5 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&sd_clkreq_pins>; - #address-cells = <3>; - #size-cells = <2>; - ranges; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &port01 0 0 0 0>, - <0 0 0 2 &port01 0 0 0 1>, - <0 0 0 3 &port01 0 0 0 2>, - <0 0 0 4 &port01 0 0 0 3>; - /* The SD power switch needs an SMC service binding. */ - status = "disabled"; - }; +&sound_jack { + compatible = "apple,j616-macaudio-jack", "apple,macaudio"; + model = "MacBook Pro J616 Jack"; }; -/* - * The SMC owns automatic fan policy. Drop the host fan trip/map instances - * after the board's thermal descriptions, retaining all passive and critical - * protection. Keep this final policy separate from ladder descriptions so - * independent ladder updates cannot restore autonomous SMC writes. - */ - -#define J616S_DELETE_FAN_TRIPS \ - /delete-node/ trip-fan1; \ - /delete-node/ trip-fan2; \ - /delete-node/ trip-fan3; \ - /delete-node/ trip-fan4; \ - /delete-node/ trip-fan5; - -/* Some CPU ladders also map full fan speed to the passive trip. */ -#define J616S_DELETE_FAN_MAPS \ - /delete-node/ map-fan1; \ - /delete-node/ map-fan2; \ - /delete-node/ map-fan3; \ - /delete-node/ map-fan4; \ - /delete-node/ map-fan5; \ - /delete-node/ map-fan6; - -/ { - thermal-zones { - cpu-die-thermal { - trips { - J616S_DELETE_FAN_TRIPS - }; - - cooling-maps { - J616S_DELETE_FAN_MAPS - }; - }; - - gpu0-thermal { - trips { - J616S_DELETE_FAN_TRIPS - }; - - cooling-maps { - J616S_DELETE_FAN_MAPS - }; - }; - - gpu1-thermal { - trips { - J616S_DELETE_FAN_TRIPS - }; - - cooling-maps { - J616S_DELETE_FAN_MAPS - }; - }; - - gpu2-thermal { - trips { - J616S_DELETE_FAN_TRIPS - }; - - cooling-maps { - J616S_DELETE_FAN_MAPS - }; - }; - - gpu3-thermal { - trips { - J616S_DELETE_FAN_TRIPS - }; - - cooling-maps { - J616S_DELETE_FAN_MAPS - }; - }; - - gpu4-thermal { - trips { - J616S_DELETE_FAN_TRIPS - }; - - cooling-maps { - J616S_DELETE_FAN_MAPS - }; - }; - - gpu5-thermal { - trips { - J616S_DELETE_FAN_TRIPS - }; - - cooling-maps { - J616S_DELETE_FAN_MAPS - }; - }; - - gpu6-thermal { - trips { - J616S_DELETE_FAN_TRIPS - }; - - cooling-maps { - J616S_DELETE_FAN_MAPS - }; - }; - }; +&mtp_mt { + firmware-name = "apple/tpmtfw-j616s.bin"; }; -#undef J616S_DELETE_FAN_TRIPS -#undef J616S_DELETE_FAN_MAPS - /* - * Proven on the J616s (MobileNetV1 top-1 16/16). The ANE stays idle until - * the loader fills and enables the two preload reservations above. + * Per-device factory data from this Mac's own iBoot system container: the + * sealed calibration and the sealed root key. */ -&ane0_dart0 { - status = "okay"; -}; - -&ane0_dart1 { - status = "okay"; -}; - -&ane0_dart2 { - status = "okay"; -}; - -&ane { - memory-region = <&ane_fw_text>, <&ane_fw_data>; - memory-region-names = "firmware-text", "firmware-data"; - /* - * The SoC rail floor, held only while ANE requests are in flight: - * MobileNet engine time 0.87 -> 0.54 ms on an idle system. - */ - power-domains = <&ps_ane_sys>, <&ps_ane_cpu>, <&ps_ane_mpm>, - <&ps_ane_td>, <&ps_ane_base>, <&pmc_soc_max>; - power-domain-names = "sys", "cpu", "mpm", "td", "base", "perf"; - status = "okay"; +&mesa { + firmware-name = "apple/mesacal-j616s.bin", "apple/msrk-j616s.bin"; }; diff --git a/arch/arm64/boot/dts/apple/t604x-j614-j616.dtsi b/arch/arm64/boot/dts/apple/t604x-j614-j616.dtsi new file mode 100644 index 0000000000000..b116e17d8ce17 --- /dev/null +++ b/arch/arm64/boot/dts/apple/t604x-j614-j616.dtsi @@ -0,0 +1,4935 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * MacBook Pro (14/16-inch, M4 Pro) + * + * This file contains the parts common to the J614s and J616s. Apple's + * device trees for the two boards differ only in the panel, the speaker + * tuning, the Wi-Fi module, the trackpad and the power limits; the board + * files set those. + * + * target-type: J614s / J616s + * + * Copyright The Asahi Linux Contributors + */ + +#include +#include +#include + +/ { + chassis-type = "laptop"; + + aliases { + keyboard = &keyboard; + nvram = &nvram; + spi0 = &qspi; + rtc0 = &smc_rtc; + rtc1 = &pmu_rtc; + wifi0 = "/pcie@1cb0000000/pci@0,0/wifi@0,0"; + bluetooth0 = "/pcie@1cb0000000/pci@0,0/bluetooth@0,1"; + /* used by the loader to hand over the display */ + dcp = &dcp; + disp0 = &display; + disp0-piodma = &disp0_piodma; + /* the boot loader finds the GPU node through this alias */ + gpu = &gpu; + pmp = &pmp; + /* the boot loader reserves the SEP firmware through this alias */ + sep = &sep; + }; + + chosen { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + framebuffer0: framebuffer@0 { + compatible = "apple,simple-framebuffer", "simple-framebuffer"; + reg = <0 0 0 0>; /* To be filled by loader */ + /* Format properties will be added by loader */ + status = "disabled"; + }; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* The loader adds its own reservations */ + + /* + * The loader must fill reg from ane0 segment-ranges, rename each + * node to match its physical address and enable it. Leave these + * disabled until then; allocating replacement memory would lose + * the personalized preload. TEXT is 0xc0000 bytes and DATA is + * 0x2ac000 bytes. Neither segment may be reclaimed before reboot. + */ + ane_fw_text: ane-firmware-text@0 { + compatible = "apple,asc-mem"; + reg = <0 0 0 0>; + no-map; + status = "disabled"; + }; + + ane_fw_data: ane-firmware-data@0 { + compatible = "apple,asc-mem"; + reg = <0 0 0 0>; + no-map; + status = "disabled"; + }; + + /* + * iBoot loads the ISP firmware below the kernel's memory. Its + * segments are the ADT's isp0 segment-ranges (macOS 26.6.2, + * iBoot mBoot-18000.161.10), mapped where the firmware runs them: + * 0x100_0000_0000 onwards, its 32 MiB main memory. The driver + * checks that the coprocessor's reset vector is this text before + * it starts the firmware. + */ + isp_fw_text: isp-firmware-text@10000c44000 { + reg = <0x100 0x00c44000 0x0 0xca8000>; + iommu-addresses = <&isp 0x100 0x0 0x0 0xca8000>; + no-map; + }; + + isp_fw_data: isp-firmware-data@10001e7c000 { + reg = <0x100 0x01e7c000 0x0 0x1344000>; + iommu-addresses = <&isp 0x100 0xca8000 0x0 0x1344000>; + no-map; + }; + + /* the firmware's main memory, the driver allocates above it */ + isp_heap: isp-heap { + iommu-addresses = <&isp 0x100 0x0 0x0 0x2000000>; + }; + + /* + * Text segment of the loaded GPU firmware (ADT gfx-asc + * segment-ranges[0]); the driver identifies the build from it. + */ + gpu_fw_text: gpu-fw-text { + reg = <0 0 0 0>; + status = "disabled"; + no-map; + }; + + /* + * Data segment of the loaded GPU firmware (ADT sgx gfx-data-*); it + * places its crash log here. + */ + gpu_fw_data: gpu-fw-data { + reg = <0 0 0 0>; + status = "disabled"; + no-map; + }; + + /* + * The UAT ranges (ADT sgx gpu-region-*, gfx-shared-region-*, + * gfx-shared-l2-region-*, gfx-handoff-*). They stay no-map until + * the boot loader adds them to /memory. + */ + uat_ttbs: uat-ttbs { + reg = <0 0 0 0>; + status = "disabled"; + no-map; + }; + + uat_pagetables: uat-pagetables { + reg = <0 0 0 0>; + status = "disabled"; + no-map; + }; + + uat_l2_pagetables: uat-l2-pagetables { + reg = <0 0 0 0>; + status = "disabled"; + no-map; + }; + + uat_handoff: uat-handoff { + reg = <0 0 0 0>; + status = "disabled"; + no-map; + }; + }; + + memory@0 { + device_type = "memory"; + reg = <0 0 0 0>; /* To be filled by loader */ + }; + + led-controller { + compatible = "pwm-leds"; + + led-0 { + pwms = <&fpwm0 0 40000>; + label = "apple::kbd_backlight"; + function = LED_FUNCTION_KBD_BACKLIGHT; + color = ; + max-brightness = <255>; + }; + }; + + /* + * GPU performance states, one opp-microvolt cell per cluster (ADT + * /arm-io/sgx perf-states and perf-states1). The operating points are + * binned per device: the loader fills these placeholders. + * The driver requires a completed calibration handoff. Entries keep the + * order of the GPU performance states, which is not sorted by frequency. + */ + gpu_opp: opp-table-gpu { + compatible = "operating-points-v2"; + + opp00 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp01 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp02 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp03 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp04 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp05 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp06 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp07 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp08 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp09 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp10 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp11 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp12 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp13 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp14 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + opp15 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0>; + }; + }; + + /* The GPU's CS clock domain (ADT cs-perf-states) */ + gpu_cs_opp: opp-table-gpucs { + compatible = "operating-points-v2"; + + opp00 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp01 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp02 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp03 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp04 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp05 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp06 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp07 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + }; + + /* The GPU's AFR clock domain (ADT afr-perf-states) */ + gpu_afr_opp: opp-table-gpuafr { + compatible = "operating-points-v2"; + + opp00 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp01 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp02 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp03 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp04 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp05 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp06 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + opp07 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + }; + + /* + * CPU die temperature: SMC key TCMz (CPU die max), sensor 0 of + * smc_hwmon. The PMP's fast die-temperature limit regulates: its loop + * holds its own hot-spot sensors at 110 C (ADT fast-die-ctrl-loop), + * and under a sustained all-core load TCMz then settles at 113.4 to + * 114.7 C with the fans running. This zone is the backstop above that: + * passive at 116 C, critical (orderly shutdown) at 118 C, polled once a + * second as the SMC refreshes TCMz. The cpufreq cooling device sits on a + * cluster's policy CPU, so each map lists every CPU of its cluster. + * + * Per-cluster and GPU zones follow, one per SMC die-maximum sensor + * (smc_hwmon channels 1-23, in the order of the temperature nodes + * below): Tex0-3 throttle the E cluster, Tpx0-5 the first P cluster + * and Tpx8-D the second, with the same 116/118 C backstop as TCMz. + * Unlike the fanless J700, this machine has two SMC-driven fans and + * the PMP regulates the dies itself, so these zones only catch a + * failure of that loop; they never act in normal use. + * + * The GPU has no cooling device of its own: its firmware sets the GPU + * performance state and starts limiting at 101 C. So when a GPU die + * sensor reaches the GPU firmware's limit, the seven + * hottest ones (Tg05, Tg0S, Tg0Y, Tg0k, Tg0z, Tg1V, Tg1l) also shed + * CPU power through the CPU clusters, from the same 101 C, leaving the + * shared heat budget to the GPU. They shut down at 118 C. While the + * GPU is powered off its sensors report placeholder values from -4 to + * 4 C. + * + * Every zone runs the power allocator, which acts at any temperature + * unless a zone has a second passive trip: the first one is then its + * switch-on point, below which it resets and grants full power. So each + * zone has one, 16 C below the die and CPU control trip (100/116 C) and + * 11 C below the GPU one (90/101 C). Without them the GPU zones, whose + * placeholder readings never warm up, held all 14 CPUs to about 7.5 W + * (1.26/1.02/1.26 GHz) under any all-core load. The GPU zones also + * carry the die's sustainable power rather than the allocator's + * estimate from the lowest CPU states (about 2.6 W). + * + * The fans: left to themselves (SMC mode 3, with no OS asking for + * cooling) they stay off, or switch on late and ramp slowly, while the + * dies heat up under load. So the CPU die zone and the GPU zones also + * run both fans through a ladder of active trips; a fan takes the + * highest state any zone asks for and goes back to the SMC once no + * zone asks for anything. States 1-8 of a fan run it from its minimum + * (1350 rpm) to its maximum (5777 rpm) in even steps. + * + * sustainable-power is what the CPUs dissipate with the die held at + * its operating point: 720 s of all-core load (10 P, 4 E busy loops), + * headless, SMC fans in their own mode. Over the last 600 s TCMz held + * 112.0 to 113.8 C with the PMP limiting the P clusters to a mean of + * about 3.7 GHz and the fans at 3450/3730 rpm (where macOS settles + * too). The SMC core rails then read P0 25.3 W, P1 23.9 W and E 2.1 W + * on average, the units of the energy model. Each zone gets the sum + * over the clusters it throttles. Without it the power allocator + * estimates a budget from the cooling devices' lowest states, which + * throttles far below what this machine sustains. + * + * All of these values were measured on the J616s. The J614s inherits + * them until it is measured: Apple's package power limits for it are + * about 78% (CPU) and 90% (GPU) of the J616s ones, so its budgets are + * generous here, but these zones are a backstop behind the PMP. + */ +#define J616S_FAN_TRIP(label, node, temp, hyst) \ + label: node { \ + temperature = ; \ + hysteresis = ; \ + type = "active"; \ + }; + +#define J616S_FAN_TRIPS(zone) \ + J616S_FAN_TRIP(zone##_fan1, trip-fan1, 75000, 10000) \ + J616S_FAN_TRIP(zone##_fan2, trip-fan2, 80000, 5000) \ + J616S_FAN_TRIP(zone##_fan3, trip-fan3, 85000, 5000) \ + J616S_FAN_TRIP(zone##_fan4, trip-fan4, 90000, 5000) \ + J616S_FAN_TRIP(zone##_fan5, trip-fan5, 95000, 5000) + +#define J616S_FAN_MAP(trip_label, node, state) \ + node { \ + trip = <&trip_label>; \ + cooling-device = <&smc_hwmon 0 state state>, \ + <&smc_hwmon 1 state state>; \ + }; + +#define J616S_FAN_MAPS(zone) \ + J616S_FAN_MAP(zone##_fan1, map-fan1, 1) \ + J616S_FAN_MAP(zone##_fan2, map-fan2, 2) \ + J616S_FAN_MAP(zone##_fan3, map-fan3, 3) \ + J616S_FAN_MAP(zone##_fan4, map-fan4, 5) \ + J616S_FAN_MAP(zone##_fan5, map-fan5, 8) + + thermal-zones { + cpu-die-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <51300>; + thermal-sensors = <&smc_hwmon 0>; /* TCMz */ + + trips { + J616S_FAN_TRIPS(cpu_die) + + cpu_die_switch_on: cpu-die-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_die_passive: cpu-die-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + cpu-die-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + J616S_FAN_MAPS(cpu_die) + + 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>; + }; + + 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-e0-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <2100>; + thermal-sensors = <&smc_hwmon 1>; /* Tex0 */ + + trips { + cpu_e0_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_e0_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-e { + trip = <&cpu_e0_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>; + }; + }; + }; + + cpu-e1-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <2100>; + thermal-sensors = <&smc_hwmon 2>; /* Tex1 */ + + trips { + cpu_e1_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_e1_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-e { + trip = <&cpu_e1_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>; + }; + }; + }; + + cpu-e2-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <2100>; + thermal-sensors = <&smc_hwmon 3>; /* Tex2 */ + + trips { + cpu_e2_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_e2_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-e { + trip = <&cpu_e2_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>; + }; + }; + }; + + cpu-e3-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <2100>; + thermal-sensors = <&smc_hwmon 4>; /* Tex3 */ + + trips { + cpu_e3_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_e3_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-e { + trip = <&cpu_e3_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>; + }; + }; + }; + + cpu-p00-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <25300>; + thermal-sensors = <&smc_hwmon 5>; /* Tpx0 */ + + trips { + cpu_p00_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p00_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p0 { + trip = <&cpu_p00_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-p01-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <25300>; + thermal-sensors = <&smc_hwmon 6>; /* Tpx1 */ + + trips { + cpu_p01_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p01_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p0 { + trip = <&cpu_p01_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-p02-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <25300>; + thermal-sensors = <&smc_hwmon 7>; /* Tpx2 */ + + trips { + cpu_p02_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p02_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p0 { + trip = <&cpu_p02_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-p03-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <25300>; + thermal-sensors = <&smc_hwmon 8>; /* Tpx3 */ + + trips { + cpu_p03_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p03_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p0 { + trip = <&cpu_p03_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-p04-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <25300>; + thermal-sensors = <&smc_hwmon 9>; /* Tpx4 */ + + trips { + cpu_p04_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p04_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p0 { + trip = <&cpu_p04_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 { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <25300>; + thermal-sensors = <&smc_hwmon 10>; /* Tpx5 */ + + trips { + cpu_p05_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p05_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p0 { + trip = <&cpu_p05_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-p10-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <23900>; + thermal-sensors = <&smc_hwmon 11>; /* Tpx8 */ + + trips { + cpu_p10_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p10_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p1 { + trip = <&cpu_p10_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-p11-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <23900>; + thermal-sensors = <&smc_hwmon 12>; /* Tpx9 */ + + trips { + cpu_p11_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p11_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p1 { + trip = <&cpu_p11_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-p12-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <23900>; + thermal-sensors = <&smc_hwmon 13>; /* TpxA */ + + trips { + cpu_p12_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p12_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p1 { + trip = <&cpu_p12_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-p13-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <23900>; + thermal-sensors = <&smc_hwmon 14>; /* TpxB */ + + trips { + cpu_p13_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p13_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p1 { + trip = <&cpu_p13_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-p14-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <23900>; + thermal-sensors = <&smc_hwmon 15>; /* TpxC */ + + trips { + cpu_p14_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p14_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p1 { + trip = <&cpu_p14_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 { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <23900>; + thermal-sensors = <&smc_hwmon 16>; /* TpxD */ + + trips { + cpu_p15_switch_on: trip-switch-on { + temperature = <100000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_p15_passive: trip-passive { + temperature = <116000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map-p1 { + trip = <&cpu_p15_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>; + }; + }; + }; + + gpu0-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <51300>; + thermal-sensors = <&smc_hwmon 17>; /* Tg05 */ + + trips { + J616S_FAN_TRIPS(gpu0) + + gpu0_switch_on: trip-switch-on { + temperature = <90000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu0_passive: trip-passive { + temperature = <101000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + J616S_FAN_MAPS(gpu0) + + map-e { + trip = <&gpu0_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 = <&gpu0_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>; + }; + + map-p1 { + trip = <&gpu0_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>; + }; + }; + }; + + gpu1-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <51300>; + thermal-sensors = <&smc_hwmon 18>; /* Tg0S */ + + trips { + J616S_FAN_TRIPS(gpu1) + + gpu1_switch_on: trip-switch-on { + temperature = <90000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu1_passive: trip-passive { + temperature = <101000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + J616S_FAN_MAPS(gpu1) + + map-e { + trip = <&gpu1_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 = <&gpu1_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>; + }; + + map-p1 { + trip = <&gpu1_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>; + }; + }; + }; + + gpu2-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <51300>; + thermal-sensors = <&smc_hwmon 19>; /* Tg0Y */ + + trips { + J616S_FAN_TRIPS(gpu2) + + gpu2_switch_on: trip-switch-on { + temperature = <90000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu2_passive: trip-passive { + temperature = <101000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + J616S_FAN_MAPS(gpu2) + + map-e { + trip = <&gpu2_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 = <&gpu2_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>; + }; + + map-p1 { + trip = <&gpu2_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>; + }; + }; + }; + + gpu3-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <51300>; + thermal-sensors = <&smc_hwmon 20>; /* Tg0k */ + + trips { + J616S_FAN_TRIPS(gpu3) + + gpu3_switch_on: trip-switch-on { + temperature = <90000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu3_passive: trip-passive { + temperature = <101000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + J616S_FAN_MAPS(gpu3) + + map-e { + trip = <&gpu3_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 = <&gpu3_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>; + }; + + map-p1 { + trip = <&gpu3_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>; + }; + }; + }; + + gpu4-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <51300>; + thermal-sensors = <&smc_hwmon 21>; /* Tg0z */ + + trips { + J616S_FAN_TRIPS(gpu4) + + gpu4_switch_on: trip-switch-on { + temperature = <90000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu4_passive: trip-passive { + temperature = <101000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + J616S_FAN_MAPS(gpu4) + + map-e { + trip = <&gpu4_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 = <&gpu4_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>; + }; + + map-p1 { + trip = <&gpu4_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>; + }; + }; + }; + + gpu5-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <51300>; + thermal-sensors = <&smc_hwmon 22>; /* Tg1V */ + + trips { + J616S_FAN_TRIPS(gpu5) + + gpu5_switch_on: trip-switch-on { + temperature = <90000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu5_passive: trip-passive { + temperature = <101000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + J616S_FAN_MAPS(gpu5) + + map-e { + trip = <&gpu5_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 = <&gpu5_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>; + }; + + map-p1 { + trip = <&gpu5_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>; + }; + }; + }; + + gpu6-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + sustainable-power = <51300>; + thermal-sensors = <&smc_hwmon 23>; /* Tg1l */ + + trips { + J616S_FAN_TRIPS(gpu6) + + gpu6_switch_on: trip-switch-on { + temperature = <90000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu6_passive: trip-passive { + temperature = <101000>; + hysteresis = <5000>; + type = "passive"; + }; + + trip-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + J616S_FAN_MAPS(gpu6) + + map-e { + trip = <&gpu6_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 = <&gpu6_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>; + }; + + map-p1 { + trip = <&gpu6_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>; + }; + }; + }; + }; + + /* + * The speaker amps' shared shutdown line (SDZ, AP pin 54, low = + * shutdown). One fixed regulator, the SDZ supply of all six, not + * per-amp shutdown-gpios: with GPIO_SHARED six references become a + * vote, and one amp driving the line low would not shut the other + * five down. + */ + speaker_sdz: regulator-sn012776-sdz { + compatible = "regulator-fixed"; + regulator-name = "sn012776-sdz"; + gpios = <&pinctrl 54 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + /* + * The AOP firmware runs the stream (MCA cluster 0, one serializer for + * all six amps); the board's variant of macaudio links the AOP audio + * component's speaker back-end (DAI 3) to the amps. The codecs are + * listed in the ADT provider order, so each gets its native playback + * slot (LW1 0, RW1 1, LW2 2, RW2 3, LT 4, RT 5). The idle masks are the + * ADT amp-tx-zd-config rows 0 and 1: LW1 drives zeros in the right + * amps' sense slots, RW1 in the left amps'. + */ + sound: sound { + speaker-id-gpios = <&pinctrl 52 GPIO_ACTIVE_HIGH>, + <&pinctrl 53 GPIO_ACTIVE_HIGH>; + #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>; + }; + }; + }; + + /* + * The headphone jack: the AOP audio component's jack back-end (DAI 4) + * to the CS42L84. A card of its own, so a codec that does not answer + * costs the jack only, never the speakers. + */ + sound_jack: sound-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>; + }; + }; + }; +}; + +&cpuidle { + status = "okay"; +}; + +&smc { + status = "okay"; +}; + +&smc_mbox { + status = "okay"; +}; + +&nub_spmi0 { + status = "okay"; +}; + +&pinctrl { + status = "okay"; + + wifi_clkreq_pins: wifi-clkreq-pins { + pinmux = ; + }; +}; + +/* + * The AP takes none of the always-on bank's interrupts: the AOP firmware + * owns some of its pins and interrupt registers, and a chained handler here + * would see their pending bits without a handler of ours. + */ +&pinctrl_nub { + status = "okay"; + /delete-property/ interrupt-controller; + /delete-property/ #interrupt-cells; + /delete-property/ interrupts; +}; + +&fpwm0 { + status = "okay"; +}; + +/* apple_sep enables the SEP and its DART when it loads. */ +&sep_mbox { + status = "okay"; +}; + +/* + * Boot NOR. The partition is the J616s ADT /arm-io/qspi/spinor/anvram, + * flash-relative; asahi-bless and asahi-nvram find it by its label. + */ +&qspi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + spi-rx-bus-width = <1>; + spi-tx-bus-width = <1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + nvram: partition@700000 { + label = "nvram"; + reg = <0x700000 0x100000>; + }; + }; + }; +}; + +/* The QSPI controller cannot probe while its power state is disabled. */ +&ps_qspi { + status = "okay"; +}; + +/* + * Touch ID sensor (Mesa 0x3356). Its power is NUB GPIO 53 and its + * data-ready line is AP GPIO 116, as the J616s ADT describes them. + */ +&spi2 { + status = "okay"; +}; + +&mesa { + status = "okay"; + enable-gpios = <&pinctrl_nub 53 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&pinctrl>; + interrupts = <116 IRQ_TYPE_EDGE_RISING>; + spi-cs-setup-delay-ns = <20>; + spi-cs-hold-delay-ns = <20>; + /* The board file names the per-device factory data. */ +}; + +/* The Type-C retimers (ADT atcrt at 0x18/0x19/0x1a) sit on this bus; no driver yet. */ +&i2c6 { + status = "okay"; +}; + +&mtp { + status = "okay"; +}; + +&mtp_mbox { + status = "okay"; +}; + +&mtp_dart { + status = "okay"; +}; + +&mtp_dockchannel { + status = "okay"; +}; + +&mtp_hid { + /* SMC key gp1c powers the trackpad analog front end. */ + apple,afe-smc = <&smc>; + + mtp_mt: multi-touch { + }; + + keyboard: keyboard { + hid-country-code = <0>; + apple,keyboard-layout-id = <2>; + }; + + stm { + }; + + actuator { + }; + + tp-accel { + }; + + mtp { + }; +}; + +&smc_hwmon { + /* + * TCMz and the 23 zone sensors after it must stay the first + * temperature children: the thermal zones name a sensor by its index, + * so the shared hwmon includes below only append after them. + * + * Every key below is in this machine's SMC key table as a readable + * float and was read on the J616s (SMC firmware of macOS 26.6.2). + * The J614s key table has not been read yet. + * Keys that only ever read a fixed placeholder (Tz1*, Ta0*) or a + * fixed limit (TVMx, TVmS, TVms, PHPB, PHPM) are left out; rails that + * read 0 W while idle are kept. GPU (Tg*), P-cluster (Tp*) and + * E-cluster (Te*) labels follow load tests: Tg* only read live while + * the GPU is powered and rise with GPU load, Tp* and Te* rise with CPU + * load. Other names follow the SMC key groups and are not otherwise + * verified. SBA1-3 are the three cells of the 3S battery. + */ + temperature-TCMz { + apple,key-id = "TCMz"; + label = "CPU Die Max"; + }; + + temperature-Tex0 { + apple,key-id = "Tex0"; + label = "E-cluster Tex0"; + }; + + temperature-Tex1 { + apple,key-id = "Tex1"; + label = "E-cluster Tex1"; + }; + + temperature-Tex2 { + apple,key-id = "Tex2"; + label = "E-cluster Tex2"; + }; + + temperature-Tex3 { + apple,key-id = "Tex3"; + label = "E-cluster Tex3"; + }; + + temperature-Tpx0 { + apple,key-id = "Tpx0"; + label = "P-cluster Tpx0"; + }; + + temperature-Tpx1 { + apple,key-id = "Tpx1"; + label = "P-cluster Tpx1"; + }; + + temperature-Tpx2 { + apple,key-id = "Tpx2"; + label = "P-cluster Tpx2"; + }; + + temperature-Tpx3 { + apple,key-id = "Tpx3"; + label = "P-cluster Tpx3"; + }; + + temperature-Tpx4 { + apple,key-id = "Tpx4"; + label = "P-cluster Tpx4"; + }; + + temperature-Tpx5 { + apple,key-id = "Tpx5"; + label = "P-cluster Tpx5"; + }; + + temperature-Tpx8 { + apple,key-id = "Tpx8"; + label = "P-cluster Tpx8"; + }; + + temperature-Tpx9 { + apple,key-id = "Tpx9"; + label = "P-cluster Tpx9"; + }; + + temperature-TpxA { + apple,key-id = "TpxA"; + label = "P-cluster TpxA"; + }; + + temperature-TpxB { + apple,key-id = "TpxB"; + label = "P-cluster TpxB"; + }; + + temperature-TpxC { + apple,key-id = "TpxC"; + label = "P-cluster TpxC"; + }; + + temperature-TpxD { + apple,key-id = "TpxD"; + label = "P-cluster TpxD"; + }; + + temperature-Tg05 { + apple,key-id = "Tg05"; + label = "GPU Tg05"; + }; + + temperature-Tg0S { + apple,key-id = "Tg0S"; + label = "GPU Tg0S"; + }; + + temperature-Tg0Y { + apple,key-id = "Tg0Y"; + label = "GPU Tg0Y"; + }; + + temperature-Tg0k { + apple,key-id = "Tg0k"; + label = "GPU Tg0k"; + }; + + temperature-Tg0z { + apple,key-id = "Tg0z"; + label = "GPU Tg0z"; + }; + + temperature-Tg1V { + apple,key-id = "Tg1V"; + label = "GPU Tg1V"; + }; + + temperature-Tg1l { + apple,key-id = "Tg1l"; + label = "GPU Tg1l"; + }; + + temperature-TAOL { + apple,key-id = "TAOL"; + label = "SMC TAOL"; + }; + + temperature-TB1T { + apple,key-id = "TB1T"; + label = "Battery 1"; + }; + + temperature-TB2T { + apple,key-id = "TB2T"; + label = "Battery 2"; + }; + + temperature-TCMb { + apple,key-id = "TCMb"; + label = "SMC TCMb"; + }; + + temperature-TD00 { + apple,key-id = "TD00"; + label = "SMC TD00"; + }; + + temperature-TD01 { + apple,key-id = "TD01"; + label = "SMC TD01"; + }; + + temperature-TD02 { + apple,key-id = "TD02"; + label = "SMC TD02"; + }; + + temperature-TD03 { + apple,key-id = "TD03"; + label = "SMC TD03"; + }; + + temperature-TD04 { + apple,key-id = "TD04"; + label = "SMC TD04"; + }; + + temperature-TD10 { + apple,key-id = "TD10"; + label = "SMC TD10"; + }; + + temperature-TD11 { + apple,key-id = "TD11"; + label = "SMC TD11"; + }; + + temperature-TD12 { + apple,key-id = "TD12"; + label = "SMC TD12"; + }; + + temperature-TD13 { + apple,key-id = "TD13"; + label = "SMC TD13"; + }; + + temperature-TD14 { + apple,key-id = "TD14"; + label = "SMC TD14"; + }; + + temperature-TD20 { + apple,key-id = "TD20"; + label = "SMC TD20"; + }; + + temperature-TD21 { + apple,key-id = "TD21"; + label = "SMC TD21"; + }; + + temperature-TD22 { + apple,key-id = "TD22"; + label = "SMC TD22"; + }; + + temperature-TD23 { + apple,key-id = "TD23"; + label = "SMC TD23"; + }; + + temperature-TD24 { + apple,key-id = "TD24"; + label = "SMC TD24"; + }; + + temperature-TDBP { + apple,key-id = "TDBP"; + label = "SMC TDBP"; + }; + + temperature-TDCR { + apple,key-id = "TDCR"; + label = "SMC TDCR"; + }; + + temperature-TDEC { + apple,key-id = "TDEC"; + label = "SMC TDEC"; + }; + + temperature-TDEL { + apple,key-id = "TDEL"; + label = "SMC TDEL"; + }; + + temperature-TDER { + apple,key-id = "TDER"; + label = "SMC TDER"; + }; + + temperature-TDTP { + apple,key-id = "TDTP"; + label = "SMC TDTP"; + }; + + temperature-TDVx { + apple,key-id = "TDVx"; + label = "SMC TDVx"; + }; + + temperature-TDeL { + apple,key-id = "TDeL"; + label = "SMC TDeL"; + }; + + temperature-TDeR { + apple,key-id = "TDeR"; + label = "SMC TDeR"; + }; + + temperature-TF2S { + apple,key-id = "TF2S"; + label = "SMC TF2S"; + }; + + temperature-TH0a { + apple,key-id = "TH0a"; + label = "SMC TH0a"; + }; + + temperature-TH0b { + apple,key-id = "TH0b"; + label = "SMC TH0b"; + }; + + temperature-TMVR { + apple,key-id = "TMVR"; + label = "SMC TMVR"; + }; + + temperature-TPD0 { + apple,key-id = "TPD0"; + label = "SMC TPD0"; + }; + + temperature-TPD1 { + apple,key-id = "TPD1"; + label = "SMC TPD1"; + }; + + temperature-TPD2 { + apple,key-id = "TPD2"; + label = "SMC TPD2"; + }; + + temperature-TPD3 { + apple,key-id = "TPD3"; + label = "SMC TPD3"; + }; + + temperature-TPD4 { + apple,key-id = "TPD4"; + label = "SMC TPD4"; + }; + + temperature-TPD5 { + apple,key-id = "TPD5"; + label = "SMC TPD5"; + }; + + temperature-TPD6 { + apple,key-id = "TPD6"; + label = "SMC TPD6"; + }; + + temperature-TPD7 { + apple,key-id = "TPD7"; + label = "SMC TPD7"; + }; + + temperature-TPD8 { + apple,key-id = "TPD8"; + label = "SMC TPD8"; + }; + + temperature-TPD9 { + apple,key-id = "TPD9"; + label = "SMC TPD9"; + }; + + temperature-TPDX { + apple,key-id = "TPDX"; + label = "SMC TPDX"; + }; + + temperature-TPDa { + apple,key-id = "TPDa"; + label = "SMC TPDa"; + }; + + temperature-TPDb { + apple,key-id = "TPDb"; + label = "SMC TPDb"; + }; + + temperature-TPDc { + apple,key-id = "TPDc"; + label = "SMC TPDc"; + }; + + temperature-TPDd { + apple,key-id = "TPDd"; + label = "SMC TPDd"; + }; + + temperature-TPDe { + apple,key-id = "TPDe"; + label = "SMC TPDe"; + }; + + temperature-TPDf { + apple,key-id = "TPDf"; + label = "SMC TPDf"; + }; + + temperature-TPH3 { + apple,key-id = "TPH3"; + label = "SMC TPH3"; + }; + + temperature-TPMP { + apple,key-id = "TPMP"; + label = "SMC TPMP"; + }; + + temperature-TPSP { + apple,key-id = "TPSP"; + label = "SMC TPSP"; + }; + + temperature-TRD0 { + apple,key-id = "TRD0"; + label = "SMC TRD0"; + }; + + temperature-TRD1 { + apple,key-id = "TRD1"; + label = "SMC TRD1"; + }; + + temperature-TRD2 { + apple,key-id = "TRD2"; + label = "SMC TRD2"; + }; + + temperature-TRD3 { + apple,key-id = "TRD3"; + label = "SMC TRD3"; + }; + + temperature-TRD4 { + apple,key-id = "TRD4"; + label = "SMC TRD4"; + }; + + temperature-TRD5 { + apple,key-id = "TRD5"; + label = "SMC TRD5"; + }; + + temperature-TRD6 { + apple,key-id = "TRD6"; + label = "SMC TRD6"; + }; + + temperature-TRD7 { + apple,key-id = "TRD7"; + label = "SMC TRD7"; + }; + + temperature-TRD8 { + apple,key-id = "TRD8"; + label = "SMC TRD8"; + }; + + temperature-TRD9 { + apple,key-id = "TRD9"; + label = "SMC TRD9"; + }; + + temperature-TRDX { + apple,key-id = "TRDX"; + label = "SMC TRDX"; + }; + + temperature-TRDa { + apple,key-id = "TRDa"; + label = "SMC TRDa"; + }; + + temperature-TRDb { + apple,key-id = "TRDb"; + label = "SMC TRDb"; + }; + + temperature-TRDc { + apple,key-id = "TRDc"; + label = "SMC TRDc"; + }; + + temperature-TRDd { + apple,key-id = "TRDd"; + label = "SMC TRDd"; + }; + + temperature-TRDe { + apple,key-id = "TRDe"; + label = "SMC TRDe"; + }; + + temperature-TRDf { + apple,key-id = "TRDf"; + label = "SMC TRDf"; + }; + + temperature-TS0P { + apple,key-id = "TS0P"; + label = "SMC TS0P"; + }; + + temperature-TSG1 { + apple,key-id = "TSG1"; + label = "SMC TSG1"; + }; + + temperature-TUD0 { + apple,key-id = "TUD0"; + label = "SMC TUD0"; + }; + + temperature-TUD1 { + apple,key-id = "TUD1"; + label = "SMC TUD1"; + }; + + temperature-TUD2 { + apple,key-id = "TUD2"; + label = "SMC TUD2"; + }; + + temperature-TUD3 { + apple,key-id = "TUD3"; + label = "SMC TUD3"; + }; + + temperature-TUD4 { + apple,key-id = "TUD4"; + label = "SMC TUD4"; + }; + + temperature-TUD5 { + apple,key-id = "TUD5"; + label = "SMC TUD5"; + }; + + temperature-TUD6 { + apple,key-id = "TUD6"; + label = "SMC TUD6"; + }; + + temperature-TUD7 { + apple,key-id = "TUD7"; + label = "SMC TUD7"; + }; + + temperature-TUD8 { + apple,key-id = "TUD8"; + label = "SMC TUD8"; + }; + + temperature-TUD9 { + apple,key-id = "TUD9"; + label = "SMC TUD9"; + }; + + temperature-TUDX { + apple,key-id = "TUDX"; + label = "SMC TUDX"; + }; + + temperature-TUDa { + apple,key-id = "TUDa"; + label = "SMC TUDa"; + }; + + temperature-TUDb { + apple,key-id = "TUDb"; + label = "SMC TUDb"; + }; + + temperature-TUDc { + apple,key-id = "TUDc"; + label = "SMC TUDc"; + }; + + temperature-TUDd { + apple,key-id = "TUDd"; + label = "SMC TUDd"; + }; + + temperature-TUDe { + apple,key-id = "TUDe"; + label = "SMC TUDe"; + }; + + temperature-TUDf { + apple,key-id = "TUDf"; + label = "SMC TUDf"; + }; + + temperature-TVA0 { + apple,key-id = "TVA0"; + label = "SMC TVA0"; + }; + + temperature-TVD0 { + apple,key-id = "TVD0"; + label = "SMC TVD0"; + }; + + temperature-TVMR { + apple,key-id = "TVMR"; + label = "SMC TVMR"; + }; + + temperature-TVMX { + apple,key-id = "TVMX"; + label = "SMC TVMX"; + }; + + temperature-TVMr { + apple,key-id = "TVMr"; + label = "SMC TVMr"; + }; + + temperature-TVS0 { + apple,key-id = "TVS0"; + label = "SMC TVS0"; + }; + + temperature-TVS1 { + apple,key-id = "TVS1"; + label = "SMC TVS1"; + }; + + temperature-TVS2 { + apple,key-id = "TVS2"; + label = "SMC TVS2"; + }; + + temperature-TVV0 { + apple,key-id = "TVV0"; + label = "SMC TVV0"; + }; + + temperature-TVXX { + apple,key-id = "TVXX"; + label = "SMC TVXX"; + }; + + temperature-TVXh { + apple,key-id = "TVXh"; + label = "SMC TVXh"; + }; + + temperature-TVXm { + apple,key-id = "TVXm"; + label = "SMC TVXm"; + }; + + temperature-TVh0 { + apple,key-id = "TVh0"; + label = "SMC TVh0"; + }; + + temperature-TVh1 { + apple,key-id = "TVh1"; + label = "SMC TVh1"; + }; + + temperature-TVm0 { + apple,key-id = "TVm0"; + label = "SMC TVm0"; + }; + + temperature-TVxx { + apple,key-id = "TVxx"; + label = "SMC TVxx"; + }; + + temperature-TaLP { + apple,key-id = "TaLP"; + label = "SMC TaLP"; + }; + + temperature-TaLT { + apple,key-id = "TaLT"; + label = "SMC TaLT"; + }; + + temperature-TaLW { + apple,key-id = "TaLW"; + label = "SMC TaLW"; + }; + + temperature-TaRF { + apple,key-id = "TaRF"; + label = "SMC TaRF"; + }; + + temperature-TaRT { + apple,key-id = "TaRT"; + label = "SMC TaRT"; + }; + + temperature-TaRW { + apple,key-id = "TaRW"; + label = "SMC TaRW"; + }; + + temperature-TaTP { + apple,key-id = "TaTP"; + label = "SMC TaTP"; + }; + + temperature-Te04 { + apple,key-id = "Te04"; + label = "E-cluster Te04"; + }; + + temperature-Te05 { + apple,key-id = "Te05"; + label = "E-cluster Te05"; + }; + + temperature-Te06 { + apple,key-id = "Te06"; + label = "E-cluster Te06"; + }; + + temperature-Te0R { + apple,key-id = "Te0R"; + label = "E-cluster Te0R"; + }; + + temperature-Te0S { + apple,key-id = "Te0S"; + label = "E-cluster Te0S"; + }; + + temperature-Te0T { + apple,key-id = "Te0T"; + label = "E-cluster Te0T"; + }; + + temperature-TfC0 { + apple,key-id = "TfC0"; + label = "SMC TfC0"; + }; + + temperature-TfC1 { + apple,key-id = "TfC1"; + label = "SMC TfC1"; + }; + + temperature-TfC2 { + apple,key-id = "TfC2"; + label = "SMC TfC2"; + }; + + temperature-TfC3 { + apple,key-id = "TfC3"; + label = "SMC TfC3"; + }; + + temperature-TfC4 { + apple,key-id = "TfC4"; + label = "SMC TfC4"; + }; + + temperature-Tg04 { + apple,key-id = "Tg04"; + label = "GPU Tg04"; + }; + + temperature-Tg0K { + apple,key-id = "Tg0K"; + label = "GPU Tg0K"; + }; + + temperature-Tg0L { + apple,key-id = "Tg0L"; + label = "GPU Tg0L"; + }; + + temperature-Tg0R { + apple,key-id = "Tg0R"; + label = "GPU Tg0R"; + }; + + temperature-Tg0X { + apple,key-id = "Tg0X"; + label = "GPU Tg0X"; + }; + + temperature-Tg0d { + apple,key-id = "Tg0d"; + label = "GPU Tg0d"; + }; + + temperature-Tg0e { + apple,key-id = "Tg0e"; + label = "GPU Tg0e"; + }; + + temperature-Tg0j { + apple,key-id = "Tg0j"; + label = "GPU Tg0j"; + }; + + temperature-Tg0y { + apple,key-id = "Tg0y"; + label = "GPU Tg0y"; + }; + + temperature-Tg1E { + apple,key-id = "Tg1E"; + label = "GPU Tg1E"; + }; + + temperature-Tg1F { + apple,key-id = "Tg1F"; + label = "GPU Tg1F"; + }; + + temperature-Tg1U { + apple,key-id = "Tg1U"; + label = "GPU Tg1U"; + }; + + temperature-Tg1c { + apple,key-id = "Tg1c"; + label = "GPU Tg1c"; + }; + + temperature-Tg1d { + apple,key-id = "Tg1d"; + label = "GPU Tg1d"; + }; + + temperature-Tg1k { + apple,key-id = "Tg1k"; + label = "GPU Tg1k"; + }; + + temperature-Tp00 { + apple,key-id = "Tp00"; + label = "P-cluster Tp00"; + }; + + temperature-Tp01 { + apple,key-id = "Tp01"; + label = "P-cluster Tp01"; + }; + + temperature-Tp02 { + apple,key-id = "Tp02"; + label = "P-cluster Tp02"; + }; + + temperature-Tp04 { + apple,key-id = "Tp04"; + label = "P-cluster Tp04"; + }; + + temperature-Tp05 { + apple,key-id = "Tp05"; + label = "P-cluster Tp05"; + }; + + temperature-Tp06 { + apple,key-id = "Tp06"; + label = "P-cluster Tp06"; + }; + + temperature-Tp08 { + apple,key-id = "Tp08"; + label = "P-cluster Tp08"; + }; + + temperature-Tp09 { + apple,key-id = "Tp09"; + label = "P-cluster Tp09"; + }; + + temperature-Tp0A { + apple,key-id = "Tp0A"; + label = "P-cluster Tp0A"; + }; + + temperature-Tp0C { + apple,key-id = "Tp0C"; + label = "P-cluster Tp0C"; + }; + + temperature-Tp0D { + apple,key-id = "Tp0D"; + label = "P-cluster Tp0D"; + }; + + temperature-Tp0E { + apple,key-id = "Tp0E"; + label = "P-cluster Tp0E"; + }; + + temperature-Tp0G { + apple,key-id = "Tp0G"; + label = "P-cluster Tp0G"; + }; + + temperature-Tp0H { + apple,key-id = "Tp0H"; + label = "P-cluster Tp0H"; + }; + + temperature-Tp0I { + apple,key-id = "Tp0I"; + label = "P-cluster Tp0I"; + }; + + temperature-Tp0K { + apple,key-id = "Tp0K"; + label = "P-cluster Tp0K"; + }; + + temperature-Tp0L { + apple,key-id = "Tp0L"; + label = "P-cluster Tp0L"; + }; + + temperature-Tp0M { + apple,key-id = "Tp0M"; + label = "P-cluster Tp0M"; + }; + + temperature-Tp0O { + apple,key-id = "Tp0O"; + label = "P-cluster Tp0O"; + }; + + temperature-Tp0P { + apple,key-id = "Tp0P"; + label = "P-cluster Tp0P"; + }; + + temperature-Tp0Q { + apple,key-id = "Tp0Q"; + label = "P-cluster Tp0Q"; + }; + + temperature-Tp0S { + apple,key-id = "Tp0S"; + label = "P-cluster Tp0S"; + }; + + temperature-Tp0T { + apple,key-id = "Tp0T"; + label = "P-cluster Tp0T"; + }; + + temperature-Tp0U { + apple,key-id = "Tp0U"; + label = "P-cluster Tp0U"; + }; + + temperature-Tp0W { + apple,key-id = "Tp0W"; + label = "P-cluster Tp0W"; + }; + + temperature-Tp0X { + apple,key-id = "Tp0X"; + label = "P-cluster Tp0X"; + }; + + temperature-Tp0Y { + apple,key-id = "Tp0Y"; + label = "P-cluster Tp0Y"; + }; + + temperature-Tp0a { + apple,key-id = "Tp0a"; + label = "P-cluster Tp0a"; + }; + + temperature-Tp0b { + apple,key-id = "Tp0b"; + label = "P-cluster Tp0b"; + }; + + temperature-Tp0c { + apple,key-id = "Tp0c"; + label = "P-cluster Tp0c"; + }; + + temperature-Tp0d { + apple,key-id = "Tp0d"; + label = "P-cluster Tp0d"; + }; + + temperature-Tp0e { + apple,key-id = "Tp0e"; + label = "P-cluster Tp0e"; + }; + + temperature-Tp0f { + apple,key-id = "Tp0f"; + label = "P-cluster Tp0f"; + }; + + temperature-Tp0g { + apple,key-id = "Tp0g"; + label = "P-cluster Tp0g"; + }; + + temperature-Tp0i { + apple,key-id = "Tp0i"; + label = "P-cluster Tp0i"; + }; + + temperature-Tp0k { + apple,key-id = "Tp0k"; + label = "P-cluster Tp0k"; + }; + + temperature-Tp0l { + apple,key-id = "Tp0l"; + label = "P-cluster Tp0l"; + }; + + temperature-Tp0m { + apple,key-id = "Tp0m"; + label = "P-cluster Tp0m"; + }; + + temperature-Tp0n { + apple,key-id = "Tp0n"; + label = "P-cluster Tp0n"; + }; + + temperature-Tp0o { + apple,key-id = "Tp0o"; + label = "P-cluster Tp0o"; + }; + + temperature-Tp0q { + apple,key-id = "Tp0q"; + label = "P-cluster Tp0q"; + }; + + temperature-Tp0t { + apple,key-id = "Tp0t"; + label = "P-cluster Tp0t"; + }; + + temperature-Tp0u { + apple,key-id = "Tp0u"; + label = "P-cluster Tp0u"; + }; + + temperature-Tp0v { + apple,key-id = "Tp0v"; + label = "P-cluster Tp0v"; + }; + + temperature-Tp0w { + apple,key-id = "Tp0w"; + label = "P-cluster Tp0w"; + }; + + temperature-Tp1i { + apple,key-id = "Tp1i"; + label = "P-cluster Tp1i"; + }; + + temperature-Tp1j { + apple,key-id = "Tp1j"; + label = "P-cluster Tp1j"; + }; + + temperature-Tp1k { + apple,key-id = "Tp1k"; + label = "P-cluster Tp1k"; + }; + + temperature-Tp1m { + apple,key-id = "Tp1m"; + label = "P-cluster Tp1m"; + }; + + temperature-Tp1n { + apple,key-id = "Tp1n"; + label = "P-cluster Tp1n"; + }; + + temperature-Tp1o { + apple,key-id = "Tp1o"; + label = "P-cluster Tp1o"; + }; + + temperature-Tp1q { + apple,key-id = "Tp1q"; + label = "P-cluster Tp1q"; + }; + + temperature-Tp1t { + apple,key-id = "Tp1t"; + label = "P-cluster Tp1t"; + }; + + temperature-Tp1u { + apple,key-id = "Tp1u"; + label = "P-cluster Tp1u"; + }; + + temperature-Tp1v { + apple,key-id = "Tp1v"; + label = "P-cluster Tp1v"; + }; + + temperature-Tp1w { + apple,key-id = "Tp1w"; + label = "P-cluster Tp1w"; + }; + + temperature-Tp1x { + apple,key-id = "Tp1x"; + label = "P-cluster Tp1x"; + }; + + temperature-Tp1y { + apple,key-id = "Tp1y"; + label = "P-cluster Tp1y"; + }; + + temperature-Tp1z { + apple,key-id = "Tp1z"; + label = "P-cluster Tp1z"; + }; + + temperature-Tp20 { + apple,key-id = "Tp20"; + label = "P-cluster Tp20"; + }; + + temperature-Tp21 { + apple,key-id = "Tp21"; + label = "P-cluster Tp21"; + }; + + temperature-Tp22 { + apple,key-id = "Tp22"; + label = "P-cluster Tp22"; + }; + + temperature-Tp23 { + apple,key-id = "Tp23"; + label = "P-cluster Tp23"; + }; + + temperature-Tp24 { + apple,key-id = "Tp24"; + label = "P-cluster Tp24"; + }; + + temperature-Tp25 { + apple,key-id = "Tp25"; + label = "P-cluster Tp25"; + }; + + temperature-Tp26 { + apple,key-id = "Tp26"; + label = "P-cluster Tp26"; + }; + + temperature-Tp27 { + apple,key-id = "Tp27"; + label = "P-cluster Tp27"; + }; + + temperature-Tp28 { + apple,key-id = "Tp28"; + label = "P-cluster Tp28"; + }; + + temperature-Tp29 { + apple,key-id = "Tp29"; + label = "P-cluster Tp29"; + }; + + temperature-Tp2A { + apple,key-id = "Tp2A"; + label = "P-cluster Tp2A"; + }; + + temperature-Tp2B { + apple,key-id = "Tp2B"; + label = "P-cluster Tp2B"; + }; + + temperature-Tp2C { + apple,key-id = "Tp2C"; + label = "P-cluster Tp2C"; + }; + + temperature-Tp2D { + apple,key-id = "Tp2D"; + label = "P-cluster Tp2D"; + }; + + temperature-Tp2E { + apple,key-id = "Tp2E"; + label = "P-cluster Tp2E"; + }; + + temperature-Tp2G { + apple,key-id = "Tp2G"; + label = "P-cluster Tp2G"; + }; + + temperature-Tp2I { + apple,key-id = "Tp2I"; + label = "P-cluster Tp2I"; + }; + + temperature-Tp2J { + apple,key-id = "Tp2J"; + label = "P-cluster Tp2J"; + }; + + temperature-Tp2K { + apple,key-id = "Tp2K"; + label = "P-cluster Tp2K"; + }; + + temperature-Tp2L { + apple,key-id = "Tp2L"; + label = "P-cluster Tp2L"; + }; + + temperature-Tp2M { + apple,key-id = "Tp2M"; + label = "P-cluster Tp2M"; + }; + + temperature-Tp2N { + apple,key-id = "Tp2N"; + label = "P-cluster Tp2N"; + }; + + temperature-Tp2O { + apple,key-id = "Tp2O"; + label = "P-cluster Tp2O"; + }; + + temperature-Tp2Q { + apple,key-id = "Tp2Q"; + label = "P-cluster Tp2Q"; + }; + + temperature-Tp2R { + apple,key-id = "Tp2R"; + label = "P-cluster Tp2R"; + }; + + temperature-Tp2S { + apple,key-id = "Tp2S"; + label = "P-cluster Tp2S"; + }; + + temperature-Tp2T { + apple,key-id = "Tp2T"; + label = "P-cluster Tp2T"; + }; + + temperature-Tp2U { + apple,key-id = "Tp2U"; + label = "P-cluster Tp2U"; + }; + + temperature-Tp2V { + apple,key-id = "Tp2V"; + label = "P-cluster Tp2V"; + }; + + temperature-Tp2W { + apple,key-id = "Tp2W"; + label = "P-cluster Tp2W"; + }; + + temperature-Tp2X { + apple,key-id = "Tp2X"; + label = "P-cluster Tp2X"; + }; + + temperature-Ts00 { + apple,key-id = "Ts00"; + label = "SMC Ts00"; + }; + + temperature-Ts01 { + apple,key-id = "Ts01"; + label = "SMC Ts01"; + }; + + temperature-Ts02 { + apple,key-id = "Ts02"; + label = "SMC Ts02"; + }; + + temperature-Ts04 { + apple,key-id = "Ts04"; + label = "SMC Ts04"; + }; + + temperature-Ts05 { + apple,key-id = "Ts05"; + label = "SMC Ts05"; + }; + + temperature-Ts06 { + apple,key-id = "Ts06"; + label = "SMC Ts06"; + }; + + temperature-Ts08 { + apple,key-id = "Ts08"; + label = "SMC Ts08"; + }; + + temperature-Ts09 { + apple,key-id = "Ts09"; + label = "SMC Ts09"; + }; + + temperature-Ts0A { + apple,key-id = "Ts0A"; + label = "SMC Ts0A"; + }; + + temperature-Ts0C { + apple,key-id = "Ts0C"; + label = "SMC Ts0C"; + }; + + temperature-Ts0D { + apple,key-id = "Ts0D"; + label = "SMC Ts0D"; + }; + + temperature-Ts0E { + apple,key-id = "Ts0E"; + label = "SMC Ts0E"; + }; + + temperature-Ts0G { + apple,key-id = "Ts0G"; + label = "SMC Ts0G"; + }; + + temperature-Ts0H { + apple,key-id = "Ts0H"; + label = "SMC Ts0H"; + }; + + temperature-Ts0I { + apple,key-id = "Ts0I"; + label = "SMC Ts0I"; + }; + + temperature-Ts0K { + apple,key-id = "Ts0K"; + label = "SMC Ts0K"; + }; + + temperature-Ts0L { + apple,key-id = "Ts0L"; + label = "SMC Ts0L"; + }; + + temperature-Ts0M { + apple,key-id = "Ts0M"; + label = "SMC Ts0M"; + }; + + temperature-Ts0O { + apple,key-id = "Ts0O"; + label = "SMC Ts0O"; + }; + + temperature-Ts0P { + apple,key-id = "Ts0P"; + label = "SMC Ts0P"; + }; + + temperature-Ts0Q { + apple,key-id = "Ts0Q"; + label = "SMC Ts0Q"; + }; + + temperature-Ts0R { + apple,key-id = "Ts0R"; + label = "SMC Ts0R"; + }; + + temperature-Ts0T { + apple,key-id = "Ts0T"; + label = "SMC Ts0T"; + }; + + temperature-Ts0U { + apple,key-id = "Ts0U"; + label = "SMC Ts0U"; + }; + + temperature-Ts0W { + apple,key-id = "Ts0W"; + label = "SMC Ts0W"; + }; + + temperature-Ts1P { + apple,key-id = "Ts1P"; + label = "SMC Ts1P"; + }; + + temperature-Tsx0 { + apple,key-id = "Tsx0"; + label = "SMC Tsx0"; + }; + + temperature-Tsx1 { + apple,key-id = "Tsx1"; + label = "SMC Tsx1"; + }; + + voltage-VDM2 { + apple,key-id = "VDM2"; + label = "SMC VDM2"; + }; + + voltage-VDMA { + apple,key-id = "VDMA"; + label = "SMC VDMA"; + }; + + voltage-VDMM { + apple,key-id = "VDMM"; + label = "SMC VDMM"; + }; + + voltage-VP0R { + apple,key-id = "VP0R"; + label = "SMC VP0R"; + }; + + voltage-VP0b { + apple,key-id = "VP0b"; + label = "SMC VP0b"; + }; + + voltage-VP1b { + apple,key-id = "VP1b"; + label = "SMC VP1b"; + }; + + voltage-VP1l { + apple,key-id = "VP1l"; + label = "SMC VP1l"; + }; + + voltage-VP2b { + apple,key-id = "VP2b"; + label = "SMC VP2b"; + }; + + voltage-VP3b { + apple,key-id = "VP3b"; + label = "SMC VP3b"; + }; + + voltage-VP4b { + apple,key-id = "VP4b"; + label = "SMC VP4b"; + }; + + voltage-VP5l { + apple,key-id = "VP5l"; + label = "SMC VP5l"; + }; + + voltage-VP7b { + apple,key-id = "VP7b"; + label = "SMC VP7b"; + }; + + voltage-VP7l { + apple,key-id = "VP7l"; + label = "SMC VP7l"; + }; + + voltage-VP9b { + apple,key-id = "VP9b"; + label = "SMC VP9b"; + }; + + voltage-VP9l { + apple,key-id = "VP9l"; + label = "SMC VP9l"; + }; + + voltage-VPal { + apple,key-id = "VPal"; + label = "SMC VPal"; + }; + + voltage-VPbb { + apple,key-id = "VPbb"; + label = "SMC VPbb"; + }; + + voltage-VPdb { + apple,key-id = "VPdb"; + label = "SMC VPdb"; + }; + + voltage-VPeb { + apple,key-id = "VPeb"; + label = "SMC VPeb"; + }; + + voltage-VR0b { + apple,key-id = "VR0b"; + label = "SMC VR0b"; + }; + + voltage-VR1b { + apple,key-id = "VR1b"; + label = "SMC VR1b"; + }; + + voltage-VR2b { + apple,key-id = "VR2b"; + label = "SMC VR2b"; + }; + + voltage-VR3b { + apple,key-id = "VR3b"; + label = "SMC VR3b"; + }; + + voltage-VR3l { + apple,key-id = "VR3l"; + label = "SMC VR3l"; + }; + + voltage-VR4b { + apple,key-id = "VR4b"; + label = "SMC VR4b"; + }; + + voltage-VR7b { + apple,key-id = "VR7b"; + label = "SMC VR7b"; + }; + + voltage-VR8l { + apple,key-id = "VR8l"; + label = "SMC VR8l"; + }; + + voltage-VR9b { + apple,key-id = "VR9b"; + label = "SMC VR9b"; + }; + + voltage-VR9l { + apple,key-id = "VR9l"; + label = "SMC VR9l"; + }; + + voltage-VRal { + apple,key-id = "VRal"; + label = "SMC VRal"; + }; + + voltage-VRbb { + apple,key-id = "VRbb"; + label = "SMC VRbb"; + }; + + voltage-VRdb { + apple,key-id = "VRdb"; + label = "SMC VRdb"; + }; + + voltage-VReb { + apple,key-id = "VReb"; + label = "SMC VReb"; + }; + + voltage-VS0b { + apple,key-id = "VS0b"; + label = "SMC VS0b"; + }; + + voltage-VS1b { + apple,key-id = "VS1b"; + label = "SMC VS1b"; + }; + + voltage-VS2b { + apple,key-id = "VS2b"; + label = "SMC VS2b"; + }; + + voltage-VS3b { + apple,key-id = "VS3b"; + label = "SMC VS3b"; + }; + + voltage-VS4b { + apple,key-id = "VS4b"; + label = "SMC VS4b"; + }; + + voltage-VS7b { + apple,key-id = "VS7b"; + label = "SMC VS7b"; + }; + + voltage-VS9b { + apple,key-id = "VS9b"; + label = "SMC VS9b"; + }; + + voltage-VS9l { + apple,key-id = "VS9l"; + label = "SMC VS9l"; + }; + + voltage-VSal { + apple,key-id = "VSal"; + label = "SMC VSal"; + }; + + voltage-VSbb { + apple,key-id = "VSbb"; + label = "SMC VSbb"; + }; + + voltage-VSeb { + apple,key-id = "VSeb"; + label = "SMC VSeb"; + }; + + voltage-Vb0f { + apple,key-id = "Vb0f"; + label = "SMC Vb0f"; + }; + + voltage-Vb1f { + apple,key-id = "Vb1f"; + label = "SMC Vb1f"; + }; + + voltage-SBA1 { + apple,key-id = "SBA1"; + label = "Battery Cell 1"; + }; + + voltage-SBA2 { + apple,key-id = "SBA2"; + label = "Battery Cell 2"; + }; + + voltage-SBA3 { + apple,key-id = "SBA3"; + label = "Battery Cell 3"; + }; + + current-I3F2 { + apple,key-id = "I3F2"; + label = "SMC I3F2"; + }; + + current-I5SR { + apple,key-id = "I5SR"; + label = "SMC I5SR"; + }; + + current-IALR { + apple,key-id = "IALR"; + label = "SMC IALR"; + }; + + current-IARR { + apple,key-id = "IARR"; + label = "SMC IARR"; + }; + + current-ICMC { + apple,key-id = "ICMC"; + label = "SMC ICMC"; + }; + + current-ID3C { + apple,key-id = "ID3C"; + label = "SMC ID3C"; + }; + + current-IDBC { + apple,key-id = "IDBC"; + label = "SMC IDBC"; + }; + + current-IDBR { + apple,key-id = "IDBR"; + label = "SMC IDBR"; + }; + + current-IFLR { + apple,key-id = "IFLR"; + label = "SMC IFLR"; + }; + + current-IH0R { + apple,key-id = "IH0R"; + label = "SMC IH0R"; + }; + + current-IHCR { + apple,key-id = "IHCR"; + label = "SMC IHCR"; + }; + + current-IIDR { + apple,key-id = "IIDR"; + label = "SMC IIDR"; + }; + + current-IINC { + apple,key-id = "IINC"; + label = "SMC IINC"; + }; + + current-IMVC { + apple,key-id = "IMVC"; + label = "SMC IMVC"; + }; + + current-IMVR { + apple,key-id = "IMVR"; + label = "SMC IMVR"; + }; + + current-IP0b { + apple,key-id = "IP0b"; + label = "SMC IP0b"; + }; + + current-IP1b { + apple,key-id = "IP1b"; + label = "SMC IP1b"; + }; + + current-IP1l { + apple,key-id = "IP1l"; + label = "SMC IP1l"; + }; + + current-IP2b { + apple,key-id = "IP2b"; + label = "SMC IP2b"; + }; + + current-IP3b { + apple,key-id = "IP3b"; + label = "SMC IP3b"; + }; + + current-IP4b { + apple,key-id = "IP4b"; + label = "SMC IP4b"; + }; + + current-IP5l { + apple,key-id = "IP5l"; + label = "SMC IP5l"; + }; + + current-IP7b { + apple,key-id = "IP7b"; + label = "SMC IP7b"; + }; + + current-IP7l { + apple,key-id = "IP7l"; + label = "SMC IP7l"; + }; + + current-IP9b { + apple,key-id = "IP9b"; + label = "SMC IP9b"; + }; + + current-IP9l { + apple,key-id = "IP9l"; + label = "SMC IP9l"; + }; + + current-IPBR { + apple,key-id = "IPBR"; + label = "SMC IPBR"; + }; + + current-IPMC { + apple,key-id = "IPMC"; + label = "SMC IPMC"; + }; + + current-IPSC { + apple,key-id = "IPSC"; + label = "SMC IPSC"; + }; + + current-IPal { + apple,key-id = "IPal"; + label = "SMC IPal"; + }; + + current-IPbb { + apple,key-id = "IPbb"; + label = "SMC IPbb"; + }; + + current-IPdb { + apple,key-id = "IPdb"; + label = "SMC IPdb"; + }; + + current-IPeb { + apple,key-id = "IPeb"; + label = "SMC IPeb"; + }; + + current-IR0b { + apple,key-id = "IR0b"; + label = "SMC IR0b"; + }; + + current-IR1b { + apple,key-id = "IR1b"; + label = "SMC IR1b"; + }; + + current-IR2b { + apple,key-id = "IR2b"; + label = "SMC IR2b"; + }; + + current-IR3b { + apple,key-id = "IR3b"; + label = "SMC IR3b"; + }; + + current-IR3l { + apple,key-id = "IR3l"; + label = "SMC IR3l"; + }; + + current-IR4b { + apple,key-id = "IR4b"; + label = "SMC IR4b"; + }; + + current-IR7b { + apple,key-id = "IR7b"; + label = "SMC IR7b"; + }; + + current-IR8l { + apple,key-id = "IR8l"; + label = "SMC IR8l"; + }; + + current-IR9b { + apple,key-id = "IR9b"; + label = "SMC IR9b"; + }; + + current-IR9l { + apple,key-id = "IR9l"; + label = "SMC IR9l"; + }; + + current-IRal { + apple,key-id = "IRal"; + label = "SMC IRal"; + }; + + current-IRbb { + apple,key-id = "IRbb"; + label = "SMC IRbb"; + }; + + current-IRdb { + apple,key-id = "IRdb"; + label = "SMC IRdb"; + }; + + current-IReb { + apple,key-id = "IReb"; + label = "SMC IReb"; + }; + + current-IS0b { + apple,key-id = "IS0b"; + label = "SMC IS0b"; + }; + + current-IS1b { + apple,key-id = "IS1b"; + label = "SMC IS1b"; + }; + + current-IS2b { + apple,key-id = "IS2b"; + label = "SMC IS2b"; + }; + + current-IS3b { + apple,key-id = "IS3b"; + label = "SMC IS3b"; + }; + + current-IS4b { + apple,key-id = "IS4b"; + label = "SMC IS4b"; + }; + + current-IS7b { + apple,key-id = "IS7b"; + label = "SMC IS7b"; + }; + + current-IS9b { + apple,key-id = "IS9b"; + label = "SMC IS9b"; + }; + + current-IS9l { + apple,key-id = "IS9l"; + label = "SMC IS9l"; + }; + + current-ISDR { + apple,key-id = "ISDR"; + label = "SMC ISDR"; + }; + + current-ISal { + apple,key-id = "ISal"; + label = "SMC ISal"; + }; + + current-ISbb { + apple,key-id = "ISbb"; + label = "SMC ISbb"; + }; + + current-ISeb { + apple,key-id = "ISeb"; + label = "SMC ISeb"; + }; + + current-IU1C { + apple,key-id = "IU1C"; + label = "SMC IU1C"; + }; + + current-IU1R { + apple,key-id = "IU1R"; + label = "SMC IU1R"; + }; + + current-IU2C { + apple,key-id = "IU2C"; + label = "SMC IU2C"; + }; + + current-IU2R { + apple,key-id = "IU2R"; + label = "SMC IU2R"; + }; + + current-IW3C { + apple,key-id = "IW3C"; + label = "SMC IW3C"; + }; + + current-Ib0f { + apple,key-id = "Ib0f"; + label = "SMC Ib0f"; + }; + + current-Ib8f { + apple,key-id = "Ib8f"; + label = "SMC Ib8f"; + }; + + current-SBAC { + apple,key-id = "SBAC"; + label = "Battery Current"; + }; + + power-P3F2 { + apple,key-id = "P3F2"; + label = "SMC P3F2"; + }; + + power-P5SR { + apple,key-id = "P5SR"; + label = "SMC P5SR"; + }; + + power-PALR { + apple,key-id = "PALR"; + label = "SMC PALR"; + }; + + power-PARR { + apple,key-id = "PARR"; + label = "SMC PARR"; + }; + + power-PCMC { + apple,key-id = "PCMC"; + label = "SMC PCMC"; + }; + + power-PD3C { + apple,key-id = "PD3C"; + label = "SMC PD3C"; + }; + + power-PDBC { + apple,key-id = "PDBC"; + label = "SMC PDBC"; + }; + + power-PDBR { + apple,key-id = "PDBR"; + label = "SMC PDBR"; + }; + + power-PFLR { + apple,key-id = "PFLR"; + label = "SMC PFLR"; + }; + + power-PH0R { + apple,key-id = "PH0R"; + label = "SMC PH0R"; + }; + + power-PHCR { + apple,key-id = "PHCR"; + label = "SMC PHCR"; + }; + + power-PIDR { + apple,key-id = "PIDR"; + label = "SMC PIDR"; + }; + + power-PINC { + apple,key-id = "PINC"; + label = "SMC PINC"; + }; + + power-PMVC { + apple,key-id = "PMVC"; + label = "SMC PMVC"; + }; + + power-PP0b { + apple,key-id = "PP0b"; + label = "SMC PP0b"; + }; + + power-PP1b { + apple,key-id = "PP1b"; + label = "SMC PP1b"; + }; + + power-PP1l { + apple,key-id = "PP1l"; + label = "SMC PP1l"; + }; + + power-PP2b { + apple,key-id = "PP2b"; + label = "SMC PP2b"; + }; + + power-PP3b { + apple,key-id = "PP3b"; + label = "SMC PP3b"; + }; + + power-PP4b { + apple,key-id = "PP4b"; + label = "SMC PP4b"; + }; + + power-PP5l { + apple,key-id = "PP5l"; + label = "SMC PP5l"; + }; + + power-PP7b { + apple,key-id = "PP7b"; + label = "SMC PP7b"; + }; + + power-PP7l { + apple,key-id = "PP7l"; + label = "SMC PP7l"; + }; + + power-PP9b { + apple,key-id = "PP9b"; + label = "SMC PP9b"; + }; + + power-PP9l { + apple,key-id = "PP9l"; + label = "SMC PP9l"; + }; + + power-PPBR { + apple,key-id = "PPBR"; + label = "SMC PPBR"; + }; + + power-PPMC { + apple,key-id = "PPMC"; + label = "SMC PPMC"; + }; + + power-PPSC { + apple,key-id = "PPSC"; + label = "SMC PPSC"; + }; + + power-PPal { + apple,key-id = "PPal"; + label = "SMC PPal"; + }; + + power-PPbb { + apple,key-id = "PPbb"; + label = "SMC PPbb"; + }; + + power-PPdb { + apple,key-id = "PPdb"; + label = "SMC PPdb"; + }; + + power-PPeb { + apple,key-id = "PPeb"; + label = "SMC PPeb"; + }; + + power-PR0b { + apple,key-id = "PR0b"; + label = "SMC PR0b"; + }; + + power-PR1b { + apple,key-id = "PR1b"; + label = "SMC PR1b"; + }; + + power-PR2b { + apple,key-id = "PR2b"; + label = "SMC PR2b"; + }; + + power-PR3b { + apple,key-id = "PR3b"; + label = "SMC PR3b"; + }; + + power-PR3l { + apple,key-id = "PR3l"; + label = "SMC PR3l"; + }; + + power-PR4b { + apple,key-id = "PR4b"; + label = "SMC PR4b"; + }; + + power-PR7b { + apple,key-id = "PR7b"; + label = "SMC PR7b"; + }; + + power-PR8l { + apple,key-id = "PR8l"; + label = "SMC PR8l"; + }; + + power-PR9b { + apple,key-id = "PR9b"; + label = "SMC PR9b"; + }; + + power-PR9l { + apple,key-id = "PR9l"; + label = "SMC PR9l"; + }; + + power-PRal { + apple,key-id = "PRal"; + label = "SMC PRal"; + }; + + power-PRbb { + apple,key-id = "PRbb"; + label = "SMC PRbb"; + }; + + power-PRdb { + apple,key-id = "PRdb"; + label = "SMC PRdb"; + }; + + power-PReb { + apple,key-id = "PReb"; + label = "SMC PReb"; + }; + + power-PS0b { + apple,key-id = "PS0b"; + label = "SMC PS0b"; + }; + + power-PS1b { + apple,key-id = "PS1b"; + label = "SMC PS1b"; + }; + + power-PS2b { + apple,key-id = "PS2b"; + label = "SMC PS2b"; + }; + + power-PS3b { + apple,key-id = "PS3b"; + label = "SMC PS3b"; + }; + + power-PS4b { + apple,key-id = "PS4b"; + label = "SMC PS4b"; + }; + + power-PS7b { + apple,key-id = "PS7b"; + label = "SMC PS7b"; + }; + + power-PS9b { + apple,key-id = "PS9b"; + label = "SMC PS9b"; + }; + + power-PS9l { + apple,key-id = "PS9l"; + label = "SMC PS9l"; + }; + + power-PSDR { + apple,key-id = "PSDR"; + label = "SMC PSDR"; + }; + + power-PSal { + apple,key-id = "PSal"; + label = "SMC PSal"; + }; + + power-PSbb { + apple,key-id = "PSbb"; + label = "SMC PSbb"; + }; + + power-PSeb { + apple,key-id = "PSeb"; + label = "SMC PSeb"; + }; + + power-PTHS { + apple,key-id = "PTHS"; + label = "SMC PTHS"; + }; + + power-PU1C { + apple,key-id = "PU1C"; + label = "SMC PU1C"; + }; + + power-PU1R { + apple,key-id = "PU1R"; + label = "SMC PU1R"; + }; + + power-PU2C { + apple,key-id = "PU2C"; + label = "SMC PU2C"; + }; + + power-PU2R { + apple,key-id = "PU2R"; + label = "SMC PU2R"; + }; + + power-PW3C { + apple,key-id = "PW3C"; + label = "SMC PW3C"; + }; + + power-PZC0 { + apple,key-id = "PZC0"; + label = "SMC PZC0"; + }; + + power-PZC1 { + apple,key-id = "PZC1"; + label = "SMC PZC1"; + }; + + power-PZCB { + apple,key-id = "PZCB"; + label = "SMC PZCB"; + }; + + power-PZCU { + apple,key-id = "PZCU"; + label = "SMC PZCU"; + }; + + power-PZD1 { + apple,key-id = "PZD1"; + label = "SMC PZD1"; + }; + + power-PZT0 { + apple,key-id = "PZT0"; + label = "SMC PZT0"; + }; + + power-Pb0f { + apple,key-id = "Pb0f"; + label = "SMC Pb0f"; + }; + + power-SBAP { + apple,key-id = "SBAP"; + label = "Battery Power"; + }; +}; + +/* Fan monitoring and explicit userspace manual control. */ +#include "hwmon-common.dtsi" +#include "hwmon-fan-dual.dtsi" +#include "hwmon-laptop.dtsi" + +&smc_hwmon { + apple,thermal-pressure-key = "mTPL"; + + /* + * The SMC accepts a manual speed for both fans once its fan test + * key unlocks them, and returns them to system mode when the + * request is dropped. + */ + fan-F0Ac { + apple,fan-manual-control; + }; + + fan-F1Ac { + apple,fan-manual-control; + }; +}; + +&pcie_dart { + status = "okay"; +}; + +/* + * Wi-Fi and Bluetooth (BCM4388). The boot loader finds these nodes by + * the paths in the wifi0 and bluetooth0 aliases and adds the per-unit + * calibration, the antenna SKU and the addresses to them. + */ +/ { + pcie0: pcie@1cb0000000 { + compatible = "apple,t6041-pcie", "apple,t6020-pcie"; + reg = <0x1c 0xb0000000 0x0 0x1000000>, /* config */ + <0x4 0x14000000 0x0 0x4000>, /* rc */ + <0x4 0x10028000 0x0 0x4000>, /* port0 */ + <0x4 0x11028000 0x0 0x4000>, /* port1 */ + <0x4 0x12028000 0x0 0x4000>, /* port2 */ + <0x4 0x13028000 0x0 0x4000>, /* port3 */ + <0x4 0x17020000 0x0 0x4000>, /* phy0 */ + <0x4 0x17024000 0x0 0x4000>, /* phy1 */ + <0x4 0x17028000 0x0 0x4000>, /* phy2 */ + <0x4 0x1702c000 0x0 0x4000>; /* phy3 */ + 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 { + 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"; + + bluetooth0: bluetooth@0,1 { + compatible = "pci14e4,5f72"; + reg = <0x100 0 0 0 0>; + /* To be filled by the loader */ + local-bd-address = [00 00 00 00 00 00]; + status = "okay"; + }; + + wifi0: wifi@0,0 { + compatible = "pci14e4,4434", "brcm,bcm4329-fmac"; + reg = <0 0 0 0 0>; + brcm,ccode-map-trivial; + }; + }; + }; +}; + +&ans_mbox { + status = "okay"; +}; + +&ans_sart { + status = "okay"; +}; + +&nvme { + status = "okay"; +}; + +&pmp_dart { + status = "okay"; +}; + +&pmp_report { + status = "okay"; +}; + +&pmp { + status = "okay"; +}; + +&pmp_mbox { + status = "okay"; +}; + +&dcp { + panel: panel { + status = "disabled"; + }; +}; + +&pmc { + status = "okay"; +}; + +&mcc { + status = "okay"; +}; + +&aop { + status = "okay"; +}; + +&aop_mbox { + status = "okay"; +}; + +&aop_dart { + status = "okay"; +}; + +/* The sensor is on the logic board, in the base. */ +&aop_accel { + label = "accel-base"; +}; + +&admac0 { + status = "okay"; +}; + +&admac1 { + status = "okay"; +}; + +&aop_audio { + apple,machine-kind = "MacBook Pro"; +}; + +/* + * The six SN012776 speaker amps, held in hardware shutdown until a sound + * card enables them (ADT /arm-io/i2c1/audio-speaker@38): one interrupt line + * on AP pin 55, level low; sense slots from speaker-config (speaker i at RX + * bytes 4i and 4i + 2, order LW1 RW1 LW2 RW2 LT RT). Names as on the J314 + * and J316, which speakersafetyd's profile uses. Every amp joins the SDZ + * fail-closed group: an over-temperature or over-current fault on any one + * forces the shared shutdown line low. + */ +&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>; + }; +}; + +/* + * The CS42L84 headphone codec (ADT /arm-io/i2c2/audio-codec-output@4B). Its + * reset line is nub GPIO pin 58, driven high to run the codec (the driver's + * "reset" is an enable, as on the J514/J516); its interrupt is AP pin 106, + * level low. The AOP firmware runs the jack's stream on MCA cluster 2. + */ +&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"; + }; +}; + +&isp { + memory-region = <&isp_fw_text>, <&isp_fw_data>, <&isp_heap>; + memory-region-names = "text", "data", "heap"; + apple,platform-id = <5>; + /* ADT isp0 cam-connections-scheme */ + apple,cam-connections-scheme = <0x10>; + status = "okay"; + + /* + * The front camera, an IMX958: firmware configuration 5 as the + * firmware reports it. + */ + sensor-presets { + /* 1920x1080 */ + preset0 { + apple,config-index = <5>; + apple,input-size = <1920 2160>; + apple,output-size = <1920 1080>; + apple,crop = <0 0 1920 1080>; + }; + /* 1280x720 */ + preset1 { + apple,config-index = <5>; + apple,input-size = <1920 2160>; + apple,output-size = <1280 720>; + apple,crop = <0 0 1280 720>; + }; + }; +}; + +&isp_dart0 { + status = "okay"; +}; + +&isp_dart1 { + status = "okay"; +}; + +&isp_dart2 { + status = "okay"; +}; + +/* + * The loaded GPU firmware keeps running across system sleep. Like the Neo's + * GFX domain, these domains must not be switched off while that image lives. + * The PMP report vote is still owned by the GPU consumer. + */ +&ps_afr { + apple,always-on; +}; + +&ps_gfx { + apple,always-on; +}; + +/* The loader fills the operating points, calibration and all six memory regions. */ +&gfx_mbox { + status = "okay"; +}; + +&gpu { + memory-region = <&uat_ttbs>, <&uat_pagetables>, <&uat_handoff>, + <&gpu_fw_data>, <&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>; + /* Avoid a core power cycle between interactive submissions, then release. */ + apple,idle-off-delay-ms = <16>; + status = "okay"; +}; + +/* + * The Type-C ports (ADT nub-spmi-a0 hpm0/hpm1, nub-spmi-a1 hpm2) and the + * MagSafe controller (nub-spmi-a0 hpm5). The ADT lists the event, sleep and + * wake interrupts; select is event + 2. + */ +&nub_spmi_a0 { + status = "okay"; + + hpm0: 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"; + + typec0: connector { + compatible = "usb-c-connector"; + label = "USB-C Left Back"; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + typec0_con_hs: endpoint { + remote-endpoint = <&usb_drd0_hs>; + }; + }; + + port@1 { + reg = <1>; + typec0_con_ss: endpoint { + remote-endpoint = <&atcphy0_ss>; + }; + }; + }; + }; + }; + + 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>; + }; + }; + + port@1 { + reg = <1>; + typec1_con_ss: endpoint { + remote-endpoint = <&atcphy1_ss>; + }; + }; + }; + }; + }; + + /* MagSafe port */ + hpm5: usb-pd@8 { + compatible = "apple,sn201202x"; + reg = <0x8 SPMI_USID>; + interrupts = <63 IRQ_TYPE_EDGE_RISING>, + <65 IRQ_TYPE_EDGE_RISING>, + <69 IRQ_TYPE_EDGE_RISING>, + <71 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "irq", "select", "sleep", "wake"; + }; +}; + +&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>; + }; + }; + + port@1 { + reg = <1>; + typec2_con_ss: endpoint { + remote-endpoint = <&atcphy2_ss>; + }; + }; + }; + }; + }; +}; + +&atcphy0 { + status = "okay"; + + port { + atcphy0_ss: endpoint { + remote-endpoint = <&typec0_con_ss>; + }; + }; +}; + +&atcphy0_mbox { + status = "okay"; +}; + +&usb_drd0_dart_0 { + status = "okay"; +}; + +&usb_drd0_dart_1 { + status = "okay"; +}; + +&usb_drd0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usb_drd0_hs: endpoint { + remote-endpoint = <&typec0_con_hs>; + }; + }; + }; +}; + +&atcphy1 { + status = "okay"; + + port { + atcphy1_ss: endpoint { + remote-endpoint = <&typec1_con_ss>; + }; + }; +}; + +&atcphy1_mbox { + status = "okay"; +}; + +&usb_drd1_dart_0 { + status = "okay"; +}; + +&usb_drd1_dart_1 { + status = "okay"; +}; + +&usb_drd1 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usb_drd1_hs: endpoint { + remote-endpoint = <&typec1_con_hs>; + }; + }; + }; +}; + +&atcphy2 { + status = "okay"; + + port { + atcphy2_ss: endpoint { + remote-endpoint = <&typec2_con_ss>; + }; + }; +}; + +&atcphy2_mbox { + status = "okay"; +}; + +&usb_drd2_dart_0 { + status = "okay"; +}; + +&usb_drd2_dart_1 { + status = "okay"; +}; + +&usb_drd2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usb_drd2_hs: endpoint { + remote-endpoint = <&typec2_con_hs>; + }; + }; + }; +}; + +/* The video encoder, its DARTs and its power domains. */ +&ps_venc0_sys { + status = "okay"; +}; + +&ps_venc0_dma { + status = "okay"; +}; + +&ps_venc0_pipe4 { + status = "okay"; +}; + +&ps_venc0_pipe5 { + status = "okay"; +}; + +&ps_venc0_me0 { + status = "okay"; +}; + +&ps_venc0_me1 { + status = "okay"; +}; + +&ave0_dart0 { + status = "okay"; +}; + +&ave0_dart1 { + status = "okay"; +}; + +&ave { + status = "okay"; +}; + +#include "t6040-j616s-usb3.dtsi" + +/* External display chain, all disabled: the gate in drivers/soc/apple/display-gate.c enables it. */ +#include "t6040-j616s-extdisp.dtsi" +#include "t6040-j616s-extdisp-mem-loader.dtsi" +#include "t6040-j616s-extdisp-hdmi.dtsi" +#include "t6040-j616s-extdisp-usbc.dtsi" +#include "t6040-j616s-dpaudio.dtsi" +/* Additional Abbey PMICs on the two independent NUB SPMI buses. */ +&nub_spmi1 { + status = "okay"; + + pmic@e { + compatible = "apple,abbey-pmic", "apple,spmi-nvmem"; + reg = <0xe SPMI_USID>; + }; +}; + +&nub_spmi2 { + status = "okay"; + + pmic@e { + compatible = "apple,abbey-pmic", "apple,spmi-nvmem"; + reg = <0xe SPMI_USID>; + }; +}; + +&ps_nub_spmi_ahb { + status = "okay"; +}; + +&ps_nub_spmi1 { + status = "okay"; +}; + +&ps_nub_spmi2 { + status = "okay"; +}; + +&pinctrl { + sd_clkreq_pins: sd-clkreq-pins { + pinmux = ; + }; +}; + +&pcie0 { + interrupts = , + ; + /* Widen bus-range only with the SD power/port ownership handoff. */ + iommu-map = <0x100 &pcie_dart 1 2>, <0x200 &apcie1_dart 1 1>; + + port01: pci@1,0 { + device_type = "pci"; + reg = <0x800 0 0 0 0>; + reset-gpios = <&pinctrl 5 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&sd_clkreq_pins>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &port01 0 0 0 0>, + <0 0 0 2 &port01 0 0 0 1>, + <0 0 0 3 &port01 0 0 0 2>, + <0 0 0 4 &port01 0 0 0 3>; + /* The SD power switch needs an SMC service binding. */ + status = "disabled"; + }; +}; + +/* + * The SMC owns automatic fan policy. Drop the host fan trip/map instances + * after the board's thermal descriptions, retaining all passive and critical + * protection. Keep this final policy separate from ladder descriptions so + * independent ladder updates cannot restore autonomous SMC writes. + */ + +#define J616S_DELETE_FAN_TRIPS \ + /delete-node/ trip-fan1; \ + /delete-node/ trip-fan2; \ + /delete-node/ trip-fan3; \ + /delete-node/ trip-fan4; \ + /delete-node/ trip-fan5; + +/* Some CPU ladders also map full fan speed to the passive trip. */ +#define J616S_DELETE_FAN_MAPS \ + /delete-node/ map-fan1; \ + /delete-node/ map-fan2; \ + /delete-node/ map-fan3; \ + /delete-node/ map-fan4; \ + /delete-node/ map-fan5; \ + /delete-node/ map-fan6; + +/ { + thermal-zones { + cpu-die-thermal { + trips { + J616S_DELETE_FAN_TRIPS + }; + + cooling-maps { + J616S_DELETE_FAN_MAPS + }; + }; + + gpu0-thermal { + trips { + J616S_DELETE_FAN_TRIPS + }; + + cooling-maps { + J616S_DELETE_FAN_MAPS + }; + }; + + gpu1-thermal { + trips { + J616S_DELETE_FAN_TRIPS + }; + + cooling-maps { + J616S_DELETE_FAN_MAPS + }; + }; + + gpu2-thermal { + trips { + J616S_DELETE_FAN_TRIPS + }; + + cooling-maps { + J616S_DELETE_FAN_MAPS + }; + }; + + gpu3-thermal { + trips { + J616S_DELETE_FAN_TRIPS + }; + + cooling-maps { + J616S_DELETE_FAN_MAPS + }; + }; + + gpu4-thermal { + trips { + J616S_DELETE_FAN_TRIPS + }; + + cooling-maps { + J616S_DELETE_FAN_MAPS + }; + }; + + gpu5-thermal { + trips { + J616S_DELETE_FAN_TRIPS + }; + + cooling-maps { + J616S_DELETE_FAN_MAPS + }; + }; + + gpu6-thermal { + trips { + J616S_DELETE_FAN_TRIPS + }; + + cooling-maps { + J616S_DELETE_FAN_MAPS + }; + }; + }; +}; + +#undef J616S_DELETE_FAN_TRIPS +#undef J616S_DELETE_FAN_MAPS + +/* + * Proven on the J616s (MobileNetV1 top-1 16/16). The ANE stays idle until + * the loader fills and enables the two preload reservations above. + */ +&ane0_dart0 { + status = "okay"; +}; + +&ane0_dart1 { + status = "okay"; +}; + +&ane0_dart2 { + status = "okay"; +}; + +&ane { + memory-region = <&ane_fw_text>, <&ane_fw_data>; + memory-region-names = "firmware-text", "firmware-data"; + /* + * The SoC rail floor, held only while ANE requests are in flight: + * MobileNet engine time 0.87 -> 0.54 ms on an idle system. + */ + power-domains = <&ps_ane_sys>, <&ps_ane_cpu>, <&ps_ane_mpm>, + <&ps_ane_td>, <&ps_ane_base>, <&pmc_soc_max>; + power-domain-names = "sys", "cpu", "mpm", "td", "base", "perf"; + status = "okay"; +}; diff --git a/drivers/accel/ane/ane_fw_cold.c b/drivers/accel/ane/ane_fw_cold.c index 6781ff1202711..acfc4cc5aac8c 100644 --- a/drivers/accel/ane/ane_fw_cold.c +++ b/drivers/accel/ane/ane_fw_cold.c @@ -1026,6 +1026,10 @@ static void ane_fw_write32(void *ctx, u32 reg, u32 value) struct ane_fw_backend *b = ctx; ane_wr32(b, value, b->engine + reg); + if (reg == b->soc->irq_ack) { + /* Complete the snapshot acknowledgment before coherent ring reads. */ + mb(); + } } static u64 ane_fw_now(void *ctx) diff --git a/drivers/accel/ane/ane_fw_transport.h b/drivers/accel/ane/ane_fw_transport.h index 99279b5d74bec..53c44178f528b 100644 --- a/drivers/accel/ane/ane_fw_transport.h +++ b/drivers/accel/ane/ane_fw_transport.h @@ -80,6 +80,7 @@ struct ane_fw_transport_ops { void (*read_barrier)(void *ctx); void (*write_barrier)(void *ctx); u32 (*read32)(void *ctx, u32 reg); + /* Complete/order an irq_ack write before subsequent coherent ring reads. */ void (*write32)(void *ctx, u32 reg, u32 value); u64 (*now_ns)(void *ctx); /* Wait before the next poll of a wait that began waited_ns ago. */ @@ -118,6 +119,10 @@ struct ane_fw_transport { struct ane_fw_channel channels[ANE_FW_CHANNELS]; struct ane_fw_transaction pending[ANE_FW_CHANNELS]; u32 head[ANE_FW_CHANNELS]; + /* SHAREDMALLOC entries captured after acknowledging their notification. */ + u32 shared_ready; + /* Polls that saw a request body before its notification (held, not served). */ + u32 shared_early; u8 table[ANE_FW_TABLE_SIZE]; size_t table_offset; size_t pool_used; @@ -266,6 +271,8 @@ static inline void *ane_fw_transport_slot(struct ane_fw_transport *t, unsigned i static inline void ane_fw_transport_advance(struct ane_fw_transport *t, unsigned int ch) { t->head[ch] = (t->head[ch] + 1) % t->channels[ch].slots; + if (ch == ANE_FW_SHAREDMALLOC) + t->shared_ready--; } static inline void ane_fw_transport_doorbell(struct ane_fw_transport *t, unsigned int ch) @@ -655,12 +662,15 @@ ane_fw_shared_reusable(const struct ane_fw_transport *t, size_t size, u64 tag) return t->shared_count; } +static inline int ane_fw_transport_irq(struct ane_fw_transport *t, u32 *pending); + static inline int ane_fw_transport_shared(struct ane_fw_transport *t) { struct ane_fw_surface s = {}; u64 word0, word1, word2; size_t size; unsigned int i; + u32 pending; u8 *p; int ret = ane_fw_transport_check(t); @@ -668,6 +678,20 @@ static inline int ane_fw_transport_shared(struct ane_fw_transport *t) return ret; if (!t->armed) return -EINVAL; + if (!t->shared_ready) { + ret = ane_fw_transport_irq(t, &pending); + if (ret) + return ret; + if (!t->shared_ready) { + p = ane_fw_transport_slot(t, ANE_FW_SHAREDMALLOC); + t->ops->read_barrier(t->ctx); + word0 = t->ops->load64(t->ctx, p); + if (!(word0 & 1) && (word0 || t->ops->load64(t->ctx, p + 8) || + t->ops->load64(t->ctx, p + 16))) + t->shared_early++; + return -EAGAIN; + } + } p = ane_fw_transport_slot(t, ANE_FW_SHAREDMALLOC); word0 = t->ops->load64(t->ctx, p); t->ops->read_barrier(t->ctx); @@ -753,6 +777,35 @@ static inline int ane_fw_transport_irq(struct ane_fw_transport *t, u32 *pending) *pending = value; if (value) t->ops->write32(t->ctx, t->soc->irq_ack, value); + if (t->armed && (value & BIT(t->channels[ANE_FW_SHAREDMALLOC].bit))) { + const struct ane_fw_channel *c = &t->channels[ANE_FW_SHAREDMALLOC]; + u32 n; + + /* + * An allocation's header is zero, including on a never-used slot. + * Its body can be visible before firmware posts the notification; + * answering then races the producer's publication/wakeup sequence. + * Capture the notified batch BEFORE replying to any entry. Draining + * until empty after a reply could pick up the next unnotified request. + * One pending bit may cover several already queued entries. + */ + t->ops->read_barrier(t->ctx); + for (n = 0; n < c->slots; n++) { + u32 slot = (t->head[ANE_FW_SHAREDMALLOC] + n) % c->slots; + u8 *p = (u8 *)t->ipc.cpu + c->offset + slot * ANE_FW_SLOT_SIZE; + u64 word0 = t->ops->load64(t->ctx, p); + u64 word1, word2; + + if (word0 & 1) + break; + t->ops->read_barrier(t->ctx); + word1 = t->ops->load64(t->ctx, p + 8); + word2 = t->ops->load64(t->ctx, p + 16); + if (!word0 && !word1 && !word2) + break; + } + t->shared_ready = n; + } return 0; } diff --git a/drivers/accel/ane/ane_fw_transport_test.c b/drivers/accel/ane/ane_fw_transport_test.c index 710845960b5d1..f1a69baa86630 100644 --- a/drivers/accel/ane/ane_fw_transport_test.c +++ b/drivers/accel/ane/ane_fw_transport_test.c @@ -41,6 +41,7 @@ struct ane_transport_test { int refused_error; int alloc_error; int alloc_bad; + bool post_next_unnotified; }; static void ane_test_access(struct ane_transport_test *f, char kind, const void *p, u64 value) @@ -92,6 +93,8 @@ static void ane_test_write32(void *ctx, u32 reg, u32 value) f->last_reg = reg; f->last_value = value; ane_test_access(f, 'o', NULL, value); + if (reg == f->soc.irq_ack) + f->irq &= ~value; } static u64 ane_test_now(void *ctx) @@ -113,6 +116,17 @@ static int ane_test_alloc(void *ctx, size_t size, u32 tag, struct ane_fw_surface f->allocs++; f->now += f->alloc_time; + if (f->post_next_unnotified) { + const struct ane_fw_channel *c = &f->t.channels[ANE_FW_SHAREDMALLOC]; + u32 next = (f->t.head[ANE_FW_SHAREDMALLOC] + 1) % c->slots; + u8 *p = (u8 *)f->ipc.cpu + c->offset + next * ANE_FW_SLOT_SIZE; + + /* Arrives after the batch snapshot, before the first reply. */ + put_unaligned_le64(0, p); + put_unaligned_le64(SZ_16K, p + 8); + put_unaligned_le64(0x5678, p + 16); + f->post_next_unnotified = false; + } if (f->alloc_error) return f->alloc_error; *s = (struct ane_fw_surface) { @@ -255,6 +269,7 @@ static void ane_test_shared_request(struct ane_transport_test *f, u64 w0, u64 w1 put_unaligned_le64(w0, p); put_unaligned_le64(w1, p + 8); put_unaligned_le64(w2, p + 16); + f->irq |= BIT(f->t.channels[ANE_FW_SHAREDMALLOC].bit); } static unsigned int ane_test_writes(struct ane_transport_test *f) @@ -722,6 +737,89 @@ static void ane_transport_shared_test(struct kunit *test) KUNIT_EXPECT_EQ(test, f->t.shared_count, 2U); } +/* The body of a fresh zero-header request is not its publication boundary. */ +static void ane_transport_shared_notification_test(struct kunit *test) +{ + struct ane_transport_test *f = test->priv; + u32 bit = BIT(f->t.channels[ANE_FW_SHAREDMALLOC].bit); + u8 *slot; + + KUNIT_ASSERT_EQ(test, ane_fw_transport_arm(&f->t), 0); + ane_test_shared_request(f, 0, SZ_16K, 0x1234); + slot = ane_test_slot(f, ANE_FW_SHAREDMALLOC); + /* Firmware filled the slot but has not published its notification yet. */ + f->irq = 0; + f->count = 0; + KUNIT_EXPECT_EQ(test, ane_fw_transport_shared(&f->t), -EAGAIN); + KUNIT_EXPECT_EQ(test, ane_test_writes(f), 0U); + KUNIT_EXPECT_EQ(test, f->allocs, 0U); + KUNIT_EXPECT_EQ(test, get_unaligned_le64(slot), 0ULL); + /* An unrelated channel notification cannot authorize an answer either. */ + f->irq = BIT(4); + KUNIT_EXPECT_EQ(test, ane_fw_transport_shared(&f->t), -EAGAIN); + KUNIT_EXPECT_EQ(test, f->allocs, 0U); + f->irq = bit; + f->count = 0; + f->post_next_unnotified = true; + KUNIT_ASSERT_EQ(test, ane_fw_transport_shared(&f->t), 0); + KUNIT_EXPECT_EQ(test, f->allocs, 1U); + KUNIT_EXPECT_EQ(test, f->irq, 0U); + KUNIT_EXPECT_EQ(test, f->t.shared_ready, 0U); + /* A later request cannot borrow the first request's notification. */ + KUNIT_EXPECT_EQ(test, ane_fw_transport_shared(&f->t), -EAGAIN); + KUNIT_EXPECT_EQ(test, f->allocs, 1U); + KUNIT_EXPECT_EQ(test, f->t.head[ANE_FW_SHAREDMALLOC], 1U); + f->irq = bit; + KUNIT_ASSERT_EQ(test, ane_fw_transport_shared(&f->t), 0); + KUNIT_EXPECT_EQ(test, f->allocs, 2U); + KUNIT_EXPECT_EQ(test, f->t.head[ANE_FW_SHAREDMALLOC], 0U); +} + +/* One bit can announce a batch, including a batch that wraps the ring. */ +static void ane_transport_shared_batch_test(struct kunit *test) +{ + struct ane_transport_test *f = test->priv; + u8 *desc = (u8 *)f->ipc.cpu + ANE_FW_SHAREDMALLOC * ANE_FW_DESCRIPTOR_SIZE; + u32 pending, i, ack = 0, first_read = 0; + u8 *slot; + + /* The descriptor, rather than logical channel 5, selects the IRQ bit. */ + put_unaligned_le32(3, desc + 0x44); + KUNIT_ASSERT_EQ(test, ane_test_init_transport(f), 0); + KUNIT_ASSERT_EQ(test, ane_fw_transport_arm(&f->t), 0); + f->t.head[ANE_FW_SHAREDMALLOC] = 1; + for (i = 0; i < 2; i++) { + slot = (u8 *)f->ipc.cpu + f->t.channels[ANE_FW_SHAREDMALLOC].offset + + i * ANE_FW_SLOT_SIZE; + put_unaligned_le64(SZ_16K, slot + 8); + put_unaligned_le64(0x1234 + i, slot + 16); + } + slot = ane_test_slot(f, ANE_FW_SHAREDMALLOC); + f->irq = BIT(3); + f->count = 0; + KUNIT_ASSERT_EQ(test, ane_fw_transport_irq(&f->t, &pending), 0); + KUNIT_EXPECT_EQ(test, pending, (u32)BIT(3)); + KUNIT_EXPECT_EQ(test, f->t.shared_ready, 2U); + /* Exact IRQ acknowledgment and a DMA read barrier precede slot reads. */ + for (i = 0; i < f->count; i++) { + if (f->access[i].kind == 'o') + ack = i; + if (f->access[i].kind == 'r' && f->access[i].p == slot) + first_read = i; + } + KUNIT_EXPECT_LT(test, ack, first_read); + KUNIT_EXPECT_EQ(test, f->access[ack].value, (u64)BIT(3)); + KUNIT_EXPECT_EQ(test, f->access[ack + 1].kind, 'R'); + KUNIT_ASSERT_EQ(test, ane_fw_transport_shared(&f->t), 0); + KUNIT_EXPECT_EQ(test, f->t.head[ANE_FW_SHAREDMALLOC], 0U); + KUNIT_EXPECT_EQ(test, f->t.shared_ready, 1U); + KUNIT_ASSERT_EQ(test, ane_fw_transport_shared(&f->t), 0); + KUNIT_EXPECT_EQ(test, f->t.head[ANE_FW_SHAREDMALLOC], 1U); + KUNIT_EXPECT_EQ(test, f->t.shared_ready, 0U); + KUNIT_EXPECT_EQ(test, f->allocs, 2U); + KUNIT_EXPECT_EQ(test, ane_fw_transport_shared(&f->t), -EAGAIN); +} + static void ane_transport_shared_rejections_test(struct kunit *test) { static const u64 tuples[][3] = { @@ -751,7 +849,9 @@ static void ane_transport_shared_rejections_test(struct kunit *test) KUNIT_EXPECT_MEMEQ(test, f->refused, tuples[i], sizeof(f->refused)); KUNIT_EXPECT_EQ(test, f->refused_error, error); KUNIT_EXPECT_EQ(test, f->allocs, 0U); - KUNIT_EXPECT_EQ(test, ane_test_writes(f), 0U); + /* The notification is acknowledged; no ring reply is written. */ + KUNIT_EXPECT_EQ(test, ane_test_writes(f), 1U); + KUNIT_EXPECT_EQ(test, f->last_reg, f->soc.irq_ack); } } @@ -769,7 +869,9 @@ static void ane_transport_allocator_rejections_test(struct kunit *test) KUNIT_EXPECT_EQ_MSG(test, ane_fw_transport_shared(&f->t), -EPROTO, "allocator result %u", i); KUNIT_EXPECT_EQ(test, f->t.shared_count, 0U); - KUNIT_EXPECT_EQ(test, ane_test_writes(f), 0U); + /* The notification is acknowledged; no ring reply is written. */ + KUNIT_EXPECT_EQ(test, ane_test_writes(f), 1U); + KUNIT_EXPECT_EQ(test, f->last_reg, f->soc.irq_ack); } KUNIT_ASSERT_EQ(test, ane_test_init_transport(f), 0); KUNIT_ASSERT_EQ(test, ane_fw_transport_arm(&f->t), 0); @@ -970,7 +1072,9 @@ static void ane_transport_free_test(struct kunit *test) ane_test_shared_request(f, dva, 0, 0); f->count = 0; KUNIT_EXPECT_EQ(test, ane_fw_transport_shared(&f->t), -ENOENT); - KUNIT_EXPECT_EQ(test, ane_test_writes(f), 0U); + /* The notification is acknowledged; no ring reply is written. */ + KUNIT_EXPECT_EQ(test, ane_test_writes(f), 1U); + KUNIT_EXPECT_EQ(test, f->last_reg, f->soc.irq_ack); } /* @@ -1235,7 +1339,9 @@ static void ane_transport_free_refusal_test(struct kunit *test) f->count = 0; KUNIT_EXPECT_EQ(test, ane_fw_transport_shared(&f->t), -EOPNOTSUPP); KUNIT_EXPECT_FALSE(test, f->t.shared_retired[0]); - KUNIT_EXPECT_EQ(test, ane_test_writes(f), 0U); + /* The notification is acknowledged; no ring reply is written. */ + KUNIT_EXPECT_EQ(test, ane_test_writes(f), 1U); + KUNIT_EXPECT_EQ(test, f->last_reg, f->soc.irq_ack); } /* Publish one EXECUTE on the data channel; return its flags word as copied. */ @@ -1403,6 +1509,8 @@ static struct kunit_case ane_transport_cases[] = { KUNIT_CASE(ane_transport_report_word2_test), KUNIT_CASE(ane_transport_presence_test), KUNIT_CASE(ane_transport_shared_test), + KUNIT_CASE(ane_transport_shared_notification_test), + KUNIT_CASE(ane_transport_shared_batch_test), KUNIT_CASE(ane_transport_shared_rejections_test), KUNIT_CASE(ane_transport_allocator_rejections_test), KUNIT_CASE(ane_transport_shared_overlap_test), diff --git a/drivers/accel/ane/ane_h16_boot.h b/drivers/accel/ane/ane_h16_boot.h index 373d07b70885f..d8c9c8e6eb102 100644 --- a/drivers/accel/ane/ane_h16_boot.h +++ b/drivers/accel/ane/ane_h16_boot.h @@ -568,6 +568,40 @@ static inline int ane_h16_scratch_boot(struct ane_h16_boot *b) return ret; } +/* Read-only evidence: never acknowledge an IRQ or change a cursor on timeout. */ +static inline void ane_h16_startup_timeout(struct ane_h16_boot *b) +{ + struct ane_fw_transport *t = &b->transport; + const struct ane_fw_channel *c = &t->channels[ANE_FW_SHAREDMALLOC]; + unsigned int i; + u8 *p; + + b->ops->log(b->ctx, "startup timeout IRQ/polls", + t->ops->read32(t->ctx, t->soc->irq_status), t->polls); + b->ops->log(b->ctx, "startup SHAREDMALLOC head/slots", + t->head[ANE_FW_SHAREDMALLOC], c->slots); + b->ops->log(b->ctx, "startup SHAREDMALLOC ready/allocations", + t->shared_ready, t->shared_count); + /* Geometry was validated before startup; include slots behind the cursor. */ + for (i = 0; i < c->slots; i++) { + p = (u8 *)t->ipc.cpu + c->offset + i * ANE_FW_SLOT_SIZE; + t->ops->read_barrier(t->ctx); + b->ops->log(b->ctx, "startup SHAREDMALLOC slot/word0", i, + t->ops->load64(t->ctx, p)); + b->ops->log(b->ctx, "startup SHAREDMALLOC word1/word2", + t->ops->load64(t->ctx, p + 8), + t->ops->load64(t->ctx, p + 16)); + } + p = ane_fw_transport_slot(t, ANE_FW_IO); + t->ops->read_barrier(t->ctx); + b->ops->log(b->ctx, "startup IO head/word0", t->head[ANE_FW_IO], + t->ops->load64(t->ctx, p)); + b->ops->log(b->ctx, "startup IO word1/word2", t->ops->load64(t->ctx, p + 8), + t->ops->load64(t->ctx, p + 16)); + for (i = 0; i < 8; i++) + b->ops->log(b->ctx, "startup timeout scratch", i, ane_h16_read(b, i)); +} + static inline int ane_h16_startup(struct ane_h16_boot *b) { const struct ane_h16_build *f = b->build; @@ -588,6 +622,8 @@ static inline int ane_h16_startup(struct ane_h16_boot *b) reply = (u8 *)b->pool.cpu + (b->transport.pending[ANE_FW_IO].dva - b->pool.dva); if (ret) { + if (ret == -ETIMEDOUT) + ane_h16_startup_timeout(b); if (ret == -EREMOTEIO) b->ops->log(b->ctx, "startup refusal ID/ack", f->startup[i].id, get_unaligned_le16(reply + 6)); @@ -618,6 +654,9 @@ static inline int ane_h16_startup(struct ane_h16_boot *b) b->pmu_base_set = true; } } + /* How often a request body was seen before its notification and held. */ + b->ops->log(b->ctx, "startup SHAREDMALLOC allocations/early polls held", + b->transport.shared_count, b->transport.shared_early); return 0; } diff --git a/drivers/accel/ane/ane_h16_boot_test.c b/drivers/accel/ane/ane_h16_boot_test.c index 32172b41f44da..581bd4b41eee6 100644 --- a/drivers/accel/ane/ane_h16_boot_test.c +++ b/drivers/accel/ane/ane_h16_boot_test.c @@ -11,6 +11,7 @@ struct ane_h16_sim { struct ane_h16_mmio mmio; struct ane_fw_platform soc; u32 scratch[8]; + u32 irq; u32 dapf[SZ_16K / 4]; u32 dart_params; u32 dapf_reads; @@ -28,6 +29,10 @@ struct ane_h16_sim { u32 pins; u32 quarantines; u32 allocations; + u32 timeout_slots; + u32 timeout_bodies; + u32 timeout_scratch; + u64 timeout_head; u32 lock; u32 fault; u32 channel_request; @@ -45,6 +50,7 @@ struct ane_h16_sim { bool wrong_table; bool stale_table; bool no_clear; + bool no_startup_reply; bool shared_pending; bool shared_replied; bool ce_timeout; @@ -108,7 +114,7 @@ static u32 sim_read32(void *ctx, enum ane_h16_window w, u32 off) if (off >= s->soc.scratch && off < s->soc.scratch + 32) return s->scratch[(off - s->soc.scratch) / 4]; if (off == s->soc.irq_status) - return 0; + return s->irq; } return 0xa5a5a5a5; } @@ -167,6 +173,10 @@ static void sim_write32(void *ctx, enum ane_h16_window w, u32 off, u32 value) return; } KUNIT_EXPECT_TRUE(s->test, w == ANE_H16_ENGINE || w == ANE_H16_XL); + if (w == ANE_H16_ENGINE && off == s->soc.irq_ack) { + s->irq &= ~value; + return; + } if (w == ANE_H16_ENGINE && off == f->cpu_control) { s->cpu = value; if (value == f->run && s->fault_after_run) @@ -213,6 +223,8 @@ static void sim_write32(void *ctx, enum ane_h16_window w, u32 off, u32 value) if (s->command_count < 4) KUNIT_EXPECT_EQ(s->test, tx->id, f->startup[s->command_count].id); s->command_count++; + if (s->no_startup_reply) + return; if (tx->id == 3 && s->lifecycle_mode) { u8 *slot = ane_fw_transport_slot(t, ANE_FW_SHAREDMALLOC); u64 dva = s->lifecycle_mode == 2 ? 0 : s->build.shared_dva; @@ -224,6 +236,7 @@ static void sim_write32(void *ctx, enum ane_h16_window w, u32 off, u32 value) put_unaligned_le64(0, slot + 8); put_unaligned_le64(s->lifecycle_mode == 2 ? 1 : 0, slot + 16); s->lifecycle_requested = true; + s->irq |= BIT(5); } else if (!tx->id) { u8 *slot = ane_fw_transport_slot(t, ANE_FW_SHAREDMALLOC); @@ -231,6 +244,7 @@ static void sim_write32(void *ctx, enum ane_h16_window w, u32 off, u32 value) put_unaligned_le64(SZ_16K, slot + 8); put_unaligned_le64(0, slot + 16); s->shared_pending = true; + s->irq |= BIT(5); } else { sim_reply(s); } @@ -362,6 +376,16 @@ static void sim_mailbox(void *ctx) static void sim_log(void *ctx, const char *item, u64 a, u64 b) { + struct ane_h16_sim *s = ctx; + + if (!strcmp(item, "startup SHAREDMALLOC head/slots")) + s->timeout_head = a; + if (!strcmp(item, "startup SHAREDMALLOC slot/word0")) + s->timeout_slots++; + if (!strcmp(item, "startup SHAREDMALLOC word1/word2")) + s->timeout_bodies++; + if (!strcmp(item, "startup timeout scratch")) + s->timeout_scratch++; } static void sim_quarantine(void *ctx, int error) @@ -696,6 +720,37 @@ static void ane_h16_scratch3_timeout_test(struct kunit *test) KUNIT_EXPECT_EQ(test, s->command_count, 0U); } +/* A timeout snapshots the ring without answering, moving it or trying again. */ +static void ane_h16_startup_timeout_test(struct kunit *test) +{ + struct ane_h16_sim *s = test->priv; + struct ane_fw_transport *t = &s->boot.transport; + u8 before[ANE_FW_SLOT_SIZE]; + u8 *slot; + + KUNIT_ASSERT_EQ(test, ane_h16_run(&s->boot, ANE_H16_BOOT), 0); + slot = ane_fw_transport_slot(t, ANE_FW_SHAREDMALLOC); + /* An earlier reply still belongs to firmware; the host must leave it. */ + put_unaligned_le64(s->build.shared_dva | 1, slot); + put_unaligned_le64(0, slot + 8); + put_unaligned_le64(1, slot + 16); + memcpy(before, slot, sizeof(before)); + s->no_startup_reply = true; + s->build.command_timeout_ns = 2000000; + KUNIT_EXPECT_EQ(test, ane_h16_run(&s->boot, ANE_H16_STARTUP), -ETIMEDOUT); + KUNIT_EXPECT_TRUE(test, s->boot.quarantined); + KUNIT_EXPECT_EQ(test, s->command_count, 1U); + KUNIT_EXPECT_TRUE(test, t->pending[ANE_FW_IO].active); + KUNIT_EXPECT_EQ(test, t->head[ANE_FW_SHAREDMALLOC], 0U); + KUNIT_EXPECT_EQ(test, s->timeout_head, 0ULL); + KUNIT_EXPECT_EQ(test, s->timeout_slots, t->channels[ANE_FW_SHAREDMALLOC].slots); + KUNIT_EXPECT_EQ(test, s->timeout_bodies, s->timeout_slots); + KUNIT_EXPECT_EQ(test, s->timeout_scratch, 8U); + KUNIT_EXPECT_MEMEQ(test, before, slot, sizeof(before)); + KUNIT_EXPECT_EQ(test, ane_h16_run(&s->boot, ANE_H16_STARTUP), -EBUSY); + KUNIT_EXPECT_EQ(test, s->command_count, 1U); +} + /* Stages advance one write at a time, each at most once, in one firmware session. */ static void ane_h16_incremental_test(struct kunit *test) { @@ -931,6 +986,7 @@ static struct kunit_case ane_h16_boot_cases[] = { KUNIT_CASE(ane_h16_ce_timeout_test), KUNIT_CASE(ane_h16_zero_tick_test), KUNIT_CASE(ane_h16_scratch3_timeout_test), + KUNIT_CASE(ane_h16_startup_timeout_test), {} }; diff --git a/drivers/gpu/drm/apple/afk.c b/drivers/gpu/drm/apple/afk.c index 688b2d2f5c622..77a7d06fe45b7 100644 --- a/drivers/gpu/drm/apple/afk.c +++ b/drivers/gpu/drm/apple/afk.c @@ -728,33 +728,40 @@ afk_compact_slot(struct apple_dcp_afkep *ep, const struct apple_epic_service_ops *ops, const char *name, s64 unit) { + u32 gen = READ_ONCE(ep->dcp->afk_power_gen); struct apple_epic_service *service; unsigned long flags; - bool free; + bool hotplug, free; u32 i; /* - * The DPDEV, DPAVSERV and AV services are announced again under a - * fresh interface after every external hotplug, without a teardown - * for the previous one: replace the same logical service in place. - * Other endpoints (DPAVCTRL) announce several services with the same - * name and no unit, so the name is no key there. + * The firmware announces every compact service again under a fresh + * interface after a DCP poweron, on every endpoint, without closing + * the previous one. The DPDEV, DPAVSERV and AV endpoints (0x27-0x29) + * also do so after an external hotplug without a poweron. Replace an + * enabled service with the same binding, name and unit in place when + * it comes from an earlier poweron, or from any announcement on the + * hotplug endpoints. Services announced since the latest poweron stay: + * DPAVCTRL announces several services with the same name and no unit + * in one generation, and those are siblings, not replacements. */ - if (ep->endpoint >= 0x27 && ep->endpoint <= 0x29) { - for (i = 0; i < ep->num_channels; i++) { - service = &ep->services[i]; - if (service->enabled && service->ops == ops && - service->unit == unit && !strcmp(service->name, name)) { - dev_info(ep->dcp->dev, - "AFK[ep:%02x]: replacing compact service %s interface %u\n", - ep->endpoint, name, service->channel); - afk_remove_service_debugfs(service); - afk_service_retire(service); - if (service->ops->teardown) - service->ops->teardown(service); - return service; - } - } + hotplug = ep->endpoint >= 0x27 && ep->endpoint <= 0x29; + for (i = 0; i < ep->num_channels; i++) { + service = &ep->services[i]; + if (!service->enabled || service->ops != ops || + service->unit != unit || strcmp(service->name, name)) + continue; + if (!hotplug && service->power_gen == gen) + continue; + dev_info(ep->dcp->dev, + "AFK[ep:%02x]: replacing compact service %s interface %u\n", + ep->endpoint, name, service->channel); + afk_remove_service_debugfs(service); + afk_service_retire(service); + if (service->ops->teardown) + service->ops->teardown(service); + service->power_gen = gen; + return service; } for (i = 0; i < ep->num_channels; i++) { @@ -763,13 +770,17 @@ afk_compact_slot(struct apple_dcp_afkep *ep, free = !service->enabled && !service->users && bitmap_empty(service->cmd_map, MAX_PENDING_CMDS); spin_unlock_irqrestore(&service->lock, flags); - if (free) + if (free) { + service->power_gen = gen; return service; + } } if (ep->num_channels >= AFK_MAX_CHANNEL) return NULL; - return &ep->services[ep->num_channels++]; + service = &ep->services[ep->num_channels++]; + service->power_gen = gen; + return service; } static void afk_recv_handle_compact_init(struct apple_dcp_afkep *ep, diff --git a/drivers/gpu/drm/apple/afk.h b/drivers/gpu/drm/apple/afk.h index 291ee12402292..a4f2afb38588f 100644 --- a/drivers/gpu/drm/apple/afk.h +++ b/drivers/gpu/drm/apple/afk.h @@ -76,6 +76,8 @@ struct apple_epic_service { /* Compact EPIC (desktop 26.x): the announced identity and OPEN state. */ char name[33]; s64 unit; + /* DCP poweron generation that announced this compact service. */ + u32 power_gen; bool defer_start; bool started; diff --git a/drivers/gpu/drm/apple/dcp-internal.h b/drivers/gpu/drm/apple/dcp-internal.h index f01925807d804..65daae9a3f5dc 100644 --- a/drivers/gpu/drm/apple/dcp-internal.h +++ b/drivers/gpu/drm/apple/dcp-internal.h @@ -414,6 +414,8 @@ struct apple_dcp { /* firmware version and compatible firmware version */ enum dcp_firmware_version fw_compat; + /* Bumped by every iomfb poweron; see afk_compact_slot(). */ + u32 afk_power_gen; bool external; /* * T8122 dcpext: the panel's DRM device never waits on this processor. diff --git a/drivers/gpu/drm/apple/iomfb_template.c b/drivers/gpu/drm/apple/iomfb_template.c index ba283faf6c1a3..2d7268f84e290 100644 --- a/drivers/gpu/drm/apple/iomfb_template.c +++ b/drivers/gpu/drm/apple/iomfb_template.c @@ -2200,6 +2200,8 @@ void DCP_FW_NAME(iomfb_poweron)(struct apple_dcp *dcp) u32 handle; #endif dev_info(dcp->dev, "dcp_poweron() starting\n"); + /* The firmware announces its compact services again after poweron. */ + WRITE_ONCE(dcp->afk_power_gen, dcp->afk_power_gen + 1); #if DCP_FW_H17(DCP_FW_VER) if (dcp->hw.iomfb_method_profile != DCP_IOMFB_METHODS_H17G) diff --git a/drivers/gpu/drm/asahi/g17/completion.rs b/drivers/gpu/drm/asahi/g17/completion.rs index 7d887f17d22c6..90f6d77780bff 100644 --- a/drivers/gpu/drm/asahi/g17/completion.rs +++ b/drivers/gpu/drm/asahi/g17/completion.rs @@ -694,7 +694,9 @@ impl Completion { return; } self.status.record_if_device_loss(error); - if self.accepted.load(Ordering::Acquire) { + // As in complete(): a cancellation is not this client's device loss. A guilty VM + // already carries its own sticky error. + if self.accepted.load(Ordering::Acquire) && error != ECANCELED { self.status.report_failure(error); } self.release_healthy(); @@ -713,7 +715,9 @@ impl Completion { guard.quarantine(); } if self.spared() { - self.status.report_failure(error); + if error != ECANCELED || self.interrupted() { + self.status.report_failure(error); + } } else { self.report(error); } diff --git a/drivers/gpu/drm/asahi/g17/completion/publication.rs b/drivers/gpu/drm/asahi/g17/completion/publication.rs index a1e05a9408552..8e16a14f05488 100644 --- a/drivers/gpu/drm/asahi/g17/completion/publication.rs +++ b/drivers/gpu/drm/asahi/g17/completion/publication.rs @@ -8,7 +8,7 @@ //! nor waits for another command; the last prerequisite publishes a ready result. use super::Output; -use crate::g17::{dependency::inherited_error, status::VmStatus}; +use crate::g17::{dependency::PRODUCER_FAILED, status::VmStatus}; use kernel::{new_mutex, prelude::*, sync::{Arc, Mutex}}; type Links = Option>; @@ -96,7 +96,9 @@ impl Publication { if let Err(error) = result { // Inherited failure is visible to the client without inventing a // permanent admission failure in this command's VM. - self.status.report_failure(error); + if error != ECANCELED { + self.status.report_failure(error); + } } self.output.publish(result); let result = result.map(|_| ()); @@ -119,10 +121,8 @@ impl Publication { let ready = { let mut state = self.state.lock(); debug_assert!(state.remaining != 0); - if let Err(error) = result { - if state.predecessor_error.is_none() { - state.predecessor_error = Some(inherited_error(error)); - } + if result.is_err() && state.predecessor_error.is_none() { + state.predecessor_error = Some(PRODUCER_FAILED); } state.remaining -= 1; state.claim() diff --git a/drivers/gpu/drm/asahi/g17/dependency.rs b/drivers/gpu/drm/asahi/g17/dependency.rs index 387ce9ba2fb3c..5a0ed611b1dde 100644 --- a/drivers/gpu/drm/asahi/g17/dependency.rs +++ b/drivers/gpu/drm/asahi/g17/dependency.rs @@ -9,6 +9,7 @@ use super::{ use kernel::prelude::*; /// A failed producer does not establish a fault in its consumer's VM. +#[cfg(CONFIG_DRM_ASAHI_G15)] pub(crate) fn inherited_error(error: Error) -> Error { if error == EIO || error == ENODEV || error == ETIMEDOUT { ECANCELED @@ -17,11 +18,16 @@ pub(crate) fn inherited_error(error: Error) -> Error { } } +/// What a G17 consumer of a failed producer fails with, whatever the producer failed with: its +/// client does not see a cancellation as a lost device. A producer a recovery dropped fails with +/// ENODATA, and passing that on made every consumer of the producer's buffers lose its device too. +pub(crate) const PRODUCER_FAILED: Error = ECANCELED; + /// A replay's original host inputs must still be signalled. Treat an unmet /// input as a failed replay, never as a wait under the device mutex. pub(crate) fn replay_status(status: i32) -> Result { if status == 0 { Err(EBUSY) } - else if status < 0 { Err(inherited_error(Error::from_errno(status))) } + else if status < 0 { Err(PRODUCER_FAILED) } else { Ok(()) } } @@ -195,4 +201,15 @@ mod tests { record.note(5, 1, &Probe::new(true)); assert_eq!(earliest(&mut record), None); } + + #[test] + fn failed_predecessor_cannot_be_bypassed() { + let mut frontier = Frontier::new(); + for error in [ECANCELED, EIO, ETIMEDOUT] { + assert_eq!(frontier.include(Some(5), 5, error.to_errno(), 0), Err(ECANCELED)); + } + assert_eq!(frontier.include(Some(5), 5, 1, 0), Ok(())); + assert_eq!(frontier.include(Some(5), 6, EIO.to_errno(), 0), Ok(())); + assert_eq!(frontier.count, 0); + } } diff --git a/drivers/gpu/drm/asahi/g17/fence.rs b/drivers/gpu/drm/asahi/g17/fence.rs index 71107371640bd..0b8819bdbd396 100644 --- a/drivers/gpu/drm/asahi/g17/fence.rs +++ b/drivers/gpu/drm/asahi/g17/fence.rs @@ -180,7 +180,7 @@ impl Submission { self.remaining.load(Ordering::Acquire) == 0 || self.retired.load(Ordering::Acquire); let error = self.error.load(Ordering::Acquire); if error != 0 { - return Err(super::dependency::inherited_error(Error::from_errno(error))); + return Err(super::dependency::PRODUCER_FAILED); } Ok(complete) } diff --git a/drivers/gpu/drm/asahi/g17/job.rs b/drivers/gpu/drm/asahi/g17/job.rs index 711dd59b0ecc2..7e43c163ac4a7 100644 --- a/drivers/gpu/drm/asahi/g17/job.rs +++ b/drivers/gpu/drm/asahi/g17/job.rs @@ -177,8 +177,9 @@ impl Packet { kernel::time::msecs_to_jiffies(10) as isize, ) }; + // An interrupted wait is not a producer failure. if waited < 0 { - return Err(super::dependency::inherited_error(Error::from_errno(waited as i32))); + return Err(Error::from_errno(waited as i32)); } if waited > 0 { break; } } @@ -257,7 +258,7 @@ pub(crate) fn fence_status(fence: &Fence) -> i32 { fn check_status(fence: &Fence) -> Result { let status = fence_status(fence); if status < 0 { - Err(super::dependency::inherited_error(Error::from_errno(status))) + Err(super::dependency::PRODUCER_FAILED) } else { Ok(()) } diff --git a/drivers/gpu/drm/asahi/g17/preparation.rs b/drivers/gpu/drm/asahi/g17/preparation.rs index 2aa3213115076..c7d1761699a24 100644 --- a/drivers/gpu/drm/asahi/g17/preparation.rs +++ b/drivers/gpu/drm/asahi/g17/preparation.rs @@ -6,6 +6,7 @@ //! the device mutex, then drops that mutex before waiting for builders. A builder's lease is //! stored after its tentative mappings so those mappings are destroyed before the join completes. +use core::cell::Cell; use core::sync::atomic::{AtomicU64, Ordering}; use kernel::{ new_condvar, new_mutex, @@ -24,25 +25,37 @@ const EPOCH: u64 = CLOSED << 3; /// packet cancellation, logical close, VM status and device loss even when no /// capacity/recovery event arrives. Wakes and nested constructors never renew it. pub(super) struct Admission<'a> { - deadline: u64, + deadline: Cell, + started: u64, check: &'a dyn Fn() -> Result, } impl<'a> Admission<'a> { pub(super) fn new(deadline: u64, check: &'a dyn Fn() -> Result) -> Self { - Self { deadline, check } + Self { deadline: Cell::new(deadline), started: super::now_ns(), check } + } + + /// A recovery is pending or this owner's spared work drains: wait as long as the + /// watchdog may take to settle it (RECOVERY_WAIT_MS from the start) instead of failing. + pub(super) fn extend_for_recovery(&self) { + let limit = self + .started + .saturating_add(u64::from(super::timeout::RECOVERY_WAIT_MS) * 1_000_000); + if self.deadline.get() < limit { + self.deadline.set(limit); + } } pub(super) fn check(&self) -> Result { (self.check)()?; - if super::now_ns() >= self.deadline { return Err(EBUSY); } + if super::now_ns() >= self.deadline.get() { return Err(EBUSY); } Ok(()) } /// Ignore condvar remaining-time reports: only the monotonic deadline counts. pub(super) fn slice_ms(&self) -> Result { self.check()?; - let remaining = self.deadline.saturating_sub(super::now_ns()); + let remaining = self.deadline.get().saturating_sub(super::now_ns()); if remaining == 0 { return Err(EBUSY); } Ok(remaining.div_ceil(1_000_000).min(10) as u32) } @@ -137,19 +150,20 @@ impl Gate { } } - /// Packet admission may wait for recovery only within its original budget. + /// Only a recovery closes the gate: packet admission waits for it up to + /// RECOVERY_WAIT_MS from the admission's start (Admission::extend_for_recovery). /// Called with no device mutex or existing preparation lease. pub(super) fn enter_until(self: &Arc, admission: &Admission<'_>) -> Result { admission.check()?; match self.try_enter() { - Err(error) if error == EAGAIN => {} + Err(error) if error == EAGAIN => admission.extend_for_recovery(), result => return result, } let mut wait = self.wait.lock(); loop { admission.check()?; match self.try_enter() { - Err(error) if error == EAGAIN => {} + Err(error) if error == EAGAIN => admission.extend_for_recovery(), result => return result, } let _ = self.changed.wait_timeout( @@ -322,6 +336,20 @@ mod growth_gate_tests { mod compute_deadline_tests { use super::*; + #[test] + fn a_recovery_extends_the_deadline_once_from_the_start() { + let check = || Ok(()); + let admission = Admission::new(super::super::now_ns(), &check); + assert_eq!(admission.check(), Err(EBUSY)); + admission.extend_for_recovery(); + assert_eq!(admission.check(), Ok(())); + let limit = admission.started + + u64::from(super::super::timeout::RECOVERY_WAIT_MS) * 1_000_000; + assert_eq!(admission.deadline.get(), limit); + admission.extend_for_recovery(); + assert_eq!(admission.deadline.get(), limit); + } + #[test] fn spent_budget_refuses_even_an_open_gate() { let gate = Gate::new().unwrap(); @@ -332,13 +360,16 @@ mod compute_deadline_tests { } #[test] - fn closed_gate_expires_without_any_recovery_wake() { + fn closed_gate_waits_past_the_budget_for_recovery() { let gate = Gate::new().unwrap(); gate.close(); let start = super::super::now_ns(); - let check = || Ok(()); + // Cancel well after the 20 ms budget: only the recovery extension keeps it waiting. + let check = || { + if super::super::now_ns() - start >= 60_000_000 { Err(ECANCELED) } else { Ok(()) } + }; let admission = Admission::new(start + 20_000_000, &check); - assert!(matches!(gate.enter_until(&admission), Err(error) if error == EBUSY)); + assert!(matches!(gate.enter_until(&admission), Err(error) if error == ECANCELED)); assert!(super::super::now_ns() - start < 500_000_000); gate.wait_drained(); assert!(gate.reopen()); diff --git a/drivers/gpu/drm/asahi/g17/queue/admission.rs b/drivers/gpu/drm/asahi/g17/queue/admission.rs index ed73323e34e6f..f09e629aa047e 100644 --- a/drivers/gpu/drm/asahi/g17/queue/admission.rs +++ b/drivers/gpu/drm/asahi/g17/queue/admission.rs @@ -494,6 +494,16 @@ impl Pool { } } } + /// The owner's pair is quarantined behind another VM's recovery (spared) and drains. + pub(crate) fn spared_quarantined(&self, owner: u64) -> bool { + let state = self.state.lock(); + state + .owners + .iter() + .position(|id| *id == owner) + .is_some_and(|slot| state.quarantined & state.spared & (1u64 << slot) != 0) + } + pub(crate) fn acquire_render( self: &Arc, owner: u64, @@ -525,17 +535,22 @@ impl Pool { .position(|id| *id == owner) .is_some_and(|slot| state.quarantined & (1u64 << slot) != 0) { - if now >= quarantine_deadline { - // Behind an innocent pair's quarantine (another VM wedged the GPU) only this - // publication fails, not the VM: it recovers once the pair drains. - let spared = state - .owners - .iter() - .position(|id| *id == owner) - .is_some_and(|slot| state.spared & (1u64 << slot) != 0); - return Err(if spared { EBUSY } else { EIO }); + // Behind an innocent pair's quarantine (another VM wedged the GPU) wait for the + // pair to drain until the caller's deadline, which the caller extends while it + // drains (RECOVERY_WAIT_MS); a guilty pair's publication fails after a second. + let spared = state + .owners + .iter() + .position(|id| *id == owner) + .is_some_and(|slot| state.spared & (1u64 << slot) != 0); + if now >= quarantine_deadline && !spared { + return Err(EIO); } - let slice = remaining_ms.min(wait_slice_ms(quarantine_deadline, now)?); + let slice = if spared { + remaining_ms + } else { + remaining_ms.min(wait_slice_ms(quarantine_deadline, now)?) + }; if matches!(self.released.wait_interruptible_timeout( &mut state, kernel::time::msecs_to_jiffies(slice) ), CondVarTimeoutResult::Signal { .. }) { @@ -1001,10 +1016,13 @@ mod fault_capacity_tests { let queue = pool.reserve_queue().unwrap(); let lease = pool.acquire_render(1, None, u64::MAX, || Ok(())).unwrap(); let bit = 1u64 << lease.slot(); + assert!(!pool.spared_quarantined(1)); lease.quarantine(true); assert_ne!(pool.state.lock().spared & bit, 0); + assert!(pool.spared_quarantined(1)); lease.quarantine(false); assert_eq!(pool.state.lock().spared & bit, 0); + assert!(!pool.spared_quarantined(1)); // Once guilty, a later spared failure does not make it spared again. lease.quarantine(true); assert_eq!(pool.state.lock().spared & bit, 0); diff --git a/drivers/gpu/drm/asahi/g17/queue/compute.rs b/drivers/gpu/drm/asahi/g17/queue/compute.rs index 368e95f144c24..55994066825f8 100644 --- a/drivers/gpu/drm/asahi/g17/queue/compute.rs +++ b/drivers/gpu/drm/asahi/g17/queue/compute.rs @@ -2056,9 +2056,7 @@ impl Queue { let ticket = active.ticket.ok_or(EIO)?; let state = crate::g17::job::fence_status(&active.packet.completion.fence()); if state < 0 { - return Err(crate::g17::dependency::inherited_error(Error::from_errno( - state, - ))); + return Err(crate::g17::dependency::PRODUCER_FAILED); } if state > 0 { return Ok(None); diff --git a/drivers/gpu/drm/asahi/g17/recovery/safety.rs b/drivers/gpu/drm/asahi/g17/recovery/safety.rs index 082416f0cb9a6..d71d3cc81553f 100644 --- a/drivers/gpu/drm/asahi/g17/recovery/safety.rs +++ b/drivers/gpu/drm/asahi/g17/recovery/safety.rs @@ -126,5 +126,6 @@ mod tests { assert_eq!(replay_status(1), Ok(())); assert_eq!(replay_status(EIO.to_errno()), Err(ECANCELED)); assert_eq!(replay_status(ETIMEDOUT.to_errno()), Err(ECANCELED)); + assert_eq!(replay_status(ENODATA.to_errno()), Err(ECANCELED)); } } diff --git a/drivers/gpu/drm/asahi/g17/runtime.rs b/drivers/gpu/drm/asahi/g17/runtime.rs index a6edfd0a80b38..d391fbb3001bb 100644 --- a/drivers/gpu/drm/asahi/g17/runtime.rs +++ b/drivers/gpu/drm/asahi/g17/runtime.rs @@ -1756,8 +1756,10 @@ impl Backend { } } // Other owners continue submitting while this owner waits for its - // queue-local drain witness. No new command has been accepted: the - // spared queue and its retained work stay intact past the deadline. + // queue-local drain witness. No new command has been accepted; if the + // admission deadline passes, the spared queue and its retained work stay + // intact until a later admission observes its witness. + admission.extend_for_recovery(); self.shared.queue_events(); self.wait_release(&self.shared.progress, observed, admission)?; } @@ -2090,6 +2092,13 @@ impl Backend { admission.check()?; let observed = progress.observe(); if !self.sources_published(packet)? { + let recovering = self.shared.state.lock().as_deref().is_some_and(|firmware| { + firmware.recovery.pending() + || super::recovery::Memory::recovery_state(&firmware.init).unwrap_or(0) != 0 + }); + if recovering { + admission.extend_for_recovery(); + } self.shared.queue_events(); self.wait_release(progress, observed, &admission)?; continue; @@ -2131,6 +2140,7 @@ impl Backend { } let recovery_state = super::recovery::Memory::recovery_state(&firmware.init)?; if firmware.recovery.pending() || recovery_state != 0 { + admission.extend_for_recovery(); drop(state); drop(lease); self.shared.queue_events(); @@ -2162,6 +2172,11 @@ impl Backend { { // Recovery or backpressure: nothing is firmware-visible. Other // queues keep submitting and the event worker retires meanwhile. + if firmware.recovery.pending() + || super::recovery::Memory::recovery_state(&firmware.init)? != 0 + { + admission.extend_for_recovery(); + } drop(state); drop(lease); self.shared.queue_events(); diff --git a/drivers/gpu/drm/asahi/g17/runtime/render/submit.rs b/drivers/gpu/drm/asahi/g17/runtime/render/submit.rs index f1a433ddb0db4..970035547dfee 100644 --- a/drivers/gpu/drm/asahi/g17/runtime/render/submit.rs +++ b/drivers/gpu/drm/asahi/g17/runtime/render/submit.rs @@ -54,13 +54,22 @@ impl Backend { ) -> Result<(RenderLease, bool)> { let pool = &self.admission; let started = super::super::now_ns(); - let deadline_ns = started.saturating_add(u64::from(crate::g17::job::TIMEOUT_MS) * 1_000_000); + let mut deadline_ns = + started.saturating_add(u64::from(crate::g17::job::TIMEOUT_MS) * 1_000_000); + let recovery_deadline_ns = started.saturating_add(recovery_wait_ns()); // A capacity refusal samples the render domain and retries once; only // a refusal after that sample waits, so no release can be missed. let mut observed = None; + let mut capacity = WaitClock::default(); loop { self.admission_open()?; - if super::super::now_ns() >= deadline_ns { return Err(EBUSY); } + if super::super::now_ns() >= deadline_ns { + if deadline_ns < recovery_deadline_ns && self.waiting_for_recovery()? { + deadline_ns = recovery_deadline_ns; + } else { + return Err(EBUSY); + } + } if packet.cancel_requested() { return Err(ECANCELED); } @@ -95,11 +104,13 @@ impl Backend { .reclaim_unused_render_spare(Some(self.owner), false)? }; if reclaimed.is_none() { - self.wait_render_capacity(&mut observed, started, sleep)?; + self.wait_render_capacity(&mut observed, &mut capacity, sleep)?; } drop(reclaimed); continue; } + // The deadline check above decides whether a recovery extends the wait. + Err(error) if error == EBUSY => continue, Err(error) => return Err(error), } }; @@ -133,7 +144,7 @@ impl Backend { drop(state); // A full queue table makes admission reuse a free killed pair instead. if reclaimed.is_none() && !ready && !pool.killed_pair_free() { - self.wait_render_capacity(&mut observed, started, sleep)?; + self.wait_render_capacity(&mut observed, &mut capacity, sleep)?; } drop(reclaimed); } @@ -221,13 +232,29 @@ impl Backend { domain.block(observed, remaining.div_ceil(1_000_000).min(10) as u32, false) } + /// A recovery is pending, or this owner's pair is spared and draining after one: an + /// innocent publication waits up to RECOVERY_WAIT_MS for it instead of failing. + fn waiting_for_recovery(&self) -> Result { + let state = self.shared.state.lock(); + let firmware = (*state).as_deref().ok_or(ENODEV)?; + Ok(firmware.recovery.pending() + || crate::g17::recovery::Memory::recovery_state(&firmware.init)? != 0 + || firmware.queues.admission.spared_quarantined(self.owner)) + } + + /// The deadline of the wait `clock` measures (WaitClock::deadline). + fn wait_deadline(&self, clock: &mut WaitClock, bound_ns: u64) -> Result { + let recovering = self.waiting_for_recovery()?; + Ok(clock.deadline(super::super::now_ns(), recovering, bound_ns)) + } + /// A pair is borrowed, still settling, waiting for firmware room or for the /// release of the scheduler it last ran for. Every pair return, retirement /// and teardown step signals the render domain, and each event pass does /// while a publisher waits; the deadline is only the failure bound. fn wait_render_busy( &self, - since: &mut Option, + clock: &mut WaitClock, observed: &mut Option, sleep: bool, packet: &Packet, @@ -235,8 +262,7 @@ impl Backend { if !sleep { return Err(FALLBACK); } - let now = super::super::now_ns(); - let deadline = since.get_or_insert(now).saturating_add(super::super::WORK_RING_WAIT_NS); + let deadline = self.wait_deadline(clock, super::super::WORK_RING_WAIT_NS)?; // Sample, then retry once: only a refusal after the sample waits. let Some(sample) = observed.take() else { *observed = Some(self.shared.renders.observe()); @@ -249,7 +275,12 @@ impl Backend { /// Render capacity is short: return what idle owners hold, then block until /// a pair, lease or owner returns. No packet is firmware-visible here, and /// neither the device mutex nor a preparation lease is held while waiting. - fn wait_render_capacity(&self, observed: &mut Option, started: u64, sleep: bool) -> Result { + fn wait_render_capacity( + &self, + observed: &mut Option, + clock: &mut WaitClock, + sleep: bool, + ) -> Result { if !sleep { return Err(FALLBACK); } @@ -263,8 +294,8 @@ impl Backend { }; self.shared.queue_events(); self.admission_open()?; - let remaining = started - .saturating_add(super::super::WORK_RING_WAIT_NS) + let remaining = self + .wait_deadline(clock, super::super::WORK_RING_WAIT_NS)? .saturating_sub(super::super::now_ns()); if remaining == 0 { return Err(EBUSY); @@ -367,9 +398,10 @@ impl Backend { return result; } } - let mut busy_since = None; - let capacity_started = super::super::now_ns(); - let deadline_ns = capacity_started.saturating_add(super::super::WORK_RING_WAIT_NS); + let mut busy = WaitClock::default(); + let mut capacity = WaitClock::default(); + let mut state_clock = WaitClock::default(); + let mut recovery_since = None; let mut seen = None; let mut states = None; loop { @@ -407,8 +439,11 @@ impl Backend { let work = packet.completion.work_state()?; match states.take() { None => states = Some(work.returns().observe()), + // Work states free as earlier, possibly spared, work retires. Some(sample) => { - self.wait_domain(work.returns(), sample, deadline_ns, packet)? + let deadline = self + .wait_deadline(&mut state_clock, super::super::WORK_RING_WAIT_NS)?; + self.wait_domain(work.returns(), sample, deadline, packet)? } } continue; @@ -426,19 +461,19 @@ impl Backend { }; match ensured { Err(error) if error == ENOSPC => { - self.wait_render_capacity(&mut seen, capacity_started, sleep)?; + self.wait_render_capacity(&mut seen, &mut capacity, sleep)?; continue; } Err(error) if error == EAGAIN => continue, Err(error) if error == EBUSY => { - self.wait_render_busy(&mut busy_since, &mut seen, sleep, packet)?; + self.wait_render_busy(&mut busy, &mut seen, sleep, packet)?; continue; } result => result?, } match self.prepare_render(slot, packet, deferred, sleep) { Err(error) if !packet.is_published() && error == ENOSPC => { - self.wait_render_capacity(&mut seen, capacity_started, sleep)?; + self.wait_render_capacity(&mut seen, &mut capacity, sleep)?; continue; } Err(error) if !packet.is_published() && [EAGAIN, EBUSY].contains(&error) => { @@ -458,10 +493,13 @@ impl Backend { // Recovery closes the preparation gate before touching // any queue; the next pass blocks in enter() until it // reopens. The worker raises the closure. + let since = *recovery_since.get_or_insert(super::super::now_ns()); self.shared.queue_events(); - self.shared.preparations.wait_closure(gate, deadline_ns)?; + self.shared + .preparations + .wait_closure(gate, since.saturating_add(recovery_wait_ns()))?; } else if error == EBUSY { - self.wait_render_busy(&mut busy_since, &mut seen, sleep, packet)?; + self.wait_render_busy(&mut busy, &mut seen, sleep, packet)?; } else if !sleep { return Err(FALLBACK); } @@ -699,3 +737,57 @@ impl crate::g17::Firmware { result } } + +fn recovery_wait_ns() -> u64 { + u64::from(crate::g17::timeout::RECOVERY_WAIT_MS) * 1_000_000 +} + +/// One bounded wait (Backend::wait_deadline). +#[derive(Default)] +struct WaitClock { + first: Option, + calm: u64, +} + +impl WaitClock { + /// `bound_ns` after the later of the first call and the last call that saw a recovery + /// pending or this owner's spared pair draining (so the usual bound applies afresh once a + /// recovery ends), and at most RECOVERY_WAIT_MS after the first call. + fn deadline(&mut self, now: u64, recovering: bool, bound_ns: u64) -> u64 { + let first = *self.first.get_or_insert(now); + self.calm = if recovering { now } else { self.calm.max(first) }; + first + .saturating_add(recovery_wait_ns()) + .min(self.calm.saturating_add(bound_ns)) + } +} + +#[kunit_tests(asahi_g17_wait_clock)] +mod tests { + use super::*; + + const BOUND: u64 = 2_000_000_000; + + #[test] + fn a_calm_wait_keeps_its_first_deadline() { + let mut clock = WaitClock::default(); + assert_eq!(clock.deadline(100, false, BOUND), 100 + BOUND); + assert_eq!(clock.deadline(500, false, BOUND), 100 + BOUND); + } + + #[test] + fn the_bound_starts_afresh_once_a_recovery_ends() { + let mut clock = WaitClock::default(); + clock.deadline(100, false, BOUND); + assert_eq!(clock.deadline(1_000, true, BOUND), 1_000 + BOUND); + assert_eq!(clock.deadline(2_000, false, BOUND), 1_000 + BOUND); + } + + #[test] + fn a_recovery_cannot_extend_past_the_recovery_wait() { + let mut clock = WaitClock::default(); + clock.deadline(100, true, BOUND); + let limit = 100 + recovery_wait_ns(); + assert_eq!(clock.deadline(limit - 1, true, BOUND), limit); + } +} diff --git a/drivers/gpu/drm/asahi/g17/timeout.rs b/drivers/gpu/drm/asahi/g17/timeout.rs index b83ea5d07f406..ce003e6b18196 100644 --- a/drivers/gpu/drm/asahi/g17/timeout.rs +++ b/drivers/gpu/drm/asahi/g17/timeout.rs @@ -18,6 +18,13 @@ pub(crate) fn transaction_grace(renewals: u8) -> bool { renewals < MAX_RENEWALS pub(crate) const POLL_MS: u32 = 2000; const EXECUTION_RENEWALS: u8 = 4; +/// How long an innocent client's publication waits for a recovery to settle and its +/// spared work to drain, instead of failing with EBUSY: the watchdog defers work behind +/// another VM at most this long before it settles it (`classify`; ray work gets the +/// execution renewals on top). +pub(crate) const RECOVERY_WAIT_MS: u32 = + POLL_MS * (1 + EXECUTION_RENEWALS as u32 + MAX_RENEWALS as u32); + /// A background control/replay poll has no scheduler fence to expire it. /// Its timestamp belongs to the exact transaction and is never renewed by work. pub(crate) fn background_stalled(since: Option, now: u64) -> bool { diff --git a/drivers/iio/common/aop_sensors/aop_als.rs b/drivers/iio/common/aop_sensors/aop_als.rs index 5e6c5001ad2b8..e64f7ff26a6e0 100644 --- a/drivers/iio/common/aop_sensors/aop_als.rs +++ b/drivers/iio/common/aop_sensors/aop_als.rs @@ -268,7 +268,7 @@ impl platform::Driver for IIOAopAlsDriver { &adata, service, offset, - [ty, bindings::BINDINGS_IIO_CCT], + [ty, bindings::BINDINGS_IIO_COLORTEMP], )?; ( listener, diff --git a/drivers/soc/apple/apple-pmgr-dcs-test.c b/drivers/soc/apple/apple-pmgr-dcs-test.c index f1021b6de4f61..82fe4acea2c97 100644 --- a/drivers/soc/apple/apple-pmgr-dcs-test.c +++ b/drivers/soc/apple/apple-pmgr-dcs-test.c @@ -3,15 +3,40 @@ #include #include +struct apple_pmgr_dcs_fixture { + struct apple_pmgr_misc misc; + u32 commands[16]; + unsigned int num_commands; + u32 fail_states; + u32 fail_actual; +}; + +static void apple_pmgr_dcs_fake_command(u32 word, void __iomem *reg) +{ + struct kunit *test = kunit_get_current_test(); + struct apple_pmgr_dcs_fixture *f = test->priv; + u32 actual = word; + + KUNIT_ASSERT_PTR_EQ(test, reg, f->misc.devices[DEV_DCS].base); + KUNIT_ASSERT_LT(test, f->num_commands, ARRAY_SIZE(f->commands)); + f->commands[f->num_commands++] = word; + if (f->fail_states & BIT(word)) + actual = f->fail_actual; + /* Model hardware updating actual independently of the command word. */ + writel(word | FIELD_PREP(APPLE_CLKGEN_PSTATE_ACTUAL, actual), reg); +} + static int apple_pmgr_dcs_test_init(struct kunit *test) { + struct apple_pmgr_dcs_fixture *f; struct apple_pmgr_misc *misc; void *reg; - misc = kunit_kzalloc(test, sizeof(*misc), GFP_KERNEL); - if (!misc) + f = kunit_kzalloc(test, sizeof(*f), GFP_KERNEL); + if (!f) return -ENOMEM; - reg = kunit_kzalloc(test, sizeof(u32), GFP_KERNEL); + misc = &f->misc; + reg = kunit_kzalloc(test, 2 * sizeof(u32), GFP_KERNEL); if (!reg) return -ENOMEM; misc->dev = kunit_device_register(test, "pmgr-dcs-test"); @@ -19,13 +44,17 @@ static int apple_pmgr_dcs_test_init(struct kunit *test) return PTR_ERR(misc->dev); mutex_init(&misc->lock); misc->devices[DEV_DCS].base = (void __iomem *)reg; - misc->devices[DEV_DCS].active_state = 10; + misc->devices[DEV_DCS].active_state = 9; misc->devices[DEV_DCS].suspend_state = DCS_DEV_PSTATE_MIN_T600X; - misc->dcs_num_opps = 3; + misc->dcs_valid_states = DCS_VALID_STATES_T600X; + misc->devices[DEV_FABRIC].base = (void __iomem *)(reg + sizeof(u32)); + writel(0xa5000077, misc->devices[DEV_FABRIC].base); + misc->fabric_now = 7; + misc->devices[DEV_FABRIC].active_state = 7; + misc->dcs_num_opps = 2; misc->dcs_opps[0] = (struct apple_pmgr_dcs_opp) { 7, 1000 }; misc->dcs_opps[1] = (struct apple_pmgr_dcs_opp) { 9, 2000 }; - misc->dcs_opps[2] = (struct apple_pmgr_dcs_opp) { 10, 3000 }; - writel(0xa50000aa, misc->devices[DEV_DCS].base); + writel(0xa5000099, misc->devices[DEV_DCS].base); misc->dcs_data = kunit_kzalloc(test, struct_size(misc->dcs_data, nodes, 2), GFP_KERNEL); if (!misc->dcs_data) return -ENOMEM; @@ -37,7 +66,8 @@ static int apple_pmgr_dcs_test_init(struct kunit *test) misc->dcs_data->nodes[i]->data = misc; } dev_set_drvdata(misc->dev, misc); - test->priv = misc; + test->priv = f; + kunit_activate_static_stub(test, apple_pmgr_dcs_command, apple_pmgr_dcs_fake_command); return 0; } @@ -46,7 +76,7 @@ static void apple_pmgr_dcs_table_test(struct kunit *test) struct apple_pmgr_misc *misc = test->priv; KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_validate(misc), 0); - swap(misc->dcs_opps[0], misc->dcs_opps[2]); + swap(misc->dcs_opps[0], misc->dcs_opps[1]); KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_validate(misc), 0); KUNIT_EXPECT_EQ(test, misc->dcs_opps[0].state, 7U); misc->dcs_opps[1].state = 7; @@ -58,10 +88,10 @@ static void apple_pmgr_dcs_table_test(struct kunit *test) misc->dcs_opps[0].bw = 0; KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_validate(misc), -EINVAL); misc->dcs_opps[0].bw = 1000; - misc->dcs_opps[0].state = 6; + misc->dcs_opps[0].state = 8; KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_validate(misc), -EINVAL); misc->dcs_opps[0].state = 7; - misc->devices[DEV_DCS].active_state = 9; + misc->devices[DEV_DCS].active_state = 7; KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_validate(misc), -EINVAL); misc->dcs_num_opps = 17; KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_validate(misc), -EINVAL); @@ -80,10 +110,10 @@ static void apple_pmgr_dcs_selection_test(struct kunit *test) KUNIT_EXPECT_EQ(test, state, 7U); KUNIT_ASSERT_EQ(test, apple_pmgr_dcs_select(misc, 1001, &state), 0); KUNIT_EXPECT_EQ(test, state, 9U); - KUNIT_ASSERT_EQ(test, apple_pmgr_dcs_select(misc, 3000, &state), 0); - KUNIT_EXPECT_EQ(test, state, 10U); - KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_select(misc, 3001, &state), -ERANGE); - KUNIT_EXPECT_EQ(test, state, 10U); + KUNIT_ASSERT_EQ(test, apple_pmgr_dcs_select(misc, 2000, &state), 0); + KUNIT_EXPECT_EQ(test, state, 9U); + KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_select(misc, 2001, &state), -ERANGE); + KUNIT_EXPECT_EQ(test, state, 9U); } static void apple_pmgr_dcs_aggregation_test(struct kunit *test) @@ -105,11 +135,11 @@ static void apple_pmgr_dcs_commit_test(struct kunit *test) node->avg_bw = 1001; - writel(0xa500009a, misc->devices[DEV_DCS].base); + writel(0x999, misc->devices[DEV_DCS].base); KUNIT_ASSERT_EQ(test, apple_pmgr_dcs_set(node, node), 0); KUNIT_EXPECT_EQ(test, misc->devices[DEV_DCS].active_state, 9U); KUNIT_EXPECT_TRUE(test, misc->dcs_bw_active); - KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0xa5000099U); + KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0x99U); } static void apple_pmgr_dcs_owner_sleep_test(struct kunit *test) @@ -124,23 +154,29 @@ static void apple_pmgr_dcs_owner_sleep_test(struct kunit *test) misc->pmp_owned = false; misc->sleeping = true; KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_set(node, node), -EBUSY); - KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0xa50000aaU); + KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0xa5000099U); } static void apple_pmgr_dcs_rollback_test(struct kunit *test) { struct apple_pmgr_misc *misc = test->priv; struct icc_node *node = misc->dcs_data->nodes[0]; + struct apple_pmgr_dcs_fixture *f = test->priv; node->peak_bw = 1000; - /* Actual stays at 10: request times out, rollback to 10 succeeds. */ + /* Failed down-command, followed by a successful whole-word restore. */ + f->fail_states = BIT(7); + f->fail_actual = 9; KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_set(node, node), -ETIMEDOUT); KUNIT_EXPECT_FALSE(test, misc->dcs_failed); - KUNIT_EXPECT_EQ(test, misc->devices[DEV_DCS].active_state, 10U); - KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0xa50000aaU); - /* An unknown actual state makes rollback fail too. */ - writel(0xa500000a, misc->devices[DEV_DCS].base); + KUNIT_EXPECT_EQ(test, misc->devices[DEV_DCS].active_state, 9U); + KUNIT_EXPECT_EQ(test, f->commands[0], 7U); + KUNIT_EXPECT_EQ(test, f->commands[1], 9U); + KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0x99U); + /* Inject failure of the restoration as well; retain the fabric hold. */ + f->fail_states |= BIT(9); + f->fail_actual = 0; KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_set(node, node), -ETIMEDOUT); KUNIT_EXPECT_TRUE(test, misc->dcs_failed); KUNIT_EXPECT_TRUE(test, misc->dcs_bw_active); @@ -154,15 +190,15 @@ static void apple_pmgr_dcs_sync_constraints_test(struct kunit *test) struct icc_node *src = misc->dcs_data->nodes[0]; struct icc_node *dst = misc->dcs_data->nodes[1]; - src->avg_bw = 1001; - dst->init_peak = 3000; + src->avg_bw = 1000; + dst->init_peak = 2000; KUNIT_ASSERT_EQ(test, apple_pmgr_dcs_set(src, src), 0); - KUNIT_EXPECT_EQ(test, misc->devices[DEV_DCS].active_state, 10U); + KUNIT_EXPECT_EQ(test, misc->devices[DEV_DCS].active_state, 9U); dst->init_peak = 0; - writel(0xa500009a, misc->devices[DEV_DCS].base); + writel(0x999, misc->devices[DEV_DCS].base); /* Releasing destination's boot constraint must retain source demand. */ KUNIT_ASSERT_EQ(test, apple_pmgr_dcs_set(dst, dst), 0); - KUNIT_EXPECT_EQ(test, misc->devices[DEV_DCS].active_state, 9U); + KUNIT_EXPECT_EQ(test, misc->devices[DEV_DCS].active_state, 7U); } static void apple_pmgr_dcs_suspend_restore_test(struct kunit *test) @@ -172,9 +208,9 @@ static void apple_pmgr_dcs_suspend_restore_test(struct kunit *test) dev_set_drvdata(misc->dev, misc); misc->devices[DEV_DCS].active_state = 9; KUNIT_ASSERT_EQ(test, apple_pmgr_misc_suspend_noirq(misc->dev), 0); - KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0xa50000a7U); + KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0x77U); KUNIT_ASSERT_EQ(test, apple_pmgr_misc_resume_noirq(misc->dev), 0); - KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0xa50000a9U); + KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0x99U); } static void apple_pmgr_dcs_no_table_test(struct kunit *test) @@ -182,7 +218,7 @@ static void apple_pmgr_dcs_no_table_test(struct kunit *test) struct apple_pmgr_misc *misc = test->priv; KUNIT_ASSERT_EQ(test, apple_pmgr_dcs_init(misc), 0); - KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0xa50000aaU); + KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0xa5000099U); } static void apple_pmgr_dcs_release_test(struct kunit *test) @@ -191,13 +227,69 @@ static void apple_pmgr_dcs_release_test(struct kunit *test) struct icc_node *node = misc->dcs_data->nodes[0]; misc->dcs_bw_active = true; - writel(0xa500007a, misc->devices[DEV_DCS].base); + writel(0x999, misc->devices[DEV_DCS].base); KUNIT_ASSERT_EQ(test, apple_pmgr_dcs_set(node, node), 0); KUNIT_EXPECT_EQ(test, misc->devices[DEV_DCS].active_state, 7U); KUNIT_EXPECT_FALSE(test, misc->dcs_bw_active); } +static void apple_pmgr_dcs_whole_word_test(struct kunit *test) +{ + struct apple_pmgr_misc *misc = test->priv; + struct apple_pmgr_dcs_fixture *f = test->priv; + + writel(0xa5000999, misc->devices[DEV_DCS].base); + KUNIT_ASSERT_EQ(test, apple_pmgr_dcs_write(misc, 7), 0); + KUNIT_EXPECT_EQ(test, f->num_commands, 1U); + KUNIT_EXPECT_EQ(test, f->commands[0], 0x00000007U); + KUNIT_ASSERT_EQ(test, apple_pmgr_dcs_write(misc, 9), 0); + KUNIT_EXPECT_EQ(test, f->commands[1], 0x00000009U); + KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_FABRIC].base), 0xa5000077U); +} + +static void apple_pmgr_dcs_invalid_state_test(struct kunit *test) +{ + struct apple_pmgr_misc *misc = test->priv; + struct apple_pmgr_dcs_fixture *f = test->priv; + + for (u32 state = 0; state < 32; state++) { + bool valid = state == 5 || state == 6 || state == 7 || state == 9; + + KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_state_valid(misc, state), valid); + if (!valid) { + KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_write(misc, state), -EINVAL); + misc->dcs_opps[0] = (struct apple_pmgr_dcs_opp) { state, 1000 }; + misc->dcs_opps[1] = (struct apple_pmgr_dcs_opp) { 9, 2000 }; + KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_validate(misc), -EINVAL); + } + } + KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_write(misc, U32_MAX), -EINVAL); + KUNIT_EXPECT_EQ(test, f->num_commands, 0U); + KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0xa5000099U); + misc->dcs_num_opps = 4; + misc->dcs_opps[0] = (struct apple_pmgr_dcs_opp) { 5, 1000 }; + misc->dcs_opps[1] = (struct apple_pmgr_dcs_opp) { 6, 2000 }; + misc->dcs_opps[2] = (struct apple_pmgr_dcs_opp) { 7, 3000 }; + misc->dcs_opps[3] = (struct apple_pmgr_dcs_opp) { 9, 4000 }; + KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_validate(misc), 0); +} + +static void apple_pmgr_dcs_unsettled_test(struct kunit *test) +{ + struct apple_pmgr_misc *misc = test->priv; + struct apple_pmgr_dcs_fixture *f = test->priv; + struct icc_node *node = misc->dcs_data->nodes[0]; + + writel(0x97, misc->devices[DEV_DCS].base); + KUNIT_EXPECT_EQ(test, apple_pmgr_dcs_set(node, node), -EBUSY); + KUNIT_EXPECT_EQ(test, f->num_commands, 0U); + KUNIT_EXPECT_EQ(test, readl(misc->devices[DEV_DCS].base), 0x97U); +} + static struct kunit_case apple_pmgr_dcs_test_cases[] = { + KUNIT_CASE(apple_pmgr_dcs_whole_word_test), + KUNIT_CASE(apple_pmgr_dcs_invalid_state_test), + KUNIT_CASE(apple_pmgr_dcs_unsettled_test), KUNIT_CASE(apple_pmgr_dcs_table_test), KUNIT_CASE(apple_pmgr_dcs_selection_test), KUNIT_CASE(apple_pmgr_dcs_aggregation_test), diff --git a/drivers/soc/apple/apple-pmgr-misc.c b/drivers/soc/apple/apple-pmgr-misc.c index d18f4ed07d8bb..3912f45bb60d3 100644 --- a/drivers/soc/apple/apple-pmgr-misc.c +++ b/drivers/soc/apple/apple-pmgr-misc.c @@ -22,12 +22,16 @@ #include #include #include +#if IS_ENABLED(CONFIG_APPLE_PMGR_DCS_KUNIT_TEST) +#include +#endif #define APPLE_CLKGEN_PSTATE 0 #define APPLE_CLKGEN_PSTATE_DESIRED GENMASK(3, 0) #define APPLE_CLKGEN_PSTATE_ACTUAL GENMASK(7, 4) #define DCS_DEV_PSTATE_MIN_T600X 7 +#define DCS_VALID_STATES_T600X (BIT(5) | BIT(6) | BIT(7) | BIT(9)) #define SYS_DEV_PSTATE_SUSPEND 1 #define APPLE_PMGR_IDLE_POLL_MS 250 @@ -59,6 +63,7 @@ struct apple_pmgr_sys_device { struct apple_pmgr_misc_hw { u32 dev_min_ps[DEV_MAX]; + u32 dcs_valid_states; }; struct apple_pmgr_dcs_opp { @@ -85,6 +90,7 @@ struct apple_pmgr_misc { struct icc_onecell_data *dcs_data; struct apple_pmgr_dcs_opp dcs_opps[16]; unsigned int dcs_num_opps; + u32 dcs_valid_states; bool dcs_failed; bool dcs_bw_active; struct { @@ -121,13 +127,29 @@ static int apple_pmgr_dcs_select(struct apple_pmgr_misc *misc, u32 bw, u32 *stat return -ERANGE; } +static bool apple_pmgr_dcs_state_valid(struct apple_pmgr_misc *misc, u32 state) +{ + return state <= FIELD_MAX(APPLE_CLKGEN_PSTATE_DESIRED) && + (misc->dcs_valid_states & BIT(state)); +} + +static void apple_pmgr_dcs_command(u32 word, void __iomem *reg) +{ +#if IS_ENABLED(CONFIG_APPLE_PMGR_DCS_KUNIT_TEST) + KUNIT_STATIC_STUB_REDIRECT(apple_pmgr_dcs_command, word, reg); +#endif + writel(word, reg); +} + static int apple_pmgr_dcs_write(struct apple_pmgr_misc *misc, u32 state) { void __iomem *reg = misc->devices[DEV_DCS].base + APPLE_CLKGEN_PSTATE; - u32 val = readl(reg); + u32 val; - FIELD_MODIFY(APPLE_CLKGEN_PSTATE_DESIRED, &val, state); - writel(val, reg); + if (!apple_pmgr_dcs_state_valid(misc, state)) + return -EINVAL; + /* DCS takes a complete command word, not a replay of readback bits. */ + apple_pmgr_dcs_command(FIELD_PREP(APPLE_CLKGEN_PSTATE_DESIRED, state), reg); return readl_poll_timeout(reg, val, FIELD_GET(APPLE_CLKGEN_PSTATE_ACTUAL, val) == state, 10, APPLE_PMGR_RAISE_TIMEOUT_US); @@ -136,7 +158,7 @@ static int apple_pmgr_dcs_write(struct apple_pmgr_misc *misc, u32 state) static int apple_pmgr_dcs_set(struct icc_node *src, struct icc_node *dst) { struct apple_pmgr_misc *misc = src->data; - u32 state, old, bw = 0; + u32 state, old, val, bw = 0; unsigned int i; int ret; @@ -157,13 +179,19 @@ static int apple_pmgr_dcs_set(struct icc_node *src, struct icc_node *dst) ret = apple_pmgr_dcs_select(misc, bw, &state); if (ret) return ret; + if (!apple_pmgr_dcs_state_valid(misc, state)) + return -EINVAL; + old = misc->devices[DEV_DCS].active_state; + val = readl(misc->devices[DEV_DCS].base + APPLE_CLKGEN_PSTATE); + if (FIELD_GET(APPLE_CLKGEN_PSTATE_DESIRED, val) != old || + FIELD_GET(APPLE_CLKGEN_PSTATE_ACTUAL, val) != old) + return -EBUSY; /* Untracked DMA clients need the fabric as well as DCS bandwidth. */ if (bw) { ret = apple_pmgr_raise_fabric(misc); if (ret) return ret; } - old = misc->devices[DEV_DCS].active_state; ret = apple_pmgr_dcs_write(misc, state); if (ret) { /* A failed request must not replace the last confirmed vote. */ @@ -207,8 +235,7 @@ static int apple_pmgr_dcs_validate(struct apple_pmgr_misc *misc) for (i = 0; i < misc->dcs_num_opps; i++) { const struct apple_pmgr_dcs_opp *opp = &misc->dcs_opps[i]; - if (!opp->bw || opp->state < DCS_DEV_PSTATE_MIN_T600X || - opp->state > FIELD_MAX(APPLE_CLKGEN_PSTATE_DESIRED)) + if (!opp->bw || !apple_pmgr_dcs_state_valid(misc, opp->state)) return -EINVAL; if (i && (opp->state <= misc->dcs_opps[i - 1].state || opp->bw <= misc->dcs_opps[i - 1].bw)) @@ -327,6 +354,14 @@ static void apple_pmgr_sys_dev_set_pstate(struct apple_pmgr_misc *misc, dev_dbg(misc->dev, "set %d ps to pstate %d\n", dev, pstate); + if (dev == DEV_DCS && misc->dcs_valid_states) { + if (WARN_ON_ONCE(!apple_pmgr_dcs_state_valid(misc, pstate))) + return; + apple_pmgr_dcs_command(FIELD_PREP(APPLE_CLKGEN_PSTATE_DESIRED, pstate), + misc->devices[dev].base + APPLE_CLKGEN_PSTATE); + return; + } + val = readl_relaxed(misc->devices[dev].base + APPLE_CLKGEN_PSTATE); FIELD_MODIFY(APPLE_CLKGEN_PSTATE_DESIRED, &val, pstate); writel_relaxed(val, misc->devices[dev].base + APPLE_CLKGEN_PSTATE); @@ -717,6 +752,7 @@ static int apple_pmgr_misc_probe(struct platform_device *pdev) hw = of_device_get_match_data(dev); if (!hw) return -EINVAL; + misc->dcs_valid_states = hw->dcs_valid_states; ret = apple_pmgr_init_device(misc, hw, DEV_FABRIC, "fabric"); if (ret) @@ -763,6 +799,7 @@ static int apple_pmgr_misc_probe(struct platform_device *pdev) } static const struct apple_pmgr_misc_hw apple_pmgr_misc_hw_t600x = { + .dcs_valid_states = DCS_VALID_STATES_T600X, .dev_min_ps = { [DEV_FABRIC] = SYS_DEV_PSTATE_SUSPEND, [DEV_DCS] = DCS_DEV_PSTATE_MIN_T600X, diff --git a/drivers/soc/apple/profile.rs b/drivers/soc/apple/profile.rs index 0e632c65da81f..aaefc62b9528b 100644 --- a/drivers/soc/apple/profile.rs +++ b/drivers/soc/apple/profile.rs @@ -613,9 +613,10 @@ pub(crate) fn detect() -> Result<&'static PlatformProfile> { if machine_has(b"apple,t8122") && (machine_has(b"apple,j613") || machine_has(b"apple,j615")) { return Ok(&T8122); } - // Only the board whose ADT was read: J616s. The other T6040 Macs share - // the SoC but their sensor wiring is unchecked. - if machine_has(b"apple,t6040") && machine_has(b"apple,j616s") { + // The T6040 profile is tested on J614s and J616s. + if machine_has(b"apple,t6040") + && (machine_has(b"apple,j616s") || machine_has(b"apple,j614s")) + { return Ok(&T6040); } Err(ENODEV) diff --git a/drivers/spi/spi-apple-qspi-policy-test.c b/drivers/spi/spi-apple-qspi-policy-test.c index f6dc555057443..5418c3a4d63ab 100644 --- a/drivers/spi/spi-apple-qspi-policy-test.c +++ b/drivers/spi/spi-apple-qspi-policy-test.c @@ -175,6 +175,39 @@ static void qspi_policy_mx_status(struct kunit *test) KUNIT_EXPECT_TRUE(test, apple_qspi_mx_status_allows_write(0x3c, 0x3c)); } +static void qspi_policy_gd_status(struct kunit *test) +{ + /* The J700 GD25UF16E part: QE is set for good and BP0 by iBoot. */ + KUNIT_EXPECT_TRUE(test, apple_qspi_gd_status_allows_write(0x00, 0x02, 0x1c)); + KUNIT_EXPECT_TRUE(test, apple_qspi_gd_status_allows_write(0x04, 0x02, 0x1c)); + KUNIT_EXPECT_FALSE(test, apple_qspi_gd_status_allows_write(0x04, 0x02, 0)); + /* SRP0, SRP1 and LB1 to LB3 stay as found and do not block a write. */ + KUNIT_EXPECT_TRUE(test, apple_qspi_gd_status_allows_write(0x80, 0x3b, 0x1c)); + /* WIP and WEL are never admitted. */ + KUNIT_EXPECT_FALSE(test, apple_qspi_gd_status_allows_write(0x01, 0, 0x1c)); + KUNIT_EXPECT_FALSE(test, apple_qspi_gd_status_allows_write(0x02, 0, 0x1c)); + /* BP3 and BP4, which Winbond calls TB and SEC. */ + KUNIT_EXPECT_FALSE(test, apple_qspi_gd_status_allows_write(0x20, 0, 0x1c)); + KUNIT_EXPECT_FALSE(test, apple_qspi_gd_status_allows_write(0x40, 0, 0x1c)); + /* SUS1, CMP and SUS2, which is reserved on Winbond parts. */ + KUNIT_EXPECT_FALSE(test, apple_qspi_gd_status_allows_write(0, 0x80, 0x1c)); + KUNIT_EXPECT_FALSE(test, apple_qspi_gd_status_allows_write(0, 0x40, 0x1c)); + KUNIT_EXPECT_FALSE(test, apple_qspi_gd_status_allows_write(0, 0x04, 0x1c)); +} + +static void qspi_policy_part_status(struct kunit *test) +{ + /* The checks follow the manufacturer the flash reports. */ + KUNIT_EXPECT_TRUE(test, apple_qspi_part_status_allows_write(0xef, 0x20, 0, 0, 0x1c)); + KUNIT_EXPECT_FALSE(test, apple_qspi_part_status_allows_write(0xc8, 0x20, 0, 0, 0x1c)); + KUNIT_EXPECT_FALSE(test, apple_qspi_part_status_allows_write(0xef, 0, 0, 0x04, 0x1c)); + /* GigaDevice SR3 bit 2 is LPE, a power setting. */ + KUNIT_EXPECT_TRUE(test, apple_qspi_part_status_allows_write(0xc8, 0, 0, 0x04, 0x1c)); + KUNIT_EXPECT_TRUE(test, apple_qspi_part_status_allows_write(0xef, 0, 0x04, 0, 0x1c)); + KUNIT_EXPECT_FALSE(test, apple_qspi_part_status_allows_write(0xc8, 0, 0x04, 0, 0x1c)); + KUNIT_EXPECT_FALSE(test, apple_qspi_part_status_allows_write(0xc2, 0x20, 0, 0, 0x1c)); +} + static struct kunit_case apple_qspi_policy_cases[] = { KUNIT_CASE(qspi_policy_write_enable), KUNIT_CASE(qspi_policy_program), @@ -185,6 +218,8 @@ static struct kunit_case apple_qspi_policy_cases[] = { KUNIT_CASE(qspi_policy_nvram_700000), KUNIT_CASE(qspi_policy_status), KUNIT_CASE(qspi_policy_mx_status), + KUNIT_CASE(qspi_policy_gd_status), + KUNIT_CASE(qspi_policy_part_status), {} }; diff --git a/drivers/spi/spi-apple-qspi-policy.h b/drivers/spi/spi-apple-qspi-policy.h index 5acd9a62d5291..361ecc689fca7 100644 --- a/drivers/spi/spi-apple-qspi-policy.h +++ b/drivers/spi/spi-apple-qspi-policy.h @@ -76,4 +76,41 @@ static inline int apple_qspi_mx_status_allows_write(unsigned int sr, { return !(sr & 0x03) && !(sr & 0x3c & ~bp_ok); } + +/* JEDEC manufacturer ID of GigaDevice parts. */ +#define APPLE_QSPI_MFR_GIGADEVICE 0xc8 + +/* + * GigaDevice GD25UF16E. SR1 holds WIP, WEL, five block-protect bits BP[4:0] + * at bits 6:2 and SRP0. SR2 holds SRP1, QE, SUS2 at bit 2, LB[3:1], CMP and + * SUS1 at bit 7. SR3 holds output drive, dummy-cycle and low-power settings + * and has no write-protect selection. BUSY and WEL, both suspend bits and + * CMP are always refused. BP[2:0] sit where they do on Winbond parts and + * are tolerated only where bp_ok allows them; BP3 and BP4 move or shrink + * the protected range and are refused unless bp_ok names them. SRP0, SRP1, + * QE and LB stay unchanged. + */ +static inline int apple_qspi_gd_status_allows_write(unsigned int sr1, + unsigned int sr2, + unsigned int bp_ok) +{ + return !(sr1 & 0x03) && !(sr1 & 0x7c & ~bp_ok) && !(sr2 & 0xc4); +} + +/* Pick the status checks from the manufacturer the flash itself reports. */ +static inline int apple_qspi_part_status_allows_write(unsigned int mfr, + unsigned int sr1, + unsigned int sr2, + unsigned int sr3, + unsigned int bp_ok) +{ + switch (mfr) { + case APPLE_QSPI_MFR_MACRONIX: + return apple_qspi_mx_status_allows_write(sr1, bp_ok); + case APPLE_QSPI_MFR_GIGADEVICE: + return apple_qspi_gd_status_allows_write(sr1, sr2, bp_ok); + default: + return apple_qspi_status_allows_write(sr1, sr2, sr3, bp_ok); + } +} #endif diff --git a/drivers/spi/spi-apple-qspi.c b/drivers/spi/spi-apple-qspi.c index 601929b85f1fd..11fb1d5553105 100644 --- a/drivers/spi/spi-apple-qspi.c +++ b/drivers/spi/spi-apple-qspi.c @@ -100,8 +100,8 @@ struct apple_qspi_soc { /* * A board whose NVRAM may be written: the controller compatible, the * machine, the controller aperture, the nvram partition the device tree - * must describe, the boot NOR JEDEC ID and the SR1 block-protect bits its - * firmware leaves set at boot. + * must describe, the boot NOR JEDEC ID, the SR1 block-protect bits its + * firmware leaves set at boot and the JEDEC ID of a second part, if any. */ struct apple_qspi_board { const char *controller; @@ -111,23 +111,30 @@ struct apple_qspi_board { u32 nvram_size; u8 jedec[3]; u8 bp_ok; + u8 jedec_alt[3]; }; #define APPLE_QSPI_JEDEC_W25Q64 { 0xef, 0x65, 0x17 } #define APPLE_QSPI_JEDEC_W25Q16 { 0xef, 0x65, 0x15 } #define APPLE_QSPI_JEDEC_MX_2B27 { 0xc2, 0x2b, 0x27 } +#define APPLE_QSPI_JEDEC_GD25UF16E { 0xc8, 0x83, 0x15 } static const struct apple_qspi_board apple_qspi_boards[] = { { "apple,t8122-qspi", "apple,j613", 0x2a1118000ULL, 0x700000, 0x100000, APPLE_QSPI_JEDEC_W25Q64, 0 }, { "apple,t8132-qspi", "apple,j713", 0x3ad118000ULL, 0x700000, 0x100000, APPLE_QSPI_JEDEC_W25Q64, 0 }, - /* Macronix; the ID macOS reports for the J616s boot NOR. */ + /* Macronix is the ID macOS reports; a J616s also reads W25Q64 on the bus. */ { "apple,t6041-qspi", "apple,j616s", 0x429118000ULL, - 0x700000, 0x100000, APPLE_QSPI_JEDEC_MX_2B27, 0 }, - /* iBoot leaves BP0 set on the J700, over the top 64 KiB. */ + 0x700000, 0x100000, APPLE_QSPI_JEDEC_MX_2B27, 0, + APPLE_QSPI_JEDEC_W25Q64 }, + /* + * iBoot leaves BP0 set on the J700, over the top 64 KiB. Some J700s + * carry a GigaDevice GD25UF16E, where BP0 covers the same range. + */ { "apple,t8140-qspi", "apple,j700", 0x385110000ULL, - 0x24000, 0x1d0000, APPLE_QSPI_JEDEC_W25Q16, 0x1c }, + 0x24000, 0x1d0000, APPLE_QSPI_JEDEC_W25Q16, 0x1c, + APPLE_QSPI_JEDEC_GD25UF16E }, }; static DEFINE_MUTEX(apple_qspi_policy_lock); @@ -198,8 +205,9 @@ struct apple_qspi { /* The nvram partition [window_start, window_end). */ u64 window_start; u64 window_end; - /* Expected JEDEC ID and the SR1 block-protect bits left by firmware. */ + /* Expected JEDEC IDs and the SR1 block-protect bits left by firmware. */ u8 jedec[3]; + u8 jedec_alt[3]; u8 bp_ok; bool nvram_write_candidate; bool write_fault; @@ -670,7 +678,8 @@ static int apple_qspi_read_array(struct spi_mem *mem, u64 addr, u8 *buf, u32 len } /* - * Winbond parts have three status registers (05h, 35h, 15h). On Macronix + * Winbond and GigaDevice parts have three status registers (05h, 35h, 15h), + * whose bits differ (see the policy header). On Macronix * parts 35h is EQIO, which switches the flash to QPI mode, so only the * status (05h) and configuration (15h) registers are read there. */ @@ -710,7 +719,8 @@ static int apple_qspi_nvram_modify(struct spi_mem *mem, const struct spi_mem_op ret = apple_qspi_read_register(mem, 0x9f, id, sizeof(id)); if (ret) goto out; - if (memcmp(id, qspi->jedec, sizeof(id))) { + if (memcmp(id, qspi->jedec, sizeof(id)) && + (!qspi->jedec_alt[0] || memcmp(id, qspi->jedec_alt, sizeof(id)))) { ret = -ENODEV; goto out; } @@ -718,10 +728,8 @@ static int apple_qspi_nvram_modify(struct spi_mem *mem, const struct spi_mem_op if (ret) goto out; /* No unlocking. Conservatively refuse BP/CMP/WPS, BUSY/WEL or suspend. */ - if (id[0] == APPLE_QSPI_MFR_MACRONIX ? - !apple_qspi_mx_status_allows_write(before[0], qspi->bp_ok) : - !apple_qspi_status_allows_write(before[0], before[1], before[2], - qspi->bp_ok)) { + if (!apple_qspi_part_status_allows_write(id[0], before[0], before[1], + before[2], qspi->bp_ok)) { ret = -EACCES; goto out; } @@ -823,14 +831,18 @@ static int apple_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) if (!apple_qspi_supports_op(mem, op) || apple_qspi_shape_op(op, &shape)) return -EOPNOTSUPP; mutex_lock(&apple_qspi_policy_lock); - /* 35h is EQIO, not a register read, on Macronix parts. */ - if (op->cmd.opcode == 0x35 && - qspi->jedec[0] == APPLE_QSPI_MFR_MACRONIX) { - ret = -EOPNOTSUPP; - goto out; - } if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes && apple_qspi_opcode_is_read(op->cmd.opcode)) { + /* 35h is EQIO, not a register read, on Macronix parts. */ + if (op->cmd.opcode == 0x35) { + u8 id[3]; + + ret = apple_qspi_read_register(mem, 0x9f, id, sizeof(id)); + if (!ret && id[0] == APPLE_QSPI_MFR_MACRONIX) + ret = -EOPNOTSUPP; + if (ret) + goto out; + } ret = apple_qspi_transfer_op(mem, op); goto out; } @@ -1006,6 +1018,7 @@ static int apple_qspi_probe(struct platform_device *pdev) if (board && qspi->window_start == board->nvram_start && qspi->window_end == (u64)board->nvram_start + board->nvram_size) { memcpy(qspi->jedec, board->jedec, sizeof(qspi->jedec)); + memcpy(qspi->jedec_alt, board->jedec_alt, sizeof(qspi->jedec_alt)); qspi->bp_ok = board->bp_ok; qspi->nvram_write_candidate = true; } @@ -1124,7 +1137,8 @@ static ssize_t flash_status_show(struct device *dev, /* spi-mem supplies queue, bus and I/O serialization for each read. * These are sequential samples, not an atomic protection snapshot. * The JEDEC ID decides which registers exist: 35h is SR2 on Winbond - * parts but EQIO on Macronix ones, so it is sent to Winbond only. + * and GigaDevice parts but EQIO on Macronix ones, so it is never sent + * to Macronix. */ ret = apple_qspi_flash_read_reg(&mem, 0x9f, data, 3) ?: apple_qspi_flash_read_reg(&mem, 0x05, data + 3, 1); @@ -1132,6 +1146,7 @@ static ssize_t flash_status_show(struct device *dev, goto out_free; switch (data[0]) { case 0xef: + case APPLE_QSPI_MFR_GIGADEVICE: ret = apple_qspi_flash_read_reg(&mem, 0x35, data + 4, 1) ?: apple_qspi_flash_read_reg(&mem, 0x15, data + 5, 1); if (!ret) diff --git a/include/uapi/drm/asahi_drm.h b/include/uapi/drm/asahi_drm.h index dc34315ec8c82..418522205ee6f 100644 --- a/include/uapi/drm/asahi_drm.h +++ b/include/uapi/drm/asahi_drm.h @@ -445,7 +445,10 @@ enum drm_asahi_feature { * The driver publishes an accepted job's failure before signaling its fence. * Thus userspace must query after a successful DRM syncobj wait/poll before * treating that fence as successful execution. Syncobj signal alone is not - * an execution-success indication. + * an execution-success indication. A job cancelled (ECANCELED) because + * another VM's recovery discarded it, an input did not signal in time, or + * its queue was closed, is not a failure of this VM: its fence carries the + * error, error stays 0, and its output is undefined. * The feature bit is the availability contract; older kernels leave it zero. * Kernel errors for invalid requests: EINVAL flags/pad/size, ENOENT foreign or * missing vm_id, EFAULT inaccessible pointer. No output on invalid request. diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 6a8789909bbc8..56f9f84689804 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -170,7 +170,7 @@ const u32 BINDINGS_IIO_CHAN_INFO_PROCESSED = IIO_CHAN_INFO_PROCESSED; const u32 BINDINGS_IIO_CHAN_INFO_SCALE = IIO_CHAN_INFO_SCALE; const u32 BINDINGS_IIO_ANGL = IIO_ANGL; const u32 BINDINGS_IIO_LIGHT = IIO_LIGHT; -const u32 BINDINGS_IIO_CCT = IIO_CCT; +const u32 BINDINGS_IIO_COLORTEMP = IIO_COLORTEMP; const u32 BINDINGS_IIO_ACCEL = IIO_ACCEL; const u32 BINDINGS_IIO_ANGL_VEL = IIO_ANGL_VEL; const u32 BINDINGS_IIO_TIMESTAMP = IIO_TIMESTAMP; diff --git a/sound/soc/apple/macaudio.c b/sound/soc/apple/macaudio.c index 569cf80387dff..1a7519c2eaa74 100644 --- a/sound/soc/apple/macaudio.c +++ b/sound/soc/apple/macaudio.c @@ -2118,12 +2118,14 @@ struct macaudio_platform_cfg macaudio_j493_cfg = { }; /* - * J616s (T6040, MacBook Pro 16" M4 Pro): the AOP firmware runs MCA cluster - * 0, so the CPU component is the AOP audio driver (front-ends j616-pcm-N, - * back-end spkr). One serializer carries all six SN012776 amps in a 250-bit - * frame at 12 MHz: six 32-bit playback slots, twelve 16-bit sense slots. The - * amps take I2S with an inverted frame clock and a normal bit clock, as on - * the J713 (T8132: the same amp and frame). + * J614s and J616s (T6040, MacBook Pro 14" and 16" M4 Pro): the AOP firmware + * runs MCA cluster 0, so the CPU component is the AOP audio driver + * (front-ends j616-pcm-N, back-end spkr). One serializer carries all six + * SN012776 amps in a 250-bit frame at 12 MHz: six 32-bit playback slots, + * twelve 16-bit sense slots. The amps take I2S with an inverted frame clock + * and a normal bit clock, as on the J713 (T8132: the same amp and frame). + * Apple's device trees for the two boards describe the same amps, slots and + * sense layout; only the speakers and their tuning differ. */ struct macaudio_platform_cfg macaudio_j616_cfg = { .enable_speakers = true, @@ -2142,8 +2144,29 @@ struct macaudio_platform_cfg macaudio_j616_cfg = { }; /* - * The J616s headphone jack, a card of its own: a CS42L84 on the AOP's - * "jack" back-end, which the firmware runs on MCA cluster 2 as a 64-SCLK + * J614s: the same amps and frame as the J616s, but its speakers have not + * been brought up and have no protection profile. Keep them off entirely + * until they get their own bring-up: the speaker link is not bound, so no + * stream ever reaches the amps. + */ +struct macaudio_platform_cfg macaudio_j614_cfg = { + .enable_speakers = false, + .amp = AMP_SN012776, + .speakers = SPKR_2W1T, + .stereo = true, + .amp_gain = 15, + .safe_vol = -20, + .fe_dai_names = { "j616-pcm-0", "j616-pcm-1", "j616-pcm-2" }, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC | + SND_SOC_DAIFMT_GATED | SND_SOC_DAIFMT_NB_IF, + .secondary_bclk_ratio = 250, + .fe_cpu_is_platform = true, + .route_only_fes = BIT(0), +}; + +/* + * The J614s and J616s headphone jack, a card of its own: a CS42L84 on the + * AOP's "jack" back-end, which the firmware runs on MCA cluster 2 as a 64-SCLK * frame at 48 kHz (3.072 MHz, the primary front-end's ratio) with a * one-SCLK FSYNC pulse, two 32-bit slots and data launched on the rising * SCLK edge: DSP_A with an inverted bit clock, as on the J700. A card binds @@ -2224,6 +2247,10 @@ static const struct of_device_id macaudio_snd_device_id[] = { /* j575 AID33 sn012776 15 1x 1W Compat: apple,j375-macaudio */ /* j613 AID20 sn012776 15 2x 1W+1T Compat: apple,j413-macaudio */ /* j615 AID21 sn012776 15 2x 2W+1T Compat: apple,j415-macaudio */ + /* j614 AID34 sn012776 15 2x 2W+1T (AOP-fed; speakers off until bring-up) */ + { .compatible = "apple,j614-macaudio", .data = &macaudio_j614_cfg }, + /* j614 AID34 cs42l84 - the jack, a card of its own (AOP-fed) */ + { .compatible = "apple,j614-macaudio-jack", .data = &macaudio_j616_jack_cfg }, /* j616 AID35 sn012776 15 2x 2W+1T (AOP-fed, one serializer) */ { .compatible = "apple,j616-macaudio", .data = &macaudio_j616_cfg }, /* j616 AID35 cs42l84 - the jack, a card of its own (AOP-fed) */ diff --git a/tools/asahi/g17-admission-deadline-tests.py b/tools/asahi/g17-admission-deadline-tests.py index b58715f6fcc58..d6e63e08d1188 100644 --- a/tools/asahi/g17-admission-deadline-tests.py +++ b/tools/asahi/g17-admission-deadline-tests.py @@ -91,7 +91,7 @@ def fixture(): assert!(NOW.load(Ordering::SeqCst)<=1_010_000_000,"quarantine budget extended"); reset(mode);let pool=new_pool(false,2);pool.state.lock().spared=2; assert!(matches!(pool.acquire_render(1,None,2_000_000_000,||Ok(())),Err(EBUSY))); - assert!(NOW.load(Ordering::SeqCst)<=1_010_000_000,"spared quarantine budget extended"); + assert!((2_000_000_000..=2_010_000_000).contains(&NOW.load(Ordering::SeqCst)),"a spared quarantine waits for the caller's deadline"); } reset(2);let pool=new_pool(true,0); assert!(matches!(pool.acquire_render(1,Some(Request(&())),2_000_000_000,||Ok(())),Err(ERESTARTSYS))); diff --git a/tools/asahi/g17-compute-constructor-tests.py b/tools/asahi/g17-compute-constructor-tests.py index 8c0c4dc772885..14b736f50436b 100644 --- a/tools/asahi/g17-compute-constructor-tests.py +++ b/tools/asahi/g17-compute-constructor-tests.py @@ -27,14 +27,16 @@ def fixture(): runtime = (ROOT / 'runtime.rs').read_text() preparation = (ROOT / 'preparation.rs').read_text() admission = (item(preparation, "pub(super) struct Admission<'a>") + '\n' + - item(preparation, "impl<'a> Admission<'a>")).replace('pub(super) ', '').replace('super::now_ns()', 'now_ns()') + item(preparation, "impl<'a> Admission<'a>")).replace('pub(super) ', '').replace('super::now_ns()', 'now_ns()').replace('super::timeout::', '') methods = '\n'.join(item(runtime, sig) for sig in [' fn shared_compute(', ' fn compute_scheduler(']) methods = methods.replace('super::object::Allocator', 'Allocator').replace('super::preparation::Lease', 'Lease').replace('super::initdata::', '') return r''' #![allow(dead_code)] +use std::cell::Cell; use std::sync::{Mutex,MutexGuard,atomic::{AtomicBool,AtomicU64,Ordering}}; type Result = std::result::Result; const EIO:i32=-5;const EAGAIN:i32=-11;const ENODEV:i32=-19;const EBUSY:i32=-16;const ECANCELED:i32=-125; +const RECOVERY_WAIT_MS:u32=26_000; static NOW:AtomicU64=AtomicU64::new(0);static CANCEL:AtomicBool=AtomicBool::new(false);static ALLOCATE:AtomicBool=AtomicBool::new(false); fn now_ns()->u64{NOW.load(Ordering::SeqCst)} mod kernel{pub mod time{pub fn msecs_to_jiffies(ms:u32)->u32{ms}}} diff --git a/tools/asahi/g17-compute-deadline-tests.py b/tools/asahi/g17-compute-deadline-tests.py index 98c8751773f9b..0b021d1b8f810 100644 --- a/tools/asahi/g17-compute-deadline-tests.py +++ b/tools/asahi/g17-compute-deadline-tests.py @@ -37,19 +37,21 @@ def fixture(): packet = packet.replace(old, new) ensure = ensure.replace(old, new) admission = (item(preparation, "pub(super) struct Admission<'a>") + '\n' + - item(preparation, "impl<'a> Admission<'a>")).replace('pub(super) ', '').replace('super::now_ns()', 'now_ns()') + item(preparation, "impl<'a> Admission<'a>")).replace('pub(super) ', '').replace('super::now_ns()', 'now_ns()').replace('super::timeout::', '') gate = item(preparation, 'pub(super) fn enter_until(').replace('pub(super) ', '') return r''' #![allow(dead_code,unused_variables,irrefutable_let_patterns)] +use std::cell::Cell; use std::sync::{Arc,Mutex,MutexGuard,atomic::{AtomicBool,AtomicU64,AtomicUsize,Ordering}}; type Result = std::result::Result; const EINVAL:i32=-22;const ECANCELED:i32=-125;const EIO:i32=-5;const ENODEV:i32=-19;const EBUSY:i32=-16;const EAGAIN:i32=-11; const RECOVERY_SETTLE_POLLS:usize=200;const WORK_RING_WAIT_NS:u64=2_000_000_000; +const RECOVERY_WAIT_MS:u32=26_000;const RECOVERY_WAIT_NS:u64=RECOVERY_WAIT_MS as u64*1_000_000; static NOW:AtomicU64=AtomicU64::new(0);static CALLS:AtomicUsize=AtomicUsize::new(0); static MODE:AtomicUsize=AtomicUsize::new(0);static CANCEL:AtomicU64=AtomicU64::new(u64::MAX); static STATUS:AtomicU64=AtomicU64::new(u64::MAX);static CLOSED:AtomicBool=AtomicBool::new(false); fn now_ns()->u64{NOW.load(Ordering::SeqCst)} -fn advance(ns:u64){NOW.fetch_add(ns,Ordering::SeqCst);assert!(now_ns()<=6_000_000_000,"admission budget exceeded");} +fn advance(ns:u64){NOW.fetch_add(ns,Ordering::SeqCst);assert!(now_ns()<=RECOVERY_WAIT_NS+4_000_000_000,"admission budget exceeded");} mod kernel{pub mod time{ pub fn msecs_to_jiffies(ms:u32)->u32{ms} pub struct Delta(pub u64);impl Delta{pub fn from_millis(ms:u64)->Self{Self(ms*1_000_000)}pub fn from_micros(us:i64)->Self{Self(us as u64*1_000)}} @@ -59,7 +61,7 @@ def fixture(): struct Wait; impl Wait{fn lock(&self){}} struct Changed; -impl Changed{fn wait_timeout(&self,_:&mut (),_:u32){advance(1_000_000);assert!(now_ns()<=WORK_RING_WAIT_NS,"gate wake storm must remain bounded");}} +impl Changed{fn wait_timeout(&self,_:&mut (),_:u32){advance(1_000_000);assert!(now_ns()<=RECOVERY_WAIT_NS,"gate wake storm must remain bounded");}} struct Gate{wait:Wait,changed:Changed} struct Lease; impl Lease{fn is_current(&self)->bool{true}} @@ -120,7 +122,8 @@ def fixture(): MODE.store(mode,Ordering::SeqCst);NOW.store(0,Ordering::SeqCst);CALLS.store(0,Ordering::SeqCst); let r=b.compute_packet(&p,&mut DeferredBatch); assert_eq!(r,Err(EBUSY),"one admission budget covers binding theft/recovery/publication"); - assert!(now_ns()<=WORK_RING_WAIT_NS+10_000_000,"admission budget exceeded"); + let budget=if mode==1{RECOVERY_WAIT_NS}else{WORK_RING_WAIT_NS}; + assert!(now_ns()>=budget&&now_ns()<=budget+10_000_000,"admission budget exceeded"); if mode==0{assert_eq!(CALLS.load(Ordering::SeqCst),4);assert_eq!(now_ns(),WORK_RING_WAIT_NS);} println!("PASS mode={} result={:?} calls={} elapsed_ms={}",mode,r,CALLS.load(Ordering::SeqCst),now_ns()/1_000_000); } @@ -147,8 +150,8 @@ def fixture(): NOW.store(0,Ordering::SeqCst);CLOSED.store(true,Ordering::SeqCst); let check=||{if cancel&&now_ns()>=10_000_000{Err(ECANCELED)}else{Ok(())}}; let admission=Admission::new(20_000_000,&check); - assert!(matches!(b.shared.preparations.enter_until(&admission),Err(e) if e==if cancel{ECANCELED}else{EBUSY}),"gate wake storm must check original deadline and cancellation"); - assert_eq!(now_ns(),if cancel{10_000_000}else{20_000_000}); + assert!(matches!(b.shared.preparations.enter_until(&admission),Err(e) if e==if cancel{ECANCELED}else{EBUSY}),"gate wake storm must check the recovery deadline and cancellation"); + assert_eq!(now_ns(),if cancel{10_000_000}else{RECOVERY_WAIT_NS}); } println!("PASS spent budgets, nested capacity cancellation/status, gate recovery wake storms"); } @@ -160,12 +163,13 @@ def main(): mutants = [ ('fixed', source, ''), ('renew-on-binding-loss', source.replace('let admission = Admission::new(deadline, &check);\n let progress = &self.shared.progress;\n loop {', 'let progress = &self.shared.progress;\n loop {\n let admission = Admission::new(now_ns().saturating_add(WORK_RING_WAIT_NS), &check);'), 'admission budget exceeded'), - ('ignore-deadline', source.replace('if now_ns() >= self.deadline', 'if false'), 'admission budget exceeded'), + ('ignore-deadline', source.replace('if now_ns() >= self.deadline.get()', 'if false'), 'admission budget exceeded'), ('render-work-state', source.replace('acquire(crate::g17::job::Engine::Compute)', 'acquire(crate::g17::job::Engine::Render)'), 'compute admission takes a compute work state'), ('omit-gate-check', source.replace(' admission.check()?;\n match self.try_enter()', ' match self.try_enter()').replace('admission.slice_ms()?', '10'), 'gate wake storm'), + ('no-recovery-extension', source.replace('admission.extend_for_recovery();', ''), 'admission budget exceeded'), ] # Bind the old unbounded mutant with the review's eventual cancellation. - mutants[1] = (mutants[1][0], mutants[1][1].replace('for mode in 0..4 {', 'CANCEL.store(10_000_000_000,Ordering::SeqCst);\n for mode in 0..4 {'), mutants[1][2]) + mutants[1] = (mutants[1][0], mutants[1][1].replace('for mode in 0..4 {', 'CANCEL.store(40_000_000_000,Ordering::SeqCst);\n for mode in 0..4 {'), mutants[1][2]) with tempfile.TemporaryDirectory(prefix='g17-compute-deadline-') as tmp: for name, code, expected in mutants: if name != 'fixed': diff --git a/tools/asahi/g17-compute-growth-deadline-tests.py b/tools/asahi/g17-compute-growth-deadline-tests.py index 3c652a96df759..f2c148e5ec46a 100644 --- a/tools/asahi/g17-compute-growth-deadline-tests.py +++ b/tools/asahi/g17-compute-growth-deadline-tests.py @@ -27,15 +27,17 @@ def fixture(): runtime = (ROOT / 'runtime.rs').read_text() prep = (ROOT / 'preparation.rs').read_text() admission = (item(prep, "pub(super) struct Admission<'a>") + '\n' + - item(prep, "impl<'a> Admission<'a>")).replace('pub(super) ', '').replace('super::now_ns()', 'now_ns()') + item(prep, "impl<'a> Admission<'a>")).replace('pub(super) ', '').replace('super::now_ns()', 'now_ns()').replace('super::timeout::', '') methods = '\n'.join(item(runtime, sig) for sig in [' fn grow_compute(', ' fn finish_uninstalled_compute(']) methods = methods.replace('super::object::Allocator', 'Allocator').replace('super::freelist::Pages', 'Pages') return r''' #![allow(dead_code)] +use std::cell::Cell; use std::sync::{Mutex,MutexGuard,atomic::{AtomicBool,AtomicU64,Ordering,fence}}; type Result = std::result::Result; type KBox = Box; const EIO:i32=-5;const EAGAIN:i32=-11;const ENODEV:i32=-19;const EBUSY:i32=-16;const ECANCELED:i32=-125; +const RECOVERY_WAIT_MS:u32=26_000; static NOW:AtomicU64=AtomicU64::new(0);static ALIAS:AtomicBool=AtomicBool::new(false);static PAGES:AtomicBool=AtomicBool::new(false); static RESERVED:AtomicBool=AtomicBool::new(false);static ABORTED:AtomicBool=AtomicBool::new(false); fn now_ns()->u64{NOW.load(Ordering::SeqCst)} @@ -112,7 +114,7 @@ def fixture(): def main(): source = fixture() mutants = [('fixed', source, ''), - ('ignore-shared-deadline', source.replace('if now_ns() >= self.deadline', 'if false').replace('if remaining == 0 { return Err(EBUSY); }', ''), 'growth admission exceeded'), + ('ignore-shared-deadline', source.replace('if now_ns() >= self.deadline.get()', 'if false').replace('if remaining == 0 { return Err(EBUSY); }', ''), 'growth admission exceeded'), ('keep-growth-alias', source.replace(' drop(alias.take());', ''), 'growth aliases must precede')] with tempfile.TemporaryDirectory(prefix='g17-compute-growth-') as tmp: for name, code, expected in mutants: diff --git a/tools/asahi/qspi-nvram-tests.py b/tools/asahi/qspi-nvram-tests.py index a13ce3ac46e17..3e377466e9444 100644 --- a/tools/asahi/qspi-nvram-tests.py +++ b/tools/asahi/qspi-nvram-tests.py @@ -69,7 +69,7 @@ def function(source, signature): struct apple_qspi { bool nvram_policy, nvram_write_candidate, write_fault, nvram_window; u64 window_start, window_end; - u8 jedec[3]; u8 bp_ok; + u8 jedec[3]; u8 jedec_alt[3]; u8 bp_ok; int irq; }; struct spi_controller; @@ -164,8 +164,10 @@ def function(source, signature): struct device_node t6041={"apple,t6041-qspi"},t8140={"apple,t8140-qspi"}; machine="apple,j616s";qb=apple_qspi_nvram_write_board(&t6041,0x429118000ULL); assert(qb&&qb->nvram_start==0x700000&&qb->nvram_size==0x100000&&qb->jedec[0]==0xc2&&qb->jedec[1]==0x2b&&qb->jedec[2]==0x27&&!qb->bp_ok); + assert(qb->jedec_alt[0]==0xef&&qb->jedec_alt[1]==0x65&&qb->jedec_alt[2]==0x17); machine="apple,j700";qb=apple_qspi_nvram_write_board(&t8140,0x385110000ULL); assert(qb&&qb->nvram_start==0x24000&&qb->nvram_size==0x1d0000&&qb->jedec[2]==0x15&&qb->bp_ok==0x1c); + assert(qb->jedec_alt[0]==0xc8&&qb->jedec_alt[1]==0x83&&qb->jedec_alt[2]==0x15); puts("PASS J613/J713/J700/J616s board, controller and full-width aperture qualification (140 combinations)"); u8 data[256];memset(data,0x55,sizeof(data));reset(); struct spi_mem_op wren=SPI_MEM_OP(SPI_MEM_OP_CMD(0x06,1),SPI_MEM_OP_NO_ADDR,SPI_MEM_OP_NO_DUMMY,SPI_MEM_OP_NO_DATA); @@ -241,12 +243,55 @@ def function(source, signature): erase.addr.val=0x701000; wire_count=0;assert(!apple_qspi_exec_op(&mem,&erase)&&sent(0x20)&&!sent(0x35)); struct spi_mem_op rdcr2=SPI_MEM_OP(SPI_MEM_OP_CMD(0x35,1),SPI_MEM_OP_NO_ADDR,SPI_MEM_OP_NO_DUMMY,SPI_MEM_OP_DATA_IN(1,id,1)); - wire_count=0;assert(apple_qspi_exec_op(&mem,&rdcr2)<0&&!wire_count); + wire_count=0;assert(apple_qspi_exec_op(&mem,&rdcr2)<0&&!sent(0x35)); for(unsigned int bp=0x04;bp<=0x20;bp<<=1){reset();jedec[0]=0xc2;jedec[1]=0x2b;jedec[2]=0x27;memcpy(q.jedec,jedec,3);arm(); sr[0]=bp;wire_count=0;o=program(0x700000,1,data);assert(apple_qspi_exec_op(&mem,&o)==-EACCES&&!sent(0x06)&&!sent(0x35));} reset();memcpy(q.jedec,(u8[]){0xc2,0x2b,0x27},3);arm();wire_count=0;o=program(0x700000,1,data); assert(apple_qspi_exec_op(&mem,&o)==-ENODEV&&!sent(0x06)); puts("PASS Macronix J616s part: no 35h on the wire, SR/CR checks, BP0-BP3 refusal and JEDEC mismatch"); + /* J616s W25Q64 part: the same board entry, and 35h is its SR2 read. */ + reset();memcpy(q.jedec,(u8[]){0xc2,0x2b,0x27},3);memcpy(q.jedec_alt,jedec,3);arm();memset(data,0x55,sizeof(data)); + o=program(0x700000,256,data);wire_count=0;assert(!apple_qspi_exec_op(&mem,&o)&&sent(0x02)&&sent(0x35)); + assert(!memcmp(flash+0x700000,data,256)&&!sr[0]); + wire_count=0;assert(!apple_qspi_exec_op(&mem,&rdcr2)&&sent(0x35)); + /* A second-slot match keeps the Winbond protection checks. */ + sr[1]=0x40;wire_count=0;o=program(0x700100,1,data);assert(apple_qspi_exec_op(&mem,&o)==-EACCES&&!sent(0x06)); + sr[1]=0;jedec[2]^=1;wire_count=0;assert(apple_qspi_exec_op(&mem,&o)==-ENODEV&&!sent(0x06)); + /* An empty second slot admits nothing, even on a bus that reads zeroes. */ + reset();memset(jedec,0,3);arm();wire_count=0;o=program(0x700000,1,data); + assert(apple_qspi_exec_op(&mem,&o)==-ENODEV&&!sent(0x06)); + puts("PASS W25Q64 J616s part: second ID admitted with SR2 read and checks, third ID and empty slot refused"); + /* J700 GD25UF16E part: the second slot of the J700 entry, GigaDevice checks. */ + const u8 w25q16[3]={0xef,0x65,0x15},gd25uf16e[3]={0xc8,0x83,0x15}; + reset();memcpy(jedec,gd25uf16e,3);memcpy(q.jedec,w25q16,3);memcpy(q.jedec_alt,gd25uf16e,3);q.bp_ok=0x1c;arm(); + memset(data,0x55,sizeof(data));sr[0]=0x04;sr[1]=0x02; + o=program(0x700000,256,data);wire_count=0;assert(!apple_qspi_exec_op(&mem,&o)&&sent(0x02)&&sent(0x35)&&sent(0x15)); + assert(!memcmp(flash+0x700000,data,256)&&sr[0]==0x04&&sr[1]==0x02); + erase.addr.val=0x701000;memset(flash+0x701000,0,4096); + wire_count=0;assert(!apple_qspi_exec_op(&mem,&erase)&&sent(0x20)); + for(unsigned int i=0;i<4096;i++)assert(flash[0x701000+i]==0xff); + wire_count=0;assert(!apple_qspi_exec_op(&mem,&rdcr2)&&sent(0x35)); + /* SRP0, SRP1, LB1-LB3 and the SR3 drive, dummy and low-power bits stay as found. */ + sr[0]=0x84;sr[1]=0x3b;sr[2]=0x67;o=program(0x700200,1,data);wire_count=0; + assert(!apple_qspi_exec_op(&mem,&o)&&sent(0x02)&&flash[0x700200]==0x55); + /* Refused before WREN: WIP, WEL, BP3, BP4, CMP, SUS1 and SUS2. */ + const u8 gd_refused[][3]={{0x01,0x02,0},{0x02,0x02,0},{0x24,0x02,0},{0x44,0x02,0}, + {0x04,0x42,0},{0x04,0x82,0},{0x04,0x06,0}}; + for(unsigned int i=0;ijedec[0] == APPLE_QSPI_MFR_MACRONIX) {', '0) {'), + ('mx-eqio-read', '!ret && id[0] == APPLE_QSPI_MFR_MACRONIX', '0'), + ('jedec-alt', 'memcmp(id, qspi->jedec_alt, sizeof(id))', '1'), + ('jedec-alt-empty', '!qspi->jedec_alt[0] || ', ''), + ('gd-dispatch', 'return apple_qspi_gd_status_allows_write(sr1, sr2, bp_ok);', + 'return apple_qspi_status_allows_write(sr1, sr2, sr3, bp_ok);'), + ('gd-bp34', '!(sr1 & 0x7c & ~bp_ok)', '!(sr1 & 0x1c & ~bp_ok)'), + ('gd-sus2', '!(sr2 & 0xc4)', '!(sr2 & 0xc0)'), + ('gd-cmp', '!(sr2 & 0xc4)', '!(sr2 & 0x84)'), + ('j700-gd-id', 'APPLE_QSPI_JEDEC_GD25UF16E\t{ 0xc8, 0x83, 0x15 }', + 'APPLE_QSPI_JEDEC_GD25UF16E\t{ 0xc8, 0x83, 0x16 }'), ('read-only', 'read_only || !qspi->nvram_write_candidate || qspi->write_fault', '!qspi->nvram_write_candidate || qspi->write_fault'), ('fault-latch', 'write_fault_latched = true;', 'write_fault_latched = false;'), diff --git a/tools/testing/selftests/drivers/apple/j616s-parity.py b/tools/testing/selftests/drivers/apple/j616s-parity.py index d8835771f36c8..78b1594d5cb60 100644 --- a/tools/testing/selftests/drivers/apple/j616s-parity.py +++ b/tools/testing/selftests/drivers/apple/j616s-parity.py @@ -30,7 +30,7 @@ for device in pathlib.Path('/sys/bus/iio/devices').glob('iio:device*'): try: if (device / 'name').read_text().strip() == 'aop-sensors-als': - als += [device / 'in_illuminance_input', device / 'in_cct_input'] + als += [device / 'in_illuminance_input', device / 'in_colortemp_input'] except OSError: pass paths += als diff --git a/tools/testing/selftests/drivers/gpu/apple-afkv2/Makefile b/tools/testing/selftests/drivers/gpu/apple-afkv2/Makefile index 95677dedc897e..b593b96456b4d 100644 --- a/tools/testing/selftests/drivers/gpu/apple-afkv2/Makefile +++ b/tools/testing/selftests/drivers/gpu/apple-afkv2/Makefile @@ -4,6 +4,6 @@ export HOSTCC export AFKV2_SOURCE_ROOT := $(abspath ../../../../../..) TEST_PROGS := run-afkv2-tests.sh test-admission.py -TEST_FILES := codec.c owned-prefix.c owned-suffix.c extract-owned.py inline-edid.c extract-service.py extract-hpd.py extract-send.py extract-edid.py extract-ring.py extract-notify.py host-include +TEST_FILES := codec.c owned-prefix.c owned-suffix.c extract-owned.py inline-edid.c extract-service.py extract-hpd.py extract-send.py extract-edid.py extract-ring.py extract-notify.py extract-compact.py compact.c host-include include ../../../lib.mk diff --git a/tools/testing/selftests/drivers/gpu/apple-afkv2/README b/tools/testing/selftests/drivers/gpu/apple-afkv2/README index bffcd55fba642..0b0423fbb8e4e 100644 --- a/tools/testing/selftests/drivers/gpu/apple-afkv2/README +++ b/tools/testing/selftests/drivers/gpu/apple-afkv2/README @@ -43,3 +43,14 @@ consumes 192 bytes at a 64-byte stride, and needs a 256-byte empty ring. The ring-admission block is extracted from the real transmitter to check this. The late-publication notifier is extracted to test asynchronous hotplug queueing and connector-registration, quiesce, routing and legacy guards. + +The compact slot allocator is extracted to model DCP poweron cycles without +service teardown, on every compact endpoint (0x20-0x2f) and both DCPs, for +64 generations. A service re-announced after a poweron replaces the same +name, unit and binding in place, so the slot count stays bounded; the +hotplug endpoints 0x27-0x29 also replace within a generation. DPAVCTRL's +same-name, no-unit siblings announced in one generation stay separate, as +do different identities. Free-slot capacity, reader pins and pending +commands are checked +separately. Publication and teardown are mocked; this does not test firmware +power transitions or concurrent service users. diff --git a/tools/testing/selftests/drivers/gpu/apple-afkv2/compact.c b/tools/testing/selftests/drivers/gpu/apple-afkv2/compact.c new file mode 100644 index 0000000000000..815748791fd1d --- /dev/null +++ b/tools/testing/selftests/drivers/gpu/apple-afkv2/compact.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* Host fixture: the slot allocator is extracted from afk.c at build time. */ +#undef NDEBUG +#include +#include +#include +#include +#include + +typedef uint32_t u32; +typedef int64_t s64; +#define MAX_PENDING_CMDS 8 +#define READ_ONCE(x) (x) +#define dev_info(...) do { } while (0) +#define spin_lock_irqsave(lock, flags) do { (void)(lock); (flags) = 0; } while (0) +#define spin_unlock_irqrestore(lock, flags) do { (void)(lock); (void)(flags); } while (0) +#define bitmap_empty(map, bits) ((void)(bits), *(map) == 0) + +struct apple_epic_service; +struct apple_epic_service_ops { + void (*teardown)(struct apple_epic_service *service); +}; + +struct apple_epic_service { + bool enabled, torndown, debugfs; + unsigned int users, channel, lock; + unsigned long cmd_map[1]; + const struct apple_epic_service_ops *ops; + char name[33]; + s64 unit; + u32 power_gen; +}; + +struct apple_dcp { + void *dev; + u32 afk_power_gen; +}; + +struct apple_dcp_afkep { + struct apple_dcp *dcp; + u32 endpoint, num_channels; + struct apple_epic_service services[AFK_MAX_CHANNEL]; +}; + +static unsigned int teardowns; + +static void afk_remove_service_debugfs(struct apple_epic_service *service) +{ + assert(service->enabled && service->debugfs); + service->debugfs = false; +} + +static void afk_service_retire(struct apple_epic_service *service) +{ + assert(service->enabled && !service->debugfs); + service->enabled = false; + service->torndown = true; +} + +static void teardown(struct apple_epic_service *service) +{ + assert(!service->enabled && service->torndown && !service->debugfs); + teardowns++; +} + +/* PRODUCTION_SLOT */ + +static const struct apple_epic_service_ops ops = { .teardown = teardown }; +static const struct apple_epic_service_ops other_ops; + +/* Model publication after allocation; poweroff performs no AFK teardown. */ +static struct apple_epic_service * +announce(struct apple_dcp_afkep *ep, const char *name, s64 unit, + unsigned int interface) +{ + struct apple_epic_service *service = afk_compact_slot(ep, &ops, name, unit); + + assert(service); + service->ops = &ops; + strcpy(service->name, name); + service->unit = unit; + service->channel = interface; + service->enabled = true; + service->torndown = false; + service->debugfs = true; + return service; +} + +/* What one DCP poweron announces on an endpoint. */ +#define SIBLINGS 4 +static unsigned int poweron_announce(struct apple_dcp_afkep *ep, + unsigned int interface) +{ + bool hotplug = ep->endpoint >= 0x27 && ep->endpoint <= 0x29; + + announce(ep, "dcpav-service-epic", 0, interface++); + announce(ep, "dcpdp-service-epic", 0, interface++); + announce(ep, "dcpav-video-interface-epi", -1, interface++); + /* DPAVCTRL-style siblings: same name, no unit, one generation. */ + if (!hotplug) + for (unsigned int i = 0; i < SIBLINGS; i++) + announce(ep, "dcpav-controller-epic:", -1, interface++); + return interface; +} + +/* Every endpoint, both DCPs, more power cycles than there are slots. */ +static void power_cycle_test(u32 endpoint) +{ + struct apple_dcp dcps[2] = { 0 }; + struct apple_dcp_afkep eps[2] = { { .dcp = &dcps[0], .endpoint = endpoint }, + { .dcp = &dcps[1], .endpoint = endpoint } }; + bool hotplug = endpoint >= 0x27 && endpoint <= 0x29; + unsigned int per_gen = hotplug ? 3 : 3 + SIBLINGS; + unsigned int interface[2] = { 1, 1 }, cycles = 64; + unsigned int before = teardowns; + + for (unsigned int cycle = 0; cycle < cycles; cycle++) { + for (unsigned int d = 0; d < 2; d++) { + struct apple_dcp_afkep *ep = &eps[d]; + unsigned int first = interface[d], enabled = 0; + + dcps[d].afk_power_gen++; /* iomfb_poweron() */ + interface[d] = poweron_announce(ep, first); + assert(ep->num_channels == per_gen); + for (unsigned int i = 0; i < ep->num_channels; i++) { + struct apple_epic_service *s = &ep->services[i]; + + if (!s->enabled) + continue; + enabled++; + /* Only this generation's interfaces are bound. */ + assert(s->channel >= first && s->channel < interface[d]); + assert(s->power_gen == dcps[d].afk_power_gen); + } + assert(enabled == per_gen); + } + } + assert(teardowns - before == 2 * per_gen * (cycles - 1)); +} + +/* Hotplug endpoints also replace within one poweron generation. */ +static void hotplug_test(void) +{ + struct apple_dcp dcp = { .afk_power_gen = 1 }; + struct apple_dcp_afkep ep = { .dcp = &dcp, .endpoint = 0x28 }; + struct apple_epic_service *av = announce(&ep, "dcpav-service-epic", 0, 1); + + for (unsigned int i = 0; i < 2 * AFK_MAX_CHANNEL; i++) + assert(announce(&ep, "dcpav-service-epic", 0, 3 + i) == av); + assert(ep.num_channels == 1 && av->channel == 2 + 2 * AFK_MAX_CHANNEL); +} + +/* Same-generation siblings are not replacements on non-hotplug endpoints. */ +static void controller_test(void) +{ + struct apple_dcp dcp = { .afk_power_gen = 7 }; + struct apple_dcp_afkep ep = { .dcp = &dcp, .endpoint = 0x24 }; + unsigned int before = teardowns; + + for (unsigned int i = 0; i < 4; i++) + assert(announce(&ep, "dcpav-controller-epic:", -1, 2 * i + 1) == + &ep.services[i]); + assert(ep.num_channels == 4 && teardowns == before); + for (unsigned int i = 0; i < 4; i++) + assert(ep.services[i].enabled && ep.services[i].channel == 2 * i + 1); + /* After the next poweron each sibling replaces one from before. */ + dcp.afk_power_gen++; + for (unsigned int i = 0; i < 4; i++) + assert(announce(&ep, "dcpav-controller-epic:", -1, 20 + i) == + &ep.services[i]); + assert(ep.num_channels == 4 && teardowns == before + 4); +} + +static void identity_test(void) +{ + struct apple_dcp dcp = { .afk_power_gen = 1 }; + struct apple_dcp_afkep ep = { .dcp = &dcp, .endpoint = 0x2a }; + struct apple_epic_service *first, *second, *third; + + first = announce(&ep, "dcpav-service-epic", 0, 1); + second = announce(&ep, "dcpav-service-epic", 1, 3); + third = announce(&ep, "dcpdp-service-epic", 0, 5); + assert(first != second && first != third && second != third); + dcp.afk_power_gen++; + assert(announce(&ep, "dcpav-service-epic", 0, 7) == first); + assert(second->channel == 3 && third->channel == 5); + /* A different binding must not take over the same name and unit. */ + assert(afk_compact_slot(&ep, &other_ops, "dcpav-service-epic", 0) == + &ep.services[3]); + /* No-unit names remain distinct from unit zero. */ + assert(announce(&ep, "dcpav-service-epic", -1, 9) == &ep.services[3]); +} + +static void free_slot_test(void) +{ + struct apple_dcp dcp = { 0 }; + struct apple_dcp_afkep ep = { .dcp = &dcp, .endpoint = 0x2a }; + + ep.num_channels = AFK_MAX_CHANNEL; + for (unsigned int i = 0; i < AFK_MAX_CHANNEL; i++) + ep.services[i].enabled = true; + assert(!afk_compact_slot(&ep, &ops, "new", 0)); + ep.services[2].enabled = false; + ep.services[2].users = 1; + assert(!afk_compact_slot(&ep, &ops, "new", 0)); + ep.services[2].users = 0; + ep.services[2].cmd_map[0] = 1; + assert(!afk_compact_slot(&ep, &ops, "new", 0)); + ep.services[2].cmd_map[0] = 0; + assert(afk_compact_slot(&ep, &ops, "new", 0) == &ep.services[2]); +} + +int main(void) +{ + for (u32 endpoint = 0x20; endpoint <= 0x2f; endpoint++) + power_cycle_test(endpoint); + hotplug_test(); + controller_test(); + identity_test(); + free_slot_test(); + puts("PASS: compact slots: 64 poweron cycles, 16 endpoints, 2 DCPs"); + return 0; +} diff --git a/tools/testing/selftests/drivers/gpu/apple-afkv2/extract-compact.py b/tools/testing/selftests/drivers/gpu/apple-afkv2/extract-compact.py new file mode 100644 index 0000000000000..4b3fbf1b810fe --- /dev/null +++ b/tools/testing/selftests/drivers/gpu/apple-afkv2/extract-compact.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-only OR MIT +"""Exercise the production compact slot allocator across DCP power cycles. + +Poweroff leaves compact services enabled; poweron announces fresh interfaces +without teardown. Synchronization, debugfs and the owner teardown are mocked. +""" +import hashlib +from pathlib import Path +import re +import sys + +source = Path(sys.argv[1]).read_text() +start = source.index("static struct apple_epic_service *\nafk_compact_slot(") +end = source.index("\nstatic void afk_recv_handle_compact_init(", start) +body = source[start:end] +header = Path(sys.argv[1]).with_name("afk.h").read_text() +limit = re.search(r"^#define AFK_MAX_CHANNEL\s+(\d+)$", header, re.M).group(1) +directory = Path(__file__).resolve().parent +fixture = (directory / "compact.c").read_text() +assert fixture.count("/* PRODUCTION_SLOT */") == 1 +Path(sys.argv[2]).write_text("#define AFK_MAX_CHANNEL " + limit + "\n" + + fixture.replace("/* PRODUCTION_SLOT */", body)) +print("Production compact slot SHA256:", hashlib.sha256(body.encode()).hexdigest()) diff --git a/tools/testing/selftests/drivers/gpu/apple-afkv2/run-afkv2-tests.sh b/tools/testing/selftests/drivers/gpu/apple-afkv2/run-afkv2-tests.sh index 5351b80edbcc5..179d8e15d2f6f 100755 --- a/tools/testing/selftests/drivers/gpu/apple-afkv2/run-afkv2-tests.sh +++ b/tools/testing/selftests/drivers/gpu/apple-afkv2/run-afkv2-tests.sh @@ -83,7 +83,9 @@ $afkv2_cc -std=gnu11 -Wall -Wextra -Werror ${CFLAGS:-} $afkv2_sanitizers \ "$afkv2_root/drivers/gpu/drm/apple/afk.c" "$afkv2_tmp/ring.c" "$afkv2_python" "$afkv2_dir/extract-notify.py" \ "$afkv2_root/drivers/gpu/drm/apple/epic/dpavservep.c" "$afkv2_tmp/notify.c" -for afkv2_test in ring notify; do +"$afkv2_python" "$afkv2_dir/extract-compact.py" \ + "$afkv2_root/drivers/gpu/drm/apple/afk.c" "$afkv2_tmp/compact.c" +for afkv2_test in ring notify compact; do # shellcheck disable=SC2086 $afkv2_cc -std=gnu11 -Wall -Wextra -Werror ${CFLAGS:-} $afkv2_sanitizers \ -I"$afkv2_dir/host-include" -I"$afkv2_root/drivers/gpu/drm/apple" \ diff --git a/tools/testing/selftests/drivers/gpu/apple-dcp/pm.py b/tools/testing/selftests/drivers/gpu/apple-dcp/pm.py index 37537310d333e..8cae88d722d88 100644 --- a/tools/testing/selftests/drivers/gpu/apple-dcp/pm.py +++ b/tools/testing/selftests/drivers/gpu/apple-dcp/pm.py @@ -558,6 +558,27 @@ def function(text, name): init_mux = block(core, 'VISIBLE_IF_KUNIT int cd321x_init_mux(') production += init_mux.replace('VISIBLE_IF_KUNIT', 'static', 1) + '\n' production += function(core, 'cd321x_register_port') + '\n' + function(core, 'cd321x_unregister_port') + # A port that probed without its USB4/Thunderbolt router keeps watching for it. + if 'cd321x_tbt_watch_late(' in core: + mocks = mocks.replace(' bool state_valid,tbt_notifier_registered;\n', + ' bool state_valid,tbt_notifier_registered;\n' + ' struct work tbt_attach_work;\n struct fwnode_handle *tbt_fwnode;\n' + ' struct notifier_block tbt_watch;\n bool tbt_watch_registered;\n', 1) + mocks = mocks.replace('static void cd321x_stop_work(struct cd321x *c) {\n', r'''#define INIT_WORK(p,fn) ((p)->pending=false) +#define dev_warn(...) ((void)0) +static int watches, watch_error; +/* Like the real watch, hold the port fwnode until the port is unregistered. */ +static int cd321x_tbt_watch_late(struct cd321x *c,struct fwnode_handle *f) { + if(watch_error)return watch_error; + f->refs++;c->tbt_fwnode=f;c->tbt_watch_registered=true;watches++;return 0; +} +static void cd321x_stop_work(struct cd321x *c) { + if(c->tbt_watch_registered){assert(watches>0);watches--;c->tbt_watch_registered=false;} +''', 1) + assert 'cd321x_tbt_watch_late(struct cd321x' in mocks and 'tbt_watch_registered;' in mocks + late_watch = True + else: + late_watch = False controls = r''' static void reset(struct cd321x *c) { memset(c,0,sizeof(*c));connector.refs=0; @@ -708,6 +729,29 @@ def function(text, name): puts("PASS actual held mux gives up after its retries until an event; other failures end the hold-up"); ''') + if late_watch: + quiet = ' mux_error=notifier_error=switch_error=0;' + assert controls.count(quiet) == 1 + controls = controls.replace(quiet, ' assert(!watches);watch_error=0;\n' + quiet, 1) + even = ' assert(!ports&&!altmodes&&!muxes&&!switches&&!notifiers&&!connector.refs);\n}' + assert controls.count(even) == 1 + controls = controls.replace(even, even[:-2] + '\n assert(!watches);\n}', 1) + optional = ' assert(cd321x_register_port(&c.tps,&connector)==0&&c.state_valid&&!c.tbt_switch);\n cd321x_unregister_port(&c.tps);balanced();\n' + assert controls.count(optional) == 1 + controls = controls.replace(optional, r''' assert(cd321x_register_port(&c.tps,&connector)==0&&c.state_valid&&!c.tbt_switch); + /* ...and the port keeps watching for a router that binds later. */ + assert(watches==1&&c.tbt_watch_registered&&c.tbt_fwnode==&connector); + cd321x_unregister_port(&c.tps);balanced(); + /* A watch that cannot start leaves the port probed without it. */ + reset(&c);switch_error=-EPROBE_DEFER;keep_waiting=false;watch_error=-ENOMEM; + assert(cd321x_register_port(&c.tps,&connector)==0&&c.state_valid&&!c.tbt_switch); + assert(!watches&&!c.tbt_watch_registered&&!c.tbt_fwnode); + cd321x_unregister_port(&c.tps);balanced(); + /* A router present at probe needs no watch. */ + reset(&c);assert(cd321x_register_port(&c.tps,&connector)==0&&c.tbt_switch&&!watches); + cd321x_unregister_port(&c.tps);balanced(); +''', 1) + return prefix + pm + mocks + production + '\n#define TEST_DEFER 1\n#define TEST_FWNODE 1\n' + controls