1 /*
2  * Copyright (C) 2018 Marvell International Ltd.
3  *
4  * SPDX-License-Identifier:     BSD-3-Clause
5  * https://spdx.org/licenses
6  */
7 
8 #include <plat_marvell.h>
9 
10 /* The power domain tree descriptor */
11 unsigned char marvell_power_domain_tree_desc[PLAT_MARVELL_CLUSTER_COUNT + 1];
12 
13 /*****************************************************************************
14  * This function dynamically constructs the topology according to
15  * PLAT_MARVELL_CLUSTER_COUNT and returns it.
16  *****************************************************************************
17  */
plat_get_power_domain_tree_desc(void)18 const unsigned char *plat_get_power_domain_tree_desc(void)
19 {
20 	int i;
21 
22 	/*
23 	 * The power domain tree does not have a single system level power
24 	 * domain i.e. a single root node. The first entry in the power domain
25 	 * descriptor specifies the number of power domains at the highest power
26 	 * level.
27 	 * For Marvell Platform this is the number of cluster power domains.
28 	 */
29 	marvell_power_domain_tree_desc[0] = PLAT_MARVELL_CLUSTER_COUNT;
30 
31 	for (i = 0; i < PLAT_MARVELL_CLUSTER_COUNT; i++)
32 		marvell_power_domain_tree_desc[i + 1] =
33 					PLAT_MARVELL_CLUSTER_CORE_COUNT;
34 
35 	return marvell_power_domain_tree_desc;
36 }
37 
38 /*****************************************************************************
39  * This function validates an MPIDR by checking whether it falls within the
40  * acceptable bounds. An error code (-1) is returned if an incorrect mpidr
41  * is passed.
42  *****************************************************************************
43  */
marvell_check_mpidr(u_register_t mpidr)44 int marvell_check_mpidr(u_register_t mpidr)
45 {
46 	unsigned int nb_id, cluster_id, cpu_id;
47 
48 	mpidr &= MPIDR_AFFINITY_MASK;
49 
50 	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK |
51 	    MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT))
52 		return -1;
53 
54 	/* Get north bridge ID */
55 	nb_id = MPIDR_AFFLVL3_VAL(mpidr);
56 	cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
57 	cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
58 
59 	if (nb_id >= PLAT_MARVELL_CLUSTER_COUNT)
60 		return -1;
61 
62 	if (cluster_id >= PLAT_MARVELL_CLUSTER_COUNT)
63 		return -1;
64 
65 	if (cpu_id >= PLAT_MARVELL_CLUSTER_CORE_COUNT)
66 		return -1;
67 
68 	return 0;
69 }
70 
71 /*****************************************************************************
72  * This function implements a part of the critical interface between the PSCI
73  * generic layer and the platform that allows the former to query the platform
74  * to convert an MPIDR to a unique linear index. An error code (-1) is returned
75  * in case the MPIDR is invalid.
76  *****************************************************************************
77  */
plat_core_pos_by_mpidr(u_register_t mpidr)78 int plat_core_pos_by_mpidr(u_register_t mpidr)
79 {
80 	if (marvell_check_mpidr(mpidr) == -1)
81 		return -1;
82 
83 	return plat_marvell_calc_core_pos(mpidr);
84 }
85