// SPDX-License-Identifier: GPL-2.0
/*
 * This file implements basic PSCI support for i.MX8M
 *
 * Copyright (C) 2022 Marek Vasut <marex@denx.de>
 */
#include <asm/arch/imx-regs.h>
#include <asm/cache.h>
#include <asm/gic.h>
#include <asm/io.h>
#include <asm/psci.h>
#include <asm/secure.h>
#include <cpu_func.h>
#include <debug_uart.h>
#include <fsl_wdog.h>
#include <linux/bitops.h>

#define SNVS_LPCR			0x38
#define SNVS_LPCR_TOP			BIT(6)
#define SNVS_LPCR_DP_EN			BIT(5)
#define SNVS_LPCR_SRTC_ENV		BIT(0)

#define MPIDR_AFF0			GENMASK(7, 0)

#define GPC_LPCR_A53_AD			0x4
#define EN_Cn_WFI_PDN(cpu)		BIT(((((cpu) & 1) * 2) + (((cpu) & 2) * 8)))
#define GPC_PGC_nCTRL(cpu)		(0x800 + ((cpu) * 0x40))
#define PGC_PCR				BIT(0)
#define GPC_CPU_PGC_SW_PUP_REQ		(IS_ENABLED(CONFIG_IMX8MP) ? 0xd0 : 0xf0)
#define COREn_A53_SW_PUP_REQ(cpu)	BIT(cpu)

#define SRC_A53RCR1			0x8
#define A53_COREn_ENABLE(n)		BIT(n)
#define SRC_GPR(n)			(0x74 + ((n) * 4))

/*
 * Helper code
 */
static u8 psci_state[CONFIG_ARMV8_PSCI_NR_CPUS] __secure_data = {
	PSCI_AFFINITY_LEVEL_ON,
	PSCI_AFFINITY_LEVEL_OFF,
	PSCI_AFFINITY_LEVEL_OFF,
	PSCI_AFFINITY_LEVEL_OFF
};

int psci_update_dt(void *fdt)
{
	return 0;
}

__secure static void psci_set_state(int cpu, u8 state)
{
	psci_state[cpu] = state;
	dsb();
	isb();
}

__secure static s32 psci_cpu_on_validate_mpidr(u64 mpidr, u32 *cpu)
{
	*cpu = mpidr & MPIDR_AFF0;

	if (mpidr & ~MPIDR_AFF0)
		return ARM_PSCI_RET_INVAL;

	if (*cpu >= CONFIG_ARMV8_PSCI_NR_CPUS)
		return ARM_PSCI_RET_INVAL;

	if (psci_state[*cpu] == PSCI_AFFINITY_LEVEL_ON)
		return ARM_PSCI_RET_ALREADY_ON;

	if (psci_state[*cpu] == PSCI_AFFINITY_LEVEL_ON_PENDING)
		return ARM_PSCI_RET_ON_PENDING;

	return ARM_PSCI_RET_SUCCESS;
}

__secure static void psci_cpu_on_write_entry_point(const u32 cpu, u64 entry_point)
{
	const u64 ep = CONFIG_SPL_TEXT_BASE;

	/* Trampoline target */
	writeq(entry_point, CPU_RELEASE_ADDR);
	/* RVBAR address HI */
	writel((u32)(ep >> 24) & 0xffff,
	       (void *)SRC_BASE_ADDR + SRC_GPR(cpu * 2));
	/* RVBAR address LO */
	writel((u32)(ep >> 2) & 0x3fffff,
	       (void *)SRC_BASE_ADDR + SRC_GPR(cpu * 2 + 1));
}

__secure static void psci_cpu_on_power_on(const u32 cpu)
{
	int i;

	clrbits_le32((void *)GPC_BASE_ADDR + GPC_LPCR_A53_AD, EN_Cn_WFI_PDN(cpu));
	clrbits_le32((void *)SRC_BASE_ADDR + SRC_A53RCR1, A53_COREn_ENABLE(cpu));
	setbits_le32((void *)GPC_BASE_ADDR + GPC_PGC_nCTRL(cpu), PGC_PCR);
	setbits_le32((void *)GPC_BASE_ADDR + GPC_CPU_PGC_SW_PUP_REQ, COREn_A53_SW_PUP_REQ(cpu));

	/* If we fail here, the core gets power cycled, hang is OK */
	while (readl(GPC_BASE_ADDR + GPC_CPU_PGC_SW_PUP_REQ) & COREn_A53_SW_PUP_REQ(cpu))
			;

	clrbits_le32((void *)GPC_BASE_ADDR + GPC_PGC_nCTRL(cpu), PGC_PCR);
	setbits_le32((void *)SRC_BASE_ADDR + SRC_A53RCR1, A53_COREn_ENABLE(cpu));

	/* Give the core a bit of time to boot and start executing code */
	for (i = 0; i < 100000; i++)
		asm volatile("nop");
}

__secure static void psci_cpu_on_power_off(const u32 cpu)
{
	setbits_le32((void *)GPC_BASE_ADDR + GPC_LPCR_A53_AD, EN_Cn_WFI_PDN(cpu));
	setbits_le32((void *)GPC_BASE_ADDR + GPC_PGC_nCTRL(cpu), PGC_PCR);
}

/*
 * Common PSCI code
 */
/* Return supported PSCI version */
__secure u32 psci_version(void)
{
	return ARM_PSCI_VER_1_0;
}

