/*
 *  Copyright (C) 2021-2022, Xilinx Inc
 *
 *  This file is dual licensed.  It may be redistributed and/or modified
 *  under the terms of the Apache 2.0 License OR version 2 of the GNU
 *  General Public License.
 *
 *  Apache License Verbiage
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  GPL license Verbiage:
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation; either version 2 of the
 *  License, or (at your option) any later version.  This program is
 *  distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
 *  License for more details.  You should have received a copy of the
 *  GNU General Public License along with this program; if not, write
 *  to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 *  Boston, MA 02111-1307 USA
 *
 */

#ifndef XGQ_CMD_VMR_H
#define XGQ_CMD_VMR_H

/* !!! This header file is for internal project use only and it is subject to removal without notice !!! */
#include "xgq_cmd_common.h"

/* This header file defines struct of mgmt command type opcode */

/* The Clock IP use index 0 for data, 1 for kernel, 2 for sys, 3 for sys1 */ 
#define XGQ_CLOCK_WIZ_MAX_RES           4

/* VMR Identify Command Version Major and Minor Numbers */
#define VMR_IDENTIFY_CMD_MAJOR		1
#define VMR_IDENTIFY_CMD_MINOR		0


/**
 * clock scaling request types
 */
enum xgq_cmd_clk_scaling_app_id {
	XGQ_CMD_CLK_THROTTLING_AID_READ		= 0x1,
	XGQ_CMD_CLK_THROTTLING_AID_CONFIGURE	= 0x2,
};

/**
 * sensor data request types
 */
enum xgq_cmd_sensor_application_id {
	XGQ_CMD_SENSOR_AID_GET_SIZE		= 0x1,
	XGQ_CMD_SENSOR_AID_GET_SDR		= 0x2,
	XGQ_CMD_SENSOR_AID_GET_SINGLE_SDR	= 0x3,
	XGQ_CMD_SENSOR_AID_GET_ALL_SDR		= 0x4,
};

/**
 * sensor data request types
 */
enum xgq_cmd_sensor_page_id {
	XGQ_CMD_SENSOR_SID_GET_SIZE	= 0x0,
	XGQ_CMD_SENSOR_SID_BDINFO	= 0x1,
	XGQ_CMD_SENSOR_SID_TEMP		= 0x2,
	XGQ_CMD_SENSOR_SID_VOLTAGE	= 0x3,
	XGQ_CMD_SENSOR_SID_CURRENT	= 0x4,
	XGQ_CMD_SENSOR_SID_POWER	= 0x5,
	XGQ_CMD_SENSOR_SID_QSFP		= 0x6,
	XGQ_CMD_SENSOR_SID_ALL		= 0x7,
	XGQ_CMD_SENSOR_SID_MAX		= 0x8,
};

/**
 * clock operation request types
 */
enum xgq_cmd_clock_req_type {
	XGQ_CMD_CLOCK_WIZARD 		= 0x0,
	XGQ_CMD_CLOCK_COUNTER		= 0x1,
	XGQ_CMD_CLOCK_SCALE		= 0x2,
};

/**
 * clock scaling request types
 */
enum xgq_cmd_clock_scaling_req_type {
	XGQ_CMD_CLK_SCALING_GET_STATUS	= 0x1,
	XGQ_CMD_CLK_SCALING_SET_OVERRIDE= 0x2,
};

/**
 * multi-boot operation request types
 */
enum xgq_cmd_vmr_control_type {
	XGQ_CMD_VMR_QUERY	= 0x0,
	XGQ_CMD_BOOT_DEFAULT	= 0x1,
	XGQ_CMD_BOOT_BACKUP	= 0x2,
	XGQ_CMD_PROGRAM_SC	= 0x3,
	XGQ_CMD_VMR_DEBUG	= 0x4,
	XGQ_CMD_VMR_EEMI_SRST	= 0x5, /* Request VMR to perform SRST using EEMI based PMC API request */
};

/**
 * log page type
 */
enum xgq_cmd_log_page_type {
	XGQ_CMD_LOG_AF_CHECK		 = 0x0,
	XGQ_CMD_LOG_FW			 = 0x1,
	XGQ_CMD_LOG_INFO		 = 0x2,
	XGQ_CMD_LOG_AF_CLEAR		 = 0x3,
	XGQ_CMD_LOG_ENDPOINT		 = 0x4,
	XGQ_CMD_LOG_TASK_STATS  	 = 0x5,
	XGQ_CMD_LOG_MEM_STATS		 = 0x6,
	XGQ_CMD_LOG_SYSTEM_DTB		 = 0x7,
	XGQ_CMD_LOG_PLM_LOG		 = 0x8,
	XGQ_CMD_LOG_APU_LOG		 = 0x9,
	XGQ_CMD_LOG_SHELL_INTERFACE_UUID = 0xa,
	XGQ_CMD_LOG_DEFAULT_FPT		 = 0xb,
	XGQ_CMD_LOG_BACKUP_FPT		 = 0xc,
};

