/*
 * Copyright (c) 2024, Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT altr_socfpga_agilex_bridge

#include <errno.h>
#include <zephyr/device.h>
#include <zephyr/sip_svc/sip_svc.h>
#include <zephyr/drivers/sip_svc/sip_svc_agilex_smc.h>
#include <zephyr/drivers/fpga.h>
#include <zephyr/logging/log.h>
#include "fpga_altera_agilex_bridge.h"

LOG_MODULE_REGISTER(fpga_altera);

struct fpga_bridge_dev_data {
	/* SiP SVC controller */
	struct sip_svc_controller *mailbox_smc_dev;
	/* SiP SVC client token id */
	uint32_t mailbox_client_token;
};

#define MAX_TIMEOUT_MSECS (1 * 1000UL)

/**
 * @brief Open SiP SVC client session
 *
 * @return 0 on success or negative value on failure
 */
static int32_t svc_client_open(const struct device *dev)
{
	if (!dev) {
		LOG_ERR("No such device found");
		return -ENODEV;
	}

	struct fpga_bridge_dev_data *const data = (struct fpga_bridge_dev_data *const)(dev->data);

	if ((!data->mailbox_smc_dev) || (data->mailbox_client_token == 0)) {
		LOG_ERR("Mailbox client is not registered");
		return -ENODEV;
	}

	if (sip_svc_open(data->mailbox_smc_dev, data->mailbox_client_token,
			 K_MSEC(MAX_TIMEOUT_MSECS))) {
		LOG_ERR("Mailbox client open fail");
		return -ENODEV;
	}

	return 0;
}

/**
 * @brief Close the svc client
 *
 * @return 0 on success or negative value on fail
 */
static int32_t svc_client_close(const struct device *dev)
{
	int32_t err;
	uint32_t cmd_size = sizeof(uint32_t);
	struct sip_svc_request request;

	if (!dev) {
		LOG_ERR("No such device found");
		return -ENODEV;
	}

	struct fpga_bridge_dev_data *const data = (struct fpga_bridge_dev_data *const)(dev->data);

	uint32_t *cmd_addr = (uint32_t *)k_malloc(cmd_size);

	if (!cmd_addr) {
		return -ENOMEM;
	}

	/* Fill the SiP SVC buffer with CANCEL request */
	*cmd_addr = MAILBOX_CANCEL_COMMAND;

	request.header = SIP_SVC_PROTO_HEADER(SIP_SVC_PROTO_CMD_ASYNC, 0);
	request.a0 = SMC_FUNC_ID_MAILBOX_SEND_COMMAND;
	request.a1 = 0;
	request.a2 = (uint64_t)cmd_addr;
	request.a3 = (uint64_t)cmd_size;
	request.a4 = 0;
	request.a5 = 0;
	request.a6 = 0;
	request.a7 = 0;
	request.resp_data_addr = (uint64_t)NULL;
	request.resp_data_size = 0;
	request.priv_data = NULL;

	err = sip_svc_close(data->mailbox_smc_dev, data->mailbox_client_token, &request);
	if (err) {
		k_free(cmd_addr);
		LOG_ERR("Mailbox client close fail (%d)", err);
	}

	return err;
}

/**
 * @brief Call back function which we receive when we send the data
 * based on the current stage it will collect the data
 *
 * @param[in] c_token Token id for our svc services
 * @param[in] response Buffer will contain the response
 *
 * @return void
 */
