aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-04-10 06:01:24 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-04-10 06:01:24 -0400
commitcdde51b9fe83a20fd6c50e81473e6ffb5ba63b92 (patch)
tree72e35bb87ad895c7cea6310d8f599886d3d9979b
parente5e02de0665ef2477e7a018193051387c6fe0fbc (diff)
parent993c592d745c467d83e753c9e8f4e9f952381478 (diff)
Merge back earlier cpuidle material for v4.1.
-rw-r--r--arch/arm/include/asm/cpuidle.h23
-rw-r--r--arch/arm/kernel/cpuidle.c133
-rw-r--r--arch/arm/mach-davinci/cpuidle.c1
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6q.c1
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sl.c1
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sx.c1
-rw-r--r--arch/arm/mach-omap2/cpuidle44xx.c1
-rw-r--r--arch/arm/mach-s3c64xx/cpuidle.c2
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra20.c1
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra30.c1
-rw-r--r--arch/arm64/configs/defconfig2
-rw-r--r--arch/arm64/include/asm/cpuidle.h9
-rw-r--r--arch/arm64/kernel/cpuidle.c2
-rw-r--r--drivers/cpuidle/Kconfig7
-rw-r--r--drivers/cpuidle/Kconfig.arm28
-rw-r--r--drivers/cpuidle/Kconfig.arm6413
-rw-r--r--drivers/cpuidle/Makefile5
-rw-r--r--drivers/cpuidle/cpuidle-arm.c (renamed from drivers/cpuidle/cpuidle-arm64.c)83
-rw-r--r--drivers/cpuidle/cpuidle-at91.c1
-rw-r--r--drivers/cpuidle/cpuidle-exynos.c1
-rw-r--r--drivers/cpuidle/cpuidle-kirkwood.c1
-rw-r--r--drivers/cpuidle/cpuidle-ux500.c1
-rw-r--r--drivers/cpuidle/cpuidle-zynq.c1
-rw-r--r--include/asm-generic/vmlinux.lds.h2
24 files changed, 249 insertions, 72 deletions
diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h
index af319ac4960c..0f8424924902 100644
--- a/arch/arm/include/asm/cpuidle.h
+++ b/arch/arm/include/asm/cpuidle.h
@@ -1,6 +1,8 @@
1#ifndef __ASM_ARM_CPUIDLE_H 1#ifndef __ASM_ARM_CPUIDLE_H
2#define __ASM_ARM_CPUIDLE_H 2#define __ASM_ARM_CPUIDLE_H
3 3
4#include <asm/proc-fns.h>
5
4#ifdef CONFIG_CPU_IDLE 6#ifdef CONFIG_CPU_IDLE
5extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev, 7extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
6 struct cpuidle_driver *drv, int index); 8 struct cpuidle_driver *drv, int index);
@@ -25,4 +27,25 @@ static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
25 */ 27 */
26#define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX) 28#define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX)
27 29
30struct device_node;
31
32struct cpuidle_ops {
33 int (*suspend)(int cpu, unsigned long arg);
34 int (*init)(struct device_node *, int cpu);
35};
36
37struct of_cpuidle_method {
38 const char *method;
39 struct cpuidle_ops *ops;
40};
41
42#define CPUIDLE_METHOD_OF_DECLARE(name, _method, _ops) \
43 static const struct of_cpuidle_method __cpuidle_method_of_table_##name \
44 __used __section(__cpuidle_method_of_table) \
45 = { .method = _method, .ops = _ops }
46
47extern int arm_cpuidle_suspend(int index);
48
49extern int arm_cpuidle_init(int cpu);
50
28#endif 51#endif
diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c
index 89545f6c8403..318da33465f4 100644
--- a/arch/arm/kernel/cpuidle.c
+++ b/arch/arm/kernel/cpuidle.c
@@ -10,8 +10,28 @@
10 */ 10 */
11 11
12#include <linux/cpuidle.h> 12#include <linux/cpuidle.h>
13#include <asm/proc-fns.h> 13#include <linux/of.h>
14#include <linux/of_device.h>
15#include <asm/cpuidle.h>
14 16
17extern struct of_cpuidle_method __cpuidle_method_of_table[];
18
19static const struct of_cpuidle_method __cpuidle_method_of_table_sentinel
20 __used __section(__cpuidle_method_of_table_end);
21
22static struct cpuidle_ops cpuidle_ops[NR_CPUS];
23
24/**
25 * arm_cpuidle_simple_enter() - a wrapper to cpu_do_idle()
26 * @dev: not used
27 * @drv: not used
28 * @index: not used
29 *
30 * A trivial wrapper to allow the cpu_do_idle function to be assigned as a
31 * cpuidle callback by matching the function signature.
32 *
33 * Returns the index passed as parameter
34 */
15int arm_cpuidle_simple_enter(struct cpuidle_device *dev, 35int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
16 struct cpuidle_driver *drv, int index) 36 struct cpuidle_driver *drv, int index)
17{ 37{
@@ -19,3 +39,114 @@ int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
19 39
20 return index; 40 return index;
21} 41}
42
43/**
44 * arm_cpuidle_suspend() - function to enter low power idle states
45 * @index: an integer used as an identifier for the low level PM callbacks
46 *
47 * This function calls the underlying arch specific low level PM code as
48 * registered at the init time.
49 *
50 * Returns -EOPNOTSUPP if no suspend callback is defined, the result of the
51 * callback otherwise.
52 */
53int arm_cpuidle_suspend(int index)
54{
55 int ret = -EOPNOTSUPP;
56 int cpu = smp_processor_id();
57
58 if (cpuidle_ops[cpu].suspend)
59 ret = cpuidle_ops[cpu].suspend(cpu, index);
60
61 return ret;
62}
63
64/**
65 * arm_cpuidle_get_ops() - find a registered cpuidle_ops by name
66 * @method: the method name
67 *
68 * Search in the __cpuidle_method_of_table array the cpuidle ops matching the
69 * method name.
70 *
71 * Returns a struct cpuidle_ops pointer, NULL if not found.
72 */
73static struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method)
74{
75 struct of_cpuidle_method *m = __cpuidle_method_of_table;
76
77 for (; m->method; m++)
78 if (!strcmp(m->method, method))
79 return m->ops;
80
81 return NULL;
82}
83
84/**
85 * arm_cpuidle_read_ops() - Initialize the cpuidle ops with the device tree
86 * @dn: a pointer to a struct device node corresponding to a cpu node
87 * @cpu: the cpu identifier
88 *
89 * Get the method name defined in the 'enable-method' property, retrieve the
90 * associated cpuidle_ops and do a struct copy. This copy is needed because all
91 * cpuidle_ops are tagged __initdata and will be unloaded after the init
92 * process.
93 *
94 * Return 0 on sucess, -ENOENT if no 'enable-method' is defined, -EOPNOTSUPP if
95 * no cpuidle_ops is registered for the 'enable-method'.
96 */
97static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu)
98{
99 const char *enable_method;
100 struct cpuidle_ops *ops;
101
102 enable_method = of_get_property(dn, "enable-method", NULL);
103 if (!enable_method)
104 return -ENOENT;
105
106 ops = arm_cpuidle_get_ops(enable_method);
107 if (!ops) {
108 pr_warn("%s: unsupported enable-method property: %s\n",
109 dn->full_name, enable_method);
110 return -EOPNOTSUPP;
111 }
112
113 cpuidle_ops[cpu] = *ops; /* structure copy */
114
115 pr_notice("cpuidle: enable-method property '%s'"
116 " found operations\n", enable_method);
117
118 return 0;
119}
120
121/**
122 * arm_cpuidle_init() - Initialize cpuidle_ops for a specific cpu
123 * @cpu: the cpu to be initialized
124 *
125 * Initialize the cpuidle ops with the device for the cpu and then call
126 * the cpu's idle initialization callback. This may fail if the underlying HW
127 * is not operational.
128 *
129 * Returns:
130 * 0 on success,
131 * -ENODEV if it fails to find the cpu node in the device tree,
132 * -EOPNOTSUPP if it does not find a registered cpuidle_ops for this cpu,
133 * -ENOENT if it fails to find an 'enable-method' property,
134 * -ENXIO if the HW reports a failure or a misconfiguration,
135 * -ENOMEM if the HW report an memory allocation failure
136 */
137int __init arm_cpuidle_init(int cpu)
138{
139 struct device_node *cpu_node = of_cpu_device_node_get(cpu);
140 int ret;
141
142 if (!cpu_node)
143 return -ENODEV;
144
145 ret = arm_cpuidle_read_ops(cpu_node, cpu);
146 if (!ret && cpuidle_ops[cpu].init)
147 ret = cpuidle_ops[cpu].init(cpu_node, cpu);
148
149 of_node_put(cpu_node);
150
151 return ret;
152}
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
index e365c1bb1265..306ebc51599a 100644
--- a/arch/arm/mach-davinci/cpuidle.c
+++ b/arch/arm/mach-davinci/cpuidle.c
@@ -17,7 +17,6 @@
17#include <linux/cpuidle.h> 17#include <linux/cpuidle.h>
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/export.h> 19#include <linux/export.h>
20#include <asm/proc-fns.h>
21#include <asm/cpuidle.h> 20#include <asm/cpuidle.h>
22 21
23#include <mach/cpuidle.h> 22#include <mach/cpuidle.h>
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
index d76d08623f9f..8e21ccc1eda2 100644
--- a/arch/arm/mach-imx/cpuidle-imx6q.c
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -9,7 +9,6 @@
9#include <linux/cpuidle.h> 9#include <linux/cpuidle.h>
10#include <linux/module.h> 10#include <linux/module.h>
11#include <asm/cpuidle.h> 11#include <asm/cpuidle.h>
12#include <asm/proc-fns.h>
13 12
14#include "common.h" 13#include "common.h"
15#include "cpuidle.h" 14#include "cpuidle.h"
diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c
index 7d92e6584551..5742a9fd1ef2 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sl.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sl.c
@@ -9,7 +9,6 @@
9#include <linux/cpuidle.h> 9#include <linux/cpuidle.h>
10#include <linux/module.h> 10#include <linux/module.h>
11#include <asm/cpuidle.h> 11#include <asm/cpuidle.h>
12#include <asm/proc-fns.h>
13 12
14#include "common.h" 13#include "common.h"
15#include "cpuidle.h" 14#include "cpuidle.h"
diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c
index 5a36722b089d..2c9f1a8bf245 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sx.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sx.c
@@ -10,7 +10,6 @@
10#include <linux/cpu_pm.h> 10#include <linux/cpu_pm.h>
11#include <linux/module.h> 11#include <linux/module.h>
12#include <asm/cpuidle.h> 12#include <asm/cpuidle.h>
13#include <asm/proc-fns.h>
14#include <asm/suspend.h> 13#include <asm/suspend.h>
15 14
16#include "common.h" 15#include "common.h"
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 01e398a868bc..7622dbb05083 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -17,7 +17,6 @@
17#include <linux/clockchips.h> 17#include <linux/clockchips.h>
18 18
19#include <asm/cpuidle.h> 19#include <asm/cpuidle.h>
20#include <asm/proc-fns.h>
21 20
22#include "common.h" 21#include "common.h"
23#include "pm.h" 22#include "pm.h"
diff --git a/arch/arm/mach-s3c64xx/cpuidle.c b/arch/arm/mach-s3c64xx/cpuidle.c
index 2eb072440dfa..93aa8cb70195 100644
--- a/arch/arm/mach-s3c64xx/cpuidle.c
+++ b/arch/arm/mach-s3c64xx/cpuidle.c
@@ -16,7 +16,7 @@
16#include <linux/export.h> 16#include <linux/export.h>
17#include <linux/time.h> 17#include <linux/time.h>
18 18
19#include <asm/proc-fns.h> 19#include <asm/cpuidle.h>
20 20
21#include <mach/map.h> 21#include <mach/map.h>
22 22
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
index 4f25a7c7ca0f..e22b0d9fdc88 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra20.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -27,7 +27,6 @@
27#include <linux/module.h> 27#include <linux/module.h>
28 28
29#include <asm/cpuidle.h> 29#include <asm/cpuidle.h>
30#include <asm/proc-fns.h>
31#include <asm/smp_plat.h> 30#include <asm/smp_plat.h>
32#include <asm/suspend.h> 31#include <asm/suspend.h>
33 32
diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
index f8815ed65d9d..a2400ab44daa 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra30.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra30.c
@@ -27,7 +27,6 @@
27#include <linux/module.h> 27#include <linux/module.h>
28 28
29#include <asm/cpuidle.h> 29#include <asm/cpuidle.h>
30#include <asm/proc-fns.h>
31#include <asm/smp_plat.h> 30#include <asm/smp_plat.h>
32#include <asm/suspend.h> 31#include <asm/suspend.h>
33 32
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index be1f12a5a5f0..af6a452b1aac 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -48,7 +48,7 @@ CONFIG_CMDLINE="console=ttyAMA0"
48# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set 48# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
49CONFIG_COMPAT=y 49CONFIG_COMPAT=y
50CONFIG_CPU_IDLE=y 50CONFIG_CPU_IDLE=y
51CONFIG_ARM64_CPUIDLE=y 51CONFIG_ARM_CPUIDLE=y
52CONFIG_NET=y 52CONFIG_NET=y
53CONFIG_PACKET=y 53CONFIG_PACKET=y
54CONFIG_UNIX=y 54CONFIG_UNIX=y
diff --git a/arch/arm64/include/asm/cpuidle.h b/arch/arm64/include/asm/cpuidle.h
index c60643f14cda..141b2fcabaa6 100644
--- a/arch/arm64/include/asm/cpuidle.h
+++ b/arch/arm64/include/asm/cpuidle.h
@@ -4,10 +4,10 @@
4#include <asm/proc-fns.h> 4#include <asm/proc-fns.h>
5 5
6#ifdef CONFIG_CPU_IDLE 6#ifdef CONFIG_CPU_IDLE
7extern int cpu_init_idle(unsigned int cpu); 7extern int arm_cpuidle_init(unsigned int cpu);
8extern int cpu_suspend(unsigned long arg); 8extern int cpu_suspend(unsigned long arg);
9#else 9#else
10static inline int cpu_init_idle(unsigned int cpu) 10static inline int arm_cpuidle_init(unsigned int cpu)
11{ 11{
12 return -EOPNOTSUPP; 12 return -EOPNOTSUPP;
13} 13}
@@ -17,5 +17,8 @@ static inline int cpu_suspend(unsigned long arg)
17 return -EOPNOTSUPP; 17 return -EOPNOTSUPP;
18} 18}
19#endif 19#endif
20 20static inline int arm_cpuidle_suspend(int index)
21{
22 return cpu_suspend(index);
23}
21#endif 24#endif
diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c
index 5c0896647fd1..a78143a5c99f 100644
--- a/arch/arm64/kernel/cpuidle.c
+++ b/arch/arm64/kernel/cpuidle.c
@@ -15,7 +15,7 @@
15#include <asm/cpuidle.h> 15#include <asm/cpuidle.h>
16#include <asm/cpu_ops.h> 16#include <asm/cpu_ops.h>
17 17
18int cpu_init_idle(unsigned int cpu) 18int arm_cpuidle_init(unsigned int cpu)
19{ 19{
20 int ret = -EOPNOTSUPP; 20 int ret = -EOPNOTSUPP;
21 struct device_node *cpu_node = of_cpu_device_node_get(cpu); 21 struct device_node *cpu_node = of_cpu_device_node_get(cpu);
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index c5029c1209b4..8c7930b5a65f 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -29,15 +29,10 @@ config DT_IDLE_STATES
29 bool 29 bool
30 30
31menu "ARM CPU Idle Drivers" 31menu "ARM CPU Idle Drivers"
32depends on ARM 32depends on ARM || ARM64
33source "drivers/cpuidle/Kconfig.arm" 33source "drivers/cpuidle/Kconfig.arm"
34endmenu 34endmenu
35 35
36menu "ARM64 CPU Idle Drivers"
37depends on ARM64
38source "drivers/cpuidle/Kconfig.arm64"
39endmenu
40
41menu "MIPS CPU Idle Drivers" 36menu "MIPS CPU Idle Drivers"
42depends on MIPS 37depends on MIPS
43source "drivers/cpuidle/Kconfig.mips" 38source "drivers/cpuidle/Kconfig.mips"
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index 8e07c9419153..21340e0be73e 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -1,10 +1,20 @@
1# 1#
2# ARM CPU Idle drivers 2# ARM CPU Idle drivers
3# 3#
4config ARM_CPUIDLE
5 bool "Generic ARM/ARM64 CPU idle Driver"
6 select DT_IDLE_STATES
7 help
8 Select this to enable generic cpuidle driver for ARM.
9 It provides a generic idle driver whose idle states are configured
10 at run-time through DT nodes. The CPUidle suspend backend is
11 initialized by calling the CPU operations init idle hook
12 provided by architecture code.
13
4config ARM_BIG_LITTLE_CPUIDLE 14config ARM_BIG_LITTLE_CPUIDLE
5 bool "Support for ARM big.LITTLE processors" 15 bool "Support for ARM big.LITTLE processors"
6 depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS 16 depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS
7 depends on MCPM 17 depends on MCPM && !ARM64
8 select ARM_CPU_SUSPEND 18 select ARM_CPU_SUSPEND
9 select CPU_IDLE_MULTIPLE_DRIVERS 19 select CPU_IDLE_MULTIPLE_DRIVERS
10 select DT_IDLE_STATES 20 select DT_IDLE_STATES
@@ -16,51 +26,51 @@ config ARM_BIG_LITTLE_CPUIDLE
16 26
17config ARM_CLPS711X_CPUIDLE 27config ARM_CLPS711X_CPUIDLE
18 bool "CPU Idle Driver for CLPS711X processors" 28 bool "CPU Idle Driver for CLPS711X processors"
19 depends on ARCH_CLPS711X || COMPILE_TEST 29 depends on ARCH_CLPS711X && !ARM64 || COMPILE_TEST
20 help 30 help
21 Select this to enable cpuidle on Cirrus Logic CLPS711X SOCs. 31 Select this to enable cpuidle on Cirrus Logic CLPS711X SOCs.
22 32
23config ARM_HIGHBANK_CPUIDLE 33config ARM_HIGHBANK_CPUIDLE
24 bool "CPU Idle Driver for Calxeda processors" 34 bool "CPU Idle Driver for Calxeda processors"
25 depends on ARM_PSCI 35 depends on ARM_PSCI && !ARM64
26 select ARM_CPU_SUSPEND 36 select ARM_CPU_SUSPEND
27 help 37 help
28 Select this to enable cpuidle on Calxeda processors. 38 Select this to enable cpuidle on Calxeda processors.
29 39
30config ARM_KIRKWOOD_CPUIDLE 40config ARM_KIRKWOOD_CPUIDLE
31 bool "CPU Idle Driver for Marvell Kirkwood SoCs" 41 bool "CPU Idle Driver for Marvell Kirkwood SoCs"
32 depends on MACH_KIRKWOOD 42 depends on MACH_KIRKWOOD && !ARM64
33 help 43 help
34 This adds the CPU Idle driver for Marvell Kirkwood SoCs. 44 This adds the CPU Idle driver for Marvell Kirkwood SoCs.
35 45
36config ARM_ZYNQ_CPUIDLE 46config ARM_ZYNQ_CPUIDLE
37 bool "CPU Idle Driver for Xilinx Zynq processors" 47 bool "CPU Idle Driver for Xilinx Zynq processors"
38 depends on ARCH_ZYNQ 48 depends on ARCH_ZYNQ && !ARM64
39 help 49 help
40 Select this to enable cpuidle on Xilinx Zynq processors. 50 Select this to enable cpuidle on Xilinx Zynq processors.
41 51
42config ARM_U8500_CPUIDLE 52config ARM_U8500_CPUIDLE
43 bool "Cpu Idle Driver for the ST-E u8500 processors" 53 bool "Cpu Idle Driver for the ST-E u8500 processors"
44 depends on ARCH_U8500 54 depends on ARCH_U8500 && !ARM64
45 help 55 help
46 Select this to enable cpuidle for ST-E u8500 processors 56 Select this to enable cpuidle for ST-E u8500 processors
47 57
48config ARM_AT91_CPUIDLE 58config ARM_AT91_CPUIDLE
49 bool "Cpu Idle Driver for the AT91 processors" 59 bool "Cpu Idle Driver for the AT91 processors"
50 default y 60 default y
51 depends on ARCH_AT91 61 depends on ARCH_AT91 && !ARM64
52 help 62 help
53 Select this to enable cpuidle for AT91 processors 63 Select this to enable cpuidle for AT91 processors
54 64
55config ARM_EXYNOS_CPUIDLE 65config ARM_EXYNOS_CPUIDLE
56 bool "Cpu Idle Driver for the Exynos processors" 66 bool "Cpu Idle Driver for the Exynos processors"
57 depends on ARCH_EXYNOS 67 depends on ARCH_EXYNOS && !ARM64
58 select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP 68 select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
59 help 69 help
60 Select this to enable cpuidle for Exynos processors 70 Select this to enable cpuidle for Exynos processors
61 71
62config ARM_MVEBU_V7_CPUIDLE 72config ARM_MVEBU_V7_CPUIDLE
63 bool "CPU Idle Driver for mvebu v7 family processors" 73 bool "CPU Idle Driver for mvebu v7 family processors"
64 depends on ARCH_MVEBU 74 depends on ARCH_MVEBU && !ARM64
65 help 75 help
66 Select this to enable cpuidle on Armada 370, 38x and XP processors. 76 Select this to enable cpuidle on Armada 370, 38x and XP processors.
diff --git a/drivers/cpuidle/Kconfig.arm64 b/drivers/cpuidle/Kconfig.arm64
deleted file mode 100644
index 6effb3656735..000000000000
--- a/drivers/cpuidle/Kconfig.arm64
+++ /dev/null
@@ -1,13 +0,0 @@
1#
2# ARM64 CPU Idle drivers
3#
4
5config ARM64_CPUIDLE
6 bool "Generic ARM64 CPU idle Driver"
7 select DT_IDLE_STATES
8 help
9 Select this to enable generic cpuidle driver for ARM64.
10 It provides a generic idle driver whose idle states are configured
11 at run-time through DT nodes. The CPUidle suspend backend is
12 initialized by calling the CPU operations init idle hook
13 provided by architecture code.
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 4d177b916f75..3ba81b1dffad 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -17,16 +17,13 @@ obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o
17obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o 17obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o
18obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o 18obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o
19obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o 19obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o
20obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o
20 21
21############################################################################### 22###############################################################################
22# MIPS drivers 23# MIPS drivers
23obj-$(CONFIG_MIPS_CPS_CPUIDLE) += cpuidle-cps.o 24obj-$(CONFIG_MIPS_CPS_CPUIDLE) += cpuidle-cps.o
24 25
25############################################################################### 26###############################################################################
26# ARM64 drivers
27obj-$(CONFIG_ARM64_CPUIDLE) += cpuidle-arm64.o
28
29###############################################################################
30# POWERPC drivers 27# POWERPC drivers
31obj-$(CONFIG_PSERIES_CPUIDLE) += cpuidle-pseries.o 28obj-$(CONFIG_PSERIES_CPUIDLE) += cpuidle-pseries.o
32obj-$(CONFIG_POWERNV_CPUIDLE) += cpuidle-powernv.o 29obj-$(CONFIG_POWERNV_CPUIDLE) += cpuidle-powernv.o
diff --git a/drivers/cpuidle/cpuidle-arm64.c b/drivers/cpuidle/cpuidle-arm.c
index 39a2c62716c3..545069d5fdfb 100644
--- a/drivers/cpuidle/cpuidle-arm64.c
+++ b/drivers/cpuidle/cpuidle-arm.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * ARM64 generic CPU idle driver. 2 * ARM/ARM64 generic CPU idle driver.
3 * 3 *
4 * Copyright (C) 2014 ARM Ltd. 4 * Copyright (C) 2014 ARM Ltd.
5 * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> 5 * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
@@ -9,7 +9,7 @@
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 */ 10 */
11 11
12#define pr_fmt(fmt) "CPUidle arm64: " fmt 12#define pr_fmt(fmt) "CPUidle arm: " fmt
13 13
14#include <linux/cpuidle.h> 14#include <linux/cpuidle.h>
15#include <linux/cpumask.h> 15#include <linux/cpumask.h>
@@ -17,13 +17,14 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/slab.h>
20 21
21#include <asm/cpuidle.h> 22#include <asm/cpuidle.h>
22 23
23#include "dt_idle_states.h" 24#include "dt_idle_states.h"
24 25
25/* 26/*
26 * arm64_enter_idle_state - Programs CPU to enter the specified state 27 * arm_enter_idle_state - Programs CPU to enter the specified state
27 * 28 *
28 * dev: cpuidle device 29 * dev: cpuidle device
29 * drv: cpuidle driver 30 * drv: cpuidle driver
@@ -32,8 +33,8 @@
32 * Called from the CPUidle framework to program the device to the 33 * Called from the CPUidle framework to program the device to the
33 * specified target state selected by the governor. 34 * specified target state selected by the governor.
34 */ 35 */
35static int arm64_enter_idle_state(struct cpuidle_device *dev, 36static int arm_enter_idle_state(struct cpuidle_device *dev,
36 struct cpuidle_driver *drv, int idx) 37 struct cpuidle_driver *drv, int idx)
37{ 38{
38 int ret; 39 int ret;
39 40
@@ -49,7 +50,7 @@ static int arm64_enter_idle_state(struct cpuidle_device *dev,
49 * call the CPU ops suspend protocol with idle index as a 50 * call the CPU ops suspend protocol with idle index as a
50 * parameter. 51 * parameter.
51 */ 52 */
52 ret = cpu_suspend(idx); 53 arm_cpuidle_suspend(idx);
53 54
54 cpu_pm_exit(); 55 cpu_pm_exit();
55 } 56 }
@@ -57,8 +58,8 @@ static int arm64_enter_idle_state(struct cpuidle_device *dev,
57 return ret ? -1 : idx; 58 return ret ? -1 : idx;
58} 59}
59 60
60static struct cpuidle_driver arm64_idle_driver = { 61static struct cpuidle_driver arm_idle_driver = {
61 .name = "arm64_idle", 62 .name = "arm_idle",
62 .owner = THIS_MODULE, 63 .owner = THIS_MODULE,
63 /* 64 /*
64 * State at index 0 is standby wfi and considered standard 65 * State at index 0 is standby wfi and considered standard
@@ -68,32 +69,33 @@ static struct cpuidle_driver arm64_idle_driver = {
68 * handler for idle state index 0. 69 * handler for idle state index 0.
69 */ 70 */
70 .states[0] = { 71 .states[0] = {
71 .enter = arm64_enter_idle_state, 72 .enter = arm_enter_idle_state,
72 .exit_latency = 1, 73 .exit_latency = 1,
73 .target_residency = 1, 74 .target_residency = 1,
74 .power_usage = UINT_MAX, 75 .power_usage = UINT_MAX,
75 .name = "WFI", 76 .name = "WFI",
76 .desc = "ARM64 WFI", 77 .desc = "ARM WFI",
77 } 78 }
78}; 79};
79 80
80static const struct of_device_id arm64_idle_state_match[] __initconst = { 81static const struct of_device_id arm_idle_state_match[] __initconst = {
81 { .compatible = "arm,idle-state", 82 { .compatible = "arm,idle-state",
82 .data = arm64_enter_idle_state }, 83 .data = arm_enter_idle_state },
83 { }, 84 { },
84}; 85};
85 86
86/* 87/*
87 * arm64_idle_init 88 * arm_idle_init
88 * 89 *
89 * Registers the arm64 specific cpuidle driver with the cpuidle 90 * Registers the arm specific cpuidle driver with the cpuidle
90 * framework. It relies on core code to parse the idle states 91 * framework. It relies on core code to parse the idle states
91 * and initialize them using driver data structures accordingly. 92 * and initialize them using driver data structures accordingly.
92 */ 93 */
93static int __init arm64_idle_init(void) 94static int __init arm_idle_init(void)
94{ 95{
95 int cpu, ret; 96 int cpu, ret;
96 struct cpuidle_driver *drv = &arm64_idle_driver; 97 struct cpuidle_driver *drv = &arm_idle_driver;
98 struct cpuidle_device *dev;
97 99
98 /* 100 /*
99 * Initialize idle states data, starting at index 1. 101 * Initialize idle states data, starting at index 1.
@@ -101,22 +103,61 @@ static int __init arm64_idle_init(void)
101 * let the driver initialization fail accordingly since there is no 103 * let the driver initialization fail accordingly since there is no
102 * reason to initialize the idle driver if only wfi is supported. 104 * reason to initialize the idle driver if only wfi is supported.
103 */ 105 */
104 ret = dt_init_idle_driver(drv, arm64_idle_state_match, 1); 106 ret = dt_init_idle_driver(drv, arm_idle_state_match, 1);
105 if (ret <= 0) 107 if (ret <= 0)
106 return ret ? : -ENODEV; 108 return ret ? : -ENODEV;
107 109
110 ret = cpuidle_register_driver(drv);
111 if (ret) {
112 pr_err("Failed to register cpuidle driver\n");
113 return ret;
114 }
115
108 /* 116 /*
109 * Call arch CPU operations in order to initialize 117 * Call arch CPU operations in order to initialize
110 * idle states suspend back-end specific data 118 * idle states suspend back-end specific data
111 */ 119 */
112 for_each_possible_cpu(cpu) { 120 for_each_possible_cpu(cpu) {
113 ret = cpu_init_idle(cpu); 121 ret = arm_cpuidle_init(cpu);
122
123 /*
124 * Skip the cpuidle device initialization if the reported
125 * failure is a HW misconfiguration/breakage (-ENXIO).
126 */
127 if (ret == -ENXIO)
128 continue;
129
114 if (ret) { 130 if (ret) {
115 pr_err("CPU %d failed to init idle CPU ops\n", cpu); 131 pr_err("CPU %d failed to init idle CPU ops\n", cpu);
116 return ret; 132 goto out_fail;
133 }
134
135 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
136 if (!dev) {
137 pr_err("Failed to allocate cpuidle device\n");
138 goto out_fail;
139 }
140 dev->cpu = cpu;
141
142 ret = cpuidle_register_device(dev);
143 if (ret) {
144 pr_err("Failed to register cpuidle device for CPU %d\n",
145 cpu);
146 kfree(dev);
147 goto out_fail;
117 } 148 }
118 } 149 }
119 150
120 return cpuidle_register(drv, NULL); 151 return 0;
152out_fail:
153 while (--cpu >= 0) {
154 dev = per_cpu(cpuidle_devices, cpu);
155 cpuidle_unregister_device(dev);
156 kfree(dev);
157 }
158
159 cpuidle_unregister_driver(drv);
160
161 return ret;
121} 162}
122device_initcall(arm64_idle_init); 163device_initcall(arm_idle_init);
diff --git a/drivers/cpuidle/cpuidle-at91.c b/drivers/cpuidle/cpuidle-at91.c
index aae7bfc1ea36..f2446c78d87c 100644
--- a/drivers/cpuidle/cpuidle-at91.c
+++ b/drivers/cpuidle/cpuidle-at91.c
@@ -19,7 +19,6 @@
19#include <linux/cpuidle.h> 19#include <linux/cpuidle.h>
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/export.h> 21#include <linux/export.h>
22#include <asm/proc-fns.h>
23#include <asm/cpuidle.h> 22#include <asm/cpuidle.h>
24 23
25#define AT91_MAX_STATES 2 24#define AT91_MAX_STATES 2
diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c
index 26f5f29fdb03..0c06ea2f50bb 100644
--- a/drivers/cpuidle/cpuidle-exynos.c
+++ b/drivers/cpuidle/cpuidle-exynos.c
@@ -19,7 +19,6 @@
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/platform_data/cpuidle-exynos.h> 20#include <linux/platform_data/cpuidle-exynos.h>
21 21
22#include <asm/proc-fns.h>
23#include <asm/suspend.h> 22#include <asm/suspend.h>
24#include <asm/cpuidle.h> 23#include <asm/cpuidle.h>
25 24
diff --git a/drivers/cpuidle/cpuidle-kirkwood.c b/drivers/cpuidle/cpuidle-kirkwood.c
index cea0a6c4b1db..d23d8f468c12 100644
--- a/drivers/cpuidle/cpuidle-kirkwood.c
+++ b/drivers/cpuidle/cpuidle-kirkwood.c
@@ -21,7 +21,6 @@
21#include <linux/cpuidle.h> 21#include <linux/cpuidle.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/export.h> 23#include <linux/export.h>
24#include <asm/proc-fns.h>
25#include <asm/cpuidle.h> 24#include <asm/cpuidle.h>
26 25
27#define KIRKWOOD_MAX_STATES 2 26#define KIRKWOOD_MAX_STATES 2
diff --git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c
index 66f81e410f0d..8bf895c0017d 100644
--- a/drivers/cpuidle/cpuidle-ux500.c
+++ b/drivers/cpuidle/cpuidle-ux500.c
@@ -19,7 +19,6 @@
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20 20
21#include <asm/cpuidle.h> 21#include <asm/cpuidle.h>
22#include <asm/proc-fns.h>
23 22
24static atomic_t master = ATOMIC_INIT(0); 23static atomic_t master = ATOMIC_INIT(0);
25static DEFINE_SPINLOCK(master_lock); 24static DEFINE_SPINLOCK(master_lock);
diff --git a/drivers/cpuidle/cpuidle-zynq.c b/drivers/cpuidle/cpuidle-zynq.c
index 002b8c9f98f5..543292b1d38e 100644
--- a/drivers/cpuidle/cpuidle-zynq.c
+++ b/drivers/cpuidle/cpuidle-zynq.c
@@ -28,7 +28,6 @@
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/cpuidle.h> 29#include <linux/cpuidle.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <asm/proc-fns.h>
32#include <asm/cpuidle.h> 31#include <asm/cpuidle.h>
33 32
34#define ZYNQ_MAX_STATES 2 33#define ZYNQ_MAX_STATES 2
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ac78910d7416..91c09305106d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -167,6 +167,7 @@
167#define IOMMU_OF_TABLES() OF_TABLE(CONFIG_OF_IOMMU, iommu) 167#define IOMMU_OF_TABLES() OF_TABLE(CONFIG_OF_IOMMU, iommu)
168#define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem) 168#define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
169#define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method) 169#define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
170#define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
170#define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon) 171#define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
171 172
172#define KERNEL_DTB() \ 173#define KERNEL_DTB() \
@@ -501,6 +502,7 @@
501 CLKSRC_OF_TABLES() \ 502 CLKSRC_OF_TABLES() \
502 IOMMU_OF_TABLES() \ 503 IOMMU_OF_TABLES() \
503 CPU_METHOD_OF_TABLES() \ 504 CPU_METHOD_OF_TABLES() \
505 CPUIDLE_METHOD_OF_TABLES() \
504 KERNEL_DTB() \ 506 KERNEL_DTB() \
505 IRQCHIP_OF_MATCH_TABLE() \ 507 IRQCHIP_OF_MATCH_TABLE() \
506 EARLYCON_OF_TABLES() 508 EARLYCON_OF_TABLES()