/*
 * XGQ VMR SC status defines
 */
typedef enum _xgq_cmd_sc_status
{
	XGQ_CMD_SC_PENDING     = 0x0,
	XGQ_CMD_SC_UNAVAILABLE = 0x1,
	XGQ_CMD_SC_READY       = 0x2,
} xgq_cmd_sc_status;

/**
 * struct xgq_cmd_log_payload: log_page request command
 *
 * @address:	pre-allocated log data, device writes log data at this address
 * @size:	size of pre-allocated log data
 * @offset:	offset of returned device data
 * @pid:	log_page page id
 * @addr_type:	pre-allocated address type
 *
 * This payload is used for log_page and sensor data report.
 */
struct xgq_cmd_log_payload {
	uint64_t address;
	uint32_t size;
	uint32_t offset;
	uint32_t pid:16;
	uint32_t addr_type:3;
	uint32_t rsvd1:13;
	uint32_t pad;
};

/**
 * struct xgq_cmd_sensor_payload: sensor_page request command
 *
 * @address:	pre-allocated sensor data, device writes sensor data at this address
 * @size:	size of pre-allocated sensor data
 * @offset:	offset of returned device data
 * @aid: Sensor API ID which decides API in VMC.
 *          0x1 - GET_SDR_SIZE
 *          0x2 - GET_SDR
 *          0x3 - GET_SINGLE_SENSOR_DATA
 *          0x4 - GET_ALL_SENSOR_DATA
 * @sid: sensor request id, it is same as repo_id
 * @addr_type: pre-allocated address type
 * @sensor_id: sensor id values used to get single instantaneous sensor data
 *
 * This payload is used for sensor data report.
 */
struct xgq_cmd_sensor_payload {
	uint64_t address;
	uint32_t size;
	uint32_t offset;
	uint32_t aid:8;
	uint32_t sid:8;
	uint32_t addr_type:3;
	uint32_t sensor_id:8;
	uint32_t rsvd1:5;
	uint32_t pad;
};

/**
 * struct xgq_cmd_clock_payload: clock request command
 *
 * @ocl_region:		clock region
 * @ocl_req_type:	clock request type
 * @ocl_req_id:		clock resource index 0,1,2,3
 * @ocl_req_num:	max effective index 1 -> 4
 * @ocl_req_freq:	request freq number array
 */
struct xgq_cmd_clock_payload {
	uint32_t ocl_region;
	uint32_t ocl_req_type:8;
	uint32_t ocl_req_id:2;
	uint32_t ocl_req_num:4;
	uint32_t rsvd1:18;
	uint32_t ocl_req_freq[XGQ_CLOCK_WIZ_MAX_RES];
};

/**
 * struct xgq_cmd_data_payload: data request payload command
 *
 * @address:		data that needs to be transferred
 * @size:		data size
 * @addr_type:		address_type
 */
struct xgq_cmd_data_payload {
	uint64_t address;
	uint32_t size;
	uint32_t remain_size;
	uint32_t addr_type:4;
	uint32_t flash_type:4;
	uint32_t rsvd1:24;
	uint32_t pad1;
	uint64_t priv;
};

enum xgq_cmd_flash_type {
	XGQ_CMD_FLASH_DEFAULT		= 0x0,
	XGQ_CMD_FLASH_NO_BACKUP		= 0x1,
	XGQ_CMD_FLASH_TO_LEGACY		= 0x2,
};

enum xgq_cmd_debug_type {
	XGQ_CMD_DBG_CLEAR		= 0x0,
	XGQ_CMD_DBG_RMGMT		= 0x1,
	XGQ_CMD_DBG_VMC			= 0x2,
};

/**
 * struct xgq_cmd_vmr_control_payload: vmr controlling ops
 *
 * @req_type:		request type
 */
struct xgq_cmd_vmr_control_payload {
	uint32_t req_type:8;
	uint32_t debug_level:3;
	uint32_t debug_type:5;
	uint32_t eemi_boot_from_backup:1;
	uint32_t rsvd:15;
};

