From 6206a16da1b17a73954e4f9067ff17c714069424 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Mon, 12 Dec 2022 22:19:46 +0000 Subject: [PATCH 1/8] xtos: mailbox: use memcpy for host mailbox_write Host based mailbox needs to be fixed in another place. It's here now until rtos partitioning is done. Signed-off-by: Liam Girdwood Signed-off-by: Ranjani Sridharan --- xtos/include/sof/lib/mailbox.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/xtos/include/sof/lib/mailbox.h b/xtos/include/sof/lib/mailbox.h index 86fc900138b3..06e2659a5847 100644 --- a/xtos/include/sof/lib/mailbox.h +++ b/xtos/include/sof/lib/mailbox.h @@ -69,9 +69,8 @@ void mailbox_dspbox_read(void *dest, size_t dest_size, #if CONFIG_LIBRARY -static inline -void mailbox_hostbox_write(size_t offset, const void *src, size_t bytes) -{} +#define mailbox_hostbox_write(_offset, _src, _bytes) \ + memcpy((char *)ipc->comp_data + _offset, _src, _bytes) #else From b6a8a180e67ebfd648d150e4c3eddb0c1dc46397 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Mon, 12 Dec 2022 22:22:50 +0000 Subject: [PATCH 2/8] host: cmake: make sure we build maths support for host config Add maths directory for host. Signed-off-by: Liam Girdwood Signed-off-by: Ranjani Sridharan --- src/math/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/math/CMakeLists.txt b/src/math/CMakeLists.txt index d27063c80b0d..899810544864 100644 --- a/src/math/CMakeLists.txt +++ b/src/math/CMakeLists.txt @@ -1,6 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause if(BUILD_LIBRARY) + add_local_sources(sof numbers.c) return() endif() From c9f06f7920ae49703de492291358a2e13a64dc19 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Mon, 28 Aug 2023 14:21:56 -0700 Subject: [PATCH 3/8] host: trace: decouple the testbench from host build Host build should not depend on testbench symbols. Also add timestamp to the trace log. Signed-off-by: Liam Girdwood Signed-off-by: Ranjani Sridharan --- src/include/sof/trace/trace.h | 29 ++++++++++++++--------- src/platform/library/lib/trace.c | 3 +-- test/cmocka/src/common_mocks.c | 2 ++ tools/testbench/common_test.c | 8 +++---- tools/testbench/include/testbench/trace.h | 2 +- tools/testbench/testbench.c | 10 ++++---- 6 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/include/sof/trace/trace.h b/src/include/sof/trace/trace.h index d3953bd16afe..737f9913cf6f 100644 --- a/src/include/sof/trace/trace.h +++ b/src/include/sof/trace/trace.h @@ -233,19 +233,26 @@ void _log_sofdict(log_func_t sofdict_logf, bool atomic, const void *log_entry, #ifdef CONFIG_LIBRARY -extern int test_bench_trace; +#include + +/* trace level used on host configurations */ +extern int host_trace_level; + char *get_trace_class(uint32_t trace_class); #define _log_message(ignored_log_func, atomic, level, comp_class, ctx, id_1, id_2, format, ...) \ -do { \ - (void)ctx; \ - (void)id_1; \ - (void)id_2; \ - if (test_bench_trace) { \ - char *msg = "(%s:%d) " format; \ - fprintf(stderr, msg, strrchr(__FILE__, '/') + 1,\ - __LINE__, ##__VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } \ +do { \ + (void)ctx; \ + (void)id_1; \ + (void)id_2; \ + struct timeval tv; \ + char *msg = "(%s:%d) " format; \ + if (level >= host_trace_level) { \ + gettimeofday(&tv, NULL); \ + fprintf(stderr, "%ld.%6.6ld:", tv.tv_sec, tv.tv_usec); \ + fprintf(stderr, msg, strrchr(__FILE__, '/') + 1, \ + __LINE__, ##__VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } \ } while (0) #define trace_point(x) do {} while (0) diff --git a/src/platform/library/lib/trace.c b/src/platform/library/lib/trace.c index fdd00b7777b6..7ca847afabec 100644 --- a/src/platform/library/lib/trace.c +++ b/src/platform/library/lib/trace.c @@ -12,8 +12,7 @@ #include /* enable trace by default in testbench */ -int test_bench_trace = 1; -int debug; +int host_trace_level = LOG_LEVEL_ERROR; /* look up subsystem class name from table */ char *get_trace_class(uint32_t trace_class) diff --git a/test/cmocka/src/common_mocks.c b/test/cmocka/src/common_mocks.c index 180c2028b019..630bdd0a0d13 100644 --- a/test/cmocka/src/common_mocks.c +++ b/test/cmocka/src/common_mocks.c @@ -41,6 +41,8 @@ WEAK struct tr_ctx buffer_tr; WEAK struct tr_ctx comp_tr; WEAK struct tr_ctx ipc_tr; +int host_trace_level = 1; + void WEAK *rballoc_align(uint32_t flags, uint32_t caps, size_t bytes, uint32_t alignment) { diff --git a/tools/testbench/common_test.c b/tools/testbench/common_test.c index c42ae4cd470e..02144b3b5ee5 100644 --- a/tools/testbench/common_test.c +++ b/tools/testbench/common_test.c @@ -264,15 +264,15 @@ int tb_pipeline_params(struct testbench_prm *tp, struct ipc *ipc, struct pipelin /* print debug messages */ void debug_print(char *message) { - if (debug) + if (host_trace_level >= LOG_LEVEL_DEBUG) printf("debug: %s", message); } /* enable trace in testbench */ -void tb_enable_trace(bool enable) +void tb_enable_trace(unsigned int log_level) { - test_bench_trace = enable; - if (enable) + host_trace_level = log_level; + if (host_trace_level) debug_print("trace print enabled\n"); else debug_print("trace print disabled\n"); diff --git a/tools/testbench/include/testbench/trace.h b/tools/testbench/include/testbench/trace.h index 73c50d43853d..66e63e217adf 100644 --- a/tools/testbench/include/testbench/trace.h +++ b/tools/testbench/include/testbench/trace.h @@ -11,6 +11,6 @@ #ifndef _TRACE_H #define _TRACE_H -void tb_enable_trace(bool enable); +void tb_enable_trace(unsigned int log_level); #endif diff --git a/tools/testbench/testbench.c b/tools/testbench/testbench.c index f4302765408f..889aba1c0209 100644 --- a/tools/testbench/testbench.c +++ b/tools/testbench/testbench.c @@ -317,9 +317,9 @@ static int parse_input_args(int argc, char **argv, struct testbench_prm *tp) tp->channels_out = atoi(optarg); break; - /* enable debug prints */ + /* set debug log level */ case 'd': - debug = 1; + host_trace_level = atoi(optarg); break; /* number of pipeline copy() iterations */ @@ -734,7 +734,6 @@ int main(int argc, char **argv) int i, err; /* initialize input and output sample rates, files, etc. */ - debug = 0; tp.total_cycles = 0; tp.fs_in = 0; tp.fs_out = 0; @@ -795,9 +794,10 @@ int main(int argc, char **argv) } if (tp.quiet) - tb_enable_trace(false); /* reduce trace output */ + tb_enable_trace(0); /* reduce trace output */ else - tb_enable_trace(true); + tb_enable_trace(1); + /* initialize ipc and scheduler */ if (tb_setup(sof_get(), &tp) < 0) { From 82bf72fe288ec5484f5d4b071d9821695452cd10 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 30 Aug 2023 15:03:58 -0700 Subject: [PATCH 4/8] posix: Add posix headers Add the posix headers for use with the SOF ALSA plugin. Signed-off-by: Liam Girdwood Signed-off-by: Ranjani Sridharan --- posix/include/CMakeLists.txt | 1 + posix/include/rtos/alloc.h | 172 +++++++ posix/include/rtos/atomic.h | 39 ++ posix/include/rtos/bit.h | 27 ++ posix/include/rtos/cache.h | 25 + posix/include/rtos/clk.h | 83 ++++ posix/include/rtos/idc.h | 201 ++++++++ posix/include/rtos/init.h | 11 + posix/include/rtos/interrupt.h | 217 +++++++++ posix/include/rtos/kernel.h | 46 ++ posix/include/rtos/mutex.h | 43 ++ posix/include/rtos/panic.h | 49 ++ posix/include/rtos/sof.h | 123 +++++ posix/include/rtos/spinlock.h | 163 +++++++ posix/include/rtos/string.h | 28 ++ posix/include/rtos/task.h | 123 +++++ posix/include/rtos/timer.h | 132 ++++++ posix/include/rtos/wait.h | 67 +++ posix/include/sof/compiler_attributes.h | 52 +++ posix/include/sof/compiler_info.h | 19 + posix/include/sof/init.h | 26 ++ posix/include/sof/lib/agent.h | 66 +++ posix/include/sof/lib/cpu.h | 93 ++++ posix/include/sof/lib/dai.h | 33 ++ posix/include/sof/lib/dma.h | 589 ++++++++++++++++++++++++ posix/include/sof/lib/io.h | 88 ++++ posix/include/sof/lib/mailbox.h | 118 +++++ posix/include/sof/lib/memory.h | 13 + posix/include/sof/lib/mm_heap.h | 113 +++++ posix/include/sof/lib/perf_cnt.h | 188 ++++++++ posix/include/sof/lib/pm_runtime.h | 176 +++++++ posix/include/sof/lib/shim.h | 13 + posix/include/sof/list.h | 127 +++++ src/arch/host/CMakeLists.txt | 3 +- tools/tplg_parser/CMakeLists.txt | 4 +- 35 files changed, 3266 insertions(+), 5 deletions(-) create mode 100644 posix/include/CMakeLists.txt create mode 100644 posix/include/rtos/alloc.h create mode 100644 posix/include/rtos/atomic.h create mode 100644 posix/include/rtos/bit.h create mode 100644 posix/include/rtos/cache.h create mode 100644 posix/include/rtos/clk.h create mode 100644 posix/include/rtos/idc.h create mode 100644 posix/include/rtos/init.h create mode 100644 posix/include/rtos/interrupt.h create mode 100644 posix/include/rtos/kernel.h create mode 100644 posix/include/rtos/mutex.h create mode 100644 posix/include/rtos/panic.h create mode 100644 posix/include/rtos/sof.h create mode 100644 posix/include/rtos/spinlock.h create mode 100644 posix/include/rtos/string.h create mode 100644 posix/include/rtos/task.h create mode 100644 posix/include/rtos/timer.h create mode 100644 posix/include/rtos/wait.h create mode 100644 posix/include/sof/compiler_attributes.h create mode 100644 posix/include/sof/compiler_info.h create mode 100644 posix/include/sof/init.h create mode 100644 posix/include/sof/lib/agent.h create mode 100644 posix/include/sof/lib/cpu.h create mode 100644 posix/include/sof/lib/dai.h create mode 100644 posix/include/sof/lib/dma.h create mode 100644 posix/include/sof/lib/io.h create mode 100644 posix/include/sof/lib/mailbox.h create mode 100644 posix/include/sof/lib/memory.h create mode 100644 posix/include/sof/lib/mm_heap.h create mode 100644 posix/include/sof/lib/perf_cnt.h create mode 100644 posix/include/sof/lib/pm_runtime.h create mode 100644 posix/include/sof/lib/shim.h create mode 100644 posix/include/sof/list.h diff --git a/posix/include/CMakeLists.txt b/posix/include/CMakeLists.txt new file mode 100644 index 000000000000..fd819740233b --- /dev/null +++ b/posix/include/CMakeLists.txt @@ -0,0 +1 @@ +target_include_directories(sof_public_headers INTERFACE include) diff --git a/posix/include/rtos/alloc.h b/posix/include/rtos/alloc.h new file mode 100644 index 000000000000..d64ea319f48e --- /dev/null +++ b/posix/include/rtos/alloc.h @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +/** + * \file xtos/include/rtos/alloc.h + * \brief Memory Allocation API definition + * \author Liam Girdwood + * \author Keyon Jie + */ + +#ifndef __SOF_LIB_ALLOC_H__ +#define __SOF_LIB_ALLOC_H__ + +#include +#include +#include +#include + +#include +#include + +/** \addtogroup alloc_api Memory Allocation API + * @{ + */ + +/** + * \brief Heap Memory Zones + * + * The heap has three different zones from where memory can be allocated :- + * + * 1) System Zone. Fixed size heap where alloc always succeeds and is never + * freed. Used by any init code that will never give up the memory. + * + * 2) System Runtime Zone. Heap zone intended for runtime objects allocated + * by the kernel part of the code. + * + * 3) Runtime Zone. Main and larger heap zone where allocs are not guaranteed to + * succeed. Memory can be freed here. + * + * 4) Buffer Zone. Largest heap zone intended for audio buffers. + * + * 5) Runtime Shared Zone. Similar to Runtime Zone, but content may be used and + * fred from any enabled core. + * + * 6) System Shared Zone. Similar to System Zone, but content may be used from + * any enabled core. + * + * See platform/memory.h for heap size configuration and mappings. + */ +enum mem_zone { + SOF_MEM_ZONE_SYS = 0, /**< System zone */ + SOF_MEM_ZONE_SYS_RUNTIME, /**< System-runtime zone */ + SOF_MEM_ZONE_RUNTIME, /**< Runtime zone */ + SOF_MEM_ZONE_BUFFER, /**< Buffer zone */ + SOF_MEM_ZONE_RUNTIME_SHARED, /**< Runtime shared zone */ + SOF_MEM_ZONE_SYS_SHARED, /**< System shared zone */ +}; + +/** \name Heap zone flags + * @{ + */ + +/** \brief Indicates that original content should not be copied by realloc. */ +#define SOF_MEM_FLAG_NO_COPY BIT(1) +/** \brief Indicates that if we should return uncached address. */ +#define SOF_MEM_FLAG_COHERENT BIT(2) + +/** @} */ + +/** + * Allocates memory block. + * @param zone Zone to allocate memory from, see enum mem_zone. + * @param flags Flags, see SOF_MEM_FLAG_... + * @param caps Capabilities, see SOF_MEM_CAPS_... + * @param bytes Size in bytes. + * @return Pointer to the allocated memory or NULL if failed. + * + * @note Do not use for buffers (SOF_MEM_ZONE_BUFFER zone). + * Use rballoc(), rballoc_align() to allocate memory for buffers. + */ +void *rmalloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes); + +/** + * Similar to rmalloc(), guarantees that returned block is zeroed. + * + * @note Do not use for buffers (SOF_MEM_ZONE_BUFFER zone). + * rballoc(), rballoc_align() to allocate memory for buffers. + */ +void *rzalloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes); + +/** + * Allocates memory block from SOF_MEM_ZONE_BUFFER. + * @param flags Flags, see SOF_MEM_FLAG_... + * @param caps Capabilities, see SOF_MEM_CAPS_... + * @param bytes Size in bytes. + * @param alignment Alignment in bytes. + * @return Pointer to the allocated memory or NULL if failed. + */ +void *rballoc_align(uint32_t flags, uint32_t caps, size_t bytes, + uint32_t alignment); + +/** + * Similar to rballoc_align(), returns buffer aligned to PLATFORM_DCACHE_ALIGN. + */ +static inline void *rballoc(uint32_t flags, uint32_t caps, size_t bytes) +{ + return rballoc_align(flags, caps, bytes, PLATFORM_DCACHE_ALIGN); +} + +/** + * Changes size of the memory block allocated from SOF_MEM_ZONE_BUFFER. + * @param ptr Address of the block to resize. + * @param flags Flags, see SOF_MEM_FLAG_... + * @param caps Capabilities, see SOF_MEM_CAPS_... + * @param bytes New size in bytes. + * @param old_bytes Old size in bytes. + * @param alignment Alignment in bytes. + * @return Pointer to the resized memory of NULL if failed. + */ +void *rbrealloc_align(void *ptr, uint32_t flags, uint32_t caps, size_t bytes, + size_t old_bytes, uint32_t alignment); + +/** + * Similar to rballoc_align(), returns resized buffer aligned to + * PLATFORM_DCACHE_ALIGN. + */ +static inline void *rbrealloc(void *ptr, uint32_t flags, uint32_t caps, + size_t bytes, size_t old_bytes) +{ + return rbrealloc_align(ptr, flags, caps, bytes, old_bytes, + PLATFORM_DCACHE_ALIGN); +} + +/** + * Frees the memory block. + * @param ptr Pointer to the memory block. + * + * @note Blocks from SOF_MEM_ZONE_SYS cannot be freed, such a call causes + * panic. + */ +void rfree(void *ptr); + +/** + * Allocates memory block from the system heap reserved for the specified core. + * @param core Core id. + * @param bytes Size in bytes. + */ +void *rzalloc_core_sys(int core, size_t bytes); + +/** + * Calculates length of the null-terminated string. + * @param s String. + * @return Length of the string in bytes. + */ +int rstrlen(const char *s); + +/** + * Compares two strings, see man strcmp. + * @param s1 First string to compare. + * @param s2 Second string to compare. + * @return See man strcmp. + */ +int rstrcmp(const char *s1, const char *s2); + +/** @}*/ + +#endif /* __SOF_LIB_ALLOC_H__ */ diff --git a/posix/include/rtos/atomic.h b/posix/include/rtos/atomic.h new file mode 100644 index 000000000000..6d16b6b6c9e6 --- /dev/null +++ b/posix/include/rtos/atomic.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __SOF_ATOMIC_H__ +#define __SOF_ATOMIC_H__ + +#include +#include + +static inline void atomic_init(atomic_t *a, int32_t value) +{ + arch_atomic_init(a, value); +} + +static inline int32_t atomic_read(const atomic_t *a) +{ + return arch_atomic_read(a); +} + +static inline void atomic_set(atomic_t *a, int32_t value) +{ + arch_atomic_set(a, value); +} + +static inline int32_t atomic_add(atomic_t *a, int32_t value) +{ + return arch_atomic_add(a, value); +} + +static inline int32_t atomic_sub(atomic_t *a, int32_t value) +{ + return arch_atomic_sub(a, value); +} + +#endif /* __SOF_ATOMIC_H__ */ diff --git a/posix/include/rtos/bit.h b/posix/include/rtos/bit.h new file mode 100644 index 000000000000..3dde908c2d6b --- /dev/null +++ b/posix/include/rtos/bit.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __XTOS_RTOS_BIT_H__ +#define __XTOS_RTOS_BIT_H__ + +#if ASSEMBLY +#define BIT(b) (1 << (b)) +#else +#define BIT(b) (1UL << (b)) +#endif + +#define MASK(b_hi, b_lo) \ + (((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL) << (b_lo)) +#define SET_BIT(b, x) (((x) & 1) << (b)) +#define SET_BITS(b_hi, b_lo, x) \ + (((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo)) +#define GET_BIT(b, x) \ + (((x) & (1ULL << (b))) >> (b)) +#define GET_BITS(b_hi, b_lo, x) \ + (((x) & MASK(b_hi, b_lo)) >> (b_lo)) + +#endif /* __XTOS_RTOS_BIT_H__ */ diff --git a/posix/include/rtos/cache.h b/posix/include/rtos/cache.h new file mode 100644 index 000000000000..914e61b52984 --- /dev/null +++ b/posix/include/rtos/cache.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + */ + +/** + * \file xtos/include/rtos/cache.h + * \brief Cache header file + * \authors Tomasz Lauda + */ + +#ifndef __SOF_LIB_CACHE_H__ +#define __SOF_LIB_CACHE_H__ + +#include + +/* writeback and invalidate data */ +#define CACHE_WRITEBACK_INV 0 + +/* invalidate data */ +#define CACHE_INVALIDATE 1 + +#endif /* __SOF_LIB_CACHE_H__ */ diff --git a/posix/include/rtos/clk.h b/posix/include/rtos/clk.h new file mode 100644 index 000000000000..e9a36796bc42 --- /dev/null +++ b/posix/include/rtos/clk.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Janusz Jankowski + */ + +#ifndef __SOF_LIB_CLK_H__ +#define __SOF_LIB_CLK_H__ + +#include +#include +#include +#include +#include + +struct timer; + +#define CLOCK_NOTIFY_PRE 0 +#define CLOCK_NOTIFY_POST 1 + +struct clock_notify_data { + uint32_t old_freq; + uint32_t old_ticks_per_msec; + uint32_t freq; + uint32_t ticks_per_msec; + uint32_t message; +}; + +struct freq_table { + uint32_t freq; + uint32_t ticks_per_msec; +}; + +struct clock_info { + uint32_t freqs_num; + const struct freq_table *freqs; + uint32_t default_freq_idx; + uint32_t current_freq_idx; + uint32_t lowest_freq_idx; /* lowest possible clock */ + uint32_t notification_id; + uint32_t notification_mask; + + /* persistent change clock value in active state, caller must hold clk_lock */ + int (*set_freq)(int clock, int freq_idx); + + /* temporary change clock - don't modify default clock settings */ + void (*low_power_mode)(int clock, bool enable); +}; + +uint32_t clock_get_freq(int clock); + +void clock_set_freq(int clock, uint32_t hz); + +void clock_low_power_mode(int clock, bool enable); + +uint64_t clock_ms_to_ticks(int clock, uint64_t ms); + +uint64_t clock_us_to_ticks(int clock, uint64_t us); + +uint64_t clock_ns_to_ticks(int clock, uint64_t ns); + +uint64_t clock_ticks_per_sample(int clock, uint32_t sample_rate); + +extern struct k_spinlock clk_lock; + +static inline k_spinlock_key_t clock_lock(void) +{ + return k_spin_lock(&clk_lock); +} + +static inline void clock_unlock(k_spinlock_key_t key) +{ + k_spin_unlock(&clk_lock, key); +} + +static inline struct clock_info *clocks_get(void) +{ + return sof_get()->clocks; +} + +#endif /* __SOF_LIB_CLK_H__ */ diff --git a/posix/include/rtos/idc.h b/posix/include/rtos/idc.h new file mode 100644 index 000000000000..d6dd69f3e9e9 --- /dev/null +++ b/posix/include/rtos/idc.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + */ + +/** + * \file include/rtos/idc.h + * \brief IDC header file + * \authors Tomasz Lauda + */ + +#ifndef __POSIX_RTOS_IDC_H__ +#define __POSIX_RTOS_IDC_H__ + +#include +#include +#include +#include +#include +#include +#include + +/** \brief IDC send blocking flag. */ +#define IDC_BLOCKING 0 + +/** \brief IDC send non-blocking flag. */ +#define IDC_NON_BLOCKING 1 + +/** \brief IDC send core power up flag. */ +#define IDC_POWER_UP 2 + +/** \brief IDC send core power down flag. */ +#define IDC_POWER_DOWN 3 + +/** \brief IDC send timeout in microseconds. */ +#define IDC_TIMEOUT 10000 + +/** \brief IDC task deadline. */ +#define IDC_DEADLINE 100 + +/** \brief ROM wake version parsed by ROM during core wake up. */ +#define IDC_ROM_WAKE_VERSION 0x2 + +/** \brief IDC message type. */ +#define IDC_TYPE_SHIFT 24 +#define IDC_TYPE_MASK 0x7f +#define IDC_TYPE(x) (((x) & IDC_TYPE_MASK) << IDC_TYPE_SHIFT) + +#define IDC_MSG_BIND IDC_TYPE(0xD) +#define IDC_MSG_UNBIND IDC_TYPE(0xE) +#define IDC_MSG_GET_ATTRIBUTE IDC_TYPE(0xF) + +/** \brief IDC pipeline set state message. */ +#define IDC_MSG_PPL_STATE IDC_TYPE(0xC) +#define IDC_PPL_STATE_PPL_ID_SHIFT 0 +#define IDC_PPL_STATE_PPL_ID_MASK MASK(23, 0) +#define IDC_PPL_STATE_PHASE_SHIFT 24 +#define IDC_PPL_STATE_PHASE_MASK MASK(27, 24) +#define IDC_PPL_STATE_PHASE_SET(x) (((x) << IDC_PPL_STATE_PHASE_SHIFT) & \ + IDC_PPL_STATE_PHASE_MASK) +#define IDC_PPL_STATE_PHASE_GET(x) (((x) & IDC_PPL_STATE_PHASE_MASK) >> \ + IDC_PPL_STATE_PHASE_SHIFT) +#define IDC_PPL_STATE_PHASE_PREPARE BIT(0) +#define IDC_PPL_STATE_PHASE_TRIGGER BIT(1) +#define IDC_PPL_STATE_PHASE_ONESHOT (IDC_PPL_STATE_PHASE_PREPARE | \ + IDC_PPL_STATE_PHASE_TRIGGER) + +#define IDC_MSG_PPL_STATE_EXT(_ppl_id, _action) \ + IDC_EXTENSION(((_ppl_id) & IDC_PPL_STATE_PPL_ID_MASK) | \ + IDC_PPL_STATE_PHASE_SET(_action)) + +/** \brief IDC message header. */ +#define IDC_HEADER_MASK 0xffffff +#define IDC_HEADER(x) ((x) & IDC_HEADER_MASK) + +/** \brief IDC message extension. */ +#define IDC_EXTENSION_MASK 0x3fffffff +#define IDC_EXTENSION(x) ((x) & IDC_EXTENSION_MASK) + +/** \brief IDC power up message. */ +#define IDC_MSG_POWER_UP (IDC_TYPE(0x1) | \ + IDC_HEADER(IDC_ROM_WAKE_VERSION)) +#define IDC_MSG_POWER_UP_EXT IDC_EXTENSION(SOF_TEXT_START >> 2) + +/** \brief IDC power down message. */ +#define IDC_MSG_POWER_DOWN IDC_TYPE(0x2) +#define IDC_MSG_POWER_DOWN_EXT IDC_EXTENSION(0x0) + +/** \brief IDC notify message. */ +#define IDC_MSG_NOTIFY IDC_TYPE(0x3) +#define IDC_MSG_NOTIFY_EXT IDC_EXTENSION(0x0) + +/** \brief IDC IPC processing message. */ +#define IDC_MSG_IPC IDC_TYPE(0x4) +#define IDC_MSG_IPC_EXT IDC_EXTENSION(0x0) + +/** \brief IDC component params message. */ +#define IDC_MSG_PARAMS IDC_TYPE(0x5) +#define IDC_MSG_PARAMS_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC component prepare message. */ +#define IDC_MSG_PREPARE IDC_TYPE(0x6) +#define IDC_MSG_PREPARE_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC component trigger message. */ +#define IDC_MSG_TRIGGER IDC_TYPE(0x7) +#define IDC_MSG_TRIGGER_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC component reset message. */ +#define IDC_MSG_RESET IDC_TYPE(0x8) +#define IDC_MSG_RESET_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC prepare D0ix message. */ +#define IDC_MSG_PREPARE_D0ix IDC_TYPE(0x9) +#define IDC_MSG_PREPARE_D0ix_EXT IDC_EXTENSION(0x0) + +/** \brief IDC secondary core crashed notify message. */ +#define IDC_MSG_SECONDARY_CORE_CRASHED IDC_TYPE(0xA) +#define IDC_MSG_SECONDARY_CORE_CRASHED_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC process async msg */ +#define IDC_MSG_AMS IDC_TYPE(0xB) +#define IDC_MSG_AMS_EXT IDC_EXTENSION(0x0) + +#define IDC_HEADER_TO_AMS_SLOT_MASK(x) (x & 0xFFFF) + +/** \brief IDC_MSG_SECONDARY_CORE_CRASHED header fields. */ +#define IDC_SCC_CORE_SHIFT 0 +#define IDC_SCC_CORE_MASK 0xff +#define IDC_SCC_CORE(x) (((x) & IDC_SCC_CORE_MASK) << IDC_SCC_CORE_SHIFT) + +#define IDC_SCC_REASON_SHIFT 8 +#define IDC_SCC_REASON_MASK 0xff +#define IDC_SCC_REASON(x) (((x) & IDC_SCC_REASON_MASK) << IDC_SCC_REASON_SHIFT) + +/** \brief Secondary core crash reasons. */ +#define IDC_SCC_REASON_WATCHDOG 0x00 +#define IDC_SCC_REASON_EXCEPTION 0x01 + +/** \brief Decodes IDC message type. */ +#define iTS(x) (((x) >> IDC_TYPE_SHIFT) & IDC_TYPE_MASK) + +/** \brief Max IDC message payload size in bytes. */ +#define IDC_MAX_PAYLOAD_SIZE (DCACHE_LINE_SIZE * 2) + +/** \brief IDC free function flags */ +#define IDC_FREE_IRQ_ONLY BIT(0) /**< disable only irqs */ + +/** \brief IDC message payload. */ +struct idc_payload { + uint8_t data[IDC_MAX_PAYLOAD_SIZE]; +}; + +/** \brief IDC message. */ +struct idc_msg { + uint32_t header; /**< header value */ + uint32_t extension; /**< extension value */ + uint32_t core; /**< core id */ + uint32_t size; /**< payload size in bytes */ + void *payload; /**< pointer to payload data */ +}; + +/** \brief IDC data. */ +struct idc { + uint32_t busy_bit_mask; /**< busy interrupt mask */ + struct idc_msg received_msg; /**< received message */ + struct task idc_task; /**< IDC processing task */ + struct idc_payload *payload; + int irq; +}; + +/* idc trace context, used by multiple units */ +extern struct tr_ctx idc_tr; + +static inline struct idc_payload *idc_payload_get(struct idc *idc, + uint32_t core) +{ + return idc->payload + core; +} + +void idc_enable_interrupts(int target_core, int source_core); + +void idc_free(uint32_t flags); + +int platform_idc_init(void); + +int platform_idc_restore(void); + +enum task_state idc_do_cmd(void *data); + +void idc_cmd(struct idc_msg *msg); + +int idc_wait_in_blocking_mode(uint32_t target_core, bool (*cond)(int)); + +int idc_msg_status_get(uint32_t core); + +void idc_init_thread(void); + +#endif /* __POSIX_RTOS_IDC_H__ */ diff --git a/posix/include/rtos/init.h b/posix/include/rtos/init.h new file mode 100644 index 000000000000..7744d6b5b1f3 --- /dev/null +++ b/posix/include/rtos/init.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __POSIX_RTOS_INIT_H__ +#define __POSIX_RTOS_INIT_H__ + +#define SOF_MODULE_INIT(name, init) + +#endif /* __POSIX_RTOS_INIT_H__ */ diff --git a/posix/include/rtos/interrupt.h b/posix/include/rtos/interrupt.h new file mode 100644 index 000000000000..839b4bef3ca3 --- /dev/null +++ b/posix/include/rtos/interrupt.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Janusz Jankowski + */ + +#ifndef __SOF_DRIVERS_INTERRUPT_H__ +#define __SOF_DRIVERS_INTERRUPT_H__ + +#include + +#if !defined(__ASSEMBLER__) && !defined(LINKER) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * \brief child IRQ descriptor for cascading IRQ controllers. + */ +struct irq_child { + int enable_count[CONFIG_CORE_COUNT]; /**< IRQ enable counter */ + struct list_item list; /**< head for IRQ descriptors, + * sharing this interrupt + */ +}; + +/** + * \brief interrupt client descriptor + */ +struct irq_desc { + int irq; /**< virtual IRQ number */ + void (*handler)(void *arg); /**< interrupt handler function */ + void *handler_arg; /**< interrupt handler argument */ + uint32_t cpu_mask; /**< a mask of CPUs on which this + * interrupt is enabled + */ + struct list_item irq_list; /**< to link to other irq_desc */ +}; + +/** + * \brief cascading IRQ controller operations. + */ +struct irq_cascade_ops { + void (*mask)(struct irq_desc *desc, uint32_t irq, + unsigned int cpu); /**< mask */ + void (*unmask)(struct irq_desc *desc, uint32_t irq, + unsigned int cpu); /**< unmask */ +}; + +/** + * \brief cascading interrupt controller descriptor. + */ +struct irq_cascade_desc { + const char *name; /**< name of the + * controller + */ + int irq_base; /**< first virtual IRQ + * number, assigned to + * this controller + */ + const struct irq_cascade_ops *ops; /**< cascading interrupt + * controller driver + * operations + */ + struct irq_desc desc; /**< the interrupt, that + * this controller is + * generating + */ + struct irq_cascade_desc *next; /**< link to the global + * list of interrupt + * controllers + */ + bool global_mask; /**< the controller + * cannot mask input + * interrupts per core + */ + struct k_spinlock lock; /**< protect child + * lists, enable and + * child counters + */ + int enable_count[CONFIG_CORE_COUNT]; /**< enabled child + * interrupt counter + */ + unsigned int num_children[CONFIG_CORE_COUNT]; /**< number of children + */ + struct irq_child child[PLATFORM_IRQ_CHILDREN]; /**< array of child + * lists - one per + * multiplexed IRQ + */ +}; + +/* A descriptor for cascading interrupt controller template */ +struct irq_cascade_tmpl { + const char *name; + const struct irq_cascade_ops *ops; + int irq; + void (*handler)(void *arg); + bool global_mask; +}; + +/** + * \brief Cascading interrupt controller root. + */ +struct cascade_root { + struct k_spinlock lock; /**< locking mechanism */ + struct irq_cascade_desc *list; /**< list of child cascade irqs */ + int last_irq; /**< last registered cascade irq */ +}; + +static inline struct cascade_root *cascade_root_get(void) +{ + return sof_get()->cascade_root; +} + +/* For i.MX, while building SOF with Zephyr use the interrupt_* + * functions from second level interrupt handling and IRQ_STEER. + */ +#if defined(__ZEPHYR__) && defined(CONFIG_IMX) +int mux_interrupt_get_irq(unsigned int irq, const char *cascade); +int mux_interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg); +void mux_interrupt_unregister(uint32_t irq, const void *arg); +uint32_t mux_interrupt_enable(uint32_t irq, void *arg); +uint32_t mux_interrupt_disable(uint32_t irq, void *arg); +#endif + +int interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg); +void interrupt_unregister(uint32_t irq, const void *arg); +uint32_t interrupt_enable(uint32_t irq, void *arg); +uint32_t interrupt_disable(uint32_t irq, void *arg); + +/* Zephyr compat */ +#if !defined(__ZEPHYR__) +#define arch_irq_lock() arch_interrupt_disable_mask(0xffffffff) +#endif + +void platform_interrupt_init(void); + +void platform_interrupt_set(uint32_t irq); +void platform_interrupt_clear(uint32_t irq, uint32_t mask); +uint32_t platform_interrupt_get_enabled(void); +void interrupt_mask(uint32_t irq, unsigned int cpu); +void interrupt_unmask(uint32_t irq, unsigned int cpu); + +/* + * On platforms, supporting cascading interrupts cascaded interrupt numbers + * are greater than or equal to PLATFORM_IRQ_HW_NUM + */ +#define interrupt_is_dsp_direct(irq) (!PLATFORM_IRQ_CHILDREN || \ + irq < PLATFORM_IRQ_HW_NUM) + +void interrupt_init(struct sof *sof); +int interrupt_cascade_register(const struct irq_cascade_tmpl *tmpl); +struct irq_cascade_desc *interrupt_get_parent(uint32_t irq); +int interrupt_get_irq(unsigned int irq, const char *cascade); + +static inline void interrupt_set(int irq) +{ + platform_interrupt_set(irq); +} + +static inline void interrupt_clear_mask(int irq, uint32_t mask) +{ + platform_interrupt_clear(irq, mask); +} + +static inline void interrupt_clear(int irq) +{ + interrupt_clear_mask(irq, 1); +} + +static inline uint32_t interrupt_global_disable(void) +{ + return arch_interrupt_global_disable(); +} + +static inline void interrupt_global_enable(uint32_t flags) +{ + arch_interrupt_global_enable(flags); +} + +#if CONFIG_LIBRARY + +/* temporary fix to remove build warning for testbench that will need shortly + * realigned when Zephyr native APIs are used. + */ +static inline void __irq_local_disable(unsigned long flags) {} +static inline void __irq_local_enable(unsigned long flags) {} + +/* disables all IRQ sources on current core - NO effect on library */ +#define irq_local_disable(flags) \ + do { \ + flags = 0; \ + __irq_local_disable(flags); \ + } while (0) + +/* re-enables IRQ sources on current core - NO effect on library*/ +#define irq_local_enable(flags) \ + __irq_local_enable(flags) + +#else +/* disables all IRQ sources on current core */ +#define irq_local_disable(flags) \ + (flags = interrupt_global_disable()) + +/* re-enables IRQ sources on current core */ +#define irq_local_enable(flags) \ + interrupt_global_enable(flags) +#endif +#endif +#endif /* __SOF_DRIVERS_INTERRUPT_H__ */ diff --git a/posix/include/rtos/kernel.h b/posix/include/rtos/kernel.h new file mode 100644 index 000000000000..5921d86b0012 --- /dev/null +++ b/posix/include/rtos/kernel.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jyri Sarha + */ + +#ifndef __POSIX_RTOS_KERNEL_H__ +#define __POSIX_RTOS_KERNEL_H__ + +#include + +#include + +#ifdef __ZEPHYR__ +#error "This file should only be included in XTOS builds." +#endif + +typedef uint32_t k_ticks_t; + +typedef struct { + k_ticks_t ticks; +} k_timeout_t; + +#define Z_TIMEOUT_TICKS(t) ((k_timeout_t) { .ticks = (t) }) + +#define Z_TIMEOUT_US(t) ((k_timeout_t) { .ticks = clock_us_to_ticks(PLATFORM_DEFAULT_CLOCK, t) }) + +#define Z_TIMEOUT_MS(t) ((k_timeout_t) { .ticks = clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, t) }) + +static inline void k_sleep(k_timeout_t timeout) +{ + wait_delay(timeout.ticks); +} + +static inline void k_msleep(int32_t ms) +{ + wait_delay_ms(ms); +} + +static inline void k_usleep(int32_t us) +{ + wait_delay_us(us); +} + +#endif /* __POSIX_RTOS_KERNEL_H__ */ diff --git a/posix/include/rtos/mutex.h b/posix/include/rtos/mutex.h new file mode 100644 index 000000000000..16c773f4cae4 --- /dev/null +++ b/posix/include/rtos/mutex.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/* + * Simple mutex implementation for SOF. + */ + +#ifndef __POSIX_RTOS_MUTEX_H +#define __POSIX_RTOS_MUTEX_H + +#include +#include +#include + +#define K_FOREVER ((k_timeout_t) { .ticks = 0xffffffff }) + +struct k_mutex { + struct k_spinlock lock; + k_spinlock_key_t key; +}; + +static inline int k_mutex_init(struct k_mutex *mutex) +{ + k_spinlock_init(&mutex->lock); + return 0; +} + +static inline int k_mutex_lock(struct k_mutex *mutex, k_timeout_t timeout) +{ + mutex->key = k_spin_lock(&mutex->lock); + return 0; +} + +static inline int k_mutex_unlock(struct k_mutex *mutex) +{ + k_spin_unlock(&mutex->lock, mutex->key); + return 0; +} + +#endif diff --git a/posix/include/rtos/panic.h b/posix/include/rtos/panic.h new file mode 100644 index 000000000000..65b06a1cab43 --- /dev/null +++ b/posix/include/rtos/panic.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __POSIX_RTOS_PANIC_H__ +#define __POSIX_RTOS_PANIC_H__ + +#include +#include +#include + +#ifdef __ZEPHYR__ +#error "This file should only be included in XTOS builds." +#endif /* __ZEPHYR__ */ + +#ifdef __clang_analyzer__ +#define SOF_NORETURN __attribute__((analyzer_noreturn)) +#elif __GNUC__ +#define SOF_NORETURN __attribute__((noreturn)) +#else +#define SOF_NORETURN +#endif + +#ifndef RELATIVE_FILE +#error "This file requires RELATIVE_FILE to be defined. "\ + "Add it to CMake's target with sof_append_relative_path_definitions." +#endif + +void dump_panicinfo(void *addr, struct sof_ipc_panic_info *panic_info); +void panic_dump(uint32_t p, struct sof_ipc_panic_info *panic_info, + uintptr_t *data) SOF_NORETURN; +void __panic(uint32_t p, char *filename, uint32_t linenum) SOF_NORETURN; + +/** panic dump filename and linenumber of the call + * + * \param x panic code defined in ipc/trace.h + */ +#define sof_panic(x) __panic((x), (RELATIVE_FILE), (__LINE__)) + +/* runtime assertion */ +#ifndef assert +#define assert(cond) (void)((cond) || (sof_panic(SOF_IPC_PANIC_ASSERT), 0)) +#endif + +#endif /* __POSIX_RTOS_PANIC_H__ */ diff --git a/posix/include/rtos/sof.h b/posix/include/rtos/sof.h new file mode 100644 index 000000000000..3cbb2e7bfefa --- /dev/null +++ b/posix/include/rtos/sof.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __POSIX_RTOS_SOF_H__ +#define __POSIX_RTOS_SOF_H__ + +#include +#include +#include + +struct cascade_root; +struct clock_info; +struct comp_driver_list; +struct dai_info; +struct dma_info; +struct dma_trace_data; +struct ipc; +struct ll_schedule_domain; +struct mm; +struct mn; +struct ams_shared_context; +struct notify_data; +struct pm_runtime_data; +struct sa; +struct timer; +struct trace; +struct pipeline_posn; +struct probe_pdata; + +/** + * \brief General firmware context. + * This structure holds all the global pointers, which can potentially + * be accessed by SMP code, hence it should be aligned to platform's + * data cache line size. Alignments in the both beginning and end are needed + * to avoid potential before and after data evictions. + */ +struct sof { + /* init data */ + int argc; + char **argv; + + /* ipc */ + struct ipc *ipc; + + /* system agent */ + struct sa *sa; + + /* DMA for Trace*/ + struct dma_trace_data *dmat; + + /* generic trace structure */ + struct trace *trace; + + /* platform clock information */ + struct clock_info *clocks; + + /* default platform timer */ + struct timer *platform_timer; + + /* cpu (arch) timers - 1 per core */ + struct timer *cpu_timers; + + /* timer domain for driving timer LL scheduler */ + struct ll_schedule_domain *platform_timer_domain; + + /* DMA domain for driving DMA LL scheduler */ + struct ll_schedule_domain *platform_dma_domain; + + /* memory map */ + struct mm *memory_map; + + /* runtime power management data */ + struct pm_runtime_data *prd; + +#ifdef CONFIG_AMS + /* asynchronous messaging service */ + struct ams_shared_context *ams_shared_ctx; +#endif + + /* shared notifier data */ + struct notify_data *notify_data; + + /* platform dai information */ + const struct dai_info *dai_info; + + /* platform DMA information */ + const struct dma_info *dma_info; + + /* cascading interrupt controller root */ + struct cascade_root *cascade_root; + + /* list of registered component drivers */ + struct comp_driver_list *comp_drivers; + + /* M/N dividers */ + struct mn *mn; + + /* probes */ + struct probe_pdata *probe; + + /* pipelines stream position */ + struct pipeline_posn *pipeline_posn; + +#ifdef CONFIG_LIBRARY_MANAGER + /* dynamically loaded libraries */ + struct ext_library *ext_library; +#endif + +#if CONFIG_IPC_MAJOR_4 + /* lock for fw_reg access */ + struct k_spinlock fw_reg_lock; +#endif + + __aligned(PLATFORM_DCACHE_ALIGN) int alignment[0]; +} __aligned(PLATFORM_DCACHE_ALIGN); + +struct sof *sof_get(void); + +#endif /* __POSIX_RTOS_SOF_H__ */ diff --git a/posix/include/rtos/spinlock.h b/posix/include/rtos/spinlock.h new file mode 100644 index 000000000000..beb20ab6e847 --- /dev/null +++ b/posix/include/rtos/spinlock.h @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +/* + * Simple spinlock implementation for SOF. + */ + +#ifndef __POSIX_RTOS_SPINLOCK_H__ +#define __POSIX_RTOS_SPINLOCK_H__ + +#include +typedef uint32_t k_spinlock_key_t; +#include +#include + +#include + +/* + * Lock debugging provides a simple interface to debug deadlocks. The rmbox + * trace output will show an output :- + * + * 0xd70 [41.306406] delta [0.359638] lock eal + * 0xd80 [41.306409] delta [0.000002] value 0x00000000000001b7 + * 0xd90 [41.306411] delta [0.000002] value 0x0000000000000001 + * 0xda0 [41.306413] delta [0.000002] value 0x0000000001000348 + * + * "eal" indicates we are holding a lock with interrupts OFF. The next value + * is the line number of where the lock was acquired. The second number is the + * number of other locks held whilst this lock is held and the subsequent + * numbers list each lock and the line number of it's holder. e.g. to find + * the locks :- + * + * grep -rn lock --include *.c | grep 840 (search for lock at line 0x348) + * src/drivers/dw-dma.c:840: spinlock_init(&dma->lock); + * + * grep -rn lock --include *.c | grep 439 + * src/lib/alloc.c:439: k_spin_lock_irq(&memmap.lock, flags); + * + * Every lock entry and exit shows LcE and LcX in trace alongside the lock + * line numbers in hex. e.g. + * + * 0xfd60 [11032.730567] delta [0.000004] lock LcE + * 0xfd70 [11032.730569] delta [0.000002] value 0x00000000000000ae + * + * Deadlock can be confirmed in rmbox :- + * + * Debug log: + * debug: 0x0 (00) = 0xdead0007 (-559087609) |....| + * .... + * Error log: + * using 19.20MHz timestamp clock + * 0xc30 [26.247240] delta [26.245851] lock DED + * 0xc40 [26.247242] delta [0.000002] value 0x00000000000002b4 + * 0xc50 [26.247244] delta [0.000002] value 0x0000000000000109 + * + * DED means deadlock has been detected and the DSP is now halted. The first + * value after DEA is the line number where deadlock occurs and the second + * number is the line number where the lock is allocated. These can be grepped + * like above. + */ + +#if CONFIG_DEBUG_LOCKS + +#include +#include +#include +#include + +#define DBG_LOCK_USERS 8 +#define DBG_LOCK_TRIES 10000 + +extern uint32_t lock_dbg_atomic; +extern uint32_t lock_dbg_user[DBG_LOCK_USERS]; + +extern struct tr_ctx sl_tr; + +/* panic on deadlock */ +#define spin_try_lock_dbg(lock, line) \ + do { \ + int __tries; \ + for (__tries = DBG_LOCK_TRIES; __tries > 0; __tries--) { \ + if (arch_try_lock(lock)) \ + break; /* lock acquired */ \ + } \ + if (__tries == 0) { \ + tr_err_atomic(&sl_tr, "DED"); \ + tr_err_atomic(&sl_tr, "line: %d", line); \ + tr_err_atomic(&sl_tr, "user: %d", (lock)->user); \ + panic(SOF_IPC_PANIC_DEADLOCK); /* lock not acquired */ \ + } \ + } while (0) + +#if CONFIG_DEBUG_LOCKS_VERBOSE +#define spin_lock_log(lock, line) \ + do { \ + if (lock_dbg_atomic) { \ + int __i = 0; \ + int __count = lock_dbg_atomic >= DBG_LOCK_USERS \ + ? DBG_LOCK_USERS : lock_dbg_atomic; \ + tr_err_atomic(&sl_tr, "eal"); \ + tr_err_atomic(&sl_tr, "line: %d", line); \ + tr_err_atomic(&sl_tr, "dbg_atomic: %d", lock_dbg_atomic); \ + for (__i = 0; __i < __count; __i++) { \ + tr_err_atomic(&sl_tr, "value: %d", \ + (lock_dbg_atomic << 24) | \ + lock_dbg_user[__i]); \ + } \ + } \ + } while (0) + +#define spin_lock_dbg(line) \ + do { \ + tr_info(&sl_tr, "LcE"); \ + tr_info(&sl_tr, "line: %d", line); \ + } while (0) + +#define spin_unlock_dbg(line) \ + do { \ + tr_info(&sl_tr, "LcX"); \ + tr_info(&sl_tr, "line: %d", line); \ + } while (0) + +#else /* CONFIG_DEBUG_LOCKS_VERBOSE */ +#define spin_lock_log(lock, line) do {} while (0) +#define spin_lock_dbg(line) do {} while (0) +#define spin_unlock_dbg(line) do {} while (0) +#endif /* CONFIG_DEBUG_LOCKS_VERBOSE */ + +#else /* CONFIG_DEBUG_LOCKS */ + +#define trace_lock(__e) do {} while (0) +#define tracev_lock(__e) do {} while (0) + +#define spin_lock_dbg(line) do {} while (0) +#define spin_unlock_dbg(line) do {} while (0) + +#endif /* CONFIG_DEBUG_LOCKS */ + +/* all SMP spinlocks need init, nothing todo on UP */ +static inline void _spinlock_init(struct k_spinlock *lock, int line) +{ + arch_spinlock_init(lock); +#if CONFIG_DEBUG_LOCKS + lock->user = line; +#endif +} + +#define k_spinlock_init(lock) _spinlock_init(lock, __LINE__) + +/* disables all IRQ sources and takes lock - enter atomic context */ +k_spinlock_key_t _k_spin_lock_irq(struct k_spinlock *lock); +#define k_spin_lock(lock) _k_spin_lock_irq(lock) + +/* re-enables current IRQ sources and releases lock - leave atomic context */ +void _k_spin_unlock_irq(struct k_spinlock *lock, k_spinlock_key_t key, int line); +#define k_spin_unlock(lock, key) _k_spin_unlock_irq(lock, key, __LINE__) + +#endif /* __POSIX_RTOS_SPINLOCK_H__ */ diff --git a/posix/include/rtos/string.h b/posix/include/rtos/string.h new file mode 100644 index 000000000000..b3ca03f9ca4e --- /dev/null +++ b/posix/include/rtos/string.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __POSIX_RTOS_STRING_H__ +#define __POSIX_RTOS_STRING_H__ + +#include +#include + +/* C memcpy for arch that don't have arch_memcpy() */ +void cmemcpy(void *dest, void *src, size_t size); +int memcmp(const void *p, const void *q, size_t count); +int rstrlen(const char *s); +int rstrcmp(const char *s1, const char *s2); + +#if defined(arch_memcpy) +#define rmemcpy(dest, src, size) \ + arch_memcpy(dest, src, size) +#else +#define rmemcpy(dest, src, size) \ + cmemcpy(dest, src, size) +#endif + +#endif /* __POSIX_RTOS_STRING_H__ */ diff --git a/posix/include/rtos/task.h b/posix/include/rtos/task.h new file mode 100644 index 000000000000..5aca574a5787 --- /dev/null +++ b/posix/include/rtos/task.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __POSIX_RTOS_TASK_H__ +#define __POSIX_RTOS_TASK_H__ + +#include +#include +#include +#include +#include +#include +#include + +struct comp_dev; +struct sof; + +/** \brief Predefined LL task priorities. */ +#define SOF_TASK_PRI_HIGH 0 /* priority level 0 - high */ +#define SOF_TASK_PRI_MED 4 /* priority level 4 - medium */ +#define SOF_TASK_PRI_LOW 9 /* priority level 9 - low */ + +/** \brief Predefined EDF task deadlines. */ +#define SOF_TASK_DEADLINE_IDLE UINT64_MAX +#define SOF_TASK_DEADLINE_ALMOST_IDLE (SOF_TASK_DEADLINE_IDLE - 1) +#define SOF_TASK_DEADLINE_NOW 0 + +/** \brief Task counter initial value. */ +#define SOF_TASK_SKIP_COUNT 0xFFFFu + +/** \brief Task states. */ +enum task_state { + SOF_TASK_STATE_INIT = 0, + SOF_TASK_STATE_QUEUED, + SOF_TASK_STATE_PENDING, + SOF_TASK_STATE_RUNNING, + SOF_TASK_STATE_PREEMPTED, + SOF_TASK_STATE_COMPLETED, + SOF_TASK_STATE_FREE, + SOF_TASK_STATE_CANCEL, + SOF_TASK_STATE_RESCHEDULE, +}; + +/** \brief Task operations. */ +struct task_ops { + enum task_state (*run)(void *data); /**< task's main operation */ + void (*complete)(void *data); /**< executed on completion */ + uint64_t (*get_deadline)(void *data); /**< returns current deadline */ +}; + +/** \brief Task used by schedulers. */ +struct task { + uint64_t start; /**< start time in [ms] since now (LL only) */ + const struct sof_uuid_entry *uid; /**< Uuid */ + uint16_t type; /**< type of the task (LL or EDF) */ + uint16_t priority; /**< priority of the task (used by LL) */ + uint16_t core; /**< execution core */ + uint16_t flags; /**< custom flags */ + enum task_state state; /**< current state */ + void *data; /**< custom data passed to all ops */ + struct list_item list; /**< used by schedulers to hold tasks */ + void *priv_data; /**< task private data */ + struct task_ops ops; /**< task operations */ +#if defined(CONFIG_SCHEDULE_LOG_CYCLE_STATISTICS) + uint32_t cycles_sum; + uint32_t cycles_max; + uint32_t cycles_cnt; +#endif +#if CONFIG_PERFORMANCE_COUNTERS + struct perf_cnt_data pcd; +#endif +}; + +static inline bool task_is_active(struct task *task) +{ + switch (task->state) { + case SOF_TASK_STATE_QUEUED: + case SOF_TASK_STATE_PENDING: + case SOF_TASK_STATE_RUNNING: + case SOF_TASK_STATE_PREEMPTED: + case SOF_TASK_STATE_RESCHEDULE: + return true; + default: + return false; + } +} + +static inline enum task_state task_run(struct task *task) +{ + assert(task->ops.run); + + return task->ops.run(task->data); +} + +static inline void task_complete(struct task *task) +{ + if (task->ops.complete) + task->ops.complete(task->data); +} + +static inline uint64_t task_get_deadline(struct task *task) +{ + assert(task->ops.get_deadline); + + return task->ops.get_deadline(task->data); +} + +enum task_state task_main_primary_core(void *data); + +enum task_state task_main_secondary_core(void *data); + +void task_main_init(void); + +void task_main_free(void); + +int task_main_start(struct sof *sof); +int start_complete(void); + +#endif /* __POSIX_RTOS_TASK_H__ */ diff --git a/posix/include/rtos/timer.h b/posix/include/rtos/timer.h new file mode 100644 index 000000000000..b9756b66c87c --- /dev/null +++ b/posix/include/rtos/timer.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Janusz Jankowski + */ + +#ifndef __SOF_DRIVERS_TIMER_H__ +#define __SOF_DRIVERS_TIMER_H__ + +#include +#include +#include +#include +#include +#include + +struct comp_dev; +struct sof_ipc_stream_posn; + +#define TIMER0 0 +#define TIMER1 1 +#define TIMER2 2 +#define TIMER3 3 +#define TIMER4 4 + +int timer_register(struct timer *timer, void (*handler)(void *arg), void *arg); +void timer_unregister(struct timer *timer, void *arg); +void timer_enable(struct timer *timer, void *arg, int core); +void timer_disable(struct timer *timer, void *arg, int core); + +static inline struct timer *timer_get(void) +{ + return sof_get()->platform_timer; +} + +static inline struct timer *cpu_timer_get(void) +{ + return &(sof_get()->cpu_timers[cpu_get_id()]); +} + +static inline int64_t timer_set(struct timer *timer, uint64_t ticks) +{ + return arch_timer_set(timer, ticks); +} + +void timer_set_ms(struct timer *timer, unsigned int ms); + +static inline void timer_clear(struct timer *timer) +{ + arch_timer_clear(timer); +} + +unsigned int timer_get_count(struct timer *timer); + +unsigned int timer_get_count_delta(struct timer *timer); + +static inline uint64_t timer_get_system(struct timer *timer) +{ + return arch_timer_get_system(timer); +} + +int64_t platform_timer_set(struct timer *timer, uint64_t ticks); +void platform_timer_clear(struct timer *timer); +uint64_t platform_timer_get(struct timer *timer); +uint64_t platform_timer_get_atomic(struct timer *timer); + +static inline uint64_t platform_safe_get_time(struct timer *timer) +{ + /* Default to something small but at least 1.0 microsecond so it + * does not look like an uninitialized zero; not even when the + * user does not request any microseconds decimals. See + * DEFAULT_CLOCK constant in logger.c + */ + return timer ? platform_timer_get(timer) : 50; +} + +void platform_timer_start(struct timer *timer); +void platform_timer_stop(struct timer *timer); + +static inline uint64_t k_ms_to_cyc_ceil64(uint64_t ms) +{ + return clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, ms); +} + +static inline uint64_t k_us_to_cyc_ceil64(uint64_t us) +{ + return clock_us_to_ticks(PLATFORM_DEFAULT_CLOCK, us); +} + +static inline uint64_t k_ns_to_cyc_near64(uint64_t ns) +{ + return clock_ns_to_ticks(PLATFORM_DEFAULT_CLOCK, ns); +} + +static inline uint64_t k_cyc_to_ms_near64(uint64_t ticks) +{ + return ticks / clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1); +} + +static inline uint64_t k_cyc_to_us_near64(uint64_t ticks) +{ + return ticks / clock_us_to_ticks(PLATFORM_DEFAULT_CLOCK, 1); +} + +static inline uint64_t sof_cycle_get_64(void) +{ + return platform_timer_get(timer_get()); +} + +static inline uint64_t sof_cycle_get_64_atomic(void) +{ + return platform_timer_get_atomic(timer_get()); +} + +static inline uint64_t sof_cycle_get_64_safe(void) +{ + return platform_safe_get_time(timer_get()); +} + +/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn); + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn); + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock); + +#endif /* __SOF_DRIVERS_TIMER_H__ */ diff --git a/posix/include/rtos/wait.h b/posix/include/rtos/wait.h new file mode 100644 index 000000000000..b6874888a763 --- /dev/null +++ b/posix/include/rtos/wait.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +/* + * Simple wait for event completion and signaling with timeouts. + */ + +#ifndef __POSIX_RTOS_WAIT_H__ +#define __POSIX_RTOS_WAIT_H__ + +#include +#include + +#if !CONFIG_LIBRARY +#include +#include +#include +#include +#include +#include + +extern struct tr_ctx wait_tr; + +static inline void wait_for_interrupt(int level) +{ + LOG_MODULE_DECLARE(wait, CONFIG_SOF_LOG_LEVEL); + + tr_dbg(&wait_tr, "WFE"); +#if CONFIG_DEBUG_LOCKS + if (lock_dbg_atomic) + tr_err_atomic(&wait_tr, "atm"); +#endif + platform_wait_for_interrupt(level); + tr_dbg(&wait_tr, "WFX"); +} + +/** + * \brief Waits at least passed number of clocks. + * \param[in] number_of_clks Minimum number of clocks to wait. + */ +void wait_delay(uint64_t number_of_clks); + +/** + * \brief Waits at least passed number of milliseconds. + * \param[in] ms Minimum number of milliseconds to wait. + */ +void wait_delay_ms(uint64_t ms); + +/** + * \brief Waits at least passed number of microseconds. + * \param[in] us Minimum number of microseconds to wait. + */ +void wait_delay_us(uint64_t us); +#else +static inline void wait_delay(uint64_t number_of_clks) {} +static inline void wait_delay_ms(uint64_t ms) {} +static inline void wait_delay_us(uint64_t us) {} +#endif + +int poll_for_register_delay(uint32_t reg, uint32_t mask, + uint32_t val, uint64_t us); + +#endif /* __POSIX_RTOS_WAIT_H__ */ diff --git a/posix/include/sof/compiler_attributes.h b/posix/include/sof/compiler_attributes.h new file mode 100644 index 000000000000..bf88bfac4369 --- /dev/null +++ b/posix/include/sof/compiler_attributes.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski + */ + +#ifdef __ZEPHYR__ + +/* Get __sparse_cache and __sparse_force definitions if __CHECKER__ is defined */ +#include + +#else + +#define __sparse_cache +#define __sparse_force + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +#ifndef __unused +#define __unused __attribute__((unused)) +#endif + +#endif + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif + +#ifndef __section +#define __section(x) __attribute__((section(x))) +#endif + +/* The fallthrough attribute is supported since GCC 7.0 + * and Clang 10.0.0. + * + * Note that Clang sets __GNUC__ == 4 so the GCC version + * test will not be true here, and must go through + * the Clang version test. + */ +#if ((defined(__GNUC__) && (__GNUC__ >= 7)) || \ + (defined(__clang__) && (__clang_major__ >= 10))) && !defined(__CHECKER__) + +#define COMPILER_FALLTHROUGH __attribute__((fallthrough)) + +#else + +#define COMPILER_FALLTHROUGH /* fallthrough */ + +#endif diff --git a/posix/include/sof/compiler_info.h b/posix/include/sof/compiler_info.h new file mode 100644 index 000000000000..9716575b7188 --- /dev/null +++ b/posix/include/sof/compiler_info.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski + */ + +/** + * \file xtos/include/sof/compiler_info.h + * \brief Compiler version and name descriptor + * \author Karol Trzcinski + */ + +#ifndef __SOF_COMPILER_INFO_H__ +#define __SOF_COMPILER_INFO_H__ + +#include + +#endif /* __SOF_COMPILER_INFO_H__ */ diff --git a/posix/include/sof/init.h b/posix/include/sof/init.h new file mode 100644 index 000000000000..ce8522cd34ad --- /dev/null +++ b/posix/include/sof/init.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __SOF_INIT_H__ +#define __SOF_INIT_H__ + +struct sof; + +/* main firmware entry point - argc and argv not currently used */ +#ifndef CONFIG_ARCH_POSIX +int main(int argc, char *argv[]); +#endif + +#if CONFIG_MULTICORE + +int secondary_core_init(struct sof *sof); + +#endif /* CONFIG_MULTICORE */ + +int arch_init(void); + +#endif /* __SOF_INIT_H__ */ diff --git a/posix/include/sof/lib/agent.h b/posix/include/sof/lib/agent.h new file mode 100644 index 000000000000..6e70a4ce997d --- /dev/null +++ b/posix/include/sof/lib/agent.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __SOF_LIB_AGENT_H__ +#define __SOF_LIB_AGENT_H__ + +#include +#include +#include +#include +#include + +#include +#include + +struct sof; + +/* simple agent */ +struct sa { + uint64_t last_check; /* time of last activity checking */ + uint64_t panic_timeout; /* threshold of panic */ + uint64_t warn_timeout; /* threshold of warning */ +#if CONFIG_PERFORMANCE_COUNTERS + struct perf_cnt_data pcd; +#endif + struct task work; + atomic_t panic_cnt; /**< ref counter for panic_on_delay property */ + bool panic_on_delay; /**< emits panic on delay if true */ +}; + +#if CONFIG_HAVE_AGENT + +/** + * Enables or disables panic on agent delay. + * @param enabled True for panic enabling, false otherwise. + */ +static inline void sa_set_panic_on_delay(bool enabled) +{ + struct sa *sa = sof_get()->sa; + + if (enabled) + atomic_add(&sa->panic_cnt, 1); + else + atomic_sub(&sa->panic_cnt, 1); + + /* enable panic only if no refs */ + sa->panic_on_delay = !atomic_read(&sa->panic_cnt); + +} + +void sa_init(struct sof *sof, uint64_t timeout); +void sa_exit(struct sof *sof); + +#else + +static inline void sa_init(struct sof *sof, uint64_t timeout) { } +static inline void sa_exit(struct sof *sof) { } +static inline void sa_set_panic_on_delay(bool enabled) { } + +#endif + +#endif /* __SOF_LIB_AGENT_H__ */ diff --git a/posix/include/sof/lib/cpu.h b/posix/include/sof/lib/cpu.h new file mode 100644 index 000000000000..d53e15e7535a --- /dev/null +++ b/posix/include/sof/lib/cpu.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + */ + +/** + * \file xtos/include/sof/lib/cpu.h + * \brief CPU header file + * \authors Tomasz Lauda + */ + +#ifndef __SOF_LIB_CPU_H__ +#define __SOF_LIB_CPU_H__ +#ifndef __ZEPHYR__ + +#include + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include +#include + +/* let the compiler optimise when in single core mode */ +#if CONFIG_CORE_COUNT == 1 + +static inline int cpu_get_id(void) +{ + return 0; +} + +static inline bool cpu_is_primary(int id) +{ + return 1; +} + +static inline bool cpu_is_me(int id) +{ + return 1; +} + +#else + +static inline int cpu_get_id(void) +{ + return arch_cpu_get_id(); +} + +static inline bool cpu_is_primary(int id) +{ + return id == PLATFORM_PRIMARY_CORE_ID; +} + +static inline bool cpu_is_me(int id) +{ + return id == cpu_get_id(); +} +#endif + +static inline int cpu_enable_core(int id) +{ + return arch_cpu_enable_core(id); +} + +static inline void cpu_disable_core(int id) +{ + arch_cpu_disable_core(id); +} + +static inline int cpu_is_core_enabled(int id) +{ + return arch_cpu_is_core_enabled(id); +} + +static inline int cpu_enabled_cores(void) +{ + return arch_cpu_enabled_cores(); +} + +static inline int cpu_restore_secondary_cores(void) +{ + return arch_cpu_restore_secondary_cores(); +} + +static inline int cpu_secondary_cores_prepare_d0ix(void) +{ + return arch_cpu_secondary_cores_prepare_d0ix(); +} + +#endif +#endif +#endif /* __SOF_LIB_CPU_H__ */ diff --git a/posix/include/sof/lib/dai.h b/posix/include/sof/lib/dai.h new file mode 100644 index 000000000000..47677c19ae4c --- /dev/null +++ b/posix/include/sof/lib/dai.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +/** + * \file xtos/include/sof/lib/dai.h + * \brief DAI Drivers definition + * \author Liam Girdwood + * \author Keyon Jie + */ + +#ifndef __SOF_LIB_DAI_H__ +#define __SOF_LIB_DAI_H__ + +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS +#include +#else +#include +#endif + +struct ipc4_ipcgtw_cmd; + +static inline int ipcgtw_process_cmd(const struct ipc4_ipcgtw_cmd *cmd, + void *reply_payload, uint32_t *reply_payload_size) +{ + return 0; +} + +#endif /* __SOF_LIB_DAI_H__ */ diff --git a/posix/include/sof/lib/dma.h b/posix/include/sof/lib/dma.h new file mode 100644 index 000000000000..af9e4191cbbb --- /dev/null +++ b/posix/include/sof/lib/dma.h @@ -0,0 +1,589 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +/** + * \file xtos/include/sof/lib/dma.h + * \brief DMA Drivers definition + * \author Liam Girdwood + * \author Keyon Jie + */ + +#ifndef __SOF_LIB_DMA_H__ +#define __SOF_LIB_DMA_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __ZEPHYR__ +#include +#include +#endif + +struct comp_buffer; + +/** \addtogroup sof_dma_drivers DMA Drivers + * DMA Drivers API specification. + * @{ + */ + +/* DMA direction bitmasks used to define DMA copy direction */ +#define DMA_DIR_MEM_TO_MEM BIT(0) /**< local memory copy */ +#define DMA_DIR_HMEM_TO_LMEM BIT(1) /**< host memory to local mem copy */ +#define DMA_DIR_LMEM_TO_HMEM BIT(2) /**< local mem to host mem copy */ +#define DMA_DIR_MEM_TO_DEV BIT(3) /**< local mem to dev copy */ +#define DMA_DIR_DEV_TO_MEM BIT(4) /**< dev to local mem copy */ +#define DMA_DIR_DEV_TO_DEV BIT(5) /**< dev to dev copy */ + +/* DMA capabilities bitmasks used to define the type of DMA */ +#define DMA_CAP_HDA BIT(0) /**< HDA DMA */ +#define DMA_CAP_GP_LP BIT(1) /**< GP LP DMA */ +#define DMA_CAP_GP_HP BIT(2) /**< GP HP DMA */ +#define DMA_CAP_BT BIT(3) /**< BT DMA */ +#define DMA_CAP_SP BIT(4) /**< SP DMA */ +#define DMA_CAP_DMIC BIT(5) /**< ACP DMA DMIC > */ +#define DMA_CAP_SP_VIRTUAL BIT(6) /**< SP VIRTUAL DMA */ +#define DMA_CAP_HS_VIRTUAL BIT(7) /**< HS VIRTUAL DMA */ + +/* DMA dev type bitmasks used to define the type of DMA */ + +#define DMA_DEV_HOST BIT(0) /**< connectable to host */ +#define DMA_DEV_HDA BIT(1) /**< connectable to HD/A link */ +#define DMA_DEV_SSP BIT(2) /**< connectable to SSP fifo */ +#define DMA_DEV_DMIC BIT(3) /**< connectable to DMIC fifo */ +#define DMA_DEV_SSI BIT(4) /**< connectable to SSI / SPI fifo */ +#define DMA_DEV_ALH BIT(5) /**< connectable to ALH link */ +#define DMA_DEV_SAI BIT(6) /**< connectable to SAI fifo */ +#define DMA_DEV_ESAI BIT(7) /**< connectable to ESAI fifo */ +#define DMA_DEV_BT BIT(8) /**< connectable to ACP BT I2S */ +#define DMA_DEV_SP BIT(9) /**< connectable to ACP SP I2S */ +#define DMA_DEV_AFE_MEMIF BIT(10) /**< connectable to AFE fifo */ +#define DMA_DEV_SP_VIRTUAL BIT(11) /**< connectable to ACP SP VIRTUAL I2S */ +#define DMA_DEV_HS_VIRTUAL BIT(12) /**< connectable to ACP HS VIRTUAL I2S */ + +/* DMA access privilege flag */ +#define DMA_ACCESS_EXCLUSIVE 1 +#define DMA_ACCESS_SHARED 0 + +/* DMA copy flags */ +#define DMA_COPY_BLOCKING BIT(0) +#define DMA_COPY_ONE_SHOT BIT(1) + +/* We will use this enum in cb handler to inform dma what + * action we need to perform. + */ +enum dma_cb_status { + DMA_CB_STATUS_RELOAD = 0, + DMA_CB_STATUS_END, +}; + +/* DMA interrupt commands */ +enum dma_irq_cmd { + DMA_IRQ_STATUS_GET = 0, + DMA_IRQ_CLEAR, + DMA_IRQ_MASK, + DMA_IRQ_UNMASK +}; + +#define DMA_CHAN_INVALID 0xFFFFFFFF +#define DMA_CORE_INVALID 0xFFFFFFFF + +/* Attributes have been ported to Zephyr. This condition is necessary until full support of + * CONFIG_SOF_ZEPHYR_STRICT_HEADERS. + */ +#ifndef CONFIG_ZEPHYR_NATIVE_DRIVERS +/* DMA attributes */ +#define DMA_ATTR_BUFFER_ALIGNMENT 0 +#define DMA_ATTR_COPY_ALIGNMENT 1 +#define DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT 2 +#define DMA_ATTR_BUFFER_PERIOD_COUNT 3 +#endif + +struct dma; + +/** + * \brief Element of SG list (as array item). + */ +struct dma_sg_elem { + uint32_t src; /**< source address */ + uint32_t dest; /**< destination address */ + uint32_t size; /**< size (in bytes) */ +}; + +/** + * \brief Data used in DMA callbacks. + */ +struct dma_cb_data { + struct dma_chan_data *channel; + struct dma_sg_elem elem; + enum dma_cb_status status; +}; + +/** + * \brief SG elem array. + */ +struct dma_sg_elem_array { + uint32_t count; /**< number of elements in elems */ + struct dma_sg_elem *elems; /**< elements */ +}; + +/* DMA physical SG params */ +struct dma_sg_config { + uint32_t src_width; /* in bytes */ + uint32_t dest_width; /* in bytes */ + uint32_t burst_elems; + uint32_t direction; + uint32_t src_dev; + uint32_t dest_dev; + uint32_t cyclic; /* circular buffer */ + uint64_t period; + struct dma_sg_elem_array elem_array; /* array of dma_sg elems */ + bool scatter; + bool irq_disabled; + /* true if configured DMA channel is the scheduling source */ + bool is_scheduling_source; +}; + +struct dma_chan_status { + uint32_t state; + uint32_t flags; + uint32_t w_pos; + uint32_t r_pos; + uint32_t timestamp; + + /* dma position info for ipc4 */ + void *ipc_posn_data; +}; + +/* DMA operations */ +struct dma_ops { + + struct dma_chan_data *(*channel_get)(struct dma *dma, + unsigned int req_channel); + void (*channel_put)(struct dma_chan_data *channel); + + int (*start)(struct dma_chan_data *channel); + int (*stop)(struct dma_chan_data *channel); + int (*stop_delayed)(struct dma_chan_data *channel); + int (*copy)(struct dma_chan_data *channel, int bytes, uint32_t flags); + int (*pause)(struct dma_chan_data *channel); + int (*release)(struct dma_chan_data *channel); + int (*status)(struct dma_chan_data *channel, + struct dma_chan_status *status, uint8_t direction); + + int (*set_config)(struct dma_chan_data *channel, + struct dma_sg_config *config); + + int (*probe)(struct dma *dma); + int (*remove)(struct dma *dma); + + int (*get_data_size)(struct dma_chan_data *channel, uint32_t *avail, + uint32_t *free); + + int (*get_attribute)(struct dma *dma, uint32_t type, uint32_t *value); + + int (*interrupt)(struct dma_chan_data *channel, enum dma_irq_cmd cmd); +}; + +/* DMA platform data */ +struct dma_plat_data { + uint32_t id; + uint32_t dir; /* bitmask of supported copy directions */ + uint32_t caps; /* bitmask of supported capabilities */ + uint32_t devs; /* bitmask of supported devs */ + uint32_t base; + uint32_t channels; + int irq; + const char *irq_name; + uint32_t chan_size; + const void *drv_plat_data; +#ifdef __ZEPHYR__ + uint32_t period_count; +#endif +}; + +struct dma { + struct dma_plat_data plat_data; + struct k_spinlock lock; /**< locking mechanism */ + int sref; /**< simple ref counter, guarded by lock */ + const struct dma_ops *ops; + atomic_t num_channels_busy; /* number of busy channels */ + struct dma_chan_data *chan; /* channels array */ +#ifdef __ZEPHYR__ + const struct device *z_dev; /* Zephyr driver */ +#endif + void *priv_data; +}; + +struct dma_chan_data { + struct dma *dma; + + uint32_t status; + uint32_t direction; + uint32_t desc_count; + uint32_t index; + uint32_t core; + uint64_t period; /* DMA channel's transfer period in us */ + /* true if this DMA channel is the scheduling source */ + bool is_scheduling_source; + + /* device specific data set by the device that requests the DMA channel */ + void *dev_data; + + void *priv_data; +}; + +struct dma_info { + struct dma *dma_array; + size_t num_dmas; +}; + +struct audio_stream; +typedef int (*dma_process_func)(const struct audio_stream __sparse_cache *source, + uint32_t ioffset, struct audio_stream __sparse_cache *sink, + uint32_t ooffset, uint32_t frames); + +/** + * \brief API to initialize a platform DMA controllers. + * + * \param[in] sof Pointer to firmware main context. + */ +int dmac_init(struct sof *sof); + +/** + * \brief API to request a platform DMAC. + * + * Users can request DMAC based on dev type, copy direction, capabilities + * and access privilege. + * For exclusive access, ret DMAC with no channels draining. + * For shared access, ret DMAC with the least number of channels draining. + */ +struct dma *dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags); + +/** + * \brief API to release a platform DMAC. + * + * @param[in] dma DMAC to relese. + */ +void dma_put(struct dma *dma); + +#define dma_set_drvdata(dma, data) \ + (dma->priv_data = data) +#define dma_get_drvdata(dma) \ + dma->priv_data +#define dma_base(dma) \ + dma->plat_data.base +#define dma_irq(dma) \ + dma->plat_data.irq +#define dma_irq_name(dma) \ + dma->plat_data.irq_name +#define dma_chan_size(dma) \ + dma->plat_data.chan_size +#define dma_chan_base(dma, chan) \ + (dma->plat_data.base + chan * dma->plat_data.chan_size) +#define dma_chan_get_data(chan) \ + ((chan)->priv_data) +#define dma_chan_set_data(chan, data) \ + ((chan)->priv_data = data) + +/* DMA API + * Programming flow is :- + * + * 1) dma_channel_get() + * 2) notifier_register() + * 3) dma_set_config() + * 4) dma_start() + * ... DMA now running ... + * 5) dma_stop() + * 6) dma_stop_delayed() + * 7) dma_channel_put() + */ + +static inline struct dma_chan_data *dma_channel_get_legacy(struct dma *dma, + int req_channel) +{ + if (!dma || !dma->ops || !dma->ops->channel_get) + return NULL; + + struct dma_chan_data *chan = dma->ops->channel_get(dma, req_channel); + + return chan; +} + +static inline void dma_channel_put_legacy(struct dma_chan_data *channel) +{ + channel->dma->ops->channel_put(channel); +} + +static inline int dma_start_legacy(struct dma_chan_data *channel) +{ + return channel->dma->ops->start(channel); +} + +static inline int dma_stop_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->stop) + return channel->dma->ops->stop(channel); + + return 0; +} + +static inline int dma_stop_delayed_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->stop_delayed) + return channel->dma->ops->stop_delayed(channel); + + return 0; +} + +/** \defgroup sof_dma_copy_func static int dma_copy (struct dma_chan_data * channel, int bytes, uint32_t flags) + * + * This function is in a separate subgroup to solve a name clash with + * struct dma_copy {} + * @{ + */ +static inline int dma_copy_legacy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + return channel->dma->ops->copy(channel, bytes, flags); +} +/** @} */ + +static inline int dma_pause_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->pause) + return channel->dma->ops->pause(channel); + + return 0; +} + +static inline int dma_release_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->release) + return channel->dma->ops->release(channel); + + return 0; +} + +static inline int dma_status_legacy(struct dma_chan_data *channel, + struct dma_chan_status *status, uint8_t direction) +{ + return channel->dma->ops->status(channel, status, direction); +} + +static inline int dma_set_config_legacy(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + return channel->dma->ops->set_config(channel, config); +} + +static inline int dma_probe_legacy(struct dma *dma) +{ + return dma->ops->probe(dma); +} + +static inline int dma_remove_legacy(struct dma *dma) +{ + return dma->ops->remove(dma); +} + +static inline int dma_get_data_size_legacy(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + return channel->dma->ops->get_data_size(channel, avail, free); +} + +static inline int dma_get_attribute_legacy(struct dma *dma, uint32_t type, + uint32_t *value) +{ + return dma->ops->get_attribute(dma, type, value); +} + +static inline int dma_interrupt_legacy(struct dma_chan_data *channel, + enum dma_irq_cmd cmd) +{ + return channel->dma->ops->interrupt(channel, cmd); +} + +/* DMA hardware register operations */ +static inline uint32_t dma_reg_read(struct dma *dma, uint32_t reg) +{ + return io_reg_read(dma_base(dma) + reg); +} + +static inline uint16_t dma_reg_read16(struct dma *dma, uint32_t reg) +{ + return io_reg_read16(dma_base(dma) + reg); +} + +static inline void dma_reg_write(struct dma *dma, uint32_t reg, uint32_t value) +{ + io_reg_write(dma_base(dma) + reg, value); +} + +static inline void dma_reg_write16(struct dma *dma, uint32_t reg, + uint16_t value) +{ + io_reg_write16(dma_base(dma) + reg, value); +} + +static inline void dma_reg_update_bits(struct dma *dma, uint32_t reg, + uint32_t mask, uint32_t value) +{ + io_reg_update_bits(dma_base(dma) + reg, mask, value); +} + +static inline uint32_t dma_chan_reg_read(struct dma_chan_data *channel, + uint32_t reg) +{ + return io_reg_read(dma_chan_base(channel->dma, channel->index) + reg); +} + +static inline uint16_t dma_chan_reg_read16(struct dma_chan_data *channel, + uint32_t reg) +{ + return io_reg_read16(dma_chan_base(channel->dma, channel->index) + reg); +} + +static inline void dma_chan_reg_write(struct dma_chan_data *channel, + uint32_t reg, uint32_t value) +{ + io_reg_write(dma_chan_base(channel->dma, channel->index) + reg, value); +} + +static inline void dma_chan_reg_write16(struct dma_chan_data *channel, + uint32_t reg, uint16_t value) +{ + io_reg_write16(dma_chan_base(channel->dma, channel->index) + reg, + value); +} + +static inline void dma_chan_reg_update_bits(struct dma_chan_data *channel, + uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_update_bits(dma_chan_base(channel->dma, channel->index) + reg, + mask, value); +} + +static inline void dma_chan_reg_update_bits16(struct dma_chan_data *channel, + uint32_t reg, uint16_t mask, + uint16_t value) +{ + io_reg_update_bits16(dma_chan_base(channel->dma, channel->index) + reg, + mask, value); +} + +static inline bool dma_is_scheduling_source(struct dma_chan_data *channel) +{ + return channel->is_scheduling_source; +} + +static inline void dma_sg_init(struct dma_sg_elem_array *ea) +{ + ea->count = 0; + ea->elems = NULL; +} + +int dma_sg_alloc(struct dma_sg_elem_array *ea, + enum mem_zone zone, + uint32_t direction, + uint32_t buffer_count, uint32_t buffer_bytes, + uintptr_t dma_buffer_addr, uintptr_t external_addr); + +void dma_sg_free(struct dma_sg_elem_array *ea); + +/** + * \brief Get the total size of SG buffer + * + * \param ea Array of SG elements. + * \return Size of the buffer. + */ +static inline uint32_t dma_sg_get_size(struct dma_sg_elem_array *ea) +{ + int i; + uint32_t size = 0; + + for (i = 0 ; i < ea->count; i++) + size += ea->elems[i].size; + + return size; +} + +struct audio_stream; +typedef void (*dma_process)(const struct audio_stream *, + struct audio_stream *, uint32_t); + +/* copies data from DMA buffer using provided processing function */ +int dma_buffer_copy_from(struct comp_buffer __sparse_cache *source, + struct comp_buffer __sparse_cache *sink, + dma_process_func process, uint32_t source_bytes); + +/* copies data to DMA buffer using provided processing function */ +int dma_buffer_copy_to(struct comp_buffer __sparse_cache *source, + struct comp_buffer __sparse_cache *sink, + dma_process_func process, uint32_t sink_bytes); + +/* + * Used when copying DMA buffer bytes into multiple sink buffers, one at a time using the provided + * conversion function. DMA buffer consume should be performed after the data has been copied + * to all sinks. + */ +int dma_buffer_copy_from_no_consume(struct comp_buffer __sparse_cache *source, + struct comp_buffer __sparse_cache *sink, + dma_process_func process, uint32_t source_bytes); + +/* generic DMA DSP <-> Host copier */ + +struct dma_copy { + struct dma_chan_data *chan; + struct dma *dmac; +}; + +/* init dma copy context */ +int dma_copy_new(struct dma_copy *dc); + +/* free dma copy context resources */ +static inline void dma_copy_free(struct dma_copy *dc) +{ + dma_channel_put_legacy(dc->chan); +} + +/* DMA copy data from host to DSP */ +int dma_copy_from_host(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size); +int dma_copy_from_host_nowait(struct dma_copy *dc, + struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, + int32_t size); + +/* DMA copy data from DSP to host */ +int dma_copy_to_host(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size); +int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size); + + +int dma_copy_set_stream_tag(struct dma_copy *dc, uint32_t stream_tag); + +static inline const struct dma_info *dma_info_get(void) +{ + return sof_get()->dma_info; +} + +/** @}*/ + +#endif /* __SOF_LIB_DMA_H__ */ diff --git a/posix/include/sof/lib/io.h b/posix/include/sof/lib/io.h new file mode 100644 index 000000000000..07f1e5aa1fbe --- /dev/null +++ b/posix/include/sof/lib/io.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __XTOS_POSIX_LIB_IO_H__ +#define __XTOS_POSIX_LIB_IO_H__ + + +#include + +#if CONFIG_LIBRARY + +static inline uint32_t io_reg_read(uint32_t reg) { return 0; } +static inline void io_reg_write(uint32_t reg, uint32_t val) {} +static inline void io_reg_update_bits(uint32_t reg, uint32_t mask, + uint32_t value) {} +static inline uint16_t io_reg_read16(uint32_t reg) { return 0; } +static inline void io_reg_write16(uint32_t reg, uint16_t val) {} +static inline void io_reg_update_bits16(uint32_t reg, uint16_t mask, + uint16_t value) {} + +#else + +static inline uint32_t io_reg_read(uint32_t reg) +{ + return *((volatile uint32_t *)reg); +} + +static inline void io_reg_write(uint32_t reg, uint32_t val) +{ + *((volatile uint32_t *)reg) = val; +} + +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 *((volatile uint16_t *)reg); +} + +static inline void io_reg_write16(uint32_t reg, uint16_t val) +{ + *((volatile uint16_t *)reg) = val; +} + +static inline uint64_t io_reg_read64(uint32_t reg) +{ + return (uint64_t)io_reg_read(reg) + + (((uint64_t)io_reg_read(reg + 4)) << 32); +} + +static inline void io_reg_write64(uint32_t reg, uint64_t val) +{ + *((volatile uint64_t *)reg) = val; +} + +static inline void io_reg_update_bits16(uint32_t reg, uint16_t mask, + uint16_t value) +{ + io_reg_write16(reg, (io_reg_read16(reg) & (~mask)) | (value & mask)); +} + +static inline uint8_t io_reg_read8(uint32_t reg) +{ + return *((volatile uint8_t *)reg); +} + +static inline void io_reg_write8(uint32_t reg, uint8_t val) +{ + *((volatile uint8_t *)reg) = val; +} + +static inline void io_reg_update_bits8(uint32_t reg, uint8_t mask, + uint8_t value) +{ + io_reg_write8(reg, (io_reg_read8(reg) & (~mask)) | (value & mask)); +} + +#endif + +#endif /* __XTOS_POSIX_LIB_IO_H__ */ diff --git a/posix/include/sof/lib/mailbox.h b/posix/include/sof/lib/mailbox.h new file mode 100644 index 000000000000..3d43a22e10ec --- /dev/null +++ b/posix/include/sof/lib/mailbox.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Xiuli Pan + */ + +#ifndef __SOF_LIB_MAILBOX_H__ +#define __SOF_LIB_MAILBOX_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define mailbox_get_exception_base() \ + MAILBOX_EXCEPTION_BASE + +#define mailbox_get_exception_size() \ + MAILBOX_EXCEPTION_SIZE + +#define mailbox_get_dspbox_base() \ + MAILBOX_DSPBOX_BASE + +#define mailbox_get_dspbox_size() \ + MAILBOX_DSPBOX_SIZE + +#define mailbox_get_hostbox_base() \ + MAILBOX_HOSTBOX_BASE + +#define mailbox_get_hostbox_size() \ + MAILBOX_HOSTBOX_SIZE + +#define mailbox_get_debug_base() \ + MAILBOX_DEBUG_BASE + +#define mailbox_get_debug_size() \ + MAILBOX_DEBUG_SIZE + +static inline +void mailbox_dspbox_write(size_t offset, const void *src, size_t bytes) +{ + int dsp_write_err __unused = memcpy_s((void *)(MAILBOX_DSPBOX_BASE + offset), + MAILBOX_DSPBOX_SIZE - offset, src, bytes); + + assert(!dsp_write_err); + dcache_writeback_region((__sparse_force void __sparse_cache *)(MAILBOX_DSPBOX_BASE + + offset), bytes); +} + +static inline +void mailbox_dspbox_read(void *dest, size_t dest_size, + size_t offset, size_t bytes) +{ + int dsp_read_err __unused; + + dcache_invalidate_region((__sparse_force void __sparse_cache *)(MAILBOX_DSPBOX_BASE + + offset), bytes); + dsp_read_err = memcpy_s(dest, dest_size, + (void *)(MAILBOX_DSPBOX_BASE + offset), bytes); + assert(!dsp_read_err); +} + +#if CONFIG_LIBRARY + +#define mailbox_hostbox_write(_offset, _src, _bytes) \ + memcpy((char *)ipc->comp_data + _offset, _src, _bytes) + +static inline uint64_t mailbox_sw_reg_read64(uint32_t offset) +{ + return 0; +} +#else + +static inline +void mailbox_hostbox_write(size_t offset, const void *src, size_t bytes) +{ + int host_write_err __unused = memcpy_s((void *)(MAILBOX_HOSTBOX_BASE + offset), + MAILBOX_HOSTBOX_SIZE - offset, src, bytes); + + assert(!host_write_err); + dcache_writeback_region((__sparse_force void __sparse_cache *)(MAILBOX_HOSTBOX_BASE + + offset), bytes); +} + +#endif + +static inline +void mailbox_hostbox_read(void *dest, size_t dest_size, + size_t offset, size_t bytes) +{ + int host_read_err __unused; + + dcache_invalidate_region((__sparse_force void __sparse_cache *)(MAILBOX_HOSTBOX_BASE + + offset), bytes); + host_read_err = memcpy_s(dest, dest_size, + (void *)(MAILBOX_HOSTBOX_BASE + offset), bytes); + assert(!host_read_err); +} + +static inline +void mailbox_stream_write(size_t offset, const void *src, size_t bytes) +{ + int stream_write_err __unused = memcpy_s((void *)(MAILBOX_STREAM_BASE + offset), + MAILBOX_STREAM_SIZE - offset, src, bytes); + + assert(!stream_write_err); + dcache_writeback_region((__sparse_force void __sparse_cache *)(MAILBOX_STREAM_BASE + + offset), bytes); +} + +#endif /* __SOF_LIB_MAILBOX_H__ */ diff --git a/posix/include/sof/lib/memory.h b/posix/include/sof/lib/memory.h new file mode 100644 index 000000000000..8fcbc1f9adbe --- /dev/null +++ b/posix/include/sof/lib/memory.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + */ + +#ifndef __SOF_LIB_MEMORY_H__ +#define __SOF_LIB_MEMORY_H__ + +#include + +#endif /* __SOF_LIB_MEMORY_H__ */ diff --git a/posix/include/sof/lib/mm_heap.h b/posix/include/sof/lib/mm_heap.h new file mode 100644 index 000000000000..7bdab176eb5f --- /dev/null +++ b/posix/include/sof/lib/mm_heap.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +#ifndef __SOF_LIB_MM_HEAP_H__ +#define __SOF_LIB_MM_HEAP_H__ + +#include +#include +#include +#include +#include +#include + +#include +#include + +struct dma_copy; +struct dma_sg_config; + +struct mm_info { + uint32_t used; + uint32_t free; +}; + +struct block_hdr { + uint16_t size; /* size in blocks for continuous allocation */ + uint16_t used; /* usage flags for page */ + void *unaligned_ptr; /* align ptr */ +} __packed; + +struct block_map { + uint16_t block_size; /* size of block in bytes */ + uint16_t count; /* number of blocks in map */ + uint16_t free_count; /* number of free blocks */ + uint16_t first_free; /* index of first free block */ + struct block_hdr *block; /* base block header */ + uint32_t base; /* base address of space */ +}; + +#define BLOCK_DEF(sz, cnt, hdr) \ + {.block_size = sz, .count = cnt, .free_count = cnt, .block = hdr, \ + .first_free = 0} + +struct mm_heap { + uint32_t blocks; + struct block_map *map; +#if CONFIG_LIBRARY + unsigned long heap; +#else + uint32_t heap; +#endif + uint32_t size; + uint32_t caps; + struct mm_info info; +}; + +/* heap block memory map */ +struct mm { + /* system heap - used during init cannot be freed */ + struct mm_heap system[PLATFORM_HEAP_SYSTEM]; + /* system runtime heap - used for runtime system components */ + struct mm_heap system_runtime[PLATFORM_HEAP_SYSTEM_RUNTIME]; +#if CONFIG_CORE_COUNT > 1 + /* object shared between different cores - used during init cannot be freed */ + struct mm_heap system_shared[PLATFORM_HEAP_SYSTEM_SHARED]; + /* object shared between different cores */ + struct mm_heap runtime_shared[PLATFORM_HEAP_RUNTIME_SHARED]; +#endif + /* general heap for components */ + struct mm_heap runtime[PLATFORM_HEAP_RUNTIME]; + /* general component buffer heap */ + struct mm_heap buffer[PLATFORM_HEAP_BUFFER]; + + struct mm_info total; + uint32_t heap_trace_updated; /* updates that can be presented */ + struct k_spinlock lock; /* all allocs and frees are atomic */ +}; + +/* Heap save/restore contents and context for PM D0/D3 events */ +uint32_t mm_pm_context_size(void); + +/* heap initialisation */ +void init_heap(struct sof *sof); + +/* frees entire heap (supported for secondary core system heap atm) */ +void free_heap(enum mem_zone zone); + +/* status */ +void heap_trace_all(int force); +void heap_trace(struct mm_heap *heap, int size); + +#if CONFIG_DEBUG_MEMORY_USAGE_SCAN +/** Fetch runtime information about heap, like used and free memory space + * @param zone to check, see enum mem_zone. + * @param index heap index, eg. cpu core index for any *SYS* zone + * @param out output variable + * @return error code or zero + */ +int heap_info(enum mem_zone zone, int index, struct mm_info *out); +#endif + +/* retrieve memory map pointer */ +static inline struct mm *memmap_get(void) +{ + return sof_get()->memory_map; +} + +#endif /* __SOF_LIB_MM_HEAP_H__ */ diff --git a/posix/include/sof/lib/perf_cnt.h b/posix/include/sof/lib/perf_cnt.h new file mode 100644 index 000000000000..bddda9c8e06b --- /dev/null +++ b/posix/include/sof/lib/perf_cnt.h @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Marcin Maka + */ + +/** + * \file xtos/include/sof/lib/perf_cnt.h + * \brief Simple performance counters + * \author Marcin Maka + */ + +#ifndef __SOF_LIB_PERF_CNT_H__ +#define __SOF_LIB_PERF_CNT_H__ + +#include + +struct perf_cnt_data { + uint32_t plat_ts; + uint32_t cpu_ts; + uint32_t plat_delta_last; + uint32_t plat_delta_peak; + uint32_t cpu_delta_last; + uint32_t cpu_delta_peak; + uint32_t cpu_delta_sum; + uint32_t sample_cnt; +}; + +#if CONFIG_PERFORMANCE_COUNTERS + +#define perf_cnt_trace(ctx, pcd) \ + tr_info(ctx, "perf plat last %u peak %u cpu last %u, peak %u", \ + (uint32_t)((pcd)->plat_delta_last), \ + (uint32_t)((pcd)->plat_delta_peak), \ + (uint32_t)((pcd)->cpu_delta_last), \ + (uint32_t)((pcd)->cpu_delta_peak)) + +/** \brief Clears performance counters data. */ +#define perf_cnt_clear(pcd) memset((pcd), 0, sizeof(struct perf_cnt_data)) + +/* NOTE: Zephyr's arch_timing_counter_get() might not be implemented + * for a particular platform. In this case let's fallback to use + * Zephyr's k_cycle_get_64(). This will result in both "platform" and + * "cpu" timestamps to be equal. + */ +#ifdef __ZEPHYR__ + #ifdef CONFIG_TIMING_FUNCTIONS + #define perf_cnt_get_cpu_ts arch_timing_counter_get + #else + #define perf_cnt_get_cpu_ts sof_cycle_get_64 + #endif /* CONFIG_TIMING_FUNCTIONS */ +#else + #define perf_cnt_get_cpu_ts() timer_get_system(cpu_timer_get()) +#endif /* __ZEPHYR__ */ + +/** \brief Initializes timestamps with current timer values. */ +#define perf_cnt_init(pcd) do { \ + (pcd)->plat_ts = sof_cycle_get_64(); \ + (pcd)->cpu_ts = perf_cnt_get_cpu_ts(); \ + } while (0) + +/* Trace macros that can be used as trace_m argument of the perf_cnt_stamp() + * to trace PCD values if the last arch timer reading exceeds the previous + * peak value. + * + * arg passed to perf_cnt_stamp() is forwarded to the trace_m() macro + * as the second argument. + */ + +/** \brief No trace when detecting peak value. */ +#define perf_trace_null(pcd, arg) + +/** \brief Simple trace, all values are printed, arg should be a tr_ctx address. + */ +#define perf_trace_simple(pcd, arg) perf_cnt_trace(arg, pcd) + +/* perf measurement windows size 2^x */ +#define PERF_CNT_CHECK_WINDOW_SIZE 10 +#define task_perf_avg_info(pcd, task_p, class) \ + tr_info(task_p, "perf_cycle task %p, %pU cpu avg %u peak %u",\ + class, (class)->uid, \ + (uint32_t)((pcd)->cpu_delta_sum), \ + (uint32_t)((pcd)->cpu_delta_peak)) +#define task_perf_cnt_avg(pcd, trace_m, arg, class) do { \ + (pcd)->cpu_delta_sum += (pcd)->cpu_delta_last; \ + if (++(pcd)->sample_cnt == 1 << PERF_CNT_CHECK_WINDOW_SIZE) { \ + (pcd)->cpu_delta_sum >>= PERF_CNT_CHECK_WINDOW_SIZE; \ + trace_m(pcd, arg, class); \ + (pcd)->cpu_delta_sum = 0; \ + (pcd)->sample_cnt = 0; \ + (pcd)->plat_delta_peak = 0; \ + (pcd)->cpu_delta_peak = 0; \ + } \ + } while (0) + +/** \brief Accumulates cpu timer delta samples calculated by perf_cnt_stamp(). + * + * If current sample count reaches the window size, compute the average and run trace_m. + * \param pcd Performance counters data. + * \param trace_m Trace function trace_m(pcd, arg) or trace macro if a + * more precise line number is desired in the logs. + * \param arg Argument passed to trace_m as arg. + */ +#define perf_cnt_average(pcd, trace_m, arg) do { \ + (pcd)->cpu_delta_sum += (pcd)->cpu_delta_last; \ + if (++(pcd)->sample_cnt == 1 << PERF_CNT_CHECK_WINDOW_SIZE) {\ + (pcd)->cpu_delta_sum >>= PERF_CNT_CHECK_WINDOW_SIZE; \ + trace_m(pcd, arg); \ + (pcd)->cpu_delta_sum = 0; \ + (pcd)->sample_cnt = 0; \ + (pcd)->plat_delta_peak = 0; \ + (pcd)->cpu_delta_peak = 0; \ + } \ + } while (0) + +/** \brief Reads the timers and computes delta to the previous readings. + * + * If current arch delta exceeds the previous peak value, trace_m is run. + * \param pcd Performance counters data. + * \param trace_m Trace function trace_m(pcd, arg) or trace macro if a + * more precise line number is desired in the logs. + * \param arg Argument passed to trace_m as arg. + */ +#define perf_cnt_stamp(pcd, trace_m, arg) do { \ + uint32_t plat_ts = \ + (uint32_t)sof_cycle_get_64(); \ + uint32_t cpu_ts = \ + (uint32_t)perf_cnt_get_cpu_ts(); \ + if (plat_ts > (pcd)->plat_ts) \ + (pcd)->plat_delta_last = plat_ts - (pcd)->plat_ts; \ + else \ + (pcd)->plat_delta_last = UINT32_MAX - (pcd)->plat_ts \ + + plat_ts; \ + if (cpu_ts > (pcd)->cpu_ts) \ + (pcd)->cpu_delta_last = cpu_ts - (pcd)->cpu_ts; \ + else \ + (pcd)->cpu_delta_last = UINT32_MAX - (pcd)->cpu_ts \ + + cpu_ts;\ + if ((pcd)->plat_delta_last > (pcd)->plat_delta_peak) \ + (pcd)->plat_delta_peak = (pcd)->plat_delta_last; \ + if ((pcd)->cpu_delta_last > (pcd)->cpu_delta_peak) { \ + (pcd)->cpu_delta_peak = (pcd)->cpu_delta_last; \ + trace_m(pcd, arg); \ + } \ + } while (0) + +/** + * For simple performance measurement and optimization in development stage, + * tic-toc api is provided. Performance data are traced at each tok call, + * to allow fast clocks usage deviation estimation. Example: + * + * \code{.c} + * void foo(struct comp_dev *dev) { + * static struct perf_cnt_data pcd; + * + * perf_tic(&pcd); + * bar(); + * perf_toc(&pcd, dev); + * } + * \endcode + */ + +/** \brief Save start timestamp in pcd structure + * + * \param pcd Performance counters data. + */ +#define perf_tic(pcd) \ + perf_cnt_init(pcd) + +/** \brief Save start timestamp in pcd structure + * + * \param pcd Performance counters data. + * \param comp Component used to get corresponding trace context. + */ +#define perf_toc(pcd, comp) do { \ + perf_cnt_stamp(pcd, perf_trace_null, NULL); \ + perf_trace_simple(pcd, trace_comp_get_tr_ctx(comp)); \ + } while (0) + +#else +#define perf_cnt_clear(pcd) +#define perf_cnt_init(pcd) +#define perf_cnt_stamp(pcd, trace_m, arg) +#define perf_cnt_average(pcd, trace_m, arg) +#endif + +#endif /* __SOF_LIB_PERF_CNT_H__ */ diff --git a/posix/include/sof/lib/pm_runtime.h b/posix/include/sof/lib/pm_runtime.h new file mode 100644 index 000000000000..c0a24116e629 --- /dev/null +++ b/posix/include/sof/lib/pm_runtime.h @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + * Janusz Jankowski + */ + +/** + * \file xtos/include/sof/lib/pm_runtime.h + * \brief Runtime power management header file + * \author Tomasz Lauda + */ + +#ifndef __SOF_LIB_PM_RUNTIME_H__ +#define __SOF_LIB_PM_RUNTIME_H__ + +#include +#include +#include +#include +#include +#include + +/** \addtogroup pm_runtime PM Runtime + * PM runtime specification. + * @{ + */ + +/* PM runtime flags */ + +#define RPM_ASYNC 0x01 /**< Request is asynchronous */ + +/** \brief Runtime power management context */ +enum pm_runtime_context { + PM_RUNTIME_HOST_DMA_L1 = 0, /**< Host DMA L1 */ + SSP_CLK, /**< SSP Clock */ + SSP_POW, /**< SSP Power */ + DMIC_CLK, /**< DMIC Clock */ + DMIC_POW, /**< DMIC Power */ + DW_DMAC_CLK, /**< DW DMAC Clock */ + CORE_MEMORY_POW, /**< Core Memory power */ + CORE_HP_CLK, /**< High Performance Clock*/ + PM_RUNTIME_DSP /**< DSP */ +}; + +/** \brief Runtime power management data. */ +struct pm_runtime_data { + struct k_spinlock lock; /**< lock mechanism */ + void *platform_data; /**< platform specific data */ +#if CONFIG_DSP_RESIDENCY_COUNTERS + struct r_counters_data *r_counters; /**< diagnostic DSP residency counters */ +#endif +}; + +#if CONFIG_DSP_RESIDENCY_COUNTERS +/** + * \brief DSP residency counters + * R0, R1, R2 are DSP residency counters which can be used differently + * based on platform implementation. + * In general R0 is the highest power consumption state while R2 is + * the lowest power consumption state. See platform specific pm_runtime.h + * for the platform HW specific mapping. + */ +enum dsp_r_state { + r0_r_state = 0, + r1_r_state, + r2_r_state +}; + +/** \brief Diagnostic DSP residency counters data */ +struct r_counters_data { + enum dsp_r_state cur_r_state; /**< current dsp_r_state */ + uint64_t ts; /**< dsp_r_state timestamp */ +}; +#endif + +/** + * \brief Initializes runtime power management. + */ +void pm_runtime_init(struct sof *sof); + +/** + * \brief Retrieves power management resource (async). + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_get(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Retrieves power management resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_get_sync(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Releases power management resource (async). + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_put(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Releases power management resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_put_sync(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Enables power management operations for the resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_enable(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Disables power management operations for the resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_disable(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Reports state of the power managed resource. + * + * @param context Type of power management context. + * @param index Index of the resource. + * + * @return true if the resource is active or pm disabled, false otherwise. + */ +bool pm_runtime_is_active(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Retrieves pointer to runtime power management data. + * + * @return Runtime power management data pointer. + */ +static inline struct pm_runtime_data *pm_runtime_data_get(void) +{ + return sof_get()->prd; +} + +#if CONFIG_DSP_RESIDENCY_COUNTERS +/** + * \brief Initializes DSP residency counters. + * + * \param[in] context Type of power management context. + */ +void init_dsp_r_state(enum dsp_r_state); + +/** + * \brief Reports DSP residency state. + * + * \param[in] new state + */ +void report_dsp_r_state(enum dsp_r_state); + +/** + * \brief Retrieves current DSP residency state. + * + * @return active DSP residency state + */ +enum dsp_r_state get_dsp_r_state(void); +#endif + +/** @}*/ + +#endif /* __SOF_LIB_PM_RUNTIME_H__ */ diff --git a/posix/include/sof/lib/shim.h b/posix/include/sof/lib/shim.h new file mode 100644 index 000000000000..518880f1f953 --- /dev/null +++ b/posix/include/sof/lib/shim.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + */ + +#ifndef __SOF_LIB_SHIM_H__ +#define __SOF_LIB_SHIM_H__ + +#include + +#endif /* __SOF_LIB_SHIM_H__ */ diff --git a/posix/include/sof/list.h b/posix/include/sof/list.h new file mode 100644 index 000000000000..a81576fb5e68 --- /dev/null +++ b/posix/include/sof/list.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +#ifndef __SOF_LIST_H__ +#define __SOF_LIST_H__ + +/* Really simple list manipulation */ + +struct list_item; + +struct list_item { + struct list_item *next; + struct list_item *prev; +}; + +/* a static list head initialiser */ +#define LIST_INIT(head) {&head, &head} + +/* initialise list before any use - list will point to itself */ +static inline void list_init(struct list_item *list) +{ + list->next = list; + list->prev = list; +} + +/* add new item to the start or head of the list */ +static inline void list_item_prepend(struct list_item *item, + struct list_item *list) +{ + struct list_item *next = list->next; + + next->prev = item; + item->next = next; + item->prev = list; + list->next = item; +} + +/* add new item to the end or tail of the list */ +static inline void list_item_append(struct list_item *item, + struct list_item *list) +{ + struct list_item *tail = list->prev; + + tail->next = item; + item->next = list; + item->prev = tail; + list->prev = item; +} + +/* delete item from the list leaves deleted list item + *in undefined state list_is_empty will return true + */ +static inline void list_item_del(struct list_item *item) +{ + item->next->prev = item->prev; + item->prev->next = item->next; + list_init(item); +} + +/* is list item the last item in list ? */ +static inline int list_item_is_last(struct list_item *item, + struct list_item *list) +{ + return item->next == list; +} + +/* is list empty ? */ +#define list_is_empty(item) \ + ((item)->next == item) + +#define __list_object(item, type, offset) \ + ((type *)((char *)(item) - (offset))) + +/* get the container object of the list item */ +#define list_item(item, type, member) \ + __list_object(item, type, offsetof(type, member)) + +/* get the container object of the first item in the list */ +#define list_first_item(list, type, member) \ + __list_object((list)->next, type, offsetof(type, member)) + +/* get the next container object in the list */ +#define list_next_item(object, member) \ + list_item((object)->member.next, typeof(*(object)), member) + +/* list iterator */ +#define list_for_item(item, list) \ + for (item = (list)->next; item != (list); item = item->next) + +/* list iterator */ +#define list_for_item_prev(item, list) \ + for (item = (list)->prev; item != (list); item = item->prev) + +/* list iterator - safe to delete items */ +#define list_for_item_safe(item, tmp, list) \ + for (item = (list)->next, tmp = item->next;\ + item != (list); \ + item = tmp, tmp = item->next) + +/** + * Re-links the list when head address changed (list moved). + * @param new_list New address of the head. + * @param old_list Old address of the head. + */ +static inline void list_relink(struct list_item *new_list, + struct list_item *old_list) +{ + struct list_item *li; + + if (new_list->next == old_list) { + list_init(new_list); + } else { + list_for_item(li, new_list) + if (li->next == old_list) + li->next = new_list; /* for stops here */ + list_for_item_prev(li, new_list) + if (li->prev == old_list) + li->prev = new_list; /* for stops here */ + } +} + +#endif /* __SOF_LIST_H__ */ diff --git a/src/arch/host/CMakeLists.txt b/src/arch/host/CMakeLists.txt index 39b0ea640bd4..7ec47e59c668 100644 --- a/src/arch/host/CMakeLists.txt +++ b/src/arch/host/CMakeLists.txt @@ -5,10 +5,9 @@ target_include_directories(sof_public_headers INTERFACE ${PROJECT_SOURCE_DIR}/sr target_include_directories(sof_public_headers INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/library/include) include(CheckCCompilerFlag) -# TODO: library should not need RTOS headers: FIX. if (NOT CONFIG_SOF_ZEPHYR_STRICT_HEADERS) target_include_directories(sof_public_headers INTERFACE - ${PROJECT_SOURCE_DIR}/xtos/include + ${PROJECT_SOURCE_DIR}/posix/include ) endif() diff --git a/tools/tplg_parser/CMakeLists.txt b/tools/tplg_parser/CMakeLists.txt index 5ede07db75d6..fbe1b6669ee4 100644 --- a/tools/tplg_parser/CMakeLists.txt +++ b/tools/tplg_parser/CMakeLists.txt @@ -42,9 +42,7 @@ target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/src/i target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/src/arch/host/include) target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/src/platform/library/include) target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/src/audio) - -# TODO: The topology parser should NOT need to include RTOS header. FIX. -target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/xtos/include) +target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/posix/include) # Configuration time, make copy configure_file(${default_asoc_h} ${CMAKE_CURRENT_BINARY_DIR}/include/alsa/sound/asoc.h) From 8faa78c2fab12cb7c290b35c616dec828bd009fa Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 30 Aug 2023 16:01:09 -0700 Subject: [PATCH 5/8] host: remove XTOS prefix from headers And add the POSIX prefix. Signed-off-by: Liam Girdwood Signed-off-by: Ranjani Sridharan --- src/arch/host/include/arch/debug/panic.h | 4 ++-- src/arch/host/include/arch/drivers/idc.h | 4 ++-- src/arch/host/include/arch/schedule/task.h | 6 +++--- src/arch/host/include/arch/spinlock.h | 2 +- src/arch/host/include/arch/string.h | 2 +- src/platform/library/include/platform/drivers/idc.h | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/arch/host/include/arch/debug/panic.h b/src/arch/host/include/arch/debug/panic.h index 67fb04aa70eb..85f47a5ecbbc 100644 --- a/src/arch/host/include/arch/debug/panic.h +++ b/src/arch/host/include/arch/debug/panic.h @@ -5,7 +5,7 @@ * Author: Tomasz Lauda */ -#ifdef __XTOS_RTOS_PANIC_H__ +#ifdef __POSIX_RTOS_PANIC_H__ #ifndef __ARCH_DEBUG_PANIC_H__ #define __ARCH_DEBUG_PANIC_H__ @@ -21,4 +21,4 @@ static inline void arch_dump_regs(void *dump_buf, uintptr_t stack_ptr, #error "This file shouldn't be included from outside of XTOS's rtos/panic.h" -#endif /* __XTOS_RTOS_PANIC_H__ */ +#endif /* __POSIX_RTOS_PANIC_H__ */ diff --git a/src/arch/host/include/arch/drivers/idc.h b/src/arch/host/include/arch/drivers/idc.h index 73719e55f2b8..3f3e67b89d76 100644 --- a/src/arch/host/include/arch/drivers/idc.h +++ b/src/arch/host/include/arch/drivers/idc.h @@ -5,7 +5,7 @@ * Author: Tomasz Lauda */ -#ifdef __XTOS_RTOS_IDC_H__ +#ifdef __POSIX_RTOS_IDC_H__ #ifndef __ARCH_DRIVERS_IDC_H__ #define __ARCH_DRIVERS_IDC_H__ @@ -16,4 +16,4 @@ #error "This file shouldn't be included from outside of XTOS's rtos/idc.h" -#endif /* __XTOS_RTOS_IDC_H__ */ +#endif /* __POSIX_RTOS_IDC_H__ */ diff --git a/src/arch/host/include/arch/schedule/task.h b/src/arch/host/include/arch/schedule/task.h index 5c6cbf102744..2b89d264e0a6 100644 --- a/src/arch/host/include/arch/schedule/task.h +++ b/src/arch/host/include/arch/schedule/task.h @@ -11,7 +11,7 @@ * \authors Liam Girdwood */ -#ifdef __XTOS_RTOS_TASK_H__ +#ifdef __POSIX_RTOS_TASK_H__ #ifndef __ARCH_SCHEDULE_TASK_H__ #define __ARCH_SCHEDULE_TASK_H__ @@ -20,6 +20,6 @@ #else -#error "This file shouldn't be included from outside of XTOS's rtos/task.h" +#error "This file shouldn't be included from outside of XTOS's posix/task.h" -#endif /* __XTOS_RTOS_TASK_H__ */ +#endif /* __POSIX_RTOS_TASK_H__ */ diff --git a/src/arch/host/include/arch/spinlock.h b/src/arch/host/include/arch/spinlock.h index 273133490e72..360cb72bdb1f 100644 --- a/src/arch/host/include/arch/spinlock.h +++ b/src/arch/host/include/arch/spinlock.h @@ -6,7 +6,7 @@ */ /* TODO: this needs fixed as part of the "host does not need rtos headers work" */ -#ifdef __XTOS_RTOS_SPINLOCK_H__ +#ifdef __POSIX_RTOS_SPINLOCK_H__ #ifndef __ARCH_SPINLOCK_H__ #define __ARCH_SPINLOCK_H__ diff --git a/src/arch/host/include/arch/string.h b/src/arch/host/include/arch/string.h index 166b417173f0..125f7bf555a6 100644 --- a/src/arch/host/include/arch/string.h +++ b/src/arch/host/include/arch/string.h @@ -5,7 +5,7 @@ * Author: Liam Girdwood */ -#ifdef __XTOS_RTOS_STRING_H__ +#ifdef __POSIX_RTOS_STRING_H__ #ifndef __ARCH_STRING_H__ #define __ARCH_STRING_H__ diff --git a/src/platform/library/include/platform/drivers/idc.h b/src/platform/library/include/platform/drivers/idc.h index 8738c87324dd..e538884bbb5f 100644 --- a/src/platform/library/include/platform/drivers/idc.h +++ b/src/platform/library/include/platform/drivers/idc.h @@ -5,7 +5,7 @@ * Author: Tomasz Lauda */ -#if defined(__XTOS_RTOS_IDC_H__) || defined(__ZEPHYR_RTOS_IDC_H__) +#ifdef __POSIX_RTOS_IDC_H__ #ifndef __PLATFORM_DRIVERS_IDC_H__ #define __PLATFORM_DRIVERS_IDC_H__ From 23678fd8305abd5c36a24c61c5e6351f87199f60 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 30 Aug 2023 16:06:59 -0700 Subject: [PATCH 6/8] library: Add missing definitions Add missing platform definitions for CPU freq, DAI definitions etc. Signed-off-by: Liam Girdwood Signed-off-by: Ranjani Sridharan --- src/include/ipc4/fw_reg.h | 2 +- src/platform/library/include/platform/lib/clk.h | 16 ++++++++++++++++ src/platform/library/include/platform/lib/dai.h | 16 ++++++++++++++++ .../library/include/platform/lib/mailbox.h | 7 +++++++ .../library/include/platform/lib/memory.h | 2 ++ src/platform/library/include/platform/platform.h | 2 ++ 6 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/include/ipc4/fw_reg.h b/src/include/ipc4/fw_reg.h index 732de50600be..a0f450954050 100644 --- a/src/include/ipc4/fw_reg.h +++ b/src/include/ipc4/fw_reg.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include /* Reports current ROM/FW status. */ struct ipc4_fw_status_reg { diff --git a/src/platform/library/include/platform/lib/clk.h b/src/platform/library/include/platform/lib/clk.h index 7c089ebac4f9..6d389a6152af 100644 --- a/src/platform/library/include/platform/lib/clk.h +++ b/src/platform/library/include/platform/lib/clk.h @@ -18,6 +18,22 @@ #define NUM_CLOCKS 2 +#define CPU_WOVCRO_FREQ_IDX 0 + +#define CPU_LPRO_FREQ_IDX 1 + +#define CPU_HPRO_FREQ_IDX 2 + +#define CPU_LOWEST_FREQ_IDX CPU_WOVCRO_FREQ_IDX + +#define CPU_DEFAULT_IDX CPU_HPRO_FREQ_IDX + +#define SSP_DEFAULT_IDX 1 + +#define NUM_CPU_FREQ 3 + +#define NUM_SSP_FREQ 3 + #endif /* __PLATFORM_LIB_CLK_H__ */ #else diff --git a/src/platform/library/include/platform/lib/dai.h b/src/platform/library/include/platform/lib/dai.h index 45065e86c3b9..5fb740e32270 100644 --- a/src/platform/library/include/platform/lib/dai.h +++ b/src/platform/library/include/platform/lib/dai.h @@ -10,6 +10,22 @@ #ifndef __PLATFORM_LIB_DAI_H__ #define __PLATFORM_LIB_DAI_H__ +#define DAI_NUM_SSP_BASE 6 + +/** \brief Number of HD/A Link Outputs */ +#define DAI_NUM_HDA_OUT 6 + +/** \brief Number of HD/A Link Inputs */ +#define DAI_NUM_HDA_IN 7 + +/* ALH */ + +/** \brief Number of ALH bi-directional links */ +#define DAI_NUM_ALH_BI_DIR_LINKS 16 + +/** \brief Number of contiguous ALH bi-dir links */ +#define DAI_NUM_ALH_BI_DIR_LINKS_GROUP 4 + #endif /* __PLATFORM_LIB_DAI_H__ */ #else diff --git a/src/platform/library/include/platform/lib/mailbox.h b/src/platform/library/include/platform/lib/mailbox.h index fbfbc3719b96..04470a43e66e 100644 --- a/src/platform/library/include/platform/lib/mailbox.h +++ b/src/platform/library/include/platform/lib/mailbox.h @@ -52,6 +52,13 @@ static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) { } +static inline void mailbox_sw_regs_write(size_t offset, const void *src, size_t bytes) {} + +static inline uint32_t mailbox_sw_reg_read(size_t offset) +{ + return 0; +} + #endif /* __PLATFORM_LIB_MAILBOX_H__ */ #else diff --git a/src/platform/library/include/platform/lib/memory.h b/src/platform/library/include/platform/lib/memory.h index f57e31617da3..fafb3df303f7 100644 --- a/src/platform/library/include/platform/lib/memory.h +++ b/src/platform/library/include/platform/lib/memory.h @@ -182,6 +182,8 @@ static inline uint32_t arch_get_stack_size(void) #define host_to_local(addr) (addr) #define local_to_host(addr) (addr) +#define IMR_BOOT_LDR_MANIFEST_BASE NULL + #endif /* __PLATFORM_LIB_MEMORY_H__ */ #else diff --git a/src/platform/library/include/platform/platform.h b/src/platform/library/include/platform/platform.h index b1912049d4ec..2b1b4f31fa0c 100644 --- a/src/platform/library/include/platform/platform.h +++ b/src/platform/library/include/platform/platform.h @@ -56,6 +56,8 @@ struct timer; */ #define DMA_TRACE_RESCHEDULE_TIME 100 +#define HW_CFG_VERSION 0 + static inline void platform_panic(uint32_t p) {} /** From 28c8db90e72b229dbe846f4def84c2ec18de2803 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 30 Aug 2023 16:11:27 -0700 Subject: [PATCH 7/8] ipc4: Add preprocessor directive Fix the base_fw.h file to add the missing preprocessor directive. Signed-off-by: Liam Girdwood Signed-off-by: Ranjani Sridharan --- src/include/ipc4/base_fw.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h index bd049fdded8c..3c4a953405e2 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -4,15 +4,8 @@ */ /* - * This file contains structures that are exact copies of an existing ABI used - * by IOT middleware. They are Intel specific and will be used by one middleware. - * * Some of the structures may contain programming implementations that makes them * unsuitable for generic use and general usage. - * - * This code is mostly copied "as-is" from existing C++ interface files hence the use of - * different style in places. The intention is to keep the interface as close as possible to - * original so it's easier to track changes with IPC host code. */ /** @@ -21,6 +14,9 @@ * NOTE: This ABI uses bit fields and is non portable. */ +#ifndef __SOF_IPC4_BASE_FW_H__ +#define __SOF_IPC4_BASE_FW_H__ + /* Three clk src states :low power XTAL, low power ring * and high power ring oscillator */ @@ -666,3 +662,5 @@ enum ipc4_power_state_type { IPC4_ACTIVE_CORES_MASK = 0, IPC4_CORE_KCPS = 1, }; + +#endif /* __SOF_IPC4_BASE_FW_H__ */ From f0bb9f3a76e2fcc7a431fd3472d8d5e67d1ddef3 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 30 Aug 2023 16:15:23 -0700 Subject: [PATCH 8/8] audio: Add new kconfig for shared library modules Add a new kconfig option to build the shared library modules that can be used to run the pipelines on the host with the testbench or the ALSA plugin. Signed-off-by: Liam Girdwood Signed-off-by: Ranjani Sridharan --- src/audio/CMakeLists.txt | 12 +++++++++--- src/audio/Kconfig | 8 ++++++++ src/audio/module_adapter/CMakeLists.txt | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index f35dd917eae0..c8c265e6dd0a 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -6,7 +6,7 @@ elseif(CONFIG_IPC_MAJOR_4) set(mixer_src mixin_mixout/mixin_mixout.c mixin_mixout/mixin_mixout_generic.c mixin_mixout/mixin_mixout_hifi3.c) endif() -if((NOT CONFIG_LIBRARY) OR CONFIG_LIBRARY_STATIC) +if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) add_local_sources(sof host-legacy.c component.c @@ -17,6 +17,7 @@ if((NOT CONFIG_LIBRARY) OR CONFIG_LIBRARY_STATIC) audio_stream.c channel_map.c ) + if(CONFIG_COMP_BLOB) add_local_sources(sof data_blob.c) endif() @@ -62,7 +63,7 @@ if((NOT CONFIG_LIBRARY) OR CONFIG_LIBRARY_STATIC) dai-legacy.c ) endif() - if(CONFIG_COMP_KPB) + if(CONFIG_COMP_KPB AND NOT CONFIG_LIBRARY_STATIC) add_local_sources(sof kpb.c ) @@ -89,7 +90,7 @@ if((NOT CONFIG_LIBRARY) OR CONFIG_LIBRARY_STATIC) if(CONFIG_COMP_RTNR) add_subdirectory(rtnr) endif() - if(CONFIG_COMP_BASEFW_IPC4) + if(CONFIG_COMP_BASEFW_IPC4 AND NOT CONFIG_LIBRARY) add_local_sources(sof base_fw.c ) @@ -125,6 +126,11 @@ add_local_sources(sof component.c data_blob.c buffer.c + source_api_helper.c + sink_api_helper.c + sink_source_utils.c + audio_stream.c + channel_map.c ) # Audio Modules with various optimizaitons diff --git a/src/audio/Kconfig b/src/audio/Kconfig index 77c6586db9f2..9781755c6001 100644 --- a/src/audio/Kconfig +++ b/src/audio/Kconfig @@ -684,4 +684,12 @@ config WRAP_ACTUAL_POSITION It is not necessary that on wrap, the buffer position would be zero.At wrap, in some cases based on the period size, the frame may not exactly be at the end of the buffer and roll over for some bytes from the beginning of the buffer. + +config COMP_MODULE_SHARED_LIBRARY_BUILD + bool "Build SOF modules as shared libraries" + default n + help + Select if you want to build modules as shared objects that can be used to run + pipelines on the host with the testbench or the ALSA plugin. + endmenu diff --git a/src/audio/module_adapter/CMakeLists.txt b/src/audio/module_adapter/CMakeLists.txt index e803f78ba91a..c49ea576ef0d 100644 --- a/src/audio/module_adapter/CMakeLists.txt +++ b/src/audio/module_adapter/CMakeLists.txt @@ -3,7 +3,7 @@ add_local_sources(sof module_adapter.c module/generic.c) -if((NOT CONFIG_LIBRARY) OR CONFIG_LIBRARY_STATIC) +if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) if(CONFIG_CADENCE_CODEC) add_local_sources(sof module/cadence.c)