/*
 * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <errno.h>

#include <arch_helpers.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/arm/cci.h>
#include <drivers/arm/gicv2.h>
#include <lib/bakery_lock.h>
#include <lib/mmio.h>
#include <lib/psci/psci.h>
#include <plat/common/platform.h>

#include "iic_dvfs.h"
#include "platform_def.h"
#include "pwrc.h"
#include "rcar_def.h"
#include "rcar_private.h"
#if RCAR_GEN3_ULCB
#include "ulcb_cpld.h"
#endif /* RCAR_GEN3_ULCB */

#define DVFS_SET_VID_0V		(0x00)
#define P_ALL_OFF		(0x80)
#define KEEPON_DDR1C		(0x08)
#define KEEPON_DDR0C		(0x04)
#define KEEPON_DDR1		(0x02)
#define KEEPON_DDR0		(0x01)

#define SYSTEM_PWR_STATE(s)	((s)->pwr_domain_state[PLAT_MAX_PWR_LVL])
#define CLUSTER_PWR_STATE(s)	((s)->pwr_domain_state[MPIDR_AFFLVL1])
#define CORE_PWR_STATE(s)	((s)->pwr_domain_state[MPIDR_AFFLVL0])

extern void rcar_pwrc_restore_generic_timer(uint64_t *stack);
extern void plat_rcar_gic_driver_init(void);
extern void plat_rcar_gic_init(void);

static uintptr_t rcar_sec_entrypoint;

static void rcar_program_mailbox(u_register_t mpidr, uintptr_t address)
{
	mailbox_t *rcar_mboxes = (mailbox_t *) MBOX_BASE;
	uint64_t linear_id = plat_core_pos_by_mpidr(mpidr);
	unsigned long range;

	rcar_mboxes[linear_id].value = address;
	range = (unsigned long)&rcar_mboxes[linear_id];

	flush_dcache_range(range, sizeof(range));
}

static void rcar_cpu_standby(plat_local_state_t cpu_state)
{
	u_register_t scr_el3 = read_scr_el3();

	write_scr_el3(scr_el3 | SCR_IRQ_BIT);
	dsb();
	wfi();
	write_scr_el3(scr_el3);
}

static int rcar_pwr_domain_on(u_register_t mpidr)
{
	rcar_program_mailbox(mpidr, rcar_sec_entrypoint);
	rcar_pwrc_cpuon(mpidr);

	return PSCI_E_SUCCESS;
}

static void rcar_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
	uint32_t cluster_type = rcar_pwrc_get_cluster();
	u_register_t mpidr = read_mpidr_el1();

	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
		if (cluster_type == RCAR_CLUSTER_A53A57)
			plat_cci_enable();

	rcar_program_mailbox(mpidr, 0);
	rcar_pwrc_enable_interrupt_wakeup(mpidr);

	gicv2_cpuif_enable();
	gicv2_pcpu_distif_init();
}

static void rcar_pwr_domain_off(const psci_power_state_t *target_state)
{
#if RCAR_LSI != RCAR_D3
	uint32_t cluster_type = rcar_pwrc_get_cluster();
#endif
	u_register_t mpidr = read_mpidr_el1();

	rcar_pwrc_disable_interrupt_wakeup(mpidr);
	gicv2_cpuif_disable();
	rcar_pwrc_cpuoff(mpidr);

#if RCAR_LSI != RCAR_D3
	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
		if (cluster_type == RCAR_CLUSTER_A53A57)
			plat_cci_disable();

		rcar_pwrc_clusteroff(mpidr);
	}
#endif
}

static void rcar_pwr_domain_suspend(const psci_power_state_t *target_state)
{
	uint32_t cluster_type = rcar_pwrc_get_cluster();
	u_register_t mpidr = read_mpidr_el1();

	if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
		return;

	rcar_program_mailbox(mpidr, rcar_sec_entrypoint);
	rcar_pwrc_enable_interrupt_wakeup(mpidr);
	gicv2_cpuif_disable();
	rcar_pwrc_cpuoff(mpidr);

	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
		if (cluster_type == RCAR_CLUSTER_A53A57)
			plat_cci_disable();

		rcar_pwrc_clusteroff(mpidr);
	}
}

static void rcar_pwr_domain_suspend_finish(const psci_power_state_t
					   *target_state)
{
	uint32_t cluster_type = rcar_pwrc_get_cluster();

	if (SYSTEM_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
		goto finish;

	plat_rcar_gic_driver_init();
	plat_rcar_gic_init();

	if (cluster_type == RCAR_CLUSTER_A53A57)
		plat_cci_init();

	rcar_pwrc_restore_timer_state();
	rcar_pwrc_setup();
	rcar_pwrc_code_copy_to_system_ram();

#if RCAR_SYSTEM_SUSPEND
	rcar_pwrc_init_suspend_to_ram();
#endif
finish:
	rcar_pwr_domain_on_finish(target_state);
}

static void __dead2 rcar_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
{
#if RCAR_SYSTEM_SUSPEND
	if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
		rcar_pwrc_suspend_to_ram();
#endif
	wfi();

	ERROR("RCAR Power Down: operation not handled.\n");
	panic();
}

static void __dead2 rcar_system_off(void)
{
#if PMIC_ROHM_BD9571
#if PMIC_LEVEL_MODE
	if (rcar_iic_dvfs_send(PMIC, DVFS_SET_VID, DVFS_SET_VID_0V))
		ERROR("BL3-1:Failed the SYSTEM-OFF.\n");
#else
	if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF))
		ERROR("BL3-1:Failed the SYSTEM-RESET.\n");
