/*
 * Copyright (c) 2022-2023, Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Intel SoC FPGA platform specific functions used by ARM SiP Services for
 * supporting EL3 communication from zephyr.
 */

#include <string.h>
#include <zephyr/drivers/sip_svc/sip_svc_agilex_mailbox.h>
#include <zephyr/drivers/sip_svc/sip_svc_agilex_smc.h>
#include <zephyr/drivers/sip_svc/sip_svc_driver.h>
#include <zephyr/syscall_handler.h>

#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(intel_agilex_socfpga_sip_smc, CONFIG_ARM_SIP_SVC_DRIVER_LOG_LEVEL);

#define DT_DRV_COMPAT intel_agilex_socfpga_sip_smc

#define DT_SIP_SMC DT_COMPAT_GET_ANY_STATUS_OKAY(DT_DRV_COMPAT)

static bool intel_sip_smc_plat_func_id_valid(const struct device *dev, uint32_t command,
					     uint32_t func_id)
{
	ARG_UNUSED(dev);
	bool valid = false;

	if (command > SIP_SVC_PROTO_CMD_MAX) {
		return false;
	}

	if (command == SIP_SVC_PROTO_CMD_SYNC) {
		/* Synchronous SMC Function IDs */
		switch (func_id) {
		case SMC_FUNC_ID_GET_SVC_VERSION:
		case SMC_FUNC_ID_REG_READ:
		case SMC_FUNC_ID_REG_WRITE:
		case SMC_FUNC_ID_REG_UPDATE:
		case SMC_FUNC_ID_SET_HPS_BRIDGES:
			valid = true;
			break;
		default:
			valid = false;
			break;
		}
	} else if (command == SIP_SVC_PROTO_CMD_ASYNC) {
		/* Asynchronous SMC Function IDs */
		switch (func_id) {
		case SMC_FUNC_ID_MAILBOX_SEND_COMMAND:
		case SMC_FUNC_ID_MAILBOX_POLL_RESPONSE:
			valid = true;
			break;
		default:
			valid = false;
			break;
		}
	}

	return valid;
}

static uint32_t intel_sip_smc_plat_format_trans_id(const struct device *dev, uint32_t client_idx,
						   uint32_t trans_idx)
{
	ARG_UNUSED(dev);

	/*combine the transaction id and client id to get the job id*/
	return (((client_idx & 0xF) << 4) | (trans_idx & 0xF));
}

static uint32_t intel_sip_smc_plat_get_trans_idx(const struct device *dev, uint32_t trans_id)
{
	ARG_UNUSED(dev);

	return (trans_id & 0xF);
}

static void intel_sip_smc_plat_update_trans_id(const struct device *dev,
					       struct sip_svc_request *request, uint32_t trans_id)
{
	ARG_UNUSED(dev);

	uint32_t *data;

	if (request == NULL) {
		LOG_ERR("request is empty");
		return;
	}

	/* Assign the trans id into intel smc header a1 */
	SMC_PLAT_PROTO_HEADER_SET_TRANS_ID(request->a1, trans_id);

	/* Assign the trans id into mailbox header */
	if ((void *)request->a2 != NULL) {
		data = (uint32_t *)request->a2;
		SIP_SVC_MB_HEADER_SET_TRANS_ID(data[0], trans_id);
	}
}

static void intel_sip_smc_plat_free_async_memory(const struct device *dev,
						 struct sip_svc_request *request)
{
	ARG_UNUSED(dev);

	/* Free mailbox command data dynamic memory space,
	 * this function will be called after sip_svc service
	 * process the async request.
	 */
	if (request->a2) {
		k_free((void *)request->a2);
	}
}

static int intel_sip_smc_plat_async_res_req(const struct device *dev, unsigned long *a0,
					    unsigned long *a1, unsigned long *a2, unsigned long *a3,
					    unsigned long *a4, unsigned long *a5, unsigned long *a6,
					    unsigned long *a7, char *buf, size_t size)
{
	ARG_UNUSED(dev);

	/* Fill in SMC parameter to read mailbox response */
	*a0 = SMC_FUNC_ID_MAILBOX_POLL_RESPONSE;
	*a1 = 0;
	*a2 = (unsigned long)buf;
	*a3 = size;

	return 0;
}

static int intel_sip_smc_plat_async_res_res(const struct device *dev, struct arm_smccc_res *res,
					    char *buf, size_t *size, uint32_t *trans_id)
{
	ARG_UNUSED(dev);
	uint32_t *resp = (uint32_t *)buf;

	__ASSERT((res && buf && size && trans_id), "invalid parameters\n");

	if (((long)res->a0) <= SMC_STATUS_OKAY) {
		/* Extract transaction id from mailbox response header */
		*trans_id = SIP_SVC_MB_HEADER_GET_TRANS_ID(resp[0]);
		/* The final length should include both header and body */
		*size = (SIP_SVC_MB_HEADER_GET_LENGTH(resp[0]) + 1) * 4;
	} else {
		LOG_INF("There is no valid polling response %ld", (long)res->a0);
		return -EINPROGRESS;
	}

	LOG_INF("Got a valid polling response");
	return 0;
}

