From c1f8fb9aec97e7d42ad5160a502921f6abaf1d4f Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 24 Aug 2022 20:51:30 -0700 Subject: [PATCH 1/6] intel_adsp: ace30: Bring up ACE 3.0 (PTL) This commit adds definition of ACE 3.0 Panther Lake board. Signed-off-by: Anas Nashif Signed-off-by: Flavio Ceolin --- boards/intel/adsp/Kconfig.intel_adsp | 1 + boards/intel/adsp/board.cmake | 8 + boards/intel/adsp/board.yml | 1 + boards/intel/adsp/intel_adsp_ace30_ptl.dts | 19 + boards/intel/adsp/intel_adsp_ace30_ptl.yaml | 10 + .../intel/adsp/intel_adsp_ace30_ptl_defconfig | 12 + dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi | 593 ++++++++++++++++++ soc/intel/intel_adsp/Kconfig | 2 + soc/intel/intel_adsp/ace/CMakeLists.txt | 4 + soc/intel/intel_adsp/ace/Kconfig | 1 + .../ace/Kconfig.defconfig.ace30_ptl | 22 + .../intel_adsp/ace/Kconfig.defconfig.series | 3 + soc/intel/intel_adsp/ace/Kconfig.soc | 7 + soc/intel/intel_adsp/ace/ace-link.ld | 144 ++++- .../ace/include/ace30_ptl/adsp_boot.h | 64 ++ .../ace/include/ace30_ptl/adsp_interrupt.h | 88 +++ .../ace/include/ace30_ptl/adsp_ipc_regs.h | 83 +++ .../ace/include/ace30_ptl/adsp_memory.h | 177 ++++++ .../include/ace30_ptl/adsp_memory_regions.h | 27 + .../ace/include/ace30_ptl/adsp_power.h | 110 ++++ .../ace/include/ace30_ptl/adsp_shim.h | 145 +++++ soc/intel/intel_adsp/ace/mmu_ptl.c | 143 +++++ soc/intel/intel_adsp/ace/multiprocessing.c | 49 +- soc/intel/intel_adsp/ace/power.c | 14 + .../intel_adsp/common/include/adsp-vectors.h | 2 +- .../intel_adsp/common/include/cpu_init.h | 7 + soc/intel/intel_adsp/soc.yml | 1 + 27 files changed, 1718 insertions(+), 19 deletions(-) create mode 100644 boards/intel/adsp/intel_adsp_ace30_ptl.dts create mode 100644 boards/intel/adsp/intel_adsp_ace30_ptl.yaml create mode 100644 boards/intel/adsp/intel_adsp_ace30_ptl_defconfig create mode 100644 dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi create mode 100644 soc/intel/intel_adsp/ace/Kconfig.defconfig.ace30_ptl create mode 100644 soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_boot.h create mode 100644 soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_interrupt.h create mode 100644 soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_ipc_regs.h create mode 100644 soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory.h create mode 100644 soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory_regions.h create mode 100644 soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_power.h create mode 100644 soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_shim.h create mode 100644 soc/intel/intel_adsp/ace/mmu_ptl.c diff --git a/boards/intel/adsp/Kconfig.intel_adsp b/boards/intel/adsp/Kconfig.intel_adsp index 2e4c98447203b2..f5a81c6dfcc633 100644 --- a/boards/intel/adsp/Kconfig.intel_adsp +++ b/boards/intel/adsp/Kconfig.intel_adsp @@ -6,3 +6,4 @@ config BOARD_INTEL_ADSP select SOC_INTEL_CAVS_V25 if BOARD_INTEL_ADSP_CAVS25_TGPH select SOC_INTEL_ACE15_MTPM if BOARD_INTEL_ADSP_ACE15_MTPM select SOC_INTEL_ACE20_LNL if BOARD_INTEL_ADSP_ACE20_LNL + select SOC_INTEL_ACE30_PTL if BOARD_INTEL_ADSP_ACE30_PTL diff --git a/boards/intel/adsp/board.cmake b/boards/intel/adsp/board.cmake index bcdfc3286467c8..584474544bf2d7 100644 --- a/boards/intel/adsp/board.cmake +++ b/boards/intel/adsp/board.cmake @@ -39,4 +39,12 @@ elseif(CONFIG_BOARD_INTEL_ADSP_ACE20_LNL) set(RIMAGE_SIGN_KEY "otc_private_key_3k.pem" CACHE STRING "default in ace20_lnl/board.cmake") +elseif(CONFIG_BOARD_INTEL_ADSP_ACE30_PTL) + + board_set_rimage_target(ptl) + + set(RIMAGE_SIGN_KEY "otc_private_key.pem" CACHE STRING "default rimage key") + + board_finalize_runner_args(intel_adsp) + endif() diff --git a/boards/intel/adsp/board.yml b/boards/intel/adsp/board.yml index 9295ae0c3eb2fd..8e35014dd66f96 100644 --- a/boards/intel/adsp/board.yml +++ b/boards/intel/adsp/board.yml @@ -7,3 +7,4 @@ boards: - name: 'tgph' - name: ace15_mtpm - name: ace20_lnl + - name: ace30_ptl diff --git a/boards/intel/adsp/intel_adsp_ace30_ptl.dts b/boards/intel/adsp/intel_adsp_ace30_ptl.dts new file mode 100644 index 00000000000000..9e25712bc2c3e2 --- /dev/null +++ b/boards/intel/adsp/intel_adsp_ace30_ptl.dts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + model = "intel_adsp_ace30_ptl"; + compatible = "intel"; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &mem_window3; + }; +}; diff --git a/boards/intel/adsp/intel_adsp_ace30_ptl.yaml b/boards/intel/adsp/intel_adsp_ace30_ptl.yaml new file mode 100644 index 00000000000000..4e9c71a9d2f566 --- /dev/null +++ b/boards/intel/adsp/intel_adsp_ace30_ptl.yaml @@ -0,0 +1,10 @@ +identifier: intel_adsp/ace30_ptl +name: ACE 3.0 Panther Lake Audio DSP +type: mcu +arch: xtensa +toolchain: + - xcc-clang +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/intel/adsp/intel_adsp_ace30_ptl_defconfig b/boards/intel/adsp/intel_adsp_ace30_ptl_defconfig new file mode 100644 index 00000000000000..913d2a8c3e3a90 --- /dev/null +++ b/boards/intel/adsp/intel_adsp_ace30_ptl_defconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=4096 + +CONFIG_GEN_ISR_TABLES=y +CONFIG_GEN_IRQ_VECTOR_TABLE=n + +CONFIG_BUILD_OUTPUT_BIN=n + +CONFIG_DAI_SSP_HAS_POWER_CONTROL=y + +CONFIG_DCACHE_LINE_SIZE=64 diff --git a/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi b/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi new file mode 100644 index 00000000000000..e823fb0fe4be25 --- /dev/null +++ b/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <0>; + cpu-power-states = <&d0i3 &d3>; + i-cache-line-size = <64>; + d-cache-line-size = <64>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <1>; + cpu-power-states = <&d0i3 &d3>; + }; + + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <2>; + cpu-power-states = <&d0i3 &d3>; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <3>; + cpu-power-states = <&d0i3 &d3>; + }; + + cpu4: cpu@4 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <4>; + cpu-power-states = <&d0i3 &d3>; + }; + }; + + power-states { + d0i3: idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + min-residency-us = <200>; + exit-latency-us = <100>; + }; + /* PM_STATE_SOFT_OFF can be entered only by calling pm_state_force. + * The procedure is triggered by IPC from the HOST (SET_DX). + */ + d3: off { + compatible = "zephyr,power-state"; + power-state-name = "soft-off"; + min-residency-us = <0>; + exit-latency-us = <0>; + status = "disabled"; + }; + }; + + sram0: memory@a0020000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0xa0020000 DT_SIZE_K(4608)>; + }; + + sram0virtual: virtualmemory@a0020000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0xa0020000 DT_SIZE_K(8192)>; + }; + + sram1: memory@a0000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0xa0000000 DT_SIZE_K(64)>; + }; + + sysclk: system-clock { + compatible = "fixed-clock"; + clock-frequency = <38400000>; + #clock-cells = <0>; + }; + + clkctl: clkctl { + compatible = "intel,adsp-shim-clkctl"; + adsp-clkctl-clk-wovcro = <0>; + adsp-clkctl-clk-ipll = <1>; + adsp-clkctl-freq-enc = <0xc 0x4>; + adsp-clkctl-freq-mask = <0x0 0x0>; + adsp-clkctl-freq-default = <1>; + adsp-clkctl-freq-lowest = <0>; + wovcro-supported; + }; + + audioclk: audio-clock { + compatible = "fixed-clock"; + clock-frequency = <24576000>; + #clock-cells = <0>; + }; + + pllclk: pll-clock { + compatible = "fixed-clock"; + clock-frequency = <96000000>; + #clock-cells = <0>; + }; + + IMR1: memory@A1000000 { + compatible = "intel,adsp-imr"; + reg = <0xA1000000 DT_SIZE_M(16)>; + block-size = <0x1000>; + zephyr,memory-region = "IMR1"; + }; + + soc { + lsbpm: lsbpm@71d80 { + compatible = "intel,adsp-lsbpm"; + reg = <0x71d80 0x0008>; + }; + + hsbpm: hsbpm@17a800 { + compatible = "intel,adsp-hsbpm"; + reg = <0x17a800 0x0008>; + }; + + core_intc: core_intc@0 { + compatible = "cdns,xtensa-core-intc"; + reg = <0x00 0x400>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + hdamlddmic: hdamlddmic@cc0 { + compatible = "intel,adsp-hda-dmic-cap"; + reg = <0xcc0 0x40>; + status = "okay"; + }; + + dmic0: dai-dmic0@10100 { + compatible = "intel,dai-dmic"; + reg = <0x10100 0x8000>; + shim = <0x10000>; + fifo = <0x0008>; + interrupts = <0x08 0 0>; + interrupt-parent = <&ace_intc>; + power-domain = <&hub_ulp_domain>; + }; + + dmic1: dai-dmic1@10100 { + compatible = "intel,dai-dmic"; + reg = <0x10100 0x8000>; + shim = <0x10000>; + fifo = <0x0108>; + interrupts = <0x08 0 0>; + interrupt-parent = <&ace_intc>; + power-domain = <&hub_ulp_domain>; + }; + + dmicvss: dmicvss@16000 { + compatible = "intel,adsp-dmic-vss"; + reg = <0x16000 0x2000>; + status = "okay"; + }; + + /* + * FIXME this is modeling individual alh channels/instances + * with node labels, which has problems. A better representation + * is discussed here: + * + * https://github.com/zephyrproject-rtos/zephyr/pull/50287#discussion_r974591009 + */ + alh0: alh0@24400 { + compatible = "intel,alh-dai"; + reg = <0x00024400 0x00024600>; + status = "okay"; + }; + + alh1: alh1@24400 { + compatible = "intel,alh-dai"; + reg = <0x00024400 0x00024600>; + status = "okay"; + }; + + sspbase: ssp_base@28000 { + compatible = "intel,ssp-sspbase"; + reg = <0x28000 0x1000>; + }; + + hdamlssp: hdamlssp@d00 { + compatible = "intel,adsp-hda-ssp-cap"; + reg = <0xD00 0x40>; + status = "okay"; + }; + + ssp0: ssp@28100 { + compatible = "intel,ssp-dai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x00028100 0x1000 + 0x00079C00 0x200>; + interrupts = <0x00 0 0>; + interrupt-parent = <&ace_intc>; + dmas = <&hda_link_out 1 + &hda_link_in 1>; + dma-names = "tx", "rx"; + power-domain = <&io0_domain>; + status = "okay"; + }; + + ssp1: ssp@29100 { + compatible = "intel,ssp-dai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x00029100 0x1000 + 0x00079C00 0x200>; + interrupts = <0x01 0 0>; + interrupt-parent = <&ace_intc>; + dmas = <&hda_link_out 2 + &hda_link_in 2>; + dma-names = "tx", "rx"; + power-domain = <&io0_domain>; + status = "okay"; + }; + + ssp2: ssp@2a100 { + compatible = "intel,ssp-dai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0002a100 0x1000 + 0x00079C00 0x200>; + interrupts = <0x02 0 0>; + interrupt-parent = <&ace_intc>; + dmas = <&hda_link_out 3 + &hda_link_in 3>; + dma-names = "tx", "rx"; + power-domain = <&io0_domain>; + status = "okay"; + }; + + ssp3: ssp@2b100 { + compatible = "intel,ssp-dai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0002b100 0x1000 + 0x00079C00 0x200>; + interrupts = <0x03 0 0>; + interrupt-parent = <&ace_intc>; + dmas = <&hda_link_out 4 + &hda_link_in 4>; + dma-names = "tx", "rx"; + power-domain = <&io0_domain>; + status = "okay"; + }; + + ssp4: ssp@2c100 { + compatible = "intel,ssp-dai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0002c100 0x1000 + 0x00079C00 0x200>; + interrupts = <0x04 0 0>; + interrupt-parent = <&ace_intc>; + dmas = <&hda_link_out 5 + &hda_link_in 5>; + dma-names = "tx", "rx"; + power-domain = <&io0_domain>; + status = "okay"; + }; + + ssp5: ssp@2d100 { + compatible = "intel,ssp-dai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0002d100 0x1000 + 0x00079C00 0x200>; + interrupts = <0x04 0 0>; + interrupt-parent = <&ace_intc>; + dmas = <&hda_link_out 6 + &hda_link_in 6>; + dma-names = "tx", "rx"; + power-domain = <&io0_domain>; + status = "okay"; + }; + + mem_window0: mem_window@70200 { + compatible = "intel,adsp-mem-window"; + reg = <0x70200 0x8>; + offset = <0x4000>; + memory = <&sram0>; + initialize; + read-only; + }; + + mem_window1: mem_window@70208 { + compatible = "intel,adsp-mem-window"; + reg = <0x70208 0x8>; + memory = <&sram0>; + }; + + mem_window2: mem_window@70210 { + compatible = "intel,adsp-mem-window"; + reg = <0x70210 0x8>; + memory = <&sram0>; + }; + + mem_window3: mem_window@70218 { + compatible = "intel,adsp-mem-window"; + reg = <0x70218 0x8>; + memory = <&sram0>; + read-only; + }; + + adsp_idc: ace_idc@92000 { + compatible = "intel,adsp-idc"; + reg = <0x92000 0x0400>; + interrupts = <24 0 0>; + interrupt-parent = <&ace_intc>; + }; + + dfpmcch: dfpmcch@71ac0 { + compatible = "intel,adsp-dfpmcch"; + reg = <0x00071ac0 0x40>; + }; + + dfpmccu: dfpmccu@71b00 { + compatible = "intel,adsp-dfpmccu"; + reg = <0x71b00 0x100>; + + hub_ulp_domain: hub_ulp_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <15>; + }; + hub_hp_domain: hub_hpp_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <6>; + }; + io0_domain: io0_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <8>; + }; + io1_domain: io1_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <9>; + }; + io2_domain: io2_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <10>; + }; + io3_domain: io3_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <11>; + }; + hst_domain: hst_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <5>; + }; + ml0_domain: ml0_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <12>; + }; + ml1_domain: ml1_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <13>; + }; + }; + + shim: shim@71f00 { + compatible = "intel,cavs-shim"; + reg = <0x71f00 0x100>; + }; + + tts: tts@72000 { + compatible = "intel,adsp-tts"; + reg = <0x72000 0x70>; + status = "okay"; + }; + + ace_rtc_counter: ace_rtc_counter@72008 { + compatible = "intel,ace-rtc-counter"; + reg = <0x72008 0x0064>; + }; + + ace_timestamp: ace_timestamp@72040 { + compatible = "intel,ace-timestamp"; + reg = <0x72040 0x0032>; + }; + + ace_art_counter: ace_art_counter@72058 { + compatible = "intel,ace-art-counter"; + reg = <0x72058 0x0064>; + }; + + hda_host_out: dma@72800 { + compatible = "intel,adsp-hda-host-out"; + #dma-cells = <1>; + reg = <0x00072800 0x40>; + dma-channels = <9>; + dma-buf-addr-alignment = <128>; + dma-buf-size-alignment = <32>; + dma-copy-alignment = <32>; + power-domain = <&hst_domain>; + interrupts = <13 0 0>; + interrupt-parent = <&ace_intc>; + status = "okay"; + }; + + hda_host_in: dma@72c00 { + compatible = "intel,adsp-hda-host-in"; + #dma-cells = <1>; + reg = <0x00072c00 0x40>; + dma-channels = <11>; + dma-buf-addr-alignment = <128>; + dma-buf-size-alignment = <32>; + dma-copy-alignment = <32>; + power-domain = <&hst_domain>; + interrupts = <12 0 0>; + interrupt-parent = <&ace_intc>; + status = "okay"; + }; + + adsp_host_ipc: ace_host_ipc@73000 { + compatible = "intel,adsp-host-ipc"; + status = "okay"; + reg = <0x73000 0x30>; + interrupts = <0 0 0>; + interrupt-parent = <&ace_intc>; + }; + + hda_link_out: dma@79400 { + compatible = "intel,adsp-hda-link-out"; + #dma-cells = <1>; + reg = <0x00079400 0x40>; + dma-channels = <9>; + dma-buf-addr-alignment = <128>; + dma-buf-size-alignment = <32>; + dma-copy-alignment = <32>; + power-domain = <&io0_domain>; + status = "okay"; + }; + + hda_link_in: dma@79800 { + compatible = "intel,adsp-hda-link-in"; + #dma-cells = <1>; + reg = <0x00079800 0x40>; + dma-channels = <11>; + dma-buf-addr-alignment = <128>; + dma-buf-size-alignment = <32>; + dma-copy-alignment = <32>; + power-domain = <&io0_domain>; + status = "okay"; + }; + + /* This is actually an array of per-core designware + * controllers, but the special setup and extra + * masking layer makes it easier for MTL to handle + * this internally. + */ + ace_intc: ace_intc@94000 { + compatible = "intel,ace-intc"; + reg = <0x94000 0xc00>; + interrupt-controller; + #interrupt-cells = <3>; + interrupts = <4 0 0>; + num-irqs = <28>; + interrupt-parent = <&core_intc>; + }; + + tlb: tlb@17e000 { + compatible = "intel,adsp-mtl-tlb"; + reg = <0x17e000 0x1000>; + paddr-size = <12>; + exec-bit-idx = <14>; + write-bit-idx= <15>; + }; + + timer: timer { + compatible = "intel,adsp-timer"; + syscon = <&tts>; + }; + }; + + hdas { + #address-cells = <1>; + #size-cells = <0>; + + hda0: hda@0 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0>; + }; + hda1: hda@1 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <1>; + }; + hda2: hda@2 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <2>; + }; + hda3: hda@3 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <3>; + }; + hda4: hda@4 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <4>; + }; + hda5: hda@5 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <5>; + }; + hda6: hda@6 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <6>; + }; + hda7: hda@7 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <7>; + }; + hda8: hda@8 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <8>; + }; + hda9: hda@9 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <9>; + }; + hda10: hda@a { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0a>; + }; + hda11: hda@b { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0b>; + }; + hda12: hda@c { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0c>; + }; + hda13: hda@d { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0d>; + }; + hda14: hda@e { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0e>; + }; + hda15: hda@f { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0f>; + }; + hda16: hda@10 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x10>; + }; + hda17: hda@11 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x11>; + }; + hda18: hda@12 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x12>; + }; + }; +}; diff --git a/soc/intel/intel_adsp/Kconfig b/soc/intel/intel_adsp/Kconfig index 135fecb575aa3e..1a0cc4350d4f3d 100644 --- a/soc/intel/intel_adsp/Kconfig +++ b/soc/intel/intel_adsp/Kconfig @@ -8,6 +8,8 @@ config SOC_FAMILY_INTEL_ADSP select ARCH_SUPPORTS_COREDUMP select CPU_HAS_DCACHE select ARCH_HAS_USERSPACE if XTENSA_MMU + imply XTENSA_MMU_DOUBLE_MAP + select ARCH_HAS_USERSPACE if XTENSA_MMU select CPU_CACHE_INCOHERENT if SOC_FAMILY_INTEL_ADSP diff --git a/soc/intel/intel_adsp/ace/CMakeLists.txt b/soc/intel/intel_adsp/ace/CMakeLists.txt index 919e7993427dbb..0c9c43eb3393c9 100644 --- a/soc/intel/intel_adsp/ace/CMakeLists.txt +++ b/soc/intel/intel_adsp/ace/CMakeLists.txt @@ -19,4 +19,8 @@ zephyr_include_directories(include/${CONFIG_SOC}) zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_COMM_WIDGET comm_widget.c) zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_COMM_WIDGET comm_widget_messages.c) +if (CONFIG_XTENSA_MMU) + zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_ACE30_PTL mmu_ptl.c) +endif() + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/intel/intel_adsp/ace/Kconfig b/soc/intel/intel_adsp/ace/Kconfig index ff86472466ead2..96778d274a45ae 100644 --- a/soc/intel/intel_adsp/ace/Kconfig +++ b/soc/intel/intel_adsp/ace/Kconfig @@ -14,6 +14,7 @@ config SOC_SERIES_INTEL_ADSP_ACE select HAS_PM select XTENSA_CPU_HAS_HIFI3 select XTENSA_CPU_HAS_HIFI4 + select ARCH_HAS_RESERVED_PAGE_FRAMES if MMU config SOC_INTEL_COMM_WIDGET bool "Intel Communication Widget driver" diff --git a/soc/intel/intel_adsp/ace/Kconfig.defconfig.ace30_ptl b/soc/intel/intel_adsp/ace/Kconfig.defconfig.ace30_ptl new file mode 100644 index 00000000000000..f7e0f19008f221 --- /dev/null +++ b/soc/intel/intel_adsp/ace/Kconfig.defconfig.ace30_ptl @@ -0,0 +1,22 @@ +# Copyright (c) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + + +if SOC_INTEL_ACE30_PTL + +config MP_MAX_NUM_CPUS + default 5 + +config CPU_HAS_MMU + def_bool y + +config XTENSA_MMU + def_bool y + +config XTENSA_MMU_NUM_L2_TABLES + # Need to have enough to accommodate samples and tests. + # Also need to have some room for future expansions or + # else we will be chasing changes all the time. + default 64 + +endif diff --git a/soc/intel/intel_adsp/ace/Kconfig.defconfig.series b/soc/intel/intel_adsp/ace/Kconfig.defconfig.series index a860d74422693b..e96c890ff6c166 100644 --- a/soc/intel/intel_adsp/ace/Kconfig.defconfig.series +++ b/soc/intel/intel_adsp/ace/Kconfig.defconfig.series @@ -50,6 +50,9 @@ config SYS_CLOCK_TICKS_PER_SEC config XTENSA_CCOUNT_HZ default 393216000 +config INTEL_ADSP_TIMER + default y + config DYNAMIC_INTERRUPTS default y diff --git a/soc/intel/intel_adsp/ace/Kconfig.soc b/soc/intel/intel_adsp/ace/Kconfig.soc index 3cab72f8f51d8b..4f981801977904 100644 --- a/soc/intel/intel_adsp/ace/Kconfig.soc +++ b/soc/intel/intel_adsp/ace/Kconfig.soc @@ -20,6 +20,12 @@ config SOC_INTEL_ACE20_LNL help ACE 2.0 Lunar Lake PCH +config SOC_INTEL_ACE30_PTL + bool + select SOC_SERIES_INTEL_ADSP_ACE + help + ACE 3.0 Panther Lake PCH + config SOC_SERIES default "intel_adsp_ace" if SOC_SERIES_INTEL_ADSP_ACE @@ -29,3 +35,4 @@ config SOC_TOOLCHAIN_NAME config SOC default "ace15_mtpm" if SOC_INTEL_ACE15_MTPM default "ace20_lnl" if SOC_INTEL_ACE20_LNL + default "ace30_ptl" if SOC_INTEL_ACE30_PTL diff --git a/soc/intel/intel_adsp/ace/ace-link.ld b/soc/intel/intel_adsp/ace/ace-link.ld index 454893055e1712..8aaf7c75c1b26b 100644 --- a/soc/intel/intel_adsp/ace/ace-link.ld +++ b/soc/intel/intel_adsp/ace/ace-link.ld @@ -37,11 +37,21 @@ ENTRY(rom_entry); */ #ifdef CONFIG_KERNEL_COHERENCE #define RPO_SET(addr, reg) ((addr & 0x1fffffff) | (reg << 29)) +#ifdef CONFIG_MMU +#define SEGSTART_CACHED RPO_SET(ALIGN(CONFIG_MMU_PAGE_SIZE), CONFIG_XTENSA_CACHED_REGION) +#define SEGSTART_UNCACHED RPO_SET(ALIGN(CONFIG_MMU_PAGE_SIZE), CONFIG_XTENSA_UNCACHED_REGION) +#else #define SEGSTART_CACHED RPO_SET(ALIGN(64), CONFIG_XTENSA_CACHED_REGION) #define SEGSTART_UNCACHED RPO_SET(ALIGN(64), CONFIG_XTENSA_UNCACHED_REGION) +#endif +#else +#ifdef CONFIG_MMU +#define SEGSTART_CACHED ALIGN(CONFIG_MMU_PAGE_SIZE) +#define SEGSTART_UNCACHED ALIGN(CONFIG_MMU_PAGE_SIZE) #else #define SEGSTART_CACHED . #define SEGSTART_UNCACHED . +#endif #define ucram ram #endif @@ -56,6 +66,18 @@ ENTRY(rom_entry); #define NOLOAD_BASE 0x20000 #define NOLOAD_SIZE 0x100000 +#ifdef CONFIG_MMU +#define MMU_PAGE_ALIGN . = ALIGN(CONFIG_MMU_PAGE_SIZE); +#define HDR_MMU_PAGE_ALIGN ALIGN(CONFIG_MMU_PAGE_SIZE) +#define HDR_4K_OR_MMU_PAGE_ALIGN ALIGN(CONFIG_MMU_PAGE_SIZE) +#else +#define MMU_PAGE_ALIGN +#define HDR_MMU_PAGE_ALIGN +#define HDR_4K_OR_MMU_PAGE_ALIGN ALIGN(4096) +#endif + +#define SMEM_PARTITION_ALIGN(size) MMU_PAGE_ALIGN + MEMORY { vector_base_text : org = VECBASE_RESET_PADDR_SRAM, @@ -102,6 +124,11 @@ MEMORY { vector_double_text : org = DOUBLEEXC_VECTOR_PADDR_SRAM, len = MEM_VECT_TEXT_SIZE +#ifdef CONFIG_XTENSA_MMU + xtensa_vector_code : + org = DOUBLEEXC_VECTOR_PADDR_SRAM + MEM_VECT_TEXT_SIZE, + len = RAM_BASE - (DOUBLEEXC_VECTOR_PADDR_SRAM + MEM_VECT_TEXT_SIZE) +#endif imr : org = IMR_BOOT_LDR_TEXT_ENTRY_BASE, len = 0x100000 @@ -233,22 +260,77 @@ SECTIONS { _DoubleExceptionVector_text_end = .; } >vector_double_text - .text : { +#ifdef CONFIG_XTENSA_MMU + .xtensa_vector_code : { + /* There is not much space between .DoubleExceptionVector + * and the beginning of .text. So need to be careful on + * what to put in this section. It would mostly be things + * that are required to handle exceptions and interrupts. + * Also things we want to avoid TLB misses during exception + * handling. + */ + + *libarch__xtensa__core.a:xtensa_asm2_util.S.obj(.literal) + *libarch__xtensa__core.a:xtensa_asm2_util.S.obj(.iram.text) + *libarch__xtensa__core.a:xtensa_asm2_util.S.obj(.text) + + *libarch__xtensa__core.a:window_vectors.S.obj(.iram.text) + + /* For _Level1Vector */ + *libarch__xtensa__core.a:vector_handlers_util.S.obj(.iram0.text) + + *libarch__xtensa__core.a:vector_handlers.c.obj(.literal.xtensa_int?_c) + *libarch__xtensa__core.a:vector_handlers.c.obj(.text.xtensa_int?_c) + + *libarch__xtensa__core.a:userspace.S.obj(.literal.xtensa_do_syscall) + *libarch__xtensa__core.a:userspace.S.obj(.text.xtensa_do_syscall) + + } > xtensa_vector_code +#endif /* CONFIG_XTENSA_MMU */ + + .text : HDR_MMU_PAGE_ALIGN + { __text_region_start = .; + _image_ram_start = .; + z_mapped_start = .; *(.iram1 .iram1.*) *(.entry.text) *(.init.literal) *(.iram0.text) + +#ifdef CONFIG_XTENSA_MMU + /* + * The C handle blows up in size significantly when logging is enabled. + * So we can't keep this in .xtensa_vector_code above. Though we try to + * leep these close enough that, hopefully, we can avoid TLB misses. + */ + *libarch__xtensa__core.a:vector_handlers.c.obj(.literal.xtensa_excint1_c) + *libarch__xtensa__core.a:vector_handlers.c.obj(.text.xtensa_excint1_c) + + /* + * Experiment shows that system would not boot if this is away from + * VECBASE more than a few pages. So workaround the issue by putting + * xtensa_mmu_init() here. + */ + *libarch__xtensa__core.a:ptables.c.obj(.literal.xtensa_mmu_init) + *libarch__xtensa__core.a:ptables.c.obj(.text.xtensa_mmu_init) +#endif + KEEP(*(.init)) KEEP(*(.lps_vector)) - *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + MMU_PAGE_ALIGN + *(.literal .text) + *(.literal.* .text.*) *(.fini.literal) KEEP(*(.fini)) *(.gnu.version) +#include + MMU_PAGE_ALIGN __text_region_end = .; } >ram - .rodata : ALIGN(4096) + .rodata : HDR_4K_OR_MMU_PAGE_ALIGN { __rodata_region_start = .; *(.rodata) @@ -258,6 +340,7 @@ SECTIONS { . = ALIGN(4); #include + #include __XT_EXCEPTION_TABLE__ = .; KEEP (*(.xt_except_table)) @@ -277,14 +360,14 @@ SECTIONS { *(.xt_except_desc_end) *(.dynamic) *(.gnu.version_d) - _image_ram_start = .; _bss_table_start = .; LONG(_bss_start) LONG(_bss_end) _bss_table_end = .; + MMU_PAGE_ALIGN } >ram - .module_init : { + .module_init : HDR_MMU_PAGE_ALIGN { _module_init_start = .; *(*.initcall) _module_init_end = .; @@ -292,21 +375,22 @@ SECTIONS { #define RAMABLE_REGION ram #define ROMABLE_REGION ram -#include - __rodata_region_end = .; - .fw_ready : { - KEEP(*(".fw_ready")); - KEEP (*(.fw_ready_metadata)) - } >ram + __common_rom_region_start = SEGSTART_CACHED; +#include + __common_rom_region_end = .; + __rodata_region_end = .; - .noinit SEGSTART_UNCACHED : { + .noinit SEGSTART_UNCACHED : HDR_MMU_PAGE_ALIGN { + __data_start = .; *(.noinit) *(.noinit.*) } >ucram - .data SEGSTART_UNCACHED : { - __data_start = .; +#include + . = SEGSTART_UNCACHED; + + .data SEGSTART_UNCACHED : HDR_MMU_PAGE_ALIGN { *(.data) *(.data.*) *(.gnu.linkonce.d.*) @@ -324,6 +408,7 @@ SECTIONS { _trace_ctx_end = ABSOLUTE(.); *(.gna_model) __data_end = .; + MMU_PAGE_ALIGN } >ucram .lit4 SEGSTART_CACHED : { @@ -344,7 +429,28 @@ SECTIONS { #define RAMABLE_REGION ucram #define ROMABLE_REGION ucram + .fw_ready SEGSTART_UNCACHED : { + KEEP(*(".fw_ready")); + KEEP (*(.fw_ready_metadata)) + } > ucram + + __common_ram_region_start = .; + +#ifdef CONFIG_USERSPACE + +#define APP_SHARED_ALIGN MMU_PAGE_ALIGN +#define EMPTY_APP_SHARED_ALIGN APP_SHARED_ALIGN + + /* APP SHARED MEMORY REGION */ +#include + _app_smem_size = _app_smem_end - _app_smem_start; + _app_smem_num_words = _app_smem_size >> 2; + _app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME); +#endif /* CONFIG_USERSPACE */ + #include +#include + __common_ram_region_end = .; .tm_clone_table : { *(.tm_clone_table) @@ -356,6 +462,11 @@ SECTIONS { .cached SEGSTART_CACHED : { _cached_start = .; *(.cached .cached.*) +#ifdef CONFIG_USERSPACE + z_user_stacks_start = .; + *(.user_stacks*) + z_user_stacks_end = .; +#endif _cached_end = .; } >ram @@ -384,6 +495,7 @@ SECTIONS { *(.gnu.linkonce.b.*) *(COMMON) . = ALIGN(8); + MMU_PAGE_ALIGN _bss_end = .; } >ucram @@ -410,17 +522,19 @@ SECTIONS { . = SEGSTART_UNCACHED; _end = ALIGN(8); . = SEGSTART_CACHED; + z_mapped_end = .; . = L2_SRAM_BASE + L2_SRAM_SIZE; . = SEGSTART_UNCACHED; _heap_end = .; _heap_sentry = .; + . = SEGSTART_CACHED; + _image_ram_end = .; /* dma buffers */ .lpbuf (NOLOAD): { _dma_buf_start = .; *(.dma_buffers) _dma_buf_end = .; - _image_ram_end = .; } >lpram /* Non-loadable sections below. Back to cached memory so diff --git a/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_boot.h b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_boot.h new file mode 100644 index 00000000000000..6cc07538da0c7f --- /dev/null +++ b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_boot.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_INTEL_ADSP_BOOT_H_ +#define ZEPHYR_SOC_INTEL_ADSP_BOOT_H_ + +#define DSPCS_REG 0x178d00 + +struct dspcs { + /* + * DSPCSx + * DSP Core Shim + * + * These registers are added by Intel outside of the Tensilica Core for general operation + * control, such as reset, stall, power gating, clock gating etc. + * Note: These registers are accessible through the host space or DSP space depending on + * ownership, as governed by SAI and RS. + */ + struct { + uint32_t cap; + uint32_t ctl; + } capctl[5]; + uint32_t unused0[6]; + + /* + * DSPBRx + * DSP Boot / Recovery + * + * These registers are added by Intel outside of the Tensilica Core for boot / recovery + * control, such as boot path, watch dog timer etc. + */ + struct { + uint32_t brcap; + uint32_t wdtcs; + uint32_t wdtipptr; + uint32_t unused1; + uint32_t bctl; + uint32_t baddr; + uint32_t battr; + uint32_t unused2; + } bootctl[5]; +}; + +#define DSPCS_CTL_SPA BIT(0) +#define DSPCS_CTL_CPA BIT(8) + +#define DSPBR_BCTL_BYPROM BIT(0) +#define DSPBR_BCTL_WAITIPCG BIT(16) +#define DSPBR_BCTL_WAITIPPG BIT(17) + +#define DSPBR_BATTR_LPSCTL_RESTORE_BOOT BIT(12) +#define DSPBR_BATTR_LPSCTL_HP_CLOCK_BOOT BIT(13) +#define DSPBR_BATTR_LPSCTL_LP_CLOCK_BOOT BIT(14) +#define DSPBR_BATTR_LPSCTL_L1_MIN_WAY BIT(15) +#define DSPBR_BATTR_LPSCTL_BATTR_SLAVE_CORE BIT(16) + +#define DSPBR_WDT_RESUME BIT(8) +#define DSPBR_WDT_RESTART_COMMAND 0x76 + +#define DSPCS (*(volatile struct dspcs *)DSPCS_REG) + +#endif /* ZEPHYR_SOC_INTEL_ADSP_BOOT_H_ */ diff --git a/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_interrupt.h b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_interrupt.h new file mode 100644 index 00000000000000..bf912746d66b7f --- /dev/null +++ b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_interrupt.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2024 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_INTEL_ADSP_INTERRUPT_H_ +#define ZEPHYR_SOC_INTEL_ADSP_INTERRUPT_H_ + +/* Low priority interrupt indices */ +#define ACE_INTL_HIPC 0 +#define ACE_INTL_SBIPC 1 +#define ACE_INTL_ML 2 +#define ACE_INTL_IDCA 3 +#define ACE_INTL_LPVML 4 +#define ACE_INTL_SHA 5 +#define ACE_INTL_L1L2M 6 +#define ACE_INTL_I2S 7 +#define ACE_INTL_DMIC 8 +#define ACE_INTL_SNDW 9 +#define ACE_INTL_TTS 10 +#define ACE_INTL_WDT 11 +#define ACE_INTL_HDAHIDMA 12 +#define ACE_INTL_HDAHODMA 13 +#define ACE_INTL_HDALIDMA 14 +#define ACE_INTL_HDALODMA 15 +#define ACE_INTL_I3C 16 +#define ACE_INTL_GPDMA 17 +#define ACE_INTL_PWM 18 +#define ACE_INTL_I2C 19 +#define ACE_INTL_SPI 20 +#define ACE_INTL_UART 21 +#define ACE_INTL_GPIO 22 +#define ACE_INTL_UAOL 23 +#define ACE_INTL_IDCB 24 +#define ACE_INTL_DCW 25 +#define ACE_INTL_DTF 26 +#define ACE_INTL_FLV 27 +#define ACE_INTL_DPDMA 28 + +/* Device interrupt control for the low priority interrupts. It + * provides per-core masking and status checking: ACE_DINT is an array + * of these structs, one per core. The state is in the bottom bits, + * indexed by ACE_INTL_*. Note that some of these use more than one + * bit to discriminate sources (e.g. TTS's bits 0-2 are + * timestamp/comparator0/comparator1). It seems safe to write all 1's + * to the short to "just enable everything", but drivers should + * probably implement proper logic. + * + * Note that this block is independent of the Designware controller + * that manages the shared IRQ. Interrupts need to unmasked in both + * in order to be delivered to software. Per simulator source code, + * this is "upstream" of DW: an interrupt will not be latched into the + * status registers of the DW controller unless the IE bits here are + * set. That seems unlikely to correctly capture the hardware + * behavior (it would mean that the DW controller was being + * independently triggered multiple times by each core!). Beware. + * + * Enable an interrupt for a core with e.g.: + * + * ACE_DINT[core_id].ie[ACE_INTL_TTS] = 0xffff; + */ +struct ace_dint { + uint16_t ie[32]; /* enable */ + uint16_t is[32]; /* status (potentially masked by ie) */ + uint16_t irs[32]; /* "raw" status (hardware input state) */ + uint32_t unused[16]; +}; + +/* This register enables (1) or disable (0) the interrupt of + * each host inter-processor communication capability instance in a single register. + */ +#define DXHIPCIE_REG 0x91040 + +#define ACE_DINT ((volatile struct ace_dint *)DXHIPCIE_REG) +#define XTENSA_IRQ_NUM_MASK 0xff +#define XTENSA_IRQ_NUM_SHIFT 0 + +#define XTENSA_IRQ_NUMBER(_irq) ((_irq >> XTENSA_IRQ_NUM_SHIFT) & XTENSA_IRQ_NUM_MASK) +/* Convert between IRQ_CONNECT() numbers and ACE_INTL_* interrupts */ +#define ACE_IRQ_NUM_SHIFT 8 +#define ACE_IRQ_NUM_MASK 0xFFU +#define ACE_IRQ_FROM_ZEPHYR(_irq) (((_irq >> ACE_IRQ_NUM_SHIFT) & ACE_IRQ_NUM_MASK) - 1) + +#define ACE_INTC_IRQ DT_IRQN(DT_NODELABEL(ace_intc)) +#define ACE_IRQ_TO_ZEPHYR(_irq) \ + ((((_irq + 1) & ACE_IRQ_NUM_MASK) << ACE_IRQ_NUM_SHIFT) + ACE_INTC_IRQ) + +#endif diff --git a/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_ipc_regs.h b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_ipc_regs.h new file mode 100644 index 00000000000000..c91e511c96c0ce --- /dev/null +++ b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_ipc_regs.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2024 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_SOC_INTEL_ADSP_ACE_IPC_REGS_H +#define ZEPHYR_SOC_INTEL_ADSP_ACE_IPC_REGS_H + +#include +#include + +/** + * @file + * + * Inter Processor Communication - used for sending interrupts to and receiving + * them from another device. ACE uses it to talk to the host and the CSME. + * In general there is one of these blocks instantiated for each endpoint of a + * connection. + */ + +/** + * @brief IPC registers layout for Intel ADSP ACE1X SoC family. + */ +struct intel_adsp_ipc { + uint32_t tdr; + uint32_t tda; + uint32_t unused0[2]; + uint32_t idr; + uint32_t ida; + uint32_t unused1[2]; + uint32_t cst; + uint32_t csr; + uint32_t ctl; + uint32_t cap; + uint32_t unused2[52]; + uint32_t tdd; + uint32_t unused3[31]; + uint32_t idd; +}; + +/** + * @brief Set TDA busy bit. + * + * On ACE SoC family boards TDA bit 31 (BUSY) during IPC doorbell acknowledgment + * must be cleared (!), not set (in contrary to CAVS SoC family boards). + * This clears BUSY on the other side of the connection in IDR register. + */ +#define INTEL_ADSP_IPC_ACE1X_TDA_DONE 0 +#define INTEL_ADSP_IPC_BUSY BIT(31) +#define INTEL_ADSP_IPC_DONE BIT(31) + +#define INTEL_ADSP_IPC_CTL_TBIE BIT(0) +#define INTEL_ADSP_IPC_CTL_IDIE BIT(1) +/** + * @brief ACE SoC family Intra DSP Communication. + * + * ACE SoC platform family provides an array of IPC endpoints to be used for + * peer-to-peer communication between DSP cores - master to slave and backwards. + * Given endpoint can be accessed by: + * @code + * IDC[slave_core_id].agents[agent_id].ipc; + * @endcode + */ +struct ace_idc { + /** + * @brief IPC Agent Endpoints. + * + * Each connection is organized into two "agents" ("A" - master core and "B" - slave core). + * Each agent is wired to its own interrupt. + * Agents array represents mutually exclusive IPC endpoint access: + * (A=1/B=0) - agents[0]. + * (A=0/B=1) - agents[1]. + */ + union { + int8_t unused[512]; + struct intel_adsp_ipc ipc; + } agents[2]; +}; + +/** + * @brief Defines register for intra DSP communication. + */ +#define IDC ((volatile struct ace_idc *)INTEL_ADSP_IDC_REG_ADDRESS) + +#endif /* ZEPHYR_SOC_INTEL_ADSP_ACE_IPC_REGS_H */ diff --git a/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory.h b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory.h new file mode 100644 index 00000000000000..1596cb489d3501 --- /dev/null +++ b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2024 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ +#define ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ + + +#include +#include +#include +#include + +#define L2_SRAM_BASE (DT_REG_ADDR(DT_NODELABEL(sram0))) +#define L2_SRAM_SIZE (DT_REG_SIZE(DT_NODELABEL(sram0))) + +#define L2_VIRTUAL_SRAM_BASE (DT_REG_ADDR(DT_NODELABEL(sram0virtual))) +#define L2_VIRTUAL_SRAM_SIZE (DT_REG_SIZE(DT_NODELABEL(sram0virtual))) + +#define LP_SRAM_BASE (DT_REG_ADDR(DT_NODELABEL(sram1))) +#define LP_SRAM_SIZE (DT_REG_SIZE(DT_NODELABEL(sram1))) + +#define ROM_JUMP_ADDR (LP_SRAM_BASE + 0x10) + +/* Linker-usable RAM region */ +#define RAM_BASE (L2_SRAM_BASE + CONFIG_HP_SRAM_RESERVE + VECTOR_TBL_SIZE) +#define RAM_SIZE (L2_SRAM_SIZE - CONFIG_HP_SRAM_RESERVE - VECTOR_TBL_SIZE) + + +/* L3 region (IMR), located in host memory */ + +#define L3_MEM_BASE_ADDR (DT_REG_ADDR(DT_NODELABEL(imr1))) +#define L3_MEM_SIZE (DT_REG_SIZE(DT_NODELABEL(imr1))) +#define L3_MEM_PAGE_SIZE (DT_PROP(DT_NODELABEL(imr1), block_size)) + +/* The rimage tool produces two blob addresses we need to find: one is + * our bootloader code block which starts at its entry point, the + * other is the "manifest" containing the HP-SRAM data to unpack, + * which appears 24k earlier in the DMA'd file, and thus in IMR + * memory. There's no ability to change this offset, it's a magic + * number from rimage we simply need to honor. + */ +#define IMR_BOOT_LDR_MANIFEST_OFFSET 0x42000 +#define IMR_BOOT_LDR_MANIFEST_SIZE 0x6000 +#define IMR_BOOT_LDR_MANIFEST_BASE (L3_MEM_BASE_ADDR + IMR_BOOT_LDR_MANIFEST_OFFSET) + +#define IMR_BOOT_LDR_TEXT_ENTRY_SIZE 0x180 +#define IMR_BOOT_LDR_TEXT_ENTRY_BASE (IMR_BOOT_LDR_MANIFEST_BASE + IMR_BOOT_LDR_MANIFEST_SIZE) + +#define IMR_BOOT_LDR_LIT_SIZE 0x40 +#define IMR_BOOT_LDR_LIT_BASE (IMR_BOOT_LDR_TEXT_ENTRY_BASE + \ + IMR_BOOT_LDR_TEXT_ENTRY_SIZE) + +#define IMR_BOOT_LDR_TEXT_SIZE 0x1C00 +#define IMR_BOOT_LDR_TEXT_BASE (IMR_BOOT_LDR_LIT_BASE + IMR_BOOT_LDR_LIT_SIZE) + +#define IMR_BOOT_LDR_DATA_OFFSET 0x49000 +#define IMR_BOOT_LDR_DATA_BASE (L3_MEM_BASE_ADDR + IMR_BOOT_LDR_DATA_OFFSET) +#define IMR_BOOT_LDR_DATA_SIZE 0xA8000 + +#define IMR_BOOT_LDR_BSS_OFFSET 0x110000 +#define IMR_BOOT_LDR_BSS_BASE (L3_MEM_BASE_ADDR + IMR_BOOT_LDR_BSS_OFFSET) +#define IMR_BOOT_LDR_BSS_SIZE 0x10000 + +/* stack to be used at boot, when RAM is not yet powered up */ +#define IMR_BOOT_LDR_STACK_BASE (IMR_BOOT_LDR_BSS_BASE + IMR_BOOT_LDR_BSS_SIZE) +#define IMR_BOOT_LDR_STACK_SIZE 0x1000 + +/* position of L3 heap, size of L3 heap - till end of the L3 memory */ +#define IMR_L3_HEAP_BASE (IMR_BOOT_LDR_STACK_BASE + IMR_BOOT_LDR_STACK_SIZE) +#define IMR_L3_HEAP_SIZE (L3_MEM_SIZE - \ + (IMR_L3_HEAP_BASE - L3_MEM_BASE_ADDR)) + +#define ADSP_L1_CACHE_PREFCTL_VALUE 0x1038 + +/* L1 init */ +#define ADSP_L1CC_ADDR (0x3FE80080) +#define ADSP_CxL1CCAP_ADDR (ADSP_L1CC_ADDR + 0x0000) +#define ADSP_CxL1CCFG_ADDR (ADSP_L1CC_ADDR + 0x0004) +#define ADSP_CxL1PCFG_ADDR (ADSP_L1CC_ADDR + 0x0008) + +#if (!defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)) + +#define ADSP_CxL1CCAP_REG (*(volatile uint32_t *)(ADSP_CxL1CCAP_ADDR)) +#define ADSP_CxL1CCFG_REG (*(volatile uint32_t *)(ADSP_CxL1CCFG_ADDR)) +#define ADSP_CxL1PCFG_REG (*(volatile uint32_t *)(ADSP_CxL1PCFG_ADDR)) + +#endif /* (!defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)) */ + +/* The number of set associative cache way supported on L1 Data Cache */ +#define ADSP_CxL1CCAP_DCMWC ((ADSP_CxL1CCAP_REG >> 16) & 7) +/* The number of set associative cache way supported on L1 Instruction Cache */ +#define ADSP_CxL1CCAP_ICMWC ((ADSP_CxL1CCAP_REG >> 20) & 7) + +#ifndef _LINKER +/* L2 Local Memory Management */ + +/* These registers are for the L2 memory control and status. */ +#define DFL2MM_REG 0x71d00 + +struct ace_l2mm { + uint32_t l2mcap; + uint32_t l2mpat; + uint32_t l2mecap; + uint32_t l2mecs; + uint32_t l2hsbpmptr; + uint32_t l2usbpmptr; + uint32_t l2usbmrpptr; + uint32_t l2ucmrpptr; + uint32_t l2ucmrpdptr; +}; + +#define ACE_L2MM ((volatile struct ace_l2mm *)DFL2MM_REG) + +/* DfL2MCAP */ +struct ace_l2mcap { + uint32_t l2hss : 8; + uint32_t l2uss : 4; + uint32_t l2hsbs : 4; + uint32_t l2hs2s : 8; + uint32_t l2usbs : 5; + uint32_t l2se : 1; + uint32_t el2se : 1; + uint32_t rsvd32 : 1; +}; + +#define ACE_L2MCAP ((volatile struct ace_l2mcap *)DFL2MM_REG) + +static ALWAYS_INLINE uint32_t ace_hpsram_get_bank_count(void) +{ + return ACE_L2MCAP->l2hss; +} + +static ALWAYS_INLINE uint32_t ace_lpsram_get_bank_count(void) +{ + return ACE_L2MCAP->l2uss; +} + +struct ace_hpsram_regs { + /** @brief power gating control */ + uint8_t HSxPGCTL; + /** @brief retention mode control */ + uint8_t HSxRMCTL; + uint8_t reserved[2]; + /** @brief power gating status */ + uint8_t HSxPGISTS; + uint8_t reserved1[3]; +}; + +struct ace_lpsram_regs { + /** @brief power gating control */ + uint8_t USxPGCTL; + /** @brief retention mode control */ + uint8_t USxRMCTL; + uint8_t reserved[2]; + /** @brief power gating status */ + uint8_t USxPGISTS; + uint8_t reserved1[3]; +}; +#endif + +/* These registers are for the L2 HP SRAM bank power management control and status.*/ +#define L2_HSBPM_BASE (DT_REG_ADDR(DT_NODELABEL(hsbpm))) +#define L2_HSBPM_SIZE (DT_REG_SIZE(DT_NODELABEL(hsbpm))) + +#define HPSRAM_REGS(block_idx) ((volatile struct ace_hpsram_regs *const) \ + (L2_HSBPM_BASE + L2_HSBPM_SIZE * (block_idx))) + +/* These registers are for the L2 LP SRAM bank power management control and status.*/ +#define L2_LSBPM_BASE (DT_REG_ADDR(DT_NODELABEL(lsbpm))) +#define L2_LSBPM_SIZE (DT_REG_SIZE(DT_NODELABEL(lsbpm))) + +#define LPSRAM_REGS(block_idx) ((volatile struct ace_lpsram_regs *const) \ + (L2_LSBPM_BASE + L2_LSBPM_SIZE * (block_idx))) + +#endif /* ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ */ diff --git a/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory_regions.h b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory_regions.h new file mode 100644 index 00000000000000..912a225588b301 --- /dev/null +++ b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory_regions.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_INTEL_ADSP_MEMORY_REGIONS_H_ +#define ZEPHYR_SOC_INTEL_ADSP_MEMORY_REGIONS_H_ + +/* Define amount of regions other than core heaps that virtual memory will be split to + * currently includes shared heap and oma region and one regions set to 0 as for table + * iterator end value. + */ +#define VIRTUAL_REGION_COUNT 3 + +#define CORE_HEAP_SIZE 0x100000 +#define SHARED_HEAP_SIZE 0x100000 +#define OPPORTUNISTIC_REGION_SIZE 0x100000 + +/* size of TLB table */ +#define TLB_SIZE DT_REG_SIZE_BY_IDX(DT_INST(0, intel_adsp_mtl_tlb), 0) + +/* Attribiutes for memory regions */ +#define MEM_REG_ATTR_CORE_HEAP 1U +#define MEM_REG_ATTR_SHARED_HEAP 2U +#define MEM_REG_ATTR_OPPORTUNISTIC_MEMORY 4U + +#endif /* ZEPHYR_SOC_INTEL_ADSP_MEMORY_REGIONS_H_ */ diff --git a/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_power.h b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_power.h new file mode 100644 index 00000000000000..f9628dbbb0dd6c --- /dev/null +++ b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_power.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2024 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#ifndef ZEPHYR_SOC_INTEL_ADSP_POWER_H_ +#define ZEPHYR_SOC_INTEL_ADSP_POWER_H_ + +/* Value used as delay when waiting for hw register state change. */ +#define HW_STATE_CHECK_DELAY 64 + +/* Power Control register - controls the power domain operations. */ +struct ace_pwrctl { + uint16_t rsvd0 : 5; + uint16_t wphstpg : 1; + uint16_t rsvd6 : 1; + uint16_t wphubhppg : 1; + uint16_t wpdspulppg : 1; + uint16_t wpioxpg : 2; + uint16_t rsvd11 : 2; + uint16_t wpmlpg : 1; + uint16_t rsvd14 : 2; + uint16_t phubulppg : 1; +}; + +struct ace_pwrctl2 { + uint16_t wpdsphpxpg : 5; +}; + +#define ACE_PWRCTL ((volatile struct ace_pwrctl *) &ACE_DfPMCCU.dfpwrctl) +#define ACE_PWRCTL2 ((volatile struct ace_pwrctl2 *) &ACE_DfPMCCU.dfpwrctl2) + +/* Power Status register - reports the power domain status. */ +struct ace_pwrsts { + uint16_t rsvd0 : 5; + uint16_t hstpgs : 1; + uint16_t rsvd6 : 1; + uint16_t hubhppgs : 1; + uint16_t dspulppgs : 1; + uint16_t ioxpgs : 4; + uint16_t mlpgs : 2; + uint16_t rsvd14 : 1; + uint16_t hubulppgs : 1; +}; + +struct ace_pwrsts2 { + uint16_t dsphpxpgs : 5; +}; + +#define ACE_PWRSTS ((volatile struct ace_pwrsts *) &ACE_DfPMCCU.dfpwrsts) +#define ACE_PWRSTS2 ((volatile struct ace_pwrsts2 *) &ACE_DfPMCCU.dfpwrsts2) + +/** + * @brief Power up a specific CPU. + * + * This sets the "not power gating" bit in the power control + * register to disable power gating to CPU, thus powering up + * the CPU. + * + * @param cpu_num CPU to be powered up. + */ +static ALWAYS_INLINE void soc_cpu_power_up(int cpu_num) +{ + ACE_PWRCTL2->wpdsphpxpg |= BIT(cpu_num); +} + +/** + * @brief Power down a specific CPU. + * + * This clears the "not power gating" bit in the power control + * register to enable power gating to CPU, thus powering down + * the CPU. + * + * @param cpu_num CPU to be powered down. + */ +static ALWAYS_INLINE void soc_cpu_power_down(int cpu_num) +{ + ACE_PWRCTL2->wpdsphpxpg &= ~BIT(cpu_num); +} + +/** + * @brief Test if a CPU is currently powered. + * + * This queries the power status register to see if the CPU + * is currently powered. + * + * @param cpu_num CPU to be queried. + * @return True if CPU is powered, false if now. + */ +static ALWAYS_INLINE bool soc_cpu_is_powered(int cpu_num) +{ + return (ACE_PWRSTS2->dsphpxpgs & BIT(cpu_num)) == BIT(cpu_num); +} + +/** + * @brief Retrieve node identifier for Intel ADSP HOST power domain. + */ +#define INTEL_ADSP_HST_DOMAIN_DTNODE DT_NODELABEL(hst_domain) + +/** + * @brief Intel ADSP HOST power domain pointer. + */ +#define INTEL_ADSP_HST_DOMAIN_DEV DEVICE_DT_GET(INTEL_ADSP_HST_DOMAIN_DTNODE) + +#endif /* ZEPHYR_SOC_INTEL_ADSP_POWER_H_ */ diff --git a/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_shim.h b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_shim.h new file mode 100644 index 00000000000000..e28e6f3d8afb45 --- /dev/null +++ b/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_shim.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_SOC_INTEL_ADSP_SHIM_H_ +#define ZEPHYR_SOC_INTEL_ADSP_SHIM_H_ + +#ifndef _ASMLANGUAGE +#include + +/** + * DfPMCCH + * Power Management / Clock Control (HST) Registers + * + * These registers block (HST domain) are for general power management + * and clock control operation for DSP FW. + */ +struct ace_dfpmcch { + uint32_t dfspsreq; /* Offset: 0x00 */ + uint32_t _unused0[3]; + uint32_t dfspsrsp; /* Offset: 0x10 */ + uint32_t _unused1[1]; + uint32_t svcfg; /* Offset: 0x18 */ + uint32_t dfltrc; /* Offset: 0x1c */ + uint32_t _unused2[8]; +}; + +/** + * DfPMCCU + * Power Management / Clock Control (ULP) Registers + * + * These registers block (ULP domain) are for general power management + * and clock control operation for DSP FW. + */ +struct ace_dfpmccu { + uint32_t dfpmccap; /* Offset: 0x00 */ + uint32_t dfhrosccf; /* Offset: 0x04 */ + uint32_t dfxosccf; /* Offset: 0x08 */ + uint32_t dflrosccf; /* Offset: 0x0c */ + uint32_t dfsiorosccf; /* Offset: 0x10 */ + uint32_t dfhsiorosccf; /* Offset: 0x14 */ + uint32_t dfipllrosccf; /* Offset: 0x18 */ + uint32_t dfirosccv; /* Offset: 0x1c */ + uint32_t dffbrcfd; /* Offset: 0x20 */ + uint32_t dfapllptr; /* Offset: 0x24 */ + uint32_t _unused0[20]; + uint32_t dfclkctl; /* Offset: 0x78 */ + uint32_t dfclksts; /* Offset: 0x7c */ + uint32_t dfintclkctl; /* Offset: 0x80 */ + uint32_t dfcrosts; /* Offset: 0x84 */ + uint32_t dfcrodiv; /* Offset: 0x88 */ + uint32_t _unused1[1]; + uint16_t dfpwrctl; /* Offset: 0x90 */ + uint16_t dfpwrsts; /* Offset: 0x92 */ + uint16_t dfpwrctl2; /* Offset: 0x94 */ + uint16_t dfpwrsts2; /* Offset: 0x96 */ + uint32_t dflpsdmas0; /* Offset: 0x98 */ + uint32_t dflpsdmas1; /* Offset: 0x9c */ + uint32_t _unused3[1]; + uint32_t dfldoctl; /* Offset: 0xa4 */ + uint32_t _unused4[2]; + uint32_t dflpsalhsso; /* Offset: 0xb0 */ + uint32_t dflpsalhss1; /* Offset: 0xb4 */ + uint32_t dflpsalhss2; /* Offset: 0xb8 */ + uint32_t dflpsalhss3; /* Offset: 0xbc */ + uint32_t _unused5[10]; +}; + +#define ACE_DfPMCCH (*((volatile struct ace_dfpmcch *)DT_REG_ADDR(DT_NODELABEL(dfpmcch)))) +#define ACE_DfPMCCU (*((volatile struct ace_dfpmccu *)DT_REG_ADDR(DT_NODELABEL(dfpmccu)))) + + +#define ADSP_TTSCAP_OFFSET 0x00 +#define ADSP_RTCWC_OFFSET 0x08 +#define ADSP_DSPWCCTL_OFFSET 0x10 +#define ADSP_DSPWCSTS_OFFSET 0x12 +#define ADSP_DSPWCAV_OFFSET 0x18 +#define ADSP_DSPWC_OFFSET 0x20 +#define ADSP_DSPWCTCS_OFFSET 0x28 +#define ADSP_DSPWCT0C_OFFSET 0x30 +#define ADSP_DSPWCT1C_OFFSET 0x38 +#define ADSP_TSCTRL_OFFSET 0x40 +#define ADSP_ISCS_OFFSET 0x44 +#define ADSP_LSCS_OFFSET 0x48 +#define ADSP_DWCCS_OFFSET 0x50 +#define ADSP_ARTCS_OFFSET 0x58 +#define ADSP_LWCCS_OFFSET 0x60 +#define ADSP_CLTSYNC_OFFSET 0x70 + + + +#define ADSP_SHIM_DSPWCTCS_TTIE(c) BIT(8 + (c)) + + +#define ADSP_SHIM_TSCTRL_NTK BIT(31) +#define ADSP_SHIM_TSCTRL_IONTE BIT(30) +#define ADSP_SHIM_TSCTRL_DMATS GENMASK(13, 12) +#define ADSP_SHIM_TSCTRL_CLNKS GENMASK(11, 10) +#define ADSP_SHIM_TSCTRL_HHTSE BIT(7) +#define ADSP_SHIM_TSCTRL_LWCS BIT(6) +#define ADSP_SHIM_TSCTRL_ODTS BIT(5) +#define ADSP_SHIM_TSCTRL_CDMAS GENMASK(4, 0) + +#endif /* _ASMLANGUAGE */ + +#define ACE_CLKCTL_WOVCRO BIT(4) /* Request WOVCRO clock */ + +#define SHIM_LDOCTL_HPSRAM_LDO_ON (3 << 0) +#define SHIM_LDOCTL_HPSRAM_LDO_BYPASS BIT(0) + +#define SHIM_LDOCTL_LPSRAM_LDO_ON (3 << 2) +#define SHIM_LDOCTL_LPSRAM_LDO_BYPASS BIT(2) + +#define ADSP_DMWBA_ENABLE BIT(0) +#define ADSP_DMWBA_READONLY BIT(1) + +#define ADSP_CLKCTL_OSC_SOURCE_MASK (3<<2) +#define ADSP_CLKCTL_OSC_REQUEST_MASK (~BIT_MASK(28)) + +/** LDO Control */ +#define ADSP_DSPRA_ADDRESS (0x71A60) +#define ADSP_LPGPDMACxO_ADDRESS(x) (ADSP_DSPRA_ADDRESS + 0x0000 + 0x0002*(x)) +#define ADSP_DSPIOPO_ADDRESS (ADSP_DSPRA_ADDRESS + 0x0008) +#define ADSP_GENO_ADDRESS (ADSP_DSPRA_ADDRESS + 0x000C) +#define ADSP_DSPALHO_ADDRESS (ADSP_DSPRA_ADDRESS + 0x0010) + + +#define DSP_INIT_IOPO ADSP_DSPIOPO_ADDRESS +#define IOPO_DMIC_FLAG BIT(0) +#define IOPO_DSPKOSEL_FLAG BIT(1) +#define IOPO_ANCOSEL_FLAG BIT(2) +#define IOPO_DMIXOSEL_FLAG BIT(3) +#define IOPO_SLIMOSEL_FLAG BIT(4) +#define IOPO_SNDWOSEL_FLAG BIT(5) +#define IOPO_SLIMDOSEL_FLAG BIT(20) +#define IOPO_I2SSEL_MASK (0x7 << 0x8) + +#define DSP_INIT_GENO ADSP_GENO_ADDRESS +#define GENO_MDIVOSEL BIT(1) +#define GENO_DIOPTOSEL BIT(2) + +#define ADSP_FORCE_DECOUPLED_HDMA_L1_EXIT_BIT BIT(1) + +#endif /* ZEPHYR_SOC_INTEL_ADSP_SHIM_H_ */ diff --git a/soc/intel/intel_adsp/ace/mmu_ptl.c b/soc/intel/intel_adsp/ace/mmu_ptl.c new file mode 100644 index 00000000000000..a59b231fbe3fe9 --- /dev/null +++ b/soc/intel/intel_adsp/ace/mmu_ptl.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include + +extern char _cached_start[]; +extern char _cached_end[]; +extern char _imr_start[]; +extern char _imr_end[]; +extern char __common_rom_region_start[]; +extern char __common_rom_region_end[]; +extern char __common_ram_region_start[]; +extern char __common_ram_region_end[]; + +const struct xtensa_mmu_range xtensa_soc_mmu_ranges[] = { + { + .start = (uint32_t)__common_ram_region_start, + .end = (uint32_t)__common_ram_region_end, + .attrs = XTENSA_MMU_PERM_W, + .name = "common-ram", + }, + { + /* Workaround for D3 flows. L2 TLB wider than MMU TLB */ + .start = (uint32_t)L2_SRAM_BASE, + .end = (uint32_t)VECBASE_RESET_PADDR_SRAM, + .attrs = XTENSA_MMU_PERM_W | XTENSA_MMU_CACHED_WB, + .name = "workaround L2 TLB/MMU TLB", + }, + { + .start = (uint32_t)VECBASE_RESET_PADDR_SRAM, + .end = (uint32_t)VECBASE_RESET_PADDR_SRAM + VECTOR_TBL_SIZE, + .attrs = XTENSA_MMU_PERM_X | XTENSA_MMU_MAP_SHARED, + .name = "exceptions", + }, + { + .start = (uint32_t)_cached_start, + .end = (uint32_t)_cached_end, + .attrs = XTENSA_MMU_PERM_W | XTENSA_MMU_CACHED_WB, + .name = "cached", + }, + { + .start = (uint32_t)HP_SRAM_WIN0_BASE, + .end = (uint32_t)HP_SRAM_WIN0_BASE + (uint32_t)HP_SRAM_WIN0_SIZE, + .attrs = XTENSA_MMU_PERM_W, + .name = "win0", + }, + { + .start = (uint32_t)HP_SRAM_WIN1_BASE, + .end = (uint32_t)HP_SRAM_WIN1_BASE + (uint32_t)HP_SRAM_WIN1_SIZE, + .attrs = XTENSA_MMU_PERM_W, + .name = "win2", + }, + { + .start = (uint32_t)HP_SRAM_WIN2_BASE, + .end = (uint32_t)HP_SRAM_WIN2_BASE + (uint32_t)HP_SRAM_WIN2_SIZE, + .attrs = XTENSA_MMU_PERM_W, + .name = "win2", + }, + { + .start = (uint32_t)HP_SRAM_WIN3_BASE, + .end = (uint32_t)HP_SRAM_WIN3_BASE + (uint32_t)HP_SRAM_WIN3_SIZE, + .attrs = XTENSA_MMU_PERM_W, + .name = "win3", + }, + /* Map IMR */ + { + .start = (uint32_t)(IMR_BOOT_LDR_MANIFEST_BASE - IMR_BOOT_LDR_MANIFEST_SIZE), + .end = (uint32_t)IMR_BOOT_LDR_MANIFEST_BASE, + .attrs = XTENSA_MMU_PERM_W | XTENSA_MMU_CACHED_WB, + .name = "imr stack", + }, + { + .start = (uint32_t)IMR_BOOT_LDR_MANIFEST_BASE, + .end = (uint32_t)(IMR_BOOT_LDR_MANIFEST_BASE + IMR_BOOT_LDR_MANIFEST_SIZE), + .name = "imr text", + }, + { + .start = (uint32_t)IMR_BOOT_LDR_BSS_BASE, + .end = (uint32_t)(IMR_BOOT_LDR_BSS_BASE + IMR_BOOT_LDR_BSS_SIZE), + .name = "imr bss", + }, + { + .start = (uint32_t)IMR_BOOT_LDR_TEXT_ENTRY_BASE, + .end = (uint32_t)(IMR_BOOT_LDR_TEXT_ENTRY_BASE + IMR_BOOT_LDR_TEXT_ENTRY_SIZE), + .attrs = XTENSA_MMU_PERM_X | XTENSA_MMU_MAP_SHARED, + .name = "imr text", + }, + { + .start = (uint32_t)IMR_BOOT_LDR_STACK_BASE, + .end = (uint32_t)(IMR_BOOT_LDR_STACK_BASE + IMR_BOOT_LDR_STACK_SIZE), + .attrs = XTENSA_MMU_PERM_W | XTENSA_MMU_CACHED_WB, + .name = "imr stack", + }, + { + .start = (uint32_t)IMR_LAYOUT_ADDRESS, + /* sizeof(struct imr_layout) happens to be 0x1000 (4096) bytes. */ + .end = (uint32_t)(IMR_LAYOUT_ADDRESS + sizeof(struct imr_layout)), + .attrs = XTENSA_MMU_PERM_W | XTENSA_MMU_CACHED_WB, + .name = "imr layout", + }, + { + .start = (uint32_t)IMR_L3_HEAP_BASE, + .end = (uint32_t)(IMR_L3_HEAP_BASE + IMR_L3_HEAP_SIZE), + .attrs = XTENSA_MMU_PERM_W | XTENSA_MMU_CACHED_WB, + .name = "imr L3 heap", + }, + { + .start = (uint32_t)LP_SRAM_BASE, + .end = (uint32_t)(LP_SRAM_BASE + LP_SRAM_SIZE), + .attrs = XTENSA_MMU_PERM_W | XTENSA_MMU_CACHED_WB, + .name = "lpsram", + }, + { + .start = (uint32_t)(ADSP_L1CC_ADDR), + .end = (uint32_t)(ADSP_L1CC_ADDR + CONFIG_MMU_PAGE_SIZE), + .attrs = XTENSA_MMU_PERM_W, + .name = "l1cc", + }, + { + /* FIXME: definitely need more refinements... */ + .start = (uint32_t)0x0, + .end = (uint32_t)0x100000, + .attrs = XTENSA_MMU_PERM_W, + .name = "hwreg0", + }, + { + /* FIXME: definitely need more refinements... */ + .start = (uint32_t)0x170000, + .end = (uint32_t)0x180000, + .attrs = XTENSA_MMU_PERM_W, + .name = "hwreg1", + }, +}; + +int xtensa_soc_mmu_ranges_num = ARRAY_SIZE(xtensa_soc_mmu_ranges); diff --git a/soc/intel/intel_adsp/ace/multiprocessing.c b/soc/intel/intel_adsp/ace/multiprocessing.c index f530232e896fa0..68b8693a520d4b 100644 --- a/soc/intel/intel_adsp/ace/multiprocessing.c +++ b/soc/intel/intel_adsp/ace/multiprocessing.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -25,12 +26,28 @@ #define CPU_POWERUP_TIMEOUT_USEC 10000 +#ifdef CONFIG_XTENSA_MMU +#include +#endif /* CONFIG_XTENSA_MMU */ + #define ACE_INTC_IRQ DT_IRQN(DT_NODELABEL(ace_intc)) +#ifdef CONFIG_XTENSA_MMU +#define IPI_TLB_FLUSH 0x01 +#endif + static void ipc_isr(void *arg) { uint32_t cpu_id = arch_proc_id(); +#if defined(CONFIG_XTENSA_MMU) && (CONFIG_MP_MAX_NUM_CPUS > 1) + uint32_t msg = IDC[cpu_id].agents[0].ipc.tdr & ~INTEL_ADSP_IPC_BUSY; + + if (msg == IPI_TLB_FLUSH) { + xtensa_mmu_tlb_shootdown(); + } +#endif + /* * Clearing the BUSY bits in both TDR and TDA are needed to * complete an IDC message. If we do only one (and not both), @@ -40,7 +57,7 @@ static void ipc_isr(void *arg) * On TDR, it is to write one to clear, while on TDA, it is * to write zero to clear. */ - IDC[cpu_id].agents[0].ipc.tdr = BIT(31); + IDC[cpu_id].agents[0].ipc.tdr = INTEL_ADSP_IPC_BUSY; IDC[cpu_id].agents[0].ipc.tda = 0; #ifdef CONFIG_SMP @@ -166,6 +183,10 @@ void soc_start_core(int cpu_num) void soc_mp_startup(uint32_t cpu) { +#ifdef CONFIG_XTENSA_MMU + xtensa_mmu_init(); +#endif /* CONFIG_XTENSA_MMU */ + /* Must have this enabled always */ xtensa_irq_enable(ACE_INTC_IRQ); @@ -178,7 +199,17 @@ void soc_mp_startup(uint32_t cpu) #endif /* CONFIG_ADSP_IDLE_CLOCK_GATING */ } -void arch_sched_ipi(void) +/** + * @brief Send a IPI to other processors. + * + * @note: Leave the MSB clear when passing @param msg. + * + * @param msg Message to be sent (31-bit integer). + */ +#ifndef CONFIG_XTENSA_MMU +ALWAYS_INLINE +#endif +static void send_ipi(uint32_t msg) { uint32_t curr = arch_proc_id(); @@ -187,11 +218,23 @@ void arch_sched_ipi(void) for (int core = 0; core < num_cpus; core++) { if (core != curr && soc_cpus_active[core]) { - IDC[core].agents[1].ipc.idr = INTEL_ADSP_IPC_BUSY; + IDC[core].agents[1].ipc.idr = msg | INTEL_ADSP_IPC_BUSY; } } } +void arch_sched_ipi(void) +{ + send_ipi(0); +} + +#if defined(CONFIG_XTENSA_MMU) && (CONFIG_MP_MAX_NUM_CPUS > 1) +void xtensa_mmu_tlb_ipi(void) +{ + send_ipi(IPI_TLB_FLUSH); +} +#endif + #if CONFIG_MP_MAX_NUM_CPUS > 1 int soc_adsp_halt_cpu(int id) { diff --git a/soc/intel/intel_adsp/ace/power.c b/soc/intel/intel_adsp/ace/power.c index afc270f9afa07f..57fd8905e564df 100644 --- a/soc/intel/intel_adsp/ace/power.c +++ b/soc/intel/intel_adsp/ace/power.c @@ -122,6 +122,9 @@ struct core_state { uint32_t intenable; uint32_t ps; uint32_t bctl; +#if (XCHAL_NUM_MISC_REGS == 2) + uint32_t misc[XCHAL_NUM_MISC_REGS]; +#endif }; static struct core_state core_desc[CONFIG_MP_MAX_NUM_CPUS] = {{0}}; @@ -142,6 +145,10 @@ static ALWAYS_INLINE void _save_core_context(uint32_t core_id) core_desc[core_id].excsave2 = XTENSA_RSR("EXCSAVE2"); core_desc[core_id].excsave3 = XTENSA_RSR("EXCSAVE3"); core_desc[core_id].thread_ptr = XTENSA_RUR("THREADPTR"); +#if (XCHAL_NUM_MISC_REGS == 2) + core_desc[core_id].misc[0] = XTENSA_RSR("MISC0"); + core_desc[core_id].misc[1] = XTENSA_RSR("MISC1"); +#endif __asm__ volatile("mov %0, a0" : "=r"(core_desc[core_id].a0)); __asm__ volatile("mov %0, a1" : "=r"(core_desc[core_id].a1)); @@ -157,11 +164,18 @@ static ALWAYS_INLINE void _restore_core_context(void) { uint32_t core_id = arch_proc_id(); +#ifdef CONFIG_XTENSA_MMU + xtensa_mmu_init(); +#endif XTENSA_WSR("PS", core_desc[core_id].ps); XTENSA_WSR("VECBASE", core_desc[core_id].vecbase); XTENSA_WSR("EXCSAVE2", core_desc[core_id].excsave2); XTENSA_WSR("EXCSAVE3", core_desc[core_id].excsave3); XTENSA_WUR("THREADPTR", core_desc[core_id].thread_ptr); +#if (XCHAL_NUM_MISC_REGS == 2) + XTENSA_WSR("MISC0", core_desc[core_id].misc[0]); + XTENSA_WSR("MISC1", core_desc[core_id].misc[1]); +#endif __asm__ volatile("mov a0, %0" :: "r"(core_desc[core_id].a0)); __asm__ volatile("mov a1, %0" :: "r"(core_desc[core_id].a1)); __asm__ volatile("rsync"); diff --git a/soc/intel/intel_adsp/common/include/adsp-vectors.h b/soc/intel/intel_adsp/common/include/adsp-vectors.h index 01e660e43ea657..97f778968b8166 100644 --- a/soc/intel/intel_adsp/common/include/adsp-vectors.h +++ b/soc/intel/intel_adsp/common/include/adsp-vectors.h @@ -45,7 +45,7 @@ #define DOUBLEEXC_VECTOR_PADDR_SRAM \ (VECBASE_RESET_PADDR_SRAM + XCHAL_DOUBLEEXC_VECOFS) -#define VECTOR_TBL_SIZE 0x0400 +#define VECTOR_TBL_SIZE 0x1000 /* Vector and literal sizes */ #define MEM_VECT_LIT_SIZE 0x8 diff --git a/soc/intel/intel_adsp/common/include/cpu_init.h b/soc/intel/intel_adsp/common/include/cpu_init.h index 571ae29f5b8a8f..dea6aa9f181fa7 100644 --- a/soc/intel/intel_adsp/common/include/cpu_init.h +++ b/soc/intel/intel_adsp/common/include/cpu_init.h @@ -76,8 +76,15 @@ static ALWAYS_INLINE void cpu_early_init(void) /* Finally we need to enable the cache in the Region * Protection Option "TLB" entries. The hardware defaults * have this set to RW/uncached everywhere. + * + * If we have MMU enabled, we don't need to do this right now. + * Let use the default configuration and properly configure the + * MMU when running from RAM. */ +#ifndef CONFIG_MMU ARCH_XTENSA_SET_RPO_TLB(); +#endif + /* Initialize ATOMCTL: Hardware defaults for S32C1I use * "internal" operations, meaning they are atomic only WRT the diff --git a/soc/intel/intel_adsp/soc.yml b/soc/intel/intel_adsp/soc.yml index 757750eeb379d8..0f889aea963821 100644 --- a/soc/intel/intel_adsp/soc.yml +++ b/soc/intel/intel_adsp/soc.yml @@ -5,6 +5,7 @@ family: socs: - name: ace15_mtpm - name: ace20_lnl + - name: ace30_ptl - name: intel_adsp_cavs socs: - name: cavs25 From 4fed5c53a8f03446e887497f21d5dde419a8e03a Mon Sep 17 00:00:00 2001 From: Jaroslaw Stelter Date: Fri, 21 Oct 2022 09:07:41 +0200 Subject: [PATCH 2/6] drivers: dai/dmic: Add support for ace30 (PTL) Add dmic support in PTL. Signed-off-by: Flavio Ceolin Signed-off-by: Jaroslaw Stelter --- drivers/dai/intel/dmic/dmic.c | 16 ++++++++-------- drivers/dai/intel/dmic/dmic.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/dai/intel/dmic/dmic.c b/drivers/dai/intel/dmic/dmic.c index f65c554cf989ac..81a404a51208c5 100644 --- a/drivers/dai/intel/dmic/dmic.c +++ b/drivers/dai/intel/dmic/dmic.c @@ -159,7 +159,7 @@ static inline void dai_dmic_release_ownership(const struct dai_intel_dmic *dmic) static inline uint32_t dai_dmic_base(const struct dai_intel_dmic *dmic) { -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) return dmic->hdamldmic_base; #else return dmic->shim_base; @@ -172,7 +172,7 @@ static inline void dai_dmic_set_sync_period(uint32_t period, const struct dai_in uint32_t val = CONFIG_DAI_DMIC_HW_IOCLK / period - 1; uint32_t base = dai_dmic_base(dmic); /* DMIC Change sync period */ -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) sys_write32(sys_read32(base + DMICSYNC_OFFSET) | FIELD_PREP(DMICSYNC_SYNCPRD, val), base + DMICSYNC_OFFSET); sys_write32(sys_read32(base + DMICSYNC_OFFSET) | DMICSYNC_SYNCPU, @@ -286,7 +286,7 @@ static void dai_dmic_irq_handler(const void *data) static inline void dai_dmic_dis_clk_gating(const struct dai_intel_dmic *dmic) { /* Disable DMIC clock gating */ -#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if (CONFIG_SOC_INTEL_ACE20_LNL || CONFIG_SOC_INTEL_ACE30_PTL) sys_write32((sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET) | DMICLVSCTL_DCGD), dmic->vshim_base + DMICLVSCTL_OFFSET); #else @@ -298,10 +298,10 @@ static inline void dai_dmic_dis_clk_gating(const struct dai_intel_dmic *dmic) static inline void dai_dmic_en_clk_gating(const struct dai_intel_dmic *dmic) { /* Enable DMIC clock gating */ -#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if (CONFIG_SOC_INTEL_ACE20_LNL || CONFIG_SOC_INTEL_ACE30_PTL) sys_write32((sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET) & ~DMICLVSCTL_DCGD), dmic->vshim_base + DMICLVSCTL_OFFSET); -#else +#else /* All other CAVS and ACE platforms */ sys_write32((sys_read32(dmic->shim_base + DMICLCTL_OFFSET) & ~DMICLCTL_DCGD), dmic->shim_base + DMICLCTL_OFFSET); #endif @@ -312,7 +312,7 @@ static inline void dai_dmic_program_channel_map(const struct dai_intel_dmic *dmi const struct dai_config *cfg, uint32_t index) { -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) uint16_t pcmsycm = cfg->link_config; uint32_t reg_add = dmic->shim_base + DMICXPCMSyCM_OFFSET + 0x0004*index; @@ -321,7 +321,7 @@ static inline void dai_dmic_program_channel_map(const struct dai_intel_dmic *dmi ARG_UNUSED(dmic); ARG_UNUSED(cfg); ARG_UNUSED(index); -#endif /* defined(CONFIG_SOC_INTEL_ACE20_LNL) */ +#endif /* defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) */ } static inline void dai_dmic_en_power(const struct dai_intel_dmic *dmic) @@ -331,7 +331,7 @@ static inline void dai_dmic_en_power(const struct dai_intel_dmic *dmic) sys_write32((sys_read32(base + DMICLCTL_OFFSET) | DMICLCTL_SPA), base + DMICLCTL_OFFSET); -#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) while (!(sys_read32(base + DMICLCTL_OFFSET) & DMICLCTL_CPA)) { k_sleep(K_USEC(100)); } diff --git a/drivers/dai/intel/dmic/dmic.h b/drivers/dai/intel/dmic/dmic.h index e06ed80daed75f..d690c0cd21a1ca 100644 --- a/drivers/dai/intel/dmic/dmic.h +++ b/drivers/dai/intel/dmic/dmic.h @@ -173,7 +173,7 @@ struct dai_intel_dmic { /* hardware parameters */ uint32_t reg_base; uint32_t shim_base; -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) uint32_t hdamldmic_base; uint32_t vshim_base; #endif From 0ad827c51453ba76bdd47501aa4d7c81ee323984 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Fri, 23 Jun 2023 20:10:05 +0000 Subject: [PATCH 3/6] intel_adsp: dmic: enable support for ptl use new headers headers for dmic are now part of the SoC and maintained per generation, so create one header for PTL and build the code for PTL in some of the drivers (dmic_nhlt). Signed-off-by: Anas Nashif --- drivers/dai/intel/dmic/dmic_nhlt.c | 6 +- .../ace/include/ace30_ptl/dmic_regs_ace3x.h | 70 +++++++++++++++++++ soc/intel/intel_adsp/ace/include/dmic_regs.h | 2 + 3 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 soc/intel/intel_adsp/ace/include/ace30_ptl/dmic_regs_ace3x.h diff --git a/drivers/dai/intel/dmic/dmic_nhlt.c b/drivers/dai/intel/dmic/dmic_nhlt.c index c7fe48e1432da7..5f150e6d0375c5 100644 --- a/drivers/dai/intel/dmic/dmic_nhlt.c +++ b/drivers/dai/intel/dmic/dmic_nhlt.c @@ -279,7 +279,7 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, const int c static inline void dai_dmic_clock_select_set(const struct dai_intel_dmic *dmic, uint32_t source) { uint32_t val; -#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) /* ACE 2.0,3.0 */ val = sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET); val &= ~DMICLVSCTL_MLCS; val |= FIELD_PREP(DMICLVSCTL_MLCS, source); @@ -300,7 +300,7 @@ static inline void dai_dmic_clock_select_set(const struct dai_intel_dmic *dmic, static inline uint32_t dai_dmic_clock_select_get(const struct dai_intel_dmic *dmic) { uint32_t val; -#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) /* ACE 2.0,3.0 */ val = sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET); return FIELD_GET(DMICLVSCTL_MLCS, val); #else @@ -322,7 +322,7 @@ static int dai_dmic_set_clock(const struct dai_intel_dmic *dmic, const uint8_t c return -ENOTSUP; } -#ifndef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if defined(CONFIG_SOC_INTEL_ACE15_MTPM) if (clock_source && !(sys_read32(dmic->shim_base + DMICLCAP_OFFSET) & DMICLCAP_MLCS)) { return -ENOTSUP; } diff --git a/soc/intel/intel_adsp/ace/include/ace30_ptl/dmic_regs_ace3x.h b/soc/intel/intel_adsp/ace/include/ace30_ptl/dmic_regs_ace3x.h new file mode 100644 index 00000000000000..4d02abea74957b --- /dev/null +++ b/soc/intel/intel_adsp/ace/include/ace30_ptl/dmic_regs_ace3x.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __INTEL_DAI_DRIVER_DMIC_REGS_ACE3X_H__ +#define __INTEL_DAI_DRIVER_DMIC_REGS_ACE3X_H__ + +/* DMIC Link Synchronization */ +#define DMICSYNC_OFFSET 0x1C + +/* Sync Period */ +#define DMICSYNC_SYNCPRD GENMASK(19, 0) + +/* Sync Period Update */ +#define DMICSYNC_SYNCPU BIT(20) + +/* Sync Go */ +#define DMICSYNC_SYNCGO BIT(23) + +/* Command Sync */ +#define DMICSYNC_CMDSYNC BIT(24) + + +/* DMIC Link Control */ +#define DMICLCTL_OFFSET 0x04 + +/* Set Clock Frequency */ +#define DMICLCTL_SCF GENMASK(3, 0) + +/* Offload Enable */ +#define DMICLCTL_OFLEN BIT(4) + +/* Interrupt Enable */ +#define DMICLCTL_INTEN BIT(5) + +/* Set Power Active */ +#define DMICLCTL_SPA BIT(16) + +/* Current Power Active */ +#define DMICLCTL_CPA BIT(23) + +/* Interrupt Status */ +#define DMICLCTL_INTSTS BIT(31) + + +/* Digital Microphone x Link Vendor Specific Control */ +#define DMICLVSCTL_OFFSET 0x04 + +/* Force Clock Gating */ +#define DMICLVSCTL_FCG BIT(26) + +/* Host Link Clock Select */ +#define DMICLVSCTL_MLCS GENMASK(29, 27) + +/* Dynamic Clock Gating Disable */ +#define DMICLVSCTL_DCGD BIT(30) + +/* Idle Clock Gating Disable */ +#define DMICLVSCTL_ICGD BIT(31) + + +/* Digital Microphone PCM Stream y Channel Map + * + * Offset: 12h + 02h * y + */ +#define DMICXPCMSyCM_OFFSET 0x16 +#define DMICXPCMSyCM_SIZE 0x02 + +#endif /* !__INTEL_DAI_DRIVER_DMIC_REGS_ACE3X_H__ */ diff --git a/soc/intel/intel_adsp/ace/include/dmic_regs.h b/soc/intel/intel_adsp/ace/include/dmic_regs.h index 201c3b2d6dfa36..df69d3687f19d7 100644 --- a/soc/intel/intel_adsp/ace/include/dmic_regs.h +++ b/soc/intel/intel_adsp/ace/include/dmic_regs.h @@ -351,6 +351,8 @@ #include #elif CONFIG_SOC_INTEL_ACE15_MTPM #include +#elif CONFIG_SOC_INTEL_ACE30_PTL +#include #else #error "Unknown SoC" #endif From 75ad16389f77c1ee4f70a1e7c9c53369a95e39cd Mon Sep 17 00:00:00 2001 From: Jaroslaw Stelter Date: Wed, 31 May 2023 16:17:15 +0200 Subject: [PATCH 4/6] drivers: mm/intel_adsp: Add MMU support to MM driver In the Intel platforms most of HPSRAM is used by modules when are required. By default all these banks are powered off and are enabled by L2 MM driver only when needed. At the driver initialisation each unused page is unmaped and when whole HPSRAM bank is unused the power is switched off. Since mapping memory in MMU TLB and flushing it at system start is not needed and time consuming, this patch modifies the init sequence to avoid it. Additionally it adds MMU maping and unmaping for pages allocated from unused pool. Signed-off-by: Flavio Ceolin Signed-off-by: Jaroslaw Stelter Signed-off-by: Anas Nashif --- drivers/mm/mm_drv_intel_adsp.h | 5 +-- drivers/mm/mm_drv_intel_adsp_mtl_tlb.c | 60 ++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/drivers/mm/mm_drv_intel_adsp.h b/drivers/mm/mm_drv_intel_adsp.h index 8de9ccc42cab62..861621a510f44d 100644 --- a/drivers/mm/mm_drv_intel_adsp.h +++ b/drivers/mm/mm_drv_intel_adsp.h @@ -30,10 +30,7 @@ #include "mm_drv_common.h" -DEVICE_MMIO_TOPLEVEL_STATIC(tlb_regs, DT_DRV_INST(0)); - -#define TLB_BASE \ - ((mm_reg_t)DEVICE_MMIO_TOPLEVEL_GET(tlb_regs)) +#define TLB_BASE (mm_reg_t)DT_REG_ADDR(DT_NODELABEL(tlb)) /* * Number of significant bits in the page index (defines the size of diff --git a/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c b/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c index b78a247ae0122c..5b0bc5e576be05 100644 --- a/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c +++ b/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c @@ -26,6 +26,7 @@ #include #include #include +#include #define SRAM_BANK_PAGE_NUM (SRAM_BANK_SIZE / CONFIG_MM_DRV_PAGE_SIZE) @@ -268,6 +269,9 @@ int sys_mm_drv_map_page(void *virt, uintptr_t phys, uint32_t flags) tlb_entries[entry_idx] = entry; +#ifdef CONFIG_MMU + arch_mem_map(virt, va, CONFIG_MM_DRV_PAGE_SIZE, flags); +#endif /* * Invalid the cache of the newly mapped virtual page to * avoid stale data. @@ -329,7 +333,7 @@ int sys_mm_drv_map_array(void *virt, uintptr_t *phys, return sys_mm_drv_simple_map_array(va, phys, cnt, flags); } -int sys_mm_drv_unmap_page(void *virt) +static int sys_mm_drv_unmap_page_wflush(void *virt, bool flush_data) { k_spinlock_key_t key; uint32_t entry_idx, bank_idx; @@ -358,8 +362,14 @@ int sys_mm_drv_unmap_page(void *virt) /* * Flush the cache to make sure the backing physical page * has the latest data. + * No flush when called from sys_mm_drv_mm_init(). */ - sys_cache_data_flush_range(virt, CONFIG_MM_DRV_PAGE_SIZE); + if (flush_data) { + sys_cache_data_flush_range(virt, CONFIG_MM_DRV_PAGE_SIZE); +#ifdef CONFIG_MMU + arch_mem_unmap(virt, CONFIG_MM_DRV_PAGE_SIZE); +#endif + } entry_idx = get_tlb_entry_idx(va); pa = tlb_entry_to_pa(tlb_entries[entry_idx]); @@ -391,6 +401,11 @@ int sys_mm_drv_unmap_page(void *virt) return ret; } +int sys_mm_drv_unmap_page(void *virt) +{ + return sys_mm_drv_unmap_page_wflush(virt, true); +} + int sys_mm_drv_unmap_region(void *virt, size_t size) { void *va = (__sparse_force void *)sys_cache_cached_ptr_get(virt); @@ -441,6 +456,42 @@ int sys_mm_drv_update_page_flags(void *virt, uint32_t flags) return ret; } +#ifdef CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM +static int sys_mm_drv_unmap_region_initial(void *virt_in, size_t size) +{ + void *virt = (__sparse_force void *)sys_cache_cached_ptr_get(virt_in); + + k_spinlock_key_t key; + int ret = 0; + size_t offset; + + CHECKIF(!sys_mm_drv_is_virt_addr_aligned(virt) || + !sys_mm_drv_is_size_aligned(size)) { + ret = -EINVAL; + goto out; + } + + key = k_spin_lock(&sys_mm_drv_common_lock); + + for (offset = 0; offset < size; offset += CONFIG_MM_DRV_PAGE_SIZE) { + uint8_t *va = (uint8_t *)virt + offset; + + int ret2 = sys_mm_drv_unmap_page_wflush(va, false); + + if (ret2 != 0) { + __ASSERT(false, "cannot unmap %p\n", va); + + ret = ret2; + } + } + + k_spin_unlock(&sys_mm_drv_common_lock, key); + +out: + return ret; +} +#endif + int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys) { uint16_t *tlb_entries = UINT_TO_POINTER(TLB_BASE); @@ -721,8 +772,9 @@ static int sys_mm_drv_mm_init(const struct device *dev) size_t unused_size = CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_SIZE - UNUSED_L2_START_ALIGNED; - ret = sys_mm_drv_unmap_region(UINT_TO_POINTER(UNUSED_L2_START_ALIGNED), - unused_size); + ret = sys_mm_drv_unmap_region_initial(UINT_TO_POINTER(UNUSED_L2_START_ALIGNED), + unused_size); + /* Need to reset max pages statistics after unmap */ for (int i = 0; i < L2_SRAM_BANK_NUM; i++) { From 2bb3ae4c9977efd115e67e7921169ddf8cff73af Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Thu, 16 May 2024 18:47:51 +0000 Subject: [PATCH 5/6] drivers: dai/ssp: Support dynamic SSP management This commit refactors the Intel SSP DAI driver to support dynamic management of SSP IP. This change additionally separates the management of the DAI part from the management part of the SSP IP. Key changes: - Add new static functions to manage SSP IP power. - Update the DAI SSP configuration functions to use the new management approach. - Update device tree bindings and instances to reflect the new SSP IP management mechanism. - ace30 (PTL) support. Signed-off-by: Flavio Ceolin Signed-off-by: Anas Nashif Signed-off-by: Jaroslaw Stelter --- drivers/dai/intel/ssp/ssp.c | 194 ++++++++++++---- drivers/dai/intel/ssp/ssp.h | 228 +------------------ drivers/dai/intel/ssp/ssp_regs_v1.h | 252 +++++++++++++++++++++ drivers/dai/intel/ssp/ssp_regs_v2.h | 250 ++++++++++++++++++++ drivers/dai/intel/ssp/ssp_regs_v3.h | 246 ++++++++++++++++++++ dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi | 70 ++---- 6 files changed, 923 insertions(+), 317 deletions(-) create mode 100644 drivers/dai/intel/ssp/ssp_regs_v1.h create mode 100644 drivers/dai/intel/ssp/ssp_regs_v2.h create mode 100644 drivers/dai/intel/ssp/ssp_regs_v3.h diff --git a/drivers/dai/intel/ssp/ssp.c b/drivers/dai/intel/ssp/ssp.c index 215f9912d57740..a7e83f7a07f9eb 100644 --- a/drivers/dai/intel/ssp/ssp.c +++ b/drivers/dai/intel/ssp/ssp.c @@ -74,11 +74,11 @@ static struct dai_intel_ssp_mn ssp_mn_divider = { .irq = DT_NUM_IRQS(node_id), \ .irq_name = irq_name_level5_z, \ .fifo[DAI_DIR_PLAYBACK].offset = \ - DT_REG_ADDR_BY_IDX(node_id, 0) + SSDR, \ + DT_REG_ADDR_BY_IDX(node_id, 0) + OUT_FIFO, \ .fifo[DAI_DIR_PLAYBACK].handshake = \ DT_DMAS_CELL_BY_NAME(node_id, tx, channel), \ .fifo[DAI_DIR_CAPTURE].offset = \ - DT_REG_ADDR_BY_IDX(node_id, 0) + SSDR, \ + DT_REG_ADDR_BY_IDX(node_id, 0) + IN_FIFO, \ .fifo[DAI_DIR_CAPTURE].handshake = \ DT_DMAS_CELL_BY_NAME(node_id, rx, channel), \ .mn_inst = &ssp_mn_divider, \ @@ -817,7 +817,7 @@ static void dai_ssp_pm_runtime_en_ssp_power(struct dai_intel_ssp *dp, uint32_t s ret = dai_ssp_poll_for_register_delay(dai_ip_base(dp) + I2SLCTL_OFFSET, I2SLCTL_CPA(ssp_index), I2SLCTL_CPA(ssp_index), DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); -#elif CONFIG_SOC_INTEL_ACE20_LNL +#elif CONFIG_SOC_INTEL_ACE20_LNL || CONFIG_SOC_INTEL_ACE30_PTL sys_write32(sys_read32(dai_hdamlssp_base(dp) + I2SLCTL_OFFSET) | I2SLCTL_SPA(ssp_index), dai_hdamlssp_base(dp) + I2SLCTL_OFFSET); @@ -851,7 +851,8 @@ static void dai_ssp_pm_runtime_dis_ssp_power(struct dai_intel_ssp *dp, uint32_t ret = dai_ssp_poll_for_register_delay(dai_ip_base(dp) + I2SLCTL_OFFSET, I2SLCTL_CPA(ssp_index), 0, DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); -#elif CONFIG_SOC_INTEL_ACE20_LNL + +#elif CONFIG_SOC_INTEL_ACE20_LNL || CONFIG_SOC_INTEL_ACE30_PTL sys_write32(sys_read32(dai_hdamlssp_base(dp) + I2SLCTL_OFFSET) & (~I2SLCTL_SPA(ssp_index)), dai_hdamlssp_base(dp) + I2SLCTL_OFFSET); @@ -874,7 +875,7 @@ static void dai_ssp_pm_runtime_dis_ssp_power(struct dai_intel_ssp *dp, uint32_t static void dai_ssp_program_channel_map(struct dai_intel_ssp *dp, const struct dai_config *cfg, uint32_t ssp_index) { -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) uint16_t pcmsycm = cfg->link_config; /* Set upper slot number from configuration */ pcmsycm = pcmsycm | (dp->ssp_plat_data->params.tdm_slots - 1) << 4; @@ -905,11 +906,21 @@ static void dai_ssp_empty_tx_fifo(struct dai_intel_ssp *dp) * SSSR_TNF is cleared when TX FIFO is empty or full, * so wait for set TNF then for TFL zero - order matter. */ +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + ret = dai_ssp_poll_for_register_delay(dai_base(dp) + SSMODyCS(0), + SSMODyCS_TNF, SSMODyCS_TNF, + DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); + + ret |= dai_ssp_poll_for_register_delay(dai_base(dp) + SSMODyCS(0), SSMODyCS_TFL, 0, + DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE * + (DAI_INTEL_SSP_FIFO_DEPTH - 1) / 2); +#else ret = dai_ssp_poll_for_register_delay(dai_base(dp) + SSSR, SSSR_TNF, SSSR_TNF, DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); ret |= dai_ssp_poll_for_register_delay(dai_base(dp) + SSCR3, SSCR3_TFL_MASK, 0, DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE * (DAI_INTEL_SSP_FIFO_DEPTH - 1) / 2); +#endif if (ret) { LOG_WRN("timeout"); @@ -923,6 +934,81 @@ static void dai_ssp_empty_tx_fifo(struct dai_intel_ssp *dp) } } +#ifdef CONFIG_SOC_INTEL_ACE30_PTL +static void ssp_empty_rx_fifo_on_start(struct dai_intel_ssp *dp) +{ + uint32_t retry = DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX; + uint32_t i, sssr; + + sssr = sys_read32(dai_base(dp) + SSSR); + + if (sssr & SSSR_ROR) { + /* The RX FIFO is in overflow condition, empty it */ + for (i = 0; i < DAI_INTEL_SSP_FIFO_DEPTH; i++) + sys_read32(dai_base(dp) + SSMIDyD(0)); + + /* Clear the overflow status */ + dai_ssp_update_bits(dp, SSSR, SSSR_ROR, SSSR_ROR); + /* Re-read the SSSR register */ + sssr = sys_read32(dai_base(dp) + SSSR); + } + + while ((sys_read32(dai_base(dp) + SSMIDyCS(0)) & SSMIDyCS_RNE) && retry--) { + uint32_t entries = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(0))); + + /* Empty the RX FIFO (the DMA is not running at this point) */ + for (i = 0; i < entries + 1; i++) + sys_read32(dai_base(dp) + SSMIDyD(0)); + + sssr = sys_read32(dai_base(dp) + SSSR); + } +} + +static void ssp_empty_rx_fifo_on_stop(struct dai_intel_ssp *dp) +{ + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); + uint64_t sample_ticks = ssp_plat_data->params.fsync_rate ? + 1000000 / ssp_plat_data->params.fsync_rate : 0; + + uint32_t retry = DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX; + uint32_t i, sssr, ssmidycs; + uint32_t entries[2]; + + sssr = sys_read32(dai_base(dp) + SSSR); + entries[0] = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(0))); + + while ((sys_read32(dai_base(dp) + SSMIDyCS(0)) & SSMIDyCS_RNE) && retry--) { + /* Wait one sample time */ + k_busy_wait(sample_ticks); + + entries[1] = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(0))); + sssr = sys_read32(dai_base(dp) + SSSR); + ssmidycs = sys_read32(dai_base(dp) + SSMIDyCS(0)); + + if (entries[0] > entries[1]) { + /* + * The DMA is reading the FIFO, check the status in the + * next loop + */ + entries[0] = entries[1]; + } else if (!(ssmidycs & SSMIDyCS_RFS)) { + /* + * The DMA request is not asserted, read the FIFO + * directly, otherwise let the next loop iteration to + * check the status + */ + for (i = 0; i < entries[1] + 1; i++) + sys_read32(dai_base(dp) + SSMIDyD(0)); + } + + sssr = sys_read32(dai_base(dp) + SSSR); + } + + /* Just in case clear the overflow status */ + dai_ssp_update_bits(dp, SSSR, SSSR_ROR, SSSR_ROR); +} + +#else static void ssp_empty_rx_fifo_on_start(struct dai_intel_ssp *dp) { uint32_t retry = DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX; @@ -994,21 +1080,20 @@ static void ssp_empty_rx_fifo_on_stop(struct dai_intel_ssp *dp) dai_ssp_update_bits(dp, SSSR, SSSR_ROR, SSSR_ROR); } +#endif + static int dai_ssp_mclk_prepare_enable(struct dai_intel_ssp *dp) { struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); - int ret = 0; + int ret; if (ssp_plat_data->clk_active & SSP_CLK_MCLK_ACTIVE) { return 0; } /* MCLK config */ - if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { - ret = dai_ssp_mn_set_mclk(dp, ssp_plat_data->params.mclk_id, - ssp_plat_data->params.mclk_rate); - } - + ret = dai_ssp_mn_set_mclk(dp, ssp_plat_data->params.mclk_id, + ssp_plat_data->params.mclk_rate); if (ret < 0) { LOG_ERR("invalid mclk_rate = %d for mclk_id = %d", ssp_plat_data->params.mclk_rate, ssp_plat_data->params.mclk_id); @@ -1027,9 +1112,7 @@ static void dai_ssp_mclk_disable_unprepare(struct dai_intel_ssp *dp) return; } - if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { - dai_ssp_mn_release_mclk(dp, ssp_plat_data->params.mclk_id); - } + dai_ssp_mn_release_mclk(dp, ssp_plat_data->params.mclk_id); ssp_plat_data->clk_active &= ~SSP_CLK_MCLK_ACTIVE; } @@ -1049,10 +1132,6 @@ static int dai_ssp_bclk_prepare_enable(struct dai_intel_ssp *dp) return 0; } - if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_IS_NEEDED)) { - goto out; - } - sscr0 = sys_read32(dai_base(dp) + SSCR0); #if CONFIG_INTEL_MN @@ -1075,9 +1154,11 @@ static int dai_ssp_bclk_prepare_enable(struct dai_intel_ssp *dp) mdiv = ft[DAI_INTEL_SSP_DEFAULT_IDX].freq / ssp_plat_data->params.bclk_rate; #endif +#ifndef CONFIG_SOC_INTEL_ACE30_PTL if (need_ecs) { sscr0 |= SSCR0_ECS; } +#endif /* clock divisor is SCR + 1 */ mdiv -= 1; @@ -1112,9 +1193,7 @@ static void dai_ssp_bclk_disable_unprepare(struct dai_intel_ssp *dp) return; } #if CONFIG_INTEL_MN - if (ssp_plat_data->clk_active & SSP_CLK_BCLK_IS_NEEDED) { - dai_ssp_mn_release_bclk(dp, ssp_plat_data->ssp_index); - } + dai_ssp_mn_release_bclk(dp, ssp_plat_data->ssp_index); #endif ssp_plat_data->clk_active &= ~SSP_CLK_BCLK_ACTIVE; } @@ -1237,19 +1316,16 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR; break; case DAI_INTEL_IPC3_SSP_FMT_CBC_CFC: - ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED | SSP_CLK_BCLK_IS_NEEDED; sscr1 |= SSCR1_SCFR; cfs = true; break; case DAI_INTEL_IPC3_SSP_FMT_CBP_CFC: - ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED; sscr1 |= SSCR1_SCLKDIR; /* FIXME: this mode has not been tested */ cfs = true; break; case DAI_INTEL_IPC3_SSP_FMT_CBC_CFP: - ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED | SSP_CLK_BCLK_IS_NEEDED; sscr1 |= SSCR1_SCFR | SSCR1_SFRMDIR; /* FIXME: this mode has not been tested */ break; @@ -1611,8 +1687,13 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co sys_write32(sspsp2, dai_base(dp) + SSPSP2); sys_write32(ssioc, dai_base(dp) + SSIOC); sys_write32(ssto, dai_base(dp) + SSTO); +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + sys_write64((uint64_t)sstsa, dai_base(dp) + SSMODyTSA(0)); + sys_write64((uint64_t)ssrsa, dai_base(dp) + SSMIDyTSA(0)); +#else sys_write32(sstsa, dai_base(dp) + SSTSA); sys_write32(ssrsa, dai_base(dp) + SSRSA); +#endif LOG_INF("sscr0 = 0x%08x, sscr1 = 0x%08x, ssto = 0x%08x, sspsp = 0x%0x", sscr0, sscr1, ssto, sspsp); @@ -1825,7 +1906,7 @@ static int dai_ssp_parse_aux_data(struct dai_intel_ssp *dp, const void *spec_con sys_write32(sys_read32(dai_ip_base(dp) + I2SLCTL_OFFSET) | I2CLCTL_MLCS(link->clock_source), dai_ip_base(dp) + I2SLCTL_OFFSET); -#elif CONFIG_SOC_INTEL_ACE20_LNL +#elif CONFIG_SOC_INTEL_ACE20_LNL || CONFIG_SOC_INTEL_ACE30_PTL sys_write32(sys_read32(dai_i2svss_base(dp) + I2SLCTL_OFFSET) | I2CLCTL_MLCS(link->clock_source), dai_i2svss_base(dp) + I2SLCTL_OFFSET); @@ -1876,14 +1957,20 @@ static int dai_ssp_set_clock_control_ver_1(struct dai_intel_ssp *dp, static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_config *cfg, const struct dai_intel_ipc4_ssp_config *regs) { - uint32_t ssc0, sstsa, ssrsa, sscr1; + uint32_t ssc0, sstsa, ssrsa; + uint32_t sscr1 = regs->ssc1; +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + sscr1 = regs->ssc1 & ~(SSCR1_RSVD21); +#else + sscr1 = regs->ssc1 & ~(SSCR1_RSRE | SSCR1_TSRE); +#endif ssc0 = regs->ssc0; sstsa = SSTSA_GET(regs->sstsa); ssrsa = SSRSA_GET(regs->ssrsa); - sscr1 = regs->ssc1 & ~(SSCR1_RSRE | SSCR1_TSRE); LOG_INF("SSP%d configuration:", dp->dai_index); +#ifndef CONFIG_SOC_INTEL_ACE30_PTL if (regs->sstsa & SSTSA_TXEN || regs->ssrsa & SSRSA_RXEN || regs->ssc1 & (SSCR1_RSRE | SSCR1_TSRE)) { LOG_INF(" Ignoring %s%s%s%sfrom blob", @@ -1892,6 +1979,7 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co regs->ssc1 & SSCR1_TSRE ? "SSCR1:TSRE " : "", regs->ssc1 & SSCR1_RSRE ? "SSCR1:RSRE " : ""); } +#endif sys_write32(ssc0, dai_base(dp) + SSCR0); sys_write32(regs->ssc2 & ~SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ @@ -1903,8 +1991,13 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co sys_write32(regs->sspsp2, dai_base(dp) + SSPSP2); sys_write32(regs->ssioc, dai_base(dp) + SSIOC); sys_write32(regs->sscto, dai_base(dp) + SSTO); +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + sys_write64((uint64_t)sstsa, dai_base(dp) + SSMODyTSA(0)); + sys_write64((uint64_t)ssrsa, dai_base(dp) + SSMIDyTSA(0)); +#else sys_write32(sstsa, dai_base(dp) + SSTSA); sys_write32(ssrsa, dai_base(dp) + SSRSA); +#endif LOG_INF(" sscr0 = 0x%08x, sscr1 = 0x%08x, ssto = 0x%08x, sspsp = 0x%0x", ssc0, sscr1, regs->sscto, regs->sspsp); @@ -1923,15 +2016,6 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co dp->ssp_plat_data->params.rx_slots = SSRSA_GET(ssrsa); dp->ssp_plat_data->params.fsync_rate = cfg->rate; - /* MCLK is needed if SSP is FS and/or BCLK provider */ - if (!(regs->ssc1 & (SSCR1_SCLKDIR | SSCR1_SFRMDIR))) { - dp->ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED; - /* BCLK is only needed if SSP is BCLK provider */ - if (!(regs->ssc1 & SSCR1_SCLKDIR)) { - dp->ssp_plat_data->clk_active |= SSP_CLK_BCLK_IS_NEEDED; - } - } - dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; } @@ -1956,19 +2040,14 @@ static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_co if (err) return err; dai_ssp_set_reg_config(dp, cfg, &blob15->i2s_ssp_config); - if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { - err = dai_ssp_set_clock_control_ver_1_5(dp, &blob15->i2s_mclk_control); - if (err) - return err; - } + err = dai_ssp_set_clock_control_ver_1_5(dp, &blob15->i2s_mclk_control); + if (err) + return err; } else { dai_ssp_set_reg_config(dp, cfg, &blob->i2s_driver_config.i2s_config); - if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { - err = dai_ssp_set_clock_control_ver_1(dp, - &blob->i2s_driver_config.mclk_config); - if (err) - return err; - } + err = dai_ssp_set_clock_control_ver_1(dp, &blob->i2s_driver_config.mclk_config); + if (err) + return err; } ssp_plat_data->clk_active |= SSP_CLK_MCLK_ES_REQ; @@ -2070,6 +2149,15 @@ static void dai_ssp_start(struct dai_intel_ssp *dp, int direction) /* enable DMA */ +#if CONFIG_SOC_INTEL_ACE30_PTL + if (direction == DAI_DIR_PLAYBACK) { + dai_ssp_update_bits(dp, SSMODyCS(0), SSMODyCS_TSRE, SSMODyCS_TSRE); + dai_ssp_update_bits(dp, SSMODyCS(0), SSMODyCS_TXEN, SSMODyCS_TXEN); + } else { + dai_ssp_update_bits(dp, SSMIDyCS(0), SSMIDyCS_RSRE, SSMIDyCS_RSRE); + dai_ssp_update_bits(dp, SSMIDyCS(0), SSMIDyCS_RXEN, SSMIDyCS_RXEN); + } +#else if (direction == DAI_DIR_PLAYBACK) { LOG_INF("SSP%d TX", dp->dai_index); dai_ssp_update_bits(dp, SSCR1, SSCR1_TSRE, SSCR1_TSRE); @@ -2079,6 +2167,7 @@ static void dai_ssp_start(struct dai_intel_ssp *dp, int direction) dai_ssp_update_bits(dp, SSCR1, SSCR1_RSRE, SSCR1_RSRE); dai_ssp_update_bits(dp, SSRSA, SSRSA_RXEN, SSRSA_RXEN); } +#endif dp->state[direction] = DAI_STATE_RUNNING; ssp_acquire_port(dp->ssp_plat_data); @@ -2128,8 +2217,13 @@ static void dai_ssp_stop(struct dai_intel_ssp *dp, int direction) if (direction == DAI_DIR_CAPTURE && dp->state[DAI_DIR_CAPTURE] != DAI_STATE_PRE_RUNNING) { LOG_INF("SSP%d RX", dp->dai_index); +#if CONFIG_SOC_INTEL_ACE30_PTL + dai_ssp_update_bits(dp, SSMIDyCS(0), SSMIDyCS_RXEN, 0); + dai_ssp_update_bits(dp, SSMIDyCS(0), SSMIDyCS_RSRE, 0); +#else dai_ssp_update_bits(dp, SSRSA, SSRSA_RXEN, 0); dai_ssp_update_bits(dp, SSCR1, SSCR1_RSRE, 0); +#endif ssp_empty_rx_fifo_on_stop(dp); dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; ssp_release_port(ssp_plat_data); @@ -2139,9 +2233,15 @@ static void dai_ssp_stop(struct dai_intel_ssp *dp, int direction) if (direction == DAI_DIR_PLAYBACK && dp->state[DAI_DIR_PLAYBACK] != DAI_STATE_PRE_RUNNING) { LOG_INF("SSP%d TX", dp->dai_index); +#if CONFIG_SOC_INTEL_ACE30_PTL + dai_ssp_update_bits(dp, SSMODyCS(0), SSMODyCS_TSRE, 0); + dai_ssp_empty_tx_fifo(dp); + dai_ssp_update_bits(dp, SSMODyCS(0), SSMODyCS_TXEN, 0); +#else dai_ssp_update_bits(dp, SSCR1, SSCR1_TSRE, 0); dai_ssp_empty_tx_fifo(dp); dai_ssp_update_bits(dp, SSTSA, SSTSA_TXEN, 0); +#endif dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; ssp_release_port(ssp_plat_data); } diff --git a/drivers/dai/intel/ssp/ssp.h b/drivers/dai/intel/ssp/ssp.h index 8c3e248a0d9b7a..877ff75e532400 100644 --- a/drivers/dai/intel/ssp/ssp.h +++ b/drivers/dai/intel/ssp/ssp.h @@ -48,234 +48,16 @@ #define DAI_INTEL_SSP_CLOCK_AUDIO_CARDINAL 0x1 #define DAI_INTEL_SSP_CLOCK_PLL_FIXED 0x2 -/* SSP register offsets */ -#define SSCR0 0x00 -#define SSCR1 0x04 -#define SSSR 0x08 -#define SSITR 0x0C -#define SSDR 0x10 -#define SSTO 0x28 -#define SSPSP 0x2C -#define SSTSA 0x30 -#define SSRSA 0x34 -#define SSTSS 0x38 -#define SSCR2 0x40 - -/* SSCR0 bits */ -#define SSCR0_DSIZE(x) DAI_INTEL_SSP_SET_BITS(3, 0, (x) - 1) -#define SSCR0_DSIZE_GET(x) (((x) & DAI_INTEL_SSP_MASK(3, 0)) + 1) -#define SSCR0_FRF DAI_INTEL_SSP_MASK(5, 4) -#define SSCR0_MOT DAI_INTEL_SSP_SET_BITS(5, 4, 0) -#define SSCR0_TI DAI_INTEL_SSP_SET_BITS(5, 4, 1) -#define SSCR0_NAT DAI_INTEL_SSP_SET_BITS(5, 4, 2) -#define SSCR0_PSP DAI_INTEL_SSP_SET_BITS(5, 4, 3) -#define SSCR0_ECS BIT(6) -#define SSCR0_SSE BIT(7) -#define SSCR0_SCR_MASK DAI_INTEL_SSP_MASK(19, 8) -#define SSCR0_SCR(x) DAI_INTEL_SSP_SET_BITS(19, 8, x) -#define SSCR0_EDSS BIT(20) -#define SSCR0_NCS BIT(21) -#define SSCR0_RIM BIT(22) -#define SSCR0_TIM BIT(23) -#define SSCR0_FRDC(x) DAI_INTEL_SSP_SET_BITS(26, 24, (x) - 1) -#define SSCR0_FRDC_GET(x) ((((x) & DAI_INTEL_SSP_MASK(26, 24)) >> 24) + 1) -#define SSCR0_ACS BIT(30) -#define SSCR0_MOD BIT(31) - -/* SSCR1 bits */ -#define SSCR1_RIE BIT(0) -#define SSCR1_TIE BIT(1) -#define SSCR1_LBM BIT(2) -#define SSCR1_SPO BIT(3) -#define SSCR1_SPH BIT(4) -#define SSCR1_MWDS BIT(5) -#define SSCR1_TFT_MASK DAI_INTEL_SSP_MASK(9, 6) -#define SSCR1_TFT(x) DAI_INTEL_SSP_SET_BITS(9, 6, (x) - 1) -#define SSCR1_RFT_MASK DAI_INTEL_SSP_MASK(13, 10) -#define SSCR1_RFT(x) DAI_INTEL_SSP_SET_BITS(13, 10, (x) - 1) -#define SSCR1_EFWR BIT(14) -#define SSCR1_STRF BIT(15) -#define SSCR1_IFS BIT(16) -#define SSCR1_PINTE BIT(18) -#define SSCR1_TINTE BIT(19) -#define SSCR1_RSRE BIT(20) -#define SSCR1_TSRE BIT(21) -#define SSCR1_TRAIL BIT(22) -#define SSCR1_RWOT BIT(23) -#define SSCR1_SFRMDIR BIT(24) -#define SSCR1_SCLKDIR BIT(25) -#define SSCR1_ECRB BIT(26) -#define SSCR1_ECRA BIT(27) -#define SSCR1_SCFR BIT(28) -#define SSCR1_EBCEI BIT(29) -#define SSCR1_TTE BIT(30) -#define SSCR1_TTELP BIT(31) - -#define SSCR2_TURM1 BIT(1) -#define SSCR2_PSPSRWFDFD BIT(3) -#define SSCR2_PSPSTWFDFD BIT(4) -#define SSCR2_SDFD BIT(14) -#define SSCR2_SDPM BIT(16) -#define SSCR2_LJDFD BIT(17) -#define SSCR2_MMRATF BIT(18) -#define SSCR2_SMTATF BIT(19) -#define SSCR2_SFRMEN BIT(20) -#define SSCR2_ACIOLBS BIT(21) - -/* SSR bits */ -#define SSSR_TNF BIT(2) -#define SSSR_RNE BIT(3) -#define SSSR_BSY BIT(4) -#define SSSR_TFS BIT(5) -#define SSSR_RFS BIT(6) -#define SSSR_ROR BIT(7) -#define SSSR_TUR BIT(21) - -/* SSPSP bits */ -#define SSPSP_SCMODE(x) DAI_INTEL_SSP_SET_BITS(1, 0, x) -#define SSPSP_SFRMP(x) DAI_INTEL_SSP_SET_BIT(2, x) -#define SSPSP_ETDS BIT(3) -#define SSPSP_STRTDLY(x) DAI_INTEL_SSP_SET_BITS(6, 4, x) -#define SSPSP_DMYSTRT(x) DAI_INTEL_SSP_SET_BITS(8, 7, x) -#define SSPSP_SFRMDLY(x) DAI_INTEL_SSP_SET_BITS(15, 9, x) -#define SSPSP_SFRMWDTH(x) DAI_INTEL_SSP_SET_BITS(21, 16, x) -#define SSPSP_DMYSTOP(x) DAI_INTEL_SSP_SET_BITS(24, 23, x) -#define SSPSP_DMYSTOP_BITS 2 -#define SSPSP_DMYSTOP_MASK DAI_INTEL_SSP_MASK(SSPSP_DMYSTOP_BITS - 1, 0) -#define SSPSP_FSRT BIT(25) -#define SSPSP_EDMYSTOP(x) DAI_INTEL_SSP_SET_BITS(28, 26, x) - -#define SSPSP2 0x44 -#define SSPSP2_FEP_MASK 0xff - -#define SSCR3 0x48 -#define SSIOC 0x4C -#define SSP_REG_MAX SSIOC - -/* SSTSA bits */ -#define SSTSA_SSTSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) -#define SSTSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) -#define SSTSA_TXEN BIT(8) - -/* SSRSA bits */ -#define SSRSA_SSRSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) -#define SSRSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) -#define SSRSA_RXEN BIT(8) - -/* SSCR3 bits */ -#define SSCR3_FRM_MST_EN BIT(0) -#define SSCR3_I2S_MODE_EN BIT(1) -#define SSCR3_I2S_FRM_POL(x) DAI_INTEL_SSP_SET_BIT(2, x) -#define SSCR3_I2S_TX_SS_FIX_EN BIT(3) -#define SSCR3_I2S_RX_SS_FIX_EN BIT(4) -#define SSCR3_I2S_TX_EN BIT(9) -#define SSCR3_I2S_RX_EN BIT(10) -#define SSCR3_CLK_EDGE_SEL BIT(12) -#define SSCR3_STRETCH_TX BIT(14) -#define SSCR3_STRETCH_RX BIT(15) -#define SSCR3_MST_CLK_EN BIT(16) -#define SSCR3_SYN_FIX_EN BIT(17) - -/* SSCR4 bits */ -#define SSCR4_TOT_FRM_PRD(x) ((x) << 7) - -/* SSCR5 bits */ -#define SSCR5_FRM_ASRT_CLOCKS(x) (((x) - 1) << 1) -#define SSCR5_FRM_POLARITY(x) DAI_INTEL_SSP_SET_BIT(0, x) - -/* SFIFOTT bits */ -#define SFIFOTT_TX(x) ((x) - 1) -#define SFIFOTT_RX(x) (((x) - 1) << 16) - -/* SFIFOL bits */ -#define SFIFOL_TFL(x) ((x) & 0xFFFF) -#define SFIFOL_RFL(x) ((x) >> 16) - -#define SSTSA_TSEN BIT(8) -#define SSRSA_RSEN BIT(8) - -#define SSCR3_TFL_MASK DAI_INTEL_SSP_MASK(5, 0) -#define SSCR3_RFL_MASK DAI_INTEL_SSP_MASK(13, 8) -#define SSCR3_TFL_VAL(scr3_val) (((scr3_val) >> 0) & DAI_INTEL_SSP_MASK(5, 0)) -#define SSCR3_RFL_VAL(scr3_val) (((scr3_val) >> 8) & DAI_INTEL_SSP_MASK(5, 0)) -#define SSCR3_TX(x) DAI_INTEL_SSP_SET_BITS(21, 16, (x) - 1) -#define SSCR3_RX(x) DAI_INTEL_SSP_SET_BITS(29, 24, (x) - 1) - -#define SSIOC_TXDPDEB BIT(1) -#define SSIOC_SFCR BIT(4) -#define SSIOC_SCOE BIT(5) - -/* For 8000 Hz rate one sample is transmitted within 125us */ -#define DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE 125 - -/* SSP flush retry counts maximum */ -#define DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX 16 - -#define SSP_CLK_MCLK_IS_NEEDED BIT(0) -#define SSP_CLK_MCLK_ES_REQ BIT(1) -#define SSP_CLK_MCLK_ACTIVE BIT(2) -#define SSP_CLK_BCLK_IS_NEEDED BIT(3) -#define SSP_CLK_BCLK_ES_REQ BIT(4) -#define SSP_CLK_BCLK_ACTIVE BIT(5) - -#define I2SLCTL_OFFSET 0x04 - #if defined(CONFIG_SOC_INTEL_ACE15_MTPM) || defined(CONFIG_SOC_SERIES_INTEL_ADSP_CAVS) -#define I2SLCTL_SPA(x) BIT(0 + x) -#define I2SLCTL_CPA(x) BIT(8 + x) +#include "ssp_regs_v1.h" #elif defined(CONFIG_SOC_INTEL_ACE20_LNL) -#define I2SLCTL_OFLEN BIT(4) -#define I2SLCTL_SPA(x) BIT(16 + x) -#define I2SLCTL_CPA(x) BIT(23 + x) -#define PCMS0CM_OFFSET 0x16 -#define PCMS1CM_OFFSET 0x1A +#include "ssp_regs_v2.h" +#elif defined(CONFIG_SOC_INTEL_ACE30_PTL) +#include "ssp_regs_v3.h" #else #error "Missing ssp definitions" #endif -#define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x) -#define SHIM_CLKCTL 0x78 -#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x) -#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x) - -#ifdef CONFIG_SOC_SERIES_INTEL_ADSP_ACE -/** \brief Offset of MCLK Divider Control Register. */ -#define MN_MDIVCTRL 0x100 - -/** \brief Offset of MCLK Divider x Ratio Register. */ -#define MN_MDIVR(x) (0x180 + (x) * 0x4) - -/** \brief Enables the output of MCLK Divider. - * On ACE+ there is a single divider for all MCLKs - */ -#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(0) - -#else -#define MN_MDIVCTRL 0x0 -#define MN_MDIVR(x) (0x80 + (x) * 0x4) - -/** \brief Enables the output of MCLK Divider. - * Each MCLK divider can be enabled separately. - */ -#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x) - -#endif - -/** \brief Bits for setting MCLK source clock. */ -#define MCDSS(x) DAI_INTEL_SSP_SET_BITS(17, 16, x) - -/** \brief Offset of BCLK x M/N Divider M Value Register. */ -#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0) - -/** \brief Offset of BCLK x M/N Divider N Value Register. */ -#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4) - -/** \brief Bits for setting M/N source clock. */ -#define MNDSS(x) DAI_INTEL_SSP_SET_BITS(21, 20, x) - -/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */ -#define MN_SOURCE_CLKS_MASK 0x3 - #if CONFIG_INTEL_MN /** \brief BCLKs can be driven by multiple sources - M/N or XTAL directly. * Even in the case of M/N, the actual clock source can be XTAL, @@ -334,7 +116,7 @@ struct dai_intel_ssp_plat_data { uint32_t base; uint32_t ip_base; uint32_t shim_base; -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) uint32_t hdamlssp_base; uint32_t i2svss_base; #endif diff --git a/drivers/dai/intel/ssp/ssp_regs_v1.h b/drivers/dai/intel/ssp/ssp_regs_v1.h new file mode 100644 index 00000000000000..a821ab8733a63e --- /dev/null +++ b/drivers/dai/intel/ssp/ssp_regs_v1.h @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2022 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __INTEL_DAI_DRIVER_SSP_REGSV1_H__ +#define __INTEL_DAI_DRIVER_SSP_REGSV1_H__ + +/* SSP register offsets */ +#define SSCR0 0x00 +#define SSCR1 0x04 +#define SSSR 0x08 +#define SSITR 0x0C +#define SSTO 0x28 +#define SSPSP 0x2C +#define SSTSS 0x38 +#define SSCR2 0x40 +#define SSPSP2 0x44 +#define SSIOC 0x4C +#define SSGFS 0x50 +#define SSDR 0x10 /* Not PTL */ +#define SSTSA 0x30 /* Not PTL */ +#define SSRSA 0x34 /* Not PTL */ + +#define OUT_FIFO SSDR +#define IN_FIFO SSDR + +/* SSCR0 bits */ +#define SSCR0_DSIZE(x) DAI_INTEL_SSP_SET_BITS(3, 0, (x) - 1) +#define SSCR0_DSIZE_GET(x) (((x) & DAI_INTEL_SSP_MASK(3, 0)) + 1) +#define SSCR0_FRF DAI_INTEL_SSP_MASK(5, 4) +#define SSCR0_MOT DAI_INTEL_SSP_SET_BITS(5, 4, 0) +#define SSCR0_TI DAI_INTEL_SSP_SET_BITS(5, 4, 1) +#define SSCR0_NAT DAI_INTEL_SSP_SET_BITS(5, 4, 2) +#define SSCR0_PSP DAI_INTEL_SSP_SET_BITS(5, 4, 3) +#define SSCR0_ECS BIT(6) +#define SSCR0_SSE BIT(7) +#define SSCR0_SCR_MASK DAI_INTEL_SSP_MASK(19, 8) +#define SSCR0_SCR(x) DAI_INTEL_SSP_SET_BITS(19, 8, x) +#define SSCR0_EDSS BIT(20) +#define SSCR0_NCS BIT(21) +#define SSCR0_RIM BIT(22) +#define SSCR0_TIM BIT(23) +#define SSCR0_FRDC(x) DAI_INTEL_SSP_SET_BITS(26, 24, (x) - 1) +#define SSCR0_FRDC_GET(x) ((((x) & DAI_INTEL_SSP_MASK(26, 24)) >> 24) + 1) +#define SSCR0_ACS BIT(30) +#define SSCR0_MOD BIT(31) + +/* SSCR1 bits */ +#define SSCR1_RIE BIT(0) +#define SSCR1_TIE BIT(1) +#define SSCR1_LBM BIT(2) +#define SSCR1_SPO BIT(3) +#define SSCR1_SPH BIT(4) +#define SSCR1_MWDS BIT(5) +#define SSCR1_TFT_MASK DAI_INTEL_SSP_MASK(9, 6) +#define SSCR1_TFT(x) DAI_INTEL_SSP_SET_BITS(9, 6, (x) - 1) +#define SSCR1_RFT_MASK DAI_INTEL_SSP_MASK(13, 10) +#define SSCR1_RFT(x) DAI_INTEL_SSP_SET_BITS(13, 10, (x) - 1) +#define SSCR1_EFWR BIT(14) +#define SSCR1_STRF BIT(15) +#define SSCR1_IFS BIT(16) +#define SSCR1_PINTE BIT(18) +#define SSCR1_TINTE BIT(19) +#define SSCR1_RSRE BIT(20) +#define SSCR1_TSRE BIT(21) +#define SSCR1_TRAIL BIT(22) +#define SSCR1_RWOT BIT(23) +#define SSCR1_SFRMDIR BIT(24) +#define SSCR1_SCLKDIR BIT(25) +#define SSCR1_ECRB BIT(26) +#define SSCR1_ECRA BIT(27) +#define SSCR1_SCFR BIT(28) +#define SSCR1_EBCEI BIT(29) +#define SSCR1_TTE BIT(30) +#define SSCR1_TTELP BIT(31) + +#define SSCR2_TURM1 BIT(1) +#define SSCR2_PSPSRWFDFD BIT(3) +#define SSCR2_PSPSTWFDFD BIT(4) +#define SSCR2_SDFD BIT(14) +#define SSCR2_SDPM BIT(16) +#define SSCR2_LJDFD BIT(17) +#define SSCR2_MMRATF BIT(18) +#define SSCR2_SMTATF BIT(19) +#define SSCR2_SFRMEN BIT(20) +#define SSCR2_ACIOLBS BIT(21) + +/* SSR bits */ +#define SSSR_TNF BIT(2) +#define SSSR_RNE BIT(3) +#define SSSR_BSY BIT(4) +#define SSSR_TFS BIT(5) +#define SSSR_RFS BIT(6) +#define SSSR_ROR BIT(7) +#define SSSR_TUR BIT(21) + +/* SSPSP bits */ +#define SSPSP_SCMODE(x) DAI_INTEL_SSP_SET_BITS(1, 0, x) +#define SSPSP_SFRMP(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSPSP_ETDS BIT(3) +#define SSPSP_STRTDLY(x) DAI_INTEL_SSP_SET_BITS(6, 4, x) +#define SSPSP_DMYSTRT(x) DAI_INTEL_SSP_SET_BITS(8, 7, x) +#define SSPSP_SFRMDLY(x) DAI_INTEL_SSP_SET_BITS(15, 9, x) +#define SSPSP_SFRMWDTH(x) DAI_INTEL_SSP_SET_BITS(21, 16, x) +#define SSPSP_DMYSTOP(x) DAI_INTEL_SSP_SET_BITS(24, 23, x) +#define SSPSP_DMYSTOP_BITS 2 +#define SSPSP_DMYSTOP_MASK DAI_INTEL_SSP_MASK(SSPSP_DMYSTOP_BITS - 1, 0) +#define SSPSP_FSRT BIT(25) +#define SSPSP_EDMYSTOP(x) DAI_INTEL_SSP_SET_BITS(28, 26, x) + +#define SSPSP2 0x44 +#define SSPSP2_FEP_MASK 0xff + +#define SSCR3 0x48 +#define SSIOC 0x4C +#define SSP_REG_MAX SSIOC + +/* SSTSA bits */ +#define SSTSA_SSTSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSTSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSTSA_TXEN BIT(8) + +/* SSRSA bits */ +#define SSRSA_SSRSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSRSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSRSA_RXEN BIT(8) + +/* SSCR3 bits */ +#define SSCR3_FRM_MST_EN BIT(0) +#define SSCR3_I2S_MODE_EN BIT(1) +#define SSCR3_I2S_FRM_POL(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSCR3_I2S_TX_SS_FIX_EN BIT(3) +#define SSCR3_I2S_RX_SS_FIX_EN BIT(4) +#define SSCR3_I2S_TX_EN BIT(9) +#define SSCR3_I2S_RX_EN BIT(10) +#define SSCR3_CLK_EDGE_SEL BIT(12) +#define SSCR3_STRETCH_TX BIT(14) +#define SSCR3_STRETCH_RX BIT(15) +#define SSCR3_MST_CLK_EN BIT(16) +#define SSCR3_SYN_FIX_EN BIT(17) + +/* SSCR4 bits */ +#define SSCR4_TOT_FRM_PRD(x) ((x) << 7) + +/* SSCR5 bits */ +#define SSCR5_FRM_ASRT_CLOCKS(x) (((x) - 1) << 1) +#define SSCR5_FRM_POLARITY(x) DAI_INTEL_SSP_SET_BIT(0, x) + +/* SFIFOTT bits */ +#define SFIFOTT_TX(x) ((x) - 1) +#define SFIFOTT_RX(x) (((x) - 1) << 16) + +/* SFIFOL bits */ +#define SFIFOL_TFL(x) ((x) & 0xFFFF) +#define SFIFOL_RFL(x) ((x) >> 16) + +#define SSTSA_TSEN BIT(8) +#define SSRSA_RSEN BIT(8) + +#define SSCR3_TFL_MASK DAI_INTEL_SSP_MASK(5, 0) +#define SSCR3_RFL_MASK DAI_INTEL_SSP_MASK(13, 8) +#define SSCR3_TFL_VAL(scr3_val) (((scr3_val) >> 0) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_RFL_VAL(scr3_val) (((scr3_val) >> 8) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_TX(x) DAI_INTEL_SSP_SET_BITS(21, 16, (x) - 1) +#define SSCR3_RX(x) DAI_INTEL_SSP_SET_BITS(29, 24, (x) - 1) + +#define SSIOC_TXDPDEB BIT(1) +#define SSIOC_SFCR BIT(4) +#define SSIOC_SCOE BIT(5) + +/* SSMIDyCS */ +#define SSMIDyCS_RXEN BIT(0) +#define SSMIDyCS_RSRE BIT(1) +#define SSMIDyCS_RFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_RFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMIDyCS_RNE BIT(26) +#define SSMIDyCS_RFS BIT(27) +#define SSMIDyCS_ROR BIT(28) +#define SSMIDyCS_PINT BIT(29) +#define SSMIDyCS_TINT BIT(30) +#define SSMIDyCS_EOC BIT(31) + +/* SSMIDyTSA */ +#define SSMIDyTSA_RTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMIDyTSA_SRTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* SSMODyCS */ +#define SSMODyCS_TXEN BIT(0) +#define SSMODyCS_TSRE BIT(1) +#define SSMODyCS_TFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_TFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMODyCS_TNF BIT(26) +#define SSMODyCS_TFS BIT(27) +#define SSMODyCS_TUR BIT(28) + +/* SSMODyTSA */ +#define SSMODyTSA_TTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMODyTSA_STTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* For 8000 Hz rate one sample is transmitted within 125us */ +#define DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE 125 + +/* SSP flush retry counts maximum */ +#define DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX 16 + +#define SSP_CLK_MCLK_ES_REQ BIT(0) +#define SSP_CLK_MCLK_ACTIVE BIT(1) +#define SSP_CLK_BCLK_ES_REQ BIT(2) +#define SSP_CLK_BCLK_ACTIVE BIT(3) + +#define I2SLCTL_OFFSET 0x04 + +#define I2SLCTL_SPA(x) BIT(0 + x) +#define I2SLCTL_CPA(x) BIT(8 + x) + +#define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x) +#define SHIM_CLKCTL 0x78 +#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x) +#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x) + +#ifdef CONFIG_SOC_SERIES_INTEL_ADSP_ACE +/** \brief Offset of MCLK Divider Control Register. */ +#define MN_MDIVCTRL 0x100 + +/** \brief Offset of MCLK Divider x Ratio Register. */ +#define MN_MDIVR(x) (0x180 + (x) * 0x4) +#else +#define MN_MDIVCTRL 0x0 +#define MN_MDIVR(x) (0x80 + (x) * 0x4) +#endif + +/** \brief Enables the output of MCLK Divider. */ +#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x) + +/** \brief Bits for setting MCLK source clock. */ +#define MCDSS(x) DAI_INTEL_SSP_SET_BITS(17, 16, x) + +/** \brief Offset of BCLK x M/N Divider M Value Register. */ +#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0) + +/** \brief Offset of BCLK x M/N Divider N Value Register. */ +#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4) + +/** \brief Bits for setting M/N source clock. */ +#define MNDSS(x) DAI_INTEL_SSP_SET_BITS(21, 20, x) + +/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */ +#define MN_SOURCE_CLKS_MASK 0x3 + +#endif /* __INTEL_DAI_DRIVER_SSP_REGSV1_H__ */ diff --git a/drivers/dai/intel/ssp/ssp_regs_v2.h b/drivers/dai/intel/ssp/ssp_regs_v2.h new file mode 100644 index 00000000000000..e2d1c826d075c3 --- /dev/null +++ b/drivers/dai/intel/ssp/ssp_regs_v2.h @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2022 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __INTEL_DAI_DRIVER_SSP_REGSV2_H__ +#define __INTEL_DAI_DRIVER_SSP_REGSV2_H__ + +/* SSP register offsets */ +#define SSCR0 0x00 +#define SSCR1 0x04 +#define SSSR 0x08 +#define SSITR 0x0C +#define SSTO 0x28 +#define SSPSP 0x2C +#define SSTSS 0x38 +#define SSCR2 0x40 +#define SSPSP2 0x44 + +#define SSIOC 0x4C +#define SSGFS 0x50 +#define SSDR 0x10 /* Not PTL */ +#define SSTSA 0x30 /* Not PTL */ +#define SSRSA 0x34 /* Not PTL */ + +#define OUT_FIFO SSDR +#define IN_FIFO SSDR + +/* SSCR0 bits */ +#define SSCR0_DSIZE(x) DAI_INTEL_SSP_SET_BITS(3, 0, (x) - 1) +#define SSCR0_DSIZE_GET(x) (((x) & DAI_INTEL_SSP_MASK(3, 0)) + 1) +#define SSCR0_FRF DAI_INTEL_SSP_MASK(5, 4) +#define SSCR0_MOT DAI_INTEL_SSP_SET_BITS(5, 4, 0) +#define SSCR0_TI DAI_INTEL_SSP_SET_BITS(5, 4, 1) +#define SSCR0_NAT DAI_INTEL_SSP_SET_BITS(5, 4, 2) +#define SSCR0_PSP DAI_INTEL_SSP_SET_BITS(5, 4, 3) +#define SSCR0_ECS BIT(6) +#define SSCR0_SSE BIT(7) +#define SSCR0_SCR_MASK DAI_INTEL_SSP_MASK(19, 8) +#define SSCR0_SCR(x) DAI_INTEL_SSP_SET_BITS(19, 8, x) +#define SSCR0_EDSS BIT(20) +#define SSCR0_NCS BIT(21) +#define SSCR0_RIM BIT(22) +#define SSCR0_TIM BIT(23) +#define SSCR0_FRDC(x) DAI_INTEL_SSP_SET_BITS(26, 24, (x) - 1) +#define SSCR0_FRDC_GET(x) ((((x) & DAI_INTEL_SSP_MASK(26, 24)) >> 24) + 1) +#define SSCR0_ACS BIT(30) +#define SSCR0_MOD BIT(31) + +/* SSCR1 bits */ +#define SSCR1_RIE BIT(0) +#define SSCR1_TIE BIT(1) +#define SSCR1_LBM BIT(2) +#define SSCR1_SPO BIT(3) +#define SSCR1_SPH BIT(4) +#define SSCR1_MWDS BIT(5) +#define SSCR1_TFT_MASK DAI_INTEL_SSP_MASK(9, 6) +#define SSCR1_TFT(x) DAI_INTEL_SSP_SET_BITS(9, 6, (x) - 1) +#define SSCR1_RFT_MASK DAI_INTEL_SSP_MASK(13, 10) +#define SSCR1_RFT(x) DAI_INTEL_SSP_SET_BITS(13, 10, (x) - 1) +#define SSCR1_EFWR BIT(14) +#define SSCR1_STRF BIT(15) +#define SSCR1_IFS BIT(16) +#define SSCR1_PINTE BIT(18) +#define SSCR1_TINTE BIT(19) +#define SSCR1_RSRE BIT(20) +#define SSCR1_TSRE BIT(21) +#define SSCR1_TRAIL BIT(22) +#define SSCR1_RWOT BIT(23) +#define SSCR1_SFRMDIR BIT(24) +#define SSCR1_SCLKDIR BIT(25) +#define SSCR1_ECRB BIT(26) +#define SSCR1_ECRA BIT(27) +#define SSCR1_SCFR BIT(28) +#define SSCR1_EBCEI BIT(29) +#define SSCR1_TTE BIT(30) +#define SSCR1_TTELP BIT(31) + +#define SSCR2_TURM1 BIT(1) +#define SSCR2_PSPSRWFDFD BIT(3) +#define SSCR2_PSPSTWFDFD BIT(4) +#define SSCR2_SDFD BIT(14) +#define SSCR2_SDPM BIT(16) +#define SSCR2_LJDFD BIT(17) +#define SSCR2_MMRATF BIT(18) +#define SSCR2_SMTATF BIT(19) +#define SSCR2_SFRMEN BIT(20) +#define SSCR2_ACIOLBS BIT(21) + +/* SSR bits */ +#define SSSR_TNF BIT(2) +#define SSSR_RNE BIT(3) +#define SSSR_BSY BIT(4) +#define SSSR_TFS BIT(5) +#define SSSR_RFS BIT(6) +#define SSSR_ROR BIT(7) +#define SSSR_TUR BIT(21) + +/* SSPSP bits */ +#define SSPSP_SCMODE(x) DAI_INTEL_SSP_SET_BITS(1, 0, x) +#define SSPSP_SFRMP(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSPSP_ETDS BIT(3) +#define SSPSP_STRTDLY(x) DAI_INTEL_SSP_SET_BITS(6, 4, x) +#define SSPSP_DMYSTRT(x) DAI_INTEL_SSP_SET_BITS(8, 7, x) +#define SSPSP_SFRMDLY(x) DAI_INTEL_SSP_SET_BITS(15, 9, x) +#define SSPSP_SFRMWDTH(x) DAI_INTEL_SSP_SET_BITS(21, 16, x) +#define SSPSP_DMYSTOP(x) DAI_INTEL_SSP_SET_BITS(24, 23, x) +#define SSPSP_DMYSTOP_BITS 2 +#define SSPSP_DMYSTOP_MASK DAI_INTEL_SSP_MASK(SSPSP_DMYSTOP_BITS - 1, 0) +#define SSPSP_FSRT BIT(25) +#define SSPSP_EDMYSTOP(x) DAI_INTEL_SSP_SET_BITS(28, 26, x) + +#define SSPSP2 0x44 +#define SSPSP2_FEP_MASK 0xff + +#define SSCR3 0x48 +#define SSIOC 0x4C +#define SSP_REG_MAX SSIOC + +/* SSTSA bits */ +#define SSTSA_SSTSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSTSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSTSA_TXEN BIT(8) + +/* SSRSA bits */ +#define SSRSA_SSRSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSRSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSRSA_RXEN BIT(8) + +/* SSCR3 bits */ +#define SSCR3_FRM_MST_EN BIT(0) +#define SSCR3_I2S_MODE_EN BIT(1) +#define SSCR3_I2S_FRM_POL(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSCR3_I2S_TX_SS_FIX_EN BIT(3) +#define SSCR3_I2S_RX_SS_FIX_EN BIT(4) +#define SSCR3_I2S_TX_EN BIT(9) +#define SSCR3_I2S_RX_EN BIT(10) +#define SSCR3_CLK_EDGE_SEL BIT(12) +#define SSCR3_STRETCH_TX BIT(14) +#define SSCR3_STRETCH_RX BIT(15) +#define SSCR3_MST_CLK_EN BIT(16) +#define SSCR3_SYN_FIX_EN BIT(17) + +/* SSCR4 bits */ +#define SSCR4_TOT_FRM_PRD(x) ((x) << 7) + +/* SSCR5 bits */ +#define SSCR5_FRM_ASRT_CLOCKS(x) (((x) - 1) << 1) +#define SSCR5_FRM_POLARITY(x) DAI_INTEL_SSP_SET_BIT(0, x) + +/* SFIFOTT bits */ +#define SFIFOTT_TX(x) ((x) - 1) +#define SFIFOTT_RX(x) (((x) - 1) << 16) + +/* SFIFOL bits */ +#define SFIFOL_TFL(x) ((x) & 0xFFFF) +#define SFIFOL_RFL(x) ((x) >> 16) + +#define SSTSA_TSEN BIT(8) +#define SSRSA_RSEN BIT(8) + +#define SSCR3_TFL_MASK DAI_INTEL_SSP_MASK(5, 0) +#define SSCR3_RFL_MASK DAI_INTEL_SSP_MASK(13, 8) +#define SSCR3_TFL_VAL(scr3_val) (((scr3_val) >> 0) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_RFL_VAL(scr3_val) (((scr3_val) >> 8) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_TX(x) DAI_INTEL_SSP_SET_BITS(21, 16, (x) - 1) +#define SSCR3_RX(x) DAI_INTEL_SSP_SET_BITS(29, 24, (x) - 1) + +#define SSIOC_TXDPDEB BIT(1) +#define SSIOC_SFCR BIT(4) +#define SSIOC_SCOE BIT(5) + +/* SSMIDyCS */ +#define SSMIDyCS_RXEN BIT(0) +#define SSMIDyCS_RSRE BIT(1) +#define SSMIDyCS_RFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_RFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMIDyCS_RNE BIT(26) +#define SSMIDyCS_RFS BIT(27) +#define SSMIDyCS_ROR BIT(28) +#define SSMIDyCS_PINT BIT(29) +#define SSMIDyCS_TINT BIT(30) +#define SSMIDyCS_EOC BIT(31) + +/* SSMIDyTSA */ +#define SSMIDyTSA_RTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMIDyTSA_SRTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* SSMODyCS */ +#define SSMODyCS_TXEN BIT(0) +#define SSMODyCS_TSRE BIT(1) +#define SSMODyCS_TFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_TFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMODyCS_TNF BIT(26) +#define SSMODyCS_TFS BIT(27) +#define SSMODyCS_TUR BIT(28) + +/* SSMODyTSA */ +#define SSMODyTSA_TTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMODyTSA_STTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* For 8000 Hz rate one sample is transmitted within 125us */ +#define DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE 125 + +/* SSP flush retry counts maximum */ +#define DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX 16 + +#define SSP_CLK_MCLK_ES_REQ BIT(0) +#define SSP_CLK_MCLK_ACTIVE BIT(1) +#define SSP_CLK_BCLK_ES_REQ BIT(2) +#define SSP_CLK_BCLK_ACTIVE BIT(3) + +#define I2SLCTL_OFFSET 0x04 +#define I2SLCTL_OFLEN BIT(4) +#define I2SLCTL_SPA(x) BIT(16 + x) +#define I2SLCTL_CPA(x) BIT(23 + x) +#define PCMS0CM_OFFSET 0x16 +#define PCMS1CM_OFFSET 0x1A + +#define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x) +#define SHIM_CLKCTL 0x78 +#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x) +#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x) + +/** \brief Offset of MCLK Divider Control Register. */ +#define MN_MDIVCTRL 0x100 + +/** \brief Offset of MCLK Divider x Ratio Register. */ +#define MN_MDIVR(x) (0x180 + (x) * 0x4) + +/** \brief Enables the output of MCLK Divider. */ +#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x) + +/** \brief Bits for setting MCLK source clock. */ +#define MCDSS(x) DAI_INTEL_SSP_SET_BITS(17, 16, x) + +/** \brief Offset of BCLK x M/N Divider M Value Register. */ +#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0) + +/** \brief Offset of BCLK x M/N Divider N Value Register. */ +#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4) + +/** \brief Bits for setting M/N source clock. */ +#define MNDSS(x) DAI_INTEL_SSP_SET_BITS(21, 20, x) + +/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */ +#define MN_SOURCE_CLKS_MASK 0x3 + +#endif /* __INTEL_DAI_DRIVER_SSP_REGSV2_H__ */ diff --git a/drivers/dai/intel/ssp/ssp_regs_v3.h b/drivers/dai/intel/ssp/ssp_regs_v3.h new file mode 100644 index 00000000000000..958c3919c6051b --- /dev/null +++ b/drivers/dai/intel/ssp/ssp_regs_v3.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2022 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __INTEL_DAI_DRIVER_SSP_REGSV3_H__ +#define __INTEL_DAI_DRIVER_SSP_REGSV3_H__ + +/* SSP register offsets */ +#define SSCR0 0x00 +#define SSCR1 0x04 +#define SSSR 0x08 +#define SSITR 0x0C +#define SSTO 0x28 +#define SSPSP 0x2C +#define SSTSS 0x38 +#define SSCR2 0x40 +#define SSPSP2 0x44 + +#define SSIOC 0x4C +#define SSGFS 0x50 + +#define I2SIPCMC 8 +#define SSMIDyCS(y) 0x60 + 0x10*y +#define SSMIDyD(y) 0x64 + 0x10*y +#define SSMIDyTSA(y) 0x68 + 0x10*y +#define SSMODyCS(y) 0x60 + 0x10*I2SIPCMC + 0x10*y +#define SSMODyD(y) 0x64 + 0x10*I2SIPCMC + 0x10*y +#define SSMODyTSA(y) 0x68 + 0x10*I2SIPCMC + 0x10*y + +#define OUT_FIFO SSMODyD(0) +#define IN_FIFO SSMIDyD(0) + +/* SSCR0 bits */ +#define SSCR0_DSIZE(x) DAI_INTEL_SSP_SET_BITS(3, 0, (x) - 1) +#define SSCR0_DSIZE_GET(x) (((x) & DAI_INTEL_SSP_MASK(3, 0)) + 1) +#define SSCR0_FRF DAI_INTEL_SSP_MASK(5, 4) +#define SSCR0_MOT DAI_INTEL_SSP_SET_BITS(5, 4, 0) +#define SSCR0_TI DAI_INTEL_SSP_SET_BITS(5, 4, 1) +#define SSCR0_NAT DAI_INTEL_SSP_SET_BITS(5, 4, 2) +#define SSCR0_PSP DAI_INTEL_SSP_SET_BITS(5, 4, 3) +#define SSCR0_RSVD1 BIT(6) +#define SSCR0_SSE BIT(7) +#define SSCR0_SCR_MASK DAI_INTEL_SSP_MASK(19, 8) +#define SSCR0_SCR(x) DAI_INTEL_SSP_SET_BITS(19, 8, x) +#define SSCR0_EDSS BIT(20) +#define SSCR0_RSVD2 BIT(21) +#define SSCR0_RIM BIT(22) +#define SSCR0_TIM BIT(23) +#define SSCR0_FRDC(x) DAI_INTEL_SSP_SET_BITS(26, 24, (x) - 1) +#define SSCR0_FRDC_GET(x) ((((x) & DAI_INTEL_SSP_MASK(26, 24)) >> 24) + 1) +#define SSCR0_EFRDC BIT(27) +#define SSCR0_EFRDC2 BIT(28) +#define SSCR0_DLE DAI_INTEL_SSP_SET_BITS(30, 29, 0) +#define SSCR0_MOD BIT(31) + +/* SSCR1 bits */ +#define SSCR1_RIE BIT(0) +#define SSCR1_TIE BIT(1) +#define SSCR1_LBM BIT(2) +#define SSCR1_RSVD1 DAI_INTEL_SSP_MASK(15, 3) +#define SSCR1_IFS BIT(16) +#define SSCR1_PINTE BIT(18) +#define SSCR1_TINTE BIT(19) +#define SSCR1_RSVD21 DAI_INTEL_SSP_MASK(21, 20) +#define SSCR1_TRAIL BIT(22) +#define SSCR1_RWOT BIT(23) +#define SSCR1_SFRMDIR BIT(24) +#define SSCR1_SCLKDIR BIT(25) +#define SSCR1_SCFR BIT(28) +#define SSCR1_EBCEI BIT(29) +#define SSCR1_TTE BIT(30) +#define SSCR1_TTELP BIT(31) + +#define SSCR2_TURM1 BIT(1) +#define SSCR2_PSPSRWFDFD BIT(3) +#define SSCR2_PSPSTWFDFD BIT(4) +#define SSCR2_SDFD BIT(14) +#define SSCR2_SDPM BIT(16) +#define SSCR2_LJDFD BIT(17) +#define SSCR2_MMRATF BIT(18) +#define SSCR2_SMTATF BIT(19) +#define SSCR2_SFRMEN BIT(20) +#define SSCR2_ACIOLBS BIT(21) + +/* SSR bits */ +#define SSSR_BSY BIT(4) +#define SSSR_ROR BIT(7) +#define SSSR_TUR BIT(21) + +/* SSPSP bits */ +#define SSPSP_SCMODE(x) DAI_INTEL_SSP_SET_BITS(1, 0, x) +#define SSPSP_SFRMP(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSPSP_STRTDLY(x) DAI_INTEL_SSP_SET_BITS(6, 4, x) +#define SSPSP_DMYSTRT(x) DAI_INTEL_SSP_SET_BITS(8, 7, x) +#define SSPSP_SFRMDLY(x) DAI_INTEL_SSP_SET_BITS(15, 9, x) +#define SSPSP_SFRMWDTH(x) DAI_INTEL_SSP_SET_BITS(21, 16, x) +#define SSPSP_DMYSTOP(x) DAI_INTEL_SSP_SET_BITS(24, 23, x) +#define SSPSP_DMYSTOP_BITS 2 +#define SSPSP_DMYSTOP_MASK DAI_INTEL_SSP_MASK(SSPSP_DMYSTOP_BITS - 1, 0) +#define SSPSP_FSRT BIT(25) +#define SSPSP_EDMYSTOP(x) DAI_INTEL_SSP_SET_BITS(28, 26, x) + +#define SSPSP2 0x44 +#define SSPSP2_FEP_MASK 0xff + +#define SSPSP2_RFAC DAI_INTEL_SSP_MASK(9, 8) +#define SSPSP2_TFAC DAI_INTEL_SSP_MASK(11, 10) +#define SSPSP2_EFEP DAI_INTEL_SSP_MASK(13, 12) +#define SSPSP2_ESFRMDW DAI_INTEL_SSP_MASK(15, 14) + + +#define SSCR3 0x48 +#define SSIOC 0x4C +#define SSP_REG_MAX SSIOC + +/* SSTSA bits */ +#define SSTSA_SSTSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSTSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) + +/* SSRSA bits */ +#define SSRSA_SSRSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSRSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) + +/* SSCR3 bits */ +#define SSCR3_FRM_MST_EN BIT(0) +#define SSCR3_I2S_MODE_EN BIT(1) +#define SSCR3_I2S_FRM_POL(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSCR3_I2S_TX_SS_FIX_EN BIT(3) +#define SSCR3_I2S_RX_SS_FIX_EN BIT(4) +#define SSCR3_I2S_TX_EN BIT(9) +#define SSCR3_I2S_RX_EN BIT(10) +#define SSCR3_CLK_EDGE_SEL BIT(12) +#define SSCR3_STRETCH_TX BIT(14) +#define SSCR3_STRETCH_RX BIT(15) +#define SSCR3_MST_CLK_EN BIT(16) +#define SSCR3_SYN_FIX_EN BIT(17) + +/* SSCR4 bits */ +#define SSCR4_TOT_FRM_PRD(x) ((x) << 7) + +/* SSCR5 bits */ +#define SSCR5_FRM_ASRT_CLOCKS(x) (((x) - 1) << 1) +#define SSCR5_FRM_POLARITY(x) DAI_INTEL_SSP_SET_BIT(0, x) + +/* SFIFOTT bits */ +#define SFIFOTT_TX(x) ((x) - 1) +#define SFIFOTT_RX(x) (((x) - 1) << 16) + +/* SFIFOL bits */ +#define SFIFOL_TFL(x) ((x) & 0xFFFF) +#define SFIFOL_RFL(x) ((x) >> 16) + +#define SSTSA_TSEN BIT(8) +#define SSRSA_RSEN BIT(8) + +#define SSCR3_TFL_MASK DAI_INTEL_SSP_MASK(5, 0) +#define SSCR3_RFL_MASK DAI_INTEL_SSP_MASK(13, 8) +#define SSCR3_TFL_VAL(scr3_val) (((scr3_val) >> 0) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_RFL_VAL(scr3_val) (((scr3_val) >> 8) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_TX(x) DAI_INTEL_SSP_SET_BITS(21, 16, (x) - 1) +#define SSCR3_RX(x) DAI_INTEL_SSP_SET_BITS(29, 24, (x) - 1) + +#define SSIOC_TXDPDEB BIT(1) +#define SSIOC_SFCR BIT(4) +#define SSIOC_SCOE BIT(5) + +/* SSMIDyCS */ +#define SSMIDyCS_RXEN BIT(0) +#define SSMIDyCS_RSRE BIT(1) +#define SSMIDyCS_RFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_RFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMIDyCS_RNE BIT(26) +#define SSMIDyCS_RFS BIT(27) +#define SSMIDyCS_ROR BIT(28) +#define SSMIDyCS_PINT BIT(29) +#define SSMIDyCS_TINT BIT(30) +#define SSMIDyCS_EOC BIT(31) + +/* SSMIDyTSA */ +#define SSMIDyTSA_RTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMIDyTSA_SRTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* SSMODyCS */ +#define SSMODyCS_TXEN BIT(0) +#define SSMODyCS_TSRE BIT(1) +#define SSMODyCS_TFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_TFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMODyCS_TNF BIT(26) +#define SSMODyCS_TFS BIT(27) +#define SSMODyCS_TUR BIT(28) + +/* SSMODyTSA */ +#define SSMODyTSA_TTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMODyTSA_STTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* For 8000 Hz rate one sample is transmitted within 125us */ +#define DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE 125 + +/* SSP flush retry counts maximum */ +#define DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX 16 + +#define SSP_CLK_MCLK_ES_REQ BIT(0) +#define SSP_CLK_MCLK_ACTIVE BIT(1) +#define SSP_CLK_BCLK_ES_REQ BIT(2) +#define SSP_CLK_BCLK_ACTIVE BIT(3) + +#define I2SLCTL_OFFSET 0x04 + +#define I2SLCTL_OFLEN BIT(4) +#define I2SLCTL_SPA(x) BIT(16 + x) +#define I2SLCTL_CPA(x) BIT(23 + x) +#define PCMS0CM_OFFSET 0x16 +#define PCMS1CM_OFFSET PCMS0CM_OFFSET + 4 * I2SIPCMC + +#define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x) +#define SHIM_CLKCTL 0x78 +#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x) +#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x) + +/** \brief Offset of MCLK Divider Control Register. */ +#define MN_MDIVCTRL 0x100 + +/** \brief Offset of MCLK Divider x Ratio Register. */ +#define MN_MDIVR(x) (0x180 + (x) * 0x4) + +/** \brief Enables the output of MCLK Divider. */ +#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x) + +/** \brief Bits for setting MCLK source clock. */ +#define MCDSS(x) DAI_INTEL_SSP_SET_BITS(17, 16, x) + +/** \brief Offset of BCLK x M/N Divider M Value Register. */ +#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0) + +/** \brief Offset of BCLK x M/N Divider N Value Register. */ +#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4) + +/** \brief Bits for setting M/N source clock. */ +#define MNDSS(x) DAI_INTEL_SSP_SET_BITS(21, 20, x) + +/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */ +#define MN_SOURCE_CLKS_MASK 0x3 + +#endif /* __INTEL_DAI_DRIVER_SSP_REGSV1_H__ */ diff --git a/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi b/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi index e823fb0fe4be25..35825e6ea6a71b 100644 --- a/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi @@ -204,7 +204,7 @@ }; ssp0: ssp@28100 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00028100 0x1000 @@ -214,12 +214,19 @@ dmas = <&hda_link_out 1 &hda_link_in 1>; dma-names = "tx", "rx"; + ssp-index = <0>; power-domain = <&io0_domain>; status = "okay"; + + ssp00: ssp@0 { + compatible = "intel,ssp-dai"; + reg = <0x0>; + status = "okay"; + }; }; ssp1: ssp@29100 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00029100 0x1000 @@ -229,12 +236,19 @@ dmas = <&hda_link_out 2 &hda_link_in 2>; dma-names = "tx", "rx"; + ssp-index = <1>; power-domain = <&io0_domain>; status = "okay"; + + ssp10: ssp@10 { + compatible = "intel,ssp-dai"; + reg = <0x10>; + status = "okay"; + }; }; ssp2: ssp@2a100 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x0002a100 0x1000 @@ -244,53 +258,15 @@ dmas = <&hda_link_out 3 &hda_link_in 3>; dma-names = "tx", "rx"; + ssp-index = <2>; power-domain = <&io0_domain>; status = "okay"; - }; - - ssp3: ssp@2b100 { - compatible = "intel,ssp-dai"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x0002b100 0x1000 - 0x00079C00 0x200>; - interrupts = <0x03 0 0>; - interrupt-parent = <&ace_intc>; - dmas = <&hda_link_out 4 - &hda_link_in 4>; - dma-names = "tx", "rx"; - power-domain = <&io0_domain>; - status = "okay"; - }; - ssp4: ssp@2c100 { - compatible = "intel,ssp-dai"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x0002c100 0x1000 - 0x00079C00 0x200>; - interrupts = <0x04 0 0>; - interrupt-parent = <&ace_intc>; - dmas = <&hda_link_out 5 - &hda_link_in 5>; - dma-names = "tx", "rx"; - power-domain = <&io0_domain>; - status = "okay"; - }; - - ssp5: ssp@2d100 { - compatible = "intel,ssp-dai"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x0002d100 0x1000 - 0x00079C00 0x200>; - interrupts = <0x04 0 0>; - interrupt-parent = <&ace_intc>; - dmas = <&hda_link_out 6 - &hda_link_in 6>; - dma-names = "tx", "rx"; - power-domain = <&io0_domain>; - status = "okay"; + ssp20: ssp@20 { + compatible = "intel,ssp-dai"; + reg = <0x20>; + status = "okay"; + }; }; mem_window0: mem_window@70200 { From afd9a00668b3d4b199fa7aea5f75d512e94abd89 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 31 May 2024 17:10:57 +0000 Subject: [PATCH 6/6] soc: intel_adsp/ace: Fix SOC_TOOLCHAIN_NAME symbol Set the appropriated toolchain name for each ace target. Signed-off-by: Flavio Ceolin --- soc/intel/intel_adsp/ace/Kconfig.soc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/soc/intel/intel_adsp/ace/Kconfig.soc b/soc/intel/intel_adsp/ace/Kconfig.soc index 4f981801977904..89ef2eb30dbd5f 100644 --- a/soc/intel/intel_adsp/ace/Kconfig.soc +++ b/soc/intel/intel_adsp/ace/Kconfig.soc @@ -30,7 +30,9 @@ config SOC_SERIES default "intel_adsp_ace" if SOC_SERIES_INTEL_ADSP_ACE config SOC_TOOLCHAIN_NAME - default "intel_ace15_mtpm" if SOC_SERIES_INTEL_ADSP_ACE + default "intel_ace15_mtpm" if SOC_INTEL_ACE15_MTPM + default "intel_ace15_mtpm" if SOC_INTEL_ACE20_LNL + default "intel_ace30_ptl" if SOC_INTEL_ACE30_PTL config SOC default "ace15_mtpm" if SOC_INTEL_ACE15_MTPM