Sound Open Firmware
Loading...
Searching...
No Matches
common.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2019 Intel Corporation. All rights reserved.
4 *
5 * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com>
6 * Janusz Jankowski <janusz.jankowski@linux.intel.com>
7 */
8
9#ifndef __SOF_COMMON_H__
10#define __SOF_COMMON_H__
11
12#if !defined(LINKER)
13
14/* callers must check/use the return value */
15#define __must_check __attribute__((warn_unused_result))
16
17#include <zephyr/sys/util.h>
18
19/* Align the number to the nearest alignment value */
20#ifndef IS_ALIGNED
21#define IS_ALIGNED(size, alignment) ((size) % (alignment) == 0)
22#endif
23
24/* Treat zero as a special case because it wraps around */
25#define is_power_of_2(x) ((x) && !((x) & ((x) - 1)))
26
27#define compile_check(x) (sizeof(struct { int _f[2 * (x) - 1]; }) != 0)
28
29#define ALIGN_UP_INTERNAL(val, align) (((val) + (align) - 1) & ~((align) - 1))
30
31#if !defined(__ASSEMBLER__) && defined(__XTENSA__)
32
33#include <ipc/trace.h>
34#include <rtos/panic.h>
35#define VERIFY_ALIGN
36
37#endif
38
39#ifdef VERIFY_ALIGN
40
41/* Using this when 'alignment' is a constant and when compiling with gcc
42 * -O0 saves about 30 bytes of .text and a few CPU cycles compared to
43 * the ALIGN_UP() combined check. There's no .text difference when
44 * optimizing.
45 */
46#define ALIGN_UP_COMPILE(size, alignment) \
47 (compile_check(is_power_of_2(alignment)) ? \
48 ALIGN_UP_INTERNAL(size, alignment) : 0xBADCAFE)
49
50#if defined(__XCC__) || defined(__clang__)
51
52/*
53 * xcc doesn't support __builtin_constant_p() so we can only do run-time
54 * verification
55 */
56
57#define ALIGN_UP(size, alignment) ({ \
58 if (!is_power_of_2(alignment)) \
59 sof_panic(SOF_IPC_PANIC_ASSERT); \
60 ALIGN_UP_INTERNAL(size, alignment); \
61})
62
63#define ALIGN_DOWN(size, alignment) ({ \
64 if (!is_power_of_2(alignment)) \
65 sof_panic(SOF_IPC_PANIC_ASSERT); \
66 (size) & ~((alignment) - 1); \
67})
68
69#else /* not __XCC__ or __clang__ */
70
71/* If we can't tell at compile time, assume it's OK and defer to run-time */
72#define COMPILE_TIME_ALIGNED(align) (!__builtin_constant_p(align) || \
73 is_power_of_2(align))
74
75#define ALIGN_UP(size, alignment) ({ \
76 if (!compile_check(COMPILE_TIME_ALIGNED(alignment)) || \
77 !is_power_of_2(alignment)) \
78 sof_panic(SOF_IPC_PANIC_ASSERT); \
79 ALIGN_UP_INTERNAL(size, alignment); \
80})
81
82#define ALIGN_DOWN(size, alignment) ({ \
83 if (!compile_check(COMPILE_TIME_ALIGNED(alignment)) || \
84 !is_power_of_2(alignment)) \
85 sof_panic(SOF_IPC_PANIC_ASSERT); \
86 (size) & ~((alignment) - 1); \
87})
88
89#endif /* not __XCC__ or __clang__ */
90
91#else /* not VERIFY_ALIGN */
92
93#define ALIGN_UP(size, alignment) ALIGN_UP_INTERNAL(size, alignment)
94#define ALIGN_UP_COMPILE ALIGN_UP
95#define ALIGN_DOWN(size, alignment) ((size) & ~((alignment) - 1))
96
97#endif
98
99/* This most basic ALIGN() must be used in header files that are
100 * included in both C and assembly code. memory.h files require this
101 * exact spelling matching the linker function because memory.h values
102 * are _also_ copied unprocessed to the .x[.in] linker script
103 */
104#define ALIGN(val, align) ALIGN_UP_INTERNAL(val, align)
105#define SOF_DIV_ROUND_UP(val, div) (((val) + (div) - 1) / (div))
106
107#if !defined(__ASSEMBLER__)
108
109#include <rtos/string_macro.h>
111#include <stddef.h>
112
113/* use same syntax as Linux for simplicity */
114#ifndef __ZEPHYR__ /* Already present and compatible via Zephyr headers */
115#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
116#endif
117#define container_of(ptr, type, member) \
118 ({const __typeof__(((type *)0)->member)*__memberptr = (ptr); \
119 (type *)((char *)__memberptr - offsetof(type, member)); })
120/*
121 * typeof() doesn't preserve __attribute__((address_space(x))) sparse
122 * annotations, so if an object belongs to such an address space, using the
123 * original form of container_of() will lose that annotation, which then will
124 * lead to sparse "different address spaces" warnings. We need to explicitly
125 * re-inforce the address space onto the new pointer.
126 */
127#define attr_container_of(ptr, type, member, attr) \
128 ({const __typeof__(((type *)0)->member) attr *__memberptr = (ptr); \
129 (type *)((char attr *)__memberptr - offsetof(type, member)); })
130
131#define ffs(i) __builtin_ffs(i)
132#define ffsl(i) __builtin_ffsl(i)
133#define ffsll(i) __builtin_ffsll(i)
134
135#define clz(i) __builtin_clz(i)
136#define clzl(i) __builtin_clzl(i)
137#define clzll(i) __builtin_clzll(i)
138
139#define popcount(x) __builtin_popcount(x)
140
141/* count number of var args */
142#define PP_NARG(...) (sizeof((unsigned int[]){0, ##__VA_ARGS__}) \
143 / sizeof(unsigned int) - 1)
144
145/* Compile-time assertion.
146 *
147 * The first, typedef-based solution silently succeeds with variables,
148 * for instance STATIC_ASSERT(n == 42, always_succeeds) when 'n' is a
149 * variable in a function. The second, array-based solution is not
150 * fooled by variables but it increases the .bss size at the -O0
151 * optimization level (no difference with any real -O). As we're often
152 * short on space, use the typedef-based version by default. If you're
153 * afraid that some assertions are being fooled by variables then
154 * temporarily and locally switch to the second one.
155 */
156#define STATIC_ASSERT(COND, MESSAGE) \
157 __attribute__((unused)) \
158 typedef char _CONCAT(assertion_failed_, MESSAGE)[(COND) ? 1 : -1]
159
160/* Allows checking preprocessor symbols in compile-time.
161 * Returns true for config with value 1, false for undefined or any other value.
162 *
163 * Expression like (CONFIG_MY ? a : b) rises compilation error when CONFIG_MY
164 * is undefined, (IS_ENABLED(CONFIG_MY) ? a : b) can be used instead of it.
165 *
166 * It is intended to be used with Kconfig's bool configs - it should rise
167 * error for other types, except positive integers, but it shouldn't be
168 * used with them.
169 */
170#ifndef __ZEPHYR__ /* Already present and compatible via Zephyr headers */
171#define IS_ENABLED(config) IS_ENABLED_STEP_1(config)
172#define IS_ENABLED_DUMMY_1 0,
173#define IS_ENABLED_STEP_1(config) IS_ENABLED_STEP_2(IS_ENABLED_DUMMY_ ## config)
174#define IS_ENABLED_STEP_2(values) IS_ENABLED_STEP_3(values 1, 0)
175#define IS_ENABLED_STEP_3(ignore, value, ...) (!!(value))
176#endif
177
178#define SOF_CONFIG_HIFI(level, component) (CONFIG_ ## component ## _HIFI_ ## level)
179
180/* True if:
181 * (1) EITHER this particular level was manually forced in Kconfig,
182 * (2) OR: - this component defaulted to "MAX"
183 * - AND this level is the max available in the XC HAL.
184 */
185#define SOF_USE_HIFI(level, component) (SOF_CONFIG_HIFI(level, component) || \
186 (SOF_CONFIG_HIFI(MAX, component) && level == SOF_MAX_XCHAL_HIFI))
187
188/* True if:
189 * (1) EITHER this particular level was manually forced in Kconfig,
190 * (2) OR: - this component defaulted to "MAX"
191 * - AND this level is less or equal to max available in the XC HAL.
192 *
193 * Use e.g. for highest optimization level source file, e.g. SOF_USE_MIN_HIFI(4, component)
194 * for HiFi4 code version that can be built with HiFi4 or HiFi5 tool chain.
195 */
196#define SOF_USE_MIN_HIFI(minlevel, component) (SOF_CONFIG_HIFI(minlevel, component) || \
197 (SOF_CONFIG_HIFI(MAX, component) && minlevel <= SOF_MAX_XCHAL_HIFI))
198
199#define SOF_CONFIG_ARM_SIMD(component) (CONFIG_ ## component ## _ARM_SIMD)
200#define SOF_USE_ARM_SIMD(component) (IS_ENABLED(CONFIG_ ## component ## _ARM_SIMD))
201#define SOF_CONFIG_ARM_FPU(component) (CONFIG_ ## component ## _ARM_FPU)
202#define SOF_USE_ARM_FPU(component) (IS_ENABLED(CONFIG_ ## component ## _ARM_FPU))
203
204#define SOF_CONFIG_RISCV_SIMD(component) (CONFIG_ ## component ## _RISCV_SIMD)
205#define SOF_USE_RISCV_SIMD(component) (IS_ENABLED(CONFIG_ ## component ## _RISCV_SIMD))
206
207#ifndef __XCC__ // Cadence toolchains: either xt-xcc or xt-clang.
208# define SOF_MAX_XCHAL_HIFI NONE
209#else
210# include <xtensa/config/core-isa.h>
211// Maybe we could make this fully generic (and less readable!) using
212// IS_ENABLED() above.
213# if XCHAL_HAVE_HIFI5
214# define SOF_MAX_XCHAL_HIFI 5
215# define SOF_FRAME_BYTE_ALIGN 16
216# elif XCHAL_HAVE_HIFI4
217# define SOF_MAX_XCHAL_HIFI 4
218# define SOF_FRAME_BYTE_ALIGN 8
219# elif XCHAL_HAVE_HIFI3
220# define SOF_MAX_XCHAL_HIFI 3
221# define SOF_FRAME_BYTE_ALIGN 8
222# else
223# define SOF_MAX_XCHAL_HIFI NONE
224# endif
225#endif
226
227/* Keep this last after all platform specific align defaults */
228#ifndef SOF_FRAME_BYTE_ALIGN
229# define SOF_FRAME_BYTE_ALIGN 4
230#endif
231
232/* Default frame-count alignment is 1 */
233#define SOF_FRAME_COUNT_ALIGN 1
234
235#ifndef __GLIBC_USE
236#define __GLIBC_USE(x) 0
237#endif
238
239#if defined(__XCC__) || defined(__CHECKER__)
240/* XCC does not currently check alignment for packed data so no need for any
241 * compiler hints.
242 */
243#define ASSUME_ALIGNED(x, a) x
244#else
245/* GCC 9.x has checks for pointer alignment within packed structures when
246 * cast from one type to another. This macro should only be used after checking
247 * alignment. This compiler builtin may not be available on all compilers so
248 * this macro can be defined as NULL if needed.
249 */
250#define ASSUME_ALIGNED(x, a) ((__typeof__(x))__builtin_assume_aligned((x), a))
251#endif /* __XCC__ */
252
253#endif /* __ASSEMBLER__ */
254#else /* LINKER */
255
256#define ALIGN_UP_INTERNAL(val, align) (((val) + (align) - 1) & ~((align) - 1))
257
258#endif /* LINKER */
259#endif /* __SOF_COMMON_H__ */
Host-DSP IPC trace DMA configuration, filtering, and panic descriptors.