summaryrefslogtreecommitdiff
path: root/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/nmf-cm/cm/engine/component/src/initializer.c')
-rw-r--r--drivers/staging/nmf-cm/cm/engine/component/src/initializer.c383
1 files changed, 383 insertions, 0 deletions
diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c
new file mode 100644
index 00000000000..7f99b710401
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c
@@ -0,0 +1,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);
+ }
+}