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.

How to turn off USB power in AM335x

Hello

I am trying to figure out a way to turn off USB power  in AM335x based device that we use. Unfortunately the only references I am getting is to autosuspend. 

Is this the only best approach? Our goal is very simple. We want  to turn off USB power and then turn it on to test if it works properly. 

I am using SDK 7 with linux kernel 3.12. The USB device attached to AM335x is a mass storage device. 

Apologies if a similar post already exists. I tried searching but didn't find a simple solution.

Thanks and Regards

Manbir Singh Jhawer

  • Do you want to turn off the power of the MUSB module on AM335x to save power? or only the USB bus?

    For latter, USB autosuspend is the best approach; but for former, I am not aware of any interface in the current Linux driver to achieve that. I will try to take a look.
  • Hi Bin

    Thanks for the quick reply.

    I want to control USB1 DRVVBUS line. Is it possible and if so how?

    Thanks and Regards
    Manbir Singh Jhawer
  • Yes, it is feasible.

    Please apply the patch http://marc.info/?l=linux-usb&m=142722815602618&w=2, which adds an debugfs interface to control DRVVBUS.
    Then mount the debugfs, and run command to turn off DRVVBUS

    # echo 0 > /sys/kernel/debug/musb-hdrc.1.auto/softconnect

    and "echo 1" to the same entry to turn it on.

  • updated the patch url in the post above, it was messed up by auto-formatting.
  • Hi Bin

    Thanks for the detailed reply.

    I tried something similar as below:

    At address 0x47401000 and offset 0xc60, if I write 0 it sets drvvbus to low and if I write 1 it sets drvvbus to high.

    I understand that the address 0xc60 corresponds to some register address for USB 1 ( I found this address from e2e.ti.com/.../270060).

    Can you let me know if there is some similar register offset for USB 0 as well. If nothing else works. I will try and patch the kernel as you had mentioned.

    Thanks and Regards
    Manbir Singh Jhawer
  • Yes, register 0x47401c60 bit0 can be used to control USB1_DRVVBUS pin, but before turn it low, you have to notify the USB driver stack that the enumerated device(s) will be disconnected. Also while turn it high, you have to handle the autosuspend situation. All those are already handled in the patch.

    The corresponding register for MUSB0 is 0x47401460.
  • Hi Bin

    Thanks for the reply and apologies for the delay in replying back.

    I checked the patch you shared and unfortunately I couldn't get it to work. Following is what happens:

    I do the following:

    echo 0 > /sys/kernel/debug/musb-hdrc.1.auto/softconnect

    With cat command the above path returns -1

    cat  /sys/kernel/debug/musb-hdrc.1.auto/softconnect returns -1

    On checking the patch I found that the state does not match with OTG_STATE_A_HOST or OTG_STATE_A_WAIT_BCON. It always is set to 0, which I found is OTG state undefined. I also verified that debugfs is enabled in kernel build and debugfs is mounted using mount command. 

    Any guesses as to what are we missing here?

    Just for information, the register approach does work but I want to try the patch as well.

    Appreciate your help on this issue. Thanks in advance.

    Regards

    Manbir Singh Jhawer

  • Manbir,


    My apologies, I forgot that the patch I referred is only applicable to 3.14+ kernel, but it requires a minor change for 3.12 kernel, due to the 'struct musb' change between the two versions. Following is the patch for the change on top of the patch I referred.

    diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
    index a4da0e6..61638b7 100644
    --- a/drivers/usb/musb/musb_debugfs.c
    +++ b/drivers/usb/musb/musb_debugfs.c
    @@ -239,7 +239,7 @@ static int musb_softconnect_show(struct seq_file *s, void *unused)
            u8              reg;
            int             connect;
    
    -       switch(musb->xceiv->otg->state) {
    +       switch(musb->xceiv->state) {
            case OTG_STATE_A_HOST:
            case OTG_STATE_A_WAIT_BCON:
                    reg = musb_readb(musb->mregs, MUSB_DEVCTL);
    @@ -273,7 +273,7 @@ static ssize_t musb_softconnect_write(struct file *file,
                    return -EFAULT;
    
            if (!strncmp(buf, "0", 1)) {
    -               switch(musb->xceiv->otg->state) {
    +               switch(musb->xceiv->state) {
                    case OTG_STATE_A_HOST:
                            musb_root_disconnect(musb);
                            reg = musb_readb(musb->mregs, MUSB_DEVCTL);
    @@ -285,7 +285,7 @@ static ssize_t musb_softconnect_write(struct file *file,
                    }
    
            } else if (!strncmp(buf, "1", 1)) {
    -               switch(musb->xceiv->otg->state) {
    +               switch(musb->xceiv->state) {
                    case OTG_STATE_A_WAIT_BCON:
                            /*
                             * musb_save_context() called in musb_runtime_suspend()
    
    

    But I am wondering why you did not get kernel compilation error without the 2nd patch? You have already manually fixed it?

    Do you have the USB device enumerated when run the test command?

    What 'dr_mode' is set to in your dts file for the USB port?

    You can 'cat /sys/bus/platform/devices/musb-hdrc.1.auto/mode' to get the runtime otg mode for USB1 port, if 'cat softconnect' returns -1.

    Please also run the following command to get some register dump at this failure time.

    # grep -i 'power\|devctl' /sys/kernel/debug/musb-hdrc.1.auto/regdump

  • Thanks, the latest patch works.

    The previous patch does not give compiler errors as xceiv object has otg object as its member variable. For above patch, the USB must be enumerated.
  • Manbir Jhawer said:
    Thanks, the latest patch works.

    Great! Thanks for the update.

    Manbir Jhawer said:
    The previous patch does not give compiler errors as xceiv object has otg object as its member variable.

    Yeah, but in older kernel, xceiv->otg does not have member state, which gave errors on my build. Anyway it no longer matters.