Skip to content

Commit 419a48c

Browse files
committed
Merge branches 'pm-cpufreq' and 'pm-cpuidle'
* pm-cpufreq: intel_pstate: Knights Landing support intel_pstate: remove MSR test cpufreq: fix qoriq uniprocessor build cpufreq: hisilicon: add acpu driver cpufreq: powernv: Report cpu frequency throttling cpufreq: qoriq: rename the driver cpufreq: qoriq: Make the driver usable on all QorIQ platforms * pm-cpuidle: intel_idle: mark cpu id array as __initconst intel_idle: Add support for the Airmont Core in the Cherrytrail and Braswell SOCs intel_idle: Update support for Silvermont Core in Baytrail SOC ARM: cpuidle: Document the code ARM: cpuidle: Register per cpuidle device ARM: cpuidle: Enable the ARM64 driver for both ARM32/ARM64 ARM64: cpuidle: Remove arm64 reference ARM64: cpuidle: Rename cpu_init_idle to a common function name ARM64: cpuidle: Replace cpu_suspend by the common ARM/ARM64 function ARM: cpuidle: Add a cpuidle ops structure to be used for DT ARM: cpuidle: Remove duplicate header inclusion
3 parents 17528b3 + b34ef93 + baa9a93 commit 419a48c

33 files changed

+544
-171
lines changed

arch/arm/include/asm/cpuidle.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef __ASM_ARM_CPUIDLE_H
22
#define __ASM_ARM_CPUIDLE_H
33

4+
#include <asm/proc-fns.h>
5+
46
#ifdef CONFIG_CPU_IDLE
57
extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
68
struct cpuidle_driver *drv, int index);
@@ -25,4 +27,25 @@ static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
2527
*/
2628
#define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX)
2729

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+
2851
#endif

arch/arm/kernel/cpuidle.c

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,143 @@
1010
*/
1111

1212
#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>
1416

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+
*/
1535
int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
1636
struct cpuidle_driver *drv, int index)
1737
{
1838
cpu_do_idle();
1939

2040
return index;
2141
}
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+
}

arch/arm/mach-davinci/cpuidle.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <linux/cpuidle.h>
1818
#include <linux/io.h>
1919
#include <linux/export.h>
20-
#include <asm/proc-fns.h>
2120
#include <asm/cpuidle.h>
2221

2322
#include <mach/cpuidle.h>

arch/arm/mach-imx/cpuidle-imx6q.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <linux/cpuidle.h>
1010
#include <linux/module.h>
1111
#include <asm/cpuidle.h>
12-
#include <asm/proc-fns.h>
1312

1413
#include "common.h"
1514
#include "cpuidle.h"

arch/arm/mach-imx/cpuidle-imx6sl.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <linux/cpuidle.h>
1010
#include <linux/module.h>
1111
#include <asm/cpuidle.h>
12-
#include <asm/proc-fns.h>
1312

1413
#include "common.h"
1514
#include "cpuidle.h"

arch/arm/mach-imx/cpuidle-imx6sx.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <linux/cpu_pm.h>
1111
#include <linux/module.h>
1212
#include <asm/cpuidle.h>
13-
#include <asm/proc-fns.h>
1413
#include <asm/suspend.h>
1514

1615
#include "common.h"

arch/arm/mach-omap2/cpuidle44xx.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <linux/clockchips.h>
1818

1919
#include <asm/cpuidle.h>
20-
#include <asm/proc-fns.h>
2120

2221
#include "common.h"
2322
#include "pm.h"

arch/arm/mach-s3c64xx/cpuidle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <linux/export.h>
1717
#include <linux/time.h>
1818

19-
#include <asm/proc-fns.h>
19+
#include <asm/cpuidle.h>
2020

2121
#include <mach/map.h>
2222

arch/arm/mach-tegra/cpuidle-tegra20.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include <linux/module.h>
2828

2929
#include <asm/cpuidle.h>
30-
#include <asm/proc-fns.h>
3130
#include <asm/smp_plat.h>
3231
#include <asm/suspend.h>
3332

