1 /*
2 * Copyright (c) 2016-2024, ARM Limited and Contributors. All rights reserved.
3 *
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
25 DEFINE_BAKERY_LOCK(rockchip_pd_lock);
26
27 static uint32_t cpu_warm_boot_addr;
28
29 static uint32_t store_pmu_pwrmode_con;
30 static uint32_t store_sgrf_soc_con0;
31 static uint32_t store_sgrf_cpu_con0;
32
33 /* These enum are variants of low power mode */
34 enum {
35 ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0,
36 ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1,
37 };
38
rk3288_sleep_disable_osc(void)39 static 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
pmu_set_sleep_mode(int level)59 static 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
cpus_power_domain_on(uint32_t cpu_id)124 static 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
cpus_power_domain_off(uint32_t cpu_id)147 static 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
nonboot_cpus_off(void)166 static 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
sram_save(void)182 void sram_save(void)
183 {
184 /* TODO: support the sdram save for rk3288 SoCs*/
185 }
186
sram_restore(void)187 void sram_restore(void)
188 {
189 /* TODO: support the sdram restore for rk3288 SoCs */
190 }
191
rockchip_soc_cores_pwr_dm_on(unsigned long mpidr,uint64_t entrypoint)192 int 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
207 * stay at wfe state, once they are activated, they will check
208 * 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
rockchip_soc_cores_pwr_dm_on_finish(void)226 int rockchip_soc_cores_pwr_dm_on_finish(void)
227 {
228 return 0;
229 }
230
rockchip_soc_sys_pwr_dm_resume(void)231 int 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
rockchip_soc_sys_pwr_dm_suspend(void)252 int 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
rockchip_plat_mmu_svc_mon(void)292 void rockchip_plat_mmu_svc_mon(void)
293 {
294 }
295
plat_rockchip_pmu_init(void)296 void 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 }
308