diff --git a/dts/xtensa/intel/intel_apl_adsp.dtsi b/dts/xtensa/intel/intel_apl_adsp.dtsi new file mode 100644 index 00000000000..630f677ecdc --- /dev/null +++ b/dts/xtensa/intel/intel_apl_adsp.dtsi @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "cadence,tensilica-xtensa-lx4"; + reg = <0>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "cadence,tensilica-xtensa-lx4"; + reg = <1>; + }; + }; + + sram0: memory@be000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0xbe000000 DT_SIZE_K(512)>; + }; + + sram1: memory@be800000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0xbe800000 DT_SIZE_K(128)>; + }; + + soc { + core_intc: core_intc@0 { + compatible = "xtensa,core-intc"; + reg = <0x00 0x400>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + cavs0: cavs@1600 { + compatible = "intel,cavs-intc"; + reg = <0x1600 0x10>; + interrupt-controller; + #interrupt-cells = <3>; + interrupts = <6 0 0>; + interrupt-parent = <&core_intc>; + }; + + cavs1: cavs@1610 { + compatible = "intel,cavs-intc"; + reg = <0x1610 0x10>; + interrupt-controller; + #interrupt-cells = <3>; + interrupts = <0xA 0 0>; + interrupt-parent = <&core_intc>; + }; + + cavs2: cavs@1620 { + compatible = "intel,cavs-intc"; + reg = <0x1620 0x10>; + interrupt-controller; + #interrupt-cells = <3>; + interrupts = <0XD 0 0>; + interrupt-parent = <&core_intc>; + }; + + cavs3: cavs@1630 { + compatible = "intel,cavs-intc"; + reg = <0x1630 0x10>; + interrupt-controller; + #interrupt-cells = <3>; + interrupts = <0x10 0 0>; + interrupt-parent = <&core_intc>; + }; + }; +}; diff --git a/soc/xtensa/intel_apl_adsp/CMakeLists.txt b/soc/xtensa/intel_apl_adsp/CMakeLists.txt new file mode 100644 index 00000000000..b1d80f2bdb0 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) +zephyr_library_sources(adsp.c) +zephyr_library_sources(soc.c) +zephyr_library_sources(main_entry.S) diff --git a/soc/xtensa/intel_apl_adsp/Kconfig.defconfig b/soc/xtensa/intel_apl_adsp/Kconfig.defconfig new file mode 100644 index 00000000000..b1f10e7e3f7 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/Kconfig.defconfig @@ -0,0 +1,62 @@ +# Xtensa board configuration + +# Copyright (c) 2017 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +if SOC_INTEL_APL_ADSP + +config SOC + string + default "intel_apl_adsp" + +config IRQ_OFFLOAD_INTNUM + default 0 + +# S1000 does not have MISC0. +# Since EXCSAVE2 is unused by Zephyr, use it instead. +config XTENSA_KERNEL_CPU_PTR_SR + default "EXCSAVE2" + +config KERNEL_ENTRY + default "_MainEntry" + +config MULTI_LEVEL_INTERRUPTS + default y + +config 2ND_LEVEL_INTERRUPTS + default y + +config DYNAMIC_INTERRUPTS + default y + +config LOG + default y + +if TEST + +# To prevent test uses TEST_LOGGING_MINIMAL +config TEST_LOGGING_DEFAULTS + default n + +endif # TEST + +if LOG + +config LOG_PRINTK + default y + +config LOG_IMMEDIATE + default y + +config LOG_BACKEND_ADSP + default y + +config LOG_BACKEND_ADSP_RINGBUF_BASE + default "0xBE008000" + +config LOG_BACKEND_ADSP_RINGBUF_SIZE + default "0x2000" + +endif # LOG + +endif diff --git a/soc/xtensa/intel_apl_adsp/Kconfig.soc b/soc/xtensa/intel_apl_adsp/Kconfig.soc new file mode 100644 index 00000000000..ebdd92b8594 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/Kconfig.soc @@ -0,0 +1,7 @@ +# Copyright (c) 2017 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config SOC_INTEL_APL_ADSP + bool "intel_apl_adsp" + select XTENSA_RESET_VECTOR + select XTENSA_USE_CORE_CRT1 diff --git a/soc/xtensa/intel_apl_adsp/adsp.c b/soc/xtensa/intel_apl_adsp/adsp.c new file mode 100644 index 00000000000..84cf5fdc0bc --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/adsp.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include + +#include "soc.h" + +static const struct adsp_ipc_fw_ready fw_ready_apl + __attribute__((section(".fw_ready"))) __attribute__((used)) = { + .hdr = { + .cmd = ADSP_IPC_FW_READY, + .size = sizeof(struct adsp_ipc_fw_ready), + }, + .version = { + .hdr.size = sizeof(struct adsp_ipc_fw_version), + .micro = 0, + .minor = 1, + .major = 0, + + .build = 0, + .date = __DATE__, + .time = __TIME__, + + .tag = "zephyr", + .abi_version = 0, + }, + .flags = 0, +}; + +#define NUM_WINDOWS 2 + +static const struct adsp_ipc_window sram_window = { + .ext_hdr = { + .hdr.cmd = ADSP_IPC_FW_READY, + .hdr.size = sizeof(struct adsp_ipc_window) + + sizeof(struct adsp_ipc_window_elem) * NUM_WINDOWS, + .type = ADSP_IPC_EXT_WINDOW, + }, + .num_windows = NUM_WINDOWS, + .window = { + { + .type = ADSP_IPC_REGION_REGS, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_SW_REG_SIZE, + .offset = 0, + }, + { + .type = ADSP_IPC_REGION_TRACE, + .id = 3, /* map to host window 3 */ + .flags = 0, + .size = MAILBOX_TRACE_SIZE, + .offset = 0, + }, + }, +}; + +/* + * Sets up the host windows so that the host can see the memory + * content on the DSP SRAM. + */ +static void prepare_host_windows(void) +{ + /* window0, for fw status */ + sys_write32((HP_SRAM_WIN0_SIZE | 0x7), DMWLO(0)); + sys_write32((HP_SRAM_WIN0_BASE | DMWBA_READONLY | DMWBA_ENABLE), + DMWBA(0)); + memset((void *)(HP_SRAM_WIN0_BASE + SRAM_REG_FW_END), 0, + HP_SRAM_WIN0_SIZE - SRAM_REG_FW_END); + SOC_DCACHE_FLUSH((void *)(HP_SRAM_WIN0_BASE + SRAM_REG_FW_END), + HP_SRAM_WIN0_SIZE - SRAM_REG_FW_END); + + /* window3, for trace + * zeroed by trace initialization + */ + sys_write32((HP_SRAM_WIN3_SIZE | 0x7), DMWLO(3)); + sys_write32((HP_SRAM_WIN3_BASE | DMWBA_READONLY | DMWBA_ENABLE), + DMWBA(3)); + memset((void *)HP_SRAM_WIN3_BASE, 0, HP_SRAM_WIN3_SIZE); + SOC_DCACHE_FLUSH((void *)HP_SRAM_WIN3_BASE, HP_SRAM_WIN3_SIZE); +} + +/* + * Sends the firmware ready message so the firmware loader can + * map the host windows. + */ +static void send_fw_ready(void) +{ + memcpy((void *)MAILBOX_DSPBOX_BASE, + &fw_ready_apl, sizeof(fw_ready_apl)); + + memcpy((void *)(MAILBOX_DSPBOX_BASE + sizeof(fw_ready_apl)), + &sram_window, + (sizeof(sram_window) + sram_window.ext_hdr.hdr.size)); + + SOC_DCACHE_FLUSH((void *)MAILBOX_DSPBOX_BASE, MAILBOX_DSPBOX_SIZE); + + ipc_write(IPC_DIPCIE, 0); + ipc_write(IPC_DIPCI, (0x80000000 | ADSP_IPC_FW_READY)); +} + +static int adsp_init(struct device *dev) +{ + prepare_host_windows(); + + send_fw_ready(); + + return 0; +} + +SYS_INIT(adsp_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/soc/xtensa/intel_apl_adsp/dts_fixup.h b/soc/xtensa/intel_apl_adsp/dts_fixup.h new file mode 100644 index 00000000000..0f2c4c97ed9 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/dts_fixup.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* SoC level DTS fixup file */ + +#define DT_L2_SRAM_BASE CONFIG_SRAM_BASE_ADDRESS +#define DT_L2_SRAM_SIZE (CONFIG_SRAM_SIZE * 1024) + +#define DT_LP_SRAM_BASE DT_INST_1_MMIO_SRAM_BASE_ADDRESS +#define DT_LP_SRAM_SIZE DT_INST_1_MMIO_SRAM_SIZE + +#define DT_CAVS_ICTL_BASE_ADDR DT_INTEL_CAVS_INTC_1600_BASE_ADDRESS +#define DT_CAVS_ICTL_0_IRQ DT_INTEL_CAVS_INTC_1600_IRQ_0 +#define DT_CAVS_ICTL_0_IRQ_PRI DT_INTEL_CAVS_INTC_1600_IRQ_0_PRIORITY +#define DT_CAVS_ICTL_0_IRQ_FLAGS DT_INTEL_CAVS_INTC_1600_IRQ_0_SENSE + +#define DT_CAVS_ICTL_1_IRQ DT_INTEL_CAVS_INTC_1610_IRQ_0 +#define DT_CAVS_ICTL_1_IRQ_PRI DT_INTEL_CAVS_INTC_1610_IRQ_0_PRIORITY +#define DT_CAVS_ICTL_1_IRQ_FLAGS DT_INTEL_CAVS_INTC_1610_IRQ_0_SENSE + +#define DT_CAVS_ICTL_2_IRQ DT_INTEL_CAVS_INTC_1620_IRQ_0 +#define DT_CAVS_ICTL_2_IRQ_PRI DT_INTEL_CAVS_INTC_1620_IRQ_0_PRIORITY +#define DT_CAVS_ICTL_2_IRQ_FLAGS DT_INTEL_CAVS_INTC_1620_IRQ_0_SENSE + +#define DT_CAVS_ICTL_3_IRQ DT_INTEL_CAVS_INTC_1630_IRQ_0 +#define DT_CAVS_ICTL_3_IRQ_PRI DT_INTEL_CAVS_INTC_1630_IRQ_0_PRIORITY +#define DT_CAVS_ICTL_3_IRQ_FLAGS DT_INTEL_CAVS_INTC_1630_IRQ_0_SENSE + +/* End of SoC Level DTS fixup file */ diff --git a/soc/xtensa/intel_apl_adsp/include/_soc_inthandlers.h b/soc/xtensa/intel_apl_adsp/include/_soc_inthandlers.h new file mode 100644 index 00000000000..10cbc50a22b --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/include/_soc_inthandlers.h @@ -0,0 +1,265 @@ +/* + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + * + * Functions here are designed to produce efficient code to + * search an Xtensa bitmask of interrupts, inspecting only those bits + * declared to be associated with a given interrupt level. Each + * dispatcher will handle exactly one flagged interrupt, in numerical + * order (low bits first) and will return a mask of that bit that can + * then be cleared by the calling code. Unrecognized bits for the + * level will invoke an error handler. + */ + +#include +#include +#include + +#if !defined(XCHAL_INT0_LEVEL) || XCHAL_INT0_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT1_LEVEL) || XCHAL_INT1_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT2_LEVEL) || XCHAL_INT2_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT3_LEVEL) || XCHAL_INT3_LEVEL != 1 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT4_LEVEL) || XCHAL_INT4_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT5_LEVEL) || XCHAL_INT5_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT6_LEVEL) || XCHAL_INT6_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT7_LEVEL) || XCHAL_INT7_LEVEL != 2 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT8_LEVEL) || XCHAL_INT8_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT9_LEVEL) || XCHAL_INT9_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT10_LEVEL) || XCHAL_INT10_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT11_LEVEL) || XCHAL_INT11_LEVEL != 3 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT12_LEVEL) || XCHAL_INT12_LEVEL != 4 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT13_LEVEL) || XCHAL_INT13_LEVEL != 4 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT14_LEVEL) || XCHAL_INT14_LEVEL != 4 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT15_LEVEL) || XCHAL_INT15_LEVEL != 5 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT16_LEVEL) || XCHAL_INT16_LEVEL != 5 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT17_LEVEL) || XCHAL_INT17_LEVEL != 5 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT18_LEVEL) || XCHAL_INT18_LEVEL != 5 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT19_LEVEL) || XCHAL_INT19_LEVEL != 5 +#error core-isa.h interrupt level does not match dispatcher! +#endif +#if !defined(XCHAL_INT20_LEVEL) || XCHAL_INT20_LEVEL != 7 +#error core-isa.h interrupt level does not match dispatcher! +#endif + +static inline int _xtensa_handle_one_int1(unsigned int mask) +{ + int irq; + + if (mask & 0x3) { + if (mask & BIT(0)) { + mask = BIT(0); + irq = 0; + goto handle_irq; + } + if (mask & BIT(1)) { + mask = BIT(1); + irq = 1; + goto handle_irq; + } + } else { + if (mask & BIT(2)) { + mask = BIT(2); + irq = 2; + goto handle_irq; + } + if (mask & BIT(3)) { + mask = BIT(3); + irq = 3; + goto handle_irq; + } + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int2(unsigned int mask) +{ + int irq; + + if (mask & 0x30) { + if (mask & BIT(4)) { + mask = BIT(4); + irq = 4; + goto handle_irq; + } + if (mask & BIT(5)) { + mask = BIT(5); + irq = 5; + goto handle_irq; + } + } else { + if (mask & BIT(6)) { + mask = BIT(6); + irq = 6; + goto handle_irq; + } + if (mask & BIT(7)) { + mask = BIT(7); + irq = 7; + goto handle_irq; + } + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int3(unsigned int mask) +{ + int irq; + + if (mask & 0x300) { + if (mask & BIT(8)) { + mask = BIT(8); + irq = 8; + goto handle_irq; + } + if (mask & BIT(9)) { + mask = BIT(9); + irq = 9; + goto handle_irq; + } + } else { + if (mask & BIT(10)) { + mask = BIT(10); + irq = 10; + goto handle_irq; + } + if (mask & BIT(11)) { + mask = BIT(11); + irq = 11; + goto handle_irq; + } + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int4(unsigned int mask) +{ + int irq; + + if (mask & BIT(12)) { + mask = BIT(12); + irq = 12; + goto handle_irq; + } + if (mask & BIT(13)) { + mask = BIT(13); + irq = 13; + goto handle_irq; + } + if (mask & BIT(14)) { + mask = BIT(14); + irq = 14; + goto handle_irq; + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int5(unsigned int mask) +{ + int irq; + + if (mask & 0x18000) { + if (mask & BIT(15)) { + mask = BIT(15); + irq = 15; + goto handle_irq; + } + if (mask & BIT(16)) { + mask = BIT(16); + irq = 16; + goto handle_irq; + } + } else { + if (mask & BIT(17)) { + mask = BIT(17); + irq = 17; + goto handle_irq; + } + if (mask & BIT(18)) { + mask = BIT(18); + irq = 18; + goto handle_irq; + } + if (mask & BIT(19)) { + mask = BIT(19); + irq = 19; + goto handle_irq; + } + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int7(unsigned int mask) +{ + int irq; + + if (mask & BIT(20)) { + mask = BIT(20); + irq = 20; + goto handle_irq; + } + return 0; +handle_irq: + _sw_isr_table[irq].isr(_sw_isr_table[irq].arg); + return mask; +} + +static inline int _xtensa_handle_one_int0(unsigned int mask) +{ + return 0; +} +static inline int _xtensa_handle_one_int6(unsigned int mask) +{ + return 0; +} diff --git a/soc/xtensa/intel_apl_adsp/include/platform/io.h b/soc/xtensa/intel_apl_adsp/include/platform/io.h new file mode 100644 index 00000000000..0fbe4bc5276 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/include/platform/io.h @@ -0,0 +1,44 @@ +/* + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Author: Liam Girdwood + */ + +#ifndef __INCLUDE_IO__ +#define __INCLUDE_IO__ + +#include +#include +#include + +static inline uint32_t io_reg_read(uint32_t reg) +{ + return sys_read32(reg); +} + +static inline void io_reg_write(uint32_t reg, uint32_t val) +{ + /* Note: Parameters in different order */ + sys_write32(val, reg); +} + +static inline void io_reg_update_bits(uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_write(reg, (io_reg_read(reg) & (~mask)) | (value & mask)); +} + +static inline uint16_t io_reg_read16(uint32_t reg) +{ + return sys_read16(reg); +} + +static inline void io_reg_write16(uint32_t reg, uint16_t val) +{ + /* Note: Parameters in different order */ + sys_write16(val, reg); +} + +#endif diff --git a/soc/xtensa/intel_apl_adsp/include/platform/ipc.h b/soc/xtensa/intel_apl_adsp/include/platform/ipc.h new file mode 100644 index 00000000000..8eca7bdf969 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/include/platform/ipc.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __INCLUDE_PLATFORM_IPC_H__ +#define __INCLUDE_PLATFORM_IPC_H__ + +/** Shift-left bits to extract the global cmd type */ +#define ADSP_GLB_TYPE_SHIFT 28 +#define ADSP_GLB_TYPE_MASK (0xf << ADSP_GLB_TYPE_SHIFT) +#define ADSP_GLB_TYPE(x) ((x) << ADSP_GLB_TYPE_SHIFT) + +/** Shift-left bits to extract the command type */ +#define ADSP_CMD_TYPE_SHIFT 16 +#define ADSP_CMD_TYPE_MASK (0xfff << ADSP_CMD_TYPE_SHIFT) +#define ADSP_CMD_TYPE(x) ((x) << ADSP_CMD_TYPE_SHIFT) + +#define ADSP_IPC_FW_READY ADSP_GLB_TYPE(0x7U) + +/* extended data types that can be appended onto end of adsp_ipc_fw_ready */ +enum adsp_ipc_ext_data { + ADSP_IPC_EXT_DMA_BUFFER = 0, + ADSP_IPC_EXT_WINDOW, +}; + +enum adsp_ipc_region { + ADSP_IPC_REGION_DOWNBOX = 0, + ADSP_IPC_REGION_UPBOX, + ADSP_IPC_REGION_TRACE, + ADSP_IPC_REGION_DEBUG, + ADSP_IPC_REGION_STREAM, + ADSP_IPC_REGION_REGS, + ADSP_IPC_REGION_EXCEPTION, +}; + +/** + * Structure Header - Header for all IPC structures except command structs. + * The size can be greater than the structure size and that means there is + * extended bespoke data beyond the end of the structure including variable + * arrays. + */ +struct adsp_ipc_hdr { + uint32_t size; /**< size of structure */ +} __packed; + +/** + * Command Header - Header for all IPC commands. Identifies IPC message. + * The size can be greater than the structure size and that means there is + * extended bespoke data beyond the end of the structure including variable + * arrays. + */ +struct adsp_ipc_cmd_hdr { + uint32_t size; /**< size of structure */ + uint32_t cmd; /**< command */ +} __packed; + +/* FW version */ +struct adsp_ipc_fw_version { + struct adsp_ipc_hdr hdr; + uint16_t major; + uint16_t minor; + uint16_t micro; + uint16_t build; + uint8_t date[12]; + uint8_t time[10]; + uint8_t tag[6]; + uint32_t abi_version; + + /* reserved for future use */ + uint32_t reserved[4]; +} __packed; + +/* FW ready Message - sent by firmware when boot has completed */ +struct adsp_ipc_fw_ready { + struct adsp_ipc_cmd_hdr hdr; + uint32_t dspbox_offset; /* dsp initiated IPC mailbox */ + uint32_t hostbox_offset; /* host initiated IPC mailbox */ + uint32_t dspbox_size; + uint32_t hostbox_size; + struct adsp_ipc_fw_version version; + + /* Miscellaneous flags */ + uint64_t flags; + + /* reserved for future use */ + uint32_t reserved[4]; +} __packed; + +struct adsp_ipc_ext_data_hdr { + struct adsp_ipc_cmd_hdr hdr; + uint32_t type; /* ADSP_IPC_EXT_ */ +} __packed; + +struct adsp_ipc_window_elem { + struct adsp_ipc_hdr hdr; + uint32_t type; /* ADSP_IPC_REGION_ */ + uint32_t id; /* platform specific */ + uint32_t flags; /**< R, W, RW, etc */ + uint32_t size; /* size of region in bytes */ + + /* offset in window region as windows can be partitioned */ + uint32_t offset; +} __packed; + +/* extended data memory windows for IPC, trace and debug */ +struct adsp_ipc_window { + struct adsp_ipc_ext_data_hdr ext_hdr; + uint32_t num_windows; + struct adsp_ipc_window_elem window[]; +} __packed; + +#endif /* __INCLUDE_PLATFORM_IPC_H__ */ diff --git a/soc/xtensa/intel_apl_adsp/include/platform/mailbox.h b/soc/xtensa/intel_apl_adsp/include/platform/mailbox.h new file mode 100644 index 00000000000..6cfff98a09a --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/include/platform/mailbox.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: Apache-2.0 + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +#ifndef __INCLUDE_PLATFORM_MAILBOX__ +#define __INCLUDE_PLATFORM_MAILBOX__ + +#include + +/* + * The Window Region on HPSRAM for cAVS platforms is organised like this :- + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_TRACE_BASE | Trace Buffer W3| SRAM_TRACE_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_DEBUG_BASE | Debug data W2 | SRAM_DEBUG_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_INBOX_BASE | Inbox W1 | SRAM_INBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_OUTBOX_BASE | Outbox W0 | SRAM_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_SW_REG_BASE | SW Registers W0| SRAM_SW_REG_SIZE | + * +---------------------+----------------+-----------------------------------+ + * + * Note: For suecreek SRAM_SW_REG window does not exist - MAILBOX_SW_REG_BASE + * and MAILBOX_SW_REG_BASE are equal to 0 + */ + + /* window 3 - trace */ +#define MAILBOX_TRACE_SIZE SRAM_TRACE_SIZE +#define MAILBOX_TRACE_BASE SRAM_TRACE_BASE + + /* window 2 debug, exception and stream */ +#define MAILBOX_DEBUG_SIZE SRAM_DEBUG_SIZE +#define MAILBOX_DEBUG_BASE SRAM_DEBUG_BASE + +#define MAILBOX_EXCEPTION_SIZE SRAM_EXCEPT_SIZE +#define MAILBOX_EXCEPTION_BASE SRAM_EXCEPT_BASE +#define MAILBOX_EXCEPTION_OFFSET SRAM_DEBUG_SIZE + +#define MAILBOX_STREAM_SIZE SRAM_STREAM_SIZE +#define MAILBOX_STREAM_BASE SRAM_STREAM_BASE +#define MAILBOX_STREAM_OFFSET (SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE) + + /* window 1 inbox/downlink and FW registers */ +#define MAILBOX_HOSTBOX_SIZE SRAM_INBOX_SIZE +#define MAILBOX_HOSTBOX_BASE SRAM_INBOX_BASE + + /* window 0 */ +#define MAILBOX_DSPBOX_SIZE SRAM_OUTBOX_SIZE +#define MAILBOX_DSPBOX_BASE SRAM_OUTBOX_BASE + +#define MAILBOX_SW_REG_SIZE SRAM_SW_REG_SIZE +#define MAILBOX_SW_REG_BASE SRAM_SW_REG_BASE + +#endif diff --git a/soc/xtensa/intel_apl_adsp/include/platform/memory.h b/soc/xtensa/intel_apl_adsp/include/platform/memory.h new file mode 100644 index 00000000000..57899d7fdc5 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/include/platform/memory.h @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: Apache-2.0 + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +#ifndef __PLATFORM_MEMORY_H__ +#define __PLATFORM_MEMORY_H__ + +/* Memory banks */ + +#define NUM_LP_MEMORY_BANKS 2 + +#define NUM_HP_MEMORY_BANKS 8 + +#define SRAM_BANK_SIZE (64 * 1024) + +#define EBB_BANKS_IN_SEGMENT 32 + +#define EBB_SEGMENT_SIZE EBB_BANKS_IN_SEGMENT + +#define PLATFORM_LPSRAM_EBB_COUNT NUM_LP_MEMORY_BANKS + +#define PLATFORM_HPSRAM_EBB_COUNT NUM_HP_MEMORY_BANKS + +#define LP_SRAM_SIZE (NUM_LP_MEMORY_BANKS * SRAM_BANK_SIZE) + +#define HP_SRAM_SIZE (NUM_HP_MEMORY_BANKS * SRAM_BANK_SIZE) + +#define LPSRAM_MASK(ignored) ((1 << PLATFORM_LPSRAM_EBB_COUNT) - 1) + +#define HPSRAM_MASK(seg_idx) ((1 << (PLATFORM_HPSRAM_EBB_COUNT \ + - EBB_BANKS_IN_SEGMENT * seg_idx)) - 1) + +/* physical DSP addresses */ + +/* shim */ +#define SHIM_BASE 0x00001000 +#define SHIM_SIZE 0x00000100 + +/* IPC to the host */ +#define IPC_HOST_BASE 0x00001180 +#define IPC_HOST_SIZE 0x00000020 + +/* SRAM window for HOST */ +#define HOST_WIN_SIZE 0x00000008 +#define HOST_WIN_BASE(x) (0x00001580 + x * HOST_WIN_SIZE) + +#define L2_VECTOR_SIZE 0x1000 + +/* + * The HP SRAM Region Apollolake is organised like this :- + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | HP_SRAM_BASE | DMA | HEAP_HP_BUFFER_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_TRACE_BASE | Trace Buffer W3| SRAM_TRACE_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_DEBUG_BASE | Debug data W2 | SRAM_DEBUG_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_EXCEPT_BASE | Debug data W2 | SRAM_EXCEPT_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_STREAM_BASE | Stream data W2 | SRAM_STREAM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_INBOX_BASE | Inbox W1 | SRAM_INBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_SW_REG_BASE | SW Registers W0| SRAM_SW_REG_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_OUTBOX_BASE | Outbox W0 | SRAM_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + */ + +/* HP SRAM */ + +#define HP_SRAM_BASE 0xBE000000 +#define HP_SRAM_MASK 0xFF000000 + +/* HP SRAM Heap */ +#define HEAP_HP_BUFFER_BASE HP_SRAM_BASE +#define HEAP_HP_BUFFER_SIZE 0x8000 + +#define HEAP_HP_BUFFER_BLOCK_SIZE 0x180 +#define HEAP_HP_BUFFER_COUNT \ + (HEAP_HP_BUFFER_SIZE / HEAP_HP_BUFFER_BLOCK_SIZE) + +/* HP SRAM windows */ + +/* window 3 */ +#define SRAM_TRACE_BASE SRAM_WND_BASE +#define SRAM_TRACE_SIZE 0x2000 + +/* window 2 */ +#define SRAM_DEBUG_BASE (SRAM_TRACE_BASE + SRAM_TRACE_SIZE) +#define SRAM_DEBUG_SIZE 0x800 + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x800 + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x1000 + +/* window 1 */ +#define SRAM_INBOX_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_INBOX_SIZE 0x2000 + +/* window 0 */ +#define SRAM_SW_REG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_SW_REG_SIZE 0x1000 + +/* SRAM window 0 FW "registers" */ +#define SRAM_REG_ROM_STATUS 0x0 +#define SRAM_REG_FW_STATUS 0x4 +#define SRAM_REG_FW_TRACEP 0x8 +#define SRAM_REG_FW_IPC_RECEIVED_COUNT 0xc +#define SRAM_REG_FW_IPC_PROCESSED_COUNT 0x10 +#define SRAM_REG_FW_END 0x14 + +#define SRAM_OUTBOX_BASE (SRAM_SW_REG_BASE + SRAM_SW_REG_SIZE) +#define SRAM_OUTBOX_SIZE 0x1000 + +#define HP_SRAM_WIN0_BASE SRAM_SW_REG_BASE +#define HP_SRAM_WIN0_SIZE (SRAM_SW_REG_SIZE + SRAM_OUTBOX_SIZE) +#define HP_SRAM_WIN1_BASE SRAM_INBOX_BASE +#define HP_SRAM_WIN1_SIZE SRAM_INBOX_SIZE +#define HP_SRAM_WIN2_BASE SRAM_DEBUG_BASE +#define HP_SRAM_WIN2_SIZE (SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE + \ + SRAM_STREAM_SIZE) +#define HP_SRAM_WIN3_BASE SRAM_TRACE_BASE +#define HP_SRAM_WIN3_SIZE SRAM_TRACE_SIZE + +/* Apollolake HP-SRAM config */ +#define SRAM_ALIAS_OFFSET 0x20000000 + +#define SRAM_WND_BASE (HEAP_HP_BUFFER_BASE + HEAP_HP_BUFFER_SIZE) + +#define HP_SRAM_VECBASE_RESET (HP_SRAM_WIN0_BASE + HP_SRAM_WIN0_SIZE) +#define HP_SRAM_VECBASE_OFFSET 0x0 + +#define SOF_FW_START (HP_SRAM_VECBASE_RESET + 0x400) +#define SOF_FW_BASE (SOF_FW_START) + +/* max size for all var-size sections (text/rodata/bss) */ +#define SOF_FW_MAX_SIZE (0x41000 - 0x400) + +#define SOF_TEXT_START (SOF_FW_START) +#define SOF_TEXT_BASE (SOF_FW_START) + +/* Stack configuration */ +#define SOF_STACK_BASE (HP_SRAM_BASE + HP_SRAM_SIZE) +#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) + +#define SOF_MEMORY_SIZE (SOF_STACK_BASE - HP_SRAM_BASE) + +/* LP SRAM */ +#define LP_SRAM_BASE 0xBE800000 + +/* boot loader in IMR */ +#define IMR_BOOT_LDR_TEXT_ENTRY_BASE 0xB000A000 + +#define IMR_BOOT_LDR_TEXT_ENTRY_SIZE 0x86 + +/* Manifest base address in IMR - used by boot loader copy procedure. */ +#define IMR_BOOT_LDR_MANIFEST_BASE 0xB0004000 + +/* Manifest size (seems unused). */ +#define IMR_BOOT_LDR_MANIFEST_SIZE 0x6000 + +#endif diff --git a/soc/xtensa/intel_apl_adsp/include/platform/platform.h b/soc/xtensa/intel_apl_adsp/include/platform/platform.h new file mode 100644 index 00000000000..95fa5ac17b6 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/include/platform/platform.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: Apache-2.0 + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + * Xiuli Pan + */ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#include + +#include + +#define PLATFORM_RESET_MHE_AT_BOOT 1 + +#define PLATFORM_DISABLE_L2CACHE_AT_BOOT 1 + +#define PLATFORM_MASTER_CORE_ID 0 + +#define MAX_CORE_COUNT 2 + +#if PLATFORM_CORE_COUNT > MAX_CORE_COUNT +#error "Invalid core count - exceeding core limit" +#endif + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include +#include +#include + +/* Host page size */ +#define HOST_PAGE_SIZE 4096 + +#endif /* !defined(__ASSEMBLER__) && !defined(LINKER) */ + +#endif /* __PLATFORM_PLATFORM_H__ */ diff --git a/soc/xtensa/intel_apl_adsp/include/platform/shim.h b/soc/xtensa/intel_apl_adsp/include/platform/shim.h new file mode 100644 index 00000000000..51cb888bfcc --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/include/platform/shim.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: Apache-2.0 + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +#ifndef __PLATFORM_SHIM_H__ +#define __PLATFORM_SHIM_H__ + +#include + +#ifndef ASSEMBLY +#include +#endif + +#if !defined(__ASSEMBLER__) && !defined(LINKER) +#include +#include +#endif + +#ifndef BIT +#define BIT(b) (1 << (b)) +#endif + +/* DSP IPC for Host Registers */ +#define IPC_DIPCT 0x00 +#define IPC_DIPCTE 0x04 +#define IPC_DIPCI 0x08 +#define IPC_DIPCIE 0x0c +#define IPC_DIPCCTL 0x10 + +/* DIPCT */ +#define IPC_DIPCT_BUSY (1 << 31) +#define IPC_DIPCT_MSG_MASK 0x7FFFFFFF + +/* DIPCTE */ +#define IPC_DIPCTE_MSG_MASK 0x3FFFFFFF + +/* DIPCI */ +#define IPC_DIPCI_BUSY (1 << 31) +#define IPC_DIPCI_MSG_MASK 0x7FFFFFFF + +/* DIPCIE */ +#define IPC_DIPCIE_DONE (1 << 30) +#define IPC_DIPCIE_MSG_MASK 0x3FFFFFFF + +/* DIPCCTL */ +#define IPC_DIPCCTL_IPCIDIE (1 << 1) +#define IPC_DIPCCTL_IPCTBIE (1 << 0) + +#define IPC_DSP_OFFSET 0x10 + +#define SHIM_PWRCTL 0x90 +#define SHIM_PWRSTS 0x92 +#define SHIM_LPSCTL 0x94 + +/* HP & LP SRAM Power Gating */ +#define SHIM_HSPGCTL 0x80 +#define SHIM_LSPGCTL 0x84 +#define SHIM_SPSREQ 0xa0 +#define LSPGCTL SHIM_LSPGCTL + +#define SHIM_SPSREQ_RVNNP (0x1 << 0) + +/** \brief LDO Control */ +#define SHIM_LDOCTL 0xA4 +#define SHIM_LDOCTL_HPSRAM_MASK (3 << 0) +#define SHIM_LDOCTL_LPSRAM_MASK (3 << 2) +#define SHIM_LDOCTL_HPSRAM_LDO_ON (3 << 0) +#define SHIM_LDOCTL_LPSRAM_LDO_ON (3 << 2) +#define SHIM_LDOCTL_HPSRAM_LDO_BYPASS BIT(0) +#define SHIM_LDOCTL_LPSRAM_LDO_BYPASS BIT(2) +#define SHIM_LDOCTL_HPSRAM_LDO_OFF (0 << 0) +#define SHIM_LDOCTL_LPSRAM_LDO_OFF (0 << 2) + +#define SHIM_HSPGISTS 0xb0 +#define SHIM_LSPGISTS 0xb4 +#define LSPGISTS (SHIM_BASE + SHIM_LSPGISTS) + + +#define SHIM_LPSCTL_FDSPRUN (0X1 << 9) +#define SHIM_LPSCTL_FDMARUN (0X1 << 8) + +#define SHIM_L2_MECS (SHIM_BASE + 0xd0) + +#define SHIM_L2_CACHE_CTRL (SHIM_BASE + 0x500) +#define SHIM_L2_PREF_CFG (SHIM_BASE + 0x508) +#define SHIM_L2_CACHE_PREF (SHIM_BASE + 0x510) + +/* host windows */ +#define DMWBA(x) (HOST_WIN_BASE(x) + 0x0) +#define DMWLO(x) (HOST_WIN_BASE(x) + 0x4) + +#define DMWBA_ENABLE (1 << 0) +#define DMWBA_READONLY (1 << 1) + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +static inline uint32_t shim_read(uint32_t reg) +{ + return sys_read32(SHIM_BASE + reg); +} + +static inline void shim_write(uint32_t reg, uint32_t val) +{ + sys_write32(val, (SHIM_BASE + reg)); +} + +static inline uint32_t ipc_read(uint32_t reg) +{ + return sys_read32(IPC_HOST_BASE + reg); +} + +static inline void ipc_write(uint32_t reg, uint32_t val) +{ + sys_write32(val, (IPC_HOST_BASE + reg)); +} + +#endif /* !defined(__ASSEMBLER__) && !defined(LINKER) */ + +#endif diff --git a/soc/xtensa/intel_apl_adsp/linker.ld b/soc/xtensa/intel_apl_adsp/linker.ld new file mode 100644 index 00000000000..45e2c2b20ff --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/linker.ld @@ -0,0 +1,497 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the intel_apl_adsp platform + */ + +OUTPUT_ARCH(xtensa) + +#include +#include "memory.h" +#include +#include + +#include +#include + +PROVIDE(__memctl_default = 0x00000000); +PROVIDE(_MemErrorHandler = 0x00000000); + +#define RAMABLE_REGION ram :ram_phdr +#define ROMABLE_REGION ram :ram_phdr +#define LPRAM_REGION lpram + +MEMORY +{ + vector_memory_lit : + org = XCHAL_MEMERROR_VECTOR_PADDR + MEM_ERROR_LIT_SIZE, + len = MEM_ERROR_LIT_SIZE + vector_memory_text : + org = XCHAL_MEMERROR_VECTOR_PADDR, + len = MEM_ERROR_TEXT_SIZE + vector_base_text : + org = XCHAL_VECBASE_RESET_PADDR_SRAM, + len = MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR_SRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR_SRAM, + len = MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR_SRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR_SRAM, + len = MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR_SRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR_SRAM, + len = MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR_SRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR_SRAM, + len = MEM_VECT_TEXT_SIZE + vector_int6_lit : + org = XCHAL_INTLEVEL6_VECTOR_PADDR_SRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_int6_text : + org = XCHAL_INTLEVEL6_VECTOR_PADDR_SRAM, + len = MEM_VECT_TEXT_SIZE + vector_int7_lit : + org = XCHAL_INTLEVEL7_VECTOR_PADDR_SRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_int7_text : + org = XCHAL_INTLEVEL7_VECTOR_PADDR_SRAM, + len = MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR_SRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR_SRAM, + len = MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR_SRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR_SRAM, + len = MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR_SRAM - MEM_VECT_LIT_SIZE, + len = MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR_SRAM, + len = MEM_VECT_TEXT_SIZE + ram : + org = RAM_BASE, + len = RAM_SIZE +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST : + org = IDT_BASE, + len = IDT_SIZE +#endif + lpram : + org = LPRAM_BASE, + len = LPRAM_SIZE +} + +PHDRS +{ + vector_memory_lit_phdr PT_LOAD; + vector_memory_text_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int6_lit_phdr PT_LOAD; + vector_int6_text_phdr PT_LOAD; + vector_int7_lit_phdr PT_LOAD; + vector_int7_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + ram_phdr PT_LOAD; +} +_rom_store_table = 0; +PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR_SRAM); + +ENTRY(CONFIG_KERNEL_ENTRY) + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x44024000; +_memmap_cacheattr_wt_base = 0x11021000; +_memmap_cacheattr_bp_base = 0x22022000; +_memmap_cacheattr_unused_mask = 0x00F00FFF; +_memmap_cacheattr_wb_trapnull = 0x4422422F; +_memmap_cacheattr_wba_trapnull = 0x4422422F; +_memmap_cacheattr_wbna_trapnull = 0x25222222; +_memmap_cacheattr_wt_trapnull = 0x1122122F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0x44F24FFF; +_memmap_cacheattr_wt_strict = 0x11F21FFF; +_memmap_cacheattr_bp_strict = 0x22F22FFF; +_memmap_cacheattr_wb_allvalid = 0x44224222; +_memmap_cacheattr_wt_allvalid = 0x11221222; +_memmap_cacheattr_bp_allvalid = 0x22222222; + +/* + * Cache attributes for memory addresses: + * (Each 4 bits correspond to 512MB of memory) + * + * 0x00000000 - 0x1FFFFFFF (bit 0 - 3) : Bypass cache + * (region for hardware registers) + * 0x20000000 - 0x3FFFFFFF (bit 4 - 7) : No access + * 0x40000000 - 0x5FFFFFFF (bit 8 - 11) : No access + * 0x60000000 - 0x7FFFFFFF (bit 12 - 15) : No access + * 0x80000000 - 0x9FFFFFFF (bit 16 - 19) : Bypass cache + * 0xA0000000 - 0xBFFFFFFF (bit 20 - 23) : Cached, write-back + * 0xC0000000 - 0xDFFFFFFF (bit 24 - 27) : No access + * 0xE0000000 - 0xFFFFFFFF (bit 28 - 31) : No access + * + * Note that this is both for instruction and data caches, + * as cacheattr_set macro sets them both to the same set of + * attributes. + */ +_memmap_cacheattr_intel_apl_adsp = 0xFF42FFF2; + +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_intel_apl_adsp); +SECTIONS +{ + +#include + + .MemoryExceptionVector.literal : ALIGN(4) + { + _MemoryExceptionVector_literal_start = ABSOLUTE(.); + KEEP (*(.MemoryExceptionVector.literal)) + _MemoryExceptionVector_literal_end = ABSOLUTE(.); + } >vector_memory_lit :vector_memory_lit_phdr + .MemoryExceptionVector.text : ALIGN(4) + { + _MemoryExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.MemoryExceptionVector.text)) + _MemoryExceptionVector_text_end = ABSOLUTE(.); + } >vector_memory_text :vector_memory_text_phdr + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + .Level4InterruptVector.literal : ALIGN(4) + { + _Level4InterruptVector_literal_start = ABSOLUTE(.); + *(.Level4InterruptVector.literal) + _Level4InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + .Level4InterruptVector.text : ALIGN(4) + { + _Level4InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level4InterruptVector.text)) + _Level4InterruptVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + .Level5InterruptVector.literal : ALIGN(4) + { + _Level5InterruptVector_literal_start = ABSOLUTE(.); + *(.Level5InterruptVector.literal) + _Level5InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + .Level5InterruptVector.text : ALIGN(4) + { + _Level5InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level5InterruptVector.text)) + _Level5InterruptVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int6_lit :vector_int6_lit_phdr + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int6_text :vector_int6_text_phdr + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int7_lit :vector_int7_lit_phdr + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int7_text :vector_int7_text_phdr + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + KEEP(*(.MainEntry.text)) + *(.MainEntry.literal) + KEEP (*(.ResetVector.text)) + *(.ResetVector.literal) + *(.entry.text) + *(.init.literal) + *(.iram0.text) + KEEP(*(.init)) + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + KEEP(*(.fini)) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + . = ALIGN(4096); + } >ram :ram_phdr + + .rodata : ALIGN(4096) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + KEEP (*(.xt_except_table)) + KEEP (*(.gcc_except_table .gcc_except_table.*)) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + KEEP (*(.eh_frame)) + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >ram :ram_phdr + +#include + + .fw_ready : ALIGN(4) + { + KEEP(*(".fw_ready")); + } >ram :ram_phdr + + .noinit : ALIGN(4) + { + *(.noinit) + *(.noinit.*) + } >ram :ram_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + . = ALIGN(4096); + *(.gna_model) + _data_end = ABSOLUTE(.); + . = ALIGN(4096); + } >ram :ram_phdr + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >ram :ram_phdr +#include + + .bss (NOLOAD) : ALIGN(4096) + { + . = ALIGN(4096); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + _bss_end = ABSOLUTE(.); + } >ram :ram_phdr + + /* stack */ + _end = ALIGN(8); + PROVIDE(end = ALIGN(8)); + __stack = DT_L2_SRAM_BASE + DT_L2_SRAM_SIZE; + /* dma buffers */ + .lpbuf (NOLOAD): ALIGN(4) + { + _dma_buf_start = ABSOLUTE(.); + *(.dma_buffers) + _dma_buf_end = ABSOLUTE(.); + } >LPRAM_REGION + _heap_sentry = DT_L2_SRAM_BASE + DT_L2_SRAM_SIZE; + .comment 0 : { *(.comment) } + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + .debug_ranges 0 : { *(.debug_ranges) } + .xtensa.info 0 : { *(.xtensa.info) } + .xt.insn 0 : + { + KEEP (*(.xt.insn)) + KEEP (*(.gnu.linkonce.x.*)) + } + .xt.prop 0 : + { + KEEP (*(.xt.prop)) + KEEP (*(.xt.prop.*)) + KEEP (*(.gnu.linkonce.prop.*)) + } + .xt.lit 0 : + { + KEEP (*(.xt.lit)) + KEEP (*(.xt.lit.*)) + KEEP (*(.gnu.linkonce.p.*)) + } + .xt.profile_range 0 : + { + KEEP (*(.xt.profile_range)) + KEEP (*(.gnu.linkonce.profile_range.*)) + } + .xt.profile_ranges 0 : + { + KEEP (*(.xt.profile_ranges)) + KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) + } + .xt.profile_files 0 : + { + KEEP (*(.xt.profile_files)) + KEEP (*(.gnu.linkonce.xt.profile_files.*)) + } +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif +} diff --git a/soc/xtensa/intel_apl_adsp/main_entry.S b/soc/xtensa/intel_apl_adsp/main_entry.S new file mode 100644 index 00000000000..efcebf91ac2 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/main_entry.S @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: Apache-2.0 + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Rander Wang + */ + +/* + * Entry point from boot loader. + * Fix link address of this entry to SOF_TEXT_START so that + * it is easy for boot loader to jump to the baseFW because + * the boot loader and baseFW are in different elf file. + */ + + +// Exports +.global _MainEntry + + +/**************************************************************************/ + + .begin literal_prefix .MainEntry + .section .MainEntry.text, "ax" + + .align 4 + .global _MainEntry + +_MainEntry: + + j __start + + .size _MainEntry, . - _MainEntry + + .end literal_prefix diff --git a/soc/xtensa/intel_apl_adsp/memory.h b/soc/xtensa/intel_apl_adsp/memory.h new file mode 100644 index 00000000000..4e57e493df7 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/memory.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2019 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __INC_MEMORY_H +#define __INC_MEMORY_H + +/* L2 HP SRAM */ +#define HP_RAM_RESERVE_HEADER_SPACE 0x00010000 + +#ifdef CONFIG_BOOTLOADER_MCUBOOT +#define SRAM_BASE (DT_L2_SRAM_BASE + CONFIG_BOOTLOADER_SRAM_SIZE * 1K) +#define SRAM_SIZE (DT_L2_SRAM_SIZE - CONFIG_BOOTLOADER_SRAM_SIZE * 1K) +#else +#define SRAM_BASE (DT_L2_SRAM_BASE) +#define SRAM_SIZE (DT_L2_SRAM_SIZE) +#endif + +/* The reset vector address in SRAM and its size */ +#define XCHAL_RESET_VECTOR0_PADDR_SRAM SRAM_BASE +#define MEM_RESET_TEXT_SIZE 0x268 +#define MEM_RESET_LIT_SIZE 0x8 + +/* This is the base address of all the vectors defined in SRAM */ +#define XCHAL_VECBASE_RESET_PADDR_SRAM \ + (SRAM_BASE + HP_RAM_RESERVE_HEADER_SPACE) + +#define MEM_VECBASE_LIT_SIZE 0x178 + +/* The addresses of the vectors in SRAM. + * Only the memerror vector continues to point to its ROM address. + */ +#define XCHAL_INTLEVEL2_VECTOR_PADDR_SRAM \ + (XCHAL_VECBASE_RESET_PADDR_SRAM + 0x180) + +#define XCHAL_INTLEVEL3_VECTOR_PADDR_SRAM \ + (XCHAL_VECBASE_RESET_PADDR_SRAM + 0x1C0) + +#define XCHAL_INTLEVEL4_VECTOR_PADDR_SRAM \ + (XCHAL_VECBASE_RESET_PADDR_SRAM + 0x200) + +#define XCHAL_INTLEVEL5_VECTOR_PADDR_SRAM \ + (XCHAL_VECBASE_RESET_PADDR_SRAM + 0x240) + +#define XCHAL_INTLEVEL6_VECTOR_PADDR_SRAM \ + (XCHAL_VECBASE_RESET_PADDR_SRAM + 0x280) + +#define XCHAL_INTLEVEL7_VECTOR_PADDR_SRAM \ + (XCHAL_VECBASE_RESET_PADDR_SRAM + 0x2C0) + +#define XCHAL_KERNEL_VECTOR_PADDR_SRAM \ + (XCHAL_VECBASE_RESET_PADDR_SRAM + 0x300) + +#define XCHAL_USER_VECTOR_PADDR_SRAM \ + (XCHAL_VECBASE_RESET_PADDR_SRAM + 0x340) + +#define XCHAL_DOUBLEEXC_VECTOR_PADDR_SRAM \ + (XCHAL_VECBASE_RESET_PADDR_SRAM + 0x3C0) + +#define VECTOR_TBL_SIZE 0x0400 + +/* Vector and literal sizes */ +#define MEM_VECT_LIT_SIZE 0x8 +#define MEM_VECT_TEXT_SIZE 0x38 +#define MEM_VECT_SIZE (MEM_VECT_TEXT_SIZE +\ + MEM_VECT_LIT_SIZE) + +/* The memerror vector address is copied as is from core-isa.h */ +#define XCHAL_MEMERROR_VECTOR_PADDR 0xBEFE0400 + +#define MEM_ERROR_TEXT_SIZE 0x180 +#define MEM_ERROR_LIT_SIZE 0x8 + +/* text and data share the same L2 HP SRAM. + * So, they lie next to each other. + */ +#define RAM_BASE \ + (SRAM_BASE + HP_RAM_RESERVE_HEADER_SPACE + VECTOR_TBL_SIZE) + +#define RAM_SIZE \ + (SRAM_SIZE - HP_RAM_RESERVE_HEADER_SPACE - VECTOR_TBL_SIZE) + +/* Location for the intList section which is later used to construct the + * Interrupt Descriptor Table (IDT). This is a bogus address as this + * section will be stripped off in the final image. + */ +#define IDT_BASE (RAM_BASE + RAM_SIZE) + +/* size of the Interrupt Descriptor Table (IDT) */ +#define IDT_SIZE 0x2000 + +/* low power ram where DMA buffers are typically placed */ +#define LPRAM_BASE (DT_LP_SRAM_BASE) +#define LPRAM_SIZE (DT_LP_SRAM_SIZE) + +#include + +#endif /* __INC_MEMORY_H */ diff --git a/soc/xtensa/intel_apl_adsp/soc.c b/soc/xtensa/intel_apl_adsp/soc.c new file mode 100644 index 00000000000..fe5ecd47825 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/soc.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include "soc.h" + +#ifdef CONFIG_DYNAMIC_INTERRUPTS +#include +#endif + +#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL +#include +LOG_MODULE_REGISTER(soc); + +void z_soc_irq_enable(u32_t irq) +{ + struct device *dev_cavs; + + switch (XTENSA_IRQ_NUMBER(irq)) { + case DT_CAVS_ICTL_0_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_0_NAME); + break; + case DT_CAVS_ICTL_1_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_1_NAME); + break; + case DT_CAVS_ICTL_2_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_2_NAME); + break; + case DT_CAVS_ICTL_3_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_3_NAME); + break; + default: + /* regular interrupt */ + z_xtensa_irq_enable(XTENSA_IRQ_NUMBER(irq)); + return; + } + + if (!dev_cavs) { + LOG_DBG("board: CAVS device binding failed"); + return; + } + + /* + * The specified interrupt is in CAVS interrupt controller. + * So enable core interrupt first. + */ + z_xtensa_irq_enable(XTENSA_IRQ_NUMBER(irq)); + + /* Then enable the interrupt in CAVS interrupt controller */ + irq_enable_next_level(dev_cavs, CAVS_IRQ_NUMBER(irq)); +} + +void z_soc_irq_disable(u32_t irq) +{ + struct device *dev_cavs; + + switch (XTENSA_IRQ_NUMBER(irq)) { + case DT_CAVS_ICTL_0_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_0_NAME); + break; + case DT_CAVS_ICTL_1_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_1_NAME); + break; + case DT_CAVS_ICTL_2_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_2_NAME); + break; + case DT_CAVS_ICTL_3_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_3_NAME); + break; + default: + /* regular interrupt */ + z_xtensa_irq_disable(XTENSA_IRQ_NUMBER(irq)); + return; + } + + if (!dev_cavs) { + LOG_DBG("board: CAVS device binding failed"); + return; + } + + /* + * The specified interrupt is in CAVS interrupt controller. + * So disable the interrupt in CAVS interrupt controller. + */ + irq_disable_next_level(dev_cavs, CAVS_IRQ_NUMBER(irq)); + + /* Then disable the parent IRQ if all children are disabled */ + if (!irq_is_enabled_next_level(dev_cavs)) { + z_xtensa_irq_disable(XTENSA_IRQ_NUMBER(irq)); + } +} + +int z_soc_irq_is_enabled(unsigned int irq) +{ + struct device *dev_cavs; + int ret = 0; + + switch (XTENSA_IRQ_NUMBER(irq)) { + case DT_CAVS_ICTL_0_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_0_NAME); + break; + case DT_CAVS_ICTL_1_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_1_NAME); + break; + case DT_CAVS_ICTL_2_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_2_NAME); + break; + case DT_CAVS_ICTL_3_IRQ: + dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_3_NAME); + break; + default: + /* regular interrupt */ + ret = z_xtensa_irq_is_enabled(XTENSA_IRQ_NUMBER(irq)); + goto out; + } + + if (!dev_cavs) { + LOG_DBG("board: CAVS device binding failed"); + ret = -ENODEV; + goto out; + } + + /* Then enable the interrupt in CAVS interrupt controller */ + ret = irq_line_is_enabled_next_level(dev_cavs, CAVS_IRQ_NUMBER(irq)); + +out: + return ret; +} + +#ifdef CONFIG_DYNAMIC_INTERRUPTS +int z_soc_irq_connect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(void *parameter), + void *parameter, u32_t flags) +{ + uint32_t table_idx; + uint32_t cavs_irq; + int ret; + + ARG_UNUSED(flags); + ARG_UNUSED(priority); + + /* extract 2nd level interrupt number */ + cavs_irq = CAVS_IRQ_NUMBER(irq); + ret = irq; + + if (cavs_irq == 0) { + /* Not affecting 2nd level interrupts */ + z_isr_install(irq, routine, parameter); + goto irq_connect_out; + } + + /* Figure out the base index. */ + switch (XTENSA_IRQ_NUMBER(irq)) { + case DT_CAVS_ICTL_0_IRQ: + table_idx = CONFIG_CAVS_ISR_TBL_OFFSET; + break; + case DT_CAVS_ICTL_1_IRQ: + table_idx = CONFIG_CAVS_ISR_TBL_OFFSET + + CONFIG_MAX_IRQ_PER_AGGREGATOR; + break; + case DT_CAVS_ICTL_2_IRQ: + table_idx = CONFIG_CAVS_ISR_TBL_OFFSET + + CONFIG_MAX_IRQ_PER_AGGREGATOR * 2; + break; + case DT_CAVS_ICTL_3_IRQ: + table_idx = CONFIG_CAVS_ISR_TBL_OFFSET + + CONFIG_MAX_IRQ_PER_AGGREGATOR * 3; + break; + default: + ret = -EINVAL; + goto irq_connect_out; + } + + table_idx += cavs_irq; + + _sw_isr_table[table_idx].arg = parameter; + _sw_isr_table[table_idx].isr = routine; + +irq_connect_out: + return ret; +} +#endif + +static inline void soc_set_power_and_clock(void) +{ + volatile struct soc_dsp_shim_regs *dsp_shim_regs = + (volatile struct soc_dsp_shim_regs *)SOC_DSP_SHIM_REG_BASE; + + /* + * DSP Core 0 PLL Clock Select divide by 1 + * DSP Core 1 PLL Clock Select divide by 1 + * Low Power Domain Clock Select depends on LMPCS bit + * High Power Domain Clock Select depands on HMPCS bit + * Low Power Domain PLL Clock Select device by 4 + * High Power Domain PLL Clock Select device by 2 + * Tensilica Core Prevent Audio PLL Shutdown (TCPAPLLS) + * Tensilica Core Prevent Local Clock Gating (Core 0) + * Tensilica Core Prevent Local Clock Gating (Core 1) + */ + dsp_shim_regs->clkctl = + SOC_CLKCTL_DPCS_DIV1(0) | + SOC_CLKCTL_DPCS_DIV1(1) | + SOC_CLKCTL_LDCS_LMPCS | + SOC_CLKCTL_HDCS_HMPCS | + SOC_CLKCTL_LPMEM_PLL_CLK_SEL_DIV4 | + SOC_CLKCTL_HPMEM_PLL_CLK_SEL_DIV2 | + SOC_CLKCTL_TCPAPLLS | + SOC_CLKCTL_TCPLCG_DIS(0) | + SOC_CLKCTL_TCPLCG_DIS(1); + + /* Disable power gating for both cores */ + dsp_shim_regs->pwrctl |= SOC_PWRCTL_DISABLE_PWR_GATING_DSP1 | + SOC_PWRCTL_DISABLE_PWR_GATING_DSP0; + + /* Rewrite the low power sequencing control bits */ + dsp_shim_regs->lpsctl = dsp_shim_regs->lpsctl; +} + +static int soc_init(struct device *dev) +{ + soc_set_power_and_clock(); + + return 0; +} + +SYS_INIT(soc_init, PRE_KERNEL_1, 99); diff --git a/soc/xtensa/intel_apl_adsp/soc.h b/soc/xtensa/intel_apl_adsp/soc.h new file mode 100644 index 00000000000..72503265299 --- /dev/null +++ b/soc/xtensa/intel_apl_adsp/soc.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2019 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#include "memory.h" + +#ifndef __INC_SOC_H +#define __INC_SOC_H + +/* macros related to interrupt handling */ +#define XTENSA_IRQ_NUM_SHIFT 0 +#define CAVS_IRQ_NUM_SHIFT 8 +#define XTENSA_IRQ_NUM_MASK 0xff +#define CAVS_IRQ_NUM_MASK 0xff + +/* + * IRQs are mapped on 2 levels. 3rd and 4th level are left as 0x00. + * + * 1. Peripheral Register bit offset. + * 2. CAVS logic bit offset. + */ +#define XTENSA_IRQ_NUMBER(_irq) \ + ((_irq >> XTENSA_IRQ_NUM_SHIFT) & XTENSA_IRQ_NUM_MASK) +#define CAVS_IRQ_NUMBER(_irq) \ + (((_irq >> CAVS_IRQ_NUM_SHIFT) & CAVS_IRQ_NUM_MASK) - 1) + +/* Macro that aggregates the bi-level interrupt into an IRQ number */ +#define SOC_AGGREGATE_IRQ(cavs_irq, core_irq) \ + ( \ + ((core_irq & XTENSA_IRQ_NUM_MASK) << XTENSA_IRQ_NUM_SHIFT) | \ + (((cavs_irq + 1) & CAVS_IRQ_NUM_MASK) << CAVS_IRQ_NUM_SHIFT) \ + ) + +#define CAVS_L2_AGG_INT_LEVEL2 DT_CAVS_ICTL_0_IRQ +#define CAVS_L2_AGG_INT_LEVEL3 DT_CAVS_ICTL_1_IRQ +#define CAVS_L2_AGG_INT_LEVEL4 DT_CAVS_ICTL_2_IRQ +#define CAVS_L2_AGG_INT_LEVEL5 DT_CAVS_ICTL_3_IRQ + +#define IOAPIC_EDGE 0 +#define IOAPIC_HIGH 0 + +/* low power DMACs */ +#define LP_GP_DMA_SIZE 0x00001000 +#define DW_DMA0_BASE_ADDR 0x0000C000 +#define DW_DMA1_BASE_ADDR (0x0000C000 +\ + 1 * LP_GP_DMA_SIZE) +#define DW_DMA2_BASE_ADDR (0x0000C000 +\ + 2 * LP_GP_DMA_SIZE) + +#define DW_DMA0_IRQ 0x00001110 +#define DW_DMA1_IRQ 0x0000010A +#define DW_DMA2_IRQ 0x0000010D + +/* address of DMA ownership register. We need to properly configure + * this register in order to access the DMA registers. + */ +#define CAVS_DMA0_OWNERSHIP_REG (0x00071A60) +#define CAVS_DMA1_OWNERSHIP_REG (0x00071A62) +#define CAVS_DMA2_OWNERSHIP_REG (0x00071A64) + +#define DMA_HANDSHAKE_DMIC_RXA 0 +#define DMA_HANDSHAKE_DMIC_RXB 1 +#define DMA_HANDSHAKE_SSP0_TX 2 +#define DMA_HANDSHAKE_SSP0_RX 3 +#define DMA_HANDSHAKE_SSP1_TX 4 +#define DMA_HANDSHAKE_SSP1_RX 5 +#define DMA_HANDSHAKE_SSP2_TX 6 +#define DMA_HANDSHAKE_SSP2_RX 7 +#define DMA_HANDSHAKE_SSP3_TX 8 +#define DMA_HANDSHAKE_SSP3_RX 9 + +/* DMA Channel Allocation + * FIXME: I2S Driver assigns channel in Kconfig. + * Perhaps DTS is a better option + */ +#define DMIC_DMA_DEV_NAME CONFIG_DMA_0_NAME +#define DMA_CHANNEL_DMIC_RXA 0 +#define DMA_CHANNEL_DMIC_RXB 1 + +/* I2S */ +#define I2S_CAVS_IRQ(i2s_num) \ + SOC_AGGREGATE_IRQ(0, (i2s_num), CAVS_L2_AGG_INT_LEVEL5) + +#define I2S0_CAVS_IRQ I2S_CAVS_IRQ(0) +#define I2S1_CAVS_IRQ I2S_CAVS_IRQ(1) +#define I2S2_CAVS_IRQ I2S_CAVS_IRQ(2) +#define I2S3_CAVS_IRQ I2S_CAVS_IRQ(3) + +#define SSP_MN_DIV_SIZE (8) +#define SSP_MN_DIV_BASE(x) \ + (0x00078D00 + ((x) * SSP_MN_DIV_SIZE)) + +/* MCLK control */ +#define SOC_MCLK_DIV_CTRL_BASE 0x00008E00 +#define SOC_NUM_MCLK_OUTPUTS 2 +#define SOC_MDIVCTRL_MCLK_OUT_EN(mclk) BIT(mclk) +#define SOC_MDIVXR_SET_DIVIDER_BYPASS BIT_MASK(12) + +struct soc_mclk_control_regs { + u32_t mdivctrl; + u32_t reserved[31]; + u32_t mdivxr[SOC_NUM_MCLK_OUTPUTS]; +}; + +#define PDM_BASE 0x00010000 + +#define SOC_NUM_LPGPDMAC 3 +#define SOC_NUM_CHANNELS_IN_DMAC 8 + +/* SOC Resource Allocation Registers */ +#define SOC_RESOURCE_ALLOC_REG_BASE 0x00071A60 +/* bit field definition for LP GPDMA ownership register */ +#define SOC_LPGPDMAC_OWNER_DSP \ + (BIT(15) | BIT_MASK(SOC_NUM_CHANNELS_IN_DMAC)) + +#define SOC_NUM_I2S_INSTANCES 4 +/* bit field definition for IO peripheral ownership register */ +#define SOC_DSPIOP_I2S_OWNSEL_DSP \ + (BIT_MASK(SOC_NUM_I2S_INSTANCES) << 8) +#define SOC_DSPIOP_DMIC_OWNSEL_DSP BIT(0) + +/* bit field definition for general ownership register */ +#define SOC_GENO_TIMESTAMP_OWNER_DSP BIT(2) +#define SOC_GENO_MNDIV_OWNER_DSP BIT(1) + +struct soc_resource_alloc_regs { + union { + u16_t lpgpdmacxo[SOC_NUM_LPGPDMAC]; + u16_t reserved[4]; + }; + u32_t dspiopo; + u32_t geno; +}; + +/* DMIC SHIM Registers */ +#define SOC_DMIC_SHIM_REG_BASE 0x00071E80 +#define SOC_DMIC_SHIM_DMICLCTL_SPA BIT(0) +#define SOC_DMIC_SHIM_DMICLCTL_CPA BIT(8) + +struct soc_dmic_shim_regs { + u32_t dmiclcap; + u32_t dmiclctl; +}; + +/* SOC DSP SHIM Registers */ +#define SOC_DSP_SHIM_REG_BASE 0x00001000 + +/* SOC DSP SHIM Register - Clock Control */ +#define SOC_CLKCTL_REQ_AUDIO_PLL_CLK BIT(31) +#define SOC_CLKCTL_REQ_XTAL_CLK BIT(30) +#define SOC_CLKCTL_REQ_FAST_CLK BIT(29) + +#define SOC_CLKCTL_TCPLCG_POS(x) (16 + x) +#define SOC_CLKCTL_TCPLCG_DIS(x) (1 << SOC_CLKCTL_TCPLCG_POS(x)) + +#define SOC_CLKCTL_DPCS_POS(x) (8 + x) +#define SOC_CLKCTL_DPCS_DIV1(x) (0 << SOC_CLKCTL_DPCS_POS(x)) +#define SOC_CLKCTL_DPCS_DIV2(x) (1 << SOC_CLKCTL_DPCS_POS(x)) +#define SOC_CLKCTL_DPCS_DIV4(x) (3 << SOC_CLKCTL_DPCS_POS(x)) + +#define SOC_CLKCTL_TCPAPLLS BIT(7) + +#define SOC_CLKCTL_LDCS_POS (5) +#define SOC_CLKCTL_LDCS_LMPCS (0 << SOC_CLKCTL_LDCS_POS) +#define SOC_CLKCTL_LDCS_LDOCS (1 << SOC_CLKCTL_LDCS_POS) + +#define SOC_CLKCTL_HDCS_POS (4) +#define SOC_CLKCTL_HDCS_HMPCS (0 << SOC_CLKCTL_HDCS_POS) +#define SOC_CLKCTL_HDCS_HDOCS (1 << SOC_CLKCTL_HDCS_POS) + +#define SOC_CLKCTL_LDOCS_POS (3) +#define SOC_CLKCTL_LDOCS_PLL (0 << SOC_CLKCTL_LDOCS_POS) +#define SOC_CLKCTL_LDOCS_FAST (1 << SOC_CLKCTL_LDOCS_POS) + +#define SOC_CLKCTL_HDOCS_POS (2) +#define SOC_CLKCTL_HDOCS_PLL (0 << SOC_CLKCTL_HDOCS_POS) +#define SOC_CLKCTL_HDOCS_FAST (1 << SOC_CLKCTL_HDOCS_POS) + +#define SOC_CLKCTL_LPMEM_PLL_CLK_SEL_POS (1) +#define SOC_CLKCTL_LPMEM_PLL_CLK_SEL_DIV2 \ + (0 << SOC_CLKCTL_LPMEM_PLL_CLK_SEL_POS) +#define SOC_CLKCTL_LPMEM_PLL_CLK_SEL_DIV4 \ + (1 << SOC_CLKCTL_LPMEM_PLL_CLK_SEL_POS) + +#define SOC_CLKCTL_HPMEM_PLL_CLK_SEL_POS (0) +#define SOC_CLKCTL_HPMEM_PLL_CLK_SEL_DIV2 \ + (0 << SOC_CLKCTL_HPMEM_PLL_CLK_SEL_POS) +#define SOC_CLKCTL_HPMEM_PLL_CLK_SEL_DIV4 \ + (1 << SOC_CLKCTL_HPMEM_PLL_CLK_SEL_POS) + +/* SOC DSP SHIM Register - Power Control */ +#define SOC_PWRCTL_DISABLE_PWR_GATING_DSP0 BIT(0) +#define SOC_PWRCTL_DISABLE_PWR_GATING_DSP1 BIT(1) + +struct soc_dsp_shim_regs { + u32_t reserved[8]; + u64_t walclk; + u64_t dspwctcs; + u64_t dspwct0c; + u64_t dspwct1c; + u32_t reserved1[14]; + u32_t clkctl; + u32_t clksts; + u32_t reserved2[4]; + u16_t pwrctl; + u16_t pwrsts; + u32_t lpsctl; + u32_t lpsdmas0; + u32_t lpsdmas1; + u32_t reserved3[22]; +}; + +/* macros for data cache operations */ +#define SOC_DCACHE_FLUSH(addr, size) \ + xthal_dcache_region_writeback((addr), (size)) +#define SOC_DCACHE_INVALIDATE(addr, size) \ + xthal_dcache_region_invalidate((addr), (size)) + +extern void z_soc_irq_enable(u32_t irq); +extern void z_soc_irq_disable(u32_t irq); +extern int z_soc_irq_is_enabled(unsigned int irq); + +#endif /* __INC_SOC_H */