USB: Add functionality to map QDSS BAM address space with USB

This change adds functionality to map QDSS BAM address space within
USB context bank, and pass that information to SPS driver.

Change-Id: Idbd13e6faed52be79d36c4bd95674636821ba3ed
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index dd10e82..52b32ce 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -577,7 +577,8 @@
 	return 0;
 }
 
-static int connect_pipe(enum usb_ctrl cur_bam, u8 idx, u32 *usb_pipe_idx)
+static int connect_pipe(enum usb_ctrl cur_bam, u8 idx, u32 *usb_pipe_idx,
+							unsigned long iova)
 {
 	int ret;
 	struct usb_bam_ctx_type *ctx = &msm_usb_bam[cur_bam];
@@ -622,9 +623,11 @@
 	if (dir == USB_TO_PEER_PERIPHERAL) {
 		sps_connection->mode = SPS_MODE_SRC;
 		*usb_pipe_idx = pipe_connect->src_pipe_index;
+		sps_connection->dest_iova = iova;
 	} else {
 		sps_connection->mode = SPS_MODE_DEST;
 		*usb_pipe_idx = pipe_connect->dst_pipe_index;
+		sps_connection->source_iova = iova;
 	}
 
 	sps_connection->data = *data_buf;
@@ -1106,7 +1109,34 @@
 	return 0;
 }
 
