/*
 * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */


#include <arch_helpers.h>

#include <lib/bakery_lock.h>
#include <lib/mmio.h>

#include <ipi.h>
#include <plat_ipi.h>
#include <plat_private.h>
#include <plat/common/platform.h>

#include "pm_ipi.h"


#define ERROR_CODE_MASK		0xFFFFU

DEFINE_BAKERY_LOCK(pm_secure_lock);

/**
 * pm_ipi_init() - Initialize IPI peripheral for communication with
 *		   remote processor
 *
 * @proc	Pointer to the processor who is initiating request
 * @return	On success, the initialization function must return 0.
 *		Any other return value will cause the framework to ignore
 *		the service
 *
 * Called from pm_setup initialization function
 */
int pm_ipi_init(const struct pm_proc *proc)
{
	bakery_lock_init(&pm_secure_lock);
	ipi_mb_open(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id);

	return 0;
}

/**
 * pm_ipi_send_common() - Sends IPI request to the remote processor
 * @proc	Pointer to the processor who is initiating request
 * @payload	API id and call arguments to be written in IPI buffer
 *
 * Send an IPI request to the power controller. Caller needs to hold
 * the 'pm_secure_lock' lock.
 *
 * @return	Returns status, either success or error+reason
 */
static enum pm_ret_status pm_ipi_send_common(const struct pm_proc *proc,
					     uint32_t payload[PAYLOAD_ARG_CNT],
					     uint32_t is_blocking)
{
	int status;
	unsigned int offset = 0;
	uintptr_t buffer_base = proc->ipi->buffer_base +
					IPI_BUFFER_TARGET_REMOTE_OFFSET +
					IPI_BUFFER_REQ_OFFSET;
#if IPI_CRC_CHECK
	payload[PAYLOAD_CRC_POS] = calculate_crc(payload, IPI_W0_TO_W6_SIZE);
#endif

	/* Write payload into IPI buffer */
	for (size_t i = 0; i < PAYLOAD_ARG_CNT; i++) {
		mmio_write_32(buffer_base + offset, payload[i]);
		offset += PAYLOAD_ARG_SIZE;
	}

	/* Generate IPI to remote processor */
	status = ipi_mb_notify(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id,
		      is_blocking);
	if (status == 0) {
		return PM_RET_SUCCESS;
	}

	return PM_RET_ERROR_TIMEOUT;
}

/**
 * pm_ipi_send_non_blocking() - Sends IPI request to the remote processor
 *			        without blocking notification
 * @proc	Pointer to the processor who is initiating request
 * @payload	API id and call arguments to be written in IPI buffer
 *
 * Send an IPI request to the power controller.
 *
 * @return	Returns status, either success or error+reason
 */
enum pm_ret_status pm_ipi_send_non_blocking(const struct pm_proc *proc,
					    uint32_t payload[PAYLOAD_ARG_CNT])
{
	enum pm_ret_status ret;

	bakery_lock_get(&pm_secure_lock);

	ret = pm_ipi_send_common(proc, payload, IPI_NON_BLOCKING);

	bakery_lock_release(&pm_secure_lock);

	return ret;
}

/**
 * pm_ipi_send() - Sends IPI request to the remote processor
 * @proc	Pointer to the processor who is initiating request
 * @payload	API id and call arguments to be written in IPI buffer
 *
 * Send an IPI request to the power controller.
 *
 * @return	Returns status, either success or error+reason
 */
enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
			       uint32_t payload[PAYLOAD_ARG_CNT])
{
	enum pm_ret_status ret;

	bakery_lock_get(&pm_secure_lock);

	ret = pm_ipi_send_common(proc, payload, IPI_BLOCKING);

	bakery_lock_release(&pm_secure_lock);

	return ret;
}


/**
 * pm_ipi_buff_read() - Reads IPI response after remote processor has handled
 *			interrupt
 * @proc	Pointer to the processor who is waiting and reading response
 * @value	Used to return value from IPI buffer element (optional)
 * @count	Number of values to return in @value
 *
 * @return	Returns status, either success or error+reason
 */
