blob: 9e17cffe08a601cb11af7f43574bcff537a5d4e3 [file] [log] [blame]
Heiko Stuebner87b9a3c2019-03-14 22:12:04 +01001/*
Quentin Schulz61a94222024-10-28 11:46:57 +01002 * Copyright (c) 2016-2024, ARM Limited and Contributors. All rights reserved.
Heiko Stuebner87b9a3c2019-03-14 22:12:04 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <errno.h>
9
10#include <platform_def.h>
11
12#include <arch_helpers.h>
13#include <common/debug.h>
14#include <drivers/delay_timer.h>
15#include <lib/mmio.h>
16#include <plat/common/platform.h>
17
18#include <plat_private.h>
19#include <pmu.h>
20#include <pmu_com.h>
21#include <rk3288_def.h>
22#include <secure.h>
23#include <soc.h>
24
25DEFINE_BAKERY_LOCK(rockchip_pd_lock);
26
27static uint32_t cpu_warm_boot_addr;
28
29static uint32_t store_pmu_pwrmode_con;
30static uint32_t store_sgrf_soc_con0;
31static uint32_t store_sgrf_cpu_con0;
32
33/* These enum are variants of low power mode */
34enum {
35 ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0,
36 ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1,
37};
38
Heiko Stuebner87b9a3c2019-03-14 22:12:04 +010039static bool rk3288_sleep_disable_osc(void)
40{
41 static const uint32_t reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0,
42 GRF_UOC2_CON0 };
43 uint32_t reg, i;
44
45 /*
46 * if any usb phy is still on(GRF_SIDDQ==0), that means we need the
47 * function of usb wakeup, so do not switch to 32khz, since the usb phy
48 * clk does not connect to 32khz osc
49 */
50 for (i = 0; i < ARRAY_SIZE(reg_offset); i++) {
51 reg = mmio_read_32(GRF_BASE + reg_offset[i]);
52 if (!(reg & GRF_SIDDQ))
53 return false;
54 }
55
56 return true;
57}
58
59static void pmu_set_sleep_mode(int level)
60{
61 uint32_t mode_set, mode_set1;
62 bool osc_disable = rk3288_sleep_disable_osc();
63
64 mode_set = BIT(pmu_mode_glb_int_dis) | BIT(pmu_mode_l2_flush_en) |
65 BIT(pmu_mode_sref0_enter) | BIT(pmu_mode_sref1_enter) |
66 BIT(pmu_mode_ddrc0_gt) | BIT(pmu_mode_ddrc1_gt) |
67 BIT(pmu_mode_en) | BIT(pmu_mode_chip_pd) |
68 BIT(pmu_mode_scu_pd);
69
70 mode_set1 = BIT(pmu_mode_clr_core) | BIT(pmu_mode_clr_cpup);
71
72 if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
73 /* arm off, logic deep sleep */
74 mode_set |= BIT(pmu_mode_bus_pd) | BIT(pmu_mode_pmu_use_lf) |
75 BIT(pmu_mode_ddrio1_ret) |
76 BIT(pmu_mode_ddrio0_ret) |
77 BIT(pmu_mode_pmu_alive_use_lf) |
78 BIT(pmu_mode_pll_pd);
79
80 if (osc_disable)
81 mode_set |= BIT(pmu_mode_osc_dis);
82
83 mode_set1 |= BIT(pmu_mode_clr_alive) | BIT(pmu_mode_clr_bus) |
84 BIT(pmu_mode_clr_peri) | BIT(pmu_mode_clr_dma);
85
86 mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1,
87 pmu_armint_wakeup_en);
88
89 /*
90 * In deep suspend we use PMU_PMU_USE_LF to let the rk3288
91 * switch its main clock supply to the alternative 32kHz
92 * source. Therefore set 30ms on a 32kHz clock for pmic
93 * stabilization. Similar 30ms on 24MHz for the other
94 * mode below.
95 */
96 mmio_write_32(PMU_BASE + PMU_STABL_CNT, 32 * 30);
97
98 /* only wait for stabilization, if we turned the osc off */
99 mmio_write_32(PMU_BASE + PMU_OSC_CNT,
100 osc_disable ? 32 * 30 : 0);
101 } else {
102 /*
103 * arm off, logic normal
104 * if pmu_clk_core_src_gate_en is not set,
105 * wakeup will be error
106 */
107 mode_set |= BIT(pmu_mode_core_src_gt);
108
109 mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1,
110 BIT(pmu_armint_wakeup_en) |
111 BIT(pmu_gpioint_wakeup_en));
112
113 /* 30ms on a 24MHz clock for pmic stabilization */
114 mmio_write_32(PMU_BASE + PMU_STABL_CNT, 24000 * 30);
115
116 /* oscillator is still running, so no need to wait */
117 mmio_write_32(PMU_BASE + PMU_OSC_CNT, 0);
118 }
119
120 mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, mode_set);
121 mmio_write_32(PMU_BASE + PMU_PWRMODE_CON1, mode_set1);
122}
123
124static int cpus_power_domain_on(uint32_t cpu_id)
125{
126 uint32_t cpu_pd;
127
128 cpu_pd = PD_CPU0 + cpu_id;
129
130 /* if the core has been on, power it off first */
131 if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
132 /* put core in reset - some sort of A12/A17 bug */
133 mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0),
134 BIT(cpu_id) | (BIT(cpu_id) << 16));
135
136 pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
137 }
138
139 pmu_power_domain_ctr(cpu_pd, pmu_pd_on);
140
141 /* pull core out of reset */
142 mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), BIT(cpu_id) << 16);
143
144 return 0;
145}
146
147static int cpus_power_domain_off(uint32_t cpu_id)
148{
149 uint32_t cpu_pd = PD_CPU0 + cpu_id;
150
151 if (pmu_power_domain_st(cpu_pd) == pmu_pd_off)
152 return 0;
153
154 if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK))
155 return -EINVAL;
156
157 /* put core in reset - some sort of A12/A17 bug */
158 mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0),
159 BIT(cpu_id) | (BIT(cpu_id) << 16));
160
161 pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
162
163 return 0;
164}
165
166static void nonboot_cpus_off(void)
167{
168 uint32_t boot_cpu, cpu;
169
170 boot_cpu = plat_my_core_pos();
171 boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr());
172
173 /* turn off noboot cpus */
174 for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
175 if (cpu == boot_cpu)
176 continue;
177
178 cpus_power_domain_off(cpu);
179 }
180}
181
182void sram_save(void)
183{
184 /* TODO: support the sdram save for rk3288 SoCs*/
185}
186
187void sram_restore(void)
188{
189 /* TODO: support the sdram restore for rk3288 SoCs */
190}
191
192int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
193{
194 uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
195
196 assert(cpu_id < PLATFORM_CORE_COUNT);
197 assert(cpuson_flags[cpu_id] == 0);
198 cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
199 cpuson_entry_point[cpu_id] = entrypoint;
200 dsb();
201
202 cpus_power_domain_on(cpu_id);
203
204 /*
205 * We communicate with the bootrom to active the cpus other
206 * than cpu0, after a blob of initialize code, they will
Elyes Haouas2be03c02023-02-13 09:14:48 +0100207 * stay at wfe state, once they are activated, they will check
Heiko Stuebner87b9a3c2019-03-14 22:12:04 +0100208 * the mailbox:
209 * sram_base_addr + 4: 0xdeadbeaf
210 * sram_base_addr + 8: start address for pc
211 * The cpu0 need to wait the other cpus other than cpu0 entering
212 * the wfe state.The wait time is affected by many aspects.
213 * (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
214 */
215 mdelay(1); /* ensure the cpus other than cpu0 to startup */
216
217 /* tell the bootrom mailbox where to start from */
218 mmio_write_32(SRAM_BASE + 8, cpu_warm_boot_addr);
219 mmio_write_32(SRAM_BASE + 4, 0xDEADBEAF);
220 dsb();
221 sev();
222
223 return 0;
224}
225
226int rockchip_soc_cores_pwr_dm_on_finish(void)
227{
228 return 0;
229}
230
231int rockchip_soc_sys_pwr_dm_resume(void)
232{
233 mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, store_pmu_pwrmode_con);
234 mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0),
235 store_sgrf_cpu_con0 | SGRF_DAPDEVICE_MSK);
236
237 /* disable fastboot mode */
238 mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0),
239 store_sgrf_soc_con0 | SGRF_FAST_BOOT_DIS);
240
241 secure_watchdog_ungate();
242 clk_gate_con_restore();
243 clk_sel_con_restore();
244 clk_plls_resume();
245
246 secure_gic_init();
247 plat_rockchip_gic_init();
248
249 return 0;
250}
251
252int rockchip_soc_sys_pwr_dm_suspend(void)
253{
254 nonboot_cpus_off();
255
256 store_sgrf_cpu_con0 = mmio_read_32(SGRF_BASE + SGRF_CPU_CON(0));
257 store_sgrf_soc_con0 = mmio_read_32(SGRF_BASE + SGRF_SOC_CON(0));
258 store_pmu_pwrmode_con = mmio_read_32(PMU_BASE + PMU_PWRMODE_CON);
259
260 /* save clk-gates and ungate all for suspend */
261 clk_gate_con_save();
262 clk_gate_con_disable();
263 clk_sel_con_save();
264
265 pmu_set_sleep_mode(ROCKCHIP_ARM_OFF_LOGIC_NORMAL);
266
267 clk_plls_suspend();
268 secure_watchdog_gate();
269
270 /*
271 * The dapswjdp can not auto reset before resume, that cause it may
272 * access some illegal address during resume. Let's disable it before
273 * suspend, and the MASKROM will enable it back.
274 */
275 mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0), SGRF_DAPDEVICE_MSK);
276
277 /*
278 * SGRF_FAST_BOOT_EN - system to boot from FAST_BOOT_ADDR
279 */
280 mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_FAST_BOOT_ENA);
281
282 /* boot-address of resuming system is from this register value */
283 mmio_write_32(SGRF_BASE + SGRF_FAST_BOOT_ADDR,
284 (uint32_t)&pmu_cpuson_entrypoint);
285
286 /* flush all caches - otherwise we might loose the resume address */
287 dcsw_op_all(DC_OP_CISW);
288
289 return 0;
290}
291
292void rockchip_plat_mmu_svc_mon(void)
293{
294}
295
296void plat_rockchip_pmu_init(void)
297{
298 uint32_t cpu;
299
300 cpu_warm_boot_addr = (uint32_t)platform_cpu_warmboot;
301
302 /* on boot all power-domains are on */
303 for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
304 cpuson_flags[cpu] = pmu_pd_on;
305
306 nonboot_cpus_off();
307}