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.

AM3358 USB OTG default state problem / sleep and shutdown problem (Android JB DevKit_4_1_1, Linux Kernel 3.2)

Other Parts Discussed in Thread: AM3358, TPS63000, TPS65218

Hi,
we are designing a custom board based on the BeagleBoneBlack (CPU is AM3358). The software used is the PSP for Android TI_Android_JB_4_2_2_DevKit_4_1_1, Kernel 3.2. Currently I encounter an USB issue that I do not fully understand. I can neither put the android to sleep nor do a software power down. Beyond that USB seems to work fine.
The USB design differs a bit from the BBB:
We use a TPS63000 to generate the +5V (USBx_VBUS), enabled by USBx_DRVVBUS.
USB1 is host only, USB0 is configured as USB OTG. One difference here is the usage of two physically separated ports for the OTG port: One USB-A slot for host mode and one USB-B slot for device mode.
The signals USB0_ID, USB0_VBUS, D_N and D_P are switched by a relay. USB0_ID is switched to GND if in host mode (default) and is switched to NC if in device mode. The relay is controlled by USB_Device_Vdd (5V applied by external host).

The DRVVBUS pins are muxed and the omap_musb_board_data looks like this:

static struct omap_musb_board_data musb_board_data = {
.interface_type = MUSB_INTERFACE_ULPI,
/*
* mode[0:3] = USB0PORT's mode
* mode[4:7] = USB1PORT's mode
*/
.mode = (MUSB_HOST << 4) | MUSB_OTG,
.power = 500,
.instances = 1,
};

Terminal when trying to sleep:
[ 793.648895] pm_op(): platform_pm_suspend+0x0/0x6c returns -16
[ 793.654968] PM: Device musb-hdrc.0 failed to suspend: error -16
Terminal on shutdown:
[ 1978.190185] musb-hdrc musb-hdrc.1: remove, state 1
[ 1978.195343] usb usb1: USB disconnect, device number 1
[ 1978.200622] usb 1-1: USB disconnect, device number 3
after that message, the system freezes and the LCD remains active.

I have traced down the problem to the USB-Controller and its role assumption for musb-hdrc.0:
On power on, without anything connected to usb, the state of /proc/driver/musb_hdrc.0 is as following:

Status: MHDRC, Mode=Peripheral (Power=e0, DevCtl=19)
OTG state: b_idle; active

I would have expected "Mode=Host" here. "Active" seems wrong, too. This would be an explanation for "error -16" I get when trying to sleep, but I don't know the origin for that mode.
If I plug a device into this port (touchscreen controller), the state of musb_hdrc.0 changes correctly:

Status: MHDRC, Mode=Host (Power=e0, DevCtl=5d)
OTG state: a_host; active

Shutdown works with that. Sleep is entered, system reacts to nothing but reset.

Removing the device again:
Status: MHDRC, Mode=Peripheral (Power=e0, DevCtl=19)
OTG state: b_idle; inactive

Shutdown works with that. Sleep is entered, system reacts to nothing but reset.

My questions:
- What can cause the usb controller/driver to assume that its in active peripheral mode?
- Why can't I wake my board from sleep? PWR_BTN, usb touchscreen and terminal didn't work.