#endif
#else
	u_register_t mpidr = read_mpidr_el1();
	u_register_t cpu = mpidr & 0x0000ffffU;
	int32_t rtn_on;

	rtn_on = rcar_pwrc_cpu_on_check(mpidr);

	if (cpu != rcar_boot_mpidr) {
		panic();
	}

	if (rtn_on != 0) {
		panic();
	}

	rcar_pwrc_cpuoff(mpidr);
	rcar_pwrc_clusteroff(mpidr);

#endif /* PMIC_ROHM_BD9571 */
	wfi();
	ERROR("RCAR System Off: operation not handled.\n");
	panic();
}

static void __dead2 rcar_system_reset(void)
{
#if PMIC_ROHM_BD9571
#if PMIC_LEVEL_MODE
#if RCAR_SYSTEM_RESET_KEEPON_DDR
	uint8_t mode;
	int32_t error;

	error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, KEEP10_MAGIC);
	if (error) {
		ERROR("Failed send KEEP10 magic ret=%d\n", error);
		goto done;
	}

	error = rcar_iic_dvfs_receive(PMIC, BKUP_MODE_CNT, &mode);
	if (error) {
		ERROR("Failed receive BKUP_Mode_Cnt ret=%d\n", error);
		goto done;
	}

	mode |= KEEPON_DDR1C | KEEPON_DDR0C | KEEPON_DDR1 | KEEPON_DDR0;
	error = rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, mode);
	if (error) {
		ERROR("Failed send KEEPON_DDRx ret=%d\n", error);
		goto done;
	}

	rcar_pwrc_set_suspend_to_ram();
done:
#else
	if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF))
		ERROR("BL3-1:Failed the SYSTEM-RESET.\n");
#endif
#else
#if (RCAR_GEN3_ULCB == 1)
	rcar_cpld_reset_cpu();
#endif
#endif
#else
	rcar_pwrc_system_reset();
#endif
	wfi();

	ERROR("RCAR System Reset: operation not handled.\n");
	panic();
}

static int rcar_validate_power_state(unsigned int power_state,
				    psci_power_state_t *req_state)
{
	unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
	unsigned int pstate = psci_get_pstate_type(power_state);
	uint32_t i;

	if (pstate == PSTATE_TYPE_STANDBY) {
		if (pwr_lvl != MPIDR_AFFLVL0)
			return PSCI_E_INVALID_PARAMS;

		req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
	} else {
		for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
			req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
	}

	if (psci_get_pstate_id(power_state))
		return PSCI_E_INVALID_PARAMS;

	return PSCI_E_SUCCESS;
}

#if RCAR_SYSTEM_SUSPEND
static void rcar_get_sys_suspend_power_state(psci_power_state_t *req_state)
{
	u_register_t mpidr = read_mpidr_el1() & 0x0000ffffU;
	int i;

	if (mpidr != rcar_boot_mpidr)
		goto deny;

	for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;

	return;
deny:
	/* deny system suspend entry */
	req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PSCI_LOCAL_STATE_RUN;
	for (i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
		req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE;
}
#endif

static const plat_psci_ops_t rcar_plat_psci_ops = {
	.cpu_standby			= rcar_cpu_standby,
	.pwr_domain_on			= rcar_pwr_domain_on,
	.pwr_domain_off			= rcar_pwr_domain_off,
	.pwr_domain_suspend		= rcar_pwr_domain_suspend,
	.pwr_domain_on_finish		= rcar_pwr_domain_on_finish,
	.pwr_domain_suspend_finish	= rcar_pwr_domain_suspend_finish,
	.system_off			= rcar_system_off,
	.system_reset			= rcar_system_reset,
	.validate_power_state		= rcar_validate_power_state,
	.pwr_domain_pwr_down_wfi	= rcar_pwr_domain_pwr_down_wfi,
#if RCAR_SYSTEM_SUSPEND
	.get_sys_suspend_power_state	= rcar_get_sys_suspend_power_state,
#endif
};

int plat_setup_psci_ops(uintptr_t sec_entrypoint, const plat_psci_ops_t **psci_ops)
{
	*psci_ops = &rcar_plat_psci_ops;
	rcar_sec_entrypoint = sec_entrypoint;

#if RCAR_SYSTEM_SUSPEND
	rcar_pwrc_init_suspend_to_ram();
#endif
	return 0;
}