arch/arm/mach-tegra/cpuidle-tegra30.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include <linux/module.h>
2828

2929
#include <asm/cpuidle.h>
30-
#include <asm/proc-fns.h>
3130
#include <asm/smp_plat.h>
3231
#include <asm/suspend.h>
3332

arch/arm64/configs/defconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ CONFIG_CMDLINE="console=ttyAMA0"
4848
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
4949
CONFIG_COMPAT=y
5050
CONFIG_CPU_IDLE=y
51-
CONFIG_ARM64_CPUIDLE=y
51+
CONFIG_ARM_CPUIDLE=y
5252
CONFIG_NET=y
5353
CONFIG_PACKET=y
5454
CONFIG_UNIX=y

arch/arm64/include/asm/cpuidle.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
#include <asm/proc-fns.h>
55

66
#ifdef CONFIG_CPU_IDLE
7-
extern int cpu_init_idle(unsigned int cpu);
7+
extern int arm_cpuidle_init(unsigned int cpu);
88
extern int cpu_suspend(unsigned long arg);
99
#else
10-
static inline int cpu_init_idle(unsigned int cpu)
10+
static inline int arm_cpuidle_init(unsigned int cpu)
1111
{
1212
return -EOPNOTSUPP;
1313
}
@@ -17,5 +17,8 @@ static inline int cpu_suspend(unsigned long arg)
1717
return -EOPNOTSUPP;
1818
}
1919
#endif
20-
20+
static inline int arm_cpuidle_suspend(int index)
21+
{
22+
return cpu_suspend(index);
23+
}
2124
#endif

arch/arm64/kernel/cpuidle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include <asm/cpuidle.h>
1616
#include <asm/cpu_ops.h>
1717

18-
int cpu_init_idle(unsigned int cpu)
18+
int arm_cpuidle_init(unsigned int cpu)
1919
{
2020
int ret = -EOPNOTSUPP;
2121
struct device_node *cpu_node = of_cpu_device_node_get(cpu);

drivers/cpufreq/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,5 +293,13 @@ config SH_CPU_FREQ
293293
If unsure, say N.
294294
endif
295295

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+
296304
endif
297305
endmenu

drivers/cpufreq/Kconfig.arm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,15 @@ config ARM_HIGHBANK_CPUFREQ
108108

109109
If in doubt, say N.
110110

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+
111120
config ARM_IMX6Q_CPUFREQ
112121
tristate "Freescale i.MX6 cpufreq support"
113122
depends on ARCH_MXC

drivers/cpufreq/Kconfig.powerpc

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,6 @@ config CPU_FREQ_MAPLE
2323
This adds support for frequency switching on Maple 970FX
2424
Evaluation Board and compatible boards (IBM JS2x blades).
2525

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-
3526
config CPU_FREQ_PMAC
3627
bool "Support for Apple PowerBooks"
3728
depends on ADB_PMU && PPC32

drivers/cpufreq/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o
5959
arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o
6060
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
6161
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
62+
obj-$(CONFIG_ARM_HISI_ACPU_CPUFREQ) += hisi-acpu-cpufreq.o
6263
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
6364
obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o
6465
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
@@ -85,7 +86,7 @@ obj-$(CONFIG_CPU_FREQ_CBE) += ppc-cbe-cpufreq.o
8586
ppc-cbe-cpufreq-y += ppc_cbe_cpufreq_pervasive.o ppc_cbe_cpufreq.o
8687
obj-$(CONFIG_CPU_FREQ_CBE_PMI) += ppc_cbe_cpufreq_pmi.o
8788
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
8990
obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o
9091
obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o
9192
obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += pasemi-cpufreq.o

drivers/cpufreq/hisi-acpu-cpufreq.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 <[email protected]>
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 <[email protected]>");
41+
MODULE_DESCRIPTION("Hisilicon acpu cpufreq driver");
42+
MODULE_LICENSE("GPL v2");

0 commit comments

Comments
 (0)