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/AM3356: USB0 OTG flash drive not mounting

Part Number: AM3356

Tool/software: Linux


Has something changed in the USB0 OTG driver code from SDK6 to ProcessorSDK 1.03 on AM335x that would cause a flash drive not mounting? (Didn't TI move from TI81xx driver to MUSB at some point?)

On the EXACT same customer HW if moving back to SDK6, the same flash drive mounts fine. 

From examination of the registers, the USB0_ID line does not even seem to be working correctly (guess we could try forcing USBnMODE [Bit7=IDDIG_MUX] as a experiment)?.  The error occurs in a normal use case after Linux is booted and just plugging in the USB flash drive. Tried various flash drives to no avail.  Sometimes a reboot might fix but honestly they have not tried automated test to see how often it fails.  But when stuck, it seems to stay stuck. No thing shows up in dmesg (which makes sense since no change in the registers).

Please see attached USB0_OTG.txt that has USB register dumps for:
1. This is the case with the sdkpro kernel and musb driver, where the controller does not recognize the insertion of the adapter with a flash drive into the OTG port.
2. These are the cases with the SDK06 kernel and driver. The first one are the register values with the drive/adapter connected and the device has properly enumerated. 
3. The second one is with the drive disconnected.

This is the case with the sdkpro kernel and musb driver, where the controller does not recognize the insertion of the adapter with a flash drive into the OTG port.

root@xxxxxx:musb-hdrc.0.auto# cat mode
root@xxxxxx:musb-hdrc.0.auto# cat /sys/kernel/debug/musb-hdrc.0.auto/regdump
MUSB (M)HDRC Register Dump
FAddr       : 00
Power       : e0
Frame       : 0000
Index       : 0f
Testmode    : 00
TxMaxPp     : 0000
TxCSRp      : 0000
RxMaxPp     : 0000
RxCSR       : 0000
RxCount     : 0000
ConfigData  : 33
DevCtl      : 80
MISC        : 44
TxFIFOsz    : 07
RxFIFOsz    : 07
TxFIFOadd   : 0780
RxFIFOadd   : 0780
VControl    : 00000000
HWVers      : 0800
EPInfo      : ff
RAMInfo     : 0d
LinkInfo    : 5c
VPLen       : 3c
HS_EOF1     : 80
FS_EOF1     : 77
LS_EOF1     : 72
SOFT_RST    : 00
DMA_CNTLch0 : 0000
DMA_ADDRch0 : 00000000
DMA_COUNTch0: 00000000
DMA_CNTLch1 : 0000
DMA_ADDRch1 : 00000000
DMA_COUNTch1: 00000000
DMA_CNTLch2 : 0000
DMA_ADDRch2 : 00000000
DMA_COUNTch2: 00000000
DMA_CNTLch3 : 0000
DMA_ADDRch3 : 00000000
DMA_COUNTch3: 00000000
DMA_CNTLch4 : 0000
DMA_ADDRch4 : 00000000
DMA_COUNTch4: 00000000
DMA_CNTLch5 : 0000
DMA_ADDRch5 : 00000000
DMA_COUNTch5: 00000000
DMA_CNTLch6 : 0000
DMA_ADDRch6 : 00000000
DMA_COUNTch6: 00000000
DMA_CNTLch7 : 0000
DMA_ADDRch7 : 00000000
DMA_COUNTch7: 00000000




These are the cases with the SDK06 kernel and driver.  
The first one are the register values with the drive/adapter connected and the device has properly enumerated.  The second one is with the drive disconnected.

root@xxxxx:~# cat mode
root@xxxxx:~# cat /sys/kernel/debug/musb-hdrc.0/regdump
MUSB (M)HDRC Register Dump
FAddr       : 00
Power       : f0
Frame       : 00d6
Index       : 0f
Testmode    : 00
TxMaxPp     : 0000
TxCSRp      : 0000
RxMaxPp     : 0000
RxCSR       : 0000
RxCount     : 0000
ConfigData  : 33
DevCtl      : 5d
MISC        : 44
TxFIFOsz    : 07
RxFIFOsz    : 07
TxFIFOadd   : 0780
RxFIFOadd   : 0780
VControl    : 00000000
HWVers      : 0800
EPInfo      : ff
RAMInfo     : 0d
LinkInfo    : 5c
VPLen       : 3c
HS_EOF1     : 80
FS_EOF1     : 77
LS_EOF1     : 72
SOFT_RST    : 00
DMA_CNTLch0 : 0000
DMA_ADDRch0 : 00000000
DMA_COUNTch0: 00000000
DMA_CNTLch1 : 0000
DMA_ADDRch1 : 00000000
DMA_COUNTch1: 00000000
DMA_CNTLch2 : 0000
DMA_ADDRch2 : 00000000
DMA_COUNTch2: 00000000
DMA_CNTLch3 : 0000
DMA_ADDRch3 : 00000000
DMA_COUNTch3: 00000000
DMA_CNTLch4 : 0000
DMA_ADDRch4 : 00000000
DMA_COUNTch4: 00000000
DMA_CNTLch5 : 0000
DMA_ADDRch5 : 00000000
DMA_COUNTch5: 00000000
DMA_CNTLch6 : 0000
DMA_ADDRch6 : 00000000
DMA_COUNTch6: 00000000
DMA_CNTLch7 : 0000
DMA_ADDRch7 : 00000000
DMA_COUNTch7: 00000000
root@xxxxxx:~# cat /sys/kernel/debug/musb-hdrc.0/regdump
MUSB (M)HDRC Register Dump
FAddr       : 00
Power       : e0
Frame       : 01c0
Index       : 0f
Testmode    : 00
TxMaxPp     : 0000
TxCSRp      : 0000
RxMaxPp     : 0000
RxCSR       : 0000
RxCount     : 0000
ConfigData  : 33
DevCtl      : 80
MISC        : 44
TxFIFOsz    : 07
RxFIFOsz    : 07
TxFIFOadd   : 0780
RxFIFOadd   : 0780
VControl    : 00000000
HWVers      : 0800
EPInfo      : ff
RAMInfo     : 0d
LinkInfo    : 5c
VPLen       : 3c
HS_EOF1     : 80
FS_EOF1     : 77
LS_EOF1     : 72
SOFT_RST    : 00
DMA_CNTLch0 : 0000
DMA_ADDRch0 : 00000000
DMA_COUNTch0: 00000000
DMA_CNTLch1 : 0000
DMA_ADDRch1 : 00000000
DMA_COUNTch1: 00000000
DMA_CNTLch2 : 0000
DMA_ADDRch2 : 00000000
DMA_COUNTch2: 00000000
DMA_CNTLch3 : 0000
DMA_ADDRch3 : 00000000
DMA_COUNTch3: 00000000
DMA_CNTLch4 : 0000
DMA_ADDRch4 : 00000000
DMA_COUNTch4: 00000000
DMA_CNTLch5 : 0000
DMA_ADDRch5 : 00000000
DMA_COUNTch5: 00000000
DMA_CNTLch6 : 0000
DMA_ADDRch6 : 00000000
DMA_COUNTch6: 00000000
DMA_CNTLch7 : 0000
DMA_ADDRch7 : 00000000
DMA_COUNTch7: 00000000



root@xxxxxx:musb-hdrc.0.auto# cat /sys/kernel/debug/musb-hdrc.0.auto/regdump
MUSB (M)HDRC Register Dump
FAddr       : 00
Power       : e0
Frame       : 0000
Index       : 0f
Testmode    : 00
TxMaxPp     : 0000
TxCSRp      : 0000
RxMaxPp     : 0000
RxCSR       : 0000
RxCount     : 0000
ConfigData  : 33
DevCtl      : 80
MISC        : 44
TxFIFOsz    : 07
RxFIFOsz    : 07
TxFIFOadd   : 0780
RxFIFOadd   : 0780
VControl    : 00000000
HWVers      : 0800
EPInfo      : ff
RAMInfo     : 0d
LinkInfo    : 5c
VPLen       : 3c
HS_EOF1     : 80
FS_EOF1     : 77
LS_EOF1     : 72
SOFT_RST    : 00
DMA_CNTLch0 : 0000
DMA_ADDRch0 : 00000000
DMA_COUNTch0: 00000000
DMA_CNTLch1 : 0000
DMA_ADDRch1 : 00000000
DMA_COUNTch1: 00000000
DMA_CNTLch2 : 0000
DMA_ADDRch2 : 00000000
DMA_COUNTch2: 00000000
DMA_CNTLch3 : 0000
DMA_ADDRch3 : 00000000
DMA_COUNTch3: 00000000
DMA_CNTLch4 : 0000
DMA_ADDRch4 : 00000000
DMA_COUNTch4: 00000000
DMA_CNTLch5 : 0000
DMA_ADDRch5 : 00000000
DMA_COUNTch5: 00000000
DMA_CNTLch6 : 0000
DMA_ADDRch6 : 00000000
DMA_COUNTch6: 00000000
DMA_CNTLch7 : 0000
DMA_ADDRch7 : 00000000
DMA_COUNTch7: 00000000

  • The software team have been notified. They will respond here.
  • Joe,

    Even the Processor SDK1.03 is already very old, I need to go back to check how the MUSB otg driver switching mode. But here are my few questions,

    - with manual test, how often does it fail?
    - does it make difference if add 'usbcore.autosuspend=-1' into the uboot bootargs? Not sure if its usb PM related in the driver.
    - can you please send me the schematics?

    When failed, the log shows the musb controller is unable to enter host mode. What is the output of command
    # /sys/bus/platform/devices/musb-hdrc.0.auto/mode
    when failed?

  • >>I have looked at /sys/bus/platform/devices/musb-hdrc.0.auto/mode, and the output is a_wait_vrise.
    Working on the rest of the items.

  • Joe,

    I am not sure what is happening. Please ask the customer to debug the flow in otg_timer() function in musb_dsps.c.

    243 static void otg_timer(unsigned long _musb)                                      
    244 {                                                                               
    245         struct musb *musb = (void *)_musb;                                      
    246         void __iomem *mregs = musb->mregs;                                      
    247         struct device *dev = musb->controller;                                  
    248         struct dsps_glue *glue = dev_get_drvdata(dev->parent);                  
    249         const struct dsps_musb_wrapper *wrp = glue->wrp;                        
    250         u8 devctl;                                                              
    251         unsigned long flags;                                                    
    252         int skip_session = 0;                                                   
    253                                                                                 
    254         /*                                                                      
    255          * We poll because DSPS IP's won't expose several OTG-critical          
    256          * status change events (from the transceiver) otherwise.               
    257          */                                                                     
    258         devctl = dsps_readb(mregs, MUSB_DEVCTL);                                
    259         dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,            
    260                                 usb_otg_state_string(musb->xceiv->otg->state)); 
    261                                                                                 
    262         spin_lock_irqsave(&musb->lock, flags);                                  
    263         switch (musb->xceiv->otg->state) {                                      
    264         case OTG_STATE_A_WAIT_BCON:                                             
    265                 dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);                       
    266                 skip_session = 1;                                               
    267                 /* fall */                                                      
    268                                                                                 
    269         case OTG_STATE_A_IDLE:                                                  
    270         case OTG_STATE_B_IDLE:                                                  
    271                 if (devctl & MUSB_DEVCTL_BDEVICE) {                             
    272                         musb->xceiv->otg->state = OTG_STATE_B_IDLE;             
    273                         MUSB_DEV_MODE(musb);                                    
    274                 } else {                                                        
    275                         musb->xceiv->otg->state = OTG_STATE_A_IDLE;             
    276                         MUSB_HST_MODE(musb);                                    
    277                 }                                                               
    278                 if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session)           
    279                         dsps_writeb(mregs, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);   
    280                 mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);      
    281                 break;                                                          
    282         case OTG_STATE_A_WAIT_VFALL:                                            
    283                 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;               
    284                 dsps_writel(musb->ctrl_base, wrp->coreintr_set,                 
    285                             MUSB_INTR_VBUSERROR << wrp->usb_shift);             
    286                 break;                                                          
    287         default:                                                                
    288                 break;                                                          
    289         }                                                                       
    290         spin_unlock_irqrestore(&musb->lock, flags);                             
    291 }
    

    When no usb device is attached, otg_timer() should be called in every 2 secs, Line 259 should prints Devctl 0x80 with b_idle state, Line 279 should be called to start the session.

    Then when a usb device is plugged in, because the ID pin is grounded now, Line 279 starting the session will establish the session, then otg_timer() is no longer called.

    Please also turn on the debug in Line 323 in dsps_interrupt() to see what interrupts we are getting when a usb device is attached.

    323         dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",                  
    324                         usbintr, epintr);
    
  • Updating with some offline communication, this issue was solved.

    Using above debug method comparing the dmesg from older and newer SDKs (on the same HW), found a system issue driving/disabling USB 5V.

    The VBUS_ERRORs are happening on both versions, and are the root cause of the issue. ...The difference with the new kernel and driver is that it [times out] after three retires trying to bring up the power, where the old driver tries forever. After it [times out] , USB will not come up even if the external 5V enable is turned on.

    So in summary a good amount of SW driver influence on USB OTG (not just HW)