blob: a70a21ae858686298cb75e19fa3b96865aa205e1 [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Dan Handleye83b0ca2014-01-14 18:17:09 +00002 * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +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#include <stdio.h>
32#include <string.h>
33#include <assert.h>
34#include <arch_helpers.h>
35#include <console.h>
36#include <platform.h>
37#include <psci_private.h>
38
39/*******************************************************************************
40 * PSCI frontend api for servicing SMCs. Described in the PSCI spec.
41 ******************************************************************************/
42int psci_cpu_on(unsigned long target_cpu,
43 unsigned long entrypoint,
44 unsigned long context_id)
45
46{
47 int rc;
Achin Gupta0959db52013-12-02 17:33:04 +000048 unsigned int start_afflvl, end_afflvl;
Achin Gupta4f6ad662013-10-25 09:08:21 +010049
50 /* Determine if the cpu exists of not */
51 rc = psci_validate_mpidr(target_cpu, MPIDR_AFFLVL0);
52 if (rc != PSCI_E_SUCCESS) {
53 goto exit;
54 }
55
Achin Gupta0959db52013-12-02 17:33:04 +000056 /*
57 * To turn this cpu on, specify which affinity
58 * levels need to be turned on
59 */
60 start_afflvl = MPIDR_AFFLVL0;
61 end_afflvl = get_max_afflvl();
Achin Gupta4f6ad662013-10-25 09:08:21 +010062 rc = psci_afflvl_on(target_cpu,
63 entrypoint,
64 context_id,
65 start_afflvl,
Achin Gupta0959db52013-12-02 17:33:04 +000066 end_afflvl);
Achin Gupta4f6ad662013-10-25 09:08:21 +010067
68exit:
69 return rc;
70}
71
72unsigned int psci_version(void)
73{
74 return PSCI_MAJOR_VER | PSCI_MINOR_VER;
75}
76
77int psci_cpu_suspend(unsigned int power_state,
78 unsigned long entrypoint,
79 unsigned long context_id)
80{
81 int rc;
82 unsigned long mpidr;
Achin Gupta0959db52013-12-02 17:33:04 +000083 unsigned int target_afflvl, pstate_type;
Achin Gupta4f6ad662013-10-25 09:08:21 +010084
85 /* TODO: Standby states are not supported at the moment */
86 pstate_type = psci_get_pstate_type(power_state);
87 if (pstate_type == 0) {
88 rc = PSCI_E_INVALID_PARAMS;
89 goto exit;
90 }
91
92 /* Sanity check the requested state */
Achin Gupta0959db52013-12-02 17:33:04 +000093 target_afflvl = psci_get_pstate_afflvl(power_state);
94 if (target_afflvl > MPIDR_MAX_AFFLVL) {
Achin Gupta4f6ad662013-10-25 09:08:21 +010095 rc = PSCI_E_INVALID_PARAMS;
96 goto exit;
97 }
98
99 mpidr = read_mpidr();
100 rc = psci_afflvl_suspend(mpidr,
101 entrypoint,
102 context_id,
103 power_state,
Achin Gupta0959db52013-12-02 17:33:04 +0000104 MPIDR_AFFLVL0,
105 target_afflvl);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100106
107exit:
108 if (rc != PSCI_E_SUCCESS)
109 assert(rc == PSCI_E_INVALID_PARAMS);
110 return rc;
111}
112
113int psci_cpu_off(void)
114{
115 int rc;
116 unsigned long mpidr;
117 int target_afflvl = get_max_afflvl();
118
119 mpidr = read_mpidr();
120
121 /*
122 * Traverse from the highest to the lowest affinity level. When the
123 * lowest affinity level is hit, all the locks are acquired. State
124 * management is done immediately followed by cpu, cluster ...
125 * ..target_afflvl specific actions as this function unwinds back.
126 */
Achin Gupta0959db52013-12-02 17:33:04 +0000127 rc = psci_afflvl_off(mpidr, MPIDR_AFFLVL0, target_afflvl);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100128
Achin Gupta3140a9e2013-12-02 16:23:12 +0000129 /*
130 * The only error cpu_off can return is E_DENIED. So check if that's
131 * indeed the case.
132 */
133 assert (rc == PSCI_E_SUCCESS || rc == PSCI_E_DENIED);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100134
135 return rc;
136}
137
138int psci_affinity_info(unsigned long target_affinity,
139 unsigned int lowest_affinity_level)
140{
141 int rc = PSCI_E_INVALID_PARAMS;
142 unsigned int aff_state;
143 aff_map_node *node;
144
Achin Gupta75f73672013-12-05 16:33:10 +0000145 if (lowest_affinity_level > get_max_afflvl())
146 return rc;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100147
148 node = psci_get_aff_map_node(target_affinity, lowest_affinity_level);
149 if (node && (node->state & PSCI_AFF_PRESENT)) {
Achin Gupta75f73672013-12-05 16:33:10 +0000150
151 /*
152 * TODO: For affinity levels higher than 0 i.e. cpu, the
153 * state will always be either ON or OFF. Need to investigate
154 * how critical is it to support ON_PENDING here.
155 */
156 aff_state = psci_get_state(node);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100157
158 /* A suspended cpu is available & on for the OS */
159 if (aff_state == PSCI_STATE_SUSPEND) {
160 aff_state = PSCI_STATE_ON;
161 }
162
163 rc = aff_state;
164 }
Achin Gupta75f73672013-12-05 16:33:10 +0000165
Achin Gupta4f6ad662013-10-25 09:08:21 +0100166 return rc;
167}
168
169/* Unimplemented */
170int psci_migrate(unsigned int target_cpu)
171{
172 return PSCI_E_NOT_SUPPORTED;
173}
174
175/* Unimplemented */
176unsigned int psci_migrate_info_type(void)
177{
178 return PSCI_TOS_NOT_PRESENT;
179}
180
181unsigned long psci_migrate_info_up_cpu(void)
182{
183 /*
184 * Return value of this currently unsupported call depends upon
185 * what psci_migrate_info_type() returns.
186 */
187 return PSCI_E_SUCCESS;
188}
189
190/* Unimplemented */
191void psci_system_off(void)
192{
193 assert(0);
194}
195
196/* Unimplemented */
197void psci_system_reset(void)
198{
199 assert(0);
200}
201