/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2019 MediaTek Inc.
 */
#ifndef __MDLA_CMD_DATA_V2_0_H__
#define __MDLA_CMD_DATA_V2_0_H__

#include <linux/types.h>
#include <linux/list.h>

#include <utilities/mdla_util.h>

struct command_entry;

struct mdla_wait_cmd {
	uint32_t id;           /* [in] command id */
	int32_t  result;       /* [out] success(0), timeout(1) */
	uint64_t queue_time;   /* [out] time queued in driver (ns) */
	uint64_t busy_time;    /* [out] mdla execution time (ns) */
	uint32_t bandwidth;    /* [out] mdla bandwidth */
};

struct mdla_run_cmd {
	uint32_t offset_code_buf;
	uint32_t reserved;
	uint32_t size;
	uint32_t mva;
	uint32_t offset;        /* [in] command byte offset in buf */
	uint32_t count;         /* [in] # of commands */
	uint32_t id;            /* [out] command id */
};

struct mdla_run_cmd_sync {
	struct mdla_run_cmd req;
	struct mdla_wait_cmd res;
	uint32_t mdla_id;
};

struct mdla_wait_entry {
	uint32_t async_id;
	struct list_head list;
	struct mdla_wait_cmd wt;
};

struct mdla_ut_run_cmd {
	uint64_t kva; // Virtual Address for Kernel
	uint32_t mva; // Physical Address for Device
	uint32_t count;
	uint32_t id;
	uint32_t mva_h; // Physical Address for Device
};

struct mdla_ut_run_cmd_sync {
	struct mdla_ut_run_cmd req;
	struct mdla_wait_cmd res;
};

#define MAX_SVP_BUF_PER_CMD 0x10
struct run_cmd_buf {
	uint32_t size;
	uint32_t iova;
	uint32_t buf_type;
	uint32_t buf_source;
};

struct mdla_run_cmd_svp {
	uint32_t secure;
	uint32_t mdla_id;
	uint32_t pipe_id;
	struct run_cmd_buf buf[MAX_SVP_BUF_PER_CMD];
	uint32_t buf_count;     /* [in] # of svp buffers */
	uint32_t cmd_count;     /* [in] # of commands */
	uint32_t model;
	uint32_t timeout;       /* [in] command timeout (us) */
	uint8_t priority;       /* [in] dvfs priority */
	uint8_t boost_value;    /* [in] dvfs boost value */
};

struct mdla_cmd_info {
	void *cmd_user;
};

struct mdla_run_cmd_sync_svp {
	struct mdla_run_cmd_svp req;
	struct mdla_wait_cmd res;
	struct mdla_cmd_info cmd_info;
};

struct command_batch {
	struct list_head node;
	u32 index;
	u32 size;
};

struct sched_smp_ce {
	spinlock_t lock;
	u64 deadline;
};

struct mdla_scheduler {
	struct list_head ce_list[PRIORITY_LEVEL];
	struct command_entry *ce[PRIORITY_LEVEL];
	struct command_entry *pro_ce;

	spinlock_t lock;
	struct mutex mtx;

	void (*sw_reset)(u32 core_id);
	void (*enqueue_ce)(u32 core_id, struct command_entry *ce, u32 resume);
	struct command_entry* (*dequeue_ce)(u32 core_id);
	void (*issue_ce)(u32 core_id);
	void (*issue_dual_lowce)(u32 core_id, uint64_t dual_cmd_id);
	int (*process_ce)(u32 core_id);
	void (*preempt_ce)(u32 core_id, struct command_entry *high_ce);
	void (*stop_ce)(u32 core_id, struct command_entry *ce);
	void (*complete_ce)(u32 core_id);
	u64 (*get_smp_deadline)(int priority);
	void (*set_smp_deadline)(int priority, u64 deadline);
};

static inline bool can_preempted(struct command_entry *old_ce,
			    struct command_entry *new_ce)
{
	return ((old_ce->priority < new_ce->priority) &&
		!(old_ce->secure && !new_ce->secure));
}

#define CMD_NOT_INIT UINT_MAX
#define MAX_BATCH_NUM INT_MAX

#endif /* __MDLA_CMD_DATA_V2_0_H__ */

