/*
 * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

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

#include <arch.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/pmf/pmf.h>
#include <lib/utils_def.h>
#include <plat/common/platform.h>

/*******************************************************************************
 * The 'pmf_svc_descs' array holds the PMF service descriptors exported by
 * services by placing them in the 'pmf_svc_descs' linker section.
 * The 'pmf_svc_descs_indices' array holds the index of a descriptor in the
 * 'pmf_svc_descs' array. The TIF[15:10] bits in the time-stamp id are used
 * to get an index into the 'pmf_svc_descs_indices' array. This gives the
 * index of the descriptor in the 'pmf_svc_descs' array  which contains the
 * service function pointers.
 ******************************************************************************/

IMPORT_SYM(uintptr_t, __PMF_SVC_DESCS_START__,		PMF_SVC_DESCS_START);
IMPORT_SYM(uintptr_t, __PMF_SVC_DESCS_END__,		PMF_SVC_DESCS_END);
IMPORT_SYM(uintptr_t, __PMF_PERCPU_TIMESTAMP_END__,	PMF_PERCPU_TIMESTAMP_END);
IMPORT_SYM(uintptr_t,  __PMF_TIMESTAMP_START__,		PMF_TIMESTAMP_ARRAY_START);

#define PMF_PERCPU_TIMESTAMP_SIZE	(PMF_PERCPU_TIMESTAMP_END - PMF_TIMESTAMP_ARRAY_START)

#define PMF_SVC_DESCS_MAX		10

/*
 * This is used to traverse through registered PMF services.
 */
static pmf_svc_desc_t *pmf_svc_descs;

/*
 * This array is used to store registered PMF services in sorted order.
 */
static int pmf_svc_descs_indices[PMF_SVC_DESCS_MAX];

/*
 * This is used to track total number of successfully registered PMF services.
 */
static int pmf_num_services;

/*
 * This is the main PMF function that initialize registered
 * PMF services and also sort them in ascending order.
 */
int pmf_setup(void)
{
	int rc, ii, jj = 0;
	int pmf_svc_descs_num, temp_val;

	/* If no PMF services are registered then simply bail out */
	pmf_svc_descs_num = (PMF_SVC_DESCS_END - PMF_SVC_DESCS_START)/
				 sizeof(pmf_svc_desc_t);
	if (pmf_svc_descs_num == 0)
		return 0;

	assert(pmf_svc_descs_num < PMF_SVC_DESCS_MAX);

	pmf_svc_descs = (pmf_svc_desc_t *) PMF_SVC_DESCS_START;
	for (ii = 0; ii < pmf_svc_descs_num; ii++) {

		assert(pmf_svc_descs[ii].get_ts != NULL);

		/*
		 * Call the initialization routine for this
		 * PMF service, if it is defined.
		 */
		if (pmf_svc_descs[ii].init != NULL) {
			rc = pmf_svc_descs[ii].init();
			if (rc != 0) {
				WARN("Could not initialize PMF"
					"service %s - skipping \n",
					pmf_svc_descs[ii].name);
				continue;
			}
		}

		/* Update the pmf_svc_descs_indices array */
		pmf_svc_descs_indices[jj++] = ii;
	}

	pmf_num_services = jj;

	/*
	 * Sort the successfully registered PMF services
	 * according to service ID
	 */
	for (ii = 1; ii < pmf_num_services; ii++) {
		for (jj = 0; jj < (pmf_num_services - ii); jj++) {
			if ((pmf_svc_descs[jj].svc_config & PMF_SVC_ID_MASK) >
				(pmf_svc_descs[jj + 1].svc_config &
						PMF_SVC_ID_MASK)) {
				temp_val = pmf_svc_descs_indices[jj];
				pmf_svc_descs_indices[jj] =
						pmf_svc_descs_indices[jj+1];
				pmf_svc_descs_indices[jj+1] = temp_val;
			}
		}
	}

	return 0;
}

/*
 * This function implements binary search to find registered
 * PMF service based on Service ID provided in `tid` argument.
 */
