Skip to contentSkip to conversation

USB hangs on AU1100

DISCUSSION Rodolfo Giometti 6 participants 11 messages May 5, 2005 – May 6, 2005 MIPS

lore
Share & tools
lore
#0 lore raw

Hello,

I'm just using USB host support on a AU1100 developing board (DB1100 configuration) and i notice that CPU locks in function au1xxx_start_hc():

        /* wait for reset complete (read register twice; see au1500 errata) */
        while (au_readl(USB_HOST_CONFIG),
                !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD))
                udelay(1000);

while waiting for USB controller to reset. I checked it out and I discovered that register USB_HOST_CONFIG is fixed at value 0xe! So the controller never reset...

Linux is 2.6.12-rc3 from CVS.

Someone knows whats wrong?

Thanks in advance,

Rodolfo Giometti

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     home page: giometti.enneenne.com
UNIX programming                     phone:     +39 349 2432127
#1 lore raw
Quoted 11 lines · Rodolfo Giometti

Hello,

I'm just using USB host support on a AU1100 developing board (DB1100 configuration) and i notice that CPU locks in function au1xxx_start_hc():

        /* wait for reset complete (read register twice; see au1500 errata) */
        while (au_readl(USB_HOST_CONFIG),
                !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD))
                udelay(1000);
Quoted 7 lines

while waiting for USB controller to reset. I checked it out and I discovered that register USB_HOST_CONFIG is fixed at value 0xe! So the controller never reset...

Linux is 2.6.12-rc3 from CVS.

Someone knows whats wrong?

It sounds like this is a custom Au1100 based board? What boot code are you running? I'm guessing the SOC isn't setup correctly or you have a HW problem.

Pete

#2 lore raw
Quoted 16 lines · Pete Popov
Quoted 15 lines · Rodolfo Giometti

Hello,

I'm just using USB host support on a AU1100 developing board (DB1100 configuration) and i notice that CPU locks in function au1xxx_start_hc():

        /* wait for reset complete (read register twice; see au1500 errata) */
        while (au_readl(USB_HOST_CONFIG),
                !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD))
                udelay(1000);

while waiting for USB controller to reset. I checked it out and I discovered that register USB_HOST_CONFIG is fixed at value 0xe! So the controller never reset...

Quoted 7 lines
Quoted 3 lines

Linux is 2.6.12-rc3 from CVS.

Someone knows whats wrong?

It sounds like this is a custom Au1100 based board? What boot code are you running? I'm guessing the SOC isn't setup correctly or you have a HW problem.

I wonder if the code works reliable. At least, a comma operator isn't a sequence point, which means the compiler is free to change the execution order.

Thiemo

#3 lore raw
Quoted 17 lines · Thiemo Seufer
Quoted 17 lines
Quoted 16 lines

I'm just using USB host support on a AU1100 developing board (DB1100 configuration) and i notice that CPU locks in function au1xxx_start_hc():

        /* wait for reset complete (read register twice; see au1500 errata) */
        while (au_readl(USB_HOST_CONFIG),
                !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD))
                udelay(1000);

while waiting for USB controller to reset. I checked it out and I discovered that register USB_HOST_CONFIG is fixed at value 0xe! So the controller never reset...

Linux is 2.6.12-rc3 from CVS.

Someone knows whats wrong?

Quoted 7 lines
Quoted 3 lines

It sounds like this is a custom Au1100 based board? What boot code are you running? I'm guessing the SOC isn't setup correctly or you have a HW problem.

I wonder if the code works reliable. At least, a comma operator isn't a sequence point, which means the compiler is free to change the execution order.

Good point -- even though the code is valid C, it's complete rubbish.
I'd suggest rewriting it to get something readable first.

Maciej

#4 lore raw
Quoted 24 lines · Maciej W. Rozycki
Quoted 13 lines · Thiemo Seufer
Quoted 13 lines
Quoted 13 lines

I'm just using USB host support on a AU1100 developing board (DB1100 configuration) and i notice that CPU locks in function au1xxx_start_hc():

        /* wait for reset complete (read register twice; see au1500 errata) */
        while (au_readl(USB_HOST_CONFIG),
                !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD))
                udelay(1000);

while waiting for USB controller to reset. I checked it out and I discovered that register USB_HOST_CONFIG is fixed at value 0xe! So the controller never reset...

Quoted 5 lines
Quoted 5 lines
Quoted 3 lines

Linux is 2.6.12-rc3 from CVS.

