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.

Inconsistent Resume Power State in DM3730 EVM

Other Parts Discussed in Thread: DM3730, TPS65950

Setup: DM3730 EVM with BSP_WINCE_ARM_A8_01_02_00

There seems to be an inconsistency as to which power state the system returns into upon resuming. When suspending using the power key, devices all go into D4 state. When resuming also using the power, the system resumes to D2. SOMETIMES, but not always, the system then automatically proceeds into D0. Other times, it stays in D2 and never goes into D0.  You can see this on the EVM where after a resume, sometimes the display comes on immediately. Other times, we need to tap the display to wake up into D0 from D2.

I confirmed this bahavior by adding debug into the SetPowerState functions of some drivers. One driver that shows this behavior is the display manager, dssai.cpp. By printing “dwPowerLevel” every time OMAPDisplayController::SetPowerLevel() is called, we see what level the system is requesting.

Here are examples on how I am able to replicate the issue.

Boot EVM: no external I/O connected except SD card.

Boot till display shows touchscreen cal. No need to calibrate touchscreen; it isn’t part of this test.

Let system sit idle.  It goes to D1 then later D2.

Power key to suspend.

Power key to resume.

System resumes to D2 then automatically to D0 state. Backlight is ON.

 

Then Plug in USB OTG, wait for connect via Windows Device Manager

Power key to suspend.

Power key to resume.

System resumes to D2.  Does NOT automatically go to D0.

 

Tap on Touchscreen, THEN system goes to D0.

 

Power-cycle system.

Boot EVM same as before, USB OTG NOT connected.

Once system is booted, BEFORE it goes to D1, power key to suspend.

Power key to resume.

System resumes to D2. Does NOT automatically go to D0.

 

It would be one thing if the system was suspended when it was in D2, then we resume to D2, and if system was in D0, then we would resume to D0. However, it is the opposite that is sometimes happening, and it isn't consistent. And regardless of if system is in D0 or D2, when OTG is connected, it is not always returning to D0.

This inconsistency is at the root of the problems that we are having with the suspend/resume of the USB OTG with the TPS65950 transceiver and driver, because if we only go into D2 and not D0, the OTG portion of the TPS doesn’t resume correctly and we cannot reconnect to OTG. Instead, the client connection with the PC eventually times out.

Any help you can provide on resolving this issue on the EVM would be greatly appreciated. We can then port over that resolution to our platform.

  • David

    For problem regarding resume power state, there is nothing much BSP can do - the kernel PM decides which state the device resumes in. It may have something to do with the activity timers. You could go through Microsoft PM driver and see how it works or post it on msdn forum.

    For OTG TPS driver, I didnt find code where TPS for OTG is not turned on for D2 state - can you point me to that piece of code. Also, can you modify it to turn on TPS for OTG on D2?

    -Madhvi

  • Madhvi,


    Thanks for your quick response. In reviewing your comments, I looked more closely at the code again, and I was misled by my own log files. The TPS for OTG is in fact turned on with the D2 state. What misled me is that when there is a switch from D2 to D0, it is turned on again (i.e. interrupts re-enabled).  So that second time essentially has no effect, but that was one of the key differences when I compared logs between a successful and unsuccessful resume; I had missed the first time it was called since that was identical in both cases.

    So the TPS isn't the issue with resuming OTG.  Nevertheless, we still have the problem. I've got log files that show that OTG resumes successfully anytime the system resumes into D0, but fails when we resume into D2.  But without the source code and all the custom debug we've added, it probably wouldn't help even if I did post that log file here. One bit of info that I have is that on a successful resume, there is always a call to PmGetSystemPowerState() around the 40th OTG interrupt after a resume; immediately after that, the connection is successful. In an unsuccessful resume, that function is not called, and it is at that point that I see the OTG driver not getting any more receive interrupts, and it times out shortly after that. The problem is that I have not been able to find the thread or code that is calling that specific function at that specific time. Whichever thread or function is making that call appears to be doing something different in D0 vs D2; if I could track down what that difference is, I could possibly get the resume to work even when the system resumes to D2.

    While the kernel PM decides which state the device resumes in, that should be based on parameters or events generated by the BSP code. So I don't think this is a Microsoft PM issue, although we haven't ruled it out. I'm still trying to find the root cause of the power key sometimes leading to generation of a PM_USER_ACTIVITY_EVENT, but not always. That *is* user activity, and thus should ALWAYS generate user-activity event. I believe if it did, then the kernel PM would resume into D0, and all would be fine. Resuming into D2 should only occur if there was something like an RTC wakeup to take care of backround OS tasks or non-user services.

    We've already cloned the Microsoft PM PDD so that we can add more custom debug; that is how I know the issue is a difference in which event is generated. I'll continue digging through that code to see if I can find the condition that is determining between a PM_USER_ACTIVITY_EVENT vs.  PM_SYSTEM_ACTIVITY_EVENT on the resume when the power key is pressed. If you have hints of where to look for this beyond the PM\PDD folder, I'll take them. :)

    One additional related question, in the case where there is a PM_SYSTEM_ACTIVITY_EVENT , there is also a PM_SYSTEM_API_EVENT following that. I haven't been able to find information on MSDN about what that specific event means. The only thing MSDN says is for more information, look at the source code. That is no help when it's that precise source code that I am trying to understand! Do you know what this event is for?

    Thanks,

    Dave

  • Here is a follow-up as to what I think is happening.

    It seems like the System-Inactivity timer is expiring. There is a call on resume to ReInitTimeOuts(), but it happens too late. The System-Inactivity timer has already expired and the event generated, thus the system goes into D2 on the resume.

    What *I think* we need to do is disable the timeouts when we are suspending, then when they get reinitialized, there won't be any pending events as a result of not disabling them.

    The problem I've encountered, however, is that the PM code has Resume code (e.g. PlatformResumeSystem() in pwstates.cpp and the file pmresume.c in the BSP code), but has no suspend counterpart. When I look at my logs, there's nothing being called in this PM Timer area where I could conveniently put the calls in to disable the timers. I would think that calling DisableUserIdleTimeout(), DisableSuspendTimeout(), and DisableSystemIdleTimeout() would do the trick, but I don't know where the best place is to put this.

    The modules pmresume.c and pmtimers.c are part of the BSP already (as opposed to being PUBLIC code), so perhaps there is somewhere in that file that would be the right place to make these calls.

    I'll be continuing to work on this tomorrow, but if you (or anyone following this thread) have any insight on what *should* be happening when suspending, I'd appreciate it.

    Thanks,

    Dave

  • David Stewart said:
    When I look at my logs, there's nothing being called in this PM Timer area where I could conveniently put the calls in to disable the timers. I would think that calling DisableUserIdleTimeout(), DisableSuspendTimeout(), and DisableSystemIdleTimeout() would do the trick, but I don't know where the best place is to put this.

    can call your APIs from OEMPowerOff?

    -Madhvi