This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

When suspended then resumes,System interrupt tick not fire,Interrupt controller regs are not accessible,System hangs up!

Other Parts Discussed in Thread: TPS65930, OMAP3515, SYSCONFIG

 

Hi all:

    We have faced this problem quite a while,when we tested the suspend/wakeup features by pressing the pwr key on our custom board(almost the same as evm-2,difference lies on IO pads,OMAP3515+TPS65930),the BSP is BSP_WINCE_ARM_A8_01_01_00.Sometimes it wakes up immediately,and output the trace wake due to sysintr -1(which is SYSINTR_UNDEFINED).Sometime the system hangs up behind outputting "-OTG SetPowerState".Two cases may happen together,very like the link:http://e2e.ti.com/support/embedded/f/353/t/74839.aspx.we tested without anything connected to OTG and EHCI ports too.

     We track the issue,find out the cause:Interrupt controller is Not Working!Exiting from OEMPowerOff(),Wince calls drivers's PowerUp(),then PM calls power manageble driver's IOCtrol to set power state.It happens when PM calls EHCI driver's HcdPdd_IOControl to set D0 state:

        DeviceIoControl(pPddObject->hRootBus, IOCTL_BUS_REQUEST_CLOCK, &dwClock, sizeof(dwClock), NULL, 0, NULL, NULL);(1)

      SetDevicePowerState(pPddObject->hParentBusHandle, D0, NULL);(2)

      DelayMilliSeconds(200, FALSE);(3)

      DelayMilliSeconds(200, FALSE) call sleep() to  release ownership to wait for 200ms,then can't get back,system loops in OEMIdle(),No timer ticks occur in OEMInterruptHandler().We doubt about the interrupt controller not working,so adds follow code before (1) and bellow (2):

      OALMSG(1, (L"MIR1="));

      OALMSG(1, (L"%08x %08x %08x\n",INREG32(&s_intr->INTC_MIR0)));

      DeviceIoControl(pPddObject->hRootBus, IOCTL_BUS_REQUEST_CLOCK, &dwClock, sizeof(dwClock), NULL, 0, NULL, NULL);(1)

      SetDevicePowerState(pPddObject->hParentBusHandle, D0, NULL);(2)

      OALMSG(1, (L"MIR2="));

      OALMSG(1, (L"%08x %08x %08x\n",INREG32(&s_intr->INTC_MIR0)));

      DelayMilliSeconds(200, FALSE);(3)

      Normally,accessing INTC_SYSCONFIG reg success,the system works fine.But sometimes can access INTC_SYSCONFIG before (1),can't access INTC_SYSCONFIG behind (2),output:MIR2=,and nothing shows up,the timer ticks also not occur in OEMInterruptHandler(),The system seems locked!!

      We continue track deeper,It happens in _PrcmDomainHwUpdate() function in Prcm_domain.c file.When system wakeups,it set wakeup and sleep dependency with MPU,snippet:

static

BOOL

_PrcmDomainHwUpdate(

    UINT powerDomain,

    UINT ffMask

    )