Someone knows whats wrong?

It sounds like this is a custom Au1100 based board? What

oot code are

Quoted 3 lines
Quoted 2 lines

you running? I'm guessing the SOC isn't setup correctly or you have a HW problem.

Quoted 6 lines
Quoted 3 lines

I wonder if the code works reliable. At least, a comma operator isn't a sequence point, which means the compiler is free to change the execution order.

Good point -- even though the code is valid C, it's complete rubbish.
I'd suggest rewriting it to get something readable first.

Interesting. I hadn't looked at this chunk of code before.

Pete

#5 lore raw
In reply to Thiemo Seufer

Hi,

[del]

Quoted 3 lines

I wonder if the code works reliable. At least, a comma operator isn't a sequence point, which means the compiler is free to change the execution order.

Not accordingly to the C standard, which notes strict left-to-right execution without reordering for the comma operator.

HTH,
Uli

Signature · 3 lines
Dipl. Inf. Ulrich Teichert|e-mail: [email protected]
Stormweg 24               |listening to: Suicide Drive (The Deep Eynde)
24539 Neumuenster, Germany|Public Pervert (Interpol) Cauchemar (Opération S)
#6 lore raw
Quoted 9 lines · Ulrich Teichert

Hi,

[del]

Quoted 3 lines

I wonder if the code works reliable. At least, a comma operator isn't a sequence point, which means the compiler is free to change the execution order.

Not accordingly to the C standard, which notes strict left-to-right execution without reordering for the comma operator.

You are right, apparently I remembered incorrectly.

Thiemo

#7 lore raw
In reply to Pete Popov
Quoted 1 line · Pete Popov

It sounds like this is a custom Au1100 based board? What boot code are

Yes, but is very close to the DB1100.

Quoted 2 lines

you running? I'm guessing the SOC isn't setup correctly or you have a HW problem.

I selected the code for the DB1100... I'm very puzzled about this problem!

However let me suggest you this little patch in order to advice the user about this problem and to avoid system locks.

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     home page: giometti.enneenne.com
UNIX programming                     phone:     +39 349 2432127

Index: ohci-au1xxx.c
===================================================================
RCS file: /home/cvs/linux/drivers/usb/host/ohci-au1xxx.c,v retrieving revision 1.5

ohci-au1xxx.c +18 -3
diff -u -r1.5 ohci-au1xxx.c
@@ -38,8 +38,10 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void au1xxx_start_hc(struct platform_device *dev)
+static int au1xxx_start_hc(struct platform_device *dev)
 {
+	int count = 3000;
+
 	printk(KERN_DEBUG __FILE__
 		": starting Au1xxx OHCI USB Controller\n");
 
@@ -51,11 +53,19 @@
 
 	/* wait for reset complete (read register twice; see au1500 errata) */
 	while (au_readl(USB_HOST_CONFIG),
-		!(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD)) 
+		!(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD)) {
 		udelay(1000);
+		if (--count == 0) {
+			printk(KERN_ERR __FILE__
+			": unable to reset USB host\n");
+			return -EBUSY;
+		}
+	}
 
 	printk(KERN_DEBUG __FILE__
 	": Clock to USB host has been enabled \n");
+
+	return 0;
 }
 
 static void au1xxx_stop_hc(struct platform_device *dev)
@@ -113,7 +123,11 @@
 		goto err2;
 	}
 
-	au1xxx_start_hc(dev);
+	retval = au1xxx_start_hc(dev);
+	if (retval < 0) {
+		pr_debug("au1xxx start failed");
+		goto err3;
+	}
 	ohci_hcd_init(hcd_to_ohci(hcd));
 
 	retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
@@ -121,6 +135,7 @@
 		return retval;
 
 	au1xxx_stop_hc(dev);
+ err3:
 	iounmap(hcd->regs);
  err2:
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
#8 lore raw
In reply to Pete Popov
Quoted 3 lines · Pete Popov

It sounds like this is a custom Au1100 based board? What boot code are you running? I'm guessing the SOC isn't setup correctly or you have a HW problem.

