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.

AM3352 USB disconnect

Guru 16800 points

Hello,

Please let me know when USB bus is disconnected by software.
Linux kernel version is PSP 04.06.00.08.

Best Regards,

Nomoto

  • Hi,

    I will forward this to the USB experts.

  • Nomoto,

    Do you mean MUSB is in host mode? When a device is removed from the USB port, MUSB_DISCONNECT interrupt is generated, then its ISR handles the disconnect teardown.

  • Hello Liu-san,

    Thank you for your reply.

    Yes, I mean MUSB is in host mode.
    Is there any possibility to disconnect the device by software intentionally?

    Best Regards,

    Nomoto

     

  • Do you mean the USB device is still physically connected on the USB bus, but software disconnect the device?

  • Hello,

    Yes.
    I assume that the USB device is still physically connected on the USB bus, but software disconnect the device.

    Best Regards,

    Nomoto

  • Do you use SDK6.0 kernel? If so, please try the attached patch.

    From cadba10089bc9c712e036b90eb8386bc1cb1b5e1 Mon Sep 17 00:00:00 2001
    From: Bin Liu <b-liu@ti.com>
    Date: Tue, 22 Apr 2014 13:31:41 -0500
    Subject: [PATCH] usb: musb: procfs: add an entry to force device disconnect
    
    echo f > /proc/driver/musb_hdrc.{0,1}
    
    Signed-off-by: Bin Liu <b-liu@ti.com>
    ---
     drivers/usb/musb/musb_procfs.c | 18 ++++++++++++++++++
     1 file changed, 18 insertions(+)
    
    diff --git a/drivers/usb/musb/musb_procfs.c b/drivers/usb/musb/musb_procfs.c
    index 2db7eac..b3c643d 100644
    --- a/drivers/usb/musb/musb_procfs.c
    +++ b/drivers/usb/musb/musb_procfs.c
    @@ -609,6 +609,8 @@ static int musb_proc_write(struct file *file, const char __user *buffer,
     	u8 reg;
     	struct musb *musb = (struct musb *)data;
     	void __iomem *mbase = musb->mregs;
    +	unsigned long flags;
    +
     
     	/* MOD_INC_USE_COUNT; */
     
    @@ -662,6 +664,22 @@ static int musb_proc_write(struct file *file, const char __user *buffer,
     		musb_writeb(mbase, MUSB_DEVCTL, reg);
     		break;
     
    +	case 'f':
    +		reg = musb_readb(musb->mregs, MUSB_DEVCTL);
    +		if ((reg & MUSB_DEVCTL_SESSION) == 0)
    +			break;
    +
    +		dev_dbg(musb->controller, "force device disconnect\n");
    +		spin_lock_irqsave(&musb->lock, flags);
    +		reg &= ~MUSB_DEVCTL_SESSION;
    +		musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
    +
    +		 /* inform stack about disconnect of root hub */
    +		musb->int_usb = MUSB_INTR_DISCONNECT;
    +		musb_interrupt(musb);
    +		spin_unlock_irqrestore(&musb->lock, flags);
    +		break;
    +
     	case 'H':
     		if (mbase) {
     			reg = musb_readb(mbase, MUSB_DEVCTL);
    -- 
    1.8.4
    
    

    From cadba10089bc9c712e036b90eb8386bc1cb1b5e1 Mon Sep 17 00:00:00 2001
    From: Bin Liu <b-liu@ti.com>
    Date: Tue, 22 Apr 2014 13:31:41 -0500
    Subject: [PATCH] usb: musb: procfs: add an entry to force device disconnect
    
    echo f > /proc/driver/musb_hdrc.{0,1}
    
    Signed-off-by: Bin Liu <b-liu@ti.com>
    ---
     drivers/usb/musb/musb_procfs.c | 18 ++++++++++++++++++
     1 file changed, 18 insertions(+)
    
    diff --git a/drivers/usb/musb/musb_procfs.c b/drivers/usb/musb/musb_procfs.c
    index 2db7eac..b3c643d 100644
    --- a/drivers/usb/musb/musb_procfs.c
    +++ b/drivers/usb/musb/musb_procfs.c
    @@ -609,6 +609,8 @@ static int musb_proc_write(struct file *file, const char __user *buffer,
            u8 reg;
            struct musb *musb = (struct musb *)data;
            void __iomem *mbase = musb->mregs;
    +       unsigned long flags;
    +
     
            /* MOD_INC_USE_COUNT; */
     
    @@ -662,6 +664,22 @@ static int musb_proc_write(struct file *file, const char __user *buffer,
                    musb_writeb(mbase, MUSB_DEVCTL, reg);
                    break;
     
    +       case 'f':
    +               reg = musb_readb(musb->mregs, MUSB_DEVCTL);
    +               if ((reg & MUSB_DEVCTL_SESSION) == 0)
    +                       break;
    +
    +               dev_dbg(musb->controller, "force device disconnect\n");
    +               spin_lock_irqsave(&musb->lock, flags);
    +               reg &= ~MUSB_DEVCTL_SESSION;
    +               musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
    +
    +                /* inform stack about disconnect of root hub */
    +               musb->int_usb = MUSB_INTR_DISCONNECT;
    +               musb_interrupt(musb);
    +               spin_unlock_irqrestore(&musb->lock, flags);
    +               break;
    +
            case 'H':
                    if (mbase) {
                            reg = musb_readb(mbase, MUSB_DEVCTL);
    -- 
    1.8.4
    
    
  • Is there an equivalent for this in SDK8.0? Or is there another option for powering off the USB?

  • No.

    Do you plan to migrate to SDK8.0? If so, I can try to make a patch for the same. It might take a while because sometimes submitting a feature to mainline kernel upstream is not a trivial process. I had submitted the similar feature to upstream a year ago but the patch has been rejected, the reason was that the feature is necessary.

  • We went from 6.0 to 8.0 because of other USB issues. When a device on one USB bus disconnected, devices on the other USB bus disconnected and then reconnected. 8.0 resolves this issue.

    We need to control the "connection" to a camera that is hard-wired to our Sitara device. In development, it works great when we plug the USB cable into the camera (the camera switches to "USB Mode") and then we unplug the cable and the camera switches back to "Normal" mode. The camera's filesystem mounts and unmounts properly and lsusb is correct.

    Since this device will be hardwired to the USB, we need a way to programmatically control this behavior.

    One strategy we tried was to externally switch the power on/off the USB via another port pin; however, we get a VBUS error because we are not satisfying the Host Mode USB driver (USBx_VBUS, USBx_DRVVBUS)

    Any ideas how we can achieve this within the confines of the Linux USB subsystem?
  • Doug,

    Ok, we have progress on this issue. I just convinced the kernel USB maintainer with a different proposal then he agreed to add this feature. I will try to find some time to make a patch for it. I will keep you updated once the patch is ready to be accepted by upstream.

    Meanwhile you can use the following sequence to archive the same, it requires you have devmem2 utility installed in your filesystem.

    After the USB device is enumerated by USB1 port:

    - to disconnect:

    # echo 0 > /sys/bus/usb/devices/usb2/authorized

    # devmem2 0x47401c60 b 0

    - to re-connect again:

    # echo 1 > /sys/bus/usb/devices/usb2/authorized

    If the host port is USB0, use the following commands instead.

    # echo 0 > /sys/bus/usb/devices/usb1/authorized

    # devmem2 0x47401460 b 0

    # echo 1 > /sys/bus/usb/devices/usb1/authorized

    Doug Griswold said:

    One strategy we tried was to externally switch the power on/off the USB via another port pin; however, we get a VBUS error because we are not satisfying the Host Mode USB driver (USBx_VBUS, USBx_DRVVBUS)

    I guess you were cutting VBUS line, which is not the right way to do it. You should control the DP/DM lines, but this is not recommended in general, because adding a switch on DP/DM could cause signal integrity issue due to the extra impedance of the switch.

  • Bin,

    Thanks for your help on this! When I do the commands you list above, the camera disconnects and returns to Normal mode. But the modem on the other USB port exhibits weird behavior.

    Starting out this is what it looks like

    Bus 001 Device 002: ID 0733:2222 ViewQuest Technologies, Inc.
    Bus 002 Device 002: ID 1bc7:1010 Telit DE910-DUAL
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub


    The Telit is using the options driver and running PPP. We can communicate with it over /dev/ttyUSB2 fine.

    After echoing 0 to authorized, the camera disappears from lsusb and we can still talk to the Telit over /dev/ttyUSB2.

    root@am335x-evm:~/process# echo 0 > /sys/bus/usb/devices/usb1/authorized
    [   81.550901] usb 1-1: USB disconnect, device number 2

    root@am335x-evm:~/process# ./at "ati3" "*" /dev/ttyUSB2
    ati3
    Telit
    OK

    root@am335x-evm:~/process# ping google.com
    PING google.com (63.84.3.24): 56 data bytes
    64 bytes from 63.84.3.24: seq=0 ttl=53 time=88.107 ms


    The problem occurs when I issue the devmem2 command. Note the VBUS_ERROR

    root@am335x-evm:~/process# devmem2 0x47401460 b 0
    /dev/mem opened.
    Memory mapped at address 0xb6f17000.
    Read at address  0x47401460 (0xb6f17460): 0x5D
    Write at address 0x47401460 (0xb6f17460): 0x00, readback 0x00
    root@am335x-evm:~/process# [  163.380412] musb-hdrc musb-hdrc.1.auto: VBUS_ERROR in a_wait_vrise (80, <SessEnd), retry #3, port1 0008050f

    The camera exits USB mode and goes to Normal mode as expected.  lsusb still shows the Telit too, but I can't talk to it. It seems like the tty is locked up

    root@am335x-evm:~/process# lsusb
    Bus 002 Device 002: ID 1bc7:1010 Telit DE910-DUAL
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

    root@am335x-evm:~/process# ./at "ati3" "*" /dev/ttyUSB2

    This hangs. If I control-c out of this I see this in the log (I've only included the 1st part of it)

    ^C[  230.237086] ------------[ cut here ]------------
    [  230.242058] WARNING: CPU: 0 PID: 1446 at drivers/usb/musb/musb_host.c:128 musb_h_tx_flush_fifo+0x9c/0xac [musb_hdrc]()
    [  230.253270] Could not flush host TX2 fifo: csr: 2403
    [  230.258472] Modules linked in: option usb_wwan usbserial musb_dsps musb_hdrc musb_am335x
    [  230.267030] CPU: 0 PID: 1446 Comm: at Not tainted 3.14.26-g07d13c6-dirty #6
    [  230.274325] Backtrace:
    [  230.276948] [<c0011258>] (dump_backtrace) from [<c00113f4>] (show_stack+0x18/0x1c)
    [  230.284882]  r6:00000080 r5:00000009 r4:ddbe9b98 r3:00000000
    [  230.290886] [<c00113dc>] (show_stack) from [<c054c9b0>] (dump_stack+0x20/0x28)
    [  230.298489] [<c054c990>] (dump_stack) from [<c00381a0>] (warn_slowpath_common+0x6c/0x8c)
    [  230.306988] [<c0038134>] (warn_slowpath_common) from [<c0038264>] (warn_slowpath_fmt+0x38/0x40)
    [  230.316102]  r8:c079b760 r7:dbae047c r6:00000000 r5:00002403 r4:e09a6c12
    [  230.323213] [<c0038230>] (warn_slowpath_fmt) from [<bf0070bc>] (musb_h_tx_flush_fifo+0x9c/0xac [musb_hdrc])

    Any ideas?

  • Doug,

    Please provide the USB portion of the schematics, it seems telling the both ports are sharing something.