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

#include <stdbool.h>

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

#include <dram.h>
#include <gpc.h>
#include <imx8m_psci.h>
#include <plat_imx8.h>

/*
 * below callback functions need to be override by i.mx8mq,
 * for other i.mx8m soc, if no special requirement,
 * reuse below ones.
 */
#pragma weak imx_validate_power_state
#pragma weak imx_domain_suspend
#pragma weak imx_domain_suspend_finish
#pragma weak imx_get_sys_suspend_power_state

int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
{
	/* The non-secure entrypoint should be in RAM space */
	if (ns_entrypoint < PLAT_NS_IMAGE_OFFSET)
		return PSCI_E_INVALID_PARAMS;

	return PSCI_E_SUCCESS;
}

int imx_pwr_domain_on(u_register_t mpidr)
{
	unsigned int core_id;
	uint64_t base_addr = BL31_START;

	core_id = MPIDR_AFFLVL0_VAL(mpidr);

	imx_set_cpu_secure_entry(core_id, base_addr);
	imx_set_cpu_pwr_on(core_id);

	return PSCI_E_SUCCESS;
}

void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
	plat_gic_pcpu_init();
	plat_gic_cpuif_enable();
}

void imx_pwr_domain_off(const psci_power_state_t *target_state)
{
	uint64_t mpidr = read_mpidr_el1();
	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);

	plat_gic_cpuif_disable();
	imx_set_cpu_pwr_off(core_id);
}

int imx_validate_power_state(unsigned int power_state,
			 psci_power_state_t *req_state)
{
	int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
	int pwr_type = psci_get_pstate_type(power_state);
	int state_id = psci_get_pstate_id(power_state);

	if (pwr_lvl > PLAT_MAX_PWR_LVL)
		return PSCI_E_INVALID_PARAMS;

	if (pwr_type == PSTATE_TYPE_STANDBY) {
		CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
		CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
	}

	if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) {
		CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE;
		CLUSTER_PWR_STATE(req_state) = PLAT_WAIT_RET_STATE;
	}

	return PSCI_E_SUCCESS;
}

void imx_cpu_standby(plat_local_state_t cpu_state)
{
	dsb();
	write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
	isb();

	wfi();

	write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
	isb();
}

void imx_domain_suspend(const psci_power_state_t *target_state)
{
	uint64_t base_addr = BL31_START;
	uint64_t mpidr = read_mpidr_el1();
	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);

	if (is_local_state_off(CORE_PWR_STATE(target_state))) {
		plat_gic_cpuif_disable();
		imx_set_cpu_secure_entry(core_id, base_addr);
		imx_set_cpu_lpm(core_id, true);
	} else {
		dsb();
		write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
		isb();
	}

	if (!is_local_state_run(CLUSTER_PWR_STATE(target_state)))
		imx_set_cluster_powerdown(core_id, CLUSTER_PWR_STATE(target_state));

	if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
		imx_set_sys_lpm(core_id, true);
		dram_enter_retention();
		imx_anamix_override(true);
	}
}

void imx_domain_suspend_finish(const psci_power_state_t *target_state)
{
	uint64_t mpidr = read_mpidr_el1();
	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);

	if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
		imx_anamix_override(false);
		dram_exit_retention();
		imx_set_sys_lpm(core_id, false);
	}

	if (!is_local_state_run(CLUSTER_PWR_STATE(target_state))) {
		imx_clear_rbc_count();
		imx_set_cluster_powerdown(core_id, PSCI_LOCAL_STATE_RUN);
	}

	if (is_local_state_off(CORE_PWR_STATE(target_state))) {
		imx_set_cpu_lpm(core_id, false);
		plat_gic_cpuif_enable();
	} else {
		write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
		isb();
	}
}

void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
{
	unsigned int i;

	for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++)
		req_state->pwr_domain_state[i] = PLAT_STOP_OFF_STATE;
}

static void __dead2 imx_wdog_restart(bool external_reset)
{
	uintptr_t wdog_base = IMX_WDOG_BASE;
	unsigned int val;

	val = mmio_read_16(wdog_base);
	/*
	 * Common watchdog init flags, for additional details check
	 * 6.6.4.1 Watchdog Control Register (WDOGx_WCR)
	 *
	 * Initial bit selection:
	 * WDOG_WCR_WDE - Enable the watchdog.
	 *
	 * 0x000E mask is used to keep previous values (that could be set
	 * in SPL) of WDBG and WDE/WDT (both are write-one once-only bits).
	 */
	val = (val & 0x000E) | WDOG_WCR_WDE;
	if (external_reset) {
		/*
		 * To assert WDOG_B (external reset) we have
		 * to set WDA bit 0 (already set in previous step).
		 * SRS bits are required to be set to 1 (no effect on the
		 * system).
		 */
		val |= WDOG_WCR_SRS;
	} else {
		/*
		 * To assert Software Reset Signal (internal reset) we have
		 * to set SRS bit to 0 (already set in previous step).
		 * SRE bit is required to be set to 1 when used in
		 * conjunction with the Software Reset Signal before
		 * SRS asserton, otherwise SRS bit will just automatically
		 * reset to 1.
		 *
		 * Also we set WDA to 1 (no effect on system).
		 */
		val |= WDOG_WCR_SRE | WDOG_WCR_WDA;
	}

	mmio_write_16(wdog_base, val);

	mmio_write_16(wdog_base + WDOG_WSR, 0x5555);
	mmio_write_16(wdog_base + WDOG_WSR, 0xaaaa);
	while (1)
		;
}

void __dead2 imx_system_reset(void)
{
#ifdef IMX_WDOG_B_RESET
	imx_wdog_restart(true);
#else
	imx_wdog_restart(false);
#endif
}

int imx_system_reset2(int is_vendor, int reset_type, u_register_t cookie)
{
	imx_wdog_restart(false);

	/*
	 * imx_wdog_restart cannot return (as it's  a __dead function),
	 * however imx_system_reset2 has to return some value according
	 * to PSCI v1.1 spec.
	 */
	return 0;
}

void __dead2 imx_system_off(void)
{
	uint32_t val;

	val = mmio_read_32(IMX_SNVS_BASE + SNVS_LPCR);
	val |= SNVS_LPCR_SRTC_ENV | SNVS_LPCR_DP_EN | SNVS_LPCR_TOP;
	mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, val);

	while (1)
		;
}

void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
{
	/*
	 * before enter WAIT or STOP mode with PLAT(SCU) power down,
	 * rbc count need to be enabled to make sure PLAT is
	 * power down successfully even if the the wakeup IRQ is pending
	 * early before the power down sequence. the RBC counter is
	 * drived by the 32K OSC, so delay 30us to make sure the counter
	 * is really running.
	 */
	if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
		imx_set_rbc_count();
		udelay(30);
	}

	while (1)
		wfi();
}