Yes, you was right, I missing to setup USB clock... I just added this code to the board init function (board_setup() function) and now USB works:

    #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_AU1X00_USB_DEVICE)
	    /* zero and disable FREQ2 */
	    sys_freqctrl = au_readl(SYS_FREQCTRL0);
	    sys_freqctrl &= ~0xFFF00000;
	    au_writel(sys_freqctrl, SYS_FREQCTRL0);
    
	    /* zero and disable USBH/USBD/IrDA clock */
	    sys_clksrc = au_readl(SYS_CLKSRC);
	    sys_clksrc &= ~0x0000001F;
	    au_writel(sys_clksrc, SYS_CLKSRC);
    
	    sys_freqctrl = au_readl(SYS_FREQCTRL0);
	    sys_freqctrl &= ~0xFFF00000;
    
	    sys_clksrc = au_readl(SYS_CLKSRC);
	    sys_clksrc &= ~0x0000001F;
    
	    /* FREQ2 = aux/2 = 48 MHz */
	    sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
	    au_writel(sys_freqctrl, SYS_FREQCTRL0);
    
	    /* Route 48MHz FREQ2 into USBH/USBD/IrDA */
	    sys_clksrc |= ((4<<2) | (0<<1) | 0 );
	    au_writel(sys_clksrc, SYS_CLKSRC);
    
	    /* setup the static bus controller */
	    au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
	    au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
	    au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
    
	    /* Get USB Functionality pin state (device vs host drive pins) */
	    pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
    #ifndef CONFIG_AU1X00_USB_DEVICE
	    /* 2nd USB port is USB host */
	    pin_func |= 0x8000;
    #endif
	    au_writel(pin_func, SYS_PINFUNC);
    #endif /* defined (CONFIG_USB_OHCI_HCD) || defined (CONFIG_AU1X00_USB_DEVICE) */

But don't you think is better to put this code into USB driver (file ohci-au1xxx.c) during probing stage? In this manner each platforms may don't worry about clock initialization...

Ciao,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     home page: giometti.enneenne.com
UNIX programming                     phone:     +39 349 2432127
#9 lore raw
Quoted 1 line · Rodolfo Giometti

Yes, you was right, I missing to setup USB clock...

The other thing you have to always remember when comparing operation to "... a board just like the Db1xxx ... " is that yamon does lots and lots of set up for the board that Linux assumes will be done. We've discussed this in the past, I just wanted to mention it again so it isn't forgotten. ;-)

Thanks.

	-- Dan
#10 lore raw
In reply to Rodolfo Giometti
Quoted 48 lines · Rodolfo Giometti
Quoted 3 lines · Pete Popov

It sounds like this is a custom Au1100 based board? What boot code are you running? I'm guessing the SOC isn't setup correctly or you have a HW problem.

Yes, you was right, I missing to setup USB clock... I just added this code to the board init function (board_setup() function) and now USB works:

    #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_AU1X00_USB_DEVICE)
	    /* zero and disable FREQ2 */
	    sys_freqctrl = au_readl(SYS_FREQCTRL0);
	    sys_freqctrl &= ~0xFFF00000;
	    au_writel(sys_freqctrl, SYS_FREQCTRL0);
    
	    /* zero and disable USBH/USBD/IrDA clock */
	    sys_clksrc = au_readl(SYS_CLKSRC);
	    sys_clksrc &= ~0x0000001F;
	    au_writel(sys_clksrc, SYS_CLKSRC);
    
	    sys_freqctrl = au_readl(SYS_FREQCTRL0);
	    sys_freqctrl &= ~0xFFF00000;
    
	    sys_clksrc = au_readl(SYS_CLKSRC);
	    sys_clksrc &= ~0x0000001F;
    
	    /* FREQ2 = aux/2 = 48 MHz */
	    sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
	    au_writel(sys_freqctrl, SYS_FREQCTRL0);
    
	    /* Route 48MHz FREQ2 into USBH/USBD/IrDA */
	    sys_clksrc |= ((4<<2) | (0<<1) | 0 );
	    au_writel(sys_clksrc, SYS_CLKSRC);
    
	    /* setup the static bus controller */
	    au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
	    au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
	    au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
    
	    /* Get USB Functionality pin state (device vs host drive pins) */
	    pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
    #ifndef CONFIG_AU1X00_USB_DEVICE
	    /* 2nd USB port is USB host */
	    pin_func |= 0x8000;
    #endif
	    au_writel(pin_func, SYS_PINFUNC);
    #endif /* defined (CONFIG_USB_OHCI_HCD) || defined (CONFIG_AU1X00_USB_DEVICE) */
Quoted 3 lines

But don't you think is better to put this code into USB driver (file ohci-au1xxx.c) during probing stage? In this manner each platforms may don't worry about clock initialization...

Seems too board specific since the clocks can be routed differently on each board.

Pete