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 7ee1ebbd1SIsla Mitchell #include <../hikey960_def.h> 828b02e23SHaojian Zhuang #include <arch_helpers.h> 928b02e23SHaojian Zhuang #include <assert.h> 10ee1ebbd1SIsla Mitchell #include <hisi_ipc.h> 1128b02e23SHaojian Zhuang #include <mmio.h> 1228b02e23SHaojian Zhuang #include <platform.h> 1328b02e23SHaojian Zhuang #include <platform_def.h> 14ee1ebbd1SIsla Mitchell 15ee1ebbd1SIsla Mitchell 1628b02e23SHaojian Zhuang #include "hisi_pwrc.h" 1728b02e23SHaojian Zhuang 1828b02e23SHaojian Zhuang 1928b02e23SHaojian Zhuang /* resource lock api */ 2028b02e23SHaojian Zhuang #define RES0_LOCK_BASE (SOC_PCTRL_RESOURCE0_LOCK_ADDR(PCTRL_BASE)) 2128b02e23SHaojian Zhuang #define RES1_LOCK_BASE (SOC_PCTRL_RESOURCE1_LOCK_ADDR(PCTRL_BASE)) 2228b02e23SHaojian Zhuang #define RES2_LOCK_BASE (SOC_PCTRL_RESOURCE2_LOCK_ADDR(PCTRL_BASE)) 2328b02e23SHaojian Zhuang 2428b02e23SHaojian Zhuang #define LOCK_BIT (0x1 << 28) 2528b02e23SHaojian Zhuang #define LOCK_ID_MASK (0x7 << 29) 2628b02e23SHaojian Zhuang #define CPUIDLE_LOCK_ID(core) (0x6 - (core)) 2728b02e23SHaojian Zhuang #define LOCK_UNLOCK_OFFSET 0x4 2828b02e23SHaojian Zhuang #define LOCK_STAT_OFFSET 0x8 2928b02e23SHaojian Zhuang 3028b02e23SHaojian Zhuang #define CLUSTER0_CPUS_ONLINE_MASK (0xF << 16) 3128b02e23SHaojian Zhuang #define CLUSTER1_CPUS_ONLINE_MASK (0xF << 20) 3228b02e23SHaojian Zhuang 3328b02e23SHaojian Zhuang /* cpu hotplug flag api */ 3428b02e23SHaojian Zhuang #define SCTRL_BASE (SOC_ACPU_SCTRL_BASE_ADDR) 3528b02e23SHaojian Zhuang #define REG_SCBAKDATA3_OFFSET (SOC_SCTRL_SCBAKDATA3_ADDR(SCTRL_BASE)) 3628b02e23SHaojian Zhuang #define REG_SCBAKDATA8_OFFSET (SOC_SCTRL_SCBAKDATA8_ADDR(SCTRL_BASE)) 3728b02e23SHaojian Zhuang #define REG_SCBAKDATA9_OFFSET (SOC_SCTRL_SCBAKDATA9_ADDR(SCTRL_BASE)) 3828b02e23SHaojian Zhuang 3928b02e23SHaojian Zhuang #define CPUIDLE_FLAG_REG(cluster) \ 4028b02e23SHaojian Zhuang ((cluster == 0) ? REG_SCBAKDATA8_OFFSET : \ 4128b02e23SHaojian Zhuang REG_SCBAKDATA9_OFFSET) 4228b02e23SHaojian Zhuang #define CLUSTER_IDLE_BIT BIT(8) 4328b02e23SHaojian Zhuang #define CLUSTER_IDLE_MASK (CLUSTER_IDLE_BIT | 0x0F) 4428b02e23SHaojian Zhuang 4528b02e23SHaojian Zhuang #define AP_SUSPEND_FLAG (1 << 16) 4628b02e23SHaojian Zhuang 4728b02e23SHaojian Zhuang #define CLUSTER_PWDN_IDLE (0<<28) 4828b02e23SHaojian Zhuang #define CLUSTER_PWDN_HOTPLUG (1<<28) 4928b02e23SHaojian Zhuang #define CLUSTER_PWDN_SR (2<<28) 5028b02e23SHaojian Zhuang 5128b02e23SHaojian Zhuang #define CLUSTER0_PDC_OFFSET 0x260 5228b02e23SHaojian Zhuang #define CLUSTER1_PDC_OFFSET 0x300 5328b02e23SHaojian Zhuang 5428b02e23SHaojian Zhuang #define PDC_EN_OFFSET 0x0 5528b02e23SHaojian Zhuang #define PDC_COREPWRINTEN_OFFSET 0x4 5628b02e23SHaojian Zhuang #define PDC_COREPWRINTSTAT_OFFSET 0x8 5728b02e23SHaojian Zhuang #define PDC_COREGICMASK_OFFSET 0xc 5828b02e23SHaojian Zhuang #define PDC_COREPOWERUP_OFFSET 0x10 5928b02e23SHaojian Zhuang #define PDC_COREPOWERDN_OFFSET 0x14 6028b02e23SHaojian Zhuang #define PDC_COREPOWERSTAT_OFFSET 0x18 6128b02e23SHaojian Zhuang 6228b02e23SHaojian Zhuang #define PDC_COREPWRSTAT_MASK (0XFFFF) 6328b02e23SHaojian Zhuang 6428b02e23SHaojian Zhuang enum pdc_gic_mask { 6528b02e23SHaojian Zhuang PDC_MASK_GIC_WAKE_IRQ, 6628b02e23SHaojian Zhuang PDC_UNMASK_GIC_WAKE_IRQ 6728b02e23SHaojian Zhuang }; 6828b02e23SHaojian Zhuang 6928b02e23SHaojian Zhuang enum pdc_finish_int_mask { 7028b02e23SHaojian Zhuang PDC_DISABLE_FINISH_INT, 7128b02e23SHaojian Zhuang PDC_ENABLE_FINISH_INT 7228b02e23SHaojian Zhuang }; 7328b02e23SHaojian Zhuang 7428b02e23SHaojian Zhuang static void hisi_resource_lock(unsigned int lockid, unsigned int offset) 7528b02e23SHaojian Zhuang { 7628b02e23SHaojian Zhuang unsigned int lock_id = (lockid << 29); 7728b02e23SHaojian Zhuang unsigned int lock_val = lock_id | LOCK_BIT; 7828b02e23SHaojian Zhuang unsigned int lock_state; 7928b02e23SHaojian Zhuang 8028b02e23SHaojian Zhuang do { 8128b02e23SHaojian Zhuang mmio_write_32(offset, lock_val); 8228b02e23SHaojian Zhuang lock_state = mmio_read_32(LOCK_STAT_OFFSET + (uintptr_t)offset); 8328b02e23SHaojian Zhuang } while ((lock_state & LOCK_ID_MASK) != lock_id); 8428b02e23SHaojian Zhuang } 8528b02e23SHaojian Zhuang 8628b02e23SHaojian Zhuang static void hisi_resource_unlock(unsigned int lockid, unsigned int offset) 8728b02e23SHaojian Zhuang { 8828b02e23SHaojian Zhuang unsigned int lock_val = (lockid << 29) | LOCK_BIT; 8928b02e23SHaojian Zhuang 9028b02e23SHaojian Zhuang mmio_write_32((LOCK_UNLOCK_OFFSET + (uintptr_t)offset), lock_val); 9128b02e23SHaojian Zhuang } 9228b02e23SHaojian Zhuang 9328b02e23SHaojian Zhuang 9428b02e23SHaojian Zhuang static void hisi_cpuhotplug_lock(unsigned int cluster, unsigned int core) 9528b02e23SHaojian Zhuang { 9628b02e23SHaojian Zhuang unsigned int lock_id; 9728b02e23SHaojian Zhuang 9828b02e23SHaojian Zhuang lock_id = (cluster << 2) + core; 9928b02e23SHaojian Zhuang 10028b02e23SHaojian Zhuang hisi_resource_lock(lock_id, RES2_LOCK_BASE); 10128b02e23SHaojian Zhuang } 10228b02e23SHaojian Zhuang 10328b02e23SHaojian Zhuang static void hisi_cpuhotplug_unlock(unsigned int cluster, unsigned int core) 10428b02e23SHaojian Zhuang { 10528b02e23SHaojian Zhuang unsigned int lock_id; 10628b02e23SHaojian Zhuang 10728b02e23SHaojian Zhuang lock_id = (cluster << 2) + core; 10828b02e23SHaojian Zhuang 10928b02e23SHaojian Zhuang hisi_resource_unlock(lock_id, RES2_LOCK_BASE); 11028b02e23SHaojian Zhuang } 11128b02e23SHaojian Zhuang 11228b02e23SHaojian Zhuang /* get the resource lock */ 11328b02e23SHaojian Zhuang void hisi_cpuidle_lock(unsigned int cluster, unsigned int core) 11428b02e23SHaojian Zhuang { 11528b02e23SHaojian Zhuang unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE); 11628b02e23SHaojian Zhuang 11728b02e23SHaojian Zhuang hisi_resource_lock(CPUIDLE_LOCK_ID(core), offset); 11828b02e23SHaojian Zhuang } 11928b02e23SHaojian Zhuang 12028b02e23SHaojian Zhuang /* release the resource lock */ 12128b02e23SHaojian Zhuang void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core) 12228b02e23SHaojian Zhuang { 12328b02e23SHaojian Zhuang unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE); 12428b02e23SHaojian Zhuang 12528b02e23SHaojian Zhuang hisi_resource_unlock(CPUIDLE_LOCK_ID(core), offset); 12628b02e23SHaojian Zhuang } 12728b02e23SHaojian Zhuang 12828b02e23SHaojian Zhuang unsigned int hisi_get_cpuidle_flag(unsigned int cluster) 12928b02e23SHaojian Zhuang { 13028b02e23SHaojian Zhuang unsigned int val; 13128b02e23SHaojian Zhuang 13228b02e23SHaojian Zhuang val = mmio_read_32(CPUIDLE_FLAG_REG(cluster)); 13328b02e23SHaojian Zhuang val &= 0xF; 13428b02e23SHaojian Zhuang 13528b02e23SHaojian Zhuang return val; 13628b02e23SHaojian Zhuang } 13728b02e23SHaojian Zhuang 13828b02e23SHaojian Zhuang void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core) 13928b02e23SHaojian Zhuang { 14028b02e23SHaojian Zhuang mmio_setbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core)); 14128b02e23SHaojian Zhuang } 14228b02e23SHaojian Zhuang 14328b02e23SHaojian Zhuang void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core) 14428b02e23SHaojian Zhuang { 14528b02e23SHaojian Zhuang mmio_clrbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core)); 14628b02e23SHaojian Zhuang 14728b02e23SHaojian Zhuang } 14828b02e23SHaojian Zhuang 14928b02e23SHaojian Zhuang int hisi_test_ap_suspend_flag(unsigned int cluster) 15028b02e23SHaojian Zhuang { 15128b02e23SHaojian Zhuang unsigned int val; 15228b02e23SHaojian Zhuang 15328b02e23SHaojian Zhuang val = mmio_read_32(CPUIDLE_FLAG_REG(cluster)); 15428b02e23SHaojian Zhuang val &= AP_SUSPEND_FLAG; 15528b02e23SHaojian Zhuang return !!val; 15628b02e23SHaojian Zhuang } 15728b02e23SHaojian Zhuang 15828b02e23SHaojian Zhuang void hisi_set_cluster_pwdn_flag(unsigned int cluster, 15928b02e23SHaojian Zhuang unsigned int core, unsigned int value) 16028b02e23SHaojian Zhuang { 16128b02e23SHaojian Zhuang unsigned int val; 16228b02e23SHaojian Zhuang 16328b02e23SHaojian Zhuang hisi_cpuhotplug_lock(cluster, core); 16428b02e23SHaojian Zhuang 16528b02e23SHaojian Zhuang val = mmio_read_32(REG_SCBAKDATA3_OFFSET); 16628b02e23SHaojian Zhuang val = (value << (cluster << 1)) | (val & 0xFFFFFFF); 16728b02e23SHaojian Zhuang mmio_write_32(REG_SCBAKDATA3_OFFSET, val); 16828b02e23SHaojian Zhuang 16928b02e23SHaojian Zhuang hisi_cpuhotplug_unlock(cluster, core); 17028b02e23SHaojian Zhuang } 17128b02e23SHaojian Zhuang 17228b02e23SHaojian Zhuang unsigned int hisi_get_cpu_boot_flag(unsigned int cluster, unsigned int core) 17328b02e23SHaojian Zhuang { 17428b02e23SHaojian Zhuang unsigned int val; 17528b02e23SHaojian Zhuang 17628b02e23SHaojian Zhuang hisi_cpuhotplug_lock(cluster, core); 17728b02e23SHaojian Zhuang val = mmio_read_32(REG_SCBAKDATA3_OFFSET); 17828b02e23SHaojian Zhuang val = val >> (16 + (cluster << 2)); 17928b02e23SHaojian Zhuang val &= 0xF; 18028b02e23SHaojian Zhuang hisi_cpuhotplug_unlock(cluster, core); 18128b02e23SHaojian Zhuang 18228b02e23SHaojian Zhuang return val; 18328b02e23SHaojian Zhuang } 18428b02e23SHaojian Zhuang 18528b02e23SHaojian Zhuang unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core) 18628b02e23SHaojian Zhuang { 18728b02e23SHaojian Zhuang unsigned int val; 18828b02e23SHaojian Zhuang 18928b02e23SHaojian Zhuang hisi_cpuhotplug_lock(cluster, core); 19028b02e23SHaojian Zhuang val = mmio_read_32(REG_SCBAKDATA3_OFFSET); 19128b02e23SHaojian Zhuang val = val >> (16 + (cluster << 2)); 19228b02e23SHaojian Zhuang val &= 0xF; 19328b02e23SHaojian Zhuang hisi_cpuhotplug_unlock(cluster, core); 19428b02e23SHaojian Zhuang 19528b02e23SHaojian Zhuang if (val) 19628b02e23SHaojian Zhuang return 0; 19728b02e23SHaojian Zhuang else 19828b02e23SHaojian Zhuang return 1; 19928b02e23SHaojian Zhuang } 20028b02e23SHaojian Zhuang 20128b02e23SHaojian Zhuang void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core) 20228b02e23SHaojian Zhuang { 20328b02e23SHaojian Zhuang unsigned int flag = BIT((cluster<<2) + core + 16); 20428b02e23SHaojian Zhuang 20528b02e23SHaojian Zhuang hisi_cpuhotplug_lock(cluster, core); 20628b02e23SHaojian Zhuang 20728b02e23SHaojian Zhuang mmio_setbits_32(REG_SCBAKDATA3_OFFSET, flag); 20828b02e23SHaojian Zhuang 20928b02e23SHaojian Zhuang hisi_cpuhotplug_unlock(cluster, core); 21028b02e23SHaojian Zhuang } 21128b02e23SHaojian Zhuang 21228b02e23SHaojian Zhuang void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core) 21328b02e23SHaojian Zhuang { 21428b02e23SHaojian Zhuang unsigned int flag = BIT((cluster<<2) + core + 16); 21528b02e23SHaojian Zhuang 21628b02e23SHaojian Zhuang hisi_cpuhotplug_lock(cluster, core); 21728b02e23SHaojian Zhuang 21828b02e23SHaojian Zhuang mmio_clrbits_32(REG_SCBAKDATA3_OFFSET, flag); 21928b02e23SHaojian Zhuang 22028b02e23SHaojian Zhuang hisi_cpuhotplug_unlock(cluster, core); 22128b02e23SHaojian Zhuang } 22228b02e23SHaojian Zhuang 22328b02e23SHaojian Zhuang int cluster_is_powered_on(unsigned int cluster) 22428b02e23SHaojian Zhuang { 22528b02e23SHaojian Zhuang unsigned int val = mmio_read_32(REG_SCBAKDATA3_OFFSET); 22628b02e23SHaojian Zhuang int ret; 22728b02e23SHaojian Zhuang 22828b02e23SHaojian Zhuang if (cluster == 0) 22928b02e23SHaojian Zhuang ret = val & CLUSTER0_CPUS_ONLINE_MASK; 23028b02e23SHaojian Zhuang else 23128b02e23SHaojian Zhuang ret = val & CLUSTER1_CPUS_ONLINE_MASK; 23228b02e23SHaojian Zhuang 23328b02e23SHaojian Zhuang return !!ret; 23428b02e23SHaojian Zhuang } 23528b02e23SHaojian Zhuang 23628b02e23SHaojian Zhuang static void *hisi_get_pdc_addr(unsigned int cluster) 23728b02e23SHaojian Zhuang { 23828b02e23SHaojian Zhuang void *pdc_base_addr; 23928b02e23SHaojian Zhuang uintptr_t addr; 24028b02e23SHaojian Zhuang 24128b02e23SHaojian Zhuang if (cluster == 0) 24228b02e23SHaojian Zhuang addr = SOC_CRGPERIPH_A53_PDCEN_ADDR(CRG_BASE); 24328b02e23SHaojian Zhuang else 24428b02e23SHaojian Zhuang addr = SOC_CRGPERIPH_MAIA_PDCEN_ADDR(CRG_BASE); 24528b02e23SHaojian Zhuang pdc_base_addr = (void *)addr; 24628b02e23SHaojian Zhuang 24728b02e23SHaojian Zhuang return pdc_base_addr; 24828b02e23SHaojian Zhuang } 24928b02e23SHaojian Zhuang 25028b02e23SHaojian Zhuang static unsigned int hisi_get_pdc_stat(unsigned int cluster) 25128b02e23SHaojian Zhuang { 25228b02e23SHaojian Zhuang void *pdc_base_addr = hisi_get_pdc_addr(cluster); 25328b02e23SHaojian Zhuang unsigned int val; 25428b02e23SHaojian Zhuang 25528b02e23SHaojian Zhuang val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPOWERSTAT_OFFSET); 25628b02e23SHaojian Zhuang 25728b02e23SHaojian Zhuang return val; 25828b02e23SHaojian Zhuang } 25928b02e23SHaojian Zhuang 26028b02e23SHaojian Zhuang int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core) 26128b02e23SHaojian Zhuang { 26228b02e23SHaojian Zhuang unsigned int mask = 0xf << (core * 4); 26328b02e23SHaojian Zhuang unsigned int pdc_stat = hisi_get_pdc_stat(cluster); 26428b02e23SHaojian Zhuang unsigned int boot_flag = hisi_get_cpu_boot_flag(cluster, core); 26528b02e23SHaojian Zhuang unsigned int cpuidle_flag = hisi_get_cpuidle_flag(cluster); 26628b02e23SHaojian Zhuang 26728b02e23SHaojian Zhuang mask = (PDC_COREPWRSTAT_MASK & (~mask)); 26828b02e23SHaojian Zhuang pdc_stat &= mask; 26928b02e23SHaojian Zhuang 27028b02e23SHaojian Zhuang if ((boot_flag ^ cpuidle_flag) || pdc_stat) 27128b02e23SHaojian Zhuang return 0; 27228b02e23SHaojian Zhuang else 27328b02e23SHaojian Zhuang return 1; 27428b02e23SHaojian Zhuang } 27528b02e23SHaojian Zhuang 27628b02e23SHaojian Zhuang void hisi_disable_pdc(unsigned int cluster) 27728b02e23SHaojian Zhuang { 27828b02e23SHaojian Zhuang void *pdc_base_addr = hisi_get_pdc_addr(cluster); 27928b02e23SHaojian Zhuang 28028b02e23SHaojian Zhuang mmio_write_32((uintptr_t)pdc_base_addr, 0x0); 28128b02e23SHaojian Zhuang } 28228b02e23SHaojian Zhuang 28328b02e23SHaojian Zhuang void hisi_enable_pdc(unsigned int cluster) 28428b02e23SHaojian Zhuang { 28528b02e23SHaojian Zhuang void *pdc_base_addr = hisi_get_pdc_addr(cluster); 28628b02e23SHaojian Zhuang 28728b02e23SHaojian Zhuang mmio_write_32((uintptr_t)pdc_base_addr, 0x1); 28828b02e23SHaojian Zhuang } 28928b02e23SHaojian Zhuang 290*056b3d49SHaojian Zhuang void hisi_pdc_set_intmask(void *pdc_base_addr, 29128b02e23SHaojian Zhuang unsigned int core, 29228b02e23SHaojian Zhuang enum pdc_finish_int_mask intmask) 29328b02e23SHaojian Zhuang { 29428b02e23SHaojian Zhuang unsigned int val; 29528b02e23SHaojian Zhuang 29628b02e23SHaojian Zhuang val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET); 29728b02e23SHaojian Zhuang if (intmask == PDC_ENABLE_FINISH_INT) 29828b02e23SHaojian Zhuang val |= BIT(core); 29928b02e23SHaojian Zhuang else 30028b02e23SHaojian Zhuang val &= ~BIT(core); 30128b02e23SHaojian Zhuang 30228b02e23SHaojian Zhuang mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, val); 30328b02e23SHaojian Zhuang } 30428b02e23SHaojian Zhuang 30528b02e23SHaojian Zhuang static inline void hisi_pdc_set_gicmask(void *pdc_base_addr, 30628b02e23SHaojian Zhuang unsigned int core, 30728b02e23SHaojian Zhuang enum pdc_gic_mask gicmask) 30828b02e23SHaojian Zhuang { 30928b02e23SHaojian Zhuang unsigned int val; 31028b02e23SHaojian Zhuang 31128b02e23SHaojian Zhuang val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET); 31228b02e23SHaojian Zhuang if (gicmask == PDC_MASK_GIC_WAKE_IRQ) 31328b02e23SHaojian Zhuang val |= BIT(core); 31428b02e23SHaojian Zhuang else 31528b02e23SHaojian Zhuang val &= ~BIT(core); 31628b02e23SHaojian Zhuang 31728b02e23SHaojian Zhuang mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET, val); 31828b02e23SHaojian Zhuang } 31928b02e23SHaojian Zhuang 32028b02e23SHaojian Zhuang void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster) 32128b02e23SHaojian Zhuang { 32228b02e23SHaojian Zhuang int i; 32328b02e23SHaojian Zhuang void *pdc_base_addr = hisi_get_pdc_addr(cluster); 32428b02e23SHaojian Zhuang 32528b02e23SHaojian Zhuang for (i = 0; i < 4; i++) 32628b02e23SHaojian Zhuang hisi_pdc_set_gicmask(pdc_base_addr, i, PDC_MASK_GIC_WAKE_IRQ); 32728b02e23SHaojian Zhuang } 32828b02e23SHaojian Zhuang 32928b02e23SHaojian Zhuang static void hisi_pdc_powerup_core(unsigned int cluster, unsigned int core, 33028b02e23SHaojian Zhuang enum pdc_gic_mask gicmask, 33128b02e23SHaojian Zhuang enum pdc_finish_int_mask intmask) 33228b02e23SHaojian Zhuang { 33328b02e23SHaojian Zhuang void *pdc_base_addr = hisi_get_pdc_addr(cluster); 33428b02e23SHaojian Zhuang 33528b02e23SHaojian Zhuang mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERUP_OFFSET, 33628b02e23SHaojian Zhuang BIT(core)); 33728b02e23SHaojian Zhuang } 33828b02e23SHaojian Zhuang 33928b02e23SHaojian Zhuang static void hisi_pdc_powerdn_core(unsigned int cluster, unsigned int core, 34028b02e23SHaojian Zhuang enum pdc_gic_mask gicmask, 34128b02e23SHaojian Zhuang enum pdc_finish_int_mask intmask) 34228b02e23SHaojian Zhuang { 34328b02e23SHaojian Zhuang void *pdc_base_addr = hisi_get_pdc_addr(cluster); 34428b02e23SHaojian Zhuang 34528b02e23SHaojian Zhuang mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, 34628b02e23SHaojian Zhuang BIT(core)); 34728b02e23SHaojian Zhuang } 34828b02e23SHaojian Zhuang 34928b02e23SHaojian Zhuang void hisi_powerup_core(unsigned int cluster, unsigned int core) 35028b02e23SHaojian Zhuang { 35128b02e23SHaojian Zhuang hisi_pdc_powerup_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ, 35228b02e23SHaojian Zhuang PDC_DISABLE_FINISH_INT); 35328b02e23SHaojian Zhuang } 35428b02e23SHaojian Zhuang 35528b02e23SHaojian Zhuang void hisi_powerdn_core(unsigned int cluster, unsigned int core) 35628b02e23SHaojian Zhuang { 35728b02e23SHaojian Zhuang hisi_pdc_powerdn_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ, 35828b02e23SHaojian Zhuang PDC_DISABLE_FINISH_INT); 35928b02e23SHaojian Zhuang } 36028b02e23SHaojian Zhuang 36128b02e23SHaojian Zhuang void hisi_powerup_cluster(unsigned int cluster, unsigned int core) 36228b02e23SHaojian Zhuang { 36328b02e23SHaojian Zhuang hisi_ipc_pm_on_off(core, cluster, PM_ON); 36428b02e23SHaojian Zhuang } 36528b02e23SHaojian Zhuang 36628b02e23SHaojian Zhuang void hisi_powerdn_cluster(unsigned int cluster, unsigned int core) 36728b02e23SHaojian Zhuang { 36828b02e23SHaojian Zhuang void *pdc_base_addr = hisi_get_pdc_addr(cluster); 36928b02e23SHaojian Zhuang 37028b02e23SHaojian Zhuang hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_HOTPLUG); 37128b02e23SHaojian Zhuang mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, 37228b02e23SHaojian Zhuang (0x10001 << core)); 37328b02e23SHaojian Zhuang mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, 37428b02e23SHaojian Zhuang BIT(core)); 37528b02e23SHaojian Zhuang } 37628b02e23SHaojian Zhuang 37728b02e23SHaojian Zhuang void hisi_enter_core_idle(unsigned int cluster, unsigned int core) 37828b02e23SHaojian Zhuang { 37928b02e23SHaojian Zhuang hisi_pdc_powerdn_core(cluster, core, PDC_UNMASK_GIC_WAKE_IRQ, 38028b02e23SHaojian Zhuang PDC_DISABLE_FINISH_INT); 38128b02e23SHaojian Zhuang } 38228b02e23SHaojian Zhuang 38328b02e23SHaojian Zhuang void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core) 38428b02e23SHaojian Zhuang { 38528b02e23SHaojian Zhuang void *pdc_base_addr = hisi_get_pdc_addr(cluster); 38628b02e23SHaojian Zhuang 38728b02e23SHaojian Zhuang hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_IDLE); 38828b02e23SHaojian Zhuang mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, 38928b02e23SHaojian Zhuang (0x10001 << core)); 39028b02e23SHaojian Zhuang mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, 39128b02e23SHaojian Zhuang BIT(core)); 39228b02e23SHaojian Zhuang } 39328b02e23SHaojian Zhuang 39428b02e23SHaojian Zhuang void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core) 39528b02e23SHaojian Zhuang { 39628b02e23SHaojian Zhuang hisi_ipc_pm_suspend(core, cluster, 0x3); 39728b02e23SHaojian Zhuang } 398