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 <anas.nashif@intel.com>
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
This commit is contained in:
Flavio Ceolin 2022-08-24 20:51:30 -07:00 committed by Henrik Brix Andersen
commit 9637b8b0bc
27 changed files with 1718 additions and 19 deletions

View file

@ -6,3 +6,4 @@ config BOARD_INTEL_ADSP
select SOC_INTEL_CAVS_V25 if BOARD_INTEL_ADSP_CAVS25_TGPH 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_ACE15_MTPM if BOARD_INTEL_ADSP_ACE15_MTPM
select SOC_INTEL_ACE20_LNL if BOARD_INTEL_ADSP_ACE20_LNL select SOC_INTEL_ACE20_LNL if BOARD_INTEL_ADSP_ACE20_LNL
select SOC_INTEL_ACE30_PTL if BOARD_INTEL_ADSP_ACE30_PTL

View file

@ -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") 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() endif()

View file

@ -7,3 +7,4 @@ boards:
- name: 'tgph' - name: 'tgph'
- name: ace15_mtpm - name: ace15_mtpm
- name: ace20_lnl - name: ace20_lnl
- name: ace30_ptl

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/dts-v1/;
#include <intel/intel_adsp_ace30_ptl.dtsi>
/ {
model = "intel_adsp_ace30_ptl";
compatible = "intel";
chosen {
zephyr,sram = &sram0;
zephyr,console = &mem_window3;
};
};

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,593 @@
/*
* Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <xtensa/xtensa.dtsi>
#include <mem.h>
/ {
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>;
};
};
};

View file

@ -8,6 +8,8 @@ config SOC_FAMILY_INTEL_ADSP
select ARCH_SUPPORTS_COREDUMP select ARCH_SUPPORTS_COREDUMP
select CPU_HAS_DCACHE select CPU_HAS_DCACHE
select ARCH_HAS_USERSPACE if XTENSA_MMU select ARCH_HAS_USERSPACE if XTENSA_MMU
imply XTENSA_MMU_DOUBLE_MAP
select ARCH_HAS_USERSPACE if XTENSA_MMU
select CPU_CACHE_INCOHERENT select CPU_CACHE_INCOHERENT
if SOC_FAMILY_INTEL_ADSP if SOC_FAMILY_INTEL_ADSP

View file

@ -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.c)
zephyr_library_sources_ifdef(CONFIG_SOC_INTEL_COMM_WIDGET comm_widget_messages.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 "") set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "")

View file

@ -14,6 +14,7 @@ config SOC_SERIES_INTEL_ADSP_ACE
select HAS_PM select HAS_PM
select XTENSA_CPU_HAS_HIFI3 select XTENSA_CPU_HAS_HIFI3
select XTENSA_CPU_HAS_HIFI4 select XTENSA_CPU_HAS_HIFI4
select ARCH_HAS_RESERVED_PAGE_FRAMES if MMU
config SOC_INTEL_COMM_WIDGET config SOC_INTEL_COMM_WIDGET
bool "Intel Communication Widget driver" bool "Intel Communication Widget driver"

View file

@ -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

View file

@ -50,6 +50,9 @@ config SYS_CLOCK_TICKS_PER_SEC
config XTENSA_CCOUNT_HZ config XTENSA_CCOUNT_HZ
default 393216000 default 393216000
config INTEL_ADSP_TIMER
default y
config DYNAMIC_INTERRUPTS config DYNAMIC_INTERRUPTS
default y default y

View file

@ -20,6 +20,12 @@ config SOC_INTEL_ACE20_LNL
help help
ACE 2.0 Lunar Lake PCH 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 config SOC_SERIES
default "intel_adsp_ace" if SOC_SERIES_INTEL_ADSP_ACE default "intel_adsp_ace" if SOC_SERIES_INTEL_ADSP_ACE
@ -29,3 +35,4 @@ config SOC_TOOLCHAIN_NAME
config SOC config SOC
default "ace15_mtpm" if SOC_INTEL_ACE15_MTPM default "ace15_mtpm" if SOC_INTEL_ACE15_MTPM
default "ace20_lnl" if SOC_INTEL_ACE20_LNL default "ace20_lnl" if SOC_INTEL_ACE20_LNL
default "ace30_ptl" if SOC_INTEL_ACE30_PTL

View file

@ -37,11 +37,21 @@ ENTRY(rom_entry);
*/ */
#ifdef CONFIG_KERNEL_COHERENCE #ifdef CONFIG_KERNEL_COHERENCE
#define RPO_SET(addr, reg) ((addr & 0x1fffffff) | (reg << 29)) #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_CACHED RPO_SET(ALIGN(64), CONFIG_XTENSA_CACHED_REGION)
#define SEGSTART_UNCACHED RPO_SET(ALIGN(64), CONFIG_XTENSA_UNCACHED_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 #else
#define SEGSTART_CACHED . #define SEGSTART_CACHED .
#define SEGSTART_UNCACHED . #define SEGSTART_UNCACHED .
#endif
#define ucram ram #define ucram ram
#endif #endif
@ -56,6 +66,18 @@ ENTRY(rom_entry);
#define NOLOAD_BASE 0x20000 #define NOLOAD_BASE 0x20000
#define NOLOAD_SIZE 0x100000 #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 { MEMORY {
vector_base_text : vector_base_text :
org = VECBASE_RESET_PADDR_SRAM, org = VECBASE_RESET_PADDR_SRAM,
@ -102,6 +124,11 @@ MEMORY {
vector_double_text : vector_double_text :
org = DOUBLEEXC_VECTOR_PADDR_SRAM, org = DOUBLEEXC_VECTOR_PADDR_SRAM,
len = MEM_VECT_TEXT_SIZE 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 : imr :
org = IMR_BOOT_LDR_TEXT_ENTRY_BASE, org = IMR_BOOT_LDR_TEXT_ENTRY_BASE,
len = 0x100000 len = 0x100000
@ -233,22 +260,77 @@ SECTIONS {
_DoubleExceptionVector_text_end = .; _DoubleExceptionVector_text_end = .;
} >vector_double_text } >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 = .; __text_region_start = .;
_image_ram_start = .;
z_mapped_start = .;
*(.iram1 .iram1.*) *(.iram1 .iram1.*)
*(.entry.text) *(.entry.text)
*(.init.literal) *(.init.literal)
*(.iram0.text) *(.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(*(.init))
KEEP(*(.lps_vector)) 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) *(.fini.literal)
KEEP(*(.fini)) KEEP(*(.fini))
*(.gnu.version) *(.gnu.version)
#include <zephyr/linker/kobject-text.ld>
MMU_PAGE_ALIGN
__text_region_end = .; __text_region_end = .;
} >ram } >ram
.rodata : ALIGN(4096) .rodata : HDR_4K_OR_MMU_PAGE_ALIGN
{ {
__rodata_region_start = .; __rodata_region_start = .;
*(.rodata) *(.rodata)
@ -258,6 +340,7 @@ SECTIONS {
. = ALIGN(4); . = ALIGN(4);
#include <snippets-rodata.ld> #include <snippets-rodata.ld>
#include <zephyr/linker/kobject-rom.ld>
__XT_EXCEPTION_TABLE__ = .; __XT_EXCEPTION_TABLE__ = .;
KEEP (*(.xt_except_table)) KEEP (*(.xt_except_table))
@ -277,14 +360,14 @@ SECTIONS {
*(.xt_except_desc_end) *(.xt_except_desc_end)
*(.dynamic) *(.dynamic)
*(.gnu.version_d) *(.gnu.version_d)
_image_ram_start = .;
_bss_table_start = .; _bss_table_start = .;
LONG(_bss_start) LONG(_bss_start)
LONG(_bss_end) LONG(_bss_end)
_bss_table_end = .; _bss_table_end = .;
MMU_PAGE_ALIGN
} >ram } >ram
.module_init : { .module_init : HDR_MMU_PAGE_ALIGN {
_module_init_start = .; _module_init_start = .;
*(*.initcall) *(*.initcall)
_module_init_end = .; _module_init_end = .;
@ -292,21 +375,22 @@ SECTIONS {
#define RAMABLE_REGION ram #define RAMABLE_REGION ram
#define ROMABLE_REGION ram #define ROMABLE_REGION ram
__common_rom_region_start = SEGSTART_CACHED;
#include <zephyr/linker/common-rom.ld> #include <zephyr/linker/common-rom.ld>
__common_rom_region_end = .;
__rodata_region_end = .; __rodata_region_end = .;
.fw_ready : { .noinit SEGSTART_UNCACHED : HDR_MMU_PAGE_ALIGN {
KEEP(*(".fw_ready")); __data_start = .;
KEEP (*(.fw_ready_metadata))
} >ram
.noinit SEGSTART_UNCACHED : {
*(.noinit) *(.noinit)
*(.noinit.*) *(.noinit.*)
} >ucram } >ucram
.data SEGSTART_UNCACHED : { #include <zephyr/linker/kobject-priv-stacks.ld>
__data_start = .; . = SEGSTART_UNCACHED;
.data SEGSTART_UNCACHED : HDR_MMU_PAGE_ALIGN {
*(.data) *(.data)
*(.data.*) *(.data.*)
*(.gnu.linkonce.d.*) *(.gnu.linkonce.d.*)
@ -324,6 +408,7 @@ SECTIONS {
_trace_ctx_end = ABSOLUTE(.); _trace_ctx_end = ABSOLUTE(.);
*(.gna_model) *(.gna_model)
__data_end = .; __data_end = .;
MMU_PAGE_ALIGN
} >ucram } >ucram
.lit4 SEGSTART_CACHED : { .lit4 SEGSTART_CACHED : {
@ -344,7 +429,28 @@ SECTIONS {
#define RAMABLE_REGION ucram #define RAMABLE_REGION ucram
#define ROMABLE_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.ld>
_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 <zephyr/linker/common-ram.ld> #include <zephyr/linker/common-ram.ld>
#include <zephyr/linker/kobject-data.ld>
__common_ram_region_end = .;
.tm_clone_table : { .tm_clone_table : {
*(.tm_clone_table) *(.tm_clone_table)
@ -356,6 +462,11 @@ SECTIONS {
.cached SEGSTART_CACHED : { .cached SEGSTART_CACHED : {
_cached_start = .; _cached_start = .;
*(.cached .cached.*) *(.cached .cached.*)
#ifdef CONFIG_USERSPACE
z_user_stacks_start = .;
*(.user_stacks*)
z_user_stacks_end = .;
#endif
_cached_end = .; _cached_end = .;
} >ram } >ram
@ -384,6 +495,7 @@ SECTIONS {
*(.gnu.linkonce.b.*) *(.gnu.linkonce.b.*)
*(COMMON) *(COMMON)
. = ALIGN(8); . = ALIGN(8);
MMU_PAGE_ALIGN
_bss_end = .; _bss_end = .;
} >ucram } >ucram
@ -410,17 +522,19 @@ SECTIONS {
. = SEGSTART_UNCACHED; . = SEGSTART_UNCACHED;
_end = ALIGN(8); _end = ALIGN(8);
. = SEGSTART_CACHED; . = SEGSTART_CACHED;
z_mapped_end = .;
. = L2_SRAM_BASE + L2_SRAM_SIZE; . = L2_SRAM_BASE + L2_SRAM_SIZE;
. = SEGSTART_UNCACHED; . = SEGSTART_UNCACHED;
_heap_end = .; _heap_end = .;
_heap_sentry = .; _heap_sentry = .;
. = SEGSTART_CACHED;
_image_ram_end = .;
/* dma buffers */ /* dma buffers */
.lpbuf (NOLOAD): { .lpbuf (NOLOAD): {
_dma_buf_start = .; _dma_buf_start = .;
*(.dma_buffers) *(.dma_buffers)
_dma_buf_end = .; _dma_buf_end = .;
_image_ram_end = .;
} >lpram } >lpram
/* Non-loadable sections below. Back to cached memory so /* Non-loadable sections below. Back to cached memory so

View file

@ -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_ */

View file

@ -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

View file

@ -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 <intel_adsp_ipc.h>
#include <intel_adsp_ipc_devtree.h>
/**
* @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 */

View file

@ -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 <zephyr/devicetree.h>
#include <zephyr/toolchain.h>
#include <adsp-vectors.h>
#include <mem_window.h>
#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_ */

View file

@ -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_ */

View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2024 Intel Corporation
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/toolchain.h>
#include <zephyr/sys/util_macro.h>
#include <adsp_shim.h>
#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_ */

View file

@ -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 <zephyr/sys/util.h>
/**
* 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_ */

View file

@ -0,0 +1,143 @@
/*
* Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/arch/xtensa/xtensa_mmu.h>
#include <zephyr/linker/linker-defs.h>
#include <adsp_memory.h>
#include <adsp_imr_layout.h>
#include <inttypes.h>
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);

View file

@ -6,6 +6,7 @@
#include <zephyr/init.h> #include <zephyr/init.h>
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/toolchain.h>
#include <zephyr/sys/check.h> #include <zephyr/sys/check.h>
#include <zephyr/arch/cpu.h> #include <zephyr/arch/cpu.h>
#include <zephyr/arch/xtensa/arch.h> #include <zephyr/arch/xtensa/arch.h>
@ -25,12 +26,28 @@
#define CPU_POWERUP_TIMEOUT_USEC 10000 #define CPU_POWERUP_TIMEOUT_USEC 10000
#ifdef CONFIG_XTENSA_MMU
#include <zephyr/arch/xtensa/xtensa_mmu.h>
#endif /* CONFIG_XTENSA_MMU */
#define ACE_INTC_IRQ DT_IRQN(DT_NODELABEL(ace_intc)) #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) static void ipc_isr(void *arg)
{ {
uint32_t cpu_id = arch_proc_id(); 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 * Clearing the BUSY bits in both TDR and TDA are needed to
* complete an IDC message. If we do only one (and not both), * 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 * On TDR, it is to write one to clear, while on TDA, it is
* to write zero to clear. * 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; IDC[cpu_id].agents[0].ipc.tda = 0;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
@ -166,6 +183,10 @@ void soc_start_core(int cpu_num)
void soc_mp_startup(uint32_t cpu) void soc_mp_startup(uint32_t cpu)
{ {
#ifdef CONFIG_XTENSA_MMU
xtensa_mmu_init();
#endif /* CONFIG_XTENSA_MMU */
/* Must have this enabled always */ /* Must have this enabled always */
xtensa_irq_enable(ACE_INTC_IRQ); xtensa_irq_enable(ACE_INTC_IRQ);
@ -178,7 +199,17 @@ void soc_mp_startup(uint32_t cpu)
#endif /* CONFIG_ADSP_IDLE_CLOCK_GATING */ #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(); uint32_t curr = arch_proc_id();
@ -187,11 +218,23 @@ void arch_sched_ipi(void)
for (int core = 0; core < num_cpus; core++) { for (int core = 0; core < num_cpus; core++) {
if (core != curr && soc_cpus_active[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 #if CONFIG_MP_MAX_NUM_CPUS > 1
int soc_adsp_halt_cpu(int id) int soc_adsp_halt_cpu(int id)
{ {

View file

@ -122,6 +122,9 @@ struct core_state {
uint32_t intenable; uint32_t intenable;
uint32_t ps; uint32_t ps;
uint32_t bctl; 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}}; 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].excsave2 = XTENSA_RSR("EXCSAVE2");
core_desc[core_id].excsave3 = XTENSA_RSR("EXCSAVE3"); core_desc[core_id].excsave3 = XTENSA_RSR("EXCSAVE3");
core_desc[core_id].thread_ptr = XTENSA_RUR("THREADPTR"); 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, a0" : "=r"(core_desc[core_id].a0));
__asm__ volatile("mov %0, a1" : "=r"(core_desc[core_id].a1)); __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(); 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("PS", core_desc[core_id].ps);
XTENSA_WSR("VECBASE", core_desc[core_id].vecbase); XTENSA_WSR("VECBASE", core_desc[core_id].vecbase);
XTENSA_WSR("EXCSAVE2", core_desc[core_id].excsave2); XTENSA_WSR("EXCSAVE2", core_desc[core_id].excsave2);
XTENSA_WSR("EXCSAVE3", core_desc[core_id].excsave3); XTENSA_WSR("EXCSAVE3", core_desc[core_id].excsave3);
XTENSA_WUR("THREADPTR", core_desc[core_id].thread_ptr); 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 a0, %0" :: "r"(core_desc[core_id].a0));
__asm__ volatile("mov a1, %0" :: "r"(core_desc[core_id].a1)); __asm__ volatile("mov a1, %0" :: "r"(core_desc[core_id].a1));
__asm__ volatile("rsync"); __asm__ volatile("rsync");

View file

@ -45,7 +45,7 @@
#define DOUBLEEXC_VECTOR_PADDR_SRAM \ #define DOUBLEEXC_VECTOR_PADDR_SRAM \
(VECBASE_RESET_PADDR_SRAM + XCHAL_DOUBLEEXC_VECOFS) (VECBASE_RESET_PADDR_SRAM + XCHAL_DOUBLEEXC_VECOFS)
#define VECTOR_TBL_SIZE 0x0400 #define VECTOR_TBL_SIZE 0x1000
/* Vector and literal sizes */ /* Vector and literal sizes */
#define MEM_VECT_LIT_SIZE 0x8 #define MEM_VECT_LIT_SIZE 0x8

View file

@ -76,8 +76,15 @@ static ALWAYS_INLINE void cpu_early_init(void)
/* Finally we need to enable the cache in the Region /* Finally we need to enable the cache in the Region
* Protection Option "TLB" entries. The hardware defaults * Protection Option "TLB" entries. The hardware defaults
* have this set to RW/uncached everywhere. * 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(); ARCH_XTENSA_SET_RPO_TLB();
#endif
/* Initialize ATOMCTL: Hardware defaults for S32C1I use /* Initialize ATOMCTL: Hardware defaults for S32C1I use
* "internal" operations, meaning they are atomic only WRT the * "internal" operations, meaning they are atomic only WRT the

View file

@ -5,6 +5,7 @@ family:
socs: socs:
- name: ace15_mtpm - name: ace15_mtpm
- name: ace20_lnl - name: ace20_lnl
- name: ace30_ptl
- name: intel_adsp_cavs - name: intel_adsp_cavs
socs: socs:
- name: cavs25 - name: cavs25