Subject: USB hangs on AU1100

From: Rodolfo Giometti <[email-masked]>
Date: Thu, 5 May 2005 17:54:35 +0200

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

-- 

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

---

From: Pete Popov <[email-masked]>
Date: Thu, 05 May 2005 09:42:41 -0700

> 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

---

From: Thiemo Seufer <[email-masked]>
Date: Thu, 5 May 2005 19:20:17 +0200

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

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

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Thu, 5 May 2005 18:51:38 +0100 (BST)

> sequence point, which means the compiler is free to change the execution

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

  Maciej

---

From: Ulrich Teichert <[email-masked]>
Date: Thu, 5 May 2005 19:56:04 +0200 (MEST)

Hi,

[del]
>sequence point, which means the compiler is free to change the execution

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

HTH,
Uli
-- 
Dipl. Inf. Ulrich Teichert|e-mail: [email-masked]
Stormweg 24               |listening to: Suicide Drive (The Deep Eynde)
24539 Neumuenster, Germany|Public Pervert (Interpol) Cauchemar (Opération S)

---

From: Pete Popov <[email-masked]>
Date: Thu, 05 May 2005 11:50:14 -0700

On Thu, 2005-05-05 at 18:51 +0100, Maciej W. Rozycki wrote:
> > > It sounds like this is a custom Au1100 based board? What 
> oot code are

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

Pete

---

From: Thiemo Seufer <[email-masked]>
Date: Thu, 5 May 2005 21:18:56 +0200

> execution without reordering for the comma operator.

You are right, apparently I remembered incorrectly.

Thiemo

---

From: Rodolfo Giometti <[email-masked]>
Date: Fri, 6 May 2005 11:18:45 +0200

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

Yes, but is very close to the DB1100.

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

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

-- 

GNU/Linux Solutions                  e-mail:    [email-masked]
Linux Device Driver                             [email-masked]
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
diff -u -r1.5 ohci-au1xxx.c
--- ohci-au1xxx.c	3 Apr 2005 20:39:19 -0000	1.5
+++ ohci-au1xxx.c	6 May 2005 09:14:35 -0000
@@ -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);

---

From: Rodolfo Giometti <[email-masked]>
Date: Fri, 6 May 2005 16:27:19 +0200

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

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

--

---

From: Dan Malek <[email-masked]>
Date: Fri, 6 May 2005 10:54:36 -0400

On May 6, 2005, at 10:27 AM, Rodolfo Giometti wrote:

> 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

---

From: Pete Popov <[email-masked]>
Date: Fri, 06 May 2005 08:51:45 -0700

> don't worry about clock initialization...

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

Pete