msm: ipa3: support MHI IPA new operation API's

Support new MHI IPA API's exposed from k-5.15.

Signed-off-by: Dor Deri <quic_dderi@quicinc.com>
Change-Id: I5177801a9aad1eed9b0a2cbc95c25007a5996273
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index 10cd2d7..43757d5 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/of.h>
@@ -3377,6 +3377,29 @@
 }
 EXPORT_SYMBOL(gsi_query_channel_db_addr);
 
+int gsi_get_channel_event_db_base_addr(uint64_t *ch_db_base_addr,
+		uint64_t *ev_db_base_addr)
+{
+        if (!gsi_ctx) {
+                pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__);
+                return -GSI_STATUS_NODEV;
+        }
+
+        if (!ch_db_base_addr || !ev_db_base_addr) {
+                GSIERR("bad params ch_db=%pK ev_db=%pK\n", ch_db_base_addr,
+                                ev_db_base_addr);
+                return -GSI_STATUS_INVALID_PARAMS;
+        }
+
+        *ch_db_base_addr = gsi_ctx->per.phys_addr +
+                gsihal_get_reg_nk_ofst(GSI_EE_n_GSI_CH_k_DOORBELL_0, 0, 0);
+        *ev_db_base_addr = gsi_ctx->per.phys_addr +
+                gsihal_get_reg_nk_ofst(GSI_EE_n_EV_CH_k_DOORBELL_0, 0, 0);
+
+        return GSI_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(gsi_get_channel_event_db_base_addr);
+
 int gsi_pending_irq_type(void)
 {
 	int ee = gsi_ctx->per.ee;
diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h
index f0b5814..9caaa24 100644
--- a/drivers/platform/msm/gsi/gsi.h
+++ b/drivers/platform/msm/gsi/gsi.h
@@ -2,7 +2,7 @@
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  *
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef GSI_H
@@ -2202,6 +2202,18 @@
 		uint32_t *db_addr_wp_lsb, uint32_t *db_addr_wp_msb);
 
 /**
+ * gsi_get_channel_event_db_base_addr - Get the physical base addresses of
+ * gsi channel doorbell and event channel doorbell
+ *
+ * @ch_db_base_addr: Physical base address of gsi channel doorbell register
+ * @ev_db_base_addr: Physical base address of event channel doorbell register
+ *
+ * @Return gsi_status
+ */
+int gsi_get_channel_event_db_base_addr(uint64_t *ch_db_base_addr,
+		uint64_t *ev_db_base_addr);
+
+/**
  * gsi_query_channel_info - Peripheral can call this function to query the
  * channel and associated event ring (if any) status.
  *
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_clients_manager.c b/drivers/platform/msm/ipa/ipa_clients/ipa_clients_manager.c
index 56f7fd9..711b334 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_clients_manager.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_clients_manager.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -30,6 +31,10 @@
 
 	ipa3_notify_clients_registered();
 
+	if (ipa3_ctx->ipa_config_is_mhi || ipa3_ctx->ipa_config_is_apq_dma) {
+		ipa_dma_mhi_provide_ops();
+	}
+
 	ipa3_qdss_register();
 
 	return 0;
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index bb9cf79..5742cf7 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/debugfs.h>
@@ -62,6 +63,15 @@
 #define IPA_MHI_MAX_UL_CHANNELS 2
 #define IPA_MHI_MAX_DL_CHANNELS 4
 
+#define IPA_MHI_TOTAL_CLIENTS 6
+static enum ipa_client_type mhi_clients[IPA_MHI_TOTAL_CLIENTS] =
+		{IPA_CLIENT_MHI_PROD,
+		IPA_CLIENT_MHI_CONS,
+		IPA_CLIENT_MHI_LOW_LAT_PROD,
+		IPA_CLIENT_MHI_LOW_LAT_CONS,
+		IPA_CLIENT_MHI_QDSS_CONS,
+		IPA_CLIENT_MHI_DPL_CONS};
+
 /* bit #40 in address should be asserted for MHI transfers over pcie */
 #define IPA_MHI_CLIENT_HOST_ADDR_COND(addr) \
 	((ipa_mhi_client_ctx->assert_bit40)?(IPA_MHI_HOST_ADDR(addr)):(addr))
