2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
7 #include <../hikey960_def.h>
8 #include <arch_helpers.h>
13 #include <platform_def.h>
16 #include "hisi_pwrc.h"
19 /* resource lock api */
20 #define RES0_LOCK_BASE (SOC_PCTRL_RESOURCE0_LOCK_ADDR(PCTRL_BASE))
21 #define RES1_LOCK_BASE (SOC_PCTRL_RESOURCE1_LOCK_ADDR(PCTRL_BASE))
22 #define RES2_LOCK_BASE (SOC_PCTRL_RESOURCE2_LOCK_ADDR(PCTRL_BASE))
24 #define LOCK_BIT (0x1 << 28)
25 #define LOCK_ID_MASK (0x7 << 29)
26 #define CPUIDLE_LOCK_ID(core) (0x6 - (core))
27 #define LOCK_UNLOCK_OFFSET 0x4
28 #define LOCK_STAT_OFFSET 0x8
30 #define CLUSTER0_CPUS_ONLINE_MASK (0xF << 16)
31 #define CLUSTER1_CPUS_ONLINE_MASK (0xF << 20)
33 /* cpu hotplug flag api */
34 #define SCTRL_BASE (SOC_ACPU_SCTRL_BASE_ADDR)
35 #define REG_SCBAKDATA3_OFFSET (SOC_SCTRL_SCBAKDATA3_ADDR(SCTRL_BASE))
36 #define REG_SCBAKDATA8_OFFSET (SOC_SCTRL_SCBAKDATA8_ADDR(SCTRL_BASE))
37 #define REG_SCBAKDATA9_OFFSET (SOC_SCTRL_SCBAKDATA9_ADDR(SCTRL_BASE))
39 #define CPUIDLE_FLAG_REG(cluster) \
40 ((cluster == 0) ? REG_SCBAKDATA8_OFFSET : \
41 REG_SCBAKDATA9_OFFSET)
42 #define CLUSTER_IDLE_BIT BIT(8)
43 #define CLUSTER_IDLE_MASK (CLUSTER_IDLE_BIT | 0x0F)
45 #define AP_SUSPEND_FLAG (1 << 16)
47 #define CLUSTER_PWDN_IDLE (0<<28)
48 #define CLUSTER_PWDN_HOTPLUG (1<<28)
49 #define CLUSTER_PWDN_SR (2<<28)
51 #define CLUSTER0_PDC_OFFSET 0x260
52 #define CLUSTER1_PDC_OFFSET 0x300
54 #define PDC_EN_OFFSET 0x0
55 #define PDC_COREPWRINTEN_OFFSET 0x4
56 #define PDC_COREPWRINTSTAT_OFFSET 0x8
57 #define PDC_COREGICMASK_OFFSET 0xc
58 #define PDC_COREPOWERUP_OFFSET 0x10
59 #define PDC_COREPOWERDN_OFFSET 0x14
60 #define PDC_COREPOWERSTAT_OFFSET 0x18
62 #define PDC_COREPWRSTAT_MASK (0XFFFF)
65 PDC_MASK_GIC_WAKE_IRQ
,
66 PDC_UNMASK_GIC_WAKE_IRQ
69 enum pdc_finish_int_mask
{
70 PDC_DISABLE_FINISH_INT
,
74 static void hisi_resource_lock(unsigned int lockid
, unsigned int offset
)
76 unsigned int lock_id
= (lockid
<< 29);
77 unsigned int lock_val
= lock_id
| LOCK_BIT
;
78 unsigned int lock_state
;
81 mmio_write_32(offset
, lock_val
);
82 lock_state
= mmio_read_32(LOCK_STAT_OFFSET
+ (uintptr_t)offset
);
83 } while ((lock_state
& LOCK_ID_MASK
) != lock_id
);
86 static void hisi_resource_unlock(unsigned int lockid
, unsigned int offset
)
88 unsigned int lock_val
= (lockid
<< 29) | LOCK_BIT
;
90 mmio_write_32((LOCK_UNLOCK_OFFSET
+ (uintptr_t)offset
), lock_val
);
94 static void hisi_cpuhotplug_lock(unsigned int cluster
, unsigned int core
)
98 lock_id
= (cluster
<< 2) + core
;
100 hisi_resource_lock(lock_id
, RES2_LOCK_BASE
);
103 static void hisi_cpuhotplug_unlock(unsigned int cluster
, unsigned int core
)
105 unsigned int lock_id
;
107 lock_id
= (cluster
<< 2) + core
;
109 hisi_resource_unlock(lock_id
, RES2_LOCK_BASE
);
112 /* get the resource lock */
113 void hisi_cpuidle_lock(unsigned int cluster
, unsigned int core
)
115 unsigned int offset
= (cluster
== 0 ? RES0_LOCK_BASE
: RES1_LOCK_BASE
);
117 hisi_resource_lock(CPUIDLE_LOCK_ID(core
), offset
);
120 /* release the resource lock */
121 void hisi_cpuidle_unlock(unsigned int cluster
, unsigned int core
)
123 unsigned int offset
= (cluster
== 0 ? RES0_LOCK_BASE
: RES1_LOCK_BASE
);
125 hisi_resource_unlock(CPUIDLE_LOCK_ID(core
), offset
);
128 unsigned int hisi_get_cpuidle_flag(unsigned int cluster
)
132 val
= mmio_read_32(CPUIDLE_FLAG_REG(cluster
));
138 void hisi_set_cpuidle_flag(unsigned int cluster
, unsigned int core
)
140 mmio_setbits_32(CPUIDLE_FLAG_REG(cluster
), BIT(core
));
143 void hisi_clear_cpuidle_flag(unsigned int cluster
, unsigned int core
)
145 mmio_clrbits_32(CPUIDLE_FLAG_REG(cluster
), BIT(core
));
149 int hisi_test_ap_suspend_flag(unsigned int cluster
)
153 val
= mmio_read_32(CPUIDLE_FLAG_REG(cluster
));
154 val
&= AP_SUSPEND_FLAG
;
158 void hisi_set_cluster_pwdn_flag(unsigned int cluster
,
159 unsigned int core
, unsigned int value
)
163 hisi_cpuhotplug_lock(cluster
, core
);
165 val
= mmio_read_32(REG_SCBAKDATA3_OFFSET
);
166 val
= (value
<< (cluster
<< 1)) | (val
& 0xFFFFFFF);
167 mmio_write_32(REG_SCBAKDATA3_OFFSET
, val
);
169 hisi_cpuhotplug_unlock(cluster
, core
);
172 unsigned int hisi_get_cpu_boot_flag(unsigned int cluster
, unsigned int core
)
176 hisi_cpuhotplug_lock(cluster
, core
);
177 val
= mmio_read_32(REG_SCBAKDATA3_OFFSET
);
178 val
= val
>> (16 + (cluster
<< 2));
180 hisi_cpuhotplug_unlock(cluster
, core
);
185 unsigned int hisi_test_cpu_down(unsigned int cluster
, unsigned int core
)
189 hisi_cpuhotplug_lock(cluster
, core
);
190 val
= mmio_read_32(REG_SCBAKDATA3_OFFSET
);
191 val
= val
>> (16 + (cluster
<< 2));
193 hisi_cpuhotplug_unlock(cluster
, core
);
201 void hisi_set_cpu_boot_flag(unsigned int cluster
, unsigned int core
)
203 unsigned int flag
= BIT((cluster
<<2) + core
+ 16);
205 hisi_cpuhotplug_lock(cluster
, core
);
207 mmio_setbits_32(REG_SCBAKDATA3_OFFSET
, flag
);
209 hisi_cpuhotplug_unlock(cluster
, core
);
212 void hisi_clear_cpu_boot_flag(unsigned int cluster
, unsigned int core
)
214 unsigned int flag
= BIT((cluster
<<2) + core
+ 16);
216 hisi_cpuhotplug_lock(cluster
, core
);
218 mmio_clrbits_32(REG_SCBAKDATA3_OFFSET
, flag
);
220 hisi_cpuhotplug_unlock(cluster
, core
);
223 int cluster_is_powered_on(unsigned int cluster
)
225 unsigned int val
= mmio_read_32(REG_SCBAKDATA3_OFFSET
);
229 ret
= val
& CLUSTER0_CPUS_ONLINE_MASK
;
231 ret
= val
& CLUSTER1_CPUS_ONLINE_MASK
;
236 static void *hisi_get_pdc_addr(unsigned int cluster
)
242 addr
= SOC_CRGPERIPH_A53_PDCEN_ADDR(CRG_BASE
);
244 addr
= SOC_CRGPERIPH_MAIA_PDCEN_ADDR(CRG_BASE
);
245 pdc_base_addr
= (void *)addr
;
247 return pdc_base_addr
;
250 static unsigned int hisi_get_pdc_stat(unsigned int cluster
)
252 void *pdc_base_addr
= hisi_get_pdc_addr(cluster
);
255 val
= mmio_read_32((uintptr_t)pdc_base_addr
+ PDC_COREPOWERSTAT_OFFSET
);
260 int hisi_test_pwrdn_allcores(unsigned int cluster
, unsigned int core
)
262 unsigned int mask
= 0xf << (core
* 4);
263 unsigned int pdc_stat
= hisi_get_pdc_stat(cluster
);
264 unsigned int boot_flag
= hisi_get_cpu_boot_flag(cluster
, core
);
265 unsigned int cpuidle_flag
= hisi_get_cpuidle_flag(cluster
);
267 mask
= (PDC_COREPWRSTAT_MASK
& (~mask
));
270 if ((boot_flag
^ cpuidle_flag
) || pdc_stat
)
276 void hisi_disable_pdc(unsigned int cluster
)
278 void *pdc_base_addr
= hisi_get_pdc_addr(cluster
);
280 mmio_write_32((uintptr_t)pdc_base_addr
, 0x0);
283 void hisi_enable_pdc(unsigned int cluster
)
285 void *pdc_base_addr
= hisi_get_pdc_addr(cluster
);
287 mmio_write_32((uintptr_t)pdc_base_addr
, 0x1);
290 void hisi_pdc_set_intmask(void *pdc_base_addr
,
292 enum pdc_finish_int_mask intmask
)
296 val
= mmio_read_32((uintptr_t)pdc_base_addr
+ PDC_COREPWRINTEN_OFFSET
);
297 if (intmask
== PDC_ENABLE_FINISH_INT
)
302 mmio_write_32((uintptr_t)pdc_base_addr
+ PDC_COREPWRINTEN_OFFSET
, val
);
305 static inline void hisi_pdc_set_gicmask(void *pdc_base_addr
,
307 enum pdc_gic_mask gicmask
)
311 val
= mmio_read_32((uintptr_t)pdc_base_addr
+ PDC_COREGICMASK_OFFSET
);
312 if (gicmask
== PDC_MASK_GIC_WAKE_IRQ
)
317 mmio_write_32((uintptr_t)pdc_base_addr
+ PDC_COREGICMASK_OFFSET
, val
);
320 void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster
)
323 void *pdc_base_addr
= hisi_get_pdc_addr(cluster
);
325 for (i
= 0; i
< 4; i
++)
326 hisi_pdc_set_gicmask(pdc_base_addr
, i
, PDC_MASK_GIC_WAKE_IRQ
);
329 static void hisi_pdc_powerup_core(unsigned int cluster
, unsigned int core
,
330 enum pdc_gic_mask gicmask
,
331 enum pdc_finish_int_mask intmask
)
333 void *pdc_base_addr
= hisi_get_pdc_addr(cluster
);
335 mmio_write_32((uintptr_t)pdc_base_addr
+ PDC_COREPOWERUP_OFFSET
,
339 static void hisi_pdc_powerdn_core(unsigned int cluster
, unsigned int core
,
340 enum pdc_gic_mask gicmask
,
341 enum pdc_finish_int_mask intmask
)
343 void *pdc_base_addr
= hisi_get_pdc_addr(cluster
);
345 mmio_write_32((uintptr_t)pdc_base_addr
+ PDC_COREPOWERDN_OFFSET
,
349 void hisi_powerup_core(unsigned int cluster
, unsigned int core
)
351 hisi_pdc_powerup_core(cluster
, core
, PDC_MASK_GIC_WAKE_IRQ
,
352 PDC_DISABLE_FINISH_INT
);
355 void hisi_powerdn_core(unsigned int cluster
, unsigned int core
)
357 hisi_pdc_powerdn_core(cluster
, core
, PDC_MASK_GIC_WAKE_IRQ
,
358 PDC_DISABLE_FINISH_INT
);
361 void hisi_powerup_cluster(unsigned int cluster
, unsigned int core
)
363 hisi_ipc_pm_on_off(core
, cluster
, PM_ON
);
366 void hisi_powerdn_cluster(unsigned int cluster
, unsigned int core
)
368 void *pdc_base_addr
= hisi_get_pdc_addr(cluster
);
370 hisi_set_cluster_pwdn_flag(cluster
, core
, CLUSTER_PWDN_HOTPLUG
);
371 mmio_write_32((uintptr_t)pdc_base_addr
+ PDC_COREPWRINTEN_OFFSET
,
373 mmio_write_32((uintptr_t)pdc_base_addr
+ PDC_COREPOWERDN_OFFSET
,
377 void hisi_enter_core_idle(unsigned int cluster
, unsigned int core
)
379 hisi_pdc_powerdn_core(cluster
, core
, PDC_UNMASK_GIC_WAKE_IRQ
,
380 PDC_DISABLE_FINISH_INT
);
383 void hisi_enter_cluster_idle(unsigned int cluster
, unsigned int core
)
385 void *pdc_base_addr
= hisi_get_pdc_addr(cluster
);
387 hisi_set_cluster_pwdn_flag(cluster
, core
, CLUSTER_PWDN_IDLE
);
388 mmio_write_32((uintptr_t)pdc_base_addr
+ PDC_COREPWRINTEN_OFFSET
,
390 mmio_write_32((uintptr_t)pdc_base_addr
+ PDC_COREPOWERDN_OFFSET
,
394 void hisi_enter_ap_suspend(unsigned int cluster
, unsigned int core
)
396 hisi_ipc_pm_suspend(core
, cluster
, 0x3);