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

#include <assert.h>

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

#if ENABLE_PSCI_STAT && ENABLE_PMF
#pragma weak plat_psci_stat_accounting_start
#pragma weak plat_psci_stat_accounting_stop
#pragma weak plat_psci_stat_get_residency

/* Maximum time-stamp value read from architectural counters */
#ifdef __aarch64__
#define MAX_TS	UINT64_MAX
#else
#define MAX_TS	UINT32_MAX
#endif

/* Following are used as ID's to capture time-stamp */
#define PSCI_STAT_ID_ENTER_LOW_PWR		0
#define PSCI_STAT_ID_EXIT_LOW_PWR		1
#define PSCI_STAT_TOTAL_IDS			2

PMF_DECLARE_CAPTURE_TIMESTAMP(psci_svc)
PMF_DECLARE_GET_TIMESTAMP(psci_svc)
PMF_REGISTER_SERVICE(psci_svc, PMF_PSCI_STAT_SVC_ID, PSCI_STAT_TOTAL_IDS,
	PMF_STORE_ENABLE)

/*
 * This function calculates the stats residency in microseconds,
 * taking in account the wrap around condition.
 */
static u_register_t calc_stat_residency(unsigned long long pwrupts,
	unsigned long long pwrdnts)
{
	/* The divisor to use to convert raw timestamp into microseconds. */
	u_register_t residency_div;
	u_register_t res;

	/*
	 * Calculate divisor so that it can be directly used to
	 * convert time-stamp into microseconds.
	 */
	residency_div = read_cntfrq_el0() / MHZ_TICKS_PER_SEC;
	assert(residency_div > 0U);

	if (pwrupts < pwrdnts)
		res = MAX_TS - pwrdnts + pwrupts;
	else
		res = pwrupts - pwrdnts;

	return res / residency_div;
}

/*
 * Capture timestamp before entering a low power state.
 * Cache maintenance may be needed when reading these timestamps.
 */
void plat_psci_stat_accounting_start(
	__unused const psci_power_state_t *state_info)
{
	assert(state_info != NULL);
	PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
		PMF_CACHE_MAINT);
}

/*
 * Capture timestamp after exiting a low power state.
 * Cache maintenance may be needed when reading these timestamps.
 */
void plat_psci_stat_accounting_stop(
	__unused const psci_power_state_t *state_info)
{
	assert(state_info != NULL);
	PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR,
		PMF_CACHE_MAINT);
}

/*
 * Calculate the residency for the given level and power state
 * information.
 */
u_register_t plat_psci_stat_get_residency(unsigned int lvl,
	const psci_power_state_t *state_info,
	unsigned int last_cpu_idx)
{
	plat_local_state_t state;
	unsigned long long pwrup_ts = 0, pwrdn_ts = 0;
	unsigned int pmf_flags;

	assert((lvl >= PSCI_CPU_PWR_LVL) && (lvl <= PLAT_MAX_PWR_LVL));
	assert(state_info != NULL);
	assert(last_cpu_idx <= PLATFORM_CORE_COUNT);

	if (lvl == PSCI_CPU_PWR_LVL)
		assert(last_cpu_idx == plat_my_core_pos());

	/*
	 * If power down is requested, then timestamp capture will
	 * be with caches OFF.  Hence we have to do cache maintenance
	 * when reading the timestamp.
	 */
	state = state_info->pwr_domain_state[PSCI_CPU_PWR_LVL];
	if (is_local_state_off(state) != 0) {
		pmf_flags = PMF_CACHE_MAINT;
	} else {
		assert(is_local_state_retn(state) == 1);
		pmf_flags = PMF_NO_CACHE_MAINT;
	}

	PMF_GET_TIMESTAMP_BY_INDEX(psci_svc,
		PSCI_STAT_ID_ENTER_LOW_PWR,
		last_cpu_idx,
		pmf_flags,
		pwrdn_ts);

	PMF_GET_TIMESTAMP_BY_INDEX(psci_svc,
		PSCI_STAT_ID_EXIT_LOW_PWR,
		plat_my_core_pos(),
		pmf_flags,
		pwrup_ts);

	return calc_stat_residency(pwrup_ts, pwrdn_ts);
}
#endif /* ENABLE_PSCI_STAT && ENABLE_PMF */

/*
 * The PSCI generic code uses this API to let the platform participate in state
 * coordination during a power management operation. It compares the platform
 * specific local power states requested by each cpu for a given power domain
 * and returns the coordinated target power state that the domain should
 * enter. A platform assigns a number to a local power state. This default
 * implementation assumes that the platform assigns these numbers in order of
 * increasing depth of the power state i.e. for two power states X & Y, if X < Y
 * then X represents a shallower power state than Y. As a result, the
 * coordinated target local power state for a power domain will be the minimum
 * of the requested local power states.
 */
plat_local_state_t plat_get_target_pwr_state(unsigned int lvl,
					     const plat_local_state_t *states,
					     unsigned int ncpu)
{
	plat_local_state_t target = PLAT_MAX_OFF_STATE, temp;
	const plat_local_state_t *st = states;
	unsigned int n = ncpu;

	assert(ncpu > 0U);

	do {
		temp = *st;
		st++;
		if (temp < target)
			target = temp;
		n--;
	} while (n > 0U);

	return target;
}