static pmf_svc_desc_t *get_service(unsigned int tid)
{
	int low = 0;
	int mid;
	int high = pmf_num_services;
	unsigned int svc_id = tid & PMF_SVC_ID_MASK;
	int index;
	unsigned int desc_svc_id;

	if (pmf_num_services == 0)
		return NULL;

	assert(pmf_svc_descs != NULL);

	do {
		mid = (low + high) / 2;
		index = pmf_svc_descs_indices[mid];

		desc_svc_id = pmf_svc_descs[index].svc_config & PMF_SVC_ID_MASK;
		if (svc_id < desc_svc_id)
			high = mid - 1;
		if (svc_id > desc_svc_id)
			low = mid + 1;
	} while ((svc_id != desc_svc_id) && (low <= high));

	/*
	 * Make sure the Service found supports the tid range.
	 */
	if ((svc_id == desc_svc_id) && ((tid & PMF_TID_MASK) <
		(pmf_svc_descs[index].svc_config & PMF_TID_MASK)))
		return (pmf_svc_desc_t *)&pmf_svc_descs[index];

	return NULL;
}

/*
 * This function gets the time-stamp value for the PMF services
 * registered for SMC interface based on `tid` and `mpidr`.
 */
int pmf_get_timestamp_smc(unsigned int tid,
		u_register_t mpidr,
		unsigned int flags,
		unsigned long long *ts_value)
{
	pmf_svc_desc_t *svc_desc;
	assert(ts_value != NULL);

	/* Search for registered service. */
	svc_desc = get_service(tid);

	if (svc_desc == NULL) {
		*ts_value = 0;
		return -EINVAL;
	} else {
		/* Call the service time-stamp handler. */
		*ts_value = svc_desc->get_ts(tid, mpidr, flags);
		return 0;
	}
}

/*
 * This function can be used to dump `ts` value for given `tid`.
 * Assumption is that the console is already initialized.
 */
void __pmf_dump_timestamp(unsigned int tid, unsigned long long ts)
{
	printf("PMF:cpu %u	tid %u	ts %llu\n",
		plat_my_core_pos(), tid, ts);
}

/*
 * This function calculate the address identified by
 * `base_addr`, `tid` and `cpuid`.
 */
static inline uintptr_t calc_ts_addr(uintptr_t base_addr,
		unsigned int tid,
		unsigned int cpuid)
{
	assert(cpuid < PLATFORM_CORE_COUNT);
	assert(base_addr >= PMF_TIMESTAMP_ARRAY_START);
	assert(base_addr < ((PMF_TIMESTAMP_ARRAY_START +
		PMF_PERCPU_TIMESTAMP_SIZE) - ((tid & PMF_TID_MASK) *
		sizeof(unsigned long long))));

	base_addr += ((cpuid * PMF_PERCPU_TIMESTAMP_SIZE) +
		((tid & PMF_TID_MASK) * sizeof(unsigned long long)));

	return base_addr;
}

/*
 * This function stores the `ts` value to the storage identified by
 * `base_addr`, `tid` and current cpu id.
 * Note: The timestamp addresses are cache line aligned per cpu
 * and only the owning CPU would ever write into it.
 */
void __pmf_store_timestamp(uintptr_t base_addr,
			unsigned int tid,
			unsigned long long ts)
{
	unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr,
				 tid, plat_my_core_pos());
	*ts_addr = ts;
}

/*
 * This is the cached version of `pmf_store_my_timestamp`
 * Note: The timestamp addresses are cache line aligned per cpu
 * and only the owning CPU would ever write into it.
 */
void __pmf_store_timestamp_with_cache_maint(uintptr_t base_addr,
			unsigned int tid,
			unsigned long long ts)
{
	unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr,
				 tid, plat_my_core_pos());
	*ts_addr = ts;
	flush_dcache_range((uintptr_t)ts_addr, sizeof(unsigned long long));
}

/*
 * This function retrieves the `ts` value from the storage identified by
 * `base_addr`, `tid` and `cpuid`.
 * Note: The timestamp addresses are cache line aligned per cpu.
 */
unsigned long long __pmf_get_timestamp(uintptr_t base_addr,
			unsigned int tid,
			unsigned int cpuid,
			unsigned int flags)
{
	assert(cpuid < PLATFORM_CORE_COUNT);
	unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr,
				tid, cpuid);

	if ((flags & PMF_CACHE_MAINT) != 0U)
		inv_dcache_range((uintptr_t)ts_addr, sizeof(unsigned long long));

	return *ts_addr;
}
