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

#include <assert.h>
#include <bpmp_ipc.h>
#include <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;
}