I'm thankful for any help and will try to provide any information necessary that could help solving my problem.

  • Moving this to the Android forum.

  • Hi,

    we did a quick search an it would confirm what you thought, the "active" status seems to be the reason for the -16 error (EBUSY) that is returned when trying to suspend.
    the function musb_suspend() will check the musb->is_active which is the flag displayed in the proc entry (see dump_header_stats() in musb_procfs.c). 

    It is hard to easily identify the reason for that flag to be setup like this, since it could be done in several location. Could you try and instrument the musb core to see where the is_active is set to true?

    Regarding the wake up from sleep mode, could you make sure that you have wake sources configured before going to sleep: 
    cat /sys/<path to your device>/power/wakeup
    if everything is "disabled", try to echo "enabled" to this file to make sure the device can wake up the system.

  • Hi,
    thanks for the reply and the hints.

    My wakeup sources seem to be okay:
    root@android:/sys/kernel/debug # cat wakeup_sources

    name active_count event_count hit_count active_since total_time max_time last_change
    gpio-keys 0 0 0 0 0 0 0
    am33xx-rtc 0 0 0 0 0 0 0
    ti_tscadc 0 0 0 0 0 0 0

    As you purposed I've tried to find the place where is_active is set to true. In musb_core.c (around Line 970)

    void musb_start(struct musb *musb)
    {
    ...
    if (is_otg_enabled(musb)) {
    ...
      if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS){
      /* mp, 2014-12-11 Try to disable OTG port on start */
      musb->is_active = 0;
      // musb->is_active = 1; //Original code
    }
    else
      devctl |= MUSB_DEVCTL_SESSION;
    ...
    }

    After that dirty fix musb_hdrc.0 prints
    Status: MHDRC, Mode=Peripheral (Power=e0, DevCtl=19)
    OTG state: b_idle; inactive

    I've found another very interesting post about sleep mode:
    http://e2e.ti.com/support/embedded/android/f/509/t/292766

    I've added the lines
    writel(0x2a0, 0x4c000038); // = EMIF PWR_MGMT_CTRL Register
    writel(0xa0, 0x4c00003c); // = EMIF PWR_MGMT_CTRL_SHDW Register
    to my u-boot code. Now shutdown works, sleep mode works with some errors and only returns with gpio-keys input. The PWR_BUT from the TPS doesn't wake up the system.
    [ 864.498626] request_suspend_state: sleep (0->3) at 817256852715 (2000-01-01 00:18:23.524160568 UTC)
    [ 864.640502] PM: Syncing filesystems ... done.
    [ 864.647949] tps65218_reg_write: REG: 17 VAL: 99
    [ 864.653991] tps65218_reg_write: REG: 1a VAL: 86
    [ 864.662170] Freezing user space processes ... (elapsed 0.01 seconds) done.
    [ 864.684906] Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done.
    [ 869.705963] LCD Controller timed out
    [ 869.736724] PM: suspend of devices complete after 5029.327 msecs
    [ 869.746704] PM: late suspend of devices complete after 3.570 msecs

    [ 887.707702] GFX domain entered low power state
    [ 887.712463] Successfully transitioned all domains to low power state
    [ 887.929840] PM: early resume of devices complete after 210.234 msecs
    [ 887.940917] wakeup wake lock: event1-306
    [ 888.138061] usb 1-1: reset full-speed USB device number 4 using musb-hdrc
    [ 888.257934] usb 1-1: device descriptor read/64, error -19
    [ 888.488037] usb 1-1: device descriptor read/64, error -19
    [ 888.718078] usb 1-1: reset full-speed USB device number 4 using musb-hdrc
    [ 888.838104] usb 1-1: device descriptor read/64, error -19
    [ 888.969390] musb_stage0_irq: (2) musb->xceiv->state = 10,
    [ 889.008819] PM: resume of devices complete after 1071.489 msecs
    [ 889.017486] Restarting tasks ...
    [ 889.023284] usb 1-1: USB disconnect, device number 4
    [ 889.056457] request_suspend_state: wakeup (3->0) at 823848280000 (2000-01-01 00:18:47.975596944 UTC)
    [ 889.318572] done.
    [ 889.338989] tps65218_reg_write: REG: 17 VAL: b0
    [ 889.348815] tps65218_reg_write: REG: 1a VAL: 86
    [ 889.380615] suspend: exit suspend, ret = 0 (2000-01-01 00:18:48.299732503 UTC)
    [ 889.548461] usb 1-1: new full-speed USB device number 5 using musb-hdrc
    ...

    And the worst part is that I get the same errors like in the thread mentioned above (+ a flickering display):
    [ 26.722686] LCDC sync lost
    [ 27.126312] LCDC sync lost
    [ 27.544158] LCDC sync lost

    Can I set the EMIF PWR_MGMT registers only when I enter sleep/shutdown and reset them afterwards?

    Side information: I am using some LEDs as Heartbeat, MMC access and Sleepmode indicator. The sleep mode kills this functionality at the first suspend until the next reset.

  • Hi,

    Could you please reproduce the issue on supported platforms like BeagleBoneBlack, Am335x SK or AM335X EVM with JB 4.2.2? Otherwise, we will not be able to support you effectively.
  • I will try to reproduce this after the holidays since I dont have a BBB + proper development environment at hand. Until now I use this (still unsatisfying because not always working) workaround:

    In pm33xx.c I activate the self refresh in PWR_MGMT_CTRL (0x4c000038) in am33xx_pm_begin(...) and clear the self refresh bit in am33xx_pm_end(...). In the bootloader I deactivate the self refresh in PWR_MGMT_CTRL if the system won' t wake up and gets a warm reset during sleep mode.

    With the usb touchcontroller disconnected and some patience until the system reports

    [ 3294.506591] PM: late suspend of devices complete after 3.448 msecs

    it will wake up with a gpio. This is some progress.

    Side question: If KEY_POWER is reported as an input (by pressing the PWR_BTN), where is the connection between this key and the "mem" state? I'd like to try the "standby" mode but could not find the code where this happens. Some ideas?