diff options
-rw-r--r-- | arch/arm/mach-exynos/exynos.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-exynos/mcpm-exynos.c | 36 | ||||
-rw-r--r-- | arch/arm/mach-exynos/regs-pmu.h | 9 | ||||
-rw-r--r-- | drivers/cpuidle/Kconfig.arm | 2 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle-big_little.c | 12 |
5 files changed, 60 insertions, 3 deletions
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 80cbbc74d2c8..2a43a1734eca 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -335,7 +335,9 @@ static void __init exynos_dt_machine_init(void) if (!IS_ENABLED(CONFIG_SMP)) exynos_sysram_init(); - exynos_cpuidle_init(); + if (!of_machine_is_compatible("samsung,exynos5420")) + exynos_cpuidle_init(); + exynos_cpufreq_init(); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); diff --git a/arch/arm/mach-exynos/mcpm-exynos.c b/arch/arm/mach-exynos/mcpm-exynos.c index ace0ed617476..13a210865c6f 100644 --- a/arch/arm/mach-exynos/mcpm-exynos.c +++ b/arch/arm/mach-exynos/mcpm-exynos.c @@ -257,10 +257,46 @@ static int exynos_wait_for_powerdown(unsigned int cpu, unsigned int cluster) return -ETIMEDOUT; /* timeout */ } +static void exynos_powered_up(void) +{ + unsigned int mpidr, cpu, cluster; + + mpidr = read_cpuid_mpidr(); + cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); + cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); + + arch_spin_lock(&exynos_mcpm_lock); + if (cpu_use_count[cpu][cluster] == 0) + cpu_use_count[cpu][cluster] = 1; + arch_spin_unlock(&exynos_mcpm_lock); +} + +static void exynos_suspend(u64 residency) +{ + unsigned int mpidr, cpunr; + + exynos_power_down(); + + /* + * Execution reaches here only if cpu did not power down. + * Hence roll back the changes done in exynos_power_down function. + * + * CAUTION: "This function requires the stack data to be visible through + * power down and can only be executed on processors like A15 and A7 + * that hit the cache with the C bit clear in the SCTLR register." + */ + mpidr = read_cpuid_mpidr(); + cpunr = exynos_pmu_cpunr(mpidr); + + exynos_cpu_power_up(cpunr); +} + static const struct mcpm_platform_ops exynos_power_ops = { .power_up = exynos_power_up, .power_down = exynos_power_down, .wait_for_powerdown = exynos_wait_for_powerdown, + .suspend = exynos_suspend, + .powered_up = exynos_powered_up, }; static void __init exynos_mcpm_usage_count_init(void) diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 1993e6bd5388..c45a2dc53e84 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -319,4 +319,13 @@ #define EXYNOS5420_SWRESET_KFC_SEL 0x3 +#include <asm/cputype.h> +#define MAX_CPUS_IN_CLUSTER 4 + +static inline unsigned int exynos_pmu_cpunr(unsigned int mpidr) +{ + return ((MPIDR_AFFINITY_LEVEL(mpidr, 1) * MAX_CPUS_IN_CLUSTER) + + MPIDR_AFFINITY_LEVEL(mpidr, 0)); +} + #endif /* __ASM_ARCH_REGS_PMU_H */ diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index b6d69e899f5d..2f6b33ea6e08 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -9,7 +9,7 @@ config ARM_ARMADA_370_XP_CPUIDLE config ARM_BIG_LITTLE_CPUIDLE bool "Support for ARM big.LITTLE processors" - depends on ARCH_VEXPRESS_TC2_PM + depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS select ARM_CPU_SUSPEND select CPU_IDLE_MULTIPLE_DRIVERS help diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c index b45fc6249041..344d79fa3407 100644 --- a/drivers/cpuidle/cpuidle-big_little.c +++ b/drivers/cpuidle/cpuidle-big_little.c @@ -163,14 +163,24 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id) return 0; } +static const struct of_device_id compatible_machine_match[] = { + { .compatible = "arm,vexpress,v2p-ca15_a7" }, + { .compatible = "samsung,exynos5420" }, + {}, +}; + static int __init bl_idle_init(void) { int ret; + struct device_node *root = of_find_node_by_path("/"); + + if (!root) + return -ENODEV; /* * Initialize the driver just for a compliant set of machines */ - if (!of_machine_is_compatible("arm,vexpress,v2p-ca15_a7")) + if (!of_match_node(compatible_machine_match, root)) return -ENODEV; /* * For now the differentiation between little and big cores |