Merge branch 'SDKv2.8.5' into mindspeed_drops
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d79e75d..45d65c8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1549,10 +1549,12 @@
 	  option alone!
 
 	config VMSPLIT_3G
+		depends on !COMCERTO_HW_KERNEL_PAGETABLE
 		bool "3G/1G user/kernel split"
 	config VMSPLIT_2G
 		bool "2G/2G user/kernel split"
 	config VMSPLIT_1G
+		depends on !COMCERTO_HW_KERNEL_PAGETABLE
 		bool "1G/3G user/kernel split"
 endchoice
 
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
old mode 100644
new mode 100755
index c133fba..399302e
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -49,7 +49,6 @@
 
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
-
 /*
  * Supported arch specific GIC irq extension.
  * Default make them NULL.
diff --git a/arch/arm/configs/c2kasic_defconfig b/arch/arm/configs/c2kasic_defconfig
old mode 100644
new mode 100755
diff --git a/arch/arm/configs/c2kevm_defconfig b/arch/arm/configs/c2kevm_defconfig
old mode 100644
new mode 100755
diff --git a/arch/arm/configs/c2klv_defconfig b/arch/arm/configs/c2klv_defconfig
old mode 100644
new mode 100755
diff --git a/arch/arm/configs/c2krtsm_defconfig b/arch/arm/configs/c2krtsm_defconfig
old mode 100644
new mode 100755
diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
index 86976d0..293fabf 100644
--- a/arch/arm/include/asm/atomic.h
+++ b/arch/arm/include/asm/atomic.h
@@ -29,6 +29,27 @@
 
 #if __LINUX_ARM_ARCH__ >= 6
 
+#ifdef CONFIG_COMCERTO_ZONE_DMA_NCNB
+
+int comcerto_atomic_add(int i, atomic_t *v);
+int comcerto_atomic_cmpxchg(atomic_t *v, int old, int new);
+void comcerto_atomic_clear_mask(unsigned long mask, unsigned long *addr);
+
+
+struct virtual_zone {
+	void *start;
+	void *end;
+};
+
+extern struct virtual_zone arm_dma_zone;
+
+static inline bool is_dma_zone_virtual_address(void *addr)
+{
+	return ((addr < arm_dma_zone.end) && (addr >= arm_dma_zone.start));
+}
+
+#endif
+
 /*
  * ARMv6 UP and SMP safe atomic ops.  We use load exclusive and
  * store exclusive to ensure that these are atomic.  We may loop
@@ -39,6 +60,13 @@
 	unsigned long tmp;
 	int result;
 
+#ifdef CONFIG_COMCERTO_ZONE_DMA_NCNB
+	if (unlikely(is_dma_zone_virtual_address(v))) {
+		comcerto_atomic_add(i, v);
+		return;
+	}
+#endif
+
 	__asm__ __volatile__("@ atomic_add\n"
 "1:	ldrex	%0, [%3]\n"
 "	add	%0, %0, %4\n"
@@ -55,6 +83,11 @@
 	unsigned long tmp;
 	int result;
 
+#ifdef CONFIG_COMCERTO_ZONE_DMA_NCNB
+	if (unlikely(is_dma_zone_virtual_address(v)))
+		return comcerto_atomic_add(i, v);
+#endif
+
 	smp_mb();
 
 	__asm__ __volatile__("@ atomic_add_return\n"
@@ -77,6 +110,13 @@
 	unsigned long tmp;
 	int result;
 
+#ifdef CONFIG_COMCERTO_ZONE_DMA_NCNB
+	if (unlikely(is_dma_zone_virtual_address(v))) {
+		comcerto_atomic_add(-i, v);
+		return;
+	}
+#endif
+
 	__asm__ __volatile__("@ atomic_sub\n"
 "1:	ldrex	%0, [%3]\n"
 "	sub	%0, %0, %4\n"
@@ -93,6 +133,11 @@
 	unsigned long tmp;
 	int result;
 
+#ifdef CONFIG_COMCERTO_ZONE_DMA_NCNB
+	if (unlikely(is_dma_zone_virtual_address(v)))
+		return comcerto_atomic_add(-i, v);
+#endif
+
 	smp_mb();
 
 	__asm__ __volatile__("@ atomic_sub_return\n"
@@ -114,6 +159,11 @@
 {
 	unsigned long oldval, res;
 
+#ifdef CONFIG_COMCERTO_ZONE_DMA_NCNB
+	if (unlikely(is_dma_zone_virtual_address(ptr)))
+		return comcerto_atomic_cmpxchg(ptr, old, new);
+#endif
+
 	smp_mb();
 
 	do {
@@ -136,6 +186,13 @@
 {
 	unsigned long tmp, tmp2;
 
+#ifdef CONFIG_COMCERTO_ZONE_DMA_NCNB
+	if (unlikely(is_dma_zone_virtual_address(addr))) {
+		atomic_clear_mask(mask, addr);
+		return;
+	}
+#endif
+
 	__asm__ __volatile__("@ atomic_clear_mask\n"
 "1:	ldrex	%0, [%3]\n"
 "	bic	%0, %0, %4\n"
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
index 88d6181..f6546a9 100644
--- a/arch/arm/include/asm/entry-macro-multi.S
+++ b/arch/arm/include/asm/entry-macro-multi.S
@@ -4,8 +4,8 @@
  * Interrupt handling.  Preserves r7, r8, r9
  */
 	.macro	arch_irq_handler_default
-	get_irqnr_preamble r6, lr
-1:	get_irqnr_and_base r0, r2, r6, lr
+	get_irqnr_preamble r6, r3, lr
+1:	get_irqnr_and_base r0, r2, r6, r3, lr
 	movne	r1, sp
 	@
 	@ routine called with r0 = irq number, r1 = struct pt_regs *
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
index bbae919..ac9fa8a 100644
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -13,7 +13,7 @@
  * 0xfffe0000 and 0xfffeffff.
  */
 
-#define FIXADDR_START		0xfff00000UL
+#define FIXADDR_START		0xfff30000UL
 #define FIXADDR_TOP		0xfffe0000UL
 #define FIXADDR_SIZE		(FIXADDR_TOP - FIXADDR_START)
 
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index e2be7f1..6e94826 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -256,6 +256,7 @@
 #define cpu_dcache_clean_area		__glue(CPU_NAME,_dcache_clean_area)
 #define cpu_do_switch_mm		__glue(CPU_NAME,_switch_mm)
 #define cpu_set_pte_ext			__glue(CPU_NAME,_set_pte_ext)
+#define cpu_uncache_pte_ext		__glue(CPU_NAME,_uncache_pte_ext)
 #define cpu_suspend_size		__glue(CPU_NAME,_suspend_size)
 #define cpu_do_suspend			__glue(CPU_NAME,_do_suspend)
 #define cpu_do_resume			__glue(CPU_NAME,_do_resume)
diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h
old mode 100644
new mode 100755
diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S
index c5ba98a..56daa10 100644
--- a/arch/arm/include/asm/hardware/entry-macro-gic.S
+++ b/arch/arm/include/asm/hardware/entry-macro-gic.S
@@ -11,7 +11,7 @@
 #include <asm/hardware/gic.h>
 
 #ifndef HAVE_GET_IRQNR_PREAMBLE
-	.macro	get_irqnr_preamble, base, tmp
+	.macro	get_irqnr_preamble, base, pending_intr, tmp
 	ldr	\base, =gic_cpu_base_addr
 	ldr	\base, [\base]
 	.endm
@@ -32,7 +32,7 @@
  * valid range for an IRQ (30-1020 inclusive).
  */
 
-	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, pending_intr, tmp
 
 #ifdef CONFIG_COMCERTO_MSP
 	ldr     \irqstat, [\base, #GIC_CPU_HIGHPRI]
@@ -53,8 +53,31 @@
 	ldr     \irqstat, [\base, #GIC_CPU_INTACK]
 	/* bits 12-10 = src CPU, 9-0 = int # */
 
-	ldr	\tmp, =1021
 	bic     \irqnr, \irqstat, #0x1c00
+	
+#ifdef CONFIG_COMCERTO_MSP
+	cmp     \irqnr, #33
+	streq	\irqstat, [\base, #GIC_CPU_EOI]
+	ldreq	\tmp, =0x2	//2 on bit1
+	ldreq	\pending_intr, =COMCERTO_DISTR_INT_SET_PENDING_OFFSET_4
+	streq	\tmp, [\pending_intr]
+	beq	1002f
+
+	cmpne   \irqnr, #66
+	streq	\irqstat, [\base, #GIC_CPU_EOI]
+	ldreq	\tmp, =0x4	//4 on bit 2
+	ldreq	\pending_intr, =COMCERTO_DISTR_INT_SET_PENDING_OFFSET_8
+	streq	\tmp, [\pending_intr]
+	beq	1002f
+
+	cmpne   \irqnr, #87
+	streq	\irqstat, [\base, #GIC_CPU_EOI]
+	ldreq	\tmp, =0x800000	//0x800000 on bit 23
+	ldreq	\pending_intr, =COMCERTO_DISTR_INT_SET_PENDING_OFFSET_8
+	streq	\tmp, [\pending_intr]
+	beq	1002f
+#endif /* CONFIG_COMCERTO_MSP */
+	ldr	\tmp, =1021
 	cmp     \irqnr, #15
 	cmpcc	\irqnr, \irqnr
 	cmpne	\irqnr, \tmp
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
old mode 100644
new mode 100755
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
old mode 100644
new mode 100755
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 8b93c02..ef333db 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -250,6 +250,7 @@
 #define mk_pte(page,prot)	pfn_pte(page_to_pfn(page), prot)
 
 #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte_val(pte),ext)
+#define uncache_pte_ext(ptep) cpu_uncache_pte_ext(ptep)
 #define pte_clear(mm,addr,ptep)	do {__sync_outer_cache(ptep, __pte(0)); set_pte_ext(ptep, __pte(0), 0); } while (0)
 
 #if !defined(CONFIG_L2X0_INSTRUCTION_ONLY)
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index b9c911c..bbb1d96 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -80,6 +80,7 @@
 extern void cpu_dcache_clean_area(void *, int);
 extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
 extern void cpu_set_pte_ext(pte_t *ptep, pteval_t pte, unsigned int ext);
+extern void cpu_uncache_pte_ext(pte_t *ptep);
 extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
 
 /* These three are private to arch/arm/kernel/suspend.c */
@@ -92,6 +93,7 @@
 #define cpu_do_idle			processor._do_idle
 #define cpu_dcache_clean_area		processor.dcache_clean_area
 #define cpu_set_pte_ext			processor.set_pte_ext
+#define cpu_uncache_pte_ext		processor.uncache_pte_ext
 #define cpu_do_switch_mm		processor.switch_mm
 
 /* These three are private to arch/arm/kernel/suspend.c */
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
old mode 100644
new mode 100755
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
old mode 100644
new mode 100755
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
old mode 100644
new mode 100755
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index cf73a7f..7c69deb 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -42,6 +42,7 @@
 
 lib-$(CONFIG_ARCH_RPC)		+= ecard.o io-acorn.o floppydma.o
 lib-$(CONFIG_ARCH_SHARK)	+= io-shark.o
+lib-$(CONFIG_COMCERTO_ZONE_DMA_NCNB) += atomic.o
 
 $(obj)/csumpartialcopy.o:	$(obj)/csumpartialcopygeneric.S
 $(obj)/csumpartialcopyuser.o:	$(obj)/csumpartialcopygeneric.S
diff --git a/arch/arm/lib/atomic.c b/arch/arm/lib/atomic.c
new file mode 100644
index 0000000..b460d00
--- /dev/null
+++ b/arch/arm/lib/atomic.c
@@ -0,0 +1,48 @@
+#include <linux/spinlock.h>
+#include <linux/export.h>
+#include <asm/atomic.h>
+
+static DEFINE_RAW_SPINLOCK(atomic_lock);
+
+struct virtual_zone arm_dma_zone; /* initialized in arch/arm/mm/mmu.c::map_lowmem() */
+EXPORT_SYMBOL(arm_dma_zone);
+
+int comcerto_atomic_add(int i, atomic_t *v)
+{
+	unsigned long flags;
+	int result;
+
+	raw_spin_lock_irqsave(&atomic_lock, flags);
+	v->counter += i;
+	result = v->counter;
+	raw_spin_unlock_irqrestore(&atomic_lock, flags);
+
+	return result;
+}
+EXPORT_SYMBOL(comcerto_atomic_add);
+
+int comcerto_atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+	unsigned long flags;
+	int result;
+
+	raw_spin_lock_irqsave(&atomic_lock, flags);
+	result = v->counter;
+	if (likely(result == old))
+		v->counter = new;
+	raw_spin_unlock_irqrestore(&atomic_lock, flags);
+
+	return result;
+}
+EXPORT_SYMBOL(comcerto_atomic_cmpxchg);
+
+void comcerto_atomic_clear_mask(unsigned long mask, unsigned long *addr)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&atomic_lock, flags);
+	*addr &= ~mask;
+	raw_spin_unlock_irqrestore(&atomic_lock, flags);
+}
+EXPORT_SYMBOL(comcerto_atomic_clear_mask);
+
diff --git a/arch/arm/mach-comcerto/Kconfig b/arch/arm/mach-comcerto/Kconfig
old mode 100644
new mode 100755
index c76dff4..075fb86
--- a/arch/arm/mach-comcerto/Kconfig
+++ b/arch/arm/mach-comcerto/Kconfig
@@ -79,6 +79,30 @@
 	  Say Y if you intend to use the Comcerto TDM and be able to change
 	  different parameters through sysfs.
 
+config COMCERTO_CSYS_TPI_CLOCK
+        bool "Comcerto device TPI and CSYS clock control "
+	default n
+	help
+	  Say Y if you intend to use the Comcerto TPI (Cortex A9 JTAG interface) and CSYS clock (Cortex A9 CoreSight module).
+
+config COMCERTO_PCIE_OCC_CLOCK
+        bool "Comcerto device PCIE OCC clock control "
+	default n
+	help
+	  Say Y if you intend to use the Comcerto PCIE OCC clock.
+
+config COMCERTO_SATA_OCC_CLOCK
+        bool "Comcerto device SATA OCC clock control "
+	default n
+	help
+	  Say Y if you intend to use the Comcerto SATA OCC clock.
+
+config COMCERTO_SGMII_OCC_CLOCK
+        bool "Comcerto device SGMII OCC clock control "
+	default n
+	help
+	  Say Y if you intend to use the Comcerto SGMII OCC clock.
+
 config COMCERTO_MEMBUF
 	bool "Comcerto memory buffer driver"
 	default n
@@ -181,6 +205,11 @@
 	select ZONE_DMA
 	default n
 
+config COMCERTO_CUSTOM_SKB_LAYOUT
+	bool "Mindspeed customized skb layout, to reduce NCNB access overhead, when NCNB buffer is used in skb"
+	depends on COMCERTO_ZONE_DMA_NCNB
+	default n
+
 config DSPG_DECT_CSS
 	bool "DSPG DECT CSS"
 	default n
@@ -218,5 +247,37 @@
 	help
 	  Compile the kernel with -O3 instead of -O2 option. Resulting kernel can be a bit faster, but
 	  it will also be bigger.
+
+config COMCERTO_HW_KERNEL_PAGETABLE
+	bool "Use the 2nd HW page table for kernel memory space"
+	select VMSPLIT_2G
+	default n
+	help
+	  By default, Linux uses only one page table at a time, and switches page tables when switching
+	  between processes. Say Y to enable the 2nd hardware page table, which will be used to map kernel
+	  addresses.
+	  Note that because of the way the ARM MMU determines which page table to use, this option can
+	  only be enabled with a 2G/2G userspace/kernel memory split.
+
+config COMCERTO_UNCACHED_DMA
+	bool "Make pages uncacheable when doing DMA operations"
+	depends on COMCERTO_HW_KERNEL_PAGETABLE
+	default n
+	help
+	  When transferring ownership of a page to a device through the DMA API, make the page uncacheable
+	  for the duration of the transfer. This makes the 2nd cache invalidate (that was needed because
+	  of the possibility of speculative accesses by the A9 cores) unnecessary, which can increase
+	  performance during heavy IO workloads. The page tables will be more complex though, resulting in
+	  more TLB misses when a DMA transfer is going on.
+
+config COMCERTO_SPLICE_READ_NOCONTIG
+	bool "Use find_get_pages in splice read code"
+	default n
+	help
+	  The splice read code normally calls find_get_pages_contig to retrieve pages mapping the requested
+	  portion of the file to read. However, using find_get_pages works just as well, as the splice code
+	  is able to handle both situations.
+	  Say Y to use find_get_pages instead of find_get_pages_contig, which seems to yield a significant
+	  performance improvement in Samba read tests.
 endmenu
 endif
diff --git a/arch/arm/mach-comcerto/Makefile b/arch/arm/mach-comcerto/Makefile
old mode 100644
new mode 100755
index 665e729..d610c02
--- a/arch/arm/mach-comcerto/Makefile
+++ b/arch/arm/mach-comcerto/Makefile
@@ -10,6 +10,7 @@
 obj- :=
 
 obj-$(CONFIG_ARCH_M86XXX) 		    	+= comcerto-2000.o
+obj-$(CONFIG_ARCH_M86XXX) 		    	+= comcerto-vwd.o
 
 obj-$(CONFIG_ARCH_M86XXX)               	+= serdes-c2000.o
 
@@ -24,4 +25,5 @@
 obj-$(CONFIG_C2K_ASIC) 				+= board-c2kasic.o
 obj-$(CONFIG_SMP)				+= platsmp.o headsmp.o
 obj-$(CONFIG_COMCERTO_MSP)			+= msp/
-obj-$(CONFIG_HOTPLUG_CPU)               	+= hotplug.o
+obj-$(CONFIG_HOTPLUG_CPU)			+= hotplug.o
+obj-$(CONFIG_COMCERTO_CSYS_TPI_CLOCK)		+= comcerto-tpicsys.o
diff --git a/arch/arm/mach-comcerto/board-c2kasic.c b/arch/arm/mach-comcerto/board-c2kasic.c
index 0b7329d..5e6d726 100644
--- a/arch/arm/mach-comcerto/board-c2kasic.c
+++ b/arch/arm/mach-comcerto/board-c2kasic.c
@@ -242,11 +242,22 @@
 	int dummy;
 };
 
+struct spi_controller_data {
+        u8 poll_mode;   /* 0 for contoller polling mode */
+        u8 type;        /* SPI/SSP/Micrwire */
+        u8 enable_dma;
+        void (*cs_control)(u32 command);
+};
+
 struct spi_platform_data spi_pdata = {
 	.type = 0,
 	.dummy = 0,
 };
 
+struct spi_controller_data spi_ctrl_data =  {
+        .poll_mode = 1,
+};
+
 static struct spi_board_info comcerto_spi_board_info[] = {
 	{
 		/* FIXME: for chipselect-0 */
@@ -257,6 +268,7 @@
 		.irq = -1,
 		.mode = SPI_MODE_3,
 		.platform_data = &spi_pdata,
+                .controller_data = &spi_ctrl_data,
 	},
 
 	{
@@ -268,6 +280,7 @@
 		.irq = -1,
 		.mode = SPI_MODE_3,
 		.platform_data = &spi_pdata,
+                .controller_data = &spi_ctrl_data,
 	},
 
 	{
@@ -278,6 +291,7 @@
 		.irq = -1,
 		.mode = SPI_MODE_3,
 		.platform_data = &spi_pdata,
+                .controller_data = &spi_ctrl_data,
 	},
 
 	{
@@ -288,6 +302,7 @@
 		.irq = -1,
 		.mode = SPI_MODE_3,
 		.platform_data = &spi_pdata,
+                .controller_data = &spi_ctrl_data,
 	},
 
 };
@@ -389,6 +404,47 @@
 };
 #endif
 
+/* --------------------------------------------------------------------
+*  Watchdog
+* -------------------------------------------------------------------- */
+#ifdef CONFIG_MPCORE_WATCHDOG
+static struct resource comcerto_a9wd_resources[] = {
+	{
+		.start	= COMCERTO_TWD_BASE,
+		.end	= COMCERTO_TWD_BASE + 0xFF,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "mpcore_wdt",
+		.start	= IRQ_LOCALWDOG,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device comcerto_a9wd = {
+	.name		= "mpcore_wdt",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(comcerto_a9wd_resources),
+	.resource       = comcerto_a9wd_resources,
+};
+#endif
+
+#ifdef CONFIG_COMCERTO_WATCHDOG
+static struct resource comcerto_wdt_resources[] = {
+	{
+		.start	= COMCERTO_APB_TIMER_BASE + 0xD0,
+		.end	= COMCERTO_APB_TIMER_BASE + 0xD8,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device comcerto_wdt = {
+        .name   = "comcerto_wdt",
+        .id     = -1,
+	.num_resources  = ARRAY_SIZE(comcerto_wdt_resources),
+	.resource       = comcerto_wdt_resources,
+};
+#endif
 
 #if defined(CONFIG_COMCERTO_ELP_SUPPORT)
 /* --------------------------------------------------------------------
@@ -605,6 +661,15 @@
 #if defined(CONFIG_COMCERTO_I2C_SUPPORT)
 		&comcerto_i2c,
 #endif
+
+#if defined (CONFIG_MPCORE_WATCHDOG)
+		&comcerto_a9wd,
+#endif
+
+#if defined(CONFIG_COMCERTO_WATCHDOG)
+		&comcerto_wdt,
+#endif
+
 #if defined(CONFIG_SPI_MSPD_HIGH_SPEED) || defined(CONFIG_SPI2_MSPD_HIGH_SPEED)
 		&comcerto_fast_spi,
 #endif
diff --git a/arch/arm/mach-comcerto/board-c2kevm.c b/arch/arm/mach-comcerto/board-c2kevm.c
old mode 100644
new mode 100755
index 5796db1..7277d92
--- a/arch/arm/mach-comcerto/board-c2kevm.c
+++ b/arch/arm/mach-comcerto/board-c2kevm.c
@@ -231,21 +231,33 @@
 	int dummy;
 };
 
+struct spi_controller_data {
+        u8 poll_mode;   /* 0 for contoller polling mode */
+        u8 type;        /* SPI/SSP/Micrwire */
+        u8 enable_dma;
+        void (*cs_control)(u32 command);
+};
+
 struct spi_platform_data spi_pdata = {
 	.type = 0,
 	.dummy = 0,
 };
 
+struct spi_controller_data spi_ctrl_data =  {
+        .poll_mode = 1,
+};
+
 static struct spi_board_info comcerto_spi_board_info[] = {
 	{
 		/* FIXME: for chipselect-0 */
-		.modalias = "comcerto_spi1",
+		.modalias = "s25fl256s0",
 		.chip_select = 0,
 		.max_speed_hz = 4*1000*1000,
 		.bus_num = 0,
 		.irq = -1,
 		.mode = SPI_MODE_3,
 		.platform_data = &spi_pdata,
+                .controller_data = &spi_ctrl_data,
 	},
 
 	{
@@ -257,6 +269,7 @@
 		.irq = -1,
 		.mode = SPI_MODE_3,
 		.platform_data = &spi_pdata,
+                .controller_data = &spi_ctrl_data,
 	},
 
 	{
@@ -267,6 +280,7 @@
 		.irq = -1,
 		.mode = SPI_MODE_3,
 		.platform_data = &spi_pdata,
+                .controller_data = &spi_ctrl_data,
 	},
 
 	{
@@ -277,6 +291,7 @@
 		.irq = -1,
 		.mode = SPI_MODE_3,
 		.platform_data = &spi_pdata,
+                .controller_data = &spi_ctrl_data,
 	},
 
 };
@@ -378,6 +393,47 @@
 };
 #endif
 
+/* --------------------------------------------------------------------
+*  Watchdog
+* -------------------------------------------------------------------- */
+#ifdef CONFIG_MPCORE_WATCHDOG
+static struct resource comcerto_a9wd_resources[] = {
+	{
+		.start	= COMCERTO_TWD_BASE,
+		.end	= COMCERTO_TWD_BASE + 0xFF,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "mpcore_wdt",
+		.start	= IRQ_LOCALWDOG,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device comcerto_a9wd = {
+	.name		= "mpcore_wdt",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(comcerto_a9wd_resources),
+	.resource       = comcerto_a9wd_resources,
+};
+#endif
+
+#ifdef CONFIG_COMCERTO_WATCHDOG
+static struct resource comcerto_wdt_resources[] = {
+	{
+		.start	= COMCERTO_APB_TIMER_BASE + 0xD0,
+		.end	= COMCERTO_APB_TIMER_BASE + 0xD8,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device comcerto_wdt = {
+        .name   = "comcerto_wdt",
+        .id     = -1,
+	.num_resources  = ARRAY_SIZE(comcerto_wdt_resources),
+	.resource       = comcerto_wdt_resources,
+};
+#endif
 
 #if defined(CONFIG_COMCERTO_ELP_SUPPORT)
 /* --------------------------------------------------------------------
@@ -554,6 +610,15 @@
 #if defined(CONFIG_COMCERTO_I2C_SUPPORT)
 		&comcerto_i2c,
 #endif
+
+#if defined (CONFIG_MPCORE_WATCHDOG)
+		&comcerto_a9wd,
+#endif
+
+#if defined(CONFIG_COMCERTO_WATCHDOG)
+		&comcerto_wdt,
+#endif
+
 #if defined(CONFIG_SPI_MSPD_HIGH_SPEED) || defined(CONFIG_SPI2_MSPD_HIGH_SPEED)
 		&comcerto_fast_spi,
 #endif
diff --git a/arch/arm/mach-comcerto/board-c2krtsm.c b/arch/arm/mach-comcerto/board-c2krtsm.c
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/clock.c b/arch/arm/mach-comcerto/clock.c
old mode 100644
new mode 100755
index f7132af..7ef79a9
--- a/arch/arm/mach-comcerto/clock.c
+++ b/arch/arm/mach-comcerto/clock.c
@@ -310,7 +310,7 @@
 /*
  * Get the reference clock after reading bootstrap
  */
-static unsigned long HAL_get_ref_clk (void)
+unsigned long HAL_get_ref_clk (void)
 {
 	unsigned long clock_freq = 0;
 	unsigned int boot_strap, tmp;
@@ -335,6 +335,7 @@
 
 	return clock_freq;
 }
+EXPORT_SYMBOL(HAL_get_ref_clk);
 
 static unsigned long HAL_get_pll_freq(int pll_no)
 {
@@ -516,123 +517,25 @@
 	return clk_out;
 }
 
-/* All get rate APIs callbacks */
-static unsigned long HAL_get_arm_clk(struct clk *clk)
+/* Get rate API callback */
+static unsigned long HAL_get_clk(struct clk *clk)
 {
 	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
 }
 
-static unsigned long HAL_get_axi_clk(struct clk *clk)
-{
-	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
-}
-
-static unsigned long HAL_get_ddr_clk(struct clk *clk)
-{
-	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
-}
-
-static unsigned long HAL_get_ipsec_eape_clk(struct clk *clk)
-{
-	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
-}
-
-static unsigned long  HAL_get_ipsec_spacc_clk(struct clk *clk)
+/* Get rate API callback for those clocks having Parent */
+static unsigned long HAL_get_parent_clk(struct clk *clk)
 {
 	return clk_get_rate(clk->parent);
 }
-
-static unsigned long  HAL_get_dpi_cie_clk(struct clk *clk)
-{
-	return clk_get_rate(clk->parent);
-}
-
-static unsigned long  HAL_get_dpi_decomp_clk(struct clk *clk)
-{
-	return clk_get_rate(clk->parent);
-}
-
-static unsigned long  HAL_get_gemtx_clk(struct clk *clk)
-{
-	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
-}
-
-static unsigned long HAL_get_hfe_core_clk(struct clk *clk)
-{
-	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
-}
-
-static unsigned long HAL_get_spi_i2c_clk(struct clk *clk)
-{
-	return clk_get_rate(clk->parent);
-}
-
-static unsigned long HAL_get_sata_oob_clk(struct clk *clk)
-{
-	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
-}
-
-static unsigned long HAL_get_sata_pmu_clk(struct clk *clk)
-{
-	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
-}
-
-static unsigned long HAL_get_ext_phy_clk(struct clk *clk)
-{
-	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
-}
-
-static unsigned long  HAL_get_tdmNTG_clk(struct clk *clk)
-{
-	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
-}
-static unsigned long HAL_get_l2cc_clk(struct clk *clk)
-{
-	return HAL_get_clk_freq(clk->clkgen_reg, clk->div_reg);
-}
-
-static unsigned long HAL_get_uart_clk(struct clk *clk)
-{
-	return clk_get_rate(clk->parent);
-}
-
-static unsigned long  HAL_get_dus_clk(struct clk *clk)
-{
-	return clk_get_rate(clk->parent);
-}
-
-static unsigned long  HAL_get_pcie0_clk(struct clk *clk)
-{
-	return clk_get_rate(clk->parent);
-}
-
-static unsigned long  HAL_get_pcie1_clk(struct clk *clk)
-{
-	return clk_get_rate(clk->parent);
-}
-
-static unsigned long  HAL_get_usb0_clk(struct clk *clk)
-{
-	return clk_get_rate(clk->parent);
-}
-
-static unsigned long  HAL_get_usb1_clk(struct clk *clk)
-{
-	return clk_get_rate(clk->parent);
-}
-
-static unsigned long  HAL_get_sata_clk(struct clk *clk)
-{
-	return clk_get_rate(clk->parent);
-}
-
+/* Specific Get rate API callback for arm peripherals */
 static unsigned long  HAL_get_arm_peri_clk(struct clk *clk)
 {
 	return clk_get_rate(clk->parent)/4 ;
 }
 
-/* All set rate APIs callbacks */
-static int HAL_set_gemtx_clk(struct clk *clk,unsigned long rate)
+/* Set rate APIs callbacks */
+static int HAL_set_clk(struct clk *clk,unsigned long rate)
 {
 	struct clk *clk_parent;
 	/* Get the parent clock */
@@ -647,126 +550,6 @@
 		return -EINVAL;
 }
 
-static int HAL_set_arm_clk(struct clk *clk,unsigned long rate)
-{
-	struct clk *clk_parent;
-	/* Get the parent clock */
-	clk_parent=clk_get_parent(clk);
-	if ( clk_parent && rate <= clk_parent->rate ){
-		/* Set the divider value to reg */
-		HAL_set_clk_divider(rate,clk->clkgen_reg,clk->div_reg);
-		/* Set the rate value to clk structure */
-		clk->rate=rate;
-		return 0;
-	}else
-		return -EINVAL;
-}
-
-static int HAL_set_l2cc_clk(struct clk *clk,unsigned long rate)
-{
-	struct clk *clk_parent;
-	/* Get the parent clock */
-	clk_parent=clk_get_parent(clk);
-	if ( clk_parent && rate <= clk_parent->rate ){
-		/* Set the divider value to reg */
-		HAL_set_clk_divider(rate,clk->clkgen_reg,clk->div_reg);
-		/* Set the rate value to clk structure */
-		clk->rate=rate;
-		return 0;
-	}else
-		return -EINVAL;
-}
-
-static int HAL_set_axi_clk(struct clk *clk,unsigned long rate)
-{
-	struct clk *clk_parent;
-	/* Get the parent clock */
-	clk_parent=clk_get_parent(clk);
-	if ( clk_parent && rate <= clk_parent->rate ){
-		/* Set the divider value to reg */
-		HAL_set_clk_divider(rate,clk->clkgen_reg,clk->div_reg);
-		/* Set the rate value to clk structure */
-		clk->rate=rate;
-		return 0;
-	}else
-		return -EINVAL;
-}
-
-static int HAL_set_hfe_core_clk(struct clk *clk,unsigned long rate)
-{
-	struct clk *clk_parent;
-	/* Get the parent clock */
-	clk_parent=clk_get_parent(clk);
-	if ( clk_parent && rate <= clk_parent->rate ){
-		/* Set the divider value to reg */
-		HAL_set_clk_divider(rate,clk->clkgen_reg,clk->div_reg);
-		/* Set the rate value to clk structure */
-		clk->rate=rate;
-		return 0;
-	}else
-		return -EINVAL;
-}
-
-static int HAL_set_tdmNTG_clk(struct clk *clk,unsigned long rate)
-{
-	struct clk *clk_parent;
-	/* Get the parent clock */
-	clk_parent=clk_get_parent(clk);
-	if ( clk_parent && rate <= clk_parent->rate ){
-		/* Set the divider value to reg */
-		HAL_set_clk_divider(rate,clk->clkgen_reg,clk->div_reg);
-		/* Set the rate value to clk structure */
-		clk->rate=rate;
-		return 0;
-	}else
-		return -EINVAL;
-}
-
-static int HAL_set_sata_oob_clk(struct clk *clk,unsigned long rate)
-{
-	struct clk *clk_parent;
-	/* Get the parent clock */
-	clk_parent=clk_get_parent(clk);
-	if ( clk_parent && rate <= clk_parent->rate ){
-		/* Set the divider value to reg */
-		HAL_set_clk_divider(rate,clk->clkgen_reg,clk->div_reg);
-		/* Set the rate value to clk structure */
-		clk->rate=rate;
-		return 0;
-	}else
-		return -EINVAL;
-}
-
-static int HAL_set_sata_pmu_clk(struct clk *clk,unsigned long rate)
-{
-	struct clk *clk_parent;
-	/* Get the parent clock */
-	clk_parent=clk_get_parent(clk);
-	if ( clk_parent && rate <= clk_parent->rate ){
-		/* Set the divider value to reg */
-		HAL_set_clk_divider(rate,clk->clkgen_reg,clk->div_reg);
-		/* Set the rate value to clk structure */
-		clk->rate=rate;
-		return 0;
-	}else
-		return -EINVAL;
-}
-
-static int HAL_set_ext_phy_clk(struct clk *clk,unsigned long rate)
-{
-	struct clk *clk_parent;
-	/* Get the parent clock */
-	clk_parent=clk_get_parent(clk);
-	if ( clk_parent && rate <= clk_parent->rate ){
-		/* Set the divider value to reg */
-		HAL_set_clk_divider(rate,clk->clkgen_reg,clk->div_reg);
-		/* Set the rate value to clk structure */
-		clk->rate=rate;
-		return 0;
-	}else
-		return -EINVAL;
-}
-
 /* Initization of clk structure for individual device */
 
 static struct clk clk_pll0 = {
@@ -793,8 +576,8 @@
 	.clkgen_reg  = GEMTX_CLK_CNTRL,
 	.div_reg     = GEMTX_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_gemtx_clk,
-	.set_rate    = HAL_set_gemtx_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
 static struct clk ddr_clk = {
@@ -803,7 +586,7 @@
 	.clkgen_reg  = DDR_CLK_CNTRL,
 	.div_reg     = DDR_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_ddr_clk,
+	.get_rate    = HAL_get_clk,
 };
 
 static struct clk arm_clk = {
@@ -812,8 +595,8 @@
 	.clkgen_reg  = A9DP_CLK_CNTRL,
 	.div_reg     = A9DP_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_arm_clk,
-	.set_rate    = HAL_set_arm_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
 static struct clk l2cc_clk = {
@@ -822,8 +605,8 @@
 	.clkgen_reg  = L2CC_CLK_CNTRL,
 	.div_reg     = L2CC_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_l2cc_clk,
-	.set_rate    = HAL_set_l2cc_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
 static struct clk axi_clk = {
@@ -832,8 +615,8 @@
 	.clkgen_reg  = AXI_CLK_CNTRL_0,
 	.div_reg     = AXI_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_axi_clk,
-	.set_rate    = HAL_set_axi_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
 static struct clk uart_clk = { /* Legacy UART */
@@ -841,7 +624,7 @@
 	.name        = "uart",
 	.enable_reg  = AXI_CLK_CNTRL_1,
 	.enable_mask = CLK_DOMAIN_UART_MASK,
-	.get_rate    = HAL_get_uart_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 
 static struct clk ipsec_eape_clk = {
@@ -850,7 +633,7 @@
 	.clkgen_reg  = IPSEC_CLK_CNTRL,
 	.div_reg     = IPSEC_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_ipsec_eape_clk,
+	.get_rate    = HAL_get_clk,
 };
 
 static struct clk ipsec_spacc_clk = {       /* IPSEC spacc clock for Elliptic EPN1802*/
@@ -858,7 +641,7 @@
 	.name        = "ipsec_spacc",
 	.enable_reg  = AXI_CLK_CNTRL_1,
 	.enable_mask = CLK_DOMAIN_IPSEC_SPACC_MASK,
-	.get_rate    = HAL_get_ipsec_spacc_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 
 static struct clk dpi_cie_clk = {       /* DPI cie clock*/
@@ -866,7 +649,7 @@
 	.name        = "dpi_cie",
 	.enable_reg  = AXI_CLK_CNTRL_0,
 	.enable_mask = CLK_DOMAIN_DPI_CIE_MASK,
-	.get_rate    = HAL_get_dpi_cie_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 
 static struct clk dpi_decomp_clk = {       /* DPI decomp clock*/
@@ -874,7 +657,7 @@
 	.name        = "dpi_decomp",
 	.enable_reg  = AXI_CLK_CNTRL_0,
 	.enable_mask = CLK_DOMAIN_DPI_DECOMP_MASK,
-	.get_rate    = HAL_get_dpi_decomp_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 
 static struct clk DUS_clk = { /* DMA,FAST-UART and SMI clock */
@@ -882,7 +665,7 @@
 	.name        = "DUS",
 	.enable_reg  = AXI_CLK_CNTRL_1,
 	.enable_mask = CLK_DOMAIN_DUS_MASK,
-	.get_rate    = HAL_get_dus_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 
 static struct clk arm_peri_clk = {
@@ -899,8 +682,8 @@
 	.clkgen_reg  = PFE_CLK_CNTRL,
 	.div_reg     = PFE_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_hfe_core_clk,
-	.set_rate    = HAL_set_hfe_core_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
 static struct clk spi_i2c_clk = {
@@ -908,7 +691,7 @@
 	.name        = "spi_i2c",
 	.enable_reg  = AXI_CLK_CNTRL_1,
 	.enable_mask = CLK_DOMAIN_SPI_I2C_MASK,
-	.get_rate    = HAL_get_spi_i2c_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 
 static struct clk tdmNTG_clk = {
@@ -917,8 +700,8 @@
 	.clkgen_reg  = TDMNTG_REF_CLK_CNTRL,
 	.div_reg     = TDMNTG_REF_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_tdmNTG_clk,
-	.set_rate    = HAL_set_tdmNTG_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
 static struct clk pcie0_clk = {
@@ -926,7 +709,7 @@
 	.name        = "pcie0",
 	.enable_reg  = AXI_CLK_CNTRL_2,
 	.enable_mask = CLK_DOMAIN_PCIE0_MASK,
-	.get_rate    = HAL_get_pcie0_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 
 static struct clk pcie1_clk = {
@@ -934,7 +717,7 @@
 	.name        = "pcie1",
 	.enable_reg  = AXI_CLK_CNTRL_2,
 	.enable_mask = CLK_DOMAIN_PCIE1_MASK,
-	.get_rate    = HAL_get_pcie1_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 
 static struct clk usb0_clk = {
@@ -942,7 +725,7 @@
 	.name        = "usb0",
 	.enable_reg  = AXI_CLK_CNTRL_2,
 	.enable_mask = CLK_DOMAIN_USB0_MASK,
-	.get_rate    = HAL_get_usb0_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 
 static struct clk usb1_clk = {
@@ -950,7 +733,7 @@
 	.name        = "usb1",
 	.enable_reg  = AXI_CLK_CNTRL_2,
 	.enable_mask = CLK_DOMAIN_USB1_MASK,
-	.get_rate    = HAL_get_usb1_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 
 static struct clk sata_clk = {            /* SATA AXI clock */
@@ -958,7 +741,7 @@
 	.name        = "sata",
 	.enable_reg  = AXI_CLK_CNTRL_2,
 	.enable_mask = CLK_DOMAIN_SATA_MASK,
-	.get_rate    = HAL_get_sata_clk,
+	.get_rate    = HAL_get_parent_clk,
 };
 static struct clk sata_oob_clk = {
 	.name        = "sata_oob",	  /* SATA PMU alive clock */
@@ -966,8 +749,8 @@
 	.clkgen_reg  = SATA_OOB_CLK_CNTRL,
 	.div_reg     = SATA_OOB_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_sata_oob_clk,
-	.set_rate    = HAL_set_sata_oob_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
 static struct clk sata_pmu_clk = {
@@ -976,40 +759,99 @@
 	.clkgen_reg  = SATA_PMU_CLK_CNTRL,
 	.div_reg     = SATA_PMU_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_sata_pmu_clk,
-	.set_rate    = HAL_set_sata_pmu_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
 static struct clk ext_phy0_clk = {
 	.name	     = "ext_phy0",
-        .enable_reg  = EXTPHY0_CLK_CNTRL,
-        .clkgen_reg  = EXTPHY0_CLK_CNTRL,
+	.enable_reg  = EXTPHY0_CLK_CNTRL,
+	.clkgen_reg  = EXTPHY0_CLK_CNTRL,
 	.div_reg     = EXTPHY0_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_ext_phy_clk,
-	.set_rate    = HAL_set_ext_phy_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
 static struct clk ext_phy1_clk = {
 	.name	     = "ext_phy1",
-        .enable_reg  = EXTPHY1_CLK_CNTRL,
-        .clkgen_reg  = EXTPHY1_CLK_CNTRL,
+	.enable_reg  = EXTPHY1_CLK_CNTRL,
+	.clkgen_reg  = EXTPHY1_CLK_CNTRL,
 	.div_reg     = EXTPHY1_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_ext_phy_clk,
-	.set_rate    = HAL_set_ext_phy_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
 static struct clk ext_phy2_clk = {
 	.name	     = "ext_phy2",
-        .enable_reg  = EXTPHY2_CLK_CNTRL,
-        .clkgen_reg  = EXTPHY2_CLK_CNTRL,
+	.enable_reg  = EXTPHY2_CLK_CNTRL,
+	.clkgen_reg  = EXTPHY2_CLK_CNTRL,
 	.div_reg     = EXTPHY2_CLK_DIV_CNTRL,
 	.enable_mask = CLK_DOMAIN_MASK,
-	.get_rate    = HAL_get_ext_phy_clk,
-	.set_rate    = HAL_set_ext_phy_clk,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
 };
 
+static struct clk tpi_clk = {
+	.name	     = "tpi",
+	.enable_reg  = TPI_CLK_CNTRL,
+	.clkgen_reg  = TPI_CLK_CNTRL,
+	.div_reg     = TPI_CLK_DIV_CNTRL,
+	.enable_mask = CLK_DOMAIN_MASK,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
+};
+
+static struct clk csys_clk = {
+	.name	     = "csys",
+	.enable_reg  = CSYS_CLK_CNTRL,
+	.clkgen_reg  = CSYS_CLK_CNTRL,
+	.div_reg     = CSYS_CLK_DIV_CNTRL,
+	.enable_mask = CLK_DOMAIN_MASK,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
+};
+
+static struct clk tsuntg_clk = {
+	.name	     = "tsuntg",
+	.enable_reg  = TSUNTG_REF_CLK_CNTRL,
+	.clkgen_reg  = TSUNTG_REF_CLK_CNTRL,
+	.div_reg     = TSUNTG_REF_CLK_DIV_CNTRL,
+	.enable_mask = CLK_DOMAIN_MASK,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
+};
+
+static struct clk sata_occ_clk = {
+	.name	     = "sata_occ",
+	.enable_reg  = SATA_OCC_CLK_CNTRL,
+	.clkgen_reg  = SATA_OCC_CLK_CNTRL,
+	.div_reg     = SATA_OCC_CLK_DIV_CNTRL,
+	.enable_mask = CLK_DOMAIN_MASK,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
+};
+
+static struct clk pcie_occ_clk = {
+	.name	     = "pcie_occ",
+	.enable_reg  = PCIE_OCC_CLK_CNTRL,
+	.clkgen_reg  = PCIE_OCC_CLK_CNTRL,
+	.div_reg     = PCIE_OCC_CLK_DIV_CNTRL,
+	.enable_mask = CLK_DOMAIN_MASK,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
+};
+
+static struct clk sgmii_occ_clk = {
+	.name	     = "sgmii_occ",
+	.enable_reg  = SGMII_OCC_CLK_CNTRL,
+	.clkgen_reg  = SGMII_OCC_CLK_CNTRL,
+	.div_reg     = SGMII_OCC_CLK_DIV_CNTRL,
+	.enable_mask = CLK_DOMAIN_MASK,
+	.get_rate    = HAL_get_clk,
+	.set_rate    = HAL_set_clk,
+};
 
 /* These clocks are visible outside this module
  * and can be initialized , this list could be expanded
@@ -1045,6 +887,12 @@
 	&ext_phy0_clk,
 	&ext_phy1_clk,
 	&ext_phy2_clk,
+	&tpi_clk,
+	&csys_clk,
+	&tsuntg_clk,
+	&sata_occ_clk,
+	&pcie_occ_clk,
+	&sgmii_occ_clk,
 };
 
 static struct clk_lookup c2k_clksreg[] = {
@@ -1077,6 +925,12 @@
 	{ .clk = &ext_phy0_clk,     .con_id = "ext_phy0"},
 	{ .clk = &ext_phy1_clk,     .con_id = "ext_phy1"},
 	{ .clk = &ext_phy2_clk,     .con_id = "ext_phy2"},
+	{ .clk = &tpi_clk,     	    .con_id = "tpi"},
+	{ .clk = &csys_clk,         .con_id = "csys"},
+	{ .clk = &tsuntg_clk,       .con_id = "tsuntg"},
+	{ .clk = &sata_occ_clk,     .con_id = "sata_occ"},
+	{ .clk = &pcie_occ_clk,     .con_id = "pcie_occ"},
+	{ .clk = &sgmii_occ_clk,    .con_id = "sgmii_occ"},
 };
 
 /* Initilize all the available clocks */
@@ -1150,13 +1004,17 @@
 		if (clk->usecount > 0)
 			continue;
 
-		/* FIXME Currently We Are Only Disabling The EXT PHY0/1/2 
-		 * Clock For No Harm.
+		/* FIXME Currently there is no clock FW support for the
+                 * following clocks in corresponding driver . So skipping these
+		 * clocks from by default disable state.
+                 * All other unused clocks will be disabled.
                 */
-		if ( !strcmp(clk->name, "ext_phy0") || !strcmp(clk->name, "ext_phy1")
-						   || !strcmp(clk->name, "ext_phy2") ) 
+		if ( strcmp(clk->name, "hfe_core") &&
+				strcmp(clk->name, "ipsec_eape") &&
+				strcmp(clk->name, "pll3") &&
+				strcmp(clk->name, "arm_peri") )
 		{
-			pr_debug("Clocks: disabled unused %s\n", clk->name);
+			pr_info("Clocks: disabled unused %s\n", clk->name);
 			__clk_disable_unused(clk);
 		}
 	}
diff --git a/arch/arm/mach-comcerto/comcerto-2000.c b/arch/arm/mach-comcerto/comcerto-2000.c
old mode 100644
new mode 100755
index 85589cd..2f736d9
--- a/arch/arm/mach-comcerto/comcerto-2000.c
+++ b/arch/arm/mach-comcerto/comcerto-2000.c
@@ -36,6 +36,8 @@
 #include <linux/dma-mapping.h>
 
 #include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
 #include <linux/smp.h>
 #include <linux/uio_driver.h>
 
@@ -344,22 +346,6 @@
 	int i;
 #endif
 
-	struct clk *l2cc_clk;
-
-	/* Get the L2CC clock */
-	l2cc_clk = clk_get(NULL,"l2cc");
-	if (IS_ERR(l2cc_clk)) {
-		pr_err("%s: Unable to obtain L2CC clock: %ld\n",__func__,PTR_ERR(l2cc_clk));
-		/* L2CC initilization cannot proceed from here */
-		BUG();
-	}
-
-	/* Enable the L2CC clk  */
-	if (clk_enable(l2cc_clk)){
-		pr_err("%s: Unable to enable L2CC clock:\n",__func__);
-		/* L2CC initilization cannot proceed from here */
-		BUG();
-	}
 
 	l2cache_base = (void *)COMCERTO_L310_VADDR;
 	BUG_ON(!l2cache_base);
@@ -367,11 +353,21 @@
 	/* Set Latency of L2CC to minimum (i.e. 1 cycle) */
 	l2x0_latency(1, 1, 1, 1, 1, 1);
 
+	/* Set L2 address filtering, use L2CC M1 port for DDR accesses */
+	writel(0x80000000, l2cache_base + L2X0_ADDR_FILTER_END);
+	writel(0x00000000 | L2X0_ADDR_FILTER_EN, l2cache_base + L2X0_ADDR_FILTER_START);
+
 	associativity = (COMCERTO_L2CC_ASSOCIATIVITY_8WAY << COMCERTO_L2CC_ASSOCIATIVITY_SHIFT) & COMCERTO_L2CC_ASSOCIATIVITY_MASK;
 	waysize = (COMCERTO_L2CC_ASSOCIATIVITY_32KB << COMCERTO_L2CC_WAYSIZE_SHIFT) & COMCERTO_L2CC_WAYSIZE_MASK;
 	aux_val = associativity | waysize;
 	aux_mask = (COMCERTO_L2CC_ASSOCIATIVITY_MASK | COMCERTO_L2CC_WAYSIZE_MASK);
 
+	/* Shareable attribute override enable */
+	/* This prevents the cache from changing "normal memory/non-cacheable" accesses to
+	"normal memory/cacheable/writethrough no read/write allocate"*/
+	aux_val |= (1 << 22);
+	aux_mask |= (1 << 22);
+
 	/* Write allocate override, no write allocate */
 	aux_val |= (1 << 23);
 	aux_mask |= (3 << 23);
@@ -430,10 +426,30 @@
 
 static int comcerto_ahci_init(struct device *dev, void __iomem *mmio)
 {
+	struct serdes_regs_s *p_sata_phy_reg_file;
+	int serdes_regs_size;
         u32 val;
-        val = readl(COMCERTO_GPIO_SYSTEM_CONFIG);
+	int ref_clk_24;
 
- 	//Bring SATA PMU and OOB out of reset
+	val = readl(COMCERTO_GPIO_SYSTEM_CONFIG);
+	ref_clk_24 = val & (BIT_5_MSK|BIT_7_MSK);
+
+	if(ref_clk_24)
+	{
+		p_sata_phy_reg_file = &sata_phy_reg_file_24[0];
+		serdes_regs_size = sizeof(sata_phy_reg_file_24);
+		printk(KERN_INFO "SATA Serdes: 24Mhz ref clk\n");
+	}
+	else
+	{
+		p_sata_phy_reg_file = &sata_phy_reg_file_48[0];
+		serdes_regs_size = sizeof(sata_phy_reg_file_48);
+		printk(KERN_INFO "SATA Serdes: 48Mhz ref clk\n");
+	}
+
+	//Take SATA AXI domain out of reset
+	c2000_block_reset(COMPONENT_AXI_SATA,0);
+	//Bring SATA PMU and OOB out of reset
 	c2000_block_reset(COMPONENT_SATA_PMU,0);
 	c2000_block_reset(COMPONENT_SATA_OOB,0);
 
@@ -447,8 +463,8 @@
 			c2000_block_reset(COMPONENT_SERDES_SATA0,0);
 
                         /* Serdes Initialization. */
-                        if( serdes_phy_init(SERDES_PHY1,  sata0_phy_reg_file,
-                                                sizeof(sata0_phy_reg_file) / sizeof(serdes_regs_t),
+                        if( serdes_phy_init(SERDES_PHY1,  p_sata_phy_reg_file,
+                                                serdes_regs_size / sizeof(serdes_regs_t),
                                                 SD_DEV_TYPE_SATA) )
                         {
                                 printk(KERN_ERR "%s: Failed to initialize serdes1 !!\n", __func__);
@@ -465,8 +481,8 @@
 			c2000_block_reset(COMPONENT_SERDES_SATA1,0);
 
                         /* Serdes Initialization. */
-                        if( serdes_phy_init(SERDES_PHY2,  sata0_phy_reg_file,
-                                                sizeof(sata0_phy_reg_file) / sizeof(serdes_regs_t),
+                        if( serdes_phy_init(SERDES_PHY2,  p_sata_phy_reg_file,
+                                                serdes_regs_size / sizeof(serdes_regs_t),
                                                 SD_DEV_TYPE_SATA) )
                         {
                                 printk(KERN_ERR "%s: Failed to initialize serdes2 !!\n", __func__);
@@ -480,6 +496,24 @@
 }
 #endif
 
+#if defined(CONFIG_COMCERTO_UART0_SUPPORT) || defined(CONFIG_COMCERTO_UART1_SUPPORT)
+#define UART_DWC_USR	0x1F
+static int fastuart_handle_irq(struct uart_port *p)
+{
+	unsigned int iir = p->serial_in(p, UART_IIR);
+	unsigned int dummy;
+	if (serial8250_handle_irq(p, iir)) {
+		return 1;
+	} else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
+		/* Clear the USR */
+		dummy = p->serial_in(p, UART_DWC_USR);
+		return 1;
+	}
+
+	return 0;
+}
+#endif
+
 static struct resource comcerto_pmu_resources[] = {
 	{
 		.start	= IRQ_A9_PMU0,
@@ -510,6 +544,7 @@
                 .mapbase        = COMCERTO_AXI_UART1_BASE,
 		.membase	= (void *)COMCERTO_AXI_UART1_VADDR,
                 .irq            = IRQ_UART1,
+		.handle_irq	= fastuart_handle_irq,
                 .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
                 .iotype         = UPIO_MEM,
                 .regshift       = 2,
@@ -520,6 +555,7 @@
                 .mapbase        = COMCERTO_AXI_UART0_BASE,
                 .membase        = (void *)COMCERTO_AXI_UART0_VADDR,
                 .irq            = IRQ_UART0,
+		.handle_irq	= fastuart_handle_irq,
                 .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
                 .iotype         = UPIO_MEM,
                 .regshift       = 2,
@@ -747,6 +783,16 @@
 };
 #endif
 
+#if defined(CONFIG_COMCERTO_CSYS_TPI_CLOCK) 
+struct platform_device comcerto_device_tpi_csys_clk = {
+	.name		= "tpi_csys",
+	.id		= -1,
+	.dev		=  {
+		.platform_data		= NULL,
+	},
+};
+#endif
+
 int usb3_clk_internal = 1;
 static int __init get_usb3_clk_mode(char *str)
 {
@@ -857,11 +903,14 @@
 	&comcerto_device_epavis_cie,
 	&comcerto_device_epavis_decomp,
 #endif
+#if defined(CONFIG_COMCERTO_CSYS_TPI_CLOCK)
+	&comcerto_device_tpi_csys_clk,
+#endif
 };
 
 void __init device_init(void)
 {
-	struct clk *axi_clk,*ddr_clk,*arm_clk;
+	struct clk *axi_clk,*ddr_clk,*arm_clk,*l2cc_clk;
 	HAL_clk_div_backup_relocate_table ();
 	system_rev = (readl(COMCERTO_GPIO_DEVICE_ID_REG) >> 24) & 0xf;
 
@@ -916,6 +965,21 @@
 		/* System cannot proceed from here */
 		BUG();
 	}
+
+	/* Get the L2CC clock */
+	l2cc_clk = clk_get(NULL,"l2cc");
+	if (IS_ERR(l2cc_clk)) {
+		pr_err("%s: Unable to obtain L2CC clock: %ld\n",__func__,PTR_ERR(l2cc_clk));
+		/* L2CC initilization cannot proceed from here */
+		BUG();
+	}
+
+	/* Enable the L2CC clk  */
+	if (clk_enable(l2cc_clk)){
+		pr_err("%s: Unable to enable L2CC clock:\n",__func__);
+		/* L2CC initilization cannot proceed from here */
+		BUG();
+	}
 	
 #ifdef CONFIG_CACHE_L2X0
 	comcerto_l2cc_init();
diff --git a/arch/arm/mach-comcerto/comcerto-tpicsys.c b/arch/arm/mach-comcerto/comcerto-tpicsys.c
new file mode 100644
index 0000000..e11e4f8
--- /dev/null
+++ b/arch/arm/mach-comcerto/comcerto-tpicsys.c
@@ -0,0 +1,118 @@
+/*
+ *  linux/arch/arm/mach-comcerto/comcerto-tpicsys.c
+ *
+ *  Copyright (C) 2008 Mindspeed Technologies, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/err.h>
+#include <linux/module.h>
+
+struct clk *clk_tpi,*clk_csys;
+
+static int tpi_csys_probe(struct platform_device *pdev)
+{
+	int err=0;
+	/* Get the refrence to TPI clk structure */
+	clk_tpi = clk_get(NULL,"tpi");
+
+	/* Error Handling , if no TPI clock reference: return error */
+	if (IS_ERR(clk_tpi)) {
+		pr_err("%s: Unable to obtain  clock: %ld\n",__func__,PTR_ERR(clk_tpi));
+		err = PTR_ERR(clk_tpi);
+		goto err_tpi_get;
+	}
+
+	/* Enable the TPI clock ,required for cortex A9 JTAG */
+	err = clk_enable(clk_tpi);
+	if (err){
+		pr_err("%s: TPI clock failed to enable:\n",__func__);
+		goto err_tpi_enable;
+	}
+
+	/* Get the CSYS clk structure ,required ofr cortex A9 coresight*/
+	clk_csys = clk_get(NULL,"csys");
+
+	/* Error Handling , if no CSYS clock reference: return error 
+	 * Disable the TPI clock enabled before. 
+	 */
+	if (IS_ERR(clk_csys)) {
+		pr_err("%s: Unable to obtain  clock: %ld\n",__func__,PTR_ERR(clk_csys));
+		err = PTR_ERR(clk_csys);
+ 		goto err_csys_get;
+	}
+
+	/*Enable the  CSYS clock */
+	err = clk_enable(clk_csys);
+	if (err){
+		pr_err("%s: CSYS clock failed to enable:\n",__func__);
+		/* Disable the CSYS(A9 coresight clock also */ 
+		goto err_csys_enable;
+	}
+
+	return 0;
+
+err_csys_enable:
+	clk_put(clk_csys);
+err_csys_get:
+	clk_disable(clk_tpi);
+err_tpi_enable:
+	clk_put(clk_tpi);
+err_tpi_get:
+	return err;
+}
+
+static int tpi_csys_remove(struct platform_device *pdev)
+{
+
+	/* Disable the TPI/CSYS clock */
+	clk_disable(clk_tpi);
+	clk_put(clk_tpi);
+
+	clk_disable(clk_csys);
+	clk_put(clk_csys);
+
+	return 0;
+}
+	
+
+/* Structure for Device Driver */
+static struct platform_driver tpi_csys_platform_driver = {
+	.probe = tpi_csys_probe,
+	.remove = tpi_csys_remove,
+	.driver = {
+		.name = "tpi_csys",
+	},	
+};
+
+static int comcerto_tpi_csys_init(void)
+{
+	return platform_driver_register(&tpi_csys_platform_driver);
+}
+
+static void comcerto_tpi_csys_exit(void)
+{
+	platform_driver_unregister(&tpi_csys_platform_driver);
+}
+
+module_init(comcerto_tpi_csys_init);
+module_exit(comcerto_tpi_csys_exit);
+
+MODULE_DESCRIPTION("Comcerto TPI/CSYS");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-comcerto/comcerto-vwd.c b/arch/arm/mach-comcerto/comcerto-vwd.c
new file mode 100644
index 0000000..c5431d9
--- /dev/null
+++ b/arch/arm/mach-comcerto/comcerto-vwd.c
@@ -0,0 +1,55 @@
+/*
+ *  linux/arch/arm/mach-comcerto/comcerto-vwd.c
+ *
+ *  Copyright (C) 2011 Mindspeed Technologies, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/module.h>
+
+
+static int comcerto_wifi_rx_dummy_hdlr(int (*hdlr)(struct sk_buff *skb));
+static int (*vwd_rx_hdlr)(struct sk_buff *) = comcerto_wifi_rx_dummy_hdlr;
+
+static int comcerto_wifi_rx_dummy_hdlr(int (*hdlr)(struct sk_buff *skb))
+{
+	return -1;
+}
+
+int comcerto_wifi_rx_fastpath_register(int (*hdlr)(struct sk_buff *skb))
+{
+	printk(KERN_INFO "%s:%d VWD Tx function registered\n", __func__, __LINE__ );
+	vwd_rx_hdlr = hdlr;
+
+	return 0;
+}
+
+void comcerto_wifi_rx_fastpath_unregister(void)
+{
+	printk(KERN_INFO "%s:%d VWD Tx function unregistered\n", __func__, __LINE__ );
+	vwd_rx_hdlr = comcerto_wifi_rx_dummy_hdlr;
+
+	return;
+}
+
+int comcerto_wifi_rx_fastpath(struct sk_buff *skb)
+{
+	return vwd_rx_hdlr(skb);
+
+}
+
+EXPORT_SYMBOL(comcerto_wifi_rx_fastpath_register);
+EXPORT_SYMBOL(comcerto_wifi_rx_fastpath_unregister);
+EXPORT_SYMBOL(comcerto_wifi_rx_fastpath);
diff --git a/arch/arm/mach-comcerto/dma.c b/arch/arm/mach-comcerto/dma.c
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/headsmp.S b/arch/arm/mach-comcerto/headsmp.S
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/hotplug.c b/arch/arm/mach-comcerto/hotplug.c
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/include/mach/c2k_dma.h b/arch/arm/mach-comcerto/include/mach/c2k_dma.h
index 765ab0b..b1dd18d 100644
--- a/arch/arm/mach-comcerto/include/mach/c2k_dma.h
+++ b/arch/arm/mach-comcerto/include/mach/c2k_dma.h
@@ -97,6 +97,7 @@
 struct comcerto_dma_buf {
 	dma_addr_t phys_addr;
 	unsigned int len;
+	unsigned int split;
 };
 
 struct comcerto_dma_sg {
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-2000.h b/arch/arm/mach-comcerto/include/mach/comcerto-2000.h
old mode 100644
new mode 100755
index 8dc4830..4a27d04
--- a/arch/arm/mach-comcerto/include/mach/comcerto-2000.h
+++ b/arch/arm/mach-comcerto/include/mach/comcerto-2000.h
@@ -155,6 +155,10 @@
 #define COMCERTO_GIC_DIST_VADDR			(COMCERTO_SCU_VADDR + 0x1000)
 #define COMCERTO_L310_VADDR				(COMCERTO_SCU_VADDR + 0x10000)
 
+#define COMCERTO_DISTR_INT_SET_PENDING                   (COMCERTO_GIC_DIST_VADDR + 0x200)
+#define COMCERTO_DISTR_INT_SET_PENDING_OFFSET_4          (COMCERTO_DISTR_INT_SET_PENDING + 0x4)
+#define COMCERTO_DISTR_INT_SET_PENDING_OFFSET_8          (COMCERTO_DISTR_INT_SET_PENDING + 0x8)
+
 #define IRAM_MEMORY_VADDR			0xf0800000
 #define COMCERTO_APB_VADDR				0xf0900000	/* VA of IO on APB bus */
 #define COMCERTO_APB_SIZE				0x00C00000	
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-2000/clk-rst.h b/arch/arm/mach-comcerto/include/mach/comcerto-2000/clk-rst.h
old mode 100644
new mode 100755
index 1d9a69b..631ea98
--- a/arch/arm/mach-comcerto/include/mach/comcerto-2000/clk-rst.h
+++ b/arch/arm/mach-comcerto/include/mach/comcerto-2000/clk-rst.h
@@ -97,6 +97,12 @@
 #define SATA_OOB_CLK_CNTRL 		APB_VADDR(COMCERTO_APB_CLK_BASE + 0x170)
 #define SATA_OOB_CLK_DIV_CNTRL 		APB_VADDR(COMCERTO_APB_CLK_BASE + 0x174)
 #define SATA_OOB_RESET 			APB_VADDR(COMCERTO_APB_CLK_BASE + 0x178)
+#define SATA_OCC_CLK_CNTRL		APB_VADDR(COMCERTO_APB_CLK_BASE + 0x180)
+#define SATA_OCC_CLK_DIV_CNTRL		APB_VADDR(COMCERTO_APB_CLK_BASE + 0x184)
+#define SATA_OCC_RESET			APB_VADDR(COMCERTO_APB_CLK_BASE + 0x188)
+#define PCIE_OCC_CLK_CNTRL		APB_VADDR(COMCERTO_APB_CLK_BASE + 0x190)
+#define PCIE_OCC_CLK_DIV_CNTRL		APB_VADDR(COMCERTO_APB_CLK_BASE + 0x194)
+#define PCIE_OCC_RESET			APB_VADDR(COMCERTO_APB_CLK_BASE + 0x198)
 #define SGMII_OCC_CLK_CNTRL 		APB_VADDR(COMCERTO_APB_CLK_BASE + 0x1A0)
 #define SGMII_OCC_CLK_DIV_CNTRL 	APB_VADDR(COMCERTO_APB_CLK_BASE + 0x1A4)
 #define SGMII_OCC_RESET 		APB_VADDR(COMCERTO_APB_CLK_BASE + 0x1A8)
@@ -142,6 +148,22 @@
 #define PLL2				2
 #define PLL3				3
 
+/* Device Reset Control Register (DEVICE_RST_CNTRL)*/
+
+#define CLK_DIV_RESTART         (1 << 7)
+#define WD_STATUS_CLR           (1 << 6)
+#define AXI_WD_RST_EN           (1 << 5)
+#define DEBUG_RST               (1 << 4)
+#define CLKRST_SCLR_RST         (1 << 3)
+#define FUNC_SCLR_RST           (1 << 2)
+#define GLB_SCLR_RST            (1 << 1)
+#define PWR_ON_SOFT_RST         (1 << 0)
+
+/* General Device Configuration Status Register (GNRL_DEVICE_STATUS) */
+#define CPU1_WD_RST_ACTIVATED   (1 << 2)
+#define CPU0_WD_RST_ACTIVATED   (1 << 1)
+#define AXI_WD_RST_ACTIVATED    (1 << 0)
+
 /* Clock Control Register */
 #define CLOCK_DOMAIN_ENABLE		1
 #define CLOCK_DOMAIN_ENABLE_SHIFT	0
@@ -223,6 +245,7 @@
 
 /* Function Declaration */
 extern void HAL_clk_div_backup_relocate_table (void);
+extern unsigned long HAL_get_ref_clk (void);
 #endif
 
 
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-2000/exp-bus.h b/arch/arm/mach-comcerto/include/mach/comcerto-2000/exp-bus.h
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-2000/gpio.h b/arch/arm/mach-comcerto/include/mach/comcerto-2000/gpio.h
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-2000/irqs.h b/arch/arm/mach-comcerto/include/mach/comcerto-2000/irqs.h
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-2000/memory.h b/arch/arm/mach-comcerto/include/mach/comcerto-2000/memory.h
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-2000/pcie.h b/arch/arm/mach-comcerto/include/mach/comcerto-2000/pcie.h
old mode 100644
new mode 100755
index 23f64e6..019596a
--- a/arch/arm/mach-comcerto/include/mach/comcerto-2000/pcie.h
+++ b/arch/arm/mach-comcerto/include/mach/comcerto-2000/pcie.h
@@ -60,9 +60,11 @@
 #define 	CFG5_APP_INIT_RST	0x01
 #define 	CFG5_LTSSM_ENABLE	0x02
 #define 	CFG5_APP_RDY_L23	0x04
+#define 	CFG5_LINK_DOWN_RST	0x200
 
 
 /* STS0 Register definitions */
+#define 	STS0_LINK_REQ_RST_NOT	0x0001
 #define 	STS0_XMLH_LINK_UP	0x8000
 #define 	STS0_RDLH_LINK_UP	0x10000
 
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-common.h b/arch/arm/mach-comcerto/include/mach/comcerto-common.h
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/include/mach/debug-macro.S b/arch/arm/mach-comcerto/include/mach/debug-macro.S
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/include/mach/hardware.h b/arch/arm/mach-comcerto/include/mach/hardware.h
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/include/mach/memory.h b/arch/arm/mach-comcerto/include/mach/memory.h
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/include/mach/pcie-c2000.h b/arch/arm/mach-comcerto/include/mach/pcie-c2000.h
old mode 100644
new mode 100755
index 65340c2..9110d4f
--- a/arch/arm/mach-comcerto/include/mach/pcie-c2000.h
+++ b/arch/arm/mach-comcerto/include/mach/pcie-c2000.h
@@ -29,6 +29,7 @@
 struct pcie_port {
 	u8			port;
 	u8			root_bus_nr;
+	u16			reset;
 	unsigned long		base;
 	unsigned long		remote_mem_baseaddr;
 	unsigned long		app_base;
@@ -56,12 +57,17 @@
 	struct pcie_app_reg	*app_regs;
 	struct resource		res[2];
 	struct clk		*ref_clock;
+#if defined(CONFIG_COMCERTO_PCIE_OCC_CLOCK)
+	struct clk              *occ_clock;
+#endif
 };
 
 #define PCIE_PORT_MODE_NONE 	-1
 #define PCIE_PORT_MODE_EP 	CFG0_DEV_TYPE_EP
 #define PCIE_PORT_MODE_RC 	CFG0_DEV_TYPE_RC
 
+/* PCIe PM related defines */
+#define PCI_CAP_PM 0x40
 
 
 /* The following register definitions are as per "DWC_regs_rev04.doc" document */
diff --git a/arch/arm/mach-comcerto/include/mach/reset.h b/arch/arm/mach-comcerto/include/mach/reset.h
index f71c3d6..fd9c73c 100644
--- a/arch/arm/mach-comcerto/include/mach/reset.h
+++ b/arch/arm/mach-comcerto/include/mach/reset.h
@@ -106,6 +106,7 @@
 	COMPONENT_TDMNTG,
 }C2000_RESET_COMPONENT;
 
+extern void comcerto_rst_cntrl_set(unsigned int dev_rst_cntrl_bit);
 extern void c2000_block_reset(int block,int state);
 extern void reset_init(void);
 
diff --git a/arch/arm/mach-comcerto/include/mach/serdes-c2000.h b/arch/arm/mach-comcerto/include/mach/serdes-c2000.h
index d9441a6..121af86 100644
--- a/arch/arm/mach-comcerto/include/mach/serdes-c2000.h
+++ b/arch/arm/mach-comcerto/include/mach/serdes-c2000.h
@@ -28,9 +28,6 @@
 /* SER-DES Address space */
 
 
-#define SATA_SERDES_48MHZ 1
-
-
 typedef struct serdes_regs_s
 {
   unsigned short ofst;
@@ -41,9 +38,9 @@
 void serdes_phy_reset(int phy_num);
 
  /*  Initialize values of the Snowbush PHY (Serdes1) for SATA0 */
-#ifdef SATA_SERDES_48MHZ
-/* 24MHz internal ref clock configuration */
-static struct serdes_regs_s sata0_phy_reg_file[] =
+
+/* 48MHz internal ref clock configuration */
+static struct serdes_regs_s sata_phy_reg_file_48[] =
         {
           { 0x000 << 2, 0x06},
           { 0x001 << 2, 0x00},
@@ -364,7 +361,332 @@
           { 0xA96 << 2, 0xf8},
           { 0x000 << 2, 0x07}
         };
-#else
+
+/* 24MHz internal ref clock configuration */
+static struct serdes_regs_s sata_phy_reg_file_24[] =
+        {
+          { 0x000 << 2, 0x06},
+          { 0x001 << 2, 0x00},
+          { 0x002 << 2, 0x88},
+          { 0x003 << 2, 0x00},
+          { 0x004 << 2, 0x7b},
+          { 0x005 << 2, 0xc9},
+          { 0x006 << 2, 0x03},
+          { 0x007 << 2, 0x00},
+          { 0x008 << 2, 0x00},
+          { 0x009 << 2, 0x00},
+          { 0x00A << 2, 0x00},
+          { 0x00B << 2, 0x00},
+          { 0x00C << 2, 0x00},
+          { 0x00D << 2, 0x00},
+          { 0x00E << 2, 0x00},
+          { 0x00F << 2, 0x00},
+          { 0x010 << 2, 0x00},
+          { 0x011 << 2, 0x00},
+          { 0x012 << 2, 0x00},
+          { 0x013 << 2, 0x00},
+          { 0x014 << 2, 0x00},
+          { 0x015 << 2, 0x00},
+          { 0x016 << 2, 0x00},
+          { 0x017 << 2, 0x00},
+          { 0x018 << 2, 0x00},
+          { 0x019 << 2, 0x00},
+          { 0x01A << 2, 0x00},
+          { 0x01B << 2, 0x00},
+          { 0x01C << 2, 0x00},
+          { 0x01D << 2, 0x00},
+          { 0x01E << 2, 0x00},
+          { 0x01F << 2, 0x00},
+          { 0x020 << 2, 0x00},
+          { 0x021 << 2, 0x00},
+          { 0x022 << 2, 0xa0},
+          { 0x023 << 2, 0x54},
+          { 0x024 << 2, 0x00},
+          { 0x025 << 2, 0x00},
+          { 0x026 << 2, 0x00},
+          { 0x027 << 2, 0x00},
+          { 0x028 << 2, 0x00},
+          { 0x029 << 2, 0x00},
+          { 0x02A << 2, 0x00},
+          { 0x02B << 2, 0x00},
+          { 0x02C << 2, 0x00},
+          { 0x02D << 2, 0x00},
+          { 0x02E << 2, 0x04},
+          { 0x02F << 2, 0x50},
+          { 0x030 << 2, 0x70},
+          { 0x031 << 2, 0x02},
+          { 0x032 << 2, 0x25},
+          { 0x033 << 2, 0x40},
+          { 0x034 << 2, 0x01},
+          { 0x035 << 2, 0x40},
+          { 0x036 << 2, 0x00},
+          { 0x037 << 2, 0x00},
+          { 0x038 << 2, 0x00},
+          { 0x039 << 2, 0x00},
+          { 0x03A << 2, 0x00},
+          { 0x03B << 2, 0x00},
+          { 0x03C << 2, 0x00},
+          { 0x03D << 2, 0x00},
+          { 0x03E << 2, 0x00},
+          { 0x03F << 2, 0x00},
+          { 0x040 << 2, 0x00},
+          { 0x041 << 2, 0x00},
+          { 0x042 << 2, 0x00},
+          { 0x043 << 2, 0x00},
+          { 0x044 << 2, 0x00},
+          { 0x045 << 2, 0x00},
+          { 0x046 << 2, 0x00},
+          { 0x047 << 2, 0x00},
+          { 0x048 << 2, 0x00},
+          { 0x049 << 2, 0x00},
+          { 0x04A << 2, 0x00},
+          { 0x04B << 2, 0x00},
+          { 0x04C << 2, 0x00},
+          { 0x04D << 2, 0x00},
+          { 0x04E << 2, 0x00},
+          { 0x04F << 2, 0x00},
+          { 0x050 << 2, 0x00},
+          { 0x051 << 2, 0x00},
+          { 0x052 << 2, 0x00},
+          { 0x053 << 2, 0x00},
+          { 0x054 << 2, 0x00},
+          { 0x055 << 2, 0x00},
+          { 0x056 << 2, 0x00},
+          { 0x057 << 2, 0x00},
+          { 0x058 << 2, 0x00},
+          { 0x059 << 2, 0x00},
+          { 0x05A << 2, 0x00},
+          { 0x05B << 2, 0x00},
+          { 0x05C << 2, 0x00},
+          { 0x05D << 2, 0x00},
+          { 0x05E << 2, 0x00},
+          { 0x05F << 2, 0x00},
+          { 0x060 << 2, 0x00},
+          //{ 0x061 << 2, 0x2e}, //for Rev-A0 device
+          { 0x061 << 2, 0x2e}, //for Rev-A1 device
+          { 0x062 << 2, 0x00},
+          { 0x063 << 2, 0x5e},
+          { 0x064 << 2, 0x00},
+          { 0x065 << 2, 0x42},
+          { 0x066 << 2, 0xd1},
+          { 0x067 << 2, 0x20},
+          { 0x068 << 2, 0x28},
+          { 0x069 << 2, 0x78},
+          { 0x06A << 2, 0x2c},
+          { 0x06B << 2, 0xb9},
+          { 0x06C << 2, 0x5e},
+          { 0x06D << 2, 0x03},
+          { 0x06E << 2, 0x00},
+          { 0x06F << 2, 0x00},
+          { 0x070 << 2, 0x00},
+          { 0x071 << 2, 0x00},
+          { 0x072 << 2, 0x00},
+          { 0x200 << 2, 0x02},
+          { 0x201 << 2, 0x00},
+          { 0x202 << 2, 0x00},
+          { 0x203 << 2, 0x00},
+          { 0x204 << 2, 0x00},
+          { 0x205 << 2, 0x10},
+          { 0x206 << 2, 0x84},
+          { 0x207 << 2, 0x3c}, 
+          { 0x208 << 2, 0xe0},
+          { 0x210 << 2, 0x23},
+          { 0x211 << 2, 0x00},
+          { 0x212 << 2, 0x40},
+          { 0x213 << 2, 0x05},
+          { 0x214 << 2, 0xd0},/* */
+          { 0x215 << 2, 0x17},
+          { 0x216 << 2, 0x00},
+          { 0x217 << 2, 0x68},
+          { 0x218 << 2, 0xf2},
+          { 0x219 << 2, 0x1e},
+          { 0x21A << 2, 0x18},
+          { 0x21B << 2, 0x0d},
+          { 0x21C << 2, 0x0c},
+          { 0x21D << 2, 0x00},
+          { 0x21E << 2, 0x00},
+          { 0x21F << 2, 0x00},
+          { 0x220 << 2, 0x00},
+          { 0x221 << 2, 0x00},
+          { 0x222 << 2, 0x00},
+          { 0x223 << 2, 0x00},
+          { 0x224 << 2, 0x00},
+          { 0x225 << 2, 0x00},
+          { 0x226 << 2, 0x00},
+          { 0x227 << 2, 0x00},
+          { 0x228 << 2, 0x00},
+          { 0x229 << 2, 0x00},
+          { 0x22A << 2, 0x00},
+          { 0x22B << 2, 0x00},
+          { 0x22C << 2, 0x00},
+          { 0x22D << 2, 0x00},
+          { 0x22E << 2, 0x00},
+          { 0x22F << 2, 0x00},
+          { 0x230 << 2, 0x00},
+          { 0x231 << 2, 0x00},
+          { 0x232 << 2, 0x00},
+          { 0x233 << 2, 0x00},
+          { 0x234 << 2, 0x00},
+          { 0x235 << 2, 0x00},
+          { 0x236 << 2, 0x00},
+          { 0x237 << 2, 0x00},
+          { 0x238 << 2, 0x00},
+          { 0x239 << 2, 0x00},
+          { 0x23A << 2, 0x00},
+          { 0x23B << 2, 0x00},
+          { 0x23C << 2, 0x00},
+          { 0x23D << 2, 0x00},
+          { 0x23E << 2, 0x00},
+          { 0x23F << 2, 0x00},
+          { 0x240 << 2, 0x00},
+          { 0x241 << 2, 0x00},
+          { 0x242 << 2, 0x00},
+          { 0x243 << 2, 0x00},
+          { 0x244 << 2, 0x00},
+          { 0x245 << 2, 0x00},
+          { 0x246 << 2, 0x00},
+          { 0x247 << 2, 0x00},
+          { 0x248 << 2, 0x00},
+          { 0x249 << 2, 0x00},
+          { 0x24A << 2, 0x00},
+          { 0x24B << 2, 0x00},
+          { 0x24C << 2, 0x00},
+          { 0x24D << 2, 0x00},
+          { 0x24E << 2, 0x00},
+          { 0x24F << 2, 0x00},
+          { 0x250 << 2, 0x60},
+          { 0x251 << 2, 0x0f},
+          { 0xA00 << 2, 0x00},
+          { 0xA01 << 2, 0x20},
+          { 0xA02 << 2, 0x00},
+          { 0xA03 << 2, 0x40},
+          { 0xA04 << 2, 0x24},
+          { 0xA05 << 2, 0xae},
+          { 0xA06 << 2, 0x19},
+          { 0xA07 << 2, 0x49},
+          { 0xA08 << 2, 0x04},
+          { 0xA09 << 2, 0x83},
+          { 0xA0A << 2, 0x4b},
+          { 0xA0B << 2, 0xc5},
+          { 0xA0C << 2, 0x01},
+          { 0xA0D << 2, 0x03},
+          { 0xA0E << 2, 0x28},
+          { 0xA0F << 2, 0x98},
+          { 0xA10 << 2, 0x19},
+          { 0xA11 << 2, 0x00},
+          { 0xA12 << 2, 0x00},
+          { 0xA13 << 2, 0x80},
+          { 0xA14 << 2, 0xf0},
+          { 0xA15 << 2, 0xd0},
+          { 0xA16 << 2, 0x00},
+          { 0xA17 << 2, 0x00},
+          { 0xA30 << 2, 0x00},
+          { 0xA31 << 2, 0x00},
+          { 0xA32 << 2, 0x00},
+          { 0xA33 << 2, 0x00},
+          { 0xA34 << 2, 0x00},
+          { 0xA35 << 2, 0x00},
+          { 0xA36 << 2, 0x00},
+          { 0xA37 << 2, 0x00},
+          { 0xA38 << 2, 0x00},
+          { 0xA39 << 2, 0xa0},
+          { 0xA3A << 2, 0xa0},
+          { 0xA3B << 2, 0xa0},
+          { 0xA3C << 2, 0xa0},
+          { 0xA3D << 2, 0xa0},
+          { 0xA3E << 2, 0xa0},
+          { 0xA3F << 2, 0x54},
+          { 0xA40 << 2, 0x62},
+          { 0xA41 << 2, 0x00},
+          { 0xA42 << 2, 0x80},
+          { 0xA43 << 2, 0x58},
+          { 0xA44 << 2, 0x00},
+          { 0xA45 << 2, 0x44},
+          { 0xA46 << 2, 0x5c},
+          { 0xA47 << 2, 0x86},
+          { 0xA48 << 2, 0x8d},
+          { 0xA49 << 2, 0xd0},
+          { 0xA4A << 2, 0x09},
+          { 0xA4B << 2, 0x90},
+          { 0xA4C << 2, 0x07},
+          { 0xA4D << 2, 0x40},
+          { 0xA4E << 2, 0x00},
+          { 0xA4F << 2, 0x00},
+          { 0xA50 << 2, 0x00},
+          { 0xA51 << 2, 0x20},
+          { 0xA52 << 2, 0x32},
+          { 0xA53 << 2, 0x00},
+          { 0xA54 << 2, 0x00},
+          { 0xA55 << 2, 0x00},
+          { 0xA56 << 2, 0x00},
+          { 0xA57 << 2, 0x00},
+          { 0xA58 << 2, 0x00},
+          { 0xA59 << 2, 0x00},
+          { 0xA5A << 2, 0x00},
+          { 0xA5B << 2, 0x00},
+          { 0xA5C << 2, 0x00},
+          { 0xA5D << 2, 0x00},
+          { 0xA5E << 2, 0x00},
+          { 0xA5F << 2, 0x00},
+          { 0xA60 << 2, 0x00},
+          { 0xA61 << 2, 0x00},
+          { 0xA62 << 2, 0x00},
+          { 0xA63 << 2, 0x00},
+          { 0xA64 << 2, 0x00},
+          { 0xA65 << 2, 0x00},
+          { 0xA66 << 2, 0x00},
+          { 0xA67 << 2, 0x00},
+          { 0xA68 << 2, 0x00},
+          { 0xA69 << 2, 0x00},
+          { 0xA6A << 2, 0x00},
+          { 0xA6B << 2, 0x00},
+          { 0xA6C << 2, 0x00},
+          { 0xA6D << 2, 0x00},
+          { 0xA6E << 2, 0x00},
+          { 0xA6F << 2, 0x00},
+          { 0xA70 << 2, 0x00},
+          { 0xA71 << 2, 0x00},
+          { 0xA72 << 2, 0x00},
+          { 0xA73 << 2, 0x00},
+          { 0xA74 << 2, 0x00},
+          { 0xA75 << 2, 0x00},
+          { 0xA76 << 2, 0x00},
+          { 0xA77 << 2, 0x00},
+          { 0xA78 << 2, 0x00},
+          { 0xA79 << 2, 0x00},
+          { 0xA7A << 2, 0x00},
+          { 0xA7B << 2, 0x00},
+          { 0xA7C << 2, 0x00},
+          { 0xA7D << 2, 0x00},
+          { 0xA7E << 2, 0x00},
+          { 0xA7F << 2, 0xd8},
+          { 0xA80 << 2, 0x1a},
+          { 0xA81 << 2, 0xff},
+          { 0xA82 << 2, 0x11},
+          { 0xA83 << 2, 0x00},
+          { 0xA84 << 2, 0x00},
+          { 0xA85 << 2, 0x00},
+          { 0xA86 << 2, 0x00},
+          { 0xA87 << 2, 0xf0},
+          { 0xA88 << 2, 0xff},
+          { 0xA89 << 2, 0xff},
+          { 0xA8A << 2, 0xff},
+          { 0xA8B << 2, 0xff},
+          { 0xA8C << 2, 0x1c},
+          { 0xA8D << 2, 0xc2},
+          { 0xA8E << 2, 0xc3},
+          { 0xA8F << 2, 0x3f},
+          { 0xA90 << 2, 0x0a},
+          { 0xA91 << 2, 0x00},
+          { 0xA92 << 2, 0x00},
+          { 0xA93 << 2, 0x00},
+          { 0xA94 << 2, 0x00},
+          { 0xA95 << 2, 0x00},
+          { 0xA96 << 2, 0xf8},
+          { 0x000 << 2, 0x07}
+        };
+
+#if 0
 /* This is 60Mhz external ref clock configuration which is not used on the board currently */
 static struct serdes_regs_s sata0_phy_reg_file[] =
 	{
@@ -696,7 +1018,7 @@
 	  /* Common CMU block */
   	  { 0x000 << 2, 0x06},
   	  { 0x001 << 2, 0x00},
-  	  { 0x002 << 2, 0x89}, //
+  	  { 0x002 << 2, 0x09}, //
  	  { 0x003 << 2, 0x00},
  	  { 0x004 << 2, 0x60}, //
  	  { 0x005 << 2, 0x09}, //
diff --git a/arch/arm/mach-comcerto/include/mach/system.h b/arch/arm/mach-comcerto/include/mach/system.h
index 52aab7f..150b46c 100644
--- a/arch/arm/mach-comcerto/include/mach/system.h
+++ b/arch/arm/mach-comcerto/include/mach/system.h
@@ -22,6 +22,8 @@
 
 #include <mach/hardware.h>
 #include <mach/io.h>
+#include <mach/comcerto-2000/clk-rst.h>
+#include <mach/reset.h>
 
 static inline void arch_idle(void)
 {
@@ -34,7 +36,7 @@
 
 static inline void arch_reset(char mode, const char *cmd)
 {
-	 __raw_writel(0x1,DEVICE_RST_CNTRL);
+	comcerto_rst_cntrl_set(PWR_ON_SOFT_RST);
 }
 
 #endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/arch/arm/mach-comcerto/include/mach/timex.h b/arch/arm/mach-comcerto/include/mach/timex.h
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/include/mach/uncompress.h b/arch/arm/mach-comcerto/include/mach/uncompress.h
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/pcie-c2000.c b/arch/arm/mach-comcerto/pcie-c2000.c
old mode 100644
new mode 100755
index 649ed9d..c657249
--- a/arch/arm/mach-comcerto/pcie-c2000.c
+++ b/arch/arm/mach-comcerto/pcie-c2000.c
@@ -39,14 +39,13 @@
 #include <linux/irq.h>
 #include <asm/io.h>
 #include <asm/mach/irq.h>
-#include <mach/comcerto-2000.h>
 #include <mach/pcie-c2000.h>
 #include <mach/serdes-c2000.h>
 #include <mach/reset.h>
+#include <mach/hardware.h>
 
 #include <linux/platform_device.h>
 #include <linux/clk.h>
-
 //#define COMCERTO_PCIE_DEBUG
 
 #ifdef CONFIG_PCI_MSI
@@ -211,15 +210,12 @@
 
 	do {
 		if (readl( pp->va_app_base + pp->app_regs->sts0 ) & STS0_RDLH_LINK_UP) {
-//			printk(KERN_INFO "%s:%d Link up success \n",__func__, __LINE__);
 			return 1;
 		}
 
 		cond_resched();
 	} while (!time_after_eq(jiffies, deadline));
 
-//	printk(KERN_ERR "%s:%d Link up failed \n",__func__, __LINE__);
-
 	return 0;
 }
 
@@ -660,7 +656,7 @@
 	}
 
 	if (status) {
-		printk(KERN_INFO "%s:Unhandled interrupt\n", __func__);
+		printk(KERN_INFO "%s:Unhandled interrupt %x\n", __func__, status);
 		/* FIXME: HP, AER, PME interrupts need to be handled */
 		writel_relaxed(status, (pp->va_app_base + app_reg->intr_sts));
 	}
@@ -777,8 +773,8 @@
 
 	/* FIXME Added for debuging */
 	writel(readl(pp->va_app_base + app_reg->intr_en) &
-			(INTR_CTRL_AER |  INTR_CTRL_PME |
-			 INTR_CTRL_HP  |  INTR_CTRL_LINK_AUTO_BW ),
+			~(INTR_CTRL_AER |  INTR_CTRL_PME |
+ 			 INTR_CTRL_HP  |  INTR_CTRL_LINK_AUTO_BW ),
 			pp->va_app_base + app_reg->intr_en );
 
 
@@ -1204,10 +1200,23 @@
 		goto err2;
 	}
 
+	/* Enable the PCIE_OCC clock */
+#if defined(CONFIG_COMCERTO_PCIE_OCC_CLOCK)
+	pp->occ_clock = clk_get(NULL,"pcie_occ");
+	if (IS_ERR(pp->occ_clock)) {
+		pr_err("%s: Unable to obtain pcie_occ clock: %ld\n", __func__, PTR_ERR(pp->occ_clock));
+		goto err_occ_clock;
+	}
+#endif
 	pcie_port_set_mode(nr, mode);
 	
 	return 0;
 
+#if defined(CONFIG_COMCERTO_PCIE_OCC_CLOCK)
+err_occ_clock:
+	clk_put(pp->occ_clock);
+#endif
+
 err2:
 	iounmap(pp->va_cfg1_base);
 err1:
@@ -1217,30 +1226,289 @@
 
 }
 
+#if defined(CONFIG_C2K_EVM) || defined(CONFIG_C2K_ASIC)
+#define PCIE_DEV_EXT_RESET_DEASSERT(_id) \
+	writel(readl(COMCERTO_GPIO_OUTPUT_REG) & ~(GPIO_PIN_27), COMCERTO_GPIO_OUTPUT_REG);
+
+#define PCIE_DEV_EXT_RESET_ASSERT(_id) \
+	writel(readl(COMCERTO_GPIO_OUTPUT_REG) | (GPIO_PIN_27), COMCERTO_GPIO_OUTPUT_REG);
+#else
+/* Board specific */
+#define PCIE_DEV_EXT_RESET_DEASSERT(_id)
+#define PCIE_DEV_EXT_RESET_ASSERT(_id)
+#endif
+
+static int comcerto_pcie_device_reset(struct pcie_port *pp)
+{
+	int ii;
+	struct pcie_port *l_pp = pp;
+	struct pci_dev *pci_dev = NULL;
+
+	printk(KERN_INFO "ENTER: Bringing PCIe%d device reset\n", pp->port);
+	if (!pp->link_state)
+		return -1;
+
+	/* On C2KEVM and ASIC same reset is connected to PCIe0/1.
+         * So, device might have kept in reset, using other PCIe host.
+	 */
+	if (!comcerto_pcie_link_up(pp)) {
+		printk(KERN_INFO "%s : Device is already link down state\n", __func__);
+		return 0;
+	}
+
+
+	/*FIXME : Below code might be required if we want to reset pcie device, without
+         *        invoking pcie device supend. If we invoke pcie device suspend it will
+	 *	  take care of saving pcie config space.
+         */
+#if 0
+	/* Now save the PCIe device configuration space.*/
+	while((pci_dev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_dev))) {
+		if (pp->root_bus_nr == pci_dev->bus->number) {
+			pci_save_state(pci_dev);
+		}
+	}
+
+	/* On C2KEVM/ASIC, since same GPIO27 is used to reset PCIe0/PCIe1 devices,
+	 * save configuration of devices on other PCIe also.
+	 * This may not be applicable for other cutomer boards.
+	 */
+#if defined(CONFIG_C2K_EVM) || defined(CONFIG_C2K_ASIC)
+	l_pp = &pcie_port[!pp->port];
+	pci_dev = NULL;
+
+	if (l_pp->link_state) {
+		while((pci_dev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_dev))) {
+			if (l_pp->root_bus_nr == pci_dev->bus->number) {
+				pci_save_state(pci_dev);
+			}
+		}
+	}
+#endif
+#endif
+
+	/************** Ready to issue rest *****************/
+	/* De-assert external reset (GPIO-27) */
+	PCIE_DEV_EXT_RESET_DEASSERT(pp->port);
+	printk(KERN_INFO "EXIT: Bringing PCIe%d device reset\n", pp->port);
+
+	return 0;
+
+}
+
+
+static int comcerto_pcie_device_reset_exit(struct pcie_port *pp)
+{
+	unsigned int val;
+	struct pci_dev *pci_dev;
+
+	printk(KERN_INFO "ENTER: Bringing PCIe%d device out-of-reset\n", pp->port);
+
+	if (!pp->link_state && pp->reset)
+		return -1;
+
+	/* Pull up external reset */
+	/* assert external reset (GPIO-27) */
+	PCIE_DEV_EXT_RESET_ASSERT(pp->port);
+
+	udelay(1000);
+	udelay(1000);
+	udelay(1000);
+	udelay(1000);
+	udelay(1000);
+	udelay(1000);
+	udelay(1000);
+
+	/* Restore the RC configuration */
+	comcerto_dbi_read_reg(pp, PCIE_AFL0L1_REG, 4, &val);
+	val &= ~(0x00FFFF00);
+	val |= 0x00F1F100;
+	comcerto_dbi_write_reg(pp, PCIE_AFL0L1_REG, 4, val);
+
+	if(pcie_gen1_only)
+	{
+		comcerto_dbi_write_reg(pp, PCIE_LCNT2_REG, 4, 0x1);
+		comcerto_dbi_write_reg(pp, PCIE_LCAP_REG, 4, 0x1);
+	}
+	else
+	{
+		comcerto_dbi_read_reg(pp, PCIE_G2CTRL_REG, 4, &val);
+		val &= ~(0xFF);
+		val |= 0xF1;
+		comcerto_dbi_write_reg(pp, PCIE_G2CTRL_REG, 4, val);
+	}
+
+	// instruct pcie to switch to gen2 after init
+	comcerto_dbi_read_reg(pp, PCIE_G2CTRL_REG, 4, &val);
+	val |= (1 << 17);
+	comcerto_dbi_write_reg(pp, PCIE_G2CTRL_REG, 4, val);
+
+	/*setup iATU for outbound translation */
+	PCIE_SETUP_iATU_OB_ENTRY( pp, iATU_ENTRY_MEM, iATU_GET_MEM_BASE(pp->remote_mem_baseaddr),
+			iATU_MEM_SIZE - 1, 0, 0, pp->remote_mem_baseaddr );
+	PCIE_SETUP_iATU_OB_ENTRY( pp, iATU_ENTRY_IO, iATU_GET_IO_BASE(pp->remote_mem_baseaddr),
+			iATU_IO_SIZE - 1, (AXI_OP_TYPE_IO_RDRW & iATU_CTRL1_TYPE_MASK),
+			0, iATU_GET_IO_BASE(pp->remote_mem_baseaddr) );
+	PCIE_SETUP_iATU_OB_ENTRY( pp, iATU_ENTRY_MSG, iATU_GET_MSG_BASE(pp->remote_mem_baseaddr),
+			iATU_MSG_SIZE - 1, (AXI_OP_TYPE_MSG_REQ & iATU_CTRL1_TYPE_MASK),
+			0, iATU_GET_MSG_BASE(pp->remote_mem_baseaddr) );
+	PCIE_SETUP_iATU_IB_ENTRY( pp, 0, 0,
+			INBOUND_ADDR_MASK, 0, 0, COMCERTO_AXI_DDR_BASE);
+
+	comcerto_dbi_write_reg(pp, PCIE_MSI_ADDR_LO, 4, pp->msi_mbox_handle);
+	comcerto_dbi_write_reg(pp, PCIE_MSI_ADDR_HI, 4, 0);
+
+	writel_relaxed(0x7, pp->va_app_base + pp->app_regs->cfg5);
+
+	/* Generic PCIe unit setup.*/
+
+	/* Enable own BME. It is necessary to enable own BME to do a
+	 * memory transaction on a downstream device
+	 */
+	comcerto_dbi_read_reg(pp, PCI_COMMAND, 2, &val);
+	val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
+			| PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+	comcerto_dbi_write_reg(pp, PCI_COMMAND, 2, val);
+
+	pp->cfg0_prev_taddr = 0xffffffff;
+	pp->cfg1_prev_taddr = 0xffffffff;
+
+	//udelay(1000);
+
+	if(comcerto_pcie_link_up(pp)) {
+	printk(KERN_INFO " Bringing PCIe%d device out-of-reset : Link Up\n", pp->port);
+	/*FIXME : Below code might be required if we want to bring pcie device out-of-reset,
+         *	  without invoking pcie device supend. If we invoke pcie device resume it will
+	 *	  take care of restoring, saved pcie config space.
+         */
+#if 0
+		pci_dev = NULL;
+		while((pci_dev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_dev))) {
+			if (pp->root_bus_nr == pci_dev->bus->number) {
+				pci_restore_state(pci_dev);
+			}
+		}
+#endif
+	}
+
+	printk(KERN_INFO "EXIT: Bringing PCIe%d device out-of-reset\n", pp->port);
+	return 0;
+
+}
+
+static ssize_t comcerto_pcie_show_reset(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+        struct pcie_port *pp = &pcie_port[pdev->id];
+
+	return sprintf(buf, "%d\n", pp->reset);
+}
+
+static ssize_t comcerto_pcie_set_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+        struct pcie_port *pp = &pcie_port[pdev->id];
+	int reset = 0;
+
+	if (!pcie_port_is_host(pdev->id) ||  !(pp->link_state))
+			return count;
+
+	sscanf(buf, "%d", &reset);
+
+	reset = reset ? 1:0;
+
+	if (pp->reset == reset) {
+		printk(KERN_INFO "%s: Already in same state\n", __func__);
+		return count;
+	}
+
+
+	if (reset) {
+		printk(KERN_INFO "ENTER : Putting PCIe%d device into reset\n", pdev->id);
+
+		if (!comcerto_pcie_device_reset(pp)) {
+			int ii = 10;
+
+			/* Wait for link_req_rst_not, to be de-asseted */
+			while (ii--) {
+
+				if (!(readl( pp->va_app_base + pp->app_regs->sts0 ) & STS0_LINK_REQ_RST_NOT)) {
+					printk(KERN_INFO "%s : (PCIe%d) link_req_rst_not is de-asseted\n", __func__, pp->port);
+					break;
+				}
+
+				udelay(1000);
+			}
+
+			if (ii == 10) 
+				printk(KERN_WARNING "%s : (PCIe%d) link_req_rst_not is not de-asseted \n", __func__, pp->port);
+
+			pp->reset = 1;
+			/* Disable LTSSM and initiate linkdown reset */
+			writel((readl(pp->va_app_base + pp->app_regs->cfg5) &
+						~(CFG5_LTSSM_ENABLE)) | CFG5_LINK_DOWN_RST,
+						 pp->va_app_base + pp->app_regs->cfg5);
+			udelay(1000);
+		}
+
+		printk(KERN_INFO "EXIT : Putting PCIe%d device into reset\n", pdev->id);
+	}
+	else {
+
+		printk(KERN_INFO "ENTER: Bringing PCIe%d device outof reset\n", pdev->id);
+
+		if (!comcerto_pcie_device_reset_exit(pp)) {
+			pp->reset = 0;
+		}
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(device_reset, 0644, comcerto_pcie_show_reset, comcerto_pcie_set_reset);
+
 #ifdef CONFIG_PM
 static int comcerto_pcie_suspend(struct platform_device *pdev, pm_message_t state)
 {
+	unsigned int val, i;
 
 	printk(KERN_INFO "%s: pcie device %p (id = %d): state %d\n", 
 		__func__, pdev, pdev->id, state.event);
 
-	if (pcie_port[pdev->id].port_mode != PCIE_PORT_MODE_NONE)
-		clk_disable(pcie_port[pdev->id].ref_clock);
-	
+	if (pcie_port[pdev->id].port_mode != PCIE_PORT_MODE_NONE) {
+		if (comcerto_pcie_link_up(&pcie_port[pdev->id])){
+
+		    /* Enable PME to root Port */
+		    comcerto_dbi_read_reg(&pcie_port[pdev->id], (PCI_CAP_PM + PCI_PM_CTRL), 4, &val);
+		    comcerto_dbi_write_reg(&pcie_port[pdev->id], (PCI_CAP_PM + PCI_PM_CTRL), 4, val | PCI_PM_CTRL_STATE_MASK);
+
+			/* Required PM Delay */
+		    for (i = 0 ; i < 40 ; i++)
+			    udelay(500);
+	    }
+	}
+
 	return 0;
 }
 
 static int comcerto_pcie_resume(struct platform_device *pdev)
 {
-	int rc;
-	
+	unsigned int val, i;
+
 	printk(KERN_INFO "%s: pcie device %p (id = %d)\n", 
 		__func__, pdev, pdev->id);
-	
-	if(pcie_port[pdev->id].port_mode != PCIE_PORT_MODE_NONE) {	
-		rc = clk_enable(pcie_port[pdev->id].ref_clock);
-		if (rc)
-			pr_err("%s: PCIe%d clock enable failed\n", __func__, pdev->id);
+
+	if(pcie_port[pdev->id].port_mode != PCIE_PORT_MODE_NONE) {
+		if (comcerto_pcie_link_up(&pcie_port[pdev->id])){
+
+		    /* Put In D0 State */
+		    comcerto_dbi_read_reg(&pcie_port[pdev->id], (PCI_CAP_PM + PCI_PM_CTRL), 4, &val);
+		    comcerto_dbi_write_reg(&pcie_port[pdev->id], (PCI_CAP_PM + PCI_PM_CTRL), 4, val & (~PCI_PM_CTRL_STATE_MASK));
+
+			/* Required PM Delay */
+		    for (i = 0 ; i < 40 ; i++)
+			    udelay(500);
+	    }
 	}
 
 	return 0;
@@ -1327,6 +1595,15 @@
 		pr_err("%s: PCIe%d clock enable failed\n", __func__, nr);
 		goto err1;
 	}
+	
+	/* Enable the PCIE_OCC clock */	
+#if defined(CONFIG_COMCERTO_PCIE_OCC_CLOCK)
+	rc =  clk_enable(pp->occ_clock);
+	if (rc){
+		pr_err("%s: PCIe_occ clock enable failed\n", __func__);
+		goto err_occ_clock;
+	}
+#endif
 
 	/* Serdes Initialization. */
 	if( serdes_phy_init(nr,  p_pcie_phy_reg_file,
@@ -1335,7 +1612,7 @@
 	{
 		pp->port_mode = PCIE_PORT_MODE_NONE;
 		pr_err("%s: Failed to initialize serdes (%d)\n", __func__, nr );
-		goto err0;
+		goto err_phy_link;
 	}
 
 	mdelay(1); //After CMU locks wait for sometime
@@ -1358,13 +1635,20 @@
 	if(!pp->link_state)
 	{
 		if_err = 0;
-		goto err0;
+		goto err_phy_link;
 	}
 
 	return 0;
 
-err0:
+err_phy_link:
 	clk_disable(pp->ref_clock);
+	clk_put(pp->ref_clock);
+#if defined(CONFIG_COMCERTO_PCIE_OCC_CLOCK)
+err_occ_clock:
+	clk_disable(pp->occ_clock);
+	clk_put(pp->occ_clock);
+#endif
+
 err1:
 	//Put all to reset
 	c2000_block_reset(axi_pcie_component,1);
@@ -1404,22 +1688,26 @@
 	}
 	else
 	{
-		int ref_clk_24;
-
-                ref_clk_24 = (readl(COMCERTO_GPIO_SYSTEM_CONFIG) & (BIT_5_MSK|BIT_7_MSK));
-
-                if(ref_clk_24)
+		if(HAL_get_ref_clk() == REF_CLK_24MHZ)
 		{
                         p_pcie_phy_reg_file = &pcie_phy_reg_file_24[0];
 			serdes_regs_size = sizeof(pcie_phy_reg_file_24);
+			printk(KERN_INFO "PCIe: Ref clk 24Mhz\n");
 		}
                 else
 		{
                         p_pcie_phy_reg_file = &pcie_phy_reg_file_48[0];
 			serdes_regs_size = sizeof(pcie_phy_reg_file_48);
+			printk(KERN_INFO "PCIe: Ref clk 48Mhz\n");
 		}
         }
 
+	if (system_rev == 1) {
+		printk(KERN_INFO "PCIe: Detected C2K RevA1 device serdes clk devider old:new=%x:%x\n",
+				p_pcie_phy_reg_file[0x61].val, 0x06);
+		p_pcie_phy_reg_file[0x61].val = 0x6;
+	}
+
 	for(polarity = 0 ; polarity < polarity_max; polarity++)
 	{
 
@@ -1454,6 +1742,7 @@
 }
 
 
+
 static int __init comcerto_pcie_init(void)
 {
         struct pcie_port *pp;
@@ -1461,10 +1750,11 @@
 	int num_pcie_port = 1;
 	struct pci_dev *pdev = NULL;
 
+
         pp = &pcie_port[0];
 	comcerto_pcie_bsp_init(pp, 0);
 
-        if ( (NUM_PCIE_PORTS == 2)  &&
+	if ( (NUM_PCIE_PORTS == 2)  &&
                         !(readl(COMCERTO_GPIO_SYSTEM_CONFIG) & BOOT_SERDES1_CNF_SATA0) )
         {
                 num_pcie_port = 2;
@@ -1500,9 +1790,16 @@
 #ifdef CONFIG_PM
 	platform_device_register(&pcie_pwr0);
 
-	if(num_pcie_port > 1)
+	if (device_create_file(&pcie_pwr0.dev, &dev_attr_device_reset))
+		printk(KERN_ERR "%s: Unable to create pcie0 reset sysfs entry\n", __func__);
+
+	if(num_pcie_port > 1) {
 		platform_device_register(&pcie_pwr1);
 
+		if (device_create_file(&pcie_pwr1.dev, &dev_attr_device_reset))
+			printk(KERN_ERR "%s: Unable to create pcie1 reset sysfs entry\n", __func__);
+	}
+
 	platform_driver_register(&comcerto_pcie_driver);
 #endif
 
diff --git a/arch/arm/mach-comcerto/platsmp.c b/arch/arm/mach-comcerto/platsmp.c
old mode 100644
new mode 100755
diff --git a/arch/arm/mach-comcerto/reset.c b/arch/arm/mach-comcerto/reset.c
index 0173867..5051344 100644
--- a/arch/arm/mach-comcerto/reset.c
+++ b/arch/arm/mach-comcerto/reset.c
@@ -23,16 +23,28 @@
  */
 
 #include <linux/module.h>
-#include <mach/reset.h> 
+#include <mach/reset.h>
 #include <asm/io.h>
 #include <linux/spinlock.h>
 
 static char i2cspi_state[2],dus_state[3];
 spinlock_t reset_lock;
 
-/* @ int block : Id of device block to be put in reset 
- * @ int state : State value 0->OUT-OF-RESET , 1->RESET. 
- * API for block reset to all the device blocks 
+
+void comcerto_rst_cntrl_set(unsigned int dev_rst_cntrl_bit)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&reset_lock, flags);
+
+	__raw_writel((dev_rst_cntrl_bit | __raw_readl(DEVICE_RST_CNTRL)), DEVICE_RST_CNTRL);
+
+	spin_unlock_irqrestore(&reset_lock,flags);
+}
+EXPORT_SYMBOL(comcerto_rst_cntrl_set);
+
+/* @ int block : Id of device block to be put in reset
+ * @ int state : State value 0->OUT-OF-RESET , 1->RESET.
+ * API for block reset to all the device blocks
  * available for C2000 devices.
  */
 void c2000_block_reset(int block,int state)
@@ -360,14 +372,14 @@
 			break;
 		default :
 			break;
-	}	
+	}
 }
 spin_unlock_irqrestore(&reset_lock,flags);
 }
 EXPORT_SYMBOL(c2000_block_reset);
 
 void reset_init(void){
-	
+
 	/*Initilize the DUS ,serde0/1/2 and I2CSPI dependancy values */
 	i2cspi_state[0]=i2cspi_state[1]=dus_state[0]=dus_state[1]=dus_state[2]=0;
 
diff --git a/arch/arm/mach-comcerto/sysfstdm.c b/arch/arm/mach-comcerto/sysfstdm.c
old mode 100644
new mode 100755
index fa7d776..1e12d59
--- a/arch/arm/mach-comcerto/sysfstdm.c
+++ b/arch/arm/mach-comcerto/sysfstdm.c
@@ -179,6 +179,7 @@
 
 	clc_data = clc_data * freq_set + tdmntg_ref_clk / 2; /* with rounding to nearest integer */
 	clc_data *= comcerto_block_clk_div[block_selected];
+	do_div(clc_data, tdmntg_ref_clk);
 
 	if (clc_data & ~0x3FFFFFFF) {
 		/* unaccounted bits dangerous */
diff --git a/arch/arm/mach-comcerto/time.c b/arch/arm/mach-comcerto/time.c
old mode 100644
new mode 100755
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
old mode 100644
new mode 100755
index 0747102..ca9764e
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -757,8 +757,15 @@
 	bool "Disable speculative accesses"
 	depends on CPU_V7 && ARCH_COMCERTO
 	help
-	  Disable speculative accesses for the processor. This reduces overhead of cache maintenance for
-	  DMA mapped memory zones but may reduce overall system memory performance. If unsure, say N.
+	  Disable speculative accesses for the processor. This may reduce overall system memory performance but
+	  can allow other, potentially unsafe, optimizations (see below). If unsure, say N.
+
+config CPU_DMA_PARTIAL_INVALIDATES
+	bool "Do partial invalidates in the DMA management functions"
+	depends on CPU_V7 && ARCH_COMCERTO && CPU_SPECULATIVE_ACCESS_DISABLED
+	help
+	  Say Y here to reduce the overhead of cache maintenance for DMA mapped memory zones. 
+	  WARNING: UNSAFE, this may lead to random memory corruption. If unsure, say N.
 
 config CPU_BPREDICT_DISABLE
 	bool "Disable branch prediction"
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index ecf531d..c89301b 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -28,11 +28,79 @@
 #include <asm/mach/arch.h>
 
 #include "mm.h"
+#if defined(CONFIG_COMCERTO_UNCACHED_DMA)
+#include <linux/hugetlb.h>
+#include <asm/pgalloc.h>
+#include <asm/mach/map.h>
+#endif
 
 #ifdef CONFIG_COMCERTO_ZONE_DMA_NCNB
 extern unsigned long arm_dma_zone_size;
 #endif
 
+#if defined(CONFIG_COMCERTO_UNCACHED_DMA)
+static pgd_t *shadow_pg_dir;
+static u16 *shadow_pmd_count;
+
+static int __init init_shadow_page_table(void)
+{
+	pmd_t *pmd, *shadow_pmd;
+	pte_t *shadow_pte, *ptep;
+	unsigned long start, addr, end, pfn;
+	const struct mem_type *mt;
+	int count;
+
+	shadow_pg_dir = (pgd_t *)__get_free_pages(GFP_KERNEL | GFP_ATOMIC, get_order(16384));
+	if (!shadow_pg_dir)
+		return -ENOMEM;
+	shadow_pmd_count = (u16 *)__get_free_pages(GFP_KERNEL | GFP_ATOMIC, get_order(sizeof(u16) * PTRS_PER_PGD));
+	if (!shadow_pmd_count)
+		goto err1;
+
+	memset(shadow_pg_dir, 0, 16384);
+	memset(shadow_pmd_count, 0, sizeof(u16) * PTRS_PER_PGD);
+
+	mt = get_mem_type(MT_MEMORY);
+	start = 0;
+	count = 0;
+	do {
+		pmd = pmd_off_k((unsigned long) start);
+		if (!pmd_none(*pmd)) {
+			if (pmd_bad(*pmd) && ((pmd_val(*pmd) & ~SECTION_MASK) == mt->prot_sect)) {  // Only do it for MT_MEMORY areas
+				shadow_pmd = (pmd_t *)shadow_pg_dir + (pmd - pmd_off_k(0));
+				addr = (unsigned long)start & PMD_MASK;
+				end = addr + PMD_SIZE;
+
+				shadow_pte = (pte_t *)__get_free_page(PGALLOC_GFP | GFP_ATOMIC);
+				if (!shadow_pte)
+					goto err2;
+				pfn = __phys_to_pfn(pmd_val(*pmd) & PMD_MASK);
+				ptep = shadow_pte;
+				do {
+					set_pte_ext(ptep, pfn_pte(pfn, __pgprot(mt->prot_pte)), 0);
+					pfn++;
+				} while (ptep++, addr += PAGE_SIZE, addr != end);
+				__pmd_populate(shadow_pmd, __pa(shadow_pte), mt->prot_l1);
+			} else {
+				// Mark the shadow in use, so we never replace the already existing 2nd-level
+				shadow_pmd_count[pgd_index(start)]++;
+			}
+		}
+	} while (count++, start += PMD_SIZE, count < PTRS_PER_PGD);
+
+	return 0;
+
+err2:
+	__free_pages((struct page *)shadow_pmd_count, get_order(sizeof(u16) * PTRS_PER_PGD));
+	shadow_pmd_count = NULL;
+	//TODO: free already allocated shadow_pte tables
+err1:
+	__free_pages((struct page *)shadow_pg_dir, get_order(16384));
+	return -ENOMEM;
+}
+core_initcall(init_shadow_page_table);
+#endif
+
 static u64 get_coherent_dma_mask(struct device *dev)
 {
 	u64 mask = (u64)arm_dma_limit;
@@ -460,13 +528,211 @@
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
+#if defined(CONFIG_COMCERTO_UNCACHED_DMA)
+static inline void shadow_pmd_inc(const void *kaddr, int incr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&init_mm.page_table_lock, flags);
+	shadow_pmd_count[pgd_index((unsigned long) kaddr)] += incr;
+	spin_unlock_irqrestore(&init_mm.page_table_lock, flags);
+}
+
+static inline void copy_pmd_fast(pmd_t *pmdpd, pmd_t *pmdps)
+{
+#if !defined(CONFIG_COMCERTO_64K_PAGES)
+	pmdpd[0] = pmdps[0];
+	pmdpd[1] = pmdps[1];
+#else
+	int i;
+	for(i = 0; i < LINKED_PMDS; i++)
+		pmdpd[i] = pmdps[i];
+#endif
+}
+#endif
+
+static inline void __dmac_map_area(const void *kaddr, size_t size,
+	int dir)
+{
+#if defined(CONFIG_COMCERTO_UNCACHED_DMA)
+	pmd_t *pmd, *shadow_pmd;
+	pte_t *pte;
+	const void *kaddr_page;
+	const struct mem_type *mt;
+	unsigned int nr_pages, nr_pages_pmd;
+
+	if (!shadow_pmd_count)
+		goto op;
+
+	// For now, be safe and only uncache full pages so we don't have to handle
+	// the case of pages being DMA-mapped multiple times
+	if ((dir == DMA_FROM_DEVICE) && ((((unsigned long) kaddr|size) & ~PAGE_MASK) == 0)) {
+		mt = get_mem_type(MT_MEMORY_NONCACHED);
+		kaddr_page = kaddr;
+		pmd = pmd_off_k((unsigned long) kaddr_page);
+		shadow_pmd = (pmd_t *)shadow_pg_dir + (pmd - pmd_off_k(0));
+		nr_pages = __phys_to_pfn(size);
+
+		if (nr_pages == 1) { // Optimize for the common case
+			shadow_pmd_inc(kaddr_page, 1);
+			if (pmd_bad(*pmd)) { //No 2nd-level page table, retrieve it from the shadows
+				// Small race condition here, but at worst we'll end up copying the shadow_pmd to the actual pmd twice.
+				// For now, map the whole PMD. TODO: try and map only 1 section (1MB).
+				copy_pmd_fast(pmd, shadow_pmd);
+			}
+
+			pte = pte_offset_kernel(pmd, (int) kaddr_page);
+			uncache_pte_ext(pte);
+			flush_tlb_kernel_page((unsigned long) kaddr_page);
+			goto op;
+		}
+
+		nr_pages_pmd = __phys_to_pfn(PMD_SIZE - ((unsigned long) kaddr_page & ~PMD_MASK));
+
+		while (nr_pages) {
+
+			nr_pages_pmd = min(nr_pages, nr_pages_pmd);
+			nr_pages -= nr_pages_pmd;
+
+			shadow_pmd_inc(kaddr_page, nr_pages_pmd);
+
+			if (pmd_bad(*pmd)) { //No 2nd-level page table, retrieve it from the shadows
+				// Small race condition here, but at worst we'll end up copying the shadow_pmd to the actual pmd twice.
+				// For now, map the whole PMD. TODO: try and map only 1 section (1MB).
+				copy_pmd_fast(pmd, shadow_pmd);
+			}
+
+			pte = pte_offset_kernel(pmd, (int) kaddr_page);
+			while (nr_pages_pmd) {
+				uncache_pte_ext(pte);
+				flush_tlb_kernel_page((unsigned long) kaddr_page);
+				pte++;
+				kaddr_page += PAGE_SIZE;
+				nr_pages_pmd--;
+			}
+
+			nr_pages_pmd = PTRS_PER_PTE;
+#if !defined(CONFIG_COMCERTO_64K_PAGES)
+			pmd += 2;
+			shadow_pmd += 2;
+#else
+			pmd += LINKED_PMDS;
+			shadow_pmd += LINKED_PMDS;
+#endif
+		}
+	}
+	op:
+#endif
+	dmac_map_area(kaddr, size, dir);
+}
+
 static inline void __dmac_unmap_area(const void *kaddr, size_t size,
 	int dir)
 {
-#if !defined(CONFIG_CPU_SPECULATIVE_ACCESS_DISABLED)
+#if defined(CONFIG_COMCERTO_UNCACHED_DMA)
+	pmd_t *pmd;
+	pte_t *pte;
+	const struct mem_type *mt;
+	unsigned long pa;
+	const void *kaddr_page;
+	unsigned long flags;
+	unsigned int nr_pages, nr_pages_pmd, page_count;
+
+	if (!shadow_pmd_count)
+		goto op;
+
+	if ((dir == DMA_FROM_DEVICE) && ((((unsigned long) kaddr|size) & ~PAGE_MASK) == 0)) {
+		mt = get_mem_type(MT_MEMORY);
+		kaddr_page = kaddr;
+
+		pmd = pmd_off_k((unsigned long) kaddr_page);
+		pa = __virt_to_phys((unsigned long)kaddr_page & PMD_MASK);
+
+		nr_pages = __phys_to_pfn(size);
+
+		if (nr_pages == 1) { // Optimize for the common case
+			if (pmd_bad(*pmd)) // No 2nd-level page table, so page was never made non-cacheable.
+				goto op;
+			pte = pte_offset_kernel(pmd, (int) kaddr_page);
+			set_pte_ext(pte, *pte, 0);
+
+			spin_lock_irqsave(&init_mm.page_table_lock, flags);
+			shadow_pmd_count[pgd_index((unsigned long) kaddr_page)]--;
+			if (shadow_pmd_count[pgd_index((unsigned long) kaddr_page)] == 0) {
+#if !defined(CONFIG_COMCERTO_64K_PAGES)
+				*pmd = __pmd(pa | mt->prot_sect);
+				pmd++;
+				pa += SECTION_SIZE;
+				*pmd = __pmd(pa | mt->prot_sect);
+#else
+				pmd_t *orig_pmd = pmd;
+				while (pmd < (orig_pmd + LINKED_PMDS)) {
+					*pmd = __pmd(pa | mt->prot_sect);
+					pa += SECTION_SIZE;
+					pmd++;
+				}
+#endif
+			}
+			spin_unlock_irqrestore(&init_mm.page_table_lock, flags);
+
+			flush_tlb_kernel_page((unsigned long) kaddr_page);
+			return;
+		}
+
+		nr_pages_pmd = __phys_to_pfn(PMD_SIZE - ((unsigned long) kaddr_page & ~PMD_MASK));
+
+		while (nr_pages) {
+			if (pmd_bad(*pmd)) // No 2nd-level page table, so page was never made non-cacheable.
+				goto op;
+			nr_pages_pmd = min(nr_pages, nr_pages_pmd);
+			nr_pages -= nr_pages_pmd;
+
+			pte = pte_offset_kernel(pmd, (int) kaddr_page);
+			page_count = nr_pages_pmd;
+			while (page_count) {
+				set_pte_ext(pte, *pte, 0);
+				pte++;
+				page_count--;
+			}
+
+			spin_lock_irqsave(&init_mm.page_table_lock, flags);
+			shadow_pmd_count[pgd_index((unsigned long) kaddr_page)] -= nr_pages_pmd;
+			if (shadow_pmd_count[pgd_index((unsigned long) kaddr_page)] == 0) {
+#if !defined(CONFIG_COMCERTO_64K_PAGES)
+				*pmd = __pmd(pa | mt->prot_sect);
+				pmd++;
+				pa += SECTION_SIZE;
+				*pmd = __pmd(pa | mt->prot_sect);
+				pmd++;
+				pa += SECTION_SIZE;
+#else
+				pmd_t *orig_pmd = pmd;
+				while (pmd < (orig_pmd + LINKED_PMDS)) {
+					*pmd = __pmd(pa | mt->prot_sect);
+					pmd++;
+					pa += SECTION_SIZE;
+				}
+#endif
+			}
+			spin_unlock_irqrestore(&init_mm.page_table_lock, flags);
+
+			while (nr_pages_pmd) {
+				flush_tlb_kernel_page((unsigned long) kaddr_page);
+				kaddr_page += PAGE_SIZE;
+				nr_pages_pmd--;
+			}
+
+			nr_pages_pmd = PTRS_PER_PTE;
+		}
+
+		return;
+	}
+	op:
+#endif
+#if !defined(CONFIG_CPU_DMA_PARTIAL_INVALIDATES)
 	dmac_unmap_area(kaddr, size, dir);
 #else
-	size_t size_inv = min((size_t) 32, size);
+	size_t size_inv = min_t(size_t, 32, size);
 
 	dmac_unmap_area(kaddr, size_inv, dir);
 	dmac_unmap_area(kaddr + size - size_inv, size_inv, dir);
@@ -487,11 +753,14 @@
 	BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
 
 #ifdef CONFIG_COMCERTO_ZONE_DMA_NCNB
-	if ((paddr + size) <= arm_dma_zone_size)
-		return;
-#endif
+	if ((paddr + size) <= arm_dma_zone_size) {
+		if (dir != DMA_FROM_DEVICE)
+			wmb();
 
-	dmac_map_area(kaddr, size, dir);
+		return;
+	}
+#endif
+	__dmac_map_area(kaddr, size, dir);
 
 #if !defined(CONFIG_L2X0_INSTRUCTION_ONLY)
 	if (dir == DMA_FROM_DEVICE) {
@@ -519,10 +788,10 @@
 #if !defined(CONFIG_L2X0_INSTRUCTION_ONLY)
 	/* don't bother invalidating if DMA to device */
 	if (dir != DMA_TO_DEVICE) {
-#if !defined(CONFIG_CPU_SPECULATIVE_ACCESS_DISABLED)
+#if !defined(CONFIG_CPU_DMA_PARTIAL_INVALIDATES)
 		outer_inv_range(paddr, paddr + size);
 #else
-		size_t size_inv = min(32, size);
+		size_t size_inv = min_t(size_t, 32, size);
 
 		outer_inv_range(paddr, paddr + size_inv);
 		outer_inv_range(paddr + size - size_inv, paddr + size);
@@ -572,6 +841,7 @@
 			vaddr = page_address(page) + offset;
 			op(vaddr, len, dir);
 		}
+
 		offset = 0;
 		page++;
 		left -= len;
@@ -584,11 +854,15 @@
 	unsigned long paddr = page_to_phys(page) + off;
 
 #ifdef CONFIG_COMCERTO_ZONE_DMA_NCNB
-	if ((paddr + size) <= arm_dma_zone_size)
+	if ((paddr + size) <= arm_dma_zone_size) {
+		if (dir != DMA_FROM_DEVICE)
+			wmb();
+
 		return;
+	}
 #endif
 
-	dma_cache_maint_page(page, off, size, dir, dmac_map_area);
+	dma_cache_maint_page(page, off, size, dir, __dmac_map_area);
 
 #if !defined(CONFIG_L2X0_INSTRUCTION_ONLY)
 	if (dir == DMA_FROM_DEVICE) {
@@ -614,10 +888,10 @@
 #if !defined(CONFIG_L2X0_INSTRUCTION_ONLY)
 	/* don't bother invalidating if DMA to device */
 	if (dir != DMA_TO_DEVICE) {
-#if !defined(CONFIG_CPU_SPECULATIVE_ACCESS_DISABLED)
+#if !defined(CONFIG_CPU_DMA_PARTIAL_INVALIDATES)
 		outer_inv_range(paddr, paddr + size);
 #else
-		size_t size_inv = min(32, size);
+		size_t size_inv = min_t(size_t, 32, size);
 
 		outer_inv_range(paddr, paddr + size_inv);
 		outer_inv_range(paddr + size - size_inv, paddr + size);
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 3c1d074..94e7396 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -241,6 +241,12 @@
 	}
 }
 
+static void sync_outer_cache(struct page *page)
+{
+	unsigned long phys = page_to_phys(page);
+
+	outer_flush_range(phys, phys + PAGE_SIZE);
+}
 #endif
 
 #if __LINUX_ARM_ARCH__ >= 6
@@ -314,6 +320,10 @@
 			__flush_dcache_aliases(mapping, page);
 		else if (mapping)
 			__flush_icache_all();
+
+#if defined(CONFIG_L2X0_INSTRUCTION_ONLY)
+		sync_outer_cache(page);
+#endif
 		set_bit(PG_dcache_clean, &page->flags);
 	}
 }
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index c143fcc..f362cf8 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -427,9 +427,15 @@
 
 	for (; pfn < end; pfn++) {
 		struct page *page = pfn_to_page(pfn);
+#if defined(CONFIG_L2X0_INSTRUCTION_ONLY)
+		unsigned long phys = page_to_phys(page);
+#endif
 		ClearPageReserved(page);
 		init_page_count(page);
 		__free_page(page);
+#if defined(CONFIG_L2X0_INSTRUCTION_ONLY)
+		outer_flush_range(phys, phys + PAGE_SIZE);
+#endif
 		pages++;
 	}
 
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index d6f70a2..f452bdc 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1045,11 +1045,19 @@
 			map.pfn = __phys_to_pfn(start);
 			map.virtual = __phys_to_virt(start);
 			map.length = length_ncnb_now;
-			map.type = MT_MSP_NCNB;
+			map.type = MT_MEMORY_NONCACHED;
+
 			printk("Comcerto: zone_dma mapping size=%lx type=%lx\n", (unsigned long) map.length, (unsigned long) map.type);
+
+			if (!arm_dma_zone.start)
+				arm_dma_zone.start = __phys_to_virt(start);
+
 			create_mapping(&map);
 			start += length_ncnb_now;
 			length_ncnb -= length_ncnb_now;
+
+			arm_dma_zone.end = __phys_to_virt(start);
+
 			if (start == end)
 				continue;
 
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index b16ffb1..5f3bd9b 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -201,6 +201,41 @@
 	mov	pc, lr
 ENDPROC(cpu_v7_set_pte_ext)
 
+/* Make the memory uncached, but keep Linux settings as is so memory may be
+ * reset to original attributes later on.
+ */
+ENTRY(cpu_v7_uncache_pte_ext)
+#ifdef CONFIG_MMU
+#if !defined(CONFIG_COMCERTO_64K_PAGES)
+ ARM(	ldr	r3, [r0, #2048]! )
+ THUMB(	add	r0, r0, #2048 )
+ THUMB( ldr r3, [r0] )
+		bic r3, r3, #0x48		@ clear TEX[0],C bits (see below)
+		orr r3, r3, #0x4  		@ set B bit (see below)
+ ARM(	str	r3, [r0, #2048]! )
+ THUMB(	str	r3, [r0] )
+ #else
+	ldr r1, =32768		@ PTE_HWTABLE_OFF
+	add r1, r1, r0
+	ldr r3, [r1]
+	add r2, r1, #64		@ 16*4 bytes
+ARM(	bic r3, r3, #0x1008 ) 	@ clear TEX[0],C bits (see below)
+THUMB(	bic r3, r3, #0x8 )
+THUMB(	bic r3, r3, #0x1000 )
+	orr r3, r3, #0x4			@ set B bit (see below)
+ 1:
+	sub r2, r2, #4
+	str	r3, [r2]!
+	cmp r1, r2
+	blo 1b
+ #endif
+
+
+#endif
+	mov	pc, lr
+ENDPROC(cpu_v7_uncache_pte_ext)
+
+
 	string	cpu_v7_name, "ARMv7 Processor"
 	.align
 
@@ -267,6 +302,9 @@
 	ALT_UP(orr	r1, r1, #TTB_FLAGS_UP)
 	mcr	p15, 0, r1, c2, c0, 0	@ TTB 0
 	mcr	p15, 0, r7, c2, c0, 1	@ TTB 1
+#if defined(CONFIG_COMCERTO_HW_KERNEL_PAGETABLE)
+	mov ip, #1						@ set TTBRCR.N to 1, so that addresses above 2GB will use TTB1
+#endif
 	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
 	mrc	p15, 0, r4, c1, c0, 1	@ Read Auxiliary control register
 	teq	r4, r9			@ Is it already set?
@@ -398,6 +436,9 @@
 	dsb
 #ifdef CONFIG_MMU
 	mcr	p15, 0, r10, c8, c7, 0		@ invalidate I + D TLBs
+#if defined(CONFIG_COMCERTO_HW_KERNEL_PAGETABLE)
+	mov r10, #1						@ set TTBRCR.N to 1, so that addresses above 2GB will use TTB1
+#endif
 	mcr	p15, 0, r10, c2, c0, 2		@ TTB control register
 	ALT_SMP(orr	r4, r4, #TTB_FLAGS_SMP)
 	ALT_UP(orr	r4, r4, #TTB_FLAGS_UP)
diff --git a/crypto/ocf/Config.in b/crypto/ocf/Config.in
old mode 100644
new mode 100755
diff --git a/crypto/ocf/Kconfig b/crypto/ocf/Kconfig
old mode 100644
new mode 100755
diff --git a/crypto/ocf/Makefile b/crypto/ocf/Makefile
old mode 100644
new mode 100755
diff --git a/crypto/ocf/criov.c b/crypto/ocf/criov.c
old mode 100644
new mode 100755
diff --git a/crypto/ocf/crypto.c b/crypto/ocf/crypto.c
old mode 100644
new mode 100755
diff --git a/crypto/ocf/cryptodev.c b/crypto/ocf/cryptodev.c
old mode 100644
new mode 100755
diff --git a/crypto/ocf/cryptodev.h b/crypto/ocf/cryptodev.h
old mode 100644
new mode 100755
diff --git a/crypto/ocf/cryptosoft.c b/crypto/ocf/cryptosoft.c
old mode 100644
new mode 100755
diff --git a/crypto/ocf/ocf-bench.c b/crypto/ocf/ocf-bench.c
old mode 100644
new mode 100755
diff --git a/crypto/ocf/ocf-compat.h b/crypto/ocf/ocf-compat.h
old mode 100644
new mode 100755
diff --git a/crypto/ocf/random.c b/crypto/ocf/random.c
old mode 100644
new mode 100755
diff --git a/crypto/ocf/rndtest.c b/crypto/ocf/rndtest.c
old mode 100644
new mode 100755
diff --git a/crypto/ocf/rndtest.h b/crypto/ocf/rndtest.h
old mode 100644
new mode 100755
diff --git a/crypto/ocf/uio.h b/crypto/ocf/uio.h
old mode 100644
new mode 100755
diff --git a/drivers/Makefile b/drivers/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index c0ef346..1fab515 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -30,6 +30,9 @@
 static struct clk *sata_oob_clk; /* Core clock */
 static struct clk *sata_pmu_clk; /* PMU alive clock */
 static struct clk *sata_clk;	/* Sata AXI ref clock */
+#if defined(CONFIG_COMCERTO_SATA_OCC_CLOCK)
+static struct clk *sata_occ_clk; /* sata OCC clock */
+#endif
 #endif 
 
 enum ahci_type {
@@ -170,7 +173,20 @@
 		pr_err("%s: SATA_PMU clock enable failed \n",__func__);
 		return rc;
 	}
-
+#if defined(CONFIG_COMCERTO_SATA_OCC_CLOCK)
+	sata_occ_clk = clk_get(NULL,"sata_occ");
+	/* Error Handling , if no sata occ clock reference: return error */
+	if (IS_ERR(sata_occ_clk)) {
+		pr_err("%s: Unable to obtain sata occ clock: %ld\n",__func__,PTR_ERR(sata_occ_clk));
+		return PTR_ERR(sata_occ_clk);
+ 	}
+	/*Enable the sata_occ clocks here */
+        rc = clk_enable(sata_occ_clk);
+	if (rc){
+		pr_err("%s: sata occ clock enable failed \n",__func__);
+		return rc;
+	}
+#endif
 	/* Set the SATA PMU clock to 30 MHZ and OOB clock to 125MHZ */
 	clk_set_rate(sata_oob_clk,125000000);
 	clk_set_rate(sata_pmu_clk,30000000);
@@ -311,7 +327,10 @@
 	clk_put(sata_oob_clk);
 	clk_disable(sata_pmu_clk);
 	clk_put(sata_pmu_clk);
-
+#if defined(CONFIG_COMCERTO_SATA_OCC_CLOCK)
+	clk_disable(sata_occ_clk);
+	clk_put(sata_occ_clk);
+#endif
 	/*Putting  SATA in reset state 
 	 * Sata axi clock domain in reset state
 	 * Serdes 1/2 in reset state, this depends upon PCIE1 and SGMII 
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
old mode 100644
new mode 100755
diff --git a/drivers/dma/c2k_dma.c b/drivers/dma/c2k_dma.c
index 0645126..dde086c 100644
--- a/drivers/dma/c2k_dma.c
+++ b/drivers/dma/c2k_dma.c
@@ -164,6 +164,7 @@
 
 		phys_addr = dma_acp_map_page(sg, page, offset, len, DMA_TO_DEVICE, use_acp);
 
+		sg->in_bdesc[sg->input_idx].split = 0;
 		sg->in_bdesc[sg->input_idx].phys_addr = phys_addr;
 		sg->in_bdesc[sg->input_idx].len = len;
 		sg->input_idx++;
@@ -176,9 +177,11 @@
 
 		phys_addr = dma_acp_map_page(sg, page, offset, len, DMA_TO_DEVICE, use_acp);
 
+		sg->in_bdesc[sg->input_idx].split = 1;
 		sg->in_bdesc[sg->input_idx].phys_addr = phys_addr;
 		sg->in_bdesc[sg->input_idx].len = MDMA_SPLIT_BUF_SIZE;
 		sg->input_idx++;
+		sg->in_bdesc[sg->input_idx].split = 0;
 		sg->in_bdesc[sg->input_idx].phys_addr = phys_addr + MDMA_SPLIT_BUF_SIZE;
 		sg->in_bdesc[sg->input_idx].len = MDMA_SPLIT_BUF_SIZE;
 		sg->input_idx++;
@@ -203,6 +206,7 @@
 
 		phys_addr = dma_acp_map_page(sg, page, offset, len, DMA_FROM_DEVICE, use_acp);
 
+		sg->out_bdesc[sg->output_idx].split = 0;
 		sg->out_bdesc[sg->output_idx].phys_addr = phys_addr;
 		sg->out_bdesc[sg->output_idx].len = len;
 		sg->output_idx++;
@@ -215,9 +219,11 @@
 
 		phys_addr = dma_acp_map_page(sg, page, offset, len, DMA_FROM_DEVICE, use_acp);
 
+		sg->out_bdesc[sg->output_idx].split = 1;
 		sg->out_bdesc[sg->output_idx].phys_addr = phys_addr;
 		sg->out_bdesc[sg->output_idx].len = MDMA_SPLIT_BUF_SIZE;
 		sg->output_idx++;
+		sg->out_bdesc[sg->output_idx].split = 0;
 		sg->out_bdesc[sg->output_idx].phys_addr = phys_addr + MDMA_SPLIT_BUF_SIZE;
 		sg->out_bdesc[sg->output_idx].len = MDMA_SPLIT_BUF_SIZE;
 		sg->output_idx++;
@@ -283,10 +289,15 @@
 	remaining = len;
 	i = 0;
 	while (remaining > sg->in_bdesc[i].len) {
-		if (sg->in_bdesc[i].phys_addr < COMCERTO_AXI_ACP_BASE)
-			dma_unmap_page(NULL, sg->in_bdesc[i].phys_addr, sg->in_bdesc[i].len, DMA_TO_DEVICE);
-
-		remaining -= sg->in_bdesc[i].len;
+		if (sg->in_bdesc[i].split) {
+			sg->in_bdesc[i+1].phys_addr = sg->in_bdesc[i].phys_addr;
+			sg->in_bdesc[i+1].len += sg->in_bdesc[i].len;
+		}
+		else {
+			if (sg->in_bdesc[i].phys_addr < COMCERTO_AXI_ACP_BASE)
+				dma_unmap_page(NULL, sg->in_bdesc[i].phys_addr, sg->in_bdesc[i].len, DMA_TO_DEVICE);
+			remaining -= sg->in_bdesc[i].len;
+		}
 		i++;
 	}
 
@@ -296,10 +307,15 @@
 	remaining = len;
 	i = 0;
 	while (remaining > sg->out_bdesc[i].len) {
-		if (sg->out_bdesc[i].phys_addr < COMCERTO_AXI_ACP_BASE)
-			dma_unmap_page(NULL, sg->out_bdesc[i].phys_addr, sg->out_bdesc[i].len, DMA_FROM_DEVICE);
-
-		remaining -= sg->out_bdesc[i].len;
+		if (sg->out_bdesc[i].split) {
+			sg->out_bdesc[i+1].phys_addr = sg->out_bdesc[i].phys_addr;
+			sg->out_bdesc[i+1].len += sg->out_bdesc[i].len;
+		}
+		else {
+			if (sg->out_bdesc[i].phys_addr < COMCERTO_AXI_ACP_BASE)
+				dma_unmap_page(NULL, sg->out_bdesc[i].phys_addr, sg->out_bdesc[i].len, DMA_FROM_DEVICE);
+			remaining -= sg->out_bdesc[i].len;
+		}
 		i++;
 	}
 
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 283d887..b6d7e9a 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -98,7 +98,7 @@
 config M25PXX_USE_FAST_READ
 	bool "Use FAST_READ OPCode allowing SPI CLK <= 50MHz"
 	depends on MTD_M25P80
-	default y
+	default n
 	help
 	  This option enables FAST_READ access supported by ST M25Pxx.
 
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 9f9982f..0506d27 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -35,6 +35,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 
+
 /* Flash opcodes. */
 #define	OPCODE_WREN		0x06	/* Write enable */
 #define	OPCODE_RDSR		0x05	/* Read status register */
@@ -100,6 +101,54 @@
 	return container_of(mtd, struct m25p, mtd);
 }
 
+
+int m25p80_write_then_read(struct spi_device *spi,
+		const void *txbuf, unsigned n_tx,
+		void *rxbuf, unsigned n_rx)
+{
+	static DEFINE_MUTEX(m25p80_lock);
+	int			status;
+	struct spi_message	message;
+	struct spi_transfer	x[2];
+	u8			*local_buf;
+	u_char rx_data[8];
+	int len_to_tx = 0;
+	int len_tx_total = 0;
+	int len_tx_done = 0;
+
+	/* Use preallocated DMA-safe buffer.  We can't avoid copying here,
+	 * (as a pure convenience thing), but we can keep heap costs
+	 * out of the hot path ...
+	 */
+	if ((n_tx + n_rx) > 8)
+	{
+		printk(KERN_ERR "##### %s: size greater than 8 #########\n",__func__);
+		return -EINVAL;
+	}
+
+	spi_message_init(&message);
+	memset(x, 0, sizeof x);
+
+	len_to_tx = n_tx + n_rx;
+
+	x[0].len = len_to_tx;
+	x[0].tx_buf = txbuf;
+	x[0].rx_buf = &rx_data[0];
+
+	spi_message_add_tail(&x[0], &message);
+
+	mutex_lock(&m25p80_lock);
+
+	/* do the i/o */
+	status = spi_sync(spi, &message);
+	if (status == 0)
+		memcpy(rxbuf, rx_data + n_tx, n_rx);
+
+	mutex_unlock(&m25p80_lock);
+
+	return status;
+}
+
 /****************************************************************************/
 
 /*
@@ -117,7 +166,7 @@
 	u8 code = OPCODE_RDSR;
 	u8 val;
 
-	retval = spi_write_then_read(flash->spi, &code, 1, &val, 1);
+	retval = m25p80_write_then_read(flash->spi, &code, 1, &val, 1);
 
 	if (retval < 0) {
 		dev_err(&flash->spi->dev, "error %d reading SR\n",
@@ -148,7 +197,7 @@
 {
 	u8	code = OPCODE_WREN;
 
-	return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
+	return m25p80_write_then_read(flash->spi, &code, 1, NULL, 0);
 }
 
 /*
@@ -158,7 +207,7 @@
 {
 	u8	code = OPCODE_WRDI;
 
-	return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
+	return m25p80_write_then_read(flash->spi, &code, 1, NULL, 0);
 }
 
 /*
@@ -249,8 +298,8 @@
  */
 static int erase_sector(struct m25p *flash, u32 offset)
 {
-	pr_debug("%s: %s %dKiB at 0x%08x\n", dev_name(&flash->spi->dev),
-			__func__, flash->mtd.erasesize / 1024, offset);
+	pr_debug("%s: %s %dKiB at 0x%08x cmdsz %d\n", dev_name(&flash->spi->dev),
+			__func__, flash->mtd.erasesize / 1024, offset, m25p_cmdsz(flash));
 
 	/* Wait until finished previous write command. */
 	if (wait_till_ready(flash))
@@ -339,6 +388,7 @@
  * Read an address range from the flash chip.  The address range
  * may be any size provided it is within the physical boundaries.
  */
+#if 0
 static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
 	size_t *retlen, u_char *buf)
 {
@@ -371,6 +421,8 @@
 	t[1].len = len;
 	spi_message_add_tail(&t[1], &m);
 
+	pr_debug("%s: t[0].len 0x%x t[1].len 0x%x\n",__func__, t[0].len, t[1].len);
+
 	/* Byte count starts at zero. */
 	*retlen = 0;
 
@@ -400,14 +452,95 @@
 
 	return 0;
 }
+#endif
+
+static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+	size_t *retlen, u_char *buf)
+{
+	struct m25p *flash = mtd_to_m25p(mtd);
+	struct spi_transfer t[2];
+	struct spi_message m;
+	int len_to_tx = 0;
+	int len_tx_total = 0;
+	int len_tx_done = 0;
+	int i;
+	u_char rx_data[8];
+	int cmd_size = m25p_cmdsz(flash);
+	int max_data_len = 8 - m25p_cmdsz(flash);
+
+	pr_debug("%s: %s from 0x%08x,len %zd\n", dev_name(&flash->spi->dev),
+			__func__, (u32)from, len);
+
+	/* sanity checks */
+	if (!len)
+		return 0;
+
+	if (from + len > flash->mtd.size)
+		return -EINVAL;
+
+	while(len_tx_done < len)
+	{
+
+		spi_message_init(&m);
+		memset(t, 0, (sizeof t));
+
+		if((len - len_tx_done) < max_data_len)
+			len_to_tx = len - len_tx_done;
+		else
+			len_to_tx = max_data_len;
+		/* NOTE:
+		 * OPCODE_FAST_READ (if available) is faster.
+		 * Should add 1 byte DUMMY_BYTE.
+		 */
+		t[0].tx_buf = flash->command;
+		t[0].rx_buf = &rx_data[0] ;
+		t[0].len = cmd_size + len_to_tx;
+		spi_message_add_tail(&t[0], &m);
+
+
+		/* Byte count starts at zero. */
+		*retlen = 0;
+
+		mutex_lock(&flash->lock);
+
+		/* Wait till previous write/erase is done. */
+		if (wait_till_ready(flash)) {
+			/* REVISIT status return?? */
+			mutex_unlock(&flash->lock);
+			return 1;
+		}
+
+		/* FIXME switch to OPCODE_FAST_READ.  It's required for higher
+		 * clocks; and at this writing, every chip this driver handles
+		 * supports that opcode.
+		 */
+
+		/* Set up the write data buffer. */
+		flash->command[0] = OPCODE_READ;
+		m25p_addr2cmd(flash, from + len_tx_done, flash->command);
+
+		spi_sync(flash->spi, &m);
+
+		memcpy(buf + len_tx_done, &rx_data[cmd_size], len_to_tx);
+
+		len_tx_done += len_to_tx;//valid data which will be read out of 8 bytes
+
+		mutex_unlock(&flash->lock);
+	}
+
+	*retlen = len_tx_done;
+
+	return 0;
+}
 
 /*
  * Write an address range to the flash chip.  Data must be written in
  * FLASH_PAGESIZE chunks.  The address range may be any size provided
  * it is within the physical boundaries.
  */
+#if 0
 static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
-	size_t *retlen, const u_char *buf)
+		size_t *retlen, const u_char *buf)
 {
 	struct m25p *flash = mtd_to_m25p(mtd);
 	u32 page_offset, page_size;
@@ -496,6 +629,78 @@
 
 	return 0;
 }
+#endif
+
+static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u_char *buf)
+{
+	struct m25p *flash = mtd_to_m25p(mtd);
+	u32 page_offset, page_size;
+	struct spi_transfer t[2];
+	struct spi_message m;
+	u_char tx_buf[8];
+	int len_to_tx = 0;
+	int len_tx_total = 0;
+	int len_tx_done = 0;
+	int cmd_size = m25p_cmdsz(flash);
+	int max_data_len = 8 - m25p_cmdsz(flash);
+
+	pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+			__func__, (u32)to, len);
+
+	*retlen = 0;
+
+	/* sanity checks */
+	if (!len)
+		return(0);
+
+	if (to + len > flash->mtd.size)
+		return -EINVAL;
+
+	mutex_lock(&flash->lock);
+
+	while(len_tx_done < len)
+	{
+
+		spi_message_init(&m);
+		memset(t, 0, (sizeof t));
+
+		if((len - len_tx_done) < max_data_len)
+			len_to_tx = len - len_tx_done;
+		else
+			len_to_tx = max_data_len;
+
+		/* Set up the opcode in the write buffer. */
+		flash->command[0] = OPCODE_PP;
+		m25p_addr2cmd(flash, to + len_tx_done, flash->command);
+		memcpy(&tx_buf[0], flash->command, cmd_size);
+		memcpy(&tx_buf[cmd_size], buf + len_tx_done, len_to_tx);
+
+		t[0].tx_buf = &tx_buf[0];
+		t[0].len = cmd_size + len_to_tx;
+
+		spi_message_add_tail(&t[0], &m);
+
+		/* Wait until finished previous write command. */
+		if (wait_till_ready(flash)) {
+			mutex_unlock(&flash->lock);
+			return 1;
+		}
+
+		write_enable(flash);
+
+		spi_sync(flash->spi, &m);
+
+		len_tx_done += len_to_tx;//valid data which sent out of 8 bytes
+	}
+
+	*retlen = len_tx_done;
+
+	mutex_unlock(&flash->lock);
+
+	return 0;
+}
+
 
 static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
 		size_t *retlen, const u_char *buf)
@@ -783,7 +988,7 @@
 	 * string for after vendor-specific data, after the three bytes
 	 * we use here.  Supporting some chips might require using it.
 	 */
-	tmp = spi_write_then_read(spi, &code, 1, id, 5);
+	tmp = m25p80_write_then_read(spi, &code, 1, id, 5);
 	if (tmp < 0) {
 		pr_debug("%s: error %d reading JEDEC ID\n",
 				dev_name(&spi->dev), tmp);
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/mtd/maps/comcerto-nor.c b/drivers/mtd/maps/comcerto-nor.c
old mode 100644
new mode 100755
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 14164c4..f035281 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -2874,6 +2874,8 @@
 
 	write_unlock_bh(&pch->upl);
 
+/*We need to revisit below changes when PPPoE automode is introduced to C2K*/
+#if 0
 #if defined(CONFIG_COMCERTO_FP)
 	if ((ppp->dev) && (!ppp->closing)) {
 		rtnl_lock();
@@ -2881,6 +2883,7 @@
 		rtnl_unlock();
 	}
 #endif
+#endif
 
 	ret = 0;
  out:
@@ -2909,6 +2912,8 @@
 			wake_up_interruptible(&ppp->file.rwait);
 		ppp_unlock(ppp);
 
+/*We need to revisit below changes when PPPoE automode is introduced to C2K*/
+#if 0
 #if defined(CONFIG_COMCERTO_FP)
 		if ((ppp->dev) && (!ppp->closing)) {
 			rtnl_lock();
@@ -2916,6 +2921,7 @@
 			rtnl_unlock();
 		}
 #endif
+#endif
 
 		if (atomic_dec_and_test(&ppp->file.refcnt))
 			ppp_destroy_interface(ppp);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index b873b5d..2864780 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -49,6 +49,14 @@
 
 #define DRIVER_VERSION		"22-Aug-2005"
 
+#ifdef CONFIG_ARCH_M86XXX
+/* 
+ * We alllocate extra 64 Bytes to reserve headroom in the sk_buff 
+ * To be used by Fast Path (Head Room must be 4 Byte aligned 
+ * because USB 2.0 controller doesn't support 2 byte alignment
+ */
+#define C2K_USBNET_SKB_HEADROOM_FAST_PATH 64
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -344,13 +352,26 @@
 	unsigned long		lockflags;
 	size_t			size = dev->rx_urb_size;
 
+#ifdef CONFIG_ARCH_M86XXX
+    /* 
+     * We alllocate extra 64 Bytes to reserve headroom in the sk_buff 
+     * To be used by Fast Path (Head Room must be 4 Byte aligned 
+     * because USB 2.0 controller doesn't support 2 byte alignment
+     */
+	if ((skb = alloc_skb (size + C2K_USBNET_SKB_HEADROOM_FAST_PATH, flags)) == NULL) {
+#else
 	if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
+#endif        
 		netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
 		usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
 		usb_free_urb (urb);
 		return -ENOMEM;
 	}
+#ifdef CONFIG_ARCH_M86XXX
+	skb_reserve (skb, C2K_USBNET_SKB_HEADROOM_FAST_PATH);
+#else
 	skb_reserve (skb, NET_IP_ALIGN);
+#endif        
 
 	entry = (struct skb_data *) skb->cb;
 	entry->urb = urb;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
old mode 100644
new mode 100755
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
old mode 100644
new mode 100755
index 8e55f77..41c6530
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -33,11 +33,12 @@
 ifeq ($(CONFIG_SPI_MSPD_LOW_SPEED),y)
     SPI_MSPD=y
 endif
-obj-$(SPI_MSPD)				+= spi-c2000-dma.o
-obj-$(SPI_MSPD)				+= spi-c2000.o
+#obj-$(SPI_MSPD)				+= spi-c2000-dma.o
+#obj-$(SPI_MSPD)				+= spi-c2000.o
 
 obj-$(CONFIG_SPI_DAVINCI)		+= spi-davinci.o
-obj-$(CONFIG_SPI_DESIGNWARE)		+= spi-dw.o
+obj-$(CONFIG_SPI_DESIGNWARE)		+= designware_spi.o
+#obj-$(CONFIG_SPI_DESIGNWARE)		+= spi-dw.o
 obj-$(CONFIG_SPI_DW_MMIO)		+= spi-dw-mmio.o
 obj-$(CONFIG_SPI_DW_PCI)		+= spi-dw-midpci.o
 spi-dw-midpci-objs			:= spi-dw-pci.o spi-dw-mid.o
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
new file mode 100644
index 0000000..ff66c1ff
--- /dev/null
+++ b/drivers/spi/designware_spi.c
@@ -0,0 +1,794 @@
+/*
+ * designware_spi.c
+ *
+ * Synopsys DesignWare AMBA SPI controller driver (master mode only)
+ *
+ * Author: Baruch Siach, Tk Open Systems
+ *	baruch-NswTu9S1W3P6gbPvEgmw2w@...org
+ *
+ * Base on the Xilinx SPI controller driver by MontaVista
+ *
+ * 2002-2007 (c) MontaVista Software, Inc.  This file is licensed under the
+ * terms of the GNU General Public License version 2.  This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ *
+ * 2008, 2009 (c) Provigent Ltd.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/designware.h>
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <mach/reset.h>
+
+#define DESIGNWARE_SPI_NAME "comcerto_spi"
+
+/* Register definitions as per "DesignWare DW_apb_ssi Databook", Capture 6. */
+
+#define DWSPI_CTRLR0        0x00
+#define DWSPI_CTRLR1        0x04
+#define DWSPI_SSIENR        0x08
+#define DWSPI_MWCR          0x0C
+#define DWSPI_SER           0x10
+#define DWSPI_BAUDR         0x14
+#define DWSPI_TXFTLR        0x18
+#define DWSPI_RXFTLR        0x1C
+#define DWSPI_TXFLR         0x20
+#define DWSPI_RXFLR         0x24
+#define DWSPI_SR            0x28
+#define DWSPI_IMR           0x2C
+#define DWSPI_ISR           0x30
+#define DWSPI_RISR          0x34
+#define DWSPI_TXOICR        0x38
+#define DWSPI_RXOICR        0x3C
+#define DWSPI_RXUICR        0x40
+#define DWSPI_ICR           0x44
+#define DWSPI_DMACR         0x4C
+#define DWSPI_DMATDLR       0x50
+#define DWSPI_DMARDLR       0x54
+#define DWSPI_IDR           0x58
+#define DWSPI_SSI_COMP_VERSION 0x5C
+#define DWSPI_DR            0x60
+
+#define DWSPI_CTRLR0_DFS_MASK	0x000f
+#define DWSPI_CTRLR0_SCPOL	0x0080
+#define DWSPI_CTRLR0_SCPH	0x0040
+#define DWSPI_CTRLR0_TMOD_MASK	0x0300
+
+#define DWSPI_SR_BUSY_MASK	0x01
+#define DWSPI_SR_TFNF_MASK	0x02
+#define DWSPI_SR_TFE_MASK	0x04
+#define DWSPI_SR_RFNE_MASK	0x08
+#define DWSPI_SR_RFF_MASK	0x10
+
+#define DWSPI_ISR_TXEIS_MASK	0x01
+#define DWSPI_ISR_RXFIS_MASK	0x10
+
+#define DWSPI_IMR_TXEIM_MASK	0x01
+#define DWSPI_IMR_RXFIM_MASK	0x10
+
+struct designware_spi {
+	struct device *dev;
+	struct workqueue_struct *workqueue;
+	struct work_struct   work;
+
+	struct tasklet_struct pump_transfers;
+
+	struct mutex         lock; /* lock this struct except from queue */
+	struct list_head     queue; /* spi_message queue */
+	spinlock_t           qlock; /* lock the queue */
+
+	void __iomem	*regs;	/* virt. address of the control registers */
+	unsigned int ssi_clk;	/* clock in Hz */
+	unsigned int tx_fifo_depth; /* bytes in TX FIFO */
+	unsigned int rx_fifo_depth; /* bytes in RX FIFO */
+
+	u32		irq;
+
+	u8 bits_per_word;	/* current data frame size */
+	struct spi_transfer *tx_t; /* current tx transfer */
+	struct spi_transfer *rx_t; /* current rx transfer */
+	const u8 *tx_ptr;       /* current tx buffer */
+	u8 *rx_ptr;             /* current rx buffer */
+	int remaining_tx_bytes;	/* bytes left to tx in the current transfer */
+	int remaining_rx_bytes;	/* bytes left to rx in the current transfer */
+	int status;             /* status of the current spi_transfer */
+
+	struct completion done; /* signal the end of tx for current sequence */
+
+	struct spi_device *spi; /* current spi slave device */
+	struct clk	*clk_spi;
+	struct list_head *transfers_list; /* head of the current sequence */
+	unsigned int tx_count, rx_count; /* bytes in the current sequence */
+};
+
+static void dwspi_init_hw(struct designware_spi *dwspi)
+{
+	u16 ctrlr0;
+
+	/* Disable the SPI master */
+	writel(0, dwspi->regs + DWSPI_SSIENR);
+	/* Disable all the interrupts just in case */
+	writel(0, dwspi->regs + DWSPI_IMR);
+	/* Set TX empty IRQ threshold */
+	writew(dwspi->tx_fifo_depth / 2, dwspi->regs + DWSPI_TXFTLR);
+
+    /* Set transmit & receive mode */
+	ctrlr0 = readw(dwspi->regs + DWSPI_CTRLR0);
+    ctrlr0 &= ~DWSPI_CTRLR0_TMOD_MASK;
+	writew(ctrlr0, dwspi->regs + DWSPI_CTRLR0);
+}
+
+static void dwspi_baudcfg(struct designware_spi *dwspi, u32 speed_hz)
+{
+	u16 div = (speed_hz) ? dwspi->ssi_clk/speed_hz : 0xffff;
+
+	writew(div, dwspi->regs + DWSPI_BAUDR);
+}
+
+static void dwspi_enable(struct designware_spi *dwspi, int on)
+{
+	writel(on ? 1 : 0, dwspi->regs + DWSPI_SSIENR);
+}
+
+static void designware_spi_chipselect(struct spi_device *spi, int on)
+{
+	struct designware_spi *dwspi = spi_master_get_devdata(spi->master);
+#if 0
+	long gpio = (long) spi->controller_data;
+	unsigned active = spi->mode & SPI_CS_HIGH;
+#endif
+	/*
+	 * Note, the SPI controller must have been enabled at this point, i.e.
+	 * SSIENR == 1
+	 */
+
+	if (on) {
+	#if 0
+
+		/* Turn the actual chip select on for GPIO chip selects */
+		if (gpio >= 0)
+			gpio_set_value(gpio, active);
+	#endif
+		/* Activate slave on the SPI controller */
+		writel(1 << spi->chip_select, dwspi->regs + DWSPI_SER);
+	} else {
+		/* Deselect the slave on the SPI bus */
+		writel(0, dwspi->regs + DWSPI_SER);
+	#if 0
+		if (gpio >= 0)
+			gpio_set_value(gpio, !active);
+	#endif
+	}
+}
+
+static int designware_spi_setup_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	u8 bits_per_word;
+	u32 hz;
+	struct designware_spi *dwspi = spi_master_get_devdata(spi->master);
+	u16 ctrlr0 = readw(dwspi->regs + DWSPI_CTRLR0);
+
+	bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
+	hz = (t) ? t->speed_hz : spi->max_speed_hz;
+
+	if (bits_per_word < 4 || bits_per_word > 16) {
+		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+			__func__, bits_per_word);
+		return -EINVAL;
+	} else {
+		ctrlr0 &= ~DWSPI_CTRLR0_DFS_MASK;
+		ctrlr0 |= bits_per_word - 1;
+
+		dwspi->bits_per_word = bits_per_word;
+	}
+
+	/* Set the SPI clock phase and polarity */
+	if (spi->mode & SPI_CPHA)
+		ctrlr0 |= DWSPI_CTRLR0_SCPH;
+	else
+		ctrlr0 &= ~DWSPI_CTRLR0_SCPH;
+	if (spi->mode & SPI_CPOL)
+		ctrlr0 |= DWSPI_CTRLR0_SCPOL;
+	else
+		ctrlr0 &= ~DWSPI_CTRLR0_SCPOL;
+
+	writew(ctrlr0, dwspi->regs + DWSPI_CTRLR0);
+
+	/* set speed */
+	dwspi_baudcfg(dwspi, hz);
+
+	return 0;
+}
+
+/* the spi->mode bits currently understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA)
+
+static int designware_spi_setup(struct spi_device *spi)
+{
+	struct designware_spi *dwspi;
+	int retval;
+
+	dwspi = spi_master_get_devdata(spi->master);
+
+	if (!spi->bits_per_word)
+		spi->bits_per_word = 8;
+
+	if (spi->mode & ~MODEBITS) {
+		dev_err(&spi->dev, "%s, SP unsupported mode bits %x\n",
+			__func__, spi->mode & ~MODEBITS);
+		return -EINVAL;
+	}
+
+	if (spi->chip_select > spi->master->num_chipselect) {
+		dev_err(&spi->dev,
+				"setup: invalid chipselect %u (%u defined)\n",
+				spi->chip_select, spi->master->num_chipselect);
+		return -EINVAL;
+	}
+
+	retval = designware_spi_setup_transfer(spi, NULL);
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
+		__func__, spi->mode & MODEBITS, spi->bits_per_word, 0);
+
+	return 0;
+}
+
+static void designware_spi_do_tx(struct designware_spi *dwspi)
+{
+	u8 sr;
+	int bytes_to_tx = dwspi->remaining_tx_bytes;
+	u8 valid_tx_fifo_bytes = readb(dwspi->regs + DWSPI_TXFLR);
+	u8 valid_rx_fifo_bytes = readb(dwspi->regs + DWSPI_RXFLR);
+	int tx_limit = min(dwspi->tx_fifo_depth - valid_tx_fifo_bytes,\
+			dwspi->rx_fifo_depth - valid_rx_fifo_bytes);
+
+	/* Fill the Tx FIFO with as many bytes as possible */
+	sr = readb(dwspi->regs + DWSPI_SR);
+	while ((sr & DWSPI_SR_TFNF_MASK) && dwspi->remaining_tx_bytes > 0) {
+		if (dwspi->bits_per_word <= 8) {
+			u8 dr = (dwspi->tx_ptr) ? *dwspi->tx_ptr++ : 0;
+
+			writeb(dr, dwspi->regs + DWSPI_DR);
+			dwspi->remaining_tx_bytes--;
+		} else {
+			u16 dr = (dwspi->tx_ptr) ? *(u16 *) dwspi->tx_ptr : 0;
+
+			dwspi->tx_ptr += 2;
+			writew(dr, dwspi->regs + DWSPI_DR);
+			dwspi->remaining_tx_bytes -= 2;
+		}
+		if (--tx_limit <= 0)
+			break;
+		sr = readb(dwspi->regs + DWSPI_SR);
+	}
+
+	dwspi->tx_count += bytes_to_tx - dwspi->remaining_tx_bytes;
+}
+
+/* Return 1 when done, 0 otherwise */
+static int designware_spi_fill_tx_fifo(struct designware_spi *dwspi)
+{
+	unsigned cs_change = 0;
+	unsigned int ser;
+
+	ser = readw(dwspi->regs + DWSPI_SER);
+
+	list_for_each_entry_from(dwspi->tx_t, dwspi->transfers_list,
+		transfer_list) {
+		if (dwspi->remaining_tx_bytes == 0) {
+			/* Initialize new spi_transfer */
+			dwspi->tx_ptr = dwspi->tx_t->tx_buf;
+			dwspi->remaining_tx_bytes = dwspi->tx_t->len;
+			dwspi->status = 0;
+
+			/* can't change speed or bits in the middle of a
+			 * message. must disable the controller for this.
+			 */
+			if (dwspi->tx_t->speed_hz
+					|| dwspi->tx_t->bits_per_word) {
+				dwspi->status = -ENOPROTOOPT;
+				break;
+			}
+
+			if (!dwspi->tx_t->tx_buf && !dwspi->tx_t->rx_buf
+					&& dwspi->tx_t->len) {
+				dwspi->status = -EINVAL;
+				break;
+			}
+
+			if (cs_change)
+				break;
+		}
+
+		designware_spi_do_tx(dwspi);
+
+		/* Don't advance dwspi->tx_t, we'll get back to this
+		 * spi_transfer later
+		 */
+		if (dwspi->remaining_tx_bytes > 0)
+		{
+			return 0;
+		}
+
+		cs_change = dwspi->tx_t->cs_change;
+	}
+
+	complete(&dwspi->done);
+	return 1;
+}
+
+static void designware_spi_do_rx(struct designware_spi *dwspi)
+{
+	u8 sr;
+	int bytes_to_rx = dwspi->remaining_rx_bytes;
+
+	sr = readb(dwspi->regs + DWSPI_SR);
+
+	if (sr & DWSPI_SR_RFF_MASK) {
+	#if 0
+		dev_err(dwspi->dev, "%s: RX FIFO overflow\n", __func__);
+		dwspi->status = -EIO;
+	#endif
+	}
+
+	/* Read as long as RX FIFO is not empty */
+	while ((sr & DWSPI_SR_RFNE_MASK) != 0
+			&& dwspi->remaining_rx_bytes > 0) {
+		int rx_level = readl(dwspi->regs + DWSPI_RXFLR);
+
+		while (rx_level-- && dwspi->remaining_rx_bytes > 0) {
+			if (dwspi->bits_per_word <= 8) {
+				u8 data;
+
+				data = readb(dwspi->regs + DWSPI_DR);
+				dwspi->remaining_rx_bytes--;
+				if (dwspi->rx_ptr)
+					*dwspi->rx_ptr++ = data;
+			} else {
+				u16 data;
+
+				data = readw(dwspi->regs + DWSPI_DR);
+				dwspi->remaining_rx_bytes -= 2;
+				if (dwspi->rx_ptr) {
+					*(u16 *) dwspi->rx_ptr = data;
+					dwspi->rx_ptr += 2;
+				}
+			}
+		}
+		sr = readb(dwspi->regs + DWSPI_SR);
+	}
+
+	dwspi->rx_count += (bytes_to_rx - dwspi->remaining_rx_bytes);
+}
+
+/* return 1 if cs_change is true, 0 otherwise */
+static int designware_spi_read_rx_fifo(struct designware_spi *dwspi)
+{
+	unsigned cs_change = 0;
+	unsigned int ser;
+
+	ser = readw(dwspi->regs + DWSPI_SER);
+
+	list_for_each_entry_from(dwspi->rx_t, dwspi->transfers_list,
+			transfer_list) {
+		if (dwspi->remaining_rx_bytes == 0) {
+			dwspi->rx_ptr = dwspi->rx_t->rx_buf;
+			dwspi->remaining_rx_bytes = dwspi->rx_t->len;
+
+			if (cs_change)
+				return 1;
+		}
+
+		designware_spi_do_rx(dwspi);
+
+		/* The rx buffer is filling up with more bytes. Don't advance
+		 * dwspi->rx_t, as we have more bytes to read in this
+		 * spi_transfer.
+		 */
+		if (dwspi->remaining_rx_bytes > 0)
+			return 0;
+
+		cs_change = dwspi->rx_t->cs_change;
+	}
+
+	return 0;
+}
+
+/* interate through the list of spi_transfer elements.
+ * stop at the end of the list or when t->cs_change is true.
+ */
+static void designware_spi_do_transfers(struct designware_spi *dwspi)
+{
+	int tx_done, cs_change;
+
+	init_completion(&dwspi->done);
+
+	/* transfer kickoff */
+	tx_done = designware_spi_fill_tx_fifo(dwspi);
+	designware_spi_chipselect(dwspi->spi, 1);
+
+	if (!tx_done) {
+		/* Enable the transmit empty interrupt, which we use to
+		 * determine progress on the transmission in case we're
+		 * not done yet.
+		 */
+		writeb(DWSPI_IMR_TXEIM_MASK, dwspi->regs + DWSPI_IMR);
+
+		/* wait for tx completion */
+		wait_for_completion(&dwspi->done);
+	}
+
+	/* This delay should be good enough for 100KHz spi transfers. Slower
+	 * transfers may need a longer delay.
+	 */
+	udelay(10);
+
+	/* get remaining rx bytes */
+    do {
+		cs_change = designware_spi_read_rx_fifo(dwspi);
+	} while (readb(dwspi->regs + DWSPI_SR) &
+			(DWSPI_SR_BUSY_MASK | DWSPI_SR_RFNE_MASK));
+
+	/* transaction is done */
+	designware_spi_chipselect(dwspi->spi, 0);
+
+	if (dwspi->status < 0)
+		return;
+
+	if (!cs_change && (dwspi->remaining_rx_bytes > 0 ||
+			dwspi->remaining_tx_bytes > 0)) {
+	#if 0
+		dev_err(dwspi->dev, "%s: remaining_rx_bytes = %d, "
+				"remaining_tx_bytes = %d\n",
+				__func__,  dwspi->remaining_rx_bytes,
+				dwspi->remaining_tx_bytes);
+	#endif
+		dwspi->status = -EIO;
+    }
+
+	if (dwspi->rx_count != dwspi->tx_count) {
+	#if 0
+		dev_err(dwspi->dev, "%s: rx_count == %d, tx_count == %d\n",
+				__func__, dwspi->rx_count, dwspi->tx_count);
+	#endif
+		dwspi->status = -EIO;
+    }
+}
+
+static int designware_spi_transfer(struct spi_device *spi,
+		struct spi_message *mesg)
+{
+	struct designware_spi *dwspi = spi_master_get_devdata(spi->master);
+
+	mesg->actual_length = 0;
+	mesg->status = -EINPROGRESS;
+
+	/* we can't block here, so we use a spinlock
+	 * here instead of the global mutex
+	 */
+	spin_lock(&dwspi->qlock);
+	list_add_tail(&mesg->queue, &dwspi->queue);
+	queue_work(dwspi->workqueue, &dwspi->work);
+	spin_unlock(&dwspi->qlock);
+
+	return 0;
+}
+
+static void designware_work(struct work_struct *work)
+{
+	struct designware_spi *dwspi = container_of(work,
+			struct designware_spi, work);
+
+	mutex_lock(&dwspi->lock);
+	spin_lock(&dwspi->qlock);
+
+	while (!list_empty(&dwspi->queue)) {
+		struct spi_message *m;
+
+		m = container_of(dwspi->queue.next, struct spi_message, queue);
+		list_del_init(&m->queue);
+		spin_unlock(&dwspi->qlock);
+
+		dwspi->spi = m->spi;
+		dwspi->tx_t = dwspi->rx_t =
+			list_first_entry(&m->transfers, struct spi_transfer,
+					transfer_list);
+
+		/*
+		 * Interate through groups of spi_transfer structs
+		 * that are separated by cs_change being true
+		 */
+		dwspi->transfers_list = &m->transfers;
+		do {
+			dwspi->remaining_tx_bytes =
+				dwspi->remaining_rx_bytes = 0;
+			dwspi->tx_count = dwspi->rx_count = 0;
+			designware_spi_setup_transfer(m->spi, NULL);
+			dwspi_enable(dwspi, 1);
+			designware_spi_do_transfers(dwspi);
+			dwspi_enable(dwspi, 0);
+			if (dwspi->status < 0)
+				break;
+			m->actual_length +=
+				dwspi->tx_count; /* same as rx_count */
+		} while (&dwspi->tx_t->transfer_list != &m->transfers);
+
+		m->status = dwspi->status;
+		m->complete(m->context);
+
+		spin_lock(&dwspi->qlock);
+	}
+	spin_unlock(&dwspi->qlock);
+	mutex_unlock(&dwspi->lock);
+}
+
+static void designware_pump_transfers(unsigned long data)
+{
+	struct designware_spi *dwspi = (struct designware_spi *) data;
+
+	designware_spi_read_rx_fifo(dwspi);
+	if (!designware_spi_fill_tx_fifo(dwspi))
+		/* reenable the interrupt */
+		writeb(DWSPI_IMR_TXEIM_MASK, dwspi->regs + DWSPI_IMR);
+}
+
+static irqreturn_t designware_spi_irq(int irq, void *dev_id)
+{
+	struct designware_spi *dwspi = dev_id;
+
+	tasklet_schedule(&dwspi->pump_transfers);
+	/* disable the interrupt for now */
+	writeb(0, dwspi->regs + DWSPI_IMR);
+
+	return IRQ_HANDLED;
+}
+
+static void designware_spi_cleanup(struct spi_device *spi)
+{
+}
+
+static int __init designware_spi_probe(struct platform_device *dev)
+{
+	int ret = 0;
+	struct spi_master *master;
+	struct designware_spi *dwspi;
+	//struct designware_platform_data *pdata;
+	struct spi_controller_pdata *pdata;
+	struct resource *r;
+	struct clk *clk_spi;
+
+	pdata = dev->dev.platform_data;
+	if (pdata == NULL) {
+		dev_err(&dev->dev, "no device data specified\n");
+		return -EINVAL;
+	}
+
+        if(memcmp(pdata->clk_name, "DUS", 3))
+                c2000_block_reset(COMPONENT_AXI_LEGACY_SPI, 0);
+        else
+                c2000_block_reset(COMPONENT_AXI_FAST_SPI, 0);
+
+	clk_spi = clk_get(NULL,pdata->clk_name);
+	if (IS_ERR(clk_spi)) {
+		ret = PTR_ERR(clk_spi);
+		pr_err("%s:Unable to obtain spi clock: %d\n",\
+				__func__, ret);
+		goto err_clk;
+	}
+
+	clk_enable(clk_spi);
+
+	printk ("%s:Initializing SPI Controller : Using dma=%d CLK(%s)=%ld Hz\n", __func__, \
+			pdata->use_dma, pdata->clk_name, clk_get_rate(clk_spi));
+
+	/* Get resources(memory, IRQ) associated with the device */
+	master = spi_alloc_master(&dev->dev, sizeof(struct designware_spi));
+	if (master == NULL) {
+		ret = -ENOMEM;
+		goto err_nomem;
+	}
+
+	master->mode_bits = SPI_CPOL | SPI_CPHA;
+	master->bus_num = pdata->bus_num;
+	master->num_chipselect = pdata->num_chipselects;
+	master->setup = designware_spi_setup;
+	master->transfer = designware_spi_transfer;
+	master->cleanup = designware_spi_cleanup;
+	platform_set_drvdata(dev, master);
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENODEV;
+		goto put_master;
+	}
+
+	dwspi = spi_master_get_devdata(master);
+	dwspi->clk_spi = clk_spi;
+	dwspi->ssi_clk = clk_get_rate(dwspi->clk_spi);
+	//dwspi->ssi_clk = pdata->max_freq;
+	dwspi->tx_fifo_depth = TX_FIFO_DEPTH;
+	dwspi->rx_fifo_depth = RX_FIFO_DEPTH;
+#if 0
+	dwspi->tx_fifo_depth = pdata->tx_fifo_depth;
+	dwspi->rx_fifo_depth = pdata->rx_fifo_depth;
+#endif
+	dwspi->dev = &dev->dev;
+	spin_lock_init(&dwspi->qlock);
+	mutex_init(&dwspi->lock);
+	INIT_LIST_HEAD(&dwspi->queue);
+	INIT_WORK(&dwspi->work, designware_work);
+	dwspi->workqueue =
+		create_singlethread_workqueue(dev_name(master->dev.parent));
+	
+	if (dwspi->workqueue == NULL) {
+		ret = -EBUSY;
+		goto put_master;
+	}
+	tasklet_init(&dwspi->pump_transfers, designware_pump_transfers,
+			(unsigned long) dwspi);
+
+	if (!request_mem_region(r->start,
+			r->end - r->start + 1, DESIGNWARE_SPI_NAME)) {
+		ret = -ENXIO;
+		goto destroy_wq;
+	}
+
+	dwspi->regs = ioremap(r->start, r->end - r->start + 1);
+	if (dwspi->regs == NULL) {
+		ret = -ENOMEM;
+		goto destroy_wq;
+	}
+
+	dwspi->irq = platform_get_irq(dev, 0);
+	if (dwspi->irq < 0) {
+		ret = -ENXIO;
+		goto unmap_io;
+	}
+
+	/* SPI controller initializations */
+	dwspi_init_hw(dwspi);
+
+	/* Register for SPI Interrupt */
+	ret = request_irq(dwspi->irq, designware_spi_irq, 0,
+			DESIGNWARE_SPI_NAME, dwspi);
+	if (ret != 0)
+		goto unmap_io;
+
+	ret = spi_register_master(master);
+    if (ret < 0)
+		goto free_irq;
+
+	dev_info(&dev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
+			r->start, (u32)dwspi->regs, dwspi->irq);
+
+	return ret;
+
+free_irq:
+	free_irq(dwspi->irq, dwspi);
+unmap_io:
+	iounmap(dwspi->regs);
+destroy_wq:
+	destroy_workqueue(dwspi->workqueue);
+put_master:
+	spi_master_put(master);
+err_nomem:
+	clk_disable(clk_spi);
+	clk_put(clk_spi);
+err_clk:
+        if(memcmp(pdata->clk_name, "DUS", 3))
+                c2000_block_reset(COMPONENT_AXI_LEGACY_SPI, 1);
+        else
+                c2000_block_reset(COMPONENT_AXI_FAST_SPI, 1);
+
+	return ret;
+}
+
+static int __devexit designware_spi_remove(struct platform_device *dev)
+{
+	struct designware_spi *dwspi;
+	struct spi_master *master;
+	struct spi_controller_pdata *pdata;
+
+	master = platform_get_drvdata(dev);
+	dwspi = spi_master_get_devdata(master);
+
+	free_irq(dwspi->irq, dwspi);
+	iounmap(dwspi->regs);
+	destroy_workqueue(dwspi->workqueue);
+	tasklet_kill(&dwspi->pump_transfers);
+	platform_set_drvdata(dev, 0);
+	spi_master_put(master);
+	clk_disable(dwspi->clk_spi);
+	clk_put(dwspi->clk_spi);
+
+        pdata = dev->dev.platform_data;
+        if(!pdata)
+        {
+                return -EINVAL;
+        }
+
+        if(memcmp(pdata->clk_name, "DUS", 3))
+                c2000_block_reset(COMPONENT_AXI_LEGACY_SPI, 1);
+        else
+                c2000_block_reset(COMPONENT_AXI_FAST_SPI, 1);
+
+	return 0;
+}
+
+#if CONFIG_PM
+static int designware_spi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct designware_spi *dwspi;
+	struct spi_master *master;
+
+	master = platform_get_drvdata(pdev);
+	dwspi = spi_master_get_devdata(master);
+
+        /* Disable the SPI master */
+        writel(0, dwspi->regs + DWSPI_SSIENR);
+
+        clk_disable(dwspi->clk_spi);
+
+        return 0;
+
+}
+
+static int designware_spi_resume(struct platform_device *pdev)
+{
+	struct designware_spi *dwspi;
+	struct spi_master *master;
+
+	master = platform_get_drvdata(pdev);
+	dwspi = spi_master_get_devdata(master);
+
+        clk_enable(dwspi->clk_spi);
+	dwspi_init_hw(dwspi);
+
+        return 0;
+}
+#endif
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:" DESIGNWARE_SPI_NAME);
+
+static struct platform_driver designware_spi_driver = {
+	.probe  = designware_spi_probe,
+	.remove	= __devexit_p(designware_spi_remove),
+#if CONFIG_PM
+        .suspend        = designware_spi_suspend,
+        .resume         = designware_spi_resume,
+#endif
+	.driver = {
+		.name = DESIGNWARE_SPI_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init designware_spi_init(void)
+{
+	return platform_driver_register(&designware_spi_driver);
+}
+module_init(designware_spi_init);
+
+static void __exit designware_spi_exit(void)
+{
+	platform_driver_unregister(&designware_spi_driver);
+}
+module_exit(designware_spi_exit);
+
+MODULE_AUTHOR("Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@...org>");
+MODULE_DESCRIPTION("Synopsys DesignWare SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi2/Kconfig b/drivers/spi2/Kconfig
old mode 100644
new mode 100755
diff --git a/drivers/spi2/Makefile b/drivers/spi2/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/spi2/busses/Kconfig b/drivers/spi2/busses/Kconfig
old mode 100644
new mode 100755
diff --git a/drivers/spi2/busses/Makefile b/drivers/spi2/busses/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/spi2/busses/comcerto_spi.c b/drivers/spi2/busses/comcerto_spi.c
old mode 100644
new mode 100755
index b52dfe7..017cd6d
--- a/drivers/spi2/busses/comcerto_spi.c
+++ b/drivers/spi2/busses/comcerto_spi.c
@@ -46,7 +46,7 @@
  *
  *
  */
-static int do_write_read_transfer8(struct comcerto_spi *spi, u8 *wbuf, unsigned int *wlen, u8 *rbuf, unsigned int *rlen)
+static int do_write_read_transfer8(struct comcerto_spi *spi, u8 *wbuf, unsigned int *wlen, u8 *rbuf, unsigned int *rlen, u32 ser_reg)
 {
 	unsigned int len_now;
 	int rc = 0;
@@ -54,6 +54,7 @@
 	u32 dr = spi->membase + COMCERTO_SPI_DR;
 	u32 txflr = spi->membase + COMCERTO_SPI_TXFLR;
 	u32 rxflr = spi->membase + COMCERTO_SPI_RXFLR;
+	int ser_done = 0;
 
 //	printk(KERN_INFO "do_write_read_transfer(%#lx, %#lx, %d, %#lx, %d)\n", (unsigned long)spi,
 //                                                                      (unsigned long)wbuf, *wlen,
@@ -70,6 +71,10 @@
 		while (len_now--)
 			__raw_writew(cpu_to_le16((u16) *wbuf++), dr);
 
+		if (!ser_done){
+			__raw_writel(ser_reg, spi->membase + COMCERTO_SPI_SER);
+			ser_done = 1;
+		}
 
 		len_now = __raw_readl(rxflr);
 		if (len_now > rtmp)
@@ -92,9 +97,8 @@
 /**
  * do_write_read_transfer16 -
  *
- *
  */
-static int do_write_read_transfer16(struct comcerto_spi *spi, u16 *wbuf, unsigned int *wlen, u16 *rbuf, unsigned int *rlen)
+static int do_write_read_transfer16(struct comcerto_spi *spi, u16 *wbuf, unsigned int *wlen, u16 *rbuf, unsigned int *rlen, u32 ser_reg)
 {
 	unsigned int len_now;
 	int rc = 0;
@@ -103,6 +107,7 @@
 	u32 dr = spi->membase + COMCERTO_SPI_DR;
 	u32 txflr = spi->membase + COMCERTO_SPI_TXFLR;
 	u32 rxflr = spi->membase + COMCERTO_SPI_RXFLR;
+	int ser_done = 0;
 
 //	printk(KERN_INFO "do_write_read_transfer(%#lx, %#lx, %d, %#lx, %d)\n", (unsigned long)spi
 //                                                                      (unsigned long)wbuf, *wlen,
@@ -138,6 +143,11 @@
 				__raw_writew(0, dr);
 		}
 
+		if (!ser_done){
+			__raw_writel(ser_reg, spi->membase + COMCERTO_SPI_SER);
+			ser_done = 1;
+		}
+
 		len_now = __raw_readl(rxflr);
 		if (rtmp) {
 			if (len_now > rtmp)
@@ -172,13 +182,14 @@
  *
  *
  */
-static int do_write_only_transfer8(struct comcerto_spi *spi, u8 *buf, unsigned int *len)
+static int do_write_only_transfer8(struct comcerto_spi *spi, u8 *buf, unsigned int *len, u32 ser_reg)
 {
 	unsigned int len_now;
 	int rc = 0;
 	unsigned int tmp = *len;
 	u32 dr = spi->membase + COMCERTO_SPI_DR;
 	u32 txflr = spi->membase + COMCERTO_SPI_TXFLR;
+	int ser_done = 0;
 
 //	printk(KERN_INFO "do_write_only_transfer8(%#lx, %#lx, %d)\n", (unsigned long)spi, (unsigned long)buf, *len);
 
@@ -191,6 +202,12 @@
 
 		while (len_now--)
 			__raw_writew(cpu_to_le16((u16) *buf++), dr);
+
+		if (!ser_done)
+		{
+			__raw_writel(ser_reg, spi->membase + COMCERTO_SPI_SER);
+			ser_done = 1;
+		}
 	}
 
 	*len -= tmp;
@@ -344,14 +361,14 @@
 
 		__raw_writel(ctrlr0, spi->membase + COMCERTO_SPI_CTRLR0);
 		__raw_writel(baudr, spi->membase + COMCERTO_SPI_BAUDR);
-		__raw_writel(ser, spi->membase + COMCERTO_SPI_SER);
+		//__raw_writel(ser, spi->membase + COMCERTO_SPI_SER);
 		__raw_writel(8, spi->membase + COMCERTO_SPI_RXFTLR);
 		__raw_writel(0, spi->membase + COMCERTO_SPI_TXFTLR);
 		__raw_writel(0, spi->membase + COMCERTO_SPI_IMR);
 		__raw_writel(1, spi->membase + COMCERTO_SPI_SSIENR);
 
 		if (transfer->fs <= 8)
-			rc = do_write_only_transfer8(spi, transfer->wbuf, &transfer->wlen);
+			rc = do_write_only_transfer8(spi, transfer->wbuf, &transfer->wlen, ser);
 		else
 			rc = do_write_only_transfer16(spi, (u16 *) transfer->wbuf, &transfer->wlen);
 
@@ -382,27 +399,28 @@
 
 		__raw_writel(ctrlr0, spi->membase + COMCERTO_SPI_CTRLR0);
 		__raw_writel(baudr, spi->membase + COMCERTO_SPI_BAUDR);
-		__raw_writel(ser, spi->membase + COMCERTO_SPI_SER);
+	//	__raw_writel(ser, spi->membase + COMCERTO_SPI_SER);
 		__raw_writel(8, spi->membase + COMCERTO_SPI_RXFTLR);
 		__raw_writel(0, spi->membase + COMCERTO_SPI_TXFTLR);
 		__raw_writel(0, spi->membase + COMCERTO_SPI_IMR);
 		__raw_writel(1, spi->membase + COMCERTO_SPI_SSIENR);
 
 		if (transfer->fs <= 8)
-			rc = do_write_read_transfer8(spi, transfer->wbuf, &transfer->wlen, transfer->rbuf, &transfer->rlen);
+		rc = do_write_read_transfer8(spi, transfer->wbuf, &transfer->wlen, transfer->rbuf, &transfer->rlen, ser);
 		else
-			rc = do_write_read_transfer16(spi, (u16 *) transfer->wbuf, &transfer->wlen, (u16 *) transfer->rbuf, &transfer->rlen);
+		rc = do_write_read_transfer16(spi, (u16 *) transfer->wbuf, &transfer->wlen, (u16 *) transfer->rbuf, &transfer->rlen, ser);
 
 		break;
 	}
 
 	if (config->ba_delay) {
+		udelay(config->ba_delay);
 	        /* make sure this transaction is finished */
         	while (__raw_readl(spi->membase + COMCERTO_SPI_SR) & BUSY) ;
-
-		udelay(config->ba_delay);
 	}
 
+	__raw_writel(0, spi->membase + COMCERTO_SPI_SER);
+
 	return rc;
 }
 
diff --git a/drivers/spi2/busses/comcerto_spi.h b/drivers/spi2/busses/comcerto_spi.h
old mode 100644
new mode 100755
diff --git a/drivers/spi2/spi-core.c b/drivers/spi2/spi-core.c
old mode 100644
new mode 100755
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
old mode 100644
new mode 100755
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
old mode 100644
new mode 100755
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
old mode 100644
new mode 100755
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/Kconfig b/drivers/usb/dwc_otg/Kconfig
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/Makefile b/drivers/usb/dwc_otg/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_cc.c b/drivers/usb/dwc_otg/dwc_cc.c
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_cc.h b/drivers/usb/dwc_otg/dwc_cc.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_cfi_common.h b/drivers/usb/dwc_otg/dwc_cfi_common.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_common_fbsd.c b/drivers/usb/dwc_otg/dwc_common_fbsd.c
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_common_linux.c b/drivers/usb/dwc_otg/dwc_common_linux.c
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_common_nbsd.c b/drivers/usb/dwc_otg/dwc_common_nbsd.c
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_crypto.c b/drivers/usb/dwc_otg/dwc_crypto.c
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_crypto.h b/drivers/usb/dwc_otg/dwc_crypto.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_dh.c b/drivers/usb/dwc_otg/dwc_dh.c
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_dh.h b/drivers/usb/dwc_otg/dwc_dh.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_list.h b/drivers/usb/dwc_otg/dwc_list.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_mem.c b/drivers/usb/dwc_otg/dwc_mem.c
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_modpow.c b/drivers/usb/dwc_otg/dwc_modpow.c
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_modpow.h b/drivers/usb/dwc_otg/dwc_modpow.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_notifier.c b/drivers/usb/dwc_otg/dwc_notifier.c
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_notifier.h b/drivers/usb/dwc_otg/dwc_notifier.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_os.h b/drivers/usb/dwc_otg/dwc_os.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_otg_adp.c b/drivers/usb/dwc_otg/dwc_otg_adp.c
old mode 100644
new mode 100755
index d1582d9..0877472
--- a/drivers/usb/dwc_otg/dwc_otg_adp.c
+++ b/drivers/usb/dwc_otg/dwc_otg_adp.c
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
- * $Revision: #9 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #12 $
+ * $Date: 2011/10/26 $
+ * $Change: 1873028 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -106,7 +106,7 @@
 {
 	dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
 	core_if->adp.sense_timer_started = 0;
-
+	DWC_PRINTF("ADP SENSE TIMEOUT\n");
 	if (core_if->adp_enable) {
 		dwc_otg_adp_sense_stop(core_if);
 		dwc_otg_adp_probe_start(core_if);
@@ -154,6 +154,7 @@
 		} else {
 			/* Enable Power Down Logic */
 			gpwrdn.b.pmuintsel = 1;
+			gpwrdn.b.pmuactv = 1;
 			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
 		}
 
@@ -190,7 +191,7 @@
 	{
 		DWC_PRINTF("SCHEDULING VBUSON TIMER\n");
 		/* 1.1 secs + 60ms necessary for cil_hcd_start*/
-		DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 2000);
+		DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);
 	} else {
 		DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer);
 	}
@@ -301,6 +302,7 @@
 	adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
 								.b.adp_sns_int = 1, b.adp_tmout_int};
 #endif
+	dwc_otg_disable_global_interrupts(core_if);
 	DWC_PRINTF("ADP Probe Start\n");
 	core_if->adp.probe_enabled = 1;
 
@@ -315,11 +317,13 @@
 	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
 
 	/* In Host mode unmask SRP detected interrupt */
+	gpwrdn.d32 = 0;
+	gpwrdn.b.sts_chngint_msk = 1;
 	if (!gpwrdn.b.idsts) {
-		gpwrdn.d32 = 0;
 		gpwrdn.b.srp_det_msk = 1;
-		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
 	}
+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
+
 	adpctl.b.adp_tmout_int_msk = 1;
 	adpctl.b.adp_prb_int_msk = 1;
 	adpctl.b.prb_dschg = 1;
@@ -334,8 +338,8 @@
 }
 
 /**
- * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted within
- * 3 seconds.
+ * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted 
+ * within 3 seconds.
  *
  * @param core_if the pointer to core_if strucure.
  */
@@ -392,18 +396,15 @@
 	adpctl_data_t adpctl;
 	DWC_PRINTF("Stop ADP probe\n");
 	core_if->adp.probe_enabled = 0;
-	adpctl.b.adpres = 1;
+	core_if->adp.probe_counter = 0;
+	adpctl.d32 = dwc_otg_adp_read_reg(core_if);
+
+	adpctl.b.adpen = 0;
+	adpctl.b.adp_prb_int = 1;
+	adpctl.b.adp_tmout_int = 1;
+	adpctl.b.adp_sns_int = 1;
 	dwc_otg_adp_write_reg(core_if, adpctl.d32);
 
-	/** todo: check if ADP is needed to be reset */
-	while (adpctl.b.adpres) {
-		adpctl.d32 = dwc_otg_adp_read_reg(core_if);
-	}
-
-	dwc_otg_adp_write_reg(core_if, 0);
-
-	dwc_otg_enable_global_interrupts(core_if);
-
 	return 0;
 }
 
@@ -420,10 +421,9 @@
 
 	adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
 	adpctl.b.enasns = 0;
+	adpctl.b.adp_sns_int = 1;
 	dwc_otg_adp_write_reg(core_if, adpctl.d32);
 
-	dwc_otg_enable_global_interrupts(core_if);
-
 	return 0;
 }
 
@@ -438,7 +438,8 @@
 {
 	hprt0_data_t hprt0 = {.d32 = 0 };
 	hprt0.d32 = dwc_otg_read_hprt0(core_if);
-	
+	DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
+
 	if (hprt0.b.prtpwr == 0) {
 		hprt0.b.prtpwr = 1;
 		//DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
@@ -452,18 +453,23 @@
  * to perform initial actions for ADP
  *
  * @param core_if the pointer to core_if structure.
+ * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN
  */
-void dwc_otg_adp_start(dwc_otg_core_if_t * core_if)
+void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)
 {
 	gpwrdn_data_t gpwrdn;
 
 	DWC_PRINTF("ADP Initial Start\n");
 	core_if->adp.adp_started = 1;
-	
-	if (!dwc_otg_is_device_mode(core_if)) {	
+
+	DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
+	dwc_otg_disable_global_interrupts(core_if);
+	if (is_host) {
+		DWC_PRINTF("HOST MODE\n");
 		/* Enable Power Down Logic Interrupt*/
 		gpwrdn.d32 = 0;
 		gpwrdn.b.pmuintsel = 1;
+		gpwrdn.b.pmuactv = 1;
 		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
 		/* Initialize first ADP probe to obtain Ramp Time value */
 		core_if->adp.initial_probe = 1;
@@ -471,11 +477,13 @@
 	} else {
 		gotgctl_data_t gotgctl;
 		gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
+		DWC_PRINTF("DEVICE MODE\n");
 		if (gotgctl.b.bsesvld == 0) {
 			/* Enable Power Down Logic Interrupt*/
 			gpwrdn.d32 = 0;
 			DWC_PRINTF("VBUS is not valid - start ADP probe\n");
 			gpwrdn.b.pmuintsel = 1;
+			gpwrdn.b.pmuactv = 1;
 			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
 			core_if->adp.initial_probe = 1;
 			dwc_otg_adp_probe_start(core_if);
@@ -501,6 +509,8 @@
 	core_if->adp.sense_enabled = 0;
 	core_if->adp.sense_timer_started = 0;
 	core_if->adp.vbuson_timer_started = 0;
+	core_if->adp.probe_counter = 0;
+	core_if->adp.gpwrdn = 0;
 	core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
 	/* Initialize timers */
 	core_if->adp.sense_timer =
@@ -515,6 +525,19 @@
 
 void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)
 {
+	gpwrdn_data_t gpwrdn = { .d32 = 0 };
+	gpwrdn.b.pmuintsel = 1;
+	gpwrdn.b.pmuactv = 1;
+	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+
+	if (core_if->adp.probe_enabled)		
+		dwc_otg_adp_probe_stop(core_if);
+	if (core_if->adp.sense_enabled)		
+		dwc_otg_adp_sense_stop(core_if);
+	if (core_if->adp.sense_timer_started)		
+		DWC_TIMER_CANCEL(core_if->adp.sense_timer);
+	if (core_if->adp.vbuson_timer_started)		
+		DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
 	DWC_TIMER_FREE(core_if->adp.sense_timer);
 	DWC_TIMER_FREE(core_if->adp.vbuson_timer);
 }
@@ -544,8 +567,12 @@
  */
 static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)
 {
-	if (core_if->adp.probe_timer_values[0] ==
-	    core_if->adp.probe_timer_values[1]) {
+	uint32_t diff;
+	if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1])
+			diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1];
+	else
+			diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0];   	
+	if(diff < 2) {
 		return 0;
 	} else {
 		return 1;
@@ -559,19 +586,25 @@
 						 uint32_t val)
 {
 	adpctl_data_t adpctl = {.d32 = 0 };
-	gpwrdn_data_t gpwrdn;
+	gpwrdn_data_t gpwrdn, temp;
 	adpctl.d32 = val;
 
+	temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
+	core_if->adp.probe_counter++;
+	core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
+	if (adpctl.b.rtim == 0 && !temp.b.idsts){
+		DWC_PRINTF("RTIM value is 0\n");	
+		goto exit;
+	}
 	if (set_timer_value(core_if, adpctl.b.rtim) &&
 	    core_if->adp.initial_probe) {
-		gpwrdn_data_t temp;
 		core_if->adp.initial_probe = 0;
 		dwc_otg_adp_probe_stop(core_if);
-		temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
-
 		gpwrdn.d32 = 0;
+		gpwrdn.b.pmuactv = 1;
 		gpwrdn.b.pmuintsel = 1;
 		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
 
 		/* check which value is for device mode and which for Host mode */
 		if (!temp.b.idsts) {	/* considered host mode value is 0 */
@@ -588,18 +621,14 @@
 			/*
 			 * Initiate SRP after initial ADP probe.
 			 */
-			core_if->op_state = B_PERIPHERAL;
-			dwc_otg_core_init(core_if);
 			dwc_otg_enable_global_interrupts(core_if);
-			cil_pcd_start(core_if);
 			dwc_otg_initiate_srp(core_if);
 		}
-	} else {
+	} else if (core_if->adp.probe_counter > 2){
 		gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
-		dwc_otg_dump_global_registers(core_if);
-		dwc_otg_dump_host_registers(core_if);
 		if (compare_timer_values(core_if)) {
-		//core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
+			DWC_PRINTF("Difference in timer values !!! \n");
+//                      core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
 			dwc_otg_adp_probe_stop(core_if);
 
 			/* Power on the core */
@@ -610,10 +639,11 @@
 			}
 
 			/* check which value is for device mode and which for Host mode */
-			if (!gpwrdn.b.idsts) {	/* considered host mode value is 0 */
+			if (!temp.b.idsts) {	/* considered host mode value is 0 */
 				/* Disable Interrupt from Power Down Logic */
 				gpwrdn.d32 = 0;
 				gpwrdn.b.pmuintsel = 1;
+				gpwrdn.b.pmuactv = 1;
 				DWC_MODIFY_REG32(&core_if->core_global_regs->
 						 gpwrdn, gpwrdn.d32, 0);
 
@@ -625,6 +655,7 @@
 				dwc_otg_enable_global_interrupts(core_if);
 				cil_hcd_start(core_if);
 			} else {
+				gotgctl_data_t gotgctl;
 				/* Mask SRP detected interrupt from Power Down Logic */
 				gpwrdn.d32 = 0;
 				gpwrdn.b.srp_det_msk = 1;
@@ -633,6 +664,7 @@
 
 				/* Disable Power Down Logic */
 				gpwrdn.d32 = 0;
+				gpwrdn.b.pmuintsel = 1;
 				gpwrdn.b.pmuactv = 1;
 				DWC_MODIFY_REG32(&core_if->core_global_regs->
 						 gpwrdn, gpwrdn.d32, 0);
@@ -645,7 +677,8 @@
 				dwc_otg_enable_global_interrupts(core_if);
 				cil_pcd_start(core_if);
 
-				if (!gpwrdn.b.bsessvld) {
+				gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
+				if (!gotgctl.b.bsesvld) {
 					dwc_otg_initiate_srp(core_if);
 				}
 			}
@@ -672,6 +705,12 @@
 			}
 		}
 	}
+exit:
+	/* Clear interrupt */
+	adpctl.d32 = dwc_otg_adp_read_reg(core_if);
+	adpctl.b.adp_prb_int = 1;
+	dwc_otg_adp_write_reg(core_if, adpctl.d32);
+
 	return 0;
 }
 
@@ -680,11 +719,17 @@
  */
 static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)
 {
+	adpctl_data_t adpctl;
 	/* Stop ADP Sense timer */
 	DWC_TIMER_CANCEL(core_if->adp.sense_timer);
 
 	/* Restart ADP Sense timer */
 	dwc_otg_adp_sense_timer_start(core_if);
+	
+	/* Clear interrupt */
+	adpctl.d32 = dwc_otg_adp_read_reg(core_if);
+	adpctl.b.adp_sns_int = 1;
+	dwc_otg_adp_write_reg(core_if, adpctl.d32);
 
 	return 0;
 }
@@ -699,6 +744,11 @@
 	adpctl.d32 = val;
 	set_timer_value(core_if, adpctl.b.rtim);
 	
+	/* Clear interrupt */
+	adpctl.d32 = dwc_otg_adp_read_reg(core_if);
+	adpctl.b.adp_tmout_int = 1;
+	dwc_otg_adp_write_reg(core_if, adpctl.d32);
+
 	return 0;
 }
 
@@ -712,15 +762,14 @@
 	adpctl_data_t adpctl = {.d32 = 0};
 
 	adpctl.d32 = dwc_otg_adp_read_reg(core_if);
+	DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);
 
 	if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
 		DWC_PRINTF("ADP Sense interrupt\n");
-		adpctl.b.adp_sns_int = 1;
 		retval |= dwc_otg_adp_handle_sns_intr(core_if);
 	}
 	if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
 		DWC_PRINTF("ADP timeout interrupt\n");
-		adpctl.b.adp_tmout_int = 1;
 		retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
 	}
 	if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
@@ -729,7 +778,9 @@
 		retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
 	}
 
-	dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
+//	dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
+	//dwc_otg_adp_write_reg(core_if, adpctl.d32);
+	DWC_PRINTF("RETURN FROM ADP ISR\n");
 
 	return retval;
 }
@@ -740,15 +791,15 @@
  */
 int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)
 {
-	hprt0_data_t hprt0;
-	gpwrdn_data_t gpwrdn;
 
 #ifndef DWC_HOST_ONLY
+	hprt0_data_t hprt0;
+	gpwrdn_data_t gpwrdn;
 	DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");
 
 	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
 	/* check which value is for device mode and which for Host mode */
-	if (gpwrdn.b.idsts) {	/* considered host mode value is 1 */
+	if (!gpwrdn.b.idsts) {	/* considered host mode value is 0 */
 		DWC_PRINTF("SRP: Host mode\n");
 
 		if (core_if->adp_enable) {
@@ -776,7 +827,7 @@
 		 * if connect does not occur within 10 seconds. */
 		cil_hcd_session_start(core_if);
 	} else {
-		DWC_PRINTF("SRP: Device mode\n");
+		DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);
 		if (core_if->adp_enable) {
 			dwc_otg_adp_probe_stop(core_if);
 
diff --git a/drivers/usb/dwc_otg/dwc_otg_adp.h b/drivers/usb/dwc_otg/dwc_otg_adp.h
old mode 100644
new mode 100755
index ab36f3a..d8c3f85
--- a/drivers/usb/dwc_otg/dwc_otg_adp.h
+++ b/drivers/usb/dwc_otg/dwc_otg_adp.h
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $
- * $Revision: #6 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #7 $
+ * $Date: 2011/10/24 $
+ * $Change: 1871159 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -57,6 +57,8 @@
 	dwc_timer_t *vbuson_timer;
 	uint32_t vbuson_timer_started;
 	uint32_t attached;
+	uint32_t probe_counter;
+	uint32_t gpwrdn;
 } dwc_otg_adp_t;
 
 /**
@@ -69,7 +71,7 @@
 extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if);
 extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if);
 extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if);
-extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if);
+extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
 extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if);
 extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if);
 extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if);
diff --git a/drivers/usb/dwc_otg/dwc_otg_attr.c b/drivers/usb/dwc_otg/dwc_otg_attr.c
old mode 100644
new mode 100755
index 4c38da81..17b0c23
--- a/drivers/usb/dwc_otg/dwc_otg_attr.c
+++ b/drivers/usb/dwc_otg/dwc_otg_attr.c
@@ -214,28 +214,28 @@
 
  <tr>
  <td> rem_wakeup_pwrdn </td>
- <td> On read, shows the status core - hibernated or not. On write, initiates 
+ <td> On read, shows the status core - hibernated or not. On write, initiates
  a remote wakeup of the device from Hibernation. </td>
  <td> Read/Write</td>
  </tr>
 
  <tr>
  <td> mode_ch_tim_en </td>
- <td> This bit is used to enable or disable the host core to wait for 200 PHY 
+ <td> This bit is used to enable or disable the host core to wait for 200 PHY
  clock cycles at the end of Resume to change the opmode signal to the PHY to 00
  after Suspend or LPM. </td>
  <td> Read/Write</td>
  </tr>
- 
+
  <tr>
  <td> fr_interval </td>
- <td> On read, shows the value of HFIR Frame Interval. On write, dynamically 
+ <td> On read, shows the value of HFIR Frame Interval. On write, dynamically
  reload HFIR register during runtime. The application can write a value to this
- register only after the Port Enable bit of the Host Port Control and Status 
+ register only after the Port Enable bit of the Host Port Control and Status
  register (HPRT.PrtEnaPort) has been set </td>
  <td> Read/Write</td>
  </tr>
- 
+
  <tr>
  <td> disconnect_us </td>
  <td> On read, shows the status of disconnect_device_us. On write, sets disconnect_us
@@ -365,7 +365,7 @@
 #define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
 static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
 { \
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);		\
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);		\
 	uint32_t val; \
 	val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
 	return sprintf (buf, "%s = 0x%x\n", _string_, val); \
@@ -374,7 +374,7 @@
 static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
 					const char *buf, size_t count) \
 { \
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev); \
 	uint32_t set = simple_strtoul(buf, NULL, 16); \
 	dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
 	return count; \
@@ -428,7 +428,7 @@
 #define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
 static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
 { \
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev); \
 	uint32_t val; \
 	val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
 	return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
@@ -437,7 +437,7 @@
 static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
 					const char *buf, size_t count) \
 { \
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev); \
 	uint32_t val = simple_strtoul(buf, NULL, 16); \
 	dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
 	return count; \
@@ -477,7 +477,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n",
@@ -497,7 +497,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	uint32_t offset = simple_strtoul(buf, NULL, 16);
@@ -506,7 +506,7 @@
 #elif  defined(PCI_INTERFACE)
 	if (offset < 0x00040000) {
 #else
-	if (offset < 0x00040000) {		
+	if (offset < 0x00040000) {
 #endif
 		otg_dev->os_dep.reg_offset = offset;
 	} else {
@@ -531,7 +531,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	uint32_t val;
@@ -567,7 +567,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	volatile uint32_t *addr;
@@ -644,7 +644,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 	return sprintf(buf, "HstNegScs = 0x%x\n",
 		       dwc_otg_get_hnpstatus(otg_dev->core_if));
@@ -663,7 +663,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 	uint32_t in = simple_strtoul(buf, NULL, 16);
 	dwc_otg_set_hnpreq(otg_dev->core_if, in);
@@ -688,7 +688,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 	return sprintf(buf, "SesReqScs = 0x%x\n",
 		       dwc_otg_get_srpstatus(otg_dev->core_if));
@@ -711,7 +711,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 	dwc_otg_pcd_initiate_srp(otg_dev->pcd);
 #endif
@@ -735,7 +735,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 	return sprintf(buf, "Bus Power = 0x%x\n",
 		       dwc_otg_get_prtpower(otg_dev->core_if));
@@ -754,7 +754,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 	uint32_t on = simple_strtoul(buf, NULL, 16);
 	dwc_otg_set_prtpower(otg_dev->core_if, on);
@@ -778,7 +778,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	return sprintf(buf, "Bus Suspend = 0x%x\n",
@@ -798,7 +798,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	uint32_t in = simple_strtoul(buf, NULL, 16);
@@ -820,7 +820,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n",
@@ -840,7 +840,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	uint32_t in = simple_strtoul(buf, NULL, 16);
@@ -862,7 +862,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	return sprintf(buf, "Frame Interval = 0x%x\n",
@@ -882,7 +882,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	uint32_t in = simple_strtoul(buf, NULL, 10);
@@ -905,7 +905,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	return sprintf(buf,
@@ -935,7 +935,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	uint32_t val = simple_strtoul(buf, NULL, 16);
@@ -953,7 +953,7 @@
 	    remote_wakeup_store);
 
 /**
- * Show the whether core is hibernated or not. 					
+ * Show the whether core is hibernated or not.
  */
 static ssize_t rem_wakeup_pwrdn_show(struct device *_dev,
 				     struct device_attribute *attr, char *buf)
@@ -965,7 +965,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 	if (dwc_otg_get_core_state(otg_dev->core_if)) {
 		DWC_PRINTF("Core is in hibernation\n");
@@ -993,7 +993,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 	dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0);
 #endif
@@ -1015,7 +1015,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 	uint32_t val = simple_strtoul(buf, NULL, 16);
 	DWC_PRINTF("The Passed value is %04x\n", val);
@@ -1041,7 +1041,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	dwc_otg_dump_global_registers(otg_dev->core_if);
@@ -1069,7 +1069,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	dwc_otg_dump_spram(otg_dev->core_if);
@@ -1092,7 +1092,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	dwc_otg_hcd_dump_state(otg_dev->hcd);
@@ -1117,7 +1117,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	dwc_otg_hcd_dump_frrem(otg_dev->hcd);
@@ -1142,7 +1142,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 	int i;
@@ -1176,7 +1176,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 
@@ -1214,7 +1214,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 
@@ -1241,7 +1241,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 
@@ -1273,7 +1273,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 
@@ -1294,7 +1294,7 @@
 #elif defined(PCI_INTERFACE)
 	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
 #else
-	dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
+	dwc_otg_device_t *otg_dev = dev_get_platdata(_dev);
 #endif
 
 
@@ -1326,7 +1326,7 @@
 				struct lm_device *dev
 #elif  defined(PCI_INTERFACE)
 				struct pci_dev *dev
-#else 
+#else
 //				struct device *dev
 				struct platform_device *dev
 #endif
@@ -1384,7 +1384,7 @@
 				struct lm_device *dev
 #elif  defined(PCI_INTERFACE)
 				struct pci_dev *dev
-#else 
+#else
 				//struct device *dev
 				struct platform_device *dev
 #endif
diff --git a/drivers/usb/dwc_otg/dwc_otg_attr.h b/drivers/usb/dwc_otg/dwc_otg_attr.h
old mode 100644
new mode 100755
index f9d6c55..9479e6c
--- a/drivers/usb/dwc_otg/dwc_otg_attr.h
+++ b/drivers/usb/dwc_otg/dwc_otg_attr.h
@@ -73,7 +73,6 @@
 #elif  PCI_INTERFACE
 				struct pci_dev *dev
 #else				
-				//struct device *dev
 				struct platform_device *dev
 #endif
     );
@@ -84,7 +83,6 @@
 #elif  PCI_INTERFACE
 				struct pci_dev *dev
 #else				
-				//struct device *dev
 				struct platform_device *dev
 #endif
     );
diff --git a/drivers/usb/dwc_otg/dwc_otg_cfi.c b/drivers/usb/dwc_otg/dwc_otg_cfi.c
old mode 100644
new mode 100755
index a9878d6..9c6fe15
--- a/drivers/usb/dwc_otg/dwc_otg_cfi.c
+++ b/drivers/usb/dwc_otg/dwc_otg_cfi.c
@@ -1568,7 +1568,7 @@
 		/* Non-periodic Tx FIFO */
 		nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz);
 		nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
-		start_address = params->dev_rx_fifo_size;
+		start_address = 0x400;
 		nptxfifosize.b.startaddr = start_address;
 
 		DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
diff --git a/drivers/usb/dwc_otg/dwc_otg_cfi.h b/drivers/usb/dwc_otg/dwc_otg_cfi.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_otg_cil.c b/drivers/usb/dwc_otg/dwc_otg_cil.c
old mode 100644
new mode 100755
index 552c003..c10917b
--- a/drivers/usb/dwc_otg/dwc_otg_cil.c
+++ b/drivers/usb/dwc_otg/dwc_otg_cil.c
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
- * $Revision: #182 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #189 $
+ * $Date: 2011/10/24 $
+ * $Change: 1871160 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -51,7 +51,7 @@
  *
  * The Core Interface Layer has the following requirements:
  * - Provides basic controller operations.
- * - Minimal use of OS services. 
+ * - Minimal use of OS services.
  * - The OS services used will be abstracted by using inline functions
  *	 or macros.
  *
@@ -188,13 +188,13 @@
 		gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
 		gusbcfg.b.force_host_mode = 1;
 		DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
-		dwc_mdelay(100); 
+		dwc_mdelay(100);
 		core_if->hptxfsiz.d32 =
 		DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
 		gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
 		gusbcfg.b.force_host_mode = 0;
 		DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
-		dwc_mdelay(100); 
+		dwc_mdelay(100);
 	}
 
 	DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32);
@@ -271,7 +271,7 @@
 
 	/** ADP initialization */
 	dwc_otg_adp_init(core_if);
-	
+
 	return core_if;
 }
 
@@ -299,7 +299,7 @@
 		DWC_FREE(core_if->host_if);
 	}
 
-	/** Remove ADP Timers  */
+	/** Remove ADP Stuff  */
 	dwc_otg_adp_remove(core_if);
 	if (core_if->core_params) {
 		DWC_FREE(core_if->core_params);
@@ -466,8 +466,8 @@
 
 	if (core_if->hibernation_suspend == 0) {
 		/*
-		 * Wait For Restore_done Interrupt. This mechanism of polling the interrupt
-		 * is introduced to avoid any possible race conditions
+		 * Wait For Restore_done Interrupt. This mechanism of polling the
+		 * interrupt is introduced to avoid any possible race conditions
 		 */
 		do {
 			gintsts_data_t gintsts;
@@ -632,7 +632,7 @@
 				gintsts.d32 = 0;
 				gintsts.b.restoredone = 1;
          		DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
-				DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n");	
+				DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n");
 				break;
 			}
 			dwc_udelay(10);
@@ -833,11 +833,6 @@
 		    DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma);
 	}
 
-	for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
-		dr->doepfn[i] =
-		    DWC_READ_REG32(&core_if->dev_if->out_ep_regs[i]->doepfn);
-	}
-
 	DWC_DEBUGPL(DBG_ANY,
 		    "=============Backing Host registers==============\n");
 	DWC_DEBUGPL(DBG_ANY, "Backed up dcfg            = %08x\n", dr->dcfg);
@@ -910,7 +905,7 @@
 	if (!gr) {
 		return -DWC_E_INVALID;
 	}
-   
+
 	DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local);
 	DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local);
 	DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local);
@@ -949,7 +944,7 @@
 	{
 		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dr->dctl);
 	}
-	
+
 	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk);
 	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk);
 	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk);
@@ -959,10 +954,6 @@
 		DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]);
 		DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]);
 	}
-	
-	for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
-		DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepfn, dr->doepfn[i]);
-	}
 
 	return 0;
 }
@@ -1388,7 +1379,7 @@
 
 	case DWC_INT_DMA_ARCH:
 		DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
-		/* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for 
+		/* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for
 		  Host mode ISOC in issue fix - vahrama */
 		ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR4;
 		core_if->dma_enable = (core_if->core_params->dma_enable != 0);
@@ -1409,6 +1400,10 @@
 		core_if->dma_desc_enable = 0;
 	}
 
+	if (core_if->core_params->ahb_single) {
+		ahbcfg.b.ahbsingle = 1;
+	}
+
 	ahbcfg.b.dmaenable = core_if->dma_enable;
 	DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
 
@@ -1504,7 +1499,7 @@
 		DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n",
 			   core_if->core_params->otg_ver, core_if->otg_ver);
 	}
-	
+
 
 	/* Enable common interrupts */
 	dwc_otg_enable_common_interrupts(core_if);
@@ -1561,6 +1556,9 @@
 		intr_mask.b.epmismatch = 1;
 	}
 
+	//intr_mask.b.incomplisoout = 1;
+	intr_mask.b.incomplisoin = 1;
+
 /* Enable the ignore frame number for ISOC xfers - MAS */
 /* Disable to support high bandwith ISOC transfers - manukz */
 #if 0
@@ -1647,9 +1645,16 @@
 	dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
 	/* Enable Device OUT NAK in case of DDMA mode*/
 	if (core_if->core_params->dev_out_nak) {
-		dcfg.b.endevoutnak = 1;		
+		dcfg.b.endevoutnak = 1;
 	}
 
+	if (core_if->core_params->cont_on_bna) {
+		dctl_data_t dctl = {.d32 = 0 };
+		dctl.b.encontonbna = 1;
+		DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
+	}
+
+
 	DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
 
 	/* Configure data FIFO sizes */
@@ -1687,7 +1692,7 @@
 				    DWC_READ_REG32(&global_regs->gnptxfsiz));
 
 			nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
-			nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
+			nptxfifosize.b.startaddr = 0x400;
 
 			DWC_WRITE_REG32(&global_regs->gnptxfsiz,
 					nptxfifosize.d32);
@@ -1739,7 +1744,7 @@
 			    params->dev_nperio_tx_fifo_size;
 #endif
 			nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
-			nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
+			nptxfifosize.b.startaddr = 0x400;
 
 			DWC_WRITE_REG32(&global_regs->gnptxfsiz,
 					nptxfifosize.d32);
@@ -1804,25 +1809,25 @@
 		for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
 			core_if->nextep_seq[i] = 0xff;	// 0xff - EP not active
 		}
-		core_if->nextep_seq[0] = 0;	
+		core_if->nextep_seq[0] = 0;
 		core_if->first_in_nextep_seq = 0;
 		diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
 		diepctl.b.nextep = 0;
 		DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
-		
+
 		/* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
 		dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
 		dcfg.b.epmscnt = 2;
 		DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
 
-		DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", 
+		DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
 			__func__, core_if->first_in_nextep_seq);
 		for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
 			DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]);
 		}
 		DWC_DEBUGPL(DBG_CILV,"\n");
 	}
-	
+
 	/* Clear all pending Device Interrupts */
 	/** @todo - if the condition needed to be checked
 	 *  or in any case all pending interrutps should be cleared?
@@ -1933,6 +1938,13 @@
 		dctl.b.nakonbble = 1;
 		DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
 	}
+
+	if (core_if->snpsid >= OTG_CORE_REV_2_94a) {
+		dctl_data_t dctl = {.d32 = 0 };
+		dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
+		dctl.b.sftdiscon = 0;
+		DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
+	}
 }
 
 /**
@@ -1961,9 +1973,6 @@
 	 * interrupts.
 	 */
 
-	/* Do not need sof interrupt for Descriptor DMA */
-	if (!core_if->dma_desc_enable)
-		intr_mask.b.sofintr = 1;
 	intr_mask.b.disconnect = 1;
 	intr_mask.b.portintr = 1;
 	intr_mask.b.hcintr = 1;
@@ -2040,7 +2049,7 @@
 	}
 
 	/* This bit allows dynamic reloading of the HFIR register
-	 * during runtime. This bit needs to be programmed during 
+	 * during runtime. This bit needs to be programmed during
 	 * initial configuration and its value must not be changed
 	 * during runtime.*/
 	if (core_if->core_params->reload_ctl == 1) {
@@ -2097,7 +2106,8 @@
 		DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
 			    DWC_READ_REG32(&global_regs->gnptxfsiz));
 		nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
-		nptxfifosize.b.startaddr = params->host_rx_fifo_size;
+		nptxfifosize.b.startaddr = 0x400;
+
 		DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
 		DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
 			    DWC_READ_REG32(&global_regs->gnptxfsiz));
@@ -2106,12 +2116,11 @@
 		DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n",
 			    DWC_READ_REG32(&global_regs->hptxfsiz));
 		ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
-		ptxfifosize.b.startaddr =
-		    nptxfifosize.b.startaddr + nptxfifosize.b.depth;
+		ptxfifosize.b.startaddr = 0xC00;
 		DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32);
 		DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n",
 			    DWC_READ_REG32(&global_regs->hptxfsiz));
-		
+
 		if (core_if->en_multiple_tx_fifo) {
 			/* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */
 			gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
@@ -2460,7 +2469,7 @@
 	hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
 
 	/* No need to set the bit in DDMA for disabling the channel */
-	//TODO check it everywhere channel is disabled          
+	//TODO check it everywhere channel is disabled
 	if (!core_if->core_params->dma_desc_enable)
 		hcchar.b.chen = 1;
 	hcchar.b.chdis = 1;
@@ -3084,9 +3093,9 @@
 }
 
 /**
- * Calculates and gets the frame Interval value of HFIR register according PHY 
+ * Calculates and gets the frame Interval value of HFIR register according PHY
  * type and speed.The application can modify a value of HFIR register only after
- * the Port Enable bit of the Host Port Control and Status register 
+ * the Port Enable bit of the Host Port Control and Status register
  * (HPRT.PrtEnaPort) has been set.
 */
 
@@ -3249,14 +3258,14 @@
 				if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq)
 				break;
 			}
-			core_if->nextep_seq[i] = ep->num;	
+			core_if->nextep_seq[i] = ep->num;
 			core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq;
 			depctl.b.nextep = core_if->nextep_seq[ep->num];
 			dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
 			dcfg.b.epmscnt++;
 			DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
 
-			DWC_DEBUGPL(DBG_PCDV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", 
+			DWC_DEBUGPL(DBG_PCDV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
 				__func__, core_if->first_in_nextep_seq);
 			for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
 				DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
@@ -3279,14 +3288,20 @@
 			diepmsk.b.ahberr = 1;
 			diepmsk.b.intknepmis = 1;
 			if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
-				diepmsk.b.intknepmis = 0; 
+				diepmsk.b.intknepmis = 0;
 			diepmsk.b.txfifoundrn = 1;	//?????
+			if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
+				diepmsk.b.nak = 1;
+			}
+
+
+
 /*
 			if (core_if->dma_desc_enable) {
 				diepmsk.b.bna = 1;
 			}
 */
-/*			
+/*
 			if (core_if->dma_enable) {
 				doepmsk.b.nak = 1;
 			}
@@ -3299,14 +3314,16 @@
 			doepmsk.b.xfercompl = 1;
 			doepmsk.b.ahberr = 1;
 			doepmsk.b.epdisabled = 1;
+			if (ep->type == DWC_OTG_EP_TYPE_ISOC)
+				doepmsk.b.outtknepdis = 1;
 
-/*			
+/*
 
 			if (core_if->dma_desc_enable) {
 				doepmsk.b.bna = 1;
 			}
 */
-/*			
+/*
 			doepmsk.b.babble = 1;
 			doepmsk.b.nyet = 1;
 			doepmsk.b.nak = 1;
@@ -3317,6 +3334,18 @@
 		DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk,
 				 0, daintmsk.d32);
 	} else {
+		if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
+			if (ep->is_in)
+			{
+				diepmsk_data_t diepmsk = {.d32 = 0 };
+				diepmsk.b.nak = 1;
+				DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32);
+			} else {
+				doepmsk_data_t doepmsk = {.d32 = 0 };
+				doepmsk.b.outtknepdis = 1;
+				DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32);
+			}
+		}
 		DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,
 				 0, daintmsk.d32);
 	}
@@ -3343,7 +3372,7 @@
 	volatile uint32_t *addr;
 	daint_data_t daintmsk = {.d32 = 0 };
 	dcfg_data_t dcfg;
-	uint8_t i;
+	uint8_t i = 0;
 
 #ifdef DWC_UTE_PER_IO
 	ep->xiso_frame_num = 0xFFFFFFFF;
@@ -3363,14 +3392,14 @@
 	depctl.d32 = DWC_READ_REG32(addr);
 
 	depctl.b.usbactep = 0;
-	
+
 	/* Update nextep_seq array and EPMSCNT in DCFG*/
 	if (!(depctl.b.eptype & 1) && ep->is_in == 1) {	// NP EP IN
 		for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
 			if (core_if->nextep_seq[i] == ep->num)
 			break;
 		}
-		core_if->nextep_seq[i] = core_if->nextep_seq[ep->num];	
+		core_if->nextep_seq[i] = core_if->nextep_seq[ep->num];
 		if (core_if->first_in_nextep_seq == ep->num)
 			core_if->first_in_nextep_seq = i;
 		core_if->nextep_seq[ep->num] = 0xff;
@@ -3379,13 +3408,13 @@
 		dcfg.b.epmscnt--;
 		DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
 
-			DWC_DEBUGPL(DBG_PCDV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", 
+			DWC_DEBUGPL(DBG_PCDV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
 				__func__, core_if->first_in_nextep_seq);
 			for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
 				DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
 			}
 	}
-		
+
 	if (ep->is_in == 1)
 		depctl.b.txfnum = 0;
 
@@ -3393,6 +3422,70 @@
 		depctl.b.epdis = 1;
 
 	DWC_WRITE_REG32(addr, depctl.d32);
+	depctl.d32 = DWC_READ_REG32(addr);
+	if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC && depctl.b.epena)
+	{
+		depctl_data_t depctl = {.d32 = 0};
+		if (ep->is_in)
+		{
+			diepint_data_t diepint = {.d32 = 0};
+
+			depctl.b.snak = 1;
+			DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->diepctl, depctl.d32);
+			do
+			{
+				dwc_udelay(10);
+				diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
+											in_ep_regs[ep->num]->diepint);
+			} while (!diepint.b.inepnakeff);
+			diepint.b.inepnakeff = 1;
+			DWC_WRITE_REG32(&core_if->dev_if->
+							in_ep_regs[ep->num]->diepint, diepint.d32);
+			depctl.d32 = 0;
+			depctl.b.epdis = 1;
+			DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->diepctl, depctl.d32);
+			do
+			{
+				dwc_udelay(10);
+				diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
+											in_ep_regs[ep->num]->diepint);
+			} while (!diepint.b.epdisabled);
+			diepint.b.epdisabled = 1;
+			DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->diepint, diepint.d32);
+		} else {
+			dctl_data_t dctl = {.d32 = 0};
+			gintmsk_data_t gintsts = {.d32 = 0};
+			doepint_data_t doepint = {.d32 = 0};
+			dctl.b.sgoutnak = 1;
+			DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
+			do
+			{
+				dwc_udelay(10);
+				gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
+			} while (!gintsts.b.goutnakeff);
+			gintsts.d32 = 0;
+			gintsts.b.goutnakeff = 1;
+			DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
+
+			depctl.d32 = 0;
+			depctl.b.epdis = 1;
+			depctl.b.snak = 1;
+			DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32);
+			do
+			{
+				dwc_udelay(10);
+				doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
+											out_ep_regs[ep->num]->doepint);
+			} while (!doepint.b.epdisabled);
+
+			doepint.b.epdisabled = 1;
+			DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32);
+
+			dctl.d32 = 0;
+			dctl.b.cgoutnak = 1;
+			DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
+		}
+	}
 
 	/* Disable the Interrupt for this EP */
 	if (core_if->multiproc_int_enable) {
@@ -3425,28 +3518,52 @@
 	uint32_t offset;
 	uint32_t xfer_est;
 	int i;
+	unsigned maxxfer_local, total_len;
 
-	ep->desc_cnt = (ep->total_len / ep->maxxfer) +
-	    ((ep->total_len % ep->maxxfer) ? 1 : 0);
+	if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR &&
+					(ep->maxpacket%4)) {
+		maxxfer_local = ep->maxpacket;
+		total_len = ep->xfer_len;
+	} else {
+		maxxfer_local = ep->maxxfer;
+		total_len = ep->total_len;
+	}
+
+	ep->desc_cnt = (total_len / maxxfer_local) +
+            ((total_len % maxxfer_local) ? 1 : 0);
+
 	if (!ep->desc_cnt)
 		ep->desc_cnt = 1;
 
+	if (ep->desc_cnt > MAX_DMA_DESC_CNT)
+		ep->desc_cnt = MAX_DMA_DESC_CNT;
+
 	dma_desc = ep->desc_addr;
-	xfer_est = ep->total_len;
+	if (maxxfer_local == ep->maxpacket) {
+		if ((total_len % maxxfer_local) &&
+				(total_len/maxxfer_local < MAX_DMA_DESC_CNT)) {
+			xfer_est = (ep->desc_cnt - 1) * maxxfer_local +
+					(total_len % maxxfer_local);
+		} else
+			xfer_est = ep->desc_cnt * maxxfer_local;
+	}
+	else
+		xfer_est = total_len;
 	offset = 0;
 	for (i = 0; i < ep->desc_cnt; ++i) {
 		/** DMA Descriptor Setup */
-		if (xfer_est > ep->maxxfer) {
+		if (xfer_est > maxxfer_local) {
 			dma_desc->status.b.bs = BS_HOST_BUSY;
 			dma_desc->status.b.l = 0;
 			dma_desc->status.b.ioc = 0;
 			dma_desc->status.b.sp = 0;
-			dma_desc->status.b.bytes = ep->maxxfer;
+			dma_desc->status.b.bytes = maxxfer_local;
 			dma_desc->buf = ep->dma_addr + offset;
+			dma_desc->status.b.sts = 0;
 			dma_desc->status.b.bs = BS_HOST_READY;
 
-			xfer_est -= ep->maxxfer;
-			offset += ep->maxxfer;
+			xfer_est -= maxxfer_local;
+			offset += maxxfer_local;
 		} else {
 			dma_desc->status.b.bs = BS_HOST_BUSY;
 			dma_desc->status.b.l = 1;
@@ -3458,17 +3575,73 @@
 							    sent_zlp) ? 1 : 0);
 				dma_desc->status.b.bytes = xfer_est;
 			} else {
-				dma_desc->status.b.bytes =
-				    xfer_est + ((4 - (xfer_est & 0x3)) & 0x3);
+				if (maxxfer_local == ep->maxpacket)
+					dma_desc->status.b.bytes = xfer_est;
+				else
+					dma_desc->status.b.bytes =
+				    		xfer_est + ((4 - (xfer_est & 0x3)) & 0x3);
 			}
 
 			dma_desc->buf = ep->dma_addr + offset;
+			dma_desc->status.b.sts = 0;
 			dma_desc->status.b.bs = BS_HOST_READY;
 		}
 		dma_desc++;
 	}
 }
+/**
+ * This function is called when to write ISOC data into appropriate dedicated
+ * periodic FIFO.
+ */
+static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
+{
+	dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+	dwc_otg_dev_in_ep_regs_t *ep_regs;
+	dtxfsts_data_t txstatus = {.d32 = 0 };
+	uint32_t len = 0;
+	int epnum = dwc_ep->num;
+	int dwords;
 
+	DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
+
+	ep_regs = core_if->dev_if->in_ep_regs[epnum];
+
+	len = dwc_ep->xfer_len - dwc_ep->xfer_count;
+
+	if (len > dwc_ep->maxpacket) {
+		len = dwc_ep->maxpacket;
+	}
+
+	dwords = (len + 3) / 4;
+
+	/* While there is space in the queue and space in the FIFO and
+	 * More data to tranfer, Write packets to the Tx FIFO */
+	txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
+	DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
+
+	while (txstatus.b.txfspcavail > dwords &&
+	       dwc_ep->xfer_count < dwc_ep->xfer_len &&
+	       dwc_ep->xfer_len != 0) {
+		/* Write the FIFO */
+		dwc_otg_ep_write_packet(core_if, dwc_ep, 0);
+
+		len = dwc_ep->xfer_len - dwc_ep->xfer_count;
+		if (len > dwc_ep->maxpacket) {
+			len = dwc_ep->maxpacket;
+		}
+
+		dwords = (len + 3) / 4;
+		txstatus.d32 =
+		    DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
+		DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
+			    txstatus.d32);
+	}
+
+	DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
+		    DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
+
+	return 1;
+}
 /**
  * This function does the setup for a data transfer for an EP and
  * starts the transfer. For an IN transfer, the packets will be
@@ -3513,8 +3686,13 @@
 		depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
 		deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
 
-		ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
-		    ep->maxxfer : (ep->total_len - ep->xfer_len);
+		if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
+			ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
+		    		ep->maxxfer : (ep->total_len - ep->xfer_len);
+		else
+			ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?
+				 MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
+
 
 		/* Zero Length Packet? */
 		if ((ep->xfer_len - ep->xfer_count) == 0) {
@@ -3524,18 +3702,25 @@
 			/* Program the transfer size and packet count
 			 *      as follows: xfersize = N * maxpacket +
 			 *      short_packet pktcnt = N + (short_packet
-			 *      exist ? 1 : 0) 
+			 *      exist ? 1 : 0)
 			 */
 			deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
 			deptsiz.b.pktcnt =
 			    (ep->xfer_len - ep->xfer_count - 1 +
 			     ep->maxpacket) / ep->maxpacket;
+			if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
+				deptsiz.b.pktcnt = MAX_PKT_CNT;
+				deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
+			}
+			if (ep->type == DWC_OTG_EP_TYPE_ISOC)
+				deptsiz.b.mc = deptsiz.b.pktcnt;
 		}
 
 		/* Write the DMA register */
 		if (core_if->dma_enable) {
 			if (core_if->dma_desc_enable == 0) {
-				deptsiz.b.mc = 1;
+				if (ep->type != DWC_OTG_EP_TYPE_ISOC)
+					deptsiz.b.mc = 1;
 				DWC_WRITE_REG32(&in_regs->dieptsiz,
 						deptsiz.d32);
 				DWC_WRITE_REG32(&(in_regs->diepdma),
@@ -3580,10 +3765,33 @@
 
 					}
 				}
+			}  else {
+					 write_isoc_tx_fifo(core_if, ep);
 			}
 		}
 		if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
 			depctl.b.nextep = core_if->nextep_seq[ep->num];
+
+		if (ep->type == DWC_OTG_EP_TYPE_ISOC)
+		{
+			dsts_data_t dsts = {.d32 = 0};
+			if (ep->bInterval == 1) {
+				dsts.d32 =
+					DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
+				ep->frame_num = dsts.b.soffn + ep->bInterval;
+				if (ep->frame_num > 0x3FFF)
+				{
+					ep->frm_overrun = 1;
+					ep->frame_num &= 0x3FFF;
+				} else
+					ep->frm_overrun = 0;
+				if (ep->frame_num & 0x1) {
+					depctl.b.setd1pid = 1;
+				} else {
+					depctl.b.setd0pid = 1;
+				}
+			}
+		}
 		/* EP enable, IN data in FIFO */
 		depctl.b.cnak = 1;
 		depctl.b.epena = 1;
@@ -3597,12 +3805,18 @@
 		depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
 		deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
 
-		ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
-		    ep->maxxfer : (ep->total_len - ep->xfer_len);
+		if (!core_if->dma_desc_enable) {
+			if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
+				ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
+                        	ep->maxxfer : (ep->total_len - ep->xfer_len);
+                else
+					ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len
+					- ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
+		}
 
 		/* Program the transfer size and packet count as follows:
 		 *
-		 *      pktcnt = N                                                                                
+		 *      pktcnt = N
 		 *      xfersize = N * maxpacket
 		 */
 		if ((ep->xfer_len - ep->xfer_count) == 0) {
@@ -3613,8 +3827,13 @@
 			deptsiz.b.pktcnt =
 			    (ep->xfer_len - ep->xfer_count +
 			     (ep->maxpacket - 1)) / ep->maxpacket;
-			ep->xfer_len =
-			    deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
+			if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
+				deptsiz.b.pktcnt = MAX_PKT_CNT;
+			}
+			if (!core_if->dma_desc_enable) {
+				ep->xfer_len =
+			    		deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
+			}
 			deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
 		}
 
@@ -3636,7 +3855,9 @@
 							ep->descs_dma_addr);
 				} else {
 #endif
-
+					/** This is used for interrupt out transfers*/
+					if (!ep->xfer_len)
+						ep->xfer_len = ep->total_len;
 					init_dma_desc_chain(core_if, ep);
 
 					if (core_if->core_params->dev_out_nak) {
@@ -3647,7 +3868,7 @@
 							/* Remember initial value of doeptsiz */
 							core_if->start_doeptsiz_val[ep->num] = deptsiz.d32;
 							DWC_WRITE_REG32(&out_regs->doeptsiz,
-								deptsiz.d32);													
+								deptsiz.d32);
 						}
 					}
 				/** DOEPDMAn Register write */
@@ -3661,6 +3882,28 @@
 			DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
 		}
 
+		if (ep->type == DWC_OTG_EP_TYPE_ISOC)
+		{
+			dsts_data_t dsts = {.d32 = 0};
+			if (ep->bInterval == 1) {
+				dsts.d32 =
+					DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
+				ep->frame_num = dsts.b.soffn + ep->bInterval;
+				if (ep->frame_num > 0x3FFF)
+				{
+					ep->frm_overrun = 1;
+					ep->frame_num &= 0x3FFF;
+				} else
+					ep->frm_overrun = 0;
+
+				if (ep->frame_num & 0x1) {
+					depctl.b.setd1pid = 1;
+				} else {
+					depctl.b.setd0pid = 1;
+				}
+			}
+		}
+
 		/* EP enable */
 		depctl.b.cnak = 1;
 		depctl.b.epena = 1;
@@ -3677,9 +3920,9 @@
 					   core_global_regs->gintmsk));
 
 
-		/* Timer is scheduling only for out bulk transfers for 
-		 * "Device DDMA OUT NAK Enhancement" feature to inform user 
-		 * about received data payload in case of timeout 
+		/* Timer is scheduling only for out bulk transfers for
+		 * "Device DDMA OUT NAK Enhancement" feature to inform user
+		 * about received data payload in case of timeout
 		 */
 		if (core_if->core_params->dev_out_nak) {
 			if (ep->type == DWC_OTG_EP_TYPE_BULK) {
@@ -3856,7 +4099,7 @@
 			/* Program the transfer size and packet count
 			 *      as follows: xfersize = N * maxpacket +
 			 *      short_packet pktcnt = N + (short_packet
-			 *      exist ? 1 : 0) 
+			 *      exist ? 1 : 0)
 			 */
 			if (ep->xfer_len > ep->maxpacket) {
 				ep->xfer_len = ep->maxpacket;
@@ -3891,6 +4134,7 @@
 				    (ep->xfer_len == ep->maxpacket) ? 0 : 1;
 				dma_desc->status.b.bytes = ep->xfer_len;
 				dma_desc->buf = ep->dma_addr;
+				dma_desc->status.b.sts = 0;
 				dma_desc->status.b.bs = BS_HOST_READY;
 
 				/** DIEPDMA0 Register write */
@@ -3964,6 +4208,7 @@
 				dma_desc->status.b.ioc = 1;
 				dma_desc->status.b.bytes = ep->maxpacket;
 				dma_desc->buf = ep->dma_addr;
+				dma_desc->status.b.sts = 0;
 				dma_desc->status.b.bs = BS_HOST_READY;
 
 				/** DOEPDMA0 Register write */
@@ -4014,7 +4259,7 @@
 		/* Program the transfer size and packet count
 		 *      as follows: xfersize = N * maxpacket +
 		 *      short_packet pktcnt = N + (short_packet
-		 *      exist ? 1 : 0) 
+		 *      exist ? 1 : 0)
 		 */
 
 		if (core_if->dma_desc_enable == 0) {
@@ -4045,6 +4290,7 @@
 			    (ep->xfer_len == ep->maxpacket) ? 0 : 1;
 			dma_desc->status.b.bytes = ep->xfer_len;
 			dma_desc->buf = ep->dma_addr;
+			dma_desc->status.b.sts = 0;
 			dma_desc->status.b.bs = BS_HOST_READY;
 
 			/** DIEPDMA0 Register write */
@@ -4103,7 +4349,7 @@
 		/* Program the transfer size and packet count
 		 *      as follows: xfersize = N * maxpacket +
 		 *      short_packet pktcnt = N + (short_packet
-		 *      exist ? 1 : 0) 
+		 *      exist ? 1 : 0)
 		 */
 		deptsiz.b.xfersize = ep->maxpacket;
 		deptsiz.b.pktcnt = 1;
@@ -4119,6 +4365,7 @@
 			dma_desc->status.b.ioc = 1;
 			dma_desc->status.b.bytes = ep->maxpacket;
 			dma_desc->buf = ep->dma_addr;
+			dma_desc->status.b.sts = 0;
 			dma_desc->status.b.bs = BS_HOST_READY;
 
 			/** DOEPDMA0 Register write */
@@ -4483,9 +4730,6 @@
 		addr = &core_if->dev_if->out_ep_regs[i]->doepctl;
 		DWC_PRINTF("DOEPCTL	 @0x%08lX : 0x%08X\n",
 			   (unsigned long)addr, DWC_READ_REG32(addr));
-		addr = &core_if->dev_if->out_ep_regs[i]->doepfn;
-		DWC_PRINTF("DOEPFN	 @0x%08lX : 0x%08X\n",
-			   (unsigned long)addr, DWC_READ_REG32(addr));
 		addr = &core_if->dev_if->out_ep_regs[i]->doepint;
 		DWC_PRINTF("DOEPINT	 @0x%08lX : 0x%08X\n",
 			   (unsigned long)addr, DWC_READ_REG32(addr));
@@ -4684,7 +4928,7 @@
 		   DWC_READ_REG32(addr));
 	addr = &core_if->core_global_regs->adpctl;
 	DWC_PRINTF("ADPCTL	 @0x%08lX : 0x%08X\n", (unsigned long)addr,
-		   DWC_READ_REG32(addr));
+		   dwc_otg_adp_read_reg(core_if));
 	addr = &core_if->core_global_regs->hptxfsiz;
 	DWC_PRINTF("HPTXFSIZ	 @0x%08lX : 0x%08X\n", (unsigned long)addr,
 		   DWC_READ_REG32(addr));
@@ -4937,7 +5181,7 @@
 		/* Program the transfer size and packet count
 		 *      as follows: xfersize = N * maxpacket +
 		 *      short_packet pktcnt = N + (short_packet
-		 *      exist ? 1 : 0) 
+		 *      exist ? 1 : 0)
 		 */
 		deptsiz.b.xfersize = ep->xfer_len;
 		deptsiz.b.pktcnt =
@@ -5096,6 +5340,8 @@
 	dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default);
 	dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default);
 	dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default);
+	dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default);
+	dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default);
 	dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default);
 	dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default);
 	return 0;
@@ -6117,7 +6363,8 @@
 	}
 	core_if->core_params->adp_supp_enable = val;
 	/*Set OTG version 2.0 in case of enabling ADP*/
-	dwc_otg_set_param_otg_ver(core_if, 1);
+	if (val)
+		dwc_otg_set_param_otg_ver(core_if, 1);
 
 	return retval;
 }
@@ -6289,6 +6536,69 @@
 	return core_if->core_params->dev_out_nak;
 }
 
+int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val)
+{
+	int retval = 0;
+	int valid = 1;
+
+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+		DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val);
+		DWC_WARN("cont_on_bna must be 0 or 1\n");
+		return -DWC_E_INVALID;
+	}
+
+	if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) ||
+		!(core_if->core_params->dma_desc_enable))) {
+			valid = 0;
+	}
+	if (valid == 0) {
+		if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) {
+			DWC_ERROR("%d invalid for parameter cont_on_bna."
+				"Check HW configuration.\n", val);
+		}
+		retval = -DWC_E_INVALID;
+		val = 0;
+	}
+	core_if->core_params->cont_on_bna = val;
+	return retval;
+}
+
+int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if)
+{
+	return core_if->core_params->cont_on_bna;
+}
+
+int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val)
+{
+	int retval = 0;
+	int valid = 1;
+
+	if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+		DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val);
+		DWC_WARN("ahb_single must be 0 or 1\n");
+		return -DWC_E_INVALID;
+	}
+
+	if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
+			valid = 0;
+	}
+	if (valid == 0) {
+		if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) {
+			DWC_ERROR("%d invalid for parameter ahb_single."
+				"Check HW configuration.\n", val);
+		}
+		retval = -DWC_E_INVALID;
+		val = 0;
+	}
+	core_if->core_params->ahb_single = val;
+	return retval;
+}
+
+int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if)
+{
+	return core_if->core_params->ahb_single;
+}
+
 int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val)
 {
 	int retval = 0;
diff --git a/drivers/usb/dwc_otg/dwc_otg_cil.h b/drivers/usb/dwc_otg/dwc_otg_cil.h
old mode 100644
new mode 100755
index efda364..9957861
--- a/drivers/usb/dwc_otg/dwc_otg_cil.h
+++ b/drivers/usb/dwc_otg/dwc_otg_cil.h
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
- * $Revision: #118 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #122 $
+ * $Date: 2011/10/24 $
+ * $Change: 1871160 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -73,6 +73,7 @@
 #define OTG_CORE_REV_2_91a	0x4F54291A
 #define OTG_CORE_REV_2_92a	0x4F54292A
 #define OTG_CORE_REV_2_93a	0x4F54293A
+#define OTG_CORE_REV_2_94a	0x4F54294A
 
 /**
  * Information for each ISOC packet.
@@ -97,8 +98,8 @@
 	unsigned active:1;
 
 	/**
-	 *Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic Tx FIFO
-	 * If dedicated Tx FIFOs are enabled for all IN Eps - Tx FIFO # FOR IN EPs*/
+	 * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic
+	 * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/
 	unsigned tx_fifo_num:4;
 	/** EP type: 0 - Control, 1 - ISOC,	 2 - BULK,	3 - INTR */
 	unsigned type:2;
@@ -160,9 +161,18 @@
 	uint32_t cfi_req_len;
 #endif				//DWC_UTE_CFI
 
+/** Max DMA Descriptor count for any EP */
+#define MAX_DMA_DESC_CNT 256
 	/** Allocated DMA Desc count */
 	uint32_t desc_cnt;
 
+	/** bInterval */
+	uint32_t bInterval;
+	/** Next frame num to setup next ISOC transfer */
+	uint32_t frame_num;
+	/** Indicates SOF number overrun in DSTS */
+	uint8_t frm_overrun;
+
 #ifdef DWC_UTE_PER_IO
 	/** Next frame num for which will be setup DMA Desc */
 	uint32_t xiso_frame_num;
@@ -201,8 +211,6 @@
 	/** Frame number of pattern data */
 	uint32_t sync_frame;
 
-	/** bInterval */
-	uint32_t bInterval;
 	/** ISO Packet number per frame */
 	uint32_t pkt_per_frm;
 	/** Next frame num for which will be setup DMA Desc */
@@ -433,9 +441,9 @@
 	int32_t dma_enable;
 
 	/**
-	 * When DMA mode is enabled specifies whether to use address DMA or DMA Descritor mode for accessing the data
-	 * FIFOs in device mode. The driver will automatically detect the value for this
-	 * parameter if none is specified.
+	 * When DMA mode is enabled specifies whether to use address DMA or DMA
+	 * Descriptor mode for accessing the data FIFOs in device mode. The driver
+	 * will automatically detect the value for this if none is specified.
 	 * 0 - address DMA
 	 * 1 - DMA Descriptor(default, if available)
 	 */
@@ -674,12 +682,28 @@
 	 */
 	int32_t reload_ctl;
 
-	/** DCFG: Enable device Out NAK 
+	/** DCFG: Enable device Out NAK
 	 * 0 - The core does not set NAK after Bulk Out transfer complete.
 	 * 1 - The core sets NAK after Bulk OUT transfer complete.
 	 */
 	int32_t dev_out_nak;
 
+	/** DCFG: Enable Continue on BNA
+	 * After receiving BNA interrupt the core disables the endpoint,when the
+	 * endpoint is re-enabled by the application the core starts processing
+	 * 0 - from the DOEPDMA descriptor
+	 * 1 - from the descriptor which received the BNA.
+	 */
+	int32_t cont_on_bna;
+
+	/** GAHBCFG: AHB Single Support
+	 * This bit when programmed supports SINGLE transfers for remainder
+	 * data in a transfer for DMA mode of operation.
+	 * 0 - in this case the remainder data will be sent using INCR burst size.
+	 * 1 - in this case the remainder data will be sent using SINGLE burst size.
+	 */
+	int32_t ahb_single;
+
 	/** Core Power down mode
 	 * 0 - No Power Down is enabled
 	 * 1 - Reserved
@@ -757,7 +781,6 @@
 	uint32_t diepctl[MAX_EPS_CHANNELS];
 	uint32_t dieptsiz[MAX_EPS_CHANNELS];
 	uint32_t diepdma[MAX_EPS_CHANNELS];
-	uint32_t doepfn[MAX_EPS_CHANNELS];
 };
 /**
  * The <code>dwc_otg_core_if</code> structure contains information needed to manage
@@ -952,13 +975,16 @@
 	 * also used as counter of disabled NP IN EP's */
 	uint8_t start_predict;
 
-	/** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and 
+	/** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and
 	 * active, 0xff otherwise */
 	uint8_t nextep_seq[MAX_EPS_CHANNELS];
 
 	/** Index of fisrt EP in nextep_seq array which should be re-enabled **/
 	uint8_t first_in_nextep_seq;
 
+	/** Frame number while entering to ISR - needed for ISOCs **/
+	uint32_t frame_num;
+
 };
 
 #ifdef DEBUG
diff --git a/drivers/usb/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/dwc_otg/dwc_otg_cil_intr.c
old mode 100644
new mode 100755
index 813203e..edc5c92
--- a/drivers/usb/dwc_otg/dwc_otg_cil_intr.c
+++ b/drivers/usb/dwc_otg/dwc_otg_cil_intr.c
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
- * $Revision: #29 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #31 $
+ * $Date: 2011/10/24 $
+ * $Change: 1871286 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -42,6 +42,9 @@
 #include "dwc_os.h"
 #include "dwc_otg_regs.h"
 #include "dwc_otg_cil.h"
+#include "dwc_otg_driver.h"
+#include "dwc_otg_pcd.h"
+#include "dwc_otg_hcd.h"
 
 #ifdef DEBUG
 inline const char *op_state_str(dwc_otg_core_if_t * core_if)
@@ -127,6 +130,7 @@
 				}
 
 				gpwrdn.d32 = 0;
+				gpwrdn.b.pmuintsel = 1;
 				gpwrdn.b.pmuactv = 1;
 				DWC_MODIFY_REG32(&core_if->core_global_regs->
 						 gpwrdn, 0, gpwrdn.d32);
@@ -331,12 +335,14 @@
 	DWC_DEBUGPL(DBG_CIL,
 		    " ++Connector ID Status Change Interrupt++  (%s)\n",
 		    (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));
+	
+	DWC_SPINUNLOCK(core_if->lock);
 
 	/*
 	 * Need to schedule a work, as there are possible DELAY function calls
 	 * Release lock before scheduling workq as it holds spinlock during scheduling
 	 */
-	DWC_SPINUNLOCK(core_if->lock);
+
 	DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,
 			   core_if, "connection id status change");
 	DWC_SPINLOCK(core_if->lock);
@@ -359,7 +365,6 @@
  */
 int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if)
 {
-	hprt0_data_t hprt0;
 	gintsts_data_t gintsts;
 
 #ifndef DWC_HOST_ONLY
@@ -368,6 +373,7 @@
 	if (dwc_otg_is_device_mode(core_if)) {
 		DWC_PRINTF("SRP: Device mode\n");
 	} else {
+		hprt0_data_t hprt0;
 		DWC_PRINTF("SRP: Host mode\n");
 
 		/* Turn on the port power bit. */
@@ -597,73 +603,119 @@
 	return 1;
 }
 
-static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_core_if_t * core_if)
+static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev)
 {
 	gpwrdn_data_t gpwrdn = {.d32 = 0 };
 	gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
-
-	if (!core_if->hibernation_suspend) {
-		DWC_PRINTF("Already exited from Hibernation\n");
-		return 1;
-	}
+	dwc_otg_core_if_t *core_if = otg_dev->core_if;
 
 	DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
 	gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
-
-	/* Switch on the voltage to the core */
-	gpwrdn.b.pwrdnswtch = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
-	dwc_udelay(10);
-
-	/* Reset the core */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pwrdnrstn = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
-	dwc_udelay(10);
-
-	/* Disable power clamps */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pwrdnclmp = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
-
-	/* Remove reset the core signal */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pwrdnrstn = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
-	dwc_udelay(10);
-
-	/* Disable PMU interrupt */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pmuintsel = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
-
-	/*Indicates that we are exiting from hibernation */
-	core_if->hibernation_suspend = 0;
-
-	/* Disable PMU */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pmuactv = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
-	dwc_udelay(10);
-
-	gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;
-	if (gpwrdn.b.dis_vbus == 1) {
-		gpwrdn.d32 = 0;
-		gpwrdn.b.dis_vbus = 1;
+	if (core_if->power_down == 2)
+	{		
+		if (!core_if->hibernation_suspend) {
+			DWC_PRINTF("Already exited from Hibernation\n");
+			return 1;
+		}
+		DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n");
+		/* Switch on the voltage to the core */
+		gpwrdn.b.pwrdnswtch = 1;
 		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		dwc_udelay(10);
+
+		/* Reset the core */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pwrdnrstn = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		dwc_udelay(10);
+
+		/* Disable power clamps */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pwrdnclmp = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+
+		/* Remove reset the core signal */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pwrdnrstn = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
+		dwc_udelay(10);
+
+		/* Disable PMU interrupt */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pmuintsel = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+
+		/*Indicates that we are exiting from hibernation */
+		core_if->hibernation_suspend = 0;
+
+		/* Disable PMU */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pmuactv = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		dwc_udelay(10);
+
+		gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;
+		if (gpwrdn.b.dis_vbus == 1) {
+			gpwrdn.d32 = 0;
+			gpwrdn.b.dis_vbus = 1;
+			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		}
+
+		if (gpwrdn_temp.b.idsts) {
+			core_if->op_state = B_PERIPHERAL;
+			dwc_otg_core_init(core_if);
+			dwc_otg_enable_global_interrupts(core_if);
+			cil_pcd_start(core_if);
+		} else {
+			core_if->op_state = A_HOST;
+			dwc_otg_core_init(core_if);
+			dwc_otg_enable_global_interrupts(core_if);
+			cil_hcd_start(core_if);
+		}
 	}
 
-	if (gpwrdn_temp.b.idsts) {
-		core_if->op_state = B_PERIPHERAL;
-		dwc_otg_core_init(core_if);
-		dwc_otg_enable_global_interrupts(core_if);
-		cil_pcd_start(core_if);
-	} else {
-		core_if->op_state = A_HOST;
-		dwc_otg_core_init(core_if);
-		dwc_otg_enable_global_interrupts(core_if);
-		cil_hcd_start(core_if);
+	if (core_if->adp_enable)
+	{
+		uint8_t is_host = 0;
+		DWC_SPINUNLOCK(core_if->lock);
+		/* Change the core_if's lock to hcd/pcd lock depend on mode? */
+#ifndef DWC_HOST_ONLY		
+		if (gpwrdn_temp.b.idsts)
+			core_if->lock = otg_dev->pcd->lock;
+#endif
+#ifndef DWC_DEVICE_ONLY
+		if (!gpwrdn_temp.b.idsts) {
+				core_if->lock = otg_dev->hcd->lock;	
+				is_host = 1;
+		}
+#endif
+		DWC_PRINTF("RESTART ADP\n");
+		if (core_if->adp.probe_enabled)		
+			dwc_otg_adp_probe_stop(core_if);
+		if (core_if->adp.sense_enabled)		
+			dwc_otg_adp_sense_stop(core_if);
+		if (core_if->adp.sense_timer_started)		
+			DWC_TIMER_CANCEL(core_if->adp.sense_timer);
+		if (core_if->adp.vbuson_timer_started)		
+			DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
+		core_if->adp.probe_timer_values[0] = -1;
+		core_if->adp.probe_timer_values[1] = -1;
+		core_if->adp.sense_timer_started = 0;
+		core_if->adp.vbuson_timer_started = 0;
+		core_if->adp.probe_counter = 0;
+		core_if->adp.gpwrdn = 0;
+		
+		/* Disable PMU and restart ADP */
+		gpwrdn_temp.d32 = 0;
+		gpwrdn_temp.b.pmuactv = 1;
+		gpwrdn_temp.b.pmuintsel = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		DWC_PRINTF("Check point 1\n");
+		dwc_mdelay(110);
+		dwc_otg_adp_start(core_if, is_host);
+		DWC_SPINLOCK(core_if->lock);
 	}
+	
 
 	return 1;
 }
@@ -675,70 +727,72 @@
 	DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
 
 	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
-	if (!core_if->hibernation_suspend) {
-		DWC_PRINTF("Already exited from Hibernation\n");
-		return 1;
-	}
+	if (core_if->power_down == 2) {
+		if (!core_if->hibernation_suspend) {
+			DWC_PRINTF("Already exited from Hibernation\n");
+			return 1;
+		}
 
-	if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
-	     otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&
-	    gpwrdn.b.bsessvld == 0) {
-		/* Save gpwrdn register for further usage if stschng interrupt */
-		core_if->gr_backup->gpwrdn_local =
-		    DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
-		/*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */
-		return 1;
-	}
+		if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
+			 otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&
+			gpwrdn.b.bsessvld == 0) {
+			/* Save gpwrdn register for further usage if stschng interrupt */
+			core_if->gr_backup->gpwrdn_local =
+				DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
+			/*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */
+			return 1;
+		}
 
-	/* Switch on the voltage to the core */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pwrdnswtch = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
-	dwc_udelay(10);
+		/* Switch on the voltage to the core */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pwrdnswtch = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		dwc_udelay(10);
 
-	/* Reset the core */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pwrdnrstn = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
-	dwc_udelay(10);
+		/* Reset the core */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pwrdnrstn = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		dwc_udelay(10);
 
-	/* Disable power clamps */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pwrdnclmp = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		/* Disable power clamps */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pwrdnclmp = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
 
-	/* Remove reset the core signal */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pwrdnrstn = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
-	dwc_udelay(10);
+		/* Remove reset the core signal */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pwrdnrstn = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
+		dwc_udelay(10);
 
-	/* Disable PMU interrupt */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pmuintsel = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
-	dwc_udelay(10);
+		/* Disable PMU interrupt */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pmuintsel = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		dwc_udelay(10);
 
-	/*Indicates that we are exiting from hibernation */
-	core_if->hibernation_suspend = 0;
+		/*Indicates that we are exiting from hibernation */
+		core_if->hibernation_suspend = 0;
 
-	/* Disable PMU */
-	gpwrdn.d32 = 0;
-	gpwrdn.b.pmuactv = 1;
-	DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
-	dwc_udelay(10);
+		/* Disable PMU */
+		gpwrdn.d32 = 0;
+		gpwrdn.b.pmuactv = 1;
+		DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
+		dwc_udelay(10);
 
-	core_if->op_state = B_PERIPHERAL;
-	dwc_otg_core_init(core_if);
-	dwc_otg_enable_global_interrupts(core_if);
-	cil_pcd_start(core_if);
+		core_if->op_state = B_PERIPHERAL;
+		dwc_otg_core_init(core_if);
+		dwc_otg_enable_global_interrupts(core_if);
+		cil_pcd_start(core_if);
 
-	if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
-	    otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {
-		/*
-		 * Initiate SRP after initial ADP probe.
-		 */
-		dwc_otg_initiate_srp(core_if);	
+		if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
+			otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {
+			/*
+			 * Initiate SRP after initial ADP probe.
+			 */
+			dwc_otg_initiate_srp(core_if);	
+		}
 	}
 
 	return 1;
@@ -747,24 +801,30 @@
  * This interrupt indicates that the Wakeup Logic has detected a
  * status change either on IDDIG or BSessVld.
  */
-static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_core_if_t * core_if)
+static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev)
 {
 	int retval;
 	gpwrdn_data_t gpwrdn = {.d32 = 0 };
 	gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
+	dwc_otg_core_if_t *core_if = otg_dev->core_if;
 
 	DWC_PRINTF("%s called\n", __FUNCTION__);
+	
+	if (core_if->power_down == 2) {
+		if (core_if->hibernation_suspend <= 0) {
+			DWC_PRINTF("Already exited from Hibernation\n");
+			return 1;
+		} else
+			gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;
 
-	if (!core_if->hibernation_suspend) {
-		DWC_PRINTF("Already exited from Hibernation\n");
-		return 1;
+	} else {
+		gpwrdn_temp.d32 = core_if->adp.gpwrdn;
 	}
 
 	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
-	gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;
-
+	
 	if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) {
-		retval = dwc_otg_handle_pwrdn_idsts_change(core_if);
+		retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev);
 	} else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) {
 		retval = dwc_otg_handle_pwrdn_session_change(core_if);
 	}
@@ -913,16 +973,13 @@
 			/* A-Cable still connected but device disconnected. */
 			cil_hcd_disconnect(core_if);
 			if (core_if->adp_enable) {
-				gpwrdn_data_t gpwrdn;
-				/* Power off the core */
-				if (core_if->power_down == 2) {
-				} else {
-					/* Enable Power Down Logic */
-					gpwrdn.b.pmuactv = 1;
-					DWC_MODIFY_REG32(&core_if->
-							 core_global_regs->
-							 gpwrdn, 0, gpwrdn.d32);
-				}
+				gpwrdn_data_t gpwrdn = { .d32 = 0 };
+				cil_hcd_stop(core_if);
+				/* Enable Power Down Logic */
+				gpwrdn.b.pmuintsel = 1;
+				gpwrdn.b.pmuactv = 1;
+				DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
+				dwc_otg_adp_probe_start(core_if);
 
 				/* Power off the core */
 				if (core_if->power_down == 2) {
@@ -932,20 +989,6 @@
 							 core_global_regs->
 							 gpwrdn, gpwrdn.d32, 0);
 				}
-
-				/* Enable Power Down Logic */
-				gpwrdn.d32 = 0;
-				gpwrdn.b.pmuactv = 1;
-				DWC_MODIFY_REG32(&core_if->core_global_regs->
-						 gpwrdn, 0, gpwrdn.d32);
-
-				/* Unmask SRP detected interrupt from Power Down Logic */
-				gpwrdn.d32 = 0;
-				gpwrdn.b.srp_det_msk = 1;
-				DWC_MODIFY_REG32(&core_if->core_global_regs->
-						 gpwrdn, 0, gpwrdn.d32);
-
-				dwc_otg_adp_probe_start(core_if);
 			}
 		}
 	}
@@ -1167,6 +1210,7 @@
  */
 static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
 {
+	gahbcfg_data_t gahbcfg = {.d32 = 0 };
 	gintsts_data_t gintsts;
 	gintmsk_data_t gintmsk;
 	gintmsk_data_t gintmsk_common = {.d32 = 0 };
@@ -1188,6 +1232,7 @@
 
 	gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
 	gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
+	gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
 
 #ifdef DEBUG
 	/* if any common interrupts set */
@@ -1196,8 +1241,10 @@
 			    gintsts.d32, gintmsk.d32);
 	}
 #endif
-
-	return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
+	if (gahbcfg.b.glblintrmsk)	
+		return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
+	else
+		return 0;
 
 }
 
@@ -1225,13 +1272,17 @@
  * - ADP Transaction Received Interrupt
  *
  */
-int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t * core_if)
+int32_t dwc_otg_handle_common_intr(void *dev)
 {
 	int retval = 0;
 	gintsts_data_t gintsts;
 	gpwrdn_data_t gpwrdn = {.d32 = 0 };
+	dwc_otg_device_t *otg_dev = dev;
+	dwc_otg_core_if_t *core_if = otg_dev->core_if;
 	gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
-
+	if (dwc_otg_is_device_mode(core_if))
+		core_if->frame_num = dwc_otg_get_frame_number(core_if);
+		
 	if (core_if->lock)
 		DWC_SPINLOCK(core_if->lock);
 
@@ -1318,12 +1369,6 @@
 			dwc_otg_handle_pwrdn_srp_intr(core_if);
 			retval |= 1;
 		}
-		if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {
-			CLEAR_GPWRDN_INTR(core_if, sts_chngint);
-			dwc_otg_handle_pwrdn_stschng_intr(core_if);
-
-			retval |= 1;
-		}
 	}
 	/* Handle ADP interrupt here */
 	if (gpwrdn.b.adp_int) {
@@ -1332,6 +1377,13 @@
 		dwc_otg_adp_handle_intr(core_if);
 		retval |= 1;
 	}
+	if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {
+		DWC_PRINTF("STS CHNG interrupt asserted\n");
+		CLEAR_GPWRDN_INTR(core_if, sts_chngint);
+		dwc_otg_handle_pwrdn_stschng_intr(otg_dev);
+
+		retval |= 1;
+	}
 	if (core_if->lock)
 		DWC_SPINUNLOCK(core_if->lock);
 
diff --git a/drivers/usb/dwc_otg/dwc_otg_core_if.h b/drivers/usb/dwc_otg/dwc_otg_core_if.h
old mode 100644
new mode 100755
index 5e12bf0..30f52fe
--- a/drivers/usb/dwc_otg/dwc_otg_core_if.h
+++ b/drivers/usb/dwc_otg/dwc_otg_core_if.h
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
- * $Revision: #10 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #12 $
+ * $Date: 2011/10/24 $
+ * $Change: 1871159 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -63,7 +63,7 @@
 extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if);
 
 /** This function should be called on every hardware interrupt. */
-extern int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t * _core_if);
+extern int32_t dwc_otg_handle_common_intr(void *otg_dev);
 
 /** @name OTG Core Parameters */
 /** @{ */
@@ -109,8 +109,7 @@
 extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if,
 					     int32_t val);
 extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if);
-//#define dwc_param_dma_desc_enable_default 1
-#define dwc_param_dma_desc_enable_default 0 // TEST
+#define dwc_param_dma_desc_enable_default 0
 
 /** The DMA Burst size (applicable only for External DMA
  * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
@@ -218,7 +217,8 @@
 extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
 					       int32_t val);
 extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if);
-#define dwc_param_host_rx_fifo_size_default 1024
+#define dwc_param_host_rx_fifo_size_default 776
+
 
 /** Number of 4-byte words in the non-periodic Tx FIFO in host mode
  * when Dynamic FIFO sizing is enabled in the core.
@@ -228,7 +228,7 @@
 						      core_if, int32_t val);
 extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
 							  core_if);
-#define dwc_param_host_nperio_tx_fifo_size_default 1024
+#define dwc_param_host_nperio_tx_fifo_size_default 512
 
 /** Number of 4-byte words in the host periodic Tx FIFO when dynamic
  * FIFO sizing is enabled.
@@ -238,7 +238,7 @@
 						     core_if, int32_t val);
 extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
 							 core_if);
-#define dwc_param_host_perio_tx_fifo_size_default 1024
+#define dwc_param_host_perio_tx_fifo_size_default 768
 
 /** The maximum transfer size supported in bytes.
  * 2047 to 65,535  (default 65,535)
@@ -263,8 +263,7 @@
 extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if,
 					   int32_t val);
 extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if);
-//#define dwc_param_host_channels_default 12
-#define dwc_param_host_channels_default 13
+#define dwc_param_host_channels_default 14
 
 /** The number of endpoints in addition to EP0 available for device
  * mode operations.
@@ -275,7 +274,7 @@
 extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if,
 					   int32_t val);
 extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if);
-#define dwc_param_dev_endpoints_default 6
+#define dwc_param_dev_endpoints_default 7
 
 /**
  * Specifies the type of PHY interface to use. By default, the driver
@@ -375,7 +374,6 @@
 extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
 						  int fifo_num);
 #define dwc_param_dev_tx_fifo_size_default 768
-//#define dwc_param_dev_tx_fifo_size_default 256 //Try this
 
 /** Thresholding enable flag-
  * bit 0 - enable non-ISO Tx thresholding
@@ -463,9 +461,19 @@
 extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if);
 #define dwc_param_dev_out_nak_default 0
 
+extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if,
+										 int32_t val);
+extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if);
+#define dwc_param_cont_on_bna_default 0
+
+extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if,
+										 int32_t val);
+extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if);
+#define dwc_param_ahb_single_default 0
+
 extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val);
 extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if);
-#define dwc_param_otg_ver_default 1
+#define dwc_param_otg_ver_default 0
 
 /** @} */
 
diff --git a/drivers/usb/dwc_otg/dwc_otg_dbg.h b/drivers/usb/dwc_otg/dwc_otg_dbg.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_otg_driver.c b/drivers/usb/dwc_otg/dwc_otg_driver.c
old mode 100644
new mode 100755
index c8f0c07..717da0b
--- a/drivers/usb/dwc_otg/dwc_otg_driver.c
+++ b/drivers/usb/dwc_otg/dwc_otg_driver.c
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
- * $Revision: #89 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #91 $
+ * $Date: 2011/10/24 $
+ * $Change: 1871159 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -57,6 +57,7 @@
 #include "dwc_otg_pcd_if.h"
 #include "dwc_otg_hcd_if.h"
 #include <mach/reset.h>
+#include <mach/hardware.h>
 
 #include <linux/clk.h>
 
@@ -66,7 +67,8 @@
 extern void dwc_otg_host_port_suspend(struct usb_hcd *hcd);
 extern void dwc_otg_host_port_resume(struct usb_hcd *hcd);
 
-#define DWC_DRIVER_VERSION	"2.93a 15-MAY-2011"
+
+#define DWC_DRIVER_VERSION	"2.94a 27-OCT-2011"
 #define DWC_DRIVER_DESC		"HS OTG USB Controller driver"
 
 static const char dwc_driver_name[] = "dwc_otg";
@@ -96,7 +98,7 @@
 #elif  defined(PCI_INTERFACE)
 			     struct pci_dev *_dev
 #else
-				struct platform_device *_dev
+				 struct platform_device *_dev
 #endif
     );
 
@@ -106,11 +108,11 @@
 #elif  defined(PCI_INTERFACE)
 			      struct pci_dev *_dev
 #else
-				struct platform_device *_dev
+					struct platform_device *_dev
 #endif
     );
 
-extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if);
+extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
 
 /*-------------------------------------------------------------------------*/
 /* Encapsulate the module parameter settings */
@@ -156,6 +158,8 @@
 	int32_t power_down;
 	int32_t reload_ctl;
 	int32_t dev_out_nak;
+	int32_t cont_on_bna;
+	int32_t ahb_single;
 	int32_t otg_ver;
 	int32_t adp_enable;
 };
@@ -237,6 +241,8 @@
 	.power_down = -1,
 	.reload_ctl = -1,
 	.dev_out_nak = -1,
+	.cont_on_bna = -1,
+	.ahb_single = -1,
 	.otg_ver = -1,
 	.adp_enable = -1,
 };
@@ -441,7 +447,8 @@
 							  dwc_otg_module_params.
 							  en_multiple_tx_fifo);
 	}
-	for (i = 0; i < 15; i++) {
+
+	for (i = 0; i < 7; i++) {
 		if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) {
 			retval +=
 			    dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
@@ -451,7 +458,7 @@
 		}
 	}
 
-	for (i = 0; i < 15; i++) {
+	for (i = 0; i < 7; i++) {
 		if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) {
 			retval += dwc_otg_set_param_dev_tx_fifo_size(core_if,
 								     dwc_otg_module_params.
@@ -521,6 +528,18 @@
 			dwc_otg_module_params.dev_out_nak);
 	}
 
+	if (dwc_otg_module_params.cont_on_bna != -1) {
+		retval +=
+			dwc_otg_set_param_cont_on_bna(core_if,
+			dwc_otg_module_params.cont_on_bna);
+	}
+
+	if (dwc_otg_module_params.ahb_single != -1) {
+		retval +=
+			dwc_otg_set_param_ahb_single(core_if,
+			dwc_otg_module_params.ahb_single);
+	}
+
 	if (dwc_otg_module_params.otg_ver != -1) {
 		retval +=
 		    dwc_otg_set_param_otg_ver(core_if,
@@ -555,7 +574,10 @@
 		 * Bit[17:16]:usb0_refclkdiv - Reference Clock Frequency Select, 48 MHz
 		 * Bit[21:20]:usb0_refclksel - The XO block uses an external, 2.5 V clock supplied on the XO pin.
 		 */
-		writel(0x00220000, COMCERTO_USB0_PHY_CTRL_REG0);
+		if(HAL_get_ref_clk() == REF_CLK_24MHZ)
+			writel(0x00210000, COMCERTO_USB0_PHY_CTRL_REG0);  //24MHz ref clk
+		else
+			writel(0x00220000, COMCERTO_USB0_PHY_CTRL_REG0);  //48MHz ref clk
 
 		/* Programming the IDSEL values to USB 2.0 Controller @ DWC_CFG_REGF register */
 		/* Configuring the usb2 controller to select the ID value from register */
@@ -643,10 +665,9 @@
  */
 static irqreturn_t dwc_otg_common_irq(int irq, void *dev)
 {
-	dwc_otg_device_t *otg_dev = dev;
 	int32_t retval = IRQ_NONE;
 
-	retval = dwc_otg_handle_common_intr(otg_dev->core_if);
+	retval = dwc_otg_handle_common_intr(dev);
 	if (retval != 0) {
 		S3C2410X_CLEAR_EINTPEND();
 	}
@@ -668,9 +689,8 @@
 #elif defined(PCI_INTERFACE)
 					 struct pci_dev *_dev
 #else
-					struct platform_device *_dev
+					 struct platform_device *_dev
 #endif
-
     )
 {
 #ifdef LM_INTERFACE
@@ -725,11 +745,8 @@
 	/*
 	 * Remove the device attributes
 	 */
-#if 1
 	dwc_otg_attr_remove(_dev);
-#else
-	dwc_otg_attr_remove(otg_dev->os_dep.parent);
-#endif
+
 	/*
 	 * Return the memory.
 	 */
@@ -753,7 +770,6 @@
 #else
 	platform_set_drvdata(_dev, 0);
 #endif
-
 }
 
 /**
@@ -796,7 +812,6 @@
 	}
 	dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0));
 	/* other stuff needed as well? */
-
 #else
 	dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource->start);
 #endif
@@ -811,7 +826,6 @@
 	memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
 	dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
 
-
 	/* Platform Specific initialization */
 	comcerto_start_dwc_otg();
 
@@ -893,14 +907,13 @@
 	/*
 	 * Retrieve the memory and IRQ resources.
 	 */
-	dwc_otg_device->irq = platform_get_irq(_dev, 0);
+	 dwc_otg_device->irq = platform_get_irq(_dev, 0);
 	if (dwc_otg_device->irq <= 0) {
 		dev_err(&_dev->dev, "no device irq\n");
 		retval = -EINVAL;
 		goto fail;
 	}
 
-
 	/*
 	 * Initialize driver data to point to the global DWC_otg
 	 * Device structure.
@@ -909,6 +922,7 @@
 	lm_set_drvdata(_dev, dwc_otg_device);
 #else
 	platform_set_drvdata(_dev, dwc_otg_device);
+	_dev->dev.platform_data = (void *) dwc_otg_device;
 #endif
 	dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);
 
@@ -944,7 +958,6 @@
 	/*
 	 * Create Device Attributes in sysfs
 	 */
-	//dwc_otg_attr_create(&_dev->dev);
 	dwc_otg_attr_create(_dev);
 
 	/*
@@ -972,9 +985,6 @@
 
 #ifdef LM_INTERFACE
 	set_irq_type(_dev->irq, IRQT_LOW);
-#else
-	/* FIXME : Makarand - Need to check about it */
-	//set_irq_type(dwc_otg_device->irq, IRQT_LOW);
 #endif
 	/*
 	 * Initialize the DWC_otg core.
@@ -1016,7 +1026,8 @@
 	if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if))
 		dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);
 	else
-		dwc_otg_adp_start(dwc_otg_device->core_if);
+		dwc_otg_adp_start(dwc_otg_device->core_if,
+							dwc_otg_is_host_mode(dwc_otg_device->core_if));
 
 	return 0;
 
@@ -1480,6 +1491,10 @@
 MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control");
 module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444);
 MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK");
+module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444);
+MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA");
+module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444);
+MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support");
 module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444);
 MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled");
 module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444);
@@ -1804,6 +1819,24 @@
  - 1: The core sets NAK after Bulk OUT transfer complete
  </td></tr>
 
+ <tr>
+ <td>cont_on_bna</td>
+ <td>Specifies whether Enable Continue on BNA enabled or no.
+ After receiving BNA interrupt the core disables the endpoint,when the
+ endpoint is re-enabled by the application the
+ - 0: Core starts processing from the DOEPDMA descriptor (default)
+ - 1: Core starts processing from the descriptor which received the BNA.
+ This parameter is valid only when OTG_EN_DESC_DMA == 1Â’b1.
+ </td></tr>
+
+ <tr>
+ <td>ahb_single</td>
+ <td>This bit when programmed supports SINGLE transfers for remainder data
+ in a transfer for DMA mode of operation.
+ - 0: The remainder data will be sent using INCR burst size (default)
+ - 1: The remainder data will be sent using SINGLE burst size.
+ </td></tr>
+
 <tr>
  <td>adp_enable</td>
  <td>Specifies whether ADP feature is enabled.
diff --git a/drivers/usb/dwc_otg/dwc_otg_driver.h b/drivers/usb/dwc_otg/dwc_otg_driver.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd.c b/drivers/usb/dwc_otg/dwc_otg_hcd.c
old mode 100644
new mode 100755
index 7f117a9..d49f475
--- a/drivers/usb/dwc_otg/dwc_otg_hcd.c
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd.c
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
- * $Revision: #102 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #104 $
+ * $Date: 2011/10/24 $
+ * $Change: 1871159 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -447,6 +447,7 @@
 	dwc_irqflags_t flags;
 	int retval = 0;
 	dwc_otg_qtd_t *qtd;
+	gintmsk_data_t intr_mask = {.d32 = 0 };
 
 	if (!hcd->flags.b.port_connect_status) {
 		/* No longer connected. */
@@ -469,12 +470,12 @@
 	} else {
 		qtd->qh = *ep_handle;
 	}
-
-	if (hcd->core_if->dma_desc_enable && retval == 0) {
+	intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
+	if (!intr_mask.b.sofintr && retval == 0) {
 		dwc_otg_transaction_type_e tr_type;
 		if ((qtd->qh->ep_type == UE_BULK)
 		    && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
-			/* Do not schedule SG transcations until qtd has URB_GIVEBACK_ASAP set */
+			/* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
 			return 0;
 		}
 		DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
@@ -870,6 +871,7 @@
 	hcd->otg_port = 1;
 	hcd->frame_list = NULL;
 	hcd->frame_list_dma = 0;
+	hcd->periodic_qh_count = 0;
 out:
 	return retval;
 }
@@ -2459,6 +2461,7 @@
 			}
 
 			/** @todo - check how sw can wait for 1 sec to check asesvld??? */
+#if 0 //vahrama !!!!!!!!!!!!!!!!!!
 			if (core_if->adp_enable) {
 				gotgctl_data_t gotgctl = {.d32 = 0 };
 				gpwrdn_data_t gpwrdn;
@@ -2485,6 +2488,7 @@
 
 				dwc_otg_adp_probe_start(core_if);
 			}
+#endif
 			break;
 		case UHF_PORT_POWER:
 			DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd.h b/drivers/usb/dwc_otg/dwc_otg_hcd.h
old mode 100644
new mode 100755
index a468df5..58a1293
--- a/drivers/usb/dwc_otg/dwc_otg_hcd.h
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd.h
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
- * $Revision: #57 $
- * $Date: 2010/11/29 $
- * $Change: 1636033 $
+ * $Revision: #58 $
+ * $Date: 2011/09/15 $
+ * $Change: 1846647 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -473,6 +473,11 @@
 	uint16_t frame_number;
 
 	/**
+	 * Count of periodic QHs, if using several eps. For SOF enable/disable.
+	 */
+	uint16_t periodic_qh_count;
+
+	/**
 	 * Free host channels in the controller. This is a list of
 	 * dwc_hc_t items.
 	 */
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/dwc_otg/dwc_otg_hcd_ddma.c
old mode 100644
new mode 100755
index 8c3ac52..6911e04
--- a/drivers/usb/dwc_otg/dwc_otg_hcd_ddma.c
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd_ddma.c
@@ -1,8 +1,8 @@
 /*==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $
- * $Revision: #8 $
- * $Date: 2010/11/29 $
- * $Change: 1636033 $
+ * $Revision: #10 $
+ * $Date: 2011/10/20 $
+ * $Change: 1869464 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -523,6 +523,7 @@
 				qh->n_bytes[idx] = frame_desc->length;
 			dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx];
 			dma_desc->status.b_isoc.a = 1;
+			dma_desc->status.b_isoc.sts = 0;
 
 			dma_desc->buf = qtd->urb->dma + frame_desc->offset;
 
@@ -640,6 +641,7 @@
 				dma_desc->status.b.sup = 1;	/* Setup Packet */
 
 			dma_desc->status.b.a = 1;	/* Active descriptor */
+			dma_desc->status.b.sts = 0;
 
 			dma_desc->buf =
 			    ((unsigned long)hc->xfer_buff & 0xffffffff);
@@ -663,6 +665,9 @@
 
 		qtd->in_process = 1;
 
+		if (qh->ep_type == UE_CONTROL)
+			break;
+
 		if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
 			break;
 	}
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/dwc_otg/dwc_otg_hcd_if.h
old mode 100644
new mode 100755
index d17561f..b3dc806
--- a/drivers/usb/dwc_otg/dwc_otg_hcd_if.h
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd_if.h
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $
- * $Revision: #11 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #12 $
+ * $Date: 2011/10/26 $
+ * $Change: 1873028 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -177,7 +177,7 @@
 /**
  * Returns OTG version - either 1.3 or 2.0.
  *
- * @param hcd The HCD
+ * @param core_if The core_if structure pointer
  */
 extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if);
 
@@ -332,6 +332,7 @@
  * @param dwc_otg_hcd The HCD
  * @param dwc_otg_urb DWC_OTG URB
  * @param ep_handle Out parameter for returning endpoint handle
+ * @param atomic_alloc Flag to do atomic allocation if needed
  *
  * Returns -DWC_E_NO_DEVICE if no device is connected.
  * Returns -DWC_E_NO_MEMORY if there is no enough memory.
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
old mode 100644
new mode 100755
index 5453500..d145fa0
--- a/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
- * $Revision: #87 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #89 $
+ * $Date: 2011/10/20 $
+ * $Change: 1869487 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -331,7 +331,7 @@
 
 	if (hprt0.b.prtconndet) {
 		/** @todo - check if steps performed in 'else' block should be perfromed regardles adp */
-		if (dwc_otg_hcd->core_if->adp_enable && 	
+		if (dwc_otg_hcd->core_if->adp_enable &&
 				dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) {
 			DWC_PRINTF("PORT CONNECT DETECTED ----------------\n");
 			DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer);
@@ -345,13 +345,13 @@
 			dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if);
 			cil_hcd_start(dwc_otg_hcd->core_if);*/
 		} else {
-		
+
 			DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
 				    "Port Connect Detected--\n", hprt0.d32);
 			dwc_otg_hcd->flags.b.port_connect_status_change = 1;
 			dwc_otg_hcd->flags.b.port_connect_status = 1;
 			hprt0_modify.b.prtconndet = 1;
-	
+
 			/* B-Device has connected, Delete the connection timer. */
 			DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);
 		}
@@ -375,7 +375,7 @@
 			    dwc_otg_hcd->core_if->core_global_regs;
 			dwc_otg_host_if_t *host_if =
 			    dwc_otg_hcd->core_if->host_if;
-			    
+
 			/* Every time when port enables calculate
 			 * HFIR.FrInterval
 			 */
@@ -603,7 +603,7 @@
 		xfer_done = 1;
 		urb->status = 0;
 	}
-	
+
 #ifdef DEBUG
 	{
 		hctsiz_data_t hctsiz;
@@ -684,7 +684,7 @@
 			dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
 				   hc->qh->dw_align_buf, frame_desc->actual_length);
 		}
-		
+
 		break;
 	case DWC_OTG_HC_XFER_FRAME_OVERRUN:
 		urb->error_count++;
@@ -821,6 +821,14 @@
 	case DWC_OTG_HC_XFER_NO_HALT_STATUS:
 		free_qtd = 0;
 		break;
+	case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE:
+		DWC_DEBUGPL(DBG_HCDV,
+			"  Complete URB with I/O error\n");
+		free_qtd = 1;
+		qtd->urb->status = -DWC_E_IO;
+		hcd->fops->complete(hcd, qtd->urb->priv,
+			qtd->urb, -DWC_E_IO);
+		break;
 	default:
 		free_qtd = 0;
 		break;
@@ -1133,16 +1141,22 @@
 		break;
 	case UE_INTERRUPT:
 		DWC_DEBUGPL(DBG_HCDV, "  Interrupt transfer complete\n");
-		update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
+		urb_xfer_done =
+			update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
 
 		/*
 		 * Interrupt URB is done on the first transfer complete
 		 * interrupt.
 		 */
-		hcd->fops->complete(hcd, urb->priv, urb, urb->status);
+		if (urb_xfer_done) {
+				hcd->fops->complete(hcd, urb->priv, urb, urb->status);
+				halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
+		} else {
+				halt_status = DWC_OTG_HC_XFER_COMPLETE;
+		}
+
 		dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
-		complete_periodic_xfer(hcd, hc, hc_regs, qtd,
-				       DWC_OTG_HC_XFER_URB_COMPLETE);
+		complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
 		break;
 	case UE_ISOCHRONOUS:
 		DWC_DEBUGPL(DBG_HCDV, "  Isochronous transfer complete\n");
@@ -1445,13 +1459,13 @@
 			qtd->isoc_split_offset = 0;
 			if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
 				hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
-				release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);	
+				release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
 			}
 			else
-				release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);	
+				release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
 			goto handle_nyet_done;
 		}
-		
+
 		if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
 		    hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
 			int frnum = dwc_otg_hcd_get_frame_number(hcd);
@@ -1653,6 +1667,15 @@
 		goto handle_xacterr_done;
 	}
 
+	if (qtd == NULL)
+		goto handle_xacterr_done;
+
+	if(qtd->urb == NULL)
+		goto handle_xacterr_done;
+
+	if (&qtd->urb->pipe_info == NULL)
+		goto handle_xacterr_done;
+
 	switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
 	case UE_CONTROL:
 	case UE_BULK:
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/dwc_otg/dwc_otg_hcd_linux.c
old mode 100644
new mode 100755
index 9a6e5f0..639321c
--- a/drivers/usb/dwc_otg/dwc_otg_hcd_linux.c
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd_linux.c
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
- * $Revision: #18 $
- * $Date: 2011/05/17 $
- * $Change: 1774126 $
+ * $Revision: #20 $
+ * $Date: 2011/10/26 $
+ * $Change: 1872981 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -51,8 +51,11 @@
 #include <linux/version.h>
 #include <asm/io.h>
 #include <linux/usb.h>
-//#include <../drivers/usb/core/hcd.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+#include <../drivers/usb/core/hcd.h>
+#else
 #include <linux/usb/hcd.h>
+#endif
 
 #include "dwc_otg_hcd_if.h"
 #include "dwc_otg_dbg.h"
@@ -65,7 +68,6 @@
 #define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
 						     ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
 
-//static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
 static const char dwc_otg_hcd_name[] = "dwc_otg";
 
 /** @name Linux HC Driver API Functions */
@@ -110,10 +112,10 @@
 
 	.flags = HCD_MEMORY | HCD_USB2,
 
-	//.reset =              
+	//.reset =
 	.start = hcd_start,
-	//.suspend =            
-	//.resume =             
+	//.suspend =
+	//.resume =
 	.stop = hcd_stop,
 
 	.urb_enqueue = urb_enqueue,
@@ -126,8 +128,8 @@
 
 	.hub_status_data = hub_status_data,
 	.hub_control = hub_control,
-	//.bus_suspend =                
-	//.bus_resume =         
+	//.bus_suspend =
+	//.bus_resume =
 };
 
 /** Gets the dwc_otg_hcd from a struct usb_hcd */
@@ -337,7 +339,7 @@
 	dwc_otg_host_if_t host_if;
 	hprt0_data_t hprt;
 
-	host_if.hprt0 = hcd->regs + DWC_OTG_HOST_PORT_REGS_OFFSET;	
+	host_if.hprt0 = hcd->regs + DWC_OTG_HOST_PORT_REGS_OFFSET;
 
 	hprt.d32= DWC_READ_REG32(host_if.hprt0);
 	hprt.b.prtsusp = 1;
@@ -353,7 +355,7 @@
 	dwc_otg_host_if_t host_if;
 	hprt0_data_t hprt;
 
-	host_if.hprt0 = hcd->regs + DWC_OTG_HOST_PORT_REGS_OFFSET;	
+	host_if.hprt0 = hcd->regs + DWC_OTG_HOST_PORT_REGS_OFFSET;
 
 	hprt.d32= DWC_READ_REG32(host_if.hprt0);
 	hprt.b.prtsusp = 0;
@@ -372,10 +374,9 @@
 		    struct lm_device *_dev
 #elif  defined(PCI_INTERFACE)
 		    struct pci_dev *_dev
-#else 
+#else
 			struct platform_device *_dev
 #endif
-
     )
 {
 	struct usb_hcd *hcd = NULL;
@@ -446,8 +447,10 @@
 
 	otg_dev->hcd->otg_dev = otg_dev;
 	hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
-	//hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if);
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel)
+	/* Don't support SG list at this point */
+	hcd->self.sg_tablesize = 0;
+#endif
 	/*
 	 * Finish generic HCD initialization and start the HCD. This function
 	 * allocates the DMA buffer pool, registers the USB bus, requests the
@@ -476,10 +479,9 @@
 		       struct lm_device *_dev
 #elif  defined(PCI_INTERFACE)
 		       struct pci_dev *_dev
-#else 
+#else
 				struct platform_device *_dev
 #endif
-
     )
 {
 #ifdef LM_INTERFACE
@@ -490,7 +492,6 @@
 	dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
 #endif
 
-
 	dwc_otg_hcd_t *dwc_otg_hcd;
 	struct usb_hcd *hcd;
 
@@ -663,15 +664,6 @@
 		break;
 	case PIPE_BULK:
 		ep_type = USB_ENDPOINT_XFER_BULK;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
-/* FIXME : Makarand - Need to comment this warning */
-#if 0
-		if (urb->sg) {
-			DWC_WARN("SG LIST received - we don't support it\n");
-		}
-#endif		
-#endif
 		break;
 	case PIPE_INTERRUPT:
 		ep_type = USB_ENDPOINT_XFER_INT;
@@ -796,7 +788,7 @@
 }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
-/* Resets endpoint specific parameter values, in current version used to reset 
+/* Resets endpoint specific parameter values, in current version used to reset
  * the data toggle(as a WA). This function can be called from usb_clear_halt routine */
 static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
 {
@@ -815,7 +807,7 @@
 #endif
 
 	if (_dev)
-		udev = to_usb_device(_dev); // udev = to_usb_device(&_dev->dev);
+		udev = to_usb_device(_dev);
 	else
 		return;
 
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c
old mode 100644
new mode 100755
index 0318b98..903a902
--- a/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $
- * $Revision: #42 $
- * $Date: 2010/11/29 $
- * $Change: 1636033 $
+ * $Revision: #44 $
+ * $Date: 2011/10/26 $
+ * $Change: 1873028 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -284,6 +284,7 @@
  * @param hcd The HCD state structure for the DWC OTG controller.
  * @param urb Holds the information about the device/endpoint that we need
  * 	      to initialize the QH.
+ * @param atomic_alloc Flag to do atomic allocation if needed
  *
  * @return Returns pointer to the newly allocated QH, or NULL on error. */
 dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
@@ -467,6 +468,7 @@
 int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
 {
 	int status = 0;
+	gintmsk_data_t intr_mask = {.d32 = 0 };
 
 	if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
 		/* QH already in a schedule. */
@@ -480,6 +482,12 @@
 				     &qh->qh_list_entry);
 	} else {
 		status = schedule_periodic(hcd, qh);
+		if ( !hcd->periodic_qh_count ) {
+			intr_mask.b.sofintr = 1;
+			DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
+								intr_mask.d32, intr_mask.d32);
+		}
+		hcd->periodic_qh_count++;
 	}
 
 	return status;
@@ -510,6 +518,8 @@
  * @param qh QH to remove from schedule. */
 void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
 {
+	gintmsk_data_t intr_mask = {.d32 = 0 };
+
 	if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
 		/* QH is not in a schedule. */
 		return;
@@ -523,6 +533,12 @@
 		DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
 	} else {
 		deschedule_periodic(hcd, qh);
+		hcd->periodic_qh_count--;
+		if( !hcd->periodic_qh_count ) {
+			intr_mask.b.sofintr = 1;
+				DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
+									intr_mask.d32, 0);
+		}
 	}
 }
 
@@ -616,6 +632,7 @@
  *
  * @param urb The URB to create a QTD from.  Each URB-QTD pair will end up
  * 	      pointing to each other so each pair should have a unique correlation.
+ * @param atomic_alloc Flag to do atomic alloc if needed
  *
  * @return Returns pointer to the newly allocated QTD, or NULL on error. */
 dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc)
@@ -670,6 +687,7 @@
  * @param[in] qtd The QTD to add
  * @param[in] hcd The DWC HCD structure
  * @param[out] qh out parameter to return queue head
+ * @param atomic_alloc Flag to do atomic alloc if needed
  *
  * @return 0 if successful, negative error code otherwise.
  */
diff --git a/drivers/usb/dwc_otg/dwc_otg_os_dep.h b/drivers/usb/dwc_otg/dwc_otg_os_dep.h
old mode 100644
new mode 100755
index 81e76553..1f8db73
--- a/drivers/usb/dwc_otg/dwc_otg_os_dep.h
+++ b/drivers/usb/dwc_otg/dwc_otg_os_dep.h
@@ -69,7 +69,6 @@
 # include <asm/param.h>
 # include <asm/io.h>
 # include <mach/irqs.h>
-//# include <asm/arch/regs-irq.h>
 #endif
 
 /** The OS page size */
diff --git a/drivers/usb/dwc_otg/dwc_otg_pcd.c b/drivers/usb/dwc_otg/dwc_otg_pcd.c
old mode 100644
new mode 100755
index 8d24249..e6792e9
--- a/drivers/usb/dwc_otg/dwc_otg_pcd.c
+++ b/drivers/usb/dwc_otg/dwc_otg_pcd.c
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
- * $Revision: #97 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #99 $
+ * $Date: 2011/10/24 $
+ * $Change: 1871160 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -82,8 +82,8 @@
 			  int32_t status)
 {
 	unsigned stopped = ep->stopped;
-
-	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, ep);
+	
+	DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req);
 	DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
 
 	/* don't modify queue heads during completion callback */
@@ -1006,6 +1006,31 @@
 	gotgctl.d32 = DWC_READ_REG32(addr);
 
 	core_if->srp_timer_started = 0;
+	
+	if (core_if->adp_enable) {
+		if (gotgctl.b.bsesvld == 0) {
+			gpwrdn_data_t gpwrdn = {.d32 = 0 };
+			DWC_PRINTF("SRP Timeout BSESSVLD = 0\n");
+			/* Power off the core */
+			if (core_if->power_down == 2) {
+				gpwrdn.b.pwrdnswtch = 1;
+				DWC_MODIFY_REG32(&core_if->core_global_regs->
+					gpwrdn, gpwrdn.d32, 0);
+			}
+
+			gpwrdn.d32 = 0;
+			gpwrdn.b.pmuintsel = 1;
+			gpwrdn.b.pmuactv = 1;
+			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
+			dwc_otg_adp_probe_start(core_if);
+		} else {
+			DWC_PRINTF("SRP Timeout BSESSVLD = 1\n");
+			core_if->op_state = B_PERIPHERAL;
+			dwc_otg_core_init(core_if);
+			dwc_otg_enable_global_interrupts(core_if);
+			cil_pcd_start(core_if);
+		}
+	}
 
 	if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&
 	    (core_if->core_params->i2c_enable)) {
@@ -1037,30 +1062,6 @@
 	} else {
 		DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);
 	}
-
-	if (core_if->adp_enable) {
-		if (gotgctl.b.bsesvld == 0) {
-			gpwrdn_data_t gpwrdn = {.d32 = 0 };
-
-			/* Power off the core */
-			if (core_if->power_down == 2) {
-				gpwrdn.b.pwrdnswtch = 1;
-				DWC_MODIFY_REG32(&core_if->core_global_regs->
-						 gpwrdn, gpwrdn.d32, 0);
-			}
-
-			gpwrdn.d32 = 0;
-			gpwrdn.b.pmuactv = 1;
-			DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
-						
-			dwc_otg_adp_probe_start(core_if);
-		} else {
-			core_if->op_state = B_PERIPHERAL;
-			dwc_otg_core_init(core_if);
-			dwc_otg_enable_global_interrupts(core_if);
-			cil_pcd_start(core_if);
-		}
-	}
 }
 
 /**
@@ -1132,6 +1133,7 @@
 	pcd->core_if = core_if;
 
 	dev_if = core_if->dev_if;
+	dev_if->isoc_ep = NULL;
 
 	if (core_if->hwcfg4.b.ded_fifo_en) {
 		DWC_PRINTF("Dedicated Tx FIFOs mode\n");
@@ -1594,6 +1596,10 @@
 #ifdef DWC_UTE_PER_IO
 	ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1);
 #endif
+	if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
+		ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1);
+		ep->dwc_ep.frame_num = 0xFFFFFFFF;
+	}	 	
 
 	dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
 
@@ -1720,7 +1726,7 @@
 	dwcep = &ep->dwc_ep;
 
 	if (dwcep->xiso_active_xfers > 0) {
-#if 0				//Disable this to decrease s/w overhead that is crucial for Isoc transfers
+#if 0	//Disable this to decrease s/w overhead that is crucial for Isoc transfers
 		DWC_WARN("There are currently active transfers for EP%d \
 				(active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers, 
 				dwcep->xiso_queued_xfers);
@@ -2107,10 +2113,38 @@
 	req->length = buflen;
 	req->sent_zlp = zero;
 	req->priv = req_handle;
-
+	req->dw_align_buf = NULL;
+	if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable
+			&& !GET_CORE_IF(pcd)->dma_desc_enable)
+		req->dw_align_buf = DWC_DMA_ALLOC(buflen,
+				 &req->dw_align_buf_dma);
 	DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
 
 	/*
+	 * After adding request to the queue for IN ISOC wait for In Token Received
+	 * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token 
+	 * Received when EP is disabled interrupt to obtain starting microframe
+	 * (odd/even) start transfer
+	 */
+	if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
+	{
+		if (req != 0) {
+			depctl_data_t depctl = {.d32 = DWC_READ_REG32(&pcd->core_if->dev_if->in_ep_regs[ep->dwc_ep.num]->diepctl)};
+			++pcd->request_pending;
+
+			DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
+			if (ep->dwc_ep.is_in)
+			{
+				depctl.b.cnak = 1;
+				DWC_WRITE_REG32(&pcd->core_if->dev_if->in_ep_regs[ep->dwc_ep.num]->diepctl, depctl.d32);
+			}
+			
+			DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
+		}
+		return 0;
+	}
+
+	/*
 	 * For EP0 IN without premature status, zlp is required?
 	 */
 	if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {
@@ -2187,9 +2221,17 @@
 				    core_params->max_transfer_size;
 
 				/* Setup and start the Transfer */
-				ep->dwc_ep.dma_addr = dma_buf;
-				ep->dwc_ep.start_xfer_buff = buf;
-				ep->dwc_ep.xfer_buff = buf;
+				if (req->dw_align_buf){
+					if (ep->dwc_ep.is_in)
+						dwc_memcpy(req->dw_align_buf, buf, buflen);
+					ep->dwc_ep.dma_addr = req->dw_align_buf_dma;
+					ep->dwc_ep.start_xfer_buff = req->dw_align_buf;
+                                        ep->dwc_ep.xfer_buff = req->dw_align_buf;
+				} else {
+					ep->dwc_ep.dma_addr = dma_buf;
+					ep->dwc_ep.start_xfer_buff = buf;
+                                        ep->dwc_ep.xfer_buff = buf;	
+				}
 				ep->dwc_ep.xfer_len = 0;
 				ep->dwc_ep.xfer_count = 0;
 				ep->dwc_ep.sent_zlp = 0;
diff --git a/drivers/usb/dwc_otg/dwc_otg_pcd.h b/drivers/usb/dwc_otg/dwc_otg_pcd.h
old mode 100644
new mode 100755
index dd56e98..4b2dde9
--- a/drivers/usb/dwc_otg/dwc_otg_pcd.h
+++ b/drivers/usb/dwc_otg/dwc_otg_pcd.h
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
- * $Revision: #44 $
- * $Date: 2010/11/29 $
- * $Change: 1636033 $
+ * $Revision: #46 $
+ * $Date: 2011/10/20 $
+ * $Change: 1870124 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -61,9 +61,6 @@
 /** Max Transfer size for any EP */
 #define DDMA_MAX_TRANSFER_SIZE 65535
 
-/** Max DMA Descriptor count for any EP */
-#define MAX_DMA_DESC_CNT 256
-
 /**
  * Get the pointer to the core_if from the pcd pointer.
  */
@@ -136,6 +133,12 @@
 	uint32_t length;
 	uint32_t actual;
 	unsigned sent_zlp:1;
+    /**
+     * Used instead of original buffer if
+     * it(physical address) is not dword-aligned.
+     **/
+     uint8_t *dw_align_buf;
+     dwc_dma_t dw_align_buf_dma;
 
 	 DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry;
 #ifdef DWC_UTE_PER_IO
diff --git a/drivers/usb/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/dwc_otg/dwc_otg_pcd_if.h
old mode 100644
new mode 100755
index fbb70df..6283867
--- a/drivers/usb/dwc_otg/dwc_otg_pcd_if.h
+++ b/drivers/usb/dwc_otg/dwc_otg_pcd_if.h
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
- * $Revision: #10 $
- * $Date: 2010/11/04 $
- * $Change: 1621728 $
+ * $Revision: #11 $
+ * $Date: 2011/10/26 $
+ * $Change: 1873028 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -168,15 +168,15 @@
  *
  * @param pcd The PCD
  * @param ep_desc Endpoint descriptor
- * @param ep_handle Handle on endpoint, that will be used to identify endpoint.
+ * @param usb_ep Handle on endpoint, that will be used to identify endpoint.
  */
 extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
-				 const uint8_t * ep_desc, void *ep_handle);
+				 const uint8_t * ep_desc, void *usb_ep);
 
 /** Disable the endpoint referenced by ep_handle.
  *
  * Returns -DWC_E_INVALID if invalid parameters were passed.
- * Returns -DWC_E_SHUTDOWN if any other error ocurred.
+ * Returns -DWC_E_SHUTDOWN if any other error occurred.
  * Returns 0 on success. */
 extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle);
 
diff --git a/drivers/usb/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/dwc_otg/dwc_otg_pcd_intr.c
old mode 100644
new mode 100755
index b11b589..32286fd
--- a/drivers/usb/dwc_otg/dwc_otg_pcd_intr.c
+++ b/drivers/usb/dwc_otg/dwc_otg_pcd_intr.c
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
- * $Revision: #108 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #113 $
+ * $Date: 2011/10/24 $
+ * $Change: 1871160 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -238,9 +238,15 @@
 		} else {
 #endif
 			/* Setup and start the Transfer */
-			ep->dwc_ep.dma_addr = req->dma;
-			ep->dwc_ep.start_xfer_buff = req->buf;
-			ep->dwc_ep.xfer_buff = req->buf;
+			if (req->dw_align_buf) {
+				ep->dwc_ep.dma_addr = req->dw_align_buf_dma;
+				ep->dwc_ep.start_xfer_buff = req->dw_align_buf;
+				ep->dwc_ep.xfer_buff = req->dw_align_buf;
+			} else {
+				ep->dwc_ep.dma_addr = req->dma;
+				ep->dwc_ep.start_xfer_buff = req->buf;
+				ep->dwc_ep.xfer_buff = req->buf;
+			}
 			ep->dwc_ep.sent_zlp = 0;
 			ep->dwc_ep.total_len = req->length;
 			ep->dwc_ep.xfer_len = 0;
@@ -279,6 +285,9 @@
 		}
 #endif
 		dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
+	} else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
+		DWC_PRINTF("There are no more ISOC requests \n");
+		ep->dwc_ep.frame_num = 0xFFFFFFFF;
 	}
 }
 
@@ -758,6 +767,7 @@
 			dma_desc->status.b.ioc = 1;
 			dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;
 			dma_desc->buf = pcd->setup_pkt_dma_handle;
+			dma_desc->status.b.sts = 0;
 			dma_desc->status.b.bs = BS_HOST_READY;
 
 			/** DOEPDMA0 Register write */
@@ -908,7 +918,7 @@
 
 		if (core_if->dma_desc_enable) {
 			doepmsk.b.stsphsercvd = 1;
-			//doepmsk.b.bna = 1;
+			doepmsk.b.bna = 1;
 		}
 /*		
 		doepmsk.b.babble = 1;
@@ -953,7 +963,7 @@
 
 		if (core_if->dma_desc_enable) {
 			doepmsk.b.stsphsercvd = 1;
-			//doepmsk.b.bna = 1;
+			doepmsk.b.bna = 1;
 		}
 		DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
 
@@ -1200,8 +1210,8 @@
 		} else {
 			DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n");
 		}
-		/* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective() handler */
-		/* after Global IN NAK Effective interrupt will be asserted */
+		/* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective()
+		 * handler after Global IN NAK Effective interrupt will be asserted */
 	}
 	/* Clear interrupt */
 	gintsts.d32 = 0;
@@ -1468,7 +1478,8 @@
 		if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */
 			DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex));
 			DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver);
-			DWC_PRINTF("OTG CAP - %d, %d\n", core_if->core_params->otg_cap, DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
+			DWC_PRINTF("OTG CAP - %d, %d\n", core_if->core_params->otg_cap,
+						DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
 			if(core_if->otg_ver == 1 && 
 			core_if->core_params->otg_cap == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
 				uint8_t *otgsts = (uint8_t*)pcd->status_buf;
@@ -1795,7 +1806,8 @@
 #ifdef DWC_UTE_CFI
 		DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));
 
-		//printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ctrl.bRequestType, ctrl.bRequest);
+		//printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", 
+				ctrl.bRequestType, ctrl.bRequest);
 		if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {
 			if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {
 				retval = cfi_setup(pcd, &cfi_req);
@@ -2135,18 +2147,18 @@
 					} else if (ep->dwc_ep.sent_zlp) {
 						/*     
 						 * This fragment of code should initiate 0
-						 * length trasfer in case if it is queued
-						 * a trasfer with size divisible to EPs max
+						 * length transfer in case if it is queued
+						 * a transfer with size divisible to EPs max
 						 * packet size and with usb_request zero field
 						 * is set, which means that after data is transfered,
 						 * it is also should be transfered
 						 * a 0 length packet at the end. For Slave and
 						 * Buffer DMA modes in this case SW has
 						 * to initiate 2 transfers one with transfer size,
-						 * and the second with 0 size. For Desriptor
+						 * and the second with 0 size. For Descriptor
 						 * DMA mode SW is able to initiate a transfer,
 						 * which will handle all the packets including
-						 * the last  0 legth.
+						 * the last  0 length.
 						 */
 						ep->dwc_ep.sent_zlp = 0;
 						dwc_otg_ep_start_zl_transfer
@@ -2155,12 +2167,24 @@
 						is_last = 1;
 					}
 				} else {
-					DWC_WARN
-					    ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
-					     ep->dwc_ep.num,
-					     (ep->dwc_ep.is_in ? "IN" : "OUT"),
-					     deptsiz.b.xfersize,
-					     deptsiz.b.pktcnt);
+					if(ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
+					{
+						req->actual = 0;
+						dwc_otg_request_done(ep, req, 0);
+
+						ep->dwc_ep.start_xfer_buff = 0;
+						ep->dwc_ep.xfer_buff = 0;
+						ep->dwc_ep.xfer_len = 0;
+
+						/* If there is a request in the queue start it. */
+						start_next_request(ep);
+					} else
+						DWC_WARN
+						("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
+						ep->dwc_ep.num,
+						(ep->dwc_ep.is_in ? "IN" : "OUT"),
+						deptsiz.b.xfersize,
+						deptsiz.b.pktcnt);
 				}
 			} else {
 				dma_desc = ep->dwc_ep.desc_addr;
@@ -2275,10 +2299,32 @@
 #ifdef DWC_UTE_CFI
 				}
 #endif
-				ep->dwc_ep.xfer_count = ep->dwc_ep.total_len
-				    - byte_count +
-				    ((4 - (ep->dwc_ep.total_len & 0x3)) & 0x3);
-				is_last = 1;
+				/* Checking for interrupt Out transfers with not 
+				 * dword aligned mps sizes 
+				 */
+				if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR &&
+							(ep->dwc_ep.maxpacket%4)) {
+					ep->dwc_ep.xfer_count = ep->dwc_ep.total_len - byte_count;
+					if ((ep->dwc_ep.xfer_len % ep->dwc_ep.maxpacket) &&
+						(ep->dwc_ep.xfer_len/ep->dwc_ep.maxpacket < MAX_DMA_DESC_CNT))
+						ep->dwc_ep.xfer_len -=
+							(ep->dwc_ep.desc_cnt - 1) * ep->dwc_ep.maxpacket +
+									ep->dwc_ep.xfer_len % ep->dwc_ep.maxpacket;
+					else						
+						ep->dwc_ep.xfer_len -=
+									ep->dwc_ep.desc_cnt * ep->dwc_ep.maxpacket;
+					if (ep->dwc_ep.xfer_len > 0) {
+                                        	dwc_otg_ep_start_transfer(core_if,
+                                                                  &ep->dwc_ep);
+					} else {
+						is_last = 1;
+					}
+				} else {
+					ep->dwc_ep.xfer_count = ep->dwc_ep.total_len
+						- byte_count +
+						((4 - (ep->dwc_ep.total_len & 0x3)) & 0x3);
+					is_last = 1;
+				}	
 			} else {
 				deptsiz.d32 = 0;
 				deptsiz.d32 =
@@ -2329,18 +2375,18 @@
 			} else if (ep->dwc_ep.sent_zlp) {
 				/*     
 				 * This fragment of code should initiate 0
-				 * length trasfer in case if it is queued
-				 * a trasfer with size divisible to EPs max
+				 * length transfer in case if it is queued
+				 * a transfer with size divisible to EPs max
 				 * packet size and with usb_request zero field
 				 * is set, which means that after data is transfered,
 				 * it is also should be transfered
 				 * a 0 length packet at the end. For Slave and
 				 * Buffer DMA modes in this case SW has
 				 * to initiate 2 transfers one with transfer size,
-				 * and the second with 0 size. For Desriptor
+				 * and the second with 0 size. For Descriptor
 				 * DMA mode SW is able to initiate a transfer,
 				 * which will handle all the packets including
-				 * the last  0 legth.
+				 * the last  0 length.
 				 */
 				ep->dwc_ep.sent_zlp = 0;
 				dwc_otg_ep_start_zl_transfer(core_if,
@@ -2369,6 +2415,13 @@
 #ifdef DWC_UTE_CFI
 		}
 #endif
+		if (req->dw_align_buf) {
+			if (!ep->dwc_ep.is_in) {
+				dwc_memcpy(req->buf, req->dw_align_buf, req->length); 
+			}
+			DWC_DMA_FREE(req->length, req->dw_align_buf,
+				     req->dw_align_buf_dma);
+		}
 
 		dwc_otg_request_done(ep, req, 0);
 
@@ -3009,14 +3062,27 @@
 	dwc_otg_pcd_t *pcd = ep->pcd;
 	dwc_otg_dev_dma_desc_t *dma_desc;
 	dev_dma_desc_sts_t sts = {.d32 = 0 };
-	int i;
+	dwc_otg_core_if_t *core_if = ep->pcd->core_if;
+	int i, start;
 
 	if (!dwc_ep->desc_cnt)
 		DWC_WARN("Descriptor count = %d\n", dwc_ep->desc_cnt);
 
-	dma_desc = dwc_ep->desc_addr;
+	if (core_if->core_params->cont_on_bna && !dwc_ep->is_in
+							&& dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) {
+		uint32_t doepdma;
+		dwc_otg_dev_out_ep_regs_t *out_regs =
+			core_if->dev_if->out_ep_regs[dwc_ep->num];
+		doepdma = DWC_READ_REG32(&(out_regs->doepdma));
+		start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t);
+		dma_desc = &(dwc_ep->desc_addr[start]);
+	} else {
+		start = 0;
+		dma_desc = dwc_ep->desc_addr;
+	}
+	
 
-	for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
+	for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
 		sts.d32 = dma_desc->status.d32;
 		sts.b.bs = BS_HOST_READY;
 		dma_desc->status.d32 = sts.d32;
@@ -3031,6 +3097,7 @@
 		    &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
 	}
 	depctl.b.epena = 1;
+	depctl.b.cnak = 1;
 	DWC_MODIFY_REG32(addr, 0, depctl.d32);
 }
 
@@ -3419,6 +3486,7 @@
 
 	if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
 		dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
+		complete_ep(ep);
 		return;
 	}
 
@@ -3430,8 +3498,7 @@
 	DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
 		    dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
 	
-	if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) {	// or Periodic EP
-
+	if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) { 
 		if (ep->stopped) {
 			if (core_if->en_multiple_tx_fifo)
 				/* Flush the Tx FIFO */
@@ -3486,12 +3553,13 @@
 					xfer_size = ep->dwc_ep.maxxfer;
 				depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
 				if (dieptsiz.b.pktcnt != 0) {
-					if (xfer_size == 0) { // zlp
+					if (xfer_size == 0) {
 						remain_to_transfer = 0;
 					} else {
-						if ((xfer_size % ep->dwc_ep.maxpacket) == 0) {	// last packet not short
-							remain_to_transfer = dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket;
-						} else {	// last packet is short
+						if ((xfer_size % ep->dwc_ep.maxpacket) == 0) {
+							remain_to_transfer = 
+								dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket;
+						} else {
 							remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket) 
 								+ (xfer_size % ep->dwc_ep.maxpacket);
 						}
@@ -3806,7 +3874,19 @@
 				}
 #endif /* DWC_UTE_PER_IO */
 				else {
+					if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC && 
+							dwc_ep->bInterval > 1) {
+						dwc_ep->frame_num += dwc_ep->bInterval;
+						if (dwc_ep->frame_num > 0x3FFF)
+						{
+							dwc_ep->frm_overrun = 1;
+							dwc_ep->frame_num &= 0x3FFF;
+						} else 
+							dwc_ep->frm_overrun = 0;
+					}
 					complete_ep(ep);
+					if(diepint.b.nak)
+						CLEAR_IN_EP_INTR(core_if, epnum, nak);
 				}
 			}
 			/* Endpoint disable      */
@@ -3931,7 +4011,35 @@
 			if (diepint.b.nak) {
 				DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",
 					    epnum);
-				handle_in_ep_nak_intr(pcd, epnum);
+				if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
+				{
+					depctl_data_t depctl;
+					if (ep->dwc_ep.frame_num == 0xFFFFFFFF) 
+					{
+						ep->dwc_ep.frame_num = core_if->frame_num;
+						if (ep->dwc_ep.bInterval > 1) 
+						{
+							depctl.d32 = 0;
+							depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
+							if (ep->dwc_ep.frame_num & 0x1) {
+								depctl.b.setd1pid = 1;
+								depctl.b.setd0pid = 0;
+							} else {
+								depctl.b.setd0pid = 1;
+								depctl.b.setd1pid = 0;
+							}
+							DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32);
+						}
+						start_next_request(ep);
+					}
+					ep->dwc_ep.frame_num += ep->dwc_ep.bInterval;
+					if (dwc_ep->frame_num > 0x3FFF)
+					{
+						dwc_ep->frm_overrun = 1;
+						dwc_ep->frame_num &= 0x3FFF;
+					} else 
+						dwc_ep->frm_overrun = 0;
+				}
 
 				CLEAR_IN_EP_INTR(core_if, epnum, nak);
 			}
@@ -4079,7 +4187,34 @@
 						complete_ep(ep);
 					}
 				}
-				
+				if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
+				{
+					dctl_data_t dctl;
+					gintmsk_data_t intr_mask = {.d32 = 0};
+					dwc_otg_pcd_request_t *req = 0;
+
+					dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
+						dev_global_regs->dctl);
+					dctl.b.cgoutnak = 1;
+					DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
+						dctl.d32);
+
+					intr_mask.d32 = 0;
+					intr_mask.b.incomplisoout = 1;	   
+
+					/* Get any pending requests */
+					if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
+						req = DWC_CIRCLEQ_FIRST(&ep->queue);
+						if (!req) {
+							DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
+						} else {
+							dwc_otg_request_done(ep, req, 0);
+							start_next_request(ep);
+						}
+					} else {
+						DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
+					}
+				}
 			}
 			/* AHB Error */
 			if (doepint.b.ahberr) {
@@ -4134,6 +4269,37 @@
 
 				CLEAR_OUT_EP_INTR(core_if, epnum, babble);
 			}
+			if (doepint.b.outtknepdis)
+			{
+				DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \
+					disabled\n",epnum);
+				if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
+				{
+					doepmsk_data_t doepmsk = {.d32 = 0};
+					ep->dwc_ep.frame_num = core_if->frame_num;
+					if (ep->dwc_ep.bInterval > 1) 
+					{
+						depctl_data_t depctl;
+						depctl.d32 = DWC_READ_REG32(&core_if->dev_if->
+													out_ep_regs[epnum]->doepctl);
+						if (ep->dwc_ep.frame_num & 0x1) {
+							depctl.b.setd1pid = 1;
+							depctl.b.setd0pid = 0;
+						} else {
+							depctl.b.setd0pid = 1;
+							depctl.b.setd1pid = 0;
+						}
+						DWC_WRITE_REG32(&core_if->dev_if->
+										out_ep_regs[epnum]->doepctl, depctl.d32);
+					}
+					start_next_request(ep);
+					doepmsk.b.outtknepdis = 1;
+					DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 
+								 doepmsk.d32, 0);
+				}
+				CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);
+			}
+			
 			/* NAK Interrutp */
 			if (doepint.b.nak) {
 				DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);
@@ -4158,7 +4324,15 @@
 
 #undef CLEAR_OUT_EP_INTR
 }
-
+static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun)
+{
+	int retval = 0;
+	if(!frm_overrun && curr_fr >= trgt_fr) 
+		retval = 1;
+	else if (frm_overrun && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF/2)))
+		retval = 1;
+	return retval;
+}
 /**
  * Incomplete ISO IN Transfer Interrupt.
  * This interrupt indicates one of the following conditions occurred
@@ -4227,13 +4401,34 @@
 	}
 
 #else
-	gintmsk_data_t intr_mask = {.d32 = 0 };
-	DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
-		   "IN ISOC Incomplete");
+	depctl_data_t depctl = {.d32 = 0 };
+	dwc_ep_t *dwc_ep;
+	dwc_otg_dev_if_t *dev_if;
+	int i;
+	dev_if = GET_CORE_IF(pcd)->dev_if;
 
-	intr_mask.b.incomplisoin = 1;
+	DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n");
+	
+	for (i = 1; i <= dev_if->num_in_eps; ++i) {
+		dwc_ep = &pcd->in_ep[i-1].dwc_ep;
+		depctl.d32 =
+			DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
+		if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
+			if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num, 
+							dwc_ep->frm_overrun))
+			{
+				depctl.d32 =
+					DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
+				depctl.b.snak = 1;
+				depctl.b.epdis = 1;
+				DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32);
+			}
+		}
+	}
+
+	/*intr_mask.b.incomplisoin = 1;
 	DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
-			 intr_mask.d32, 0);
+			 intr_mask.d32, 0);	 */
 #endif				//DWC_EN_ISOC
 
 	/* Clear interrupt */
@@ -4320,14 +4515,49 @@
 #else
 	/** @todo implement ISR */
 	gintmsk_data_t intr_mask = {.d32 = 0 };
+	dwc_otg_core_if_t *core_if;
+	deptsiz_data_t deptsiz = {.d32 = 0 };
+	depctl_data_t depctl = {.d32 = 0 };
+	dctl_data_t dctl = {.d32 = 0 };
+	dwc_ep_t *dwc_ep = NULL;
+	int i;
+	core_if = GET_CORE_IF(pcd);
 
-	DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
-		   "OUT ISOC Incomplete");
+	for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
+		dwc_ep = &pcd->out_ep[i].dwc_ep;
+		depctl.d32 =
+			DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
+		if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) {
+			core_if->dev_if->isoc_ep = dwc_ep;	
+			deptsiz.d32 =
+					DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz);
+				break;
+		}
+	}
+	dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
+	gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
+	intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
 
+	if (!intr_mask.b.goutnakeff) {
+		/* Unmask it */
+		intr_mask.b.goutnakeff = 1;
+		DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32);
+ 	}
+	if (!gintsts.b.goutnakeff) {
+		dctl.b.sgoutnak = 1;
+	}
+	DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
+
+	depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
+	if (depctl.b.epena) {
+		depctl.b.epdis = 1;
+		depctl.b.snak = 1;
+	}
+	DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32);
+
+	intr_mask.d32 = 0;
 	intr_mask.b.incomplisoout = 1;
-	DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
-			 intr_mask.d32, 0);
-
+		
 #endif /* DWC_EN_ISOC */
 
 	/* Clear interrupt */
@@ -4357,7 +4587,7 @@
 	/* Disable all active IN EPs */
 	for (i = 0; i <= dev_if->num_in_eps; i++) {
 		diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
-		if (!(diepctl.b.eptype & 1) && diepctl.b.epena) {	// NP IN enabled EP's only
+		if (!(diepctl.b.eptype & 1) && diepctl.b.epena) {
 			if (core_if->start_predict > 0)
 				core_if->start_predict++;
 			diepctl.b.epdis = 1;
@@ -4406,9 +4636,19 @@
 		for (i = 0; i <= dev_if->num_out_eps; i++) {
 			if ( pcd->core_if->ep_xfer_info[i].state == 2 )
 				break;
-		} 		
+		}
+		if (i > dev_if->num_out_eps) {
+			dctl_data_t dctl;
+			dctl.d32 = DWC_READ_REG32(&dev_if->
+				dev_global_regs->dctl);
+			dctl.b.cgoutnak = 1;
+			DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl,
+				dctl.d32);
+			goto out;
+		}
+
 		/* Disable the endpoint */
-		doepctl.d32 = DWC_READ_REG32(&pcd->core_if->dev_if->
+		doepctl.d32 = DWC_READ_REG32(&dev_if->
 										out_ep_regs[i]->doepctl);
 		if (doepctl.b.epena) {
 			doepctl.b.epdis = 1;
@@ -4417,10 +4657,27 @@
 		DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
 		return 1;
 	}
+	/* We come here from Incomplete ISO OUT handler */
+	if(dev_if->isoc_ep)
+	{
+		dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep;
+		uint32_t epnum = dwc_ep->num;
+		doepint_data_t doepint;
+		doepint.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint);
+		dev_if->isoc_ep = NULL;
+		doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl);
+		DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32);
+		if (doepctl.b.epena) {
+			doepctl.b.epdis = 1;
+			doepctl.b.snak = 1;
+		}
+		DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl, doepctl.d32);
+		return 1;
+	} else
+		DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
+			   "Global OUT NAK Effective\n");
 	
-	DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
-		   "Global IN NAK Effective\n");
-	
+out:
 	/* Clear interrupt */
 	gintsts.d32 = 0;
 	gintsts.b.goutnakeff = 1;
@@ -4538,7 +4795,7 @@
 			    dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
 		}
 
-		/* In MPI mode De vice Endpoints intterrupts are asserted
+		/* In MPI mode Device Endpoints interrupts are asserted
 		 * without setting outepintr and inepint bits set, so these
 		 * Interrupt handlers are called without checking these bit-fields
 		 */
diff --git a/drivers/usb/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/dwc_otg/dwc_otg_pcd_linux.c
old mode 100644
new mode 100755
index f403f58..387d725
--- a/drivers/usb/dwc_otg/dwc_otg_pcd_linux.c
+++ b/drivers/usb/dwc_otg/dwc_otg_pcd_linux.c
@@ -1,8 +1,8 @@
  /* ==========================================================================
   * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
-  * $Revision: #17 $
-  * $Date: 2011/05/17 $
-  * $Change: 1774110 $
+  * $Revision: #19 $
+  * $Date: 2011/10/26 $
+  * $Change: 1873028 $
   *
   * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
   * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -361,7 +361,7 @@
 	if (GET_CORE_IF(pcd)->dma_enable) {
 		struct pci_dev *dev = gadget_wrapper->pcd->otg_dev->os_dep.pcidev;
 		if (usb_req->length != 0 && usb_req->dma == DWC_DMA_ADDR_INVALID) {
-			dma_addr = pci_map_single(dev, usb_req->buf, usb_req->length, 
+			dma_addr = pci_map_single(dev, usb_req->buf, usb_req->length,
 					ep->dwc_ep.is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
 		}
 	}
@@ -1143,10 +1143,9 @@
 	struct lm_device *_dev
 #elif  defined(PCI_INTERFACE)
 	struct pci_dev *_dev
-#else 
+#else
 	struct platform_device *_dev
 #endif
-
     )
 {
 #ifdef LM_INTERFACE
@@ -1229,8 +1228,14 @@
  * then a host may connect again, or the driver might get unbound.
  *
  * @param driver The driver being registered
+ * @param bind The bind function of gadget driver
  */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
 int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+#else
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
+#endif
 {
 	int retval;
 
@@ -1238,7 +1243,11 @@
 		    driver->driver.name);
 
 	if (!driver || driver->speed == USB_SPEED_UNKNOWN ||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
 	    !driver->bind ||
+#else
+		!bind ||
+#endif
 	    !driver->unbind || !driver->disconnect || !driver->setup) {
 		DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
 		return -EINVAL;
@@ -1257,7 +1266,11 @@
 	gadget_wrapper->gadget.dev.driver = &driver->driver;
 
 	DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
 	retval = driver->bind(&gadget_wrapper->gadget);
+#else
+	retval = bind(&gadget_wrapper->gadget);
+#endif
 	if (retval) {
 		DWC_ERROR("bind to driver %s --> error %d\n",
 			  driver->driver.name, retval);
@@ -1269,8 +1282,11 @@
 		    driver->driver.name);
 	return 0;
 }
-
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
 EXPORT_SYMBOL(usb_gadget_register_driver);
+#else
+EXPORT_SYMBOL(usb_gadget_probe_driver);
+#endif
 
 /**
  * This function unregisters a gadget driver
diff --git a/drivers/usb/dwc_otg/dwc_otg_regs.h b/drivers/usb/dwc_otg/dwc_otg_regs.h
old mode 100644
new mode 100755
index 83298a1..8dc648b
--- a/drivers/usb/dwc_otg/dwc_otg_regs.h
+++ b/drivers/usb/dwc_otg/dwc_otg_regs.h
@@ -1,8 +1,8 @@
 /* ==========================================================================
  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
- * $Revision: #93 $
- * $Date: 2011/05/17 $
- * $Change: 1774110 $
+ * $Revision: #97 $
+ * $Date: 2011/10/24 $
+ * $Change: 1871160 $
  *
  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
@@ -254,7 +254,8 @@
 		unsigned reserved9_20:12;
 		unsigned remmemsupp:1;
 		unsigned notialldmawrit:1;
-		unsigned reserved23_31:9;
+		unsigned ahbsingle:1;
+		unsigned reserved24_31:8;
 	} b;
 } gahbcfg_data_t;
 
@@ -565,8 +566,8 @@
 
 /**
  * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
- * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element then
- * read out the bits using the <i>b</i>it elements.
+ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element 
+ * then read out the bits using the <i>b</i>it elements.
  */
 typedef union fifosize_data {
 	/** raw register data */
@@ -984,8 +985,8 @@
 		 *  2'b11  -  Reserved
 		 */
 		unsigned prb_per:2;
-		/** These bits capture the latest time it took for VBUS to ramp from VADP_SINK
-		 *  to VADP_PRB.  The bits are defined in units of 32 kHz clock cycles as follows:
+		/** These bits capture the latest time it took for VBUS to ramp from 
+		 *  VADP_SINK to VADP_PRB. 
 		 *  0x000  -  1 cycles
 		 *  0x001  -  2 cycles
 		 *  0x002  -  3 cycles
@@ -1195,7 +1196,6 @@
 		unsigned sgoutnak:1;
 		/** Clear Global OUT NAK */
 		unsigned cgoutnak:1;
-
 		/** Power-On Programming Done */
 		unsigned pwronprgdone:1;
 		/** Reserved */
@@ -1206,8 +1206,10 @@
 		unsigned ifrmnum:1;
 		/** NAK on Babble */
 		unsigned nakonbble:1;
+		/** Enable Continue on BNA */
+		unsigned encontonbna:1;
 
-		unsigned reserved17_31:15;
+		unsigned reserved18_31:14;
 	} b;
 } dctl_data_t;
 
@@ -1496,9 +1498,8 @@
 	/** Device OUT Endpoint Control Register. <i>Offset:B00h +
 	 * (ep_num * 20h) + 00h</i> */
 	volatile uint32_t doepctl;
-	/** Device OUT Endpoint Frame number Register.	<i>Offset:
-	 * B00h + (ep_num * 20h) + 04h</i> */
-	volatile uint32_t doepfn;
+	/** Reserved. <i>Offset:B00h + (ep_num * 20h) + 04h</i> */
+	uint32_t reserved04;
 	/** Device OUT Endpoint Interrupt Register. <i>Offset:B00h +
 	 * (ep_num * 20h) + 08h</i> */
 	volatile uint32_t doepint;
@@ -1628,6 +1629,8 @@
 	struct {
 		/** Transfer size */
 		unsigned xfersize:19;
+/** Max packet count for EP (pow(2,10)-1) */
+#define MAX_PKT_CNT 1023
 		/** Packet Count */
 		unsigned pktcnt:10;
 		/** Multi Count - Periodic IN endpoints */
@@ -1691,8 +1694,9 @@
 	struct {
 		/** Received number of bytes */
 		unsigned bytes:16;
-
-		unsigned reserved16_22:7;
+		/** NAK bit - only for OUT EPs */
+		unsigned nak:1;
+		unsigned reserved17_22:6;
 		/** Multiple Transfer - only for OUT EPs */
 		unsigned mtrf:1;
 		/** Setup Packet received - only for OUT EPs */
@@ -1834,6 +1838,8 @@
 
 	/** Setup Packet Detected - if set clear NAK when queueing */
 	uint32_t spd;
+	/** Isoc ep pointer on which incomplete happens */
+	void *isoc_ep;
 
 } dwc_otg_dev_if_t;
 
@@ -2456,9 +2462,9 @@
 } pcgcctl_data_t;
 
 /**
- * This union represents the bit fields in the Global Data FIFO Software Configuration Register.
- * Read the register into the <i>d32</i> member then set/clear the
- * bits using the <i>b</i>it elements.
+ * This union represents the bit fields in the Global Data FIFO Software
+ * Configuration Register. Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
  */
 typedef union gdfifocfg_data {
 	/* raw register data */
diff --git a/drivers/usb/dwc_otg/linux/dwc_otg_plat.h b/drivers/usb/dwc_otg/linux/dwc_otg_plat.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/dwc_otg/usb.h b/drivers/usb/dwc_otg/usb.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
old mode 100644
new mode 100755
diff --git a/drivers/usb/host/xhci-comcerto2000.c b/drivers/usb/host/xhci-comcerto2000.c
old mode 100644
new mode 100755
index 08078a2..ec765f0
--- a/drivers/usb/host/xhci-comcerto2000.c
+++ b/drivers/usb/host/xhci-comcerto2000.c
@@ -10,13 +10,11 @@
 #include <linux/slab.h>
 #include "xhci.h"
 
-#include <mach/comcerto-2000.h>
-#include <mach/comcerto-2000/clk-rst.h>
 #include <linux/clk.h>
 #include <mach/reset.h>
+#include <mach/hardware.h>
 
 extern int usb3_clk_internal;
-
 /* USB 3.0 clock */
 static struct clk *usb3_clk;
 
@@ -107,20 +105,27 @@
 
 static void comcerto_usb3_phy_init(void)
 {
+	u32 val;
+
         writel(0x00E00080, USB3_PHY_BASE + 0x10);
 
 	//Configuration for internal clock
 	if(usb3_clk_internal)
 	{
-		writel(0x420E82A9, USB3_PHY_BASE + 0x20);
 		printk(KERN_INFO "USB3.0 clock selected: internal\n", __func__);
+
+		if(HAL_get_ref_clk() == REF_CLK_24MHZ)
+			val = 0x420E82A8;
+		else
+			val = 0x420E82A9;
 	}
 	else
 	{
-		writel(0x4209927A, USB3_PHY_BASE + 0x20);
+		val = 0x4209927A;
 		printk(KERN_INFO "USB3.0 clock selected: external\n", __func__);
 	}
 
+	writel(val, USB3_PHY_BASE + 0x20);
         writel(0x69C34F53, USB3_PHY_BASE + 0x24);
         writel(0x0005D815, USB3_PHY_BASE + 0x28);
         writel(0x00000801, USB3_PHY_BASE + 0x2C);
diff --git a/drivers/usb/host/xhci-comcerto2000.h b/drivers/usb/host/xhci-comcerto2000.h
old mode 100644
new mode 100755
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
old mode 100644
new mode 100755
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 79fd606..ad7818a 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -343,6 +343,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called imx2_wdt.
 
+config COMCERTO_WATCHDOG
+	tristate "Comcerto Watchdog"
+	depends on ARCH_COMCERTO
+	help
+	  Say Y here if to include support for the watchdog timer in
+	  Comcerto device.
+
+	  This driver can be built as a module by choosing M.
+	  The module will be called comcerto_wdt
+
+
 # AVR32 Architecture
 
 config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index fe893e9..0ffbb99 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -53,6 +53,7 @@
 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
 obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
 obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
+obj-$(CONFIG_COMCERTO_WATCHDOG) += comcerto_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/comcerto_wdt.c b/drivers/watchdog/comcerto_wdt.c
new file mode 100644
index 0000000..d89aeb2
--- /dev/null
+++ b/drivers/watchdog/comcerto_wdt.c
@@ -0,0 +1,406 @@
+/*
+ *  drivers/char/watchdog/comcerto_wdt.c
+ *
+ *  Copyright (C) 2004,2005,2013 Mindspeed Technologies, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <linux/clk.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/wdt.h>
+#include <mach/reset.h>
+
+#define WDT_NAME					"comcerto_wdt"
+#define WDT_DEFAULT_TIMEOUT				5
+#define WDT_MAX_TIMEOUT					(0xffffffff / COMCERTO_AHBCLK)
+
+static unsigned long COMCERTO_AHBCLK;
+static int wd_heartbeat = WDT_DEFAULT_TIMEOUT;
+static int nowayout = WATCHDOG_NOWAYOUT;
+static struct clk *clk_axi;
+
+module_param(wd_heartbeat, int, 0);
+MODULE_PARM_DESC(wd_heartbeat, "Watchdog heartbeat in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIMEOUT) ")");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+#endif
+
+static unsigned long comcerto_wdt_busy;
+static char expect_close;
+static spinlock_t wdt_lock;
+
+/*
+ * Inform whether the boot was caused by AXI watchdog or not.
+ * If the boot was caused by AXI WDT, the WD status is cleared from
+ * reset control register.
+ */
+static int comcerto_wdt_rst_status(void)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&wdt_lock, flags);
+
+	if(__raw_readl(GNRL_DEVICE_STATUS) & AXI_WD_RST_ACTIVATED) {
+		__raw_writel(WD_STATUS_CLR | __raw_readl(DEVICE_RST_CNTRL), DEVICE_RST_CNTRL);
+		ret = 1;
+	}
+
+	spin_unlock_irqrestore(&wdt_lock, flags);
+
+	return ret;
+}
+
+/*
+ * Set a new heartbeat value for the watchdog device. If the heartbeat value is
+ * incorrect we keep the old value and return -EINVAL. If successfull we return 0.
+ */
+static int comcerto_wdt_set_heartbeat(int t)
+{
+	if (t < 1 || t > WDT_MAX_TIMEOUT)
+		return -EINVAL;
+
+	wd_heartbeat = t;
+	return 0;
+}
+
+/*
+ * Write wd_heartbeat to high bound register.
+ */
+static void comcerto_wdt_set_timeout(void)
+{
+	__raw_writel(wd_heartbeat * COMCERTO_AHBCLK, COMCERTO_TIMER_WDT_HIGH_BOUND);
+}
+
+/*
+ * Disable the watchdog.
+ */
+static void comcerto_wdt_stop(void)
+{
+	unsigned long flags;
+	u32 wdt_control;
+
+	spin_lock_irqsave(&wdt_lock, flags);
+
+	wdt_control = __raw_readl(COMCERTO_TIMER_WDT_CONTROL);
+
+	__raw_writel(wdt_control & ~COMCERTO_TIMER_WDT_CONTROL_TIMER_ENABLE, COMCERTO_TIMER_WDT_CONTROL);
+
+	spin_unlock_irqrestore(&wdt_lock, flags);
+
+	comcerto_wdt_set_timeout();
+}
+
+/*
+ * Enable the watchdog.
+ */
+static void comcerto_wdt_start(void)
+{
+	unsigned long flags;
+	u32 wdt_control;
+
+	spin_lock_irqsave(&wdt_lock, flags);
+
+	wdt_control = __raw_readl(COMCERTO_TIMER_WDT_CONTROL);
+
+	__raw_writel(wdt_control | COMCERTO_TIMER_WDT_CONTROL_TIMER_ENABLE, COMCERTO_TIMER_WDT_CONTROL);
+
+	comcerto_rst_cntrl_set(AXI_WD_RST_EN);
+
+	spin_unlock_irqrestore(&wdt_lock, flags);
+}
+
+/*
+ * Disable WDT and:
+ * - set max. possible timeout to avoid reset, it can occur
+ * since current counter value could be bigger then
+ * high bound one at the moment
+ * Function is called once at start (while configuration),
+ * and it's safe not to disable/enable IRQs.
+ */
+static void comcerto_wdt_config(void)
+{
+	comcerto_wdt_stop();
+
+	__raw_writel(~0, COMCERTO_TIMER_WDT_HIGH_BOUND);			/* write max timout */
+}
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int comcerto_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(0, &comcerto_wdt_busy))
+		return -EBUSY;
+
+	comcerto_wdt_set_timeout();
+	comcerto_wdt_start();
+
+	return nonseekable_open(inode, file);
+}
+
+/*
+ * Release the watchdog device.
+ * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined and expect_close == 42
+ * i.e. magic char 'V' has been passed while write() then the watchdog
+ * is also disabled.
+ */
+static int comcerto_wdt_release(struct inode *inode, struct file *file)
+{
+	if (expect_close == 42) {
+		comcerto_wdt_stop();	/* disable the watchdog when file is closed */
+		clear_bit(0, &comcerto_wdt_busy);
+	} else {
+		printk(KERN_CRIT "%s: closed unexpectedly. WDT will not stop!\n", WDT_NAME);
+	}
+
+	expect_close = 0;
+	return 0;
+}
+
+/*
+ * Handle commands from user-space.
+ */
+static long comcerto_wdt_ioctl(struct file *file, uint cmd, ulong arg)
+{
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	int new_value;
+	int err;
+	static struct watchdog_info comcerto_wdt_info = {
+		.options = 	WDIOF_SETTIMEOUT |
+				WDIOF_MAGICCLOSE |
+				WDIOF_KEEPALIVEPING,
+		.firmware_version = 1,
+	};
+
+	switch(cmd) {
+	case WDIOC_KEEPALIVE:
+		comcerto_wdt_set_timeout();
+		break;
+
+	case WDIOC_GETSUPPORT:
+		strncpy(comcerto_wdt_info.identity, WDT_NAME, sizeof(comcerto_wdt_info.identity));
+		if (copy_to_user(argp, &comcerto_wdt_info, sizeof(comcerto_wdt_info)) != 0) {
+			err = -EFAULT;
+			goto err;
+		}
+		break;
+
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_value, p)) {
+			err = -EFAULT;
+			goto err;
+		}
+
+		if (comcerto_wdt_set_heartbeat(new_value)) {
+			err = -EINVAL;
+			goto err;
+		}
+
+		comcerto_wdt_set_timeout();
+
+		return put_user(wd_heartbeat, p);
+		break;
+
+	case WDIOC_GETTIMEOUT:
+		return put_user(wd_heartbeat, p);
+		break;
+
+	case WDIOC_GETSTATUS:
+		return put_user(0, p);
+		break;
+
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(comcerto_wdt_rst_status(), p);
+		break;
+
+	case WDIOC_SETOPTIONS:
+		if (get_user(new_value, p)) {
+			err = -EFAULT;
+			goto err;
+		}
+
+		if (new_value & WDIOS_DISABLECARD)
+			comcerto_wdt_stop();
+
+		if (new_value & WDIOS_ENABLECARD)
+			comcerto_wdt_start();
+
+		break;
+
+	default:
+		err = -ENOIOCTLCMD;
+		goto err;
+		break;
+	}
+
+	return 0;
+
+err:
+	return err;
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t comcerto_wdt_write(struct file *file, const char *buf, size_t len, loff_t *ppos)
+{
+	if (len) {
+		if (!nowayout) {
+			size_t i;
+			char c;
+
+			/* in case it was set long ago */
+			expect_close = 0;
+
+			for (i = 0; i != len; i++) {
+				if (get_user(c, buf + i))
+					return -EFAULT;
+
+				if (c == 'V')
+					expect_close = 42;
+			}
+		}
+
+		comcerto_wdt_set_timeout();
+	}
+
+	return len;
+}
+
+static const struct file_operations comcerto_wdt_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.unlocked_ioctl	= comcerto_wdt_ioctl,
+	.open		= comcerto_wdt_open,
+	.release	= comcerto_wdt_release,
+	.write		= comcerto_wdt_write,
+};
+
+static struct miscdevice comcerto_wdt_miscdev = {
+	.minor		= WATCHDOG_MINOR,
+	.name		= WDT_NAME,
+	.fops		= &comcerto_wdt_fops,
+};
+
+static int __init comcerto_wdt_probe(struct platform_device *pdev)
+{
+	int res;
+
+	if (comcerto_wdt_miscdev.parent)
+		return -EBUSY;
+
+	clk_axi = clk_get(NULL, "axi");
+
+	if (IS_ERR(clk_axi)){
+		pr_err("%s: Unable to obtain axi clock: %ld\n",__func__,PTR_ERR(clk_axi));
+		/* System cannot proceed from here */
+		BUG();
+	}
+
+	res = clk_enable(clk_axi);
+	if (res){
+		pr_err("%s: axi clock failed to enable:\n", __func__);
+		goto err_clk;
+	}
+
+	COMCERTO_AHBCLK = clk_get_rate(clk_axi);
+
+	comcerto_wdt_miscdev.parent = &pdev->dev;
+	comcerto_wdt_config();
+
+	res = misc_register(&comcerto_wdt_miscdev);
+	if (res)
+		goto err_misc;
+
+	printk(KERN_INFO "%s: support registered\n", WDT_NAME);
+
+        /* check that the heartbeat value is within range; if not reset to the default */
+        if (comcerto_wdt_set_heartbeat(wd_heartbeat)) {
+                comcerto_wdt_set_heartbeat(WDT_DEFAULT_TIMEOUT);
+
+                printk(KERN_INFO "%s: wd_heartbeat value is out of range: 1..%lu, using %d\n",
+                        WDT_NAME, WDT_MAX_TIMEOUT, WDT_DEFAULT_TIMEOUT);
+        }
+
+	return 0;
+
+err_misc:
+	clk_disable(clk_axi);
+err_clk:
+	clk_put(clk_axi);
+
+	return res;
+}
+
+static int __exit comcerto_wdt_remove(struct platform_device *pdev)
+{
+	int res;
+
+
+	clk_disable(clk_axi);
+	clk_put(clk_axi);
+	res = misc_deregister(&comcerto_wdt_miscdev);
+	if (!res)
+		comcerto_wdt_miscdev.parent = NULL;
+
+	return res;
+}
+
+static struct platform_driver comcerto_wdt_driver = {
+	.probe		= comcerto_wdt_probe,
+	.remove		= __exit_p(comcerto_wdt_remove),
+	.driver		= {
+		.name	= WDT_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init comcerto_wdt_init(void)
+{
+        spin_lock_init(&wdt_lock);
+
+	return platform_driver_register(&comcerto_wdt_driver);
+}
+
+static void __exit comcerto_wdt_exit(void)
+{
+	platform_driver_unregister(&comcerto_wdt_driver);
+}
+
+module_init(comcerto_wdt_init);
+module_exit(comcerto_wdt_exit);
+
+MODULE_AUTHOR("Mindspeed Technologies, Inc.");
+MODULE_DESCRIPTION("Watchdog driver for Comcerto 2000 devices");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/fs/splice.c b/fs/splice.c
index ed194f0..f8899bd 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -336,7 +336,11 @@
 	/*
 	 * Lookup the (hopefully) full range of pages we need.
 	 */
+#ifdef CONFIG_COMCERTO_SPLICE_READ_NOCONTIG
+	spd.nr_pages = find_get_pages(mapping, index, nr_pages, spd.pages);
+#else
 	spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, spd.pages);
+#endif
 	index += spd.nr_pages;
 
 	/*
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index b1038bd..a165ab8 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -108,6 +108,10 @@
 	struct dentry *debug_dir;
 	struct dentry *debug_stats;
 #endif
+
+#ifdef CONFIG_ARCH_M86XXX
+	unsigned int cpu0_bind;
+#endif
 };
 
 int bdi_init(struct backing_dev_info *bdi);
diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
index 16b92d0..9453ec2 100644
--- a/include/linux/if_tunnel.h
+++ b/include/linux/if_tunnel.h
@@ -21,6 +21,10 @@
 #define SIOCADD6RD      (SIOCDEVPRIVATE + 9)
 #define SIOCDEL6RD      (SIOCDEVPRIVATE + 10)
 #define SIOCCHG6RD      (SIOCDEVPRIVATE + 11)
+#define SIOCGET4RD      (SIOCDEVPRIVATE + 12)  
+#define SIOCADD4RD      (SIOCDEVPRIVATE + 13) 
+#define SIOCDEL4RD      (SIOCDEVPRIVATE + 14)
+#define SIOCCHG4RD      (SIOCDEVPRIVATE + 15)
 
 #define GRE_CSUM	__cpu_to_be16(0x8000)
 #define GRE_ROUTING	__cpu_to_be16(0x4000)
@@ -63,6 +67,20 @@
 	__u16			relay_prefixlen;
 };
 
+/* ip6 tnl 4rd parm -start  */ 
+struct ip6_tnl_4rd {
+       __be32                  prefix;
+       struct in6_addr         relay_prefix;
+       struct in6_addr         relay_suffix;
+       __u16                   prefixlen;
+       __u16                   relay_prefixlen;
+       __u16                   relay_suffixlen;
+       __u16                   psid_offsetlen;
+       __u16                   eabit_len;
+       __u16                   entry_num;
+};
+/* ip6 tnl 4rd parm -end  */ 
+
 enum {
 	IFLA_GRE_UNSPEC,
 	IFLA_GRE_LINK,
diff --git a/include/linux/ip6_tunnel.h b/include/linux/ip6_tunnel.h
index 5970daf9..554e24e 100644
--- a/include/linux/ip6_tunnel.h
+++ b/include/linux/ip6_tunnel.h
@@ -32,4 +32,50 @@
 };
 
 
+struct ip6_4rd_map_msg {
+       __u32 reset;
+       __u32 ifindex;
+       __be32 prefix;
+       __u16 prefixlen;
+       struct in6_addr relay_prefix;
+       struct in6_addr relay_suffix;
+       __u16 relay_prefixlen;
+       __u16 relay_suffixlen;
+       __u16 psid_offsetlen;
+       __u16 eabit_len;
+       __u16 entry_num;
+};
+
+struct ip6_tnl_4rd_map_rule {
+       __be32 prefix;
+       __u16 prefixlen;
+       struct in6_addr relay_prefix;
+       struct in6_addr relay_suffix;
+       __u16 relay_prefixlen;
+       __u16 relay_suffixlen;
+       __u16 psid_offsetlen;
+       __u16 eabit_len;
+       __u16 entry_num;
+       struct list_head mr_list;
+};
+
+#ifdef __KERNEL__
+struct ip6_tnl_4rd_parm {
+       __be32 prefix;
+       struct in6_addr relay_prefix;
+       struct in6_addr relay_suffix;
+       __u16 prefixlen;
+       __u16 relay_prefixlen;
+       __u16 relay_suffixlen;
+       __be32 laddr4;
+       __u16 port_set_id;
+       __u16 port_set_id_len;
+       __u16 psid_offsetlen;
+       __u16 eabit_len;
+
+       struct list_head map_list;
+       rwlock_t map_lock;
+};
+#endif
+
 #endif
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ae451f8..3fa93b1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2048,6 +2048,9 @@
 extern int		netif_rx(struct sk_buff *skb);
 extern int		netif_rx_ni(struct sk_buff *skb);
 extern int		netif_receive_skb(struct sk_buff *skb);
+#if defined(CONFIG_ARCH_COMCERTO)
+extern int              capture_receive_skb(struct sk_buff *skb);
+#endif
 extern gro_result_t	dev_gro_receive(struct napi_struct *napi,
 					struct sk_buff *skb);
 extern gro_result_t	napi_skb_finish(gro_result_t ret, struct sk_buff *skb);
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index a1b410c..e91c119 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -45,6 +45,7 @@
 header-y += xt_helper.h
 header-y += xt_iprange.h
 header-y += xt_ipvs.h
+header-y += xt_layer7.h
 header-y += xt_length.h
 header-y += xt_limit.h
 header-y += xt_mac.h
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index eaeea3f..3ca1f46 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -88,9 +88,11 @@
 	IPS_PERMANENT_BIT = 13,
 	IPS_PERMANENT = (1 << IPS_PERMANENT_BIT),
 
+#ifdef CONFIG_COMCERTO_FP
 	/* Connection is assured by DPI application */
 	IPS_DPI_ALLOWED_BIT = 14,
 	IPS_DPI_ALLOWED = (1 << IPS_DPI_ALLOWED_BIT),
+#endif
 };
 
 /* Connection tracking event types */
diff --git a/include/linux/netfilter_ipv4/nf_nat.h b/include/linux/netfilter_ipv4/nf_nat.h
index 7a861d0..a7275b3 100644
--- a/include/linux/netfilter_ipv4/nf_nat.h
+++ b/include/linux/netfilter_ipv4/nf_nat.h
@@ -7,6 +7,7 @@
 #define IP_NAT_RANGE_PROTO_SPECIFIED 2
 #define IP_NAT_RANGE_PROTO_RANDOM 4
 #define IP_NAT_RANGE_PERSISTENT 8
+#define IP_NAT_RANGE_4RD_NAPT 16
 
 /* The protocol-specific manipulable parts of the tuple. */
 union nf_conntrack_man_proto {
diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild
index bd095bc..b88c005 100644
--- a/include/linux/netfilter_ipv6/Kbuild
+++ b/include/linux/netfilter_ipv6/Kbuild
@@ -1,6 +1,7 @@
 header-y += ip6_tables.h
 header-y += ip6t_HL.h
 header-y += ip6t_LOG.h
+header-y += ip6t_NPT.h
 header-y += ip6t_REJECT.h
 header-y += ip6t_ah.h
 header-y += ip6t_frag.h
diff --git a/include/linux/netfilter_ipv6/ip6t_NPT.h b/include/linux/netfilter_ipv6/ip6t_NPT.h
new file mode 100755
index 0000000..f763355
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_NPT.h
@@ -0,0 +1,16 @@
+#ifndef __NETFILTER_IP6T_NPT
+#define __NETFILTER_IP6T_NPT
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+
+struct ip6t_npt_tginfo {
+	union nf_inet_addr	src_pfx;
+	union nf_inet_addr	dst_pfx;
+	__u8			src_pfx_len;
+	__u8			dst_pfx_len;
+	/* Used internally by the kernel */
+	__sum16			adjustment;
+};
+
+#endif /* __NETFILTER_IP6T_NPT */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 511fd43..80a0e22 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -119,7 +119,12 @@
 #define RTM_GETDCB RTM_GETDCB
 	RTM_SETDCB,
 #define RTM_SETDCB RTM_SETDCB
-
+       RTM_NEW4RD = 80,
+#define RTM_NEW4RD      RTM_NEW4RD
+       RTM_DEL4RD,
+#define RTM_DEL4RD      RTM_DEL4RD
+       RTM_GET4RD,
+#define RTM_GET4RD      RTM_GET4RD
 	__RTM_MAX,
 #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
 };
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 170a2f9..96348263 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -471,6 +471,11 @@
 	sk_buff_data_t		end;
 	unsigned char		*head,
 				*data;
+#if defined(CONFIG_COMCERTO_CUSTOM_SKB_LAYOUT)
+	unsigned char 		*mspd_data;
+	__u32 			mspd_len;
+	__u32 			mspd_ofst;
+#endif
 	unsigned int		truesize;
 	atomic_t		users;
 };
diff --git a/include/linux/spi/designware.h b/include/linux/spi/designware.h
new file mode 100644
index 0000000..cc0335b
--- /dev/null
+++ b/include/linux/spi/designware.h
@@ -0,0 +1,15 @@
+/*
+ * designware.h - platform glue for the Synopsys DesignWare SPI controller
+ */
+
+#define        CLK_NAME       10
+#define        TX_FIFO_DEPTH  8
+#define        RX_FIFO_DEPTH  8
+
+struct spi_controller_pdata {
+	int use_dma;
+	int num_chipselects;
+	int bus_num;
+	u32 max_freq;
+	char clk_name[CLK_NAME];
+};
diff --git a/include/linux/spi2/spi.h b/include/linux/spi2/spi.h
old mode 100644
new mode 100755
diff --git a/include/net/ip.h b/include/net/ip.h
index eca0ef7..6616ba5 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -408,6 +408,7 @@
 	IP_DEFRAG_VS_FWD,
 	IP_DEFRAG_AF_PACKET,
 	IP_DEFRAG_MACVLAN,
+	IP_DEFRAG_IP6_TNL_4RD /* Used to support Post Fragmentation for 4o6 tunnels */
 };
 
 int ip_defrag(struct sk_buff *skb, u32 user);
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index 500e449..68205dd 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -22,6 +22,7 @@
 #if defined(CONFIG_INET6_IPSEC_OFFLOAD)
 	u32 genid;
 #endif
+       struct ip6_tnl_4rd_parm ip4rd; /* 4rd parameters for the tunnel */ 
 };
 
 /* Tunnel encapsulation limit destination sub-option */
diff --git a/include/net/udp.h b/include/net/udp.h
index 3b285f4..009c6b0 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -191,6 +191,9 @@
 extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
 			      char __user *optval, unsigned int optlen,
 			      int (*push_pending_frames)(struct sock *));
+extern int 	udp6_lib_setsockopt(struct sock *sk, int level, int optname,
+				   char __user *optval, unsigned int optlen,
+				   int (*push_pending_frames)(struct sock *));
 extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
 				    __be32 daddr, __be16 dport,
 				    int dif);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 017a1cb..add91c3 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1516,6 +1516,10 @@
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
 extern int xfrm6_extract_header(struct sk_buff *skb);
 extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
+/* NAT-T changes Start */
+extern int xfrm6_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
+			   int encap_type);
+/* NAT-T changes End */
 extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
 extern int xfrm6_transport_finish(struct sk_buff *skb, int async);
 extern int xfrm6_rcv(struct sk_buff *skb);
@@ -1534,12 +1538,21 @@
 
 #ifdef CONFIG_XFRM
 extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
+extern int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
 extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen);
 #else
 static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
 {
  	return -ENOPROTOOPT;
 } 
+/* NAT-T changes Start */
+static inline int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	/* should not happen */
+	kfree_skb(skb);
+	return 0;
+}
+/* NAT-T changes End */
 
 static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
 {
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 2b49dd2..0462891 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -225,12 +225,40 @@
 }
 BDI_SHOW(max_ratio, bdi->max_ratio)
 
+#ifdef CONFIG_ARCH_M86XXX
+static ssize_t cpu0_bind_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct backing_dev_info *bdi = dev_get_drvdata(dev);
+	unsigned int flag;
+
+	flag = simple_strtoul(buf, NULL, 10);
+	if (flag)
+		bdi->cpu0_bind = 1;
+	else
+		bdi->cpu0_bind = 0;
+
+	return count;
+}
+
+static ssize_t cpu0_bind_show(struct device *dev,
+			   struct device_attribute *attr, char *page)
+{
+	struct backing_dev_info *bdi = dev_get_drvdata(dev);
+
+	return snprintf(page, PAGE_SIZE-1, "%d\n", bdi->cpu0_bind);
+}
+#endif /* CONFIG_ARCH_M86XXX */
+
 #define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
 
 static struct device_attribute bdi_dev_attrs[] = {
 	__ATTR_RW(read_ahead_kb),
 	__ATTR_RW(min_ratio),
 	__ATTR_RW(max_ratio),
+#ifdef CONFIG_ARCH_M86XXX
+	__ATTR_RW(cpu0_bind),
+#endif
 	__ATTR_NULL,
 };
 
@@ -478,6 +506,10 @@
 				writeback_inodes_wb(&bdi->wb, 1024,
 						    WB_REASON_FORKER_THREAD);
 			} else {
+#ifdef CONFIG_ARCH_M86XXX
+				if (bdi->cpu0_bind)
+					kthread_bind(task, 0);
+#endif
 				/*
 				 * The spinlock makes sure we do not lose
 				 * wake-ups when racing with 'bdi_queue_work()'.
diff --git a/net/core/dev.c b/net/core/dev.c
index 5738654..0308601 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3367,6 +3367,52 @@
 }
 EXPORT_SYMBOL(netif_receive_skb);
 
+#if defined(CONFIG_ARCH_COMCERTO)
+int capture_receive_skb(struct sk_buff *skb)
+{
+        struct net_device *null_or_orig = NULL;
+        struct packet_type *ptype, *pt_prev;
+        struct net_device *orig_dev;
+        int ret = NET_RX_DROP;
+
+	if (!netdev_tstamp_prequeue)
+		net_timestamp_check(skb);
+
+        if (!skb->skb_iif)
+                skb->skb_iif = skb->dev->ifindex;
+
+        skb_reset_network_header(skb);
+        skb_reset_transport_header(skb);
+	skb_reset_mac_len(skb);
+
+        pt_prev = NULL;
+        orig_dev = skb->dev;
+
+        rcu_read_lock();
+        list_for_each_entry_rcu(ptype, &ptype_all, list) {
+                if (!ptype->dev || ptype->dev == skb->dev) {
+                        if (pt_prev)
+                                ret = deliver_skb(skb, pt_prev, orig_dev);
+                        pt_prev = ptype;
+                }
+        }
+
+        if (pt_prev) {
+                ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
+        } else {
+                kfree_skb(skb);
+                /* Jamal, now you will not able to escape explaining
+                 * me how you were going to use this. :-)
+                 */
+                ret = NET_RX_DROP;
+        }
+        rcu_read_unlock();
+        return ret;
+}
+
+EXPORT_SYMBOL(capture_receive_skb);
+#endif
+
 /* Network device is going away, flush any packets still pending
  * Called with irqs disabled.
  */
diff --git a/net/core/flow.c b/net/core/flow.c
index f0eb4f8..9287067 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -39,6 +39,10 @@
 	u32				genid;
 	struct flowi			key;
 	struct flow_cache_object	*object;
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+	u8				flags;
+	#define FLOW_CACHE_FLAG_IPSEC_OFFLOAD 0x01
+#endif
 };
 
 struct flow_cache_percpu {
@@ -75,6 +79,10 @@
 #define flow_cache_hash_size(cache)	(1 << (cache)->hash_shift)
 #define FLOW_HASH_RND_PERIOD		(10 * 60 * HZ)
 
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+extern int ipsec_nlkey_flow_remove(struct flowi *fl, u16 family, u16 dir);
+#endif
+
 static void flow_cache_new_hashrnd(unsigned long arg)
 {
 	struct flow_cache *fc = (void *) arg;
@@ -113,8 +121,14 @@
 	list_splice_tail_init(&flow_cache_gc_list, &gc_list);
 	spin_unlock_bh(&flow_cache_gc_lock);
 
-	list_for_each_entry_safe(fce, n, &gc_list, u.gc_list)
+	list_for_each_entry_safe(fce, n, &gc_list, u.gc_list) {
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+		/*call nl_key_flow_remove*/
+		if (fce->flags & FLOW_CACHE_FLAG_IPSEC_OFFLOAD)
+			ipsec_nlkey_flow_remove(&fce->key, fce->family, fce->dir);
+#endif
 		flow_entry_kill(fce);
+	}
 }
 static DECLARE_WORK(flow_cache_gc_work, flow_cache_gc_task);
 
@@ -298,8 +312,10 @@
 		if (!IS_ERR(flo)) {
 			fle->object = flo;
 #if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
-			if (new_flow)
+			if (new_flow) {
 				*new_flow = 1;
+				fle->flags |= FLOW_CACHE_FLAG_IPSEC_OFFLOAD;
+			}
 #endif
 		}
 		else
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 7aafaed..fba58b8 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1138,6 +1138,10 @@
 						 neigh->parms->reachable_time :
 						 0)));
 		neigh->nud_state = new;
+#ifdef CONFIG_COMCERTO_FP
+		if ((old & (NUD_STALE | NUD_DELAY | NUD_PROBE)) && (new & NUD_REACHABLE))
+			notify = 1;
+#endif
 	}
 
 	if (lladdr != neigh->ha) {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index eba7baa..f2adb20 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -218,6 +218,10 @@
 	skb->mac_header = ~0U;
 #endif
 
+#if defined(CONFIG_COMCERTO_CUSTOM_SKB_LAYOUT)
+	skb->mspd_data = NULL;
+	skb->mspd_len = 0;
+#endif
 	/* make sure we initialize shinfo sequentially */
 	shinfo = skb_shinfo(skb);
 	memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
@@ -303,6 +307,11 @@
 	skb->mac_header = ~0U;
 #endif
 
+#if defined(CONFIG_COMCERTO_CUSTOM_SKB_LAYOUT)
+	skb->mspd_data = NULL;
+	skb->mspd_len = 0;
+#endif
+
 	/* make sure we initialize shinfo sequentially */
 	shinfo = skb_shinfo(skb);
 	memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
@@ -438,6 +447,13 @@
 			skb_drop_fraglist(skb);
 
 		kfree(skb->head);
+
+#if defined(CONFIG_COMCERTO_CUSTOM_SKB_LAYOUT)
+		if (skb->mspd_data) {
+			kfree(skb->mspd_data);
+			skb->mspd_data = NULL;
+		}
+#endif
 	}
 }
 
@@ -579,6 +595,9 @@
 {
 	struct skb_shared_info *shinfo;
 
+#if defined(CONFIG_COMCERTO_CUSTOM_SKB_LAYOUT)
+	WARN_ON(skb->mspd_len);
+#endif
 	skb_release_head_state(skb);
 
 	shinfo = skb_shinfo(skb);
@@ -686,6 +705,12 @@
 	C(truesize);
 	atomic_set(&n->users, 1);
 
+#if defined(CONFIG_COMCERTO_CUSTOM_SKB_LAYOUT)
+	C(mspd_data);
+	C(mspd_len);
+	C(mspd_ofst);
+#endif
+
 	atomic_inc(&(skb_shinfo(skb)->dataref));
 	skb->cloned = 1;
 
@@ -859,6 +884,9 @@
 	unsigned int size = (skb_end_pointer(skb) - skb->head) + skb->data_len;
 	struct sk_buff *n = alloc_skb(size, gfp_mask);
 
+#if defined(CONFIG_COMCERTO_CUSTOM_SKB_LAYOUT)
+	WARN_ON(skb->mspd_len);
+#endif
 	if (!n)
 		return NULL;
 
@@ -893,6 +921,10 @@
 	unsigned int size = skb_end_pointer(skb) - skb->head;
 	struct sk_buff *n = alloc_skb(size, gfp_mask);
 
+#if defined(CONFIG_COMCERTO_CUSTOM_SKB_LAYOUT)
+	WARN_ON(skb->mspd_len);
+#endif
+
 	if (!n)
 		goto out;
 
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 0bc95f3..fedf053 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -238,7 +238,13 @@
 		return dst_output(skb);
 	}
 #endif
+
+#if defined(CONFIG_INET_IPSEC_OFFLOAD)
+	if ((skb->ipsec_offload == 0) &&
+		skb->len > ip_skb_dst_mtu(skb) && !skb_is_gso(skb))
+#else
 	if (skb->len > ip_skb_dst_mtu(skb) && !skb_is_gso(skb))
+#endif
 		return ip_fragment(skb, ip_finish_output2);
 	else
 		return ip_finish_output2(skb);
diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/ipv4/netfilter/nf_nat_proto_common.c
index a3d9976..986a298 100644
--- a/net/ipv4/netfilter/nf_nat_proto_common.c
+++ b/net/ipv4/netfilter/nf_nat_proto_common.c
@@ -83,14 +83,123 @@
 	else
 		off = *rover;
 
-	for (i = 0; ; ++off) {
-		*portptr = htons(min + off % range_size);
-		if (++i != range_size && nf_nat_used_tuple(tuple, ct))
-			continue;
-		if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
-			*rover = off;
-		return;
-	}
+       /* 4rd specific range NAPT - start */
+       if ((range->flags & IP_NAT_RANGE_4RD_NAPT) && (maniptype == IP_NAT_MANIP_SRC)){
+               __be16 fix_port;
+               __be16 port_min, port_max;
+               u_int16_t port_set_id;
+               u_int16_t mbitlen   = 0 ;
+               u_int16_t offsetlen = 0 ;
+               u_int16_t psidlen   = 0 ;
+               u_int16_t range_total_size = 0 ;
+               u_int16_t offset_4rd;
+               u_int16_t o_state;
+               u_int16_t m_state;
+
+               u_int16_t offset_min;
+               u_int16_t offset_max;
+               u_int16_t offset_cnt;
+               u_int16_t mbit_cnt;
+
+               # define MAXBITLEN 16
+               port_min = ntohs(range->min.all);
+               port_max = ntohs(range->max.all);
+
+               for(i = 0; i < MAXBITLEN; i++){
+                       if( ((port_min >> i) & 0x0001) == ((port_max >> i) & 0x0001) ){
+                               psidlen++;
+                               i++;
+                               break;
+                       }
+                       else{
+                               mbitlen++;
+                       }
+               }
+
+               for( ; i < MAXBITLEN; i++){
+                       if( ((port_min >> i) & 0x0001) == ((port_max >> i) & 0x0001) ){
+                               psidlen++;
+                       }
+                       else{
+                               break;
+                       }
+               }
+
+               offsetlen = MAXBITLEN - psidlen - mbitlen;
+
+               if((psidlen == 0) || (mbitlen == 0)){
+                       /* ERROR */
+                       printk(KERN_INFO "4rd parameter INVALID");
+               }
+
+               port_set_id = (port_min & port_max) >> mbitlen;
+
+               if( offsetlen ){
+                       if(port_min < 4096){
+                               if(offsetlen > 4){
+
+
+                                       offset_min = 0x1000 >> (psidlen + mbitlen);
+                                       offset_max = (1 << offsetlen) - 1;
+                                       offset_cnt = offset_max - offset_min + 1;
+                                       mbit_cnt = 1 << mbitlen;
+                                       range_total_size = offset_cnt * mbit_cnt;
+                               }
+                               else{
+                                       offset_min = 0x0001;
+                                       offset_cnt = (1 << offsetlen) - 1;
+                                       mbit_cnt = 1 << mbitlen;
+                                       range_total_size = offset_cnt * mbit_cnt;
+                               }
+                       }
+                       else{
+                               offset_min = 0x0000;
+                               offset_cnt = 1 << offsetlen;
+                               mbit_cnt = 1 << mbitlen;
+                               range_total_size = offset_cnt * mbit_cnt;
+                       }
+               }
+               else{
+                       offset_min = 0;
+                       range_total_size = ( 1 << mbitlen ) ;
+               }
+
+               for (i = 0; ; ++off) {
+
+                       offset_4rd = off % range_total_size ;
+
+                       if ( mbitlen != 0 ){
+                               o_state = offset_4rd / ( 1 << mbitlen ) ;
+                               m_state = offset_4rd % ( 1 << mbitlen ) ;
+                       }else{
+                               o_state = offset_4rd / ( 1 << mbitlen ) ;
+                               m_state = 0 ;
+                       }
+
+                       fix_port = (( offset_min + o_state ) << ( mbitlen + psidlen ));
+                       fix_port |= ( port_set_id << mbitlen );
+                       fix_port |= m_state;
+
+                       *portptr = htons(fix_port);
+
+                       if ((++i != range_total_size) && nf_nat_used_tuple(tuple, ct))
+                               continue;
+
+                       //printk(KERN_INFO "fix_port = %d ",fix_port);
+                       return ;
+               }
+       } /* 4rd specific range NAPT - end */
+       else{
+
+	       for (i = 0; ; ++off) {
+		       *portptr = htons(min + off % range_size);
+		       if (++i != range_size && nf_nat_used_tuple(tuple, ct))
+			       continue;
+		       if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
+			       *rover = off;
+		       return;
+	       }
+       }
 	return;
 }
 EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple);
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 65dd543..0b9e148 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -138,11 +138,26 @@
 	kfree(ESP_SKB_CB(skb)->tmp);
 	xfrm_output_resume(skb, err);
 }
+static void udp_v6_send_check(struct sk_buff *skb)
+{
+	struct ipv6hdr *ipv6h=ipv6_hdr(skb);
+	struct udphdr *uh=udp_hdr(skb);
+	uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
+			IPPROTO_UDP, 0);
+	skb->csum_start = skb_transport_header(skb) - skb->head;
+	skb->csum_offset = offsetof(struct udphdr, check);
+	skb->ip_summed = CHECKSUM_PARTIAL;
+
+	if (uh->check == 0)
+		uh->check = CSUM_MANGLED_0;
+
+}
 
 static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
 	struct ip_esp_hdr *esph;
+	struct udphdr *uh=NULL;
 	struct crypto_aead *aead;
 	struct aead_givcrypt_request *req;
 	struct scatterlist *sg;
@@ -228,13 +243,46 @@
 	esph = ip_esp_hdr(skb);
 	*skb_mac_header(skb) = IPPROTO_ESP;
 
+	/* NAT-T changes Start */
+	/* this is non-NULL only with UDP Encapsulation */
+	if (x->encap) {
+		struct xfrm_encap_tmpl *encap = x->encap;
+		__be32 *udpdata32;
+		__be16 sport, dport;
+		int encap_type;
+		spin_lock_bh(&x->lock);
+		sport = encap->encap_sport;
+		dport = encap->encap_dport;
+		encap_type = encap->encap_type;
+		spin_unlock_bh(&x->lock);
+		uh = (struct udphdr *)esph;
+		uh->source = sport;
+		uh->dest = dport;
+		uh->len = htons(skb->len - skb_transport_offset(skb));
+		uh->check = 0;
+
+		switch (encap_type) {
+			default:
+			case UDP_ENCAP_ESPINUDP:
+				esph = (struct ip_esp_hdr *)(uh + 1);
+				break;
+			case UDP_ENCAP_ESPINUDP_NON_IKE:
+				udpdata32 = (__be32 *)(uh + 1);
+				udpdata32[0] = udpdata32[1] = 0;
+				esph = (struct ip_esp_hdr *)(udpdata32 + 2);
+				break;
+		}
+		*skb_mac_header(skb) = IPPROTO_UDP;
+	}
+
+
 	esph->spi = x->id.spi;
 	esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
 
 	sg_init_table(sg, nfrags);
 	skb_to_sgvec(skb, sg,
-		     esph->enc_data + crypto_aead_ivsize(aead) - skb->data,
-		     clen + alen);
+			esph->enc_data + crypto_aead_ivsize(aead) - skb->data,
+			clen + alen);
 
 	if ((x->props.flags & XFRM_STATE_ESN)) {
 		sg_init_table(asg, 3);
@@ -249,7 +297,7 @@
 	aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
 	aead_givcrypt_set_assoc(req, asg, assoclen);
 	aead_givcrypt_set_giv(req, esph->enc_data,
-			      XFRM_SKB_CB(skb)->seq.output.low);
+			XFRM_SKB_CB(skb)->seq.output.low);
 
 	ESP_SKB_CB(skb)->tmp = tmp;
 	err = crypto_aead_givencrypt(req);
@@ -259,6 +307,13 @@
 	if (err == -EBUSY)
 		err = NET_XMIT_DROP;
 
+
+	/* NAT-T changes Start */
+	if (x->encap) {
+		udp_v6_send_check(skb);
+	}
+	/* NAT-T changes End */
+
 	kfree(tmp);
 
 error:
@@ -267,6 +322,7 @@
 
 static int esp_input_done2(struct sk_buff *skb, int err)
 {
+	struct ipv6hdr *ipv6h;
 	struct xfrm_state *x = xfrm_input_state(skb);
 	struct esp_data *esp = x->data;
 	struct crypto_aead *aead = esp->aead;
@@ -289,11 +345,48 @@
 	padlen = nexthdr[0];
 	if (padlen + 2 + alen >= elen) {
 		LIMIT_NETDEBUG(KERN_WARNING "ipsec esp packet is garbage "
-			       "padlen=%d, elen=%d\n", padlen + 2, elen - alen);
+				"padlen=%d, elen=%d\n", padlen + 2, elen - alen);
 		goto out;
 	}
 
 	/* ... check padding bits here. Silly. :-) */
+	/* NAT-T changes Start */
+	ipv6h = ipv6_hdr(skb);
+	if (x->encap) {
+		struct xfrm_encap_tmpl *encap = x->encap;
+		struct udphdr *uh = (void *)(skb_network_header(skb) + hdr_len);
+
+		/* 1) if the NAT-T peer's IP or port changed then
+		 *    advertize the change to the keying daemon.
+		 *    This is an inbound SA, so just compare
+		 *    SRC ports.
+		 */
+		if (memcmp(&ipv6h->saddr, x->props.saddr.a6 ,sizeof(ipv6h->saddr)) ||
+				uh->source != encap->encap_sport) {
+			xfrm_address_t ipaddr;
+			memcpy(ipaddr.a6, &ipv6h->saddr, sizeof(ipaddr.a6));
+			km_new_mapping(x, &ipaddr, uh->source);
+			/* XXX: perhaps add an extra
+			 * policy check here, to see
+			 * if we should allow or
+			 * reject a packet from a
+			 * different source
+			 * address/port.
+			 */
+		}
+
+		/*
+		 * 2) ignore UDP/TCP checksums in case
+		 *    of NAT-T in Transport Mode, or
+		 *    perform other post-processing fixes
+		 *    as per draft-ietf-ipsec-udp-encaps-06,
+		 *    section 3.1.2
+		 */
+		if (x->props.mode == XFRM_MODE_TRANSPORT || x->props.mode == XFRM_MODE_BEET) 
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	}
+	/*NAT-T changes End*/
 
 	pskb_trim(skb, skb->len - alen - padlen - 2);
 	__skb_pull(skb, hlen);
@@ -577,8 +670,8 @@
 	u32 align;
 	int err;
 
-	if (x->encap)
-		return -EINVAL;
+	//if (x->encap)
+	//	return -EINVAL;
 
 	esp = kzalloc(sizeof(*esp), GFP_KERNEL);
 	if (esp == NULL)
@@ -615,6 +708,22 @@
 		goto error;
 	}
 
+	/* NAT-T  changes Start */
+	if (x->encap) {
+		struct xfrm_encap_tmpl *encap = x->encap;
+		switch (encap->encap_type) {
+		default:
+			goto error;
+		case UDP_ENCAP_ESPINUDP:
+			x->props.header_len += sizeof(struct udphdr);
+			break;
+		case UDP_ENCAP_ESPINUDP_NON_IKE:
+			x->props.header_len += sizeof(struct udphdr) + 2 * sizeof(u32) * 4;
+			break;
+		}
+	}
+	/* NAT-T changes End */
+
 	align = ALIGN(crypto_aead_blocksize(aead), 4);
 	if (esp->padlen)
 		align = max_t(u32, align, esp->padlen);
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index d19f499..d0cf5b5 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -37,6 +37,7 @@
 #include <linux/route.h>
 #include <linux/rtnetlink.h>
 #include <linux/netfilter_ipv6.h>
+#include <linux/netfilter/nf_conntrack_proto_gre.h>
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
@@ -74,6 +75,10 @@
 		     (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \
 		    (HASH_SIZE - 1))
 
+
+#define for_each_ip6_tunnel_rcu(start) \
+	for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
+
 static int ip6_tnl_dev_init(struct net_device *dev);
 static void ip6_tnl_dev_setup(struct net_device *dev);
 
@@ -119,6 +124,550 @@
  * Locking : hash tables are protected by RCU and RTNL
  */
 
+static struct kmem_cache *mr_kmem __read_mostly;
+int mr_kmem_alloced = 0;
+
+static inline size_t  ip6_4rd_nlmsg_size(void)
+{
+	return NLMSG_ALIGN(sizeof(struct ip6_4rd_map_msg));
+}
+
+static int ip6_4rd_fill_node( struct sk_buff *skb, struct ip6_tnl_4rd_map_rule *mr,
+			u32 pid, u32 seq,int type, unsigned int flags, int reset, unsigned int ifindex)
+{
+	struct ip6_4rd_map_msg *mr_msg;
+	struct nlmsghdr *nlh;
+
+	nlh = nlmsg_put(skb, pid , seq, type, sizeof(*mr_msg), flags);
+	if (nlh == NULL)
+		return -EMSGSIZE;
+
+	mr_msg = nlmsg_data(nlh);
+	if(reset)
+	{
+		memset(mr_msg,0,sizeof(*mr_msg));
+		mr_msg->reset = 1;
+		mr_msg->ifindex = ifindex;
+		
+	}
+	else
+	{
+		//	memcpy(mr_msg,mr, sizeof(*mr_msg));
+		memset(mr_msg,0,sizeof(*mr_msg));
+		mr_msg->prefix = mr->prefix;
+		mr_msg->prefixlen = mr->prefixlen ;
+		ipv6_addr_copy(&mr_msg->relay_prefix, &mr->relay_prefix);
+		ipv6_addr_copy(&mr_msg->relay_suffix, &mr->relay_suffix);
+		mr_msg->relay_prefixlen = mr->relay_prefixlen ;
+		mr_msg->relay_suffixlen = mr->relay_suffixlen ;
+		mr_msg->psid_offsetlen = mr->psid_offsetlen ;
+		mr_msg->eabit_len = mr->eabit_len ;
+		mr_msg->entry_num = mr->entry_num ;
+		mr_msg->ifindex = ifindex;
+	}
+	return nlmsg_end(skb, nlh);
+
+}
+
+
+static int inet6_dump4rd_mrule(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct net *net = sock_net(skb->sk);
+	unsigned int h, s_h;
+	int s_idx, s_ip_idx;
+	int idx, ip_idx;
+	struct ip6_tnl_4rd_map_rule *mr ;
+	int err = 0;
+
+
+	struct ip6_tnl *t;
+	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+
+	s_h = cb->args[0];
+	s_idx = idx = cb->args[1];
+	s_ip_idx = ip_idx = cb->args[2];
+
+	for (h = s_h; h < HASH_SIZE ; h++, s_idx = 0) {
+		idx = 0;
+		for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[h])
+		{
+			if (idx < s_idx)
+				goto cont_tunnel;
+			if (idx > s_idx)
+				s_ip_idx = 0;
+			ip_idx = 0;
+			read_lock(&t->ip4rd.map_lock);
+			list_for_each_entry (mr, &t->ip4rd.map_list, mr_list){
+				if (ip_idx < s_ip_idx)
+					goto cont_mr;
+				err = ip6_4rd_fill_node(skb, mr,NETLINK_CB(cb->skb).pid,
+						cb->nlh->nlmsg_seq,RTM_NEW4RD, NLM_F_MULTI , 0, t->dev->ifindex);
+				if (err < 0) {
+					WARN_ON(err == -EMSGSIZE);
+					kfree_skb(skb);
+					read_unlock(&t->ip4rd.map_lock);
+					goto out;
+				}
+cont_mr:
+				ip_idx++;
+			}
+			read_unlock(&t->ip4rd.map_lock);
+cont_tunnel:
+			idx++;	
+		}
+	}
+out:
+	cb->args[0] = h;
+	cb->args[1] = idx;
+	cb->args[2] = ip_idx;
+	
+	return skb->len;
+}
+
+
+void ip6_4rd_notify(int event, struct ip6_tnl_4rd_map_rule *mr ,struct net_device *dev, int reset)
+{
+	struct sk_buff *skb;
+	struct net *net = dev_net(dev);
+	int err;
+
+	err = -ENOBUFS;
+
+	skb = nlmsg_new(ip6_4rd_nlmsg_size(), gfp_any());
+	if (skb == NULL)
+		goto errout;
+
+	err = ip6_4rd_fill_node(skb, mr,0,0,event,  0, reset, dev->ifindex);
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
+	rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR,
+		    NULL, gfp_any());
+	return;
+errout:
+	if (err < 0)
+		rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
+}
+
+static inline void
+ip6_tnl_4rd_mr_destroy(char *f, struct ip6_tnl_4rd_map_rule *mr)
+{
+	list_del(&mr->mr_list);
+	kmem_cache_free(mr_kmem, mr);
+	--mr_kmem_alloced;
+}
+
+static int
+ip6_tnl_4rd_mr_create(struct ip6_tnl_4rd *ip4rd, struct ip6_tnl_4rd_parm *parm, struct net_device *dev)
+{
+	struct ip6_tnl_4rd_map_rule *mr ;
+	int err = 0;
+
+       write_lock_bh(&parm->map_lock);
+       list_for_each_entry (mr, &parm->map_list, mr_list){
+               if( mr->entry_num == ip4rd->entry_num ){
+                       printk(KERN_DEBUG "ip6_tnl_4rd_mr_create: map rule found update");
+                       mr->prefix = ip4rd->prefix ;
+                       ipv6_addr_copy(&mr->relay_prefix, &ip4rd->relay_prefix);
+                       ipv6_addr_copy(&mr->relay_suffix, &ip4rd->relay_suffix);
+                       mr->prefixlen = ip4rd->prefixlen ;
+                       mr->relay_prefixlen = ip4rd->relay_prefixlen ;
+                       mr->relay_suffixlen = ip4rd->relay_suffixlen ;
+                       mr->psid_offsetlen = ip4rd->psid_offsetlen ;
+                       mr->eabit_len = ip4rd->eabit_len ;
+                       mr->entry_num = ip4rd->entry_num ;
+                       goto out;
+               }
+       }
+
+       mr = kmem_cache_alloc(mr_kmem, GFP_KERNEL);
+
+       if (!mr) {
+               printk(KERN_INFO "ip6_tnl_4rd_mr_create: kmem_cache_alloc fail");
+               err = -1 ;
+               goto out;
+       }
+
+       mr->prefix = ip4rd->prefix ;
+       ipv6_addr_copy(&mr->relay_prefix, &ip4rd->relay_prefix);
+       ipv6_addr_copy(&mr->relay_suffix, &ip4rd->relay_suffix);
+       mr->prefixlen = ip4rd->prefixlen ;
+       mr->relay_prefixlen = ip4rd->relay_prefixlen ;
+       mr->relay_suffixlen = ip4rd->relay_suffixlen ;
+       mr->psid_offsetlen = ip4rd->psid_offsetlen ;
+       mr->eabit_len = ip4rd->eabit_len ;
+       mr->entry_num = ip4rd->entry_num ;
+
+       ++mr_kmem_alloced;
+       list_add_tail(&mr->mr_list, &parm->map_list);
+
+out:
+	ip6_4rd_notify(RTM_NEW4RD,mr, dev,0); /* modified by MSPD */
+	write_unlock_bh(&parm->map_lock);
+	return err;
+}
+
+static void
+ip6_tnl_4rd_mr_delete_all(struct ip6_tnl_4rd_parm *parm, struct net_device *dev)
+{
+	struct ip6_tnl_4rd_map_rule *mr, *mr_rule;
+
+	write_lock_bh(&parm->map_lock);
+	list_for_each_entry_safe (mr, mr_rule, &parm->map_list, mr_list){
+		ip6_tnl_4rd_mr_destroy("all", mr);
+	}
+	ip6_4rd_notify(RTM_DEL4RD,mr, dev ,1);
+	write_unlock_bh(&parm->map_lock);
+
+}
+
+static int
+ip6_tnl_4rd_mr_delete(__u16 entry_num , struct ip6_tnl_4rd_parm *parm, struct net_device *dev)
+{
+	struct ip6_tnl_4rd_map_rule *mr, *mr_rule;
+	int err = -1 ;
+
+	write_lock_bh(&parm->map_lock);
+	list_for_each_entry_safe (mr, mr_rule, &parm->map_list, mr_list){
+		if( mr->entry_num == entry_num ){
+			printk(KERN_DEBUG "ip6_tnl_4rd_mr_delete: map rule found delete");
+			ip6_tnl_4rd_mr_destroy("one", mr);
+			err = 0 ;
+			break;
+		}
+	}
+	ip6_4rd_notify(RTM_DEL4RD,mr,dev,0);
+	write_unlock_bh(&parm->map_lock);
+	return err ;
+}
+
+static void
+ip6_tnl_4rd_mr_show(struct ip6_tnl_4rd_parm *parm)
+{
+	struct ip6_tnl_4rd_map_rule *mr;
+
+       printk(KERN_DEBUG "-- 4rd mapping rule list\n");
+       printk(KERN_DEBUG "-- entry num = %d \n",mr_kmem_alloced);
+
+	read_lock(&parm->map_lock);
+	list_for_each_entry(mr, &parm->map_list, mr_list){
+		printk(KERN_DEBUG "%03d : %03d.%03d.%03d.%03d/%02d %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x/%03d %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x/%03d eabit:%03d offset:%03d \n",
+			mr->entry_num,
+			(ntohl(mr->prefix) >> 24) & 0xff,
+			(ntohl(mr->prefix) >> 16) & 0xff,
+			(ntohl(mr->prefix) >>  8) & 0xff,
+			ntohl(mr->prefix) & 0xff,
+			mr->prefixlen,
+			mr->relay_prefix.s6_addr[0],
+			mr->relay_prefix.s6_addr[1],
+			mr->relay_prefix.s6_addr[2],
+			mr->relay_prefix.s6_addr[3],
+			mr->relay_prefix.s6_addr[4],
+			mr->relay_prefix.s6_addr[5],
+			mr->relay_prefix.s6_addr[6],
+			mr->relay_prefix.s6_addr[7],
+			mr->relay_prefix.s6_addr[8],
+			mr->relay_prefix.s6_addr[9],
+			mr->relay_prefix.s6_addr[10],
+			mr->relay_prefix.s6_addr[11],
+			mr->relay_prefix.s6_addr[12],
+			mr->relay_prefix.s6_addr[13],
+			mr->relay_prefix.s6_addr[14],
+			mr->relay_prefix.s6_addr[15],
+			mr->relay_prefixlen,
+			mr->relay_suffix.s6_addr[0],
+			mr->relay_suffix.s6_addr[1],
+			mr->relay_suffix.s6_addr[2],
+			mr->relay_suffix.s6_addr[3],
+			mr->relay_suffix.s6_addr[4],
+			mr->relay_suffix.s6_addr[5],
+			mr->relay_suffix.s6_addr[6],
+			mr->relay_suffix.s6_addr[7],
+			mr->relay_suffix.s6_addr[8],
+			mr->relay_suffix.s6_addr[9],
+			mr->relay_suffix.s6_addr[10],
+			mr->relay_suffix.s6_addr[11],
+			mr->relay_suffix.s6_addr[12],
+			mr->relay_suffix.s6_addr[13],
+			mr->relay_suffix.s6_addr[14],
+			mr->relay_suffix.s6_addr[15],
+			mr->relay_suffixlen,
+			mr->eabit_len,
+			mr->psid_offsetlen );
+	}
+	read_unlock(&parm->map_lock);
+}
+
+static int
+ip6_tnl_4rd_modify_daddr(struct in6_addr *daddr6, __be32 daddr4, __be16 dport4,
+		struct ip6_tnl_4rd_map_rule *mr)
+{
+       int i, pbw0, pbi0, pbi1;
+       __u32 daddr[4];
+       __u32 port_set_id = 0;
+       __u32 mask;
+       __u32 da = ntohl(daddr4);
+       __u16 dp = ntohs(dport4);
+       __u32 diaddr[4];
+       int port_set_id_len = ( mr->eabit_len ) - ( 32 - mr->prefixlen ) ;
+
+       if ( port_set_id_len < 0) {
+               printk(KERN_DEBUG "ip6_tnl_4rd_modify_daddr: PSID length ERROR %d\n", port_set_id_len);
+               return -1;
+       }
+
+       if ( port_set_id_len > 0) {
+               mask = 0xffffffff >> (32 - port_set_id_len);
+               port_set_id = ( dp >> (16 - mr->psid_offsetlen - port_set_id_len ) & mask ) ;
+       }
+
+       for (i = 0; i < 4; ++i)
+               daddr[i] = ntohl(mr->relay_prefix.s6_addr32[i])
+                       | ntohl(mr->relay_suffix.s6_addr32[i]);
+
+       if( mr->prefixlen < 32 ) {
+               pbw0 = mr->relay_prefixlen >> 5;
+               pbi0 = mr->relay_prefixlen & 0x1f;
+               daddr[pbw0] |= (da << mr->prefixlen) >> pbi0;
+               pbi1 = pbi0 - mr->prefixlen;
+               if (pbi1 > 0)
+                       daddr[pbw0+1] |= da << (32 - pbi1);
+	}
+       if ( port_set_id_len > 0) {
+	       pbw0 = (mr->relay_prefixlen + 32 - mr->prefixlen) >> 5;
+	       pbi0 = (mr->relay_prefixlen + 32 - mr->prefixlen) & 0x1f;
+	       daddr[pbw0] |= (port_set_id << (32 - port_set_id_len)) >> pbi0;
+	       pbi1 = pbi0 - (32 - port_set_id_len);
+	       if (pbi1 > 0)
+		       daddr[pbw0+1] |= port_set_id << (32 - pbi1);
+       }
+
+       memset(diaddr, 0, sizeof(diaddr));
+
+       diaddr[2] = ( da >> 8 ) ;
+       diaddr[3] = ( da << 24 ) ;
+       diaddr[3] |= ( port_set_id << 8 ) ;
+
+       for (i = 0; i < 4; ++i)
+               daddr[i] = daddr[i] | diaddr[i] ;
+
+       for (i = 0; i < 4; ++i)
+               daddr6->s6_addr32[i] = htonl(daddr[i]);
+
+       /* DBG */
+       printk(KERN_DEBUG "ip6_tnl_4rd_modify_daddr: %08x %08x %08x %08x  PSID:%04x\n",
+               daddr[0], daddr[1], daddr[2], daddr[3], port_set_id);
+
+       return 0;
+}
+
+/**
+ * ip6_tnl_4rd_rcv_helper - 
+ *   @skb: received socket buffer
+ *   @t: tunnel device
+ **/
+
+static int
+ip6_tnl_4rd_rcv_helper(struct sk_buff *skb, struct ip6_tnl *t)
+{
+       int err = 0;
+       struct iphdr *iph;
+
+       iph = ip_hdr(skb);
+
+       switch (iph->protocol) {
+       case IPPROTO_TCP:
+       case IPPROTO_UDP:
+       case IPPROTO_ICMP:
+       case IPPROTO_GRE:
+               break;
+       default:
+               err = -1;
+               break;
+       }
+
+       return err;
+}
+
+static int
+ip6_tnl_4rd_xmit_helper(struct sk_buff *skb, struct flowi6 *fl6,
+		struct ip6_tnl *t)
+{
+       int err = 0;
+       struct iphdr *iph, *icmpiph;
+       __be16  *idp;
+       struct tcphdr *tcph, *icmptcph;
+       struct udphdr *udph, *icmpudph;
+       struct icmphdr *icmph;
+       struct gre_hdr *greh;
+       __u32 mask;
+       __be16 *sportp = NULL;
+       __be32 daddr;
+       __be16 dport;
+       u8 *ptr;
+       int no_dst_chg = 0;
+       struct ip6_tnl_4rd_map_rule *mr,*mr_tmp;
+       int mr_prefixlen ;
+       int count ;
+
+       iph = ip_hdr(skb);
+
+       daddr = iph->daddr;
+       idp = &iph->id;
+
+       ptr = (u8 *)iph;
+       ptr += iph->ihl * 4;
+       switch (iph->protocol) {
+       case IPPROTO_TCP:
+               tcph = (struct tcphdr *)ptr;
+               sportp = &tcph->source;
+               dport = tcph->dest;
+               break;
+       case IPPROTO_UDP:
+               udph = (struct udphdr *)ptr;
+               sportp = &udph->source;
+               dport = udph->dest;
+               break;
+       case IPPROTO_ICMP:
+               icmph = (struct icmphdr *)ptr;
+               switch (icmph->type) {
+               case ICMP_DEST_UNREACH:
+               case ICMP_SOURCE_QUENCH:
+               case ICMP_REDIRECT:
+               case ICMP_TIME_EXCEEDED:
+               case ICMP_PARAMETERPROB:
+                       ptr = (u8 *)icmph;
+                       ptr += sizeof(struct icmphdr);
+                       icmpiph = (struct iphdr*)ptr;
+                       if (ntohs(iph->tot_len) < icmpiph->ihl * 4 + 12) {
+                               err = -1;
+                               goto out;
+                       }
+                       daddr = icmpiph->saddr;
+                       ptr += icmpiph->ihl * 4;
+                       switch (icmpiph->protocol) {
+                       case IPPROTO_TCP:
+                               icmptcph = (struct tcphdr *)ptr;
+                               sportp = &icmptcph->dest;
+                               dport = icmptcph->source;
+                               break;
+                       case IPPROTO_UDP:
+                               icmpudph = (struct udphdr *)ptr;
+                               sportp = &icmpudph->dest;
+                               dport = icmpudph->source;
+                               break;
+                       default:
+                               err = -1;
+                               goto out;
+                       }
+                       break;
+               default:
+                       no_dst_chg = 1;
+                       break;
+               }
+               break;
+       case IPPROTO_GRE:
+               greh = (struct gre_hdr *)ptr;
+               if(greh->protocol != GRE_PROTOCOL_PPTP){
+                       err = -1;
+                       goto out;
+               }
+               no_dst_chg = 1;
+               break;
+       default:
+               err = -1;
+               goto out;
+       }
+
+       if ( no_dst_chg == 0 ){
+
+               count = 0;
+               mr_prefixlen = 0;
+
+               read_lock(&t->ip4rd.map_lock);
+               list_for_each_entry (mr, &t->ip4rd.map_list, mr_list){
+                       mask = 0xffffffff << (32 - mr->prefixlen) ;
+                       if( (htonl(daddr) & mask ) == htonl( mr->prefix) ) {
+                               if ( mr->prefixlen >= mr_prefixlen ){
+                                       mr_prefixlen = mr->prefixlen ;
+                                       mr_tmp = mr;
+                                       count++;
+                               }
+                       }
+               }
+
+               if (count){
+                       err = ip6_tnl_4rd_modify_daddr(&fl6->daddr, daddr, dport, mr_tmp );
+                       if (err){
+                                       read_unlock(&t->ip4rd.map_lock);
+                                       goto out;
+                       }
+               }
+               read_unlock(&t->ip4rd.map_lock);
+
+               if(sportp && idp){
+                       *idp=*sportp;
+               }
+       }
+
+       iph->check = 0;
+       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+       /* XXX: */
+       skb->local_df = 1;
+
+out:
+	return err;
+}
+
+/**
+ * ip6_tnl_4rd_update_parms - update 4rd parameters
+ *   @t: tunnel to be updated
+ *
+ * Description:
+ *   ip6_tnl_4rd_update_parms() updates 4rd parameters
+ **/
+static void
+ip6_tnl_4rd_update_parms(struct ip6_tnl *t)
+{
+	int pbw0, pbi0, pbi1;
+	__u32 d;
+
+	t->ip4rd.port_set_id_len = t->ip4rd.relay_suffixlen
+				- t->ip4rd.relay_prefixlen
+				- (32 - t->ip4rd.prefixlen);
+	pbw0 = (t->ip4rd.relay_suffixlen - t->ip4rd.port_set_id_len) >> 5;
+	pbi0 = (t->ip4rd.relay_suffixlen - t->ip4rd.port_set_id_len) & 0x1f;
+	d = (ntohl(t->parms.laddr.s6_addr32[pbw0]) << pbi0)
+		>> (32 - t->ip4rd.port_set_id_len);
+	pbi1 = pbi0 - (32 - t->ip4rd.port_set_id_len);
+
+	if (pbi1 > 0)
+		d |= ntohl(t->parms.laddr.s6_addr32[pbw0+1]) >> (32 - pbi1);
+	t->ip4rd.port_set_id = d;
+
+	/* local v4 address */
+	t->ip4rd.laddr4 = t->ip4rd.prefix;
+	pbw0 = t->ip4rd.relay_prefixlen >> 5;
+	pbi0 = t->ip4rd.relay_prefixlen & 0x1f;
+	d = (ntohl(t->parms.laddr.s6_addr32[pbw0]) << pbi0)
+		>> t->ip4rd.prefixlen;
+	pbi1 = pbi0 - t->ip4rd.prefixlen;
+	if (pbi1 > 0)
+		d |= ntohl(t->parms.laddr.s6_addr32[pbw0+1]) >> (32 - pbi1);
+	t->ip4rd.laddr4 |= htonl(d);
+	if (t->ip4rd.port_set_id_len < 0) {
+		d = ntohl(t->ip4rd.laddr4);
+		d &= 0xffffffff << -t->ip4rd.port_set_id_len;
+		t->ip4rd.laddr4 = htonl(d);
+	}
+
+}
+
+
 static inline struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t)
 {
 	struct dst_entry *dst = t->dst_cache;
@@ -158,22 +707,26 @@
  *   else %NULL
  **/
 
-#define for_each_ip6_tunnel_rcu(start) \
-	for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
 
 static struct ip6_tnl *
 ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_addr *local)
 {
-	unsigned int h0 = HASH(remote);
-	unsigned int h1 = HASH(local);
+//	unsigned int h0 = HASH(remote); /* 4rd support, remote could be any, so hashing to be done only based on local address */
+	unsigned int h1 = HASH(local); 
 	struct ip6_tnl *t;
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
 
-	for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[h0 ^ h1]) {
+	for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[h1]) {
 		if (ipv6_addr_equal(local, &t->parms.laddr) &&
 		    ipv6_addr_equal(remote, &t->parms.raddr) &&
 		    (t->dev->flags & IFF_UP))
 			return t;
+                if (t->ip4rd.prefix &&
+                   ipv6_addr_equal(local, &t->parms.laddr) &&
+                /* ipv6_prefix_equal(remote, &t->ip4rd.relay_prefix,
+                       t->ip4rd.relay_prefixlen) && 4RD D  */
+                   (t->dev->flags & IFF_UP))
+                       return t;
 	}
 	t = rcu_dereference(ip6n->tnls_wc[0]);
 	if (t && (t->dev->flags & IFF_UP))
@@ -196,14 +749,14 @@
 static struct ip6_tnl __rcu **
 ip6_tnl_bucket(struct ip6_tnl_net *ip6n, const struct ip6_tnl_parm *p)
 {
-	const struct in6_addr *remote = &p->raddr;
+//	const struct in6_addr *remote = &p->raddr;
 	const struct in6_addr *local = &p->laddr;
 	unsigned h = 0;
 	int prio = 0;
 
-	if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) {
+	if (!ipv6_addr_any(local)) {      /* 4rd support, since remote address could be any address, refrain from checking based on remote */ 
 		prio = 1;
-		h = HASH(remote) ^ HASH(local);
+		h = HASH(local);	
 	}
 	return &ip6n->tnls[prio][h];
 }
@@ -291,6 +844,9 @@
 
 	strcpy(t->parms.name, dev->name);
 
+	rwlock_init(&t->ip4rd.map_lock);
+	INIT_LIST_HEAD(&t->ip4rd.map_list); 
+
 	dev_hold(dev);
 	ip6_tnl_link(ip6n, t);
 	return t;
@@ -766,6 +1322,10 @@
 		__skb_tunnel_rx(skb, t->dev);
 
 		dscp_ecn_decapsulate(t, ipv6h, skb);
+                if (ip6_tnl_4rd_rcv_helper(skb, t)) {
+                        rcu_read_unlock();
+                        goto discard;
+                }
 
 		netif_rx(skb);
 
@@ -898,6 +1458,7 @@
 	u8 proto;
 	int err = -1;
 	int pkt_len;
+	__u8 hop_limit;    
 
 	if (!fl6->flowi6_mark)
 		dst = ip6_tnl_dst_check(t);
@@ -934,10 +1495,21 @@
 		mtu = IPV6_MIN_MTU;
 	if (skb_dst(skb))
 		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
-	if (skb->len > mtu) {
-		*pmtu = mtu;
-		err = -EMSGSIZE;
-		goto tx_err_dst_release;
+        if (!t->ip4rd.prefix) {   /* 4rd support requires Post Fragmentation, so skb->len could be greater than MTU */ 
+                if (skb->len > mtu) {
+                        *pmtu = mtu;
+                        err = -EMSGSIZE;
+                        goto tx_err_dst_release;
+                }
+        }                         
+
+	if (t->ip4rd.prefix) {
+		struct iphdr *iph;
+		iph = ip_hdr(skb);
+		hop_limit = iph->ttl;
+	}
+	else {
+		hop_limit = t->parms.hop_limit;
 	}
 
 	/*
@@ -977,7 +1549,7 @@
 	*(__be32*)ipv6h = fl6->flowlabel | htonl(0x60000000);
 	dsfield = INET_ECN_encapsulate(0, dsfield);
 	ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield);
-	ipv6h->hop_limit = t->parms.hop_limit;
+	ipv6h->hop_limit = hop_limit;    
 	ipv6h->nexthdr = proto;
 	ipv6_addr_copy(&ipv6h->saddr, &fl6->saddr);
 	ipv6_addr_copy(&ipv6h->daddr, &fl6->daddr);
@@ -1034,6 +1606,10 @@
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
 		fl6.flowi6_mark = skb->mark;
 
+
+        if (t->ip4rd.prefix && ip6_tnl_4rd_xmit_helper(skb, &fl6, t))
+                return -1;
+
 	err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
 	if (err != 0) {
 		/* XXX: send ICMP error even if DF is not set. */
@@ -1105,6 +1681,8 @@
 
 	switch (skb->protocol) {
 	case htons(ETH_P_IP):
+                if (t->ip4rd.prefix && ip_defrag(skb, IP_DEFRAG_IP6_TNL_4RD))
+                        return NETDEV_TX_OK;
 		ret = ip4ip6_tnl_xmit(skb, dev);
 		break;
 	case htons(ETH_P_IPV6):
@@ -1143,6 +1721,11 @@
 		if (rtype&IPV6_ADDR_UNICAST)
 			p->flags |= IP6_TNL_F_CAP_RCV;
 	}
+
+        if (t->ip4rd.prefix) {
+                p->flags |= IP6_TNL_F_CAP_XMIT;
+                p->flags |= IP6_TNL_F_CAP_RCV;
+        }
 }
 
 static void ip6_tnl_link_config(struct ip6_tnl *t)
@@ -1220,6 +1803,7 @@
 	t->parms.flowinfo = p->flowinfo;
 	t->parms.link = p->link;
 	t->parms.proto = p->proto;
+        ip6_tnl_4rd_update_parms(t);        
 	ip6_tnl_dst_reset(t);
 	ip6_tnl_link_config(t);
 	return 0;
@@ -1261,6 +1845,8 @@
 	struct ip6_tnl *t = NULL;
 	struct net *net = dev_net(dev);
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+        struct ip6_tnl_4rd ip4rd, *ip4rdp;  
+        struct ip6_tnl_4rd_map_rule *mr;   
 
 	switch (cmd) {
 	case SIOCGETTUNNEL:
@@ -1334,9 +1920,115 @@
 		err = 0;
 		unregister_netdevice(dev);
 		break;
+	case SIOCADD4RD:
+	case SIOCDEL4RD:
+		err = -EPERM;
+		if (!capable(CAP_NET_ADMIN))
+			goto done;
+
+		err = -EFAULT;
+		if (copy_from_user(&ip4rd, ifr->ifr_ifru.ifru_data, sizeof(ip4rd)))
+			goto done;
+
+		t = netdev_priv(dev);
+
+		if (cmd == SIOCADD4RD) {
+
+			__be32 prefix;
+			struct in6_addr relay_prefix, relay_suffix;
+
+			err = -EINVAL;
+
+			if (ip4rd.relay_suffixlen > 64)
+				goto done;
+
+			if (ip4rd.relay_suffixlen <= ip4rd.relay_prefixlen)
+				goto done;
+
+			prefix = ip4rd.prefix & htonl(0xffffffffUL << (32 - ip4rd.prefixlen));
+			if (prefix != ip4rd.prefix)
+				goto done;
+
+			ipv6_addr_prefix(&relay_prefix, &ip4rd.relay_prefix, ip4rd.relay_prefixlen);
+			if (!ipv6_addr_equal(&relay_prefix, &ip4rd.relay_prefix))
+				goto done;
+
+			ipv6_addr_prefix(&relay_suffix, &ip4rd.relay_suffix, ip4rd.relay_suffixlen);
+			if (!ipv6_addr_equal(&relay_suffix, &ip4rd.relay_suffix))
+				goto done;
+
+
+			err = ip6_tnl_4rd_mr_create(&ip4rd, &t->ip4rd, t->dev); /* modified by MSPD */
+
+			if ( ip4rd.entry_num == 0 ){
+
+				t->ip4rd.prefix = prefix;
+				ipv6_addr_copy(&t->ip4rd.relay_prefix, &relay_prefix);
+				ipv6_addr_copy(&t->ip4rd.relay_suffix, &relay_suffix);
+				t->ip4rd.prefixlen = ip4rd.prefixlen;
+				t->ip4rd.relay_prefixlen = ip4rd.relay_prefixlen;
+				t->ip4rd.relay_suffixlen = ip4rd.relay_suffixlen;
+				t->ip4rd.psid_offsetlen = ip4rd.psid_offsetlen;
+
+				ip6_tnl_4rd_update_parms(t);
+				ip6_tnl_dst_reset(t);
+				ip6_tnl_link_config(t);
+			}
+			/* DBG */
+			ip6_tnl_4rd_mr_show(&t->ip4rd);
+		}else if(cmd == SIOCDEL4RD){
+			if ( ip4rd.entry_num == 0 ){
+				ip6_tnl_4rd_mr_delete_all(&t->ip4rd, t->dev);
+				t->ip4rd.prefix = 0;
+				memset(&t->ip4rd.relay_prefix, 0, sizeof(t->ip4rd.relay_prefix));
+				memset(&t->ip4rd.relay_suffix, 0, sizeof(t->ip4rd.relay_suffix));
+				t->ip4rd.prefixlen = 0;
+				t->ip4rd.relay_prefixlen = 0;
+				t->ip4rd.relay_suffixlen = 0;
+				t->ip4rd.psid_offsetlen = 0;
+				t->ip4rd.laddr4 = 0;
+				t->ip4rd.port_set_id = t->ip4rd.port_set_id_len = 0;
+
+				ip6_tnl_dst_reset(t);
+				ip6_tnl_link_config(t);
+			}else{
+				err = ip6_tnl_4rd_mr_delete( ip4rd.entry_num , &t->ip4rd, t->dev);  /* modified by MSPD */
+			}
+			/* DBG */
+			ip6_tnl_4rd_mr_show(&t->ip4rd);
+		}else{
+			printk(KERN_ERR "=== ioctl_cmd 0x%x \n",cmd );
+		}
+		err = 0;
+		break;
+        case SIOCGET4RD:
+                t = netdev_priv(dev);
+                ip4rdp = (struct ip6_tnl_4r *)ifr->ifr_ifru.ifru_data;
+ 
+                read_lock(&t->ip4rd.map_lock);
+                list_for_each_entry (mr, &t->ip4rd.map_list, mr_list){
+                        ipv6_addr_copy(&ip4rd.relay_prefix, &mr->relay_prefix);
+                        ipv6_addr_copy(&ip4rd.relay_suffix, &mr->relay_suffix);
+                        ip4rd.prefix = mr->prefix;
+                        ip4rd.relay_prefixlen = mr->relay_prefixlen;
+                        ip4rd.relay_suffixlen = mr->relay_suffixlen;
+                        ip4rd.prefixlen = mr->prefixlen;
+                        ip4rd.eabit_len = mr->eabit_len;
+                        ip4rd.psid_offsetlen = mr->psid_offsetlen;
+                        ip4rd.entry_num = mr->entry_num;
+ 
+                        if (copy_to_user(ip4rdp, &ip4rd, sizeof(ip4rd))) {
+                                read_unlock(&t->ip4rd.map_lock);
+                                err = -EFAULT;
+                        }
+                        ip4rdp++;
+                }
+                read_unlock(&t->ip4rd.map_lock);
+                break;
 	default:
 		err = -EINVAL;
 	}
+done:
 	return err;
 }
 
@@ -1545,12 +2237,22 @@
 
 static int __init ip6_tunnel_init(void)
 {
-	int  err;
+        int err = 0;                
+ 
+        mr_kmem = kmem_cache_create("ip6_tnl_4rd_map_rule",
+                sizeof(struct ip6_tnl_4rd_map_rule), 0, SLAB_HWCACHE_ALIGN,
+                NULL);
+        if (!mr_kmem)
+	{
+		err= -ENOMEM; 
+                goto out_pernet;
+	}
 
 	err = register_pernet_device(&ip6_tnl_net_ops);
 	if (err < 0)
-		goto out_pernet;
+		goto out_kmem;
 
+	
 	err = xfrm6_tunnel_register(&ip4ip6_handler, AF_INET);
 	if (err < 0) {
 		printk(KERN_ERR "ip6_tunnel init: can't register ip4ip6\n");
@@ -1563,12 +2265,18 @@
 		goto out_ip6ip6;
 	}
 
+        err =__rtnl_register(PF_UNSPEC, RTM_GET4RD, NULL , inet6_dump4rd_mrule, NULL);
+        if(err < 0)
+                goto out_ip6ip6;
+
 	return 0;
 
 out_ip6ip6:
 	xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET);
 out_ip4ip6:
 	unregister_pernet_device(&ip6_tnl_net_ops);
+out_kmem:
+	kmem_cache_destroy(mr_kmem);
 out_pernet:
 	return err;
 }
@@ -1585,7 +2293,12 @@
 	if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6))
 		printk(KERN_INFO "ip6_tunnel close: can't deregister ip6ip6\n");
 
+        kmem_cache_destroy(mr_kmem);     
+ 
 	unregister_pernet_device(&ip6_tnl_net_ops);
+
+        rtnl_unregister(PF_UNSPEC, RTM_GET4RD);
+ 
 }
 
 module_init(ip6_tunnel_init);
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index f792b34..95d651c 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -205,6 +205,14 @@
         
          If unsure, say N.
 
+config IP6_NF_TARGET_NPT
+	tristate "NPT (Network Prefix translation) target support"
+	help
+	  This option adds the `SNPT' and `DNPT' target, which perform
+	  stateless IPv6-to-IPv6 Network Prefix Translation per RFC 6296.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 endif # IP6_NF_IPTABLES
 
 endmenu
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index abfee91..91b0806 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -31,4 +31,5 @@
 
 # targets
 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
+obj-$(CONFIG_IP6_NF_TARGET_NPT) += ip6t_NPT.o
 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c
new file mode 100644
index 0000000..ebbb836
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_NPT.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2011, 2012 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter_ipv6/ip6t_NPT.h>
+#include <linux/netfilter/x_tables.h>
+#include <net/netfilter/nf_conntrack.h>
+
+static int ip6t_npt_checkentry(const struct xt_tgchk_param *par)
+{
+	struct ip6t_npt_tginfo *npt = par->targinfo;
+	__wsum src_sum = 0, dst_sum = 0;
+	struct in6_addr pfx;
+	unsigned int i;
+
+	if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64)
+		return -EINVAL;
+
+	/* Ensure that LSB of prefix is zero */
+	ipv6_addr_prefix(&pfx, &npt->src_pfx.in6, npt->src_pfx_len);
+	if (!ipv6_addr_equal(&pfx, &npt->src_pfx.in6))
+		return -EINVAL;
+	ipv6_addr_prefix(&pfx, &npt->dst_pfx.in6, npt->dst_pfx_len);
+	if (!ipv6_addr_equal(&pfx, &npt->dst_pfx.in6))
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) {
+		src_sum = csum_add(src_sum,
+				(__force __wsum)npt->src_pfx.in6.s6_addr16[i]);
+		dst_sum = csum_add(dst_sum,
+				(__force __wsum)npt->dst_pfx.in6.s6_addr16[i]);
+	}
+
+	npt->adjustment = ~csum_fold(csum_sub(src_sum, dst_sum));
+	return 0;
+}
+
+static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,
+			     struct in6_addr *addr)
+{
+	unsigned int pfx_len;
+	unsigned int i, idx;
+	__be32 mask;
+	__sum16 sum;
+
+	pfx_len = max(npt->src_pfx_len, npt->dst_pfx_len);
+	for (i = 0; i < pfx_len; i += 32) {
+		if (pfx_len - i >= 32)
+			mask = 0;
+		else
+			mask = htonl(~((1 << (pfx_len - i)) - 1));
+
+		idx = i / 32;
+		addr->s6_addr32[idx] &= mask;
+		addr->s6_addr32[idx] |= ~mask & npt->dst_pfx.in6.s6_addr32[idx];
+	}
+
+	if (pfx_len <= 48)
+		idx = 3;
+	else {
+		for (idx = 4; idx < ARRAY_SIZE(addr->s6_addr16); idx++) {
+			if ((__force __sum16)addr->s6_addr16[idx] !=
+			    CSUM_MANGLED_0)
+				break;
+		}
+		if (idx == ARRAY_SIZE(addr->s6_addr16))
+			return false;
+	}
+
+	sum = ~csum_fold(csum_add(csum_unfold((__force __sum16)addr->s6_addr16[idx]),
+				  csum_unfold(npt->adjustment)));
+	if (sum == CSUM_MANGLED_0)
+		sum = 0;
+	*(__force __sum16 *)&addr->s6_addr16[idx] = sum;
+
+	return true;
+}
+
+static unsigned int
+ip6t_snpt_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct ip6t_npt_tginfo *npt = par->targinfo;
+	struct nf_conn *ct;
+	enum ip_conntrack_info ctinfo;
+
+	if (!ip6t_npt_map_pfx(npt, &ipv6_hdr(skb)->saddr)) {
+		icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD,
+			    offsetof(struct ipv6hdr, saddr));
+		return NF_DROP;
+	}
+#ifdef CONFIG_COMCERTO_FP
+	ct = nf_ct_get(skb, &ctinfo);
+	if (ct && ((ctinfo == IP_CT_NEW) || (ctinfo == IP_CT_RELATED))) {
+		rcu_read_lock();
+		memcpy(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.in6, &ipv6_hdr(skb)->saddr, sizeof(struct in6_addr));
+		rcu_read_unlock();
+	}
+#endif
+	return XT_CONTINUE;
+}
+
+static unsigned int
+ip6t_dnpt_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct ip6t_npt_tginfo *npt = par->targinfo;
+	struct nf_conn *ct;
+	enum ip_conntrack_info ctinfo;
+
+	if (!ip6t_npt_map_pfx(npt, &ipv6_hdr(skb)->daddr)) {
+		icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD,
+			    offsetof(struct ipv6hdr, daddr));
+		return NF_DROP;
+	}
+#ifdef CONFIG_COMCERTO_FP
+	ct = nf_ct_get(skb, &ctinfo);
+	if (ct && ((ctinfo == IP_CT_NEW) || (ctinfo == IP_CT_RELATED))) {
+		rcu_read_lock();
+		memcpy(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.in6, &ipv6_hdr(skb)->daddr, sizeof(struct in6_addr));
+		rcu_read_unlock();
+	}
+#endif
+	return XT_CONTINUE;
+}
+
+static struct xt_target ip6t_npt_target_reg[] __read_mostly = {
+	{
+		.name		= "SNPT",
+		.target		= ip6t_snpt_tg,
+		.targetsize	= sizeof(struct ip6t_npt_tginfo),
+		.checkentry	= ip6t_npt_checkentry,
+		.family		= NFPROTO_IPV6,
+		.hooks		= (1 << NF_INET_LOCAL_IN) |
+				  (1 << NF_INET_POST_ROUTING),
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "DNPT",
+		.target		= ip6t_dnpt_tg,
+		.targetsize	= sizeof(struct ip6t_npt_tginfo),
+		.checkentry	= ip6t_npt_checkentry,
+		.family		= NFPROTO_IPV6,
+		.hooks		= (1 << NF_INET_PRE_ROUTING) |
+				  (1 << NF_INET_LOCAL_OUT),
+		.me		= THIS_MODULE,
+	},
+};
+
+static int __init ip6t_npt_init(void)
+{
+	return xt_register_targets(ip6t_npt_target_reg,
+				   ARRAY_SIZE(ip6t_npt_target_reg));
+}
+
+static void __exit ip6t_npt_exit(void)
+{
+	xt_unregister_targets(ip6t_npt_target_reg,
+			      ARRAY_SIZE(ip6t_npt_target_reg));
+}
+
+module_init(ip6t_npt_init);
+module_exit(ip6t_npt_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IPv6-to-IPv6 Network Prefix Translation (RFC 6296)");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_ALIAS("ip6t_SNPT");
+MODULE_ALIAS("ip6t_DNPT");
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 8c25419..2be1dee 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -515,6 +515,36 @@
 	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
 		goto drop;
 
+
+	/* NAT-T changes Start */
+	if ( up->encap_type ) {
+		/*
+		 * This is an encapsulation socket, so pass the skb to
+		 * the socket's udp6_encap_rcv() hook.Otherwise, just
+		 * fall through and pass this up the UDP socket.
+		 * up->encap_rcv() returns the following value:
+		 * =0 if skb was successfully passed to the encap
+		 * handler or was discarded by it.
+		 * >0 if skb should be passed on to UDP.
+		 * <0 if skb should be resubmitted as proto -N
+		 */
+
+		/* if we're overly short, let UDP handle it */
+		if (skb->len > sizeof(struct udphdr) &&
+		    up->encap_rcv != NULL) {
+			int ret;
+
+			ret = (*up->encap_rcv)(sk, skb);
+			if (ret <= 0) {
+				UDP_INC_STATS_BH(sock_net(sk),
+						UDP_MIB_INDATAGRAMS,
+						is_udplite);
+				return -ret;
+			}
+			 /* FALLTHROUGH -- it's a UDP Packet */
+		}
+	}
+
 	/*
 	 * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c).
 	 */
@@ -1240,24 +1270,111 @@
 }
 
 /*
+*	Socket option code for UDP for IPV6
+*/
+int udp6_lib_setsockopt(struct sock *sk, int level, int optname,
+		       char __user *optval, unsigned int optlen,
+		       int (*push_pending_frames)(struct sock *))
+{
+	struct udp_sock *up = udp_sk(sk);
+	int val;
+	int err = 0;
+	int is_udplite = IS_UDPLITE(sk);
+
+	if (optlen < sizeof(int))
+		return -EINVAL;
+
+	if (get_user(val, (int __user *)optval))
+		return -EFAULT;
+
+	switch (optname) {
+		case UDP_CORK:
+			if (val != 0) {
+				up->corkflag = 1;
+			} else {
+				up->corkflag = 0;
+				lock_sock(sk);
+				(*push_pending_frames)(sk);
+				release_sock(sk);
+			}
+			break;
+
+		case UDP_ENCAP:
+			switch (val) {
+				case 0:
+				case UDP_ENCAP_ESPINUDP:
+				case UDP_ENCAP_ESPINUDP_NON_IKE:
+					up->encap_rcv = xfrm6_udp_encap_rcv;
+					/* FALLTHROUGH */
+				case UDP_ENCAP_L2TPINUDP:
+					up->encap_type = val;
+					break;
+				default:
+					err = -ENOPROTOOPT;
+					break;
+			}
+			break;
+
+			/*
+			 * 	UDP-Lite's partial checksum coverage (RFC 3828).
+			 */
+			/* The sender sets actual checksum coverage length via this option.
+			 * The case coverage > packet length is handled by send module. */
+		case UDPLITE_SEND_CSCOV:
+			if (!is_udplite)         /* Disable the option on UDP sockets */
+				return -ENOPROTOOPT;
+			if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
+				val = 8;
+			else if (val > USHRT_MAX)
+				val = USHRT_MAX;
+			up->pcslen = val;
+			up->pcflag |= UDPLITE_SEND_CC;
+			break;
+
+			/* The receiver specifies a minimum checksum coverage value. To make
+			 * sense, this should be set to at least 8 (as done below). If zero is
+			 * used, this again means full checksum coverage.                     */
+		case UDPLITE_RECV_CSCOV:
+			if (!is_udplite)         /* Disable the option on UDP sockets */
+				return -ENOPROTOOPT;
+			if (val != 0 && val < 8) /* Avoid silly minimal values.       */
+				val = 8;
+			else if (val > USHRT_MAX)
+				val = USHRT_MAX;
+			up->pcrlen = val;
+			up->pcflag |= UDPLITE_RECV_CC;
+			break;
+
+		default:
+			err = -ENOPROTOOPT;
+			break;
+	}
+
+	return err;
+}
+
+EXPORT_SYMBOL(udp6_lib_setsockopt);
+
+
+/*
  *	Socket option code for UDP
  */
 int udpv6_setsockopt(struct sock *sk, int level, int optname,
-		     char __user *optval, unsigned int optlen)
+		char __user *optval, unsigned int optlen)
 {
 	if (level == SOL_UDP  ||  level == SOL_UDPLITE)
-		return udp_lib_setsockopt(sk, level, optname, optval, optlen,
-					  udp_v6_push_pending_frames);
+		return udp6_lib_setsockopt(sk, level, optname, optval, optlen,
+				udp_v6_push_pending_frames);
 	return ipv6_setsockopt(sk, level, optname, optval, optlen);
 }
 
 #ifdef CONFIG_COMPAT
 int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
-			    char __user *optval, unsigned int optlen)
+		char __user *optval, unsigned int optlen)
 {
 	if (level == SOL_UDP  ||  level == SOL_UDPLITE)
-		return udp_lib_setsockopt(sk, level, optname, optval, optlen,
-					  udp_v6_push_pending_frames);
+		return udp6_lib_setsockopt(sk, level, optname, optval, optlen,
+				udp_v6_push_pending_frames);
 	return compat_ipv6_setsockopt(sk, level, optname, optval, optlen);
 }
 #endif
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index f8c3cf8..e23b7ef 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -21,6 +21,15 @@
 	return xfrm6_extract_header(skb);
 }
 
+int xfrm6_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
+		    int encap_type)
+{
+	XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
+	XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
+	return xfrm_input(skb, nexthdr, spi, encap_type);
+}
+EXPORT_SYMBOL(xfrm6_rcv_encap);
+
 int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
 {
 	XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
@@ -46,6 +55,106 @@
 		ip6_rcv_finish);
 	return -1;
 }
+/* If it's a keepalive packet, then just eat it.
+ * If it's an encapsulated packet, then pass it to the
+ * IPsec xfrm input.
+ * Returns 0 if skb passed to xfrm or was dropped.
+ * Returns >0 if skb should be passed to UDP.
+ * Returns <0 if skb should be resubmitted (-ret is protocol)
+ */
+int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
+{
+
+#ifndef CONFIG_XFRM
+	return 1;
+#else
+	struct udp_sock *up = udp_sk(sk);
+	struct udphdr *uh;
+	struct ipv6hdr *iph;
+	int iphlen, len;
+
+	__u8 *udpdata;
+	__be32 *udpdata32;
+	__u16 encap_type = up->encap_type;
+
+
+
+	/* if this is not encapsulated socket, then just return now */
+	if (!encap_type)
+		return 1;
+
+	/* If this is a paged skb, make sure we pull up
+	 * whatever data we need to look at. */
+	len = skb->len - sizeof(struct udphdr);
+	if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
+		return 1;
+
+	/* Now we can get the pointers */
+	uh = udp_hdr(skb);
+	udpdata = (__u8 *)uh + sizeof(struct udphdr);
+	udpdata32 = (__be32 *)udpdata;
+
+	switch (encap_type) {
+	default:
+	case UDP_ENCAP_ESPINUDP:
+		/* Check if this is a keepalive packet.  If so, eat it. */
+		if (len == 1 && udpdata[0] == 0xff) {
+			goto drop;
+		} else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {
+			/* ESP Packet without Non-ESP header */
+			len = sizeof(struct udphdr);
+		} else
+			/* Must be an IKE packet.. pass it through */
+			return 1;
+		break;
+	case UDP_ENCAP_ESPINUDP_NON_IKE:
+		/* Check if this is a keepalive packet.  If so, eat it. */
+		if (len == 1 && udpdata[0] == 0xff) {
+			goto drop;
+		} else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
+			   udpdata32[0] == 0 && udpdata32[1] == 0) {
+
+			/* ESP Packet with Non-IKE marker */
+			len = sizeof(struct udphdr) + 2 * (sizeof(u32) * 4);
+		} else
+			/* Must be an IKE packet.. pass it through */
+			return 1;
+		break;
+	}
+
+	/* At this point we are sure that this is an ESPinUDP packet,
+	 * so we need to remove 'len' bytes from the packet (the UDP
+	 * header and optional ESP marker bytes) and then modify the
+	 * protocol to ESP, and then call into the transform receiver.
+	 */
+	if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)){
+		goto drop;
+	}
+
+	/* Now we can update and verify the packet length... */
+	iph = ipv6_hdr(skb);
+	iphlen = ntohs(iph->payload_len);
+	if (skb->len < iphlen) {
+		/* packet is too small!?! */
+		goto drop;
+	}
+
+	/* pull the data buffer up to the ESP header and set the
+	 * transport header to point to ESP.  Keep UDP on the stack
+	 * for later.
+	 */
+	__skb_pull(skb, len);
+	skb_reset_transport_header(skb);
+
+	/* process ESP */
+	return xfrm6_rcv_encap(skb, IPPROTO_ESP, 0, encap_type);
+
+drop:
+	kfree_skb(skb);
+	return 0;
+#endif
+}
+
 
 int xfrm6_rcv(struct sk_buff *skb)
 {
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 4edefbd..1a72eb2 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1610,11 +1610,7 @@
 }
 
 /* ADD/UPD/DEL */
-#if NLKEY_SUPPORT
-static int key_notify_sa(struct net *net, struct xfrm_state *x, const struct km_event *c)
-#else
 static int key_notify_sa(struct xfrm_state *x, const struct km_event *c)
-#endif
 {
 	struct sk_buff *skb;
 	struct sadb_msg *hdr;
@@ -1635,10 +1631,6 @@
 
 	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xs_net(x));
 
-#ifdef NLKEY_SUPPORT
-	/* now sent message also to the user space through NETLINK_KEY socket*/
-	ipsec_nlkey_send(net, x, c);
-#endif
 	return 0;
 }
 
@@ -1877,11 +1869,7 @@
 	return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
 }
 
-#if defined(NLKEY_SUPPORT)
-static int key_notify_sa_flush(struct net *net, const struct km_event *c)
-#else
 static int key_notify_sa_flush(const struct km_event *c)
-#endif
 {
 	struct sk_buff *skb;
 	struct sadb_msg *hdr;
@@ -1900,11 +1888,6 @@
 
 	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
 
-#ifdef NLKEY_SUPPORT
-	/* now sent message also to the user space through NETLINK_KEY socket*/
-	ipsec_nlkey_send(net, NULL, c);
-#endif
-
 	return 0;
 }
 
@@ -3129,11 +3112,7 @@
 	return 0;
 }
 
-#if defined(NLKEY_SUPPORT)
-static int key_notify_sa_expire(struct net *net, struct xfrm_state *x, const struct km_event *c)
-#else
 static int key_notify_sa_expire(struct xfrm_state *x, const struct km_event *c)
-#endif
 {
 	struct sk_buff *out_skb;
 	struct sadb_msg *out_hdr;
@@ -3161,10 +3140,6 @@
 
 	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x));
 
-#ifdef NLKEY_SUPPORT
-	/* now sent message also to the user space through NETLINK_KEY socket*/
-	ipsec_nlkey_send(net, x, c);
-#endif
 	return 0;
 }
 
@@ -3173,30 +3148,24 @@
 	struct net *net = x ? xs_net(x) : c->net;
 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
 
+
+#ifdef NLKEY_SUPPORT
+	/* send message to the user space through NETLINK_KEY socket*/
+	ipsec_nlkey_send(net, x, c);
+#endif
+
 	if (atomic_read(&net_pfkey->socks_nr) == 0)
 		return 0;
 
 	switch (c->event) {
 	case XFRM_MSG_EXPIRE:
-#if NLKEY_SUPPORT
-		return key_notify_sa_expire(net, x, c);
-#else
 		return key_notify_sa_expire(x, c);
-#endif
 	case XFRM_MSG_DELSA:
 	case XFRM_MSG_NEWSA:
 	case XFRM_MSG_UPDSA:
-#if NLKEY_SUPPORT
-		return key_notify_sa(net, x, c);
-#else
-	return key_notify_sa(x, c);
-#endif
+		return key_notify_sa(x, c);
 	case XFRM_MSG_FLUSHSA:
-#if NLKEY_SUPPORT
-		return key_notify_sa_flush(net, c);
-#else
 		return key_notify_sa_flush(c);
-#endif
 	case XFRM_MSG_NEWAE: /* not yet supported */
 		break;
 	default:
@@ -4489,6 +4458,60 @@
 EXPORT_SYMBOL(ipsec_nlkey_flow);
 
 
+int ipsec_nlkey_flow_remove(struct flowi *fl, u16 family, u16 dir)
+{
+	struct sk_buff *skb;
+	struct nlkey_msg msg;
+	struct nlmsghdr *nlh = NULL;
+	unsigned short *p;
+	gfp_t allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+
+	
+	//printk(KERN_INFO "ipsec_nlkey_flow_remove\n");
+
+	/* next message to build */
+	memset(&msg, 0, sizeof(struct nlkey_msg));
+	msg.fcode = NLKEY_FLOW_REMOVE;
+
+	p = msg.payload;
+	// flow family
+	*p++ = family;
+	msg.length += sizeof(unsigned short);
+	// flow family
+	*p++ = dir;
+	msg.length += sizeof(unsigned short);
+	// flow descriptor
+	memcpy(p, fl, sizeof(struct flowi));
+	msg.length +=sizeof(struct flowi);
+	p+=sizeof(struct flowi) / sizeof(u16);
+
+	skb = alloc_skb(NLMSG_SPACE(NLKEY_MSG_LEN + NLKEY_HDR_LEN), allocation);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	/* prepare netlink message for kernel to user space direction */
+	nlh = (struct nlmsghdr *)skb_put(skb, NLMSG_SPACE(NLKEY_HDR_LEN + msg.length));
+	memcpy(NLMSG_DATA(nlh), (unsigned char *)&msg, (NLKEY_HDR_LEN + msg.length));
+	
+	/* whole length of the message i.e. header + payload */
+	nlh->nlmsg_len = NLMSG_SPACE(NLKEY_HDR_LEN + msg.length);
+
+	/* from kernel */
+	nlh->nlmsg_pid = 0; 
+	nlh->nlmsg_flags = 0;
+        nlh->nlmsg_type = 0;
+	NETLINK_CB(skb).pid = 0;
+	NETLINK_CB(skb).dst_group = 1;	
+
+		
+        return(netlink_broadcast(nlkey_socket, skb, 0, 1, allocation));
+
+	
+}
+EXPORT_SYMBOL(ipsec_nlkey_flow_remove);
+
+
+
 static void ipsec_nlkey_init(void)
 {
 	printk(KERN_INFO "Initializing NETLINK_KEY socket\n");
diff --git a/net/netfilter/comcerto_fp_netfilter.c b/net/netfilter/comcerto_fp_netfilter.c
index 538c3d5..bc6ef68 100644
--- a/net/netfilter/comcerto_fp_netfilter.c
+++ b/net/netfilter/comcerto_fp_netfilter.c
@@ -38,7 +38,7 @@
 		goto done;
 
 	protonum = nf_ct_protonum(ct);
-	if ((protonum != IPPROTO_TCP) && (protonum != IPPROTO_UDP))
+	if ((protonum != IPPROTO_TCP) && (protonum != IPPROTO_UDP) && (protonum != IPPROTO_IPIP))
 		goto done;
 
 	dir = CTINFO2DIR(ctinfo);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 1c6a403..3d7fe03 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1407,6 +1407,7 @@
 }
 EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable);
 
+#ifdef CONFIG_COMCERTO_FP
 int nf_conntrack_set_dpi_allow_report(struct sk_buff *skb)
 {
 	int err = 0;
@@ -1433,7 +1434,9 @@
 
 	set_bit(IPS_DPI_ALLOWED_BIT, &ct->status);
 
+#ifdef CONFIG_NF_CONNTRACK_MARK
 	ct->mark = mark;
+#endif
 
 	nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
 
@@ -1442,6 +1445,7 @@
 	return err;
 }
 EXPORT_SYMBOL(nf_conntrack_set_dpi_allow_and_mark);
+#endif
 
 int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
 {