Merge "msm: usb_bam : Add support for CI2.0 HSUSB BAM" into msm-3.4
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 8a4b833..ed84219 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -57,11 +57,17 @@
 
 Required properties:
 - compatible: should be "qcom,usb-bam-msm"
-- regs: offset and length of the register set in the memory map
-- interrupts: IRQ line
+- reg  : pairs of physical base addresses and region sizes
+            of all the memory mapped BAM devices present
+- reg-names : Register region name(s) referenced in reg above
+            SSUSB BAM expects "ssusb" and "hsusb" for HSSUB BAM
+- interrupts: IRQ lines for BAM devices
+- interrupt-names: BAM interrupt name(s) referenced in interrupts above
+            SSUSB BAM expects "ssusb" and "hsusb" for HSSUB BAM
 - qcom,usb-active-bam: active BAM type. Can be one of
-            0 - HSUSB_BAM
-            1 - HSIC_BAM
+            0 - SSUSB_BAM
+            1 - HSUSB_BAM
+            2 - HSIC_BAM
 - qcom,usb-total-bam-num: total number of BAMs that are supported
 - qcom,usb-bam-num-pipes: max number of pipes that can be used
 - qcom,usb-base-address: physical base address of the BAM
@@ -69,10 +75,15 @@
 A number of USB BAM pipe parameters are represented as sub-nodes:
 
 Subnode Required:
-- label: a string describing the pipe's direction and use
+- label: a string describing the pipe's direction and BAM instance under use
 - qcom,usb-bam-type: BAM type. Can be one of
-            0 - HSUSB_BAM
-            1 - HSIC_BAM
+            0 - SSUSB_BAM
+            1 - HSUSB_BAM
+            2 - HSIC_BAM
+- qcom,usb-bam-mem-type: Type of memory used by this PIPE. Can be one of
+            0 - Uses SPS's dedicated pipe memory
+            1 - USB's private memory residing @ 'qcom,usb-base-address'
+            2 - System RAM allocated by driver
 - qcom,src-bam-physical-address: source BAM physical address
 - qcom,src-bam-pipe-index: source BAM pipe index
 - qcom,dst-bam-physical-address: destination BAM physical address
