// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright 2019 Broadcom.
 */

#include <drivers/bcm/bnxt.h>
#include <io.h>
#include <kernel/pseudo_ta.h>
#include <mm/core_memprot.h>
#include <mm/core_mmu.h>
#include <string.h>
#include <trace.h>

#define ELOG_SERVICE_UUID \
		{ 0x6272636D, 0x2019, 0x0701, \
		{ 0x42, 0x43, 0x4D, 0x5F, 0x45, 0x4C, 0x4F, 0x47 } }

#define ELOG_TA_NAME			"pta_bcm_elog.ta"

#define BCM_NITRO_FW_LOAD_ADDR			0x8ae00000
#define BCM_NITRO_CRASH_DUMP_BASE_ADDR		0x8b000000

/* Default ELOG buffer size 1MB */
#define DEFAULT_ELOG_BUFFER_SIZE		0x100000

/*
 * Get Error log memory dump
 *
 * [out]    memref[0]:    Destination
 * [in]     value[1].a:   Offset
 */
#define PTA_BCM_ELOG_CMD_GET_ELOG_MEM		1

/*
 * Get nitro crash_dump memory
 *
 * [out]    memref[0]:    Destination
 * [in]     value[1].a:   Offset
 */
#define PTA_BCM_ELOG_CMD_GET_NITRO_CRASH_DUMP	2

/*
 * Load nitro firmware memory
 *
 * [in]     memref[0]:    Nitro f/w image data
 * [in]     value[1].a:   Offset for loading f/w image
 * [in]     value[2].a:   Firmware image size
 */
#define PTA_BCM_ELOG_CMD_LOAD_NITRO_FW		3

#define BCM_ELOG_GLOBAL_METADATA_SIG		0x45524c47

#define MAX_NITRO_CRASH_DUMP_MEM_SIZE		0x2000000
#define MAX_NITRO_FW_LOAD_MEM_SIZE		0x200000

/* Load Nitro fw image to SEC DDR memory */
static TEE_Result pta_elog_load_nitro_fw(uint32_t param_types,
					 TEE_Param params[TEE_NUM_PARAMS])
{
	TEE_Result res = TEE_SUCCESS;
	paddr_t src_paddr = BCM_NITRO_FW_LOAD_ADDR + BNXT_IMG_SECMEM_OFFSET;
	vaddr_t src_vaddr = 0;
	uint32_t offset = 0, sz = 0;
	char *buf = NULL;
	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
						   TEE_PARAM_TYPE_VALUE_INPUT,
						   TEE_PARAM_TYPE_VALUE_INPUT,
						   TEE_PARAM_TYPE_NONE);

	if (exp_param_types != param_types) {
		EMSG("Invalid Param types");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	/* Check if firmware file size exceeds reserved memory size */
	if (params[2].value.a > MAX_NITRO_FW_LOAD_MEM_SIZE) {
		EMSG("Invalid access");
		return TEE_ERROR_EXCESS_DATA;
	}

	offset = params[1].value.a;

	/*
	 * Check if offset is within memory range reserved for nitro firmware
	 * minus default size of buffer
	 */
	if (offset > MAX_NITRO_FW_LOAD_MEM_SIZE - DEFAULT_ELOG_BUFFER_SIZE) {
		EMSG("Invalid access");
		return TEE_ERROR_ACCESS_DENIED;
	}

	src_vaddr = (vaddr_t)phys_to_virt((uintptr_t)src_paddr + offset,
					  MEM_AREA_RAM_SEC);

	buf = params[0].memref.buffer;
	sz = params[0].memref.size;

	memcpy((char *)src_vaddr, buf, sz);

	cache_op_inner(DCACHE_AREA_CLEAN, (void *)src_vaddr, sz);

	return res;
}

static uint32_t get_dump_data(vaddr_t src, TEE_Param params[TEE_NUM_PARAMS])
{
	char *buf = NULL;
	uint32_t sz = 0;

	buf = params[0].memref.buffer;
	sz = params[0].memref.size;

	/*
	 * If request size exceeds default buf size
	 * override request size to default DEFAULT_ELOG_BUFFER_SIZE
	 */
	if (sz > DEFAULT_ELOG_BUFFER_SIZE)
		sz = DEFAULT_ELOG_BUFFER_SIZE;

	DMSG("buf %p sz 0x%x", buf, sz);

	memcpy(buf, (char *)src, sz);

	params[0].memref.size = sz;

	return sz;
}

