1/*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <assert.h>
9#include <cortex_a53.h>
10#include <debug.h>
11#include <delay_timer.h>
12#include <flowctrl.h>
13#include <mmio.h>
14#include <pmc.h>
15#include <tegra_def.h>
16
17#define CLK_RST_DEV_L_SET		0x300
18#define CLK_RST_DEV_L_CLR		0x304
19#define  CLK_BPMP_RST			(1 << 1)
20
21#define EVP_BPMP_RESET_VECTOR		0x200
22
23static const uint64_t flowctrl_offset_cpu_csr[4] = {
24	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU0_CSR),
25	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR),
26	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 8),
27	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 16)
28};
29
30static const uint64_t flowctrl_offset_halt_cpu[4] = {
31	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU0_EVENTS),
32	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS),
33	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 8),
34	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 16)
35};
36
37static const uint64_t flowctrl_offset_cc4_ctrl[4] = {
38	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL),
39	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 4),
40	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 8),
41	(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 12)
42};
43
44static inline void tegra_fc_cc4_ctrl(int cpu_id, uint32_t val)
45{
46	mmio_write_32(flowctrl_offset_cc4_ctrl[cpu_id], val);
47	val = mmio_read_32(flowctrl_offset_cc4_ctrl[cpu_id]);
48}
49
50static inline void tegra_fc_cpu_csr(int cpu_id, uint32_t val)
51{
52	mmio_write_32(flowctrl_offset_cpu_csr[cpu_id], val);
53	val = mmio_read_32(flowctrl_offset_cpu_csr[cpu_id]);
54}
55
56static inline void tegra_fc_halt_cpu(int cpu_id, uint32_t val)
57{
58	mmio_write_32(flowctrl_offset_halt_cpu[cpu_id], val);
59	val = mmio_read_32(flowctrl_offset_halt_cpu[cpu_id]);
60}
61
62static void tegra_fc_prepare_suspend(int cpu_id, uint32_t csr)
63{
64	uint32_t val;
65
66	val = FLOWCTRL_HALT_GIC_IRQ | FLOWCTRL_HALT_GIC_FIQ |
67	      FLOWCTRL_HALT_LIC_IRQ | FLOWCTRL_HALT_LIC_FIQ |
68	      FLOWCTRL_WAITEVENT;
69	tegra_fc_halt_cpu(cpu_id, val);
70
71	val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
72	      FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu_id);
73	tegra_fc_cpu_csr(cpu_id, val | csr);
74}
75
76/*******************************************************************************
77 * Powerdn the current CPU
78 ******************************************************************************/
79void tegra_fc_cpu_powerdn(uint32_t mpidr)
80{
81	int cpu = mpidr & MPIDR_CPU_MASK;
82
83	VERBOSE("CPU%d powering down...\n", cpu);
84	tegra_fc_prepare_suspend(cpu, 0);
85}
86
87/*******************************************************************************
88 * Suspend the current CPU cluster
89 ******************************************************************************/
90void tegra_fc_cluster_idle(uint32_t mpidr)
91{
92	int cpu = mpidr & MPIDR_CPU_MASK;
93	uint32_t val;
94
95	VERBOSE("Entering cluster idle state...\n");
96
97	tegra_fc_cc4_ctrl(cpu, 0);
98
99	/* hardware L2 flush is faster for A53 only */
100	tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
101		!!MPIDR_AFFLVL1_VAL(mpidr));
102
103	/* suspend the CPU cluster */
104	val = FLOWCTRL_PG_CPU_NONCPU << FLOWCTRL_ENABLE_EXT;
105	tegra_fc_prepare_suspend(cpu, val);
106}
107
108/*******************************************************************************
109 * Power down the current CPU cluster
110 ******************************************************************************/
111void tegra_fc_cluster_powerdn(uint32_t mpidr)
112{
113	int cpu = mpidr & MPIDR_CPU_MASK;
114	uint32_t val;
115
116	VERBOSE("Entering cluster powerdn state...\n");
117
118	tegra_fc_cc4_ctrl(cpu, 0);
119
120	/* hardware L2 flush is faster for A53 only */
121	tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
122		read_midr() == CORTEX_A53_MIDR);
123
124	/* power down the CPU cluster */
125	val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
126	tegra_fc_prepare_suspend(cpu, val);
127}
128
129/*******************************************************************************
130 * Suspend the entire SoC
131 ******************************************************************************/
132void tegra_fc_soc_powerdn(uint32_t mpidr)
133{
134	int cpu = mpidr & MPIDR_CPU_MASK;
135	uint32_t val;
136
137	VERBOSE("Entering SoC powerdn state...\n");
138
139	tegra_fc_cc4_ctrl(cpu, 0);
140
141	tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL, 1);
142
143	val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
144	tegra_fc_prepare_suspend(cpu, val);
145
146	/* overwrite HALT register */
147	tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
148}
149
150/*******************************************************************************
151 * Power up the CPU
152 ******************************************************************************/
153void tegra_fc_cpu_on(int cpu)
154{
155	tegra_fc_cpu_csr(cpu, FLOWCTRL_CSR_ENABLE);
156	tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT | FLOWCTRL_HALT_SCLK);
157}
158
159/*******************************************************************************
160 * Power down the CPU
161 ******************************************************************************/
162void tegra_fc_cpu_off(int cpu)
163{
164	uint32_t val;
165
166	/*
167	 * Flow controller powers down the CPU during wfi. The CPU would be
168	 * powered on when it receives any interrupt.
169	 */
170	val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
171		FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu);
172	tegra_fc_cpu_csr(cpu, val);
173	tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
174	tegra_fc_cc4_ctrl(cpu, 0);
175}
176
177/*******************************************************************************
178 * Inform the BPMP that we have completed the cluster power up
179 ******************************************************************************/
180void tegra_fc_lock_active_cluster(void)
181{
182	uint32_t val;
183
184	val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
185	val |= FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK;
186	tegra_fc_write_32(FLOWCTRL_BPMP_CLUSTER_CONTROL, val);
187	val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
188}
189
190/*******************************************************************************
191 * Reset BPMP processor
192 ******************************************************************************/
193void tegra_fc_reset_bpmp(void)
194{
195	uint32_t val;
196
197	/* halt BPMP */
198	tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
199
200	/* Assert BPMP reset */
201	mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
202
203	/* Restore reset address (stored in PMC_SCRATCH39) */
204	val = tegra_pmc_read_32(PMC_SCRATCH39);
205	mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, val);
206	while (val != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
207		; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
208
209	/* Wait for 2us before de-asserting the reset signal. */
210	udelay(2);
211
212	/* De-assert BPMP reset */
213	mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_CLR, CLK_BPMP_RST);
214
215	/* Un-halt BPMP */
216	tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, 0);
217}
218