/*
 * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <bpmp_ipc.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <errno.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <stdbool.h>
#include <string.h>
#include <tegra_def.h>

#include "intf.h"
#include "ivc.h"

/**
 * Holds IVC channel data
 */
struct ccplex_bpmp_channel_data {
	/* Buffer for incoming data */
	struct frame_data *ib;

	/* Buffer for outgoing data */
	struct frame_data *ob;
};

static struct ccplex_bpmp_channel_data s_channel;
static struct ivc ivc_ccplex_bpmp_channel;

/*
 * Helper functions to access the HSP doorbell registers
 */
static inline uint32_t hsp_db_read(uint32_t reg)
{
	return mmio_read_32((uint32_t)(TEGRA_HSP_DBELL_BASE + reg));
}

static inline void hsp_db_write(uint32_t reg, uint32_t val)
{
	mmio_write_32((uint32_t)(TEGRA_HSP_DBELL_BASE + reg), val);
}

/*******************************************************************************
 *      IVC wrappers for CCPLEX <-> BPMP communication.
 ******************************************************************************/

static void tegra_bpmp_ring_bpmp_doorbell(void);

/*
 * Get the next frame where data can be written.
 */
static struct frame_data *tegra_bpmp_get_next_out_frame(void)
{
	struct frame_data *frame;
	const struct ivc *ch = &ivc_ccplex_bpmp_channel;

	frame = (struct frame_data *)tegra_ivc_write_get_next_frame(ch);
	if (frame == NULL) {
		ERROR("%s: Error in getting next frame, exiting\n", __func__);
	} else {
		s_channel.ob = frame;
	}

	return frame;
}

static void tegra_bpmp_signal_slave(void)
{
	(void)tegra_ivc_write_advance(&ivc_ccplex_bpmp_channel);
	tegra_bpmp_ring_bpmp_doorbell();
}

static int32_t tegra_bpmp_free_master(void)
{
	return tegra_ivc_read_advance(&ivc_ccplex_bpmp_channel);
}

static bool tegra_bpmp_slave_acked(void)
{
	struct frame_data *frame;
	bool ret = true;

	frame = (struct frame_data *)tegra_ivc_read_get_next_frame(&ivc_ccplex_bpmp_channel);
	if (frame == NULL) {
		ret = false;
	} else {
		s_channel.ib = frame;
	}

	return ret;
}

static struct frame_data *tegra_bpmp_get_cur_in_frame(void)
{
	return s_channel.ib;
}

/*
 * Enables BPMP to ring CCPlex doorbell
 */
static void tegra_bpmp_enable_ccplex_doorbell(void)
{
	uint32_t reg;

	reg = hsp_db_read(HSP_DBELL_1_ENABLE);
	reg |= HSP_MASTER_BPMP_BIT;
	hsp_db_write(HSP_DBELL_1_ENABLE, reg);
}

/*
 * CCPlex rings the BPMP doorbell
 */
static void tegra_bpmp_ring_bpmp_doorbell(void)
{
	/*
	 * Any writes to this register has the same effect,
	 * uses master ID of the write transaction and set
	 * corresponding flag.
	 */
	hsp_db_write(HSP_DBELL_3_TRIGGER, HSP_MASTER_CCPLEX_BIT);
}

/*
 * Returns true if CCPLex can ring BPMP doorbell, otherwise false.
 * This also signals that BPMP is up and ready.
 */
static bool tegra_bpmp_can_ccplex_ring_doorbell(void)
{
	uint32_t reg;

	/* check if ccplex can communicate with bpmp */
	reg = hsp_db_read(HSP_DBELL_3_ENABLE);

	return ((reg & HSP_MASTER_CCPLEX_BIT) != 0U);
}

static int32_t tegra_bpmp_wait_for_slave_ack(void)
{
	uint32_t timeout = TIMEOUT_RESPONSE_FROM_BPMP_US;

	while (!tegra_bpmp_slave_acked() && (timeout != 0U)) {
		udelay(1);
		timeout--;
	};

	return ((timeout == 0U) ? -ETIMEDOUT : 0);
}

/*
 * Notification from the ivc layer
 */
static void tegra_bpmp_ivc_notify(const struct ivc *ivc)
{
	(void)(ivc);

	tegra_bpmp_ring_bpmp_doorbell();
}

/*
 * Atomic send/receive API, which means it waits until slave acks
 */
