diff --git a/Documentation/devicetree/bindings/gpu/apple,agx.yaml b/Documentation/devicetree/bindings/gpu/apple,agx.yaml index 7a1ef097abe0b..cd70f456cde18 100644 --- a/Documentation/devicetree/bindings/gpu/apple,agx.yaml +++ b/Documentation/devicetree/bindings/gpu/apple,agx.yaml @@ -23,6 +23,7 @@ properties: - apple,agx-t6050 - apple,agx-t8132 - apple,agx-t8140 + - apple,agx-t8142 - items: - const: apple,agx-g17c - const: apple,agx-g17s @@ -83,16 +84,11 @@ properties: - description: Shared global variables, preserved firmware data or text segment of the loaded GPU firmware + - description: Additional firmware crash-log data on T8142 memory-region-names: minItems: 3 - items: - - const: ttbs - - const: pagetables - - const: handoff - - enum: [hw-cal-a, shared-l2, fw-data] - - enum: [hw-cal-b, fw-text, l2-pagetables] - - enum: [globals, fw-data, fw-text] + maxItems: 7 apple,clpc: $ref: /schemas/types.yaml#/definitions/phandle @@ -536,7 +532,7 @@ allOf: - apple,agx-t6050 - apple,agx-t8132 - apple,agx-t8140 - - apple,agx-g17s + - apple,agx-t8142 then: properties: reg: @@ -562,6 +558,64 @@ allOf: required: - apple,firmware-abi + - if: + properties: + compatible: + contains: + const: apple,agx-t8142 + then: + properties: + reg: + items: + - description: GFX coprocessor control registers + - description: GPU block MMIO registers + reg-names: + items: + - const: asc + - const: sgx + mboxes: + items: + - description: GFX coprocessor mailbox + - description: GFX1 coprocessor mailbox + memory-region: + items: + - description: GPU MMU TTBs + - description: GPU MMU page tables + - description: Shared GPU MMU handoff structure + - description: Shared L2 page tables + - description: GFX firmware data + - description: GFX1 firmware data + - description: Combined firmware data and shared read-only crash logs + memory-region-names: + items: + - const: ttbs + - const: pagetables + - const: handoff + - const: shared-l2 + - const: gfx-data + - const: gfx1-data + - const: fw-data + required: + - reg-names + - mboxes + - memory-region + - memory-region-names + - power-domains + - operating-points-v2 + else: + properties: + memory-region: + maxItems: 6 + memory-region-names: + minItems: 3 + items: + - const: ttbs + - const: pagetables + - const: handoff + - enum: [hw-cal-a, shared-l2, fw-data] + - enum: [hw-cal-b, fw-text, l2-pagetables] + - enum: [globals, fw-data, fw-text] + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/i2c/apple,i2c.yaml b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml index f2e16482d9218..6c649719118af 100644 --- a/Documentation/devicetree/bindings/i2c/apple,i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml @@ -31,6 +31,7 @@ properties: - apple,t8122-i2c - apple,t8132-i2c - apple,t8140-i2c + - apple,t8142-i2c - const: apple,t8103-i2c - items: - enum: diff --git a/Documentation/devicetree/bindings/iio/light/apple,aop-als.yaml b/Documentation/devicetree/bindings/iio/light/apple,aop-als.yaml index f714c1c7e1327..95d68076b116e 100644 --- a/Documentation/devicetree/bindings/iio/light/apple,aop-als.yaml +++ b/Documentation/devicetree/bindings/iio/light/apple,aop-als.yaml @@ -22,6 +22,7 @@ select: - apple,t6020-aop-als - apple,t6050-aop-als - apple,t8112-aop-als + - apple,t8142-aop-als required: - compatible @@ -32,6 +33,7 @@ properties: - apple,t6020-aop-als - apple,t6050-aop-als - apple,t8112-aop-als + - apple,t8142-aop-als - const: apple,aop-als required: diff --git a/Documentation/devicetree/bindings/net/wireless/apple,centauri.yaml b/Documentation/devicetree/bindings/net/wireless/apple,centauri.yaml index f73dd9afceca1..8d226eec13091 100644 --- a/Documentation/devicetree/bindings/net/wireless/apple,centauri.yaml +++ b/Documentation/devicetree/bindings/net/wireless/apple,centauri.yaml @@ -17,11 +17,22 @@ description: | bootstrap. This binding does not authorize adopting an existing live firmware session or releasing another owner's retained DART streams. + The T8142 native transport uses the same PCI function IDs but is a + different firmware profile. Its SoC-specific compatible identifies this + binding profile; the generic PCI compatible is retained as the fallback. + Runtime driver selection continues to use the PCI ID and host SoC, and the + native driver selects personalized firmware and transport data from its + root-board match table rather than the T6050 wire-protocol properties. + properties: compatible: - enum: - - pci106b,1900 - - pci106b,1901 + oneOf: + - enum: + - pci106b,1900 + - pci106b,1901 + - items: + - const: apple,t8142-centauri-control + - const: pci106b,1900 reg: maxItems: 1 @@ -40,11 +51,25 @@ properties: const: 27 description: Shared firmware wire protocol profile +allOf: + - if: + properties: + compatible: + contains: + const: apple,t8142-centauri-control + then: + properties: + firmware-name: false + apple,centauri-platform-id: false + apple,centauri-protocol: false + else: + required: + - firmware-name + - apple,centauri-platform-id + - apple,centauri-protocol + required: - compatible - reg - - firmware-name - - apple,centauri-platform-id - - apple,centauri-protocol additionalProperties: false diff --git a/Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml index e2bec4d954de9..bfa8894eac727 100644 --- a/Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml @@ -29,6 +29,10 @@ properties: - apple,t8140-pinctrl - apple,t8152-pinctrl - const: apple,t8103-pinctrl + - items: + - const: apple,t8142-pinctrl + - const: apple,t8140-pinctrl + - const: apple,t8103-pinctrl - items: - const: apple,t6050-pinctrl - const: apple,t8132-pinctrl diff --git a/Documentation/devicetree/bindings/soc/apple/apple,t8152-aop.yaml b/Documentation/devicetree/bindings/soc/apple/apple,t8152-aop.yaml index 32b0a2e631bc9..2b1148961368c 100644 --- a/Documentation/devicetree/bindings/soc/apple/apple,t8152-aop.yaml +++ b/Documentation/devicetree/bindings/soc/apple/apple,t8152-aop.yaml @@ -75,6 +75,29 @@ properties: description: The lid angle sensor service. unevaluatedProperties: false +allOf: + - if: + properties: + compatible: + contains: + const: apple,t8142-aop + then: + properties: + als: + properties: + compatible: + items: + - const: apple,t8142-aop-als + - const: apple,aop-als + else: + properties: + als: + properties: + compatible: + not: + contains: + const: apple,t8142-aop-als + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/spi/apple,spi.yaml b/Documentation/devicetree/bindings/spi/apple,spi.yaml index 62d5afda0d310..70954d834fa8c 100644 --- a/Documentation/devicetree/bindings/spi/apple,spi.yaml +++ b/Documentation/devicetree/bindings/spi/apple,spi.yaml @@ -27,6 +27,7 @@ properties: - apple,t8122-spi - apple,t8132-spi - apple,t8140-spi + - apple,t8142-spi - const: apple,t8103-spi - items: - enum: diff --git a/arch/arm64/boot/dts/apple/t8142-j813-audio.dtsi b/arch/arm64/boot/dts/apple/t8142-j813-audio.dtsi index 892155da27ee0..c345bc3ff50ac 100644 --- a/arch/arm64/boot/dts/apple/t8142-j813-audio.dtsi +++ b/arch/arm64/boot/dts/apple/t8142-j813-audio.dtsi @@ -210,13 +210,6 @@ * (setup port) and 11 (admac-leap-s) on the raw boot. As on T8140, the * firmware's own mappings own the first slot, host buffers go above it. */ - aop_dart: iommu@390fc0000 { - compatible = "apple,t8142-dart", "apple,t8110-dart"; - reg = <0x3 0x90fc0000 0x0 0xc000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - }; admac_base_ns: dma-controller@393800000 { compatible = "apple,t8140-admac"; @@ -415,3 +408,7 @@ }; }; }; + +&aop_dart { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/apple/t8142-j813-avd.dtsi b/arch/arm64/boot/dts/apple/t8142-j813-avd.dtsi index 5672ebb885a51..3dd7ff576fea4 100644 --- a/arch/arm64/boot/dts/apple/t8142-j813-avd.dtsi +++ b/arch/arm64/boot/dts/apple/t8142-j813-avd.dtsi @@ -33,13 +33,9 @@ reg-names = "code", "sram", "mbox", "ctrl"; iommus = <&avd_dart 0>, <&avd_dart 1>, <&avd_dart 2>; }; +}; - avd_dart: iommu@501020000 { - compatible = "apple,t8142-dart", "apple,t8110-dart"; - reg = <0x5 0x01020000 0x0 0x20000>; - #iommu-cells = <1>; - interrupt-parent = <&aic>; - interrupts = ; - power-domains = <&ps_avd_sys>; - }; +&avd_dart { + power-domains = <&ps_avd_sys>; + status = "okay"; }; diff --git a/arch/arm64/boot/dts/apple/t8142-j813-dcpext.dtsi b/arch/arm64/boot/dts/apple/t8142-j813-dcpext.dtsi new file mode 100644 index 0000000000000..983793a03769d --- /dev/null +++ b/arch/arm64/boot/dts/apple/t8142-j813-dcpext.dtsi @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * External displays of the T8142 MacBook Airs (J813, J815): DisplayPort alt + * mode on the two USB-C ports. + * + * iBoot preloads both external display processors with the internal DCP's + * image and leaves them running idle. The boot loader checks each one and + * hands it over: it reserves the firmware, publishes its version and enables + * the processor, its mailbox, its DARTs and its Type-C route together. Until + * then everything here stays disabled and the ports are plain USB. + * + * dcpext0 serves the front port (ATC0), dcpext1 the rear port (ATC1): one + * processor per port, so two displays need no arbitration. Crossbar source + * numbers are twice the ADT dp-switch-ufp-endpoint (dcpext0 1, dcpext1 2). + * Addresses and interrupts are from the J815AP ADT (the J813AP 27.0 ADT is + * identical in every node used here); the bandwidth scratch + * slots are the /arm-io/pmgr bwr-agent indexes of DISP_EXT0 (3) and DISP_EXT1 + * (4) at 0x20000 + n * 0x4000. The T8142 topology follows the J704's. + */ + +/ { + aliases { + dcpext0 = &dcpext0; + dcpext1 = &dcpext1; + }; +}; + +&{/soc} { + pmgr_dcpext0: power-management@38272c000 { + reg = <3 0x8272c000 0 0x8>, <3 0x827b0000 0 0x4>; + reg-names = "dcp-bw-scratch", "dcp-bw-doorbell"; + #apple,bw-scratch-cells = <3>; + #apple,bw-doorbell-cells = <2>; + }; + + pmgr_dcpext1: power-management@382730000 { + reg = <3 0x82730000 0 0x8>, <3 0x827b4000 0 0x4>; + reg-names = "dcp-bw-scratch", "dcp-bw-doorbell"; + #apple,bw-scratch-cells = <3>; + #apple,bw-doorbell-cells = <2>; + }; + + dcpext0_mbox: mailbox@506e08000 { + compatible = "apple,t8142-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <5 0x06e08000 0 0x4000>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + status = "disabled"; + }; + + dcpext0: dcp@506e00000 { + compatible = "apple,t8142-dcpext", "apple,dcpext"; + reg = <5 0x06e00000 0 0x4000>, + <5 0x04000000 0 0xb1c000>, + <5 0x06240000 0 0x10000>, + <5 0x063ac000 0 0x4000>, + <5 0x06800000 0 0x800000>, + <3 0x82700000 0 0x114000>, + <5 0x06850000 0 0x4000>; + reg-names = "coproc", "disp-0", "disp-1", "disp-2", + "disp-3", "disp-4", "iop-vbar"; + mboxes = <&dcpext0_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext0_dart 23>; + clocks = <&clkref>; + apple,bw-scratch = <&pmgr_dcpext0 0 5 0>; + apple,bw-doorbell = <&pmgr_dcpext0 1 6>; + apple,iomfb-surfaces = <0 0 1 0>; + apple,dcp-index = <1>; + apple,connector-type = "USB-C"; + apple,typec-dptx-phys = <0>; + apple,typec-mux-indices = <2>; + phys = <&atcphy0 PHY_TYPE_DP>; + phy-names = "typec0"; + mux-controls = <&dpxbar0 0>; + mux-control-names = "typec0"; + /* Enabled by the boot loader once it has checked the session. */ + status = "disabled"; + #address-cells = <2>; + #size-cells = <2>; + + piodma { + iommus = <&dispext0_dart 16>; + }; + + typec-routes { + #address-cells = <1>; + #size-cells = <0>; + + route@0 { + reg = <0>; + mode-switch; + status = "disabled"; + + port { + dcpext0_typec0: endpoint { + remote-endpoint = <&typec0_display>; + }; + }; + }; + }; + }; + + dcpext1_mbox: mailbox@3aae08000 { + compatible = "apple,t8142-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <3 0xaae08000 0 0x4000>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + status = "disabled"; + }; + + dcpext1: dcp@3aae00000 { + compatible = "apple,t8142-dcpext", "apple,dcpext"; + reg = <3 0xaae00000 0 0x4000>, + <3 0xa8000000 0 0xb1c000>, + <3 0xaa240000 0 0x10000>, + <3 0xaa3ac000 0 0x4000>, + <3 0xaa800000 0 0x800000>, + <3 0x82700000 0 0x114000>, + <3 0xaa850000 0 0x4000>; + reg-names = "coproc", "disp-0", "disp-1", "disp-2", + "disp-3", "disp-4", "iop-vbar"; + mboxes = <&dcpext1_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext1_dart 23>; + clocks = <&clkref>; + apple,bw-scratch = <&pmgr_dcpext1 0 5 0>; + apple,bw-doorbell = <&pmgr_dcpext1 1 6>; + apple,iomfb-surfaces = <0 0 1 0>; + apple,dcp-index = <2>; + apple,connector-type = "USB-C"; + apple,typec-dptx-phys = <1>; + apple,typec-mux-indices = <4>; + phys = <&atcphy1 PHY_TYPE_DP>; + phy-names = "typec0"; + mux-controls = <&dpxbar1 0>; + mux-control-names = "typec0"; + /* Enabled by the boot loader once it has checked the session. */ + status = "disabled"; + #address-cells = <2>; + #size-cells = <2>; + + piodma { + iommus = <&dispext1_dart 16>; + }; + + typec-routes { + #address-cells = <1>; + #size-cells = <0>; + + route@0 { + reg = <0>; + mode-switch; + status = "disabled"; + + port { + dcpext1_typec1: endpoint { + remote-endpoint = <&typec1_display>; + }; + }; + }; + }; + }; + + /* Each ATC's display crossbar sits behind its PHY's core window. */ + dpxbar0: mux-controller@40304c000 { + compatible = "apple,t8142-display-crossbar"; + reg = <4 0x0304c000 0 0x4000>; + #mux-control-cells = <1>; + power-domains = <&ps_atc0_usb>; + }; + + dpxbar1: mux-controller@40b04c000 { + compatible = "apple,t8142-display-crossbar"; + reg = <4 0x0b04c000 0 0x4000>; + #mux-control-cells = <1>; + power-domains = <&ps_atc1_usb>; + }; +}; + +/* + * DisplayPort needs the LIOA bank (in the AXI2AF window) for the calibration + * the boot loader copies from the ADT. Without both, the PHY stays USB only. + */ +&atcphy0 { + reg = <4 0x03000000 0 0x4c000>, + <4 0x03050000 0 0x8000>, + <4 0x00000000 0 0x8000>, + <4 0x02a90000 0 0x4000>, + <4 0x02a84000 0 0x4000>, + <4 0x00020000 0 0x4000>; + reg-names = "core", "lpdptx", "axi2af", "usb2phy", "pipehandler", "lioa"; +}; + +&atcphy1 { + reg = <4 0x0b000000 0 0x4c000>, + <4 0x0b050000 0 0x8000>, + <4 0x08000000 0 0x8000>, + <4 0x0aa90000 0 0x4000>, + <4 0x0aa84000 0 0x4000>, + <4 0x08020000 0 0x4000>; + reg-names = "core", "lpdptx", "axi2af", "usb2phy", "pipehandler", "lioa"; +}; + +&typec0 { + ports { + port@3 { + reg = <3>; + + typec0_display: endpoint { + remote-endpoint = <&dcpext0_typec0>; + }; + }; + }; +}; + +&typec1 { + ports { + port@3 { + reg = <3>; + + typec1_display: endpoint { + remote-endpoint = <&dcpext1_typec1>; + }; + }; + }; +}; + +/* Scanout and PIODMA share the first register window, as on disp0. */ +&dispext0_dart { + reg = <5 0x06300000 0 0xc000>; + apple,dma-range = <0x100 0x0 0x10 0x0>; +}; + +&dcpext0_dart { + apple,dma-range = <0x100 0x0 0x10 0x0>; +}; + +&dispext1_dart { + reg = <3 0xaa300000 0 0xc000>; + apple,dma-range = <0x100 0x0 0x10 0x0>; +}; + +&dcpext1_dart { + apple,dma-range = <0x100 0x0 0x10 0x0>; +}; diff --git a/arch/arm64/boot/dts/apple/t8142-j813-display.dtsi b/arch/arm64/boot/dts/apple/t8142-j813-display.dtsi index 812b558be0ee6..650517b561734 100644 --- a/arch/arm64/boot/dts/apple/t8142-j813-display.dtsi +++ b/arch/arm64/boot/dts/apple/t8142-j813-display.dtsi @@ -44,23 +44,6 @@ #mbox-cells = <0>; }; - disp0_dart: iommu@286300000 { - compatible = "apple,t8142-dart", "apple,t8110-dart"; - reg = <2 0x86300000 0 0xc000>; - interrupts = ; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x10 0x0>; - status = "disabled"; - }; - - dcp_dart: iommu@286340000 { - compatible = "apple,t8142-dart", "apple,t8110-dart"; - reg = <2 0x86340000 0 0x20000>; - interrupts = ; - #iommu-cells = <1>; - apple,dma-range = <0x100 0x0 0x10 0x0>; - }; - dcp: dcp@286e00000 { compatible = "apple,t8142-dcp", "apple,dcp"; mboxes = <&dcp_mbox>; @@ -114,6 +97,16 @@ }; }; +&disp0_dart { + reg = <2 0x86300000 0 0xc000>; + apple,dma-range = <0x100 0x0 0x10 0x0>; +}; + +&dcp_dart { + apple,dma-range = <0x100 0x0 0x10 0x0>; + status = "okay"; +}; + / { /* * The DCP firmware's clocks 585 and 431 (/arm-io/disp0 clock-ids). The diff --git a/arch/arm64/boot/dts/apple/t8142-j813-n1.dtsi b/arch/arm64/boot/dts/apple/t8142-j813-n1.dtsi index 052491f27233b..e99e7876e7c66 100644 --- a/arch/arm64/boot/dts/apple/t8142-j813-n1.dtsi +++ b/arch/arm64/boot/dts/apple/t8142-j813-n1.dtsi @@ -36,12 +36,8 @@ msi-controller; msi-ranges = <&aic AIC_IRQ 1741 IRQ_TYPE_EDGE_RISING 32>; }; +}; - pcie0_dart: iommu@488000000 { - compatible = "apple,t8142-dart", "apple,t8110-dart"; - reg = <4 0x88000000 0 0x20000>; - interrupt-parent = <&aic>; - interrupts = ; - #iommu-cells = <1>; - }; +&pcie0_dart { + status = "okay"; }; diff --git a/arch/arm64/boot/dts/apple/t8142-j813-peripherals.dtsi b/arch/arm64/boot/dts/apple/t8142-j813-peripherals.dtsi index e5220708202e8..d4293c35b601b 100644 --- a/arch/arm64/boot/dts/apple/t8142-j813-peripherals.dtsi +++ b/arch/arm64/boot/dts/apple/t8142-j813-peripherals.dtsi @@ -28,81 +28,70 @@ }; }; -&{/soc} { - pmgr: power-management@380700000 { - compatible = "apple,t8142-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd"; - /* As on T8140: up to the ISP17a slots at +0x4000..+0x4060. */ - reg = <3 0x80700000 0 0x14000>; - #address-cells = <1>; - #size-cells = <1>; - - ps_fpwm0: power-controller@330 { - compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; - reg = <0x330 4>; - #power-domain-cells = <0>; - #reset-cells = <0>; - label = "fpwm0"; - }; +&pmgr { + /* As on T8140: up to the ISP17a slots at +0x4000..+0x4060. */ + reg = <3 0x80700000 0 0x14000>; + status = "okay"; + + ps_fpwm0: power-controller@330 { + compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; + reg = <0x330 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "fpwm0"; + }; - /* ADT pmgr devices: SPI_P id 94 (+0x390), QSPI id 120 (+0x460). */ - ps_spi_p: power-controller@390 { - compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; - reg = <0x390 4>; - #power-domain-cells = <0>; - #reset-cells = <0>; - label = "spi_p"; - }; + /* ADT pmgr devices: SPI_P id 94 (+0x390), QSPI id 120 (+0x460). */ + ps_spi_p: power-controller@390 { + compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; + reg = <0x390 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "spi_p"; + }; - /* ADT pmgr devices: PMP id 159 (+0x598), PMS_SRAM id 160 (+0x5a0). */ - ps_pmp: power-controller@598 { - compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; - reg = <0x598 4>; - #power-domain-cells = <0>; - #reset-cells = <0>; - label = "pmp"; - /* The PMP's SRAM, which the driver reads first. */ - power-domains = <&ps_pms_sram>; - /* - * As on T8140/T8132: the PMP firmware keeps running. If genpd - * gates this domain at s2idle, the PMP crashes on its own MMIO. - */ - apple,always-on; - }; + /* ADT pmgr devices: PMP id 159 (+0x598), PMS_SRAM id 160 (+0x5a0). */ + ps_pmp: power-controller@598 { + compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; + reg = <0x598 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "pmp"; + /* The PMP's SRAM, which the driver reads first. */ + power-domains = <&ps_pms_sram>; + /* + * As on T8140/T8132: the PMP firmware keeps running. If genpd + * gates this domain at s2idle, the PMP crashes on its own MMIO. + */ + apple,always-on; + }; - ps_pms_sram: power-controller@5a0 { - compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; - reg = <0x5a0 4>; - #power-domain-cells = <0>; - #reset-cells = <0>; - label = "pms_sram"; - /* T8140 holds it through its always-on PMP report node. */ - apple,always-on; - }; + ps_pms_sram: power-controller@5a0 { + compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; + reg = <0x5a0 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "pms_sram"; + /* T8140 holds it through its always-on PMP report node. */ + apple,always-on; + }; - ps_qspi: power-controller@460 { - compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; - reg = <0x460 4>; - #power-domain-cells = <0>; - #reset-cells = <0>; - label = "qspi"; - power-domains = <&ps_spi_p>; - }; + ps_qspi: power-controller@460 { + compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; + reg = <0x460 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "qspi"; + power-domains = <&ps_spi_p>; }; +}; +&{/soc} { /* * PMP, laid out as on T8140 (ADT /arm-io/pmp, dart-pmp): it runs the * DRAM controller (DCS) and fabric DVFS. Without it the memory stays at * the bootloader's state (memcpy ~20 GB/s against ~120 GB/s on macOS). */ - pmp_dart: iommu@380300000 { - compatible = "apple,t8142-dart", "apple,t8110-dart"; - reg = <0x3 0x80300000 0x0 0xc000>; - interrupt-parent = <&aic>; - interrupts = ; - #iommu-cells = <1>; - apple,dma-range = /bits/ 64 <0x10000000000 0xbff00000>; - power-domains = <&ps_pmp>; - }; pmp: pmp@380500000 { compatible = "apple,t8142-pmp-v2", "apple,t8140-pmp-v2"; @@ -173,14 +162,19 @@ clocks = <&clkref>; #pwm-cells = <2>; }; - - mtp_dart: iommu@394800000 { - compatible = "apple,t8142-dart", "apple,t8110-dart"; - reg = <3 0x94800000 0 0xc000>; - interrupts = ; - #iommu-cells = <1>; - /* Keep host allocations clear of firmware's low IOVA mappings. */ - apple,dma-range = <0 0x02000000 0 0x10000000>; - }; }; #include "t8142-j813-pmp-tunables.dtsi" + +&pmp_dart { + apple,dma-range = /bits/ 64 <0x10000000000 0xbff00000>; + power-domains = <&ps_pmp>; + status = "okay"; +}; + +&mtp_dart { + reg = <3 0x94800000 0 0xc000>; + /delete-property/ reg-names; + /* Keep host allocations clear of firmware's low IOVA mappings. */ + apple,dma-range = <0 0x02000000 0 0x10000000>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/apple/t8142-j813-usb.dtsi b/arch/arm64/boot/dts/apple/t8142-j813-usb.dtsi index e27e40c04e268..2eb0b1f16af47 100644 --- a/arch/arm64/boot/dts/apple/t8142-j813-usb.dtsi +++ b/arch/arm64/boot/dts/apple/t8142-j813-usb.dtsi @@ -132,6 +132,7 @@ power-domains = <&ps_atc0_usb>; #iommu-cells = <1>; apple,dma-range = <0x100 0x4000 0 0xffff0000>; + status = "okay"; }; dwc3_0_dart_1: iommu@402f80000 { @@ -278,6 +279,7 @@ power-domains = <&ps_atc1_usb>; #iommu-cells = <1>; apple,dma-range = <0x100 0x4000 0 0xffff0000>; + status = "okay"; }; dwc3_1_dart_1: iommu@40af80000 { diff --git a/arch/arm64/boot/dts/apple/t8142-j813.dts b/arch/arm64/boot/dts/apple/t8142-j813.dts index 21b1688e83f8a..69178aa4c4e51 100644 --- a/arch/arm64/boot/dts/apple/t8142-j813.dts +++ b/arch/arm64/boot/dts/apple/t8142-j813.dts @@ -8,18 +8,13 @@ */ /dts-v1/; -#include -#include +#include "t8142.dtsi" / { compatible = "apple,j813", "apple,t8142", "apple,arm-platform"; model = "Apple MacBook Air (13-inch, M5, 2026)"; chassis-type = "laptop"; - #address-cells = <2>; - #size-cells = <2>; - interrupt-parent = <&aic>; - aliases { serial0 = &dockchannel; serial1 = &serial0; @@ -39,173 +34,81 @@ }; }; - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - /* Filled by the loader. */ - }; - memory@10000000000 { - device_type = "memory"; reg = <0x100 0 0x4 0>; /* Filled by the loader. */ }; +}; - cpus { - #address-cells = <2>; - #size-cells = <0>; - - cpu0: cpu@0 { - compatible = "apple,t8142-e"; - device_type = "cpu"; - reg = <0 0x0>; - operating-points-v2 = <&ecluster_opp>; - performance-domains = <&cpufreq_e>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* Filled by the loader. */ - }; - - cpu1: cpu@1 { - compatible = "apple,t8142-e"; - device_type = "cpu"; - reg = <0 0x1>; - operating-points-v2 = <&ecluster_opp>; - performance-domains = <&cpufreq_e>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* Filled by the loader. */ - }; - - cpu2: cpu@2 { - compatible = "apple,t8142-e"; - device_type = "cpu"; - reg = <0 0x2>; - operating-points-v2 = <&ecluster_opp>; - performance-domains = <&cpufreq_e>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* Filled by the loader. */ - }; +&cpu0 { + operating-points-v2 = <&ecluster_opp>; + performance-domains = <&cpufreq_e>; + status = "okay"; +}; - cpu3: cpu@3 { - compatible = "apple,t8142-e"; - device_type = "cpu"; - reg = <0 0x3>; - operating-points-v2 = <&ecluster_opp>; - performance-domains = <&cpufreq_e>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* Filled by the loader. */ - }; +&cpu1 { + operating-points-v2 = <&ecluster_opp>; + performance-domains = <&cpufreq_e>; + status = "okay"; +}; - cpu4: cpu@4 { - compatible = "apple,t8142-e"; - device_type = "cpu"; - reg = <0 0x4>; - operating-points-v2 = <&ecluster_opp>; - performance-domains = <&cpufreq_e>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* Filled by the loader. */ - }; +&cpu2 { + operating-points-v2 = <&ecluster_opp>; + performance-domains = <&cpufreq_e>; + status = "okay"; +}; - cpu5: cpu@5 { - compatible = "apple,t8142-e"; - device_type = "cpu"; - reg = <0 0x5>; - operating-points-v2 = <&ecluster_opp>; - performance-domains = <&cpufreq_e>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* Filled by the loader. */ - }; +&cpu3 { + operating-points-v2 = <&ecluster_opp>; + performance-domains = <&cpufreq_e>; + status = "okay"; +}; - cpu6: cpu@10100 { - compatible = "apple,t8142-p"; - device_type = "cpu"; - reg = <0 0x10100>; - operating-points-v2 = <&pcluster_opp>; - performance-domains = <&cpufreq_p>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* Filled by the loader. */ - }; +&cpu4 { + operating-points-v2 = <&ecluster_opp>; + performance-domains = <&cpufreq_e>; + status = "okay"; +}; - cpu7: cpu@10101 { - compatible = "apple,t8142-p"; - device_type = "cpu"; - reg = <0 0x10101>; - operating-points-v2 = <&pcluster_opp>; - performance-domains = <&cpufreq_p>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* Filled by the loader. */ - }; +&cpu5 { + operating-points-v2 = <&ecluster_opp>; + performance-domains = <&cpufreq_e>; + status = "okay"; +}; - cpu8: cpu@10102 { - compatible = "apple,t8142-p"; - device_type = "cpu"; - reg = <0 0x10102>; - operating-points-v2 = <&pcluster_opp>; - performance-domains = <&cpufreq_p>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* Filled by the loader. */ - }; +&cpu6 { + operating-points-v2 = <&pcluster_opp>; + performance-domains = <&cpufreq_p>; + status = "okay"; +}; - cpu9: cpu@10103 { - compatible = "apple,t8142-p"; - device_type = "cpu"; - reg = <0 0x10103>; - operating-points-v2 = <&pcluster_opp>; - performance-domains = <&cpufreq_p>; - enable-method = "spin-table"; - cpu-release-addr = <0 0>; /* Filled by the loader. */ - }; - }; +&cpu7 { + operating-points-v2 = <&pcluster_opp>; + performance-domains = <&cpufreq_p>; + status = "okay"; +}; - timer { - compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; - interrupt-names = "phys", "virt", "hyp-phys", "hyp-virt"; - }; +&cpu8 { + operating-points-v2 = <&pcluster_opp>; + performance-domains = <&cpufreq_p>; + status = "okay"; +}; - clkref: clock-ref { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <24000000>; - }; +&cpu9 { + operating-points-v2 = <&pcluster_opp>; + performance-domains = <&cpufreq_p>; + status = "okay"; +}; - soc { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - nonposted-mmio; - - aic: interrupt-controller@381000000 { - compatible = "apple,t8142-aic3", "apple,t8122-aic3"; - interrupt-controller; - #interrupt-cells = <3>; - reg = <3 0x81000000 0 0x1cc000>, - <3 0x81040000 0 0x4000>; - reg-names = "core", "event"; - }; +&{/timer} { + status = "okay"; +}; - serial0: serial@3a5200000 { - compatible = "apple,s5l-uart"; - reg = <3 0xa5200000 0 0x4000>; - reg-io-width = <4>; - interrupts = ; - clocks = <&clkref>, <&clkref>; - clock-names = "uart", "clk_uart_baud0"; - status = "disabled"; - }; +&aic { + status = "okay"; +}; - dockchannel: serial@38812c000 { - compatible = "apple,dockchannel-uart"; - reg = <3 0x8812c000 0 0x4000>, - <3 0x88128000 0 0x4000>, - <3 0x8810c000 0 0x1000>; - reg-names = "data", "config", "irq"; - interrupts = ; - }; - }; +&dockchannel { + status = "okay"; }; #include "t8142-j813-display.dtsi" @@ -213,12 +116,66 @@ #include "t8142-j813-peripherals.dtsi" #include "t8142-j813-j815.dtsi" #include "t8142-j813-usb.dtsi" +#include "t8142-j813-dcpext.dtsi" #include "t8142-j813-avd.dtsi" #include "t8142-j813-isp.dtsi" #include "t8142-j813-n1.dtsi" #include "t8142-j813-audio.dtsi" -#include "t8142-peripherals.dtsi" +/* + * Ambient light sensor, the AOP's "als" service: an ST VD6286, as on J815 + * (same ADT node, /arm-io/aop/iop-aop-nub/als). aop_als sends it the + * per-device calibration (apple/aop-als-cal.bin). No firmware-name: that + * names the CT817 setup-port message, which this sensor does not take. + */ +&aop { + aop_als: als { + compatible = "apple,t8142-aop-als", "apple,aop-als"; + }; +}; + +/* + * N1 functions behind apcie port 0 (0000:00:00.0 -> 01:00.{0,1,2}), so the + * loader has somewhere to put the factory addresses: it copies ADT /chosen + * mac-address-wifi0 and mac-address-bluetooth0 into the wifi0/bluetooth0 + * alias targets. Same nodes as t8142-j815.dts (same N1, same PCI IDs). + */ +/ { + aliases { + wifi0 = &n1_alpha; + bluetooth0 = &n1_beta; + }; +}; + +&pcie0 { + n1_port: pci@0,0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + bus-range = <1 1>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + n1_control: control@0,0 { + compatible = "apple,t8142-centauri-control", "pci106b,1900"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + }; + + n1_alpha: wifi@0,1 { + compatible = "pci106b,1902"; + reg = <0x10100 0x0 0x0 0x0 0x0>; + /* Filled by the loader */ + local-mac-address = [00 00 00 00 00 00]; + }; + + n1_beta: bluetooth@0,2 { + compatible = "pci106b,1903"; + reg = <0x10200 0x0 0x0 0x0 0x0>; + /* Filled by the loader */ + local-bd-address = [00 00 00 00 00 00]; + }; + }; +}; &mtp_hid { multi-touch { diff --git a/arch/arm64/boot/dts/apple/t8142-j815.dts b/arch/arm64/boot/dts/apple/t8142-j815.dts index 9ce5fe5cd7e99..851da5a7d3256 100644 --- a/arch/arm64/boot/dts/apple/t8142-j815.dts +++ b/arch/arm64/boot/dts/apple/t8142-j815.dts @@ -2,12 +2,20 @@ /* * Apple MacBook Air (15-inch, M5), J815. * - * Boots on the T8142 inventory with the resources its ADT (25G83) shares - * with J813: CPUs, timer, AIC, DockChannel UART, PMGR, CPU performance - * states, PMC, SMC, the MTP keyboard and trackpad, ANS NVMe, watchdog and - * PMU. The loader supplies usable memory, CPU release addresses and - * framebuffer geometry. Audio, display, USB, camera, GPU and radios are not - * described yet: their J815 wiring has not been checked. + * J815 is the 15-inch sibling of J813 on the same T8142 die. It uses the + * J813 board fragments and overrides what the J815 ADT shows to be + * different: + * + * - /chosen board-id 0x26 (J813: 0x24) + * - 15.3" 2880x1864 panel (2880x1800 below the notch), 326 x 211 mm + * - six SN012776 speaker amplifiers on i2c3 (0x38-0x3d: two tweeters and + * four force-cancelling woofers); J813 has four + * - ISP sensor-type 0x72 (J813: 0x71) + * - MTP hid-merge-personality C1FD3,3 (J813: C1FD1,4) + * + * The rest of the J813/J815 ADT difference is firmware selection (AOP + * j815aop, acoustic-id 0x2b), ADMAC speaker channel counts and higher + * CLPC package power limits. */ /dts-v1/; @@ -110,17 +118,16 @@ status = "okay"; }; -&pmgr { - status = "okay"; -}; - -&mtp_dart { - /* Keep host allocations clear of firmware's low IOVA mappings. */ - apple,dma-range = <0 0x02000000 0 0x10000000>; - status = "okay"; -}; - +#include "t8142-j813-display.dtsi" +#include "t8142-j813-gpu.dtsi" +#include "t8142-j813-peripherals.dtsi" #include "t8142-j813-j815.dtsi" +#include "t8142-j813-usb.dtsi" +#include "t8142-j813-dcpext.dtsi" +#include "t8142-j813-avd.dtsi" +#include "t8142-j813-isp.dtsi" +#include "t8142-j813-n1.dtsi" +#include "t8142-j813-audio.dtsi" &mtp_hid { multi-touch { @@ -129,7 +136,241 @@ }; }; -/* Unexposed chassis port instances remain described and disabled. */ +&pmp { + /* ADT /chosen board-id (J815) */ + apple,board-id = <38>; +}; + +&panel { + compatible = "apple,panel-j815", "apple,panel"; + width-mm = <326>; + height-mm = <211>; + adj-height-mm = <204>; +}; + +&isp { + /* J815 ADT /arm-io/isp sensor-type */ + apple,platform-id = <0x72>; +}; + +/* + * Ambient light sensor, the AOP's "als" service: an ST VD6286, as on the + * M4 Pro, not T8140's CT817. aop_als sends it the per-device calibration + * (apple/aop-als-cal.bin) as its calibration property. There is no + * firmware-name: that names the CT817 setup-port message, which this sensor + * does not take. + */ +&aop { + aop_als: als { + compatible = "apple,t8142-aop-als", "apple,aop-als"; + }; +}; + +/* + * N1 functions behind apcie port 0 (0000:00:00.0 -> 01:00.{0,1,2}), so the + * loader has somewhere to put the factory addresses: it copies ADT /chosen + * mac-address-wifi0 and mac-address-bluetooth0 into the wifi0/bluetooth0 + * alias targets, as on T6050 (t6050-j716s.dts). + */ +/ { + aliases { + wifi0 = &n1_alpha; + bluetooth0 = &n1_beta; + /* + * The loader finds the SEP through this alias: it reserves SEPFW + * and copies the boot's local-policy and iBoot manifests onto + * the node. + */ + sep = &sep; + }; +}; + +&pcie0 { + n1_port: pci@0,0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + bus-range = <1 1>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + n1_control: control@0,0 { + compatible = "apple,t8142-centauri-control", "pci106b,1900"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + }; + + n1_alpha: wifi@0,1 { + compatible = "pci106b,1902"; + reg = <0x10100 0x0 0x0 0x0 0x0>; + /* Filled by the loader */ + local-mac-address = [00 00 00 00 00 00]; + }; + + n1_beta: bluetooth@0,2 { + compatible = "pci106b,1903"; + reg = <0x10200 0x0 0x0 0x0 0x0>; + /* Filled by the loader */ + local-bd-address = [00 00 00 00 00 00]; + }; + }; +}; + +/* + * SMC sensors beyond the discovered temperatures. Only non-temperature nodes + * may be added here: a temperature-* node would stop + * apple,discover-temperatures. Keys the SMC lacks are skipped at probe. The + * die key list is J704's (same T8142): the listed keys form the SoC die + * thermal zone. + */ +&smc { + hwmon { + apple,soc-die-keys = "Te04", "Te08", "Te0C", "Te0R", + "Tp00", "Tp04", "Tp0C", "Tp0G", "Tp0O", + "Tp0R", "Tp0X", "Tp0a", "Tp0p", "Tp0u", + "Tp0y", "Tp12", "Tp16", "Tp1E", + "Tg0U", "Tg0X", "Tg0d", "Tg0g", "Tg0j", + "Tg1Y", "Tg1c", "Tg1g"; + apple,thermal-pressure-key = "mTPL"; + + power-PSTR { + apple,key-id = "PSTR"; + label = "Total System Power"; + }; + + power-PDTR { + apple,key-id = "PDTR"; + label = "AC Input Power"; + }; + + power-PMVR { + apple,key-id = "PMVR"; + label = "3.8 V Rail Power"; + }; + + voltage-VD0R { + apple,key-id = "VD0R"; + label = "AC Input Voltage"; + }; + + voltage-SBAV { + apple,key-id = "SBAV"; + label = "Battery Voltage"; + }; + + current-ID0R { + apple,key-id = "ID0R"; + label = "AC Input Current"; + }; + }; +}; + +/* + * Secure Enclave and the Touch ID sensor. All values are from the J815 ADT + * (macOS 27.0): + * - sep: iop-sep,ascwrap-v6 at 0x30a600000 (0x88000), pre-booted by iBoot + * (sepfw-booted), so apple_sep warm-attaches; its mailbox is the ASC + * mailbox at +0x8000, AIC 445-448 (ADT order 446,445,448,447 as on the + * AOP: send-empty..recv-not-empty ascending). + * - dart-sep: t8110 at 0x308b80000, irq 455; input aperture vm-base-0 + * 0x10000004000 + vm-size-0 0xffff0000 (the BIT(40) alias, as T8132). + * - spi2 at 0x3a5108000, irq 0x4d9; PMGR device SPI2 at +0x440, parent + * SPI_P (id 94). + * - mesa: "biosensor,mesa", sensor-id V3, 8 MHz, CS0; power + * function-mesa_pwr = NUB GPIO pin 36; data-ready interrupt on AP + * GPIO pin 200. + * The SEP and its DART stay disabled here: apple_sep enables them at module + * init (drivers/soc/apple/dt.rs). + */ +&pmgr { + ps_spi2: power-controller@440 { + compatible = "apple,t8142-pmgr-pwrstate", "apple,t8103-pmgr-pwrstate"; + reg = <0x440 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + power-domains = <&ps_spi_p>; + label = "spi2"; + }; +}; + +&{/soc} { + sep: sep@30a600000 { + compatible = "apple,sep"; + reg = <0x3 0x0a600000 0x0 0x88000>; + mboxes = <&sep_mbox>; + mbox-names = "mbox"; + iommus = <&sep_dart 0>; + status = "disabled"; + }; + + sep_mbox: mbox@30a608000 { + compatible = "apple,t8142-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x3 0x0a608000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + status = "okay"; + }; + + spi2: spi@3a5108000 { + compatible = "apple,t8142-spi", "apple,t8103-spi"; + reg = <0x3 0xa5108000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + clocks = <&clkref>; + power-domains = <&ps_spi2>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + mesa: fingerprint@0 { + compatible = "apple,mesa-fingerprint"; + reg = <0>; + spi-max-frequency = <8000000>; + spi-cpol; + spi-cs-setup-delay-ns = <20>; + spi-cs-hold-delay-ns = <20>; + enable-gpios = <&pinctrl_nub 36 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&pinctrl_ap>; + interrupts = <200 IRQ_TYPE_EDGE_RISING>; + /* Per-device files, built from the Mac's own factory records. */ + firmware-name = "apple/mesacal-j815.bin", "apple/msrk-j815.bin"; + status = "okay"; + }; + }; +}; + +&sep_dart { + apple,dma-range = /bits/ 64 <0x10000004000 0xffff0000>; + apple,dma-offset = /bits/ 64 <0x0>; +}; + +/* Expose the sensor's two pins next to the ones sound uses. */ +&pinctrl_ap { + gpio-reserved-ranges = <0 100>, <101 49>, <152 48>, <201 23>; +}; + +&pinctrl_nub { + gpio-reserved-ranges = <0 18>, <19 17>, <37 3>; +}; + +/* + * J815 has six speaker amplifiers, not J813's four. Keep J813's sound card + * and the AOP audio service off until the J815 speaker layout is described. + */ +&aop_audio { + status = "disabled"; +}; + +/ { + sound { + status = "disabled"; + }; +}; /* aura (mcc_init_m5) turns the system level cache on; the driver confirms it and flushes on shutdown. */ &mcc { diff --git a/drivers/gpu/drm/apple/dcp-fabric.c b/drivers/gpu/drm/apple/dcp-fabric.c index e00de74092ed9..248a6d024288b 100644 --- a/drivers/gpu/drm/apple/dcp-fabric.c +++ b/drivers/gpu/drm/apple/dcp-fabric.c @@ -1760,13 +1760,31 @@ static int dcp_typec_route_prepare(struct typec_mux_dev *mux, return 0; } +/* + * A T8142 external processor (firmware 27) behind a Type-C PHY of the T8122 + * generation: the firmware probes AUX as soon as its route is offered, so the + * route is applied only once the PHY has finished its own mode change. + */ +static bool dcp_t8142_ext(struct apple_dcp *dcp) +{ + return dcp->fw_compat == DCP_FIRMWARE_V_27_0 && + of_device_is_compatible(dcp->dev->of_node, "apple,t8142-dcpext"); +} + +static int dcp_typec_route_apply(struct typec_mux_dev *mux, + struct typec_mux_state *state); + static int dcp_typec_route_finish(struct typec_mux_dev *mux, struct typec_mux_state *state) { - struct apple_dcp_typec_port *port = - ((struct apple_dcp_typec_route *)typec_mux_get_drvdata(mux))->port; + struct apple_dcp_typec_route *route = typec_mux_get_drvdata(mux); + struct apple_dcp_typec_port *port = route->port; int ret; + /* Every provider's set phase (including the PHY) has completed. */ + if (dcp_t8142_ext(route->dcp) && state->mode != TYPEC_STATE_SAFE) + return dcp_typec_route_apply(mux, state); + guard(mutex)(&dcp_typec_fabric_lock); if (state->mode != TYPEC_STATE_SAFE || !port->safe_pending || port->safe_finish_ready) @@ -1823,7 +1841,7 @@ static int dcp_typec_port_busy(struct apple_dcp_typec_port *port, return -ENOSPC; } -static int dcp_typec_route_set(struct typec_mux_dev *mux, +static int dcp_typec_route_apply(struct typec_mux_dev *mux, struct typec_mux_state *state) { struct apple_dcp_typec_route *route = typec_mux_get_drvdata(mux); @@ -1895,7 +1913,8 @@ static int dcp_typec_route_set(struct typec_mux_dev *mux, * another port is refused as busy. The route is taken again * when HPD returns. */ - if (dcp->fw_compat == DCP_FIRMWARE_V_26_6_DESKTOP) { + if (dcp->fw_compat == DCP_FIRMWARE_V_26_6_DESKTOP || + dcp_t8142_ext(dcp)) { port->preferred_route = port->owner; port->hpd = false; /* @@ -2020,7 +2039,8 @@ static int dcp_typec_route_set(struct typec_mux_dev *mux, * would otherwise hold it against the port that has one. */ if (!port->owner && !hpd && - route->dcp->fw_compat == DCP_FIRMWARE_V_26_6_DESKTOP) { + (route->dcp->fw_compat == DCP_FIRMWARE_V_26_6_DESKTOP || + dcp_t8142_ext(route->dcp))) { port->applied_valid = true; return 0; } @@ -2088,6 +2108,16 @@ static int dcp_typec_route_set(struct typec_mux_dev *mux, return 0; } +static int dcp_typec_route_set(struct typec_mux_dev *mux, + struct typec_mux_state *state) +{ + struct apple_dcp_typec_route *route = typec_mux_get_drvdata(mux); + + if (dcp_t8142_ext(route->dcp) && state->mode != TYPEC_STATE_SAFE) + return 0; + return dcp_typec_route_apply(mux, state); +} + /* The T8142-layout crossbar (one per ATC on T6050) */ static bool dcp_xbar_t8142(struct mux_control *mux) { @@ -2433,6 +2463,25 @@ static int dcp_direct_crossbar_link_t6050(struct apple_dcp *dcp, bool up) * output's mux (or NULL on a Type-C-only pipeline). */ xbar = dcp->active_typec_route ? dcp->active_typec_route->active_xbar : dcp->xbar; + /* + * T8142's Type-C PHYs are of the T8122 generation and have no link + * report: they always drive PCLK1 with 8b/10b coding (as on the J704). + */ + if (dcp_t8142_ext(dcp)) { + if (dcp->dptx_tunnel || !xbar) + return 0; + if (!up) + return dcp_dpxbar_link(xbar, false); + configure = symbol_get(apple_dpxbar_link_configure); + if (!configure) + return -ENODEV; + ret = configure(xbar, 1, false); + symbol_put(apple_dpxbar_link_configure); + /* A link that is already up keeps its configuration. */ + if (ret == -EBUSY) + return 0; + return ret ? ret : dcp_dpxbar_link(xbar, true); + } if (dcp->dptx_tunnel || !dcp->phy || !xbar) return 0; get_config = symbol_get(apple_dp_phy_link_config); diff --git a/drivers/gpu/drm/apple/dcp.c b/drivers/gpu/drm/apple/dcp.c index e819a3565b5f3..9701bc3547bf4 100644 --- a/drivers/gpu/drm/apple/dcp.c +++ b/drivers/gpu/drm/apple/dcp.c @@ -5987,7 +5987,7 @@ static void dcp_ext_give_up(struct apple_dcp *dcp, int err, const char *when); /* * The external processors whose failure must not take the DRM device down: - * T8122's, T6041's and T6050's dcpext. One that fails to probe or bind joins + * T8122's, T6041's, T6050's and T8142's dcpext. One that fails to probe or bind joins * as an unusable pipe (ext_dead), and the other displays go on without it. * With every processor failed the DRM device has no pipe and does not bind. */ @@ -5995,7 +5995,8 @@ static bool dcp_ext_is_failsafe(struct device_node *np) { return of_device_is_compatible(np, "apple,t8122-dcpext") || of_device_is_compatible(np, "apple,t6041-dcpext") || - of_device_is_compatible(np, "apple,t6050-dcpext"); + of_device_is_compatible(np, "apple,t6050-dcpext") || + of_device_is_compatible(np, "apple,t8142-dcpext"); } /* @@ -8878,7 +8879,20 @@ static const struct apple_dcp_hw_data apple_dcp_hw_t6050_dcpext = { .sink_metadata_edid = true, }; +/* + * T8142's external processors (dcpext0/1: the Airs' two USB-C ports, the + * J704's HDMI) run the internal DCP's firmware 27 image and are left running + * idle by iBoot, like T6050's. One DPTX port each, behind an ATC PHY. + */ +static const struct apple_dcp_hw_data apple_dcp_hw_t8142_dcpext = { + .num_dptx_ports = 1, + .adopt_live_session = true, + .firmware_compat = DCP_FIRMWARE_V_27_0, + .sink_metadata_edid = true, +}; + static const struct of_device_id of_match[] = { + { .compatible = "apple,t8142-dcpext", .data = &apple_dcp_hw_t8142_dcpext }, { .compatible = "apple,t6041-dcp", .data = &apple_dcp_hw_t6041, }, { .compatible = "apple,t6041-dcpext", .data = &apple_dcp_hw_t6041_dcpext, }, { .compatible = "apple,t6050-dcp", .data = &apple_dcp_hw_t6050 }, diff --git a/drivers/phy/apple/atc.c b/drivers/phy/apple/atc.c index c833f389b5311..1f9cde83f60f5 100644 --- a/drivers/phy/apple/atc.c +++ b/drivers/phy/apple/atc.c @@ -530,6 +530,8 @@ enum atcphy_lane_mode { #define PIPEHANDLER_NONSELECTED_OVERRIDE 0x20 #define PIPEHANDLER_NATIVE_RESET BIT(12) #define PIPEHANDLER_DUMMY_PHY_EN BIT(15) +/* Boot-owned PIPE hold, released before selecting the dummy backend. */ +#define PIPEHANDLER_NONSELECTED_BOOT_HOLD BIT(16) #define PIPEHANDLER_NATIVE_POWER_DOWN GENMASK(3, 0) #define PIPEHANDLER_LOCK_ACK_TIMEOUT_US 1000 @@ -687,6 +689,8 @@ struct apple_atcphy; * generation has none) and the SuperSpeed tunables; USB2 * still works without the latter * @park_pipe_unlocked: A stopped controller may park without a PIPE handshake + * @clear_boot_hold: Release the boot PIPE hold before dummy backend selection + * @dp_banked_tunables: DisplayPort requires separate LIOA/common calibration * @dp_t8122: DisplayPort runs the T8122 AUX, AUSPLL and lane sequences * @park_dummy_phy: Enable the dummy PIPE backend whenever the PIPE is parked on * it; the lock handshake that starts the next PIPE change is @@ -714,8 +718,10 @@ struct atcphy_hw { bool optional_tunables; bool has_t8140_dp; bool dp_t8122; + bool dp_banked_tunables; bool park_pipe_unlocked; bool park_dummy_phy; + bool clear_boot_hold; bool restore_after_pd_off; bool idle_power_off; }; @@ -855,6 +861,8 @@ struct apple_atcphy { struct apple_tunable *lane_usb4[2]; struct apple_tunable *usb2phy_reg_dflt; struct apple_tunable *usb3_dp; + struct apple_tunable *dp_lioa; + struct apple_tunable *dp_common_config; struct apple_tunable *dp_common_pre; struct apple_tunable *dp_lpdptx; struct apple_tunable *dp_common_post; @@ -963,11 +971,13 @@ struct apple_atcphy { void __iomem *pipehandler; void __iomem *lpdptx; void __iomem *pwrctl; + void __iomem *lioa; } regs; struct { struct resource *core; struct resource *lpdptx; + struct resource *lioa; struct resource *axi2af; struct resource *usb2phy_reg; } res; @@ -1808,6 +1818,9 @@ static int atcphy_configure_pipehandler_usb4(struct apple_atcphy *atcphy) */ static void atcphy_enable_dummy_phy(struct apple_atcphy *atcphy) { + if (atcphy->hw->clear_boot_hold) + clear32(atcphy->regs.pipehandler + PIPEHANDLER_NONSELECTED_OVERRIDE, + PIPEHANDLER_NONSELECTED_BOOT_HOLD); set32(atcphy->regs.pipehandler + PIPEHANDLER_NONSELECTED_OVERRIDE, PIPEHANDLER_DUMMY_PHY_EN); } @@ -4113,7 +4126,8 @@ static int atcphy_configure(struct apple_atcphy *atcphy, enum atcphy_mode mode) if (ret) return ret; } - if (atcphy->hw->has_t8140_dp && atcphy_modes[mode].enable_dp_aux && + if ((atcphy->hw->has_t8140_dp || atcphy->hw->dp_banked_tunables) && + atcphy_modes[mode].enable_dp_aux && !atcphy->dp_tunables) return -EOPNOTSUPP; if (atcphy->hw->has_t8140_dp && @@ -4184,6 +4198,10 @@ static int atcphy_configure(struct apple_atcphy *atcphy, enum atcphy_mode mode) } atcphy_apply_tunables(atcphy, mode); + if (atcphy->hw->dp_banked_tunables && atcphy_modes[mode].enable_dp_aux) { + apple_tunable_apply(atcphy->regs.lioa, atcphy->tunables.dp_lioa); + apple_tunable_apply(atcphy->regs.lpdptx, atcphy->tunables.dp_common_config); + } atcphy->hw->configure_post_tunable(atcphy, mode); /* Setup AUX channel if DP altmode is requested */ @@ -4763,6 +4781,14 @@ static int atcphy_dpphy_validate(struct phy *phy, enum phy_mode mode, int submod if (submode != 0 && !atcphy_t8132_dp_on(atcphy)) return -EINVAL; + /* The Type-C mux owns lane setup; validate observes its completed epoch. */ + guard(mutex)(&atcphy->lock); + if (atcphy->hw->dp_t8122 && + (atcphy->mode_dirty || !atcphy->dp_t8122.aux)) { + opts->lanes = 0; + return 0; + } + switch (atcphy->mode) { case APPLE_ATCPHY_MODE_USB3_DP: opts->lanes = 2; @@ -6194,6 +6220,36 @@ static int atcphy_load_t8132_tunables(struct apple_atcphy *atcphy) return 0; } +static int atcphy_load_dp_banks(struct apple_atcphy *atcphy) +{ + struct apple_tunable *lioa, *common; + + if (!atcphy->res.lioa) { + atcphy->dp_tunables = false; + return 0; + } + + lioa = devm_apple_tunable_parse(atcphy->dev, atcphy->np, + "apple,tunable-dp-lioa", atcphy->res.lioa); + common = devm_apple_tunable_parse(atcphy->dev, atcphy->np, + "apple,tunable-dp-common-config", atcphy->res.lpdptx); + if (IS_ERR(lioa) || IS_ERR(common)) { + int ret = IS_ERR(lioa) ? PTR_ERR(lioa) : PTR_ERR(common); + + if ((IS_ERR(lioa) && PTR_ERR(lioa) != -ENOENT) || + (IS_ERR(common) && PTR_ERR(common) != -ENOENT)) + return ret == -ENOENT ? PTR_ERR(common) : ret; + atcphy->dp_tunables = false; + dev_warn(atcphy->dev, "DisplayPort bank calibration missing; DP disabled\n"); + return 0; + } + if (!lioa->sz || !common->sz) + return -EINVAL; + atcphy->tunables.dp_lioa = lioa; + atcphy->tunables.dp_common_config = common; + return 0; +} + static int atcphy_load_tunables(struct apple_atcphy *atcphy) { size_t tunable_count; @@ -6306,6 +6362,12 @@ static int atcphy_load_tunables(struct apple_atcphy *atcphy) atcphy->ss_tunables = !ss_missing; if (atcphy->hw->dp_t8122) atcphy->dp_tunables = !common_missing; + if (atcphy->hw->dp_banked_tunables) { + int ret = atcphy_load_dp_banks(atcphy); + + if (ret) + return ret; + } if (atcphy->dp_only && !atcphy->dp_tunables) dev_warn(atcphy->dev, "Calibration tunables missing, DisplayPort disabled\n"); else if (ss_missing && atcphy->dp_tunables && !atcphy->dp_only) @@ -6391,6 +6453,21 @@ static int atcphy_map_resources(struct platform_device *pdev, struct apple_atcph *resources[i].res = res; } + /* + * Device trees written before DisplayPort was supported have no LIOA + * bank: the PHY then serves USB as before, without DisplayPort. + */ + res = atcphy->hw->dp_banked_tunables ? + platform_get_resource_byname(pdev, IORESOURCE_MEM, "lioa") : NULL; + if (res) { + addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(addr)) + return dev_err_probe(atcphy->dev, PTR_ERR(addr), + "Unable to map LIOA bank\n"); + atcphy->res.lioa = res; + atcphy->regs.lioa = addr; + } + if (atcphy->hw->has_usb2phy_reg) { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usb2phy-reg"); addr = devm_ioremap_resource(&pdev->dev, res); @@ -7544,6 +7621,11 @@ static const struct atcphy_hw atcphy_hw_t8142 = { .pipe_mux_clk = PIPEHANDLER_MUX_CTRL_CLK_T8142, .pipe_mux_data = PIPEHANDLER_MUX_CTRL_DATA_T8142, .has_usb4 = true, + .dp_t8122 = true, + .dp_banked_tunables = true, + .park_dummy_phy = true, + .restore_after_pd_off = true, + .clear_boot_hold = true, }; static const struct of_device_id atcphy_match[] = {