-int usb_bam_connect(enum usb_ctrl cur_bam, int idx, u32 *bam_pipe_idx)
+int get_qdss_bam_info(enum usb_ctrl cur_bam, u8 idx,
+				phys_addr_t *p_addr, u32 *bam_size)
+{
+	int ret = 0;
+	struct usb_bam_ctx_type *ctx = &msm_usb_bam[cur_bam];
+	struct usb_bam_pipe_connect *pipe_connect =
+					&ctx->usb_bam_connections[idx];
+	unsigned long peer_bam_handle;
+
+	ret = sps_phy2h(pipe_connect->dst_phy_addr, &peer_bam_handle);
+	if (ret) {
+		log_event_err("%s: sps_phy2h failed (src BAM) %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	ret = sps_get_bam_addr(peer_bam_handle, p_addr, bam_size);
+	if (ret) {
+		log_event_err("%s: sps_get_bam_addr failed%d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int usb_bam_connect(enum usb_ctrl cur_bam, int idx, u32 *bam_pipe_idx,
+						unsigned long iova)
 {
 	int ret;
 	struct usb_bam_ctx_type *ctx = &msm_usb_bam[cur_bam];
@@ -1157,7 +1187,7 @@
 	/* Set the BAM mode (host/device) according to connected pipe */
 	info[cur_bam].cur_bam_mode = pipe_connect->bam_mode;
 
-	ret = connect_pipe(cur_bam, idx, bam_pipe_idx);
+	ret = connect_pipe(cur_bam, idx, bam_pipe_idx, iova);
 	if (ret) {
 		log_event_err("%s: pipe connection[%d] failure\n",
 				__func__, idx);
diff --git a/drivers/usb/gadget/function/f_qdss.h b/drivers/usb/gadget/function/f_qdss.h
index 4ba2e9b..72edb90 100644
--- a/drivers/usb/gadget/function/f_qdss.h
+++ b/drivers/usb/gadget/function/f_qdss.h
@@ -31,6 +31,9 @@
 	u32 peer_pipe_idx;
 	unsigned long usb_bam_handle;
 	struct sps_mem_buffer *data_fifo;
+	unsigned long qdss_bam_iova;
+	phys_addr_t qdss_bam_phys;
+	u32 qdss_bam_size;
 };
 
 struct gqdss {
diff --git a/drivers/usb/gadget/function/u_qdss.c b/drivers/usb/gadget/function/u_qdss.c
index 0bfef9a..b4353ac 100644
--- a/drivers/usb/gadget/function/u_qdss.c
+++ b/drivers/usb/gadget/function/u_qdss.c
@@ -47,6 +47,8 @@
 	int			idx;
 	struct usb_qdss_bam_connect_info bam_info;
 	struct usb_gadget *gadget;
+	struct device *dev;
+	int ret;
 
 	pr_debug("set_qdss_data_connection\n");
 
@@ -57,6 +59,7 @@
 
 	gadget = qdss->gadget;
 	usb_bam_type = usb_bam_get_bam_type(gadget->name);
+	dev = gadget->dev.parent;
 
 	bam_info = qdss->bam_info;
 	/* There is only one qdss pipe, so the pipe number can be set to 0 */
@@ -68,6 +71,23 @@
 	}
 
 	if (enable) {
+		ret = get_qdss_bam_info(usb_bam_type, idx,
+				&bam_info.qdss_bam_phys,
+				&bam_info.qdss_bam_size);
+		if (ret) {
+			pr_err("%s(): failed to get qdss bam info err(%d)\n",
+								__func__, ret);
+			return ret;
+		}
+
+		bam_info.qdss_bam_iova = dma_map_resource(dev->parent,
+				bam_info.qdss_bam_phys, bam_info.qdss_bam_size,
+				DMA_BIDIRECTIONAL, 0);
+		if (!bam_info.qdss_bam_iova) {
+			pr_err("dma_map_resource failed\n");
+			return -ENOMEM;
+		}
+
 		usb_bam_alloc_fifos(usb_bam_type, idx);
 		bam_info.data_fifo =
 			kzalloc(sizeof(struct sps_mem_buffer), GFP_KERNEL);
@@ -76,6 +96,12 @@
 			usb_bam_free_fifos(usb_bam_type, idx);
 			return -ENOMEM;
 		}
+
+		pr_debug("%s(): qdss_bam: iova:%lx p_addr:%lx size:%x\n",
+				__func__, bam_info.qdss_bam_iova,
+				(unsigned long)bam_info.qdss_bam_phys,
+				bam_info.qdss_bam_size);
+
 		get_bam2bam_connection_info(usb_bam_type, idx,
 				&bam_info.usb_bam_pipe_idx,
 				NULL, bam_info.data_fifo, NULL);
@@ -88,13 +114,16 @@
 		init_data(qdss->port.data);
 
 		res = usb_bam_connect(usb_bam_type, idx,
-					&(bam_info.usb_bam_pipe_idx));
+					&(bam_info.usb_bam_pipe_idx),
+					bam_info.qdss_bam_iova);
 	} else {
-		kfree(bam_info.data_fifo);
 		res = usb_bam_disconnect_pipe(usb_bam_type, idx);
 		if (res)
 			pr_err("usb_bam_disconnection error\n");
+		dma_unmap_resource(dev->parent, bam_info.qdss_bam_iova,
+				bam_info.qdss_bam_size, DMA_BIDIRECTIONAL, 0);
 		usb_bam_free_fifos(usb_bam_type, idx);
+		kfree(bam_info.data_fifo);
 	}
 
 	return res;
diff --git a/include/linux/usb_bam.h b/include/linux/usb_bam.h
index 1b0ca4a..84d7549 100644
--- a/include/linux/usb_bam.h
+++ b/include/linux/usb_bam.h
@@ -245,10 +245,13 @@
  *
  * @bam_pipe_idx - allocated pipe index.
  *
+ * @iova - IPA address of USB peer BAM (i.e. QDSS BAM)
+ *
  * @return 0 on success, negative value on error
  *
  */
-int usb_bam_connect(enum usb_ctrl bam_type, int idx, u32 *bam_pipe_idx);
+int usb_bam_connect(enum usb_ctrl bam_type, int idx, u32 *bam_pipe_idx,
+						unsigned long iova);
 
 /**
  * Connect USB-to-IPA SPS connection.
@@ -430,12 +433,14 @@
 
 /* Frees memory for data fifo and descriptor fifos. */
 int usb_bam_free_fifos(enum usb_ctrl cur_bam, u8 idx);
-
+int get_qdss_bam_info(enum usb_ctrl cur_bam, u8 idx,
+			phys_addr_t *p_addr, u32 *bam_size);
 bool msm_bam_hsic_lpm_ok(void);
 bool msm_bam_hsic_host_pipe_empty(void);
 bool msm_usb_bam_enable(enum usb_ctrl ctrl, bool bam_enable);
 #else
-static inline int usb_bam_connect(enum usb_ctrl bam, u8 idx, u32 *bam_pipe_idx)
+static inline int usb_bam_connect(enum usb_ctrl bam, u8 idx, u32 *bam_pipe_idx,
+							unsigned long iova)
 {
 	return -ENODEV;
 }
@@ -529,6 +534,11 @@
 	return false;
 }
 
+static int get_qdss_bam_info(enum usb_ctrl cur_bam, u8 idx,
+				phys_addr_t *p_addr, u32 *bam_size)
+{
+	return false;
+}
 static inline bool msm_bam_hsic_lpm_ok(void) { return true; }
 static inline bool msm_bam_hsic_host_pipe_empty(void) { return true; }
 static inline bool msm_usb_bam_enable(enum usb_ctrl ctrl, bool bam_enable)