blob: 3b643e6692d5ea617dca950c0ec37b310ec832d9 [file] [log] [blame]
Soby Mathew200fffd2016-10-21 11:34:59 +01001/*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
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 <arch_helpers.h>
32#include <assert.h>
33#include <css_pm.h>
34#include <debug.h>
dp-arm199fb4a2017-04-11 11:48:49 +010035#include <plat_arm.h>
Soby Mathew200fffd2016-10-21 11:34:59 +010036#include "../scpi/css_scpi.h"
37#include "css_scp.h"
38
39/*
40 * This file implements the SCP power management functions using SCPI protocol.
41 */
42
43/*
44 * Helper function to inform power down state to SCP.
45 */
46void css_scp_suspend(const psci_power_state_t *target_state)
47{
48 uint32_t cluster_state = scpi_power_on;
49 uint32_t system_state = scpi_power_on;
50
51 /* Check if power down at system power domain level is requested */
52 if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
53 system_state = scpi_power_retention;
54
55 /* Cluster is to be turned off, so disable coherency */
56 if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
57 cluster_state = scpi_power_off;
58
59 /*
60 * Ask the SCP to power down the appropriate components depending upon
61 * their state.
62 */
63 scpi_set_css_power_state(read_mpidr_el1(),
64 scpi_power_off,
65 cluster_state,
66 system_state);
67}
68
69/*
70 * Helper function to turn off a CPU power domain and its parent power domains
71 * if applicable. Since SCPI doesn't differentiate between OFF and suspend, we
72 * call the suspend helper here.
73 */
74void css_scp_off(const psci_power_state_t *target_state)
75{
76 css_scp_suspend(target_state);
77}
78
79/*
80 * Helper function to turn ON a CPU power domain and its parent power domains
81 * if applicable.
82 */
83void css_scp_on(u_register_t mpidr)
84{
85 /*
86 * SCP takes care of powering up parent power domains so we
87 * only need to care about level 0
88 */
89 scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on,
90 scpi_power_on);
91}
92
93/*
94 * Helper function to get the power state of a power domain node as reported
95 * by the SCP.
96 */
97int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level)
98{
99 int rc, element;
100 unsigned int cpu_state, cluster_state;
101
102 /*
103 * The format of 'power_level' is implementation-defined, but 0 must
104 * mean a CPU. We also allow 1 to denote the cluster
105 */
106 if (power_level != ARM_PWR_LVL0 && power_level != ARM_PWR_LVL1)
107 return PSCI_E_INVALID_PARAMS;
108
109 /* Query SCP */
110 rc = scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state);
111 if (rc != 0)
112 return PSCI_E_INVALID_PARAMS;
113
114 /* Map power states of CPU and cluster to expected PSCI return codes */
115 if (power_level == ARM_PWR_LVL0) {
116 /*
117 * The CPU state returned by SCP is an 8-bit bit mask
118 * corresponding to each CPU in the cluster
119 */
120 element = mpidr & MPIDR_AFFLVL_MASK;
121 return CSS_CPU_PWR_STATE(cpu_state, element) ==
122 CSS_CPU_PWR_STATE_ON ? HW_ON : HW_OFF;
123 } else {
124 assert(cluster_state == CSS_CLUSTER_PWR_STATE_ON ||
125 cluster_state == CSS_CLUSTER_PWR_STATE_OFF);
126 return cluster_state == CSS_CLUSTER_PWR_STATE_ON ? HW_ON :
127 HW_OFF;
128 }
129}
130
131/*
132 * Helper function to shutdown the system via SCPI.
133 */
134void __dead2 css_scp_sys_shutdown(void)
135{
136 uint32_t response;
137
dp-arm199fb4a2017-04-11 11:48:49 +0100138 /*
139 * Disable GIC CPU interface to prevent pending interrupt
140 * from waking up the AP from WFI.
141 */
142 plat_arm_gic_cpuif_disable();
143
Soby Mathew200fffd2016-10-21 11:34:59 +0100144 /* Send the power down request to the SCP */
145 response = scpi_sys_power_state(scpi_system_shutdown);
146
147 if (response != SCP_OK) {
148 ERROR("CSS System Off: SCP error %u.\n", response);
149 panic();
150 }
151 wfi();
152 ERROR("CSS System Off: operation not handled.\n");
153 panic();
154}
155
156/*
157 * Helper function to reset the system via SCPI.
158 */
159void __dead2 css_scp_sys_reboot(void)
160{
161 uint32_t response;
162
dp-arm199fb4a2017-04-11 11:48:49 +0100163 /*
164 * Disable GIC CPU interface to prevent pending interrupt
165 * from waking up the AP from WFI.
166 */
167 plat_arm_gic_cpuif_disable();
168
Soby Mathew200fffd2016-10-21 11:34:59 +0100169 /* Send the system reset request to the SCP */
170 response = scpi_sys_power_state(scpi_system_reboot);
171
172 if (response != SCP_OK) {
173 ERROR("CSS System Reset: SCP error %u.\n", response);
174 panic();
175 }
176 wfi();
177 ERROR("CSS System Reset: operation not handled.\n");
178 panic();
179}