diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-04-10 06:01:24 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-04-10 06:01:24 -0400 |
commit | cdde51b9fe83a20fd6c50e81473e6ffb5ba63b92 (patch) | |
tree | 72e35bb87ad895c7cea6310d8f599886d3d9979b | |
parent | e5e02de0665ef2477e7a018193051387c6fe0fbc (diff) | |
parent | 993c592d745c467d83e753c9e8f4e9f952381478 (diff) |
Merge back earlier cpuidle material for v4.1.
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 |
5 | extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev, | 7 | extern 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 | ||
30 | struct device_node; | ||
31 | |||
32 | struct cpuidle_ops { | ||
33 | int (*suspend)(int cpu, unsigned long arg); | ||
34 | int (*init)(struct device_node *, int cpu); | ||
35 | }; | ||
36 | |||
37 | struct 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 | |||
47 | extern int arm_cpuidle_suspend(int index); | ||
48 | |||
49 | extern 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 | ||
17 | extern struct of_cpuidle_method __cpuidle_method_of_table[]; | ||
18 | |||
19 | static const struct of_cpuidle_method __cpuidle_method_of_table_sentinel | ||
20 | __used __section(__cpuidle_method_of_table_end); | ||
21 | |||
22 | static 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 | */ | ||
15 | int arm_cpuidle_simple_enter(struct cpuidle_device *dev, | 35 | int 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 | */ | ||
53 | int 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 | */ | ||
73 | static 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 | */ | ||
97 | static 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 | */ | ||
137 | int __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 |
49 | CONFIG_COMPAT=y | 49 | CONFIG_COMPAT=y |
50 | CONFIG_CPU_IDLE=y | 50 | CONFIG_CPU_IDLE=y |
51 | CONFIG_ARM64_CPUIDLE=y | 51 | CONFIG_ARM_CPUIDLE=y |
52 | CONFIG_NET=y | 52 | CONFIG_NET=y |
53 | CONFIG_PACKET=y | 53 | CONFIG_PACKET=y |
54 | CONFIG_UNIX=y | 54 | CONFIG_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 |
7 | extern int cpu_init_idle(unsigned int cpu); | 7 | extern int arm_cpuidle_init(unsigned int cpu); |
8 | extern int cpu_suspend(unsigned long arg); | 8 | extern int cpu_suspend(unsigned long arg); |
9 | #else | 9 | #else |
10 | static inline int cpu_init_idle(unsigned int cpu) | 10 | static 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 | 20 | static 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 | ||
18 | int cpu_init_idle(unsigned int cpu) | 18 | int 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 | ||
31 | menu "ARM CPU Idle Drivers" | 31 | menu "ARM CPU Idle Drivers" |
32 | depends on ARM | 32 | depends on ARM || ARM64 |
33 | source "drivers/cpuidle/Kconfig.arm" | 33 | source "drivers/cpuidle/Kconfig.arm" |
34 | endmenu | 34 | endmenu |
35 | 35 | ||
36 | menu "ARM64 CPU Idle Drivers" | ||
37 | depends on ARM64 | ||
38 | source "drivers/cpuidle/Kconfig.arm64" | ||
39 | endmenu | ||
40 | |||
41 | menu "MIPS CPU Idle Drivers" | 36 | menu "MIPS CPU Idle Drivers" |
42 | depends on MIPS | 37 | depends on MIPS |
43 | source "drivers/cpuidle/Kconfig.mips" | 38 | source "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 | # |
4 | config 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 | |||
4 | config ARM_BIG_LITTLE_CPUIDLE | 14 | config 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 | ||
17 | config ARM_CLPS711X_CPUIDLE | 27 | config 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 | ||
23 | config ARM_HIGHBANK_CPUIDLE | 33 | config 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 | ||
30 | config ARM_KIRKWOOD_CPUIDLE | 40 | config 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 | ||
36 | config ARM_ZYNQ_CPUIDLE | 46 | config 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 | ||
42 | config ARM_U8500_CPUIDLE | 52 | config 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 | ||
48 | config ARM_AT91_CPUIDLE | 58 | config 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 | ||
55 | config ARM_EXYNOS_CPUIDLE | 65 | config 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 | ||
62 | config ARM_MVEBU_V7_CPUIDLE | 72 | config 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 | |||
5 | config 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 | |||
17 | obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o | 17 | obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o |
18 | obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o | 18 | obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o |
19 | obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o | 19 | obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o |
20 | obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o | ||
20 | 21 | ||
21 | ############################################################################### | 22 | ############################################################################### |
22 | # MIPS drivers | 23 | # MIPS drivers |
23 | obj-$(CONFIG_MIPS_CPS_CPUIDLE) += cpuidle-cps.o | 24 | obj-$(CONFIG_MIPS_CPS_CPUIDLE) += cpuidle-cps.o |
24 | 25 | ||
25 | ############################################################################### | 26 | ############################################################################### |
26 | # ARM64 drivers | ||
27 | obj-$(CONFIG_ARM64_CPUIDLE) += cpuidle-arm64.o | ||
28 | |||
29 | ############################################################################### | ||
30 | # POWERPC drivers | 27 | # POWERPC drivers |
31 | obj-$(CONFIG_PSERIES_CPUIDLE) += cpuidle-pseries.o | 28 | obj-$(CONFIG_PSERIES_CPUIDLE) += cpuidle-pseries.o |
32 | obj-$(CONFIG_POWERNV_CPUIDLE) += cpuidle-powernv.o | 29 | obj-$(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 | */ |
35 | static int arm64_enter_idle_state(struct cpuidle_device *dev, | 36 | static 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 | ||
60 | static struct cpuidle_driver arm64_idle_driver = { | 61 | static 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 | ||
80 | static const struct of_device_id arm64_idle_state_match[] __initconst = { | 81 | static 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 | */ |
93 | static int __init arm64_idle_init(void) | 94 | static 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; |
152 | out_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 | } |
122 | device_initcall(arm64_idle_init); | 163 | device_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 | ||
24 | static atomic_t master = ATOMIC_INIT(0); | 23 | static atomic_t master = ATOMIC_INIT(0); |
25 | static DEFINE_SPINLOCK(master_lock); | 24 | static 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() |