static void smc_callback(uint32_t c_token, struct sip_svc_response *response)
{
	if (response == NULL) {
		return;
	}

	uint32_t *resp_data = NULL;
	uint32_t resp_len = 0;
	uint32_t mbox_idx = 0;

	struct sip_svc_private_data *private_data =
		(struct sip_svc_private_data *)response->priv_data;
	union mailbox_response_header response_header;

	LOG_DBG("SiP SVC callback");

	LOG_DBG("\tresponse data below:");
	LOG_DBG("\theader=%08x", response->header);
	LOG_DBG("\ta0=%016lx", response->a0);
	LOG_DBG("\ta1=%016lx", response->a1);
	LOG_DBG("\ta2=%016lx", response->a2);
	LOG_DBG("\ta3=%016lx", response->a3);

	private_data->response.header = response->header;
	private_data->response.a0 = response->a0;
	private_data->response.a1 = response->a1;
	private_data->response.a2 = response->a2;
	private_data->response.a3 = response->a3;
	private_data->response.resp_data_size = response->resp_data_size;

	/* Condition to check only for the mailbox command not for the non-mailbox command */
	if (response->resp_data_size) {
		resp_data = (uint32_t *)response->resp_data_addr;
		resp_len = response->resp_data_size / 4;
		private_data->mbox_response_len = resp_len;
		if (resp_data && resp_len) {
			response_header = (union mailbox_response_header)resp_data[0];
			private_data->mbox_response_data =
				(uint32_t *)k_malloc(sizeof(uint32_t) * resp_len);
			for (mbox_idx = 0; mbox_idx < resp_len; mbox_idx++) {
				LOG_DBG("\t\t[%4d] %08x", mbox_idx, resp_data[mbox_idx]);
				private_data->mbox_response_data[mbox_idx] = resp_data[mbox_idx];
			}
		} else {
			LOG_ERR("\t\tInvalid addr (%p) or len (%d)", resp_data, resp_len);
		}
	}
	/* Condition for non-mailbox command*/
	else {
		LOG_DBG("Response Data size is zero !!");
	}

	/* Client only responsible to free the response data memory space,
	 * the command data memory space had been freed by SiP SVC service.
	 */
	if (response->resp_data_addr) {
		LOG_DBG("\tFree response memory %p", (char *)response->resp_data_addr);
		k_free((char *)response->resp_data_addr);
	}

	k_sem_give(&(private_data->smc_sem));
}

/**
 * @brief Send the data to SiP SVC service layer
 *	based on the command type further data will be send to SDM using mailbox
 *
 * @param[in] cmd_type Command type (Mailbox or Non-Mailbox)
 * @param[in] function_identifier Function identifier for each command type
 * @param[in] cmd_request
 * @param[in] private_data
 *
 * @return 0 on success or negative value on fail
 */
static int32_t smc_send(const struct device *dev, uint32_t cmd_type, uint64_t function_identifier,
			uint32_t *cmd_request, struct sip_svc_private_data *private_data)
{
	int32_t trans_id = 0;
	uint32_t *cmd_addr = NULL;
	uint32_t *resp_addr = NULL;
	struct sip_svc_request request;

	if (!dev) {
		LOG_ERR("No such device found");
		return -ENODEV;
	}

	struct fpga_bridge_dev_data *const data = (struct fpga_bridge_dev_data *const)(dev->data);

	if (!data->mailbox_smc_dev) {
		LOG_ERR("Mailbox client is not registered");
		return -ENODEV;
	}

	if (cmd_type == SIP_SVC_PROTO_CMD_ASYNC) {
		cmd_addr = (uint32_t *)k_malloc(FPGA_MB_CMD_ADDR_MEM_SIZE);
		if (!cmd_addr) {
			LOG_ERR("Failed to allocate command memory");
			return -ENOMEM;
		}
		cmd_addr[MBOX_CMD_HEADER_INDEX] =
			MBOX_REQUEST_HEADER(cmd_request[SMC_REQUEST_A2_INDEX], 0, 0);
		resp_addr = (uint32_t *)k_malloc(FPGA_MB_RESPONSE_MEM_SIZE);
		if (!resp_addr) {
			k_free(cmd_addr);
			return -ENOMEM;
		}

		request.a2 = (uint64_t)cmd_addr;
		request.a3 = sizeof(uint32_t);
		request.resp_data_addr = (uint64_t)resp_addr;
		request.resp_data_size = FPGA_MB_RESPONSE_MEM_SIZE;

#if defined(CONFIG_LOG)
		for (int32_t mbox_idx = 0; mbox_idx < request.a3 / 4; mbox_idx++) {
			LOG_DBG("\t [%d ] %08x", mbox_idx, cmd_addr[mbox_idx]);
		}
#endif

	} else {
		request.a2 = cmd_request[SMC_REQUEST_A2_INDEX];
		request.a3 = cmd_request[SMC_REQUEST_A3_INDEX];
		request.resp_data_addr = 0;
		request.resp_data_size = 0;
	}

	/* Fill SiP SVC request buffer */
	request.header = SIP_SVC_PROTO_HEADER(cmd_type, 0);
	request.a0 = function_identifier;
	request.a1 = 0;
	request.a4 = 0;
	request.a5 = 0;
	request.a6 = 0;
	request.a7 = 0;
	request.priv_data = (void *)private_data;

	/* Send SiP SVC request */
	trans_id = sip_svc_send(data->mailbox_smc_dev, data->mailbox_client_token, &request,
				smc_callback);

	if (trans_id == SIP_SVC_ID_INVALID) {
		LOG_ERR("SiP SVC send request fail");
		return -EBUSY;
	}

	return 0;
}

