summaryrefslogtreecommitdiff
path: root/hifi/xaf/hifi-dpf/include/sys/xt-shmem/xf-ipc.h
blob: 3ce5bd668c7a74148c2ce402ed4caed13de26fd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
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 */