@@ -552,6 +562,26 @@
 	IPA_MHI_FUNC_EXIT();
 }
 
+
+/**
+ * ipa_mhi_get_ch_bitmap() - Get MHI channels numbers in bitmap.
+ *
+ * @ch_bitmap: the bitmap to fill with the MHI clients channels
+ *           numbers.
+ */
+static void ipa_mhi_get_ch_bitmap(u32 *ch_bitmap)
+{
+	int i;
+	const struct ipa_gsi_ep_config *gsi_ep_config;
+
+	*ch_bitmap = 0;
+	for (i = 0; i < IPA_MHI_TOTAL_CLIENTS; i++) {
+		gsi_ep_config = ipa_get_gsi_ep_info(mhi_clients[i]);
+		if (gsi_ep_config)
+			*ch_bitmap |= 1 << gsi_ep_config->ipa_gsi_chan_num;
+	}
+}
+
 /**
  * ipa_mhi_set_state() - Set new state to IPA MHI
  * @state: new state
@@ -2444,6 +2474,167 @@
 }
 EXPORT_SYMBOL(ipa_mhi_register);
 
+/* New mhi API implementation for mhi_dma.h */
+
+int ipa_mhi_dma_register_ready_cb(void (*mhi_ready_cb)(void *user_data),
+		void *user_data)
+{
+
+	IPA_MHI_DBG("Begin\n");
+	return ipa_register_ipa_ready_cb(mhi_ready_cb,user_data);
+	IPA_MHI_DBG("End\n");
+}
+EXPORT_SYMBOL(ipa_mhi_dma_register_ready_cb);
+
+int ipa_mhi_dma_init(struct mhi_dma_function_params function,
+                struct mhi_dma_init_params *params,
+                struct mhi_dma_init_out *out)
+{
+	int gsi_res;
+	if (!out) {
+		IPA_MHI_DBG("null out arg\n");
+		return -EINVAL;
+	}
+
+	gsi_res = gsi_get_channel_event_db_base_addr(&out->ch_db_fwd_base,
+		&out->ev_db_fwd_base);
+	if (gsi_res != GSI_STATUS_SUCCESS) {
+		IPA_MHI_DBG("Error getting DB base addresses: %d\n", gsi_res);
+		return -EFAULT;
+	}
+
+	ipa_mhi_get_ch_bitmap(&out->ch_db_fwd_msk);
+	out->ev_db_fwd_msk = out->ch_db_fwd_msk;
+
+	return ipa_mhi_init_internal((struct ipa_mhi_init_params *)params);;
+}
+EXPORT_SYMBOL(ipa_mhi_dma_init);
+
+int ipa_mhi_dma_start(struct mhi_dma_function_params function,
+		struct mhi_dma_start_params *params)
+{
+	return ipa_mhi_start_internal((struct ipa_mhi_start_params *)params);
+}
+EXPORT_SYMBOL(ipa_mhi_dma_start);
+
+int ipa_mhi_dma_connect_endp(struct mhi_dma_function_params function,
+		struct mhi_dma_connect_params *in, u32 *clnt_hdl)
+{
+	struct ipa_mhi_connect_params connect_params = {0};
+
+	/* struct mhi_dma_function_params is not the same as struct ipa_mhi_connect_params.
+	  Casting needs to be done explictly.*/
+	connect_params.channel_id = in->channel_id;
+	connect_params.sys.desc_fifo_sz = in->desc_fifo_sz;
+	connect_params.sys.priv = in->priv;
+	connect_params.sys.notify = (ipa_notify_cb)in->notify;
+	connect_params.sys.int_modt = in->int_modt;
+	connect_params.sys.int_modc = in->int_modc;
+	connect_params.sys.buff_size = in->buff_size;
+
+	connect_params.sys.skip_ep_cfg = true;
+
+	return ipa_mhi_connect_pipe_internal(&connect_params, clnt_hdl);
+}
+EXPORT_SYMBOL(ipa_mhi_dma_connect_endp);
+
+int ipa_mhi_dma_disconnect_endp(struct mhi_dma_function_params function,
+                struct mhi_dma_disconnect_params *in)
+{
+	return ipa_mhi_disconnect_pipe_internal(in->clnt_hdl);
+}
+EXPORT_SYMBOL(ipa_mhi_dma_disconnect_endp);
+
+int ipa_mhi_dma_suspend(struct mhi_dma_function_params function, bool force)
+{
+	return ipa_mhi_suspend_internal(force);
+}
+EXPORT_SYMBOL(ipa_mhi_dma_suspend);
+
+int ipa_mhi_dma_resume(struct mhi_dma_function_params function)
+{
+	return ipa_mhi_resume_internal();
+}
+EXPORT_SYMBOL(ipa_mhi_dma_resume);
+
+int ipa_mhi_dma_update_mstate(struct mhi_dma_function_params function,
+		enum mhi_dma_mstate mstate_info)
+{
+	return ipa_mhi_update_mstate_internal((enum ipa_mhi_mstate)mstate_info);
+}
+EXPORT_SYMBOL(ipa_mhi_dma_update_mstate);
+
+void ipa_mhi_dma_destroy(struct mhi_dma_function_params function)
+{
+	ipa_mhi_destroy_internal();
+}
+EXPORT_SYMBOL(ipa_mhi_dma_destroy);
+
+static dma_addr_t ipa_mhi_dma_map_buffer(void* virt, size_t size,
+	enum dma_data_direction dir)
+{
+	dma_addr_t phys;
+	IPA_MHI_DBG("Begin\n");
+
+	phys = dma_map_single(ipa3_ctx->pdev, virt, size, dir);
+	if (dma_mapping_error(ipa3_ctx->pdev, phys)) {
+		IPA_MHI_ERR("failed to do dma map.\n");
+		ipa_assert();
+	}
+
+	return phys;
+}
+
+static void ipa_mhi_dma_unmap_buffer(dma_addr_t phys, size_t size,
+	enum dma_data_direction dir)
+{
+	IPA_MHI_DBG("Begin\n");
+	dma_unmap_single(ipa3_ctx->pdev, phys, size, dir);
+}
+
+static void *ipa_mhi_dma_alloc_buffer(size_t size,
+	dma_addr_t* phys, gfp_t gfp)
+{
+	IPA_MHI_DBG("Begin\n");
+	return  dma_alloc_coherent(ipa3_ctx->pdev, size, phys, gfp);
+}
+
+static void ipa_mhi_dma_free_buffer(size_t size, void* virt,
+	dma_addr_t phys)
+{
+	IPA_MHI_DBG("Begin\n");
+	dma_free_coherent(ipa3_ctx->pdev, size, virt, phys);
+}
+
+/* API exposed structure */
+const struct mhi_dma_ops ipa_dma_mhi_driver_ops = {
+	.mhi_dma_register_ready_cb = ipa_mhi_dma_register_ready_cb,
+	.mhi_dma_init = ipa_mhi_dma_init,
+	.mhi_dma_start = ipa_mhi_dma_start,
+	.mhi_dma_connect_endp = ipa_mhi_dma_connect_endp,
+	.mhi_dma_disconnect_endp = ipa_mhi_dma_disconnect_endp,
+	.mhi_dma_destroy = ipa_mhi_dma_destroy,
+	.mhi_dma_memcpy_init = ipa_mhi_dma_memcpy_init,
+	.mhi_dma_memcpy_destroy = ipa_mhi_dma_memcpy_destroy,
+	.mhi_dma_sync_memcpy = ipa_mhi_dma_sync_memcpy,
+	.mhi_dma_async_memcpy = ipa_mhi_dma_async_memcpy,
+	.mhi_dma_memcpy_enable = ipa_mhi_dma_memcpy_enable,
+	.mhi_dma_memcpy_disable = ipa_mhi_dma_memcpy_disable,
+	.mhi_dma_map_buffer = ipa_mhi_dma_map_buffer,
+	.mhi_dma_unmap_buffer = ipa_mhi_dma_unmap_buffer,
+	.mhi_dma_alloc_buffer = ipa_mhi_dma_alloc_buffer,
+	.mhi_dma_free_buffer = ipa_mhi_dma_free_buffer,
+	.mhi_dma_update_mstate = ipa_mhi_dma_update_mstate,
+	.mhi_dma_resume = ipa_mhi_dma_resume,
+	.mhi_dma_suspend = ipa_mhi_dma_suspend,
+};
+
+int ipa_dma_mhi_provide_ops()
+{
+	return mhi_dma_provide_ops(&ipa_dma_mhi_driver_ops);
+}
+EXPORT_SYMBOL(ipa_dma_mhi_provide_ops);
+/* End of the new mhi API */
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("IPA MHI client driver");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index b3519be..a7c81f5 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -9298,6 +9298,7 @@
         ipa3_ctx->ipa_gen_rx_cmn_temp_pool_sz_factor = get_ipa_gen_rx_cmn_temp_pool_size(
                         resource_p->ipa_gen_rx_cmn_temp_pool_sz_factor);
 	ipa3_ctx->ipa_config_is_auto = resource_p->ipa_config_is_auto;