/**
 * struct xgq_cmd_clk_scaling_payload: clock_scaling configuration request command
 *
 * @aid: Clock scaling API ID which decides API in VMC.
 *          0x1 - READ_CLOCK_THROTTLING_CONFIGURATION
 *          0x2 - SET_CLOCK_THROTTLING_CONFIGURATION
 * @scaling_en: enable or disable flag
 * @pwr_scaling_ovrd_limit: set power override value
 * @temp_scaling_ovrd_limit: set temperature override value
 * @reset: reset the clock scaling configs to defaults
 * @pwr_scaling_ovrd_en: power override enable/disable flag
 * @temp_scaling_ovrd_en: temperature override enable/disable flag
 *
 * This payload is used for clock scaling configuration report.
 */
struct xgq_cmd_clk_scaling_payload {
	uint32_t aid:3;
	uint32_t scaling_en:1;
	uint32_t pwr_scaling_ovrd_limit:16;
	uint32_t temp_scaling_ovrd_limit:8;
	uint32_t reset:1;
	uint32_t pwr_scaling_ovrd_en:1;
	uint32_t temp_scaling_ovrd_en:1;
	uint32_t rsvd1:1;
};

/**
 * struct xgq_cmd_sq: vmr xgq command
 *
 * @hdr:		vmr xgq command header
 *
 * @log_payload:	corresponding payload definition in a union
 * @clock_payload:
 * @pdi_payload:
 * @xclbin_payload:
 * @sensor_payload:
 * @vmr_control_payload:
 * @clk_scaling_payload:
 */
struct xgq_cmd_sq {
	struct xgq_cmd_sq_hdr hdr;
	union {
		struct xgq_cmd_log_payload		log_payload;
		struct xgq_cmd_clock_payload		clock_payload;
		struct xgq_cmd_data_payload		pdi_payload;
		struct xgq_cmd_data_payload		xclbin_payload;
		struct xgq_cmd_sensor_payload		sensor_payload;
		struct xgq_cmd_vmr_control_payload	vmr_control_payload;
		struct xgq_cmd_clk_scaling_payload	clk_scaling_payload;
	};
};

/**
 * struct xgq_cmd_cq_default_payload: vmr default completion payload
 *
 * @result:	result code
 */
struct xgq_cmd_cq_default_payload {
	uint32_t resvd0;
	uint32_t resvd1;
};

/**
 * struct xgq_cmd_cq_clock_payload: vmr clock completion payload 
 *
 * @ocl_freq: 	result of clock frequency value
 */
struct xgq_cmd_cq_clock_payload {
	uint32_t ocl_freq;
	uint32_t resvd;
};

/**
 * struct xgq_cmd_cq_sensor_payload: vmr sensor completion payload
 *
 * @result: 	result code
 */
struct xgq_cmd_cq_sensor_payload {
	uint32_t result;
	uint32_t resvd;
};

/**
 * struct xgq_cmd_cq_log_page_payload: vmr log page completion payload
 *
 * @count:	how many data returned in bytes
 */
struct xgq_cmd_cq_log_page_payload {
	uint32_t count;
	uint32_t resvd1;
};

/**
 * struct xgq_cmd_cq_log_page_payload: load xclbin/pdi data payload
 *
 * @count:	how many data returned in bytes
 */
struct xgq_cmd_cq_data_payload {
	uint32_t count;
	uint32_t resvd1;
};

/**
 * struct xgq_cmd_cq_clk_scaling_payload: clock scaling status payload
 *
 * @has_clk scaling: shows if the platform support clock scaling feature
 * @clk_scaling_mode: which clock scaling mode enabled currently
 * @clk_scaling_en: shows if clock scaling is enabled (1) or disabled (0)
 * @pwr_scaling_ovrd_en: power scaling override is enabled or not
 * @temp_scaling_ovrd_en: temperature scaling override is enabled or not
 * @temp_shutdown_limit: temperature shutdown limit
 * @temp_scaling_limit: temperature scaling override value set
 * @pwr_shutdown_limit: power shutdown limit
 * @pwr_scaling_limit: power scaling override value set
 */
struct xgq_cmd_cq_clk_scaling_payload {
	uint8_t has_clk_scaling:1;
	uint8_t clk_scaling_mode:2;
	uint8_t clk_scaling_en:1;
	uint8_t pwr_scaling_ovrd_en:1;
	uint8_t temp_scaling_ovrd_en:1;
	uint8_t rsvd:2;
	uint8_t temp_shutdown_limit;
	uint8_t temp_scaling_limit;
	uint16_t pwr_shutdown_limit;
	uint16_t pwr_scaling_limit;
};

