blob: e7ad711fd97d8cbdb0fa5cf47937dff7aa0ca4c3 [file] [log] [blame]
Soby Mathewb48349e2015-06-29 16:30:12 +01001/*
Soby Mathew4067dc32015-05-05 16:33:16 +01002 * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
Soby Mathewb48349e2015-06-29 16:30:12 +01003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef __PSCI_PRIVATE_H__
32#define __PSCI_PRIVATE_H__
33
34#include <arch.h>
35#include <bakery_lock.h>
36#include <bl_common.h>
Soby Mathew82dcc032015-04-08 17:42:06 +010037#include <cpu_data.h>
Soby Mathewb48349e2015-06-29 16:30:12 +010038#include <psci.h>
Soby Mathew82dcc032015-04-08 17:42:06 +010039#include <spinlock.h>
Soby Mathewb48349e2015-06-29 16:30:12 +010040
41/*
42 * The following helper macros abstract the interface to the Bakery
43 * Lock API.
44 */
45#if USE_COHERENT_MEM
Soby Mathew82dcc032015-04-08 17:42:06 +010046#define psci_lock_init(non_cpu_pd_node, idx) \
47 bakery_lock_init(&(non_cpu_pd_node)[(idx)].lock)
48#define psci_lock_get(non_cpu_pd_node) \
49 bakery_lock_get(&((non_cpu_pd_node)->lock))
50#define psci_lock_release(non_cpu_pd_node) \
51 bakery_lock_release(&((non_cpu_pd_node)->lock))
Soby Mathewb48349e2015-06-29 16:30:12 +010052#else
Soby Mathew82dcc032015-04-08 17:42:06 +010053#define psci_lock_init(non_cpu_pd_node, idx) \
54 ((non_cpu_pd_node)[(idx)].lock_index = (idx))
55#define psci_lock_get(non_cpu_pd_node) \
56 bakery_lock_get((non_cpu_pd_node)->lock_index, \
57 CPU_DATA_PSCI_LOCK_OFFSET)
58#define psci_lock_release(non_cpu_pd_node) \
59 bakery_lock_release((non_cpu_pd_node)->lock_index, \
60 CPU_DATA_PSCI_LOCK_OFFSET)
Soby Mathewb48349e2015-06-29 16:30:12 +010061#endif
62
63/*
64 * The PSCI capability which are provided by the generic code but does not
65 * depend on the platform or spd capabilities.
66 */
67#define PSCI_GENERIC_CAP \
68 (define_psci_cap(PSCI_VERSION) | \
69 define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) | \
70 define_psci_cap(PSCI_FEATURES))
71
72/*
73 * The PSCI capabilities mask for 64 bit functions.
74 */
75#define PSCI_CAP_64BIT_MASK \
76 (define_psci_cap(PSCI_CPU_SUSPEND_AARCH64) | \
77 define_psci_cap(PSCI_CPU_ON_AARCH64) | \
78 define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) | \
79 define_psci_cap(PSCI_MIG_AARCH64) | \
80 define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64) | \
81 define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64))
82
Soby Mathew82dcc032015-04-08 17:42:06 +010083/*
84 * Helper macros for the CPU level spinlocks
85 */
86#define psci_spin_lock_cpu(idx) spin_lock(&psci_cpu_pd_nodes[idx].cpu_lock)
87#define psci_spin_unlock_cpu(idx) spin_unlock(&psci_cpu_pd_nodes[idx].cpu_lock)
Soby Mathewb48349e2015-06-29 16:30:12 +010088
89/*******************************************************************************
Soby Mathew82dcc032015-04-08 17:42:06 +010090 * The following two data structures implement the power domain tree. The tree
91 * is used to track the state of all the nodes i.e. power domain instances
92 * described by the platform. The tree consists of nodes that describe CPU power
93 * domains i.e. leaf nodes and all other power domains which are parents of a
94 * CPU power domain i.e. non-leaf nodes.
Soby Mathewb48349e2015-06-29 16:30:12 +010095 ******************************************************************************/
Soby Mathew82dcc032015-04-08 17:42:06 +010096typedef struct non_cpu_pwr_domain_node {
97 /*
98 * Index of the first CPU power domain node level 0 which has this node
99 * as its parent.
100 */
101 unsigned int cpu_start_idx;
102
103 /*
104 * Number of CPU power domains which are siblings of the domain indexed
105 * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx
106 * -> cpu_start_idx + ncpus' have this node as their parent.
107 */
108 unsigned int ncpus;
109
110 /*
111 * Index of the parent power domain node.
112 * TODO: Figure out whether to whether using pointer is more efficient.
113 */
114 unsigned int parent_node;
115
Soby Mathewb48349e2015-06-29 16:30:12 +0100116 unsigned char ref_count;
Soby Mathewb48349e2015-06-29 16:30:12 +0100117 unsigned char level;
118#if USE_COHERENT_MEM
119 bakery_lock_t lock;
120#else
121 /* For indexing the bakery_info array in per CPU data */
Soby Mathew82dcc032015-04-08 17:42:06 +0100122 unsigned char lock_index;
Soby Mathewb48349e2015-06-29 16:30:12 +0100123#endif
Soby Mathew82dcc032015-04-08 17:42:06 +0100124} non_cpu_pd_node_t;
Soby Mathewb48349e2015-06-29 16:30:12 +0100125
Soby Mathew82dcc032015-04-08 17:42:06 +0100126typedef struct cpu_pwr_domain_node {
127 unsigned long mpidr;
Soby Mathewb48349e2015-06-29 16:30:12 +0100128
Soby Mathew82dcc032015-04-08 17:42:06 +0100129 /*
130 * Index of the parent power domain node.
131 * TODO: Figure out whether to whether using pointer is more efficient.
132 */
133 unsigned int parent_node;
134
135 /*
136 * A CPU power domain does not require state coordination like its
137 * parent power domains. Hence this node does not include a bakery
138 * lock. A spinlock is required by the CPU_ON handler to prevent a race
139 * when multiple CPUs try to turn ON the same target CPU.
140 */
141 spinlock_t cpu_lock;
142} cpu_pd_node_t;
143
144typedef void (*pwrlvl_power_on_finisher_t)(unsigned int cpu_idx,
145 int max_off_pwrlvl);
Soby Mathewb48349e2015-06-29 16:30:12 +0100146
147/*******************************************************************************
148 * Data prototypes
149 ******************************************************************************/
150extern const plat_pm_ops_t *psci_plat_pm_ops;
Soby Mathew82dcc032015-04-08 17:42:06 +0100151extern non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS];
152extern cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT];
Soby Mathewb48349e2015-06-29 16:30:12 +0100153extern uint32_t psci_caps;
154
155/*******************************************************************************
156 * SPD's power management hooks registered with PSCI
157 ******************************************************************************/
158extern const spd_pm_ops_t *psci_spd_pm;
159
160/*******************************************************************************
161 * Function prototypes
162 ******************************************************************************/
163/* Private exported functions from psci_common.c */
Soby Mathew82dcc032015-04-08 17:42:06 +0100164unsigned short psci_get_state(unsigned int idx, int level);
165unsigned short psci_get_phys_state(unsigned int idx, int level);
166void psci_set_state(unsigned int idx, unsigned short state, int level);
Soby Mathew12d0d002015-04-09 13:40:55 +0100167int psci_validate_mpidr(unsigned long mpidr);
Soby Mathew4067dc32015-05-05 16:33:16 +0100168int get_power_on_target_pwrlvl(void);
169void psci_power_up_finish(int end_pwrlvl,
170 pwrlvl_power_on_finisher_t pon_handler);
Soby Mathewb48349e2015-06-29 16:30:12 +0100171int psci_get_ns_ep_info(entry_point_info_t *ep,
172 uint64_t entrypoint, uint64_t context_id);
Soby Mathew82dcc032015-04-08 17:42:06 +0100173void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx,
174 int end_lvl,
175 unsigned int node_index[]);
176void psci_do_state_coordination(int end_pwrlvl,
177 unsigned int cpu_idx,
178 uint32_t state);
179void psci_acquire_pwr_domain_locks(int end_pwrlvl,
180 unsigned int cpu_idx);
181void psci_release_pwr_domain_locks(int end_pwrlvl,
182 unsigned int cpu_idx);
Soby Mathew4067dc32015-05-05 16:33:16 +0100183void psci_print_power_domain_map(void);
Soby Mathew82dcc032015-04-08 17:42:06 +0100184uint32_t psci_find_max_phys_off_pwrlvl(uint32_t end_pwrlvl,
185 unsigned int cpu_idx);
Soby Mathewb48349e2015-06-29 16:30:12 +0100186unsigned int psci_is_last_on_cpu(void);
187int psci_spd_migrate_info(uint64_t *mpidr);
188
Soby Mathew82dcc032015-04-08 17:42:06 +0100189/* Private exported functions from psci_on.c */
Soby Mathew4067dc32015-05-05 16:33:16 +0100190int psci_cpu_on_start(unsigned long target_cpu,
Soby Mathew82dcc032015-04-08 17:42:06 +0100191 entry_point_info_t *ep,
192 int end_pwrlvl);
Soby Mathewb48349e2015-06-29 16:30:12 +0100193
Soby Mathew82dcc032015-04-08 17:42:06 +0100194void psci_cpu_on_finish(unsigned int cpu_idx,
195 int max_off_pwrlvl);
Soby Mathew6590ce22015-06-30 11:00:24 +0100196
Soby Mathew4067dc32015-05-05 16:33:16 +0100197/* Private exported functions from psci_cpu_off.c */
198int psci_do_cpu_off(int end_pwrlvl);
Soby Mathewb48349e2015-06-29 16:30:12 +0100199
Soby Mathew82dcc032015-04-08 17:42:06 +0100200/* Private exported functions from psci_suspend.c */
Soby Mathew4067dc32015-05-05 16:33:16 +0100201void psci_cpu_suspend_start(entry_point_info_t *ep,
202 int end_pwrlvl);
Soby Mathew82dcc032015-04-08 17:42:06 +0100203void psci_cpu_suspend_finish(unsigned int cpu_idx,
204 int max_off_pwrlvl);
Soby Mathew6590ce22015-06-30 11:00:24 +0100205
Soby Mathewb48349e2015-06-29 16:30:12 +0100206void psci_set_suspend_power_state(unsigned int power_state);
207
208/* Private exported functions from psci_helpers.S */
Soby Mathew4067dc32015-05-05 16:33:16 +0100209void psci_do_pwrdown_cache_maintenance(uint32_t pwr_level);
Soby Mathewb48349e2015-06-29 16:30:12 +0100210void psci_do_pwrup_cache_maintenance(void);
211
212/* Private exported functions from psci_system_off.c */
213void __dead2 psci_system_off(void);
214void __dead2 psci_system_reset(void);
215
216#endif /* __PSCI_PRIVATE_H__ */