+	ipa3_ctx->ipa_config_is_apq_dma = resource_p->ipa_config_is_apq_dma;
 	ipa3_ctx->ipa_mhi_proxy = resource_p->ipa_mhi_proxy;
 	ipa3_ctx->max_num_smmu_cb = resource_p->max_num_smmu_cb;
 	ipa3_ctx->hw_type_index = ipa3_get_hw_type_index();
@@ -10262,6 +10263,7 @@
 	ipa_drv_res->skip_ieob_mask_wa = false;
 	ipa_drv_res->ipa_gpi_event_rp_ddr = false;
 	ipa_drv_res->ipa_config_is_auto = false;
+	ipa_drv_res->ipa_config_is_apq_dma = false;
 	ipa_drv_res->max_num_smmu_cb = IPA_SMMU_CB_MAX;
 	ipa_drv_res->ipa_endp_delay_wa_v2 = false;
 	ipa_drv_res->use_tput_est_ep = false;
@@ -10407,6 +10409,13 @@
 		ipa_drv_res->ipa_config_is_auto
 		? "True" : "False");
 
+	ipa_drv_res->ipa_config_is_apq_dma =
+		of_property_read_bool(pdev->dev.of_node,
+		"qcom,ipa-config-is-apq-dma");
+	IPADBG(": ipa-config-is-apq-dma = %s\n",
+		ipa_drv_res->ipa_config_is_apq_dma
+		? "True" : "False");
+
 	ipa_drv_res->ipa_wan_skb_page =
 			of_property_read_bool(pdev->dev.of_node,
 			"qcom,wan-use-skb-page");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c
