diff -Nur linux-2.6.36.orig/arch/cris/Kconfig linux-2.6.36/arch/cris/Kconfig
--- linux-2.6.36.orig/arch/cris/Kconfig	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/arch/cris/Kconfig	2010-11-15 17:57:17.000000000 +0100
@@ -177,6 +177,12 @@
 	help
 	  Size of DRAM (decimal in MB) typically 2, 8 or 16.
 
+config ETRAX_MTD_SIZE
+	hex "MTD size (hex)"
+	default "0x00800000"
+	help
+	  Size of MTD device typically 4 or 8 MB.
+
 config ETRAX_VMEM_SIZE
        int "Video memory size (dec, in MB)"
        depends on ETRAX_ARCH_V32 && !ETRAXFS
@@ -282,7 +288,7 @@
 	select MTD_CFI_AMDSTD
 	select MTD_JEDECPROBE if ETRAX_ARCH_V32
 	select MTD_CHAR
-	select MTD_BLOCK
+	select MTD_BLOCK_RO
 	select MTD_PARTITIONS
 	select MTD_CONCAT
 	select MTD_COMPLEX_MAPPINGS
@@ -671,6 +677,11 @@
 
 source "drivers/ide/Kconfig"
 
+#mysteriously part of this standard linux driver was removed from cris build! - info@crisos.org  
+source "drivers/scsi/Kconfig"
+
+source "drivers/media/Kconfig"
+
 source "drivers/net/Kconfig"
 
 source "drivers/i2c/Kconfig"
diff -Nur linux-2.6.36.orig/arch/cris/Makefile linux-2.6.36/arch/cris/Makefile
--- linux-2.6.36.orig/arch/cris/Makefile	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/arch/cris/Makefile	2010-11-15 17:57:17.000000000 +0100
@@ -40,10 +40,10 @@
 
 LD = $(CROSS_COMPILE)ld -mcrislinux
 
-OBJCOPYFLAGS := -O binary -R .note -R .comment -S
+OBJCOPYFLAGS := -O binary -R .bss -R .note -R .note.gnu.build-id -R .comment -S
 
 KBUILD_AFLAGS += -mlinux -march=$(arch-y) $(inc)
-KBUILD_CFLAGS += -mlinux -march=$(arch-y) -pipe $(inc)
+KBUILD_CFLAGS += -mlinux -march=$(arch-y) -pipe -fno-peephole2 $(inc)
 KBUILD_CPPFLAGS += $(inc)
 
 ifdef CONFIG_FRAME_POINTER
diff -Nur linux-2.6.36.orig/arch/cris/arch-v10/drivers/axisflashmap.c linux-2.6.36/arch/cris/arch-v10/drivers/axisflashmap.c
--- linux-2.6.36.orig/arch/cris/arch-v10/drivers/axisflashmap.c	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/arch/cris/arch-v10/drivers/axisflashmap.c	2010-11-15 17:57:17.000000000 +0100
@@ -113,7 +113,7 @@
 
 /* If no partition-table was found, we use this default-set. */
 #define MAX_PARTITIONS         7
-#define NUM_DEFAULT_PARTITIONS 3
+#define NUM_DEFAULT_PARTITIONS 4
 
 /*
  * Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the
@@ -122,19 +122,24 @@
  */
 static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
 	{
-		.name = "boot firmware",
-		.size = CONFIG_ETRAX_PTABLE_SECTOR,
+		.name = "kernel",
+		.size = 0x00,
 		.offset = 0
 	},
 	{
-		.name = "kernel",
-		.size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR),
-		.offset = CONFIG_ETRAX_PTABLE_SECTOR
+		.name = "rootfs",
+		.size = 0x200000 ,
+		.offset = 0x200000
 	},
 	{
-		.name = "filesystem",
-		.size = 5 * CONFIG_ETRAX_PTABLE_SECTOR,
-		.offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR)
+		.name = "cfgfs",
+		.size = 0x20000 ,
+		.offset = CONFIG_ETRAX_MTD_SIZE - 0x20000
+	},
+	{
+		.name = "linux",
+		.size = CONFIG_ETRAX_MTD_SIZE - 0x20000,
+		.offset = 0
 	}
 };
 
@@ -281,6 +286,11 @@
 	struct partitiontable_entry *ptable;
 	int use_default_ptable = 1; /* Until proven otherwise. */
 	const char pmsg[] = "  /dev/flash%d at 0x%08x, size 0x%08x\n";
+	unsigned int kernel_part_size = 0;
+	unsigned char *flash_mem = (unsigned char*)(FLASH_CACHED_ADDR);
+	unsigned int flash_scan_count = 0;
+	const char *part_magic = "ACME_PART_MAGIC";
+	unsigned int magic_len = strlen(part_magic);
 
 	if (!(mymtd = flash_probe())) {
 		/* There's no reason to use this module if no flash chip can
@@ -292,6 +302,31 @@
 		       mymtd->name, mymtd->size);
 		axisflash_mtd = mymtd;
 	}
+	/* scan flash to findout where out partition starts */
+
+	printk(KERN_INFO "Scanning flash for end of kernel magic\n");
+	for(flash_scan_count = 0; flash_scan_count < 100000; flash_scan_count++){
+		if(strncmp(&flash_mem[flash_scan_count], part_magic, magic_len - 1) == 0)
+		{
+			kernel_part_size = flash_mem[flash_scan_count + magic_len ];
+			kernel_part_size <<= 8;
+			kernel_part_size += flash_mem[flash_scan_count + magic_len + 2];
+			kernel_part_size <<= 8;
+			kernel_part_size += flash_mem[flash_scan_count + magic_len + 1];
+			kernel_part_size <<= 8;
+			kernel_part_size += flash_mem[flash_scan_count + magic_len + 3];
+			printk(KERN_INFO "Kernel ends at 0x%.08X\n", kernel_part_size);
+			flash_scan_count = 1100000;
+		}
+	}
+
+
+	if(kernel_part_size){
+		kernel_part_size = (kernel_part_size & 0xffff0000);
+		axis_default_partitions[0].size = kernel_part_size;
+		axis_default_partitions[1].size =  mymtd->size - axis_default_partitions[0].size - axis_default_partitions[2].size;
+		axis_default_partitions[1].offset = axis_default_partitions[0].size;
+	}
 
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
@@ -360,21 +395,6 @@
 		use_default_ptable = !ptable_ok;
 	}
 
-	if (romfs_in_flash) {
-		/* Add an overlapping device for the root partition (romfs). */
-
-		axis_partitions[pidx].name = "romfs";
-		axis_partitions[pidx].size = romfs_length;
-		axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR;
-		axis_partitions[pidx].mask_flags |= MTD_WRITEABLE;
-
-		printk(KERN_INFO
-                       " Adding readonly flash partition for romfs image:\n");
-		printk(pmsg, pidx, axis_partitions[pidx].offset,
-		       axis_partitions[pidx].size);
-		pidx++;
-	}
-
 #ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE
 	if (mymtd) {
 		main_partition.size = mymtd->size;
@@ -397,36 +417,6 @@
 		if (err)
 			panic("axisflashmap could not add MTD partitions!\n");
 	}
-
-	if (!romfs_in_flash) {
-		/* Create an RAM device for the root partition (romfs). */
-
-#if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0)
-		/* No use trying to boot this kernel from RAM. Panic! */
-		printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM "
-		       "device due to kernel (mis)configuration!\n");
-		panic("This kernel cannot boot from RAM!\n");
-#else
-		struct mtd_info *mtd_ram;
-
-		mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
-		if (!mtd_ram)
-			panic("axisflashmap couldn't allocate memory for "
-			      "mtd_info!\n");
-
-		printk(KERN_INFO " Adding RAM partition for romfs image:\n");
-		printk(pmsg, pidx, (unsigned)romfs_start,
-			(unsigned)romfs_length);
-
-		err = mtdram_init_device(mtd_ram,
-			(void *)romfs_start,
-			romfs_length,
-			"romfs");
-		if (err)
-			panic("axisflashmap could not initialize MTD RAM "
-			      "device!\n");
-#endif
-	}
 	return err;
 }
 
diff -Nur linux-2.6.36.orig/arch/cris/arch-v10/drivers/ds1302.c linux-2.6.36/arch/cris/arch-v10/drivers/ds1302.c
--- linux-2.6.36.orig/arch/cris/arch-v10/drivers/ds1302.c	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/arch/cris/arch-v10/drivers/ds1302.c	2010-11-15 17:57:17.000000000 +0100
@@ -22,6 +22,7 @@
 #include <linux/smp_lock.h>
 #include <linux/bcd.h>
 #include <linux/capability.h>
+#include <linux/device.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -499,6 +500,10 @@
 	return 0;
 }
 
+#ifdef CONFIG_SYSFS
+static struct class *rtc_class;
+#endif
+
 static int __init ds1302_register(void)
 {
 	ds1302_init();
@@ -507,6 +512,12 @@
 		       ds1302_name, RTC_MAJOR_NR);
 		return -1;
 	}
+	#ifdef CONFIG_SYSFS
+	rtc_class = class_create(THIS_MODULE, "rtc");
+	class_device_create(rtc_class, NULL, MKDEV(RTC_MAJOR_NR, 0),
+		NULL, "rtc");
+	#endif
+
         return 0;
 
 }
diff -Nur linux-2.6.36.orig/arch/cris/arch-v10/drivers/gpio.c linux-2.6.36/arch/cris/arch-v10/drivers/gpio.c
--- linux-2.6.36.orig/arch/cris/arch-v10/drivers/gpio.c	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/arch/cris/arch-v10/drivers/gpio.c	2010-11-15 17:57:17.000000000 +0100
@@ -20,6 +20,7 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
 
 #include <asm/etraxgpio.h>
 #include <arch/svinto.h>
@@ -797,6 +798,10 @@
 
 /* main driver initialization routine, called from mem.c */
 