static uint32_t intel_sip_smc_plat_get_error_code(const struct device *dev,
						  struct arm_smccc_res *res)
{
	ARG_UNUSED(dev);

	if (res != NULL) {
		return res->a0;
	} else {
		return SIP_SVC_ID_INVALID;
	}
}

static void intel_sip_secure_monitor_call(const struct device *dev, unsigned long function_id,
					  unsigned long arg0, unsigned long arg1,
					  unsigned long arg2, unsigned long arg3,
					  unsigned long arg4, unsigned long arg5,
					  unsigned long arg6, struct arm_smccc_res *res)
{
	__ASSERT_NO_MSG(dev != NULL);
	__ASSERT_NO_MSG(res != NULL);

	LOG_INF("Before %s call", DT_PROP(DT_SIP_SMC, method));
	LOG_DBG("\tfunction_id       %08lx", function_id);
	LOG_DBG("\targ0              %08lx", arg0);
	LOG_DBG("\targ1              %08lx", arg1);
	LOG_DBG("\targ2              %08lx", arg2);
	LOG_DBG("\targ3              %08lx", arg3);
	LOG_DBG("\targ4              %08lx", arg4);
	LOG_DBG("\targ5              %08lx", arg5);
	LOG_DBG("\targ6              %08lx", arg6);

	arm_smccc_smc(function_id, arg0, arg1, arg2, arg3, arg4, arg5, arg6, res);

	LOG_INF("After %s call", DT_PROP(DT_SIP_SMC, method));
	LOG_DBG("\tres->a0           %08lx", res->a0);
	LOG_DBG("\tres->a1           %08lx", res->a1);
	LOG_DBG("\tres->a2           %08lx", res->a2);
	LOG_DBG("\tres->a3           %08lx", res->a3);
	LOG_DBG("\tres->a4           %08lx", res->a4);
	LOG_DBG("\tres->a5           %08lx", res->a5);
	LOG_DBG("\tres->a6           %08lx", res->a6);
	LOG_DBG("\tres->a7           %08lx", res->a7);
}

static int arm_sip_smc_init(const struct device *dev)
{
	ARG_UNUSED(dev);

	LOG_INF("Supervisory call %s registered successfully", DT_PROP(DT_SIP_SMC, method));

	return 0;
}

static const struct svc_driver_api api = {
	.sip_supervisory_call = intel_sip_secure_monitor_call,
	.sip_svc_plat_get_trans_idx = intel_sip_smc_plat_get_trans_idx,
	.sip_svc_plat_format_trans_id = intel_sip_smc_plat_format_trans_id,
	.sip_svc_plat_func_id_valid = intel_sip_smc_plat_func_id_valid,
	.sip_svc_plat_update_trans_id = intel_sip_smc_plat_update_trans_id,
	.sip_svc_plat_get_error_code = intel_sip_smc_plat_get_error_code,
	.sip_svc_plat_async_res_req = intel_sip_smc_plat_async_res_req,
	.sip_svc_plat_async_res_res = intel_sip_smc_plat_async_res_res,
	.sip_svc_plat_free_async_memory = intel_sip_smc_plat_free_async_memory};

BUILD_ASSERT((DT_PROP(DT_SIP_SMC, zephyr_num_clients) != 0), "num-clients should not be zero");
BUILD_ASSERT((CONFIG_ARM_SIP_SVC_EL3_MAX_ALLOWED_TRANSACTIONS > 0),
	     "CONFIG_ARM_SIP_SVC_EL3_MAX_ALLOWED_TRANSACTIONS should be greater than 0");

#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)

SIP_SVC_CONTROLLER_DEFINE(0, DT_PROP(DT_SIP_SMC, method), DEVICE_DT_GET(DT_SIP_SMC),
			  DT_PROP(DT_SIP_SMC, zephyr_num_clients),
			  CONFIG_ARM_SIP_SVC_EL3_MAX_ALLOWED_TRANSACTIONS,
			  CONFIG_ARM_SIP_SVC_EL3_MAILBOX_RESPONSE_SIZE);

DEVICE_DT_DEFINE(DT_SIP_SMC, arm_sip_smc_init, NULL, NULL, NULL, POST_KERNEL,
		 CONFIG_ARM_SIP_SVC_DRIVER_INIT_PRIORITY, &api);

#endif