index 597e344..82282a7 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 
@@ -1119,6 +1120,50 @@
 	IPADMA_FUNC_EXIT();
 }
 
+/* New dma API implementation for mhi_dma.h */
+
+int ipa_mhi_dma_memcpy_init(struct mhi_dma_function_params function)
+{
+	return ipa3_dma_init();
+}
+EXPORT_SYMBOL(ipa_mhi_dma_memcpy_init);
+
+void ipa_mhi_dma_memcpy_destroy(struct mhi_dma_function_params function)
+{
+	return ipa3_dma_destroy();
+}
+EXPORT_SYMBOL(ipa_mhi_dma_memcpy_destroy);
+
+int ipa_mhi_dma_sync_memcpy(u64 dest, u64 src, int len,
+		struct mhi_dma_function_params function)
+{
+	return ipa3_dma_sync_memcpy(dest, src, len);
+}
+EXPORT_SYMBOL(ipa_mhi_dma_sync_memcpy);
+
+int ipa_mhi_dma_async_memcpy(u64 dest, u64 src, int len,
+		 struct mhi_dma_function_params function,
+		 void (*user_cb)(void *user1), void *user_param)
+{
+	return ipa3_dma_async_memcpy(dest, src, len, user_cb, user_param);
+}
+EXPORT_SYMBOL(ipa_mhi_dma_async_memcpy);
+
+int ipa_mhi_dma_memcpy_enable(struct mhi_dma_function_params function)
+{
+	return ipa3_dma_enable();
+}
+EXPORT_SYMBOL(ipa_mhi_dma_memcpy_enable);
+
+int ipa_mhi_dma_memcpy_disable(struct mhi_dma_function_params function)
+{
+	return ipa3_dma_disable();
+}
+EXPORT_SYMBOL(ipa_mhi_dma_memcpy_disable);
+
+/* End of the new dma API */
+
+
 #ifdef CONFIG_DEBUG_FS
 static struct dentry *dent;
 static struct dentry *dfile_info;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 6eaea66..5eb8ad3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -41,6 +41,7 @@
 #include <linux/mailbox/qmp.h>
 #include <linux/rmnet_ipa_fd_ioctl.h>
 #include <linux/ipa_fmwk.h>