{

    BOOL rc = TRUE;

    UINT pm_wkdep;

    UINT pm_pwstctrl;

    UINT cm_sleepdep;

    UINT cm_clkstctrl;

       UINT32 test = 0;

    OMAP_CM_REGS   *pCmRegs;

    OMAP_PRM_REGS  *pPrmRegs;

    ClockDomainInfo_t  *pClockStates;   

    PowerDomainState_t *pDomainState;

   

    // update the following hw registers

    // PM_WKDEP_xxx

    // CM_SLEEPDEP_xxx

    // PM_PWSTCTRL_xxx.POWERSTATE

    // CM_CLKSTCTRL_xxx

 

    pCmRegs = GetCmRegisterSet(powerDomain);

    pPrmRegs = GetPrmRegisterSet(powerDomain);

    pClockStates = s_DomainTable[powerDomain].pClockStates;

    pDomainState = s_DomainTable[powerDomain].pDomainState;

       

    if (pDomainState != NULL)

        {

        if (ffMask & DOMAIN_UPDATE_WKUPDEP)

            {

              if((POWERDOMAIN_USBHOST == powerDomain) && (pDomainState->wakeDependency != 0))

              {

                     OALMSG(1,(L"W1"));

                     test = INREG32(&g_pIntr->pICLRegs->INTC_SYSCONFIG);

                     OALMSG(1,(L":"));

                     OALMSG(1, (L"%08x\n",test));

              }

            pm_wkdep = INREG32(&pPrmRegs->PM_WKDEP_xxx) & ~WKDEP_MASK;

            pm_wkdep |= pDomainState->wakeDependency << WKDEP_SHIFT;

            OUTREG32(&pPrmRegs->PM_WKDEP_xxx, pm_wkdep);

              if((POWERDOMAIN_USBHOST == powerDomain) && (pDomainState->wakeDependency != 0))

              {

                     OALMSG(1,(L"W2"));

                     test = INREG32(&g_pIntr->pICLRegs->INTC_SYSCONFIG);

                     OALMSG(1,(L":"));

                     OALMSG(1, (L"%08x\n",test));

              }

            }

 

        if (ffMask & DOMAIN_UPDATE_SLEEPDEP)

            {

              if((POWERDOMAIN_USBHOST == powerDomain) && (pDomainState->sleepDependency != 0))

              {

                     OALMSG(1,(L"S1"));

                     test = INREG32(&g_pIntr->pICLRegs->INTC_SYSCONFIG);

                     OALMSG(1,(L":"));

                     OALMSG(1, (L"%08x\n",test));

                       //DumpPrcmRegsSnapshot();

              }

            cm_sleepdep = INREG32(&pCmRegs->CM_SLEEPDEP_xxx) & ~SLEEPDEP_MASK;

            cm_sleepdep |= pDomainState->sleepDependency << SLEEPDEP_SHIFT;

            OUTREG32(&pCmRegs->CM_SLEEPDEP_xxx, cm_sleepdep);

               if((POWERDOMAIN_USBHOST == powerDomain) && (pDomainState->sleepDependency != 0))

              {

                     OALMSG(1,(L"S2:"));

                        //     PrcmRegsSnapshot();

                     //     DumpPrcmRegsSnapshot();

                     test = INREG32(&g_pIntr->pICLRegs->INTC_SYSCONFIG);

                     OALMSG(1,(L":"));

                     OALMSG(1, (L"%08x\n",test));

              }

            }

 

        if (ffMask & DOMAIN_UPDATE_POWERSTATE)

            {

            pm_pwstctrl = INREG32(&pPrmRegs->PM_PWSTCTRL_xxx) & ~(POWERSTATE_MASK | LOGICRETSTATE_MASK);

            pm_pwstctrl |= pDomainState->powerState << POWERSTATE_SHIFT;

            pm_pwstctrl |= pDomainState->logicState;

            OUTREG32(&pPrmRegs->PM_PWSTCTRL_xxx, pm_pwstctrl);

            }

        }

 

    if (pClockStates != NULL)

        {

        if (ffMask & DOMAIN_UPDATE_CLOCKSTATE)

            {

            UINT i;

            cm_clkstctrl = INREG32(&pCmRegs->CM_CLKSTCTRL_xxx);

            for (i = 0; i < pClockStates->count; ++i)

                {

                cm_clkstctrl &= ~(CLKSTCTRL_MASK << pClockStates->rgClockDomains[i].clockShift);

                cm_clkstctrl |= (pClockStates->rgClockDomains[i].clockState << pClockStates->rgClockDomains[i].clockShift) << CLKSTCTRL_SHIFT;

                }

            OUTREG32(&pCmRegs->CM_CLKSTCTRL_xxx, cm_clkstctrl);

 

            // save context

            if (powerDomain == POWERDOMAIN_MPU)

                {

                OUTREG32(&g_pPrcmRestore->CM_CLKSTCTRL_MPU, cm_clkstctrl);

                }

            else if (powerDomain == POWERDOMAIN_CORE)

                {

                OUTREG32(&g_pPrcmRestore->CM_CLKSTCTRL_CORE, cm_clkstctrl);

                }

            }

        }

   

    return rc;

}

    Under normal circumstances,output:

    S1:00000000

    S2::00000000

    W1:00000000

    W2:00000000

    But sometimes,output:

   S1:00000000

    S2::00000000

    W1:00000000

    W2:

    then nothing shows up,system seems locked,interrupts not fire(gptimer1,and gpio interrupt).We printed prcm regs before suspend and in _PrcmDomainHwUpdate() using DumpPrcmRegsSnapshot() and PrcmRegsSnapshot();the attachment three cases's outputs,before enter suspend,the prcm regs are exactly the same,but the wakeup prcm regs are different.

