/*
 * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
 * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <errno.h>

#include <bl31/bl31.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/arm/dcc.h>
#include <drivers/console.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
#include <lib/mmio.h>

#include <custom_svc.h>
#include <plat_startup.h>
#include <plat_private.h>
#include <zynqmp_def.h>

#include <common/fdt_fixup.h>
#include <common/fdt_wrappers.h>
#include <libfdt.h>

static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;

/*
 * Return a pointer to the 'entry_point_info' structure of the next image for
 * the security state specified. BL33 corresponds to the non-secure image type
 * while BL32 corresponds to the secure image type. A NULL pointer is returned
 * if the image does not exist.
 */
struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
{
	entry_point_info_t *next_image_info;

	assert(sec_state_is_valid(type));
	if (type == NON_SECURE) {
		next_image_info = &bl33_image_ep_info;
	} else {
		next_image_info = &bl32_image_ep_info;
	}

	return next_image_info;
}

/*
 * Set the build time defaults. We want to do this when doing a JTAG boot
 * or if we can't find any other config data.
 */
static inline void bl31_set_default_config(void)
{
	bl32_image_ep_info.pc = BL32_BASE;
	bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
	bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
					  DISABLE_ALL_EXCEPTIONS);
}

/*
 * Perform any BL31 specific platform actions. Here is an opportunity to copy
 * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before they
 * are lost (potentially). This needs to be done before the MMU is initialized
 * so that the memory layout can be used while creating page tables.
 */
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
				u_register_t arg2, u_register_t arg3)
{
	uint64_t atf_handoff_addr;

	if (ZYNQMP_CONSOLE_IS(cadence) || (ZYNQMP_CONSOLE_IS(cadence1))) {
		/* Register the console to provide early debug support */
		static console_t bl31_boot_console;
		(void)console_cdns_register(ZYNQMP_UART_BASE,
					       zynqmp_get_uart_clk(),
					       ZYNQMP_UART_BAUDRATE,
					       &bl31_boot_console);
		console_set_scope(&bl31_boot_console,
				  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT);
	} else if (ZYNQMP_CONSOLE_IS(dcc)) {
		/* Initialize the dcc console for debug */
		int32_t rc = console_dcc_register();
		if (rc == 0) {
			panic();
		}
	} else {
		ERROR("BL31: No console device found.\n");
	}
	/* Initialize the platform config for future decision making */
	zynqmp_config_setup();

	/*
	 * Do initial security configuration to allow DRAM/device access. On
	 * Base ZYNQMP only DRAM security is programmable (via TrustZone), but
	 * other platforms might have more programmable security devices
	 * present.
	 */

	/* Populate common information for BL32 and BL33 */
	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);

	atf_handoff_addr = mmio_read_32(PMU_GLOBAL_GEN_STORAGE6);

	if (zynqmp_get_bootmode() == ZYNQMP_BOOTMODE_JTAG) {
		bl31_set_default_config();
	} else {
		/* use parameters from FSBL */
		enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info,
							  &bl33_image_ep_info,
							  atf_handoff_addr);
		if (ret != FSBL_HANDOFF_SUCCESS) {
			panic();
		}
	}
	if (bl32_image_ep_info.pc != 0) {
		NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
	}
	if (bl33_image_ep_info.pc != 0) {
		NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
	}

	custom_early_setup();

}

#if ZYNQMP_WDT_RESTART
static interrupt_type_handler_t type_el3_interrupt_table[MAX_INTR_EL3];

int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
{
	/* Validate 'handler' and 'id' parameters */
	if (!handler || id >= MAX_INTR_EL3) {
		return -EINVAL;
	}

	/* Check if a handler has already been registered */
	if (type_el3_interrupt_table[id]) {
		return -EALREADY;
	}

	type_el3_interrupt_table[id] = handler;

	return 0;
}

static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
					  void *handle, void *cookie)
{
	uint32_t intr_id;
	interrupt_type_handler_t handler;

	intr_id = plat_ic_get_pending_interrupt_id();
	handler = type_el3_interrupt_table[intr_id];
	if (handler != NULL) {
		handler(intr_id, flags, handle, cookie);
	}

	return 0;
}
#endif

#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
static void prepare_dtb(void)
{
	void *dtb = (void *)XILINX_OF_BOARD_DTB_ADDR;
	int ret;

	/* Return if no device tree is detected */
	if (fdt_check_header(dtb) != 0) {
		NOTICE("Can't read DT at %p\n", dtb);
		return;
	}

	ret = fdt_open_into(dtb, dtb, XILINX_OF_BOARD_DTB_MAX_SIZE);
	if (ret < 0) {
		ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret);
		return;
	}

	if (dt_add_psci_node(dtb)) {
		ERROR("Failed to add PSCI Device Tree node\n");
		return;
	}

	if (dt_add_psci_cpu_enable_methods(dtb)) {
		ERROR("Failed to add PSCI cpu enable methods in Device Tree\n");
		return;
	}

	/* Reserve memory used by Trusted Firmware. */
	if (fdt_add_reserved_memory(dtb, "tf-a", BL31_BASE,
				    BL31_LIMIT - BL31_BASE + 1)) {
		WARN("Failed to add reserved memory nodes for BL31 to DT.\n");
	}

	ret = fdt_pack(dtb);
	if (ret < 0) {
		ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret);
	}

	clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb));
	INFO("Changed device tree to advertise PSCI and reserved memories.\n");
}
#endif

void bl31_platform_setup(void)
{
#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
	prepare_dtb();
#endif

	/* Initialize the gic cpu and distributor interfaces */
	plat_arm_gic_driver_init();
	plat_arm_gic_init();
}

void bl31_plat_runtime_setup(void)
{
#if ZYNQMP_WDT_RESTART
	uint64_t flags = 0;
	uint64_t rc;

	set_interrupt_rm_flag(flags, NON_SECURE);
	rc = register_interrupt_type_handler(INTR_TYPE_EL3,
					     rdo_el3_interrupt_handler, flags);
	if (rc) {
		panic();
	}
#endif

	custom_runtime_setup();
}

/*
 * Perform the very early platform specific architectural setup here.
 */
void bl31_plat_arch_setup(void)
{
	plat_arm_interconnect_init();
	plat_arm_interconnect_enter_coherency();

	const mmap_region_t bl_regions[] = {
#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
		MAP_REGION_FLAT(XILINX_OF_BOARD_DTB_ADDR, XILINX_OF_BOARD_DTB_MAX_SIZE,
			MT_MEMORY | MT_RW | MT_NS),
#endif
		MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
			MT_MEMORY | MT_RW | MT_SECURE),
		MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
				MT_CODE | MT_SECURE),
		MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE,
				MT_RO_DATA | MT_SECURE),
		MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
				BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
				MT_DEVICE | MT_RW | MT_SECURE),
		{0}
	};

	custom_mmap_add();

	setup_page_tables(bl_regions, plat_arm_get_mmap());
	enable_mmu_el3(0);
}
