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


#ifndef __MSM_HW_FENCE_H
#define __MSM_HW_FENCE_H

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


#define MSM_HW_FENCE_FLAG_ENABLED_BIT    31


#define MSM_HW_FENCE_FLAG_SIGNALED_BIT    30


#define MSM_HW_FENCE_ERROR_RESET    BIT(0)


#define MSM_HW_FENCE_RESET_WITHOUT_ERROR    BIT(0)
#define MSM_HW_FENCE_RESET_WITHOUT_DESTROY  BIT(1)


#define MSM_HW_FENCE_UPDATE_ERROR_WITH_MOVE      BIT(0)


#define MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT 64


#define MSM_HW_FENCE_DBG_DUMP_QUEUES        BIT(0)
#define MSM_HW_FENCE_DBG_DUMP_TABLE         BIT(1)
#define MSM_HW_FENCE_DBG_DUMP_EVENTS        BIT(2)


struct msm_hw_fence_create_params {
	const char *name;
	u64 *handle;
	void *fence;
	u32 flags;
};


struct msm_hw_fence_hfi_queue_table_header {
	u32 version;
	u32 size;
	u32 qhdr0_offset;
	u32 qhdr_size;
	u32 num_q;
	u32 num_active_q;
};


struct msm_hw_fence_hfi_queue_header {
	u32 status;
	u32 start_addr;
	u32 type;
	u32 queue_size;
	u32 pkt_size;
	u32 pkt_drop_cnt;
	u32 rx_wm;
	u32 tx_wm;
	u32 rx_req;
	u32 tx_req;
	u32 rx_irq_status;
	u32 tx_irq_status;
	u32 read_index;
	u32 write_index;
};


struct msm_hw_fence_mem_addr {
	void *virtual_addr;
	phys_addr_t device_addr;
	u64 size;
	void *mem_data;
};


struct msm_hw_fence_cb_data {
	void *data;
	struct dma_fence *fence;
};


typedef void (*msm_hw_fence_error_cb_t)(u32 handle, int error, void *cb_data);


enum hw_fence_client_id {
	HW_FENCE_CLIENT_ID_CTX0 = 0x1,
	HW_FENCE_CLIENT_ID_CTL0,
	HW_FENCE_CLIENT_ID_CTL1,
	HW_FENCE_CLIENT_ID_CTL2,
	HW_FENCE_CLIENT_ID_CTL3,
	HW_FENCE_CLIENT_ID_CTL4,
	HW_FENCE_CLIENT_ID_CTL5,
	HW_FENCE_CLIENT_ID_VAL0,
	HW_FENCE_CLIENT_ID_VAL1,
	HW_FENCE_CLIENT_ID_VAL2,
	HW_FENCE_CLIENT_ID_VAL3,
	HW_FENCE_CLIENT_ID_VAL4,
	HW_FENCE_CLIENT_ID_VAL5,
	HW_FENCE_CLIENT_ID_VAL6,
	HW_FENCE_CLIENT_ID_IPE,
	HW_FENCE_CLIENT_ID_VPU = HW_FENCE_CLIENT_ID_IPE + MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT,
	HW_FENCE_CLIENT_ID_IFE0 = HW_FENCE_CLIENT_ID_VPU + MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT,
	HW_FENCE_CLIENT_ID_IFE1 = HW_FENCE_CLIENT_ID_IFE0 + MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT,
	HW_FENCE_CLIENT_ID_IFE2 = HW_FENCE_CLIENT_ID_IFE1 + MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT,
	HW_FENCE_CLIENT_ID_IFE3 = HW_FENCE_CLIENT_ID_IFE2 + MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT,
	HW_FENCE_CLIENT_ID_IFE4 = HW_FENCE_CLIENT_ID_IFE3 + MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT,
	HW_FENCE_CLIENT_ID_IFE5 = HW_FENCE_CLIENT_ID_IFE4 + MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT,
	HW_FENCE_CLIENT_ID_IFE6 = HW_FENCE_CLIENT_ID_IFE5 + MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT,
	HW_FENCE_CLIENT_ID_IFE7 = HW_FENCE_CLIENT_ID_IFE6 + MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT,
	HW_FENCE_CLIENT_MAX = HW_FENCE_CLIENT_ID_IFE7 + MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT
};

#if IS_ENABLED(CONFIG_QTI_HW_FENCE)