/**
 * struct xgq_cmd_cq_vmr_payload: vmr device status payload
 *
 * bitfields for indicting flash partition statistics.
 * vmr device status.
 */
struct xgq_cmd_cq_vmr_payload {
	uint16_t has_fpt:1;
	uint16_t has_fpt_recovery:1;
	uint16_t boot_on_default:1;
	uint16_t boot_on_backup:1;
	uint16_t boot_on_recovery:1;
	uint16_t has_extfpt:1;
	uint16_t has_ext_xsabin:1;
	uint16_t has_ext_scfw:1;
	uint16_t has_ext_sysdtb:1;
	uint16_t ps_is_ready:1;
	uint16_t pl_is_ready:1;
	uint16_t sc_is_ready:1;
	uint16_t resvd1:4;
	uint16_t current_multi_boot_offset;
	uint32_t debug_level:3;
	uint32_t program_progress:7;
	uint16_t resvd2:6;
	uint16_t boot_on_offset;
};

/*
 * struct xgq_cmd_cq_vmr_identify_payload: Identify Command payload
 *
 * VMR Identify Command
*/
struct xgq_cmd_cq_vmr_identify_payload {
	uint16_t ver_major;
	uint16_t ver_minor;
	uint32_t resvd;
};

/*
 * struct xgq_cmd_cq: vmr completion command
 *
 * @hdr:		vmr completion command header
 *
 * @default_payload: 	payload definitions in a union
 * @clock_payload:
 * @sensor_payload:
 * @multiboot_payload:
 * @log_payload:
 * @xclbin_payload:
 * @clk_scaling_payload:
 * @vmr_identify_payload:
 */
struct xgq_cmd_cq {
	struct xgq_cmd_cq_hdr hdr;
	union {
		struct xgq_cmd_cq_default_payload	cq_default_payload;
		struct xgq_cmd_cq_clock_payload		cq_clock_payload;
		struct xgq_cmd_cq_sensor_payload	cq_sensor_payload;
		struct xgq_cmd_cq_vmr_payload		cq_vmr_payload;
		struct xgq_cmd_cq_log_page_payload	cq_log_payload;
		struct xgq_cmd_cq_data_payload		cq_xclbin_payload;
		struct xgq_cmd_cq_clk_scaling_payload	cq_clk_scaling_payload;
		struct xgq_cmd_cq_vmr_identify_payload  cq_vmr_identify_payload;
	};
	uint32_t rcode;
};
XGQ_STATIC_ASSERT(sizeof(struct xgq_cmd_cq) == 16, "xgq_cmd_cq has to be 16 bytes in size");

/**
 * XGQ memory partition table, should be positioned at shared memory offset 0,
 *     and inited by VMR software on RPU device.
 *
 * We use the memory partition table for sharing info between host and RPU.
 * Including:
 *
 * @vmr_magic_no:	the magic no.
 * @ring_buffer_off:	the offset of xgq ring buffer inited by xgq server
 * @ring_buffer_len:	the length of xgq ring buffer inited by xgq server
 * TODO: only support hearbeat now
 * @vmr_status_off:	the offset of vmr device status
 * @vmr_status_len:	the length of vmr device status
 * @log_msg_index:	the current index of ring buffer log
 * @log_msg_buf_off:	the offset of dbg log 
 * @log_msg_buf_len:	the length of dbg log
 * @vmr_data_start:	the offset of data buffer started
 * @vmr_data_end: 	the offset of data buffer ended
 */
struct vmr_shared_mem {
	uint32_t	vmr_magic_no;
	uint32_t	ring_buffer_off;
	uint32_t	ring_buffer_len;
	uint32_t	vmr_status_off;
	uint32_t	vmr_status_len;
	uint32_t	log_msg_index;
	uint32_t	log_msg_buf_off;
	uint32_t	log_msg_buf_len;
	uint32_t	vmr_data_start;
	uint32_t	vmr_data_end;
};

#define VMR_MAGIC_NO	0x564D5230 /* VMR0 */

#define VMR_LOG_ENTRY_SIZE (96)
#define VMR_LOG_MAX_RECS (50)

struct vmr_log {
	char	log_buf[VMR_LOG_ENTRY_SIZE];
};

#define LOG_BUF_LEN (sizeof(struct vmr_log) * VMR_LOG_MAX_RECS);

#endif
