summaryrefslogtreecommitdiff
path: root/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c
blob: 7f99b710401654b87092eee85a318a30917ecbfc (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
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
/*
 * Copyright (C) ST-Ericsson SA 2010
 * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson.
 * License terms: GNU General Public License (GPL) version 2.
 */
#include <cm/inc/cm_type.h>
#include <cm/engine/component/inc/introspection.h>
#include <cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h>
#include <cm/engine/communication/inc/communication.h>
#include <cm/engine/dsp/inc/dsp.h>
#include <cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h>

#include <cm/engine/power_mgt/inc/power.h>
#include <cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h>

#include <cm/engine/trace/inc/trace.h>

#include "../inc/dspevent.h"
#include "../inc/initializer.h"

// Since now due to semaphore use call is synchrone so we only need a fifo size of three
// (due to updateStack + (InstructionCacheLock or InstructionCacheUnlock))
#define DEFAULT_INITIALIZER_FIFO_SIZE 3

/* private prototype */
PRIVATE t_cm_error cm_COMP_generic(t_nmf_core_id coreId, t_event_params_handle paramArray, t_uint32 paramNumber, t_uint32 serviceIndex);
PRIVATE void cm_COMP_generatePanic(t_nmf_core_id coreId);

/*
 * This module is tightly coupled with cm_DSP_components one (communication/initializer)
 */
static struct {
    t_nmf_fifo_arm_desc* downlinkFifo;
    t_nmf_fifo_arm_desc* uplinkFifo;
    t_memory_handle dspfifoHandle;
    t_nmf_osal_sem_handle fifoSemHandle;
    t_uint32 servicePending;                // TODO : Use sem counter instead of defining such variable (need to create new OSAL)
} initializerDesc[NB_CORE_IDS];

PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId)
{
    t_uint32 i;
    t_cm_error error;
    t_component_instance *ee;
    t_dsp_offset sharedVarOffset;
    t_interface_provide_description itfProvide;
    t_interface_provide* provide;
    t_interface_provide_loaded* provideLoaded;

    ee = cm_EEM_getExecutiveEngine(coreId)->instance;

    // Get interface description
    if((error = cm_getProvidedInterface(ee, "service", &itfProvide)) != CM_OK)
        return error;
    provide = &ee->Template->provides[itfProvide.provideIndex];
    provideLoaded = &ee->Template->providesLoaded[itfProvide.provideIndex];


    if ((error = dspevent_createDspEventFifo(
                    ee, "comms/TOP",
                    DEFAULT_INITIALIZER_FIFO_SIZE,
                    DSP_REMOTE_EVENT_SIZE_IN_DSPWORD,
                    INTERNAL_XRAM24,
                    &initializerDesc[coreId].dspfifoHandle)) != CM_OK)
        return error;

    /* create fifo semaphore */
    initializerDesc[coreId].servicePending = 0;
    initializerDesc[coreId].fifoSemHandle = OSAL_CreateSemaphore(DEFAULT_INITIALIZER_FIFO_SIZE);
    if (initializerDesc[coreId].fifoSemHandle == 0) {
        dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle);
        return CM_NO_MORE_MEMORY;
    }

    /* static armTHis initialisation */
    /*
     * In the two next fifo_alloc call (1+n) means that we want to manage the hostThis_or_TOP and one method for each params fifos */
    initializerDesc[coreId].downlinkFifo =
        fifo_alloc(ARM_CORE_ID, coreId,
                INIT_COMPONENT_CMD_SIZE, DEFAULT_INITIALIZER_FIFO_SIZE,
                (1+provide->interface->methodNumber), paramsLocation,  extendedFieldLocation, cm_DSP_GetState(coreId)->domainEE);
    if (initializerDesc[coreId].downlinkFifo == NULL)
    {
        OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle);
        dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle);
        ERROR("CM_NO_MORE_MEMORY: fifo_alloc() failed in cm_COMP_INIT_Init()\n", 0, 0, 0, 0, 0, 0);
        return CM_NO_MORE_MEMORY;
    }

    initializerDesc[coreId].uplinkFifo =
        fifo_alloc(coreId, ARM_CORE_ID,
                INIT_COMPONENT_ACK_SIZE, DEFAULT_INITIALIZER_FIFO_SIZE,
                (1), paramsLocation, extendedFieldLocation, cm_DSP_GetState(coreId)->domainEE);              /* 1 is mandatory to compute internally the indexMask */
                                                                                              /* this statement is acceptable only written by skilled man ;) */
                                                                                              /* We don't used bcDescRef, since we assume that we don't need params size */
    if (initializerDesc[coreId].uplinkFifo == NULL)
    {
        OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle);
        fifo_free(initializerDesc[coreId].downlinkFifo);
        dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle);
        ERROR("CM_NO_MORE_MEMORY: fifo_alloc() failed in cm_COMP_INIT_Init()\n", 0, 0, 0, 0, 0, 0);
        return CM_NO_MORE_MEMORY;
    }

    cm_writeAttribute(ee, "comms/FIFOcmd", initializerDesc[coreId].downlinkFifo->dspAdress);

    cm_writeAttribute(ee, "comms/FIFOack", initializerDesc[coreId].uplinkFifo->dspAdress);

    sharedVarOffset = cm_getAttributeMpcAddress(ee, "comms/TOP");

    /* HOST->DSP ParamsFifo extended fields initialisation */
    fifo_params_setSharedField(
            initializerDesc[coreId].downlinkFifo,
            0,
            (t_shared_field)sharedVarOffset /* TOP DSP Address */
    );
    for(i=0; i<provide->interface->methodNumber; i++)
    {
        fifo_params_setSharedField(
                initializerDesc[coreId].downlinkFifo,
                i + 1,
                provideLoaded->indexesLoaded[itfProvide.collectionIndex][i].methodAddresses);
    }

    /* DSP->HOST ParamsFifo extended fields initialisation */
    fifo_params_setSharedField(
            initializerDesc[coreId].uplinkFifo,
            0,
            (t_shared_field)NMF_INTERNAL_USERTHIS
            );

    return CM_OK;
}