/* Validate the Reconfig status response */
static int32_t fpga_reconfig_status_validate(struct fpga_config_status *reconfig_status_resp)
{
	uint32_t ret = 0;

	/* Check for any error */
	ret = reconfig_status_resp->state;
	if (ret == MBOX_CFGSTAT_VAB_BS_PREAUTH) {
		return MBOX_CONFIG_STATUS_STATE_CONFIG;
	}

	if (ret && ret != MBOX_CONFIG_STATUS_STATE_CONFIG)
		return ret;

	/* Make sure nStatus is not 0 */
	ret = reconfig_status_resp->pin_status.pin_status;
	if (!(ret & RECONFIG_PIN_STATUS_NSTATUS))
		return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;

	ret = reconfig_status_resp->soft_function_status;
	if ((ret & RECONFIG_SOFTFUNC_STATUS_CONF_DONE) &&
		(ret & RECONFIG_SOFTFUNC_STATUS_INIT_DONE) && !reconfig_status_resp->state)
		return 0; /* Configuration success */

	return MBOX_CONFIG_STATUS_STATE_CONFIG;
}

/* Will send the SMC command to check the status of the FPGA */
static int32_t fpga_config_ready_check(const struct device *dev)
{
	uint32_t smc_cmd[2] = {0};
	int32_t ret = 0;
	struct sip_svc_private_data priv_data;

	/* Initialize the semaphore */
	k_sem_init(&(priv_data.smc_sem), 0, 1);

	smc_cmd[SMC_REQUEST_A2_INDEX] = FPGA_CONFIG_STATUS;
	smc_cmd[SMC_REQUEST_A3_INDEX] = 0;

	/* Sending the FPGA config status mailbox command */
	ret = smc_send(dev, SIP_SVC_PROTO_CMD_ASYNC, SMC_FUNC_ID_MAILBOX_SEND_COMMAND, smc_cmd,
				&priv_data);
	if (ret) {
		LOG_ERR("Failed to Send the Mailbox Command !!");
		return -ECANCELED;
	}

	k_sem_take(&(priv_data.smc_sem), K_FOREVER);

	/* Verify the SMC response */
	if (!priv_data.response.resp_data_size &&
		priv_data.mbox_response_len != FPGA_CONFIG_STATUS_RESPONSE_LEN) {
		return -EINVAL;
	}

	/* Verify the FPGA config status response */
	ret = fpga_reconfig_status_validate(
		(struct fpga_config_status *)priv_data.mbox_response_data);

	k_free(priv_data.mbox_response_data);

	return ret;
}

