diff options
Diffstat (limited to 'hifi/xaf/hifi-dpf/include/sys/xt-shmem/xf-ipc.h')
-rw-r--r-- | hifi/xaf/hifi-dpf/include/sys/xt-shmem/xf-ipc.h | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/hifi/xaf/hifi-dpf/include/sys/xt-shmem/xf-ipc.h b/hifi/xaf/hifi-dpf/include/sys/xt-shmem/xf-ipc.h new file mode 100644 index 00000000..3ce5bd66 --- /dev/null +++ b/hifi/xaf/hifi-dpf/include/sys/xt-shmem/xf-ipc.h @@ -0,0 +1,345 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +/******************************************************************************* + * xf-ipc.h + * + * Xtensa IPC mechanism + * + *******************************************************************************/ + +#ifndef __XF_H +#error "xf-ipc.h mustn't be included directly" +#endif + +/******************************************************************************* + * Includes + ******************************************************************************/ + +/* ...system-specific shared memory configuration */ +#include "xf-shmem.h" +#ifndef XAF_ENABLE_NON_HIKEY +#include <xtensa/xtruntime.h> +extern volatile int waitstate; +#endif + +#ifdef XAF_ENABLE_NON_HIKEY +/******************************************************************************* + * Macros definitions (should better go to some other header) + ******************************************************************************/ + +/* + * Execute WAITI 0 (enabling interrupts) only if *(ptr) is zero. + * The decision to execute WAITI is done atomically by disabling + * interrupts at level 'level' (level must be a constant) + * before checking the pointer. Interrupts are always re-enabled + * on exit from this macro. + */ +#define _WAITI_ON_PTR(ptr, level) \ +do { \ + int __tmp; \ + __asm__ (" rsil %0, " #level " \n" \ + " l32i %0, %1, 0 \n" \ + " bnez %0, 1f \n" \ + " waiti 0 \n" \ + "1:rsil %0, 0 \n" \ + : "=a" (__tmp) : "a" (ptr) : "memory"); \ +} while(0) + +/* ...enable gdbstub */ +//#define XF_CFG_USE_GDBSTUB 0 + +#ifndef XF_CFG_USE_GDBSTUB +/* ...maybe "level" should be hidden here - we always magically set 15 */ +#define WAITI_ON_PTR(ptr, level) _WAITI_ON_PTR(ptr, level) +#else +/* ...if debugger is enabled, do polling instead of waiting */ +static inline void WAITI_ON_PTR(volatile u32 *ptr, u32 level) +{ + extern void poll_debug_ring(void); + + while (*ptr == 0) + { + /* ...should be called with interrupts disabled - tbd */ + poll_debug_ring(); + } +} +#endif + +/******************************************************************************* + * Remote IPI interrupt mode + ******************************************************************************/ + +/* ...enable/disable IPI interrupt */ +static inline void xf_ipi_enable(u32 core, int on) +{ + if (on) + _xtos_ints_on(1 << XF_PROXY_IPI_NUM(core)); + else + _xtos_ints_off(1 << XF_PROXY_IPI_NUM(core)); +} + +/* ...wait in low-power mode for interrupt arrival if "ptr" is 0 */ +static inline void xf_ipi_wait(u32 core) +{ + xf_core_ro_data_t *ro = XF_CORE_RO_DATA(core); + + /* ...enable IPI interrupt before sleeping */ + xf_ipi_enable(core, 1); + + /* ...wait in low-power mode, atomically checking *ipc != 0 */ + WAITI_ON_PTR(&ro->ipc.wait, 15); + + /* ...force disabling of IPI interrupts */ + xf_ipi_enable(core, 0); + + /* ...reset waiting object upon leaving */ + ro->ipc.wait = 0; +} +#else +#define _WAITI_ON_PTR(ptr, level) \ + do { \ + int __tmp; \ + __asm__ (" rsil %0, " #level " \n" \ + " l32i %0, %1, 0 \n" \ + " bnez %0, 1f \n" \ + " waiti 0 \n" \ + "1:rsil %0, 0 \n" \ + : "=a" (__tmp) : "a" (ptr) : "memory"); \ + } while(0) + +#define WAITI_ON_PTR(ptr, level) _WAITI_ON_PTR(ptr, level) +static inline void xf_ipi_wait(u32 core) +{ +#if 0 + // VOS_EnableInterrupt(DSP_IPC_FROM_AP_INT_NO); + _xtos_ints_on(1 << DSP_IPC_FROM_AP_INT_NO); + while(1) + { + if(waitstate ==1) + { + // VOS_DisableInterrupt(DSP_IPC_FROM_AP_INT_NO); + _xtos_ints_off(1 << DSP_IPC_FROM_AP_INT_NO); + waitstate = 0; + break; + } + } +#else + + _xtos_ints_on(1 << DSP_IPC_FROM_AP_INT_NO); + /* ...wait in low-power mode, atomically checking *ipc != 0 */ + WAITI_ON_PTR(&waitstate, 15); + + /* ...force disabling of IPI interrupts */ + + _xtos_ints_off(1 << DSP_IPC_FROM_AP_INT_NO); + /* ...reset waiting object upon leaving */ + waitstate = 0; + +#endif +} +#endif +#ifdef XAF_ENABLE_NON_HIKEY +/* ...complete IPI waiting (may be called from any context on local core) */ +static inline void xf_ipi_resume(u32 core) +{ + xf_core_ro_data_t *ro = XF_CORE_RO_DATA(core); + + /* ...single instruction is written atomically; no need to mask interrupts */ + ro->ipc.wait = 1; +} +#else +/* ...complete IPI waiting (may be called from any context on local core) */ +static inline void xf_ipi_resume(u32 core) +{ + unsigned int ipc_int_state = 0; + unsigned int ipc_data = 0; + + _xtos_ints_off(1 << DSP_IPC_FROM_AP_INT_NO); + + //process message + ipc_int_state = SYS_IPC_CPUIRST(DSP_SYS_IPC_BASE_ADDR_NS, SYS_IPC_CORE_HIFI); + + if (ipc_int_state & BIT_MASK(DSP_AP_TO_DSP_MAILBOX_NO)) { //mailbox-18 + SYS_IPC_ICLR(DSP_SYS_IPC_BASE_ADDR_NS, DSP_AP_TO_DSP_MAILBOX_NO) = BIT_MASK(SYS_IPC_CORE_HIFI); + waitstate = 1; + } + + //_xtos_ints_on(1 << DSP_IPC_FROM_AP_INT_NO); + + return; +} +#endif +#if 0//ndef HIKEY_XAF_IPC_COMMENT_OUT +/* ...notify remote side about status change */ +//#define XF_PROXY_NOTIFY_PEER(core) dsp_ipc_send_irq_to_ap() + +static inline void dsp_ipc_send_irq_to_ap(void) +{ + unsigned int mode = 0; + unsigned int mode_1 = 0; + + mode = SYS_IPC_MODE(DSP_SYS_IPC_BASE_ADDR_NS, DSP_DSP_TO_AP_MAILBOX_NO); + + if (mode & BIT_MASK(SYS_IPC_MODE_IDLE)) { + mode_1=0; + } else { + return; + } + + + SYS_IPC_SOURCE(DSP_SYS_IPC_BASE_ADDR_NS, DSP_DSP_TO_AP_MAILBOX_NO) = BIT_MASK(SYS_IPC_CORE_HIFI); + SYS_IPC_IMASK(DSP_SYS_IPC_BASE_ADDR_NS, DSP_DSP_TO_AP_MAILBOX_NO) = ~((unsigned int)(BIT_MASK(SYS_IPC_CORE_HIFI)|BIT_MASK(SYS_IPC_CORE_A15))); + SYS_IPC_DATA(DSP_SYS_IPC_BASE_ADDR_NS, DSP_DSP_TO_AP_MAILBOX_NO, 0) = IPC_ACPU_INT_SRC_HIFI_MSG; + SYS_IPC_MODE(DSP_SYS_IPC_BASE_ADDR_NS, DSP_DSP_TO_AP_MAILBOX_NO) = BIT_MASK(SYS_IPC_MODE_AUTOACK); + SYS_IPC_SEND(DSP_SYS_IPC_BASE_ADDR_NS, DSP_DSP_TO_AP_MAILBOX_NO) = BIT_MASK(SYS_IPC_CORE_HIFI); + + return; +} +#endif +/* ...assert IPI interrupt on remote core - board-specific */ +static inline void xf_ipi_assert(u32 core) +{ + XF_PROXY_NOTIFY_PEER(core); +} + +#ifdef XAF_ENABLE_NON_HIKEY +/* ...initialize IPI subsystem */ +static inline int xf_ipi_init(u32 core) +{ + xf_core_ro_data_t *ro = XF_CORE_RO_DATA(core); + extern void (* const xf_ipi_handlers[])(void); + + /* ...reset IPC data - no interrupt yet */ + ro->ipc.wait = 0; + + /* ...install interrupt handler */ + _xtos_set_interrupt_handler(XF_PROXY_IPI_NUM(core), xf_ipi_handlers[core]); + + return 0; +} +#else +/* ...initialize IPI subsystem */ +static inline int xf_ipi_init(u32 core) +{ + + waitstate =0; + + dsp_debug_init(); + //dsp_init_share_mem(HIKEY_AP2DSP_MSG_QUEUE_ADDR,HIKEY_DSP2AP_MSG_QUEUE_SIZE); + /* unlock reg */ + SYS_IPC_LOCK(DSP_SYS_IPC_BASE_ADDR_NS) = 0x1ACCE551; + //VOS_ConnectInterrupt(DSP_IPC_FROM_AP_INT_NO, _ap_to_dsp_ipc_irq_proc); + VOS_ConnectInterrupt(DSP_IPC_FROM_AP_INT_NO, xf_ipi_resume); + +// VOS_EnableInterrupt(DSP_IPC_FROM_AP_INT_NO); + + return; +} +#endif + +/******************************************************************************* + * Shared memory operations + ******************************************************************************/ + +/* ...NULL-address specification */ +#define XF_PROXY_NULL (~0U) + +/* ...invalid proxy address */ +#define XF_PROXY_BADADDR XF_CFG_REMOTE_IPC_POOL_SIZE +/* ...translate buffer address to shared proxy address */ +static inline u32 xf_ipc_b2a(u32 core, void *b) +{ + xf_shmem_data_t *shmem = XF_CORE_DATA(core)->shmem; + void *start = shmem->buffer; + + if (b == NULL) + return XF_PROXY_NULL; + else if ((s32)(b - start) < XF_CFG_REMOTE_IPC_POOL_SIZE) + return (u32)(b - start); + else + return XF_PROXY_BADADDR; +} +/* ...translate shared proxy address to local pointer */ +static inline void * xf_ipc_a2b(u32 core, u32 address) +{ + xf_shmem_data_t *shmem = XF_CORE_DATA(core)->shmem; + void *start = shmem->buffer; + + if (address < XF_CFG_REMOTE_IPC_POOL_SIZE) + return start + address; + else if (address == XF_PROXY_NULL) + return NULL; + else + return (void *)-1; +} + +/* ...component association with remote IPC client */ +static inline void xf_ipc_component_addref(u32 session) +{ +} + +/* ...delete record about component association with remote IPC client */ +static inline void xf_ipc_component_rmref(u32 id) +{ +} + +/* ...system-specific IPC layer initialization */ +extern int xf_ipc_init(u32 core); + +/******************************************************************************* + * Mutex definitions + ******************************************************************************/ + +/* ...export shared memory access macros */ +#define MUTEX_SHARED_READ(core) \ + ({ xf_core_ro_data_t *__ro = XF_CORE_RO_DATA(core); __ro->lock[0]; }) + +#define MUTEX_SHARED_WRITE(core, val) \ + ({ xf_core_ro_data_t *__ro = XF_CORE_RO_DATA(core); __ro->lock[0] = (val); }) + +/* ...include library header */ +#include "lib/mutex.h" + +#if XF_CFG_CORES_NUM > 1 +/* ...rename API functions */ +static inline void xf_mutex_lock(u32 core) +{ + mutex_lock(core); +} + +static inline void xf_mutex_unlock(u32 core) +{ + mutex_unlock(core); +} + +#else +/* ...for single-core setting no locking is actually needed */ +static inline void xf_mutex_lock(u32 core) +{ +} + +static inline void xf_mutex_unlock(u32 core) +{ +} + +#endif /* XF_CFG_CORES_NUM > 1 */ |