PUBLIC t_cm_error cm_COMP_CallService(
        int serviceIndex,
        t_component_instance *pComp,
        t_uint32 methodAddress) {
    t_cm_error error;
    t_uint16 params[INIT_COMPONENT_CMD_SIZE];
    t_bool isSynchronous = (serviceIndex == NMF_CONSTRUCT_SYNC_INDEX ||
                            serviceIndex == NMF_START_SYNC_INDEX ||
                            serviceIndex == NMF_STOP_SYNC_INDEX ||
                            serviceIndex == NMF_DESTROY_INDEX)?TRUE:FALSE;

    params[INIT_COMPONENT_CMD_HANDLE_INDEX] = (t_uint16)((unsigned int)pComp & 0xFFFF);
    params[INIT_COMPONENT_CMD_HANDLE_INDEX+1] =  (t_uint16)((unsigned int)pComp >> 16);
    params[INIT_COMPONENT_CMD_THIS_INDEX] =  (t_uint16)(pComp->thisAddress & 0xFFFF);
    params[INIT_COMPONENT_CMD_THIS_INDEX+1] =  (t_uint16)(pComp->thisAddress >> 16);
    params[INIT_COMPONENT_CMD_METHOD_INDEX] =  (t_uint16)(methodAddress & 0xFFFF);
    params[INIT_COMPONENT_CMD_METHOD_INDEX+1] =  (t_uint16)(methodAddress >> 16);

    error = cm_COMP_generic(pComp->Template->dspId, params, sizeof(params) / sizeof(t_uint16), serviceIndex);

    if (isSynchronous == TRUE && error == CM_OK) {
        if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) {
            cm_COMP_generatePanic(pComp->Template->dspId);
            error = CM_MPC_NOT_RESPONDING;
        }
    }

    return error;
}

