diff options
Diffstat (limited to 'arch/arm/common/mcpm_entry.c')
| -rw-r--r-- | arch/arm/common/mcpm_entry.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c index 370236dd1a0..f91136ab447 100644 --- a/arch/arm/common/mcpm_entry.c +++ b/arch/arm/common/mcpm_entry.c @@ -27,6 +27,17 @@ void mcpm_set_entry_vector(unsigned cpu, unsigned cluster, void *ptr) sync_cache_w(&mcpm_entry_vectors[cluster][cpu]); } +extern unsigned long mcpm_entry_early_pokes[MAX_NR_CLUSTERS][MAX_CPUS_PER_CLUSTER][2]; + +void mcpm_set_early_poke(unsigned cpu, unsigned cluster, + unsigned long poke_phys_addr, unsigned long poke_val) +{ + unsigned long *poke = &mcpm_entry_early_pokes[cluster][cpu][0]; + poke[0] = poke_phys_addr; + poke[1] = poke_val; + __sync_cache_range_w(poke, 2 * sizeof(*poke)); +} + static const struct mcpm_platform_ops *platform_ops; int __init mcpm_platform_register(const struct mcpm_platform_ops *ops) @@ -37,6 +48,11 @@ int __init mcpm_platform_register(const struct mcpm_platform_ops *ops) return 0; } +bool mcpm_is_available(void) +{ + return (platform_ops) ? true : false; +} + int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster) { if (!platform_ops) @@ -51,7 +67,8 @@ void mcpm_cpu_power_down(void) { phys_reset_t phys_reset; - BUG_ON(!platform_ops); + if (WARN_ON_ONCE(!platform_ops || !platform_ops->power_down)) + return; BUG_ON(!irqs_disabled()); /* @@ -89,11 +106,27 @@ void mcpm_cpu_power_down(void) BUG(); } +int mcpm_wait_for_cpu_powerdown(unsigned int cpu, unsigned int cluster) +{ + int ret; + + if (WARN_ON_ONCE(!platform_ops || !platform_ops->wait_for_powerdown)) + return -EUNATCH; + + ret = platform_ops->wait_for_powerdown(cpu, cluster); + if (ret) + pr_warn("%s: cpu %u, cluster %u failed to power down (%d)\n", + __func__, cpu, cluster, ret); + + return ret; +} + void mcpm_cpu_suspend(u64 expected_residency) { phys_reset_t phys_reset; - BUG_ON(!platform_ops); + if (WARN_ON_ONCE(!platform_ops || !platform_ops->suspend)) + return; BUG_ON(!irqs_disabled()); /* Very similar to mcpm_cpu_power_down() */ @@ -138,7 +171,7 @@ void __mcpm_cpu_down(unsigned int cpu, unsigned int cluster) dmb(); mcpm_sync.clusters[cluster].cpus[cpu].cpu = CPU_DOWN; sync_cache_w(&mcpm_sync.clusters[cluster].cpus[cpu].cpu); - dsb_sev(); + sev(); } /* @@ -154,7 +187,7 @@ void __mcpm_outbound_leave_critical(unsigned int cluster, int state) dmb(); mcpm_sync.clusters[cluster].cluster = state; sync_cache_w(&mcpm_sync.clusters[cluster].cluster); - dsb_sev(); + sev(); } /* |