+#ifdef CONFIG_SYSFS
+static struct class *gpio_class;
+#endif
+
 static int __init gpio_init(void)
 {
 	int res;
@@ -810,6 +815,13 @@
 		return res;
 	}
 
+#ifdef CONFIG_SYSFS
+	gpio_class = class_create(THIS_MODULE, "gpio");
+	device_create(gpio_class, NULL, MKDEV(GPIO_MAJOR, 0), NULL, "gpioa");
+	device_create(gpio_class, NULL, MKDEV(GPIO_MAJOR, 1), NULL, "gpiob");
+	device_create(gpio_class, NULL, MKDEV(GPIO_MAJOR, 2), NULL, "leds");
+	device_create(gpio_class, NULL, MKDEV(GPIO_MAJOR, 3), NULL, "gpiog");
+#endif
 	/* Clear all leds */
 #if defined (CONFIG_ETRAX_CSP0_LEDS) ||  defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
 	CRIS_LED_NETWORK_SET(0);
diff -Nur linux-2.6.36.orig/arch/cris/arch-v10/lib/hw_settings.S linux-2.6.36/arch/cris/arch-v10/lib/hw_settings.S
--- linux-2.6.36.orig/arch/cris/arch-v10/lib/hw_settings.S	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/arch/cris/arch-v10/lib/hw_settings.S	2010-11-15 17:57:17.000000000 +0100
@@ -58,3 +58,5 @@
 	.dword R_PORT_PB_SET
 	.dword PB_SET_VALUE
 	.dword 0 ; No more register values
+	.ascii "ACME_PART_MAGIC" 
+	.dword 0xdeadc0de
diff -Nur linux-2.6.36.orig/arch/cris/arch-v10/mm/init.c linux-2.6.36/arch/cris/arch-v10/mm/init.c
--- linux-2.6.36.orig/arch/cris/arch-v10/mm/init.c	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/arch/cris/arch-v10/mm/init.c	2010-11-15 17:57:17.000000000 +0100
@@ -184,6 +184,9 @@
 
 	free_area_init_node(0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
 }
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+}
 
 /* Initialize remaps of some I/O-ports. It is important that this
  * is called before any driver is initialized.
diff -Nur linux-2.6.36.orig/arch/cris/boot/Makefile linux-2.6.36/arch/cris/boot/Makefile
--- linux-2.6.36.orig/arch/cris/boot/Makefile	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/arch/cris/boot/Makefile	2010-11-15 17:57:17.000000000 +0100
@@ -5,7 +5,7 @@
 objcopyflags-$(CONFIG_ETRAX_ARCH_V10) += -R .note -R .comment
 objcopyflags-$(CONFIG_ETRAX_ARCH_V32) += --remove-section=.bss --remove-section=.note.gnu.build-id
 
-OBJCOPYFLAGS = -O binary $(objcopyflags-y)
+#OBJCOPYFLAGS = -O binary $(objcopyflags-y)
 
 
 subdir- := compressed rescue
@@ -17,7 +17,6 @@
 
 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
-	$(Q)$(MAKE) $(build)=$(obj)/rescue $(obj)/rescue/rescue.bin
 
 $(obj)/zImage:  $(obj)/compressed/vmlinux
 	@cp $< $@
diff -Nur linux-2.6.36.orig/arch/cris/boot/compressed/Makefile linux-2.6.36/arch/cris/boot/compressed/Makefile
--- linux-2.6.36.orig/arch/cris/boot/compressed/Makefile	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/arch/cris/boot/compressed/Makefile	2010-11-15 17:57:17.000000000 +0100
@@ -18,7 +18,7 @@
 OBJECTS-$(CONFIG_ETRAX_ARCH_V32) = $(obj)/head_v32.o
 OBJECTS-$(CONFIG_ETRAX_ARCH_V10) = $(obj)/head_v10.o
 OBJECTS= $(OBJECTS-y) $(obj)/misc.o
-OBJCOPYFLAGS = -O binary --remove-section=.bss
+#OBJCOPYFLAGS = -O binary --remove-section=.bss
 
 quiet_cmd_image = BUILD   $@
 cmd_image = cat $(obj)/decompress.bin $(obj)/piggy.gz > $@
diff -Nur linux-2.6.36.orig/drivers/net/cris/eth_v10.c linux-2.6.36/drivers/net/cris/eth_v10.c
--- linux-2.6.36.orig/drivers/net/cris/eth_v10.c	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/drivers/net/cris/eth_v10.c	2010-11-15 17:57:17.000000000 +0100
@@ -1718,7 +1718,7 @@
 static void
 e100_netpoll(struct net_device* netdev)
 {
-	e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL);
+	e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev);
 }
 #endif
 
diff -Nur linux-2.6.36.orig/drivers/serial/crisv10.c linux-2.6.36/drivers/serial/crisv10.c
--- linux-2.6.36.orig/drivers/serial/crisv10.c	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/drivers/serial/crisv10.c	2010-11-15 17:57:17.000000000 +0100
@@ -13,6 +13,7 @@
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h> 
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
@@ -27,6 +28,7 @@
 #include <linux/kernel.h>
 #include <linux/mutex.h>
 #include <linux/bitops.h>
+#include <linux/device.h>
 #include <linux/seq_file.h>
 #include <linux/delay.h>
 #include <linux/module.h>
@@ -4426,6 +4428,7 @@
 #endif
 };
 
+static struct class *rs_class;
 static int __init rs_init(void)
 {
 	int i;
@@ -4559,6 +4562,24 @@
 #endif
 #endif /* CONFIG_SVINTO_SIM */
 
+	rs_class = class_create(THIS_MODULE, "rs_tty");
+#ifdef CONFIG_ETRAX_SERIAL_PORT0 
+	device_create(rs_class, NULL,
+		MKDEV(TTY_MAJOR, 64), NULL, "ttyS0");
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT1 
+	device_create(rs_class, NULL,
+		MKDEV(TTY_MAJOR, 65), NULL, "ttyS1");
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT2 
+	device_create(rs_class, NULL,
+		MKDEV(TTY_MAJOR, 66), NULL, "ttyS2");
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT3 
+	device_create(rs_class, NULL,
+		MKDEV(TTY_MAJOR, 67), NULL, "ttyS3");
+#endif
+
 	return 0;
 }
 
diff -Nur linux-2.6.36.orig/drivers/usb/Makefile linux-2.6.36/drivers/usb/Makefile
--- linux-2.6.36.orig/drivers/usb/Makefile	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/drivers/usb/Makefile	2010-11-15 17:57:18.000000000 +0100
@@ -21,6 +21,7 @@
 obj-$(CONFIG_USB_R8A66597_HCD)	+= host/
 obj-$(CONFIG_USB_HWA_HCD)	+= host/
 obj-$(CONFIG_USB_ISP1760_HCD)	+= host/
+obj-$(CONFIG_ETRAX_USB_HOST)	+= host/
 obj-$(CONFIG_USB_IMX21_HCD)	+= host/
 
 obj-$(CONFIG_USB_C67X00_HCD)	+= c67x00/
diff -Nur linux-2.6.36.orig/drivers/usb/host/Makefile linux-2.6.36/drivers/usb/host/Makefile
--- linux-2.6.36.orig/drivers/usb/host/Makefile	2010-10-20 22:30:22.000000000 +0200
+++ linux-2.6.36/drivers/usb/host/Makefile	2010-11-15 17:57:18.000000000 +0100
@@ -32,5 +32,6 @@
 obj-$(CONFIG_USB_R8A66597_HCD)	+= r8a66597-hcd.o
 obj-$(CONFIG_USB_ISP1760_HCD)	+= isp1760.o
 obj-$(CONFIG_USB_HWA_HCD)	+= hwa-hc.o
+obj-$(CONFIG_ETRAX_USB_HOST)	+= hc-crisv10.o
 obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd.o
 