void *msm_hw_fence_register(
	enum hw_fence_client_id client_id,
	struct msm_hw_fence_mem_addr *mem_descriptor);


int msm_hw_fence_deregister(void *client_handle);


int msm_hw_fence_create(void *client_handle,
	struct msm_hw_fence_create_params *params);


int msm_hw_fence_destroy(void *client_handle,
	struct dma_fence *fence);


int msm_hw_fence_destroy_with_handle(void *client_handle, u64 handle);


int msm_hw_fence_wait_update_v2(void *client_handle,
	struct dma_fence **fences, u64 *handles, u64 *client_data_list, u32 num_fences, bool reg);


int msm_hw_fence_wait_update(void *client_handle,
	struct dma_fence **fences, u32 num_fences, bool reg);


int msm_hw_fence_reset_client(void *client_handle, u32 reset_flags);


int msm_hw_fence_reset_client_by_id(enum hw_fence_client_id client_id, u32 reset_flags);


int msm_hw_fence_update_txq(void *client_handle, u64 handle, u64 flags, u32 error);


int msm_hw_fence_update_txq_error(void *client_handle, u64 handle, u32 error, u32 update_flags);


int msm_hw_fence_trigger_signal(void *client_handle, u32 tx_client_id, u32 rx_client_id,
	u32 signal_id);


int msm_hw_fence_register_error_cb(void *client_handle, msm_hw_fence_error_cb_t cb, void *data);


int msm_hw_fence_deregister_error_cb(void *client_handle);

#else
static inline void *msm_hw_fence_register(enum hw_fence_client_id client_id,
	struct msm_hw_fence_mem_addr *mem_descriptor)
{
	return NULL;
}

static inline int msm_hw_fence_deregister(void *client_handle)
{
	return -EINVAL;
}

static inline int msm_hw_fence_create(void *client_handle,
	struct msm_hw_fence_create_params *params)
{
	return -EINVAL;
}

static inline int msm_hw_fence_destroy(void *client_handle, struct dma_fence *fence)
{
	return -EINVAL;
}

static inline int msm_hw_fence_destroy_with_handle(void *client_handle, u64 handle)
{
	return -EINVAL;
}

static inline int msm_hw_fence_wait_update_v2(void *client_handle,
	struct dma_fence **fences, u64 *handles, u64 *client_data_list, u32 num_fences, bool reg)
{
	return -EINVAL;
}

static inline int msm_hw_fence_wait_update(void *client_handle,
	struct dma_fence **fences, u32 num_fences, bool reg)
{
	return -EINVAL;
}

static inline int msm_hw_fence_reset_client(void *client_handle, u32 reset_flags)
{
	return -EINVAL;
}

static inline int msm_hw_fence_reset_client_by_id(enum hw_fence_client_id client_id,
	u32 reset_flags)
{
	return -EINVAL;
}

static inline int msm_hw_fence_update_txq(void *client_handle, u64 handle, u64 flags, u32 error)
{
	return -EINVAL;
}

static inline int msm_hw_fence_update_txq_error(void *client_handle, u64 handle, u32 error,
	u32 update_flags)
{
	return -EINVAL;
}

static inline int msm_hw_fence_trigger_signal(void *client_handle, u32 tx_client_id,
	u32 rx_client_id, u32 signal_id)
{
	return -EINVAL;
}

static inline int msm_hw_fence_register_error_cb(void *client_handle, msm_hw_fence_error_cb_t cb,
	void *data)
{
	return -EINVAL;
}

static inline int msm_hw_fence_deregister_error_cb(void *client_handle)
{
	return -EINVAL;
}
#endif

#if IS_ENABLED(CONFIG_DEBUG_FS) && IS_ENABLED(CONFIG_QTI_HW_FENCE)

int msm_hw_fence_dump_debug_data(void *client_handle, u32 dump_flags, u32 dump_clients_mask);


int msm_hw_fence_dump_fence(void *client_handle, struct dma_fence *fence);

#else
static inline int msm_hw_fence_dump_debug_data(void *client_handle, u32 dump_flags,
	u32 dump_clients_mask)
{
	return -EINVAL;
}

static inline int msm_hw_fence_dump_fence(void *client_handle, struct dma_fence *fence)
{
	return -EINVAL;
}
#endif

#endif
