From: Park Bumgyu Date: Fri, 26 Jan 2018 10:15:49 +0000 (+0900) Subject: soc: cpupm: support c2 state idle X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=6de00e18cbfaa4c389c6d13578ca082e34323d9c;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git soc: cpupm: support c2 state idle Change-Id: I27d951d61470de912fde7fe21419ecaa3d9ffecb Signed-off-by: Park Bumgyu --- diff --git a/drivers/cpuidle/cpuidle-exynos64.c b/drivers/cpuidle/cpuidle-exynos64.c index e6191fd48ef0..705a6432e28e 100644 --- a/drivers/cpuidle/cpuidle-exynos64.c +++ b/drivers/cpuidle/cpuidle-exynos64.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include "dt_idle_states.h" #include "profiler.h" diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile index 4bf06f88ef4f..34eb685df2e5 100644 --- a/drivers/soc/samsung/Makefile +++ b/drivers/soc/samsung/Makefile @@ -34,3 +34,6 @@ obj-$(CONFIG_EXYNOS_PD) += exynos-pd.o exynos-pd-dbg.o obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o #CPUHOTPLUG obj-$(CONFIG_ARCH_EXYNOS) += exynos-cpu_hotplug.o + +#CPU Power Management +obj-$(CONFIG_ARCH_EXYNOS) += exynos-cpupm.o diff --git a/drivers/soc/samsung/exynos-cpupm.c b/drivers/soc/samsung/exynos-cpupm.c new file mode 100644 index 000000000000..ec33586dd145 --- /dev/null +++ b/drivers/soc/samsung/exynos-cpupm.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2018 Park Bumgyu, Samsung Electronics Co., Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Exynos CPU Power Management driver implementation + */ + +#include +#include + +#include + +/****************************************************************************** + * CAL interfaces * + ******************************************************************************/ +static void cpu_enable(unsigned int cpu) +{ + cal_cpu_enable(cpu); +} + +static void cpu_disable(unsigned int cpu) +{ + cal_cpu_disable(cpu); +} + +/****************************************************************************** + * CPU idle management * + ******************************************************************************/ +/* + * State of CPUPM objects + * All CPUPM objects have 2 states, RUN and POWERDOWN. + * + * @RUN + * a state in which the power domain referred to by the object is turned on. + * + * @POWERDOWN + * a state in which the power domain referred to by the object is turned off. + * However, the power domain is not necessarily turned off even if the object + * is in POEWRDOWN state because the cpu may be booting or executing power off + * sequence. + */ +enum { + CPUPM_STATE_RUN = 0, + CPUPM_STATE_POWERDOWN, +}; + +/* Macros for CPUPM state */ +#define set_state_run(object) (object)->state = CPUPM_STATE_RUN +#define set_state_powerdown(object) (object)->state = CPUPM_STATE_POWERDOWN + +/* + * Main struct of CPUPM + * Each cpu has its own data structure and main purpose of this struct is to + * manage the state of the cpu. + */ +struct exynos_cpupm { + /* cpu state, RUN or POWERDOWN */ + int state; +}; + +static DEFINE_PER_CPU(struct exynos_cpupm, cpupm); + +/* + * State of each cpu is managed by a structure declared by percpu, so there + * is no need for protection for synchronization. However, when entering + * the power mode, it is necessary to set the critical section to check the + * state of cpus in the power domain, cpupm_lock is used for it. + */ +static spinlock_t cpupm_lock; + +/* + * Exynos cpuidle driver call exynos_cpu_pm_enter() and exynos_cpu_pm_exit() + * to handle platform specific configuration to control cpu power domain. + */ +int exynos_cpu_pm_enter(int cpu, int index) +{ + struct exynos_cpupm *pm; + + spin_lock(&cpupm_lock); + pm = &per_cpu(cpupm, cpu); + + /* Configure PMUCAL to power down core */ + cpu_disable(cpu); + + /* Set cpu state to POWERDOWN */ + set_state_powerdown(pm); + + spin_unlock(&cpupm_lock); + + return index; +} + +void exynos_cpu_pm_exit(int cpu, int cancel) +{ + struct exynos_cpupm *pm; + + spin_lock(&cpupm_lock); + pm = &per_cpu(cpupm, cpu); + + /* Set cpu state to RUN */ + set_state_run(pm); + + /* Configure PMUCAL to power up core */ + cpu_enable(cpu); + + spin_unlock(&cpupm_lock); +} + +/****************************************************************************** + * Initialization * + ******************************************************************************/ +static int __init exynos_cpupm_init(void) +{ + spin_lock_init(&cpupm_lock); + + return 0; +} +arch_initcall(exynos_cpupm_init); diff --git a/include/soc/samsung/exynos-cpupm.h b/include/soc/samsung/exynos-cpupm.h new file mode 100644 index 000000000000..41281a2fac8d --- /dev/null +++ b/include/soc/samsung/exynos-cpupm.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018 Park Bumgyu, Samsung Electronics Co., Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __EXYNOS_CPUPM_H +#define __EXYNOS_CPUPM_H __FILE__ + +extern int exynos_cpu_pm_enter(int cpu, int index); +extern void exynos_cpu_pm_exit(int cpu, int cancel); + +#endif /* __EXYNOS_CPUPM_H */