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.

Linux/PROCESSOR-SDK-AM335X: Turn off USB power in AM335x

Part Number: PROCESSOR-SDK-AM335X


Tool/software: Linux

I am looking for turning off USB power. I want to turn off the power of the MUSB module on AM335x to save power.

I found similar thread in e2e forums  

I am facing problem in below step 

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

After that if I do cat I am getting -1

#cat /sys/kernel/debug/musb-hdrc.0/softconnect

-1

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

Power : e0
DevCtl : 80

Can you help me on this

 

  • Please post which Linux version you use.
  • Hi Dheeraj,

    First please clarify what exact you want to turn off. You post seems indicating you don't USB function and want to turn off the MUSB module in AM335x to save power. This has something to do with the peripheral power domain in AM335x, which is not controlled in USB drivers.

    The softconnect command you referred is to turn off USB BUS power (VBUS) to disconnect the attached USB devices, this is not related to the MUSB module power in AM335x. And this command is only effective when the MUSB controller is in host mode - DevCtl has to be 0x19 or 0x5D.
  • Hi Bin,

    The requirement is that upon our product boot up phase, it should power USB on, enable  host mode(OTG) and check for plugged in devices. If no device is found then power off USB, disable OTG mode and enable DEVICE mode.

    Are there any proc/sysfs entries that can control this?

    Regards

    Dheeraj

  • Dheeraj,

    the description is still a little blurry to me - host mode and OTG are two different things, what do you mean by enable host/OTG and disable OTG enable DEVICE mode?

    And why you want to power off the MUSB module when switching mode?

    Anyway the Linux MUSB driver already does most of your requirement, when dr_mode is set to 'otg' in device tree, the MUSB module starts as in device mode, then periodically checking for device attach (in every 2 seconds). If a device is found, MUSB switch to host mode. When the device is detached, MUSB switches back to device mode and periodically checks for device attach again.
  • What my understanding is that when USB flash drive is plugged into my system, the system operates in host mode.
    So basically I have a requirement where-in I should enable and disable host mode on demand i.e with a virtual button I should be able to turn on host mode such that the system will only then check for plugged in devices.
    Device mode (i.e ) my system connecting to another system as a peripheral over USB cable should be possible all the time.

    And why you want to power off the MUSB module when switching mode?
    >>Please just ignore this line for now.. I don't think I need this.

    Anyway the Linux MUSB driver already does most of your requirement, when dr_mode is set to 'otg' in device tree, the MUSB module starts as in device mode, then periodically checking for device attach (in every 2 seconds). If a device is found, MUSB switch to host mode. When the device is detached, MUSB switches back to device mode and periodically checks for device attach again.
    >>As per our requirement as I said only when a virtual button is pressed (from GUI something like enable USB host mode button is clicked) only then USB flash drives should be checked and attached.

  • Hi,

    Please try with the following patch on Processor SDK v5.x kernel. Please ensure the dr_mode is set to 'otg' in dts for the musb port you use.

    After kernel is booted, the usb port will stay in peripheral mode. After a usb gadget driver is loaded, the port is ready to connect to the usb host at any time. Nothing will happen if plug in a usb device to the port.

    To let the usb port to work in host mode, plug in a usb device, then run the following command (I use usb0 as an example), the usb device should be enumerated.

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

    When the usb device is removed from the usb port, the port will goes back to and stay in peripheral mode.

    diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
    index 952733ceaac8..459616f560b2 100644
    --- a/drivers/usb/musb/musb_debugfs.c
    +++ b/drivers/usb/musb/musb_debugfs.c
    @@ -324,8 +324,6 @@ static ssize_t musb_softconnect_write(struct file *file,
                            break;
                    }
            } else if (!strncmp(buf, "1", 1)) {
    -               switch (musb->xceiv->otg->state) {
    -               case OTG_STATE_A_WAIT_BCON:
                            /*
                             * musb_save_context() called in musb_runtime_suspend()
                             * might cache devctl with SESSION bit cleared during
    @@ -336,10 +334,6 @@ static ssize_t musb_softconnect_write(struct file *file,
                            reg = musb_readb(musb->mregs, MUSB_DEVCTL);
                            reg |= MUSB_DEVCTL_SESSION;
                            musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
    -                       break;
    -               default:
    -                       break;
    -               }
            }
     
            pm_runtime_mark_last_busy(musb->controller);
    diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
    index 0c50f38ae4ef..f8df6d9999b3 100644
    --- a/drivers/usb/musb/musb_dsps.c
    +++ b/drivers/usb/musb/musb_dsps.c
    @@ -227,7 +227,7 @@ static int dsps_check_status(struct musb *musb, void *unused)
            struct dsps_glue *glue = dev_get_drvdata(dev->parent);
            const struct dsps_musb_wrapper *wrp = glue->wrp;
            u8 devctl;
    -       int skip_session = 0;
    +       int skip_session = 1;
     
            if (glue->vbus_irq)
                    del_timer(&glue->timer);
    
  • Thanks Bin, above patch working fine but in one scenario I am getting issue.

    Below scenario working fine for me

    1. USB connected
        echo 1 > /sys/kernel/debug/musb-hdrc.0/softconnect
    2. USB detected
    3. Removed USB  (Physically)
    4. RNDIS connected
    RNDIS detected

    But I am facing issue in below scnario

    1. USB connected
        echo 1 > /sys/kernel/debug/musb-hdrc.0/softconnect
    2. USB detected
    3. echo 0 > /sys/kernel/debug/musb-hdrc.0/softconnect
    USB successfully unmounted
    3. Removed USB (Physically)
    4. RNDIS connected it is not detected (below error I am getting)


    [ 510.364502] musb_h_ep0_irq 1195: no URB for end 0
    [ 516.021722] musb_h_ep0_irq 1195: no URB for end 0
    [ 521.679294] musb_h_ep0_irq 1195: no URB for end 0
    [ 527.336552] musb_h_ep0_irq 1195: no URB for end 0
    [ 606.394794] musb_stage0_irq 902: unhandled DISCONNECT transition (a_wait_vrise)

     

    Can you help me on this.

  • My understanding is that in the failure case you did extra 'echo 0 > .../softconnect' command. But your product end user doesn't have access to the linux console but yourself, does it? Then nobody else can get into this failure scenario but you, why would you do the extra step?
  • Hi Bin,

    One of the requirement is below,
    If over USB drive no transactions have taken place for 30 seconds (we have our own call backs to find whether user using USB or other functionality), I need to disable USB 5V supply from my board (i.e echo 0 > .../softconnect) i.e disable OTG mode. As I earlier said, device mode should still be available but when I connect RNDIS USB cable, I see the issue reported above.

    Regards
    Dheeraj

  • Hi Dheeraj,

    Please use the following patch instead.

    diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
    index 952733ceaac8..ce83344d36d4 100644
    --- a/drivers/usb/musb/musb_debugfs.c
    +++ b/drivers/usb/musb/musb_debugfs.c
    @@ -319,13 +319,15 @@ static ssize_t musb_softconnect_write(struct file *file,
                            reg = musb_readb(musb->mregs, MUSB_DEVCTL);
                            reg &= ~MUSB_DEVCTL_SESSION;
                            musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
    +                       if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) {
    +                               musb->xceiv->otg->state = OTG_STATE_B_IDLE;
    +                               MUSB_DEV_MODE(musb);
    +                       }
                            break;
                    default:
                            break;
                    }
            } else if (!strncmp(buf, "1", 1)) {
    -               switch (musb->xceiv->otg->state) {
    -               case OTG_STATE_A_WAIT_BCON:
                            /*
                             * musb_save_context() called in musb_runtime_suspend()
                             * might cache devctl with SESSION bit cleared during
    @@ -336,10 +338,6 @@ static ssize_t musb_softconnect_write(struct file *file,
                            reg = musb_readb(musb->mregs, MUSB_DEVCTL);
                            reg |= MUSB_DEVCTL_SESSION;
                            musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
    -                       break;
    -               default:
    -                       break;
    -               }
            }
     
            pm_runtime_mark_last_busy(musb->controller);
    diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
    index 0c50f38ae4ef..f8df6d9999b3 100644
    --- a/drivers/usb/musb/musb_dsps.c
    +++ b/drivers/usb/musb/musb_dsps.c
    @@ -227,7 +227,7 @@ static int dsps_check_status(struct musb *musb, void *unused)
            struct dsps_glue *glue = dev_get_drvdata(dev->parent);
            const struct dsps_musb_wrapper *wrp = glue->wrp;
            u8 devctl;
    -       int skip_session = 0;
    +       int skip_session = 1;
     
            if (glue->vbus_irq)
                    del_timer(&glue->timer);
    
  • Thanks Bin, Above patch is working in two scenarios as I mentioned above.

    While testing I observed below scenario facing issue.

    Issue-
    If my board power on with USB drive connected it is automatically detected.
    Steps-
    1. Device powered off
    2.USB connected
    3.Power on device
    4. USB detected, But expectation is I need to run echo 1>../softconnect to detect USB drive
  • Dheeraj kumar said:
    Issue-
    If my board power on with USB drive connected it is automatically detected.

    Please use the following additional patch to solve this issue.

    diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
    index ff17e94ef465..30959261c016 100644
    --- a/drivers/usb/musb/musb_core.c
    +++ b/drivers/usb/musb/musb_core.c
    @@ -1071,9 +1071,7 @@ void musb_start(struct musb *musb)
             * (b) vbus present/connect IRQ, peripheral mode;
             * (c) peripheral initiates, using SRP
             */
    -       if (musb->port_mode != MUSB_PORT_MODE_HOST &&
    -                       musb->xceiv->otg->state != OTG_STATE_A_WAIT_BCON &&
    -                       (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
    +       if (musb->port_mode != MUSB_PORT_MODE_HOST) {
                    musb->is_active = 1;
            } else {
                    devctl |= MUSB_DEVCTL_SESSION