We compared the three results,differences[(before suspend)     (wakeup in _PrcmDomainHwUpdate) ]:

normal and immediately wakeup

1CM_AUTOIDLE_DSS        [01 00]==>[01 01]   Display Sub-System interface clock is automatically enabled

2PRM_IRQSTATUS_MPU    [11 00]==>[11 10]   Software supervised transition completed,event is true (pending)

3RM_RSTST_USBHOST      [04 00]==>[04 04]   USB HOST domain has been reset following an USB HOST power domain wake-up.

 

immediately wakeup and dead locked

1PRM_IRQSTATUS_MPU    [11 10]==>[11 11]   Wake-up event is true (pending)

2PM_WKST_WKUP            [00 00]==>[00 01]   GPTIMER 1 wakeup occurred.

Please could anyone shed some light on this?

 

Best regards

 

  • anybody tell me how to edit the style of post????
  • Qingsong

    We have seen the issues that you have mentioned above. Please modify the PrcmSuspend() code as follows and let us know if you still see the issue.

    -Madhvi

     


    //------------------------------------------------------------------------------
    //
    //  Function:  PrcmSuspend()
    //
    //  Performs the necessary steps to enter full retention and then wake-up
    //  from full retention.  This routine only sets up the necessary clocks
    //  to try to enter full retention.  The external preconditions for full
    //  retentions must be met for full retention to be entered.
    //
    void
    PrcmSuspend()
    {
        DWORD latencyState;
        UINT32 prevCoreState;
        UINT32 prevMpuState;
        UINT32 prevPerState;
        UINT32 prevMpuPerNeonDssState;
        UINT32 prevCoreCamUsbSgxState;
        UINT32 irq = (UINT32) OAL_INTR_IRQ_UNDEFINED;
        BOOL isTimerIntrPending = FALSE;
       
        OALSaveAllVfpNeonRegisters(VfpNeonSave);

        //--------------------------------------------------------------------------
        // perform power down sequence
        //--------------------------------------------------------------------------

        // Disable match interrupt   
        irq = INREG32(&g_pIntr->pICLRegs->INTC_SIR_IRQ);
        if (irq == g_oalTimerIrq)
        {
            isTimerIntrPending = TRUE;          
            OALTimerSetReg(&g_pTimerRegs->TISR, GPTIMER_TIER_MATCH);
            OUTREG32(&g_pIntr->pICLRegs->INTC_CONTROL, IC_CNTL_NEW_IRQ);
            OALTimerSetReg(&g_pTimerRegs->TIER, 0);
        }

        PrcmDeviceEnableClocksKernel(OMAP_DEVICE_GPTIMER1, FALSE);

        // clear previous power state registers
        OUTREG32(&g_pPrcmPrm->pOMAP_MPU_PRM->PM_PREPWSTST_MPU, 0);
        OUTREG32(&g_pPrcmPrm->pOMAP_CORE_PRM->PM_PREPWSTST_CORE, 0);
        OUTREG32(&g_pPrcmPrm->pOMAP_PER_PRM->PM_PREPWSTST_PER, 0);
        OUTREG32(&g_pPrcmPrm->pOMAP_NEON_PRM->PM_PREPWSTST_NEON, 0);
        OUTREG32(&g_pPrcmPrm->pOMAP_DSS_PRM->PM_PREPWSTST_DSS, 0);
        OUTREG32(&g_pPrcmPrm->pOMAP_CAM_PRM->PM_PREPWSTST_CAM, 0);
        OUTREG32(&g_pPrcmPrm->pOMAP_USBHOST_PRM->PM_PREPWSTST_USBHOST, 0);
        OUTREG32(&g_pPrcmPrm->pOMAP_SGX_PRM->PM_PREPWSTST_SGX, 0);

        // use the latency module to transition to a valid sleep state
        latencyState = OALWakeupLatency_GetSuspendState();
        if (OALWakeupLatency_IsChipOff(latencyState))
            {
            if (!OALContextSave())
                {
                // wake-up will fail so just return
                goto cleanUp;
                }
            }
        OALWakeupLatency_PushState(latencyState);


        // Move SoC/CPU to idle mode
       

    #ifndef SHIP_BUILD
        if (g_PrcmDebugSuspendResume)
        {
            OALWakeupLatency_SaveSnapshot();
            PrcmSaveRefCounts();
            PrcmRegsSnapshot();       
        }
    #endif
           
        PrcmDeviceEnableClocksKernel(OMAP_DEVICE_OMAPCTRL, FALSE);

        // Move SoC/CPU to idle mode (suspend)
        fnOALCPUIdle(g_pCPUInfo);

        // resume starts here...
        PrcmDeviceEnableClocksKernel(OMAP_DEVICE_OMAPCTRL, TRUE);

        OALWakeupLatency_PopState();

        prevMpuState = INREG32(&g_pPrcmPrm->pOMAP_MPU_PRM->PM_PREPWSTST_MPU);
        prevCoreState = INREG32(&g_pPrcmPrm->pOMAP_CORE_PRM->PM_PREPWSTST_CORE);
        prevPerState = INREG32(&g_pPrcmPrm->pOMAP_PER_PRM->PM_PREPWSTST_PER);

        prevMpuPerNeonDssState =  (prevMpuState & 0xFF);
        prevMpuPerNeonDssState |= ((INREG32(&g_pPrcmPrm->pOMAP_PER_PRM->PM_PREPWSTST_PER) & 0xFF) << 8);   
        prevMpuPerNeonDssState |= ((INREG32(&g_pPrcmPrm->pOMAP_NEON_PRM->PM_PREPWSTST_NEON) & 0xFF) << 16);   
        prevMpuPerNeonDssState |= ((INREG32(&g_pPrcmPrm->pOMAP_DSS_PRM->PM_PREPWSTST_DSS) & 0xFF) << 24);   

        prevCoreCamUsbSgxState = (prevCoreState & 0xFF);
        prevCoreCamUsbSgxState |= ((INREG32(&g_pPrcmPrm->pOMAP_CAM_PRM->PM_PREPWSTST_CAM) & 0xFF) << 8);   
        prevCoreCamUsbSgxState |= ((INREG32(&g_pPrcmPrm->pOMAP_USBHOST_PRM->PM_PREPWSTST_USBHOST) & 0xFF) << 16);   
        prevCoreCamUsbSgxState |= ((INREG32(&g_pPrcmPrm->pOMAP_SGX_PRM->PM_PREPWSTST_SGX) & 0xFF) << 24);   
       

        OALContextRestore(prevMpuState, prevCoreState, prevPerState);

        PrcmProcessPostMpuWakeup();

        OALLED(LED_IDX_MPU_PREV_STATE, INREG32(&g_pPrcmPrm->pOMAP_MPU_PRM->PM_PREPWSTST_MPU));
        OALLED(LED_IDX_CORE_PREV_STATE, INREG32(&g_pPrcmPrm->pOMAP_CORE_PRM->PM_PREPWSTST_CORE));
        OALLED(LED_IDX_PER_PREV_STATE, INREG32(&g_pPrcmPrm->pOMAP_PER_PRM->PM_PREPWSTST_PER));
        OALLED(LED_IDX_CORE_CAM_USB_SGX_PREV_STATE, prevCoreCamUsbSgxState);
        OALLED(LED_IDX_MPU_PER_NEON_DSS_PREV_STATE, prevMpuPerNeonDssState);

    cleanUp:

        // restart GPTIMER1
        PrcmDeviceEnableClocksKernel(OMAP_DEVICE_GPTIMER1, TRUE);

        if (isTimerIntrPending)
            OALTimerSetReg(&g_pTimerRegs->TMAR, OALTimerGetReg(&g_pTimerRegs->TCRR)+2);
       
        OALTimerStart();
       
        // UNDONE:
        //   Need to update curridlehigh and curridlelow to track cpu loads
        OALRestoreAllVfpNeonRegisters(VfpNeonSave);

    }

  • Thanks Madhvei!

    We changed PrcmSuspend() with your suggestion,if pressing pwr key normally,it works fine.Pressing quikly,due to the gpio1 interrupt(TPS65930 connects to omap3515) occurs before fnOALCPUIdle(g_pCPUInfo) slightly,it will wakeup immidietely,this is reasonable.So,the change may solved our first problem.

    By pressing pwr key quikly,it's very easy to hang system up,and find out the MPU loops in OEMIdle() by printing in OEMIdle.the last output:

     

    WakeUp source: 19 sys 128

    I2C: RESET device 12

    kernel IOCTL_POWER_SET setting state 2

    -OTG SetPowerState

    BKL: POWER_SET to D0 

    DSSAI::SetPowerLevel D2 

    kernel IOCTL_POWER_SET setting state 0

    DSSAI::SetPowerLevel D0 

    kernel IOCTL_POWER_SET setting state 3

    -OTG SetPowerState

    BKL: POWER_SET to D4 

    DSSAI::SetPowerLevel D3 

    OEMPowerOff()++

    WakeUp source: 19 sys 128

    I2C: RESET device 12

    kernel IOCTL_POWER_SET setting state 2

    -OTG SetPowerState

     

     We changed CM_WKDEP_USBHOST_INIT from (0x00000000) to (0x00000002),pressing pwr key puts board into sleep and resume to normal quikly and repeadedly,it seems very hard to reproduce the case,but after many times,it stalls too,output:

    WakeUp source: 20 sys 128

    I2C: RESET device 12

    OPM2

    SetOpp to 1 

    VDD1 1.0500V 

    kernel IOCTL_POWER_SET setting state 2

    -OTG SetPowerState

    BKL: POWER_SET to D0 

    DSSAI::SetPowerLevel D2 

     

     

    Why interrupt controller don't fire interrupt?it seems not work anymore.

    appreciated!


    By the way,we've found a bug in spi driver.Our display device and touch panel connected with spi2 with different channels,it works when system first up,but suspend and wakeup,the touch panel driver can't work,by digging into the bsp,found only restore one channel(the active) when system wakes up,another channel's configuration lost.attachment is our changed source code.


  •  

    Hi all:

    I post the problem again,because the link marked answered,http://e2e.ti.com/support/embedded/f/353/p/103563/365316.aspx#365316,but actually,only solved one problem.

    We test suspend and wakeup fetures,By pressing pwr key quikly,it's very easy to hang system up,and find out the MPU loops in OEMIdle() by printing in OEMIdle.the last output: 

    WakeUp source: 19 sys 128

    I2C: RESET device 12

    kernel IOCTL_POWER_SET setting state 2

    -OTG SetPowerState

    BKL: POWER_SET to D0 

    DSSAI::SetPowerLevel D2 

    kernel IOCTL_POWER_SET setting state 0

    DSSAI::SetPowerLevel D0 

    kernel IOCTL_POWER_SET setting state 3

    -OTG SetPowerState

    BKL: POWER_SET to D4 

    DSSAI::SetPowerLevel D3 

    OEMPowerOff()++

    WakeUp source: 19 sys 128

    I2C: RESET device 12

    kernel IOCTL_POWER_SET setting state 2

    -OTG SetPowerState 

    We tested access to INTC's regs,the system halts,it seems MPU doesn't work anymore,why?

    any help or suggestions will be great because I stuck on this problem for a while. I really want to solve this problem as soon as possible.

    Thanks

    Regards

     

  • we will look into the issue and get back to you.

  • Thanks for the updated SPI file. We ran into the same issue when touchscreen and display shared SPI3. However, after using it, we still had issues with one of the two channels not being configured correctly after resuming.

    We tracked it down to ContextRestore(), which is called once per instance. The following lines must be removed:

        SETREG32(&pDevice->pSPIRegs->MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_SOFTRESET);
        // Wait until resetting is done
        while ( !(INREG32(&pDevice->pSPIRegs->MCSPI_SYSSTATUS) & MCSPI_SYSSTATUS_RESETDONE))
            {
            Sleep (1);
            if (dwCount++>0x100)
                {
                // Break out dead lock, something is wrong.
                ERRORMSG (TRUE, (TEXT("SPI: ERROR holding in reset.\n")));
                return FALSE;
                }
            }

    Otherwise, when the second instance is restored, this reset command clobbers the settings setup when the first instance was restored.

    On a resume, it seems like these registers are already reset, thus no need to do a reset. If such a need became necessary, then it would make more sense to do this reset in the SPI_PowerUp() function.

    I'm curious, how did the attached code work for you given such a reset is occurring? Perhaps there is a different fix or I am missing something with the posted code?

    Thanks,

    Dave

  • Hi All,

     

    Madhvi, can you please post the answer that you found to this issue? A customer I am working with is experiencing something similar.

     

    Thank you,

    Sean