/* SPDX-License-Identifier: GPL-2.0-only */


#ifndef _MHI_DMA_H_
#define _MHI_DMA_H_

#include <linux/types.h>
#include <linux/dma-mapping.h>




#define MHI_DMA_HOST_ADDR(addr) ((addr) | BIT_ULL(40))


enum mhi_dma_function_type {
	MHI_DMA_FUNCTION_TYPE_PHYSICAL,
	MHI_DMA_FUNCTION_TYPE_VIRTUAL,
};


enum mhi_dma_event_type {
	MHI_DMA_EVENT_READY,
	MHI_DMA_EVENT_DATA_AVAILABLE,
	MHI_DMA_EVENT_SSR_RESET,
	MHI_DMA_EVENT_MAX,
};

enum mhi_dma_mstate {
	MHI_DMA_STATE_M0,
	MHI_DMA_STATE_M1,
	MHI_DMA_STATE_M2,
	MHI_DMA_STATE_M3,
	MHI_DMA_STATE_M_MAX
};

typedef void (*mhi_dma_cb)(void *priv, enum mhi_dma_event_type event,
			   unsigned long data);




struct mhi_dma_function_params {
	enum mhi_dma_function_type function_type;
	u8 vf_id;
};


struct mhi_dma_msi_info {
	u32 addr_low;
	u32 addr_hi;
	u32 data;
	u32 mask;
};


struct mhi_dma_init_params {
	struct mhi_dma_msi_info msi;
	u32 mmio_addr;
	u32 first_ch_idx;
	u32 first_er_idx;
	bool assert_bit40;
	mhi_dma_cb notify;
	void *priv;
	bool test_mode;
};


struct mhi_dma_init_out {
	u64 ch_db_fwd_base;
	u64 ev_db_fwd_base;
	u32 ch_db_fwd_msk;
	u32 ev_db_fwd_msk;
};


struct mhi_dma_start_params {
	u32 host_ctrl_addr;
	u32 host_data_addr;
	u64 channel_context_array_addr;
	u64 event_context_array_addr;
};


struct mhi_dma_connect_params {
	u8 channel_id;
	u32 desc_fifo_sz;
	void *priv;
	mhi_dma_cb notify;
	u32 int_modt;
	u32 int_modc;
	u32 buff_size;
};


struct mhi_dma_disconnect_params {
	u32 clnt_hdl;
};


struct mhi_dma_ops {
	int (*mhi_dma_register_ready_cb)(void (*mhi_ready_cb)(void *user_data),
				void *user_data);
	int (*mhi_dma_init)(struct mhi_dma_function_params function,
			    struct mhi_dma_init_params *params,
			    struct mhi_dma_init_out *out);
	int (*mhi_dma_start)(struct mhi_dma_function_params function,
			     struct mhi_dma_start_params *params);
	int (*mhi_dma_connect_endp)(struct mhi_dma_function_params function,
				    struct mhi_dma_connect_params *in,
				    u32 *clnt_hdl);
	int (*mhi_dma_disconnect_endp)(struct mhi_dma_function_params function,
				       struct mhi_dma_disconnect_params *in);
	void (*mhi_dma_destroy)(struct mhi_dma_function_params function);
	int (*mhi_dma_memcpy_init)(struct mhi_dma_function_params function);
	void (*mhi_dma_memcpy_destroy)(struct mhi_dma_function_params function);
	int (*mhi_dma_memcpy_enable)(struct mhi_dma_function_params function);
	int (*mhi_dma_memcpy_disable)(struct mhi_dma_function_params function);
	int (*mhi_dma_sync_memcpy)(u64 dest, u64 src, int len,
				   struct mhi_dma_function_params function);
	int (*mhi_dma_async_memcpy)(u64 dest, u64 src, int len,
				    struct mhi_dma_function_params function,
				    void (*user_cb)(void *user1),
				    void *user_param);
	dma_addr_t (*mhi_dma_map_buffer)(void *virt, size_t size,
					 enum dma_data_direction dir);
	void (*mhi_dma_unmap_buffer)(dma_addr_t phys, size_t size,
		enum dma_data_direction dir);
	void* (*mhi_dma_alloc_buffer)(size_t size, dma_addr_t *phys, gfp_t gfp);
	void (*mhi_dma_free_buffer)(size_t size, void *virt, dma_addr_t phys);
	int (*mhi_dma_update_mstate)(struct mhi_dma_function_params function,
				  enum mhi_dma_mstate mstate_info);
	int (*mhi_dma_resume)(struct mhi_dma_function_params function);
	int (*mhi_dma_suspend)(struct mhi_dma_function_params function, bool force);
};

#if IS_ENABLED(CONFIG_MSM_MHI_DEV)

int mhi_dma_provide_ops(const struct mhi_dma_ops *ops);

#else

static inline int mhi_dma_provide_ops(const struct mhi_dma_ops *ops)
{
	return -EPERM;
}
#endif



int mhi_dma_register_ready_cb(void (*mhi_ready_cb)(void *user_data),
		void *user_data);


int mhi_dma_init(struct mhi_dma_function_params function,
		 struct mhi_dma_init_params *params,
		 struct mhi_dma_init_out *out);


int mhi_dma_start(struct mhi_dma_function_params function,
		  struct mhi_dma_start_params *params);


int mhi_dma_connect_endp(struct mhi_dma_function_params function,
			 struct mhi_dma_connect_params *in, u32 *clnt_hdl);


int mhi_dma_disconnect_endp(struct mhi_dma_function_params function,
			    struct mhi_dma_disconnect_params *in);


int mhi_dma_suspend(struct mhi_dma_function_params function, bool force);


int mhi_dma_resume(struct mhi_dma_function_params function);


int mhi_dma_update_mstate(struct mhi_dma_function_params function,
			  enum mhi_dma_mstate mstate_info);


void mhi_dma_destroy(struct mhi_dma_function_params function);


int mhi_dma_memcpy_init(struct mhi_dma_function_params function);



void mhi_dma_memcpy_destroy(struct mhi_dma_function_params function);


int mhi_dma_memcpy_enable(struct mhi_dma_function_params function);


int mhi_dma_memcpy_disable(struct mhi_dma_function_params function);


int mhi_dma_sync_memcpy(u64 dest, u64 src, int len,
			struct mhi_dma_function_params function);


int mhi_dma_async_memcpy(u64 dest, u64 src, int len,
			 struct mhi_dma_function_params function,
			 void (*user_cb)(void *user1), void *user_param);


dma_addr_t mhi_dma_map_buffer(void *virt, size_t size,
			      enum dma_data_direction dir);


void mhi_dma_unmap_buffer(dma_addr_t phys, size_t size,
				enum dma_data_direction dir);


void *mhi_dma_alloc_buffer(size_t size, dma_addr_t *phys, gfp_t gfp);


void mhi_dma_free_buffer(size_t size, void *virt, dma_addr_t phys);

#endif //_MHI_DMA_H_