PUBLIC void cm_COMP_Flush(t_nmf_core_id coreId) {

    if(initializerDesc[coreId].servicePending > 0)
    {
        t_uint16 params[INIT_COMPONENT_CMD_SIZE];
        t_uint32 methodAddress = cm_EEM_getExecutiveEngine(coreId)->voidAddr;

        // If service still pending on MMDSP side, send a flush command (today, we reuse Destroy to not create new empty service)
        // When we receive the result, this mean that we have flushed all previous request.

        params[INIT_COMPONENT_CMD_HANDLE_INDEX] = (t_uint16)(0x0 & 0xFFFF);
        params[INIT_COMPONENT_CMD_HANDLE_INDEX+1] =  (t_uint16)(0x0 >> 16);
        params[INIT_COMPONENT_CMD_THIS_INDEX] =  (t_uint16)(0x0 & 0xFFFF);
        params[INIT_COMPONENT_CMD_THIS_INDEX+1] =  (t_uint16)(0x0 >> 16);
        params[INIT_COMPONENT_CMD_METHOD_INDEX] =  (t_uint16)(methodAddress & 0xFFFF);
        params[INIT_COMPONENT_CMD_METHOD_INDEX+1] =  (t_uint16)(methodAddress >> 16);

        if (cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_DESTROY_INDEX) != CM_OK ||
                OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK)
        {
            cm_COMP_generatePanic(coreId);
            ERROR("CM_MPC_NOT_RESPONDING: can't call flush service\n", 0, 0, 0, 0, 0, 0);
        }
    }
}

PUBLIC void cm_COMP_INIT_Close(t_nmf_core_id coreId)
{
    unsigned int i;

    /* wait for semaphore to be sure it would not be touch later on */
    /* in case of timeout we break and try to clean everythink */
    for(i = 0; i < DEFAULT_INITIALIZER_FIFO_SIZE; i++) {
        if (OSAL_SEMAPHORE_WAIT_TIMEOUT(initializerDesc[coreId].fifoSemHandle) != SYNC_OK)
            break;
    }

    /* destroy semaphore */
    OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle);

    /* Unallocate initializerDesc[index].uplinkFifo */
    /* (who is used in this particular case to store dummy (with no data space (only descriptor)) DSP->HOST params fifo */
    fifo_free(initializerDesc[coreId].uplinkFifo);

    /* Unallocate initializerDesc[index].downlinkFifo */
    fifo_free(initializerDesc[coreId].downlinkFifo);

    /* Unallocate initializerDesc[index].dspfifoHandle */
    dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle);
}

PUBLIC void processAsyncAcknowledge(t_nmf_core_id coreId, t_event_params_handle pParam)
{
    cm_AcknowledgeEvent(initializerDesc[coreId].uplinkFifo);

    initializerDesc[coreId].servicePending--;
    OSAL_SemaphorePost(initializerDesc[coreId].fifoSemHandle,1);
}

PUBLIC void processSyncAcknowledge(t_nmf_core_id coreId, t_event_params_handle pParam)
{
    cm_AcknowledgeEvent(initializerDesc[coreId].uplinkFifo);

    initializerDesc[coreId].servicePending--;
    OSAL_SemaphorePost(initializerDesc[coreId].fifoSemHandle,1);
    OSAL_SemaphorePost(semHandle,1);
}

PUBLIC t_cm_error cm_COMP_UpdateStack(
    t_nmf_core_id coreId,
    t_uint32 stackSize
)
{
    t_uint16 params[2];

    // Marshall parameter
    params[0] =  (t_uint16)((unsigned int)stackSize & 0xFFFF);
    params[1] =  (t_uint16)((unsigned int)stackSize >> 16);

    return cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_UPDATE_STACK);
}

PUBLIC t_cm_error cm_COMP_ULPForceWakeup(
    t_nmf_core_id coreId
)
{
    t_cm_error error;

    error = cm_COMP_generic(coreId, NULL, 0, NMF_ULP_FORCEWAKEUP);

    if (error == CM_OK) {
        if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) {
            cm_COMP_generatePanic(coreId);
            error = CM_MPC_NOT_RESPONDING;
        }
    }

    return error;
}

