diff options
33 files changed, 544 insertions, 171 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/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index a171fef2c2b6..659879a56dba 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig | |||
@@ -293,5 +293,13 @@ config SH_CPU_FREQ | |||
293 | If unsure, say N. | 293 | If unsure, say N. |
294 | endif | 294 | endif |
295 | 295 | ||
296 | config QORIQ_CPUFREQ | ||
297 | tristate "CPU frequency scaling driver for Freescale QorIQ SoCs" | ||
298 | depends on OF && COMMON_CLK && (PPC_E500MC || ARM) | ||
299 | select CLK_QORIQ | ||
300 | help | ||
301 | This adds the CPUFreq driver support for Freescale QorIQ SoCs | ||
302 | which are capable of changing the CPU's frequency dynamically. | ||
303 | |||
296 | endif | 304 | endif |
297 | endmenu | 305 | endmenu |
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 1b06fc4640e2..4f3dbc8cf729 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm | |||
@@ -108,6 +108,15 @@ config ARM_HIGHBANK_CPUFREQ | |||
108 | 108 | ||
109 | If in doubt, say N. | 109 | If in doubt, say N. |
110 | 110 | ||
111 | config ARM_HISI_ACPU_CPUFREQ | ||
112 | tristate "Hisilicon ACPU CPUfreq driver" | ||
113 | depends on ARCH_HISI && CPUFREQ_DT | ||
114 | select PM_OPP | ||
115 | help | ||
116 | This enables the hisilicon ACPU CPUfreq driver. | ||
117 | |||
118 | If in doubt, say N. | ||
119 | |||
111 | config ARM_IMX6Q_CPUFREQ | 120 | config ARM_IMX6Q_CPUFREQ |
112 | tristate "Freescale i.MX6 cpufreq support" | 121 | tristate "Freescale i.MX6 cpufreq support" |
113 | depends on ARCH_MXC | 122 | depends on ARCH_MXC |
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc index 7ea24413cee6..3a0595b41eab 100644 --- a/drivers/cpufreq/Kconfig.powerpc +++ b/drivers/cpufreq/Kconfig.powerpc | |||
@@ -23,15 +23,6 @@ config CPU_FREQ_MAPLE | |||
23 | This adds support for frequency switching on Maple 970FX | 23 | This adds support for frequency switching on Maple 970FX |
24 | Evaluation Board and compatible boards (IBM JS2x blades). | 24 | Evaluation Board and compatible boards (IBM JS2x blades). |
25 | 25 | ||
26 | config PPC_CORENET_CPUFREQ | ||
27 | tristate "CPU frequency scaling driver for Freescale E500MC SoCs" | ||
28 | depends on PPC_E500MC && OF && COMMON_CLK | ||
29 | select CLK_QORIQ | ||
30 | help | ||
31 | This adds the CPUFreq driver support for Freescale e500mc, | ||
32 | e5500 and e6500 series SoCs which are capable of changing | ||
33 | the CPU's frequency dynamically. | ||
34 | |||
35 | config CPU_FREQ_PMAC | 26 | config CPU_FREQ_PMAC |
36 | bool "Support for Apple PowerBooks" | 27 | bool "Support for Apple PowerBooks" |
37 | depends on ADB_PMU && PPC32 | 28 | depends on ADB_PMU && PPC32 |
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 82a1821471fd..cdce92ae2e8b 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile | |||
@@ -59,6 +59,7 @@ arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o | |||
59 | arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o | 59 | arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o |
60 | obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o | 60 | obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o |
61 | obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o | 61 | obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o |
62 | obj-$(CONFIG_ARM_HISI_ACPU_CPUFREQ) += hisi-acpu-cpufreq.o | ||
62 | obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o | 63 | obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o |
63 | obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o | 64 | obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o |
64 | obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o | 65 | obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o |
@@ -85,7 +86,7 @@ obj-$(CONFIG_CPU_FREQ_CBE) += ppc-cbe-cpufreq.o | |||
85 | ppc-cbe-cpufreq-y += ppc_cbe_cpufreq_pervasive.o ppc_cbe_cpufreq.o | 86 | ppc-cbe-cpufreq-y += ppc_cbe_cpufreq_pervasive.o ppc_cbe_cpufreq.o |
86 | obj-$(CONFIG_CPU_FREQ_CBE_PMI) += ppc_cbe_cpufreq_pmi.o | 87 | obj-$(CONFIG_CPU_FREQ_CBE_PMI) += ppc_cbe_cpufreq_pmi.o |
87 | obj-$(CONFIG_CPU_FREQ_MAPLE) += maple-cpufreq.o | 88 | obj-$(CONFIG_CPU_FREQ_MAPLE) += maple-cpufreq.o |
88 | obj-$(CONFIG_PPC_CORENET_CPUFREQ) += ppc-corenet-cpufreq.o | 89 | obj-$(CONFIG_QORIQ_CPUFREQ) += qoriq-cpufreq.o |
89 | obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o | 90 | obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o |
90 | obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o | 91 | obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o |
91 | obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += pasemi-cpufreq.o | 92 | obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += pasemi-cpufreq.o |
diff --git a/drivers/cpufreq/hisi-acpu-cpufreq.c b/drivers/cpufreq/hisi-acpu-cpufreq.c new file mode 100644 index 000000000000..026d5b2224de --- /dev/null +++ b/drivers/cpufreq/hisi-acpu-cpufreq.c | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Hisilicon Platforms Using ACPU CPUFreq Support | ||
3 | * | ||
4 | * Copyright (c) 2015 Hisilicon Limited. | ||
5 | * Copyright (c) 2015 Linaro Limited. | ||
6 | * | ||
7 | * Leo Yan <leo.yan@linaro.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
14 | * kind, whether express or implied; without even the implied warranty | ||
15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
21 | #include <linux/err.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/of.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | |||
28 | static int __init hisi_acpu_cpufreq_driver_init(void) | ||
29 | { | ||
30 | struct platform_device *pdev; | ||
31 | |||
32 | if (!of_machine_is_compatible("hisilicon,hi6220")) | ||
33 | return -ENODEV; | ||
34 | |||
35 | pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0); | ||
36 | return PTR_ERR_OR_ZERO(pdev); | ||
37 | } | ||
38 | module_init(hisi_acpu_cpufreq_driver_init); | ||
39 | |||
40 | MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>"); | ||
41 | MODULE_DESCRIPTION("Hisilicon acpu cpufreq driver"); | ||
42 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 872c5772c5d3..c5b81beccc8e 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -614,6 +614,19 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate) | |||
614 | wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); | 614 | wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); |
615 | } | 615 | } |
616 | 616 | ||
617 | static int knl_get_turbo_pstate(void) | ||
618 | { | ||
619 | u64 value; | ||
620 | int nont, ret; | ||
621 | |||
622 | rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value); | ||
623 | nont = core_get_max_pstate(); | ||
624 | ret = (((value) >> 8) & 0xFF); | ||
625 | if (ret <= nont) | ||
626 | ret = nont; | ||
627 | return ret; | ||
628 | } | ||
629 | |||
617 | static struct cpu_defaults core_params = { | 630 | static struct cpu_defaults core_params = { |
618 | .pid_policy = { | 631 | .pid_policy = { |
619 | .sample_rate_ms = 10, | 632 | .sample_rate_ms = 10, |
@@ -651,6 +664,23 @@ static struct cpu_defaults byt_params = { | |||
651 | }, | 664 | }, |
652 | }; | 665 | }; |
653 | 666 | ||
667 | static struct cpu_defaults knl_params = { | ||
668 | .pid_policy = { | ||
669 | .sample_rate_ms = 10, | ||
670 | .deadband = 0, | ||
671 | .setpoint = 97, | ||
672 | .p_gain_pct = 20, | ||
673 | .d_gain_pct = 0, | ||
674 | .i_gain_pct = 0, | ||
675 | }, | ||
676 | .funcs = { | ||
677 | .get_max = core_get_max_pstate, | ||
678 | .get_min = core_get_min_pstate, | ||
679 | .get_turbo = knl_get_turbo_pstate, | ||
680 | .set = core_set_pstate, | ||
681 | }, | ||
682 | }; | ||
683 | |||
654 | static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) | 684 | static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) |
655 | { | 685 | { |
656 | int max_perf = cpu->pstate.turbo_pstate; | 686 | int max_perf = cpu->pstate.turbo_pstate; |
@@ -865,6 +895,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = { | |||
865 | ICPU(0x4e, core_params), | 895 | ICPU(0x4e, core_params), |
866 | ICPU(0x4f, core_params), | 896 | ICPU(0x4f, core_params), |
867 | ICPU(0x56, core_params), | 897 | ICPU(0x56, core_params), |
898 | ICPU(0x57, knl_params), | ||
868 | {} | 899 | {} |
869 | }; | 900 | }; |
870 | MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); | 901 | MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); |
@@ -1024,25 +1055,11 @@ static unsigned int force_load; | |||
1024 | 1055 | ||
1025 | static int intel_pstate_msrs_not_valid(void) | 1056 | static int intel_pstate_msrs_not_valid(void) |
1026 | { | 1057 | { |
1027 | /* Check that all the msr's we are using are valid. */ | ||
1028 | u64 aperf, mperf, tmp; | ||
1029 | |||
1030 | rdmsrl(MSR_IA32_APERF, aperf); | ||
1031 | rdmsrl(MSR_IA32_MPERF, mperf); | ||
1032 | |||
1033 | if (!pstate_funcs.get_max() || | 1058 | if (!pstate_funcs.get_max() || |
1034 | !pstate_funcs.get_min() || | 1059 | !pstate_funcs.get_min() || |
1035 | !pstate_funcs.get_turbo()) | 1060 | !pstate_funcs.get_turbo()) |
1036 | return -ENODEV; | 1061 | return -ENODEV; |
1037 | 1062 | ||
1038 | rdmsrl(MSR_IA32_APERF, tmp); | ||
1039 | if (!(tmp - aperf)) | ||
1040 | return -ENODEV; | ||
1041 | |||
1042 | rdmsrl(MSR_IA32_MPERF, tmp); | ||
1043 | if (!(tmp - mperf)) | ||
1044 | return -ENODEV; | ||
1045 | |||
1046 | return 0; | 1063 | return 0; |
1047 | } | 1064 | } |
1048 | 1065 | ||
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 2dfd4fdb5a52..ebef0d8279c7 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c | |||
@@ -34,9 +34,13 @@ | |||
34 | #include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */ | 34 | #include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */ |
35 | 35 | ||
36 | #define POWERNV_MAX_PSTATES 256 | 36 | #define POWERNV_MAX_PSTATES 256 |
37 | #define PMSR_PSAFE_ENABLE (1UL << 30) | ||
38 | #define PMSR_SPR_EM_DISABLE (1UL << 31) | ||
39 | #define PMSR_MAX(x) ((x >> 32) & 0xFF) | ||
40 | #define PMSR_LP(x) ((x >> 48) & 0xFF) | ||
37 | 41 | ||
38 | static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; | 42 | static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; |
39 | static bool rebooting; | 43 | static bool rebooting, throttled; |
40 | 44 | ||
41 | /* | 45 | /* |
42 | * Note: The set of pstates consists of contiguous integers, the | 46 | * Note: The set of pstates consists of contiguous integers, the |
@@ -294,6 +298,44 @@ static inline unsigned int get_nominal_index(void) | |||
294 | return powernv_pstate_info.max - powernv_pstate_info.nominal; | 298 | return powernv_pstate_info.max - powernv_pstate_info.nominal; |
295 | } | 299 | } |
296 | 300 | ||
301 | static void powernv_cpufreq_throttle_check(unsigned int cpu) | ||
302 | { | ||
303 | unsigned long pmsr; | ||
304 | int pmsr_pmax, pmsr_lp; | ||
305 | |||
306 | pmsr = get_pmspr(SPRN_PMSR); | ||
307 | |||
308 | /* Check for Pmax Capping */ | ||
309 | pmsr_pmax = (s8)PMSR_MAX(pmsr); | ||
310 | if (pmsr_pmax != powernv_pstate_info.max) { | ||
311 | throttled = true; | ||
312 | pr_info("CPU %d Pmax is reduced to %d\n", cpu, pmsr_pmax); | ||
313 | pr_info("Max allowed Pstate is capped\n"); | ||
314 | } | ||
315 | |||
316 | /* | ||
317 | * Check for Psafe by reading LocalPstate | ||
318 | * or check if Psafe_mode_active is set in PMSR. | ||
319 | */ | ||
320 | pmsr_lp = (s8)PMSR_LP(pmsr); | ||
321 | if ((pmsr_lp < powernv_pstate_info.min) || | ||
322 | (pmsr & PMSR_PSAFE_ENABLE)) { | ||
323 | throttled = true; | ||
324 | pr_info("Pstate set to safe frequency\n"); | ||
325 | } | ||
326 | |||
327 | /* Check if SPR_EM_DISABLE is set in PMSR */ | ||
328 | if (pmsr & PMSR_SPR_EM_DISABLE) { | ||
329 | throttled = true; | ||
330 | pr_info("Frequency Control disabled from OS\n"); | ||
331 | } | ||
332 | |||
333 | if (throttled) { | ||
334 | pr_info("PMSR = %16lx\n", pmsr); | ||
335 | pr_crit("CPU Frequency could be throttled\n"); | ||
336 | } | ||
337 | } | ||
338 | |||
297 | /* | 339 | /* |
298 | * powernv_cpufreq_target_index: Sets the frequency corresponding to | 340 | * powernv_cpufreq_target_index: Sets the frequency corresponding to |
299 | * the cpufreq table entry indexed by new_index on the cpus in the | 341 | * the cpufreq table entry indexed by new_index on the cpus in the |
@@ -307,6 +349,9 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, | |||
307 | if (unlikely(rebooting) && new_index != get_nominal_index()) | 349 | if (unlikely(rebooting) && new_index != get_nominal_index()) |
308 | return 0; | 350 | return 0; |
309 | 351 | ||
352 | if (!throttled) | ||
353 | powernv_cpufreq_throttle_check(smp_processor_id()); | ||
354 | |||
310 | freq_data.pstate_id = powernv_freqs[new_index].driver_data; | 355 | freq_data.pstate_id = powernv_freqs[new_index].driver_data; |
311 | 356 | ||
312 | /* | 357 | /* |
diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index 7cb4b766cf94..88b21ae0d6b0 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2013 Freescale Semiconductor, Inc. | 2 | * Copyright 2013 Freescale Semiconductor, Inc. |
3 | * | 3 | * |
4 | * CPU Frequency Scaling driver for Freescale PowerPC corenet SoCs. | 4 | * CPU Frequency Scaling driver for Freescale QorIQ SoCs. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -20,12 +20,13 @@ | |||
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/smp.h> | 22 | #include <linux/smp.h> |
23 | #include <sysdev/fsl_soc.h> | ||
24 | 23 | ||
24 | #if !defined(CONFIG_ARM) | ||
25 | #include <asm/smp.h> /* for get_hard_smp_processor_id() in UP configs */ | 25 | #include <asm/smp.h> /* for get_hard_smp_processor_id() in UP configs */ |
26 | #endif | ||
26 | 27 | ||
27 | /** | 28 | /** |
28 | * struct cpu_data - per CPU data struct | 29 | * struct cpu_data |
29 | * @parent: the parent node of cpu clock | 30 | * @parent: the parent node of cpu clock |
30 | * @table: frequency table | 31 | * @table: frequency table |
31 | */ | 32 | */ |
@@ -69,17 +70,78 @@ static const struct soc_data sdata[] = { | |||
69 | static u32 min_cpufreq; | 70 | static u32 min_cpufreq; |
70 | static const u32 *fmask; | 71 | static const u32 *fmask; |
71 | 72 | ||
72 | static DEFINE_PER_CPU(struct cpu_data *, cpu_data); | 73 | #if defined(CONFIG_ARM) |
74 | static int get_cpu_physical_id(int cpu) | ||
75 | { | ||
76 | return topology_core_id(cpu); | ||
77 | } | ||
78 | #else | ||
79 | static int get_cpu_physical_id(int cpu) | ||
80 | { | ||
81 | return get_hard_smp_processor_id(cpu); | ||
82 | } | ||
83 | #endif | ||
73 | 84 | ||
74 | /* cpumask in a cluster */ | 85 | static u32 get_bus_freq(void) |
75 | static DEFINE_PER_CPU(cpumask_var_t, cpu_mask); | 86 | { |
87 | struct device_node *soc; | ||
88 | u32 sysfreq; | ||
89 | |||
90 | soc = of_find_node_by_type(NULL, "soc"); | ||
91 | if (!soc) | ||
92 | return 0; | ||
93 | |||
94 | if (of_property_read_u32(soc, "bus-frequency", &sysfreq)) | ||
95 | sysfreq = 0; | ||
76 | 96 | ||
77 | #ifndef CONFIG_SMP | 97 | of_node_put(soc); |
78 | static inline const struct cpumask *cpu_core_mask(int cpu) | 98 | |
99 | return sysfreq; | ||
100 | } | ||
101 | |||
102 | static struct device_node *cpu_to_clk_node(int cpu) | ||
79 | { | 103 | { |
80 | return cpumask_of(0); | 104 | struct device_node *np, *clk_np; |
105 | |||
106 | if (!cpu_present(cpu)) | ||
107 | return NULL; | ||
108 | |||
109 | np = of_get_cpu_node(cpu, NULL); | ||
110 | if (!np) | ||
111 | return NULL; | ||
112 | |||
113 | clk_np = of_parse_phandle(np, "clocks", 0); | ||
114 | if (!clk_np) | ||
115 | return NULL; | ||
116 | |||
117 | of_node_put(np); | ||
118 | |||
119 | return clk_np; | ||
120 | } | ||
121 | |||
122 | /* traverse cpu nodes to get cpu mask of sharing clock wire */ | ||
123 | static void set_affected_cpus(struct cpufreq_policy *policy) | ||
124 | { | ||
125 | struct device_node *np, *clk_np; | ||
126 | struct cpumask *dstp = policy->cpus; | ||
127 | int i; | ||
128 | |||
129 | np = cpu_to_clk_node(policy->cpu); | ||
130 | if (!np) | ||
131 | return; | ||
132 | |||
133 | for_each_present_cpu(i) { | ||
134 | clk_np = cpu_to_clk_node(i); | ||
135 | if (!clk_np) | ||
136 | continue; | ||
137 | |||
138 | if (clk_np == np) | ||
139 | cpumask_set_cpu(i, dstp); | ||
140 | |||
141 | of_node_put(clk_np); | ||
142 | } | ||
143 | of_node_put(np); | ||
81 | } | 144 | } |
82 | #endif | ||
83 | 145 | ||
84 | /* reduce the duplicated frequencies in frequency table */ | 146 | /* reduce the duplicated frequencies in frequency table */ |
85 | static void freq_table_redup(struct cpufreq_frequency_table *freq_table, | 147 | static void freq_table_redup(struct cpufreq_frequency_table *freq_table, |
@@ -107,6 +169,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table, | |||
107 | int i, j, ind; | 169 | int i, j, ind; |
108 | unsigned int freq, max_freq; | 170 | unsigned int freq, max_freq; |
109 | struct cpufreq_frequency_table table; | 171 | struct cpufreq_frequency_table table; |
172 | |||
110 | for (i = 0; i < count - 1; i++) { | 173 | for (i = 0; i < count - 1; i++) { |
111 | max_freq = freq_table[i].frequency; | 174 | max_freq = freq_table[i].frequency; |
112 | ind = i; | 175 | ind = i; |
@@ -131,7 +194,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table, | |||
131 | } | 194 | } |
132 | } | 195 | } |
133 | 196 | ||
134 | static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) | 197 | static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) |
135 | { | 198 | { |
136 | struct device_node *np; | 199 | struct device_node *np; |
137 | int i, count, ret; | 200 | int i, count, ret; |
@@ -147,10 +210,8 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
147 | return -ENODEV; | 210 | return -ENODEV; |
148 | 211 | ||
149 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 212 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
150 | if (!data) { | 213 | if (!data) |
151 | pr_err("%s: no memory\n", __func__); | ||
152 | goto err_np; | 214 | goto err_np; |
153 | } | ||
154 | 215 | ||
155 | policy->clk = of_clk_get(np, 0); | 216 | policy->clk = of_clk_get(np, 0); |
156 | if (IS_ERR(policy->clk)) { | 217 | if (IS_ERR(policy->clk)) { |
@@ -172,7 +233,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
172 | } | 233 | } |
173 | 234 | ||
174 | if (fmask) | 235 | if (fmask) |
175 | mask = fmask[get_hard_smp_processor_id(cpu)]; | 236 | mask = fmask[get_cpu_physical_id(cpu)]; |
176 | else | 237 | else |
177 | mask = 0x0; | 238 | mask = 0x0; |
178 | 239 | ||
@@ -203,13 +264,12 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
203 | data->table = table; | 264 | data->table = table; |
204 | 265 | ||
205 | /* update ->cpus if we have cluster, no harm if not */ | 266 | /* update ->cpus if we have cluster, no harm if not */ |
206 | cpumask_copy(policy->cpus, per_cpu(cpu_mask, cpu)); | 267 | set_affected_cpus(policy); |
207 | for_each_cpu(i, per_cpu(cpu_mask, cpu)) | 268 | policy->driver_data = data; |
208 | per_cpu(cpu_data, i) = data; | ||
209 | 269 | ||
210 | /* Minimum transition latency is 12 platform clocks */ | 270 | /* Minimum transition latency is 12 platform clocks */ |
211 | u64temp = 12ULL * NSEC_PER_SEC; | 271 | u64temp = 12ULL * NSEC_PER_SEC; |
212 | do_div(u64temp, fsl_get_sys_freq()); | 272 | do_div(u64temp, get_bus_freq()); |
213 | policy->cpuinfo.transition_latency = u64temp + 1; | 273 | policy->cpuinfo.transition_latency = u64temp + 1; |
214 | 274 | ||
215 | of_node_put(np); | 275 | of_node_put(np); |
@@ -221,7 +281,7 @@ err_nomem1: | |||
221 | err_node: | 281 | err_node: |
222 | of_node_put(data->parent); | 282 | of_node_put(data->parent); |
223 | err_nomem2: | 283 | err_nomem2: |
224 | per_cpu(cpu_data, cpu) = NULL; | 284 | policy->driver_data = NULL; |
225 | kfree(data); | 285 | kfree(data); |
226 | err_np: | 286 | err_np: |
227 | of_node_put(np); | 287 | of_node_put(np); |
@@ -229,43 +289,40 @@ err_np: | |||
229 | return -ENODEV; | 289 | return -ENODEV; |
230 | } | 290 | } |
231 | 291 | ||
232 | static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy) | 292 | static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) |
233 | { | 293 | { |
234 | struct cpu_data *data = per_cpu(cpu_data, policy->cpu); | 294 | struct cpu_data *data = policy->driver_data; |
235 | unsigned int cpu; | ||
236 | 295 | ||
237 | of_node_put(data->parent); | 296 | of_node_put(data->parent); |
238 | kfree(data->table); | 297 | kfree(data->table); |
239 | kfree(data); | 298 | kfree(data); |
240 | 299 | policy->driver_data = NULL; | |
241 | for_each_cpu(cpu, per_cpu(cpu_mask, policy->cpu)) | ||
242 | per_cpu(cpu_data, cpu) = NULL; | ||
243 | 300 | ||
244 | return 0; | 301 | return 0; |
245 | } | 302 | } |
246 | 303 | ||
247 | static int corenet_cpufreq_target(struct cpufreq_policy *policy, | 304 | static int qoriq_cpufreq_target(struct cpufreq_policy *policy, |
248 | unsigned int index) | 305 | unsigned int index) |
249 | { | 306 | { |
250 | struct clk *parent; | 307 | struct clk *parent; |
251 | struct cpu_data *data = per_cpu(cpu_data, policy->cpu); | 308 | struct cpu_data *data = policy->driver_data; |
252 | 309 | ||
253 | parent = of_clk_get(data->parent, data->table[index].driver_data); | 310 | parent = of_clk_get(data->parent, data->table[index].driver_data); |
254 | return clk_set_parent(policy->clk, parent); | 311 | return clk_set_parent(policy->clk, parent); |
255 | } | 312 | } |
256 | 313 | ||
257 | static struct cpufreq_driver ppc_corenet_cpufreq_driver = { | 314 | static struct cpufreq_driver qoriq_cpufreq_driver = { |
258 | .name = "ppc_cpufreq", | 315 | .name = "qoriq_cpufreq", |
259 | .flags = CPUFREQ_CONST_LOOPS, | 316 | .flags = CPUFREQ_CONST_LOOPS, |
260 | .init = corenet_cpufreq_cpu_init, | 317 | .init = qoriq_cpufreq_cpu_init, |
261 | .exit = __exit_p(corenet_cpufreq_cpu_exit), | 318 | .exit = __exit_p(qoriq_cpufreq_cpu_exit), |
262 | .verify = cpufreq_generic_frequency_table_verify, | 319 | .verify = cpufreq_generic_frequency_table_verify, |
263 | .target_index = corenet_cpufreq_target, | 320 | .target_index = qoriq_cpufreq_target, |
264 | .get = cpufreq_generic_get, | 321 | .get = cpufreq_generic_get, |
265 | .attr = cpufreq_generic_attr, | 322 | .attr = cpufreq_generic_attr, |
266 | }; | 323 | }; |
267 | 324 | ||
268 | static const struct of_device_id node_matches[] __initdata = { | 325 | static const struct of_device_id node_matches[] __initconst = { |
269 | { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], }, | 326 | { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], }, |
270 | { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], }, | 327 | { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], }, |
271 | { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], }, | 328 | { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], }, |
@@ -275,61 +332,43 @@ static const struct of_device_id node_matches[] __initdata = { | |||
275 | {} | 332 | {} |
276 | }; | 333 | }; |
277 | 334 | ||
278 | static int __init ppc_corenet_cpufreq_init(void) | 335 | static int __init qoriq_cpufreq_init(void) |
279 | { | 336 | { |
280 | int ret; | 337 | int ret; |
281 | struct device_node *np; | 338 | struct device_node *np; |
282 | const struct of_device_id *match; | 339 | const struct of_device_id *match; |
283 | const struct soc_data *data; | 340 | const struct soc_data *data; |
284 | unsigned int cpu; | ||
285 | 341 | ||
286 | np = of_find_matching_node(NULL, node_matches); | 342 | np = of_find_matching_node(NULL, node_matches); |
287 | if (!np) | 343 | if (!np) |
288 | return -ENODEV; | 344 | return -ENODEV; |
289 | 345 | ||
290 | for_each_possible_cpu(cpu) { | ||
291 | if (!alloc_cpumask_var(&per_cpu(cpu_mask, cpu), GFP_KERNEL)) | ||
292 | goto err_mask; | ||
293 | cpumask_copy(per_cpu(cpu_mask, cpu), cpu_core_mask(cpu)); | ||
294 | } | ||
295 | |||
296 | match = of_match_node(node_matches, np); | 346 | match = of_match_node(node_matches, np); |
297 | data = match->data; | 347 | data = match->data; |
298 | if (data) { | 348 | if (data) { |
299 | if (data->flag) | 349 | if (data->flag) |
300 | fmask = data->freq_mask; | 350 | fmask = data->freq_mask; |
301 | min_cpufreq = fsl_get_sys_freq(); | 351 | min_cpufreq = get_bus_freq(); |
302 | } else { | 352 | } else { |
303 | min_cpufreq = fsl_get_sys_freq() / 2; | 353 | min_cpufreq = get_bus_freq() / 2; |
304 | } | 354 | } |
305 | 355 | ||
306 | of_node_put(np); | 356 | of_node_put(np); |
307 | 357 | ||
308 | ret = cpufreq_register_driver(&ppc_corenet_cpufreq_driver); | 358 | ret = cpufreq_register_driver(&qoriq_cpufreq_driver); |
309 | if (!ret) | 359 | if (!ret) |
310 | pr_info("Freescale PowerPC corenet CPU frequency scaling driver\n"); | 360 | pr_info("Freescale QorIQ CPU frequency scaling driver\n"); |
311 | 361 | ||
312 | return ret; | 362 | return ret; |
313 | |||
314 | err_mask: | ||
315 | for_each_possible_cpu(cpu) | ||
316 | free_cpumask_var(per_cpu(cpu_mask, cpu)); | ||
317 | |||
318 | return -ENOMEM; | ||
319 | } | 363 | } |
320 | module_init(ppc_corenet_cpufreq_init); | 364 | module_init(qoriq_cpufreq_init); |
321 | 365 | ||
322 | static void __exit ppc_corenet_cpufreq_exit(void) | 366 | static void __exit qoriq_cpufreq_exit(void) |
323 | { | 367 | { |
324 | unsigned int cpu; | 368 | cpufreq_unregister_driver(&qoriq_cpufreq_driver); |
325 | |||
326 | for_each_possible_cpu(cpu) | ||
327 | free_cpumask_var(per_cpu(cpu_mask, cpu)); | ||
328 | |||
329 | cpufreq_unregister_driver(&ppc_corenet_cpufreq_driver); | ||
330 | } | 369 | } |
331 | module_exit(ppc_corenet_cpufreq_exit); | 370 | module_exit(qoriq_cpufreq_exit); |
332 | 371 | ||
333 | MODULE_LICENSE("GPL"); | 372 | MODULE_LICENSE("GPL"); |
334 | MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>"); | 373 | MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>"); |
335 | MODULE_DESCRIPTION("cpufreq driver for Freescale e500mc series SoCs"); | 374 | MODULE_DESCRIPTION("cpufreq driver for Freescale QorIQ series SoCs"); |
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/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index b0e58522780d..1fb52f4e5870 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -218,18 +218,10 @@ static struct cpuidle_state byt_cstates[] = { | |||
218 | .enter = &intel_idle, | 218 | .enter = &intel_idle, |
219 | .enter_freeze = intel_idle_freeze, }, | 219 | .enter_freeze = intel_idle_freeze, }, |
220 | { | 220 | { |
221 | .name = "C1E-BYT", | ||
222 | .desc = "MWAIT 0x01", | ||
223 | .flags = MWAIT2flg(0x01), | ||
224 | .exit_latency = 15, | ||
225 | .target_residency = 30, | ||
226 | .enter = &intel_idle, | ||
227 | .enter_freeze = intel_idle_freeze, }, | ||
228 | { | ||
229 | .name = "C6N-BYT", | 221 | .name = "C6N-BYT", |
230 | .desc = "MWAIT 0x58", | 222 | .desc = "MWAIT 0x58", |
231 | .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, | 223 | .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, |
232 | .exit_latency = 40, | 224 | .exit_latency = 300, |
233 | .target_residency = 275, | 225 | .target_residency = 275, |
234 | .enter = &intel_idle, | 226 | .enter = &intel_idle, |
235 | .enter_freeze = intel_idle_freeze, }, | 227 | .enter_freeze = intel_idle_freeze, }, |
@@ -237,7 +229,7 @@ static struct cpuidle_state byt_cstates[] = { | |||
237 | .name = "C6S-BYT", | 229 | .name = "C6S-BYT", |
238 | .desc = "MWAIT 0x52", | 230 | .desc = "MWAIT 0x52", |
239 | .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, | 231 | .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, |
240 | .exit_latency = 140, | 232 | .exit_latency = 500, |
241 | .target_residency = 560, | 233 | .target_residency = 560, |
242 | .enter = &intel_idle, | 234 | .enter = &intel_idle, |
243 | .enter_freeze = intel_idle_freeze, }, | 235 | .enter_freeze = intel_idle_freeze, }, |
@@ -246,7 +238,7 @@ static struct cpuidle_state byt_cstates[] = { | |||
246 | .desc = "MWAIT 0x60", | 238 | .desc = "MWAIT 0x60", |
247 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, | 239 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, |
248 | .exit_latency = 1200, | 240 | .exit_latency = 1200, |
249 | .target_residency = 1500, | 241 | .target_residency = 4000, |
250 | .enter = &intel_idle, | 242 | .enter = &intel_idle, |
251 | .enter_freeze = intel_idle_freeze, }, | 243 | .enter_freeze = intel_idle_freeze, }, |
252 | { | 244 | { |
@@ -261,6 +253,51 @@ static struct cpuidle_state byt_cstates[] = { | |||
261 | .enter = NULL } | 253 | .enter = NULL } |
262 | }; | 254 | }; |
263 | 255 | ||
256 | static struct cpuidle_state cht_cstates[] = { | ||
257 | { | ||
258 | .name = "C1-CHT", | ||
259 | .desc = "MWAIT 0x00", | ||
260 | .flags = MWAIT2flg(0x00), | ||
261 | .exit_latency = 1, | ||
262 | .target_residency = 1, | ||
263 | .enter = &intel_idle, | ||
264 | .enter_freeze = intel_idle_freeze, }, | ||
265 | { | ||
266 | .name = "C6N-CHT", | ||
267 | .desc = "MWAIT 0x58", | ||
268 | .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, | ||
269 | .exit_latency = 80, | ||
270 | .target_residency = 275, | ||
271 | .enter = &intel_idle, | ||
272 | .enter_freeze = intel_idle_freeze, }, | ||
273 | { | ||
274 | .name = "C6S-CHT", | ||
275 | .desc = "MWAIT 0x52", | ||
276 | .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, | ||
277 | .exit_latency = 200, | ||
278 | .target_residency = 560, | ||
279 | .enter = &intel_idle, | ||
280 | .enter_freeze = intel_idle_freeze, }, | ||
281 | { | ||
282 | .name = "C7-CHT", | ||
283 | .desc = "MWAIT 0x60", | ||
284 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, | ||
285 | .exit_latency = 1200, | ||
286 | .target_residency = 4000, | ||
287 | .enter = &intel_idle, | ||
288 | .enter_freeze = intel_idle_freeze, }, | ||
289 | { | ||
290 | .name = "C7S-CHT", | ||
291 | .desc = "MWAIT 0x64", | ||
292 | .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, | ||
293 | .exit_latency = 10000, | ||
294 | .target_residency = 20000, | ||
295 | .enter = &intel_idle, | ||
296 | .enter_freeze = intel_idle_freeze, }, | ||
297 | { | ||
298 | .enter = NULL } | ||
299 | }; | ||
300 | |||
264 | static struct cpuidle_state ivb_cstates[] = { | 301 | static struct cpuidle_state ivb_cstates[] = { |
265 | { | 302 | { |
266 | .name = "C1-IVB", | 303 | .name = "C1-IVB", |
@@ -748,6 +785,12 @@ static const struct idle_cpu idle_cpu_byt = { | |||
748 | .byt_auto_demotion_disable_flag = true, | 785 | .byt_auto_demotion_disable_flag = true, |
749 | }; | 786 | }; |
750 | 787 | ||
788 | static const struct idle_cpu idle_cpu_cht = { | ||
789 | .state_table = cht_cstates, | ||
790 | .disable_promotion_to_c1e = true, | ||
791 | .byt_auto_demotion_disable_flag = true, | ||
792 | }; | ||
793 | |||
751 | static const struct idle_cpu idle_cpu_ivb = { | 794 | static const struct idle_cpu idle_cpu_ivb = { |
752 | .state_table = ivb_cstates, | 795 | .state_table = ivb_cstates, |
753 | .disable_promotion_to_c1e = true, | 796 | .disable_promotion_to_c1e = true, |
@@ -776,7 +819,7 @@ static const struct idle_cpu idle_cpu_avn = { | |||
776 | #define ICPU(model, cpu) \ | 819 | #define ICPU(model, cpu) \ |
777 | { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } | 820 | { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } |
778 | 821 | ||
779 | static const struct x86_cpu_id intel_idle_ids[] = { | 822 | static const struct x86_cpu_id intel_idle_ids[] __initconst = { |
780 | ICPU(0x1a, idle_cpu_nehalem), | 823 | ICPU(0x1a, idle_cpu_nehalem), |
781 | ICPU(0x1e, idle_cpu_nehalem), | 824 | ICPU(0x1e, idle_cpu_nehalem), |
782 | ICPU(0x1f, idle_cpu_nehalem), | 825 | ICPU(0x1f, idle_cpu_nehalem), |
@@ -790,6 +833,7 @@ static const struct x86_cpu_id intel_idle_ids[] = { | |||
790 | ICPU(0x2d, idle_cpu_snb), | 833 | ICPU(0x2d, idle_cpu_snb), |
791 | ICPU(0x36, idle_cpu_atom), | 834 | ICPU(0x36, idle_cpu_atom), |
792 | ICPU(0x37, idle_cpu_byt), | 835 | ICPU(0x37, idle_cpu_byt), |
836 | ICPU(0x4c, idle_cpu_cht), | ||
793 | ICPU(0x3a, idle_cpu_ivb), | 837 | ICPU(0x3a, idle_cpu_ivb), |
794 | ICPU(0x3e, idle_cpu_ivt), | 838 | ICPU(0x3e, idle_cpu_ivt), |
795 | ICPU(0x3c, idle_cpu_hsw), | 839 | ICPU(0x3c, idle_cpu_hsw), |
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() |