static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
					   unsigned int *value, size_t count)
{
	size_t i;
#if IPI_CRC_CHECK
	size_t j;
	unsigned int response_payload[PAYLOAD_ARG_CNT];
#endif
	uintptr_t buffer_base = proc->ipi->buffer_base +
				IPI_BUFFER_TARGET_REMOTE_OFFSET +
				IPI_BUFFER_RESP_OFFSET;

	/*
	 * Read response from IPI buffer
	 * buf-0: success or error+reason
	 * buf-1: value
	 * buf-2: unused
	 * buf-3: unused
	 */
	for (i = 1; i <= count; i++) {
		*value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
		value++;
	}
#if IPI_CRC_CHECK
	for (j = 0; j < PAYLOAD_ARG_CNT; j++)
		response_payload[j] = mmio_read_32(buffer_base +
						(j * PAYLOAD_ARG_SIZE));

	if (response_payload[PAYLOAD_CRC_POS] !=
			calculate_crc(response_payload, IPI_W0_TO_W6_SIZE))
		NOTICE("ERROR in CRC response payload value:0x%x\n",
					response_payload[PAYLOAD_CRC_POS]);
#endif

	return mmio_read_32(buffer_base);
}

/**
 * pm_ipi_buff_read_callb() - Reads IPI response after remote processor has
 *			      handled interrupt
 * @value	Used to return value from IPI buffer element (optional)
 * @count	Number of values to return in @value
 *
 * @return	Returns status, either success or error+reason
 */
void pm_ipi_buff_read_callb(unsigned int *value, size_t count)
{
	size_t i;
#if IPI_CRC_CHECK
	size_t j;
	unsigned int response_payload[PAYLOAD_ARG_CNT];
#endif
	uintptr_t buffer_base = IPI_BUFFER_REMOTE_BASE +
				IPI_BUFFER_TARGET_LOCAL_OFFSET +
				IPI_BUFFER_REQ_OFFSET;

	if (count > IPI_BUFFER_MAX_WORDS)
		count = IPI_BUFFER_MAX_WORDS;

	for (i = 0; i <= count; i++) {
		*value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
		value++;
	}
#if IPI_CRC_CHECK
	for (j = 0; j < PAYLOAD_ARG_CNT; j++)
		response_payload[j] = mmio_read_32(buffer_base +
						(j * PAYLOAD_ARG_SIZE));

	if (response_payload[PAYLOAD_CRC_POS] !=
			calculate_crc(response_payload, IPI_W0_TO_W6_SIZE))
		NOTICE("ERROR in CRC response payload value:0x%x\n",
					response_payload[PAYLOAD_CRC_POS]);
#endif
}

/**
 * pm_ipi_send_sync() - Sends IPI request to the remote processor
 * @proc	Pointer to the processor who is initiating request
 * @payload	API id and call arguments to be written in IPI buffer
 * @value	Used to return value from IPI buffer element (optional)
 * @count	Number of values to return in @value
 *
 * Send an IPI request to the power controller and wait for it to be handled.
 *
 * @return	Returns status, either success or error+reason and, optionally,
 *		@value
 */
enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
				    uint32_t payload[PAYLOAD_ARG_CNT],
				    unsigned int *value, size_t count)
{
	enum pm_ret_status ret;

	bakery_lock_get(&pm_secure_lock);

	ret = pm_ipi_send_common(proc, payload, IPI_BLOCKING);
	if (ret != PM_RET_SUCCESS)
		goto unlock;

	ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, value, count));

unlock:
	bakery_lock_release(&pm_secure_lock);

	return ret;
}

void pm_ipi_irq_enable(const struct pm_proc *proc)
{
	ipi_mb_enable_irq(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id);
}

void pm_ipi_irq_clear(const struct pm_proc *proc)
{
	ipi_mb_ack(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id);
}

uint32_t pm_ipi_irq_status(const struct pm_proc *proc)
{
	int ret;

	ret = ipi_mb_enquire_status(proc->ipi->local_ipi_id,
				    proc->ipi->remote_ipi_id);
	if (ret & IPI_MB_STATUS_RECV_PENDING)
		return 1;
	else
		return 0;
}

#if IPI_CRC_CHECK
uint32_t calculate_crc(uint32_t *payload, uint32_t bufsize)
{
	uint32_t crcinit = CRC_INIT_VALUE;
	uint32_t order   = CRC_ORDER;
	uint32_t polynom = CRC_POLYNOM;
	uint32_t i, j, c, bit, datain, crcmask, crchighbit;
	uint32_t crc = crcinit;

	crcmask = ((uint32_t)((1U << (order - 1U)) - 1U) << 1U) | 1U;
	crchighbit = (uint32_t)(1U << (order - 1U));

	for (i = 0U; i < bufsize; i++) {
		datain = mmio_read_8((unsigned long)payload + i);
		c = datain;
		j = 0x80U;
		while (j != 0U) {
			bit = crc & crchighbit;
			crc <<= 1U;
			if (0U != (c & j))
				bit ^= crchighbit;
			if (bit != 0U)
				crc ^= polynom;
			j >>= 1U;
		}
		crc &= crcmask;
	}
	return crc;
}
#endif