+#include <linux/mhi_dma.h>
 #include "ipa_uc_holb_monitor.h"
 #include <soc/qcom/minidump.h>
 
@@ -2269,6 +2270,7 @@
  * @logbuf_clk: ipc log buffer for ipa clock messages
  * @ipa_wdi2: using wdi-2.0
  * @ipa_config_is_auto: is this AUTO use case
+ * @ipa_config_is_apq_dma: this is for APQ DMA use case
  * @ipa_fltrt_not_hashable: filter/route rules not hashable
  * @use_xbl_boot: use xbl loading for IPA FW
  * @use_64_bit_dma_mask: using 64bits dma mask
@@ -2405,6 +2407,7 @@
 	bool modem_cfg_emb_pipe_flt;
 	bool ipa_wdi2;
 	bool ipa_config_is_auto;
+	bool ipa_config_is_apq_dma;
 	bool ipa_wdi2_over_gsi;
 	bool ipa_wdi3_over_gsi;
 	bool ipa_endp_delay_wa;
@@ -2620,6 +2623,7 @@
 	bool modem_cfg_emb_pipe_flt;
 	bool ipa_wdi2;
 	bool ipa_config_is_auto;
+	bool ipa_config_is_apq_dma;
 	bool ipa_wdi2_over_gsi;
 	bool ipa_wdi3_over_gsi;
 	bool ipa_fltrt_not_hashable;
@@ -3298,10 +3302,54 @@
 
 void ipa3_dma_destroy(void);
 
+int ipa_mhi_dma_memcpy_init(struct mhi_dma_function_params function);
+
+void ipa_mhi_dma_memcpy_destroy(struct mhi_dma_function_params function);
+
+int ipa_mhi_dma_sync_memcpy(u64 dest, u64 src, int len,
+		struct mhi_dma_function_params function);
+
+int ipa_mhi_dma_async_memcpy(u64 dest, u64 src, int len,
+		 struct mhi_dma_function_params function,
+		 void (*user_cb)(void *user1), void *user_param);
+
+int ipa_mhi_dma_memcpy_enable(struct mhi_dma_function_params function);
+
+int ipa_mhi_dma_memcpy_disable(struct mhi_dma_function_params function);
+
+
+
 /*
  * MHI
  */
 
+int ipa_mhi_dma_register_ready_cb(void (*mhi_ready_cb)(void *user_data),
+		void *user_data);
+
+int ipa_mhi_dma_init(struct mhi_dma_function_params function,
+                struct mhi_dma_init_params *params,
+                struct mhi_dma_init_out *out);
+
+int ipa_mhi_dma_start(struct mhi_dma_function_params function,
+		struct mhi_dma_start_params *params);
+
+int ipa_mhi_dma_connect_endp(struct mhi_dma_function_params function,
+		struct mhi_dma_connect_params *in, u32 *clnt_hdl);
+
+int ipa_mhi_dma_disconnect_endp(struct mhi_dma_function_params function,
+                struct mhi_dma_disconnect_params *in);
+
+int ipa_mhi_dma_suspend(struct mhi_dma_function_params function, bool force);
+
+int ipa_mhi_dma_resume(struct mhi_dma_function_params function);
+
+int ipa_mhi_dma_update_mstate(struct mhi_dma_function_params function,
+		enum mhi_dma_mstate mstate_info);
+
+void ipa_mhi_dma_destroy(struct mhi_dma_function_params function);
+
+int ipa_dma_mhi_provide_ops(void);
+
 /*
  * mux id
  */