Merge "msm_11ad: Add 11ad platform driver" into msm-4.9
diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-qcom-geni.txt b/Documentation/devicetree/bindings/i2c/qcom,i2c-qcom-geni.txt
new file mode 100644
index 0000000..f6b7552
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-qcom-geni.txt
@@ -0,0 +1,22 @@
+GENI based Qualcomm Technologies Inc Universal Peripheral version 3 (QUPv3)
+								I2C controller
+
+Required properties:
+ - compatible: Should be:
+   * "qcom,i2c-geni.
+ - reg: Should contain QUP register address and length.
+ - interrupts: Should contain I2C interrupt.
+ - #address-cells: Should be <1> Address cells for i2c device address
+ - #size-cells: Should be <0> as i2c addresses have no size component
+
+Child nodes should conform to i2c bus binding.
+
+Example:
+
+i2c@a94000 {
+	compatible = "qcom,i2c-geni";
+	reg = <0xa94000 0x4000>;
+	interrupts = <GIC_SPI 358 0>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+};
diff --git a/Documentation/devicetree/bindings/qdsp/msm-cdsp-loader.txt b/Documentation/devicetree/bindings/qdsp/msm-cdsp-loader.txt
new file mode 100644
index 0000000..155514f
--- /dev/null
+++ b/Documentation/devicetree/bindings/qdsp/msm-cdsp-loader.txt
@@ -0,0 +1,16 @@
+Qualcomm Technologies, Inc. CDSP Loader Driver
+
+msm-cdsp-loader driver implements the mechanism that allows to load CDSP firmware images.
+
+Required properties:
+
+ - compatible:  This must be "qcom,msm-cdsp-loader".
+ - qcom,proc-img-to-load: CDSP firmware name, must be "cdsp".
+
+Example:
+ The following for sdm660.
+
+	qcom,msm-cdsp-loader {
+		compatible = "qcom,cdsp-loader";
+		qcom,proc-img-to-load = "cdsp";
+	};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 00be82f..63ea69d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -548,6 +548,31 @@
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
+config ARCH_QCOM
+       bool "Qualcomm MSM (non-multiplatform)"
+       select ARCH_REQUIRE_GPIOLIB
+       select CPU_V7
+       select AUTO_ZRELADDR
+       select HAVE_SMP
+       select CLKDEV_LOOKUP
+       select GENERIC_CLOCKEVENTS
+       select GENERIC_ALLOCATOR
+       select ARM_PATCH_PHYS_VIRT
+       select ARM_HAS_SG_CHAIN
+       select ARCH_HAS_OPP
+       select SOC_BUS
+       select MULTI_IRQ_HANDLER
+       select PM_OPP
+       select SPARSE_IRQ
+       select USE_OF
+       select PINCTRL
+       help
+         Support for Qualcomm MSM/QSD based systems.  This runs on the
+         apps processor of the MSM/QSD and depends on a shared memory
+         interface to the modem processor which runs the baseband
+         stack and controls some vital subsystems
+         (clock and power control, etc).
+
 config ARCH_RPC
 	bool "RiscPC"
 	depends on MMU
@@ -1478,7 +1503,7 @@
 config ARCH_NR_GPIO
 	int
 	default 1024 if ARCH_BRCMSTB || ARCH_SHMOBILE || ARCH_TEGRA || \
-		ARCH_ZYNQ
+		ARCH_ZYNQ || ARCH_QCOM
 	default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \
 		SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210
 	default 416 if ARCH_SUNXI
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 17dcd94..771896f 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1712,7 +1712,7 @@
 config UNCOMPRESS_INCLUDE
 	string
 	default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \
-					PLAT_SAMSUNG || ARM_SINGLE_ARMV7M
+				ARCH_QCOM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M
 	default "mach/uncompress.h"
 
 config EARLY_PRINTK
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index b53a7b4..f56516c 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -309,6 +309,8 @@
 KBUILD_DTBS := dtbs
 endif
 
+DTSSUBDIR	:= qcom
+
 all:	$(KBUILD_IMAGE) $(KBUILD_DTBS)
 
 boot := arch/arm/boot
@@ -337,13 +339,9 @@
 %.dtb: | scripts
 	$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
 
-PHONY += dtbs dtbs_install
-
-dtbs: prepare scripts
-	$(Q)$(MAKE) $(build)=$(boot)/dts
-
-dtbs_install:
-	$(Q)$(MAKE) $(dtbinst)=$(boot)/dts
+dtbs: scripts
+	$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs
+	$(foreach DIR, $(DTSSUBDIR), $(Q)$(MAKE) $(build)=$(boot)/dts/$(DIR) MACHINE=$(MACHINE) dtbs)
 
 PHONY += vdso_install
 vdso_install:
@@ -352,7 +350,7 @@
 endif
 
 zImage-dtb: vmlinux scripts dtbs
-	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) DTSSUBDIR=$(DTSSUBDIR) $(boot)/$@
 
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index da75630..4175dfe 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -13,10 +13,11 @@
 
 OBJCOPYFLAGS	:=-O binary -R .comment -S
 
-ifneq ($(MACHINE),)
-include $(MACHINE)/Makefile.boot
-endif
 include $(srctree)/arch/arm/boot/dts/Makefile
+ifneq ($(DTSSUBDIR),)
+DTSSUBDIR_INCS=$(foreach DIR, $(DTSSUBDIR), $(addsuffix /Makefile, $(addprefix $(srctree)/arch/arm/boot/dts/, $(DIR))))
+include $(DTSSUBDIR_INCS)
+endif
 
 # Note: the following conditions must always be true:
 #   ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 54f95d3..4266ea6 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -970,5 +970,10 @@
 targets += dtbs dtbs_install
 targets += $(DTB_LIST)
 
+ifeq ($(CONFIG_ARM64),y)
 always		:= $(DTB_LIST)
+else
+dtbs: $(addprefix $(obj)/, $(DTB_LIST))
+	$(Q)rm -f $(obj)/../*.dtb
+endif
 clean-files	:= *.dtb
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
new file mode 100644
index 0000000..14422e5
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -0,0 +1,16 @@
+
+
+
+ifeq ($(CONFIG_ARM64),y)
+always          := $(dtb-y)
+subdir-y        := $(dts-dirs)
+else
+targets += dtbs
+targets += $(addprefix ../, $(dtb-y))
+
+$(obj)/../%.dtb: $(src)/%.dts FORCE
+	$(call if_changed_dep,dtc)
+
+dtbs: $(addprefix $(obj)/../,$(dtb-y))
+endif
+clean-files := *.dtb
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index bdd283b..58c6398 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -94,6 +94,21 @@
  *	DMA Cache Coherency
  *	===================
  *
+ *	dma_inv_range(start, end)
+ *
+ *		Invalidate (discard) the specified virtual address range.
+ *		May not write back any entries.  If 'start' or 'end'
+ *		are not cache line aligned, those lines must be written
+ *		back.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
+ *	dma_clean_range(start, end)
+ *
+ *		Clean (write back) the specified virtual address range.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
  *	dma_flush_range(start, end)
  *
  *		Clean and invalidate the specified virtual address range.
@@ -115,6 +130,8 @@ struct cpu_cache_fns {
 	void (*dma_map_area)(const void *, size_t, int);
 	void (*dma_unmap_area)(const void *, size_t, int);
 
+	void (*dma_inv_range)(const void *, const void *);
+	void (*dma_clean_range)(const void *, const void *);
 	void (*dma_flush_range)(const void *, const void *);
 };
 
@@ -140,6 +157,8 @@ extern struct cpu_cache_fns cpu_cache;
  * is visible to DMA, or data written by DMA to system memory is
  * visible to the CPU.
  */
+#define dmac_inv_range			cpu_cache.dma_inv_range
+#define dmac_clean_range		cpu_cache.dma_clean_range
 #define dmac_flush_range		cpu_cache.dma_flush_range
 
 #else
@@ -159,6 +178,8 @@ extern void __cpuc_flush_dcache_area(void *, size_t);
  * is visible to DMA, or data written by DMA to system memory is
  * visible to the CPU.
  */
+extern void dmac_inv_range(const void *, const void *);
+extern void dmac_clean_range(const void *, const void *);
 extern void dmac_flush_range(const void *, const void *);
 
 #endif
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
index 01c3d92..d14f310 100644
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -155,6 +155,8 @@ static inline void nop_dma_unmap_area(const void *s, size_t l, int f) { }
 #define __cpuc_flush_dcache_area	__glue(_CACHE,_flush_kern_dcache_area)
 
 #define dmac_flush_range		__glue(_CACHE,_dma_flush_range)
+#define dmac_inv_range			__glue(_CACHE, _dma_inv_range)
+#define dmac_clean_range		__glue(_CACHE, _dma_clean_range)
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 021692c..66003a8 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -29,6 +29,7 @@
 #include <asm/byteorder.h>
 #include <asm/memory.h>
 #include <asm-generic/pci_iomap.h>
+#include <linux/msm_rtb.h>
 #include <xen/xen.h>
 
 /*
@@ -62,23 +63,21 @@ void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen);
  * the bus. Rather than special-case the machine, just let the compiler
  * generate the access for CPUs prior to ARMv6.
  */
-#define __raw_readw(a)         (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
-#define __raw_writew(v,a)      ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)))
+#define __raw_readw_no_log(a)         (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
+#define __raw_writew_no_log(v, a)      ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)))
 #else
 /*
  * When running under a hypervisor, we want to avoid I/O accesses with
  * writeback addressing modes as these incur a significant performance
  * overhead (the address generation must be emulated in software).
  */
-#define __raw_writew __raw_writew
-static inline void __raw_writew(u16 val, volatile void __iomem *addr)
+static inline void __raw_writew_no_log(u16 val, volatile void __iomem *addr)
 {
 	asm volatile("strh %1, %0"
 		     : : "Q" (*(volatile u16 __force *)addr), "r" (val));
 }
 
-#define __raw_readw __raw_readw
-static inline u16 __raw_readw(const volatile void __iomem *addr)
+static inline u16 __raw_readw_no_log(const volatile void __iomem *addr)
 {
 	u16 val;
 	asm volatile("ldrh %0, %1"
@@ -88,22 +87,30 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
 }
 #endif
 
-#define __raw_writeb __raw_writeb
-static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
+static inline void __raw_writeb_no_log(u8 val, volatile void __iomem *addr)
 {
 	asm volatile("strb %1, %0"
 		     : : "Qo" (*(volatile u8 __force *)addr), "r" (val));
 }
 
-#define __raw_writel __raw_writel
-static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+static inline void __raw_writel_no_log(u32 val, volatile void __iomem *addr)
 {
 	asm volatile("str %1, %0"
 		     : : "Qo" (*(volatile u32 __force *)addr), "r" (val));
 }
 
-#define __raw_readb __raw_readb
-static inline u8 __raw_readb(const volatile void __iomem *addr)
+static inline void __raw_writeq_no_log(u64 val, volatile void __iomem *addr)
+{
+	register u64 v asm ("r2");
+
+	v = val;
+
+	asm volatile("strd %1, %0"
+		     : "+Qo" (*(volatile u64 __force *)addr)
+		     : "r" (v));
+}
+
+static inline u8 __raw_readb_no_log(const volatile void __iomem *addr)
 {
 	u8 val;
 	asm volatile("ldrb %0, %1"
@@ -112,8 +119,7 @@ static inline u8 __raw_readb(const volatile void __iomem *addr)
 	return val;
 }
 
-#define __raw_readl __raw_readl
-static inline u32 __raw_readl(const volatile void __iomem *addr)
+static inline u32 __raw_readl_no_log(const volatile void __iomem *addr)
 {
 	u32 val;
 	asm volatile("ldr %0, %1"
@@ -122,6 +128,58 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
 	return val;
 }
 
+static inline u64 __raw_readq_no_log(const volatile void __iomem *addr)
+{
+	register u64 val asm ("r2");
+
+	asm volatile("ldrd %1, %0"
+		     : "+Qo" (*(volatile u64 __force *)addr),
+		       "=r" (val));
+	return val;
+}
+
+/*
+ * There may be cases when clients don't want to support or can't support the
+ * logging. The appropriate functions can be used but clients should carefully
+ * consider why they can't support the logging.
+ */
+
+#define __raw_write_logged(v, a, _t)	({ \
+	int _ret; \
+	volatile void __iomem *_a = (a); \
+	void *_addr = (void __force *)(_a); \
+	_ret = uncached_logk(LOGK_WRITEL, _addr); \
+	ETB_WAYPOINT; \
+	__raw_write##_t##_no_log((v), _a); \
+	if (_ret) \
+		LOG_BARRIER; \
+	})
+
+
+#define __raw_writeb(v, a)	__raw_write_logged((v), (a), b)
+#define __raw_writew(v, a)	__raw_write_logged((v), (a), w)
+#define __raw_writel(v, a)	__raw_write_logged((v), (a), l)
+#define __raw_writeq(v, a)	__raw_write_logged((v), (a), q)
+
+#define __raw_read_logged(a, _l, _t)		({ \
+	unsigned _t __a; \
+	const volatile void __iomem *_a = (a); \
+	void *_addr = (void __force *)(_a); \
+	int _ret; \
+	_ret = uncached_logk(LOGK_READL, _addr); \
+	ETB_WAYPOINT; \
+	__a = __raw_read##_l##_no_log(_a);\
+	if (_ret) \
+		LOG_BARRIER; \
+	__a; \
+	})
+
+
+#define __raw_readb(a)		__raw_read_logged((a), b, char)
+#define __raw_readw(a)		__raw_read_logged((a), w, short)
+#define __raw_readl(a)		__raw_read_logged((a), l, int)
+#define __raw_readq(a)		__raw_read_logged((a), q, long long)
+
 /*
  * Architecture ioremap implementation.
  */
@@ -291,18 +349,32 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
 					__raw_readw(c)); __r; })
 #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
 					__raw_readl(c)); __r; })
+#define readq_relaxed(c) ({ u64 __r = le64_to_cpu((__force __le64) \
+					__raw_readq(c)); __r; })
+#define readb_relaxed_no_log(c)	({ u8 __r = __raw_readb_no_log(c); __r; })
+#define readl_relaxed_no_log(c) ({ u32 __r = le32_to_cpu((__force __le32) \
+					__raw_readl_no_log(c)); __r; })
+#define readq_relaxed_no_log(c) ({ u64 __r = le64_to_cpu((__force __le64) \
+					__raw_readq_no_log(c)); __r; })
 
-#define writeb_relaxed(v,c)	__raw_writeb(v,c)
-#define writew_relaxed(v,c)	__raw_writew((__force u16) cpu_to_le16(v),c)
-#define writel_relaxed(v,c)	__raw_writel((__force u32) cpu_to_le32(v),c)
+
+#define writeb_relaxed(v, c)	__raw_writeb(v, c)
+#define writew_relaxed(v, c)	__raw_writew((__force u16) cpu_to_le16(v), c)
+#define writel_relaxed(v, c)	__raw_writel((__force u32) cpu_to_le32(v), c)
+#define writeq_relaxed(v, c)	__raw_writeq((__force u64) cpu_to_le64(v), c)
+#define writeb_relaxed_no_log(v, c)	((void)__raw_writeb_no_log((v), (c)))
+#define writel_relaxed_no_log(v, c) __raw_writel_no_log((__force u32) cpu_to_le32(v), c)
+#define writeq_relaxed_no_log(v, c) __raw_writeq_no_log((__force u64) cpu_to_le64(v), c)
 
 #define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(); __v; })
 #define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })
 #define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(); __v; })
+#define readq(c)		({ u64 __v = readq_relaxed(c); __iormb(); __v; })
 
 #define writeb(v,c)		({ __iowmb(); writeb_relaxed(v,c); })
 #define writew(v,c)		({ __iowmb(); writew_relaxed(v,c); })
 #define writel(v,c)		({ __iowmb(); writel_relaxed(v,c); })
+#define writeq(v, c)		({ __iowmb(); writeq_relaxed(v, c); })
 
 #define readsb(p,d,l)		__raw_readsb(p,d,l)
 #define readsw(p,d,l)		__raw_readsw(p,d,l)
@@ -410,6 +482,23 @@ void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size);
 
 void iounmap(volatile void __iomem *iomem_cookie);
 #define iounmap iounmap
+/*
+ * io{read,write}{8,16,32,64} macros
+ */
+#ifndef ioread8
+#define ioread8(p)	({ unsigned int __v = __raw_readb(p); __iormb(); __v; })
+#define ioread16(p)	({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; })
+#define ioread32(p)	({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; })
+#define ioread64(p)	({ unsigned int __v = le64_to_cpu((__force __le64)__raw_readq(p)); __iormb(); __v; })
+
+#define ioread64be(p)	({ unsigned int __v = be64_to_cpu((__force __be64)__raw_readq(p)); __iormb(); __v; })
+
+#define iowrite8(v, p)	({ __iowmb(); __raw_writeb(v, p); })
+#define iowrite16(v, p)	({ __iowmb(); __raw_writew((__force __u16)cpu_to_le16(v), p); })
+#define iowrite32(v, p)	({ __iowmb(); __raw_writel((__force __u32)cpu_to_le32(v), p); })
+#define iowrite64(v, p)	({ __iowmb(); __raw_writeq((__force __u64)cpu_to_le64(v), p); })
+
+#define iowrite64be(v, p) ({ __iowmb(); __raw_writeq((__force __u64)cpu_to_be64(v), p); })
 
 void *arch_memremap_wb(phys_addr_t phys_addr, size_t size);
 #define arch_memremap_wb arch_memremap_wb
@@ -431,6 +520,7 @@ extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
 #define ioport_unmap ioport_unmap
 extern void ioport_unmap(void __iomem *addr);
 #endif
+#endif
 
 struct pci_dev;
 
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index 46ed10a..6e6ebcb 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -1,30 +1,46 @@
-menuconfig ARCH_QCOM
-	bool "Qualcomm Support"
-	depends on ARCH_MULTI_V7
-	select ARCH_SUPPORTS_BIG_ENDIAN
-	select ARM_GIC
-	select ARM_AMBA
-	select PINCTRL
-	select QCOM_SCM if SMP
-	help
-	  Support for Qualcomm's devicetree based systems.
-
 if ARCH_QCOM
+menu "QCOM SoC Type"
 
 config ARCH_MSM8X60
 	bool "Enable support for MSM8X60"
+	select ARCH_SUPPORTS_BIG_ENDIAN
+	select ARM_GIC
+	select ARM_AMBA
+	select QCOM_SCM if SMP
 	select CLKSRC_QCOM
+	select CLKSRC_OF
+	select COMMON_CLK
 
 config ARCH_MSM8960
 	bool "Enable support for MSM8960"
 	select CLKSRC_QCOM
+	select ARCH_SUPPORTS_BIG_ENDIAN
+	select ARM_GIC
+	select ARM_AMBA
+	select QCOM_SCM if SMP
+	select CLKSRC_OF
+	select COMMON_CLK
+
 
 config ARCH_MSM8974
 	bool "Enable support for MSM8974"
 	select HAVE_ARM_ARCH_TIMER
+	select ARCH_SUPPORTS_BIG_ENDIAN
+	select ARM_GIC
+	select ARM_AMBA
+	select QCOM_SCM if SMP
+	select CLKSRC_OF
+	select COMMON_CLK
 
 config ARCH_MDM9615
 	bool "Enable support for MDM9615"
 	select CLKSRC_QCOM
+	select ARCH_SUPPORTS_BIG_ENDIAN
+	select ARM_GIC
+	select ARM_AMBA
+	select QCOM_SCM if SMP
+	select CLKSRC_OF
+	select COMMON_CLK
 
+endmenu
 endif
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index a134d8a..2ddf364 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -349,7 +349,7 @@
  *	- start   - virtual start address of region
  *	- end     - virtual end address of region
  */
-v7_dma_inv_range:
+ENTRY(v7_dma_inv_range)
 	dcache_line_size r2, r3
 	sub	r3, r2, #1
 	tst	r0, r3
@@ -377,7 +377,7 @@
  *	- start   - virtual start address of region
  *	- end     - virtual end address of region
  */
-v7_dma_clean_range:
+ENTRY(v7_dma_clean_range)
 	dcache_line_size r2, r3
 	sub	r3, r2, #1
 	bic	r0, r0, r3
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index 0d40c28..60bd916 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -325,6 +325,8 @@
 	.long	\name\()_flush_kern_dcache_area
 	.long	\name\()_dma_map_area
 	.long	\name\()_dma_unmap_area
+	.long   \name\()_dma_inv_range
+	.long   \name\()_dma_clean_range
 	.long	\name\()_dma_flush_range
 	.size	\name\()_cache_fns, . - \name\()_cache_fns
 .endm
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index 054b491..70e8b7d 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -30,6 +30,9 @@ EXPORT_SYMBOL(__cpuc_flush_user_all);
 EXPORT_SYMBOL(__cpuc_flush_user_range);
 EXPORT_SYMBOL(__cpuc_coherent_kern_range);
 EXPORT_SYMBOL(__cpuc_flush_dcache_area);
+EXPORT_SYMBOL(dmac_inv_range);
+EXPORT_SYMBOL(dmac_clean_range);
+EXPORT_SYMBOL(dmac_flush_range);
 #else
 EXPORT_SYMBOL(cpu_cache);
 #endif
diff --git a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
index d36c0ff..e7ff343 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
@@ -13,11 +13,19 @@
 &soc {
 
 	replicator_qdss: replicator@6046000 {
-		compatible = "arm,coresight-replicator";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b909>;
+
+		reg = <0x6046000 0x1000>;
+		reg-names = "replicator-base";
 
 		coresight-name = "coresight-replicator";
 
-		ports{
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "apb_pclk", "core_a_clk";
+
+		ports {
 			#address-cells = <1>;
 			#size-cells = <0>;
 
@@ -40,7 +48,215 @@
 		};
 	};
 
-	tmc_etr:tmc@6048000 {
+	replicator_swao: replicator@6b0a000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b909>;
+
+		reg = <0x6b0a000 0x1000>;
+		reg-names = "replicator-base";
+
+		coresight-name = "coresight-replicator-swao";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "apb_pclk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				replicator_swao_in_tmc_etf_swao: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tmc_etf_swao_out_replicator>;
+				};
+			};
+
+			/* Always have EUD before funnel leading to ETR. If both
+			 * sink are active we need to give preference to EUD
+			 * over ETR
+			 */
+			port@1 {
+				reg = <1>;
+				replicator_swao_out_eud: endpoint {
+					remote-endpoint =
+					  <&eud_in_replicator_swao>;
+				};
+			};
+
+			port@2 {
+				reg = <0>;
+				replicator_swao_out_funnel_in2: endpoint {
+					remote-endpoint =
+					  <&funnel_in2_in_replicator_swao>;
+				};
+			};
+
+		};
+	};
+
+	tmc_etf_swao: tmc@6b09000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b961>;
+
+		reg = <0x6b09000 0x1000>;
+		reg-names = "tmc-base";
+
+		coresight-name = "coresight-tmc-etf-swao";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "apb_pclk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				tmc_etf_swao_out_replicator: endpoint {
+					remote-endpoint=
+					  <&replicator_swao_in_tmc_etf_swao>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				tmc_etf_swao_in_funnel_swao: endpoint {
+					slave-mode;
+					remote-endpoint=
+					  <&funnel_swao_out_tmc_etf_swao>;
+				};
+			};
+		};
+
+	};
+
+	funnel_swao:funnel@0x6b08000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6b08000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-swao";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "apb_pclk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_swao_out_tmc_etf_swao: endpoint {
+					remote-endpoint =
+						<&tmc_etf_swao_in_funnel_swao>;
+				};
+			};
+
+			port@1 {
+				reg = <7>;
+				funnel_swao_in_tpda_swao: endpoint {
+					slave-mode;
+					remote-endpoint=
+						<&tpda_swao_out_funnel_swao>;
+				};
+			};
+		};
+	};
+
+	tpda_swao: tpda@6b01000 {
+		compatible = "qcom,coresight-tpda";
+		reg = <0x6b01000 0x1000>;
+		reg-names = "tpda-base";
+
+		coresight-name = "coresight-tpda-swao";
+
+		qcom,tpda-atid = <71>;
+		qcom,dsb-elem-size = <1 32>;
+		qcom,cmb-elem-size = <0 64>;
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				tpda_swao_out_funnel_swao: endpoint {
+					remote-endpoint =
+						<&funnel_swao_in_tpda_swao>;
+				};
+
+			};
+
+			port@1 {
+				reg = <0>;
+				tpda_swao_in_tpdm_swao0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_swao0_out_tpda_swao>;
+				};
+			};
+
+			port@2 {
+				reg = <1>;
+				tpda_swao_in_tpdm_swao1: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_swao1_out_tpda_swao>;
+				};
+
+			};
+		};
+	};
+
+	tpdm_swao0: tpdm@6b02000 {
+		compatible = "qcom,coresight-tpdm";
+
+		reg = <0x6b02000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-swao-0";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		port {
+			tpdm_swao0_out_tpda_swao: endpoint {
+			remote-endpoint = <&tpda_swao_in_tpdm_swao0>;
+			};
+		};
+	};
+
+	tpdm_swao1: tpdm@6b03000 {
+		compatible = "qcom,coresight-tpdm";
+		reg = <0x6b03000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name="coresight-tpdm-swao-1";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		port {
+			tpdm_swao1_out_tpda_swao: endpoint {
+				remote-endpoint = <&tpda_swao_in_tpdm_swao1>;
+			};
+		};
+	};
+
+	tmc_etr: tmc@6048000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b961>;
 
@@ -65,7 +281,7 @@
 		};
 	};
 
-	tmc_etf:tmc@6047000 {
+	tmc_etf: tmc@6047000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b961>;
 
@@ -104,6 +320,51 @@
 
 	};
 
+	funnel_merg: funnel@6045000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6045000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-merg";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "apb_pclk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_merg_out_tmc_etf: endpoint {
+					remote-endpoint =
+						<&tmc_etf_in_funnel_merg>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				funnel_merg_in_funnel_in0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_in0_out_funnel_merg>;
+				};
+			};
+
+			port@2 {
+				reg = <2>;
+				funnel_merg_in_funnel_in2: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_in2_out_funnel_merg>;
+				};
+			};
+		};
+	};
+
 	stm: stm@6002000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b962>;
@@ -152,6 +413,24 @@
 			};
 
 			port@1 {
+				reg = <3>;
+				funnel_in0_in_funnel_spss: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_spss_out_funnel_in0>;
+				};
+			};
+
+			port@2 {
+				reg = <6>;
+				funnel_in0_in_funnel_qatb: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_qatb_out_funnel_in0>;
+				};
+			};
+
+			port@3 {
 				reg = <7>;
 				funnel_in0_in_stm: endpoint {
 					slave-mode;
@@ -161,14 +440,14 @@
 		};
 	};
 
