diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c index 659a1c4ad25669e6ad11060a9bf37be13ab4ae71..bcf68650cd37cd6e20bdfd2d72c219e197921dfe 100644 --- a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c +++ b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c @@ -147,13 +147,19 @@ void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core) } -int hisi_test_ap_suspend_flag(unsigned int cluster) +int hisi_test_ap_suspend_flag(void) { - unsigned int val; + unsigned int val1; + unsigned int val2; - val = mmio_read_32(CPUIDLE_FLAG_REG(cluster)); - val &= AP_SUSPEND_FLAG; - return !!val; + val1 = mmio_read_32(CPUIDLE_FLAG_REG(0)); + val1 &= AP_SUSPEND_FLAG; + + val2 = mmio_read_32(CPUIDLE_FLAG_REG(1)); + val2 &= AP_SUSPEND_FLAG; + + val1 |= val2; + return (val1 != 0); } void hisi_set_cluster_pwdn_flag(unsigned int cluster, @@ -164,7 +170,8 @@ void hisi_set_cluster_pwdn_flag(unsigned int cluster, hisi_cpuhotplug_lock(cluster, core); val = mmio_read_32(REG_SCBAKDATA3_OFFSET); - val = (value << (cluster << 1)) | (val & 0xFFFFFFF); + val &= ~(0x3U << ((2 * cluster) + 28)); + val |= (value << (2 * cluster)); mmio_write_32(REG_SCBAKDATA3_OFFSET, val); hisi_cpuhotplug_unlock(cluster, core); @@ -258,6 +265,17 @@ static unsigned int hisi_get_pdc_stat(unsigned int cluster) return val; } +static int check_hotplug(unsigned int cluster, unsigned int boot_flag) +{ + unsigned int mask = 0xF; + + if (hisi_test_ap_suspend_flag() || + ((boot_flag & mask) == mask)) + return 0; + + return 1; +} + int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core) { unsigned int mask = 0xf << (core * 4); @@ -268,7 +286,8 @@ int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core) mask = (PDC_COREPWRSTAT_MASK & (~mask)); pdc_stat &= mask; - if ((boot_flag ^ cpuidle_flag) || pdc_stat) + if ((boot_flag ^ cpuidle_flag) || pdc_stat || + check_hotplug(cluster, boot_flag)) return 0; else return 1; diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h index c0170ad96ab259e04f658440ff21c3c3b2dfbbe3..e0cb3815fbddf77b061ef3f0af1a8c61adacdc01 100644 --- a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h +++ b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h @@ -39,7 +39,7 @@ void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core); int cluster_is_powered_on(unsigned int cluster); void hisi_enter_core_idle(unsigned int cluster, unsigned int core); void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core); -int hisi_test_ap_suspend_flag(unsigned int cluster); +int hisi_test_ap_suspend_flag(void); void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core); diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c index 676cfa3f3cd01bb0ae38b8e351b09a6ae9e60b67..ede893ecbd9c40f98e96d65c83d0f4c33449b29b 100644 --- a/plat/hisilicon/hikey960/hikey960_pm.c +++ b/plat/hisilicon/hikey960/hikey960_pm.c @@ -228,7 +228,7 @@ static void hikey960_pwr_domain_suspend(const psci_power_state_t *target_state) /* check the SR flag bit to determine * CLUSTER_IDLE_IPC or AP_SR_IPC to send */ - if (hisi_test_ap_suspend_flag(cluster)) + if (hisi_test_ap_suspend_flag()) hisi_enter_ap_suspend(cluster, core); else hisi_enter_cluster_idle(cluster, core); @@ -268,7 +268,7 @@ hikey960_pwr_domain_suspend_finish(const psci_power_state_t *target_state) hisi_clear_cpuidle_flag(cluster, core); hisi_cpuidle_unlock(cluster, core); - if (hisi_test_ap_suspend_flag(cluster)) { + if (hisi_test_ap_suspend_flag()) { hikey960_sr_dma_reinit(); gicv2_cpuif_enable(); console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ,