diff --git a/boards/intel/adsp/Kconfig.intel_adsp b/boards/intel/adsp/Kconfig.intel_adsp index 2e4c9844720..f5a81c6dfcc 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 bcdfc328646..584474544bf 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 9295ae0c3eb..8e35014dd66 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 00000000000..9e25712bc2c --- /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 00000000000..4e9c71a9d2f --- /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 00000000000..913d2a8c3e3 --- /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 00000000000..e823fb0fe4b --- /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 135fecb575a..1a0cc4350d4 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 919e7993427..0c9c43eb339 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 ff86472466e..96778d274a4 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 00000000000..f7e0f19008f --- /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 a860d744226..e96c890ff6c 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 3cab72f8f51..4f981801977 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 b259c842995..f6205a5c77c 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 + + __common_rom_region_start = SEGSTART_CACHED; #include - __rodata_region_end = .; + __common_rom_region_end = .; + __rodata_region_end = .; - .fw_ready : { - KEEP(*(".fw_ready")); - KEEP (*(.fw_ready_metadata)) - } >ram - - .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 00000000000..6cc07538da0 --- /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 00000000000..bf912746d66 --- /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 00000000000..c91e511c96c --- /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 00000000000..1596cb489d3 --- /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 00000000000..912a225588b --- /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 00000000000..f9628dbbb0d --- /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 00000000000..e28e6f3d8af --- /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 00000000000..a59b231fbe3 --- /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 f530232e896..68b8693a520 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 6eb504178e3..6e734c23424 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 01e660e43ea..97f778968b8 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 571ae29f5b8..dea6aa9f181 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 757750eeb37..0f889aea963 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