static int32_t socfpga_bridges_reset(const struct device *dev, uint32_t enable)
{
	uint32_t smc_cmd[2] = {0};
	int ret = 0;
	struct sip_svc_private_data priv_data;

	if (!dev) {
		LOG_ERR("No such device found");
		return -ENODEV;
	}

	/* Initialize the semaphore */
	k_sem_init(&(priv_data.smc_sem), 0, 1);

	smc_cmd[SMC_REQUEST_A2_INDEX] = FIELD_GET(BIT(0), enable);

	smc_cmd[SMC_REQUEST_A2_INDEX] |= BIT(1);
	smc_cmd[SMC_REQUEST_A3_INDEX] = BRIDGE_MASK;

	ret = smc_send(dev, SIP_SVC_PROTO_CMD_SYNC, SMC_FUNC_ID_SET_HPS_BRIDGES, smc_cmd,
				&priv_data);
	if (ret) {
		LOG_ERR("Failed to send the smc Command !!");
		return ret;
	}

	/* Wait for the SiP SVC callback */
	k_sem_take(&(priv_data.smc_sem), K_FOREVER);

	/* Check error code */
	if (priv_data.response.a0) {
		ret = -ENOMSG;
	}

	return ret;
}

static int altera_fpga_on(const struct device *dev)
{
	int32_t ret = 0;

	if (!dev) {
		LOG_ERR("No such device found");
		return -ENODEV;
	}

	/* Opening SIP SVC session */
	ret = svc_client_open(dev);
	if (ret) {
		LOG_ERR("Client open Failed!");
		return ret;
	}

	/* Check FPGA status before bridge enable/disable */
	ret = fpga_config_ready_check(dev);
	if (ret) {
		LOG_ERR("FPGA not ready. Bridge reset aborted!");
		svc_client_close(dev);
		return -EIO;
	}

	/* Bridge reset */
	ret = socfpga_bridges_reset(dev, 0x01);
	if (ret) {
		LOG_ERR("Bridge reset failed");
	}

	/* Ignoring the return value to return bridge reset status */
	if (svc_client_close(dev)) {
		LOG_ERR("Unregistering & Closing failed");
	}

	return ret;
}

static int altera_fpga_off(const struct device *dev)
{
	int32_t ret = 0;

	if (!dev) {
		LOG_ERR("No such device found");
		return -ENODEV;
	}

	/* Opening SIP SVC session */
	ret = svc_client_open(dev);
	if (ret) {
		LOG_ERR("Client open Failed!");
		return ret;
	}

	/* Check FPGA status before bridge enable/disable */
	ret = fpga_config_ready_check(dev);
	if (ret) {
		LOG_ERR("FPGA not ready. Bridge reset aborted!");
		svc_client_close(dev);
		return -EIO;
	}

	/* Bridge reset */
	ret = socfpga_bridges_reset(dev, 0x00);
	if (ret) {
		LOG_ERR("Bridge reset failed");
	}

	/* Ignoring the return value to return bridge reset status */
	if (svc_client_close(dev)) {
		LOG_ERR("Unregistering & Closing failed");
	}

	return ret;
}

static int altera_fpga_init(const struct device *dev)
{
	if (!dev) {
		LOG_ERR("No such device found");
		return -ENODEV;
	}

	struct fpga_bridge_dev_data *const data = (struct fpga_bridge_dev_data *const)(dev->data);

	data->mailbox_smc_dev = sip_svc_get_controller("smc");
	if (!data->mailbox_smc_dev) {
		LOG_ERR("Arm SiP service not found");
		return -ENODEV;
	}

	data->mailbox_client_token = sip_svc_register(data->mailbox_smc_dev, NULL);
	if (data->mailbox_client_token == SIP_SVC_ID_INVALID) {
		data->mailbox_smc_dev = NULL;
		LOG_ERR("Mailbox client register fail");
		return -EINVAL;
	}

	return 0;
}

static const struct fpga_driver_api altera_fpga_api = {
	.on = altera_fpga_on,
	.off = altera_fpga_off,
};

#define CREATE_ALTERA_FPGA_BRIDGE_DEV(inst)						\
	static struct fpga_bridge_dev_data fpga_bridge_data_##inst;		\
	DEVICE_DT_INST_DEFINE(inst,						\
			altera_fpga_init,					\
			NULL, &fpga_bridge_data_##inst,				\
			NULL, POST_KERNEL,			\
			CONFIG_FPGA_INIT_PRIORITY,				\
			&altera_fpga_api);					\

DT_INST_FOREACH_STATUS_OKAY(CREATE_ALTERA_FPGA_BRIDGE_DEV);
