diff --git a/Documentation/devicetree/bindings/arm/apple/apple,pmgr.yaml b/Documentation/devicetree/bindings/arm/apple/apple,pmgr.yaml index 91ae5a3ce1bca..e2e75a8c29f13 100644 --- a/Documentation/devicetree/bindings/arm/apple/apple,pmgr.yaml +++ b/Documentation/devicetree/bindings/arm/apple/apple,pmgr.yaml @@ -46,6 +46,7 @@ properties: - apple,t8132-pmgr - apple,t8140-pmgr - apple,t8142-pmgr + - apple,t8152-pmgr - const: apple,t8103-pmgr - const: syscon - const: simple-mfd diff --git a/Documentation/devicetree/bindings/dma/apple,admac.yaml b/Documentation/devicetree/bindings/dma/apple,admac.yaml index d445faceda863..e472332dc97e7 100644 --- a/Documentation/devicetree/bindings/dma/apple,admac.yaml +++ b/Documentation/devicetree/bindings/dma/apple,admac.yaml @@ -53,6 +53,7 @@ properties: - items: - const: apple,t6041-admac - const: apple,t8132-admac + - const: apple,t8152-admac - items: - const: apple,t6050-admac - const: apple,t8140-admac diff --git a/Documentation/devicetree/bindings/i2c/apple,i2c.yaml b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml index f2e16482d9218..c3a306b0c8ea4 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,t8152-i2c - const: apple,t8103-i2c - items: - enum: diff --git a/Documentation/devicetree/bindings/iommu/apple,dart.yaml b/Documentation/devicetree/bindings/iommu/apple,dart.yaml index 3f0a7adf403d8..a5acfb9f36753 100644 --- a/Documentation/devicetree/bindings/iommu/apple,dart.yaml +++ b/Documentation/devicetree/bindings/iommu/apple,dart.yaml @@ -282,6 +282,17 @@ properties: and filtering state without a separate page-table root. Source and destination must differ, and both must exist on the controller. + apple,retain-translation: + type: boolean + description: > + The bootloader hands this DART over translating, with stream page + tables that a co-processor's firmware keeps using, but without setting + the hardware lock. The operating system then treats the DART as locked: + it does not reset it or replace the inherited stream roots, adds its + own mappings only in root entries that are empty at handoff, and on + detach clears only the entries it added. The entries present at handoff + stay owned by the firmware, which may keep using them at any time. + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/iommu/apple,sart.yaml b/Documentation/devicetree/bindings/iommu/apple,sart.yaml index 19ffe1bf167f7..a545bddf78d80 100644 --- a/Documentation/devicetree/bindings/iommu/apple,sart.yaml +++ b/Documentation/devicetree/bindings/iommu/apple,sart.yaml @@ -26,8 +26,8 @@ description: SART3, first seen in M1 Pro/Max, extends both the address space and filter entry size to 42 bit. - SART4, seen on M5 Ultra (T6050), keeps SART3's entries but moves the - address and size arrays, so it has no SART3 fallback. + SART4, seen on M5 Ultra (T6050) and M6 (T8152), keeps SART3's entries but + moves the address and size arrays, so it has no SART3 fallback. properties: compatible: @@ -49,6 +49,7 @@ properties: - apple,t6050-sart - apple,t8015-sart - apple,t8103-sart + - apple,t8152-sart reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml b/Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml index 8afd38261fe30..9dc9c7d7f0b88 100644 --- a/Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml +++ b/Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml @@ -27,6 +27,12 @@ properties: masking provided by the interrupt controller. const: apple,t8152-smc-mailbox + - description: + T8152 ASC wrapper (v8) mailbox of the AOP, with the counted + FIFOs of the SMC mailbox, described with its send-empty and + recv-not-empty interrupts. + const: apple,t8152-ascwrap-v8-mailbox + - description: ASC mailboxes are the most common variant found on the M1 used for example for the display controller, the system management @@ -92,6 +98,11 @@ properties: - apple,t8142-aop-setup-mailbox - const: apple,t8140-aop-setup-mailbox + - description: + T8152 ANS post-office mailbox, a 0x80 window in the post-office + bank. No interrupts are described for it; the host polls it. + const: apple,t8152-ans-mailbox + - description: An older ASC mailbox interface found on T2 and A11 that is also used for the NVMe coprocessor and the system management @@ -155,7 +166,9 @@ allOf: properties: compatible: contains: - const: apple,secure-rtbuddy-proxy + enum: + - apple,secure-rtbuddy-proxy + - apple,t8152-ans-mailbox then: required: - interrupts @@ -164,7 +177,9 @@ allOf: properties: compatible: contains: - const: apple,t8152-smc-mailbox + enum: + - apple,t8152-ascwrap-v8-mailbox + - apple,t8152-smc-mailbox then: properties: interrupts: @@ -175,6 +190,16 @@ allOf: - const: send-empty - const: recv-not-empty + - if: + properties: + compatible: + contains: + const: apple,t8152-ans-mailbox + then: + properties: + interrupts: false + interrupt-names: false + - if: properties: compatible: @@ -223,6 +248,8 @@ allOf: - apple,t6021-ane-mailbox - apple,t8112-ane-mailbox - apple,t8140-aop-setup-mailbox + - apple,t8152-ans-mailbox + - apple,t8152-ascwrap-v8-mailbox - apple,t8152-smc-mailbox then: properties: diff --git a/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml b/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml index 7f289a02d4b21..22e7bf14e9529 100644 --- a/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml +++ b/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml @@ -23,6 +23,7 @@ properties: - apple,t8122-nvme-ans2 - const: apple,t8103-nvme-ans2 - const: apple,t8132-nvme-ans2 + - const: apple,t8152-nvme-ans2 - items: - const: apple,t8132-nvme-ans2 - const: apple,t8103-nvme-ans2 @@ -111,6 +112,20 @@ properties: buffers must remain reserved and protected by the SART. allOf: + - if: + properties: + compatible: + not: + contains: + enum: + - apple,t6050-nvme-ans2 + - apple,t8152-nvme-ans2 + then: + required: + - resets + - power-domains + - power-domain-names + - if: properties: compatible: @@ -183,11 +198,6 @@ allOf: resets: false power-domains: false power-domain-names: false - else: - required: - - resets - - power-domains - - power-domain-names required: - compatible diff --git a/Documentation/devicetree/bindings/nvmem/apple,spmi-nvmem.yaml b/Documentation/devicetree/bindings/nvmem/apple,spmi-nvmem.yaml index fe8b2001f4fa5..4a2ba5158b0f6 100644 --- a/Documentation/devicetree/bindings/nvmem/apple,spmi-nvmem.yaml +++ b/Documentation/devicetree/bindings/nvmem/apple,spmi-nvmem.yaml @@ -28,6 +28,7 @@ properties: - apple,simetra-pmic - apple,stowe-pmic - apple,vale-pmic + - apple,woodcote-pmic - const: apple,spmi-nvmem reg: diff --git a/Documentation/devicetree/bindings/power/apple,pmgr-pwrstate.yaml b/Documentation/devicetree/bindings/power/apple,pmgr-pwrstate.yaml index 420f47e4522bc..efdd71a9c6521 100644 --- a/Documentation/devicetree/bindings/power/apple,pmgr-pwrstate.yaml +++ b/Documentation/devicetree/bindings/power/apple,pmgr-pwrstate.yaml @@ -84,6 +84,7 @@ properties: - apple,t8132-pmgr-pwrstate - apple,t8140-pmgr-pwrstate - apple,t8142-pmgr-pwrstate + - apple,t8152-pmgr-pwrstate - const: apple,t8103-pmgr-pwrstate reg: diff --git a/Documentation/devicetree/bindings/sound/apple,t8152-aop-audio.yaml b/Documentation/devicetree/bindings/sound/apple,t8152-aop-audio.yaml index 9c14c3fff2e41..b23e734de9206 100644 --- a/Documentation/devicetree/bindings/sound/apple,t8152-aop-audio.yaml +++ b/Documentation/devicetree/bindings/sound/apple,t8152-aop-audio.yaml @@ -26,6 +26,7 @@ properties: - const: apple,t8142-aop-audio - const: apple,t8152-aop-audio - const: apple,t6050-aop-audio + - const: apple,t8152-aop-audio dmas: minItems: 4 diff --git a/Documentation/devicetree/bindings/spmi/apple,spmi.yaml b/Documentation/devicetree/bindings/spmi/apple,spmi.yaml index 48706095da208..14d037a00aedd 100644 --- a/Documentation/devicetree/bindings/spmi/apple,spmi.yaml +++ b/Documentation/devicetree/bindings/spmi/apple,spmi.yaml @@ -41,6 +41,11 @@ properties: - apple,t8132-spmi - apple,t8140-spmi - const: apple,t8103-spmi + - description: + The gen-4 controller of T8152, with its FIFO registers at 0x200. + items: + - const: apple,t8152-spmi + - const: apple,t8142-spmi reg: minItems: 1 diff --git a/Documentation/devicetree/bindings/usb/apple,dwc3.yaml b/Documentation/devicetree/bindings/usb/apple,dwc3.yaml index 6612a5370ee36..6bc0c202dceec 100644 --- a/Documentation/devicetree/bindings/usb/apple,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/apple,dwc3.yaml @@ -13,6 +13,12 @@ description: Apple Silicon SoCs use a Synopsys DesignWare DWC3 based controller for each of their Type-C ports. + On T8152 the bootloader can hand a controller over already running, powered + and with the USB2 side of its ATC PHY set up for host mode. Such a controller + is described by its DWC3 core region, as a host. Its PHY reset and power + domain, and on a Type-C port its USB role switch, exist but are left to the + bootloader, so they are optional. + allOf: - $ref: snps,dwc3-common.yaml# - if: @@ -20,11 +26,37 @@ allOf: compatible: not: contains: - const: apple,t8132-dwc3 + enum: + - apple,t8132-dwc3 + - apple,t8152-dwc3 then: required: - power-domains - if: + properties: + compatible: + contains: + const: apple,t8152-dwc3 + then: + properties: + dr_mode: + const: host + required: + - dr_mode + else: + properties: + reg: + minItems: 2 + reg-names: + minItems: 2 + required: + - reg-names + - if: + properties: + compatible: + not: + contains: + const: apple,t8152-dwc3 not: properties: status: @@ -85,9 +117,10 @@ properties: - const: apple,t8103-dwc3 - const: apple,t8103-dwc3 - const: apple,t8132-dwc3 + - const: apple,t8152-dwc3 reg: - minItems: 2 + minItems: 1 items: - description: Core DWC3 region - description: Apple-specific DWC3 region @@ -96,7 +129,7 @@ properties: - description: AUSBC debug block (T6050) reg-names: - minItems: 2 + minItems: 1 items: - const: dwc3-core - const: dwc3-apple @@ -160,7 +193,6 @@ properties: required: - compatible - reg - - reg-names - interrupts - iommus @@ -183,3 +215,18 @@ examples: usb-role-switch; }; + + - | + #include + #include + + usb@82430000 { + compatible = "apple,t8152-dwc3"; + reg = <0x82430000 0xcd00>; + interrupts = ; + iommus = <&dwc3_2_dart_0 0>, <&dwc3_2_dart_1 1>; + dr_mode = "host"; + maximum-speed = "high-speed"; + snps,dis_u2_susphy_quirk; + snps,dis_u3_susphy_quirk; + }; diff --git a/Documentation/devicetree/bindings/watchdog/apple,wdt.yaml b/Documentation/devicetree/bindings/watchdog/apple,wdt.yaml index e321ee28733d1..9a6634e146d75 100644 --- a/Documentation/devicetree/bindings/watchdog/apple,wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/apple,wdt.yaml @@ -26,6 +26,7 @@ properties: - apple,t8132-wdt - apple,t8140-wdt - apple,t8142-wdt + - apple,t8152-wdt - const: apple,t8103-wdt - items: - enum: diff --git a/arch/arm64/boot/dts/apple/t8152-j873-audio.dtsi b/arch/arm64/boot/dts/apple/t8152-j873-audio.dtsi new file mode 100644 index 0000000000000..72bfb845022b8 --- /dev/null +++ b/arch/arm64/boot/dts/apple/t8152-j873-audio.dtsi @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * J873g audio: the AOP (always-on processor) owns the audio fabric, as + * on T8140. iBoot loads the AOP firmware (j873gaop) and leaves the CPU + * stopped; Linux starts it. The jack codec (CS42L84) and the speaker amp + * (SN012776) are on AP I2C buses; their data goes through AOP services on + * the base-ns ADMAC. Resources are from the 26A434 ADT: aop, dart-sbr, + * admac-base-ns, iop-audio-controller, i2c1, i2c3, pmgr. + */ +#include + +/* + * ADT dart-sbr (sbr_dart in t8152-peripherals.dtsi), shared with the PMP: + * mapper-aop 0, mapper-admac-base-ns 42. iBoot leaves streams 0, 1 and 42 + * translating (root slot 16 owned by the firmware) without setting the + * lock bit. + */ +&sbr_dart { + apple,retain-translation; + status = "okay"; +}; + +/ { + soc { + /* + * ADT aop: iop,ascwrap-v8, msgbox-mailbox-num 0, using-alias, + * not post-office: mailbox 0, aperture 1 of the bank at reg[2] + * (0x310740000) = 0x310740080. ADT interrupts [627, 626, 628]; + * the first two in the SMC order (send-empty, recv-not-empty). + */ + aop_mbox: mailbox@310740080 { + compatible = "apple,t8152-ascwrap-v8-mailbox"; + reg = <0x3 0x10740080 0x0 0x80>; + interrupts = , + ; + interrupt-names = "send-empty", "recv-not-empty"; + #mbox-cells = <0>; + }; + + /* + * ADT admac-base-ns (admac-evolution,t8152): 13 TX and 13 RX + * channels, interrupt destination 0, dart-sbr stream 42. + */ + admac_base_ns: dma-controller@313900000 { + compatible = "apple,t8152-admac"; + reg = <0x3 0x13900000 0x0 0xb4000>; + dma-channels = <26>; + interrupts-extended = <&aic AIC_IRQ 640 IRQ_TYPE_LEVEL_HIGH>, + <0>, <0>, <0>; + #dma-cells = <1>; + iommus = <&sbr_dart 42>; + /* slot 17: slot 16 of stream 42 belongs to the firmware */ + apple,dma-range = <0x110 0x0 0x0 0x10000000>; + }; + + /* + * The AOP's PMGR (ADT pmgr devices AUDIO_MCA0_M..AUDIO_MCA5_M at + * 0x308284400 + 0x20 * N). Their parent audio_p is the + * firmware's: it is up while a service is in pw0 or pwrd. + */ + pmgr_aop: power-management@308284000 { + compatible = "apple,t8152-pmgr", "apple,t8103-pmgr", + "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x3 0x08284000 0x0 0x1000>; + + ps_audio_mca0_m: power-controller@400 { + compatible = "apple,t8152-pmgr-pwrstate", + "apple,t8103-pmgr-pwrstate"; + reg = <0x400 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "audio_mca0_m"; + }; + + ps_audio_mca1_m: power-controller@420 { + compatible = "apple,t8152-pmgr-pwrstate", + "apple,t8103-pmgr-pwrstate"; + reg = <0x420 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "audio_mca1_m"; + }; + + ps_audio_mca2_m: power-controller@440 { + compatible = "apple,t8152-pmgr-pwrstate", + "apple,t8103-pmgr-pwrstate"; + reg = <0x440 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "audio_mca2_m"; + }; + + ps_audio_mca3_m: power-controller@460 { + compatible = "apple,t8152-pmgr-pwrstate", + "apple,t8103-pmgr-pwrstate"; + reg = <0x460 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "audio_mca3_m"; + }; + + ps_audio_mca4_m: power-controller@480 { + compatible = "apple,t8152-pmgr-pwrstate", + "apple,t8103-pmgr-pwrstate"; + reg = <0x480 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "audio_mca4_m"; + }; + + ps_audio_mca5_m: power-controller@4a0 { + compatible = "apple,t8152-pmgr-pwrstate", + "apple,t8103-pmgr-pwrstate"; + reg = <0x4a0 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "audio_mca5_m"; + }; + }; + + /* ADT i2c1: the CS42L84 jack codec (and the aqc NIC's EEPROM). */ + i2c1: i2c@331014000 { + compatible = "apple,t8152-i2c", "apple,t8103-i2c"; + reg = <0x3 0x31014000 0x0 0x4000>; + clocks = <&clkref>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&ps_i2c1>; + + /* + * ADT audio-codec-output: function-reset GPIO 0xcc, + * interrupt on gpio0 pin 203. + */ + jack_codec: codec@4b { + compatible = "cirrus,cs42l84"; + reg = <0x4b>; + reset-gpios = <&pinctrl_ap 204 GPIO_ACTIVE_HIGH>; + interrupts-extended = <&pinctrl_ap 203 IRQ_TYPE_LEVEL_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "Jack"; + }; + }; + + /* ADT i2c3: the SN012776 speaker amplifier. */ + i2c3: i2c@33101c000 { + compatible = "apple,t8152-i2c", "apple,t8103-i2c"; + reg = <0x3 0x3101c000 0x0 0x4000>; + clocks = <&clkref>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + power-domains = <&ps_i2c3>; + + /* + * ADT audio-speaker: function-reset GPIO 0xca, interrupt + * on gpio0 pin 193, speaker-config rx_slot 0, + * vsense_slot 0, isense_slot 2. + */ + speaker_amp: codec@38 { + compatible = "ti,sn012776", "ti,tas2764"; + reg = <0x38>; + shutdown-gpios = <&pinctrl_ap 202 GPIO_ACTIVE_HIGH>; + interrupts-extended = <&pinctrl_ap 193 IRQ_TYPE_LEVEL_LOW>; + #sound-dai-cells = <0>; + ti,imon-slot-no = <2>; + ti,vmon-slot-no = <0>; + /* the AOP's speaker frame: 250 BCLKs at 12 MHz */ + ti,bclk-ratio = <250>; + }; + }; + + aop: aop@310c00000 { + compatible = "apple,t8152-aop"; + reg = <0x3 0x10c00000 0x0 0x1e0000>, + <0x3 0x10600000 0x0 0x4000>; + reg-names = "mmio", "asc"; + mboxes = <&aop_mbox>; + mbox-names = "mbox"; + iommus = <&sbr_dart 0>; + /* slot 17: slot 16 belongs to the firmware */ + apple,dma-range = <0x110 0x0 0x10 0x0>; + + /* + * Bound by name to the firmware's "audio" EPIC service. + * ADT iop-audio-controller: cout/cin on base-ns TX5/RX5, + * spkr on TX1 with its sense data on RX1; Linux ADMAC + * channel = 2 * N for TX N, 2 * N + 1 for RX N. + */ + aop_audio: audio { + compatible = "apple,t8152-aop-audio"; + dmas = <&admac_base_ns 10>, <&admac_base_ns 11>, + <&admac_base_ns 2>, <&admac_base_ns 3>; + dma-names = "cout", "cin", "spkr", "sense"; + power-domains = <&ps_audio_mca0_m>, <&ps_audio_mca1_m>, + <&ps_audio_mca2_m>, <&ps_audio_mca3_m>, + <&ps_audio_mca4_m>, <&ps_audio_mca5_m>; + power-domain-names = "mca0", "mca1", "mca2", + "mca3", "mca4", "mca5"; + #sound-dai-cells = <1>; + }; + }; + }; + + sound { + compatible = "apple,j873-macaudio", "apple,macaudio"; + model = "Mac mini J873"; + #address-cells = <1>; + #size-cells = <0>; + + dai-link@0 { + reg = <0>; + link-name = "Headphone Jack"; + + cpu { + sound-dai = <&aop_audio 0>; + }; + codec { + sound-dai = <&jack_codec>; + }; + }; + + dai-link@1 { + reg = <1>; + link-name = "Speaker"; + + cpu { + sound-dai = <&aop_audio 3>; + }; + codec { + sound-dai = <&speaker_amp>; + }; + }; + }; +}; + +/* The I2C power states (PMGR, parent SIO_CPU is always on). */ +&pmgr { + ps_i2c1: power-controller@cc0 { + compatible = "apple,t8152-pmgr-pwrstate", + "apple,t8103-pmgr-pwrstate"; + reg = <0xcc0 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "i2c1"; + }; + + ps_i2c3: power-controller@d00 { + compatible = "apple,t8152-pmgr-pwrstate", + "apple,t8103-pmgr-pwrstate"; + reg = <0xd00 4>; + #power-domain-cells = <0>; + #reset-cells = <0>; + label = "i2c3"; + }; +}; diff --git a/arch/arm64/boot/dts/apple/t8152-j873-ethernet.dtsi b/arch/arm64/boot/dts/apple/t8152-j873-ethernet.dtsi new file mode 100644 index 0000000000000..8b4f0f007df54 --- /dev/null +++ b/arch/arm64/boot/dts/apple/t8152-j873-ethernet.dtsi @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * J873g internal PCIe (apcie) port 2: the on-board 10GbE NIC (ADT + * /arm-io/apcie/pci-bridge2/lan0; the ADT names an aqc107, the device has + * PCI ID 10ec:8127 and identifies as a Realtek RTL8125CP, XID 0x708). + * iBoot leaves the APCIE power domains on and + * the root complex enabled, but the AUS5 PHY gated and the lanes assigned + * to port 0; the loader ungates the PHY, writes the ADT lane-cfg and applies + * the dart-apcie2 tunables first. Port setup follows the T602x/T8122 + * register layout. Port 0 (N1) is bus 1, port 2 is bus 2. + * Resources are from the 26A434 ADT: apcie, dart-apcie2, gpio0. + */ +#include + +/ { + aliases { + ethernet0 = ðernet0; + }; +}; + +/* + * dart-apcie2, described in t8152-peripherals.dtsi. The ADT window is + * 0x20000; keep the 0xc000 this port was brought up with, the size that + * pcie0_dart has in t8152-j873-n1.dtsi. + */ +&pcie2_dart { + reg = <0x3 0x8a000000 0x0 0xc000>; + status = "okay"; +}; + +&pcie { + reg = <0x1c 0xb0000000 0x0 0x1000000>, /* config */ + <0x3 0x8c000000 0x0 0x4000>, /* rc */ + <0x3 0x88028000 0x0 0x4000>, /* port0 */ + <0x3 0x8f010000 0x0 0x4000>, /* phy0 */ + <0x3 0x8a028000 0x0 0x4000>, /* port2 */ + <0x3 0x8f018000 0x0 0x4000>; /* phy2 */ + reg-names = "config", "rc", "port0", "phy0", "port2", "phy2"; + /* One per root port, indexed by the port number. */ + interrupts = , + , + ; + iommu-map = <0x100 &pcie0_dart 1 1>, + <0x101 &pcie0_dart 2 1>, + <0x102 &pcie0_dart 3 1>, + <0x200 &pcie2_dart 1 1>; + bus-range = <0 7>; + + port02: pci@2,0 { + device_type = "pci"; + reg = <0x1000 0x0 0x0 0x0 0x0>; + reset-gpios = <&pinctrl_ap 5 GPIO_ACTIVE_LOW>; + bus-range = <2 2>; + #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 &port02 0 0 0 0>, + <0 0 0 2 &port02 0 0 0 1>, + <0 0 0 3 &port02 0 0 0 2>, + <0 0 0 4 &port02 0 0 0 3>; + + ethernet0: ethernet@0,0 { + reg = <0x20000 0x0 0x0 0x0 0x0>; + /* Filled in by the loader from the ADT. */ + local-mac-address = [00 00 00 00 00 00]; + }; + }; +}; diff --git a/arch/arm64/boot/dts/apple/t8152-j873-nvme.dtsi b/arch/arm64/boot/dts/apple/t8152-j873-nvme.dtsi new file mode 100644 index 0000000000000..c53059ab55d34 --- /dev/null +++ b/arch/arm64/boot/dts/apple/t8152-j873-nvme.dtsi @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * J873g ANS2 NVMe. + * iBoot leaves the ANS firmware running with the NVMe controller disabled; + * the driver wakes it with a fresh RTKit handshake (as m1n1 does). NVMe + * registers and NVMMU share the 0x325cc0000 window. The mailbox is the ANS + * post-office window (msgbox-mailbox-num 3, no alias: 0x316000000 + + * 0x10300). No PMGR power or reset yet. + * Resources are from the 26A434 ADT: ans, sart-ans. + */ + +/ { + soc { + ans_mbox: mailbox@316010300 { + compatible = "apple,t8152-ans-mailbox"; + reg = <0x3 0x16010300 0x0 0x80>; + #mbox-cells = <0>; + }; + + sart: iommu@325c50000 { + compatible = "apple,t8152-sart"; + reg = <0x3 0x25c50000 0x0 0xc000>; + }; + + nvme: nvme@325cc0000 { + compatible = "apple,t8152-nvme-ans2"; + reg = <0x3 0x25cc0000 0x0 0x60000>, + <0x3 0x21600000 0x0 0x4000>; + reg-names = "nvme", "ans"; + interrupts = ; + mboxes = <&ans_mbox>; + apple,sart = <&sart>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/apple/t8152-j873-usb.dtsi b/arch/arm64/boot/dts/apple/t8152-j873-usb.dtsi new file mode 100644 index 0000000000000..6f1a956bd68e3 --- /dev/null +++ b/arch/arm64/boot/dts/apple/t8152-j873-usb.dtsi @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * J873g USB2 host bring-up: usb-drd1 (back-left port) and usb-drd2 + * (front ports via the on-board hub). + * The loader powers the controllers and sets up the USB2 side of their ATC + * PHYs for host mode before Linux starts (there is no T8152 USB power-domain, + * ATC PHY or Type-C support yet). + * The controllers are described by their DWC3 core region, as hosts behind + * their two DARTs (apple,t8152-dwc3); their PHY reset and power domain, and on + * the Type-C port the role switch, exist but are left to the loader. + * Resources are from the 26A434 ADT: dart-usb1/2, usb-drd1/2. + * + * dart-usb1 and dart-usb2 each have two DART instances (ADT reg[0] and + * reg[1], 0xc000 each, sharing one interrupt). t8152-peripherals.dtsi lists + * both windows on one node (dwc3_1_dart, dwc3_2_dart), but the DART driver + * drives one instance per node and the binding reads a second reg entry as + * DAPF or auxiliary registers. Keep instance 0 on the shared node, with its + * own window only, and describe instance 1 as a node of its own. + */ + +&dwc3_1_dart { + reg = <0x4 0x0b020000 0x0 0xc000>; + status = "okay"; +}; + +&dwc3_2_dart { + reg = <0x3 0x83020000 0x0 0xc000>; + status = "okay"; +}; + +/ { + soc { + dwc3_1_dart_1: iommu@40b040000 { + compatible = "apple,t8152-dart", "apple,t8110-dart"; + reg = <0x4 0x0b040000 0x0 0xc000>; + interrupts = ; + #iommu-cells = <1>; + }; + + usb1: usb@40a430000 { + compatible = "apple,t8152-dwc3"; + reg = <0x4 0x0a430000 0x0 0xcd00>; + interrupts = ; + dr_mode = "host"; + maximum-speed = "high-speed"; + iommus = <&dwc3_1_dart 0>, <&dwc3_1_dart_1 1>; + snps,dis_u2_susphy_quirk; + snps,dis_u3_susphy_quirk; + }; + + dwc3_2_dart_1: iommu@383040000 { + compatible = "apple,t8152-dart", "apple,t8110-dart"; + reg = <0x3 0x83040000 0x0 0xc000>; + interrupts = ; + #iommu-cells = <1>; + }; + + /* usb-drd2: on-board VL822 hub behind the two front USB-C ports. */ + usb2: usb@382430000 { + compatible = "apple,t8152-dwc3"; + reg = <0x3 0x82430000 0x0 0xcd00>; + interrupts = ; + dr_mode = "host"; + maximum-speed = "high-speed"; + iommus = <&dwc3_2_dart 0>, <&dwc3_2_dart_1 1>; + snps,dis_u2_susphy_quirk; + snps,dis_u3_susphy_quirk; + }; + }; +}; diff --git a/arch/arm64/boot/dts/apple/t8152-j873g.dts b/arch/arm64/boot/dts/apple/t8152-j873g.dts index 00fe5207a1956..0f98b07748b01 100644 --- a/arch/arm64/boot/dts/apple/t8152-j873g.dts +++ b/arch/arm64/boot/dts/apple/t8152-j873g.dts @@ -10,6 +10,7 @@ #include #include +#include / { compatible = "apple,j873g", "apple,t8152", "apple,arm-platform"; @@ -205,6 +206,15 @@ opp-level = <3>; }; }; + + /* The 24 MHz timebase (ADT timebase-frequency), as on T8103. */ + clkref: clock-ref { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "clkref"; + }; + timer { compatible = "arm,armv8-timer"; interrupts = , @@ -241,6 +251,62 @@ #performance-domain-cells = <0>; }; + /* + * ADT /arm-io/nub-spmi0 (gen 4) and its primary PMU, pmu-main + * ("woodcote", slave 0xe). The boot flags live in the legacy + * scratchpad (info-leg_scrpad = 0xf800), laid out as on T8103 + * and T8140; boot_stage read 0x30 (kernel started) here. + */ + nub_spmi0: spmi@308714000 { + /* + * Gen 4: FIFO registers at 0x200 (the block is 0x4000 + * long); polled, so no interrupts are described yet. + */ + compatible = "apple,t8152-spmi", "apple,t8142-spmi"; + reg = <0x3 0x08714000 0x0 0x4000>; + #address-cells = <2>; + #size-cells = <0>; + + pmic@e { + compatible = "apple,woodcote-pmic", "apple,spmi-nvmem"; + reg = <0xe SPMI_USID>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + boot_stage: boot-stage@f801 { + reg = <0xf801 0x1>; + }; + + boot_error_count: boot-error-count@f802,0 { + reg = <0xf802 0x1>; + bits = <0 4>; + }; + + panic_count: panic-count@f802,4 { + reg = <0xf802 0x1>; + bits = <4 4>; + }; + + /* Set before off1, or the machine powers back on. */ + shutdown_flag: shutdown-flag@f80f,3 { + reg = <0xf80f 0x1>; + bits = <3 1>; + }; + }; + }; + }; + + /* ADT /arm-io/wdt (wdt,t8152): restart fallback and /dev/watchdog. */ + wdt: watchdog@3082b0000 { + compatible = "apple,t8152-wdt", "apple,t8103-wdt"; + reg = <3 0x082b0000 0 0x4000>; + clocks = <&clkref>; + interrupts = ; + }; + smc_mbox: mailbox@30c710080 { compatible = "apple,t8152-smc-mailbox"; reg = <3 0x0c710080 0 0x80>; @@ -257,6 +323,15 @@ reg-names = "smc", "sram"; mboxes = <&smc_mbox>; + /* Power off (MBSE = off1) and restart (MBSE = phra). */ + smc_reboot: reboot { + compatible = "apple,smc-reboot"; + nvmem-cells = <&shutdown_flag>, <&boot_stage>, + <&boot_error_count>, <&panic_count>; + nvmem-cell-names = "shutdown_flag", "boot_stage", + "boot_error_count", "panic_count"; + }; + hwmon { compatible = "apple,smc-hwmon"; apple,discover-temperatures; @@ -265,6 +340,8 @@ apple,key-id = "F0Ac"; apple,fan-minimum = "F0Mn"; apple,fan-maximum = "F0Mx"; + apple,fan-target = "F0Tg"; + apple,fan-mode = "F0md"; label = "Fan"; }; }; @@ -295,12 +372,6 @@ <0x4 0x3040000 0x0 0xc000>; }; -/* Retain the register view published by this board's live hardware capture. */ -&dwc3_1_dart { - reg = <0x4 0xb020000 0x0 0xc000>, - <0x4 0xb040000 0x0 0xc000>; -}; - /* Retain the register view published by this board's live hardware capture. */ &dwc3_3_dart { reg = <0x4 0x13020000 0x0 0xc000>, @@ -423,10 +494,11 @@ <0x3 0xa0000000 0x0 0x8000>; }; -/* Unexposed chassis port instances remain described and disabled. */ - -/* Retain the register view published by this board's live hardware capture. */ -&dwc3_2_dart { - reg = <0x3 0x83020000 0x0 0xc000>, - <0x3 0x83040000 0x0 0xc000>; -}; +/* + * The J873g fragments enable and refine nodes of t8152-peripherals.dtsi + * (the USB, apcie port 2 and dart-sbr DARTs), so they come after it. + */ +#include "t8152-j873-nvme.dtsi" +#include "t8152-j873-usb.dtsi" +#include "t8152-j873-ethernet.dtsi" +#include "t8152-j873-audio.dtsi" diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c index e330bb9300975..cc57d9c76847e 100644 --- a/drivers/dma/apple-admac.c +++ b/drivers/dma/apple-admac.c @@ -78,13 +78,29 @@ */ #define REG_CHAN_BASE_LEGACY(ch) (0x8000 + (ch) * 0x200) #define REG_CHAN_BASE_EVOLVED(ch) (((ch) & 1 ? 0xc000 : 0x8000) + ((ch) / 2) * 0x200) -#define REG_CHAN_BASE(ad, ch) ((ad)->evolved_layout ? \ +/* + * T8152 (ADT admac-evolution,t8152; the macOS AudioDMAController-T8152 + * driver): the same per-channel block, 0x4000 apart, TX at 0x40000 and RX + * at 0x80000, and a channel has to be put in state 2 (+0x30 bits 3:0) + * before it is started. The descriptor and report FIFO ports are the legacy + * ones (the RX descriptor port answers at 0x14000 + 4n, not at the ADT's + * 0x10040 + 4n). + */ +#define REG_CHAN_BASE_T8152(ch) (((ch) & 1 ? 0x80000 : 0x40000) + ((ch) / 2) * 0x4000) +#define REG_CHAN_BASE(ad, ch) ((ad)->t8152_layout ? REG_CHAN_BASE_T8152(ch) : \ + (ad)->evolved_layout ? \ REG_CHAN_BASE_EVOLVED(ch) : REG_CHAN_BASE_LEGACY(ch)) #define REG_CHAN_CTL(ad, ch) (REG_CHAN_BASE(ad, ch) + 0x00) #define REG_CHAN_CTL_RST_RINGS BIT(0) #define REG_CHAN_CONFIG(ad, ch) (REG_CHAN_BASE(ad, ch) + 0x04) +/* macOS writes this for the T8152 base-ns channels before every start */ +#define CHAN_CONFIG_T8152 0x029b0000 #define REG_CHAN_BURST(ad, ch) (REG_CHAN_BASE(ad, ch) + 0x30) +/* T8152: the low nibble of the same register is the channel state */ +#define REG_CHAN_STATE(ad, ch) REG_CHAN_BURST(ad, ch) +#define CHAN_STATE_MASK GENMASK(3, 0) +#define CHAN_STATE_READY 2 #define REG_DESC_RING(ad, ch) (REG_CHAN_BASE(ad, ch) + 0x70) #define REG_REPORT_RING(ad, ch) (REG_CHAN_BASE(ad, ch) + 0x74) @@ -112,6 +128,11 @@ #define REG_DESC_WRITE(ch) (0x10000 + ((ch) / 2) * 0x4 + ((ch) & 1) * 0x4000) #define REG_REPORT_READ(ch) (0x10100 + ((ch) / 2) * 0x4 + ((ch) & 1) * 0x4000) +/* T8152: the AP's share of each SRAM pool starts above the firmware's. */ +#define T8152_SRAM_BASE 0x1000 +#define T8152_SRAM_BLOCK 1024 +#define SRAM_SIZE_MASK GENMASK(15, 0) + #define REG_TX_INTSTATE(idx) (0x0030 + (idx) * 4) #define REG_RX_INTSTATE(idx) (0x0040 + (idx) * 4) #define REG_GLOBAL_INTSTATE(idx) (0x0050 + (idx) * 4) @@ -163,6 +184,8 @@ struct admac_chan { struct tasklet_struct tasklet; u32 carveout; + /* T8152: transfer descriptor id, 1..255 */ + u8 desc_id; spinlock_t lock; struct admac_tx *current_tx; @@ -214,6 +237,7 @@ struct admac_data { bool evolved_layout; bool split_channels; bool display; + bool t8152_layout; bool ctl_programmed; /* Display ADMAC: its control block's two windows and their tunables */ void __iomem *control[2]; @@ -247,6 +271,7 @@ struct admac_hw { bool evolved_layout; bool split_channels; bool display; + bool t8152_layout; }; static int admac_alloc_sram_carveout(struct admac_data *ad, @@ -255,6 +280,8 @@ static int admac_alloc_sram_carveout(struct admac_data *ad, { struct admac_sram *sram; int i, ret = 0, nblocks; + u32 first = 0, block = SRAM_BLOCK; + ad->txcache.size = readl_relaxed(ad->base + REG_TX_SRAM_SIZE); ad->rxcache.size = readl_relaxed(ad->base + REG_RX_SRAM_SIZE); /* T8132 reports channel metadata in the upper half of these words. */ @@ -262,6 +289,13 @@ static int admac_alloc_sram_carveout(struct admac_data *ad, ad->txcache.size &= GENMASK(15, 0); ad->rxcache.size &= GENMASK(15, 0); } + if (ad->t8152_layout) { + /* bits 31:24 are the channel count */ + ad->txcache.size &= SRAM_SIZE_MASK; + ad->rxcache.size &= SRAM_SIZE_MASK; + first = T8152_SRAM_BASE; + block = T8152_SRAM_BLOCK; + } if (dir == DMA_MEM_TO_DEV) sram = &ad->txcache; @@ -270,14 +304,14 @@ static int admac_alloc_sram_carveout(struct admac_data *ad, mutex_lock(&ad->cache_alloc_lock); - nblocks = sram->size / SRAM_BLOCK; + nblocks = sram->size > first ? (sram->size - first) / block : 0; for (i = ad->split_channels ? 1 : 0; i < nblocks; i++) if (!(sram->allocated & BIT(i))) break; if (i < nblocks) { - *out = FIELD_PREP(CHAN_SRAM_CARVEOUT_BASE, i * SRAM_BLOCK) | - FIELD_PREP(CHAN_SRAM_CARVEOUT_SIZE, SRAM_BLOCK); + *out = FIELD_PREP(CHAN_SRAM_CARVEOUT_BASE, first + i * block) | + FIELD_PREP(CHAN_SRAM_CARVEOUT_SIZE, block); sram->allocated |= BIT(i); } else { ret = -EBUSY; @@ -294,18 +328,24 @@ static void admac_free_sram_carveout(struct admac_data *ad, { struct admac_sram *sram; u32 base = FIELD_GET(CHAN_SRAM_CARVEOUT_BASE, carveout); + u32 first = 0, block = SRAM_BLOCK; int i; + if (ad->t8152_layout) { + first = T8152_SRAM_BASE; + block = T8152_SRAM_BLOCK; + } + if (dir == DMA_MEM_TO_DEV) sram = &ad->txcache; else sram = &ad->rxcache; - if (WARN_ON(base >= sram->size)) + if (WARN_ON(base < first || base >= sram->size)) return; mutex_lock(&ad->cache_alloc_lock); - i = base / SRAM_BLOCK; + i = (base - first) / block; sram->allocated &= ~BIT(i); mutex_unlock(&ad->cache_alloc_lock); } @@ -409,6 +449,15 @@ static void admac_write_hw_desc(struct admac_data *ad, int channo, adchan->seq = adchan->seq == 0xff ? 1 : adchan->seq + 1; flags = DISPLAY_FLAG_DESC_REPORT | adchan->seq; + } else if (ad->t8152_layout) { + /* + * T8152: the low byte of the last word is a descriptor id, + * which macOS counts 1..255 and never leaves at 0. + */ + struct admac_chan *adchan = &ad->channels[channo]; + + adchan->desc_id = adchan->desc_id == 255 ? 1 : adchan->desc_id + 1; + flags = FLAG_DESC_NOTIFY | adchan->desc_id; } dev_dbg(ad->dev, "ch%d descriptor: addr=0x%pad len=0x%zx flags=0x%x\n", @@ -671,6 +720,11 @@ static void admac_start_chan(struct admac_chan *adchan) writel_relaxed(STATUS_DESC_DONE | STATUS_ERR, ad->base + REG_CHAN_INTMASK(ad, adchan->no, ad->irq_index)); } + if (ad->t8152_layout) { + writel_relaxed(CHAN_CONFIG_T8152, ad->base + REG_CHAN_CONFIG(ad, adchan->no)); + admac_modify(ad, REG_CHAN_STATE(ad, adchan->no), CHAN_STATE_MASK, + CHAN_STATE_READY); + } switch (admac_chan_direction(adchan->no)) { case DMA_MEM_TO_DEV: @@ -1445,7 +1499,8 @@ static int admac_device_config(struct dma_chan *chan, * of words position in a frame. That's where the importance of this control * comes from. */ - switch (is_tx ? config->dst_port_window_size : config->src_port_window_size) { + switch (ad->t8152_layout ? 0 : + is_tx ? config->dst_port_window_size : config->src_port_window_size) { case 0 ... 1: break; case 2: @@ -1467,6 +1522,15 @@ static int admac_device_config(struct dma_chan *chan, adchan->realign_bytes = admac_config_realign_bytes(config); + /* + * Optional: a u32 frame size in bytes, which a paused capture is + * restarted aligned to on resume (see admac_cyclic_realign()). + */ + if (config->peripheral_config && config->peripheral_size == sizeof(u32)) + adchan->realign_bytes = *(u32 *)config->peripheral_config; + else + adchan->realign_bytes = 0; + /* * By FIFOCTL_LIMIT we seem to set the maximal number of bytes allowed to be * held in controller's per-channel FIFO. Transfers seem to be triggered @@ -1588,6 +1652,7 @@ static int admac_probe(struct platform_device *pdev) ad->evolved_layout = hw->evolved_layout; ad->split_channels = hw->split_channels; ad->display = hw->display; + ad->t8152_layout = hw->t8152_layout; mutex_init(&ad->cache_alloc_lock); if (ad->display) { @@ -1751,8 +1816,13 @@ static const struct admac_hw admac_t6050_display_hw = { .display = true, }; +static const struct admac_hw admac_t8152_hw = { + .t8152_layout = true, +}; + static const struct of_device_id admac_of_match[] = { { .compatible = "apple,t6050-display-admac", .data = &admac_t6050_display_hw }, + { .compatible = "apple,t8152-admac", .data = &admac_t8152_hw }, { .compatible = "apple,t8140-admac", .data = &admac_t8140_hw }, { .compatible = "apple,t8132-admac", .data = &admac_t8132_hw }, { .compatible = "apple,t8122-admac", .data = &admac_t8122_hw }, diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c index fb2a96284262f..b5df6afaafb8e 100644 --- a/drivers/iommu/apple-dart.c +++ b/drivers/iommu/apple-dart.c @@ -4507,6 +4507,14 @@ static irqreturn_t apple_dart_irq(int irq, void *dev) static bool apple_dart_is_locked(struct apple_dart *dart) { + /* + * apple,retain-translation: the bootloader left live stream tables + * that a co-processor's firmware depends on, but did not set the lock + * bit (T8152 dart-sbr: AOP and audio ADMAC streams). Treat it as + * locked so the tables are inherited rather than reset. + */ + if (of_property_read_bool(dart->dev->of_node, "apple,retain-translation")) + return true; return !!(apple_dart_readl(dart, dart->hw->lock) & dart->hw->lock_bit); } diff --git a/drivers/mfd/macsmc.c b/drivers/mfd/macsmc.c index 7c525b6c7b2e1..99940afa2cc65 100644 --- a/drivers/mfd/macsmc.c +++ b/drivers/mfd/macsmc.c @@ -111,9 +111,15 @@ static int apple_smc_add_described_devices(struct apple_smc *smc, const struct m return 0; } -/* T8152 currently exposes read-only telemetry; firmware owns fan control. */ +/* + * T8152: temperatures and fans (hwmon; the fan keys are read-only unless the + * unsafe fan_control parameter is set) and power off/restart (reboot, which + * only writes the MBSE key). Notifications, GPIO and the power supply are not + * qualified there yet. + */ static const struct mfd_cell apple_smc_telemetry_devs[] = { MFD_CELL_OF("macsmc-hwmon", NULL, NULL, 0, 0, "apple,smc-hwmon"), + MFD_CELL_OF("macsmc-reboot", NULL, NULL, 0, 0, "apple,smc-reboot"), }; static void apple_smc_read_sram(struct apple_smc *smc, void *buf, size_t size) @@ -615,7 +621,7 @@ static int apple_smc_probe(struct platform_device *pdev) return dev_err_probe(smc->dev, ret, "Failed to get key count"); smc->key_count = be32_to_cpu(count); - /* Notifications, GPIO and power management are not qualified on T8152. */ + /* T8152: key reads and writes are qualified; notifications and GPIO are not. */ if (of_device_is_compatible(dev->of_node, "apple,t8152-smc")) return devm_mfd_add_devices(smc->dev, PLATFORM_DEVID_NONE, apple_smc_telemetry_devs, diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c index f0892f4986b94..41ce8b6ef7274 100644 --- a/drivers/nvme/host/apple.c +++ b/drivers/nvme/host/apple.c @@ -72,6 +72,15 @@ #define APPLE_ANS_LINEAR_ASQ_DB 0x2490c #define APPLE_ANS_LINEAR_IOSQ_DB 0x24910 +/* + * ADT nvme-secure-reg-layout (T8152, macOS AppleANS2NVMeController with its + * 0x92a flag set): AQA/ASQ/ACQ and the I/O queue registers move up by + * 0x4000 and LINEAR_SQ_CTRL moves into the NVMMU block. CC/CSTS, the + * doorbells and the NVMMU TCB registers stay where they are. + */ +#define APPLE_ANS_SECURE_QREG_SHIFT 0x4000 +#define APPLE_ANS_SECURE_LINEAR_SQ_CTRL 0x2813c + #define APPLE_NVMMU_NUM_TCBS 0x28100 #define APPLE_NVMMU_ASQ_TCB_BASE 0x28108 #define APPLE_NVMMU_IOSQ_TCB_BASE 0x28110 @@ -225,6 +234,9 @@ struct apple_nvme_hw { u32 sleep_shn; /* The ANS is never reset through PMGR here, so no reset is named. */ bool reset_optional; + bool secure_reg_layout; + /* Also send the NVMe shutdown notification (CC.SHN) on removal. */ + bool shutdown_notify; u32 max_queue_depth; unsigned long quirks; }; @@ -407,6 +419,17 @@ static int apple_nvme_read_handoff(struct apple_nvme *anv) return apple_nvme_can_adopt_rtkit(anv) ? 0 : -EIO; } +static u32 apple_nvme_qreg(const struct apple_nvme *anv, u32 reg) +{ + return anv->hw->secure_reg_layout ? reg + APPLE_ANS_SECURE_QREG_SHIFT : reg; +} + +static u32 apple_nvme_lsq_ctrl(const struct apple_nvme *anv) +{ + return anv->hw->secure_reg_layout ? APPLE_ANS_SECURE_LINEAR_SQ_CTRL : + APPLE_ANS_LINEAR_SQ_CTRL; +} + static inline struct apple_nvme *queue_to_apple_nvme(struct apple_nvme_queue *q) { if (q->is_adminq) @@ -1383,10 +1406,13 @@ static int apple_nvme_disable_locked(struct apple_nvme *anv, bool shutdown) * The final system shutdown is the exception for SHN: without it the * controller counts every Linux shutdown as unsafe (SMART * unsafe_shutdowns) and recovers on the next start, which slows the - * loader and the first seconds of I/O. A failed SHN changes nothing: - * the CC.EN clear below still runs. + * loader and the first seconds of I/O. Where the firmware handles it, + * removal sends it too. A failed SHN changes nothing: the CC.EN clear + * below still runs. */ - if (READ_ONCE(anv->final_shutdown) && !apple_rtkit_is_crashed(anv->rtk)) { + if ((READ_ONCE(anv->final_shutdown) || + (shutdown && anv->hw->shutdown_notify && READ_ONCE(anv->removing))) && + !apple_rtkit_is_crashed(anv->rtk)) { ret = nvme_disable_ctrl(&anv->ctrl, true); if (ret) dev_warn(anv->dev, "shutdown notification failed: %d\n", ret); @@ -1922,10 +1948,10 @@ static void apple_nvme_reset_work(struct work_struct *work) */ if (!anv->lsq_in_nvmmu) { writel(APPLE_ANS_LINEAR_SQ_EN, - anv->mmio_nvme + APPLE_ANS_LINEAR_SQ_CTRL); + anv->mmio_nvme + apple_nvme_lsq_ctrl(anv)); if (anv->hw->needs_ioq_registers) { u32 lsq_ctrl = readl(anv->mmio_nvme + - APPLE_ANS_LINEAR_SQ_CTRL); + apple_nvme_lsq_ctrl(anv)); if (!(lsq_ctrl & APPLE_ANS_LINEAR_SQ_EN)) { dev_err(anv->dev, @@ -1948,9 +1974,11 @@ static void apple_nvme_reset_work(struct work_struct *work) if (anv->hw->needs_ioq_registers) ioqa_depth--; ioqa = ioqa_depth | (ioqa_depth << 16); - writel(ioqa, anv->mmio_nvme + APPLE_ANS_MAX_PEND_CMDS_CTRL); + writel(ioqa, anv->mmio_nvme + + apple_nvme_qreg(anv, APPLE_ANS_MAX_PEND_CMDS_CTRL)); if (anv->hw->needs_ioq_registers && - readl(anv->mmio_nvme + APPLE_ANS_MAX_PEND_CMDS_CTRL) != ioqa) { + readl(anv->mmio_nvme + + apple_nvme_qreg(anv, APPLE_ANS_MAX_PEND_CMDS_CTRL)) != ioqa) { dev_err(anv->dev, "failed to program I/O queue aperture\n"); ret = -EIO; goto out; @@ -1964,11 +1992,11 @@ static void apple_nvme_reset_work(struct work_struct *work) /* Setup the admin queue */ aqa = APPLE_NVME_AQ_DEPTH - 1; aqa |= aqa << 16; - writel(aqa, anv->mmio_nvme + NVME_REG_AQA); + writel(aqa, anv->mmio_nvme + apple_nvme_qreg(anv, NVME_REG_AQA)); apple_nvme_writeq(anv, anv->adminq.sq_dma_addr, - anv->mmio_nvme + NVME_REG_ASQ); + anv->mmio_nvme + apple_nvme_qreg(anv, NVME_REG_ASQ)); apple_nvme_writeq(anv, anv->adminq.cq_dma_addr, - anv->mmio_nvme + NVME_REG_ACQ); + anv->mmio_nvme + apple_nvme_qreg(anv, NVME_REG_ACQ)); if (anv->hw->has_lsq_nvmmu) { /* Setup NVMMU for both queues */ @@ -2035,10 +2063,10 @@ static void apple_nvme_reset_work(struct work_struct *work) * dedicated registers. Without them it crashes and its crash log * reports null I/O SQ and CQ addresses. */ - apple_nvme_writeq(anv, anv->ioq.cq_dma_addr, - anv->mmio_nvme + APPLE_ANS_IOCQ_REGISTER); - apple_nvme_writeq(anv, anv->ioq.sq_dma_addr, - anv->mmio_nvme + APPLE_ANS_IOSQ_REGISTER); + apple_nvme_writeq(anv, anv->ioq.cq_dma_addr, anv->mmio_nvme + + apple_nvme_qreg(anv, APPLE_ANS_IOCQ_REGISTER)); + apple_nvme_writeq(anv, anv->ioq.sq_dma_addr, anv->mmio_nvme + + apple_nvme_qreg(anv, APPLE_ANS_IOSQ_REGISTER)); } nr_io_queues = 1; if (anv->hw->has_queue_count) { @@ -3189,6 +3217,22 @@ static const struct apple_nvme_hw apple_nvme_t6050_hw = { .quirks = NVME_QUIRK_NO_APST | NVME_QUIRK_BROKEN_FUA, }; +/* + * T8152 uses the post-M4 queue setup, but its NVMe registers and NVMMU share + * one window (0x325cc0000 on J873) like T8103, with the secure register + * layout. There is no T8152 PMGR driver yet, so the controller has no reset + * line in the DT. + */ +static const struct apple_nvme_hw apple_nvme_t8152_hw = { + .has_lsq_nvmmu = true, + .needs_ioq_registers = true, + .reset_optional = true, + .secure_reg_layout = true, + .shutdown_notify = true, + .max_queue_depth = 64, + .quirks = NVME_QUIRK_BROKEN_FUA, +}; + static const struct of_device_id apple_nvme_of_match[] = { { .compatible = "apple,t6041-nvme-ans2", .data = &apple_nvme_t6040_hw }, { .compatible = "apple,t6050-nvme-ans2", .data = &apple_nvme_t6050_hw }, @@ -3197,6 +3241,7 @@ static const struct of_device_id apple_nvme_of_match[] = { { .compatible = "apple,t8132-nvme-ans2", .data = &apple_nvme_t8132_hw }, { .compatible = "apple,t8140-nvme-ans2", .data = &apple_nvme_t8140_hw }, { .compatible = "apple,t8142-nvme-ans2", .data = &apple_nvme_t8142_hw }, + { .compatible = "apple,t8152-nvme-ans2", .data = &apple_nvme_t8152_hw }, { .compatible = "apple,nvme-ans2", .data = &apple_nvme_t8103_hw }, {}, }; diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c index dec95de353ca9..6419c05577818 100644 --- a/drivers/pci/controller/pcie-apple.c +++ b/drivers/pci/controller/pcie-apple.c @@ -267,6 +267,12 @@ struct hw_info { bool pipe_rst; bool no_port_reset; bool mps_timers; + /* + * Keep endpoints at their reset Max_Read_Request_Size (512 bytes). + * On T8152 an RTL8127 at MRRS 4096 (what r8169 asks for) transmits + * 9000-byte frames at 7.0 Gbit/s; at 512 it reaches 9.93. + */ + bool no_inc_mrrs; }; static const struct hw_info t8103_hw = { @@ -322,6 +328,7 @@ static const struct hw_info t8152_hw = { .max_rid2sid = 512, .refbuf_off = true, .pipe_rst = true, + .no_inc_mrrs = true, }; /* @@ -4859,6 +4866,7 @@ static int apple_pcie_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "Failed to attach power domains\n"); + bridge->no_inc_mrrs = hw->no_inc_mrrs; if (of_property_present(dev->of_node, "apple,managed-sids")) { u32 ids[15]; int count = of_property_count_u32_elems(dev->of_node, "apple,managed-sids"); diff --git a/drivers/soc/apple/mailbox.c b/drivers/soc/apple/mailbox.c index b73e7da0b2b59..caea0c70ae8ff 100644 --- a/drivers/soc/apple/mailbox.c +++ b/drivers/soc/apple/mailbox.c @@ -238,6 +238,10 @@ struct apple_mbox_hw { bool is_ascwrap_v8; /* The mailbox interrupt never reaches the AIC: receive by polling. */ bool rx_poll_only; + /* No interrupts are described; receive and send are polled. */ + bool rx_poll_required; + /* J873 post-office window a polled provider must sit at. */ + u64 j873_window; /* Status word counts RX occupancy and free TX slots; paired transfers. */ bool counted_fifo; bool ap_initializes_mailboxes; @@ -271,7 +275,7 @@ struct apple_mbox_priv { struct apple_mbox mbox; /* ASCWrap v8 only: the provider's PMGR2 PSD service block (read-only). */ void __iomem *psd_regs; - /* ASCWrap v8 only: receive by polling; fixed at probe. */ + /* ASCWrap v8 and polled providers: receive by polling; fixed at probe. */ bool rx_poll_only; /* rx_lock: recv interrupt enabled and not yet disabled again. */ bool rx_irq_live; @@ -293,7 +297,8 @@ static struct apple_mbox_priv *apple_mbox_to_priv(struct apple_mbox *mbox) /* Only providers allocated by apple_mbox_probe() have a receive poller. */ static bool apple_mbox_has_rx_poller(const struct apple_mbox *mbox) { - return mbox->hw->is_ascwrap_v8 || mbox->hw->rx_poll_only; + return mbox->hw->is_ascwrap_v8 || mbox->hw->rx_poll_only || + mbox->hw->rx_poll_required; } /* Both ASCWrap generations share the consumer lifecycle API below. */ @@ -1614,6 +1619,16 @@ static int apple_mbox_probe(struct platform_device *pdev) return ret; } else { res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + /* + * A polled provider must be exactly its own 0x80-byte window of + * the J873 post-office bank; the rest belongs to other roles. + */ + if (mbox->hw->rx_poll_required && + (!of_machine_is_compatible("apple,j873g") || !res || + res->start != mbox->hw->j873_window || + resource_size(res) != APPLE_ASCWRAP_V8_MBOX_SIZE)) + return dev_err_probe(dev, -EINVAL, + "post-office window does not match the J873 profile\n"); if (!res || resource_size(res) < mbox->hw->reg_offset + mbox->hw->i2a_recv1 + sizeof(u64)) return dev_err_probe(dev, -EINVAL, @@ -1625,6 +1640,21 @@ static int apple_mbox_probe(struct platform_device *pdev) mbox->regs = (u8 __iomem *)mbox->regs + mbox->hw->reg_offset; } + if (mbox->hw->rx_poll_required) { + mbox->rx_util_min = -1; + mbox->rx_util_min_applied = -1; + spin_lock_init(&mbox->rx_lock); + spin_lock_init(&mbox->tx_lock); + mutex_init(&mbox->lifecycle_lock); + init_completion(&mbox->tx_empty); + priv->rx_poll_only = true; + INIT_DELAYED_WORK(&priv->rx_poll_work, apple_mbox_v8_rx_poll_work); + mbox->irq_recv_not_empty = -ENXIO; + mbox->irq_send_empty = -ENXIO; + dev_info(dev, "J873 post-office: paired transfers, bounded polling, no IRQ claim\n"); + goto setup_pm; + } + if (mbox->hw->polled) { mbox->irq_recv_not_empty = -ENXIO; mbox->irq_send_empty = -ENXIO; @@ -1684,6 +1714,7 @@ static int apple_mbox_probe(struct platform_device *pdev) return ret; } +setup_pm: ret = devm_pm_runtime_enable(dev); if (ret) return ret; @@ -1979,8 +2010,31 @@ static const struct apple_mbox_hw apple_mbox_t8152_smc_hw = { .has_irq_controls = false, }; +/* + * T8152 ANS: msgbox-mailbox-num 3 in the non-alias post-office bank, the + * same counted FIFO as the SMC mailbox. Its interrupt ordering is not known, + * so no interrupt is described and both directions are polled. + */ +static const struct apple_mbox_hw apple_mbox_t8152_ans_hw = { + .rx_poll_required = true, + .j873_window = 0x316010300ULL, + .counted_fifo = true, + .control_full = GENMASK(11, 8), /* free TX slots */ + .control_empty = GENMASK(3, 0), /* RX occupancy */ + .a2i_control = 0x20, + .a2i_send0 = 0x10, + .a2i_send1 = 0x18, + .i2a_control = 0x20, + .i2a_recv0 = 0x00, + .i2a_recv1 = 0x08, + .has_irq_controls = false, +}; + static const struct of_device_id apple_mbox_of_match[] = { { .compatible = "apple,t8152-smc-mailbox", .data = &apple_mbox_t8152_smc_hw }, + /* The AOP's ASC wrapper mailbox has the SMC mailbox's counted FIFOs. */ + { .compatible = "apple,t8152-ascwrap-v8-mailbox", .data = &apple_mbox_t8152_smc_hw }, + { .compatible = "apple,t8152-ans-mailbox", .data = &apple_mbox_t8152_ans_hw }, { .compatible = "apple,t6031-agx-asc-mailbox", .data = &apple_mbox_asc_hw }, { .compatible = "apple,t8122-agx-asc-mailbox", .data = &apple_mbox_asc_hw }, { .compatible = "apple,t8152-gfx-ascwrap-v8", .data = &apple_mbox_t8152_gfx_ascwrap_v8_hw }, diff --git a/drivers/soc/apple/sart.c b/drivers/soc/apple/sart.c index 4fa31a0e54f47..a19468673fcdf 100644 --- a/drivers/soc/apple/sart.c +++ b/drivers/soc/apple/sart.c @@ -505,6 +505,10 @@ static const struct of_device_id apple_sart_of_match[] = { .compatible = "apple,t6050-sart", .data = &sart_ops_v4, }, + { + .compatible = "apple,t8152-sart", + .data = &sart_ops_v4, + }, { .compatible = "apple,t6000-sart", .data = &sart_ops_v3, diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7f68eba95e1f1..3566533dda5a2 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -2962,6 +2962,10 @@ static const struct of_device_id of_dwc3_match[] = { { .compatible = "synopsys,dwc3" }, + { + /* Handed over in host mode by the bootloader, see apple,dwc3.yaml */ + .compatible = "apple,t8152-dwc3" + }, { }, }; MODULE_DEVICE_TABLE(of, of_dwc3_match);