aboutsummaryrefslogtreecommitdiffstats
path: root/plat
diff options
context:
space:
mode:
authorAntonio Niño Díaz <antonio.ninodiaz@arm.com>2019-04-12 09:32:08 +0000
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2019-04-12 09:32:08 +0000
commit5c92aeab4f74357be61251dae601e41f5adc9991 (patch)
treecd8bb3eeb24c04e3e01d122f30a927188d2fa398 /plat
parentc554e1ad82b0cf874a76e4685a4da61da14da1fe (diff)
parent7d76df7db2c79b37f3c2357758fb2c565d4cce6f (diff)
downloadplatform_external_arm-trusted-firmware-5c92aeab4f74357be61251dae601e41f5adc9991.tar.gz
platform_external_arm-trusted-firmware-5c92aeab4f74357be61251dae601e41f5adc9991.tar.bz2
platform_external_arm-trusted-firmware-5c92aeab4f74357be61251dae601e41f5adc9991.zip
Merge "hikey960: Fix race condition between hotplug and idles" into integration
Diffstat (limited to 'plat')
-rw-r--r--plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c33
-rw-r--r--plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h2
-rw-r--r--plat/hisilicon/hikey960/hikey960_pm.c4
3 files changed, 29 insertions, 10 deletions
diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c
index 659a1c4ad..bcf68650c 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 c0170ad96..e0cb3815f 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 676cfa3f3..ede893ecb 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,