-	funnel_merg:funnel@6045000 {
+	funnel_in2: funnel@0x6043000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b908>;
 
-		reg = <0x6045000 0x1000>;
+		reg = <0x6043000 0x1000>;
 		reg-names = "funnel-base";
 
-		coresight-name = "coresight-funnel-merg";
+		coresight-name = "coresight-funnel-in2";
 
 		clocks = <&clock_gcc RPMH_QDSS_CLK>,
 			 <&clock_gcc RPMH_QDSS_A_CLK>;
@@ -180,18 +459,325 @@
 
 			port@0 {
 				reg = <0>;
-				funnel_merg_out_tmc_etf: endpoint {
+				funnel_in2_out_funnel_merg: endpoint {
 					remote-endpoint =
-						<&tmc_etf_in_funnel_merg>;
+					  <&funnel_merg_in_funnel_in2>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				funnel_in2_in_replicator_swao: endpoint {
+					slave-mode;
+					remote-endpoint =
+					  <&replicator_swao_out_funnel_in2>;
+				};
+
+			};
+
+			port@2 {
+				reg = <5>;
+				funnel_in2_in_funnel_apss_merg: endpoint {
+					slave-mode;
+					remote-endpoint =
+					  <&funnel_apss_merg_out_funnel_in2>;
+				};
+			};
+
+		};
+	};
+
+	tpda: tpda@6004000 {
+		compatible = "qcom,coresight-tpda";
+		reg = <0x6004000 0x1000>;
+		reg-names = "tpda-base";
+
+		coresight-name = "coresight-tpda";
+
+		qcom,tpda-atid = <65>;
+		qcom,bc-elem-size = <13 32>;
+		qcom,tc-elem-size = <7 32>,
+				    <13 32>;
+		qcom,dsb-elem-size = <13 32>;
+		qcom,cmb-elem-size = <7 32>,
+				     <8 32>,
+				     <13 64>;
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				tpda_out_funnel_qatb: endpoint {
+					remote-endpoint =
+						<&funnel_qatb_in_tpda>;
+				};
+
+			};
+
+			port@1 {
+				reg = <7>;
+				tpda_in_tpdm_vsense: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_vsense_out_tpda>;
+				};
+			};
+
+			port@2 {
+				reg = <8>;
+				tpda_in_tpdm_dcc: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_dcc_out_tpda>;
+				};
+			};
+
+			port@3 {
+				reg = <13>;
+				tpda_in_tpdm_pimem: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_pimem_out_tpda>;
+				};
+			};
+		};
+	};
+
+	tpdm_pimem: tpdm@6850000 {
+		compatible = "qcom,coresight-tpdm";
+		reg = <0x6850000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-pimem";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		port {
+			tpdm_pimem_out_tpda: endpoint {
+				remote-endpoint = <&tpda_in_tpdm_pimem>;
+			};
+		};
+	};
+
+
+	tpdm_dcc: tpdm@6870000 {
+		compatible = "qcom,coresight-tpdm";
+		reg = <0x6870000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-dcc";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		port {
+			tpdm_dcc_out_tpda: endpoint {
+				remote-endpoint = <&tpda_in_tpdm_dcc>;
+			};
+		};
+	};
+
+	tpdm_vsense: tpdm@6840000 {
+		compatible = "qcom,coresight-tpdm";
+		reg = <0x6840000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-vsense";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		port{
+			tpdm_vsense_out_tpda: endpoint {
+				remote-endpoint = <&tpda_in_tpdm_vsense>;
+			};
+		};
+	};
+
+	tpda_olc: tpda@7832000 {
+		compatible = "qcom,coresight-tpda";
+		reg = <0x7832000 0x1000>;
+		reg-names = "tpda-base";
+
+		coresight-name = "coresight-tpda-olc";
+
+		qcom,tpda-atid = <69>;
+		qcom,cmb-elem-size = <0 64>;
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				tpda_olc_out_funnel_apss_merg: endpoint {
+					remote-endpoint =
+						<&funnel_apss_merg_in_tpda_olc>;
+				};
+			};
+			port@1 {
+				reg = <0>;
+				tpda_olc_in_tpdm_olc: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_olc_out_tpda_olc>;
+				};
+			};
+		};
+	};
+
+	tpdm_olc: tpdm@7830000 {
+		compatible = "qcom,coresight-tpdm";
+		reg = <0x7830000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-olc";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		port{
+			tpdm_olc_out_tpda_olc: endpoint {
+				remote-endpoint = <&tpda_olc_in_tpdm_olc>;
+			};
+		};
+	};
+
+	tpda_spss: tpda@6882000 {
+		compatible = "qcom,coresight-tpda";
+		reg = <0x6882000 0x1000>;
+		reg-names = "tpda-base";
+
+		coresight-name = "coresight-tpda-spss";
+
+		qcom,tpda-atid = <70>;
+		qcom,dsb-elem-size = <0 32>;
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				tpda_spss_out_funnel_spss: endpoint {
+					remote-endpoint =
+						<&funnel_spss_in_tpda_spss>;
+				};
+			};
+			port@1 {
+				reg = <0>;
+				tpda_spss_in_tpdm_spss: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_spss_out_tpda_spss>;
+				};
+			};
+		};
+	};
+
+	tpdm_spss: tpdm@6880000 {
+		compatible = "qcom,coresight-tpdm";
+		reg = <0x6880000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-spss";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "core_clk", "core_a_clk";
+
+		qcom,msr-fix-req;
+
+		port{
+			tpdm_spss_out_tpda_spss: endpoint {
+				remote-endpoint = <&tpda_spss_in_tpdm_spss>;
+			};
+		};
+	};
+
+	funnel_spss: funnel@6883000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6883000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-spss";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "apb_pclk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_spss_out_funnel_in0: endpoint {
+					remote-endpoint =
+					    <&funnel_in0_in_funnel_spss>;
 				};
 			};
 
 			port@1 {
 				reg = <0>;
-				funnel_merg_in_funnel_in0: endpoint {
+				funnel_spss_in_tpda_spss: endpoint {
 					slave-mode;
 					remote-endpoint =
-						<&funnel_in0_out_funnel_merg>;
+						<&tpda_spss_out_funnel_spss>;
+				};
+			};
+		};
+	};
+
+	funnel_qatb: funnel@6005000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6005000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-qatb";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "apb_pclk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_qatb_out_funnel_in0: endpoint {
+					remote-endpoint =
+						<&funnel_in0_in_funnel_qatb>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				funnel_qatb_in_tpda: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpda_out_funnel_qatb>;
 				};
 			};
 		};
@@ -389,9 +975,9 @@
 		clock-names = "core_clk", "core_a_clk";
 	};
 
