/* Copyright (c) 2017, Texas Instruments Incorporated - http://www.ti.com/ All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // // // McASP implementations for SAP_PORT (d10 specific) // // // #include #include #include #include "sap_mcasp.h" #define ENABLE_TRACE #ifdef ENABLE_TRACE #include //#define TRACE_TERSE0(a) Log_info0(a) #endif // Allow a developer to selectively enable tracing. // For release, you might set the mask to 0, but I'd always leave it at 1. #define CURRENT_TRACE_MASK 0x01 // terse only #define TRACE_MASK_TERSE 0x01 // only flag errors and show init #define TRACE_MASK_GENERAL 0x02 // half dozen lines per frame #define TRACE_MASK_VERBOSE 0x04 // trace full operation #define TRACE_MASK_DATA 0x08 // Show data #define TRACE_MASK_TIME 0x10 // Timing related traces #if (CURRENT_TRACE_MASK & TRACE_MASK_TERSE) //#define TRACE_TERSE(a) LOG_printf a #define TRACE_TERSE0(a) Log_info0(a) #define TRACE_TERSE1(a,b) Log_info1(a,b) #define TRACE_TERSE2(a,b,c) Log_info2(a,b,c) #define TRACE_TERSE3(a,b,c,d) Log_info3(a,b,c,d) #define TRACE_TERSE4(a,b,c,d,e) Log_info4(a,b,c,d,e) #else //#define TRACE_TERSE(a) #define TRACE_TERSE0(a) #define TRACE_TERSE1(a,b) #define TRACE_TERSE2(a,b,c) #define TRACE_TERSE3(a,b,c,d) #define TRACE_TERSE4(a,b,c,d,e) #endif #if (CURRENT_TRACE_MASK & TRACE_MASK_GENERAL) //#define TRACE_GEN(a) LOG_printf a #define TRACE_GEN0(a) Log_info0(a) #define TRACE_GEN1(a,b) Log_info1(a,b) #define TRACE_GEN2(a,b,c) Log_info2(a,b,c) #define TRACE_GEN3(a,b,c,d) Log_info3(a,b,c,d) #define TRACE_GEN4(a,b,c,d,e) Log_info4(a,b,c,d,e) #else //#define TRACE_GEN(a) #define TRACE_GEN0(a) #define TRACE_GEN1(a,b) #define TRACE_GEN2(a,b,c) #define TRACE_GEN3(a,b,c,d) #define TRACE_GEN4(a,b,c,d,e) #endif #if (CURRENT_TRACE_MASK & TRACE_MASK_DATA) #define TRACE_DATA(a) LOG_printf a #else #define TRACE_DATA(a) #endif #if (CURRENT_TRACE_MASK & TRACE_MASK_VERBOSE) #define TRACE_VERBOSE(a) LOG_printf a #define TRACE_VERBOSE0(a) Log_info0(a) #define TRACE_VERBOSE1(a,b) Log_info1(a,b) #define TRACE_VERBOSE2(a,b,c) Log_info2(a,b,c) #define TRACE_VERBOSE3(a,b,c,d) Log_info3(a,b,c,d) #define TRACE_VERBOSE4(a,b,c,d,e) Log_info4(a,b,c,d,e) #else #define TRACE_VERBOSE(a) #define TRACE_VERBOSE0(a) #define TRACE_VERBOSE1(a,b) #define TRACE_VERBOSE2(a,b,c) #define TRACE_VERBOSE3(a,b,c,d) #define TRACE_VERBOSE4(a,b,c,d,e) #endif // ............................................................................. // Resource Access Control // // The resources which must be controlled here are the McASP registers. There // is layer context (sapMcaspDrv) but this essentially only holds the // addresses of the resources. Further this is intitialized, i.e. written to // only once, before the task scheduler begins and hence need not be controlled. // Therefore we focus only on the McASP registers themselves. // // There are two sources of switching which must be considered: // (A) Interrupts // (B) Tasks // // While SAP does not access McASP registers at ISR levels, other users may // access some of the registers for other functionality, e.g. GPIO, at any // priority level. Therefore all accesses to these registers must be protected // using HWI disable/enable blocks. Registers in this category are: // PDIR/PFUNC/PDOUT/PDIN // // Within (B) there are two types of accesses which we must consider: // (i) Modifications to non-direction specific registers not in (A) // (ii) Modifications to direction specific registers // // Within this layer there are no accesses to registers of type (i). If there // were then there are at least two choices for appropriate access control. // . HWI disable/enable macros // This is effective but inefficient since it blocks all // processing regardless of its resource usage. // // . Raise the TSK priority > max priority of all tasks using SAP. // This assumes that no tasks using SAP run at TSK_MAXPRI. // // For (ii) there is no need to perform resource access control since these // registers are *owned* by the device and hence the calling thread and not // accessed by any other context. Registers in this category are: // AFSyCTL, ACLKyCTL, AHCLKyCTL, SRCTLz, yTDM, yGBLCTL, yINTCTL, // ySTAT, ySLOTCNT, yCLKCHK, yBUFz // where y is X or R and z is between 1 and 15. // // Of concern maybe the ASYNC bit in the ACLKXCTL since this is arguably a // receive option in a transmit register. However, to date, this bit is only // modified when the transmitter is configured not when the input is // configured; which would be problematic. // // Also we make no assumptions about the calling priority; e.g. we do not // depend on the SAP layer to disable switching before making a call to this // (SAP_MCASP) layer. // ............................................................................. // max time to wait in SAP_MCASP_enableX functions (in mS) #define REGISTER_SET_TIMEOUT 2. // ............................................................................. // Function table Int SAP_MCASP_alloc (DEV2_Handle device); Int SAP_MCASP_close (DEV2_Handle device); Int SAP_MCASP_enable (DEV2_Handle device); Void SAP_MCASP_init (Void); Int SAP_MCASP_open (DEV2_Handle device); Int SAP_MCASP_reset (DEV2_Handle device); Int SAP_MCASP_watchDog (DEV2_Handle device); Int SAP_MCASP_waitSet (MCASP_Handle hMcasp, Uint32 wrReg, Uint32 rdReg, Uint32 mask, Uint32 timeout); //Int SAP_MCASP_updateDITRam(DEV_Handle device ); SAP_MCASP_Fxns SAP_MCASP_FXNS = { SAP_MCASP_alloc, SAP_MCASP_close, SAP_MCASP_enable, SAP_MCASP_init, SAP_MCASP_open, SAP_MCASP_reset, SAP_MCASP_watchDog, SAP_MCASP_waitSet }; SAP_MCASP_DriverObject sapMcaspDrv; // ----------------------------------------------------------------------------- Void SAP_MCASP_init (Void) { volatile Uint32 *base; volatile Uint32 *fifoBase; volatile Uint32 *pSers; int i, j; TRACE_TERSE0("SAP_MCASP_init"); // open McASP ports via CSL. This CSL call, MCASP_open, does not require // CSL_init which is important since this function is called before main // and hence before any chance to call CSL_init. for (i=0; i < _MCASP_PORT_CNT; i++) { sapMcaspDrv.hPort[i] = MCASP_open (i, MCASP_OPEN); base = (volatile Uint32 *) sapMcaspDrv.hPort[i]->baseAddr; fifoBase = base + _MCASP_FIFO_OFFSET; //if (fifoBase[_MCASP_AFIFOREV_OFFSET] == 0x44311100) sapMcaspDrv.fifoPresent[i] = 1; //else // sapMcaspDrv.fifoPresent[i] = 0; // zero out all serializers pSers = &base[_MCASP_SRCTL0_OFFSET]; for (j=0; j<_MCASP_CHANNEL_CNT; j++) { Uint32 save = *pSers; *pSers = 0; pSers++; } base[_MCASP_PDIR_OFFSET] = 0; // all input by default } } // SAP_MCASP_init // ----------------------------------------------------------------------------- // TODO: // Add control for: // 1. DLB // 2. DIT // 3. AMUTE? Int SAP_MCASP_alloc (DEV2_Handle device) { SAP_DeviceExtension *pDevExt = (SAP_DeviceExtension *)(device->object); const SAP_Params *pParams = pDevExt->pParams; MCASP_Handle hPort = sapMcaspDrv.hPort[pParams->sio.moduleNum]; volatile Uint32 *base = (volatile Uint32 *) hPort->baseAddr; volatile Uint32 *pSers =&base[_MCASP_SRCTL0_OFFSET]; Int i, oldMask, tdmMask; //TRACE_TERSE1(("SAP_MCASP_alloc(0x%x)", device)); // validate mcasp number if (pParams->sio.moduleNum >= _MCASP_PORT_CNT) return DEV2_EINVAL; // Could/should validate pin mask here. // Check: McAsp0 has 16 pins. McAsp1 has 10. McAsp2 has 6. // !!!! This code is DA10x specific !!!!!!!!!! switch (pParams->sio.moduleNum) { case 0: if (pParams->sap.pinMask & 0x00FF0000) { //TRACE_TERSE1(("ERROR. McAsp0 has only 16 pins. PinMask requests 0x%x.\n", pParams->sap.pinMask)); System_printf("ERROR. McAsp0 has only 16 pins. PinMask requests 0x%x.\n", pParams->sap.pinMask); System_abort("ABORT. McAsp0 has only 16 pins."); } break; case 1: if (pParams->sap.pinMask & 0x00FFFC00) { //TRACE_TERSE1(("ERROR. McAsp1 has only 10 pins. PinMask requests 0x%x.\n", pParams->sap.pinMask)); System_printf("ERROR. McAsp1 has only 10 pins. PinMask requests 0x%x.\n", pParams->sap.pinMask); System_abort("ABORT. McAsp1 has only 10 pins."); } break; case 2: if (pParams->sap.pinMask & 0x00FFFFC0) { //TRACE_TERSE1(("ERROR. McAsp2 has only 6 pins. PinMask requests 0x%x.\n", pParams->sap.pinMask)); System_printf("ERROR. McAsp2 has only 6 pins. PinMask requests 0x%x.\n", pParams->sap.pinMask); System_abort("ABORT. McAsp2 has only 6 pins."); } break; } // lock context -- see class (A) above oldMask = Hwi_disable (); // use pinMask to configure MCASP vs. GPIO functionality base[_MCASP_PFUNC_OFFSET] &= ~(pParams->sap.pinMask & 0xFE00FFFF); // infer serializer config from pinMask and mode //TRACE_TERSE2(("SAP_MCASP_alloc(): serializer: pinMask : 0x%x PDIR on entry: 0x%x.", pParams->sap.pinMask, base[_MCASP_PDIR_OFFSET])); pDevExt->numSers = 0; for (i=0; i < _MCASP_CHANNEL_CNT; i++) { if (pParams->sap.pinMask & (1 << i)) { pDevExt->numSers += 1; if (device->mode == DEV2_INPUT) { *pSers = MCASP_SRCTL_SRMOD_RCV; if (*pSers != MCASP_SRCTL_SRMOD_RCV) { //TRACE_TERSE2(( "SAP_MCASP_alloc(): serializer input: write to pSers failed: 0x%x. *pSers: 0x%x", pSers, *pSers)); } else { //TRACE_TERSE2(( "SAP_MCASP_alloc(): serializer input: pSers: 0x%x. *pSers: 0x%x", pSers, *pSers)); } base[_MCASP_PDIR_OFFSET] &= ~(1 << i); //TRACE_TERSE1(("SAP_MCASP_alloc(): serializer input: clear pin %d.", i)); } else { *pSers = MCASP_SRCTL_SRMOD_XMT; if (*pSers != MCASP_SRCTL_SRMOD_XMT) { //TRACE_TERSE2(( "SAP_MCASP_alloc(): serializer output: write to pSers failed: 0x%x. *pSers: 0x%x", pSers, *pSers)); } else { //TRACE_TERSE2(( "SAP_MCASP_alloc(): serializer output: pSers: 0x%x. *pSers: 0x%x", pSers, *pSers)); } base[_MCASP_PDIR_OFFSET] |= (1 << i); //TRACE_TERSE1(( "SAP_MCASP_alloc(): serializer output: set pin %d.", i)); } } *pSers++; } //TRACE_TERSE3(("SAP_MCASP_alloc(): serializer PDIR: 0x%x, numSers %d, *pSers: 0x%x", base[_MCASP_PDIR_OFFSET], pDevExt->numSers, *pSers)); if (device->mode == DEV2_INPUT) { MCASP_ConfigRcv *pRxConfig = (MCASP_ConfigRcv *)pParams->sio.pConfig; // infer clock pin directions if (pParams->sap.pinMask & _MCASP_PFUNC_ACLKR_MASK) if (pRxConfig->aclkrctl & _MCASP_ACLKRCTL_CLKRM_MASK) base[_MCASP_PDIR_OFFSET] |= _MCASP_PDIR_ACLKR_MASK; else base[_MCASP_PDIR_OFFSET] &= ~_MCASP_PDIR_ACLKR_MASK; if (pParams->sap.pinMask & _MCASP_PFUNC_AHCLKR_MASK) if (pRxConfig->ahclkrctl & _MCASP_AHCLKRCTL_HCLKRM_MASK) base[_MCASP_PDIR_OFFSET] |= _MCASP_PDIR_AHCLKR_MASK; else base[_MCASP_PDIR_OFFSET] &= ~_MCASP_PDIR_AHCLKR_MASK; if (pParams->sap.pinMask & _MCASP_PFUNC_AFSR_MASK) if (pRxConfig->afsrctl & _MCASP_AFSRCTL_FSRM_MASK) base[_MCASP_PDIR_OFFSET] |= _MCASP_PDIR_AFSR_MASK; else base[_MCASP_PDIR_OFFSET] &= ~_MCASP_PDIR_AFSR_MASK; //TRACE_TERSE1(( "SAP_MCASP_alloc(): rx clock: 0x%x", base[_MCASP_PDIR_OFFSET])); MCASP_configRcv (hPort, pRxConfig); } else { MCASP_ConfigXmt *pTxConfig = (MCASP_ConfigXmt *)pParams->sio.pConfig; // infer clock pin directions if (pParams->sap.pinMask & _MCASP_PFUNC_ACLKX_MASK) if (pTxConfig->aclkxctl & _MCASP_ACLKXCTL_CLKXM_MASK) base[_MCASP_PDIR_OFFSET] |= _MCASP_PDIR_ACLKX_MASK; else base[_MCASP_PDIR_OFFSET] &= ~_MCASP_PDIR_ACLKX_MASK; if (pParams->sap.pinMask & _MCASP_PFUNC_AHCLKX_MASK) if( pTxConfig->ahclkxctl & _MCASP_AHCLKXCTL_HCLKXM_MASK ) base[_MCASP_PDIR_OFFSET] |= _MCASP_PDIR_AHCLKX_MASK; else base[_MCASP_PDIR_OFFSET] &= ~_MCASP_PDIR_AHCLKX_MASK; if (pParams->sap.pinMask & _MCASP_PFUNC_AFSX_MASK) if( pTxConfig->afsxctl & _MCASP_AFSXCTL_FSXM_MASK ) base[_MCASP_PDIR_OFFSET] |= _MCASP_PDIR_AFSX_MASK; else base[_MCASP_PDIR_OFFSET] &= ~_MCASP_PDIR_AFSX_MASK; if (pParams->sap.pinMask & _MCASP_PFUNC_AMUTE_MASK) base[_MCASP_PDIR_OFFSET] |= _MCASP_PDIR_AMUTE_MASK; // HACK -- determine DIT need by FXWID if (((pTxConfig->afsxctl & _MCASP_AFSXCTL_FXWID_MASK)>> _MCASP_AFSXCTL_FXWID_SHIFT) == MCASP_AFSXCTL_FXWID_BIT) base[_MCASP_DITCTL_OFFSET] = MCASP_DITCTL_RMK (MCASP_DITCTL_VB_ZERO, MCASP_DITCTL_VA_ZERO, MCASP_DITCTL_DITEN_DIT); else base[_MCASP_DITCTL_OFFSET] = MCASP_DITCTL_DEFAULT; //TRACE_TERSE1(( "SAP_MCASP_alloc(): tx clock: 0x%x", base[_MCASP_PDIR_OFFSET])); MCASP_configXmt (hPort, pTxConfig); } SAP_PORT_FTABLE_reset (device); // unlock context Hwi_restore (oldMask); // determine number of TDM slots (32 max), if DIT must be 2, must be // done after MCASP_config since the registers are referenced directly if (device->mode == DEV2_OUTPUT) { if ((base[_MCASP_AFSXCTL_OFFSET] & _MCASP_AFSXCTL_XMOD_MASK) == (MCASP_AFSXCTL_XMOD_OF(0x180) << _MCASP_AFSXCTL_XMOD_SHIFT) ) tdmMask = 0x3; else tdmMask = base[_MCASP_XTDM_OFFSET]; } else tdmMask = base[_MCASP_RTDM_OFFSET]; pDevExt->numSlots = 0; for (i=0; i < 32; i++) if (tdmMask & (1 << i)) pDevExt->numSlots +=1; //Log_info2("Leaving SAP_MCASP_alloc: tdmMask: 0x%x. numSlots: %d", tdmMask, pDevExt->numSlots); return DEV2_OK; } // SAP_MCASP_alloc // ----------------------------------------------------------------------------- Int SAP_MCASP_close (DEV2_Handle device) { SAP_DeviceExtension *pDevExt = (SAP_DeviceExtension *)(device->object); const SAP_Params *pParams = pDevExt->pParams; MCASP_Handle hPort = sapMcaspDrv.hPort[pParams->sio.moduleNum]; volatile Uint32 *base = (volatile Uint32 *) hPort->baseAddr; volatile Uint32 *pSers =&base[_MCASP_SRCTL0_OFFSET]; Int i; //TRACE_TERSE1(( "SAP_MCASP_close(0x%x)", device)); for (i=0; i < _MCASP_CHANNEL_CNT; i++) { if (pParams->sap.pinMask & (1 << i)) *pSers = (MCASP_SRCTL_SRMOD_INACTIVE | ( MCASP_SRCTL_DISMOD_LOW << _MCASP_SRCTL_DISMOD_SHIFT )); *pSers++; } return DEV2_OK; } //SAP_MCASP_close // ----------------------------------------------------------------------------- // Enable appropriate section of McASP. See McASP data sheet (Operation) for // more info on the steps. Int SAP_MCASP_enable (DEV2_Handle device) { SAP_DeviceExtension *pDevExt = (SAP_DeviceExtension *)device->object; const SAP_Params *pParams = pDevExt->pParams; Int mcaspNum = pParams->sio.moduleNum; MCASP_Handle hPort = sapMcaspDrv.hPort[mcaspNum]; volatile Uint32 *base = (volatile Uint32 *)(hPort->baseAddr); volatile Uint32 *fifoBase = base + _MCASP_FIFO_OFFSET; int i, mask0, mask1, mask2, mask3, mask4; Uint32 wrReg, rdReg; Int result = 0; //TRACE_TERSE1(( "SAP_MCASP_enable(0x%x)", device)); // STEP 1: Reset McASP to default values // This was done in preceding function call. // STEP 2: Enable FIFO // If present, for input and output. Set NUMEVT = NUMDMA to disable pacing // so that the same DMA setup can be used with FIFO enabled or disbaled if (sapMcaspDrv.fifoPresent[mcaspNum]) { if (device->mode == DEV2_OUTPUT) { fifoBase[_MCASP_WFIFOCTL_OFFSET] = (pDevExt->numSers << _MCASP_WFIFOCTL_WNUMEVT_SHIFT) | (pDevExt->numSers << _MCASP_WFIFOCTL_WNUMDMA_SHIFT); fifoBase[_MCASP_WFIFOCTL_OFFSET] |= (MCASP_WFIFOCTL_WENA_ENABLE << _MCASP_WFIFOCTL_WENA_SHIFT); //TRACE_TERSE1(( "SAP_MCASP_enable(): output fifos: numSers %d", pDevExt->numSers)); } else { fifoBase[_MCASP_RFIFOCTL_OFFSET] = (pDevExt->numSers << _MCASP_RFIFOCTL_RNUMEVT_SHIFT) | (pDevExt->numSers << _MCASP_RFIFOCTL_RNUMDMA_SHIFT); fifoBase[_MCASP_RFIFOCTL_OFFSET] |= (MCASP_RFIFOCTL_RENA_ENABLE << _MCASP_RFIFOCTL_RENA_SHIFT); // TRACE_TERSE1(( "SAP_MCASP_enable(): input fifos: numSers %d", pDevExt->numSers)); } } mask1 = 0; rdReg = _MCASP_GBLCTL_OFFSET; if (device->mode == DEV2_INPUT) { wrReg = _MCASP_RGBLCTL_OFFSET; mask0 = MCASP_FMKS (GBLCTL,RHCLKRST,ACTIVE); if (base[_MCASP_ACLKRCTL_OFFSET] & _MCASP_ACLKRCTL_CLKRM_MASK) mask1 = MCASP_FMKS (GBLCTL,RCLKRST,ACTIVE); mask2 = MCASP_FMKS (GBLCTL,RSRCLR,ACTIVE); mask3 = MCASP_FMKS (GBLCTL,RSMRST,ACTIVE); mask4 = MCASP_FMKS (GBLCTL,RFRST,ACTIVE); } else { wrReg = _MCASP_XGBLCTL_OFFSET; mask0 = MCASP_FMKS (GBLCTL,XHCLKRST,ACTIVE); if (base[_MCASP_ACLKXCTL_OFFSET] & _MCASP_ACLKXCTL_CLKXM_MASK) mask1 = MCASP_FMKS (GBLCTL,XCLKRST,ACTIVE); mask2 = MCASP_FMKS (GBLCTL,XSRCLR,ACTIVE); mask3 = MCASP_FMKS (GBLCTL,XSMRST,ACTIVE); mask4 = MCASP_FMKS (GBLCTL,XFRST,ACTIVE); } // STEP 4: Start high-frequency clocks // According to McASP datasheet this step is necessary even if the high- // frequency clocks are external. if (mask0) { //TRACE_TERSE1(( "SAP_MCASP_enable(): HF clock mask 0: 0x%x. ", mask0)); result = SAP_MCASP_FTABLE_waitSet (hPort, wrReg, rdReg, mask0, REGISTER_SET_TIMEOUT); if (result) return result; } // STEP 5: Enable bit clock generator if internally generated if (mask1) { //TRACE_TERSE1(( "SAP_MCASP_enable(): bit clock mask 1: 0x%x. ", mask1)); result = SAP_MCASP_FTABLE_waitSet (hPort, wrReg, rdReg, mask1, REGISTER_SET_TIMEOUT); if (result) return result; } // STEP 6: Setup DMA (this was done earlier -- out of order OK) // STEP 7: Activate serializers //TRACE_TERSE1(( "SAP_MCASP_enable(): serializers mask 2: 0x%x. ", mask2)); result = SAP_MCASP_FTABLE_waitSet (hPort, wrReg, rdReg, mask2, REGISTER_SET_TIMEOUT); if (result) return result; // STEP 8: Verify that all transmit buffers are serviced. // This is guaranteed to succeed since by now we now that there is a clock // and hence XDATA empty will be generated if (device->mode == DEV2_OUTPUT) { volatile Uint32 *pSers; volatile int timeout; result = 0; // configure serializers and associated pins pSers =&base[_MCASP_SRCTL0_OFFSET]; for (i=0; i < _MCASP_CHANNEL_CNT; i++) { if (pDevExt->pParams->sap.pinMask & (1 << i)) { //Log_info3(( "SAP_MCASP_enable(): wait for serializer %d. pSers: 0x%x, *pSers: 0x%x", i, pSers, *pSers)); while ((*pSers & _MCASP_SRCTL_XRDY_MASK) != 0); } *pSers++; } if (result) { #ifdef ENABLE_TRACE TRACE_TERSE0(( "SAP_MCASP_enable(): Stopping trace on serializer error.")); //Log_disable(&trace); #endif return result; } } // STEP 9: Release state machine from reset //TRACE_TERSE1(( "SAP_MCASP_enable(): reset state machine, mask 3: 0x%x.", mask3)); result = SAP_MCASP_FTABLE_waitSet (hPort, wrReg, rdReg, mask3, REGISTER_SET_TIMEOUT); if (result) return result; // STEP 10: Release FS generators from reset // This needs to be enabled even if external frame sync because counter // for frame sync errors is in frame sync generator. //TRACE_TERSE1(( "SAP_MCASP_enable(): release FS generators, mask 4: 0x%x.", mask4)); result = SAP_MCASP_FTABLE_waitSet (hPort, wrReg, rdReg, mask4, REGISTER_SET_TIMEOUT); //TRACE_TERSE1(( "SAP_MCASP_enable(): SAP_MCASP_enable(0x%x) complete.", device)); return result; } //SAP_MCASP_enable // ----------------------------------------------------------------------------- Int SAP_MCASP_open (DEV2_Handle device) { return DEV2_OK; } // SAP_MCASP_open // ----------------------------------------------------------------------------- Int SAP_MCASP_reset (DEV2_Handle device) { SAP_DeviceExtension *pDevExt = (SAP_DeviceExtension *) device->object; const SAP_Params *pParams = pDevExt->pParams; Int mcaspNum = pParams->sio.moduleNum; MCASP_Handle hPort = sapMcaspDrv.hPort[mcaspNum]; int oldhclk, oldclk, newhclk, newclk; volatile int * base = (volatile int *) hPort->baseAddr; volatile Uint32 *fifoBase = (volatile Uint32 *) (base + _MCASP_FIFO_OFFSET); if (device->mode == DEV2_INPUT) { //TRACE_TERSE1(( "SAP_MCASP_reset(0x%x) input device.", device)); // disable FIFO if present Log_info1("SAP_MCASP_reset(0x%x) input device.", device); if (sapMcaspDrv.fifoPresent[mcaspNum]) fifoBase[_MCASP_RFIFOCTL_OFFSET] &= ~(MCASP_RFIFOCTL_RENA_ENABLE << _MCASP_RFIFOCTL_RENA_SHIFT); // set to internal clock source (see spru041d.pdf page 117) oldhclk = base[_MCASP_AHCLKRCTL_OFFSET]; oldclk = base[_MCASP_ACLKRCTL_OFFSET]; newhclk = (oldhclk & ~_MCASP_AHCLKRCTL_HCLKRM_MASK) | (MCASP_AHCLKRCTL_HCLKRM_INTERNAL << _MCASP_AHCLKRCTL_HCLKRM_SHIFT); newclk = (oldclk & ~_MCASP_ACLKRCTL_CLKRM_MASK) | (MCASP_ACLKRCTL_CLKRM_INTERNAL << _MCASP_ACLKRCTL_CLKRM_SHIFT); base[_MCASP_AHCLKRCTL_OFFSET] = newhclk; base[_MCASP_ACLKRCTL_OFFSET] = newclk; // assert RHCLKRST,RCLKRST to force signals to pass through with divide by 1 base[_MCASP_RGBLCTL_OFFSET] &= ~ _MCASP_GBLCTL_RHCLKRST_MASK; base[_MCASP_RGBLCTL_OFFSET] &= ~ _MCASP_GBLCTL_RCLKRST_MASK; while (base[_MCASP_GBLCTL_OFFSET] & _MCASP_GBLCTL_RHCLKRST_MASK); while (base[_MCASP_GBLCTL_OFFSET] & _MCASP_GBLCTL_RCLKRST_MASK); // Reset all other transmitter functions base[_MCASP_RGBLCTL_OFFSET] = 0; while (base[_MCASP_GBLCTL_OFFSET] & _MCASP_GBLCTL_RSMRST_MASK); while (base[_MCASP_GBLCTL_OFFSET] & _MCASP_GBLCTL_RFRST_MASK); while (base[_MCASP_GBLCTL_OFFSET] & _MCASP_GBLCTL_RSRCLR_MASK); // clear status register by writing ones // don't write to the RTDMSLOT register since it is read only and // causes a simulator warning when written base[_MCASP_RSTAT_OFFSET] = 0x1F7; while (base[_MCASP_RSTAT_OFFSET] & _MCASP_RSTAT_RDATA_MASK); // restore clock settings base[_MCASP_AHCLKRCTL_OFFSET] = oldhclk; base[_MCASP_ACLKRCTL_OFFSET] = oldclk; } else { //TRACE_TERSE1(("SAP_MCASP_reset(0x%x) output device.", device)); Log_info1("SAP_MCASP_reset(0x%x) output device.", device); // disable FIFO if present if (sapMcaspDrv.fifoPresent[mcaspNum]) fifoBase[_MCASP_WFIFOCTL_OFFSET] &= ~(MCASP_WFIFOCTL_WENA_ENABLE << _MCASP_WFIFOCTL_WENA_SHIFT); { volatile Uint32 *pSers = (volatile Uint32 *)(&base[_MCASP_SRCTL0_OFFSET]); Int i; for (i=0; i < _MCASP_CHANNEL_CNT; i++) { if (pParams->sap.pinMask & (1 << i)) *pSers = (MCASP_SRCTL_SRMOD_INACTIVE | ( MCASP_SRCTL_DISMOD_LOW << _MCASP_SRCTL_DISMOD_SHIFT )); *pSers++; } } // set to internal clock source (see spru041d.pdf page 117) oldhclk = base[_MCASP_AHCLKXCTL_OFFSET]; oldclk = base[_MCASP_ACLKXCTL_OFFSET]; newhclk = (oldhclk & ~_MCASP_AHCLKXCTL_HCLKXM_MASK) | (MCASP_AHCLKXCTL_HCLKXM_INTERNAL << _MCASP_AHCLKXCTL_HCLKXM_SHIFT); newclk = (oldclk & ~_MCASP_ACLKXCTL_CLKXM_MASK) | (MCASP_ACLKXCTL_CLKXM_INTERNAL << _MCASP_ACLKXCTL_CLKXM_SHIFT); base[_MCASP_AHCLKXCTL_OFFSET] = newhclk; base[_MCASP_ACLKXCTL_OFFSET] = newclk; // assert XHCLKRST,XCLKRST to force signals to pass through with divide by 1 base[_MCASP_XGBLCTL_OFFSET] &= ~ _MCASP_GBLCTL_XHCLKRST_MASK; base[_MCASP_XGBLCTL_OFFSET] &= ~ _MCASP_GBLCTL_XCLKRST_MASK; while (base[_MCASP_GBLCTL_OFFSET] & _MCASP_GBLCTL_XHCLKRST_MASK); while (base[_MCASP_GBLCTL_OFFSET] & _MCASP_GBLCTL_XCLKRST_MASK); // Reset all other transmitter functions base[_MCASP_XGBLCTL_OFFSET] = 0; while (base[_MCASP_GBLCTL_OFFSET] & _MCASP_GBLCTL_XSMRST_MASK); while (base[_MCASP_GBLCTL_OFFSET] & _MCASP_GBLCTL_XFRST_MASK); while (base[_MCASP_GBLCTL_OFFSET] & _MCASP_GBLCTL_XSRCLR_MASK); // clear status register by writing ones // don't write to the RTDMSLOT register since it is read only and // causes a simulator warning when written base[_MCASP_XSTAT_OFFSET] = 0x1F7; while (base[_MCASP_XSTAT_OFFSET] & _MCASP_XSTAT_XDATA_MASK); { volatile Uint32 *pSers = (volatile Uint32 *)(&base[_MCASP_SRCTL0_OFFSET]); Int i; for (i=0; i < _MCASP_CHANNEL_CNT; i++) { if (pParams->sap.pinMask & (1 << i)) *pSers = MCASP_SRCTL_SRMOD_XMT; *pSers++; } } // restore clock settings base[_MCASP_AHCLKXCTL_OFFSET] = oldhclk; base[_MCASP_ACLKXCTL_OFFSET] = oldclk; } //TRACE_TERSE1(( "SAP_MCASP_reset(0x%x) complete.", device)); return DEV2_OK; } // SAP_MCASP_reset // ----------------------------------------------------------------------------- // Set and wait for settings to registers (e.g. GBLCTL) to take effect // we nee such a timeout since if the clocks are not available then // the settings will never take affect which would lead to a lockup condition. #define INT_MAX 0xFFFFFFFF // maximum value returned by Clock_getTicks Int SAP_MCASP_waitSet (MCASP_Handle hMcasp, Uint32 wrReg, Uint32 rdReg, Uint32 mask, Uint32 timeout) { volatile Uint32 *base = (volatile Uint32 *)(hMcasp->baseAddr); Uint32 timeStart, timeNow, elapsed, resMask; //TRACE_TERSE3(("SAP_MCASP_waitSet(0x%x, 0x%x, 0x%x).", hMcasp, wrReg, rdReg)); // configure reserved mask to eliminate debug messages from simulator when // writing to read only bits. Set default to all ones so that this function // can be, although is not at this time, used by registers other than // R/XGBCTL. resMask = 0xFFFFFFFF; if (wrReg == _MCASP_RGBLCTL_OFFSET) resMask = 0x1F; else if (wrReg == _MCASP_XGBLCTL_OFFSET) resMask = 0x1F00; // set register with mask value base[wrReg] = (base[rdReg] | mask) & resMask; timeStart = Clock_getTicks(); while (1) { if ((base[rdReg] & mask) == mask) break; timeNow = Clock_getTicks(); elapsed = timeNow - timeStart; // check for wrap aound if (timeNow < timeStart) elapsed = INT_MAX - timeStart + timeNow; // return error if timeout reached; //note: tick period = 1 ms; so timeout in ms = nticks if (elapsed > timeout) return SIO2_ETIMEOUT; } return DEV2_OK; } //SAP_MCASP_waitSet int gMcASPWatchDogInCnt=0; int gMcASPWatchDogOutCnt=0; // ----------------------------------------------------------------------------- Int SAP_MCASP_watchDog (DEV2_Handle device) { SAP_DeviceExtension *pDevExt = (SAP_DeviceExtension *) device->object; MCASP_Handle hPort = sapMcaspDrv.hPort[pDevExt->pParams->sio.moduleNum]; int stat; if (device->mode == DEV2_INPUT) { stat = MCASP_RGETH (hPort, RSTAT); if ((stat & _MCASP_RSTAT_ROVRN_MASK) || (stat & _MCASP_RSTAT_RDMAERR_MASK)) { gMcASPWatchDogInCnt++; return DEV2_EBADIO; } } else { stat = MCASP_RGETH (hPort, XSTAT); if ((stat & _MCASP_XSTAT_XUNDRN_MASK) || (stat & _MCASP_XSTAT_XDMAERR_MASK)) { gMcASPWatchDogOutCnt++; return DEV2_EBADIO; } } return DEV2_OK; } // SAP_MCASP_watchDog // -----------------------------------------------------------------------------