/*
 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of ARM nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <arch_helpers.h>
#include <assert.h>
#include <platform.h>
#include <platform_def.h>
#include <psci.h>

/* The power domain tree descriptor */
static unsigned char power_domain_tree_desc
				[PLATFORM_NUM_AFFS - PLATFORM_CORE_COUNT + 1];

/*******************************************************************************
 * Simple routine to set the id of an affinity instance at a given level
 * in the mpidr. The assumption is that the affinity level and the power
 * domain level are the same.
 ******************************************************************************/
unsigned long mpidr_set_aff_inst(unsigned long mpidr,
				 unsigned char aff_inst,
				 int aff_lvl)
{
	unsigned long aff_shift;

	assert(aff_lvl <= MPIDR_AFFLVL3);

	/*
	 * Decide the number of bits to shift by depending upon
	 * the power level
	 */
	aff_shift = get_afflvl_shift(aff_lvl);

	/* Clear the existing power instance & set the new one*/
	mpidr &= ~((unsigned long)MPIDR_AFFLVL_MASK << aff_shift);
	mpidr |= (unsigned long)aff_inst << aff_shift;

	return mpidr;
}

/******************************************************************************
 * This function uses insertion sort to sort a given list of mpidr's in the
 * ascending order of the index returned by platform_get_core_pos.
 *****************************************************************************/
void sort_mpidr_by_cpu_idx(unsigned int aff_count, unsigned long mpidr_list[])
{
	int i, j;
	unsigned long temp_mpidr;

	for (i = 1; i < aff_count; i++) {
		temp_mpidr = mpidr_list[i];

		for (j = i;
			j > 0 &&
			platform_get_core_pos(mpidr_list[j-1]) >
			platform_get_core_pos(temp_mpidr);
			j--)
			mpidr_list[j] = mpidr_list[j-1];

		mpidr_list[j] = temp_mpidr;
	}
}

/*******************************************************************************
 * The compatibility routine to construct the power domain tree description.
 * The assumption made is that the power domains correspond to affinity
 * instances on the platform. This routine's aim is to traverse to the target
 * affinity level and populate the number of siblings at that level in
 * 'power_domain_tree_desc' array. It uses the current affinity level to keep
 * track of how many levels from the root of the tree have been traversed.
 * If the current affinity level != target affinity level, then the platform
 * is asked to return the number of children that each affinity instance has
 * at the current affinity level. Traversal is then done for each child at the
 * next lower level i.e. current affinity level - 1.
 *
 * The power domain description needs to be constructed in such a way that
 * affinity instances containing CPUs with lower cpu indices need to be
 * described first.  Hence when traversing the power domain levels, the list
 * of mpidrs at that power domain level is sorted in the ascending order of CPU
 * indices before the lower levels are recursively described.
 *
 * CAUTION: This routine assumes that affinity instance ids are allocated in a
 * monotonically increasing manner at each affinity level in a mpidr starting
 * from 0. If the platform breaks this assumption then this code will have to
 * be reworked accordingly.
 ******************************************************************************/
static unsigned int init_pwr_domain_tree_desc(unsigned long mpidr,
					unsigned int affmap_idx,
					int cur_afflvl,
					int tgt_afflvl)
{
	unsigned int ctr, aff_count;

	/*
	 * Temporary list to hold the MPIDR list at a particular power domain
	 * level so as to sort them.
	 */
	unsigned long mpidr_list[PLATFORM_CORE_COUNT];

	assert(cur_afflvl >= tgt_afflvl);

	/*
	 * Find the number of siblings at the current power level &
	 * assert if there are none 'cause then we have been invoked with
	 * an invalid mpidr.
	 */
	aff_count = plat_get_aff_count(cur_afflvl, mpidr);
	assert(aff_count);

	if (tgt_afflvl < cur_afflvl) {
		for (ctr = 0; ctr < aff_count; ctr++) {
			mpidr_list[ctr] = mpidr_set_aff_inst(mpidr, ctr,
						cur_afflvl);
		}

		/* Need to sort mpidr list according to CPU index */
		sort_mpidr_by_cpu_idx(aff_count, mpidr_list);
		for (ctr = 0; ctr < aff_count; ctr++) {
			affmap_idx = init_pwr_domain_tree_desc(mpidr_list[ctr],
						       affmap_idx,
						       cur_afflvl - 1,
						       tgt_afflvl);
		}
	} else {
		power_domain_tree_desc[affmap_idx++] = aff_count;
	}
	return affmap_idx;
}


/*******************************************************************************
 * This function constructs the topology tree description at runtime
 * and returns it. The assumption made is that the power domains correspond
 * to affinity instances on the platform.
 ******************************************************************************/
const unsigned char *plat_get_power_domain_tree_desc(void)
{
	int afflvl, affmap_idx;

	/*
	 * We assume that the platform allocates affinity instance ids from
	 * 0 onwards at each affinity level in the mpidr. FIRST_MPIDR = 0.0.0.0
	 */
	affmap_idx = 0;
	for (afflvl = PLATFORM_MAX_AFFLVL; afflvl >= MPIDR_AFFLVL0; afflvl--) {
		affmap_idx = init_pwr_domain_tree_desc(FIRST_MPIDR,
					       affmap_idx,
					       PLATFORM_MAX_AFFLVL,
					       afflvl);
	}

	assert(affmap_idx == (PLATFORM_NUM_AFFS - PLATFORM_CORE_COUNT + 1));

	return power_domain_tree_desc;
}

/******************************************************************************
 * The compatibility helper function for plat_core_pos_by_mpidr(). It
 * validates the 'mpidr' by making sure that it is within acceptable bounds
 * for the platform and queries the platform layer whether the CPU specified
 * by the mpidr is present or not. If present, it returns the index of the
 * core corresponding to the 'mpidr'. Else it returns -1.
 *****************************************************************************/
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
	unsigned long shift, aff_inst;
	int i;

	/* Ignore the Reserved bits and U bit in MPIDR */
	mpidr &= MPIDR_AFFINITY_MASK;

	/*
	 * Check if any affinity field higher than
	 * the PLATFORM_MAX_AFFLVL is set.
	 */
	shift = get_afflvl_shift(PLATFORM_MAX_AFFLVL + 1);
	if (mpidr >> shift)
		return -1;

	for (i = PLATFORM_MAX_AFFLVL; i >= 0; i--) {
		shift = get_afflvl_shift(i);
		aff_inst = ((mpidr &
			((unsigned long)MPIDR_AFFLVL_MASK << shift)) >> shift);
		if (aff_inst >= plat_get_aff_count(i, mpidr))
			return -1;
	}

	if (plat_get_aff_state(0, mpidr) == PSCI_AFF_ABSENT)
		return -1;

	return platform_get_core_pos(mpidr);
}