-	cti_cpu0: cti@7420000 {
+	cti_cpu0: cti@7020000 {
 		compatible = "arm,coresight-cti";
-		reg = <0x7420000 0x1000>;
+		reg = <0x7020000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu0";
@@ -402,9 +988,9 @@
 		clock-names = "core_clk", "core_a_clk";
 	};
 
-	cti_cpu1: cti@7520000 {
+	cti_cpu1: cti@7120000 {
 		compatible = "arm,coresight-cti";
-		reg = <0x7520000 0x1000>;
+		reg = <0x7120000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu1";
@@ -415,9 +1001,9 @@
 		clock-names = "core_clk", "core_a_clk";
 	};
 
-	cti_cpu2: cti@7620000 {
+	cti_cpu2: cti@7220000 {
 		compatible = "arm,coresight-cti";
-		reg = <0x7620000 0x1000>;
+		reg = <0x7220000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu2";
@@ -428,9 +1014,9 @@
 		clock-names = "core_clk", "core_a_clk";
 	};
 
-	cti_cpu3: cti@7720000 {
+	cti_cpu3: cti@7320000 {
 		compatible = "arm,coresight-cti";
-		reg = <0x7720000 0x1000>;
+		reg = <0x7320000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu3";
@@ -441,9 +1027,9 @@
 		clock-names = "core_clk", "core_a_clk";
 	};
 
-	cti_cpu4: cti@7020000 {
+	cti_cpu4: cti@7420000 {
 		compatible = "arm,coresight-cti";
-		reg = <0x7020000 0x1000>;
+		reg = <0x7420000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu4";
@@ -454,9 +1040,9 @@
 		clock-names = "core_clk", "core_a_clk";
 	};
 
-	cti_cpu5: cti@7120000 {
+	cti_cpu5: cti@7520000 {
 		compatible = "arm,coresight-cti";
-		reg = <0x7120000 0x1000>;
+		reg = <0x7520000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu5";
@@ -467,9 +1053,9 @@
 		clock-names = "core_clk", "core_a_clk";
 	};
 
-	cti_cpu6: cti@7220000 {
+	cti_cpu6: cti@7620000 {
 		compatible = "arm,coresight-cti";
-		reg = <0x7220000 0x1000>;
+		reg = <0x7620000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu6";
@@ -480,9 +1066,9 @@
 		clock-names = "core_clk", "core_a_clk";
 	};
 
-	cti_cpu7: cti@7320000 {
+	cti_cpu7: cti@7720000 {
 		compatible = "arm,coresight-cti";
-		reg = <0x7320000 0x1000>;
+		reg = <0x7720000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu7";
@@ -492,4 +1078,91 @@
 			 <&clock_gcc RPMH_QDSS_A_CLK>;
 		clock-names = "core_clk", "core_a_clk";
 	};
+
+	dummy_eud: dummy_sink {
+		compatible = "qcom,coresight-dummy";
+
+		coresight-name = "coresight-eud";
+
+		qcom,dummy-sink;
+		port {
+			eud_in_replicator_swao: endpoint {
+				slave-mode;
+				remote-endpoint =
+					<&replicator_swao_out_eud>;
+			};
+		};
+	};
+
+	funnel_apss_merg: funnel@7810000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x7810000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-apss-merg";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "apb_pclk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_apss_merg_out_funnel_in2: endpoint {
+					remote-endpoint =
+					    <&funnel_in2_in_funnel_apss_merg>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				funnel_apss_merg_in_funnel_apss: endpoint {
+					slave-mode;
+					remote-endpoint =
+					    <&funnel_apss_out_funnel_apss_merg>;
+				};
+			};
+
+			port@2 {
+				reg = <1>;
+				funnel_apss_merg_in_tpda_olc: endpoint {
+					slave-mode;
+					remote-endpoint =
+					    <&tpda_olc_out_funnel_apss_merg>;
+				};
+			};
+		};
+	};
+
+	funnel_apss: funnel@7800000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x7800000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-apss";
+
+		clocks = <&clock_gcc RPMH_QDSS_CLK>,
+			 <&clock_gcc RPMH_QDSS_A_CLK>;
+		clock-names = "apb_pclk", "core_a_clk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_apss_out_funnel_apss_merg: endpoint {
+					remote-endpoint =
+					    <&funnel_apss_merg_in_funnel_apss>;
+				};
+			};
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index f3b529c..8974ef8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -710,7 +710,7 @@
 		      <0x1f65000 0x008>,
 		      <0x1f64000 0x008>,
 		      <0x4180000 0x020>,
-		      <0x00179000 0x004>;
+		      <0xc2b0000 0x004>;
 		reg-names = "qdsp6_base", "halt_q6", "halt_modem",
 			    "halt_nc", "rmb_base", "restart_reg";
 
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index e029f82..ea34214 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -61,6 +61,7 @@
 CONFIG_PM_WAKELOCKS=y
 CONFIG_PM_WAKELOCKS_LIMIT=0
 # CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_CPU_IDLE=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -382,6 +383,8 @@
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
 CONFIG_ICNSS=y
 CONFIG_QCOM_COMMAND_DB=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_PM=y
 CONFIG_EXTCON=y
 CONFIG_IIO=y
 CONFIG_QCOM_RRADC=y
@@ -414,6 +417,8 @@
 CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
 CONFIG_CORESIGHT_QCOM_REPLICATOR=y
 CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
 CONFIG_CORESIGHT_CTI=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_SELINUX=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 6cca05a..7faf735 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -65,6 +65,7 @@
 CONFIG_PM_WAKELOCKS_LIMIT=0
 # CONFIG_PM_WAKELOCKS_GC is not set
 CONFIG_PM_DEBUG=y
+CONFIG_CPU_IDLE=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -346,6 +347,9 @@
 CONFIG_MMC_SDHCI_MSM=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
+CONFIG_EDAC_KRYO3XX_ARM64=y
+CONFIG_EDAC_KRYO3XX_ARM64_PANIC_ON_CE=y
+CONFIG_EDAC_KRYO3XX_ARM64_PANIC_ON_UE=y
 CONFIG_EDAC_QCOM_LLCC=y
 CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE=y
 CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y
@@ -394,6 +398,8 @@
 CONFIG_ICNSS=y
 CONFIG_ICNSS_DEBUG=y
 CONFIG_QCOM_COMMAND_DB=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_PM=y
 CONFIG_EXTCON=y
 CONFIG_IIO=y
 CONFIG_QCOM_RRADC=y
@@ -463,6 +469,8 @@
 CONFIG_CORESIGHT_SOURCE_ETM4X=y
 CONFIG_CORESIGHT_QCOM_REPLICATOR=y
 CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
 CONFIG_CORESIGHT_CTI=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_SELINUX=y
diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h
index ee469be..c731ca0 100644
--- a/arch/arm64/include/uapi/asm/sigcontext.h
+++ b/arch/arm64/include/uapi/asm/sigcontext.h
@@ -16,6 +16,7 @@
 #ifndef _UAPI__ASM_SIGCONTEXT_H
 #define _UAPI__ASM_SIGCONTEXT_H
 
+#ifdef CONFIG_64BIT
 #include <linux/types.h>
 
 /*
@@ -61,4 +62,35 @@ struct esr_context {
 	__u64 esr;
 };
 
+#else /* CONFIG_64BIT */
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+	unsigned long trap_no;
+	unsigned long error_code;
+	unsigned long oldmask;
+	unsigned long arm_r0;
+	unsigned long arm_r1;
+	unsigned long arm_r2;
+	unsigned long arm_r3;
+	unsigned long arm_r4;
+	unsigned long arm_r5;
+	unsigned long arm_r6;
+	unsigned long arm_r7;
+	unsigned long arm_r8;
+	unsigned long arm_r9;
+	unsigned long arm_r10;
+	unsigned long arm_fp;
+	unsigned long arm_ip;
+	unsigned long arm_sp;
+	unsigned long arm_lr;
+	unsigned long arm_pc;
+	unsigned long arm_cpsr;
+	unsigned long fault_address;
+};
+#endif /* CONFIG_64BIT */
 #endif /* _UAPI__ASM_SIGCONTEXT_H */
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index d5c4242..a69ed75 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -317,7 +317,7 @@ void die(const char *str, struct pt_regs *regs, int err)
 
 	if (!user_mode(regs))
 		bug_type = report_bug(regs->pc, regs);
-	if (bug_type != BUG_TRAP_TYPE_NONE)
+	if (bug_type != BUG_TRAP_TYPE_NONE && !strlen(str))
 		str = "Oops - BUG";
 
 	ret = __die(str, err, thread, regs);
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 3fd76d9..a13a45e 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -378,6 +378,7 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	const struct freq_tbl *f;
+	int ret;
 
 	f = qcom_find_freq(rcg->freq_tbl, rate);
 	if (!f)
@@ -392,7 +393,13 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
 		return 0;
 	}
 
-	return clk_rcg2_configure(rcg, f);
+	ret = clk_rcg2_configure(rcg, f);
+	if (ret)
+		return ret;
+
+	/* Update current frequency with the requested frequency. */
+	rcg->current_freq = rate;
+	return ret;
 }
 
 static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -410,7 +417,7 @@ static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
 static int clk_rcg2_enable(struct clk_hw *hw)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
-	unsigned long rate = clk_get_rate(hw->clk);
+	unsigned long rate;
 	const struct freq_tbl *f;
 
 	if (!rcg->enable_safe_config)
@@ -424,6 +431,7 @@ static int clk_rcg2_enable(struct clk_hw *hw)
 	 * is always on while APPS is online. Therefore, the RCG can safely be
 	 * switched.
 	 */
+	rate = rcg->current_freq;
 	f = qcom_find_freq(rcg->freq_tbl, rate);
 	if (!f)
 		return -EINVAL;
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index e5a2016..82e62c5 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -824,6 +824,7 @@ static int __init arch_timer_common_init(void)
 
 	arch_timer_banner(arch_timers_present);
 	arch_counter_register(arch_timers_present);
+	clocksource_select_force();
 	return arch_timer_arch_init();
 }
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
deleted file mode 100644
index 652331f..0000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
+++ /dev/null
@@ -1,671 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * 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.
- */
-
-#include "sde_hw_catalog.h"
-#include "sde_hw_mdss.h"
-#include "sde_hwio.h"
-
-/* VIG layer capability */
-#define VIG_17X_MASK \
-	(BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_SCALER_QSEED2) |\
-	BIT(SDE_SSPP_CSC) | BIT(SDE_SSPP_HSIC) |\
-	BIT(SDE_SSPP_PCC) | BIT(SDE_SSPP_IGC) |\
-	BIT(SDE_SSPP_MEMCOLOR) | BIT(SDE_SSPP_QOS))
-
-/* RGB layer capability */
-#define RGB_17X_MASK \
-	(BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_SCALER_RGB) |\
-	BIT(SDE_SSPP_PCC) | BIT(SDE_SSPP_IGC) | BIT(SDE_SSPP_QOS))
-
-/* DMA layer capability */
-#define DMA_17X_MASK \
-	(BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_PCC) | BIT(SDE_SSPP_IGC) |\
-	BIT(SDE_SSPP_QOS))
-
-/* Cursor layer capability */
-#define CURSOR_17X_MASK  (BIT(SDE_SSPP_SRC) | BIT(SDE_SSPP_CURSOR))
-
-#define MIXER_17X_MASK (BIT(SDE_MIXER_SOURCESPLIT) |\
-	BIT(SDE_MIXER_GC))
-
-#define DSPP_17X_MASK \
-	(BIT(SDE_DSPP_IGC) | BIT(SDE_DSPP_PCC) |\
-	BIT(SDE_DSPP_GC) | BIT(SDE_DSPP_HSIC) | BIT(SDE_DSPP_GAMUT) |\
-	BIT(SDE_DSPP_DITHER) | BIT(SDE_DSPP_HIST) | BIT(SDE_DSPP_MEMCOLOR) |\
-	BIT(SDE_DSPP_SIXZONE) | BIT(SDE_DSPP_AD) | BIT(SDE_DSPP_VLUT))
-
-#define PINGPONG_17X_MASK \
-	(BIT(SDE_PINGPONG_TE) | BIT(SDE_PINGPONG_DSC))
-
-#define PINGPONG_17X_SPLIT_MASK \
-	(PINGPONG_17X_MASK | BIT(SDE_PINGPONG_SPLIT) |\
-	BIT(SDE_PINGPONG_TE2))
-
-#define WB01_17X_MASK \
-	(BIT(SDE_WB_LINE_MODE) | BIT(SDE_WB_BLOCK_MODE) |\
-	BIT(SDE_WB_CSC) | BIT(SDE_WB_CHROMA_DOWN) | BIT(SDE_WB_DOWNSCALE) |\
-	BIT(SDE_WB_DITHER) | BIT(SDE_WB_TRAFFIC_SHAPER) |\
-	BIT(SDE_WB_UBWC_1_0) | BIT(SDE_WB_YUV_CONFIG))
-
-#define WB2_17X_MASK \
-	(BIT(SDE_WB_LINE_MODE) | BIT(SDE_WB_TRAFFIC_SHAPER) |\
-	BIT(SDE_WB_YUV_CONFIG))
-
-#define DECIMATION_17X_MAX_H	4
-#define DECIMATION_17X_MAX_V	4
-
-#define RES_1080p		((u64)(1088*1920))
-#define RES_UHD			((u64)(3840*2160))
-
-static const struct sde_format_extended plane_formats[] = {
-	{DRM_FORMAT_ARGB8888, 0},
-	{DRM_FORMAT_ABGR8888, 0},
-	{DRM_FORMAT_RGBA8888, 0},
-	{DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-	{DRM_FORMAT_BGRA8888, 0},
-	{DRM_FORMAT_XRGB8888, 0},
-	{DRM_FORMAT_RGBX8888, 0},
-	{DRM_FORMAT_RGBX8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-	{DRM_FORMAT_RGB888, 0},
-	{DRM_FORMAT_BGR888, 0},
-	{DRM_FORMAT_RGB565, 0},
-	{DRM_FORMAT_RGB565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-	{DRM_FORMAT_BGR565, 0},
-	{DRM_FORMAT_ARGB1555, 0},
-	{DRM_FORMAT_ABGR1555, 0},
-	{DRM_FORMAT_RGBA5551, 0},
-	{DRM_FORMAT_BGRA5551, 0},
-	{DRM_FORMAT_XRGB1555, 0},
-	{DRM_FORMAT_XBGR1555, 0},
-	{DRM_FORMAT_RGBX5551, 0},
-	{DRM_FORMAT_BGRX5551, 0},
-	{DRM_FORMAT_ARGB4444, 0},
-	{DRM_FORMAT_ABGR4444, 0},
-	{DRM_FORMAT_RGBA4444, 0},
-	{DRM_FORMAT_BGRA4444, 0},
-	{DRM_FORMAT_XRGB4444, 0},
-	{DRM_FORMAT_XBGR4444, 0},
-	{DRM_FORMAT_RGBX4444, 0},
-	{DRM_FORMAT_BGRX4444, 0},
-	{0, 0},
-};
-
-static const struct sde_format_extended plane_formats_yuv[] = {
-	{DRM_FORMAT_ARGB8888, 0},
-	{DRM_FORMAT_ABGR8888, 0},
-	{DRM_FORMAT_RGBA8888, 0},
-	{DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-	{DRM_FORMAT_BGRA8888, 0},
-	{DRM_FORMAT_XRGB8888, 0},
-	{DRM_FORMAT_RGBX8888, 0},
-	{DRM_FORMAT_RGBX8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-	{DRM_FORMAT_RGB888, 0},
-	{DRM_FORMAT_BGR888, 0},
-	{DRM_FORMAT_RGB565, 0},
-	{DRM_FORMAT_RGB565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-	{DRM_FORMAT_BGR565, 0},
-	{DRM_FORMAT_ARGB1555, 0},
-	{DRM_FORMAT_ABGR1555, 0},
-	{DRM_FORMAT_RGBA5551, 0},
-	{DRM_FORMAT_BGRA5551, 0},
-	{DRM_FORMAT_XRGB1555, 0},
-	{DRM_FORMAT_XBGR1555, 0},
-	{DRM_FORMAT_RGBX5551, 0},
-	{DRM_FORMAT_BGRX5551, 0},
-	{DRM_FORMAT_ARGB4444, 0},
-	{DRM_FORMAT_ABGR4444, 0},
-	{DRM_FORMAT_RGBA4444, 0},
-	{DRM_FORMAT_BGRA4444, 0},
-	{DRM_FORMAT_XRGB4444, 0},
-	{DRM_FORMAT_XBGR4444, 0},
-	{DRM_FORMAT_RGBX4444, 0},
-	{DRM_FORMAT_BGRX4444, 0},
-	{DRM_FORMAT_NV12, 0},
-	{DRM_FORMAT_NV12, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-	{DRM_FORMAT_NV21, 0},
-	{DRM_FORMAT_NV16, 0},
-	{DRM_FORMAT_NV61, 0},
-	{DRM_FORMAT_VYUY, 0},
-	{DRM_FORMAT_UYVY, 0},
-	{DRM_FORMAT_YUYV, 0},
-	{DRM_FORMAT_YVYU, 0},
-	{DRM_FORMAT_YUV420, 0},
-	{DRM_FORMAT_YVU420, 0},
-	{0, 0},
-};
-
-static const struct sde_format_extended wb0_formats[] = {
-	{DRM_FORMAT_RGB565, 0},
-	{DRM_FORMAT_RGB888, 0},
-	{DRM_FORMAT_ARGB8888, 0},
-	{DRM_FORMAT_RGBA8888, 0},
-	{DRM_FORMAT_XRGB8888, 0},
-	{DRM_FORMAT_RGBX8888, 0},
-	{DRM_FORMAT_ARGB1555, 0},
-	{DRM_FORMAT_RGBA5551, 0},
-	{DRM_FORMAT_XRGB1555, 0},
-	{DRM_FORMAT_RGBX5551, 0},
-	{DRM_FORMAT_ARGB4444, 0},
-	{DRM_FORMAT_RGBA4444, 0},
-	{DRM_FORMAT_RGBX4444, 0},
-	{DRM_FORMAT_XRGB4444, 0},
-
-	{DRM_FORMAT_BGR565, 0},
-	{DRM_FORMAT_BGR888, 0},
-	{DRM_FORMAT_ABGR8888, 0},
-	{DRM_FORMAT_BGRA8888, 0},
-	{DRM_FORMAT_BGRX8888, 0},
-	{DRM_FORMAT_ABGR1555, 0},
-	{DRM_FORMAT_BGRA5551, 0},
-	{DRM_FORMAT_XBGR1555, 0},
-	{DRM_FORMAT_BGRX5551, 0},
-	{DRM_FORMAT_ABGR4444, 0},
-	{DRM_FORMAT_BGRA4444, 0},
-	{DRM_FORMAT_BGRX4444, 0},
-	{DRM_FORMAT_XBGR4444, 0},
-
-	{DRM_FORMAT_RGBX8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-	{DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-	{DRM_FORMAT_RGB565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-
-	{DRM_FORMAT_YUV420, 0},
-	{DRM_FORMAT_NV12, 0},
-	{DRM_FORMAT_NV16, 0},
-	{DRM_FORMAT_NV21, 0},
-	{DRM_FORMAT_NV61, 0},
-	{DRM_FORMAT_UYVY, 0},
-	{DRM_FORMAT_YUYV, 0},
-
-	{DRM_FORMAT_NV12, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-	{DRM_FORMAT_AYUV, DRM_FORMAT_MOD_QCOM_COMPRESSED},
-
-	{0, 0},
-};
-
-static const struct sde_format_extended wb2_formats[] = {
-	{DRM_FORMAT_RGB565, 0},
-	{DRM_FORMAT_RGB888, 0},
-	{DRM_FORMAT_ARGB8888, 0},
-	{DRM_FORMAT_RGBA8888, 0},
-	{DRM_FORMAT_XRGB8888, 0},
-	{DRM_FORMAT_RGBX8888, 0},
-	{DRM_FORMAT_ARGB1555, 0},
-	{DRM_FORMAT_RGBA5551, 0},
-	{DRM_FORMAT_XRGB1555, 0},
-	{DRM_FORMAT_RGBX5551, 0},
-	{DRM_FORMAT_ARGB4444, 0},
-	{DRM_FORMAT_RGBA4444, 0},
-	{DRM_FORMAT_RGBX4444, 0},
-	{DRM_FORMAT_XRGB4444, 0},
-
-	{DRM_FORMAT_BGR565, 0},
-	{DRM_FORMAT_BGR888, 0},
-	{DRM_FORMAT_ABGR8888, 0},
-	{DRM_FORMAT_BGRA8888, 0},
-	{DRM_FORMAT_BGRX8888, 0},
-	{DRM_FORMAT_ABGR1555, 0},
-	{DRM_FORMAT_BGRA5551, 0},
-	{DRM_FORMAT_XBGR1555, 0},
-	{DRM_FORMAT_BGRX5551, 0},
-	{DRM_FORMAT_ABGR4444, 0},
-	{DRM_FORMAT_BGRA4444, 0},
-	{DRM_FORMAT_BGRX4444, 0},
-	{DRM_FORMAT_XBGR4444, 0},
-
-	{DRM_FORMAT_YUV420, 0},
-	{DRM_FORMAT_NV12, 0},
-	{DRM_FORMAT_NV16, 0},
-	{DRM_FORMAT_YUYV, 0},
-
-	{0, 0},
-};
-
-/**
- * set_cfg_1xx_init(): populate sde sub-blocks reg offsets and instance counts
- */
-static inline int set_cfg_1xx_init(struct sde_mdss_cfg *cfg)
-{
-
-	/* Layer capability */
-	static const struct sde_sspp_sub_blks vig_layer = {
-		.maxlinewidth = 2560,
-		.danger_lut_linear = 0x000f,
-		.safe_lut_linear = 0xfffc,
-		.danger_lut_tile = 0xffff,
-		.safe_lut_tile = 0xff00,
-		.danger_lut_nrt = 0x0,
-		.safe_lut_nrt = 0xffff,
-		.creq_lut_nrt = 0x0,
-		.creq_vblank = 0x2,
-		.danger_vblank = 0,
-		.pixel_ram_size = 50 * 1024,
-		.maxdwnscale = 4, .maxupscale = 20,
-		.maxhdeciexp = DECIMATION_17X_MAX_H,
-		.maxvdeciexp = DECIMATION_17X_MAX_V,
-		.src_blk = {.id = SDE_SSPP_SRC,
-			.base = 0x00, .len = 0x150,},
-		.scaler_blk = {.id = SDE_SSPP_SCALER_QSEED2,
-			.base = 0x200, .len = 0x70,},
-		.csc_blk = {.id = SDE_SSPP_CSC,
-			.base = 0x320, .len = 0x44,},
-		.format_list = plane_formats_yuv,
-		.igc_blk = {.id = SDE_SSPP_IGC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.pcc_blk = {.id = SDE_SSPP_PCC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.hsic = {.id = SDE_SSPP_HSIC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.memcolor = {.id = SDE_SSPP_MEMCOLOR, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-	};
-
-	static const struct sde_sspp_sub_blks layer = {
-		.maxlinewidth = 2560,
-		.danger_lut_linear = 0x000f,
-		.safe_lut_linear = 0xfffc,
-		.danger_lut_tile = 0xffff,
-		.safe_lut_tile = 0xff00,
-		.danger_lut_nrt = 0x0,
-		.safe_lut_nrt = 0xffff,
-		.creq_lut_nrt = 0x0,
-		.creq_vblank = 0x2,
-		.danger_vblank = 0,
-		.pixel_ram_size = 50 * 1024,
-		.maxdwnscale = 4, .maxupscale = 20,
-		.maxhdeciexp = DECIMATION_17X_MAX_H,
-		.maxvdeciexp = DECIMATION_17X_MAX_V,
-		.src_blk = {.id = SDE_SSPP_SRC,
-			.base = 0x00, .len = 0x150,},
-		.scaler_blk = {.id = SDE_SSPP_SCALER_QSEED2,
-			.base = 0x200, .len = 0x70,},
-		.csc_blk = {.id = SDE_SSPP_CSC,
-			.base = 0x320, .len = 0x44,},
-		.format_list = plane_formats,
-		.igc_blk = {.id = SDE_SSPP_IGC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.pcc_blk = {.id = SDE_SSPP_PCC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-	};
-
-	static const struct sde_sspp_sub_blks dma = {
-		.maxlinewidth = 2560,
-		.danger_lut_linear = 0x000f,
-		.safe_lut_linear = 0xfffc,
-		.danger_lut_tile = 0xffff,
-		.safe_lut_tile = 0xff00,
-		.danger_lut_nrt = 0x0,
-		.safe_lut_nrt = 0xffff,
-		.creq_lut_nrt = 0x0,
-		.creq_vblank = 0x2,
-		.danger_vblank = 0,
-		.pixel_ram_size = 50 * 1024,
-		.maxdwnscale = 1, .maxupscale = 1,
-		.maxhdeciexp = DECIMATION_17X_MAX_H,
-		.maxvdeciexp = DECIMATION_17X_MAX_V,
-		.src_blk = {.id = SDE_SSPP_SRC, .base = 0x00, .len = 0x150,},
-		.scaler_blk = {.id = 0, .base = 0x00, .len = 0x0,},
-		.csc_blk = {.id = 0, .base = 0x00, .len = 0x0,},
-		.format_list = plane_formats,
-		.igc_blk = {.id = SDE_SSPP_IGC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.pcc_blk = {.id = SDE_SSPP_PCC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-	};
-
-	static const struct sde_sspp_sub_blks cursor = {
-		.maxlinewidth = 128,
-		.maxdwnscale = 1, .maxupscale = 1,
-		.maxhdeciexp = 0,
-		.maxvdeciexp = 0,
-		.src_blk = {.id = SDE_SSPP_SRC, .base = 0x00, .len = 0x150,},
-		.scaler_blk = {.id = 0, .base = 0x00, .len = 0x0,},
-		.csc_blk = {.id = 0, .base = 0x00, .len = 0x0,},
-		.format_list = plane_formats,
-	};
-
-	/* MIXER capability */
-	static const struct sde_lm_sub_blks lm = {
-		.maxwidth = 2560,
-		.maxblendstages = 7, /* excluding base layer */
-		.blendstage_base = { /* offsets relative to mixer base */
-			0x20, 0x50, 0x80, 0xB0, 0x230, 0x260, 0x290 },
-		.gc = {.id = SDE_DSPP_GC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-	};
-
-	/* DSPP capability */
-	static const struct sde_dspp_sub_blks dspp = {
-		.igc = {.id = SDE_DSPP_IGC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.pcc = {.id = SDE_DSPP_PCC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.gamut = {.id = SDE_DSPP_GAMUT, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.dither = {.id = SDE_DSPP_DITHER, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.hsic = {.id = SDE_DSPP_HSIC, .base = 0x00, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.memcolor = {.id = SDE_DSPP_MEMCOLOR, .base = 0x00, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.sixzone = {.id = SDE_DSPP_SIXZONE, .base = 0x00, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.hist = {.id = SDE_DSPP_HIST, .base = 0x00, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.gc = {.id = SDE_DSPP_GC, .base = 0x0, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-		.ad = {.id = SDE_DSPP_AD, .base = 0x00, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x3, 0x0)},
-		.vlut = {.id = SDE_DSPP_VLUT, .base = 0x1400, .len = 0x0,
-			.version = SDE_COLOR_PROCESS_VER(0x1, 0x0)},
-	};
-
-	/* PINGPONG capability */
-	static const struct sde_pingpong_sub_blks pingpong = {
-		.te = {.id = SDE_PINGPONG_TE, .base = 0x0000, .len = 0x0,
-			.version = 0x1},
-		.te2 = {.id = SDE_PINGPONG_TE2, .base = 0x2000, .len = 0x0,
-			.version = 0x1},
-		.dsc = {.id = SDE_PINGPONG_DSC, .base = 0x10000, .len = 0x0,
-			.version = 0x1},
-	};
-
-	/* Writeback 0/1 capability */
-	static const struct sde_wb_sub_blocks wb0 = {
-		.maxlinewidth = 2048,
-	};
-
-	/* Writeback 2 capability */
-	static const struct sde_wb_sub_blocks wb2 = {
-		.maxlinewidth = 4096,
-	};
-
-	static const struct sde_vbif_dynamic_ot_cfg dynamic_ot_cfg[] = {
-		{RES_1080p * 30, 2},
-		{RES_1080p * 60, 4},
-		{RES_UHD * 30, 16},
-	};
-
-	/* Setup Register maps and defaults */
-	*cfg = (struct sde_mdss_cfg){
-		.mdss_count = 1,
-		.mdss = {
-			{.id = MDP_TOP, .base = 0x00000000, .features = 0}
-		},
-		.mdp_count = 1,
-		.mdp = {
-			{.id = MDP_TOP, .base = 0x00001000, .features = 0,
-				.highest_bank_bit = 0x2,
-				.clk_ctrls[SDE_CLK_CTRL_VIG0] = {
-					.reg_off = 0x2AC, .bit_off = 0},
-				.clk_ctrls[SDE_CLK_CTRL_VIG1] = {
-					.reg_off = 0x2B4, .bit_off = 0},
-				.clk_ctrls[SDE_CLK_CTRL_VIG2] = {
-					.reg_off = 0x2BC, .bit_off = 0},
-				.clk_ctrls[SDE_CLK_CTRL_VIG3] = {
-					.reg_off = 0x2C4, .bit_off = 0},
-				.clk_ctrls[SDE_CLK_CTRL_RGB0] = {
-					.reg_off = 0x2AC, .bit_off = 4},
-				.clk_ctrls[SDE_CLK_CTRL_RGB1] = {
-					.reg_off = 0x2B4, .bit_off = 4},
-				.clk_ctrls[SDE_CLK_CTRL_RGB2] = {
-					.reg_off = 0x2BC, .bit_off = 4},
-				.clk_ctrls[SDE_CLK_CTRL_RGB3] = {
-					.reg_off = 0x2C4, .bit_off = 4},
-				.clk_ctrls[SDE_CLK_CTRL_DMA0] = {
-					.reg_off = 0x2AC, .bit_off = 8},
-				.clk_ctrls[SDE_CLK_CTRL_DMA1] = {
-					.reg_off = 0x2B4, .bit_off = 8},
-				.clk_ctrls[SDE_CLK_CTRL_CURSOR0] = {
-					.reg_off = 0x3A8, .bit_off = 16},
-				.clk_ctrls[SDE_CLK_CTRL_CURSOR1] = {
-					.reg_off = 0x3B0, .bit_off = 16},
-				.clk_ctrls[SDE_CLK_CTRL_WB0] = {
-					.reg_off = 0x2BC, .bit_off = 8},
-				.clk_ctrls[SDE_CLK_CTRL_WB1] = {
-					.reg_off = 0x2BC, .bit_off = 12},
-				.clk_ctrls[SDE_CLK_CTRL_WB2] = {
-					.reg_off = 0x2BC, .bit_off = 16},
-			},
-		},
-		.ctl_count = 5,
-		.ctl = {
-			{.id = CTL_0,
-				.base = 0x00002000,
-				.features = BIT(SDE_CTL_SPLIT_DISPLAY) |
-					BIT(SDE_CTL_PINGPONG_SPLIT) },
-			{.id = CTL_1,
-				.base = 0x00002200,
-				.features = BIT(SDE_CTL_SPLIT_DISPLAY) },
-			{.id = CTL_2,
-				.base = 0x00002400},
-			{.id = CTL_3,
-				.base = 0x00002600},
-			{.id = CTL_4,
-				.base = 0x00002800},
-		},
-			/* 4 VIG, + 4 RGB + 2 DMA + 2 CURSOR */
-		.sspp_count = 12,
-		.sspp = {
-			{.id = SSPP_VIG0, .base = 0x00005000,
-			.features = VIG_17X_MASK, .sblk = &vig_layer,
-			.xin_id = 0,
-			.clk_ctrl = SDE_CLK_CTRL_VIG0},
-			{.id = SSPP_VIG1, .base = 0x00007000,
-			.features = VIG_17X_MASK, .sblk = &vig_layer,
-			.xin_id = 4,
-			.clk_ctrl = SDE_CLK_CTRL_VIG1},
-			{.id = SSPP_VIG2, .base = 0x00009000,
-			.features = VIG_17X_MASK, .sblk = &vig_layer,
-			.xin_id = 8,
-			.clk_ctrl = SDE_CLK_CTRL_VIG2},
-			{.id = SSPP_VIG3, .base = 0x0000b000,
-			.features = VIG_17X_MASK, .sblk = &vig_layer,
-			.xin_id = 12,
-			.clk_ctrl = SDE_CLK_CTRL_VIG3},
-
-			{.id = SSPP_RGB0, .base = 0x00015000,
-			.features = RGB_17X_MASK, .sblk = &layer,
-			.xin_id = 1,
-			.clk_ctrl = SDE_CLK_CTRL_RGB0},
-			{.id = SSPP_RGB1, .base = 0x00017000,
-			.features = RGB_17X_MASK, .sblk = &layer,
-			.xin_id = 5,
-			.clk_ctrl = SDE_CLK_CTRL_RGB1},
-			{.id = SSPP_RGB2, .base = 0x00019000,
-			.features = RGB_17X_MASK, .sblk = &layer,
-			.xin_id = 9,
-			.clk_ctrl = SDE_CLK_CTRL_RGB2},
-			{.id = SSPP_RGB3, .base = 0x0001B000,
-			.features = RGB_17X_MASK, .sblk = &layer,
-			.xin_id = 13,
-			.clk_ctrl = SDE_CLK_CTRL_RGB3},
-
-			{.id = SSPP_DMA0, .base = 0x00025000,
-			.features = DMA_17X_MASK, .sblk = &dma,
-			.xin_id = 2,
-			.clk_ctrl = SDE_CLK_CTRL_DMA0},
-			{.id = SSPP_DMA1, .base = 0x00027000,
-			.features = DMA_17X_MASK, .sblk = &dma,
-			.xin_id = 10,
-			.clk_ctrl = SDE_CLK_CTRL_DMA1},
-
-			{.id = SSPP_CURSOR0, .base = 0x00035000,
-			.features = CURSOR_17X_MASK, .sblk = &cursor,
-			.xin_id = 7,
-			.clk_ctrl = SDE_CLK_CTRL_CURSOR0},
-			{.id = SSPP_CURSOR1, .base = 0x00037000,
-			.features = CURSOR_17X_MASK, .sblk = &cursor,
-			.xin_id = 7,
-			.clk_ctrl = SDE_CLK_CTRL_CURSOR1},
-		},
-		.mixer_count = 6,
-		.mixer = {
-			{.id = LM_0, .base = 0x00045000,
-				.features = MIXER_17X_MASK,
-				.sblk = &lm,
-				.dspp = DSPP_0,
-				.pingpong = PINGPONG_0,
-				.lm_pair_mask = (1 << LM_1) },
-			{.id = LM_1, .base = 0x00046000,
-				.features = MIXER_17X_MASK,
-				.sblk = &lm,
-				.dspp = DSPP_1,
-				.pingpong = PINGPONG_1,
-				.lm_pair_mask = (1 << LM_0) },
-			{.id = LM_2, .base = 0x00047000,
-				.features = MIXER_17X_MASK,
-				.sblk = &lm,
-				.dspp = DSPP_MAX,
-				.pingpong = PINGPONG_2,
-				.lm_pair_mask = (1 << LM_5) },
-			{.id = LM_3, .base = 0x00048000,
-				.features = MIXER_17X_MASK,
-				.sblk = &lm,
-				.dspp = DSPP_MAX,
-				.pingpong = PINGPONG_MAX},
-			{.id = LM_4, .base = 0x00049000,
-				.features = MIXER_17X_MASK,
-				.sblk = &lm,
-				.dspp = DSPP_MAX,
-				.pingpong = PINGPONG_MAX},
-			{.id = LM_5, .base = 0x0004a000,
-				.features = MIXER_17X_MASK,
-				.sblk = &lm,
-				.dspp = DSPP_MAX,
-				.pingpong = PINGPONG_3,
-				.lm_pair_mask = (1 << LM_2) },
-		},
-		.dspp_count = 2,
-		.dspp = {
-			{.id = DSPP_0, .base = 0x00055000,
-			.features = DSPP_17X_MASK,
-				.sblk = &dspp},
-			{.id = DSPP_1, .base = 0x00057000,
-			.features = DSPP_17X_MASK,
-				.sblk = &dspp},
-		},
-		.pingpong_count = 4,
-		.pingpong = {
-			{.id = PINGPONG_0, .base = 0x00071000,
-				.features = PINGPONG_17X_SPLIT_MASK,
-				.sblk = &pingpong},
-			{.id = PINGPONG_1, .base = 0x00071800,
-				.features = PINGPONG_17X_SPLIT_MASK,
-				.sblk = &pingpong},
-			{.id = PINGPONG_2, .base = 0x00072000,
-				.features = PINGPONG_17X_MASK,
-				.sblk = &pingpong},
-			{.id = PINGPONG_3, .base = 0x00072800,
-				.features = PINGPONG_17X_MASK,
-				.sblk = &pingpong},
-		},
-		.cdm_count = 1,
-		.cdm = {
-			{.id = CDM_0, .base = 0x0007A200, .features = 0,
-				.intf_connect = BIT(INTF_3),
-				.wb_connect = BIT(WB_2),}
-		},
-		.intf_count = 4,
-		.intf = {
-			{.id = INTF_0, .base = 0x0006B000,
-				.type = INTF_NONE, .controller_id = 0,
-				.prog_fetch_lines_worst_case = 21},
-			{.id = INTF_1, .base = 0x0006B800,
-				.type = INTF_DSI, .controller_id = 0,
-				.prog_fetch_lines_worst_case = 21},
-			{.id = INTF_2, .base = 0x0006C000,
-				.type = INTF_DSI, .controller_id = 1,
-				.prog_fetch_lines_worst_case = 21},
-			{.id = INTF_3, .base = 0x0006C800,
-				.type = INTF_HDMI, .controller_id = 0,
-				.prog_fetch_lines_worst_case = 21},
-		},
-		.wb_count = 3,
-		.wb = {
-			{.id = WB_0, .base = 0x00065000,
-				.features = WB01_17X_MASK,
-				.sblk = &wb0,
-				.format_list = wb0_formats,
-				.vbif_idx = VBIF_NRT,
-				.xin_id = 3,
-				.clk_ctrl = SDE_CLK_CTRL_WB0},
-			{.id = WB_1, .base = 0x00065800,
-				.features = WB01_17X_MASK,
-				.sblk = &wb0,
-				.format_list = wb0_formats,
-				.vbif_idx = VBIF_NRT,
-				.xin_id = 11,
-				.clk_ctrl = SDE_CLK_CTRL_WB1},
-			{.id = WB_2, .base = 0x00066000,
-				.features = WB2_17X_MASK,
-				.sblk = &wb2,
-				.format_list = wb2_formats,
-				.vbif_idx = VBIF_NRT,
-				.xin_id = 6,
-				.clk_ctrl = SDE_CLK_CTRL_WB2},
-		},
-		.vbif_count = 2,
-		.vbif = {
-			{.id = VBIF_0,
-				.base = 0, /* 0x000B0000 */
-				.features = BIT(SDE_VBIF_QOS_OTLIM),
-				.default_ot_rd_limit = 32,
-				.default_ot_wr_limit = 16,
-				.xin_halt_timeout = 0x4000,
-				.dynamic_ot_rd_tbl = {
-					.count = ARRAY_SIZE(dynamic_ot_cfg),
-					.cfg = dynamic_ot_cfg},
-				.dynamic_ot_wr_tbl = {
-					.count = ARRAY_SIZE(dynamic_ot_cfg),
-					.cfg = dynamic_ot_cfg},
-			},
-			{.id = VBIF_1,
-				.base = 0, /* 0x000B8000 */
-				.features = BIT(SDE_VBIF_QOS_OTLIM),
-				.default_ot_rd_limit = 32,
-				.default_ot_wr_limit = 16,
-				.xin_halt_timeout = 0x4000,
-				.dynamic_ot_rd_tbl = {
-					.count = ARRAY_SIZE(dynamic_ot_cfg),
-					.cfg = dynamic_ot_cfg},
-				.dynamic_ot_wr_tbl = {
-					.count = ARRAY_SIZE(dynamic_ot_cfg),
-					.cfg = dynamic_ot_cfg},
-			},
-		},
-	};
-	return 0;
-}
-
-/**
- * sde_mdp_cfg_170_init(): Populate the sde sub-blocks catalog information
- */
-struct sde_mdss_cfg *sde_mdss_cfg_170_init(u32 step)
-{
-	struct sde_mdss_cfg *m = NULL;
-
-	/*
-	 * This function, for each sub-block sets,
-	 * instance count, IO regions,
-	 * default capabilities and this version capabilities,
-	 * Additional catalog items
-	 */
-
-	m = kzalloc(sizeof(*m), GFP_KERNEL);
-	if (!m)
-		return NULL;
-
-	set_cfg_1xx_init(m);
-	m->hwversion = SDE_HW_VER(1, 7, step);
-
-	return m;
-}
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 2cd7c71..a9cedba 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -120,6 +120,7 @@ static void free_event_data(struct work_struct *work)
 	cpumask_t *mask;
 	struct etm_event_data *event_data;
 	struct coresight_device *sink;
+	struct coresight_device *source;
 
 	event_data = container_of(work, struct etm_event_data, work);
 	mask = &event_data->mask;
@@ -135,8 +136,9 @@ static void free_event_data(struct work_struct *work)
 	}
 
 	for_each_cpu(cpu, mask) {
+		source = coresight_get_source(event_data->path[cpu]);
 		if (!(IS_ERR_OR_NULL(event_data->path[cpu])))
-			coresight_release_path(event_data->path[cpu]);
+			coresight_release_path(source, event_data->path[cpu]);
 	}
 
 	kfree(event_data->path);
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index aa5538c..3af358a 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2011-2012, 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2012, 2016-2017, The Linux Foundation.
+ * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -134,8 +135,10 @@ static inline bool coresight_authstatus_enabled(void __iomem *addr)
 void coresight_disable_path(struct list_head *path);
 int coresight_enable_path(struct list_head *path, u32 mode);
 struct coresight_device *coresight_get_sink(struct list_head *path);
+struct coresight_device *coresight_get_source(struct list_head *path);
 struct list_head *coresight_build_path(struct coresight_device *csdev);
-void coresight_release_path(struct list_head *path);
+void coresight_release_path(struct coresight_device *csdev,
+			    struct list_head *path);
 
 #ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
 extern int etm_readl_cp14(u32 off, unsigned int *val);
diff --git a/drivers/hwtracing/coresight/coresight-replicator-qcom.c b/drivers/hwtracing/coresight/coresight-replicator-qcom.c
index 0a3d15f..0bd8b78 100644
--- a/drivers/hwtracing/coresight/coresight-replicator-qcom.c
+++ b/drivers/hwtracing/coresight/coresight-replicator-qcom.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, 2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -47,6 +47,8 @@ static int replicator_enable(struct coresight_device *csdev, int inport,
 {
 	struct replicator_state *drvdata = dev_get_drvdata(csdev->dev.parent);
 
+	pm_runtime_get_sync(drvdata->dev);
+
 	CS_UNLOCK(drvdata->base);
 
 	/*
@@ -83,6 +85,7 @@ static void replicator_disable(struct coresight_device *csdev, int inport,
 
 	CS_LOCK(drvdata->base);
 
+	pm_runtime_put(drvdata->dev);
 	dev_info(drvdata->dev, "REPLICATOR disabled\n");
 }
 
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 95d7a90..1ccf3da 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -655,7 +655,7 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
 }
 
 static int tpdm_enable(struct coresight_device *csdev,
-		       struct perf_event_attr *attr,  u32 mode)
+		       struct perf_event *event, u32 mode)
 {
 	struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	int ret;
@@ -731,7 +731,8 @@ static void __tpdm_disable(struct tpdm_drvdata *drvdata)
 	TPDM_LOCK(drvdata);
 }
 
-static void tpdm_disable(struct coresight_device *csdev)
+static void tpdm_disable(struct coresight_device *csdev,
+			 struct perf_event *event)
 {
 	struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 7bf00a0..3a4474d 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,19 +39,17 @@ struct coresight_node {
 	struct list_head link;
 };
 
-/*
- * When operating Coresight drivers from the sysFS interface, only a single
- * path can exist from a tracer (associated to a CPU) to a sink.
+/**
+ * struct coresight_path - path from source to sink
+ * @path:	Address of path list.
+ * @link:	hook to the list.
  */
-static DEFINE_PER_CPU(struct list_head *, tracer_path);
+struct coresight_path {
+	struct list_head *path;
+	struct list_head link;
+};
 
-/*
- * As of this writing only a single STM can be found in CS topologies.  Since
- * there is no way to know if we'll ever see more and what kind of
- * configuration they will enact, for the time being only define a single path
- * for STM.
- */
-static struct list_head *stm_path;
+static LIST_HEAD(cs_active_paths);
 
 static int coresight_id_match(struct device *dev, void *data)
 {
@@ -152,6 +150,7 @@ static void coresight_disable_sink(struct coresight_device *csdev)
 		if (sink_ops(csdev)->disable) {
 			sink_ops(csdev)->disable(csdev);
 			csdev->enable = false;
+			csdev->activated = false;
 		}
 	}
 }
@@ -353,6 +352,20 @@ int coresight_enable_path(struct list_head *path, u32 mode)
 	goto out;
 }
 
+struct coresight_device *coresight_get_source(struct list_head *path)
+{
+	struct coresight_device *csdev;
+
+	if (!path)
+		return NULL;
+
+	csdev = list_first_entry(path, struct coresight_node, link)->csdev;
+	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE)
+		return NULL;
+
+	return csdev;
+}
+
 struct coresight_device *coresight_get_sink(struct list_head *path)
 {
 	struct coresight_device *csdev;
@@ -446,14 +459,23 @@ struct list_head *coresight_build_path(struct coresight_device *csdev)
  * coresight_release_path - release a previously built path.
  * @path:	the path to release.
  *
+ * Remove coresight path entry from source device
  * Go through all the elements of a path and 1) removed it from the list and
  * 2) free the memory allocated for each node.
  */
-void coresight_release_path(struct list_head *path)
+void coresight_release_path(struct coresight_device *csdev,
+			    struct list_head *path)
 {
-	struct coresight_device *csdev;
 	struct coresight_node *nd, *next;
 
+	if (csdev != NULL && csdev->node != NULL) {
+		/* Remove path entry from source device */
+		list_del(&csdev->node->link);
+		kfree(csdev->node);
+		csdev->node = NULL;
+	}
+
+	/* Free the path */
 	list_for_each_entry_safe(nd, next, path, link) {
 		csdev = nd->csdev;
 
@@ -494,9 +516,25 @@ static int coresight_validate_source(struct coresight_device *csdev,
 	return 0;
 }
 
+int coresight_store_path(struct coresight_device *csdev, struct list_head *path)
+{
+	struct coresight_path *node;
+
+	node = kzalloc(sizeof(struct coresight_path), GFP_KERNEL);
+	if (!node)
+		return -ENOMEM;
+
+	node->path = path;
+	list_add(&node->link, &cs_active_paths);
+
+	csdev->node = node;
+
+	return 0;
+}
+
 int coresight_enable(struct coresight_device *csdev)
 {
-	int cpu, ret = 0;
+	int ret = 0;
 	struct list_head *path;
 
 	mutex_lock(&coresight_mutex);
@@ -523,25 +561,9 @@ int coresight_enable(struct coresight_device *csdev)
 	if (ret)
 		goto err_source;
 
-	switch (csdev->subtype.source_subtype) {
-	case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
-		/*
-		 * When working from sysFS it is important to keep track
-		 * of the paths that were created so that they can be
-		 * undone in 'coresight_disable()'.  Since there can only
-		 * be a single session per tracer (when working from sysFS)
-		 * a per-cpu variable will do just fine.
-		 */
-		cpu = source_ops(csdev)->cpu_id(csdev);
-		per_cpu(tracer_path, cpu) = path;
-		break;
-	case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
-		stm_path = path;
-		break;
-	default:
-		/* We can't be here */
-		break;
-	}
+	ret = coresight_store_path(csdev, path);
+	if (ret)
+		goto err_source;
 
 out:
 	mutex_unlock(&coresight_mutex);
@@ -551,15 +573,14 @@ int coresight_enable(struct coresight_device *csdev)
 	coresight_disable_path(path);
 
 err_path:
-	coresight_release_path(path);
+	coresight_release_path(csdev, path);
 	goto out;
 }
 EXPORT_SYMBOL_GPL(coresight_enable);
 
 void coresight_disable(struct coresight_device *csdev)
 {
-	int cpu, ret;
-	struct list_head *path = NULL;
+	int  ret;
 
 	mutex_lock(&coresight_mutex);
 
@@ -570,24 +591,12 @@ void coresight_disable(struct coresight_device *csdev)
 	if (!csdev->enable)
 		goto out;
 
-	switch (csdev->subtype.source_subtype) {
-	case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
-		cpu = source_ops(csdev)->cpu_id(csdev);
-		path = per_cpu(tracer_path, cpu);
-		per_cpu(tracer_path, cpu) = NULL;
-		break;
-	case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
-		path = stm_path;
-		stm_path = NULL;
-		break;
-	default:
-		/* We can't be here */
-		break;
-	}
+	if (csdev->node == NULL)
+		goto out;
 
 	coresight_disable_source(csdev);
-	coresight_disable_path(path);
-	coresight_release_path(path);
+	coresight_disable_path(csdev->node->path);
+	coresight_release_path(csdev, csdev->node->path);
 
 out:
 	mutex_unlock(&coresight_mutex);
@@ -876,8 +885,42 @@ int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
 	return -EAGAIN;
 }
 
+static ssize_t reset_source_sink_store(struct bus_type *bus,
+				       const char *buf, size_t size)
+{
+	int ret = 0;
+	unsigned long val;
+	struct coresight_path *cspath = NULL;
+	struct coresight_path *cspath_next = NULL;
+	struct coresight_device *csdev;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	mutex_lock(&coresight_mutex);
+
+	list_for_each_entry_safe(cspath, cspath_next, &cs_active_paths, link) {
+		csdev = coresight_get_source(cspath->path);
+		if (!csdev)
+			continue;
+		coresight_disable(csdev);
+	}
+
+	mutex_unlock(&coresight_mutex);
+	return size;
+}
+static BUS_ATTR_WO(reset_source_sink);
+
+static struct attribute *coresight_reset_source_sink_attrs[] = {
+	&bus_attr_reset_source_sink.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(coresight_reset_source_sink);
+
 struct bus_type coresight_bustype = {
-	.name	= "coresight",
+	.name		= "coresight",
+	.bus_groups	= coresight_reset_source_sink_groups,
 };
 
 static int __init coresight_init(void)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d252276..a9cf687 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -790,6 +790,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-qup.
 
+config I2C_QCOM_GENI
+	tristate "Qualcomm Technologies Inc.'s GENI based I2C controller"
+	depends on ARCH_QCOM
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in I2C interface on the Qualcomm Technologies Inc.'s SoCs.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-qcom-geni.
+
 config I2C_RIIC
 	tristate "Renesas RIIC adapter"
 	depends on ARCH_RENESAS || COMPILE_TEST
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 29764cc..7f2523f 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -76,6 +76,7 @@
 obj-$(CONFIG_I2C_PXA)		+= i2c-pxa.o
 obj-$(CONFIG_I2C_PXA_PCI)	+= i2c-pxa-pci.o
 obj-$(CONFIG_I2C_QUP)		+= i2c-qup.o
+obj-$(CONFIG_I2C_QCOM_GENI)	+= i2c-qcom-geni.o
 obj-$(CONFIG_I2C_RIIC)		+= i2c-riic.o
 obj-$(CONFIG_I2C_RK3X)		+= i2c-rk3x.o
 obj-$(CONFIG_I2C_S3C2410)	+= i2c-s3c2410.o
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
new file mode 100644
index 0000000..8e38a24
--- /dev/null
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/qcom-geni-se.h>
+
+#define SE_I2C_TX_TRANS_LEN		(0x26C)
+#define SE_I2C_RX_TRANS_LEN		(0x270)
+#define SE_I2C_SCL_COUNTERS		(0x278)
+
+#define SE_I2C_ERR  (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |\
+			M_GP_IRQ_1_EN | M_GP_IRQ_3_EN | M_GP_IRQ_4_EN)
+#define SE_I2C_ABORT (1U << 1)
+/* M_CMD OP codes for I2C */
+#define I2C_WRITE		(0x1)
+#define I2C_READ		(0x2)
+#define I2C_WRITE_READ		(0x3)
+#define I2C_ADDR_ONLY		(0x4)
+#define I2C_BUS_CLEAR		(0x6)
+#define I2C_STOP_ON_BUS		(0x7)
+/* M_CMD params for I2C */
+#define PRE_CMD_DELAY		(BIT(0))
+#define TIMESTAMP_BEFORE	(BIT(1))
+#define STOP_STRETCH		(BIT(2))
+#define TIMESTAMP_AFTER		(BIT(3))
+#define POST_COMMAND_DELAY	(BIT(4))
+#define IGNORE_ADD_NACK		(BIT(6))
+#define READ_FINISHED_WITH_ACK	(BIT(7))
+#define BYPASS_ADDR_PHASE	(BIT(8))
+#define SLV_ADDR_MSK		(GENMASK(15, 9))
+#define SLV_ADDR_SHFT		(9)
+
+struct geni_i2c_dev {
+	struct device *dev;
+	void __iomem *base;
+	int irq;
+	int err;
+	struct i2c_adapter adap;
+	struct completion xfer;
+	struct i2c_msg *cur;
+	int cur_wr;
+	int cur_rd;
+};
+
+static inline void qcom_geni_i2c_conf(void __iomem *base, int dfs, int div)
+{
+	geni_write_reg(dfs, base, SE_GENI_CLK_SEL);
+	geni_write_reg((div << 4) | 1, base, GENI_SER_M_CLK_CFG);
+	geni_write_reg(((5 << 20) | (0xC << 10) | 0x18),
+				base, SE_I2C_SCL_COUNTERS);
+	/*
+	 * Ensure Clk config completes before return.
+	 */
+	mb();
+}
+
+static irqreturn_t geni_i2c_irq(int irq, void *dev)
+{
+	struct geni_i2c_dev *gi2c = dev;
+	int i, j;
+	u32 m_stat = readl_relaxed(gi2c->base + SE_GENI_M_IRQ_STATUS);
+	u32 tx_stat = readl_relaxed(gi2c->base + SE_GENI_TX_FIFO_STATUS);
+	u32 rx_stat = readl_relaxed(gi2c->base + SE_GENI_RX_FIFO_STATUS);
+	struct i2c_msg *cur = gi2c->cur;
+
+	dev_dbg(gi2c->dev,
+		"got i2c irq:%d, stat:0x%x, tx stat:0x%x, rx stat:0x%x\n",
+		irq, m_stat, tx_stat, rx_stat);
+	if (!cur || m_stat & SE_I2C_ERR) {
+		dev_err(gi2c->dev, "i2c txn err");
+		writel_relaxed(0, (gi2c->base + SE_GENI_TX_WATERMARK_REG));
+		gi2c->err = -EIO;
+		goto irqret;
+	}
+	if (((m_stat & M_RX_FIFO_WATERMARK_EN) ||
+		(m_stat & M_RX_FIFO_LAST_EN)) && (cur->flags & I2C_M_RD)) {
+		u32 rxcnt = rx_stat & RX_FIFO_WC_MSK;
+
+		for (j = 0; j < rxcnt; j++) {
+			u32 temp;
+			int p;
+
+			temp = readl_relaxed(gi2c->base + SE_GENI_RX_FIFOn);
+			for (i = gi2c->cur_rd, p = 0; (i < cur->len && p < 4);
+				i++, p++)
+				cur->buf[i] = (u8) ((temp >> (p * 8)) & 0xff);
+			gi2c->cur_rd = i;
+			if (gi2c->cur_rd == cur->len) {
+				dev_dbg(gi2c->dev, "i:%d,read 0x%x\n", i, temp);
+				break;
+			}
+			dev_dbg(gi2c->dev, "i: %d, read 0x%x\n", i, temp);
+		}
+	} else if ((m_stat & M_TX_FIFO_WATERMARK_EN) &&
+					!(cur->flags & I2C_M_RD)) {
+		for (j = 0; j < 0x1f; j++) {
+			u32 temp = 0;
+			int p;
+
+			for (i = gi2c->cur_wr, p = 0; (i < cur->len && p < 4);
+				i++, p++)
+				temp |= (((u32)(cur->buf[i]) << (p * 8)));
+			writel_relaxed(temp, gi2c->base + SE_GENI_TX_FIFOn);
+			gi2c->cur_wr = i;
+			dev_dbg(gi2c->dev, "i:%d,wrote 0x%x\n", i, temp);
+			if (gi2c->cur_wr == cur->len) {
+				dev_dbg(gi2c->dev, "i2c bytes done writing\n");
+				writel_relaxed(0,
+				(gi2c->base + SE_GENI_TX_WATERMARK_REG));
+				break;
+			}
+		}
+	}
+irqret:
+	writel_relaxed(m_stat, gi2c->base + SE_GENI_M_IRQ_CLEAR);
+	/* Ensure all writes are done before returning from ISR. */
+	wmb();
+	/* if this is err with done-bit not set, handle that thr' timeout. */
+	if (m_stat & M_CMD_DONE_EN) {
+		dev_dbg(gi2c->dev, "i2c irq: err:%d, stat:0x%x\n",
+							gi2c->err, m_stat);
+		complete(&gi2c->xfer);
+	}
+	return IRQ_HANDLED;
+}
+
+static int geni_i2c_xfer(struct i2c_adapter *adap,
+			 struct i2c_msg msgs[],
+			 int num)
+{
+	struct geni_i2c_dev *gi2c = i2c_get_adapdata(adap);
+	int i, ret = 0, timeout = 0;
+
+	gi2c->err = 0;
+	gi2c->cur = &msgs[0];
+	reinit_completion(&gi2c->xfer);
+	enable_irq(gi2c->irq);
+	qcom_geni_i2c_conf(gi2c->base, 0, 2);
+	se_config_packing(gi2c->base, 8, 4, true);
+	dev_dbg(gi2c->dev, "i2c xfer:num:%d, msgs:len:%d,flg:%d\n",
+				num, msgs[0].len, msgs[0].flags);
+	for (i = 0; i < num; i++) {
+		int stretch = (i < (num - 1));
+		u32 m_param = 0;
+		u32 m_cmd = 0;
+
+		m_param |= (stretch ? STOP_STRETCH : ~(STOP_STRETCH));
+		m_param |= ((msgs[i].addr & 0x7F) << SLV_ADDR_SHFT);
+
+		gi2c->cur = &msgs[i];
+		if (msgs[i].flags & I2C_M_RD) {
+			dev_dbg(gi2c->dev,
+				"READ,n:%d,i:%d len:%d, stretch:%d\n",
+					num, i, msgs[i].len, stretch);
+			geni_write_reg(msgs[i].len,
+				       gi2c->base, SE_I2C_RX_TRANS_LEN);
+			m_cmd = I2C_READ;
+			geni_setup_m_cmd(gi2c->base, m_cmd, m_param);
+		} else {
+			dev_dbg(gi2c->dev,
+				"WRITE:n:%d,i%d len:%d, stretch:%d\n",
+					num, i, msgs[i].len, stretch);
+			geni_write_reg(msgs[i].len, gi2c->base,
+						SE_I2C_TX_TRANS_LEN);
+			m_cmd = I2C_WRITE;
+			geni_setup_m_cmd(gi2c->base, m_cmd, m_param);
+			/* Get FIFO IRQ */
+			geni_write_reg(1, gi2c->base, SE_GENI_TX_WATERMARK_REG);
+		}
+		/* Ensure FIFO write go through before waiting for Done evet */
+		mb();
+		timeout = wait_for_completion_timeout(&gi2c->xfer, HZ);
+		if (!timeout) {
+			dev_err(gi2c->dev, "Timed out\n");
+			gi2c->err = -ETIMEDOUT;
+			gi2c->cur = NULL;
+			geni_abort_m_cmd(gi2c->base);
+			timeout = wait_for_completion_timeout(&gi2c->xfer, HZ);
+		}
+		gi2c->cur_wr = 0;
+		gi2c->cur_rd = 0;
+		if (gi2c->err) {
+			dev_err(gi2c->dev, "i2c error :%d\n", gi2c->err);
+			ret = gi2c->err;
+			break;
+		}
+	}
+	if (ret == 0)
+		ret = i;
+	disable_irq(gi2c->irq);
+	gi2c->cur = NULL;
+	gi2c->err = 0;
+	dev_dbg(gi2c->dev, "i2c txn ret:%d\n", ret);
+	return ret;
+}
+
+static u32 geni_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+}
+
+static const struct i2c_algorithm geni_i2c_algo = {
+	.master_xfer	= geni_i2c_xfer,
+	.functionality	= geni_i2c_func,
+};
+
+static int geni_i2c_probe(struct platform_device *pdev)
+{
+	struct geni_i2c_dev *gi2c;
+	struct resource *res;
+	int ret;
+
+	gi2c = devm_kzalloc(&pdev->dev, sizeof(*gi2c), GFP_KERNEL);
+	if (!gi2c)
+		return -ENOMEM;
+
+	gi2c->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	gi2c->base = devm_ioremap_resource(gi2c->dev, res);
+	if (IS_ERR(gi2c->base))
+		return PTR_ERR(gi2c->base);
+
+	gi2c->irq = platform_get_irq(pdev, 0);
+	if (gi2c->irq < 0) {
+		dev_err(gi2c->dev, "IRQ error for i2c-geni\n");
+		return gi2c->irq;
+	}
+
+	gi2c->adap.algo = &geni_i2c_algo;
+	init_completion(&gi2c->xfer);
+	platform_set_drvdata(pdev, gi2c);
+	ret = devm_request_irq(gi2c->dev, gi2c->irq, geni_i2c_irq,
+			       IRQF_TRIGGER_HIGH, "i2c_geni", gi2c);
+	if (ret) {
+		dev_err(gi2c->dev, "Request_irq failed:%d: err:%d\n",
+				   gi2c->irq, ret);
+		return ret;
+	}
+	disable_irq(gi2c->irq);
+	i2c_set_adapdata(&gi2c->adap, gi2c);
+	gi2c->adap.dev.parent = gi2c->dev;
+	gi2c->adap.dev.of_node = pdev->dev.of_node;
+
+	strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
+
+	i2c_add_adapter(&gi2c->adap);
+	geni_se_init(gi2c->base, FIFO_MODE, 0xF, 0x10);
+
+	return 0;
+}
+
+static int geni_i2c_remove(struct platform_device *pdev)
+{
+	struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
+
+	disable_irq(gi2c->irq);
+	i2c_del_adapter(&gi2c->adap);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int geni_i2c_suspend(struct device *device)
+{
+	return 0;
+}
+
+static int geni_i2c_resume(struct device *device)
+{
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops geni_i2c_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		geni_i2c_suspend,
+		geni_i2c_resume)
+};
+
+static const struct of_device_id geni_i2c_dt_match[] = {
+	{ .compatible = "qcom,i2c-geni" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
+
+static struct platform_driver geni_i2c_driver = {
+	.probe  = geni_i2c_probe,
+	.remove = geni_i2c_remove,
+	.driver = {
+		.name = "i2c_geni",
+		.pm = &geni_i2c_pm_ops,
+		.of_match_table = geni_i2c_dt_match,
+	},
+};
+
+module_platform_driver(geni_i2c_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:i2c_geni");
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 4d6ee1b..c704c47 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -635,7 +635,7 @@ static int arm_smmu_register_legacy_master(struct device *dev,
 	__be32 pci_sid;
 	int err = 0;
 
-	memset(&it, sizeof(it), 0);
+	memset(&it, 0, sizeof(it));
 	np = dev_get_dev_node(dev);
 	if (!np || !of_find_property(np, "#stream-id-cells", NULL)) {
 		of_node_put(np);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 949bc47..3267999 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -62,6 +62,7 @@
 #define HFI_BUFFER_EXTRADATA_OUTPUT2 (HFI_OX_BASE + 0x4)
 #define HFI_BUFFER_INTERNAL_SCRATCH_1 (HFI_OX_BASE + 0x5)
 #define HFI_BUFFER_INTERNAL_SCRATCH_2 (HFI_OX_BASE + 0x6)
+#define HFI_BUFFER_INTERNAL_RECON (HFI_OX_BASE + 0x9)
 
 #define HFI_BUFFER_MODE_DYNAMIC (HFI_OX_BASE + 0x3)
 
@@ -84,6 +85,7 @@
 #define HFI_EXTRADATA_FRAME_QP			0x0000000F
 #define HFI_EXTRADATA_FRAME_BITS_INFO		0x00000010
 #define HFI_EXTRADATA_VPX_COLORSPACE		0x00000014
+#define HFI_EXTRADATA_UBWC_CR_STAT_INFO		0x00000019
 #define HFI_EXTRADATA_MULTISLICE_INFO		0x7F100000
 #define HFI_EXTRADATA_NUM_CONCEALED_MB		0x7F100001
 #define HFI_EXTRADATA_INDEX					0x7F100002
@@ -119,6 +121,7 @@ struct hfi_extradata_header {
 #define HFI_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST	0x04
 #define HFI_INTERLACE_FRAME_TOPFIELDFIRST				0x08
 #define HFI_INTERLACE_FRAME_BOTTOMFIELDFIRST			0x10
+#define HFI_INTERLACE_FRAME_MBAFF					0x20
 
 #define HFI_PROPERTY_SYS_OX_START			\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x0000)
@@ -135,9 +138,7 @@ struct hfi_extradata_header {
 	(HFI_PROPERTY_PARAM_OX_START + 0x006)
 #define HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA	\
 	(HFI_PROPERTY_PARAM_OX_START + 0x009)
-#define HFI_PROPERTY_PARAM_ERR_DETECTION_CODE_EXTRADATA \
-	(HFI_PROPERTY_PARAM_OX_START + 0x00A)
-#define HFI_PROPERTY_PARAM_BUFFER_SIZE_MINIMUM			\
+#define  HFI_PROPERTY_PARAM_BUFFER_SIZE_MINIMUM			\
 	(HFI_PROPERTY_PARAM_OX_START + 0x00C)
 #define HFI_PROPERTY_PARAM_SYNC_BASED_INTERRUPT			\
 	(HFI_PROPERTY_PARAM_OX_START + 0x00E)
@@ -591,6 +592,21 @@ struct hfi_msg_session_flush_done_packet {
 	u32 flush_type;
 };
 
+struct hfi_ubwc_cr_stats_info_type {
+	u32 cr_stats_info0;
+	u32 cr_stats_info1;
+	u32 cr_stats_info2;
+	u32 cr_stats_info3;
+	u32 cr_stats_info4;
+	u32 cr_stats_info5;
+	u32 cr_stats_info6;
+};
+
+struct hfi_frame_cr_stats_type {
+	u32 frame_index;
+	struct hfi_ubwc_cr_stats_info_type ubwc_stats_info;
+};
+
 struct hfi_msg_session_empty_buffer_done_packet {
 	u32 size;
 	u32 packet_type;
@@ -601,6 +617,8 @@ struct hfi_msg_session_empty_buffer_done_packet {
 	u32 input_tag;
 	u32 packet_buffer;
 	u32 extra_data_buffer;
+	u32 flags;
+	struct hfi_frame_cr_stats_type ubwc_cr_stats;
 	u32 rgData[0];
 };
 
@@ -761,6 +779,11 @@ struct hfi_extradata_interlace_video_payload {
 	u32 format;
 };
 
+struct hfi_conceal_color_type {
+	u32 value_8bit;
+	u32 value_10bit;
+};
+
 struct hfi_extradata_num_concealed_mb_payload {
 	u32 num_mb_concealed;
 };
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 6863d5e..e9a5bb3 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -83,6 +83,7 @@
 #define HFI_VIDEO_CODEC_VP9				0x00004000
 #define HFI_VIDEO_CODEC_HEVC_HYBRID			0x80000000
 
+#define HFI_PROFILE_UNKNOWN					0x00000000
 #define HFI_H264_PROFILE_BASELINE			0x00000001
 #define HFI_H264_PROFILE_MAIN				0x00000002
 #define HFI_H264_PROFILE_HIGH				0x00000004
@@ -91,6 +92,7 @@
 #define HFI_H264_PROFILE_CONSTRAINED_BASE	0x00000020
 #define HFI_H264_PROFILE_CONSTRAINED_HIGH	0x00000040
 
+#define HFI_LEVEL_UNKNOWN					0x00000000
 #define HFI_H264_LEVEL_1					0x00000001
 #define HFI_H264_LEVEL_1b					0x00000002
 #define HFI_H264_LEVEL_11					0x00000004
@@ -249,8 +251,8 @@ struct hfi_buffer_info {
 	(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x003)
 #define HFI_PROPERTY_PARAM_VENC_RATE_CONTROL				\
 	(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x004)
-#define  HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE           \
-	(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x008)
+#define  HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE		\
+	(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x009)
 #define  HFI_PROPERTY_PARAM_VENC_OPEN_GOP                   \
 	(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x00C)
 #define HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH				\
@@ -537,11 +539,13 @@ struct hfi_quality_vs_speed {
 struct hfi_quantization {
 	u32 qp_packed;
 	u32 layer_id;
+	u32 reserved[4];
 };
 
 struct hfi_quantization_range {
 	struct hfi_quantization min_qp;
 	struct hfi_quantization max_qp;
+	u32 reserved[4];
 };
 
 #define HFI_LTR_MODE_DISABLE	0x0
@@ -617,10 +621,10 @@ struct hfi_picture_type {
 #define HFI_COLOR_FORMAT_YUV444				(HFI_COMMON_BASE + 0xE)
 #define HFI_COLOR_FORMAT_RGBA8888			(HFI_COMMON_BASE + 0x10)
 
-#define HFI_COLOR_FORMAT_P010						\
-		(HFI_COLOR_FORMAT_10_BIT_BASE + HFI_COLOR_FORMAT_NV12)
 #define HFI_COLOR_FORMAT_YUV420_TP10					\
-		(HFI_COLOR_FORMAT_10_BIT_BASE + HFI_COLOR_FORMAT_NV12_4x4TILE)
+		(HFI_COLOR_FORMAT_10_BIT_BASE + HFI_COLOR_FORMAT_NV12)
+#define HFI_COLOR_FORMAT_P010					\
+		(HFI_COLOR_FORMAT_10_BIT_BASE + HFI_COLOR_FORMAT_NV12 + 0x1)
 
 #define HFI_COLOR_FORMAT_NV12_UBWC					\
 		(HFI_COLOR_FORMAT_UBWC_BASE + HFI_COLOR_FORMAT_NV12)
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 06881d3..aa81bdc 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2510,15 +2510,15 @@ EXPORT_SYMBOL(ipa_create_wdi_mapping);
 
 /**
  * ipa_get_gsi_ep_info() - provide gsi ep information
- * @ipa_ep_idx: IPA endpoint index
+ * @client: IPA client type
  *
  * Return value: pointer to ipa_gsi_ep_info
  */
-struct ipa_gsi_ep_config *ipa_get_gsi_ep_info(int ipa_ep_idx)
+const struct ipa_gsi_ep_config *ipa_get_gsi_ep_info(enum ipa_client_type client)
 {
 	if (!ipa_api_ctrl || !ipa_api_ctrl->ipa_get_gsi_ep_info)
 		return NULL;
-	return ipa_api_ctrl->ipa_get_gsi_ep_info(ipa_ep_idx);
+	return ipa_api_ctrl->ipa_get_gsi_ep_info(client);
 }
 EXPORT_SYMBOL(ipa_get_gsi_ep_info);
 
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index 171c9fb..1b8e3d6 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -331,7 +331,8 @@ struct ipa_api_controller {
 	int (*ipa_create_wdi_mapping)(u32 num_buffers,
 		struct ipa_wdi_buffer_info *info);
 
-	struct ipa_gsi_ep_config *(*ipa_get_gsi_ep_info)(int ipa_ep_idx);
+	const struct ipa_gsi_ep_config *(*ipa_get_gsi_ep_info)
+		(enum ipa_client_type client);
 
 	int (*ipa_register_ipa_ready_cb)(void (*ipa_ready_cb)(void *user_data),
 		void *user_data);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index feec2aa..4d735df 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -1827,7 +1827,7 @@ static int ipa_q6_clean_q6_tables(void)
 	u32 max_cmds = ipa_get_max_flt_rt_cmds(ipa_ctx->ipa_num_pipes);
 
 	mem.base = dma_alloc_coherent(ipa_ctx->pdev, 4, &mem.phys_base,
-		GFP_KERNEL);
+		GFP_ATOMIC);
 	if (!mem.base) {
 		IPAERR("failed to alloc DMA buff of size 4\n");
 		return -ENOMEM;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index 4fdd84b..dd12169 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -4929,7 +4929,8 @@ int ipa2_disable_apps_wan_cons_deaggr(uint32_t agg_size, uint32_t agg_count)
 	return res;
 }
 
-static struct ipa_gsi_ep_config *ipa2_get_gsi_ep_info(int ipa_ep_idx)
+static const struct ipa_gsi_ep_config *ipa2_get_gsi_ep_info
+	(enum ipa_client_type client)
 {
 	IPAERR("Not supported for IPA 2.x\n");
 	return NULL;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index 75b2824..d293a9d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -1152,8 +1152,7 @@ int ipa3_request_gsi_channel(struct ipa_request_gsi_channel_params *params,
 	struct ipahal_reg_ep_cfg_status ep_status;
 	unsigned long gsi_dev_hdl;
 	enum gsi_status gsi_res;
-	struct ipa_gsi_ep_config gsi_ep_cfg;
-	struct ipa_gsi_ep_config *gsi_ep_cfg_ptr = &gsi_ep_cfg;
+	const struct ipa_gsi_ep_config *gsi_ep_cfg_ptr;
 
 	IPADBG("entry\n");
 	if (params == NULL || out_params == NULL ||
@@ -1227,8 +1226,7 @@ int ipa3_request_gsi_channel(struct ipa_request_gsi_channel_params *params,
 		goto write_evt_scratch_fail;
 	}
 
-	memset(gsi_ep_cfg_ptr, 0, sizeof(struct ipa_gsi_ep_config));
-	gsi_ep_cfg_ptr = ipa_get_gsi_ep_info(ipa_ep_idx);
+	gsi_ep_cfg_ptr = ipa3_get_gsi_ep_info(ep->client);
 	params->chan_params.evt_ring_hdl = ep->gsi_evt_ring_hdl;
 	params->chan_params.ch_id = gsi_ep_cfg_ptr->ipa_gsi_chan_num;
 	gsi_res = gsi_alloc_channel(&params->chan_params, gsi_dev_hdl,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 34c7227..2bcc365 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -474,8 +474,7 @@ int ipa3_send(struct ipa3_sys_context *sys,
 	int fail_dma_wrap = 0;
 	uint size;
 	u32 mem_flag = GFP_ATOMIC;
-	int ipa_ep_idx;
-	struct ipa_gsi_ep_config *gsi_ep_cfg;
+	const struct ipa_gsi_ep_config *gsi_ep_cfg;
 
 	if (unlikely(!in_atomic))
 		mem_flag = GFP_KERNEL;
@@ -483,16 +482,10 @@ int ipa3_send(struct ipa3_sys_context *sys,
 	size = num_desc * sizeof(struct sps_iovec);
 
 	if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) {
-		ipa_ep_idx = ipa3_get_ep_mapping(sys->ep->client);
-		if (unlikely(ipa_ep_idx < 0)) {
-			IPAERR("invalid ep_index of client = %d\n",
-				sys->ep->client);
-			return -EFAULT;
-		}
-		gsi_ep_cfg = ipa3_get_gsi_ep_info(ipa_ep_idx);
+		gsi_ep_cfg = ipa3_get_gsi_ep_info(sys->ep->client);
 		if (unlikely(!gsi_ep_cfg)) {
-			IPAERR("failed to get gsi EP config of ep_idx=%d\n",
-				ipa_ep_idx);
+			IPAERR("failed to get gsi EP config for client=%d\n",
+				sys->ep->client);
 			return -EFAULT;
 		}
 		if (unlikely(num_desc > gsi_ep_cfg->ipa_if_tlv)) {
@@ -1723,7 +1716,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
 	struct ipa3_sys_context *sys;
 	int src_ep_idx;
 	int num_frags, f;
-	struct ipa_gsi_ep_config *gsi_ep;
+	const struct ipa_gsi_ep_config *gsi_ep;
 
 	if (unlikely(!ipa3_ctx)) {
 		IPAERR("IPA3 driver was not initialized\n");
@@ -1777,7 +1770,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
 	 * 2 descriptors are needed for IP_PACKET_INIT and TAG_STATUS.
 	 * 1 descriptor needed for the linear portion of skb.
 	 */
-	gsi_ep = ipa3_get_gsi_ep_info(src_ep_idx);
+	gsi_ep = ipa3_get_gsi_ep_info(ipa3_ctx->ep[src_ep_idx].client);
 	if (gsi_ep && (num_frags + 3 > gsi_ep->ipa_if_tlv)) {
 		if (skb_linearize(skb)) {
 			IPAERR("Failed to linear skb with %d frags\n",
@@ -3958,7 +3951,7 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in,
 	struct gsi_evt_ring_props gsi_evt_ring_props;
 	struct gsi_chan_props gsi_channel_props;
 	union __packed gsi_channel_scratch ch_scratch;
-	struct ipa_gsi_ep_config *gsi_ep_info;
+	const struct ipa_gsi_ep_config *gsi_ep_info;
 	dma_addr_t dma_addr;
 	dma_addr_t evt_dma_addr;
 	int result;
@@ -4021,9 +4014,10 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in,
 		gsi_channel_props.max_re_expected = ep->sys->rx_pool_sz;
 	}
 
-	gsi_ep_info = ipa3_get_gsi_ep_info(ipa3_get_ep_mapping(ep->client));
+	gsi_ep_info = ipa3_get_gsi_ep_info(ep->client);
 	if (!gsi_ep_info) {
-		IPAERR("Invalid ep number\n");
+		IPAERR("Failed getting GSI EP info for client=%d\n",
+		       ep->client);
 		result = -EINVAL;
 		goto fail_get_gsi_ep_info;
 	} else
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index acad448..9f5fa1b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1995,7 +1995,8 @@ int ipa3_uc_mhi_stop_event_update_channel(int channelHandle);
 int ipa3_uc_mhi_print_stats(char *dbg_buff, int size);
 int ipa3_uc_memcpy(phys_addr_t dest, phys_addr_t src, int len);
 void ipa3_tag_destroy_imm(void *user1, int user2);
-struct ipa_gsi_ep_config *ipa3_get_gsi_ep_info(int ipa_ep_idx);
+const struct ipa_gsi_ep_config *ipa3_get_gsi_ep_info
+	(enum ipa_client_type client);
 void ipa3_uc_rg10_write_reg(enum ipahal_reg_name reg, u32 n, u32 val);
 
 u32 ipa3_get_num_pipes(void);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index 9e2ffe7..77ddffa 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
@@ -197,14 +197,14 @@ static int ipa_mhi_start_gsi_channel(enum ipa_client_type client,
 	struct gsi_chan_props ch_props;
 	union __packed gsi_channel_scratch ch_scratch;
 	struct ipa3_ep_context *ep;
-	struct ipa_gsi_ep_config *ep_cfg;
+	const struct ipa_gsi_ep_config *ep_cfg;
 
 	IPA_MHI_FUNC_ENTRY();
 
 	ep = &ipa3_ctx->ep[ipa_ep_idx];
 
 	msi = params->msi;
-	ep_cfg = ipa_get_gsi_ep_info(ipa_ep_idx);
+	ep_cfg = ipa3_get_gsi_ep_info(client);
 	if (!ep_cfg) {
 		IPA_MHI_ERR("Wrong parameter, ep_cfg is NULL\n");
 		return -EPERM;
@@ -332,7 +332,7 @@ int ipa3_mhi_init_engine(struct ipa_mhi_init_engine *params)
 {
 	int res;
 	struct gsi_device_scratch gsi_scratch;
-	struct ipa_gsi_ep_config *gsi_ep_info;
+	const struct ipa_gsi_ep_config *gsi_ep_info;
 
 	IPA_MHI_FUNC_ENTRY();
 
@@ -342,8 +342,7 @@ int ipa3_mhi_init_engine(struct ipa_mhi_init_engine *params)
 	}
 
 	/* Initialize IPA MHI engine */
-	gsi_ep_info = ipa_get_gsi_ep_info(
-		ipa_get_ep_mapping(IPA_CLIENT_MHI_PROD));
+	gsi_ep_info = ipa3_get_gsi_ep_info(IPA_CLIENT_MHI_PROD);
 	if (!gsi_ep_info) {
 		IPAERR("MHI PROD has no ep allocated\n");
 		ipa_assert();
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
index 6167301..352ed88 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
@@ -844,13 +844,14 @@ int ipa3_uc_reset_pipe(enum ipa_client_type ipa_client)
 
 int ipa3_uc_is_gsi_channel_empty(enum ipa_client_type ipa_client)
 {
-	struct ipa_gsi_ep_config *gsi_ep_info;
+	const struct ipa_gsi_ep_config *gsi_ep_info;
 	union IpaHwChkChEmptyCmdData_t cmd;
 	int ret;
 
-	gsi_ep_info = ipa3_get_gsi_ep_info(ipa3_get_ep_mapping(ipa_client));
+	gsi_ep_info = ipa3_get_gsi_ep_info(ipa_client);
 	if (!gsi_ep_info) {
-		IPAERR("Invalid IPA ep index\n");
+		IPAERR("Failed getting GSI EP info for client=%d\n",
+		       ipa_client);
 		return 0;
 	}
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 4c1f2b35..5f7b763 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -95,8 +95,9 @@
 #define QMB_MASTER_SELECT_PCIE (1)
 
 #define IPA_CLIENT_NOT_USED \
-	{IPA_EP_NOT_ALLOCATED, IPA_EP_NOT_ALLOCATED, false, \
-		IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR}
+	{ IPA_EP_NOT_ALLOCATED, IPA_EP_NOT_ALLOCATED, false, \
+	IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, \
+		{ -1, -1, -1, -1, -1 } }
 
 /* Resource Group index*/
 #define IPA_v3_0_GROUP_UL		(0)
@@ -111,12 +112,12 @@
 #define IPA_v3_0_GROUP_Q6ZIP_ENGINE	IPA_v3_0_GROUP_UC_RX_Q
 #define IPA_v3_0_GROUP_MAX		(6)
 
-#define IPA_v3_5_1_GROUP_LWA_DL	(0)
-#define IPA_v3_5_1_GROUP_UL_DL		(1)
-#define IPA_v3_5_1_GROUP_DMA		(2)
-#define IPA_v3_5_1_GROUP_UC_RX_Q	(3)
-#define IPA_v3_5_1_SRC_GROUP_MAX	(4)
-#define IPA_v3_5_1_DST_GROUP_MAX	(3)
+#define IPA_v3_5_GROUP_LWA_DL		(0)
+#define IPA_v3_5_GROUP_UL_DL		(1)
+#define IPA_v3_5_GROUP_DMA		(2)
+#define IPA_v3_5_GROUP_UC_RX_Q		(3)
+#define IPA_v3_5_SRC_GROUP_MAX		(4)
+#define IPA_v3_5_DST_GROUP_MAX		(3)
 
 #define IPA_GROUP_MAX IPA_v3_0_GROUP_MAX
 
@@ -131,12 +132,12 @@ enum ipa_rsrc_grp_type_src {
 	IPA_v3_0_RSRC_GRP_TYPE_SRC_ACK_ENTRIES,
 	IPA_v3_0_RSRC_GRP_TYPE_SRC_MAX,
 
-	IPA_v3_5_1_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS = 0,
-	IPA_v3_5_1_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS,
-	IPA_v3_5_1_RSRC_GRP_TYPE_SRC_DESCRIPTOR_BUFF,
-	IPA_v3_5_1_RSRC_GRP_TYPE_SRC_HPS_DMARS,
-	IPA_v3_5_1_RSRC_GRP_TYPE_SRC_ACK_ENTRIES,
-	IPA_v3_5_1_RSRC_GRP_TYPE_SRC_MAX
+	IPA_v3_5_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS = 0,
+	IPA_v3_5_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS,
+	IPA_v3_5_RSRC_GRP_TYPE_SRC_DESCRIPTOR_BUFF,
+	IPA_v3_5_RSRC_GRP_TYPE_SRC_HPS_DMARS,
+	IPA_v3_5_RSRC_GRP_TYPE_SRC_ACK_ENTRIES,
+	IPA_v3_5_RSRC_GRP_TYPE_SRC_MAX
 };
 
 #define IPA_RSRC_GRP_TYPE_SRC_MAX IPA_v3_0_RSRC_GRP_TYPE_SRC_MAX
@@ -147,9 +148,9 @@ enum ipa_rsrc_grp_type_dst {
 	IPA_v3_0_RSRC_GRP_TYPE_DST_DPS_DMARS,
 	IPA_v3_0_RSRC_GRP_TYPE_DST_MAX,
 
-	IPA_v3_5_1_RSRC_GRP_TYPE_DST_DATA_SECTORS = 0,
-	IPA_v3_5_1_RSRC_GRP_TYPE_DST_DPS_DMARS,
-	IPA_v3_5_1_RSRC_GRP_TYPE_DST_MAX,
+	IPA_v3_5_RSRC_GRP_TYPE_DST_DATA_SECTORS = 0,
+	IPA_v3_5_RSRC_GRP_TYPE_DST_DPS_DMARS,
+	IPA_v3_5_RSRC_GRP_TYPE_DST_MAX,
 };
 #define IPA_RSRC_GRP_TYPE_DST_MAX IPA_v3_0_RSRC_GRP_TYPE_DST_MAX
 
@@ -192,15 +193,15 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config
 	},
 	[IPA_3_5_1] = {
 		/* LWA_DL  UL_DL    not used  UC_RX_Q, other are invalid */
-		[IPA_v3_5_1_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = {
+		[IPA_v3_5_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = {
 		{1, 255}, {1, 255}, {0, 0}, {1, 255}, {0, 0}, {0, 0} },
-		[IPA_v3_5_1_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = {
+		[IPA_v3_5_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = {
 		{10, 10}, {10, 10}, {0, 0}, {8, 8}, {0, 0}, {0, 0} },
-		[IPA_v3_5_1_RSRC_GRP_TYPE_SRC_DESCRIPTOR_BUFF] = {
+		[IPA_v3_5_RSRC_GRP_TYPE_SRC_DESCRIPTOR_BUFF] = {
 		{12, 12}, {14, 14}, {0, 0}, {8, 8}, {0, 0}, {0, 0} },
-		[IPA_v3_5_1_RSRC_GRP_TYPE_SRC_HPS_DMARS] = {
+		[IPA_v3_5_RSRC_GRP_TYPE_SRC_HPS_DMARS] = {
 		{0, 255}, {0, 255}, {0, 255}, {0, 255},  {0, 0}, {0, 0} },
-		[IPA_v3_5_1_RSRC_GRP_TYPE_SRC_ACK_ENTRIES] = {
+		[IPA_v3_5_RSRC_GRP_TYPE_SRC_ACK_ENTRIES] = {
 		{14, 14}, {20, 20}, {0, 0}, {14, 14}, {0, 0}, {0, 0} },
 	}
 };
@@ -218,9 +219,9 @@ static const struct rsrc_min_max ipa3_rsrc_dst_grp_config
 	},
 	[IPA_3_5_1] = {
 			/*LWA_DL UL/DL/DPL not used, other are invalid */
-		[IPA_v3_5_1_RSRC_GRP_TYPE_DST_DATA_SECTORS] = {
+		[IPA_v3_5_RSRC_GRP_TYPE_DST_DATA_SECTORS] = {
 		{4, 4}, {4, 4}, {3, 3}, {0, 0}, {0, 0}, {0, 0} },
-		[IPA_v3_5_1_RSRC_GRP_TYPE_DST_DPS_DMARS] = {
+		[IPA_v3_5_RSRC_GRP_TYPE_DST_DPS_DMARS] = {
 		{2, 255}, {1, 255}, {1, 2}, {0, 0}, {0, 0}, {0, 0} },
 	}
 };
@@ -238,12 +239,19 @@ static const struct rsrc_min_max ipa3_rsrc_rx_grp_config
 		},
 };
 
+enum ipa_ees {
+	IPA_EE_AP = 0,
+	IPA_EE_Q6 = 1,
+	IPA_EE_UC = 3,
+};
+
 struct ipa_ep_configuration {
 	int pipe_num;
 	int group_num;
 	bool support_flt;
 	int sequencer_type;
 	u8 qmb_master_sel;
+	struct ipa_gsi_ep_config ipa_gsi_ep_info;
 };
 
 static const struct ipa_ep_configuration ipa3_ep_mapping
@@ -252,7 +260,8 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 	[IPA_3_0][IPA_CLIENT_WLAN1_PROD]          = {
 			10, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 10, 1, 8, 16, IPA_EE_UC } },
 	[IPA_3_0][IPA_CLIENT_HSIC2_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_USB2_PROD]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_HSIC3_PROD]          = IPA_CLIENT_NOT_USED,
@@ -263,188 +272,227 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 	[IPA_3_0][IPA_CLIENT_USB_PROD]            = {
 			1, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_0][IPA_CLIENT_UC_USB_PROD]         = {
-			2, IPA_v3_0_GROUP_UL, true,
-			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 1, 3, 8, 16, IPA_EE_AP } },
+	[IPA_3_0][IPA_CLIENT_UC_USB_PROD]         = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_A5_WLAN_AMPDU_PROD]  = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_A2_EMBEDDED_PROD]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_A2_TETHERED_PROD]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_APPS_LAN_WAN_PROD]   = {
 			14, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_0][IPA_CLIENT_APPS_CMD_PROD]
-			= {22, IPA_v3_0_GROUP_IMM_CMD, false,
+			QMB_MASTER_SELECT_DDR,
+			{ 14, 11, 8, 16, IPA_EE_AP } },
+	[IPA_3_0][IPA_CLIENT_APPS_CMD_PROD]	  = {
+			22, IPA_v3_0_GROUP_IMM_CMD, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 22, 6, 18, 28, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_ODU_PROD]            = {
 			12, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 12, 9, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_MHI_PROD]            = {
 			0, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_PCIE},
+			QMB_MASTER_SELECT_PCIE,
+			{ 0, 0, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_Q6_LAN_PROD]         = {
 			9, IPA_v3_0_GROUP_UL, false,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 9, 4, 8, 12, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_WAN_PROD]         = {
-			5, IPA_v3_0_GROUP_DL,
-			true, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_0][IPA_CLIENT_Q6_CMD_PROD]
-			= {6, IPA_v3_0_GROUP_IMM_CMD, false,
+			5, IPA_v3_0_GROUP_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_0][IPA_CLIENT_Q6_DECOMP_PROD]      = {7, IPA_v3_0_GROUP_Q6ZIP,
+			QMB_MASTER_SELECT_DDR,
+			{ 5, 0, 16, 32, IPA_EE_Q6 } },
+	[IPA_3_0][IPA_CLIENT_Q6_CMD_PROD] = {
+			6, IPA_v3_0_GROUP_IMM_CMD, false,
+			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
+			QMB_MASTER_SELECT_DDR,
+			{ 6, 1, 18, 28, IPA_EE_Q6 } },
+	[IPA_3_0][IPA_CLIENT_Q6_DECOMP_PROD]      = {
+			7, IPA_v3_0_GROUP_Q6ZIP,
 			false, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_0][IPA_CLIENT_Q6_DECOMP2_PROD]     = {8, IPA_v3_0_GROUP_Q6ZIP,
+			QMB_MASTER_SELECT_DDR,
+			{ 7, 2, 0, 0, IPA_EE_Q6 } },
+	[IPA_3_0][IPA_CLIENT_Q6_DECOMP2_PROD]     = {
+			8, IPA_v3_0_GROUP_Q6ZIP,
 			false, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD]
-			= {12, IPA_v3_0_GROUP_DMA, false,
+			QMB_MASTER_SELECT_DDR,
+			{ 8, 3, 0, 0, IPA_EE_Q6 } },
+	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD] = {
+			12, IPA_v3_0_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
-			QMB_MASTER_SELECT_PCIE},
-	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD]
-			= {13, IPA_v3_0_GROUP_DMA, false,
+			QMB_MASTER_SELECT_PCIE,
+			{ 12, 9, 8, 16, IPA_EE_AP } },
+	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD] = {
+			13, IPA_v3_0_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
-			QMB_MASTER_SELECT_PCIE},
+			QMB_MASTER_SELECT_PCIE,
+			{ 13, 10, 8, 16, IPA_EE_AP } },
 	/* Only for test purpose */
 	[IPA_3_0][IPA_CLIENT_TEST_PROD]           = {
 			1, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 1, 3, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST1_PROD]          = {
 			1, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 1, 3, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST2_PROD]          = {
 			3, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 3, 5, 16, 32, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST3_PROD]          = {
 			12, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 12, 9, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST4_PROD]          = {
 			13, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 13, 10, 8, 16, IPA_EE_AP } },
 
 	[IPA_3_0][IPA_CLIENT_HSIC1_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_WLAN1_CONS]          = {
 			25, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 25, 4, 8, 8, IPA_EE_UC } },
 	[IPA_3_0][IPA_CLIENT_HSIC2_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_USB2_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_WLAN2_CONS]          = {
 			27, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 27, 4, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_HSIC3_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_USB3_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_WLAN3_CONS]          = {
 			28, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 28, 13, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_HSIC4_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_USB4_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_WLAN4_CONS]          = {
 			29, IPA_v3_0_GROUP_DL, false,
-			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			IPA_DPS_HPS_SEQ_TYPE_INVALID,
+			QMB_MASTER_SELECT_DDR,
+			{ 29, 14, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_HSIC5_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_USB_CONS]            = {
 			26, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 26, 12, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_USB_DPL_CONS]        = {
 			17, IPA_v3_0_GROUP_DPL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 17, 2, 8, 12, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_A2_EMBEDDED_CONS]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_A2_TETHERED_CONS]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_A5_LAN_WAN_CONS]     = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_APPS_LAN_CONS]       = {
 			15, IPA_v3_0_GROUP_UL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 15, 7, 8, 12, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_APPS_WAN_CONS]       = {
 			16, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 16, 8, 8, 12, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_ODU_EMB_CONS]        = {
 			23, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 23, 1, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_ODU_TETH_CONS]       = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_MHI_CONS]            = {
 			23, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_PCIE},
+			QMB_MASTER_SELECT_PCIE,
+			{ 23, 1, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_Q6_LAN_CONS]         = {
 			19, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 19, 6, 8, 12, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_WAN_CONS]         = {
 			18, IPA_v3_0_GROUP_UL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 18, 5, 8, 12, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_DUN_CONS]         = {
-			30, IPA_v3_0_GROUP_DIAG,
-			false, IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_0][IPA_CLIENT_Q6_DECOMP_CONS]
-			= {21, IPA_v3_0_GROUP_Q6ZIP, false,
+			30, IPA_v3_0_GROUP_DIAG, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_0][IPA_CLIENT_Q6_DECOMP2_CONS]
-			= {4, IPA_v3_0_GROUP_Q6ZIP, false,
+			QMB_MASTER_SELECT_DDR,
+			{ 30, 7, 4, 4, IPA_EE_Q6 } },
+	[IPA_3_0][IPA_CLIENT_Q6_DECOMP_CONS] = {
+			21, IPA_v3_0_GROUP_Q6ZIP, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS]
-			= {28, IPA_v3_0_GROUP_DMA, false,
+			QMB_MASTER_SELECT_DDR,
+			{ 21, 8, 4, 4, IPA_EE_Q6 } },
+	[IPA_3_0][IPA_CLIENT_Q6_DECOMP2_CONS] = {
+			4, IPA_v3_0_GROUP_Q6ZIP, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_PCIE},
-	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS]
-			= {29, IPA_v3_0_GROUP_DMA, false,
+			QMB_MASTER_SELECT_DDR,
+			{ 4, 9, 4, 4, IPA_EE_Q6 } },
+	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS] = {
+			28, IPA_v3_0_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_PCIE},
+			QMB_MASTER_SELECT_PCIE,
+			{ 28, 13, 8, 8, IPA_EE_AP } },
+	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS] = {
+			29, IPA_v3_0_GROUP_DMA, false,
+			IPA_DPS_HPS_SEQ_TYPE_INVALID,
+			QMB_MASTER_SELECT_PCIE,
+			{ 29, 14, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS]     = IPA_CLIENT_NOT_USED,
 	/* Only for test purpose */
 	[IPA_3_0][IPA_CLIENT_TEST_CONS]           = {
 			26, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 26, 12, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST1_CONS]          = {
 			26, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 26, 12, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST2_CONS]          = {
 			27, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 27, 4, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST3_CONS]          = {
 			28, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 28, 13, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST4_CONS]          = {
 			29, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 29, 14, 8, 8, IPA_EE_AP } },
+
 
 	/* IPA_3_5_1 */
 	[IPA_3_5_1][IPA_CLIENT_HSIC1_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_WLAN1_PROD]          = {
-			7, IPA_v3_5_1_GROUP_UL_DL,
-			true,
+			7, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 7, 1, 8, 16, IPA_EE_UC } },
 	[IPA_3_5_1][IPA_CLIENT_HSIC2_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_USB2_PROD]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_HSIC3_PROD]          = IPA_CLIENT_NOT_USED,
@@ -453,244 +501,169 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 	[IPA_3_5_1][IPA_CLIENT_USB4_PROD]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_HSIC5_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_USB_PROD]            = {
-			0, IPA_v3_5_1_GROUP_UL_DL,
-			true,
+			0, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 0, 0, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_UC_USB_PROD]         = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_A5_WLAN_AMPDU_PROD]  = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_A2_EMBEDDED_PROD]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_A2_TETHERED_PROD]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_APPS_LAN_WAN_PROD]   = {
-			8, IPA_v3_5_1_GROUP_UL_DL,
-			true,
+			8, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 8, 7, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_APPS_CMD_PROD]		= {
-			5, IPA_v3_5_1_GROUP_UL_DL,
-			false,
+			5, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 5, 4, 20, 23, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_ODU_PROD]            = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_MHI_PROD]            = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_Q6_LAN_PROD]         = {
-			3, IPA_v3_5_1_GROUP_UL_DL,
-			true, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR },
-	[IPA_3_5_1][IPA_CLIENT_Q6_WAN_PROD]         = {
-			6, IPA_v3_5_1_GROUP_UL_DL,
-			true, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_5_1][IPA_CLIENT_Q6_CMD_PROD]
-			= {4, IPA_v3_5_1_GROUP_UL_DL, false,
+			3, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 3, 0, 16, 32, IPA_EE_Q6 } },
+	[IPA_3_5_1][IPA_CLIENT_Q6_WAN_PROD]         = {
+			6, IPA_v3_5_GROUP_UL_DL, true,
+			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
+			QMB_MASTER_SELECT_DDR,
+			{ 6, 4, 12, 30, IPA_EE_Q6 } },
+	[IPA_3_5_1][IPA_CLIENT_Q6_CMD_PROD]	    = {
+			4, IPA_v3_5_GROUP_UL_DL, false,
+			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
+			QMB_MASTER_SELECT_DDR,
+			{ 4, 1, 20, 23, IPA_EE_Q6 } },
 	[IPA_3_5_1][IPA_CLIENT_Q6_DECOMP_PROD]      = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_Q6_DECOMP2_PROD]     = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD] = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD] = IPA_CLIENT_NOT_USED,
 	/* Only for test purpose */
 	[IPA_3_5_1][IPA_CLIENT_TEST_PROD]           = {
-			0, IPA_v3_5_1_GROUP_UL_DL, true,
+			0, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 0, 0, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST1_PROD]          = {
-			0, IPA_v3_5_1_GROUP_UL_DL, true,
+			0, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 0, 0, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST2_PROD]          = {
-			2, IPA_v3_5_1_GROUP_UL_DL, true,
+			2, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 2, 3, 16, 32, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST3_PROD]          = {
-			4, IPA_v3_5_1_GROUP_UL_DL, true,
+			4, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 4, 1, 20, 23, IPA_EE_Q6 } },
 	[IPA_3_5_1][IPA_CLIENT_TEST4_PROD]          = {
-			1, IPA_v3_5_1_GROUP_UL_DL, true,
+			1, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 1, 0, 8, 16, IPA_EE_UC } },
 
 	[IPA_3_5_1][IPA_CLIENT_HSIC1_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_WLAN1_CONS]          = {
-			16, IPA_v3_5_1_GROUP_UL_DL,
-			false,
+			16, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 16, 3, 8, 8, IPA_EE_UC } },
 	[IPA_3_5_1][IPA_CLIENT_HSIC2_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_USB2_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_WLAN2_CONS]          =  {
-			18, IPA_v3_5_1_GROUP_UL_DL, false,
+			18, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 18, 9, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_HSIC3_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_USB3_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_WLAN3_CONS]          =  {
-			19, IPA_v3_5_1_GROUP_UL_DL, false,
+			19, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 19, 10, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_HSIC4_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_USB4_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_WLAN4_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_HSIC5_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_USB_CONS]            = {
-			17, IPA_v3_5_1_GROUP_UL_DL,
-			false,
+			17, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 17, 8, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_USB_DPL_CONS]        = {
-			11, IPA_v3_5_1_GROUP_UL_DL,
-			false,
+			11, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 11, 2, 4, 6, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_A2_EMBEDDED_CONS]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_A2_TETHERED_CONS]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_A5_LAN_WAN_CONS]     = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_APPS_LAN_CONS]       = {
-			9, IPA_v3_5_1_GROUP_UL_DL,
-			false,
+			9, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 9, 5, 8, 12, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_APPS_WAN_CONS]       = {
-			10, IPA_v3_5_1_GROUP_UL_DL,
-			false,
+			10, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 10, 6, 8, 12, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_ODU_EMB_CONS]        = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_ODU_TETH_CONS]       = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_MHI_CONS]            = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_Q6_LAN_CONS]         = {
-			13, IPA_v3_5_1_GROUP_UL_DL,
-			false,
+			13, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 13, 3, 8, 12, IPA_EE_Q6 } },
 	[IPA_3_5_1][IPA_CLIENT_Q6_WAN_CONS]         = {
-			12, IPA_v3_5_1_GROUP_UL_DL,
-			false,
+			12, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
-	[IPA_3_5_1][IPA_CLIENT_Q6_DUN_CONS]         = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_Q6_DECOMP_CONS]		= IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_Q6_DECOMP2_CONS]		= IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS] = IPA_CLIENT_NOT_USED,
+			QMB_MASTER_SELECT_DDR,
+			{ 12, 2, 8, 12, IPA_EE_Q6 } },
+	[IPA_3_5_1][IPA_CLIENT_Q6_DUN_CONS]           = IPA_CLIENT_NOT_USED,
+	[IPA_3_5_1][IPA_CLIENT_Q6_DECOMP_CONS]	      = IPA_CLIENT_NOT_USED,
+	[IPA_3_5_1][IPA_CLIENT_Q6_DECOMP2_CONS]	      = IPA_CLIENT_NOT_USED,
+	[IPA_3_5_1][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS]  = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS] = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS] = IPA_CLIENT_NOT_USED,
 	/* Only for test purpose */
 	[IPA_3_5_1][IPA_CLIENT_TEST_CONS]           = {
-			17, IPA_v3_5_1_GROUP_UL_DL,
+			17, IPA_v3_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 17, 8, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST1_CONS]          = {
-			17, IPA_v3_5_1_GROUP_UL_DL,
+			17, IPA_v3_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 17, 8, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST2_CONS]          = {
-			18, IPA_v3_5_1_GROUP_UL_DL,
+			18, IPA_v3_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 18, 9, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST3_CONS]          = {
-			19, IPA_v3_5_1_GROUP_UL_DL,
+			19, IPA_v3_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
+			QMB_MASTER_SELECT_DDR,
+			{ 19, 10, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST4_CONS]          = {
-			11, IPA_v3_5_1_GROUP_UL_DL,
+			11, IPA_v3_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_DDR},
-};
-
-enum ipa_ees {
-	IPA_EE_AP = 0,
-	IPA_EE_Q6 = 1,
-	IPA_EE_UC = 3,
-};
-
-static struct ipa_gsi_ep_config
-	ipa_gsi_ep_info[IPA_VER_MAX][IPA3_MAX_NUM_PIPES] = {
-		/* IPA_3_0 - valid also for IPAv3.1 */
-	[IPA_3_0] = {
-	/* {ipa_ep_num, ipa_gsi_chan_num, ipa_if_tlv, ipa_if_aos, ee} */
-		{0, 0, 8, 16, IPA_EE_AP},
-		{1, 3, 8, 16, IPA_EE_AP},
-		{3, 5, 16, 32, IPA_EE_AP},
-		{4, 9, 4, 4, IPA_EE_Q6},
-		{5, 0, 16, 32, IPA_EE_Q6},
-		{6, 1, 18, 28, IPA_EE_Q6},
-		{7, 2, 0, 0, IPA_EE_Q6},
-		{8, 3, 0, 0, IPA_EE_Q6},
-		{9, 4, 8, 12, IPA_EE_Q6},
-		{10, 1, 8, 16, IPA_EE_UC},
-		{12, 9, 8, 16, IPA_EE_AP},
-		{13, 10, 8, 16, IPA_EE_AP},
-		{14, 11, 8, 16, IPA_EE_AP},
-		{15, 7, 8, 12, IPA_EE_AP},
-		{16, 8, 8, 12, IPA_EE_AP},
-		{17, 2, 8, 12, IPA_EE_AP},
-		{18, 5, 8, 12, IPA_EE_Q6},
-		{19, 6, 8, 12, IPA_EE_Q6},
-		{21, 8, 4, 4, IPA_EE_Q6},
-		{22, 6, 18, 28, IPA_EE_AP},
-		{23, 1, 8, 8, IPA_EE_AP},
-		{25, 4, 8, 8, IPA_EE_UC},
-		{26, 12, 8, 8, IPA_EE_AP},
-		{27, 4, 8, 8, IPA_EE_AP},
-		{28, 13, 8, 8, IPA_EE_AP},
-		{29, 14, 8, 8, IPA_EE_AP},
-		{30, 7, 4, 4, IPA_EE_Q6},
-		{-1, -1, -1, -1, -1}
-	},
-	[IPA_3_5] = {
-	/* {ipa_ep_num, ipa_gsi_chan_num, ipa_if_tlv, ipa_if_aos, ee} */
-		{0, 7, 8, 16, IPA_EE_AP},
-		{1, 0, 8, 16, IPA_EE_UC},
-		{2, 3, 16, 32, IPA_EE_AP},
-		{3, 0, 16, 32, IPA_EE_Q6},
-		{4, 1, 20, 23, IPA_EE_Q6},
-		{5, 4, 20, 23, IPA_EE_AP},
-		{6, 4, 12, 30, IPA_EE_Q6},
-		{7, 1, 8, 16, IPA_EE_UC},
-		{8, 9, 8, 16, IPA_EE_AP},
-		{9, 5, 8, 12, IPA_EE_AP},
-		{10, 6, 8, 12, IPA_EE_AP},
-		{11, 2, 4, 6, IPA_EE_AP},
-		{12, 2, 8, 12, IPA_EE_Q6},
-		{13, 3, 8, 12, IPA_EE_Q6},
-		{14, 10, 4, 6, IPA_EE_AP},
-		{15, 2, 8, 8, IPA_EE_UC},
-		{16, 3, 8, 8, IPA_EE_UC},
-		{17, 11, 8, 8, IPA_EE_AP},
-		{18, 12, 8, 8, IPA_EE_AP},
-		{19, 13, 8, 8, IPA_EE_AP},
-		{-1, -1, -1, -1, -1}
-	},
-	[IPA_3_5_1] = {
-	/* {ipa_ep_num, ipa_gsi_chan_num, ipa_if_tlv, ipa_if_aos, ee} */
-		{0, 0, 8, 16, IPA_EE_AP},
-		{1, 0, 8, 16, IPA_EE_UC},
-		{2, 3, 16, 32, IPA_EE_AP},
-		{3, 0, 16, 32, IPA_EE_Q6},
-		{4, 1, 20, 23, IPA_EE_Q6},
-		{5, 4, 20, 23, IPA_EE_AP},
-		{6, 4, 12, 30, IPA_EE_Q6},
-		{7, 1, 8, 16, IPA_EE_UC},
-		{8, 7, 8, 16, IPA_EE_AP},
-		{9, 5, 8, 12, IPA_EE_AP},
-		{10, 6, 8, 12, IPA_EE_AP},
-		{11, 2, 4, 6, IPA_EE_AP},
-		{12, 2, 8, 12, IPA_EE_Q6},
-		{13, 3, 8, 12, IPA_EE_Q6},
-		{14, 5, 8, 8, IPA_EE_Q6},
-		{15, 2, 8, 8, IPA_EE_UC},
-		{16, 3, 8, 8, IPA_EE_UC},
-		{17, 8, 8, 8, IPA_EE_AP},
-		{18, 9, 8, 8, IPA_EE_AP},
-		{19, 10, 8, 8, IPA_EE_AP},
-		{-1, -1, -1, -1, -1}
-	},
+			QMB_MASTER_SELECT_DDR,
+			{ 11, 2, 4, 6, IPA_EE_AP } },
 };
 
 static struct msm_bus_vectors ipa_init_vectors_v3_0[]  = {
@@ -1253,27 +1226,20 @@ int ipa3_get_ep_mapping(enum ipa_client_type client)
 
 /**
  * ipa3_get_gsi_ep_info() - provide gsi ep information
- * @ipa_ep_idx: IPA endpoint index
+ * @client: IPA client value
  *
  * Return value: pointer to ipa_gsi_ep_info
  */
-struct ipa_gsi_ep_config *ipa3_get_gsi_ep_info(int ipa_ep_idx)
+const struct ipa_gsi_ep_config *ipa3_get_gsi_ep_info
+	(enum ipa_client_type client)
 {
-	int i;
-	u8 hw_index;
-
-	hw_index = ipa3_get_hw_type_index();
-
-	for (i = 0; ; i++) {
-		if (ipa_gsi_ep_info[hw_index][i].ipa_ep_num < 0)
-			break;
-
-		if (ipa_gsi_ep_info[hw_index][i].ipa_ep_num ==
-			ipa_ep_idx)
-			return &(ipa_gsi_ep_info[hw_index][i]);
+	if (client >= IPA_CLIENT_MAX || client < 0) {
+		IPAERR("Bad client number! client =%d\n", client);
+		return NULL;
 	}
 
-	return NULL;
+	return &(ipa3_ep_mapping[ipa3_get_hw_type_index()]
+		[client].ipa_gsi_ep_info);
 }
 
 /**
@@ -3633,14 +3599,14 @@ static void ipa3_write_rsrc_grp_type_reg(int group_index,
 	case IPA_3_5_1:
 		if (src) {
 			switch (group_index) {
-			case IPA_v3_5_1_GROUP_LWA_DL:
-			case IPA_v3_5_1_GROUP_UL_DL:
+			case IPA_v3_5_GROUP_LWA_DL:
+			case IPA_v3_5_GROUP_UL_DL:
 				ipahal_write_reg_n_fields(
 					IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n,
 					n, val);
 				break;
-			case IPA_v3_5_1_GROUP_DMA:
-			case IPA_v3_5_1_GROUP_UC_RX_Q:
+			case IPA_v3_5_GROUP_DMA:
+			case IPA_v3_5_GROUP_UC_RX_Q:
 				ipahal_write_reg_n_fields(
 					IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n,
 					n, val);
@@ -3653,13 +3619,13 @@ static void ipa3_write_rsrc_grp_type_reg(int group_index,
 			}
 		} else {
 			switch (group_index) {
-			case IPA_v3_5_1_GROUP_LWA_DL:
-			case IPA_v3_5_1_GROUP_UL_DL:
+			case IPA_v3_5_GROUP_LWA_DL:
+			case IPA_v3_5_GROUP_UL_DL:
 				ipahal_write_reg_n_fields(
 					IPA_DST_RSRC_GRP_01_RSRC_TYPE_n,
 					n, val);
 				break;
-			case IPA_v3_5_1_GROUP_DMA:
+			case IPA_v3_5_GROUP_DMA:
 				ipahal_write_reg_n_fields(
 					IPA_DST_RSRC_GRP_23_RSRC_TYPE_n,
 					n, val);
@@ -3739,10 +3705,10 @@ void ipa3_set_resorce_groups_min_max_limits(void)
 		dst_grp_idx_max = IPA_v3_0_GROUP_MAX;
 		break;
 	case IPA_3_5_1:
-		src_rsrc_type_max = IPA_v3_5_1_RSRC_GRP_TYPE_SRC_MAX;
-		dst_rsrc_type_max = IPA_v3_5_1_RSRC_GRP_TYPE_DST_MAX;
-		src_grp_idx_max = IPA_v3_5_1_SRC_GROUP_MAX;
-		dst_grp_idx_max = IPA_v3_5_1_DST_GROUP_MAX;
+		src_rsrc_type_max = IPA_v3_5_RSRC_GRP_TYPE_SRC_MAX;
+		dst_rsrc_type_max = IPA_v3_5_RSRC_GRP_TYPE_DST_MAX;
+		src_grp_idx_max = IPA_v3_5_SRC_GROUP_MAX;
+		dst_grp_idx_max = IPA_v3_5_DST_GROUP_MAX;
 		break;
 	default:
 		IPAERR("invalid hw type index\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c
index 67b3cb3..f15f79a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2721,7 +2721,7 @@ static int ipa_fltrt_alloc_init_tbl_hdr(
 	params->nhash_hdr.base = dma_alloc_coherent(ipahal_ctx->ipa_pdev,
 		params->nhash_hdr.size,
 		&params->nhash_hdr.phys_base, GFP_KERNEL);
-	if (!params->nhash_hdr.size) {
+	if (!params->nhash_hdr.base) {
 		IPAHAL_ERR("fail to alloc DMA buff of size %d\n",
 			params->nhash_hdr.size);
 		goto nhash_alloc_fail;
diff --git a/drivers/platform/msm/ipa/test/Makefile b/drivers/platform/msm/ipa/test/Makefile
index e1686e6..c20fd2b 100644
--- a/drivers/platform/msm/ipa/test/Makefile
+++ b/drivers/platform/msm/ipa/test/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_IPA_UT) += ipa_ut_mod.o
-ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o ipa_test_mhi.o
+ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o ipa_test_mhi.o ipa_test_dma.o
diff --git a/drivers/platform/msm/ipa/test/ipa_test_dma.c b/drivers/platform/msm/ipa/test/ipa_test_dma.c
new file mode 100644
index 0000000..78393a3
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_test_dma.c
@@ -0,0 +1,931 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/ipa.h>
+#include "../ipa_v3/ipa_i.h"
+#include "ipa_ut_framework.h"
+
+#define IPA_TEST_DMA_WQ_NAME_BUFF_SZ		64
+#define IPA_TEST_DMA_MT_TEST_NUM_WQ		500
+#define IPA_TEST_DMA_MEMCPY_BUFF_SIZE		16384
+#define IPA_TEST_DMA_MAX_PKT_SIZE		0xFF00
+#define IPA_DMA_TEST_LOOP_NUM			1000
+#define IPA_DMA_TEST_INT_LOOP_NUM		50
+#define IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM	128
+#define IPA_DMA_RUN_TEST_UNIT_IN_LOOP(test_unit, iters, rc, args...)	\
+	do {								\
+		int __i;						\
+		for (__i = 0; __i < iters; __i++) {	\
+			IPA_UT_LOG(#test_unit " START iter %d\n", __i);	\
+			rc = test_unit(args);				\
+			if (!rc)					\
+				continue;				\
+			IPA_UT_LOG(#test_unit " failed %d\n", rc);	\
+			break;						\
+		}							\
+	} while (0)
+
+/**
+ * struct ipa_test_dma_async_user_data - user_data structure for async memcpy
+ * @src_mem: source memory buffer
+ * @dest_mem: destination memory buffer
+ * @call_serial_number: Id of the caller
+ * @copy_done: Completion object
+ */
+struct ipa_test_dma_async_user_data {
+	struct ipa_mem_buffer src_mem;
+	struct ipa_mem_buffer dest_mem;
+	int call_serial_number;
+	struct completion copy_done;
+};
+
+/**
+ * ipa_test_dma_setup() - Suite setup function
+ */
+static int ipa_test_dma_setup(void **ppriv)
+{
+	int rc;
+
+	IPA_UT_DBG("Start Setup\n");
+
+	if (!ipa3_ctx) {
+		IPA_UT_ERR("No IPA ctx\n");
+		return -EINVAL;
+	}
+
+	rc = ipa_dma_init();
+	if (rc)
+		IPA_UT_ERR("Fail to init ipa_dma - return code %d\n", rc);
+	else
+		IPA_UT_DBG("ipa_dma_init() Completed successfully!\n");
+
+	*ppriv = NULL;
+
+	return rc;
+}
+
+/**
+ * ipa_test_dma_teardown() - Suite teardown function
+ */
+static int ipa_test_dma_teardown(void *priv)
+{
+	IPA_UT_DBG("Start Teardown\n");
+	ipa_dma_destroy();
+	return 0;
+}
+
+static int ipa_test_dma_alloc_buffs(struct ipa_mem_buffer *src,
+				struct ipa_mem_buffer *dest,
+				int size)
+{
+	int i;
+	static int val = 1;
+	int rc;
+
+	val++;
+	src->size = size;
+	src->base = dma_alloc_coherent(ipa3_ctx->pdev, src->size,
+				       &src->phys_base, GFP_KERNEL);
+	if (!src->base) {
+		IPA_UT_LOG("fail to alloc dma mem %d bytes\n", size);
+		IPA_UT_TEST_FAIL_REPORT("fail to alloc dma mem");
+		return -ENOMEM;
+	}
+
+	dest->size = size;
+	dest->base = dma_alloc_coherent(ipa3_ctx->pdev, dest->size,
+					&dest->phys_base, GFP_KERNEL);
+	if (!dest->base) {
+		IPA_UT_LOG("fail to alloc dma mem %d bytes\n", size);
+		IPA_UT_TEST_FAIL_REPORT("fail to alloc dma mem");
+		rc = -ENOMEM;
+		goto fail_alloc_dest;
+	}
+
+	memset(dest->base, 0, dest->size);
+	for (i = 0; i < src->size; i++)
+		memset(src->base + i, (val + i) & 0xFF, 1);
+	rc = memcmp(dest->base, src->base, dest->size);
+	if (rc == 0) {
+		IPA_UT_LOG("dest & src buffers are equal\n");
+		IPA_UT_TEST_FAIL_REPORT("dest & src buffers are equal");
+		rc = -EFAULT;
+		goto fail_buf_cmp;
+	}
+
+	return 0;
+
+fail_buf_cmp:
+	dma_free_coherent(ipa3_ctx->pdev, dest->size, dest->base,
+		dest->phys_base);
+fail_alloc_dest:
+	dma_free_coherent(ipa3_ctx->pdev, src->size, src->base,
+		src->phys_base);
+	return rc;
+}
+
+static void ipa_test_dma_destroy_buffs(struct ipa_mem_buffer *src,
+				struct ipa_mem_buffer *dest)
+{
+	dma_free_coherent(ipa3_ctx->pdev, src->size, src->base,
+		src->phys_base);
+	dma_free_coherent(ipa3_ctx->pdev, dest->size, dest->base,
+		dest->phys_base);
+}
+
+/**
+ * ipa_test_dma_memcpy_sync() - memcpy in sync mode
+ *
+ * @size: buffer size
+ * @expect_fail: test expects the memcpy to fail
+ *
+ * To be run during tests
+ * 1. Alloc src and dst buffers
+ * 2. sync memcpy src to dst via dma
+ * 3. compare src and dts if memcpy succeeded as expected
+ */
+static int ipa_test_dma_memcpy_sync(int size, bool expect_fail)
+{
+	int rc = 0;
+	int i;
+	struct ipa_mem_buffer src_mem;
+	struct ipa_mem_buffer dest_mem;
+	u8 *src;
+	u8 *dest;
+
+	rc = ipa_test_dma_alloc_buffs(&src_mem, &dest_mem, size);
+	if (rc) {
+		IPA_UT_LOG("fail to alloc buffers\n");
+		IPA_UT_TEST_FAIL_REPORT("fail to alloc buffers");
+		return rc;
+	}
+
+	rc = ipa_dma_sync_memcpy(dest_mem.phys_base, src_mem.phys_base, size);
+	if (!expect_fail && rc) {
+		IPA_UT_LOG("fail to sync memcpy - rc = %d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("sync memcpy failed");
+		goto free_buffs;
+	}
+	if (expect_fail && !rc) {
+		IPA_UT_LOG("sync memcpy succeeded while expected to fail\n");
+		IPA_UT_TEST_FAIL_REPORT(
+			"sync memcpy succeeded while expected to fail");
+		rc = -EFAULT;
+		goto free_buffs;
+	}
+
+	if (!rc) {
+		/* if memcpy succeeded, compare the buffers */
+		rc = memcmp(dest_mem.base, src_mem.base, size);
+		if (rc) {
+			IPA_UT_LOG("BAD memcpy - buffs are not equals\n");
+			IPA_UT_TEST_FAIL_REPORT(
+				"BAD memcpy - buffs are not equals");
+			src = src_mem.base;
+			dest = dest_mem.base;
+			for (i = 0; i < size; i++)  {
+				if (*(src + i) != *(dest + i)) {
+					IPA_UT_LOG("byte: %d 0x%x != 0x%x\n",
+						i, *(src + i), *(dest + i));
+				}
+			}
+		}
+	} else {
+		/* if memcpy failed as expected, update the rc */
+		rc = 0;
+	}
+
+free_buffs:
+	ipa_test_dma_destroy_buffs(&src_mem, &dest_mem);
+	return rc;
+}
+
+static void ipa_test_dma_async_memcpy_cb(void *comp_obj)
+{
+	struct completion *xfer_done;
+
+	if (!comp_obj) {
+		IPA_UT_ERR("Invalid Input\n");
+		return;
+	}
+	xfer_done = (struct completion *)comp_obj;
+	complete(xfer_done);
+}
+
+static void ipa_test_dma_async_memcpy_cb_user_data(void *user_param)
+{
+	int rc;
+	int i;
+	u8 *src;
+	u8 *dest;
+	struct ipa_test_dma_async_user_data *udata =
+		(struct ipa_test_dma_async_user_data *)user_param;
+
+	if (!udata) {
+		IPA_UT_ERR("Invalid user param\n");
+		return;
+	}
+
+	rc = memcmp(udata->dest_mem.base, udata->src_mem.base,
+		udata->src_mem.size);
+	if (rc) {
+		IPA_UT_LOG("BAD memcpy - buffs are not equal sn=%d\n",
+			udata->call_serial_number);
+		IPA_UT_TEST_FAIL_REPORT(
+			"BAD memcpy - buffs are not equal");
+		src = udata->src_mem.base;
+		dest = udata->dest_mem.base;
+		for (i = 0; i < udata->src_mem.size; i++)  {
+			if (*(src + i) != *(dest + i)) {
+				IPA_UT_ERR("byte: %d 0x%x != 0x%x\n", i,
+					   *(src + i), *(dest + i));
+			}
+		}
+		return;
+	}
+
+	IPA_UT_LOG("Notify on async memcopy sn=%d\n",
+		udata->call_serial_number);
+	complete(&(udata->copy_done));
+}
+
+/**
+ * ipa_test_dma_memcpy_async() - memcpy in async mode
+ *
+ * @size: buffer size
+ * @expect_fail: test expected the memcpy to fail
+ *
+ * To be run during tests
+ * 1. Alloc src and dst buffers
+ * 2. async memcpy src to dst via dma and wait for completion
+ * 3. compare src and dts if memcpy succeeded as expected
+ */
+static int ipa_test_dma_memcpy_async(int size, bool expect_fail)
+{
+	int rc = 0;
+	int i;
+	struct ipa_mem_buffer src_mem;
+	struct ipa_mem_buffer dest_mem;
+	u8 *src;
+	u8 *dest;
+	struct completion xfer_done;
+
+	rc = ipa_test_dma_alloc_buffs(&src_mem, &dest_mem, size);
+	if (rc) {
+		IPA_UT_LOG("fail to alloc buffers\n");
+		IPA_UT_TEST_FAIL_REPORT("fail to alloc buffers");
+		return rc;
+	}
+
+	init_completion(&xfer_done);
+	rc = ipa_dma_async_memcpy(dest_mem.phys_base, src_mem.phys_base, size,
+		ipa_test_dma_async_memcpy_cb, &xfer_done);
+	if (!expect_fail && rc) {
+		IPA_UT_LOG("fail to initiate async memcpy - rc=%d\n",
+			rc);
+		IPA_UT_TEST_FAIL_REPORT("async memcpy initiate failed");
+		goto free_buffs;
+	}
+	if (expect_fail && !rc) {
+		IPA_UT_LOG("async memcpy succeeded while expected to fail\n");
+		IPA_UT_TEST_FAIL_REPORT(
+			"async memcpy succeeded while expected to fail");
+		rc = -EFAULT;
+		goto free_buffs;
+	}
+
+	if (!rc) {
+		/* if memcpy succeeded, compare the buffers */
+		wait_for_completion(&xfer_done);
+		rc = memcmp(dest_mem.base, src_mem.base, size);
+		if (rc) {
+			IPA_UT_LOG("BAD memcpy - buffs are not equals\n");
+			IPA_UT_TEST_FAIL_REPORT(
+				"BAD memcpy - buffs are not equals");
+			src = src_mem.base;
+			dest = dest_mem.base;
+			for (i = 0; i < size; i++)  {
+				if (*(src + i) != *(dest + i)) {
+					IPA_UT_LOG("byte: %d 0x%x != 0x%x\n",
+						i, *(src + i), *(dest + i));
+				}
+			}
+		}
+	} else {
+		/* if memcpy failed as expected, update the rc */
+		rc = 0;
+	}
+
+free_buffs:
+	ipa_test_dma_destroy_buffs(&src_mem, &dest_mem);
+	return rc;
+}
+
+/**
+ * ipa_test_dma_sync_async_memcpy() - memcpy in sync and then async mode
+ *
+ * @size: buffer size
+ *
+ * To be run during tests
+ * 1. several sync memcopy in row
+ * 2. several async memcopy -
+ *	back-to-back (next async try initiated after prev is completed)
+ */
+static int ipa_test_dma_sync_async_memcpy(int size)
+{
+	int rc;
+
+	IPA_DMA_RUN_TEST_UNIT_IN_LOOP(ipa_test_dma_memcpy_sync,
+		IPA_DMA_TEST_INT_LOOP_NUM, rc, size, false);
+	if (rc) {
+		IPA_UT_LOG("sync memcopy fail rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("sync memcopy fail");
+		return rc;
+	}
+
+	IPA_DMA_RUN_TEST_UNIT_IN_LOOP(ipa_test_dma_memcpy_async,
+		IPA_DMA_TEST_INT_LOOP_NUM, rc, size, false);
+	if (rc) {
+		IPA_UT_LOG("async memcopy fail rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("async memcopy fail");
+		return rc;
+	}
+
+	return 0;
+}
+
+/**
+ * TEST: test control API - enable/disable dma
+ *	1. enable dma
+ *	2. disable dma
+ */
+static int ipa_test_dma_control_api(void *priv)
+{
+	int rc;
+
+	IPA_UT_LOG("Test Start\n");
+
+	rc = ipa_dma_enable();
+	if (rc) {
+		IPA_UT_LOG("DMA enable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail enable dma");
+		return rc;
+	}
+
+	rc = ipa_dma_disable();
+	if (rc) {
+		IPA_UT_LOG("DMA disable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail disable dma");
+		return rc;
+	}
+
+	return 0;
+}
+
+/**
+ * TEST: memcpy before dma enable
+ *
+ *	1. sync memcpy - should fail
+ *	2. async memcpy - should fail
+ */
+static int ipa_test_dma_memcpy_before_enable(void *priv)
+{
+	int rc;
+
+	IPA_UT_LOG("Test Start\n");
+
+	rc = ipa_test_dma_memcpy_sync(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, true);
+	if (rc) {
+		IPA_UT_LOG("sync memcpy succeeded unexpectedly rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("sync memcpy succeeded unexpectedly");
+		return rc;
+	}
+
+	rc = ipa_test_dma_memcpy_async(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, true);
+	if (rc) {
+		IPA_UT_LOG("async memcpy succeeded unexpectedly rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("sync memcpy succeeded unexpectedly");
+		return rc;
+	}
+
+	return 0;
+}
+
+/**
+ * TEST: Sync memory copy
+ *
+ *	1. dma enable
+ *	2. sync memcpy
+ *	3. dma disable
+ */
+static int ipa_test_dma_sync_memcpy(void *priv)
+{
+	int rc;
+
+	IPA_UT_LOG("Test Start\n");
+
+	rc = ipa_dma_enable();
+	if (rc) {
+		IPA_UT_LOG("DMA enable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail enable dma");
+		return rc;
+	}
+
+	rc = ipa_test_dma_memcpy_sync(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false);
+	if (rc) {
+		IPA_UT_LOG("sync memcpy failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("sync memcpy failed");
+		(void)ipa_dma_disable();
+		return rc;
+	}
+
+	rc = ipa_dma_disable();
+	if (rc) {
+		IPA_UT_LOG("DMA disable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail disable dma");
+		return rc;
+	}
+
+	return 0;
+}
+
+/**
+ * TEST: Async memory copy
+ *
+ *	1. dma enable
+ *	2. async memcpy
+ *	3. dma disable
+ */
+static int ipa_test_dma_async_memcpy(void *priv)
+{
+	int rc;
+
+	IPA_UT_LOG("Test Start\n");
+
+	rc = ipa_dma_enable();
+	if (rc) {
+		IPA_UT_LOG("DMA enable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail enable dma");
+		return rc;
+	}
+
+	rc = ipa_test_dma_memcpy_async(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false);
+	if (rc) {
+		IPA_UT_LOG("async memcpy failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("async memcpy failed");
+		(void)ipa_dma_disable();
+		return rc;
+	}
+
+	rc = ipa_dma_disable();
+	if (rc) {
+		IPA_UT_LOG("DMA disable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail disable dma");
+		return rc;
+	}
+
+	return 0;
+}
+
+/**
+ * TEST: Iteration of sync memory copy
+ *
+ *	1. dma enable
+ *	2. sync memcpy in loop - in row
+ *	3. dma disable
+ */
+static int ipa_test_dma_sync_memcpy_in_loop(void *priv)
+{
+	int rc;
+
+	IPA_UT_LOG("Test Start\n");
+
+	rc = ipa_dma_enable();
+	if (rc) {
+		IPA_UT_LOG("DMA enable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail enable dma");
+		return rc;
+	}
+
+	IPA_DMA_RUN_TEST_UNIT_IN_LOOP(ipa_test_dma_memcpy_sync,
+		IPA_DMA_TEST_LOOP_NUM, rc,
+		IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false);
+	if (rc) {
+		IPA_UT_LOG("Iterations of sync memcpy failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("Iterations of sync memcpy failed");
+		(void)ipa_dma_disable();
+		return rc;
+	}
+
+	rc = ipa_dma_disable();
+	if (rc) {
+		IPA_UT_LOG("DMA disable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail disable dma");
+		return rc;
+	}
+
+	return 0;
+}
+
+/**
+ * TEST: Iteration of async memory copy
+ *
+ *	1. dma enable
+ *	2. async memcpy in loop - back-to-back
+ *		next async copy is initiated once previous one completed
+ *	3. dma disable
+ */
+static int ipa_test_dma_async_memcpy_in_loop(void *priv)
+{
+	int rc;
+
+	IPA_UT_LOG("Test Start\n");
+
+	rc = ipa_dma_enable();
+	if (rc) {
+		IPA_UT_LOG("DMA enable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail enable dma");
+		return rc;
+	}
+
+	IPA_DMA_RUN_TEST_UNIT_IN_LOOP(ipa_test_dma_memcpy_async,
+		IPA_DMA_TEST_LOOP_NUM, rc,
+		IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false);
+	if (rc) {
+		IPA_UT_LOG("Iterations of async memcpy failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("Iterations of async memcpy failed");
+		(void)ipa_dma_disable();
+		return rc;
+	}
+
+	rc = ipa_dma_disable();
+	if (rc) {
+		IPA_UT_LOG("DMA disable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail disable dma");
+		return rc;
+	}
+
+	return 0;
+}
+
+/**
+ * TEST: Iteration of interleaved sync and async memory copy
+ *
+ *	1. dma enable
+ *	2. sync and async memcpy in loop - interleaved
+ *	3. dma disable
+ */
+static int ipa_test_dma_interleaved_sync_async_memcpy_in_loop(void *priv)
+{
+	int rc;
+
+	IPA_UT_LOG("Test Start\n");
+
+	rc = ipa_dma_enable();
+	if (rc) {
+		IPA_UT_LOG("DMA enable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail enable dma");
+		return rc;
+	}
+
+	IPA_DMA_RUN_TEST_UNIT_IN_LOOP(ipa_test_dma_sync_async_memcpy,
+		IPA_DMA_TEST_INT_LOOP_NUM, rc,
+		IPA_TEST_DMA_MEMCPY_BUFF_SIZE);
+	if (rc) {
+		IPA_UT_LOG(
+			"Iterations of interleaved sync async memcpy failed rc=%d\n"
+			, rc);
+		IPA_UT_TEST_FAIL_REPORT(
+			"Iterations of interleaved sync async memcpy failed");
+		(void)ipa_dma_disable();
+		return rc;
+	}
+
+	rc = ipa_dma_disable();
+	if (rc) {
+		IPA_UT_LOG("DMA disable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail disable dma");
+		return rc;
+	}
+
+	return 0;
+}
+
+static atomic_t ipa_test_dma_mt_test_pass;
+
+static void ipa_test_dma_wrapper_test_one_sync(struct work_struct *work)
+{
+	int rc;
+
+	rc = ipa_test_dma_memcpy_sync(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false);
+	if (rc) {
+		IPA_UT_LOG("fail sync memcpy from thread rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail sync memcpy from thread");
+		return;
+	}
+	atomic_inc(&ipa_test_dma_mt_test_pass);
+}
+
+static void ipa_test_dma_wrapper_test_one_async(struct work_struct *work)
+{
+	int rc;
+
+	rc = ipa_test_dma_memcpy_async(IPA_TEST_DMA_MEMCPY_BUFF_SIZE, false);
+	if (rc) {
+		IPA_UT_LOG("fail async memcpy from thread rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail async memcpy from thread");
+		return;
+	}
+	atomic_inc(&ipa_test_dma_mt_test_pass);
+}
+
+/**
+ * TEST: Multiple threads running sync and sync mem copy
+ *
+ *	1. dma enable
+ *	2. In-loop
+ *		2.1 create wq for sync memcpy
+ *		2.2 create wq for async memcpy
+ *		2.3 queue sync memcpy work
+ *		2.4 queue async memcoy work
+ *	3. In-loop
+ *		3.1 flush and destroy wq sync
+ *		3.2 flush and destroy wq async
+ *	3. dma disable
+ */
+static int ipa_test_dma_mt_sync_async(void *priv)
+{
+	int rc;
+	int i;
+	static struct workqueue_struct *wq_sync[IPA_TEST_DMA_MT_TEST_NUM_WQ];
+	static struct workqueue_struct *wq_async[IPA_TEST_DMA_MT_TEST_NUM_WQ];
+	static struct work_struct work_async[IPA_TEST_DMA_MT_TEST_NUM_WQ];
+	static struct work_struct work_sync[IPA_TEST_DMA_MT_TEST_NUM_WQ];
+	char buff[IPA_TEST_DMA_WQ_NAME_BUFF_SZ];
+
+	memset(wq_sync, 0, sizeof(wq_sync));
+	memset(wq_sync, 0, sizeof(wq_async));
+	memset(work_async, 0, sizeof(work_async));
+	memset(work_sync, 0, sizeof(work_sync));
+
+	rc = ipa_dma_enable();
+	if (rc) {
+		IPA_UT_LOG("DMA enable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail enable dma");
+		return rc;
+	}
+
+	atomic_set(&ipa_test_dma_mt_test_pass, 0);
+	for (i = 0; i < IPA_TEST_DMA_MT_TEST_NUM_WQ; i++) {
+		snprintf(buff, sizeof(buff), "ipa_test_dmaSwq%d", i);
+		wq_sync[i] = create_singlethread_workqueue(buff);
+		if (!wq_sync[i]) {
+			IPA_UT_ERR("failed to create sync wq#%d\n", i);
+			rc = -EFAULT;
+			goto fail_create_wq;
+		}
+		snprintf(buff, IPA_RESOURCE_NAME_MAX, "ipa_test_dmaAwq%d", i);
+		wq_async[i] = create_singlethread_workqueue(buff);
+		if (!wq_async[i]) {
+			IPA_UT_ERR("failed to create async wq#%d\n", i);
+			rc = -EFAULT;
+			goto fail_create_wq;
+		}
+
+		INIT_WORK(&work_sync[i], ipa_test_dma_wrapper_test_one_sync);
+		queue_work(wq_sync[i], &work_sync[i]);
+		INIT_WORK(&work_async[i], ipa_test_dma_wrapper_test_one_async);
+		queue_work(wq_async[i], &work_async[i]);
+	}
+
+	for (i = 0; i < IPA_TEST_DMA_MT_TEST_NUM_WQ; i++) {
+		flush_workqueue(wq_sync[i]);
+		destroy_workqueue(wq_sync[i]);
+		flush_workqueue(wq_async[i]);
+		destroy_workqueue(wq_async[i]);
+	}
+
+	rc = ipa_dma_disable();
+	if (rc) {
+		IPA_UT_LOG("DMA disable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail disable dma");
+		return rc;
+	}
+
+	if ((2 * IPA_TEST_DMA_MT_TEST_NUM_WQ) !=
+		atomic_read(&ipa_test_dma_mt_test_pass)) {
+		IPA_UT_LOG(
+			"Multi-threaded sync/async memcopy failed passed=%d\n"
+			, atomic_read(&ipa_test_dma_mt_test_pass));
+		IPA_UT_TEST_FAIL_REPORT(
+			"Multi-threaded sync/async memcopy failed");
+		return -EFAULT;
+	}
+
+	return 0;
+
+fail_create_wq:
+	(void)ipa_dma_disable();
+	for (i = 0; i < IPA_TEST_DMA_MT_TEST_NUM_WQ; i++) {
+		if (wq_sync[i])
+			destroy_workqueue(wq_sync[i]);
+		if (wq_async[i])
+			destroy_workqueue(wq_async[i]);
+	}
+
+	return rc;
+}
+
+/**
+ * TEST: Several parallel async memory copy iterations
+ *
+ *	1. create several user_data structures - one per iteration
+ *	2. allocate buffs. Give slice for each iteration
+ *	3. iterations of async mem copy
+ *	4. wait for all to complete
+ *	5. dma disable
+ */
+static int ipa_test_dma_parallel_async_memcpy_in_loop(void *priv)
+{
+	int rc;
+	struct ipa_test_dma_async_user_data *udata;
+	struct ipa_mem_buffer all_src_mem;
+	struct ipa_mem_buffer all_dest_mem;
+	int i;
+	bool is_fail = false;
+
+	IPA_UT_LOG("Test Start\n");
+
+	rc = ipa_dma_enable();
+	if (rc) {
+		IPA_UT_LOG("DMA enable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail enable dma");
+		return rc;
+	}
+
+	udata = kzalloc(IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM *
+		sizeof(struct ipa_test_dma_async_user_data), GFP_KERNEL);
+	if (!udata) {
+		IPA_UT_ERR("fail allocate user_data array\n");
+		(void)ipa_dma_disable();
+		return -ENOMEM;
+	}
+
+	rc = ipa_test_dma_alloc_buffs(&all_src_mem, &all_dest_mem,
+		IPA_TEST_DMA_MEMCPY_BUFF_SIZE);
+	if (rc) {
+		IPA_UT_LOG("fail to alloc buffers\n");
+		IPA_UT_TEST_FAIL_REPORT("fail to alloc buffers");
+		kfree(udata);
+		(void)ipa_dma_disable();
+		return rc;
+	}
+
+	for (i = 0 ; i < IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM ; i++) {
+		udata[i].src_mem.size =
+			IPA_TEST_DMA_MEMCPY_BUFF_SIZE /
+			IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM;
+		udata[i].src_mem.base = all_src_mem.base + i *
+			(IPA_TEST_DMA_MEMCPY_BUFF_SIZE /
+			IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM);
+		udata[i].src_mem.phys_base = all_src_mem.phys_base + i *
+			(IPA_TEST_DMA_MEMCPY_BUFF_SIZE /
+			IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM);
+
+		udata[i].dest_mem.size =
+			(IPA_TEST_DMA_MEMCPY_BUFF_SIZE /
+			IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM);
+		udata[i].dest_mem.base = all_dest_mem.base + i *
+			(IPA_TEST_DMA_MEMCPY_BUFF_SIZE /
+			IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM);
+		udata[i].dest_mem.phys_base = all_dest_mem.phys_base + i *
+			(IPA_TEST_DMA_MEMCPY_BUFF_SIZE /
+			IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM);
+
+		udata[i].call_serial_number = i + 1;
+		init_completion(&(udata[i].copy_done));
+		rc = ipa_dma_async_memcpy(udata[i].dest_mem.phys_base,
+			udata[i].src_mem.phys_base,
+			(IPA_TEST_DMA_MEMCPY_BUFF_SIZE /
+			IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM),
+			ipa_test_dma_async_memcpy_cb_user_data, &udata[i]);
+		if (rc) {
+			IPA_UT_LOG("async memcpy initiation fail i=%d rc=%d\n",
+				i, rc);
+			is_fail = true;
+		}
+	}
+
+	for (i = 0; i < IPA_DMA_TEST_ASYNC_PARALLEL_LOOP_NUM ; i++)
+		wait_for_completion(&udata[i].copy_done);
+
+	ipa_test_dma_destroy_buffs(&all_src_mem, &all_dest_mem);
+	kfree(udata);
+	rc = ipa_dma_disable();
+	if (rc) {
+		IPA_UT_LOG("DMA disable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail disable dma");
+		return rc;
+	}
+
+	if (is_fail) {
+		IPA_UT_LOG("async memcopy failed\n");
+		IPA_UT_TEST_FAIL_REPORT("async memcopy failed");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+/**
+ * TEST: Sync memory copy
+ *
+ *	1. dma enable
+ *	2. sync memcpy with max packet size
+ *	3. dma disable
+ */
+static int ipa_test_dma_sync_memcpy_max_pkt_size(void *priv)
+{
+	int rc;
+
+	IPA_UT_LOG("Test Start\n");
+
+	rc = ipa_dma_enable();
+	if (rc) {
+		IPA_UT_LOG("DMA enable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail enable dma");
+		return rc;
+	}
+
+	rc = ipa_test_dma_memcpy_sync(IPA_TEST_DMA_MAX_PKT_SIZE, false);
+	if (rc) {
+		IPA_UT_LOG("sync memcpy failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("sync memcpy failed");
+		(void)ipa_dma_disable();
+		return rc;
+	}
+
+	rc = ipa_dma_disable();
+	if (rc) {
+		IPA_UT_LOG("DMA disable failed rc=%d\n", rc);
+		IPA_UT_TEST_FAIL_REPORT("fail disable dma");
+		return rc;
+	}
+
+	return 0;
+}
+
+/* Suite definition block */
+IPA_UT_DEFINE_SUITE_START(dma, "DMA for GSI",
+	ipa_test_dma_setup, ipa_test_dma_teardown)
+{
+	IPA_UT_ADD_TEST(control_api,
+		"Control API",
+		ipa_test_dma_control_api,
+		true, IPA_HW_v3_0, IPA_HW_MAX),
+	IPA_UT_ADD_TEST(memcpy_before_enable,
+		"Call memcpy before dma enable and expect it to fail",
+		ipa_test_dma_memcpy_before_enable,
+		true, IPA_HW_v3_0, IPA_HW_MAX),
+	IPA_UT_ADD_TEST(sync_memcpy,
+		"Sync memory copy",
+		ipa_test_dma_sync_memcpy,
+		true, IPA_HW_v3_0, IPA_HW_MAX),
+	IPA_UT_ADD_TEST(async_memcpy,
+		"Async memory copy",
+		ipa_test_dma_async_memcpy,
+		true, IPA_HW_v3_0, IPA_HW_MAX),
+	IPA_UT_ADD_TEST(sync_memcpy_in_loop,
+		"Several sync memory copy iterations",
+		ipa_test_dma_sync_memcpy_in_loop,
+		true, IPA_HW_v3_0, IPA_HW_MAX),
+	IPA_UT_ADD_TEST(async_memcpy_in_loop,
+		"Several async memory copy iterations",
+		ipa_test_dma_async_memcpy_in_loop,
+		true, IPA_HW_v3_0, IPA_HW_MAX),
+	IPA_UT_ADD_TEST(interleaved_sync_async_memcpy_in_loop,
+		"Several interleaved sync and async memory copy iterations",
+		ipa_test_dma_interleaved_sync_async_memcpy_in_loop,
+		true, IPA_HW_v3_0, IPA_HW_MAX),
+	IPA_UT_ADD_TEST(multi_threaded_multiple_sync_async_memcpy,
+		"Several multi-threaded sync and async memory copy iterations",
+		ipa_test_dma_mt_sync_async,
+		true, IPA_HW_v3_0, IPA_HW_MAX),
+	IPA_UT_ADD_TEST(parallel_async_memcpy_in_loop,
+		"Several parallel async memory copy iterations",
+		ipa_test_dma_parallel_async_memcpy_in_loop,
+		true, IPA_HW_v3_0, IPA_HW_MAX),
+	IPA_UT_ADD_TEST(sync_memcpy_max_pkt_size,
+		"Sync memory copy with max packet size",
+		ipa_test_dma_sync_memcpy_max_pkt_size,
+		true, IPA_HW_v3_0, IPA_HW_MAX),
+} IPA_UT_DEFINE_SUITE_END(dma);
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h b/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
index 944800f..4a9d3b0 100644
--- a/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
+++ b/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,7 @@
  * No importance for order.
  */
 IPA_UT_DECLARE_SUITE(mhi);
+IPA_UT_DECLARE_SUITE(dma);
 IPA_UT_DECLARE_SUITE(example);
 
 
@@ -31,6 +32,7 @@ IPA_UT_DECLARE_SUITE(example);
 IPA_UT_DEFINE_ALL_SUITES_START
 {
 	IPA_UT_REGISTER_SUITE(mhi),
+	IPA_UT_REGISTER_SUITE(dma),
 	IPA_UT_REGISTER_SUITE(example),
 } IPA_UT_DEFINE_ALL_SUITES_END;
 
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index aa51411..a072d35 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -525,6 +525,15 @@
 	  for the platforms that use APRv2.
 	  Say M if you want to enable this module.
 
+config MSM_CDSP_LOADER
+	tristate "CDSP loader support"
+	depends on MSM_GLINK
+	help
+	  Enable CDSP image loader.
+	  The CDSP loader brings CDSP out of reset
+	  for platforms that have compute DSP.
+	  Say M if you want to enable this module.
+
 config MSM_AVTIMER
 	tristate "Avtimer Driver"
 	depends on MSM_QDSP6_APRV2_GLINK || MSM_QDSP6_APRV3_GLINK
diff --git a/drivers/soc/qcom/qdsp6v2/Makefile b/drivers/soc/qcom/qdsp6v2/Makefile
index f3505ba..8c5b0d0 100644
--- a/drivers/soc/qcom/qdsp6v2/Makefile
+++ b/drivers/soc/qcom/qdsp6v2/Makefile
@@ -7,3 +7,4 @@
 obj-$(CONFIG_MSM_QDSP6_SSR) += audio_ssr.o
 obj-$(CONFIG_MSM_QDSP6_PDR) += audio_pdr.o
 obj-$(CONFIG_MSM_QDSP6_NOTIFIER) += audio_notifier.o
+obj-$(CONFIG_MSM_CDSP_LOADER) += cdsp-loader.o
diff --git a/drivers/soc/qcom/qdsp6v2/cdsp-loader.c b/drivers/soc/qcom/qdsp6v2/cdsp-loader.c
new file mode 100644
index 0000000..9bb4eb0
--- /dev/null
+++ b/drivers/soc/qcom/qdsp6v2/cdsp-loader.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2012-2014, 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/sysfs.h>
+#include <soc/qcom/subsystem_restart.h>
+
+#define BOOT_CMD 1
+#define IMAGE_UNLOAD_CMD 0
+
+#define CDSP_SUBSYS_DOWN 0
+#define CDSP_SUBSYS_LOADED 1
+
+static ssize_t cdsp_boot_store(struct kobject *kobj,
+	struct kobj_attribute *attr,
+	const char *buf, size_t count);
+
+struct cdsp_loader_private {
+	void *pil_h;
+	struct kobject *boot_cdsp_obj;
+	struct attribute_group *attr_group;
+};
+
+static struct kobj_attribute cdsp_boot_attribute =
+	__ATTR(boot, 0220, NULL, cdsp_boot_store);
+
+static struct attribute *attrs[] = {
+	&cdsp_boot_attribute.attr,
+	NULL,
+};
+
+static u32 cdsp_state = CDSP_SUBSYS_DOWN;
+static struct platform_device *cdsp_private;
+static void cdsp_loader_unload(struct platform_device *pdev);
+
+static int cdsp_loader_do(struct platform_device *pdev)
+{
+	struct cdsp_loader_private *priv = NULL;
+
+	int rc = 0;
+	const char *img_name;
+
+	if (!pdev) {
+		dev_err(&pdev->dev, "%s: Platform device null\n", __func__);
+		goto fail;
+	}
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev,
+			"%s: Device tree information missing\n", __func__);
+
+		goto fail;
+	}
+
+	rc = of_property_read_string(pdev->dev.of_node,
+					"qcom,proc-img-to-load",
+					&img_name);
+	if (rc)
+		goto fail;
+
+	if (!strcmp(img_name, "cdsp")) {
+		/* cdsp_state always returns "0".*/
+		if (cdsp_state == CDSP_SUBSYS_DOWN) {
+			priv = platform_get_drvdata(pdev);
+			if (!priv) {
+				dev_err(&pdev->dev,
+				" %s: Private data get failed\n", __func__);
+				goto fail;
+			}
+
+			priv->pil_h = subsystem_get("cdsp");
+			if (IS_ERR(priv->pil_h)) {
+				dev_err(&pdev->dev, "%s: pil get failed,\n",
+					__func__);
+				goto fail;
+			}
+
+			/* Set the state of the CDSP.*/
+			cdsp_state = CDSP_SUBSYS_LOADED;
+		} else if (cdsp_state == CDSP_SUBSYS_LOADED) {
+			dev_dbg(&pdev->dev,
+			"%s: CDSP state = %x\n", __func__, cdsp_state);
+		}
+
+		dev_dbg(&pdev->dev, "%s: CDSP image is loaded\n", __func__);
+		return rc;
+	}
+
+fail:
+	dev_err(&pdev->dev, "%s: CDSP image loading failed\n", __func__);
+	return rc;
+}
+
+
+static ssize_t cdsp_boot_store(struct kobject *kobj,
+	struct kobj_attribute *attr,
+	const char *buf,
+	size_t count)
+{
+	int boot = 0, ret = 0;
+
+	ret = sscanf(buf, "%du", &boot);
+
+	if (ret != 1)
+		pr_debug("%s: invalid arguments for cdsp_loader.\n", __func__);
+
+	if (boot == BOOT_CMD) {
+		pr_debug("%s: going to call cdsp_loader_do\n", __func__);
+		cdsp_loader_do(cdsp_private);
+	} else if (boot == IMAGE_UNLOAD_CMD) {
+		pr_debug("%s: going to call adsp_unloader\n", __func__);
+		cdsp_loader_unload(cdsp_private);
+	}
+	return count;
+}
+
+static void cdsp_loader_unload(struct platform_device *pdev)
+{
+	struct cdsp_loader_private *priv = NULL;
+
+	priv = platform_get_drvdata(pdev);
+
+	if (!priv)
+		return;
+
+	if (priv->pil_h) {
+		dev_dbg(&pdev->dev, "%s: calling subsystem put\n", __func__);
+		subsystem_put(priv->pil_h);
+		priv->pil_h = NULL;
+	}
+}
+
+static int cdsp_loader_init_sysfs(struct platform_device *pdev)
+{
+	int ret = -EINVAL;
+	struct cdsp_loader_private *priv = NULL;
+
+	cdsp_private = NULL;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	priv->pil_h = NULL;
+	priv->boot_cdsp_obj = NULL;
+	priv->attr_group = devm_kzalloc(&pdev->dev,
+				sizeof(*(priv->attr_group)),
+				GFP_KERNEL);
+	if (!priv->attr_group) {
+		dev_err(&pdev->dev, "%s: malloc attr_group failed\n",
+						__func__);
+		ret = -ENOMEM;
+		goto error_return;
+	}
+
+	priv->attr_group->attrs = attrs;
+
+	priv->boot_cdsp_obj = kobject_create_and_add("boot_cdsp", kernel_kobj);
+	if (!priv->boot_cdsp_obj) {
+		dev_err(&pdev->dev, "%s: sysfs create and add failed\n",
+						__func__);
+		ret = -ENOMEM;
+		goto error_return;
+	}
+
+	ret = sysfs_create_group(priv->boot_cdsp_obj, priv->attr_group);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: sysfs create group failed %d\n",
+							__func__, ret);
+		goto error_return;
+	}
+
+	cdsp_private = pdev;
+
+	return 0;
+
+error_return:
+
+	if (priv->boot_cdsp_obj) {
+		kobject_del(priv->boot_cdsp_obj);
+		priv->boot_cdsp_obj = NULL;
+	}
+
+	return ret;
+}
+
+static int cdsp_loader_remove(struct platform_device *pdev)
+{
+	struct cdsp_loader_private *priv = NULL;
+
+	priv = platform_get_drvdata(pdev);
+
+	if (!priv)
+		return 0;
+
+	if (priv->pil_h) {
+		subsystem_put(priv->pil_h);
+		priv->pil_h = NULL;
+	}
+
+	if (priv->boot_cdsp_obj) {
+		sysfs_remove_group(priv->boot_cdsp_obj, priv->attr_group);
+		kobject_del(priv->boot_cdsp_obj);
+		priv->boot_cdsp_obj = NULL;
+	}
+
+	return 0;
+}
+
+static int cdsp_loader_probe(struct platform_device *pdev)
+{
+	int ret = cdsp_loader_init_sysfs(pdev);
+
+	if (ret != 0) {
+		dev_err(&pdev->dev, "%s: Error in initing sysfs\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id cdsp_loader_dt_match[] = {
+	{ .compatible = "qcom,cdsp-loader" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, cdsp_loader_dt_match);
+
+static struct platform_driver cdsp_loader_driver = {
+	.driver = {
+		.name = "cdsp-loader",
+		.owner = THIS_MODULE,
+		.of_match_table = cdsp_loader_dt_match,
+	},
+	.probe = cdsp_loader_probe,
+	.remove = cdsp_loader_remove,
+};
+
+static int __init cdsp_loader_init(void)
+{
+	return platform_driver_register(&cdsp_loader_driver);
+}
+module_init(cdsp_loader_init);
+
+static void __exit cdsp_loader_exit(void)
+{
+	platform_driver_unregister(&cdsp_loader_driver);
+}
+module_exit(cdsp_loader_exit);
+
+MODULE_DESCRIPTION("CDSP Loader module");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 0839818..3a4f264 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -186,6 +186,7 @@ extern void clocksource_suspend(void);
 extern void clocksource_resume(void);
 extern struct clocksource * __init clocksource_default_clock(void);
 extern void clocksource_mark_unstable(struct clocksource *cs);
+extern void clocksource_select_force(void);
 
 extern u64
 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cycles);
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 9535e79..ec7047c 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2016-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -175,6 +175,7 @@ struct coresight_device {
 	const struct coresight_ops *ops;
 	struct device dev;
 	atomic_t *refcnt;
+	struct coresight_path *node;
 	bool orphan;
 	bool enable;	/* true only if configured as part of a path */
 	bool activated;	/* true only if a sink is part of a path */
diff --git a/include/linux/device.h b/include/linux/device.h
index d85101c..d469121 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -55,6 +55,8 @@ struct bus_attribute {
 	struct bus_attribute bus_attr_##_name = __ATTR_RW(_name)
 #define BUS_ATTR_RO(_name) \
 	struct bus_attribute bus_attr_##_name = __ATTR_RO(_name)
+#define BUS_ATTR_WO(_name) \
+	struct bus_attribute bus_attr_##_name = __ATTR_WO(_name)
 
 extern int __must_check bus_create_file(struct bus_type *,
 					struct bus_attribute *);
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index 5fc7dda..985d2f5 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -1412,7 +1412,8 @@ struct iommu_domain *ipa_get_smmu_domain(void);
 
 int ipa_disable_apps_wan_cons_deaggr(uint32_t agg_size, uint32_t agg_count);
 
-struct ipa_gsi_ep_config *ipa_get_gsi_ep_info(int ipa_ep_idx);
+const struct ipa_gsi_ep_config *ipa_get_gsi_ep_info
+	(enum ipa_client_type client);
 
 int ipa_stop_gsi_channel(u32 clnt_hdl);
 
@@ -2156,7 +2157,8 @@ static inline int ipa_disable_apps_wan_cons_deaggr(void)
 	return -EINVAL;
 }
 
-static inline struct ipa_gsi_ep_config *ipa_get_gsi_ep_info(int ipa_ep_idx)
+static inline const struct ipa_gsi_ep_config *ipa_get_gsi_ep_info
+	(enum ipa_client_type client)
 {
 	return NULL;
 }
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index da25f07..f7033fa 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -341,7 +341,7 @@ int memblock_is_map_memory(phys_addr_t addr);
 int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
 bool memblock_is_reserved(phys_addr_t addr);
 bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
-int memblock_overlaps_memory(phys_addr_t base, phys_addr_t size);
+bool memblock_overlaps_memory(phys_addr_t base, phys_addr_t size);
 
 extern void __memblock_dump_all(void);
 
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
new file mode 100644
index 0000000..5b644c5
--- /dev/null
+++ b/include/linux/qcom-geni-se.h
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_QCOM_GENI_SE
+#define _LINUX_QCOM_GENI_SE
+#include <linux/io.h>
+
+enum se_xfer_mode {
+	INVALID,
+	FIFO_MODE,
+	GSI_DMA,
+};
+
+enum se_protocol_types {
+	NONE,
+	SPI,
+	UART,
+	I2C,
+	I3C
+};
+
+#define GENI_INIT_CFG_REVISION		(0x0)
+#define GENI_S_INIT_CFG_REVISION	(0x4)
+#define GENI_FORCE_DEFAULT_REG		(0x20)
+#define GENI_OUTPUT_CTRL		(0x24)
+#define GENI_CGC_CTRL			(0x28)
+#define SE_GENI_STATUS			(0x40)
+#define GENI_SER_M_CLK_CFG		(0x48)
+#define GENI_SER_S_CLK_CFG		(0x4C)
+#define GENI_CLK_CTRL_RO		(0x60)
+#define GENI_IF_DISABLE_RO		(0x64)
+#define GENI_FW_REVISION_RO		(0x68)
+#define GENI_FW_S_REVISION_RO		(0x6C)
+#define SE_GENI_CLK_SEL			(0x7C)
+#define SE_GENI_DMA_MODE_EN		(0x258)
+#define SE_GENI_TX_PACKING_CFG0		(0x260)
+#define SE_GENI_TX_PACKING_CFG1		(0x264)
+#define SE_GENI_RX_PACKING_CFG0		(0x284)
+#define SE_GENI_RX_PACKING_CFG1		(0x288)
+#define SE_GENI_M_CMD0			(0x600)
+#define SE_GENI_M_CMD_CTRL_REG		(0x604)
+#define SE_GENI_M_IRQ_STATUS		(0x610)
+#define SE_GENI_M_IRQ_EN		(0x614)
+#define SE_GENI_M_IRQ_CLEAR		(0x618)
+#define SE_GENI_S_CMD0			(0x630)
+#define SE_GENI_S_CMD_CTRL_REG		(0x634)
+#define SE_GENI_S_IRQ_STATUS		(0x640)
+#define SE_GENI_S_IRQ_EN		(0x644)
+#define SE_GENI_S_IRQ_CLEAR		(0x648)
+#define SE_GENI_TX_FIFOn		(0x700)
+#define SE_GENI_RX_FIFOn		(0x780)
+#define SE_GENI_TX_FIFO_STATUS		(0x800)
+#define SE_GENI_RX_FIFO_STATUS		(0x804)
+#define SE_GENI_TX_WATERMARK_REG	(0x80C)
+#define SE_GENI_RX_WATERMARK_REG	(0x810)
+#define SE_GENI_RX_RFR_WATERMARK_REG	(0x814)
+#define SE_GENI_M_GP_LENGTH		(0x910)
+#define SE_GENI_S_GP_LENGTH		(0x914)
+#define SE_IRQ_EN			(0xE1C)
+#define SE_HW_PARAM_0			(0xE24)
+#define SE_HW_PARAM_1			(0xE28)
+#define SE_DMA_GENERAL_CFG		(0xE30)
+
+/* GENI_OUTPUT_CTRL fields */
+#define DEFAULT_IO_OUTPUT_CTRL_MSK	(GENMASK(6, 0))
+
+/* GENI_FORCE_DEFAULT_REG fields */
+#define FORCE_DEFAULT	(BIT(0))
+
+/* GENI_CGC_CTRL fields */
+#define CFG_AHB_CLK_CGC_ON		(BIT(0))
+#define CFG_AHB_WR_ACLK_CGC_ON		(BIT(1))
+#define DATA_AHB_CLK_CGC_ON		(BIT(2))
+#define SCLK_CGC_ON			(BIT(3))
+#define TX_CLK_CGC_ON			(BIT(4))
+#define RX_CLK_CGC_ON			(BIT(5))
+#define EXT_CLK_CGC_ON			(BIT(6))
+#define PROG_RAM_HCLK_OFF		(BIT(8))
+#define PROG_RAM_SCLK_OFF		(BIT(9))
+#define DEFAULT_CGC_EN			(GENMASK(6, 0))
+
+/* GENI_STATUS fields */
+#define M_GENI_CMD_ACTIVE		(BIT(0))
+#define S_GENI_CMD_ACTIVE		(BIT(12))
+
+/* GENI_SER_M_CLK_CFG/GENI_SER_S_CLK_CFG */
+#define SER_CLK_EN			(BIT(0))
+#define CLK_DIV_MSK			(GENMASK(15, 4))
+#define CLK_DIV_SHFT			(4)
+
+/* CLK_CTRL_RO fields */
+
+/* IF_DISABLE_RO fields */
+
+/* FW_REVISION_RO fields */
+#define FW_REV_PROTOCOL_MSK	(GENMASK(15, 8))
+#define FW_REV_PROTOCOL_SHFT	(8)
+
+/* SE_GENI_DMA_MODE_EN */
+#define GENI_DMA_MODE_EN	(BIT(0))
+
+/* GENI_M_CMD0 fields */
+#define M_OPCODE_MSK		(GENMASK(31, 27))
+#define M_OPCODE_SHFT		(27)
+#define M_PARAMS_MSK		(GENMASK(26, 0))
+
+/* GENI_M_CMD_CTRL_REG */
+#define M_GENI_CMD_CANCEL	BIT(2)
+#define M_GENI_CMD_ABORT	BIT(1)
+#define M_GENI_DISABLE		BIT(0)
+
+/* GENI_S_CMD0 fields */
+#define S_OPCODE_MSK		(GENMASK(31, 27))
+#define S_OPCODE_SHFT		(27)
+#define S_PARAMS_MSK		(GENMASK(26, 0))
+
+/* GENI_S_CMD_CTRL_REG */
+#define S_GENI_CMD_CANCEL	(BIT(2))
+#define S_GENI_CMD_ABORT	(BIT(1))
+#define S_GENI_DISABLE		(BIT(0))
+
+/* GENI_M_IRQ_EN fields */
+#define M_CMD_DONE_EN		(BIT(0))
+#define M_CMD_OVERRUN_EN	(BIT(1))
+#define M_ILLEGAL_CMD_EN	(BIT(2))
+#define M_CMD_FAILURE_EN	(BIT(3))
+#define M_CMD_CANCEL_EN		(BIT(4))
+#define M_CMD_ABORT_EN		(BIT(5))
+#define M_TIMESTAMP_EN		(BIT(6))
+#define M_RX_IRQ_EN		(BIT(7))
+#define M_GP_SYNC_IRQ_0_EN	(BIT(8))
+#define M_GP_IRQ_0_EN		(BIT(9))
+#define M_GP_IRQ_1_EN		(BIT(10))
+#define M_GP_IRQ_2_EN		(BIT(11))
+#define M_GP_IRQ_3_EN		(BIT(12))
+#define M_GP_IRQ_4_EN		(BIT(13))
+#define M_GP_IRQ_5_EN		(BIT(14))
+#define M_IO_DATA_DEASSERT_EN	(BIT(22))
+#define M_IO_DATA_ASSERT_EN	(BIT(23))
+#define M_RX_FIFO_RD_ERR_EN	(BIT(24))
+#define M_RX_FIFO_WR_ERR_EN	(BIT(25))
+#define M_RX_FIFO_WATERMARK_EN	(BIT(26))
+#define M_RX_FIFO_LAST_EN	(BIT(27))
+#define M_TX_FIFO_RD_ERR_EN	(BIT(28))
+#define M_TX_FIFO_WR_ERR_EN	(BIT(29))
+#define M_TX_FIFO_WATERMARK_EN	(BIT(30))
+#define M_SEC_IRQ_EN		(BIT(31))
+#define M_COMMON_GENI_M_IRQ_EN	(GENMASK(3, 0) |  M_TIMESTAMP_EN | \
+				GENMASK(14, 8) | M_IO_DATA_DEASSERT_EN | \
+				M_IO_DATA_ASSERT_EN | M_RX_FIFO_RD_ERR_EN | \
+				M_RX_FIFO_WR_ERR_EN | M_TX_FIFO_RD_ERR_EN | \
+				M_TX_FIFO_WR_ERR_EN | M_SEC_IRQ_EN)
+
+/* GENI_S_IRQ_EN fields */
+#define S_CMD_DONE_EN		(BIT(0))
+#define S_CMD_OVERRUN_EN	(BIT(1))
+#define S_ILLEGAL_CMD_EN	(BIT(2))
+#define S_CMD_FAILURE_EN	(BIT(3))
+#define S_CMD_CANCEL_EN		(BIT(4))
+#define S_CMD_ABORT_EN		(BIT(5))
+#define S_GP_SYNC_IRQ_0_EN	(BIT(8))
+#define S_GP_IRQ_0_EN		(BIT(9))
+#define S_GP_IRQ_1_EN		(BIT(10))
+#define S_GP_IRQ_2_EN		(BIT(11))
+#define S_GP_IRQ_3_EN		(BIT(12))
+#define S_GP_IRQ_4_EN		(BIT(13))
+#define S_GP_IRQ_5_EN		(BIT(14))
+#define S_IO_DATA_DEASSERT_EN	(BIT(22))
+#define S_IO_DATA_ASSERT_EN	(BIT(23))
+#define S_RX_FIFO_RD_ERR_EN	(BIT(24))
+#define S_RX_FIFO_WR_ERR_EN	(BIT(25))
+#define S_RX_FIFO_WATERMARK_EN	(BIT(26))
+#define S_RX_FIFO_LAST_EN	(BIT(27))
+#define S_COMMON_GENI_S_IRQ_EN	(GENMASK(3, 0) | GENMASK(14, 8) | \
+				 S_RX_FIFO_RD_ERR_EN | S_RX_FIFO_WR_ERR_EN)
+
+/*  GENI_/TX/RX/RX_RFR/_WATERMARK_REG fields */
+#define WATERMARK_MSK		(GENMASK(5, 0))
+
+/* GENI_TX_FIFO_STATUS fields */
+#define TX_FIFO_WC		(GENMASK(27, 0))
+
+/*  GENI_RX_FIFO_STATUS fields */
+#define RX_LAST			(BIT(31))
+#define RX_LAST_BYTE_VALID_MSK	(GENMASK(30, 28))
+#define RX_LAST_BYTE_VALID_SHFT	(28)
+#define RX_FIFO_WC_MSK		(GENMASK(24, 0))
+
+/* SE_IRQ_EN fields */
+#define DMA_RX_IRQ_EN		(BIT(0))
+#define DMA_TX_IRQ_EN		(BIT(1))
+#define GENI_M_IRQ_EN		(BIT(2))
+#define GENI_S_IRQ_EN		(BIT(3))
+
+/* SE_HW_PARAM_0 fields */
+#define TX_FIFO_WIDTH_MSK	(GENMASK(29, 24))
+#define TX_FIFO_WIDTH_SHFT	(24)
+#define TX_FIFO_DEPTH_MSK	(GENMASK(21, 16))
+#define TX_FIFO_DEPTH_SHFT	(16)
+
+/* SE_HW_PARAM_1 fields */
+#define RX_FIFO_WIDTH_MSK	(GENMASK(29, 24))
+#define RX_FIFO_WIDTH_SHFT	(24)
+#define RX_FIFO_DEPTH_MSK	(GENMASK(21, 16))
+#define RX_FIFO_DEPTH_SHFT	(16)
+
+/* SE_DMA_GENERAL_CFG */
+#define DMA_RX_CLK_CGC_ON	(BIT(0))
+#define DMA_TX_CLK_CGC_ON	(BIT(1))
+#define DMA_AHB_SLV_CFG_ON	(BIT(2))
+#define AHB_SEC_SLV_CLK_CGC_ON	(BIT(3))
+#define DUMMY_RX_NON_BUFFERABLE	(BIT(4))
+#define RX_DMA_ZERO_PADDING_EN	(BIT(5))
+#define RX_DMA_IRQ_DELAY_MSK	(GENMASK(8, 6))
+#define RX_DMA_IRQ_DELAY_SHFT	(6)
+
+static inline unsigned int geni_read_reg(void __iomem *base, int offset)
+{
+	return readl_relaxed(base + offset);
+}
+
+static inline void geni_write_reg(unsigned int value, void __iomem *base,
+				int offset)
+{
+	return writel_relaxed(value, (base + offset));
+}
+
+static inline int get_se_proto(void __iomem *base)
+{
+	int proto = 0;
+
+	proto = ((geni_read_reg(base, GENI_FW_REVISION_RO)
+			& FW_REV_PROTOCOL_MSK) >> FW_REV_PROTOCOL_SHFT);
+	return proto;
+}
+
+static inline int se_geni_irq_en(void __iomem *base, int mode)
+{
+	int ret = 0;
+	unsigned int common_geni_m_irq_en;
+	unsigned int common_geni_s_irq_en;
+	int proto = get_se_proto(base);
+
+	common_geni_m_irq_en = geni_read_reg(base, SE_GENI_M_IRQ_EN);
+	common_geni_s_irq_en = geni_read_reg(base, SE_GENI_S_IRQ_EN);
+	/* Common to all modes */
+	common_geni_m_irq_en |= M_COMMON_GENI_M_IRQ_EN;
+	common_geni_s_irq_en |= S_COMMON_GENI_S_IRQ_EN;
+
+	switch (mode) {
+	case FIFO_MODE:
+	{
+		if (proto == I2C) {
+			common_geni_m_irq_en |=
+				(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN);
+			common_geni_s_irq_en |= S_CMD_DONE_EN;
+		}
+		break;
+	}
+	case GSI_DMA:
+		break;
+	default:
+		pr_err("%s: Invalid mode %d\n", __func__, mode);
+		ret = -ENXIO;
+		goto exit_irq_en;
+	}
+
+
+	geni_write_reg(common_geni_m_irq_en, base, SE_GENI_M_IRQ_EN);
+	geni_write_reg(common_geni_s_irq_en, base, SE_GENI_S_IRQ_EN);
+exit_irq_en:
+	return ret;
+}
+
+
+static inline void se_set_rx_rfr_wm(void __iomem *base, unsigned int rx_wm,
+						unsigned int rx_rfr)
+{
+	geni_write_reg(rx_wm, base, SE_GENI_RX_WATERMARK_REG);
+	geni_write_reg(rx_rfr, base, SE_GENI_RX_RFR_WATERMARK_REG);
+}
+
+static inline int se_io_set_mode(void __iomem *base, int mode)
+{
+	int ret = 0;
+	unsigned int io_mode = 0;
+	unsigned int geni_dma_mode = 0;
+
+	io_mode = geni_read_reg(base, SE_IRQ_EN);
+	geni_dma_mode = geni_read_reg(base, SE_GENI_DMA_MODE_EN);
+
+	switch (mode) {
+	case FIFO_MODE:
+	{
+		io_mode |= (GENI_M_IRQ_EN | GENI_S_IRQ_EN);
+		io_mode |= (DMA_TX_IRQ_EN | DMA_RX_IRQ_EN);
+		geni_dma_mode &= ~GENI_DMA_MODE_EN;
+		break;
+
+	}
+	default:
+		ret = -ENXIO;
+		goto exit_set_mode;
+	}
+	geni_write_reg(io_mode, base, SE_IRQ_EN);
+	geni_write_reg(geni_dma_mode, base, SE_GENI_DMA_MODE_EN);
+exit_set_mode:
+	return ret;
+}
+
+static inline void se_io_init(void __iomem *base)
+{
+	unsigned int io_op_ctrl = 0;
+	unsigned int geni_cgc_ctrl;
+	unsigned int dma_general_cfg;
+
+	geni_cgc_ctrl = geni_read_reg(base, GENI_CGC_CTRL);
+	dma_general_cfg = geni_read_reg(base, SE_DMA_GENERAL_CFG);
+	geni_cgc_ctrl |= DEFAULT_CGC_EN;
+	dma_general_cfg |= (AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CFG_ON |
+			DMA_TX_CLK_CGC_ON | DMA_RX_CLK_CGC_ON);
+	io_op_ctrl |= DEFAULT_IO_OUTPUT_CTRL_MSK;
+	geni_write_reg(geni_cgc_ctrl, base, GENI_CGC_CTRL);
+	geni_write_reg(dma_general_cfg, base, SE_DMA_GENERAL_CFG);
+
+	geni_write_reg(io_op_ctrl, base, GENI_OUTPUT_CTRL);
+	geni_write_reg(FORCE_DEFAULT, base, GENI_FORCE_DEFAULT_REG);
+}
+
+static inline int geni_se_init(void __iomem *base, int mode,
+		unsigned int rx_wm, unsigned int rx_rfr)
+{
+	int ret = 0;
+
+	se_io_init(base);
+	ret = se_io_set_mode(base, mode);
+	if (ret)
+		goto exit_geni_se_init;
+
+	se_set_rx_rfr_wm(base, rx_wm, rx_rfr);
+	ret = se_geni_irq_en(base, mode);
+	if (ret)
+		goto exit_geni_se_init;
+
+exit_geni_se_init:
+	return ret;
+}
+
+static inline void geni_setup_m_cmd(void __iomem *base, u32 cmd,
+								u32 params)
+{
+	u32 m_cmd = geni_read_reg(base, SE_GENI_M_CMD0);
+
+	m_cmd &= ~(M_OPCODE_MSK | M_PARAMS_MSK);
+	m_cmd |= (cmd << M_OPCODE_SHFT);
+	m_cmd |= (params & M_PARAMS_MSK);
+	geni_write_reg(m_cmd, base, SE_GENI_M_CMD0);
+}
+
+static inline void geni_setup_s_cmd(void __iomem *base, u32 cmd,
+								u32 params)
+{
+	u32 s_cmd = geni_read_reg(base, SE_GENI_S_CMD0);
+
+	s_cmd &= ~(S_OPCODE_MSK | S_PARAMS_MSK);
+	s_cmd |= (cmd << S_OPCODE_SHFT);
+	s_cmd |= (params & S_PARAMS_MSK);
+	geni_write_reg(s_cmd, base, SE_GENI_S_CMD0);
+}
+
+static inline void geni_cancel_m_cmd(void __iomem *base)
+{
+	geni_write_reg(M_GENI_CMD_CANCEL, base, SE_GENI_S_CMD_CTRL_REG);
+}
+
+static inline void geni_cancel_s_cmd(void __iomem *base)
+{
+	geni_write_reg(S_GENI_CMD_CANCEL, base, SE_GENI_S_CMD_CTRL_REG);
+}
+
+static inline void geni_abort_m_cmd(void __iomem *base)
+{
+	geni_write_reg(M_GENI_CMD_ABORT, base, SE_GENI_M_CMD_CTRL_REG);
+}
+
+static inline void qcom_geni_abort_s_cmd(void __iomem *base)
+{
+	geni_write_reg(S_GENI_CMD_ABORT, base, SE_GENI_S_CMD_CTRL_REG);
+}
+
+static inline int get_tx_fifo_depth(void __iomem *base)
+{
+	int tx_fifo_depth;
+
+	tx_fifo_depth = ((geni_read_reg(base, SE_HW_PARAM_0)
+			& TX_FIFO_DEPTH_MSK) >> TX_FIFO_DEPTH_SHFT);
+	return tx_fifo_depth;
+}
+
+static inline int get_tx_fifo_width(void __iomem *base)
+{
+	int tx_fifo_width;
+
+	tx_fifo_width = ((geni_read_reg(base, SE_HW_PARAM_0)
+			& TX_FIFO_WIDTH_MSK) >> TX_FIFO_WIDTH_SHFT);
+	return tx_fifo_width;
+}
+
+static inline int get_rx_fifo_depth(void __iomem *base)
+{
+	int rx_fifo_depth;
+
+	rx_fifo_depth = ((geni_read_reg(base, SE_HW_PARAM_1)
+			& RX_FIFO_DEPTH_MSK) >> RX_FIFO_DEPTH_SHFT);
+	return rx_fifo_depth;
+}
+
+static inline void se_config_packing(void __iomem *base, int bpw,
+				int pack_words, bool msb_to_lsb)
+{
+	u32 cfg[4] = {0};
+	unsigned long cfg0, cfg1;
+	int len = ((bpw < 8) ? (bpw - 1) : 7);
+	int idx = ((msb_to_lsb == 1) ? len : 0);
+	int iter = (bpw * pack_words) >> 3;
+	int i;
+
+	for (i = 0; i < iter; i++) {
+		cfg[i] = ((idx << 5) | (msb_to_lsb << 4) | (len << 1));
+		idx += (len + 1);
+		if (i == iter - 1)
+			cfg[i] |= 1;
+	}
+	cfg0 = cfg[0] | (cfg[1] << 10);
+	cfg1 = cfg[2] | (cfg[3] << 10);
+	geni_write_reg(cfg0, base, SE_GENI_TX_PACKING_CFG0);
+	geni_write_reg(cfg1, base, SE_GENI_TX_PACKING_CFG1);
+	geni_write_reg(cfg0, base, SE_GENI_RX_PACKING_CFG0);
+	geni_write_reg(cfg1, base, SE_GENI_RX_PACKING_CFG1);
+}
+#endif
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 356793e..3e354fd 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -244,6 +244,8 @@ extern void add_timer(struct timer_list *timer);
 
 extern int try_to_del_timer_sync(struct timer_list *timer);
 
+extern struct timer_base timer_base_deferrable;
+
 #ifdef CONFIG_SMP
   extern int del_timer_sync(struct timer_list *timer);
 #else
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 7e4fad7..8a6970e 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -108,7 +108,7 @@ static int finished_booting;
 
 #ifdef CONFIG_CLOCKSOURCE_WATCHDOG
 static void clocksource_watchdog_work(struct work_struct *work);
-static void clocksource_select(void);
+static void clocksource_select(bool force);
 
 static LIST_HEAD(watchdog_list);
 static struct clocksource *watchdog;
@@ -415,7 +415,7 @@ static int clocksource_watchdog_kthread(void *data)
 {
 	mutex_lock(&clocksource_mutex);
 	if (__clocksource_watchdog_kthread())
-		clocksource_select();
+		clocksource_select(false);
 	mutex_unlock(&clocksource_mutex);
 	return 0;
 }
@@ -555,11 +555,12 @@ static inline void clocksource_update_max_deferment(struct clocksource *cs)
 
 #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
 
-static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur)
+static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur,
+						bool force)
 {
 	struct clocksource *cs;
 
-	if (!finished_booting || list_empty(&clocksource_list))
+	if ((!finished_booting && !force) || list_empty(&clocksource_list))
 		return NULL;
 
 	/*
@@ -577,13 +578,13 @@ static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur)
 	return NULL;
 }
 
-static void __clocksource_select(bool skipcur)
+static void __clocksource_select(bool skipcur, bool force)
 {
 	bool oneshot = tick_oneshot_mode_active();
 	struct clocksource *best, *cs;
 
 	/* Find the best suitable clocksource */
-	best = clocksource_find_best(oneshot, skipcur);
+	best = clocksource_find_best(oneshot, skipcur, force);
 	if (!best)
 		return;
 
@@ -632,22 +633,40 @@ static void __clocksource_select(bool skipcur)
  * Select the clocksource with the best rating, or the clocksource,
  * which is selected by userspace override.
  */
-static void clocksource_select(void)
+static void clocksource_select(bool force)
 {
-	__clocksource_select(false);
+	return __clocksource_select(false, force);
 }
 
 static void clocksource_select_fallback(void)
 {
-	__clocksource_select(true);
+	__clocksource_select(true, false);
 }
 
 #else /* !CONFIG_ARCH_USES_GETTIMEOFFSET */
-static inline void clocksource_select(void) { }
+
+static inline void clocksource_select(bool force) { }
 static inline void clocksource_select_fallback(void) { }
 
 #endif
 
+/**
+ * clocksource_select_force - Force re-selection of the best clocksource
+ *				among registered clocksources
+ *
+ * clocksource_select() can't select the best clocksource before
+ * calling clocksource_done_booting() and since clocksource_select()
+ * should be called with clocksource_mutex held, provide a new API
+ * can be called from other files to select best clockrouce irrespective
+ * of finished_booting flag.
+ */
+void clocksource_select_force(void)
+{
+	mutex_lock(&clocksource_mutex);
+	clocksource_select(true);
+	mutex_unlock(&clocksource_mutex);
+}
+
 /*
  * clocksource_done_booting - Called near the end of core bootup
  *
@@ -664,7 +683,7 @@ static int __init clocksource_done_booting(void)
 	 * Run the watchdog first to eliminate unstable clock sources
 	 */
 	__clocksource_watchdog_kthread();
-	clocksource_select();
+	clocksource_select(false);
 	mutex_unlock(&clocksource_mutex);
 	return 0;
 }
@@ -755,6 +774,7 @@ void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq
 }
 EXPORT_SYMBOL_GPL(__clocksource_update_freq_scale);
 
+
 /**
  * __clocksource_register_scale - Used to install new clocksources
  * @cs:		clocksource to be registered
@@ -776,7 +796,7 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
 	mutex_lock(&clocksource_mutex);
 	clocksource_enqueue(cs);
 	clocksource_enqueue_watchdog(cs);
-	clocksource_select();
+	clocksource_select(false);
 	clocksource_select_watchdog(false);
 	mutex_unlock(&clocksource_mutex);
 	return 0;
@@ -799,7 +819,7 @@ void clocksource_change_rating(struct clocksource *cs, int rating)
 {
 	mutex_lock(&clocksource_mutex);
 	__clocksource_change_rating(cs, rating);
-	clocksource_select();
+	clocksource_select(false);
 	clocksource_select_watchdog(false);
 	mutex_unlock(&clocksource_mutex);
 }
@@ -903,7 +923,7 @@ static ssize_t sysfs_override_clocksource(struct device *dev,
 
 	ret = sysfs_get_uname(buf, override_name, count);
 	if (ret >= 0)
-		clocksource_select();
+		clocksource_select(false);
 
 	mutex_unlock(&clocksource_mutex);
 
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index f605186..400920e 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -206,6 +206,7 @@ struct timer_base {
 } ____cacheline_aligned;
 
 static DEFINE_PER_CPU(struct timer_base, timer_bases[NR_BASES]);
+struct timer_base timer_base_deferrable;
 
 #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
 unsigned int sysctl_timer_migration = 1;
@@ -229,6 +230,9 @@ void timers_update_migration(bool update_nohz)
 		per_cpu(timer_bases[BASE_DEF].nohz_active, cpu) = true;
 		per_cpu(hrtimer_bases.nohz_active, cpu) = true;
 	}
+
+	timer_base_deferrable.migration_enabled = on;
+	timer_base_deferrable.nohz_active = true;
 }
 
 int timer_migration_handler(struct ctl_table *table, int write,
@@ -852,8 +856,11 @@ static inline struct timer_base *get_timer_cpu_base(u32 tflags, u32 cpu)
 	 * the deferrable base.
 	 */
 	if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && base->nohz_active &&
-	    (tflags & TIMER_DEFERRABLE))
-		base = per_cpu_ptr(&timer_bases[BASE_DEF], cpu);
+	    (tflags & TIMER_DEFERRABLE)) {
+		base = &timer_base_deferrable;
+		if (tflags & TIMER_PINNED)
+			base = per_cpu_ptr(&timer_bases[BASE_DEF], cpu);
+	}
 	return base;
 }
 
@@ -867,7 +874,9 @@ static inline struct timer_base *get_timer_this_cpu_base(u32 tflags)
 	 */
 	if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && base->nohz_active &&
 	    (tflags & TIMER_DEFERRABLE))
-		base = this_cpu_ptr(&timer_bases[BASE_DEF]);
+		base = &timer_base_deferrable;
+		if (tflags & TIMER_PINNED)
+			base = this_cpu_ptr(&timer_bases[BASE_DEF]);
 	return base;
 }
 
@@ -1652,8 +1661,10 @@ static __latent_entropy void run_timer_softirq(struct softirq_action *h)
 	struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
 
 	__run_timers(base);
-	if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && base->nohz_active)
+	if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && base->nohz_active) {
+		__run_timers(&timer_base_deferrable);
 		__run_timers(this_cpu_ptr(&timer_bases[BASE_DEF]));
+	}
 }
 
 /*
diff --git a/mm/memblock.c b/mm/memblock.c
index 166f17a..49b7c1e 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1641,11 +1641,12 @@ int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size
 		 memblock.memory.regions[idx].size) >= end;
 }
 
-int __init_memblock memblock_overlaps_memory(phys_addr_t base, phys_addr_t size)
+bool __init_memblock memblock_overlaps_memory(phys_addr_t base,
+					      phys_addr_t size)
 {
 	memblock_cap_size(base, &size);
 
-	return memblock_overlaps_region(&memblock.memory, base, size) >= 0;
+	return memblock_overlaps_region(&memblock.memory, base, size);
 }
 
 /**