summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos
diff options
context:
space:
mode:
authorKukjin Kim2014-07-23 01:18:15 +0200
committerKukjin Kim2014-07-23 01:18:15 +0200
commit5f534d10d223636b3cd214376471fcfef71baea2 (patch)
tree38c14b78e01e7270ccce6d6144d124a7129ca707 /arch/arm/mach-exynos
parentMerge branch 'v3.17-next/cleanup-samsung' into v3.17-next/power-exynos (diff)
parentARM: EXYNOS: populate suspend and powered_up callbacks for mcpm (diff)
downloadkernel-qcow2-linux-5f534d10d223636b3cd214376471fcfef71baea2.tar.gz
kernel-qcow2-linux-5f534d10d223636b3cd214376471fcfef71baea2.tar.xz
kernel-qcow2-linux-5f534d10d223636b3cd214376471fcfef71baea2.zip
Merge branch 'v3.17-next/cpuidle-exynos' into v3.17-next/power-exynos
Diffstat (limited to 'arch/arm/mach-exynos')
-rw-r--r--arch/arm/mach-exynos/exynos.c4
-rw-r--r--arch/arm/mach-exynos/mcpm-exynos.c36
-rw-r--r--arch/arm/mach-exynos/regs-pmu.h9
3 files changed, 48 insertions, 1 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 */