/* * ======== DSP_Deinit ======== * Frees the resources allocated for bridge. */ bool DSP_Deinit(u32 deviceContext) { bool retVal = true; u32 deviceNode; struct MGR_OBJECT *mgrObject = NULL; GT_0trace(curTrace, GT_ENTER, "Entering DSP_Deinit \r\n"); while ((deviceNode = DRV_GetFirstDevExtension()) != 0) { (void)DEV_RemoveDevice((struct CFG_DEVNODE *)deviceNode); (void)DRV_ReleaseResources((u32)deviceNode, (struct DRV_OBJECT *)deviceContext); } (void) DRV_Destroy((struct DRV_OBJECT *) deviceContext); /* Get the Manager Object from Registry * MGR Destroy will unload the DCD dll */ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&mgrObject, REG_MGR_OBJECT))) (void)MGR_Destroy(mgrObject); WCD_Exit(); return retVal; }
bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *pDevContext, bool *pfSchedDPC, u16 *pwIntrVal) { struct CFG_HOSTRES resources; u32 numMbxMsg; u32 mbxValue; DBG_Trace(DBG_ENTER, "CHNLSM_ISR(0x%x)\n", pDevContext); CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources); HW_MBOX_NumMsgGet(resources.dwMboxBase, MBOX_DSP2ARM, &numMbxMsg); if (numMbxMsg > 0) { HW_MBOX_MsgRead(resources.dwMboxBase, MBOX_DSP2ARM, &mbxValue); HW_MBOX_EventAck(resources.dwMboxBase, MBOX_DSP2ARM, HW_MBOX_U0_ARM, HW_MBOX_INT_NEW_MSG); DBG_Trace(DBG_LEVEL3, "Read %x from Mailbox\n", mbxValue); *pwIntrVal = (u16) mbxValue; } /* Set *pfSchedDPC to true; */ *pfSchedDPC = true; return true; }
DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT *pDevContext) { struct CFG_HOSTRES resources; DBG_Trace(DBG_ENTER, "CHNLSM_DisableInterrupt(0x%x)\n", pDevContext); CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources); HW_MBOX_EventDisable(resources.dwMboxBase, MBOX_DSP2ARM, MBOX_ARM, HW_MBOX_INT_NEW_MSG); return DSP_SOK; }
DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT *pDevContext) { DSP_STATUS status = DSP_SOK; u32 numMbxMsg; u32 mbxValue; struct CFG_HOSTRES resources; u32 devType; struct IO_MGR *hIOMgr; DBG_Trace(DBG_ENTER, "CHNLSM_EnableInterrupt(0x%x)\n", pDevContext); /* Read the messages in the mailbox until the message queue is empty */ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources); DEV_GetDevType(pDevContext->hDevObject, &devType); status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr); if (devType == DSP_UNIT) { HW_MBOX_NumMsgGet(resources.dwMboxBase, MBOX_DSP2ARM, &numMbxMsg); while (numMbxMsg != 0) { HW_MBOX_MsgRead(resources.dwMboxBase, MBOX_DSP2ARM, &mbxValue); numMbxMsg--; } /* clear the DSP mailbox as well...*/ HW_MBOX_NumMsgGet(resources.dwMboxBase, MBOX_ARM2DSP, &numMbxMsg); while (numMbxMsg != 0) { HW_MBOX_MsgRead(resources.dwMboxBase, MBOX_ARM2DSP, &mbxValue); numMbxMsg--; udelay(10); HW_MBOX_EventAck(resources.dwMboxBase, MBOX_ARM2DSP, HW_MBOX_U1_DSP1, HW_MBOX_INT_NEW_MSG); } /* Enable the new message events on this IRQ line */ HW_MBOX_EventEnable(resources.dwMboxBase, MBOX_DSP2ARM, MBOX_ARM, HW_MBOX_INT_NEW_MSG); } return status; }
/* * ======== WriteDspData ======== * purpose: * Copies buffers to the DSP internal/external memory. */ DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *hDevContext, IN u8 *pbHostBuf, u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType) { u32 offset; u32 dwBaseAddr = hDevContext->dwDspBaseAddr; struct CFG_HOSTRES resources; DSP_STATUS status; u32 base1, base2, base3; base1 = OMAP_DSP_MEM1_SIZE; base2 = OMAP_DSP_MEM2_BASE - OMAP_DSP_MEM1_BASE; base3 = OMAP_DSP_MEM3_BASE - OMAP_DSP_MEM1_BASE; status = CFG_GetHostResources( (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources); if (DSP_FAILED(status)) return status; offset = dwDSPAddr - hDevContext->dwDSPStartAdd; if (offset < base1) { dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[2], resources.dwMemLength[2]); } else if (offset > base1 && offset < base2+OMAP_DSP_MEM2_SIZE) { dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[3], resources.dwMemLength[3]); offset = offset - base2; } else if (offset >= base2+OMAP_DSP_MEM2_SIZE && offset < base3 + OMAP_DSP_MEM3_SIZE) { dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[4], resources.dwMemLength[4]); offset = offset - base3; } else{ return DSP_EFAIL; } if (ulNumBytes) memcpy((u8 *) (dwBaseAddr+offset), pbHostBuf, ulNumBytes); else *((u32 *) pbHostBuf) = dwBaseAddr+offset; return status; }
DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT *pDevContext, u16 wMbVal) { struct CFG_HOSTRES resources; DSP_STATUS status = DSP_SOK; unsigned long timeout; u32 temp; status = CFG_GetHostResources((struct CFG_DEVNODE *) DRV_GetFirstDevExtension(), &resources); if (DSP_FAILED(status)) return DSP_EFAIL; if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION || pDevContext->dwBrdState == BRD_HIBERNATION) { #ifdef CONFIG_BRIDGE_DVFS struct dspbridge_platform_data *pdata = omap_dspbridge_dev->dev.platform_data; /* * When Smartreflex is ON, DSP requires at least OPP level 3 * to operate reliably. So boost lower OPP levels to OPP3. */ if (pdata->dsp_set_min_opp) (*pdata->dsp_set_min_opp)(min_active_opp); #endif /* Restart the peripheral clocks */ DSP_PeripheralClocks_Enable(pDevContext, NULL); /* * 2:0 AUTO_IVA2_DPLL - Enabling IVA2 DPLL auto control * in CM_AUTOIDLE_PLL_IVA2 register */ *(REG_UWORD32 *)(resources.dwCmBase + 0x34) = 0x1; /* * 7:4 IVA2_DPLL_FREQSEL - IVA2 internal frq set to * 0.75 MHz - 1.0 MHz * 2:0 EN_IVA2_DPLL - Enable IVA2 DPLL in lock mode */ temp = *(REG_UWORD32 *)(resources.dwCmBase + 0x4); temp = (temp & 0xFFFFFF08) | 0x37; *(REG_UWORD32 *)(resources.dwCmBase + 0x4) = temp; /* * This delay is needed to avoid mailbox timed out * issue experienced while SmartReflex is ON. * TODO: Instead of 1 ms calculate proper value. */ mdelay(1); /* Restore mailbox settings */ HW_MBOX_restoreSettings(resources.dwMboxBase); /* Access MMU SYS CONFIG register to generate a short wakeup */ temp = *(REG_UWORD32 *)(resources.dwDmmuBase + 0x10); pDevContext->dwBrdState = BRD_RUNNING; } timeout = jiffies + msecs_to_jiffies(1); while (fifo_full((void __iomem *) resources.dwMboxBase, 0)) { if (time_after(jiffies, timeout)) { pr_err("dspbridge: timed out waiting for mailbox\n"); return WMD_E_TIMEOUT; } } DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n", wMbVal); HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP, wMbVal); return DSP_SOK; }
DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT *pDevContext, u16 wMbVal) { #ifndef CONFIG_DISABLE_BRIDGE_PM #ifndef CONFIG_DISABLE_BRIDGE_DVFS u32 opplevel; #endif #endif struct CFG_HOSTRES resources; unsigned long timeout; u32 temp; DSP_STATUS status = DSP_SOK; /* We are waiting indefinitely here. This needs to be fixed in the * second phase */ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources); if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION || pDevContext->dwBrdState == BRD_HIBERNATION) { #ifndef CONFIG_DISABLE_BRIDGE_PM #ifndef CONFIG_DISABLE_BRIDGE_DVFS #ifndef CONFIG_OMAP3_PM opplevel = omap_pm_dsp_get_opp(); /* If OPP is at minimum level, increase it before waking up * the DSP */ if (opplevel == 1) { omap_pm_dsp_set_min_opp(opplevel+1); DBG_Trace(DBG_LEVEL7, "CHNLSM_InterruptDSP:Setting " "the vdd1 constraint level to %d before " "waking DSP \n", (opplevel + 1)); } #else opplevel = constraint_get_level(dsp_constraint_handle); /* If OPP is at minimum level, increase it before waking up * the DSP */ if (opplevel == 1) { if (constraint_set(dsp_constraint_handle, (opplevel+1)) != 0) { DBG_Trace(DBG_LEVEL7, "CHNLSM_InterruptDSP: " "Constraint set failed\n"); return DSP_EFAIL; } DBG_Trace(DBG_LEVEL7, "CHNLSM_InterruptDSP:Setting " "the vdd1 constraint level to %d before " "waking DSP \n", (opplevel + 1)); } #endif #endif #endif /* Restart the IVA clock that was disabled while * the DSP initiated Hibernation. */ if ((pDevContext->dwBrdState == BRD_DSP_HIBERNATION) || (pDevContext->dwBrdState == BRD_HIBERNATION)) { status = CLK_Enable(SERVICESCLK_iva2_ck); if (DSP_FAILED(status)) return status; } /* Read MMU register to invoke short wakeup of DSP */ temp = (u32) *((REG_UWORD32 *) ((u32) (resources.dwDmmuBase) + 0x10)); /* Restore mailbox settings */ HW_MBOX_restoreSettings(resources.dwMboxBase); DBG_Trace(DBG_LEVEL6, "MailBoxSettings: SYSCONFIG = 0x%x\n", mboxsetting.sysconfig); DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE0 = 0x%x\n", mboxsetting.irqEnable0); DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE1 = 0x%x\n", mboxsetting.irqEnable1); /* Restart the peripheral clocks that were disabled only * in DSP initiated Hibernation case.*/ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION) DSP_PeripheralClocks_Enable(pDevContext, NULL); pDevContext->dwBrdState = BRD_RUNNING; } timeout = jiffies + msecs_to_jiffies(35); while (HW_MBOX_IsFull(resources.dwMboxBase, MBOX_ARM2DSP)) { if (time_after(jiffies, timeout)) { printk(KERN_ERR "dspbridge: " "timed out waiting for mailbox\n"); return WMD_E_TIMEOUT; } } DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n", wMbVal); HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP, wMbVal); return DSP_SOK; }
/* * ======== WriteExtDspData ======== * purpose: * Copies buffers to the external memory. * */ DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext, IN u8 *pbHostBuf, u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType, bool bDynamicLoad) { u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr; u32 dwOffset = 0; u8 bTempByte1, bTempByte2; u8 remainByte[4]; s32 i; DSP_STATUS retVal = DSP_SOK; u32 dwExtProgVirtMem; u32 ulTLBBaseVirt = 0; u32 ulShmOffsetVirt = 0; struct CFG_HOSTRES hostRes; bool bTraceLoad = false; bTempByte1 = 0x0; bTempByte2 = 0x0; if (bSymbolsReloaded) { /* Check if it is a load to Trace section */ retVal = DEV_GetSymbol(pDevContext->hDevObject, DSP_TRACESEC_BEG, &ulTraceSecBeg); if (DSP_SUCCEEDED(retVal)) retVal = DEV_GetSymbol(pDevContext->hDevObject, DSP_TRACESEC_END, &ulTraceSecEnd); } if (DSP_SUCCEEDED(retVal)) { if ((dwDSPAddr <= ulTraceSecEnd) && (dwDSPAddr >= ulTraceSecBeg)) bTraceLoad = true; } /* If dynamic, force remap/unmap */ if ((bDynamicLoad || bTraceLoad) && dwBaseAddr) { dwBaseAddr = 0; MEM_UnmapLinearAddress((void *)pDevContext->dwDspExtBaseAddr); pDevContext->dwDspExtBaseAddr = 0x0; } if (!dwBaseAddr) { if (bSymbolsReloaded) /* Get SHM_BEG EXT_BEG and EXT_END. */ retVal = DEV_GetSymbol(pDevContext->hDevObject, SHMBASENAME, &ulShmBaseVirt); DBC_Assert(ulShmBaseVirt != 0); if (bDynamicLoad) { if (DSP_SUCCEEDED(retVal)) { if (bSymbolsReloaded) retVal = DEV_GetSymbol(pDevContext-> hDevObject, DYNEXTBASE, &ulExtBase); } DBC_Assert(ulExtBase != 0); if (DSP_SUCCEEDED(retVal)) { /* DR OMAPS00013235 : DLModules array may be * in EXTMEM. It is expected that DYNEXTMEM and * EXTMEM are contiguous, so checking for the * upper bound at EXTEND should be Ok. */ if (bSymbolsReloaded) retVal = DEV_GetSymbol(pDevContext-> hDevObject, EXTEND, &ulExtEnd); } } else { if (bSymbolsReloaded) { if (DSP_SUCCEEDED(retVal)) retVal = DEV_GetSymbol(pDevContext-> hDevObject, EXTBASE, &ulExtBase); DBC_Assert(ulExtBase != 0); if (DSP_SUCCEEDED(retVal)) retVal = DEV_GetSymbol(pDevContext-> hDevObject, EXTEND, &ulExtEnd); } } /* Trace buffer it right after the SHM SEG0, so set the * base address to SHMBASE */ if (bTraceLoad) ulExtBase = ulShmBaseVirt; DBC_Assert(ulExtEnd != 0); DBC_Assert(ulExtEnd > ulExtBase); if (ulExtEnd < ulExtBase) retVal = DSP_EFAIL; if (DSP_SUCCEEDED(retVal)) { ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa * DSPWORDSIZE; DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt); if (bSymbolsReloaded) { if (DSP_SUCCEEDED(retVal)) { retVal = DEV_GetSymbol(pDevContext-> hDevObject, DSP_TRACESEC_END, &ulShm0End); } if (DSP_SUCCEEDED(retVal)) { retVal = DEV_GetSymbol(pDevContext-> hDevObject, DYNEXTBASE, &ulDynExtBase); } } ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt; if (bTraceLoad) { dwExtProgVirtMem = pDevContext->aTLBEntry[0]. ulGppVa; } else { CFG_GetHostResources( (struct CFG_DEVNODE *) DRV_GetFirstDevExtension(), &hostRes); dwExtProgVirtMem = hostRes.dwMemBase[1]; dwExtProgVirtMem += (ulExtBase - ulDynExtBase); } pDevContext->dwDspExtBaseAddr = (u32)MEM_LinearAddress((void *)dwExtProgVirtMem, ulExtEnd - ulExtBase); dwBaseAddr += pDevContext->dwDspExtBaseAddr; /* This dwDspExtBaseAddr will get cleared only when * the board is stopped. */ if (!pDevContext->dwDspExtBaseAddr) retVal = DSP_EFAIL; } } if (!dwBaseAddr || !ulExtBase || !ulExtEnd) retVal = DSP_EFAIL; if (DSP_SUCCEEDED(retVal)) { for (i = 0; i < 4; i++) remainByte[i] = 0x0; dwOffset = dwDSPAddr - ulExtBase; /* Also make sure the dwDSPAddr is < ulExtEnd */ if (dwDSPAddr > ulExtEnd || dwOffset > dwDSPAddr) retVal = DSP_EFAIL; } if (DSP_SUCCEEDED(retVal)) { if (ulNumBytes) memcpy((u8 *) dwBaseAddr + dwOffset, pbHostBuf, ulNumBytes); else *((u32 *) pbHostBuf) = dwBaseAddr+dwOffset; } /* Unmap here to force remap for other Ext loads */ if ((bDynamicLoad || bTraceLoad) && pDevContext->dwDspExtBaseAddr) { MEM_UnmapLinearAddress((void *) pDevContext->dwDspExtBaseAddr); pDevContext->dwDspExtBaseAddr = 0x0; } bSymbolsReloaded = false; return retVal; }
DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT *pDevContext, u16 wMbVal) { #ifdef CONFIG_BRIDGE_DVFS struct dspbridge_platform_data *pdata = omap_dspbridge_dev->dev.platform_data; u32 opplevel = 0; #endif struct CFG_HOSTRES resources; DSP_STATUS status = DSP_SOK; unsigned long timeout; u32 temp; status = CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources); if (DSP_FAILED(status)) return DSP_EFAIL; #ifdef CONFIG_BRIDGE_DVFS if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION || pDevContext->dwBrdState == BRD_HIBERNATION) { if (pdata->dsp_get_opp) opplevel = (*pdata->dsp_get_opp)(); if (opplevel == 1) { if (pdata->dsp_set_min_opp) (*pdata->dsp_set_min_opp)(opplevel+1); } } #endif if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION || pDevContext->dwBrdState == BRD_HIBERNATION) { /* Restart the IVA clock that was disabled while * the DSP initiated Hibernation. */ status = CLK_Enable(SERVICESCLK_iva2_ck); if (DSP_FAILED(status)) return status; /* Restore mailbox settings */ /* Restart the peripheral clocks that were disabled only * in DSP initiated Hibernation case.*/ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION) { DSP_PeripheralClocks_Enable(pDevContext, NULL); /* Enabling Dpll in lock mode*/ temp = (u32) *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)); temp = (temp & 0xFFFFFFFE) | 0x1; *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) = (u32) temp; temp = (u32) *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)); temp = (temp & 0xFFFFFC8) | 0x37; *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) = (u32) temp; } HW_MBOX_restoreSettings(resources.dwMboxBase); /* Access MMU SYS CONFIG register to generate a short wakeup */ temp = (u32) *((REG_UWORD32 *) ((u32) (resources.dwDmmuBase) + 0x10)); pDevContext->dwBrdState = BRD_RUNNING; } timeout = jiffies + msecs_to_jiffies(1); while (fifo_full((void __iomem *) resources.dwMboxBase, 0)) { if (time_after(jiffies, timeout)) { printk(KERN_ERR "dspbridge: timed out waiting for mailbox\n"); return WMD_E_TIMEOUT; } } DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n", wMbVal); HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP, wMbVal); return DSP_SOK; }
/* * ======== DSP_Init ======== * Allocates bridge resources. Loads a base image onto DSP, if specified. */ u32 DSP_Init(OUT u32 *initStatus) { char devNode[MAXREGPATHLENGTH] = "TIOMAP1510"; DSP_STATUS status = DSP_EFAIL; struct DRV_OBJECT *drvObject = NULL; u32 index = 0; u32 deviceNode; u32 deviceNodeString; GT_create(&curTrace, "DD"); GT_0trace(curTrace, GT_ENTER, "Entering DSP_Init \r\n"); if (DSP_FAILED(WCD_Init())) { GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed \n"); goto func_cont; } /* End WCD_Exit */ if (DSP_FAILED(DRV_Create(&drvObject))) { GT_0trace(curTrace, GT_7CLASS, "DSP_Init:DRV_Create Failed \n"); WCD_Exit(); goto func_cont; } /* End DRV_Create */ GT_0trace(curTrace, GT_5CLASS, "DSP_Init:DRV Created \r\n"); /* Request Resources */ if (DSP_SUCCEEDED(DRV_RequestResources((u32)&devNode, &deviceNodeString))) { /* Attempt to Start the Device */ if (DSP_SUCCEEDED(DEV_StartDevice( (struct CFG_DEVNODE *)deviceNodeString))) { /* Retreive the DevObject from the Registry */ GT_2trace(curTrace, GT_1CLASS, "DSP_Init Succeeded for Device1:" "%d: value: %x\n", index, deviceNodeString); status = DSP_SOK; } else { GT_0trace(curTrace, GT_7CLASS, "DSP_Init:DEV_StartDevice Failed\n"); (void)DRV_ReleaseResources ((u32) deviceNodeString, drvObject); status = DSP_EFAIL; } } else { GT_0trace(curTrace, GT_7CLASS, "DSP_Init:DRV_RequestResources Failed \r\n"); status = DSP_EFAIL; } /* DRV_RequestResources */ index++; /* Unwind whatever was loaded */ if (DSP_FAILED(status)) { /* irrespective of the status of DEV_RemoveDevice we conitinue * unloading. Get the Driver Object iterate through and remove. * Reset the status to E_FAIL to avoid going through * WCD_InitComplete2. */ status = DSP_EFAIL; for (deviceNode = DRV_GetFirstDevExtension(); deviceNode != 0; deviceNode = DRV_GetNextDevExtension(deviceNode)) { (void)DEV_RemoveDevice ((struct CFG_DEVNODE *)deviceNode); (void)DRV_ReleaseResources((u32)deviceNode, drvObject); } /* Remove the Driver Object */ (void)DRV_Destroy(drvObject); drvObject = NULL; WCD_Exit(); GT_0trace(curTrace, GT_7CLASS, "DSP_Init:Logical device Failed to Load\n"); } /* Unwinding the loaded drivers */ func_cont: /* Attempt to Start the Board */ if (DSP_SUCCEEDED(status)) { /* BRD_AutoStart could fail if the dsp execuetable is not the * correct one. We should not propagate that error * into the device loader. */ (void)WCD_InitComplete2(); GT_0trace(curTrace, GT_1CLASS, "DSP_Init Succeeded\n"); } else { GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed\n"); } /* End WCD_InitComplete2 */ DBC_Ensure((DSP_SUCCEEDED(status) && drvObject != NULL) || (DSP_FAILED(status) && drvObject == NULL)); *initStatus = status; /* Return the Driver Object */ return (u32)drvObject; }