@@ -86,16 +97,20 @@
 
 	qcom,usbbam@f9304000 {
 		compatible = "qcom,usb-bam-msm";
-		reg = <0xf9304000 0x9000>;
-		interrupts = <0 132 0>;
+		reg = <0xf9304000 0x5000>,
+		      <0xf9a44000 0x11000>;
+		reg-names = "ssusb", "hsusb";
+		interrupts = <0 132 0 0 135 0>;
+		interrupt-names = "ssusb", "hsusb";
 		qcom,usb-active-bam = <0>;
-		qcom,usb-total-bam-num = <1>;
+		qcom,usb-total-bam-num = <2>;
 		qcom,usb-bam-num-pipes = <16>;
 		qcom,usb-base-address = <0xf9200000>;
 
 		qcom,pipe1 {
 			label = "usb-to-peri-qdss-dwc3";
 			qcom,usb-bam-type = <0>;
+			qcom,usb-bam-mem-type = <1>;
 			qcom,src-bam-physical-address = <0>;
 			qcom,src-bam-pipe-index = <0>;
 			qcom,dst-bam-physical-address = <0>;
@@ -109,6 +124,7 @@
 		qcom,pipe2 {
 			label = "peri-to-usb-qdss-dwc3";
 			qcom,usb-bam-type = <0>;
+			qcom,usb-bam-mem-type = <1>;
 			qcom,src-bam-physical-address = <0xfc37C000>;
 			qcom,src-bam-pipe-index = <0>;
 			qcom,dst-bam-physical-address = <0xf9304000>;
@@ -118,4 +134,32 @@
 			qcom,descriptor-fifo-offset = <0xf4000>;
 			qcom,descriptor-fifo-size = <0x1400>;
 		};
+
+		qcom,pipe3 {
+			label = "usb-to-peri-qdss-hsusb";
+			qcom,usb-bam-type = <1>;
+			qcom,usb-bam-mem-type = <2>;
+			qcom,src-bam-physical-address = <0>;
+			qcom,src-bam-pipe-index = <0>;
+			qcom,dst-bam-physical-address = <0>;
+			qcom,dst-bam-pipe-index = <0>;
+			qcom,data-fifo-offset = <0>;
+			qcom,data-fifo-size = <0>;
+			qcom,descriptor-fifo-offset = <0>;
+			qcom,descriptor-fifo-size = <0>;
+		};
+
+		qcom,pipe4 {
+			label = "peri-to-usb-qdss-hsusb";
+			qcom,usb-bam-type = <1>;
+			qcom,usb-bam-mem-type = <2>;
+			qcom,src-bam-physical-address = <0xfc37c000>;
+			qcom,src-bam-pipe-index = <0>;
+			qcom,dst-bam-physical-address = <0xf9a44000>;
+			qcom,dst-bam-pipe-index = <2>;
+			qcom,data-fifo-offset = <0>;
+			qcom,data-fifo-size = <0x4000>;
+			qcom,descriptor-fifo-offset = <0>;
+			qcom,descriptor-fifo-size = <0x1400>;
+		};
 	};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 166a17d..5620648 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -726,16 +726,20 @@
 
 	qcom,usbbam@f9304000 {
 		compatible = "qcom,usb-bam-msm";
-		reg = <0xf9304000 0x9000>;
-		interrupts = <0 132 0>;
+		reg = <0xf9304000 0x5000>,
+		      <0xf9a44000 0x11000>;
+		reg-names = "ssusb", "hsusb";
+		interrupts = <0 132 0 0 135 0>;
+		interrupt-names = "ssusb", "hsusb";
 		qcom,usb-active-bam = <0>;
-		qcom,usb-total-bam-num = <1>;
+		qcom,usb-total-bam-num = <2>;
 		qcom,usb-bam-num-pipes = <16>;
 		qcom,usb-base-address = <0xf9200000>;
 
 		qcom,pipe1 {
 			label = "usb-to-peri-qdss-dwc3";
 			qcom,usb-bam-type = <0>;
+			qcom,usb-bam-mem-type = <1>;
 			qcom,src-bam-physical-address = <0>;
 			qcom,src-bam-pipe-index = <0>;
 			qcom,dst-bam-physical-address = <0>;
@@ -749,6 +753,7 @@
 		qcom,pipe2 {
 			label = "peri-to-usb-qdss-dwc3";
 			qcom,usb-bam-type = <0>;
+			qcom,usb-bam-mem-type = <1>;
 			qcom,src-bam-physical-address = <0xfc37C000>;
 			qcom,src-bam-pipe-index = <0>;
 			qcom,dst-bam-physical-address = <0xf9304000>;
@@ -758,6 +763,34 @@
 			qcom,descriptor-fifo-offset = <0xf4000>;
 			qcom,descriptor-fifo-size = <0x1400>;
 		};
+
+		qcom,pipe3 {
+			label = "usb-to-peri-qdss-hsusb";
+			qcom,usb-bam-type = <1>;
+			qcom,usb-bam-mem-type = <2>;
+			qcom,src-bam-physical-address = <0>;
+			qcom,src-bam-pipe-index = <0>;
+			qcom,dst-bam-physical-address = <0>;
+			qcom,dst-bam-pipe-index = <0>;
+			qcom,data-fifo-offset = <0>;
+			qcom,data-fifo-size = <0>;
+			qcom,descriptor-fifo-offset = <0>;
+			qcom,descriptor-fifo-size = <0>;
+		};
+
+		qcom,pipe4 {
+			label = "peri-to-usb-qdss-hsusb";
+			qcom,usb-bam-type = <1>;
+			qcom,usb-bam-mem-type = <2>;
+			qcom,src-bam-physical-address = <0xfc37c000>;
+			qcom,src-bam-pipe-index = <0>;
+			qcom,dst-bam-physical-address = <0xf9a44000>;
+			qcom,dst-bam-pipe-index = <2>;
+			qcom,data-fifo-offset = <0>;
+			qcom,data-fifo-size = <0x4000>;
+			qcom,descriptor-fifo-offset = <0>;
+			qcom,descriptor-fifo-size = <0x1400>;
+		};
 	};
 
 	qcom,msm-thermal {
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index f885774..e599739 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -620,8 +620,8 @@
 #define USB_BAM_PHY_BASE	0x12502000
 #define HSIC_BAM_PHY_BASE	0x12542000
 #define A2_BAM_PHY_BASE		0x124C2000
-static struct usb_bam_pipe_connect msm_usb_bam_connections[2][4][2] = {
-	[0][0][USB_TO_PEER_PERIPHERAL] = {
+static struct usb_bam_pipe_connect msm_usb_bam_connections[MAX_BAMS][4][2] = {
+	[HSUSB_BAM][0][USB_TO_PEER_PERIPHERAL] = {
 		.src_phy_addr = USB_BAM_PHY_BASE,
 		.src_pipe_index = 11,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -631,7 +631,7 @@
 		.desc_fifo_base_offset = 0x1700,
 		.desc_fifo_size = 0x300,
 	},
-	[0][0][PEER_PERIPHERAL_TO_USB] = {
+	[HSUSB_BAM][0][PEER_PERIPHERAL_TO_USB] = {
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 1,
 		.dst_phy_addr = USB_BAM_PHY_BASE,
@@ -641,7 +641,7 @@
 		.desc_fifo_base_offset = 0x1000,
 		.desc_fifo_size = 0x100,
 	},
-	[0][1][USB_TO_PEER_PERIPHERAL] = {
+	[HSUSB_BAM][1][USB_TO_PEER_PERIPHERAL] = {
 		.src_phy_addr = USB_BAM_PHY_BASE,
 		.src_pipe_index = 13,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -651,7 +651,7 @@
 		.desc_fifo_base_offset = 0x2700,
 		.desc_fifo_size = 0x300,
 	},
-	[0][1][PEER_PERIPHERAL_TO_USB] = {
+	[HSUSB_BAM][1][PEER_PERIPHERAL_TO_USB] = {
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 3,
 		.dst_phy_addr = USB_BAM_PHY_BASE,
@@ -661,7 +661,7 @@
 		.desc_fifo_base_offset = 0x2000,
 		.desc_fifo_size = 0x100,
 	},
-	[0][2][USB_TO_PEER_PERIPHERAL] = {
+	[HSUSB_BAM][2][USB_TO_PEER_PERIPHERAL] = {
 		.src_phy_addr = USB_BAM_PHY_BASE,
 		.src_pipe_index = 15,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -671,7 +671,7 @@
 		.desc_fifo_base_offset = 0x3700,
 		.desc_fifo_size = 0x300,
 	},
-	[0][2][PEER_PERIPHERAL_TO_USB] = {
+	[HSUSB_BAM][2][PEER_PERIPHERAL_TO_USB] = {
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 5,
 		.dst_phy_addr = USB_BAM_PHY_BASE,
@@ -681,7 +681,7 @@
 		.desc_fifo_base_offset = 0x3000,
 		.desc_fifo_size = 0x100,
 	},
-	[1][0][USB_TO_PEER_PERIPHERAL] = {
+	[HSIC_BAM][0][USB_TO_PEER_PERIPHERAL] = {
 		.src_phy_addr = HSIC_BAM_PHY_BASE,
 		.src_pipe_index = 1,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -691,7 +691,7 @@
 		.desc_fifo_base_offset = 0x1700,
 		.desc_fifo_size = 0x300,
 	},
-	[1][0][PEER_PERIPHERAL_TO_USB] = {
+	[HSIC_BAM][0][PEER_PERIPHERAL_TO_USB] = {
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 1,
 		.dst_phy_addr = HSIC_BAM_PHY_BASE,
@@ -701,7 +701,7 @@
 		.desc_fifo_base_offset = 0x1000,
 		.desc_fifo_size = 0x100,
 	},
-	[1][1][USB_TO_PEER_PERIPHERAL] = {
+	[HSIC_BAM][1][USB_TO_PEER_PERIPHERAL] = {
 		.src_phy_addr = HSIC_BAM_PHY_BASE,
 		.src_pipe_index = 3,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -711,7 +711,7 @@
 		.desc_fifo_base_offset = 0x2700,
 		.desc_fifo_size = 0x300,
 	},
-	[1][1][PEER_PERIPHERAL_TO_USB] = {
+	[HSIC_BAM][1][PEER_PERIPHERAL_TO_USB] = {
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 3,
 		.dst_phy_addr = HSIC_BAM_PHY_BASE,
@@ -721,7 +721,7 @@
 		.desc_fifo_base_offset = 0x2000,
 		.desc_fifo_size = 0x100,
 	},
-	[1][2][USB_TO_PEER_PERIPHERAL] = {
+	[HSIC_BAM][2][USB_TO_PEER_PERIPHERAL] = {
 		.src_phy_addr = HSIC_BAM_PHY_BASE,
 		.src_pipe_index = 5,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -731,7 +731,7 @@
 		.desc_fifo_base_offset = 0x3700,
 		.desc_fifo_size = 0x300,
 	},
-	[1][2][PEER_PERIPHERAL_TO_USB] = {
+	[HSIC_BAM][2][PEER_PERIPHERAL_TO_USB] = {
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 5,
 		.dst_phy_addr = HSIC_BAM_PHY_BASE,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index c307714..0a9bbf6 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -174,25 +174,25 @@
 
 static struct resource resources_usb_bam[] = {
 	{
-		.name	= "usb_bam_addr",
+		.name	= "hsusb",
 		.start	= MSM_USB_BAM_BASE,
 		.end	= MSM_USB_BAM_BASE + MSM_USB_BAM_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.name	= "usb_bam_irq",
+		.name	= "hsusb",
 		.start	= USB1_HS_BAM_IRQ,
 		.end	= USB1_HS_BAM_IRQ,
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
-		.name	= "hsic_bam_addr",
+		.name	= "hsic",
 		.start	= MSM_HSIC_BAM_BASE,
 		.end	= MSM_HSIC_BAM_BASE + MSM_HSIC_BAM_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.name	= "hsic_bam_irq",
+		.name	= "hsic",
 		.start	= USB_HSIC_BAM_IRQ,
 		.end	= USB_HSIC_BAM_IRQ,
 		.flags	= IORESOURCE_IRQ,
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index b7c73de..f6b50a0 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -23,6 +23,7 @@
 #include <mach/usb_bam.h>
 #include <mach/sps.h>
 #include <linux/workqueue.h>
+#include <linux/dma-mapping.h>
 
 #define USB_SUMMING_THRESHOLD 512
 #define CONNECTIONS_NUM	4
@@ -54,13 +55,6 @@
 static struct usb_bam_pipe_connect ***msm_usb_bam_connections_info;
 static struct usb_bam_pipe_connect *bam_connection_arr;
 
-static bool device_tree_enabled;
-
-static inline int bam_offset(struct msm_usb_bam_platform_data *pdata)
-{
-	return pdata->usb_active_bam * CONNECTIONS_NUM * 2;
-}
-
 static int connect_pipe(u8 conn_idx, enum usb_bam_pipe_dir pipe_dir,
 						u32 *usb_pipe_idx)
 {
@@ -71,8 +65,8 @@
 	struct msm_usb_bam_platform_data *pdata =
 		usb_bam_pdev->dev.platform_data;
 	struct usb_bam_pipe_connect *pipe_connection =
-		(struct usb_bam_pipe_connect *)(pdata->connections +
-			 bam_offset(pdata) + (2*conn_idx+pipe_dir));
+				&msm_usb_bam_connections_info
+				[pdata->usb_active_bam][conn_idx][pipe_dir];
 
 	*pipe = sps_alloc_endpoint();
 	if (*pipe == NULL) {
@@ -109,7 +103,9 @@
 		*usb_pipe_idx = connection->dest_pipe_index;
 	}
 
-	if (!device_tree_enabled) {
+	/* If BAM is using dedicated SPS pipe memory, get it */
+	if (pipe_connection->mem_type == SPS_PIPE_MEM) {
+		pr_debug("%s: USB BAM using SPS pipe memory\n", __func__);
 		ret = sps_setup_bam2bam_fifo(
 				&data_mem_buf[conn_idx][pipe_dir],
 				pipe_connection->data_fifo_base_offset,
@@ -129,7 +125,9 @@
 				ret);
 			goto fifo_setup_error;
 		}
-	} else {
+	} else if (pipe_connection->mem_type == USB_PRIVATE_MEM) {
+		pr_debug("%s: USB BAM using private memory\n", __func__);
+		/* BAM is using dedicated USB private memory, map it */
 		data_mem_buf[conn_idx][pipe_dir].phys_base =
 			pipe_connection->data_fifo_base_offset +
 				pdata->usb_base_address;
@@ -151,6 +149,28 @@
 				desc_mem_buf[conn_idx][pipe_dir].size);
 		memset(desc_mem_buf[conn_idx][pipe_dir].base, 0,
 			desc_mem_buf[conn_idx][pipe_dir].size);
+	} else {
+		pr_debug("%s: USB BAM using system memory\n", __func__);
+		/* BAM would use system memory, allocate FIFOs */
+		data_mem_buf[conn_idx][pipe_dir].size =
+					pipe_connection->data_fifo_size;
+		data_mem_buf[conn_idx][pipe_dir].base =
+			dma_alloc_coherent(&usb_bam_pdev->dev,
+				    pipe_connection->data_fifo_size,
+				    &data_mem_buf[conn_idx][pipe_dir].phys_base,
+				    0);
+		memset(data_mem_buf[conn_idx][pipe_dir].base, 0,
+					pipe_connection->data_fifo_size);
+
+		desc_mem_buf[conn_idx][pipe_dir].size =
+					pipe_connection->desc_fifo_size;
+		desc_mem_buf[conn_idx][pipe_dir].base =
+			dma_alloc_coherent(&usb_bam_pdev->dev,
+				    pipe_connection->desc_fifo_size,
+				    &desc_mem_buf[conn_idx][pipe_dir].phys_base,
+				    0);
+		memset(desc_mem_buf[conn_idx][pipe_dir].base, 0,
+					pipe_connection->desc_fifo_size);
 	}
 
 	connection->data = data_mem_buf[conn_idx][pipe_dir];
@@ -177,6 +197,11 @@
 static int disconnect_pipe(u8 connection_idx, enum usb_bam_pipe_dir pipe_dir,
 						u32 *usb_pipe_idx)
 {
+	struct msm_usb_bam_platform_data *pdata =
+				usb_bam_pdev->dev.platform_data;
+	struct usb_bam_pipe_connect *pipe_connection =
+			&msm_usb_bam_connections_info
+			[pdata->usb_active_bam][connection_idx][pipe_dir];
 	struct sps_pipe *pipe = sps_pipes[connection_idx][pipe_dir];
 	struct sps_connect *connection =
 		&sps_connections[connection_idx][pipe_dir];
@@ -184,6 +209,14 @@
 	sps_disconnect(pipe);
 	sps_free_endpoint(pipe);
 
+	if (pipe_connection->mem_type == SYSTEM_MEM) {
+		pr_debug("%s: Freeing system memory used by PIPE\n", __func__);
+		dma_free_coherent(&usb_bam_pdev->dev, connection->data.size,
+			  connection->data.base, connection->data.phys_base);
+		dma_free_coherent(&usb_bam_pdev->dev, connection->desc.size,
+			  connection->desc.base, connection->desc.phys_base);
+	}
+
 	connection->options &= ~SPS_O_AUTO_ENABLE;
 	return 0;
 }
@@ -328,7 +361,7 @@
 }
 
 static int update_connections_info(struct device_node *node, int bam,
-	int conn_num, int dir)
+	int conn_num, int dir, enum usb_pipe_mem_type mem_type)
 {
 	u32 rc;
 	char *key = NULL;
@@ -338,6 +371,8 @@
 
 	pipe_connection = &msm_usb_bam_connections_info[bam][conn_num][dir];
 
+	pipe_connection->mem_type = mem_type;
+
 	key = "qcom,src-bam-physical-address";
 	rc = of_property_read_u32(node, key, &val);
 	if (rc)
@@ -394,18 +429,49 @@
 	return -EFAULT;
 }
 
+static int usb_bam_update_conn_array_index(struct platform_device *pdev,
+		void *buff, int bam_max, int conn_max, int pipe_dirs)
+{
+	int bam_num, conn_num;
+	struct usb_bam_pipe_connect *bam_connection_arr = buff;
+
+	msm_usb_bam_connections_info = devm_kzalloc(&pdev->dev,
+		bam_max * sizeof(struct usb_bam_pipe_connect **),
+		GFP_KERNEL);
+
+	if (!msm_usb_bam_connections_info)
+		return -ENOMEM;
+
+	for (bam_num = 0; bam_num < bam_max; bam_num++) {
+		msm_usb_bam_connections_info[bam_num] =
+			devm_kzalloc(&pdev->dev, conn_max *
+			sizeof(struct usb_bam_pipe_connect *),
+			GFP_KERNEL);
+		if (!msm_usb_bam_connections_info[bam_num])
+			return -ENOMEM;
+
+		for (conn_num = 0; conn_num < conn_max; conn_num++)
+			msm_usb_bam_connections_info[bam_num][conn_num] =
+				bam_connection_arr +
+				(bam_num * conn_max * pipe_dirs) +
+				(conn_num * pipe_dirs);
+	}
+
+	return 0;
+}
+
 static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
 	struct platform_device *pdev)
 {
 	struct msm_usb_bam_platform_data *pdata;
 	struct device_node *node = pdev->dev.of_node;
-	u32 i, j;
 	int conn_num, bam;
 	u8 dir;
 	u8 ncolumns = 2;
 	int bam_amount, rc = 0;
 	u32 pipe_entry = 0;
 	char *key = NULL;
+	enum usb_pipe_mem_type mem_type;
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
@@ -451,79 +517,79 @@
 	conn_num = pipe_entry / 2;
 	bam_amount = pdata->total_bam_num;
 
-	if (conn_num > 0 && conn_num < pdata->usb_bam_num_pipes) {
-		/* alloc msm_usb_bam_connections_info */
-		bam_connection_arr = devm_kzalloc(&pdev->dev, bam_amount *
-			conn_num * ncolumns *
-			sizeof(struct usb_bam_pipe_connect), GFP_KERNEL);
-
-		if (!bam_connection_arr)
-			goto err;
-
-		msm_usb_bam_connections_info = devm_kzalloc(&pdev->dev,
-			bam_amount * sizeof(struct usb_bam_pipe_connect **),
-			GFP_KERNEL);
-
-		if (!msm_usb_bam_connections_info)
-			goto err;
-
-		for (j = 0; j < bam_amount; j++) {
-			msm_usb_bam_connections_info[j] =
-				devm_kzalloc(&pdev->dev, conn_num *
-				sizeof(struct usb_bam_pipe_connect *),
-				GFP_KERNEL);
-			for (i = 0; i < conn_num; i++)
-				msm_usb_bam_connections_info[j][i] =
-					bam_connection_arr +
-					(j * conn_num * ncolumns) +
-					(i * ncolumns);
-		}
-
-		/* retrieve device tree parameters */
-		for_each_child_of_node(pdev->dev.of_node, node) {
-			const char *str;
-
-			key = "qcom,usb-bam-type";
-			rc = of_property_read_u32(node, key, &bam);
-			if (rc)
-				goto err;
-
-			rc = of_property_read_string(node, "label", &str);
-			if (rc) {
-				pr_err("Cannot read string\n");
-				goto err;
-			}
-
-			if (strstr(str, "usb-to-peri"))
-				dir = USB_TO_PEER_PERIPHERAL;
-			else if (strstr(str, "peri-to-usb"))
-				dir = PEER_PERIPHERAL_TO_USB;
-			else
-				goto err;
-
-			if (!strcmp(str, "usb-to-peri-qdss-dwc3") ||
-				!strcmp(str, "peri-to-usb-qdss-dwc3"))
-					conn_num = 0;
-			else
-				goto err;
-
-			rc = update_connections_info(node, bam, conn_num, dir);
-			if (rc)
-				goto err;
-		}
-
-		pdata->connections = &msm_usb_bam_connections_info[0][0][0];
-
-	} else {
+	if (conn_num <= 0 || conn_num >= pdata->usb_bam_num_pipes)
 		goto err;
+
+
+	/* alloc msm_usb_bam_connections_info */
+	bam_connection_arr = devm_kzalloc(&pdev->dev, bam_amount *
+		conn_num * ncolumns *
+		sizeof(struct usb_bam_pipe_connect), GFP_KERNEL);
+
+	if (!bam_connection_arr)
+		goto err;
+
+	rc = usb_bam_update_conn_array_index(pdev, bam_connection_arr,
+					bam_amount, conn_num, ncolumns);
+	if (rc)
+		goto err;
+
+	/* retrieve device tree parameters */
+	for_each_child_of_node(pdev->dev.of_node, node) {
+		const char *str;
+
+		key = "qcom,usb-bam-type";
+		rc = of_property_read_u32(node, key, &bam);
+		if (rc)
+			goto err;
+
+		key = "qcom,usb-bam-mem-type";
+		rc = of_property_read_u32(node, key, &mem_type);
+		if (rc)
+			goto err;
+
+		rc = of_property_read_string(node, "label", &str);
+		if (rc) {
+			pr_err("Cannot read string\n");
+			goto err;
+		}
+
+		if (strstr(str, "usb-to-peri"))
+			dir = USB_TO_PEER_PERIPHERAL;
+		else if (strstr(str, "peri-to-usb"))
+			dir = PEER_PERIPHERAL_TO_USB;
+		else
+			goto err;
+
+		/* Check if connection type is suported */
+		if (!strcmp(str, "usb-to-peri-qdss-dwc3") ||
+			!strcmp(str, "peri-to-usb-qdss-dwc3") ||
+			!strcmp(str, "usb-to-peri-qdss-hsusb") ||
+			!strcmp(str, "peri-to-usb-qdss-hsusb"))
+				conn_num = 0;
+		else
+			goto err;
+
+		rc = update_connections_info(node, bam, conn_num,
+						dir, mem_type);
+		if (rc)
+			goto err;
 	}
 
+	pdata->connections = &msm_usb_bam_connections_info[0][0][0];
+
 	return pdata;
 err:
 	pr_err("%s: failed\n", __func__);
 	return NULL;
 }
 
+static char *bam_enable_strings[3] = {
+	[SSUSB_BAM] = "ssusb",
+	[HSUSB_BAM] = "hsusb",
+	[HSIC_BAM]  = "hsic",
+};
+
 static int usb_bam_init(void)
 {
 	u32 h_usb;
@@ -534,14 +600,15 @@
 	struct resource *res;
 	int irq;
 
-	res = platform_get_resource(usb_bam_pdev, IORESOURCE_MEM,
-		pdata->usb_active_bam);
+	res = platform_get_resource_byname(usb_bam_pdev, IORESOURCE_MEM,
+				bam_enable_strings[pdata->usb_active_bam]);
 	if (!res) {
 		dev_err(&usb_bam_pdev->dev, "Unable to get memory resource\n");
 		return -ENODEV;
 	}
 
-	irq = platform_get_irq(usb_bam_pdev, pdata->usb_active_bam);
+	irq = platform_get_irq_byname(usb_bam_pdev,
+				bam_enable_strings[pdata->usb_active_bam]);
 	if (irq < 0) {
 		dev_err(&usb_bam_pdev->dev, "Unable to get IRQ resource\n");
 		return irq;
@@ -569,11 +636,6 @@
 	return 0;
 }
 
-static char *bam_enable_strings[2] = {
-	[HSUSB_BAM] = "hsusb",
-	[HSIC_BAM]  = "hsic",
-};
-
 static ssize_t
 usb_bam_show_enable(struct device *dev, struct device_attribute *attr,
 		    char *buf)
@@ -638,7 +700,6 @@
 
 	if (pdev->dev.of_node) {
 		dev_dbg(&pdev->dev, "device tree enabled\n");
-		device_tree_enabled = 1;
 		pdata = usb_bam_dt_to_pdata(pdev);
 		if (!pdata)
 			return -ENOMEM;
@@ -648,7 +709,12 @@
 		return -ENODEV;
 	} else {
 		pdata = pdev->dev.platform_data;
-		device_tree_enabled = 0;
+		ret = usb_bam_update_conn_array_index(pdev, pdata->connections,
+				MAX_BAMS, CONNECTIONS_NUM, 2);
+		if (ret) {
+			pr_err("usb_bam_update_conn_array_index failed\n");
+			return ret;
+		}
 	}
 	usb_bam_pdev = pdev;
 
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index ffa542f..aaabca9 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -396,6 +396,12 @@
 	bool core_clk_always_on_workaround;
 };
 
+enum usb_pipe_mem_type {
+	SPS_PIPE_MEM = 0,	/* Default, SPS dedicated pipe memory */
+	USB_PRIVATE_MEM,	/* USB's private memory */
+	SYSTEM_MEM,		/* System RAM, requires allocation */
+};
+
 /**
  * struct usb_bam_pipe_connect: pipe connection information
  * between USB/HSIC BAM and another BAM. USB/HSIC BAM can be
@@ -404,6 +410,7 @@
  * @src_pipe_index: src bam pipe index.
  * @dst_phy_addr: dst bam physical address.
  * @dst_pipe_index: dst bam pipe index.
+ * @mem_type: type of memory used for BAM FIFOs
  * @data_fifo_base_offset: data fifo offset.
  * @data_fifo_size: data fifo size.
  * @desc_fifo_base_offset: descriptor fifo offset.
@@ -414,6 +421,7 @@
 	u32 src_pipe_index;
 	u32 dst_phy_addr;
 	u32 dst_pipe_index;
+	enum usb_pipe_mem_type mem_type;
 	u32 data_fifo_base_offset;
 	u32 data_fifo_size;
 	u32 desc_fifo_base_offset;
@@ -439,8 +447,10 @@
 };
 
 enum usb_bam {
-	HSUSB_BAM = 0,
+	SSUSB_BAM = 0,
+	HSUSB_BAM,
 	HSIC_BAM,
+	MAX_BAMS,
 };
 
 #ifdef CONFIG_USB_DWC3_MSM