diff -Nur linux-2.6.36.orig/drivers/usb/host/hc-cris-dbg.h linux-2.6.36/drivers/usb/host/hc-cris-dbg.h
--- linux-2.6.36.orig/drivers/usb/host/hc-cris-dbg.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.36/drivers/usb/host/hc-cris-dbg.h	2010-11-15 17:57:17.000000000 +0100
@@ -0,0 +1,146 @@
+
+/* macros for debug output */
+
+#define warn(fmt, args...) \
+        printk(KERN_INFO "crisv10 warn: ");printk(fmt, ## args)
+
+#define hcd_dbg(hcd, fmt, args...) \
+	dev_info(hcd->self.controller, fmt, ## args)
+#define hcd_err(hcd, fmt, args...) \
+	dev_err(hcd->self.controller, fmt, ## args)
+#define hcd_info(hcd, fmt, args...) \
+	dev_info(hcd->self.controller, fmt, ## args)
+#define hcd_warn(hcd, fmt, args...) \
+	dev_warn(hcd->self.controller, fmt, ## args)
+
+/*
+#define devdrv_dbg(fmt, args...) \
+        printk(KERN_INFO "usb_devdrv dbg: ");printk(fmt, ## args)
+*/
+#define devdrv_dbg(fmt, args...) {}
+
+#define devdrv_err(fmt, args...) \
+        printk(KERN_ERR "usb_devdrv error: ");printk(fmt, ## args)
+#define devdrv_info(fmt, args...) \
+        printk(KERN_INFO "usb_devdrv: ");printk(fmt, ## args)
+
+#define irq_dbg(fmt, args...) \
+        printk(KERN_INFO "crisv10_irq dbg: ");printk(fmt, ## args)
+#define irq_err(fmt, args...) \
+        printk(KERN_ERR "crisv10_irq error: ");printk(fmt, ## args)
+#define irq_warn(fmt, args...) \
+        printk(KERN_INFO "crisv10_irq warn: ");printk(fmt, ## args)
+#define irq_info(fmt, args...) \
+        printk(KERN_INFO "crisv10_hcd: ");printk(fmt, ## args)
+
+/*
+#define rh_dbg(fmt, args...) \
+  printk(KERN_DEBUG "crisv10_rh dbg: ");printk(fmt, ## args)
+*/
+#define rh_dbg(fmt, args...) {}
+
+#define rh_err(fmt, args...) \
+        printk(KERN_ERR "crisv10_rh error: ");printk(fmt, ## args)
+#define rh_warn(fmt, args...) \
+        printk(KERN_INFO "crisv10_rh warning: ");printk(fmt, ## args)
+#define rh_info(fmt, args...) \
+        printk(KERN_INFO "crisv10_rh: ");printk(fmt, ## args)
+
+/*
+#define tc_dbg(fmt, args...) \
+        printk(KERN_INFO "crisv10_tc dbg: ");printk(fmt, ## args)
+*/
+#define tc_dbg(fmt, args...) {while(0){}}
+
+#define tc_err(fmt, args...) \
+        printk(KERN_ERR "crisv10_tc error: ");printk(fmt, ## args)
+/*
+#define tc_warn(fmt, args...) \
+        printk(KERN_INFO "crisv10_tc warning: ");printk(fmt, ## args)
+*/
+#define tc_warn(fmt, args...) {while(0){}}
+
+#define tc_info(fmt, args...) \
+        printk(KERN_INFO "crisv10_tc: ");printk(fmt, ## args)
+
+
+/* Debug print-outs for various traffic types */
+
+#define intr_warn(fmt, args...) \
+        printk(KERN_INFO "crisv10_intr warning: ");printk(fmt, ## args)
+
+#define intr_dbg(fmt, args...) \
+        printk(KERN_DEBUG "crisv10_intr dbg: ");printk(fmt, ## args)
+/*
+#define intr_dbg(fmt, args...) {while(0){}}
+*/
+
+
+#define isoc_err(fmt, args...) \
+        printk(KERN_ERR "crisv10_isoc error: ");printk(fmt, ## args)
+/*
+#define isoc_warn(fmt, args...) \
+        printk(KERN_INFO "crisv10_isoc warning: ");printk(fmt, ## args)
+*/
+#define isoc_warn(fmt, args...) {while(0){}}
+
+/*
+#define isoc_dbg(fmt, args...) \
+        printk(KERN_INFO "crisv10_isoc dbg: ");printk(fmt, ## args)
+*/
+#define isoc_dbg(fmt, args...) {while(0){}}
+
+/*
+#define timer_warn(fmt, args...) \
+        printk(KERN_INFO "crisv10_timer warning: ");printk(fmt, ## args)
+*/
+#define timer_warn(fmt, args...) {while(0){}}
+
+/*
+#define timer_dbg(fmt, args...) \
+        printk(KERN_INFO "crisv10_timer dbg: ");printk(fmt, ## args)
+*/
+#define timer_dbg(fmt, args...) {while(0){}}
+
+
+/* Debug printouts for events related to late finishing of URBs */
+
+#define late_dbg(fmt, args...) \
+        printk(KERN_INFO "crisv10_late dbg: ");printk(fmt, ## args)
+/*
+#define late_dbg(fmt, args...) {while(0){}}
+*/
+
+#define late_warn(fmt, args...) \
+        printk(KERN_INFO "crisv10_late warning: ");printk(fmt, ## args)
+/*
+#define errno_dbg(fmt, args...) \
+        printk(KERN_INFO "crisv10_errno dbg: ");printk(fmt, ## args)
+*/
+#define errno_dbg(fmt, args...) {while(0){}}
+
+
+#define dma_dbg(fmt, args...) \
+        printk(KERN_INFO "crisv10_dma dbg: ");printk(fmt, ## args)
+#define dma_err(fmt, args...) \
+        printk(KERN_ERR "crisv10_dma error: ");printk(fmt, ## args)
+#define dma_warn(fmt, args...) \
+        printk(KERN_INFO "crisv10_dma warning: ");printk(fmt, ## args)
+#define dma_info(fmt, args...) \
+        printk(KERN_INFO "crisv10_dma: ");printk(fmt, ## args)
+
+
+
+#define str_dir(pipe) \
+	(usb_pipeout(pipe) ? "out" : "in")
+#define str_type(pipe) \
+	({								\
+		char *s = "?";						\
+		switch (usb_pipetype(pipe)) {				\
+		case PIPE_ISOCHRONOUS:	s = "iso";  break;		\
+		case PIPE_INTERRUPT:	s = "intr"; break;		\
+		case PIPE_CONTROL:	s = "ctrl"; break;		\
+		case PIPE_BULK:		s = "bulk"; break;		\
+		};							\
+		s;							\
+	})
diff -Nur linux-2.6.36.orig/drivers/usb/host/hc-crisv10.c linux-2.6.36/drivers/usb/host/hc-crisv10.c
--- linux-2.6.36.orig/drivers/usb/host/hc-crisv10.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.36/drivers/usb/host/hc-crisv10.c	2010-11-15 17:57:18.000000000 +0100
@@ -0,0 +1,4801 @@
+/*
+ *
+ * ETRAX 100LX USB Host Controller Driver
+ *
+ * Copyright (C) 2005, 2006  Axis Communications AB
+ *
+ * Author: Konrad Eriksson <konrad.eriksson@axis.se>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <linux/platform_device.h>
+#include <linux/usb/hcd.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <arch/dma.h>
+#include <arch/io_interface_mux.h>
+
+#include "hc-crisv10.h"
+#include "hc-cris-dbg.h"
+
+
+/***************************************************************************/
+/***************************************************************************/
+/* Host Controller settings                                                */
+/***************************************************************************/
+/***************************************************************************/
+
+#define VERSION			"1.00 hinko.4"
+#define COPYRIGHT		"(c) 2005, 2006 Axis Communications AB"
+#define DESCRIPTION     "ETRAX 100LX USB Host Controller"
+
+#define ETRAX_USB_HC_IRQ USB_HC_IRQ_NBR
+#define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR
+#define ETRAX_USB_TX_IRQ USB_DMA_TX_IRQ_NBR
+
+/* Number of physical ports in Etrax 100LX */
+#define USB_ROOT_HUB_PORTS 2
+
+const char hc_name[] = "hc-crisv10";
+const char product_desc[] = DESCRIPTION;
+
+/* The number of epids is, among other things, used for pre-allocating
+   ctrl, bulk and isoc EP descriptors (one for each epid).
+   Assumed to be > 1 when initiating the DMA lists. */
+#define NBR_OF_EPIDS       32
+
+/* Support interrupt traffic intervals up to 128 ms. */
+#define MAX_INTR_INTERVAL  128
+
+/* If periodic traffic (intr or isoc) is to be used, then one entry in the EP
+   table must be "invalid". By this we mean that we shouldn't care about epid
+   attentions for this epid, or at least handle them differently from epid
+   attentions for "valid" epids. This define determines which one to use
+   (don't change it). */
+#define INVALID_EPID       31
+/* A special epid for the bulk dummys. */
+#define DUMMY_EPID         30
+
+/* Module settings */
+
+MODULE_DESCRIPTION(DESCRIPTION);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Konrad Eriksson <konrad.eriksson@axis.se>");
+
+
+/* Module parameters */
+
+/* 0 = No ports enabled
+   1 = Only port 1 enabled (on board ethernet on devboard)
+   2 = Only port 2 enabled (external connector on devboard)
+   3 = Both ports enabled
+*/
+static unsigned int ports = 3;
+module_param(ports, uint, S_IRUGO);
+MODULE_PARM_DESC(ports, "Bitmask indicating USB ports to use");
+
+
+/***************************************************************************/
+/***************************************************************************/
+/* Shared global variables for this module                                 */
+/***************************************************************************/
+/***************************************************************************/
+
+/* EP descriptor lists for non period transfers. Must be 32-bit aligned. */
+static volatile struct USB_EP_Desc TxBulkEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));
+
+static volatile struct USB_EP_Desc TxCtrlEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));
+
+/* EP descriptor lists for period transfers. Must be 32-bit aligned. */
+static volatile struct USB_EP_Desc TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4)));
+static volatile struct USB_SB_Desc TxIntrSB_zout __attribute__ ((aligned (4)));
+
+static volatile struct USB_EP_Desc TxIsocEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));
+static volatile struct USB_SB_Desc TxIsocSB_zout __attribute__ ((aligned (4)));
+
+//static volatile struct USB_SB_Desc TxIsocSBList[NBR_OF_EPIDS] __attribute__ ((aligned (4))); 
+
+/* After each enabled bulk EP IN we put two disabled EP descriptors with the eol flag set,
+   causing the DMA to stop the DMA channel. The first of these two has the intr flag set, which
+   gives us a dma8_sub0_descr interrupt. When we receive this, we advance the DMA one step in the
+   EP list and then restart the bulk channel, thus forcing a switch between bulk EP descriptors
+   in each frame. */
+static volatile struct USB_EP_Desc TxBulkDummyEPList[NBR_OF_EPIDS][2] __attribute__ ((aligned (4)));
+
+/* List of URB pointers, where each points to the active URB for a epid.
+   For Bulk, Ctrl and Intr this means which URB that currently is added to
+   DMA lists (Isoc URBs are all directly added to DMA lists). As soon as
+   URB has completed is the queue examined and the first URB in queue is
+   removed and moved to the activeUrbList while its state change to STARTED and
+   its transfer(s) gets added to DMA list (exception Isoc where URBs enter
+   state STARTED directly and added transfers added to DMA lists). */
+static struct urb *activeUrbList[NBR_OF_EPIDS];
+
+/* Additional software state info for each epid */
+static struct etrax_epid epid_state[NBR_OF_EPIDS];
+
+/* Timer handles for bulk traffic timer used to avoid DMA bug where DMA stops
+   even if there is new data waiting to be processed */
+static struct timer_list bulk_start_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static struct timer_list bulk_eot_timer = TIMER_INITIALIZER(NULL, 0, 0);
+
+/* We want the start timer to expire before the eot timer, because the former
+   might start traffic, thus making it unnecessary for the latter to time
+   out. */
+#define BULK_START_TIMER_INTERVAL (HZ/50) /* 20 ms */
+#define BULK_EOT_TIMER_INTERVAL (HZ/16) /* 60 ms */
+
+/* Delay before a URB completion happen when it's scheduled to be delayed */
+#define LATER_TIMER_DELAY (HZ/50) /* 20 ms */
+
+/* Simplifying macros for checking software state info of a epid */
+/* ----------------------------------------------------------------------- */
+#define epid_inuse(epid)       epid_state[epid].inuse
+#define epid_out_traffic(epid) epid_state[epid].out_traffic
+#define epid_isoc(epid)   (epid_state[epid].type == PIPE_ISOCHRONOUS ? 1 : 0)
+#define epid_intr(epid)   (epid_state[epid].type == PIPE_INTERRUPT ? 1 : 0)
+
+
+/***************************************************************************/
+/***************************************************************************/
+/* DEBUG FUNCTIONS                                                         */
+/***************************************************************************/
+/***************************************************************************/
+/* Note that these functions are always available in their "__" variants,
+   for use in error situations. The "__" missing variants are controlled by
+   the USB_DEBUG_DESC/USB_DEBUG_URB macros. */
+static void __dump_urb(struct urb* purb)
+{
+  struct crisv10_urb_priv *urb_priv = purb->hcpriv;
+  int urb_num = -1;
+  if(urb_priv) {
+    urb_num = urb_priv->urb_num;
+  }
+  printk("\nURB:0x%x[%d]\n", (unsigned int)purb, urb_num);
+  printk("dev                   :0x%08lx\n", (unsigned long)purb->dev);
+  printk("pipe                  :0x%08x\n", purb->pipe);
+  printk("status                :%d\n", purb->status);
+  printk("transfer_flags        :0x%08x\n", purb->transfer_flags);
+  printk("transfer_buffer       :0x%08lx\n", (unsigned long)purb->transfer_buffer);
+  printk("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
+  printk("actual_length         :%d\n", purb->actual_length);
+  printk("setup_packet          :0x%08lx\n", (unsigned long)purb->setup_packet);
+  printk("start_frame           :%d\n", purb->start_frame);
+  printk("number_of_packets     :%d\n", purb->number_of_packets);
+  printk("interval              :%d\n", purb->interval);
+  printk("error_count           :%d\n", purb->error_count);
+  printk("context               :0x%08lx\n", (unsigned long)purb->context);
+  printk("complete              :0x%08lx\n\n", (unsigned long)purb->complete);
+}
+
+static void __dump_in_desc(volatile struct USB_IN_Desc *in)
+{
+  printk("\nUSB_IN_Desc at 0x%08lx\n", (unsigned long)in);
+  printk("  sw_len  : 0x%04x (%d)\n", in->sw_len, in->sw_len);
+  printk("  command : 0x%04x\n", in->command);
+  printk("  next    : 0x%08lx\n", in->next);
+  printk("  buf     : 0x%08lx\n", in->buf);
+  printk("  hw_len  : 0x%04x (%d)\n", in->hw_len, in->hw_len);
+  printk("  status  : 0x%04x\n\n", in->status);
+}
+
+static void __dump_sb_desc(volatile struct USB_SB_Desc *sb)
+{
+  char tt = (sb->command & 0x30) >> 4;
+  char *tt_string;
+
+  switch (tt) {
+  case 0:
+    tt_string = "zout";
+    break;
+  case 1:
+    tt_string = "in";
+    break;
+  case 2:
+    tt_string = "out";
+    break;
+  case 3:
+    tt_string = "setup";
+    break;
+  default:
+    tt_string = "unknown (weird)";
+  }
+
+  printk(" USB_SB_Desc at 0x%08lx ", (unsigned long)sb);
+  printk(" command:0x%04x (", sb->command);
+  printk("rem:%d ", (sb->command & 0x3f00) >> 8);
+  printk("full:%d ", (sb->command & 0x40) >> 6);
+  printk("tt:%d(%s) ", tt, tt_string);
+  printk("intr:%d ", (sb->command & 0x8) >> 3);
+  printk("eot:%d ", (sb->command & 0x2) >> 1);
+  printk("eol:%d)", sb->command & 0x1);
+  printk(" sw_len:0x%04x(%d)", sb->sw_len, sb->sw_len);
+  printk(" next:0x%08lx", sb->next);
+  printk(" buf:0x%08lx\n", sb->buf);
+}
+
+
+static void __dump_ep_desc(volatile struct USB_EP_Desc *ep)
+{
+  printk("USB_EP_Desc at 0x%08lx ", (unsigned long)ep);
+  printk(" command:0x%04x (", ep->command);
+  printk("ep_id:%d ", (ep->command & 0x1f00) >> 8);
+  printk("enable:%d ", (ep->command & 0x10) >> 4);
+  printk("intr:%d ", (ep->command & 0x8) >> 3);
+  printk("eof:%d ", (ep->command & 0x2) >> 1);
+  printk("eol:%d)", ep->command & 0x1);
+  printk(" hw_len:0x%04x(%d)", ep->hw_len, ep->hw_len);
+  printk(" next:0x%08lx", ep->next);
+  printk(" sub:0x%08lx\n", ep->sub);
+}
+
+static inline void __dump_ep_list(int pipe_type)
+{
+  volatile struct USB_EP_Desc *ep;
+  volatile struct USB_EP_Desc *first_ep;
+  volatile struct USB_SB_Desc *sb;
+
+  switch (pipe_type)
+    {
+    case PIPE_BULK:
+      first_ep = &TxBulkEPList[0];
+      break;
+    case PIPE_CONTROL:
+      first_ep = &TxCtrlEPList[0];
+      break;
+    case PIPE_INTERRUPT:
+      first_ep = &TxIntrEPList[0];
+      break;
+    case PIPE_ISOCHRONOUS:
+      first_ep = &TxIsocEPList[0];
+      break;
+    default:
+      warn("Cannot dump unknown traffic type");
+      return;
+    }
+  ep = first_ep;
+
+  printk("\n\nDumping EP list...\n\n");
+
+  do {
+    __dump_ep_desc(ep);
+    /* Cannot phys_to_virt on 0 as it turns into 80000000, which is != 0. */
+    sb = ep->sub ? phys_to_virt(ep->sub) : 0;
+    while (sb) {
+      __dump_sb_desc(sb);
+      sb = sb->next ? phys_to_virt(sb->next) : 0;
+    }
+    ep = (volatile struct USB_EP_Desc *)(phys_to_virt(ep->next));
+
+  } while (ep != first_ep);
+}
+
+static inline void __dump_ept_data(int epid)
+{
+  unsigned long flags;
+  __u32 r_usb_ept_data;
+
+  if (epid < 0 || epid > 31) {
+    printk("Cannot dump ept data for invalid epid %d\n", epid);
+    return;
+  }
+
+  local_irq_save(flags);
+  *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
+  nop();
+  r_usb_ept_data = *R_USB_EPT_DATA;
+  local_irq_restore(flags);
+
+  printk(" R_USB_EPT_DATA = 0x%x for epid %d :\n", r_usb_ept_data, epid);
+  if (r_usb_ept_data == 0) {
+    /* No need for more detailed printing. */
+    return;
+  }
+  printk("  valid           : %d\n", (r_usb_ept_data & 0x80000000) >> 31);
+  printk("  hold            : %d\n", (r_usb_ept_data & 0x40000000) >> 30);
+  printk("  error_count_in  : %d\n", (r_usb_ept_data & 0x30000000) >> 28);
+  printk("  t_in            : %d\n", (r_usb_ept_data & 0x08000000) >> 27);
+  printk("  low_speed       : %d\n", (r_usb_ept_data & 0x04000000) >> 26);
+  printk("  port            : %d\n", (r_usb_ept_data & 0x03000000) >> 24);
+  printk("  error_code      : %d\n", (r_usb_ept_data & 0x00c00000) >> 22);
+  printk("  t_out           : %d\n", (r_usb_ept_data & 0x00200000) >> 21);
+  printk("  error_count_out : %d\n", (r_usb_ept_data & 0x00180000) >> 19);
+  printk("  max_len         : %d\n", (r_usb_ept_data & 0x0003f800) >> 11);
+  printk("  ep              : %d\n", (r_usb_ept_data & 0x00000780) >> 7);
+  printk("  dev             : %d\n", (r_usb_ept_data & 0x0000003f));
+}
+
+static inline void __dump_ept_data_iso(int epid)
+{
+  unsigned long flags;
+  __u32 ept_data;
+
+  if (epid < 0 || epid > 31) {
+    printk("Cannot dump ept data for invalid epid %d\n", epid);
+    return;
+  }
+
+  local_irq_save(flags);
+  *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
+  nop();
+  ept_data = *R_USB_EPT_DATA_ISO;
+  local_irq_restore(flags);
+
+  printk(" R_USB_EPT_DATA = 0x%x for epid %d :\n", ept_data, epid);
+  if (ept_data == 0) {
+    /* No need for more detailed printing. */
+    return;
+  }
+  printk("  valid           : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, valid,
+						ept_data));
+  printk("  port            : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, port,
+						ept_data));
+  printk("  error_code      : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code,
+						ept_data));
+  printk("  max_len         : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, max_len,
+						ept_data));
+  printk("  ep              : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, ep,
+						ept_data));
+  printk("  dev             : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, dev,
+						ept_data));
+}
+
+static inline void __dump_ept_data_list(void)
+{
+  int i;
+
+  printk("Dumping the whole R_USB_EPT_DATA list\n");
+
+  for (i = 0; i < 32; i++) {
+    __dump_ept_data(i);
+  }
+}
+
+static void debug_epid(int epid) {
+  int i;
+  
+  if(epid_isoc(epid)) {
+    __dump_ept_data_iso(epid);
+  } else {
+    __dump_ept_data(epid);
+  }
+
+  printk("Bulk:\n");
+  for(i = 0; i < 32; i++) {
+    if(IO_EXTRACT(USB_EP_command, epid, TxBulkEPList[i].command) ==
+       epid) {
+      printk("%d: ", i); __dump_ep_desc(&(TxBulkEPList[i]));
+    }
+  }
+
+  printk("Ctrl:\n");
+  for(i = 0; i < 32; i++) {
+    if(IO_EXTRACT(USB_EP_command, epid, TxCtrlEPList[i].command) ==
+       epid) {
+      printk("%d: ", i); __dump_ep_desc(&(TxCtrlEPList[i]));
+    }
+  }
+
+  printk("Intr:\n");
+  for(i = 0; i < MAX_INTR_INTERVAL; i++) {
+    if(IO_EXTRACT(USB_EP_command, epid, TxIntrEPList[i].command) ==
+       epid) {
+      printk("%d: ", i); __dump_ep_desc(&(TxIntrEPList[i]));
+    }
+  }
+  
+  printk("Isoc:\n");
+  for(i = 0; i < 32; i++) {
+    if(IO_EXTRACT(USB_EP_command, epid, TxIsocEPList[i].command) ==
+       epid) {
+      printk("%d: ", i); __dump_ep_desc(&(TxIsocEPList[i]));
+    }
+  }
+
+  __dump_ept_data_list();
+  __dump_ep_list(PIPE_INTERRUPT);
+  printk("\n\n");
+}
+
+
+
+char* hcd_status_to_str(__u8 bUsbStatus) {
+  static char hcd_status_str[128];
+  hcd_status_str[0] = '\0';
+  if(bUsbStatus & IO_STATE(R_USB_STATUS, ourun, yes)) {
+    strcat(hcd_status_str, "ourun ");
+  }
+  if(bUsbStatus & IO_STATE(R_USB_STATUS, perror, yes)) {
+    strcat(hcd_status_str, "perror ");
+  }
+  if(bUsbStatus & IO_STATE(R_USB_STATUS, device_mode, yes)) {
+    strcat(hcd_status_str, "device_mode ");
+  }
+  if(bUsbStatus & IO_STATE(R_USB_STATUS, host_mode, yes)) {
+    strcat(hcd_status_str, "host_mode ");
+  }
+  if(bUsbStatus & IO_STATE(R_USB_STATUS, started, yes)) {
+    strcat(hcd_status_str, "started ");
+  }
+  if(bUsbStatus & IO_STATE(R_USB_STATUS, running, yes)) {
+    strcat(hcd_status_str, "running ");
+  }
+  return hcd_status_str;
+}
+
+
+char* sblist_to_str(struct USB_SB_Desc* sb_desc) {
+  static char sblist_to_str_buff[128];
+  char tmp[32], tmp2[32];
+  sblist_to_str_buff[0] = '\0';
+  while(sb_desc != NULL) {
+    switch(IO_EXTRACT(USB_SB_command, tt, sb_desc->command)) {
+    case 0: sprintf(tmp, "zout");  break;
+    case 1: sprintf(tmp, "in");    break;
+    case 2: sprintf(tmp, "out");   break;
+    case 3: sprintf(tmp, "setup"); break;
+    }
+    sprintf(tmp2, "(%s %d)", tmp, sb_desc->sw_len);
+    strcat(sblist_to_str_buff, tmp2);
+    if(sb_desc->next != 0) {
+      sb_desc = phys_to_virt(sb_desc->next);
+    } else {
+      sb_desc = NULL;
+    }
+  }
+  return sblist_to_str_buff;
+}
+
+char* port_status_to_str(__u16 wPortStatus) {
+  static char port_status_str[128];
+  port_status_str[0] = '\0';
+  if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, connected, yes)) {
+    strcat(port_status_str, "connected ");
+  }
+  if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes)) {
+    strcat(port_status_str, "enabled ");
+  }
+  if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, suspended, yes)) {
+    strcat(port_status_str, "suspended ");
+  }
+  if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, reset, yes)) {
+    strcat(port_status_str, "reset ");
+  }
+  if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, speed, full)) {
+    strcat(port_status_str, "full-speed ");
+  } else {
+    strcat(port_status_str, "low-speed ");
+  }
+  return port_status_str;
+}
+
+
+char* endpoint_to_str(struct usb_endpoint_descriptor *ed) {
+  static char endpoint_to_str_buff[128];
+  char tmp[32];
+  int epnum = ed->bEndpointAddress & 0x0F;
+  int dir = ed->bEndpointAddress & 0x80;
+  int type = ed->bmAttributes & 0x03;
+  endpoint_to_str_buff[0] = '\0';
+  sprintf(endpoint_to_str_buff, "ep:%d ", epnum);
+  switch(type) {
+  case 0:
+    sprintf(tmp, " ctrl");
+    break;
+  case 1:
+    sprintf(tmp, " isoc");
+    break;
+  case 2:
+    sprintf(tmp, " bulk");
+    break;
+  case 3:
+    sprintf(tmp, " intr");
+    break;
+  }
+  strcat(endpoint_to_str_buff, tmp);
+  if(dir) {
+    sprintf(tmp, " in");
+  } else {
+    sprintf(tmp, " out");
+  }
+  strcat(endpoint_to_str_buff, tmp);
+
+  return endpoint_to_str_buff;
+}
+
+/* Debug helper functions for Transfer Controller */
+char* pipe_to_str(unsigned int pipe) {
+  static char pipe_to_str_buff[128];
+  char tmp[64];
+  sprintf(pipe_to_str_buff, "dir:%s", str_dir(pipe));
+  sprintf(tmp, " type:%s", str_type(pipe));
+  strcat(pipe_to_str_buff, tmp);
+
+  sprintf(tmp, " dev:%d", usb_pipedevice(pipe));
+  strcat(pipe_to_str_buff, tmp);
+  sprintf(tmp, " ep:%d", usb_pipeendpoint(pipe));
+  strcat(pipe_to_str_buff, tmp);
+  return pipe_to_str_buff;
+}
+
+
+#define USB_DEBUG_DESC 1
+
+#ifdef USB_DEBUG_DESC
+#define dump_in_desc(x) __dump_in_desc(x)
+#define dump_sb_desc(...) __dump_sb_desc(...)
+#define dump_ep_desc(x) __dump_ep_desc(x)
+#define dump_ept_data(x) __dump_ept_data(x)
+#else
+#define dump_in_desc(...) do {} while (0)
+#define dump_sb_desc(...) do {} while (0)
+#define dump_ep_desc(...) do {} while (0)
+#endif
+
+
+/* Uncomment this to enable massive function call trace
+   #define USB_DEBUG_TRACE */
+//#define USB_DEBUG_TRACE 1
+
+#ifdef USB_DEBUG_TRACE
+#define DBFENTER (printk(": Entering: %s\n", __FUNCTION__))
+#define DBFEXIT  (printk(": Exiting:  %s\n", __FUNCTION__))
+#else
+#define DBFENTER do {} while (0)
+#define DBFEXIT  do {} while (0)
+#endif
+
+#define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \
+{panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);}
+
+/* Most helpful debugging aid */
+#define ASSERT(expr) ((void) ((expr) ? 0 : (err("assert failed at: %s %d",__FUNCTION__, __LINE__))))
+
+
+/***************************************************************************/
+/***************************************************************************/
+/* Forward declarations                                                    */
+/***************************************************************************/
+/***************************************************************************/
+void crisv10_hcd_epid_attn_irq(struct crisv10_irq_reg *reg);
+void crisv10_hcd_port_status_irq(struct crisv10_irq_reg *reg);
+void crisv10_hcd_ctl_status_irq(struct crisv10_irq_reg *reg);
+void crisv10_hcd_isoc_eof_irq(struct crisv10_irq_reg *reg);
+
+void rh_port_status_change(__u16[]);
+int  rh_clear_port_feature(__u8, __u16);
+int  rh_set_port_feature(__u8, __u16);
+static void rh_disable_port(unsigned int port);
+
+static void check_finished_bulk_tx_epids(struct usb_hcd *hcd,
+					 int timer);
+
+//static int  tc_setup_epid(struct usb_host_endpoint *ep, struct urb *urb,
+//			 int mem_flags);
+static int tc_setup_epid(struct urb *urb, int mem_flags);
+static void tc_free_epid(struct usb_host_endpoint *ep);
+static int  tc_allocate_epid(void);
+static void tc_finish_urb(struct usb_hcd *hcd, struct urb *urb, int status);
+static void tc_finish_urb_later(struct usb_hcd *hcd, struct urb *urb,
+				int status);
+
+static int  urb_priv_create(struct usb_hcd *hcd, struct urb *urb, int epid,
+			   int mem_flags);
+static void urb_priv_free(struct usb_hcd *hcd, struct urb *urb);
+
+static inline struct urb *urb_list_first(int epid);
+static inline void        urb_list_add(struct urb *urb, int epid,
+				      int mem_flags);
+static inline urb_entry_t *urb_list_entry(struct urb *urb, int epid);
+static inline void        urb_list_del(struct urb *urb, int epid);
+static inline void        urb_list_move_last(struct urb *urb, int epid);
+static inline struct urb *urb_list_next(struct urb *urb, int epid);
+
+int create_sb_for_urb(struct urb *urb, int mem_flags);
+int init_intr_urb(struct urb *urb, int mem_flags);
+
+static inline void  etrax_epid_set(__u8 index, __u32 data);
+static inline void  etrax_epid_clear_error(__u8 index);
+static inline void  etrax_epid_set_toggle(__u8 index, __u8 dirout,
+					      __u8 toggle);
+static inline __u8  etrax_epid_get_toggle(__u8 index, __u8 dirout);
+static inline __u32 etrax_epid_get(__u8 index);
+
+/* We're accessing the same register position in Etrax so
+   when we do full access the internal difference doesn't matter */
+#define etrax_epid_iso_set(index, data) etrax_epid_set(index, data)
+#define etrax_epid_iso_get(index) etrax_epid_get(index)
+
+
+//static void        tc_dma_process_isoc_urb(struct urb *urb);
+static void        tc_dma_process_queue(int epid);
+static void        tc_dma_unlink_intr_urb(struct urb *urb);
+static irqreturn_t tc_dma_tx_interrupt(int irq, void *vhc);
+static irqreturn_t tc_dma_rx_interrupt(int irq, void *vhc);
+
+static void tc_bulk_start_timer_func(unsigned long dummy);
+static void tc_bulk_eot_timer_func(unsigned long dummy);
+
+
+/*************************************************************/
+/*************************************************************/
+/* Host Controler Driver block                               */
+/*************************************************************/
+/*************************************************************/
+
+/* HCD operations */
+static irqreturn_t crisv10_hcd_top_irq(int irq, void*);
+static int crisv10_hcd_reset(struct usb_hcd *);
+static int crisv10_hcd_start(struct usb_hcd *);
+static void crisv10_hcd_stop(struct usb_hcd *);
+#ifdef CONFIG_PM
+static int crisv10_hcd_suspend(struct device *, u32, u32);
+static int crisv10_hcd_resume(struct device *, u32);
+#endif /* CONFIG_PM */
+static int crisv10_hcd_get_frame(struct usb_hcd *);
+
+//static int  tc_urb_enqueue(struct usb_hcd *, struct usb_host_endpoint *ep, struct urb *, gfp_t mem_flags);
+static int tc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
+//static int  tc_urb_dequeue(struct usb_hcd *, struct urb *);
+static int tc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
+static void tc_endpoint_disable(struct usb_hcd *, struct usb_host_endpoint *ep);
+
+static int rh_status_data_request(struct usb_hcd *, char *);
+static int rh_control_request(struct usb_hcd *, u16, u16, u16, char*, u16);
+
+#ifdef CONFIG_PM
+static int crisv10_hcd_hub_suspend(struct usb_hcd *);
+static int crisv10_hcd_hub_resume(struct usb_hcd *);
+#endif /* CONFIG_PM */
+#ifdef CONFIG_USB_OTG
+static int crisv10_hcd_start_port_reset(struct usb_hcd *, unsigned);
+#endif /* CONFIG_USB_OTG */
+
+/* host controller driver interface */
+static const struct hc_driver crisv10_hc_driver = 
+  {
+    .description =	hc_name,
+    .product_desc =	product_desc,
+    .hcd_priv_size =	sizeof(struct crisv10_hcd),
+
+    /* Attaching IRQ handler manualy in probe() */
+    /* .irq =		crisv10_hcd_irq, */
+
+    .flags =		HCD_USB11,
+
+    /* called to init HCD and root hub */
+    .reset =		crisv10_hcd_reset,
+    .start =		crisv10_hcd_start,	
+
+    /* cleanly make HCD stop writing memory and doing I/O */
+    .stop =		crisv10_hcd_stop,
+
+    /* return current frame number */
+    .get_frame_number =	crisv10_hcd_get_frame,
+
+
+    /* Manage i/o requests via the Transfer Controller */
+    .urb_enqueue =	tc_urb_enqueue,
+    .urb_dequeue =	tc_urb_dequeue,
+
+    /* hw synch, freeing endpoint resources that urb_dequeue can't */
+    .endpoint_disable = tc_endpoint_disable,
+
+
+    /* Root Hub support */
+    .hub_status_data =	rh_status_data_request,
+    .hub_control =	rh_control_request,
+#ifdef CONFIG_PM
+    .hub_suspend =	rh_suspend_request,
+    .hub_resume =	rh_resume_request,
+#endif /* CONFIG_PM */
+#ifdef	CONFIG_USB_OTG
+    .start_port_reset =	crisv10_hcd_start_port_reset,
+#endif /* CONFIG_USB_OTG */
+  };
+
+
+/*
+ * conversion between pointers to a hcd and the corresponding
+ * crisv10_hcd 
+ */
+
+static inline struct crisv10_hcd *hcd_to_crisv10_hcd(struct usb_hcd *hcd)
+{
+	return (struct crisv10_hcd *) hcd->hcd_priv;
+}
+
+static inline struct usb_hcd *crisv10_hcd_to_hcd(struct crisv10_hcd *hcd)
+{
+	return container_of((void *) hcd, struct usb_hcd, hcd_priv);
+}
+
+/* check if specified port is in use */
+static inline int port_in_use(unsigned int port)
+{
+	return ports & (1 << port);
+}
+
+/* number of ports in use */
+static inline unsigned int num_ports(void)
+{
+	unsigned int i, num = 0;
+	for (i = 0; i < USB_ROOT_HUB_PORTS; i++)
+		if (port_in_use(i))
+			num++;
+	return num;
+}
+
+/* map hub port number to the port number used internally by the HC */
+static inline unsigned int map_port(unsigned int port)
+{
+  unsigned int i, num = 0;
+  for (i = 0; i < USB_ROOT_HUB_PORTS; i++)
+    if (port_in_use(i))
+      if (++num == port)
+	return i;
+  return -1;
+}
+
+/* size of descriptors in slab cache */
+#ifndef MAX
+#define MAX(x, y)		((x) > (y) ? (x) : (y))
+#endif
+
+
+/******************************************************************/
+/* Hardware Interrupt functions                                   */
+/******************************************************************/
+
+/* Fast interrupt handler for HC */
+static irqreturn_t crisv10_hcd_top_irq(int irq, void *vcd)
+{
+  struct usb_hcd *hcd = vcd;
+  struct crisv10_irq_reg reg;
+  __u32 irq_mask;
+  unsigned long flags;
+
+  DBFENTER;
+
+  ASSERT(hcd != NULL);
+  reg.hcd = hcd;
+
+  /* Turn of other interrupts while handling these sensitive cases */
+  local_irq_save(flags);
+  
+  /* Read out which interrupts that are flaged */
+  irq_mask = *R_USB_IRQ_MASK_READ;
+  reg.r_usb_irq_mask_read = irq_mask;
+
+  /* Reading R_USB_STATUS clears the ctl_status interrupt. Note that
+     R_USB_STATUS must be read before R_USB_EPID_ATTN since reading the latter
+     clears the ourun and perror fields of R_USB_STATUS. */
+  reg.r_usb_status = *R_USB_STATUS;
+  
+  /* Reading R_USB_EPID_ATTN clears the iso_eof, bulk_eot and epid_attn
+     interrupts. */
+  reg.r_usb_epid_attn = *R_USB_EPID_ATTN;
+  
+  /* Reading R_USB_RH_PORT_STATUS_1 and R_USB_RH_PORT_STATUS_2 clears the
+     port_status interrupt. */
+  reg.r_usb_rh_port_status_1 = *R_USB_RH_PORT_STATUS_1;
+  reg.r_usb_rh_port_status_2 = *R_USB_RH_PORT_STATUS_2;
+  
+  /* Reading R_USB_FM_NUMBER clears the sof interrupt. */
+  /* Note: the lower 11 bits contain the actual frame number, sent with each
+     sof. */
+  reg.r_usb_fm_number = *R_USB_FM_NUMBER;
+
+  /* Interrupts are handled in order of priority. */
+  if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, port_status)) {
+    crisv10_hcd_port_status_irq(&reg);
+  }
+  if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, epid_attn)) {
+    crisv10_hcd_epid_attn_irq(&reg);
+  }
+  if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, ctl_status)) {
+    crisv10_hcd_ctl_status_irq(&reg);
+  }
+  if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, iso_eof)) {
+    crisv10_hcd_isoc_eof_irq(&reg);
+  }
+  if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, bulk_eot)) {
+    /* Update/restart the bulk start timer since obviously the channel is
+       running. */
+    mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL);
+    /* Update/restart the bulk eot timer since we just received an bulk eot
+       interrupt. */
+    mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL);
+
+    /* Check for finished bulk transfers on epids */
+    check_finished_bulk_tx_epids(hcd, 0);
+  }
+  local_irq_restore(flags);
+
+  DBFEXIT;
+  return IRQ_HANDLED;
+}
+
+
+void crisv10_hcd_epid_attn_irq(struct crisv10_irq_reg *reg) {
+  struct usb_hcd *hcd = reg->hcd;
+  struct crisv10_urb_priv *urb_priv;
+  int epid;
+  DBFENTER;
+
+  for (epid = 0; epid < NBR_OF_EPIDS; epid++) {
+    if (test_bit(epid, (void *)&reg->r_usb_epid_attn)) {
+      struct urb *urb;
+      __u32 ept_data;
+      int error_code;
+
+      if (epid == DUMMY_EPID || epid == INVALID_EPID) {
+	/* We definitely don't care about these ones. Besides, they are
+	   always disabled, so any possible disabling caused by the
+	   epid attention interrupt is irrelevant. */
+	warn("Got epid_attn for INVALID_EPID or DUMMY_EPID (%d).", epid);
+	continue;
+      }
+
+      if(!epid_inuse(epid)) {
+	irq_err("Epid attention on epid:%d that isn't in use\n", epid);
+	printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status);
+	debug_epid(epid);
+	continue;
+      }
+
+      /* Note that although there are separate R_USB_EPT_DATA and
+	 R_USB_EPT_DATA_ISO registers, they are located at the same address and
+	 are of the same size. In other words, this read should be ok for isoc
+	 also. */
+      ept_data = etrax_epid_get(epid);
+      error_code = IO_EXTRACT(R_USB_EPT_DATA, error_code, ept_data);
+
+      /* Get the active URB for this epid. We blatantly assume
+	 that only this URB could have caused the epid attention. */
+      urb = activeUrbList[epid];
+      if (urb == NULL) {
+	irq_err("Attention on epid:%d error:%d with no active URB.\n",
+		epid, error_code);
+	printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status);
+	debug_epid(epid);
+	continue;
+      }
+
+      urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;
+      ASSERT(urb_priv);
+
+      /* Using IO_STATE_VALUE on R_USB_EPT_DATA should be ok for isoc also. */
+      if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
+
+	/* Isoc traffic doesn't have error_count_in/error_count_out. */
+	if ((usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS) &&
+	    (IO_EXTRACT(R_USB_EPT_DATA, error_count_in, ept_data) == 3 ||
+	     IO_EXTRACT(R_USB_EPT_DATA, error_count_out, ept_data) == 3)) {
+	  /* Check if URB allready is marked for late-finish, we can get
+	     several 3rd error for Intr traffic when a device is unplugged */
+	  if(urb_priv->later_data == NULL) {
+	    /* 3rd error. */
+	    irq_warn("3rd error for epid:%d (%s %s) URB:0x%x[%d]\n", epid,
+		     str_dir(urb->pipe), str_type(urb->pipe),
+		     (unsigned int)urb, urb_priv->urb_num);
+	  
+	    tc_finish_urb_later(hcd, urb, -EPROTO);
+	  }
+
+	} else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {
+	  irq_warn("Perror for epid:%d\n", epid);
+	  printk("FM_NUMBER: %d\n", reg->r_usb_fm_number & 0x7ff);
+	  printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status);
+	  __dump_urb(urb);
+	  debug_epid(epid);
+
+	  if (!(ept_data & IO_MASK(R_USB_EPT_DATA, valid))) {
+	    /* invalid ep_id */
+	    panic("Perror because of invalid epid."
+		  " Deconfigured too early?");
+	  } else {
+	    /* past eof1, near eof, zout transfer, setup transfer */
+	    /* Dump the urb and the relevant EP descriptor. */
+	    panic("Something wrong with DMA descriptor contents."
+		  " Too much traffic inserted?");
+	  }
+	} else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {
+	  /* buffer ourun */
+	  printk("FM_NUMBER: %d\n", reg->r_usb_fm_number & 0x7ff);
+	  printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status);
+	  __dump_urb(urb);
+	  debug_epid(epid);
+
+	  panic("Buffer overrun/underrun for epid:%d. DMA too busy?", epid);
+	} else {
+	  irq_warn("Attention on epid:%d (%s %s) with no error code\n", epid,
+		   str_dir(urb->pipe), str_type(urb->pipe));
+	  printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status);
+	  __dump_urb(urb);
+	  debug_epid(epid);
+	}
+
+      } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code,
+					      stall)) {
+	/* Not really a protocol error, just says that the endpoint gave
+	   a stall response. Note that error_code cannot be stall for isoc. */
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+	  panic("Isoc traffic cannot stall");
+	}
+
+	tc_dbg("Stall for epid:%d (%s %s) URB:0x%x\n", epid,
+	       str_dir(urb->pipe), str_type(urb->pipe), (unsigned int)urb);
+	tc_finish_urb(hcd, urb, -EPIPE);
+
+      } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code,
+					      bus_error)) {
+	/* Two devices responded to a transaction request. Must be resolved
+	   by software. FIXME: Reset ports? */
+	panic("Bus error for epid %d."
+	      " Two devices responded to transaction request\n",
+	      epid);
+
+      } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code,
+					      buffer_error)) {
+	/* DMA overrun or underrun. */
+	irq_warn("Buffer overrun/underrun for epid:%d (%s %s)\n", epid,
+		 str_dir(urb->pipe), str_type(urb->pipe));
+
+	/* It seems that error_code = buffer_error in
+	   R_USB_EPT_DATA/R_USB_EPT_DATA_ISO and ourun = yes in R_USB_STATUS
+	   are the same error. */
+	tc_finish_urb(hcd, urb, -EPROTO);
+      } else {
+	  irq_warn("Unknown attention on epid:%d (%s %s)\n", epid,
+		   str_dir(urb->pipe), str_type(urb->pipe));
+	  dump_ept_data(epid);
+      }
+    }
+  }
+  DBFEXIT;
+}
+
+void crisv10_hcd_port_status_irq(struct crisv10_irq_reg *reg)
+{
+  __u16 port_reg[USB_ROOT_HUB_PORTS];
+  DBFENTER;
+  port_reg[0] = reg->r_usb_rh_port_status_1;
+  port_reg[1] = reg->r_usb_rh_port_status_2;
+  rh_port_status_change(port_reg);
+  DBFEXIT;
+}
+
+void crisv10_hcd_isoc_eof_irq(struct crisv10_irq_reg *reg)
+{
+  int epid;
+  struct urb *urb;
+  struct crisv10_urb_priv *urb_priv;
+
+  DBFENTER;
+
+  for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) {
+
+    /* Only check epids that are in use, is valid and has SB list */
+    if (!epid_inuse(epid) || epid == INVALID_EPID ||
+	TxIsocEPList[epid].sub == 0 || epid == DUMMY_EPID) {
+      /* Nothing here to see. */
+      continue;
+    }
+    ASSERT(epid_isoc(epid));
+
+    /* Get the active URB for this epid (if any). */
+    urb = activeUrbList[epid];
+    if (urb == 0) {
+      isoc_warn("Ignoring NULL urb for epid:%d\n", epid);
+      continue;
+    }
+    if(!epid_out_traffic(epid)) {
+      /* Sanity check. */
+      ASSERT(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS);
+
+      urb_priv = (struct crisv10_urb_priv *)urb->hcpriv;
+      ASSERT(urb_priv);
+
+      if (urb_priv->urb_state == NOT_STARTED) {
+	/* If ASAP is not set and urb->start_frame is the current frame,
+	   start the transfer. */
+	if (!(urb->transfer_flags & URB_ISO_ASAP) &&
+	    (urb->start_frame == (*R_USB_FM_NUMBER & 0x7ff))) {
+	  /* EP should not be enabled if we're waiting for start_frame */
+	  ASSERT((TxIsocEPList[epid].command &
+		  IO_STATE(USB_EP_command, enable, yes)) == 0);
+
+	  isoc_warn("Enabling isoc IN EP descr for epid %d\n", epid);
+	  TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
+
+	  /* This urb is now active. */
+	  urb_priv->urb_state = STARTED;
+	  continue;
+	}
+      }
+    }
+  }
+
+  DBFEXIT;
+}
+
+void crisv10_hcd_ctl_status_irq(struct crisv10_irq_reg *reg)
+{
+  struct crisv10_hcd* crisv10_hcd = hcd_to_crisv10_hcd(reg->hcd);
+
+  DBFENTER;
+  ASSERT(crisv10_hcd);
+
+  irq_dbg("ctr_status_irq, controller status: %s\n",
+	  hcd_status_to_str(reg->r_usb_status));
+  
+  /* FIXME: What should we do if we get ourun or perror? Dump the EP and SB
+     list for the corresponding epid? */
+  if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {
+    panic("USB controller got ourun.");
+  }
+  if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {
+    
+    /* Before, etrax_usb_do_intr_recover was called on this epid if it was
+       an interrupt pipe. I don't see how re-enabling all EP descriptors
+       will help if there was a programming error. */
+    panic("USB controller got perror.");
+  }
+
+  /* Keep track of USB Controller, if it's running or not */
+  if(reg->r_usb_status & IO_STATE(R_USB_STATUS, running, yes)) {
+    crisv10_hcd->running = 1;
+  } else {
+    crisv10_hcd->running = 0;
+  }
+  
+  if (reg->r_usb_status & IO_MASK(R_USB_STATUS, device_mode)) {
+    /* We should never operate in device mode. */
+    panic("USB controller in device mode.");
+  }
+
+  /* Set the flag to avoid getting "Unlink after no-IRQ? Controller is probably
+     using the wrong IRQ" from hcd_unlink_urb() in drivers/usb/core/hcd.c */
+  set_bit(HCD_FLAG_SAW_IRQ, &reg->hcd->flags);
+  
+  DBFEXIT;
+}
+
+
+/******************************************************************/
+/* Host Controller interface functions                            */
+/******************************************************************/
+
+static inline void crisv10_ready_wait(void) {
+  volatile int timeout = 10000;
+  /* Check the busy bit of USB controller in Etrax */
+  while((*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)) &&
+	(timeout-- > 0));
+  if(timeout == 0) {
+    warn("Timeout while waiting for USB controller to be idle\n");
+  }
+}
+
+/* reset host controller */
+static int crisv10_hcd_reset(struct usb_hcd *hcd)
+{
+  DBFENTER;
+  hcd_dbg(hcd, "reset\n");
+
+
+  /* Reset the USB interface. */
+  /*
+  *R_USB_COMMAND =
+    IO_STATE(R_USB_COMMAND, port_sel, nop) |
+    IO_STATE(R_USB_COMMAND, port_cmd, reset) |
+    IO_STATE(R_USB_COMMAND, ctrl_cmd, reset);
+  nop();
+  */
+  DBFEXIT;
+  return 0;
+}
+
+/* start host controller */
+static int crisv10_hcd_start(struct usb_hcd *hcd)
+{
+  DBFENTER;
+  hcd_dbg(hcd, "start\n");
+
+  crisv10_ready_wait();
+
+  /* Start processing of USB traffic. */
+  *R_USB_COMMAND =
+    IO_STATE(R_USB_COMMAND, port_sel, nop) |
+    IO_STATE(R_USB_COMMAND, port_cmd, reset) |
+    IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);
+
+  nop();
+
+  hcd->state = HC_STATE_RUNNING;
+
+  DBFEXIT;
+  return 0;
+}
+
+/* stop host controller */
+static void crisv10_hcd_stop(struct usb_hcd *hcd)
+{
+  DBFENTER;
+  hcd_dbg(hcd, "stop\n");
+  crisv10_hcd_reset(hcd);
+  DBFEXIT;
+}
+
+/* return the current frame number */
+static int crisv10_hcd_get_frame(struct usb_hcd *hcd)
+{
+  DBFENTER;
+  DBFEXIT;
+  return (*R_USB_FM_NUMBER & 0x7ff);
+}
+
+#ifdef	CONFIG_USB_OTG
+
+static int crisv10_hcd_start_port_reset(struct usb_hcd *hcd, unsigned port)
+{
+  return 0; /* no-op for now */
+}
+
+#endif /* CONFIG_USB_OTG */
+
+
+/******************************************************************/
+/* Root Hub functions                                             */
+/******************************************************************/
+
+/* root hub status */
+static const struct usb_hub_status rh_hub_status = 
+  {
+    .wHubStatus =		0,
+    .wHubChange =		0,
+  };
+
+/* root hub descriptor */
+static const u8 rh_hub_descr[] =
+  {
+    0x09,			/* bDescLength	       */
+    0x29,			/* bDescriptorType     */
+    USB_ROOT_HUB_PORTS,         /* bNbrPorts	       */
+    0x00,			/* wHubCharacteristics */
+    0x00,		 
+    0x01,			/* bPwrOn2pwrGood      */
+    0x00,			/* bHubContrCurrent    */
+    0x00,			/* DeviceRemovable     */
+    0xff			/* PortPwrCtrlMask     */
+  };
+
+/* Actual holder of root hub status*/
+struct crisv10_rh rh;
+
+/* Initialize root hub data structures (called from dvdrv_hcd_probe()) */
+int rh_init(void) {
+  int i;
+  /* Reset port status flags */
+  for (i = 0; i < USB_ROOT_HUB_PORTS; i++) {
+    rh.wPortChange[i] = 0;
+    rh.wPortStatusPrev[i] = 0;
+  }
+  return 0;
+}
+
+#define RH_FEAT_MASK ((1<<USB_PORT_FEAT_CONNECTION)|\
+		      (1<<USB_PORT_FEAT_ENABLE)|\
+		      (1<<USB_PORT_FEAT_SUSPEND)|\
+		      (1<<USB_PORT_FEAT_RESET))
+
+/* Handle port status change interrupt (called from bottom part interrupt) */
+void rh_port_status_change(__u16 port_reg[]) {
+  int i;
+  __u16 wChange;
+
+  for(i = 0; i < USB_ROOT_HUB_PORTS; i++) {
+    /* Xor out changes since last read, masked for important flags */
+    wChange = (port_reg[i] & RH_FEAT_MASK) ^ rh.wPortStatusPrev[i];
+    /* Or changes together with (if any) saved changes */
+    rh.wPortChange[i] |= wChange;
+    /* Save new status */
+    rh.wPortStatusPrev[i] = port_reg[i];
+
+    if(wChange) {
+      rh_dbg("Interrupt port_status change port%d: %s  Current-status:%s\n", i+1,
+	     port_status_to_str(wChange),
+	     port_status_to_str(port_reg[i]));
+    }
+  }
+}
+
+/* Construct port status change bitmap for the root hub */
+static int rh_status_data_request(struct usb_hcd *hcd, char *buf)
+{
+  struct crisv10_hcd* crisv10_hcd = hcd_to_crisv10_hcd(hcd);
+  unsigned int i;
+
+//  DBFENTER;
+  
+  /*
+   * corresponds to hub status change EP (USB 2.0 spec section 11.13.4)
+   * return bitmap indicating ports with status change
+   */
+  *buf = 0;
+  spin_lock(&crisv10_hcd->lock);
+  for (i = 1; i <= crisv10_hcd->num_ports; i++) {
+    if (rh.wPortChange[map_port(i)]) {
+      *buf |= (1 << i);
+      rh_dbg("rh_status_data_request, change on port %d: %s  Current Status: %s\n", i,
+	     port_status_to_str(rh.wPortChange[map_port(i)]),
+	     port_status_to_str(rh.wPortStatusPrev[map_port(i)]));
+    }
+  }
+  spin_unlock(&crisv10_hcd->lock);
+
+// DBFEXIT;
+
+  return *buf == 0 ? 0 : 1;
+}
+
+/* Handle a control request for the root hub (called from hcd_driver) */
+static int rh_control_request(struct usb_hcd *hcd, 
+			      u16 typeReq, 
+			      u16 wValue, 
+			      u16 wIndex,
+			      char *buf, 
+			      u16 wLength) {
+
+  struct crisv10_hcd *crisv10_hcd = hcd_to_crisv10_hcd(hcd);
+  int retval = 0;
+  int len;
+  DBFENTER;
+
+  switch (typeReq) {
+  case GetHubDescriptor:
+    rh_dbg("GetHubDescriptor\n");
+    len = min_t(unsigned int, sizeof rh_hub_descr, wLength);
+    memcpy(buf, rh_hub_descr, len);
+    buf[2] = crisv10_hcd->num_ports;
+    break;
+  case GetHubStatus:
+    rh_dbg("GetHubStatus\n");
+    len = min_t(unsigned int, sizeof rh_hub_status, wLength);
+    memcpy(buf, &rh_hub_status, len);
+    break;
+  case GetPortStatus:
+    if (!wIndex || wIndex > crisv10_hcd->num_ports)
+      goto error;
+    rh_dbg("GetportStatus, port:%d change:%s  status:%s\n", wIndex,
+	   port_status_to_str(rh.wPortChange[map_port(wIndex)]),
+	   port_status_to_str(rh.wPortStatusPrev[map_port(wIndex)]));
+    *(u16 *) buf = cpu_to_le16(rh.wPortStatusPrev[map_port(wIndex)]);
+    *(u16 *) (buf + 2) = cpu_to_le16(rh.wPortChange[map_port(wIndex)]);
+    break;
+  case SetHubFeature:
+    rh_dbg("SetHubFeature\n");
+  case ClearHubFeature:
+    rh_dbg("ClearHubFeature\n");
+    switch (wValue) {
+    case C_HUB_OVER_CURRENT:
+    case C_HUB_LOCAL_POWER:
+      rh_warn("Not implemented hub request:%d \n", typeReq);
+      /* not implemented */
+      break;
+    default:
+      goto error;
+    }
+    break;
+  case SetPortFeature:
+    if (!wIndex || wIndex > crisv10_hcd->num_ports)
+      goto error;
+    if(rh_set_port_feature(map_port(wIndex), wValue))
+      goto error;
+    break;
+  case ClearPortFeature:
+    if (!wIndex || wIndex > crisv10_hcd->num_ports)
+      goto error;
+    if(rh_clear_port_feature(map_port(wIndex), wValue))
+      goto error;
+    break;
+  default:
+    rh_warn("Unknown hub request: %d\n", typeReq);
+  error:
+    retval = -EPIPE;
+  }
+  DBFEXIT;
+  return retval;
+}
+
+int rh_set_port_feature(__u8 bPort, __u16 wFeature) {
+  __u8 bUsbCommand = 0;
+  switch(wFeature) {
+  case USB_PORT_FEAT_RESET:
+    rh_dbg("SetPortFeature: reset\n");
+    bUsbCommand |= IO_STATE(R_USB_COMMAND, port_cmd, reset);
+    goto set;
+    break;
+  case USB_PORT_FEAT_SUSPEND:
+    rh_dbg("SetPortFeature: suspend\n");
+    bUsbCommand |= IO_STATE(R_USB_COMMAND, port_cmd, suspend);
+    goto set;
+    break;
+  case USB_PORT_FEAT_POWER:
+    rh_dbg("SetPortFeature: power\n");
+    break;
+  case USB_PORT_FEAT_C_CONNECTION:
+    rh_dbg("SetPortFeature: c_connection\n");
+    break;
+  case USB_PORT_FEAT_C_RESET:
+    rh_dbg("SetPortFeature: c_reset\n");
+    break;
+  case USB_PORT_FEAT_C_OVER_CURRENT:
+    rh_dbg("SetPortFeature: c_over_current\n");
+    break;
+
+  set:
+    /* Select which port via the port_sel field */
+    bUsbCommand |= IO_FIELD(R_USB_COMMAND, port_sel, bPort+1);
+
+    /* Make sure the controller isn't busy. */
+    crisv10_ready_wait();
+    /* Send out the actual command to the USB controller */
+    *R_USB_COMMAND = bUsbCommand;
+
+    /* If port reset then also bring USB controller into running state */
+    if(wFeature == USB_PORT_FEAT_RESET) {
+      /* Wait a while for controller to first become started after port reset */
+      udelay(12000); /* 12ms blocking wait */
+      
+      /* Make sure the controller isn't busy. */
+      crisv10_ready_wait();
+
+      /* If all enabled ports were disabled the host controller goes down into
+	 started mode, so we need to bring it back into the running state.
+	 (This is safe even if it's already in the running state.) */
+      *R_USB_COMMAND =
+	IO_STATE(R_USB_COMMAND, port_sel, nop) |
+	IO_STATE(R_USB_COMMAND, port_cmd, reset) |
+	IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);
+    }
+
+    break;
+  default:
+    rh_dbg("SetPortFeature: unknown feature\n");
+    return -1;
+  }
+  return 0;
+}
+
+int rh_clear_port_feature(__u8 bPort, __u16 wFeature) {
+  switch(wFeature) {
+  case USB_PORT_FEAT_ENABLE:
+    rh_dbg("ClearPortFeature: enable\n");
+    rh_disable_port(bPort);
+    break;
+  case USB_PORT_FEAT_SUSPEND:
+    rh_dbg("Cle