/*
 * 64bit PSCI code
 */
__secure s32 psci_cpu_on_64(u32 __always_unused function_id, u64 mpidr,
			    u64 entry_point_address, u64 context_id)
{
	u32 cpu = 0;
	int ret;

	ret = psci_cpu_on_validate_mpidr(mpidr, &cpu);
	if (ret != ARM_PSCI_RET_SUCCESS)
		return ret;

	psci_cpu_on_write_entry_point(cpu, entry_point_address);

	psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON);

	psci_cpu_on_power_on(cpu);

	smp_kick_all_cpus();

	return ARM_PSCI_RET_SUCCESS;
}

__secure s32 psci_affinity_info_64(u32 __always_unused function_id,
				   u64 target_affinity, u32 lowest_affinity_level)
{
	u32 cpu = target_affinity & MPIDR_AFF0;

	if (lowest_affinity_level > 0)
		return ARM_PSCI_RET_INVAL;

	if (target_affinity & ~MPIDR_AFF0)
		return ARM_PSCI_RET_INVAL;

	if (cpu >= CONFIG_ARMV8_PSCI_NR_CPUS)
		return ARM_PSCI_RET_INVAL;

	return psci_state[cpu];
}

__secure s32 psci_system_reset2_64(u32 __always_unused function_id,
				   u32 reset_type, u64 cookie)
{
	psci_system_reset();
	return 0;	/* Not reached */
}

/*
 * 32bit PSCI code
 */
__secure s32 psci_affinity_info(u32 __always_unused function_id,
				u32 target_affinity, u32 lowest_affinity_level)
{
	return psci_affinity_info_64(function_id, target_affinity, lowest_affinity_level);
}

__secure s32 psci_cpu_on(u32 __always_unused function_id, u32 mpidr,
			 u32 entry_point_address, u32 context_id)
{
	return psci_cpu_on_64(function_id, mpidr, entry_point_address, context_id);
}

__secure s32 psci_cpu_off(void)
{
	u32 cpu = psci_get_cpu_id();

	psci_cpu_on_power_off(cpu);
	psci_set_state(cpu, PSCI_AFFINITY_LEVEL_OFF);

	while (1)
		wfi();
}

__secure u32 psci_migrate_info_type(void)
{
	/* Trusted OS is either not present or does not require migration */
	return 2;
}

__secure void psci_system_reset(void)
{
	struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
	bool ext_reset = true;

	u16 wcr = WCR_WDE;

	if (ext_reset)
		wcr |= WCR_SRS; /* do not assert internal reset */
	else
		wcr |= WCR_WDA; /* do not assert external reset */

	/* Write 3 times to ensure it works, due to IMX6Q errata ERR004346 */
	writew(wcr, &wdog->wcr);
	writew(wcr, &wdog->wcr);
	writew(wcr, &wdog->wcr);

	while (1)
		wfi();
}

__secure void psci_system_off(void)
{
	writel(SNVS_LPCR_TOP | SNVS_LPCR_DP_EN | SNVS_LPCR_SRTC_ENV,
	       SNVS_BASE_ADDR + SNVS_LPCR);

	while (1)
		wfi();
}

/*
 * PSCI jump table
 */
__secure s32 psci_features(u32 __always_unused function_id, u32 psci_fid)
{
	switch (psci_fid) {
	case ARM_PSCI_0_2_FN_PSCI_VERSION:
	case ARM_PSCI_0_2_FN_CPU_OFF:
	case ARM_PSCI_0_2_FN_CPU_ON:
	case ARM_PSCI_0_2_FN_AFFINITY_INFO:
	case ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
	case ARM_PSCI_0_2_FN_SYSTEM_OFF:
	case ARM_PSCI_0_2_FN_SYSTEM_RESET:
	case ARM_PSCI_0_2_FN64_CPU_ON:
	case ARM_PSCI_0_2_FN64_AFFINITY_INFO:

	/* PSCI 1.0 interface */
	case ARM_PSCI_1_0_FN_PSCI_FEATURES:

	/* PSCI 1.1 interface */
	case ARM_PSCI_1_1_FN64_SYSTEM_RESET2:
		return 0x0;

	/*
	 * Not implemented:
	 * ARM_PSCI_0_2_FN_CPU_SUSPEND
	 * ARM_PSCI_1_0_FN_CPU_FREEZE
	 * ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND
	 * ARM_PSCI_1_0_FN_NODE_HW_STATE
	 * ARM_PSCI_1_0_FN_SYSTEM_SUSPEND
	 * ARM_PSCI_1_0_FN_SET_SUSPEND_MODE
	 * ARM_PSCI_1_0_FN_STAT_RESIDENCY
	 * ARM_PSCI_1_0_FN_STAT_COUNT
	 * ARM_PSCI_0_2_FN64_CPU_SUSPEND
	 * ARM_PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND
	 * ARM_PSCI_1_0_FN64_NODE_HW_STATE
	 * ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND
	 * ARM_PSCI_1_0_FN64_STAT_RESIDENCY
	 * ARM_PSCI_1_0_FN64_STAT_COUNT
	 */

	/* Not required, ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE returns 2 */
	case ARM_PSCI_0_2_FN_MIGRATE:
	case ARM_PSCI_0_2_FN64_MIGRATE:
	/* Not required */
	case ARM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
	case ARM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
	default:
		return ARM_PSCI_RET_NI;
	}
}
