xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c (revision d3b6df7c3b0db0c5791dd92b66f195a601d69559)
128b02e23SHaojian Zhuang /*
228b02e23SHaojian Zhuang  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
328b02e23SHaojian Zhuang  *
428b02e23SHaojian Zhuang  * SPDX-License-Identifier: BSD-3-Clause
528b02e23SHaojian Zhuang  */
628b02e23SHaojian Zhuang 
728b02e23SHaojian Zhuang #include <assert.h>
809d40e0eSAntonio Nino Diaz 
928b02e23SHaojian Zhuang #include <platform_def.h>
10ee1ebbd1SIsla Mitchell 
1109d40e0eSAntonio Nino Diaz #include <arch_helpers.h>
1209d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
1309d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
14ee1ebbd1SIsla Mitchell 
1509d40e0eSAntonio Nino Diaz #include <../hikey960_def.h>
1609d40e0eSAntonio Nino Diaz #include <hisi_ipc.h>
1728b02e23SHaojian Zhuang #include "hisi_pwrc.h"
1828b02e23SHaojian Zhuang 
1928b02e23SHaojian Zhuang 
2028b02e23SHaojian Zhuang /* resource lock api */
2128b02e23SHaojian Zhuang #define RES0_LOCK_BASE		(SOC_PCTRL_RESOURCE0_LOCK_ADDR(PCTRL_BASE))
2228b02e23SHaojian Zhuang #define RES1_LOCK_BASE		(SOC_PCTRL_RESOURCE1_LOCK_ADDR(PCTRL_BASE))
2328b02e23SHaojian Zhuang #define RES2_LOCK_BASE		(SOC_PCTRL_RESOURCE2_LOCK_ADDR(PCTRL_BASE))
2428b02e23SHaojian Zhuang 
2528b02e23SHaojian Zhuang #define LOCK_BIT			(0x1 << 28)
26*d3b6df7cSJustin Chadwell #define LOCK_ID_MASK			(0x7u << 29)
2728b02e23SHaojian Zhuang #define CPUIDLE_LOCK_ID(core)		(0x6 - (core))
2828b02e23SHaojian Zhuang #define LOCK_UNLOCK_OFFSET		0x4
2928b02e23SHaojian Zhuang #define LOCK_STAT_OFFSET		0x8
3028b02e23SHaojian Zhuang 
3128b02e23SHaojian Zhuang #define CLUSTER0_CPUS_ONLINE_MASK	(0xF << 16)
3228b02e23SHaojian Zhuang #define	CLUSTER1_CPUS_ONLINE_MASK	(0xF << 20)
3328b02e23SHaojian Zhuang 
3428b02e23SHaojian Zhuang /* cpu hotplug flag api */
3528b02e23SHaojian Zhuang #define SCTRL_BASE			(SOC_ACPU_SCTRL_BASE_ADDR)
3628b02e23SHaojian Zhuang #define REG_SCBAKDATA3_OFFSET		(SOC_SCTRL_SCBAKDATA3_ADDR(SCTRL_BASE))
3728b02e23SHaojian Zhuang #define REG_SCBAKDATA8_OFFSET		(SOC_SCTRL_SCBAKDATA8_ADDR(SCTRL_BASE))
3828b02e23SHaojian Zhuang #define REG_SCBAKDATA9_OFFSET		(SOC_SCTRL_SCBAKDATA9_ADDR(SCTRL_BASE))
3928b02e23SHaojian Zhuang 
4028b02e23SHaojian Zhuang #define CPUIDLE_FLAG_REG(cluster) \
4128b02e23SHaojian Zhuang 			((cluster == 0) ? REG_SCBAKDATA8_OFFSET : \
4228b02e23SHaojian Zhuang 			 REG_SCBAKDATA9_OFFSET)
4328b02e23SHaojian Zhuang #define CLUSTER_IDLE_BIT				BIT(8)
4428b02e23SHaojian Zhuang #define CLUSTER_IDLE_MASK		(CLUSTER_IDLE_BIT | 0x0F)
4528b02e23SHaojian Zhuang 
4628b02e23SHaojian Zhuang #define AP_SUSPEND_FLAG			(1 << 16)
4728b02e23SHaojian Zhuang 
4828b02e23SHaojian Zhuang #define CLUSTER_PWDN_IDLE		(0<<28)
4928b02e23SHaojian Zhuang #define CLUSTER_PWDN_HOTPLUG		(1<<28)
5028b02e23SHaojian Zhuang #define CLUSTER_PWDN_SR			(2<<28)
5128b02e23SHaojian Zhuang 
5228b02e23SHaojian Zhuang #define CLUSTER0_PDC_OFFSET			0x260
5328b02e23SHaojian Zhuang #define CLUSTER1_PDC_OFFSET			0x300
5428b02e23SHaojian Zhuang 
5528b02e23SHaojian Zhuang #define PDC_EN_OFFSET				0x0
5628b02e23SHaojian Zhuang #define PDC_COREPWRINTEN_OFFSET		0x4
5728b02e23SHaojian Zhuang #define PDC_COREPWRINTSTAT_OFFSET	0x8
5828b02e23SHaojian Zhuang #define PDC_COREGICMASK_OFFSET		0xc
5928b02e23SHaojian Zhuang #define PDC_COREPOWERUP_OFFSET		0x10
6028b02e23SHaojian Zhuang #define PDC_COREPOWERDN_OFFSET		0x14
6128b02e23SHaojian Zhuang #define PDC_COREPOWERSTAT_OFFSET	0x18
6228b02e23SHaojian Zhuang 
6328b02e23SHaojian Zhuang #define PDC_COREPWRSTAT_MASK   (0XFFFF)
6428b02e23SHaojian Zhuang 
6528b02e23SHaojian Zhuang enum pdc_gic_mask {
6628b02e23SHaojian Zhuang 	PDC_MASK_GIC_WAKE_IRQ,
6728b02e23SHaojian Zhuang 	PDC_UNMASK_GIC_WAKE_IRQ
6828b02e23SHaojian Zhuang };
6928b02e23SHaojian Zhuang 
7028b02e23SHaojian Zhuang enum pdc_finish_int_mask {
7128b02e23SHaojian Zhuang 	PDC_DISABLE_FINISH_INT,
7228b02e23SHaojian Zhuang 	PDC_ENABLE_FINISH_INT
7328b02e23SHaojian Zhuang };
7428b02e23SHaojian Zhuang 
7528b02e23SHaojian Zhuang static void hisi_resource_lock(unsigned int lockid, unsigned int offset)
7628b02e23SHaojian Zhuang {
7728b02e23SHaojian Zhuang 	unsigned int lock_id = (lockid << 29);
7828b02e23SHaojian Zhuang 	unsigned int lock_val =  lock_id | LOCK_BIT;
7928b02e23SHaojian Zhuang 	unsigned int lock_state;
8028b02e23SHaojian Zhuang 
8128b02e23SHaojian Zhuang 	do {
8228b02e23SHaojian Zhuang 		mmio_write_32(offset, lock_val);
8328b02e23SHaojian Zhuang 		lock_state = mmio_read_32(LOCK_STAT_OFFSET + (uintptr_t)offset);
8428b02e23SHaojian Zhuang 	} while ((lock_state & LOCK_ID_MASK) != lock_id);
8528b02e23SHaojian Zhuang }
8628b02e23SHaojian Zhuang 
8728b02e23SHaojian Zhuang static void hisi_resource_unlock(unsigned int lockid, unsigned int offset)
8828b02e23SHaojian Zhuang {
8928b02e23SHaojian Zhuang 	unsigned int lock_val = (lockid << 29) | LOCK_BIT;
9028b02e23SHaojian Zhuang 
9128b02e23SHaojian Zhuang 	mmio_write_32((LOCK_UNLOCK_OFFSET + (uintptr_t)offset), lock_val);
9228b02e23SHaojian Zhuang }
9328b02e23SHaojian Zhuang 
9428b02e23SHaojian Zhuang 
9528b02e23SHaojian Zhuang static void hisi_cpuhotplug_lock(unsigned int cluster, unsigned int core)
9628b02e23SHaojian Zhuang {
9728b02e23SHaojian Zhuang 	unsigned int lock_id;
9828b02e23SHaojian Zhuang 
9928b02e23SHaojian Zhuang 	lock_id = (cluster << 2) + core;
10028b02e23SHaojian Zhuang 
10128b02e23SHaojian Zhuang 	hisi_resource_lock(lock_id, RES2_LOCK_BASE);
10228b02e23SHaojian Zhuang }
10328b02e23SHaojian Zhuang 
10428b02e23SHaojian Zhuang static void hisi_cpuhotplug_unlock(unsigned int cluster, unsigned int core)
10528b02e23SHaojian Zhuang {
10628b02e23SHaojian Zhuang 	unsigned int lock_id;
10728b02e23SHaojian Zhuang 
10828b02e23SHaojian Zhuang 	lock_id = (cluster << 2) + core;
10928b02e23SHaojian Zhuang 
11028b02e23SHaojian Zhuang 	hisi_resource_unlock(lock_id, RES2_LOCK_BASE);
11128b02e23SHaojian Zhuang }
11228b02e23SHaojian Zhuang 
11328b02e23SHaojian Zhuang /* get the resource lock */
11428b02e23SHaojian Zhuang void hisi_cpuidle_lock(unsigned int cluster, unsigned int core)
11528b02e23SHaojian Zhuang {
11628b02e23SHaojian Zhuang 	unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE);
11728b02e23SHaojian Zhuang 
11828b02e23SHaojian Zhuang 	hisi_resource_lock(CPUIDLE_LOCK_ID(core), offset);
11928b02e23SHaojian Zhuang }
12028b02e23SHaojian Zhuang 
12128b02e23SHaojian Zhuang /* release the resource lock */
12228b02e23SHaojian Zhuang void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core)
12328b02e23SHaojian Zhuang {
12428b02e23SHaojian Zhuang 	unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE);
12528b02e23SHaojian Zhuang 
12628b02e23SHaojian Zhuang 	hisi_resource_unlock(CPUIDLE_LOCK_ID(core), offset);
12728b02e23SHaojian Zhuang }
12828b02e23SHaojian Zhuang 
12928b02e23SHaojian Zhuang unsigned int hisi_get_cpuidle_flag(unsigned int cluster)
13028b02e23SHaojian Zhuang {
13128b02e23SHaojian Zhuang 	unsigned int val;
13228b02e23SHaojian Zhuang 
13328b02e23SHaojian Zhuang 	val = mmio_read_32(CPUIDLE_FLAG_REG(cluster));
13428b02e23SHaojian Zhuang 	val &= 0xF;
13528b02e23SHaojian Zhuang 
13628b02e23SHaojian Zhuang 	return val;
13728b02e23SHaojian Zhuang }
13828b02e23SHaojian Zhuang 
13928b02e23SHaojian Zhuang void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core)
14028b02e23SHaojian Zhuang {
14128b02e23SHaojian Zhuang 	mmio_setbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core));
14228b02e23SHaojian Zhuang }
14328b02e23SHaojian Zhuang 
14428b02e23SHaojian Zhuang void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core)
14528b02e23SHaojian Zhuang {
14628b02e23SHaojian Zhuang 	mmio_clrbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core));
14728b02e23SHaojian Zhuang 
14828b02e23SHaojian Zhuang }
14928b02e23SHaojian Zhuang 
1507d76df7dSWei Yu int hisi_test_ap_suspend_flag(void)
15128b02e23SHaojian Zhuang {
1527d76df7dSWei Yu 	unsigned int val1;
1537d76df7dSWei Yu 	unsigned int val2;
15428b02e23SHaojian Zhuang 
1557d76df7dSWei Yu 	val1 = mmio_read_32(CPUIDLE_FLAG_REG(0));
1567d76df7dSWei Yu 	val1 &= AP_SUSPEND_FLAG;
1577d76df7dSWei Yu 
1587d76df7dSWei Yu 	val2 = mmio_read_32(CPUIDLE_FLAG_REG(1));
1597d76df7dSWei Yu 	val2 &= AP_SUSPEND_FLAG;
1607d76df7dSWei Yu 
1617d76df7dSWei Yu 	val1 |= val2;
1627d76df7dSWei Yu 	return (val1 != 0);
16328b02e23SHaojian Zhuang }
16428b02e23SHaojian Zhuang 
16528b02e23SHaojian Zhuang void hisi_set_cluster_pwdn_flag(unsigned int cluster,
16628b02e23SHaojian Zhuang 				unsigned int core, unsigned int value)
16728b02e23SHaojian Zhuang {
16828b02e23SHaojian Zhuang 	unsigned int val;
16928b02e23SHaojian Zhuang 
17028b02e23SHaojian Zhuang 	hisi_cpuhotplug_lock(cluster, core);
17128b02e23SHaojian Zhuang 
17228b02e23SHaojian Zhuang 	val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
1737d76df7dSWei Yu 	val &= ~(0x3U << ((2 * cluster) + 28));
1747d76df7dSWei Yu 	val |= (value << (2 * cluster));
17528b02e23SHaojian Zhuang 	mmio_write_32(REG_SCBAKDATA3_OFFSET, val);
17628b02e23SHaojian Zhuang 
17728b02e23SHaojian Zhuang 	hisi_cpuhotplug_unlock(cluster, core);
17828b02e23SHaojian Zhuang }
17928b02e23SHaojian Zhuang 
18028b02e23SHaojian Zhuang unsigned int hisi_get_cpu_boot_flag(unsigned int cluster, unsigned int core)
18128b02e23SHaojian Zhuang {
18228b02e23SHaojian Zhuang 	unsigned int val;
18328b02e23SHaojian Zhuang 
18428b02e23SHaojian Zhuang 	hisi_cpuhotplug_lock(cluster, core);
18528b02e23SHaojian Zhuang 	val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
18628b02e23SHaojian Zhuang 	val = val >> (16 + (cluster << 2));
18728b02e23SHaojian Zhuang 	val &= 0xF;
18828b02e23SHaojian Zhuang 	hisi_cpuhotplug_unlock(cluster, core);
18928b02e23SHaojian Zhuang 
19028b02e23SHaojian Zhuang 	return val;
19128b02e23SHaojian Zhuang }
19228b02e23SHaojian Zhuang 
19328b02e23SHaojian Zhuang unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core)
19428b02e23SHaojian Zhuang {
19528b02e23SHaojian Zhuang 	unsigned int val;
19628b02e23SHaojian Zhuang 
19728b02e23SHaojian Zhuang 	hisi_cpuhotplug_lock(cluster, core);
19828b02e23SHaojian Zhuang 	val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
19928b02e23SHaojian Zhuang 	val = val >> (16 + (cluster << 2));
20028b02e23SHaojian Zhuang 	val &= 0xF;
20128b02e23SHaojian Zhuang 	hisi_cpuhotplug_unlock(cluster, core);
20228b02e23SHaojian Zhuang 
20328b02e23SHaojian Zhuang 	if (val)
20428b02e23SHaojian Zhuang 		return 0;
20528b02e23SHaojian Zhuang 	else
20628b02e23SHaojian Zhuang 		return 1;
20728b02e23SHaojian Zhuang }
20828b02e23SHaojian Zhuang 
20928b02e23SHaojian Zhuang void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core)
21028b02e23SHaojian Zhuang {
21128b02e23SHaojian Zhuang 	unsigned int flag = BIT((cluster<<2) + core + 16);
21228b02e23SHaojian Zhuang 
21328b02e23SHaojian Zhuang 	hisi_cpuhotplug_lock(cluster, core);
21428b02e23SHaojian Zhuang 
21528b02e23SHaojian Zhuang 	mmio_setbits_32(REG_SCBAKDATA3_OFFSET, flag);
21628b02e23SHaojian Zhuang 
21728b02e23SHaojian Zhuang 	hisi_cpuhotplug_unlock(cluster, core);
21828b02e23SHaojian Zhuang }
21928b02e23SHaojian Zhuang 
22028b02e23SHaojian Zhuang void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core)
22128b02e23SHaojian Zhuang {
22228b02e23SHaojian Zhuang 	unsigned int flag = BIT((cluster<<2) + core + 16);
22328b02e23SHaojian Zhuang 
22428b02e23SHaojian Zhuang 	hisi_cpuhotplug_lock(cluster, core);
22528b02e23SHaojian Zhuang 
22628b02e23SHaojian Zhuang 	mmio_clrbits_32(REG_SCBAKDATA3_OFFSET, flag);
22728b02e23SHaojian Zhuang 
22828b02e23SHaojian Zhuang 	hisi_cpuhotplug_unlock(cluster, core);
22928b02e23SHaojian Zhuang }
23028b02e23SHaojian Zhuang 
23128b02e23SHaojian Zhuang int cluster_is_powered_on(unsigned int cluster)
23228b02e23SHaojian Zhuang {
23328b02e23SHaojian Zhuang 	unsigned int val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
23428b02e23SHaojian Zhuang 	int ret;
23528b02e23SHaojian Zhuang 
23628b02e23SHaojian Zhuang 	if (cluster == 0)
23728b02e23SHaojian Zhuang 		ret = val & CLUSTER0_CPUS_ONLINE_MASK;
23828b02e23SHaojian Zhuang 	else
23928b02e23SHaojian Zhuang 		ret = val & CLUSTER1_CPUS_ONLINE_MASK;
24028b02e23SHaojian Zhuang 
24128b02e23SHaojian Zhuang 	return !!ret;
24228b02e23SHaojian Zhuang }
24328b02e23SHaojian Zhuang 
24428b02e23SHaojian Zhuang static void *hisi_get_pdc_addr(unsigned int cluster)
24528b02e23SHaojian Zhuang {
24628b02e23SHaojian Zhuang 	void *pdc_base_addr;
24728b02e23SHaojian Zhuang 	uintptr_t addr;
24828b02e23SHaojian Zhuang 
24928b02e23SHaojian Zhuang 	if (cluster == 0)
25028b02e23SHaojian Zhuang 		addr = SOC_CRGPERIPH_A53_PDCEN_ADDR(CRG_BASE);
25128b02e23SHaojian Zhuang 	else
25228b02e23SHaojian Zhuang 		addr = SOC_CRGPERIPH_MAIA_PDCEN_ADDR(CRG_BASE);
25328b02e23SHaojian Zhuang 	pdc_base_addr = (void *)addr;
25428b02e23SHaojian Zhuang 
25528b02e23SHaojian Zhuang 	return pdc_base_addr;
25628b02e23SHaojian Zhuang }
25728b02e23SHaojian Zhuang 
25828b02e23SHaojian Zhuang static unsigned int hisi_get_pdc_stat(unsigned int cluster)
25928b02e23SHaojian Zhuang {
26028b02e23SHaojian Zhuang 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
26128b02e23SHaojian Zhuang 	unsigned int val;
26228b02e23SHaojian Zhuang 
26328b02e23SHaojian Zhuang 	val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPOWERSTAT_OFFSET);
26428b02e23SHaojian Zhuang 
26528b02e23SHaojian Zhuang 	return val;
26628b02e23SHaojian Zhuang }
26728b02e23SHaojian Zhuang 
2687d76df7dSWei Yu static int check_hotplug(unsigned int cluster, unsigned int boot_flag)
2697d76df7dSWei Yu {
2707d76df7dSWei Yu 	unsigned int mask = 0xF;
2717d76df7dSWei Yu 
2727d76df7dSWei Yu 	if (hisi_test_ap_suspend_flag() ||
2737d76df7dSWei Yu 	    ((boot_flag & mask) == mask))
2747d76df7dSWei Yu 		return 0;
2757d76df7dSWei Yu 
2767d76df7dSWei Yu 	return 1;
2777d76df7dSWei Yu }
2787d76df7dSWei Yu 
27928b02e23SHaojian Zhuang int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core)
28028b02e23SHaojian Zhuang {
28128b02e23SHaojian Zhuang 	unsigned int mask = 0xf << (core * 4);
28228b02e23SHaojian Zhuang 	unsigned int pdc_stat = hisi_get_pdc_stat(cluster);
28328b02e23SHaojian Zhuang 	unsigned int boot_flag = hisi_get_cpu_boot_flag(cluster, core);
28428b02e23SHaojian Zhuang 	unsigned int cpuidle_flag = hisi_get_cpuidle_flag(cluster);
28528b02e23SHaojian Zhuang 
28628b02e23SHaojian Zhuang 	mask = (PDC_COREPWRSTAT_MASK & (~mask));
28728b02e23SHaojian Zhuang 	pdc_stat &= mask;
28828b02e23SHaojian Zhuang 
2897d76df7dSWei Yu 	if ((boot_flag ^ cpuidle_flag) || pdc_stat ||
2907d76df7dSWei Yu 	    check_hotplug(cluster, boot_flag))
29128b02e23SHaojian Zhuang 		return 0;
29228b02e23SHaojian Zhuang 	else
29328b02e23SHaojian Zhuang 		return 1;
29428b02e23SHaojian Zhuang }
29528b02e23SHaojian Zhuang 
29628b02e23SHaojian Zhuang void hisi_disable_pdc(unsigned int cluster)
29728b02e23SHaojian Zhuang {
29828b02e23SHaojian Zhuang 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
29928b02e23SHaojian Zhuang 
30028b02e23SHaojian Zhuang 	mmio_write_32((uintptr_t)pdc_base_addr, 0x0);
30128b02e23SHaojian Zhuang }
30228b02e23SHaojian Zhuang 
30328b02e23SHaojian Zhuang void hisi_enable_pdc(unsigned int cluster)
30428b02e23SHaojian Zhuang {
30528b02e23SHaojian Zhuang 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
30628b02e23SHaojian Zhuang 
30728b02e23SHaojian Zhuang 	mmio_write_32((uintptr_t)pdc_base_addr, 0x1);
30828b02e23SHaojian Zhuang }
30928b02e23SHaojian Zhuang 
310056b3d49SHaojian Zhuang void hisi_pdc_set_intmask(void *pdc_base_addr,
31128b02e23SHaojian Zhuang 			unsigned int core,
31228b02e23SHaojian Zhuang 			enum pdc_finish_int_mask intmask)
31328b02e23SHaojian Zhuang {
31428b02e23SHaojian Zhuang 	unsigned int val;
31528b02e23SHaojian Zhuang 
31628b02e23SHaojian Zhuang 	val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET);
31728b02e23SHaojian Zhuang 	if (intmask == PDC_ENABLE_FINISH_INT)
31828b02e23SHaojian Zhuang 		val |= BIT(core);
31928b02e23SHaojian Zhuang 	else
32028b02e23SHaojian Zhuang 		val &= ~BIT(core);
32128b02e23SHaojian Zhuang 
32228b02e23SHaojian Zhuang 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, val);
32328b02e23SHaojian Zhuang }
32428b02e23SHaojian Zhuang 
32528b02e23SHaojian Zhuang static inline void hisi_pdc_set_gicmask(void *pdc_base_addr,
32628b02e23SHaojian Zhuang 					unsigned int core,
32728b02e23SHaojian Zhuang 					enum pdc_gic_mask gicmask)
32828b02e23SHaojian Zhuang {
32928b02e23SHaojian Zhuang 	unsigned int val;
33028b02e23SHaojian Zhuang 
33128b02e23SHaojian Zhuang 	val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET);
33228b02e23SHaojian Zhuang 	if (gicmask == PDC_MASK_GIC_WAKE_IRQ)
33328b02e23SHaojian Zhuang 		val |= BIT(core);
33428b02e23SHaojian Zhuang 	else
33528b02e23SHaojian Zhuang 		val &= ~BIT(core);
33628b02e23SHaojian Zhuang 
33728b02e23SHaojian Zhuang 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET, val);
33828b02e23SHaojian Zhuang }
33928b02e23SHaojian Zhuang 
34028b02e23SHaojian Zhuang void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster)
34128b02e23SHaojian Zhuang {
34228b02e23SHaojian Zhuang 	int i;
34328b02e23SHaojian Zhuang 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
34428b02e23SHaojian Zhuang 
34528b02e23SHaojian Zhuang 	for (i = 0; i < 4; i++)
34628b02e23SHaojian Zhuang 		hisi_pdc_set_gicmask(pdc_base_addr, i, PDC_MASK_GIC_WAKE_IRQ);
34728b02e23SHaojian Zhuang }
34828b02e23SHaojian Zhuang 
34928b02e23SHaojian Zhuang static void hisi_pdc_powerup_core(unsigned int cluster, unsigned int core,
35028b02e23SHaojian Zhuang 				  enum pdc_gic_mask gicmask,
35128b02e23SHaojian Zhuang 				  enum pdc_finish_int_mask intmask)
35228b02e23SHaojian Zhuang {
35328b02e23SHaojian Zhuang 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
35428b02e23SHaojian Zhuang 
35528b02e23SHaojian Zhuang 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERUP_OFFSET,
35628b02e23SHaojian Zhuang 		      BIT(core));
35728b02e23SHaojian Zhuang }
35828b02e23SHaojian Zhuang 
35928b02e23SHaojian Zhuang static void hisi_pdc_powerdn_core(unsigned int cluster, unsigned int core,
36028b02e23SHaojian Zhuang 				  enum pdc_gic_mask gicmask,
36128b02e23SHaojian Zhuang 				  enum pdc_finish_int_mask intmask)
36228b02e23SHaojian Zhuang {
36328b02e23SHaojian Zhuang 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
36428b02e23SHaojian Zhuang 
36528b02e23SHaojian Zhuang 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET,
36628b02e23SHaojian Zhuang 		      BIT(core));
36728b02e23SHaojian Zhuang }
36828b02e23SHaojian Zhuang 
36928b02e23SHaojian Zhuang void hisi_powerup_core(unsigned int cluster, unsigned int core)
37028b02e23SHaojian Zhuang {
37128b02e23SHaojian Zhuang 	hisi_pdc_powerup_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ,
37228b02e23SHaojian Zhuang 			      PDC_DISABLE_FINISH_INT);
37328b02e23SHaojian Zhuang }
37428b02e23SHaojian Zhuang 
37528b02e23SHaojian Zhuang void hisi_powerdn_core(unsigned int cluster, unsigned int core)
37628b02e23SHaojian Zhuang {
37728b02e23SHaojian Zhuang 	hisi_pdc_powerdn_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ,
37828b02e23SHaojian Zhuang 			      PDC_DISABLE_FINISH_INT);
37928b02e23SHaojian Zhuang }
38028b02e23SHaojian Zhuang 
38128b02e23SHaojian Zhuang void hisi_powerup_cluster(unsigned int cluster, unsigned int core)
38228b02e23SHaojian Zhuang {
38328b02e23SHaojian Zhuang 	hisi_ipc_pm_on_off(core, cluster, PM_ON);
38428b02e23SHaojian Zhuang }
38528b02e23SHaojian Zhuang 
38628b02e23SHaojian Zhuang void hisi_powerdn_cluster(unsigned int cluster, unsigned int core)
38728b02e23SHaojian Zhuang {
38828b02e23SHaojian Zhuang 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
38928b02e23SHaojian Zhuang 
39028b02e23SHaojian Zhuang 	hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_HOTPLUG);
39128b02e23SHaojian Zhuang 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET,
39228b02e23SHaojian Zhuang 		      (0x10001 << core));
39328b02e23SHaojian Zhuang 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET,
39428b02e23SHaojian Zhuang 		      BIT(core));
39528b02e23SHaojian Zhuang }
39628b02e23SHaojian Zhuang 
39728b02e23SHaojian Zhuang void hisi_enter_core_idle(unsigned int cluster, unsigned int core)
39828b02e23SHaojian Zhuang {
39928b02e23SHaojian Zhuang 	hisi_pdc_powerdn_core(cluster, core, PDC_UNMASK_GIC_WAKE_IRQ,
40028b02e23SHaojian Zhuang 			      PDC_DISABLE_FINISH_INT);
40128b02e23SHaojian Zhuang }
40228b02e23SHaojian Zhuang 
40328b02e23SHaojian Zhuang void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core)
40428b02e23SHaojian Zhuang {
40528b02e23SHaojian Zhuang 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
40628b02e23SHaojian Zhuang 
40728b02e23SHaojian Zhuang 	hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_IDLE);
40828b02e23SHaojian Zhuang 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET,
40928b02e23SHaojian Zhuang 		      (0x10001 << core));
41028b02e23SHaojian Zhuang 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET,
41128b02e23SHaojian Zhuang 		      BIT(core));
41228b02e23SHaojian Zhuang }
41328b02e23SHaojian Zhuang 
41428b02e23SHaojian Zhuang void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core)
41528b02e23SHaojian Zhuang {
41628b02e23SHaojian Zhuang 	hisi_ipc_pm_suspend(core, cluster, 0x3);
41728b02e23SHaojian Zhuang }
418