/* Copy nitro crash dump data */
static TEE_Result pta_elog_nitro_crash_dump(uint32_t param_types,
					    TEE_Param params[TEE_NUM_PARAMS])
{
	TEE_Result res = TEE_SUCCESS;
	paddr_t src_paddr = BCM_NITRO_CRASH_DUMP_BASE_ADDR;
	vaddr_t src_vaddr = 0;
	uint32_t offset = 0;
	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
						   TEE_PARAM_TYPE_VALUE_INPUT,
						   TEE_PARAM_TYPE_NONE,
						   TEE_PARAM_TYPE_NONE);

	if (exp_param_types != param_types) {
		EMSG("Invalid Param types");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	offset = params[1].value.a;

	/*
	 * Check if offset is within memory range reserved for nitro crash dump
	 * minus default size of buffer
	 */
	if (offset > MAX_NITRO_CRASH_DUMP_MEM_SIZE - DEFAULT_ELOG_BUFFER_SIZE) {
		EMSG("Invalid access");
		return TEE_ERROR_ACCESS_DENIED;
	}

	src_vaddr = (vaddr_t)phys_to_virt((uintptr_t)src_paddr + offset,
					  MEM_AREA_RAM_SEC);

	/* TODO : check if NITRO_CRASH_DUMP is available */

	cache_op_inner(DCACHE_AREA_INVALIDATE,
		       (void *)src_vaddr, DEFAULT_ELOG_BUFFER_SIZE);

	get_dump_data(src_vaddr, params);

	return res;
}

/* Copy soc error log data */
static TEE_Result pta_elog_dump(uint32_t param_types,
				TEE_Param params[TEE_NUM_PARAMS])
{
	TEE_Result res = TEE_SUCCESS;
	paddr_t src_paddr = CFG_BCM_ELOG_BASE;
	vaddr_t src_vaddr = 0;
	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
						   TEE_PARAM_TYPE_VALUE_INPUT,
						   TEE_PARAM_TYPE_NONE,
						   TEE_PARAM_TYPE_NONE);

	if (exp_param_types != param_types) {
		EMSG("Invalid Param types");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	src_vaddr = (vaddr_t)phys_to_virt(src_paddr, MEM_AREA_RAM_NSEC);

	/* Validate if Error logs are present */
	if ((*(uint32_t *)src_vaddr) != BCM_ELOG_GLOBAL_METADATA_SIG) {
		EMSG("Elog Not setup");
		return TEE_ERROR_NOT_SUPPORTED;
	}

	get_dump_data(src_vaddr, params);

	return res;
}

static TEE_Result invoke_command(void *session_context __unused,
				 uint32_t cmd_id,
				 uint32_t param_types,
				 TEE_Param params[TEE_NUM_PARAMS])
{
	TEE_Result res = TEE_SUCCESS;

	DMSG("command entry point[%d] for \"%s\"", cmd_id, ELOG_TA_NAME);

	switch (cmd_id) {
	case PTA_BCM_ELOG_CMD_GET_ELOG_MEM:
		res = pta_elog_dump(param_types, params);
		break;
	case PTA_BCM_ELOG_CMD_GET_NITRO_CRASH_DUMP:
		res = pta_elog_nitro_crash_dump(param_types, params);
		break;
	case PTA_BCM_ELOG_CMD_LOAD_NITRO_FW:
		res = pta_elog_load_nitro_fw(param_types, params);
		break;
	default:
		EMSG("cmd: %d Not supported %s", cmd_id, ELOG_TA_NAME);
		res = TEE_ERROR_NOT_SUPPORTED;
		break;
	}

	return res;
}

pseudo_ta_register(.uuid = ELOG_SERVICE_UUID,
		   .name = ELOG_TA_NAME,
		   .flags = PTA_DEFAULT_FLAGS,
		   .invoke_command_entry_point = invoke_command);
