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

#include <arch_helpers.h>
#include <bakery_lock.h>
#include <bl_common.h>
#include <cci.h>
#include <debug.h>
#include <errno.h>
#include <gicv2.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <psci.h>

#include "iic_dvfs.h"
#include "pwrc.h"
#include "rcar_def.h"
#include "rcar_private.h"

#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])

uint64_t rcar_stack_generic_timer[5] __attribute__ ((section("data")));

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);
extern u_register_t rcar_boot_mpidr;

#if (RCAR_GEN3_ULCB == 1)
extern void rcar_cpld_reset_cpu(void);
#endif

static uintptr_t rcar_sec_entrypoint;

static void rcar_program_mailbox(uint64_t mpidr, uint64_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)
{
	uint32_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();
	unsigned long mpidr = read_mpidr_el1();

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

	rcar_pwrc_disable_interrupt_wakeup(mpidr);
	rcar_program_mailbox(mpidr, 0);

	gicv2_cpuif_enable();
	gicv2_pcpu_distif_init();
}

static void rcar_pwr_domain_off(const psci_power_state_t *target_state)
{
	uint32_t cluster_type = rcar_pwrc_get_cluster();
	unsigned long mpidr = read_mpidr_el1();

	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(const psci_power_state_t *target_state)
{
	uint32_t cluster_type = rcar_pwrc_get_cluster();
	unsigned long 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);
	}

#if RCAR_SYSTEM_SUSPEND
	if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
		rcar_pwrc_suspend_to_ram();
#endif
}

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_generic_timer(rcar_stack_generic_timer);

	/* start generic timer */
	write_cntfrq_el0(plat_get_syscnt_freq2());
	mmio_write_32(RCAR_CNTC_BASE + CNTCR_OFF, CNTCR_FCREQ(U(0)) | CNTCR_EN);
	rcar_pwrc_setup();

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

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

	rtn_on = cpu_on_check(cpu);

	if (cpu == rcar_boot_mpidr)
		panic();

	if (rtn_on)
		panic();

	rcar_pwrc_cpuoff(cpu);
	rcar_pwrc_clusteroff(cpu);

#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;

	rcar_pwrc_code_copy_to_system_ram();
	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 recieve 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
	rcar_pwrc_code_copy_to_system_ram();
	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)
{
	unsigned long 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,
#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;
}

