/*
 * Copyright (C) 2020 Marek Behun, CZ.NIC
 *
 * SPDX-License-Identifier:     BSD-3-Clause
 * https://spdx.org/licenses
 */

#include <stdbool.h>

#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>

#include <mvebu_def.h>

/* Cortex-M3 Secure Processor Mailbox Registers */
#define MVEBU_RWTM_PARAM0_REG			(MVEBU_RWTM_REG_BASE)
#define MVEBU_RWTM_CMD_REG			(MVEBU_RWTM_REG_BASE + 0x40)
#define MVEBU_RWTM_HOST_INT_RESET_REG		(MVEBU_RWTM_REG_BASE + 0xC8)
#define MVEBU_RWTM_HOST_INT_MASK_REG		(MVEBU_RWTM_REG_BASE + 0xCC)
#define MVEBU_RWTM_HOST_INT_SP_COMPLETE		BIT(0)

#define MVEBU_RWTM_REBOOT_CMD		0x0009
#define MVEBU_RWTM_REBOOT_MAGIC		0xDEADBEEF

static inline bool rwtm_completed(void)
{
	return (mmio_read_32(MVEBU_RWTM_HOST_INT_RESET_REG) &
		MVEBU_RWTM_HOST_INT_SP_COMPLETE) != 0;
}

static bool rwtm_wait(int ms)
{
	while (ms && !rwtm_completed()) {
		mdelay(1);
		--ms;
	}

	return rwtm_completed();
}

void cm3_system_reset(void)
{
	int tries = 5;

	for (; tries > 0; --tries) {
		mmio_clrbits_32(MVEBU_RWTM_HOST_INT_RESET_REG,
				MVEBU_RWTM_HOST_INT_SP_COMPLETE);

		mmio_write_32(MVEBU_RWTM_PARAM0_REG, MVEBU_RWTM_REBOOT_MAGIC);
		mmio_write_32(MVEBU_RWTM_CMD_REG, MVEBU_RWTM_REBOOT_CMD);

		if (rwtm_wait(10)) {
			break;
		}

		mdelay(100);
	}

	/* If we reach here, the command is not implemented. */
	ERROR("System reset command not implemented in WTMI firmware!\n");
}