static int32_t tegra_bpmp_ipc_send_req_atomic(uint32_t mrq, void *p_out,
			uint32_t size_out, void *p_in, uint32_t size_in)
{
	struct frame_data *frame = tegra_bpmp_get_next_out_frame();
	const struct frame_data *f_in = NULL;
	int32_t ret = 0;
	void *p_fdata;

	if ((p_out == NULL) || (size_out > IVC_DATA_SZ_BYTES) ||
	    (frame == NULL)) {
		ERROR("%s: invalid parameters, exiting\n", __func__);
		ret = -EINVAL;
	}

	if (ret == 0) {

		/* prepare the command frame */
		frame->mrq = mrq;
		frame->flags = FLAG_DO_ACK;
		p_fdata = frame->data;
		(void)memcpy(p_fdata, p_out, (size_t)size_out);

		/* signal the slave */
		tegra_bpmp_signal_slave();

		/* wait for slave to ack */
		ret = tegra_bpmp_wait_for_slave_ack();
		if (ret != 0) {
			ERROR("failed waiting for the slave to ack\n");
		}

		/* retrieve the response frame */
		if ((size_in <= IVC_DATA_SZ_BYTES) && (p_in != NULL) &&
		    (ret == 0)) {

			f_in = tegra_bpmp_get_cur_in_frame();
			if (f_in != NULL) {
				ERROR("Failed to get next input frame!\n");
			} else {
				(void)memcpy(p_in, p_fdata, (size_t)size_in);
			}
		}

		if (ret == 0) {
			ret = tegra_bpmp_free_master();
			if (ret != 0) {
				ERROR("Failed to free master\n");
			}
		}
	}

	return ret;
}

/*
 * Initializes the BPMP<--->CCPlex communication path.
 */
int32_t tegra_bpmp_ipc_init(void)
{
	size_t msg_size;
	uint32_t frame_size, timeout;
	int32_t error = 0;

	/* allow bpmp to ring CCPLEX's doorbell */
	tegra_bpmp_enable_ccplex_doorbell();

	/* wait for BPMP to actually ring the doorbell */
	timeout = TIMEOUT_RESPONSE_FROM_BPMP_US;
	while ((timeout != 0U) && !tegra_bpmp_can_ccplex_ring_doorbell()) {
		udelay(1); /* bpmp turn-around time */
		timeout--;
	}

	if (timeout == 0U) {
		ERROR("%s: BPMP firmware is not ready\n", __func__);
		return -ENOTSUP;
	}

	INFO("%s: BPMP handshake completed\n", __func__);

	msg_size = tegra_ivc_align(IVC_CMD_SZ_BYTES);
	frame_size = (uint32_t)tegra_ivc_total_queue_size(msg_size);
	if (frame_size > TEGRA_BPMP_IPC_CH_MAP_SIZE) {
		ERROR("%s: carveout size is not sufficient\n", __func__);
		return -EINVAL;
	}

	error = tegra_ivc_init(&ivc_ccplex_bpmp_channel,
				(uint32_t)TEGRA_BPMP_IPC_RX_PHYS_BASE,
				(uint32_t)TEGRA_BPMP_IPC_TX_PHYS_BASE,
				1U, frame_size, tegra_bpmp_ivc_notify);
	if (error != 0) {

		ERROR("%s: IVC init failed (%d)\n", __func__, error);

	} else {

		/* reset channel */
		tegra_ivc_channel_reset(&ivc_ccplex_bpmp_channel);

		/* wait for notification from BPMP */
		while (tegra_ivc_channel_notified(&ivc_ccplex_bpmp_channel) != 0) {
			/*
			 * Interrupt BPMP with doorbell each time after
			 * tegra_ivc_channel_notified() returns non zero
			 * value.
			 */
			tegra_bpmp_ring_bpmp_doorbell();
		}

		INFO("%s: All communication channels initialized\n", __func__);
	}

	return error;
}

/* Handler to reset a hardware module */
int32_t tegra_bpmp_ipc_reset_module(uint32_t rst_id)
{
	int32_t ret;
	struct mrq_reset_request req = {
		.cmd = (uint32_t)CMD_RESET_MODULE,
		.reset_id = rst_id
	};

	/* only GPCDMA/XUSB_PADCTL resets are supported */
	assert((rst_id == TEGRA_RESET_ID_XUSB_PADCTL) ||
	       (rst_id == TEGRA_RESET_ID_GPCDMA));

	ret = tegra_bpmp_ipc_send_req_atomic(MRQ_RESET, &req,
			(uint32_t)sizeof(req), NULL, 0);
	if (ret != 0) {
		ERROR("%s: failed for module %d with error %d\n", __func__,
		      rst_id, ret);
	}

	return ret;
}

int tegra_bpmp_ipc_enable_clock(uint32_t clk_id)
{
	int ret;
	struct mrq_clk_request req;

	/* only SE clocks are supported */
	if (clk_id != TEGRA_CLK_SE) {
		return -ENOTSUP;
	}

	/* prepare the MRQ_CLK command */
	req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_ENABLE, clk_id);

	ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, sizeof(req),
			NULL, 0);
	if (ret != 0) {
		ERROR("%s: failed for module %d with error %d\n", __func__,
		      clk_id, ret);
	}

	return ret;
}

int tegra_bpmp_ipc_disable_clock(uint32_t clk_id)
{
	int ret;
	struct mrq_clk_request req;

	/* only SE clocks are supported */
	if (clk_id != TEGRA_CLK_SE) {
		return -ENOTSUP;
	}

	/* prepare the MRQ_CLK command */
	req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_DISABLE, clk_id);

	ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, sizeof(req),
			NULL, 0);
	if (ret != 0) {
		ERROR("%s: failed for module %d with error %d\n", __func__,
		      clk_id, ret);
	}

	return ret;
}