PUBLIC t_cm_error cm_COMP_ULPAllowSleep(
    t_nmf_core_id coreId
)
{
    return cm_COMP_generic(coreId, NULL, 0, NMF_ULP_ALLOWSLEEP);
}

PUBLIC t_cm_error cm_COMP_InstructionCacheLock(
    t_nmf_core_id coreId,
    t_uint32 mmdspAddr,
    t_uint32 mmdspSize
)
{
    t_uint16 params[4];
    t_uint32 startAddr = cm_DSP_GetState(coreId)->locked_offset;
    int way;

    for(way = 1; startAddr < mmdspAddr + mmdspSize; startAddr += MMDSP_CODE_CACHE_WAY_SIZE, way++)
    {
        if(mmdspAddr < startAddr + MMDSP_CODE_CACHE_WAY_SIZE)
        {
            t_cm_error error;

            // Marshall parameter
            params[0] =  (t_uint16)((unsigned int)startAddr & 0xFFFF);
            params[1] =  (t_uint16)((unsigned int)startAddr >> 16);
            params[2] =  (t_uint16)((unsigned int)way & 0xFFFF);
            params[3] =  (t_uint16)((unsigned int)way >> 16);

             if((error = cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_LOCK_CACHE)) != CM_OK)
                 return error;
        }
    }

    return CM_OK;
}

PUBLIC t_cm_error cm_COMP_InstructionCacheUnlock(
    t_nmf_core_id coreId,
    t_uint32 mmdspAddr,
    t_uint32 mmdspSize
)
{
    t_uint16 params[2];
    t_uint32 startAddr = cm_DSP_GetState(coreId)->locked_offset;
    int way;

    for(way = 1; startAddr < mmdspAddr + mmdspSize; startAddr += MMDSP_CODE_CACHE_WAY_SIZE, way++)
    {
        if(mmdspAddr < startAddr + MMDSP_CODE_CACHE_WAY_SIZE)
        {
            t_cm_error error;

            // Marshall parameter
            params[0] =  (t_uint16)((unsigned int)way & 0xFFFF);
            params[1] =  (t_uint16)((unsigned int)way >> 16);

             if((error = cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_UNLOCK_CACHE)) != CM_OK)
                 return error;
        }
    }

    return CM_OK;
}

/* private method */
PRIVATE t_cm_error cm_COMP_generic(
        t_nmf_core_id coreId,
    t_event_params_handle paramArray,
    t_uint32 paramNumber,
    t_uint32 serviceIndex
)
{
    t_event_params_handle _xyuv_data;
    t_cm_error error;
    t_uint32 i;

    // wait for an event in fifo
    if (OSAL_SEMAPHORE_WAIT_TIMEOUT(initializerDesc[coreId].fifoSemHandle) != SYNC_OK) {
        cm_COMP_generatePanic(coreId);
        return CM_MPC_NOT_RESPONDING;
    }


    // AllocEvent
    if((_xyuv_data = cm_AllocEvent(initializerDesc[coreId].downlinkFifo)) == NULL)
    {
        ERROR("CM_INTERNAL_FIFO_OVERFLOW: service FIFO full\n", 0, 0, 0, 0, 0, 0);
        error = CM_INTERNAL_FIFO_OVERFLOW;
        goto unlock;
    }

    // Copy param
    for(i=0;i<paramNumber;i++)
        _xyuv_data[i] = paramArray[i];

    OSAL_LOCK_COM();

    // Send Command
    error = cm_PushEventTrace(initializerDesc[coreId].downlinkFifo, _xyuv_data, serviceIndex,0);
    if(error == CM_OK)
        initializerDesc[coreId].servicePending++;

unlock:
    OSAL_UNLOCK_COM();

    return error;
}

PRIVATE void cm_COMP_generatePanic(t_nmf_core_id coreId)
{
    const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId);

    if (pDspDesc->state != MPC_STATE_PANIC) {
        cm_DSP_SetStatePanic(coreId);
        OSAL_GeneratePanic(coreId, 0);
    }
}