1 /*
2 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8
9 #include <arch_helpers.h>
10 #include <cortex_a53.h>
11 #include <common/debug.h>
12 #include <drivers/delay_timer.h>
13 #include <lib/mmio.h>
14
15 #include <flowctrl.h>
16 #include <lib/utils_def.h>
17 #include <pmc.h>
18 #include <tegra_def.h>
19
20 #define CLK_RST_DEV_L_SET 0x300
21 #define CLK_RST_DEV_L_CLR 0x304
22 #define CLK_BPMP_RST (1 << 1)
23
24 #define EVP_BPMP_RESET_VECTOR 0x200
25
26 static const uint64_t flowctrl_offset_cpu_csr[4] = {
27 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU0_CSR),
28 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR),
29 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 8),
30 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 16)
31 };
32
33 static const uint64_t flowctrl_offset_halt_cpu[4] = {
34 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU0_EVENTS),
35 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS),
36 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 8),
37 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 16)
38 };
39
40 static const uint64_t flowctrl_offset_cc4_ctrl[4] = {
41 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL),
42 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 4),
43 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 8),
44 (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 12)
45 };
46
tegra_fc_cc4_ctrl(int cpu_id,uint32_t val)47 static inline void tegra_fc_cc4_ctrl(int cpu_id, uint32_t val)
48 {
49 mmio_write_32(flowctrl_offset_cc4_ctrl[cpu_id], val);
50 val = mmio_read_32(flowctrl_offset_cc4_ctrl[cpu_id]);
51 }
52
tegra_fc_cpu_csr(int cpu_id,uint32_t val)53 static inline void tegra_fc_cpu_csr(int cpu_id, uint32_t val)
54 {
55 mmio_write_32(flowctrl_offset_cpu_csr[cpu_id], val);
56 val = mmio_read_32(flowctrl_offset_cpu_csr[cpu_id]);
57 }
58
tegra_fc_halt_cpu(int cpu_id,uint32_t val)59 static inline void tegra_fc_halt_cpu(int cpu_id, uint32_t val)
60 {
61 mmio_write_32(flowctrl_offset_halt_cpu[cpu_id], val);
62 val = mmio_read_32(flowctrl_offset_halt_cpu[cpu_id]);
63 }
64
tegra_fc_prepare_suspend(int cpu_id,uint32_t csr)65 static void tegra_fc_prepare_suspend(int cpu_id, uint32_t csr)
66 {
67 uint32_t val;
68
69 val = FLOWCTRL_HALT_GIC_IRQ | FLOWCTRL_HALT_GIC_FIQ |
70 FLOWCTRL_HALT_LIC_IRQ | FLOWCTRL_HALT_LIC_FIQ |
71 FLOWCTRL_WAITEVENT;
72 tegra_fc_halt_cpu(cpu_id, val);
73
74 val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
75 FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu_id);
76 tegra_fc_cpu_csr(cpu_id, val | csr);
77 }
78
79 /*******************************************************************************
80 * After this, no core can wake from C7 until the action is reverted.
81 * If a wake up event is asserted, the FC state machine will stall until
82 * the action is reverted.
83 ******************************************************************************/
tegra_fc_ccplex_pgexit_lock(void)84 void tegra_fc_ccplex_pgexit_lock(void)
85 {
86 unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
87 uint32_t flags = tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT) & ~INTERCEPT_IRQ_PENDING;;
88 uint32_t icept_cpu_flags[] = {
89 INTERCEPT_EXIT_PG_CORE0,
90 INTERCEPT_EXIT_PG_CORE1,
91 INTERCEPT_EXIT_PG_CORE2,
92 INTERCEPT_EXIT_PG_CORE3
93 };
94
95 /* set the intercept flags */
96 for (i = 0; i < ARRAY_SIZE(icept_cpu_flags); i++) {
97
98 /* skip current CPU */
99 if (i == cpu)
100 continue;
101
102 /* enable power gate exit intercept locks */
103 flags |= icept_cpu_flags[i];
104 }
105
106 tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, flags);
107 (void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT);
108 }
109
110 /*******************************************************************************
111 * Revert the ccplex powergate exit locks
112 ******************************************************************************/
tegra_fc_ccplex_pgexit_unlock(void)113 void tegra_fc_ccplex_pgexit_unlock(void)
114 {
115 /* clear lock bits, clear pending interrupts */
116 tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, INTERCEPT_IRQ_PENDING);
117 (void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT);
118 }
119
120 /*******************************************************************************
121 * Powerdn the current CPU
122 ******************************************************************************/
tegra_fc_cpu_powerdn(uint32_t mpidr)123 void tegra_fc_cpu_powerdn(uint32_t mpidr)
124 {
125 int cpu = mpidr & MPIDR_CPU_MASK;
126
127 VERBOSE("CPU%d powering down...\n", cpu);
128 tegra_fc_prepare_suspend(cpu, 0);
129 }
130
131 /*******************************************************************************
132 * Suspend the current CPU cluster
133 ******************************************************************************/
tegra_fc_cluster_idle(uint32_t mpidr)134 void tegra_fc_cluster_idle(uint32_t mpidr)
135 {
136 int cpu = mpidr & MPIDR_CPU_MASK;
137 uint32_t val;
138
139 VERBOSE("Entering cluster idle state...\n");
140
141 tegra_fc_cc4_ctrl(cpu, 0);
142
143 /* hardware L2 flush is faster for A53 only */
144 tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
145 !!MPIDR_AFFLVL1_VAL(mpidr));
146
147 /* suspend the CPU cluster */
148 val = FLOWCTRL_PG_CPU_NONCPU << FLOWCTRL_ENABLE_EXT;
149 tegra_fc_prepare_suspend(cpu, val);
150 }
151
152 /*******************************************************************************
153 * Power down the current CPU cluster
154 ******************************************************************************/
tegra_fc_cluster_powerdn(uint32_t mpidr)155 void tegra_fc_cluster_powerdn(uint32_t mpidr)
156 {
157 int cpu = mpidr & MPIDR_CPU_MASK;
158 uint32_t val;
159
160 VERBOSE("Entering cluster powerdn state...\n");
161
162 tegra_fc_cc4_ctrl(cpu, 0);
163
164 /* hardware L2 flush is faster for A53 only */
165 tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
166 read_midr() == CORTEX_A53_MIDR);
167
168 /* power down the CPU cluster */
169 val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
170 tegra_fc_prepare_suspend(cpu, val);
171 }
172
173 /*******************************************************************************
174 * Check if cluster idle or power down state is allowed from this CPU
175 ******************************************************************************/
tegra_fc_is_ccx_allowed(void)176 bool tegra_fc_is_ccx_allowed(void)
177 {
178 unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
179 uint32_t val;
180 bool ccx_allowed = true;
181
182 for (i = 0; i < ARRAY_SIZE(flowctrl_offset_cpu_csr); i++) {
183
184 /* skip current CPU */
185 if (i == cpu)
186 continue;
187
188 /* check if all other CPUs are already halted */
189 val = mmio_read_32(flowctrl_offset_cpu_csr[i]);
190 if ((val & FLOWCTRL_CSR_HALT_MASK) == 0U) {
191 ccx_allowed = false;
192 }
193 }
194
195 return ccx_allowed;
196 }
197
198 /*******************************************************************************
199 * Suspend the entire SoC
200 ******************************************************************************/
tegra_fc_soc_powerdn(uint32_t mpidr)201 void tegra_fc_soc_powerdn(uint32_t mpidr)
202 {
203 int cpu = mpidr & MPIDR_CPU_MASK;
204 uint32_t val;
205
206 VERBOSE("Entering SoC powerdn state...\n");
207
208 tegra_fc_cc4_ctrl(cpu, 0);
209
210 tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL, 1);
211
212 val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
213 tegra_fc_prepare_suspend(cpu, val);
214
215 /* overwrite HALT register */
216 tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
217 }
218
219 /*******************************************************************************
220 * Power up the CPU
221 ******************************************************************************/
tegra_fc_cpu_on(int cpu)222 void tegra_fc_cpu_on(int cpu)
223 {
224 tegra_fc_cpu_csr(cpu, FLOWCTRL_CSR_ENABLE);
225 tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT | FLOWCTRL_HALT_SCLK);
226 }
227
228 /*******************************************************************************
229 * Power down the CPU
230 ******************************************************************************/
tegra_fc_cpu_off(int cpu)231 void tegra_fc_cpu_off(int cpu)
232 {
233 uint32_t val;
234
235 /*
236 * Flow controller powers down the CPU during wfi. The CPU would be
237 * powered on when it receives any interrupt.
238 */
239 val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
240 FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu);
241 tegra_fc_cpu_csr(cpu, val);
242 tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
243 tegra_fc_cc4_ctrl(cpu, 0);
244 }
245
246 /*******************************************************************************
247 * Inform the BPMP that we have completed the cluster power up
248 ******************************************************************************/
tegra_fc_lock_active_cluster(void)249 void tegra_fc_lock_active_cluster(void)
250 {
251 uint32_t val;
252
253 val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
254 val |= FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK;
255 tegra_fc_write_32(FLOWCTRL_BPMP_CLUSTER_CONTROL, val);
256 val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
257 }
258
259 /*******************************************************************************
260 * Power ON BPMP processor
261 ******************************************************************************/
tegra_fc_bpmp_on(uint32_t entrypoint)262 void tegra_fc_bpmp_on(uint32_t entrypoint)
263 {
264 /* halt BPMP */
265 tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
266
267 /* Assert BPMP reset */
268 mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
269
270 /* Set reset address (stored in PMC_SCRATCH39) */
271 mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, entrypoint);
272 while (entrypoint != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
273 ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
274
275 /* Wait for 2us before de-asserting the reset signal. */
276 udelay(2);
277
278 /* De-assert BPMP reset */
279 mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_CLR, CLK_BPMP_RST);
280
281 /* Un-halt BPMP */
282 tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, 0);
283 }
284
285 /*******************************************************************************
286 * Power OFF BPMP processor
287 ******************************************************************************/
tegra_fc_bpmp_off(void)288 void tegra_fc_bpmp_off(void)
289 {
290 /* halt BPMP */
291 tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
292
293 /* Assert BPMP reset */
294 mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
295
296 /* Clear reset address */
297 mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, 0);
298 while (0 != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
299 ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
300 }
301
302 /*******************************************************************************
303 * Route legacy FIQ to the GICD
304 ******************************************************************************/
tegra_fc_enable_fiq_to_ccplex_routing(void)305 void tegra_fc_enable_fiq_to_ccplex_routing(void)
306 {
307 uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL);
308
309 /* set the bit to pass FIQs to the GICD */
310 tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val | FLOWCTRL_FIQ2CCPLEX_ENABLE);
311 }
312
313 /*******************************************************************************
314 * Disable routing legacy FIQ to the GICD
315 ******************************************************************************/
tegra_fc_disable_fiq_to_ccplex_routing(void)316 void tegra_fc_disable_fiq_to_ccplex_routing(void)
317 {
318 uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL);
319
320 /* clear the bit to pass FIQs to the GICD */
321 tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val & ~FLOWCTRL_FIQ2CCPLEX_ENABLE);
322 }
323